1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 * Copyright (C) 2016 Red Hat Inc.
15 #include "dmclock_server.h"
16 #include "dmclock_util.h"
17 #include "gtest/gtest.h"
19 // process control to prevent core dumps during gtest death tests
23 namespace dmc
= crimson::dmclock
;
26 // we need a request object; an empty one will do
35 * Allows us to test the code provided with the mutex provided locked.
37 static void test_locked(std::mutex
& mtx
, std::function
<void()> code
) {
38 std::unique_lock
<std::mutex
> l(mtx
);
43 TEST(dmclock_server
, bad_tag_deathtest
) {
45 using Queue
= dmc::PullPriorityQueue
<ClientId
,Request
>;
46 using QueueRef
= std::unique_ptr
<Queue
>;
48 ClientId client1
= 17;
49 ClientId client2
= 18;
51 double reservation
= 0.0;
54 dmc::ClientInfo
ci1(reservation
, weight
, 0.0);
55 dmc::ClientInfo
ci2(reservation
, weight
, 1.0);
57 auto client_info_f
= [&] (ClientId c
) -> dmc::ClientInfo
{
58 if (client1
== c
) return ci1
;
59 else if (client2
== c
) return ci2
;
61 ADD_FAILURE() << "got request from neither of two clients";
62 return ci1
; // must return
66 QueueRef
pq(new Queue(client_info_f
, false));
67 ReqParams
req_params(1,1);
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";
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";
87 TEST(dmclock_server
, client_idle_erase
) {
89 using Queue
= dmc::PushPriorityQueue
<ClientId
,Request
>;
91 double reservation
= 100.0;
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
) {
102 Queue
pq(client_info_f
,
105 std::chrono::seconds(3),
106 std::chrono::seconds(5),
107 std::chrono::seconds(2),
110 auto lock_pq
= [&](std::function
<void()> code
) {
111 test_locked(pq
.data_mtx
, code
);
115 /* The timeline should be as follows:
117 * 0 seconds : request created
119 * 1 seconds : map is size 1, idle is false
121 * 2 seconds : clean notes first mark; +2 is base for further calcs
123 * 4 seconds : clean does nothing except makes another mark
125 * 5 seconds : when we're secheduled to idle (+2 + 3)
127 * 6 seconds : clean idles client
129 * 7 seconds : when we're secheduled to erase (+2 + 5)
131 * 7 seconds : verified client is idle
133 * 8 seconds : clean erases client info
135 * 9 seconds : verified client is erased
139 EXPECT_EQ(0u, pq
.client_map
.size()) <<
140 "client map initially has size 0";
144 dmc::ReqParams
req_params(1, 1);
145 pq
.add_request_time(req
, client
, req_params
, dmc::get_time());
147 std::this_thread::sleep_for(std::chrono::seconds(1));
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.";
156 std::this_thread::sleep_for(std::chrono::seconds(6));
159 EXPECT_TRUE(pq
.client_map
.at(client
)->idle
) <<
160 "after idle age client map entry shows idle.";
163 std::this_thread::sleep_for(std::chrono::seconds(2));
166 EXPECT_EQ(0u, pq
.client_map
.size()) <<
167 "client map loses its entry after erase age";
173 TEST(dmclock_server
, reservation_timing
) {
174 using ClientId
= int;
176 using Queue
= std::unique_ptr
<dmc::PriorityQueue
<ClientId
,Request
>>;
177 using std::chrono::steady_clock
;
181 std::vector
<dmc::Time
> times
;
182 std::mutex times_mtx
;
183 using Guard
= std::lock_guard
<decltype(times_mtx
)>;
185 // reservation every second
186 dmc::ClientInfo
ci(1.0, 0.0, 0.0);
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
) {
196 times
.emplace_back(dmc::get_time());
198 std::thread
complete([&](){ pq
->request_completed(); });
203 pq
= Queue(new dmc::PriorityQueue
<ClientId
,Request
>(client_info_f
,
209 ReqParams
<ClientId
> req_params(client
, 1, 1);
211 for (int i
= 0; i
< 5; ++i
) {
212 pq
->add_request_time(req
, req_params
, dmc::get_time());
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";
225 TEST(dmclock_server
, remove_by_req_filter
) {
236 using ClientId
= int;
237 using Queue
= dmc::PullPriorityQueue
<ClientId
,MyReq
>;
239 ClientId client1
= 17;
240 ClientId client2
= 98;
242 dmc::ClientInfo
info1(0.0, 1.0, 0.0);
244 auto client_info_f
= [&] (ClientId c
) -> dmc::ClientInfo
{
248 Queue
pq(client_info_f
, true);
250 EXPECT_EQ(0u, pq
.client_count());
251 EXPECT_EQ(0u, pq
.request_count());
253 ReqParams
req_params(1,1);
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
);
265 EXPECT_EQ(2u, pq
.client_count());
266 EXPECT_EQ(9u, pq
.request_count());
268 pq
.remove_by_req_filter([](const MyReq
& r
) -> bool {return 1 == r
.id
% 2;});
270 EXPECT_EQ(5u, pq
.request_count());
272 std::list
<MyReq
> capture
;
273 pq
.remove_by_req_filter(
274 [&capture
] (const MyReq
& r
) -> bool {
276 capture
.push_front(r
);
284 EXPECT_EQ(0u, pq
.request_count());
285 EXPECT_EQ(5u, capture
.size());
287 for (auto i
: capture
) {
290 EXPECT_EQ(146, total
) << " sum of captured items should be 146";
294 TEST(dmclock_server
, remove_by_req_filter_ordering_forwards_visit
) {
305 using ClientId
= int;
306 using Queue
= dmc::PullPriorityQueue
<ClientId
,MyReq
>;
308 ClientId client1
= 17;
310 dmc::ClientInfo
info1(0.0, 1.0, 0.0);
312 auto client_info_f
= [&] (ClientId c
) -> dmc::ClientInfo
{
316 Queue
pq(client_info_f
, true);
318 EXPECT_EQ(0u, pq
.client_count());
319 EXPECT_EQ(0u, pq
.request_count());
321 ReqParams
req_params(1,1);
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
);
330 EXPECT_EQ(1u, pq
.client_count());
331 EXPECT_EQ(6u, pq
.request_count());
333 // remove odd ids in forward order and append to end
335 std::vector
<MyReq
> capture
;
336 pq
.remove_by_req_filter(
337 [&capture
] (const MyReq
& r
) -> bool {
339 capture
.push_back(r
);
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";
353 // remove even ids in reverse order but insert at front so comes
356 std::vector
<MyReq
> capture2
;
357 pq
.remove_by_req_filter(
358 [&capture2
] (const MyReq
& r
) -> bool {
360 capture2
.insert(capture2
.begin(), r
);
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";
376 TEST(dmclock_server
, remove_by_req_filter_ordering_backwards_visit
) {
387 using ClientId
= int;
388 using Queue
= dmc::PullPriorityQueue
<ClientId
,MyReq
>;
390 ClientId client1
= 17;
392 dmc::ClientInfo
info1(0.0, 1.0, 0.0);
394 auto client_info_f
= [&] (ClientId c
) -> dmc::ClientInfo
{
398 Queue
pq(client_info_f
, true);
400 EXPECT_EQ(0u, pq
.client_count());
401 EXPECT_EQ(0u, pq
.request_count());
403 ReqParams
req_params(1,1);
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
);
412 EXPECT_EQ(1u, pq
.client_count());
413 EXPECT_EQ(6u, pq
.request_count());
415 // now remove odd ids in forward order
417 std::vector
<MyReq
> capture
;
418 pq
.remove_by_req_filter(
419 [&capture
] (const MyReq
& r
) -> bool {
421 capture
.insert(capture
.begin(), r
);
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";
435 // now remove even ids in reverse order
437 std::vector
<MyReq
> capture2
;
438 pq
.remove_by_req_filter(
439 [&capture2
] (const MyReq
& r
) -> bool {
441 capture2
.push_back(r
);
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";
457 TEST(dmclock_server
, remove_by_client
) {
468 using ClientId
= int;
469 using Queue
= dmc::PullPriorityQueue
<ClientId
,MyReq
>;
471 ClientId client1
= 17;
472 ClientId client2
= 98;
474 dmc::ClientInfo
info1(0.0, 1.0, 0.0);
476 auto client_info_f
= [&] (ClientId c
) -> dmc::ClientInfo
{
480 Queue
pq(client_info_f
, true);
482 EXPECT_EQ(0u, pq
.client_count());
483 EXPECT_EQ(0u, pq
.request_count());
485 ReqParams
req_params(1,1);
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
);
497 EXPECT_EQ(2u, pq
.client_count());
498 EXPECT_EQ(9u, pq
.request_count());
500 std::list
<MyReq
> removed
;
502 pq
.remove_by_client(client1
,
504 [&removed
] (const MyReq
& r
) {
505 removed
.push_front(r
);
508 EXPECT_EQ(3u, removed
.size());
509 EXPECT_EQ(1, removed
.front().id
);
511 EXPECT_EQ(11, removed
.front().id
);
513 EXPECT_EQ(44, removed
.front().id
);
516 EXPECT_EQ(6u, pq
.request_count());
518 Queue::PullReq pr
= pq
.pull_request();
519 EXPECT_TRUE(pr
.is_retn());
520 EXPECT_EQ(2, pr
.get_retn().request
->id
);
522 pr
= pq
.pull_request();
523 EXPECT_TRUE(pr
.is_retn());
524 EXPECT_EQ(0, pr
.get_retn().request
->id
);
526 pq
.remove_by_client(client2
);
527 EXPECT_EQ(0u, pq
.request_count()) <<
528 "after second client removed, none left";
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
>;
537 ClientId client1
= 17;
538 ClientId client2
= 98;
540 dmc::ClientInfo
info1(0.0, 1.0, 0.0);
541 dmc::ClientInfo
info2(0.0, 2.0, 0.0);
545 auto client_info_f
= [&] (ClientId c
) -> dmc::ClientInfo
{
546 if (client1
== c
) return info1
;
547 else if (client2
== c
) return info2
;
549 ADD_FAILURE() << "client info looked up for non-existant client";
554 pq
= QueueRef(new Queue(client_info_f
, false));
556 ReqParams
req_params(1,1);
558 auto now
= dmc::get_time();
560 for (int i
= 0; i
< 5; ++i
) {
561 pq
->add_request(Request
{}, client1
, req_params
);
562 pq
->add_request(Request
{}, client2
, req_params
);
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
);
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";
577 EXPECT_EQ(PhaseType::priority
, retn
.phase
);
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";
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
>;
592 ClientId client1
= 52;
593 ClientId client2
= 8;
595 dmc::ClientInfo
info1(2.0, 0.0, 0.0);
596 dmc::ClientInfo
info2(1.0, 0.0, 0.0);
598 auto client_info_f
= [&] (ClientId c
) -> dmc::ClientInfo
{
599 if (client1
== c
) return info1
;
600 else if (client2
== c
) return info2
;
602 ADD_FAILURE() << "client info looked up for non-existant client";
607 QueueRef
pq(new Queue(client_info_f
, false));
609 ReqParams
req_params(1,1);
611 // make sure all times are well before now
612 auto old_time
= dmc::get_time() - 100.0;
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
);
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
);
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";
632 EXPECT_EQ(PhaseType::reservation
, retn
.phase
);
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
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
>;
650 ClientId client1
= 52;
651 ClientId client2
= 8;
653 dmc::ClientInfo
info1(1.0, 0.0, 0.0);
654 dmc::ClientInfo
info2(1.0, 0.0, 0.0);
656 auto client_info_f
= [&] (ClientId c
) -> dmc::ClientInfo
{
657 if (client1
== c
) return info1
;
658 else if (client2
== c
) return info2
;
660 ADD_FAILURE() << "client info looked up for non-existant client";
665 QueueRef
pq(new Queue(client_info_f
, false));
667 ReqParams
req_params(1,1);
669 // make sure all times are well before now
670 auto start_time
= dmc::get_time() - 100.0;
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
);
678 Queue::PullReq pr
= pq
->pull_request(start_time
+ 0.5);
679 EXPECT_EQ(Queue::NextReqType::returning
, pr
.type
);
681 pr
= pq
->pull_request(start_time
+ 0.5);
682 EXPECT_EQ(Queue::NextReqType::returning
, pr
.type
);
684 pr
= pq
->pull_request(start_time
+ 0.5);
685 EXPECT_EQ(Queue::NextReqType::future
, pr
.type
) <<
686 "too soon for next reservation";
688 pr
= pq
->pull_request(start_time
+ 1.5);
689 EXPECT_EQ(Queue::NextReqType::returning
, pr
.type
);
691 pr
= pq
->pull_request(start_time
+ 1.5);
692 EXPECT_EQ(Queue::NextReqType::returning
, pr
.type
);
694 pr
= pq
->pull_request(start_time
+ 1.5);
695 EXPECT_EQ(Queue::NextReqType::future
, pr
.type
) <<
696 "too soon for next reservation";
698 pr
= pq
->pull_request(start_time
+ 2.5);
699 EXPECT_EQ(Queue::NextReqType::returning
, pr
.type
);
701 pr
= pq
->pull_request(start_time
+ 2.5);
702 EXPECT_EQ(Queue::NextReqType::returning
, pr
.type
);
704 pr
= pq
->pull_request(start_time
+ 2.5);
705 EXPECT_EQ(Queue::NextReqType::none
, pr
.type
) << "no more requests left";
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
>;
714 dmc::ClientInfo
info(1.0, 1.0, 1.0);
716 auto client_info_f
= [&] (ClientId c
) -> dmc::ClientInfo
{
720 QueueRef
pq(new Queue(client_info_f
, false));
723 ReqParams
req_params(1,1);
725 auto now
= dmc::get_time();
727 Queue::PullReq pr
= pq
->pull_request(now
+ 100);
729 EXPECT_EQ(Queue::NextReqType::none
, pr
.type
);
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
>;
738 ClientId client1
= 52;
739 // ClientId client2 = 8;
741 dmc::ClientInfo
info(1.0, 0.0, 1.0);
743 auto client_info_f
= [&] (ClientId c
) -> dmc::ClientInfo
{
747 QueueRef
pq(new Queue(client_info_f
, false));
749 ReqParams
req_params(1,1);
751 // make sure all times are well before now
752 auto now
= dmc::get_time();
754 pq
->add_request_time(Request
{}, client1
, req_params
, now
+ 100);
755 Queue::PullReq pr
= pq
->pull_request(now
);
757 EXPECT_EQ(Queue::NextReqType::future
, pr
.type
);
759 Time when
= boost::get
<Time
>(pr
.data
);
760 EXPECT_EQ(now
+ 100, when
);
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
>;
769 ClientId client1
= 52;
770 // ClientId client2 = 8;
772 dmc::ClientInfo
info(0.0, 1.0, 1.0);
774 auto client_info_f
= [&] (ClientId c
) -> dmc::ClientInfo
{
778 QueueRef
pq(new Queue(client_info_f
, true));
780 ReqParams
req_params(1,1);
782 // make sure all times are well before now
783 auto now
= dmc::get_time();
785 pq
->add_request_time(Request
{}, client1
, req_params
, now
+ 100);
786 Queue::PullReq pr
= pq
->pull_request(now
);
788 EXPECT_EQ(Queue::NextReqType::returning
, pr
.type
);
790 auto& retn
= boost::get
<Queue::PullReq::Retn
>(pr
.data
);
791 EXPECT_EQ(client1
, retn
.client
);
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
>;
800 ClientId client1
= 52;
801 // ClientId client2 = 8;
803 dmc::ClientInfo
info(1.0, 0.0, 1.0);
805 auto client_info_f
= [&] (ClientId c
) -> dmc::ClientInfo
{
809 QueueRef
pq(new Queue(client_info_f
, true));
811 ReqParams
req_params(1,1);
813 // make sure all times are well before now
814 auto now
= dmc::get_time();
816 pq
->add_request_time(Request
{}, client1
, req_params
, now
+ 100);
817 Queue::PullReq pr
= pq
->pull_request(now
);
819 EXPECT_EQ(Queue::NextReqType::returning
, pr
.type
);
821 auto& retn
= boost::get
<Queue::PullReq::Retn
>(pr
.data
);
822 EXPECT_EQ(client1
, retn
.client
);
824 } // namespace dmclock
825 } // namespace crimson