Fix some bugs when testing opensds ansible
[stor4nfv.git] / src / 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