Mercurial > hg > orthanc-stone
comparison UnitTestsSources/TestStrategy.cpp @ 695:7bf91c4ebd65
strategy
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Fri, 17 May 2019 18:04:14 +0200 |
parents | |
children | 14557e550920 |
comparison
equal
deleted
inserted
replaced
693:9a474e90e832 | 695:7bf91c4ebd65 |
---|---|
1 /** | |
2 * Stone of Orthanc | |
3 * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics | |
4 * Department, University Hospital of Liege, Belgium | |
5 * Copyright (C) 2017-2019 Osimis S.A., Belgium | |
6 * | |
7 * This program is free software: you can redistribute it and/or | |
8 * modify it under the terms of the GNU Affero General Public License | |
9 * as published by the Free Software Foundation, either version 3 of | |
10 * the License, or (at your option) any later version. | |
11 * | |
12 * This program is distributed in the hope that it will be useful, but | |
13 * WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
15 * Affero General Public License for more details. | |
16 * | |
17 * You should have received a copy of the GNU Affero General Public License | |
18 * along with this program. If not, see <http://www.gnu.org/licenses/>. | |
19 **/ | |
20 | |
21 | |
22 #include "gtest/gtest.h" | |
23 | |
24 #include <Core/OrthancException.h> | |
25 | |
26 #include <boost/noncopyable.hpp> | |
27 #include <vector> | |
28 | |
29 namespace OrthancStone | |
30 { | |
31 class IFetchingStrategy : public boost::noncopyable | |
32 { | |
33 public: | |
34 virtual ~IFetchingStrategy() | |
35 { | |
36 } | |
37 | |
38 virtual unsigned int GetItemsCount() const = 0; | |
39 | |
40 virtual unsigned int GetMaxQuality() const = 0; | |
41 | |
42 virtual bool GetNext(unsigned int& item, | |
43 unsigned int& quality) = 0; | |
44 | |
45 virtual void SetCurrent(unsigned int item) = 0; | |
46 | |
47 // Ask the strategy to re-schedule the item with the lowest | |
48 // priority in the fetching order. This allows to know which item | |
49 // should be dropped from a cache. | |
50 virtual void RecycleFurthest(unsigned int& item) = 0; | |
51 }; | |
52 | |
53 | |
54 class IFetchingItemsSorter : public boost::noncopyable | |
55 { | |
56 public: | |
57 virtual ~IFetchingItemsSorter() | |
58 { | |
59 } | |
60 | |
61 virtual unsigned int GetItemsCount() const = 0; | |
62 | |
63 // Sort a set of items given the current item | |
64 virtual void Sort(std::vector<unsigned int>& target, | |
65 unsigned int current) = 0; | |
66 }; | |
67 | |
68 | |
69 | |
70 class BasicFetchingItemsSorter : public IFetchingItemsSorter | |
71 { | |
72 private: | |
73 unsigned int itemsCount_; | |
74 | |
75 public: | |
76 BasicFetchingItemsSorter(unsigned int itemsCount) : | |
77 itemsCount_(itemsCount) | |
78 { | |
79 if (itemsCount == 0) | |
80 { | |
81 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); | |
82 } | |
83 } | |
84 | |
85 virtual unsigned int GetItemsCount() const | |
86 { | |
87 return itemsCount_; | |
88 } | |
89 | |
90 virtual void Sort(std::vector<unsigned int>& target, | |
91 unsigned int current) | |
92 { | |
93 if (current >= itemsCount_) | |
94 { | |
95 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); | |
96 } | |
97 | |
98 target.clear(); | |
99 target.reserve(itemsCount_); | |
100 target.push_back(current); | |
101 | |
102 const unsigned int countBelow = current; | |
103 const unsigned int countAbove = (itemsCount_ - 1) - current; | |
104 const unsigned int n = std::min(countBelow, countAbove); | |
105 | |
106 for (unsigned int i = 1; i <= n; i++) | |
107 { | |
108 assert(current + i < itemsCount_ && | |
109 current >= i); | |
110 target.push_back(current + i); | |
111 target.push_back(current - i); | |
112 } | |
113 | |
114 for (unsigned int i = current - n; i > 0; i--) | |
115 { | |
116 target.push_back(i - 1); | |
117 } | |
118 | |
119 for (unsigned int i = current + n + 1; i < itemsCount_; i++) | |
120 { | |
121 target.push_back(i); | |
122 } | |
123 | |
124 assert(target.size() == itemsCount_); | |
125 } | |
126 }; | |
127 | |
128 | |
129 class BasicFetchingStrategy : public IFetchingStrategy | |
130 { | |
131 private: | |
132 struct Item | |
133 { | |
134 unsigned int item_; | |
135 unsigned int quality_; | |
136 }; | |
137 | |
138 std::auto_ptr<IFetchingItemsSorter> sorter_; | |
139 std::vector<unsigned int> nextQuality_; | |
140 unsigned int maxQuality_; | |
141 std::vector<Item> content_; | |
142 size_t currentItem_; | |
143 | |
144 public: | |
145 BasicFetchingStrategy(IFetchingItemsSorter* sorter, // Takes ownership | |
146 unsigned int maxQuality) : | |
147 sorter_(sorter), | |
148 nextQuality_(sorter_->GetItemsCount(), 0), | |
149 maxQuality_(maxQuality), | |
150 currentItem_(0) | |
151 { | |
152 if (sorter == NULL) | |
153 { | |
154 throw Orthanc::OrthancException(Orthanc::ErrorCode_NullPointer); | |
155 } | |
156 | |
157 SetCurrent(0); | |
158 } | |
159 | |
160 virtual unsigned int GetItemsCount() const | |
161 { | |
162 return sorter_->GetItemsCount(); | |
163 } | |
164 | |
165 virtual unsigned int GetMaxQuality() const | |
166 { | |
167 return maxQuality_; | |
168 } | |
169 | |
170 virtual bool GetNext(unsigned int& item, | |
171 unsigned int& quality) | |
172 { | |
173 if (currentItem_ >= content_.size()) | |
174 { | |
175 return false; | |
176 } | |
177 else | |
178 { | |
179 item = content_[currentItem_].item_; | |
180 quality = content_[currentItem_].quality_; | |
181 | |
182 assert(nextQuality_[item] <= quality); | |
183 nextQuality_[item] = quality + 1; | |
184 | |
185 return true; | |
186 } | |
187 } | |
188 | |
189 virtual void SetCurrent(unsigned int item) | |
190 { | |
191 std::vector<unsigned int> v; | |
192 sorter_->Sort(v, item); | |
193 | |
194 assert(v.size() == GetItemsCount()); | |
195 | |
196 content_.clear(); | |
197 content_.reserve(v.size() * maxQuality_); | |
198 | |
199 for (unsigned int q = 0; q < maxQuality_; q++) | |
200 { | |
201 for (size_t i = 0; i < v.size(); i++) | |
202 { | |
203 | |
204 } | |
205 } | |
206 } | |
207 | |
208 // Ask the strategy to re-schedule the item with the lowest | |
209 // priority in the fetching order. This allows to know which item | |
210 // should be dropped from a cache. | |
211 virtual void RecycleFurthest(unsigned int& item) | |
212 { | |
213 throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented); | |
214 } | |
215 }; | |
216 } | |
217 | |
218 | |
219 | |
220 TEST(BasicFetchingStrategy, Test) | |
221 { | |
222 OrthancStone::BasicFetchingStrategy s(new OrthancStone::BasicFetchingItemsSorter(10), 3); | |
223 } | |
224 | |
225 | |
226 | |
227 | |
228 TEST(BasicFetchingItemsSorter, Small) | |
229 { | |
230 ASSERT_THROW(OrthancStone::BasicFetchingItemsSorter(0), Orthanc::OrthancException); | |
231 std::vector<unsigned int> v; | |
232 | |
233 { | |
234 OrthancStone::BasicFetchingItemsSorter s(1); | |
235 s.Sort(v, 0); | |
236 ASSERT_EQ(1u, v.size()); | |
237 ASSERT_EQ(0u, v[0]); | |
238 | |
239 ASSERT_THROW(s.Sort(v, 1), Orthanc::OrthancException); | |
240 } | |
241 | |
242 { | |
243 OrthancStone::BasicFetchingItemsSorter s(2); | |
244 s.Sort(v, 0); | |
245 ASSERT_EQ(2u, v.size()); | |
246 ASSERT_EQ(0u, v[0]); | |
247 ASSERT_EQ(1u, v[1]); | |
248 | |
249 s.Sort(v, 1); | |
250 ASSERT_EQ(2u, v.size()); | |
251 ASSERT_EQ(1u, v[0]); | |
252 ASSERT_EQ(0u, v[1]); | |
253 | |
254 ASSERT_THROW(s.Sort(v, 2), Orthanc::OrthancException); | |
255 } | |
256 | |
257 { | |
258 OrthancStone::BasicFetchingItemsSorter s(3); | |
259 s.Sort(v, 0); | |
260 ASSERT_EQ(3u, v.size()); | |
261 ASSERT_EQ(0u, v[0]); | |
262 ASSERT_EQ(1u, v[1]); | |
263 ASSERT_EQ(2u, v[2]); | |
264 | |
265 s.Sort(v, 1); | |
266 ASSERT_EQ(3u, v.size()); | |
267 ASSERT_EQ(1u, v[0]); | |
268 ASSERT_EQ(2u, v[1]); | |
269 ASSERT_EQ(0u, v[2]); | |
270 | |
271 s.Sort(v, 2); | |
272 ASSERT_EQ(3u, v.size()); | |
273 ASSERT_EQ(2u, v[0]); | |
274 ASSERT_EQ(1u, v[1]); | |
275 ASSERT_EQ(0u, v[2]); | |
276 | |
277 ASSERT_THROW(s.Sort(v, 3), Orthanc::OrthancException); | |
278 } | |
279 } | |
280 | |
281 | |
282 TEST(BasicFetchingItemsSorter, Odd) | |
283 { | |
284 OrthancStone::BasicFetchingItemsSorter s(7); | |
285 std::vector<unsigned int> v; | |
286 | |
287 ASSERT_THROW(s.Sort(v, 7), Orthanc::OrthancException); | |
288 | |
289 { | |
290 s.Sort(v, 0); | |
291 ASSERT_EQ(7u, v.size()); | |
292 ASSERT_EQ(0u, v[0]); | |
293 ASSERT_EQ(1u, v[1]); | |
294 ASSERT_EQ(2u, v[2]); | |
295 ASSERT_EQ(3u, v[3]); | |
296 ASSERT_EQ(4u, v[4]); | |
297 ASSERT_EQ(5u, v[5]); | |
298 ASSERT_EQ(6u, v[6]); | |
299 } | |
300 | |
301 { | |
302 s.Sort(v, 1); | |
303 ASSERT_EQ(7u, v.size()); | |
304 ASSERT_EQ(1u, v[0]); | |
305 ASSERT_EQ(2u, v[1]); | |
306 ASSERT_EQ(0u, v[2]); | |
307 ASSERT_EQ(3u, v[3]); | |
308 ASSERT_EQ(4u, v[4]); | |
309 ASSERT_EQ(5u, v[5]); | |
310 ASSERT_EQ(6u, v[6]); | |
311 } | |
312 | |
313 { | |
314 s.Sort(v, 2); | |
315 ASSERT_EQ(7u, v.size()); | |
316 ASSERT_EQ(2u, v[0]); | |
317 ASSERT_EQ(3u, v[1]); | |
318 ASSERT_EQ(1u, v[2]); | |
319 ASSERT_EQ(4u, v[3]); | |
320 ASSERT_EQ(0u, v[4]); | |
321 ASSERT_EQ(5u, v[5]); | |
322 ASSERT_EQ(6u, v[6]); | |
323 } | |
324 | |
325 { | |
326 s.Sort(v, 3); | |
327 ASSERT_EQ(7u, v.size()); | |
328 ASSERT_EQ(3u, v[0]); | |
329 ASSERT_EQ(4u, v[1]); | |
330 ASSERT_EQ(2u, v[2]); | |
331 ASSERT_EQ(5u, v[3]); | |
332 ASSERT_EQ(1u, v[4]); | |
333 ASSERT_EQ(6u, v[5]); | |
334 ASSERT_EQ(0u, v[6]); | |
335 } | |
336 | |
337 { | |
338 s.Sort(v, 4); | |
339 ASSERT_EQ(7u, v.size()); | |
340 ASSERT_EQ(4u, v[0]); | |
341 ASSERT_EQ(5u, v[1]); | |
342 ASSERT_EQ(3u, v[2]); | |
343 ASSERT_EQ(6u, v[3]); | |
344 ASSERT_EQ(2u, v[4]); | |
345 ASSERT_EQ(1u, v[5]); | |
346 ASSERT_EQ(0u, v[6]); | |
347 } | |
348 | |
349 { | |
350 s.Sort(v, 5); | |
351 ASSERT_EQ(7u, v.size()); | |
352 ASSERT_EQ(5u, v[0]); | |
353 ASSERT_EQ(6u, v[1]); | |
354 ASSERT_EQ(4u, v[2]); | |
355 ASSERT_EQ(3u, v[3]); | |
356 ASSERT_EQ(2u, v[4]); | |
357 ASSERT_EQ(1u, v[5]); | |
358 ASSERT_EQ(0u, v[6]); | |
359 } | |
360 | |
361 { | |
362 s.Sort(v, 6); | |
363 ASSERT_EQ(7u, v.size()); | |
364 ASSERT_EQ(6u, v[0]); | |
365 ASSERT_EQ(5u, v[1]); | |
366 ASSERT_EQ(4u, v[2]); | |
367 ASSERT_EQ(3u, v[3]); | |
368 ASSERT_EQ(2u, v[4]); | |
369 ASSERT_EQ(1u, v[5]); | |
370 ASSERT_EQ(0u, v[6]); | |
371 } | |
372 } | |
373 | |
374 | |
375 TEST(BasicFetchingItemsSorter, Even) | |
376 { | |
377 OrthancStone::BasicFetchingItemsSorter s(6); | |
378 std::vector<unsigned int> v; | |
379 | |
380 { | |
381 s.Sort(v, 0); | |
382 ASSERT_EQ(6u, v.size()); | |
383 ASSERT_EQ(0u, v[0]); | |
384 ASSERT_EQ(1u, v[1]); | |
385 ASSERT_EQ(2u, v[2]); | |
386 ASSERT_EQ(3u, v[3]); | |
387 ASSERT_EQ(4u, v[4]); | |
388 ASSERT_EQ(5u, v[5]); | |
389 } | |
390 | |
391 { | |
392 s.Sort(v, 1); | |
393 ASSERT_EQ(6u, v.size()); | |
394 ASSERT_EQ(1u, v[0]); | |
395 ASSERT_EQ(2u, v[1]); | |
396 ASSERT_EQ(0u, v[2]); | |
397 ASSERT_EQ(3u, v[3]); | |
398 ASSERT_EQ(4u, v[4]); | |
399 ASSERT_EQ(5u, v[5]); | |
400 } | |
401 | |
402 { | |
403 s.Sort(v, 2); | |
404 ASSERT_EQ(6u, v.size()); | |
405 ASSERT_EQ(2u, v[0]); | |
406 ASSERT_EQ(3u, v[1]); | |
407 ASSERT_EQ(1u, v[2]); | |
408 ASSERT_EQ(4u, v[3]); | |
409 ASSERT_EQ(0u, v[4]); | |
410 ASSERT_EQ(5u, v[5]); | |
411 } | |
412 | |
413 { | |
414 s.Sort(v, 3); | |
415 ASSERT_EQ(6u, v.size()); | |
416 ASSERT_EQ(3u, v[0]); | |
417 ASSERT_EQ(4u, v[1]); | |
418 ASSERT_EQ(2u, v[2]); | |
419 ASSERT_EQ(5u, v[3]); | |
420 ASSERT_EQ(1u, v[4]); | |
421 ASSERT_EQ(0u, v[5]); | |
422 } | |
423 | |
424 { | |
425 s.Sort(v, 4); | |
426 ASSERT_EQ(6u, v.size()); | |
427 ASSERT_EQ(4u, v[0]); | |
428 ASSERT_EQ(5u, v[1]); | |
429 ASSERT_EQ(3u, v[2]); | |
430 ASSERT_EQ(2u, v[3]); | |
431 ASSERT_EQ(1u, v[4]); | |
432 ASSERT_EQ(0u, v[5]); | |
433 } | |
434 | |
435 { | |
436 s.Sort(v, 5); | |
437 ASSERT_EQ(6u, v.size()); | |
438 ASSERT_EQ(5u, v[0]); | |
439 ASSERT_EQ(4u, v[1]); | |
440 ASSERT_EQ(3u, v[2]); | |
441 ASSERT_EQ(2u, v[3]); | |
442 ASSERT_EQ(1u, v[4]); | |
443 ASSERT_EQ(0u, v[5]); | |
444 } | |
445 } |