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