]> git.proxmox.com Git - ceph.git/blob - ceph/src/dmclock/test/test_dmclock_server.cc
4555e377323e9ff87af6341efb47740ea60207cc
[ceph.git] / ceph / src / dmclock / test / test_dmclock_server.cc
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
3 /*
4 * Copyright (C) 2016 Red Hat Inc.
5 */
6
7
8 #include <memory>
9 #include <chrono>
10 #include <iostream>
11 #include <list>
12 #include <vector>
13
14
15 #include "dmclock_server.h"
16 #include "dmclock_util.h"
17 #include "gtest/gtest.h"
18
19
20 namespace dmc = crimson::dmclock;
21
22
23 // we need a request object; an empty one will do
24 struct Request {
25 };
26
27
28 namespace crimson {
29 namespace dmclock {
30
31 /*
32 * Allows us to test the code provided with the mutex provided locked.
33 */
34 static void test_locked(std::mutex& mtx, std::function<void()> code) {
35 std::unique_lock<std::mutex> l(mtx);
36 code();
37 }
38
39
40 TEST(dmclock_server, bad_tag_deathtest) {
41 using ClientId = int;
42 using Queue = dmc::PullPriorityQueue<ClientId,Request>;
43 using QueueRef = std::unique_ptr<Queue>;
44
45 ClientId client1 = 17;
46 ClientId client2 = 18;
47
48 double reservation = 0.0;
49 double weight = 0.0;
50
51 dmc::ClientInfo ci1(reservation, weight, 0.0);
52 dmc::ClientInfo ci2(reservation, weight, 1.0);
53
54 auto client_info_f = [&] (ClientId c) -> dmc::ClientInfo {
55 if (client1 == c) return ci1;
56 else if (client2 == c) return ci2;
57 else {
58 ADD_FAILURE() << "got request from neither of two clients";
59 return ci1; // must return
60 }
61 };
62
63 QueueRef pq(new Queue(client_info_f, false));
64 Request req;
65 ReqParams req_params(1,1);
66
67 EXPECT_DEATH_IF_SUPPORTED(pq->add_request(req, client1, req_params),
68 "Assertion.*reservation.*max_tag.*"
69 "proportion.*max_tag") <<
70 "we should fail if a client tries to generate a reservation tag "
71 "where reservation and proportion are both 0";
72
73
74 EXPECT_DEATH_IF_SUPPORTED(pq->add_request(req, client2, req_params),
75 "Assertion.*reservation.*max_tag.*"
76 "proportion.*max_tag") <<
77 "we should fail if a client tries to generate a reservation tag "
78 "where reservation and proportion are both 0";
79 }
80
81
82 TEST(dmclock_server, client_idle_erase) {
83 using ClientId = int;
84 using Queue = dmc::PushPriorityQueue<ClientId,Request>;
85 int client = 17;
86 double reservation = 100.0;
87
88 dmc::ClientInfo ci(reservation, 1.0, 0.0);
89 auto client_info_f = [&] (ClientId c) -> dmc::ClientInfo { return ci; };
90 auto server_ready_f = [] () -> bool { return true; };
91 auto submit_req_f = [] (const ClientId& c,
92 std::unique_ptr<Request> req,
93 dmc::PhaseType phase) {
94 // empty; do nothing
95 };
96
97 Queue pq(client_info_f,
98 server_ready_f,
99 submit_req_f,
100 std::chrono::seconds(3),
101 std::chrono::seconds(5),
102 std::chrono::seconds(2),
103 false);
104
105 auto lock_pq = [&](std::function<void()> code) {
106 test_locked(pq.data_mtx, code);
107 };
108
109
110 /* The timeline should be as follows:
111 *
112 * 0 seconds : request created
113 *
114 * 1 seconds : map is size 1, idle is false
115 *
116 * 2 seconds : clean notes first mark; +2 is base for further calcs
117 *
118 * 4 seconds : clean does nothing except makes another mark
119 *
120 * 5 seconds : when we're secheduled to idle (+2 + 3)
121 *
122 * 6 seconds : clean idles client
123 *
124 * 7 seconds : when we're secheduled to erase (+2 + 5)
125 *
126 * 7 seconds : verified client is idle
127 *
128 * 8 seconds : clean erases client info
129 *
130 * 9 seconds : verified client is erased
131 */
132
133 lock_pq([&] () {
134 EXPECT_EQ(0u, pq.client_map.size()) <<
135 "client map initially has size 0";
136 });
137
138 Request req;
139 dmc::ReqParams req_params(1, 1);
140 pq.add_request_time(req, client, req_params, dmc::get_time());
141
142 std::this_thread::sleep_for(std::chrono::seconds(1));
143
144 lock_pq([&] () {
145 EXPECT_EQ(1u, pq.client_map.size()) <<
146 "client map has 1 after 1 client";
147 EXPECT_FALSE(pq.client_map.at(client)->idle) <<
148 "initially client map entry shows not idle.";
149 });
150
151 std::this_thread::sleep_for(std::chrono::seconds(6));
152
153 lock_pq([&] () {
154 EXPECT_TRUE(pq.client_map.at(client)->idle) <<
155 "after idle age client map entry shows idle.";
156 });
157
158 std::this_thread::sleep_for(std::chrono::seconds(2));
159
160 lock_pq([&] () {
161 EXPECT_EQ(0u, pq.client_map.size()) <<
162 "client map loses its entry after erase age";
163 });
164 } // TEST
165
166
167 #if 0
168 TEST(dmclock_server, reservation_timing) {
169 using ClientId = int;
170 // NB? PUSH OR PULL
171 using Queue = std::unique_ptr<dmc::PriorityQueue<ClientId,Request>>;
172 using std::chrono::steady_clock;
173
174 int client = 17;
175
176 std::vector<dmc::Time> times;
177 std::mutex times_mtx;
178 using Guard = std::lock_guard<decltype(times_mtx)>;
179
180 // reservation every second
181 dmc::ClientInfo ci(1.0, 0.0, 0.0);
182 Queue pq;
183
184 auto client_info_f = [&] (ClientId c) -> dmc::ClientInfo { return ci; };
185 auto server_ready_f = [] () -> bool { return true; };
186 auto submit_req_f = [&] (const ClientId& c,
187 std::unique_ptr<Request> req,
188 dmc::PhaseType phase) {
189 {
190 Guard g(times_mtx);
191 times.emplace_back(dmc::get_time());
192 }
193 std::thread complete([&](){ pq->request_completed(); });
194 complete.detach();
195 };
196
197 // NB? PUSH OR PULL
198 pq = Queue(new dmc::PriorityQueue<ClientId,Request>(client_info_f,
199 server_ready_f,
200 submit_req_f,
201 false));
202
203 Request req;
204 ReqParams<ClientId> req_params(client, 1, 1);
205
206 for (int i = 0; i < 5; ++i) {
207 pq->add_request_time(req, req_params, dmc::get_time());
208 }
209
210 {
211 Guard g(times_mtx);
212 std::this_thread::sleep_for(std::chrono::milliseconds(5500));
213 EXPECT_EQ(5, times.size()) <<
214 "after 5.5 seconds, we should have 5 requests times at 1 second apart";
215 }
216 } // TEST
217 #endif
218
219
220 TEST(dmclock_server, remove_by_req_filter) {
221 struct MyReq {
222 int id;
223
224 MyReq(int _id) :
225 id(_id)
226 {
227 // empty
228 }
229 }; // MyReq
230
231 using ClientId = int;
232 using Queue = dmc::PullPriorityQueue<ClientId,MyReq>;
233
234 ClientId client1 = 17;
235 ClientId client2 = 98;
236
237 dmc::ClientInfo info1(0.0, 1.0, 0.0);
238
239 auto client_info_f = [&] (ClientId c) -> dmc::ClientInfo {
240 return info1;
241 };
242
243 Queue pq(client_info_f, true);
244
245 EXPECT_EQ(0u, pq.client_count());
246 EXPECT_EQ(0u, pq.request_count());
247
248 ReqParams req_params(1,1);
249
250 pq.add_request(MyReq(1), client1, req_params);
251 pq.add_request(MyReq(11), client1, req_params);
252 pq.add_request(MyReq(2), client2, req_params);
253 pq.add_request(MyReq(0), client2, req_params);
254 pq.add_request(MyReq(13), client2, req_params);
255 pq.add_request(MyReq(2), client2, req_params);
256 pq.add_request(MyReq(13), client2, req_params);
257 pq.add_request(MyReq(98), client2, req_params);
258 pq.add_request(MyReq(44), client1, req_params);
259
260 EXPECT_EQ(2u, pq.client_count());
261 EXPECT_EQ(9u, pq.request_count());
262
263 pq.remove_by_req_filter([](const MyReq& r) -> bool {return 1 == r.id % 2;});
264
265 EXPECT_EQ(5u, pq.request_count());
266
267 std::list<MyReq> capture;
268 pq.remove_by_req_filter(
269 [&capture] (const MyReq& r) -> bool {
270 if (0 == r.id % 2) {
271 capture.push_front(r);
272 return true;
273 } else {
274 return false;
275 }
276 },
277 true);
278
279 EXPECT_EQ(0u, pq.request_count());
280 EXPECT_EQ(5u, capture.size());
281 int total = 0;
282 for (auto i : capture) {
283 total += i.id;
284 }
285 EXPECT_EQ(146, total) << " sum of captured items should be 146";
286 } // TEST
287
288
289 TEST(dmclock_server, remove_by_req_filter_ordering_forwards_visit) {
290 struct MyReq {
291 int id;
292
293 MyReq(int _id) :
294 id(_id)
295 {
296 // empty
297 }
298 }; // MyReq
299
300 using ClientId = int;
301 using Queue = dmc::PullPriorityQueue<ClientId,MyReq>;
302
303 ClientId client1 = 17;
304
305 dmc::ClientInfo info1(0.0, 1.0, 0.0);
306
307 auto client_info_f = [&] (ClientId c) -> dmc::ClientInfo {
308 return info1;
309 };
310
311 Queue pq(client_info_f, true);
312
313 EXPECT_EQ(0u, pq.client_count());
314 EXPECT_EQ(0u, pq.request_count());
315
316 ReqParams req_params(1,1);
317
318 pq.add_request(MyReq(1), client1, req_params);
319 pq.add_request(MyReq(2), client1, req_params);
320 pq.add_request(MyReq(3), client1, req_params);
321 pq.add_request(MyReq(4), client1, req_params);
322 pq.add_request(MyReq(5), client1, req_params);
323 pq.add_request(MyReq(6), client1, req_params);
324
325 EXPECT_EQ(1u, pq.client_count());
326 EXPECT_EQ(6u, pq.request_count());
327
328 // remove odd ids in forward order and append to end
329
330 std::vector<MyReq> capture;
331 pq.remove_by_req_filter(
332 [&capture] (const MyReq& r) -> bool {
333 if (1 == r.id % 2) {
334 capture.push_back(r);
335 return true;
336 } else {
337 return false;
338 }
339 },
340 false);
341
342 EXPECT_EQ(3u, pq.request_count());
343 EXPECT_EQ(3u, capture.size());
344 EXPECT_EQ(1, capture[0].id) << "items should come out in forward order";
345 EXPECT_EQ(3, capture[1].id) << "items should come out in forward order";
346 EXPECT_EQ(5, capture[2].id) << "items should come out in forward order";
347
348 // remove even ids in reverse order but insert at front so comes
349 // out forwards
350
351 std::vector<MyReq> capture2;
352 pq.remove_by_req_filter(
353 [&capture2] (const MyReq& r) -> bool {
354 if (0 == r.id % 2) {
355 capture2.insert(capture2.begin(), r);
356 return true;
357 } else {
358 return false;
359 }
360 },
361 false);
362
363 EXPECT_EQ(0u, pq.request_count());
364 EXPECT_EQ(3u, capture2.size());
365 EXPECT_EQ(6, capture2[0].id) << "items should come out in reverse order";
366 EXPECT_EQ(4, capture2[1].id) << "items should come out in reverse order";
367 EXPECT_EQ(2, capture2[2].id) << "items should come out in reverse order";
368 } // TEST
369
370
371 TEST(dmclock_server, remove_by_req_filter_ordering_backwards_visit) {
372 struct MyReq {
373 int id;
374
375 MyReq(int _id) :
376 id(_id)
377 {
378 // empty
379 }
380 }; // MyReq
381
382 using ClientId = int;
383 using Queue = dmc::PullPriorityQueue<ClientId,MyReq>;
384
385 ClientId client1 = 17;
386
387 dmc::ClientInfo info1(0.0, 1.0, 0.0);
388
389 auto client_info_f = [&] (ClientId c) -> dmc::ClientInfo {
390 return info1;
391 };
392
393 Queue pq(client_info_f, true);
394
395 EXPECT_EQ(0u, pq.client_count());
396 EXPECT_EQ(0u, pq.request_count());
397
398 ReqParams req_params(1,1);
399
400 pq.add_request(MyReq(1), client1, req_params);
401 pq.add_request(MyReq(2), client1, req_params);
402 pq.add_request(MyReq(3), client1, req_params);
403 pq.add_request(MyReq(4), client1, req_params);
404 pq.add_request(MyReq(5), client1, req_params);
405 pq.add_request(MyReq(6), client1, req_params);
406
407 EXPECT_EQ(1u, pq.client_count());
408 EXPECT_EQ(6u, pq.request_count());
409
410 // now remove odd ids in forward order
411
412 std::vector<MyReq> capture;
413 pq.remove_by_req_filter(
414 [&capture] (const MyReq& r) -> bool {
415 if (1 == r.id % 2) {
416 capture.insert(capture.begin(), r);
417 return true;
418 } else {
419 return false;
420 }
421 },
422 true);
423
424 EXPECT_EQ(3u, pq.request_count());
425 EXPECT_EQ(3u, capture.size());
426 EXPECT_EQ(1, capture[0].id) << "items should come out in forward order";
427 EXPECT_EQ(3, capture[1].id) << "items should come out in forward order";
428 EXPECT_EQ(5, capture[2].id) << "items should come out in forward order";
429
430 // now remove even ids in reverse order
431
432 std::vector<MyReq> capture2;
433 pq.remove_by_req_filter(
434 [&capture2] (const MyReq& r) -> bool {
435 if (0 == r.id % 2) {
436 capture2.push_back(r);
437 return true;
438 } else {
439 return false;
440 }
441 },
442 true);
443
444 EXPECT_EQ(0u, pq.request_count());
445 EXPECT_EQ(3u, capture2.size());
446 EXPECT_EQ(6, capture2[0].id) << "items should come out in reverse order";
447 EXPECT_EQ(4, capture2[1].id) << "items should come out in reverse order";
448 EXPECT_EQ(2, capture2[2].id) << "items should come out in reverse order";
449 } // TEST
450
451
452 TEST(dmclock_server, remove_by_client) {
453 struct MyReq {
454 int id;
455
456 MyReq(int _id) :
457 id(_id)
458 {
459 // empty
460 }
461 }; // MyReq
462
463 using ClientId = int;
464 using Queue = dmc::PullPriorityQueue<ClientId,MyReq>;
465
466 ClientId client1 = 17;
467 ClientId client2 = 98;
468
469 dmc::ClientInfo info1(0.0, 1.0, 0.0);
470
471 auto client_info_f = [&] (ClientId c) -> dmc::ClientInfo {
472 return info1;
473 };
474
475 Queue pq(client_info_f, true);
476
477 EXPECT_EQ(0u, pq.client_count());
478 EXPECT_EQ(0u, pq.request_count());
479
480 ReqParams req_params(1,1);
481
482 pq.add_request(MyReq(1), client1, req_params);
483 pq.add_request(MyReq(11), client1, req_params);
484 pq.add_request(MyReq(2), client2, req_params);
485 pq.add_request(MyReq(0), client2, req_params);
486 pq.add_request(MyReq(13), client2, req_params);
487 pq.add_request(MyReq(2), client2, req_params);
488 pq.add_request(MyReq(13), client2, req_params);
489 pq.add_request(MyReq(98), client2, req_params);
490 pq.add_request(MyReq(44), client1, req_params);
491
492 EXPECT_EQ(2u, pq.client_count());
493 EXPECT_EQ(9u, pq.request_count());
494
495 std::list<MyReq> removed;
496
497 pq.remove_by_client(client1,
498 true,
499 [&removed] (const MyReq& r) {
500 removed.push_front(r);
501 });
502
503 EXPECT_EQ(3u, removed.size());
504 EXPECT_EQ(1, removed.front().id);
505 removed.pop_front();
506 EXPECT_EQ(11, removed.front().id);
507 removed.pop_front();
508 EXPECT_EQ(44, removed.front().id);
509 removed.pop_front();
510
511 EXPECT_EQ(6u, pq.request_count());
512
513 Queue::PullReq pr = pq.pull_request();
514 EXPECT_TRUE(pr.is_retn());
515 EXPECT_EQ(2, pr.get_retn().request->id);
516
517 pr = pq.pull_request();
518 EXPECT_TRUE(pr.is_retn());
519 EXPECT_EQ(0, pr.get_retn().request->id);
520
521 pq.remove_by_client(client2);
522 EXPECT_EQ(0u, pq.request_count()) <<
523 "after second client removed, none left";
524 } // TEST
525
526
527 TEST(dmclock_server_pull, pull_weight) {
528 using ClientId = int;
529 using Queue = dmc::PullPriorityQueue<ClientId,Request>;
530 using QueueRef = std::unique_ptr<Queue>;
531
532 ClientId client1 = 17;
533 ClientId client2 = 98;
534
535 dmc::ClientInfo info1(0.0, 1.0, 0.0);
536 dmc::ClientInfo info2(0.0, 2.0, 0.0);
537
538 QueueRef pq;
539
540 auto client_info_f = [&] (ClientId c) -> dmc::ClientInfo {
541 if (client1 == c) return info1;
542 else if (client2 == c) return info2;
543 else {
544 ADD_FAILURE() << "client info looked up for non-existant client";
545 return info1;
546 }
547 };
548
549 pq = QueueRef(new Queue(client_info_f, false));
550
551 Request req;
552 ReqParams req_params(1,1);
553
554 auto now = dmc::get_time();
555
556 for (int i = 0; i < 5; ++i) {
557 pq->add_request(req, client1, req_params);
558 pq->add_request(req, client2, req_params);
559 now += 0.0001;
560 }
561
562 int c1_count = 0;
563 int c2_count = 0;
564 for (int i = 0; i < 6; ++i) {
565 Queue::PullReq pr = pq->pull_request();
566 EXPECT_EQ(Queue::NextReqType::returning, pr.type);
567 auto& retn = boost::get<Queue::PullReq::Retn>(pr.data);
568
569 if (client1 == retn.client) ++c1_count;
570 else if (client2 == retn.client) ++c2_count;
571 else ADD_FAILURE() << "got request from neither of two clients";
572
573 EXPECT_EQ(PhaseType::priority, retn.phase);
574 }
575
576 EXPECT_EQ(2, c1_count) <<
577 "one-third of request should have come from first client";
578 EXPECT_EQ(4, c2_count) <<
579 "two-thirds of request should have come from second client";
580 }
581
582
583 TEST(dmclock_server_pull, pull_reservation) {
584 using ClientId = int;
585 using Queue = dmc::PullPriorityQueue<ClientId,Request>;
586 using QueueRef = std::unique_ptr<Queue>;
587
588 ClientId client1 = 52;
589 ClientId client2 = 8;
590
591 dmc::ClientInfo info1(2.0, 0.0, 0.0);
592 dmc::ClientInfo info2(1.0, 0.0, 0.0);
593
594 auto client_info_f = [&] (ClientId c) -> dmc::ClientInfo {
595 if (client1 == c) return info1;
596 else if (client2 == c) return info2;
597 else {
598 ADD_FAILURE() << "client info looked up for non-existant client";
599 return info1;
600 }
601 };
602
603 QueueRef pq(new Queue(client_info_f, false));
604
605 Request req;
606 ReqParams req_params(1,1);
607
608 // make sure all times are well before now
609 auto old_time = dmc::get_time() - 100.0;
610
611 for (int i = 0; i < 5; ++i) {
612 pq->add_request_time(req, client1, req_params, old_time);
613 pq->add_request_time(req, client2, req_params, old_time);
614 old_time += 0.001;
615 }
616
617 int c1_count = 0;
618 int c2_count = 0;
619
620 for (int i = 0; i < 6; ++i) {
621 Queue::PullReq pr = pq->pull_request();
622 EXPECT_EQ(Queue::NextReqType::returning, pr.type);
623 auto& retn = boost::get<Queue::PullReq::Retn>(pr.data);
624
625 if (client1 == retn.client) ++c1_count;
626 else if (client2 == retn.client) ++c2_count;
627 else ADD_FAILURE() << "got request from neither of two clients";
628
629 EXPECT_EQ(PhaseType::reservation, retn.phase);
630 }
631
632 EXPECT_EQ(4, c1_count) <<
633 "two-thirds of request should have come from first client";
634 EXPECT_EQ(2, c2_count) <<
635 "one-third of request should have come from second client";
636 } // dmclock_server_pull.pull_reservation
637
638
639 // This test shows what happens when a request can be ready (under
640 // limit) but not schedulable since proportion tag is 0. We expect
641 // to get some future and none responses.
642 TEST(dmclock_server_pull, ready_and_under_limit) {
643 using ClientId = int;
644 using Queue = dmc::PullPriorityQueue<ClientId,Request>;
645 using QueueRef = std::unique_ptr<Queue>;
646
647 ClientId client1 = 52;
648 ClientId client2 = 8;
649
650 dmc::ClientInfo info1(1.0, 0.0, 0.0);
651 dmc::ClientInfo info2(1.0, 0.0, 0.0);
652
653 auto client_info_f = [&] (ClientId c) -> dmc::ClientInfo {
654 if (client1 == c) return info1;
655 else if (client2 == c) return info2;
656 else {
657 ADD_FAILURE() << "client info looked up for non-existant client";
658 return info1;
659 }
660 };
661
662 QueueRef pq(new Queue(client_info_f, false));
663
664 Request req;
665 ReqParams req_params(1,1);
666
667 // make sure all times are well before now
668 auto start_time = dmc::get_time() - 100.0;
669
670 // add six requests; for same client reservations spaced one apart
671 for (int i = 0; i < 3; ++i) {
672 pq->add_request_time(req, client1, req_params, start_time);
673 pq->add_request_time(req, client2, req_params, start_time);
674 }
675
676 Queue::PullReq pr = pq->pull_request(start_time + 0.5);
677 EXPECT_EQ(Queue::NextReqType::returning, pr.type);
678
679 pr = pq->pull_request(start_time + 0.5);
680 EXPECT_EQ(Queue::NextReqType::returning, pr.type);
681
682 pr = pq->pull_request(start_time + 0.5);
683 EXPECT_EQ(Queue::NextReqType::future, pr.type) <<
684 "too soon for next reservation";
685
686 pr = pq->pull_request(start_time + 1.5);
687 EXPECT_EQ(Queue::NextReqType::returning, pr.type);
688
689 pr = pq->pull_request(start_time + 1.5);
690 EXPECT_EQ(Queue::NextReqType::returning, pr.type);
691
692 pr = pq->pull_request(start_time + 1.5);
693 EXPECT_EQ(Queue::NextReqType::future, pr.type) <<
694 "too soon for next reservation";
695
696 pr = pq->pull_request(start_time + 2.5);
697 EXPECT_EQ(Queue::NextReqType::returning, pr.type);
698
699 pr = pq->pull_request(start_time + 2.5);
700 EXPECT_EQ(Queue::NextReqType::returning, pr.type);
701
702 pr = pq->pull_request(start_time + 2.5);
703 EXPECT_EQ(Queue::NextReqType::none, pr.type) << "no more requests left";
704 }
705
706
707 TEST(dmclock_server_pull, pull_none) {
708 using ClientId = int;
709 using Queue = dmc::PullPriorityQueue<ClientId,Request>;
710 using QueueRef = std::unique_ptr<Queue>;
711
712 dmc::ClientInfo info(1.0, 1.0, 1.0);
713
714 auto client_info_f = [&] (ClientId c) -> dmc::ClientInfo {
715 return info;
716 };
717
718 QueueRef pq(new Queue(client_info_f, false));
719
720 // Request req;
721 ReqParams req_params(1,1);
722
723 auto now = dmc::get_time();
724
725 Queue::PullReq pr = pq->pull_request(now + 100);
726
727 EXPECT_EQ(Queue::NextReqType::none, pr.type);
728 }
729
730
731 TEST(dmclock_server_pull, pull_future) {
732 using ClientId = int;
733 using Queue = dmc::PullPriorityQueue<ClientId,Request>;
734 using QueueRef = std::unique_ptr<Queue>;
735
736 ClientId client1 = 52;
737 // ClientId client2 = 8;
738
739 dmc::ClientInfo info(1.0, 0.0, 1.0);
740
741 auto client_info_f = [&] (ClientId c) -> dmc::ClientInfo {
742 return info;
743 };
744
745 QueueRef pq(new Queue(client_info_f, false));
746
747 Request req;
748 ReqParams req_params(1,1);
749
750 // make sure all times are well before now
751 auto now = dmc::get_time();
752
753 pq->add_request_time(req, client1, req_params, now + 100);
754 Queue::PullReq pr = pq->pull_request(now);
755
756 EXPECT_EQ(Queue::NextReqType::future, pr.type);
757
758 Time when = boost::get<Time>(pr.data);
759 EXPECT_EQ(now + 100, when);
760 }
761
762
763 TEST(dmclock_server_pull, pull_future_limit_break_weight) {
764 using ClientId = int;
765 using Queue = dmc::PullPriorityQueue<ClientId,Request>;
766 using QueueRef = std::unique_ptr<Queue>;
767
768 ClientId client1 = 52;
769 // ClientId client2 = 8;
770
771 dmc::ClientInfo info(0.0, 1.0, 1.0);
772
773 auto client_info_f = [&] (ClientId c) -> dmc::ClientInfo {
774 return info;
775 };
776
777 QueueRef pq(new Queue(client_info_f, true));
778
779 Request req;
780 ReqParams req_params(1,1);
781
782 // make sure all times are well before now
783 auto now = dmc::get_time();
784
785 pq->add_request_time(req, client1, req_params, now + 100);
786 Queue::PullReq pr = pq->pull_request(now);
787
788 EXPECT_EQ(Queue::NextReqType::returning, pr.type);
789
790 auto& retn = boost::get<Queue::PullReq::Retn>(pr.data);
791 EXPECT_EQ(client1, retn.client);
792 }
793
794
795 TEST(dmclock_server_pull, pull_future_limit_break_reservation) {
796 using ClientId = int;
797 using Queue = dmc::PullPriorityQueue<ClientId,Request>;
798 using QueueRef = std::unique_ptr<Queue>;
799
800 ClientId client1 = 52;
801 // ClientId client2 = 8;
802
803 dmc::ClientInfo info(1.0, 0.0, 1.0);
804
805 auto client_info_f = [&] (ClientId c) -> dmc::ClientInfo {
806 return info;
807 };
808
809 QueueRef pq(new Queue(client_info_f, true));
810
811 Request req;
812 ReqParams req_params(1,1);
813
814 // make sure all times are well before now
815 auto now = dmc::get_time();
816
817 pq->add_request_time(req, client1, req_params, now + 100);
818 Queue::PullReq pr = pq->pull_request(now);
819
820 EXPECT_EQ(Queue::NextReqType::returning, pr.type);
821
822 auto& retn = boost::get<Queue::PullReq::Retn>(pr.data);
823 EXPECT_EQ(client1, retn.client);
824 }
825 } // namespace dmclock
826 } // namespace crimson