27 static char* fakeTxn = (
char*)0xface0000;
43 return std::uniform_int_distribution<uint32_t>(0, max - 1)(rng);
50 using IDList = std::list<std::pair<HTTPCodec::StreamID, uint8_t>>;
60 bool pnode=
false,
uint64_t* depth =
nullptr) {
63 id, pri, pnode ?
nullptr : makeFakeTxn(
id),
false, depth);
64 handles_.insert(std::make_pair(
id, h));
71 q_.removeTransaction(handles_[
id]);
76 handles_[id] = q_.updatePriority(handles_[
id], pri, depth);
81 q_.signalPendingEgress(handles_[
id]);
83 q_.clearPendingEgress(handles_[
id]);
88 addTransaction(1, {0,
false, 15});
89 addTransaction(3, {1,
false, 3});
90 addTransaction(5, {1,
false, 3});
91 addTransaction(7, {1,
false, 7});
92 addTransaction(9, {5,
false, 7});
97 nodes_.push_back(std::make_pair(
id, r * 100));
103 q_.iterate(
std::bind(&QueueTest::visitNode,
this, std::ref(q_), _1, _2, _3),
104 [] {
return false; },
true);
107 void dumpBFS(
const std::function<
bool()>& stopFn) {
109 q_.iterateBFS(
std::bind(&QueueTest::visitNode,
this, _1, _2, _3, _4),
115 q_.nextEgress(nextEgressResults, spdyMode);
117 for (
auto p: nextEgressResults) {
118 nodes_.push_back(std::make_pair(getTxnID(p.first), p.second * 100));
123 std::map<HTTPCodec::StreamID, HTTP2PriorityQueue::Handle>
handles_;
131 EXPECT_EQ(nodes_,
IDList({{1, 100}, {3, 25}, {5, 25}, {9, 100}, {7, 50}}));
135 addTransaction(11, {7,
false, 15},
false, &depth);
142 removeTransaction(3);
151 removeTransaction(5);
159 addTransaction(1, {0,
false, 0});
160 addTransaction(3, {1,
false, 255});
161 addTransaction(5, {1,
false, 255});
163 removeTransaction(1);
171 addTransaction(1, {0,
false, 15},
false, &depth);
174 addTransaction(3, {1,
false, 3},
false, &depth);
177 addTransaction(5, {3,
true, 7},
false, &depth);
180 addTransaction(9, {1,
false, 3},
true, &depth);
186 addTransaction(9, {1,
false, 31},
false, &depth);
191 addTransaction(11, {1,
true, 7},
false, &depth);
196 addTransaction(13, {0,
true, 23},
true, &depth);
202 addTransaction(13, {0,
true, 33},
false, &depth);
212 updatePriority(5, {1,
false, 7}, &depth);
215 EXPECT_EQ(nodes_,
IDList({{1, 100}, {3, 20}, {5, 40}, {9, 100}, {7, 40}}));
222 q_.addOrUpdatePriorityNode(1, {0,
false, 15});
223 addTransaction(1, {0,
true, 15});
224 q_.addOrUpdatePriorityNode(3, {1,
false, 15});
225 addTransaction(5, {3,
false, 15});
226 addTransaction(3, {5,
false, 15});
227 removeTransaction(5);
237 addTransaction(1, {0,
false, 7});
238 addTransaction(3, {0,
false, 7});
240 signalEgress(1,
false);
241 signalEgress(3,
false);
243 updatePriority(1, {3,
false, 7}, &depth);
253 updatePriority(5, {1,
true, 7});
256 EXPECT_EQ(nodes_,
IDList({{1, 100}, {5, 100}, {9, 40}, {3, 20}, {7, 40}}));
257 signalEgress(1,
false);
265 signalEgress(5,
false);
266 updatePriority(5, {1,
true, 7});
267 signalEgress(1,
false);
277 updatePriority(5, {97,
false, 15}, &depth);
282 IDList({{1, 50}, {3, 33}, {7, 66}, {97, 50}, {5, 100}, {9, 100}})
287 updatePriority(9, {99,
false, 15}, &depth);
292 IDList({{1, 33}, {3, 33}, {7, 66}, {97, 33}, {5, 100}, {99, 33}, {9, 100}})
300 updatePriority(5, {3,
false, 3});
304 {9, 100}, {7, 66}}));
305 signalEgress(1,
false);
311 signalEgress(5,
false);
312 updatePriority(5, {1,
false, 3});
315 EXPECT_EQ(nodes_,
IDList({{1, 100}, {3, 25}, {7, 50}, {5, 25}, {9, 100}}));
324 updatePriority(7, {5,
true, 3});
328 {7, 100}, {9, 100}}));
329 signalEgress(1,
false);
330 signalEgress(3,
false);
331 signalEgress(5,
false);
339 updatePriority(9, {0,
false, 15});
342 EXPECT_EQ(nodes_,
IDList({{1, 50}, {3, 25}, {5, 25}, {7, 50}, {9, 50}}));
350 updatePriority(9, {0,
true, 15});
353 EXPECT_EQ(nodes_,
IDList({{9, 100}, {1, 100}, {3, 25}, {5, 25}, {7, 50}}));
361 updatePriority(1, {5,
false, 7});
364 EXPECT_EQ(nodes_,
IDList({{5, 100}, {9, 50}, {1, 50}, {3, 33}, {7, 66}}));
367 signalEgress(5,
false);
375 updatePriority(1, {5,
true, 7});
378 EXPECT_EQ(nodes_,
IDList({{5, 100}, {1, 100}, {3, 20}, {7, 40}, {9, 40}}));
381 signalEgress(5,
false);
382 signalEgress(1,
false);
390 addTransaction(11, {1,
true, 100});
394 {1, 100}, {11, 100}, {3, 25}, {5, 25}, {9, 100}, {7, 50}
401 addTransaction(11, {75,
false, 15});
405 {1, 50}, {3, 25}, {5, 25}, {9, 100}, {7, 50}, {75, 50}, {11, 100}
410 addTransaction(75, {1,
false, 7});
414 {1, 100}, {3, 16}, {5, 16}, {9, 100}, {7, 33}, {75, 33}, {11, 100}
419 addTransaction(1, {0,
false, 255});
430 signalEgress(1,
false);
433 removeTransaction(9);
434 removeTransaction(1);
442 auto stopFn = [
this] {
443 return nodes_.size() > 2;
456 addTransaction(11, {7,
false, 15});
457 signalEgress(1,
false);
462 signalEgress(5,
false);
465 signalEgress(5,
true);
467 signalEgress(3,
false);
471 signalEgress(5,
false);
475 signalEgress(7,
false);
479 signalEgress(9,
false);
483 signalEgress(3,
true);
484 signalEgress(7,
true);
485 signalEgress(9,
true);
494 signalEgress(1,
false);
495 signalEgress(3,
false);
496 signalEgress(5,
false);
497 signalEgress(7,
false);
498 signalEgress(9,
false);
501 addTransaction(11, {1,
true, 100});
502 signalEgress(11,
false);
505 signalEgress(3,
true);
515 signalEgress(1,
false);
516 signalEgress(5,
false);
517 signalEgress(7,
false);
518 signalEgress(9,
false);
521 addTransaction(11, {1,
true, 100});
522 signalEgress(11,
false);
532 signalEgress(1,
false);
533 signalEgress(3,
false);
534 signalEgress(5,
false);
535 signalEgress(7,
false);
538 updatePriority(5, {1,
false, 14},
nullptr);
541 updatePriority(9, {3,
false, 14},
nullptr);
551 signalEgress(1,
false);
552 signalEgress(3,
false);
553 signalEgress(5,
false);
554 signalEgress(7,
false);
557 removeTransaction(5);
562 signalEgress(3,
true);
563 signalEgress(7,
true);
570 addTransaction(1, {0,
false, 100});
571 addTransaction(3, {1,
false, 100});
572 addTransaction(5, {3,
false, 100});
573 signalEgress(1,
false);
574 signalEgress(3,
false);
577 addTransaction(7, {1,
true, 100});
583 addTransaction(1, {0,
false, 100});
584 addTransaction(3, {1,
false, 100});
585 addTransaction(5, {3,
false, 100});
586 signalEgress(3,
false);
589 removeTransaction(3);
590 signalEgress(1,
false);
596 addTransaction(1, {0,
false, 100});
597 addTransaction(3, {1,
false, 100});
598 addTransaction(5, {3,
false, 100});
599 addTransaction(7, {1,
false, 100});
600 signalEgress(3,
false);
601 signalEgress(1,
false);
604 removeTransaction(3);
615 addTransaction(1, {0,
true, 99});
616 signalEgress(1,
false);
617 addTransaction(3, {1,
true, 99});
618 signalEgress(3,
false);
619 addTransaction(5, {3,
true, 99});
620 signalEgress(5,
false);
622 std::vector<HTTPCodec::StreamID> txns;
623 std::vector<HTTPCodec::StreamID> active;
624 std::vector<HTTPCodec::StreamID> inactive;
628 auto gen = Random::create();
630 for (
auto i = 4;
i < 1000;
i++) {
638 VLOG(2) <<
"Adding txn=" << txn <<
" with dep=" << dep;
639 addTransaction(txn, {(
uint32_t)dep,
true, 99});
641 active.push_back(txn);
642 }
else if (action == 1 && !inactive.empty()) {
644 idx = rand32(inactive.size(), gen);
646 VLOG(2) <<
"Activating txn=" << txn;
647 signalEgress(txn,
true);
648 inactive.erase(inactive.begin() + idx);
649 active.push_back(txn);
650 }
else if (action == 2 && !active.empty()) {
652 idx = rand32(active.size(), gen);
654 VLOG(2) <<
"Deactivating txn=" << txn;
655 signalEgress(txn,
false);
656 active.erase(active.begin() + idx);
657 inactive.push_back(txn);
658 }
else if (action == 3 && !txns.empty()) {
660 idx = rand32(txns.size(), gen);
662 VLOG(2) <<
"Removing txn=" << txn;
663 removeTransaction(txn);
664 txns.erase(txns.begin() + idx);
665 auto it = std::find(active.begin(), active.end(), txn);
666 if (it != active.end()) {
669 it = std::find(inactive.begin(), inactive.end(), txn);
670 if (it != inactive.end()) {
674 VLOG(2) <<
"Active nodes=" << q_.numPendingEgress();
685 addTransaction(1, {0,
false, 0},
true);
686 addTransaction(3, {1,
false, 0},
true);
689 addTransaction(7, {1,
false, 15});
690 addTransaction(9, {1,
false, 15});
691 addTransaction(11, {3,
false, 15});
692 addTransaction(13, {3,
false, 15});
697 signalEgress(7,
false);
701 signalEgress(9,
false);
707 q_.addOrUpdatePriorityNode(1, {0,
false, 15});
708 q_.addOrUpdatePriorityNode(3, {0,
false, 15});
711 q_.addOrUpdatePriorityNode(1, {0,
false, 3});
720 HTTP2PriorityQueue::setNodeLifetime(
721 std::chrono::milliseconds(2 * HHWheelTimer::DEFAULT_TICK_INTERVAL - 1));
724 std::chrono::milliseconds) {
725 timeouts_.push_back(timeout);
732 std::this_thread::sleep_for(
733 std::chrono::milliseconds(2 * HHWheelTimer::DEFAULT_TICK_INTERVAL));
740 std::list<folly::AsyncTimeout*> timeouts;
742 for (
auto timeout: timeouts) {
743 timeout->timeoutExpired();
764 addTransaction(1, {0,
false, 15});
765 removeTransaction(1);
774 addTransaction(1, {0,
false, 15},
true);
775 addTransaction(3, {1,
false, 15},
true);
776 addTransaction(5, {3,
false, 15},
true);
791 addTransaction(1, {0,
false, 15},
true);
792 addTransaction(3, {0,
false, 15},
true);
793 addTransaction(5, {1,
false, 15},
true);
795 q_.dropPriorityNodes();
801 addTransaction(1, {0,
true, 219},
false);
802 addTransaction(3, {1,
false, 146},
false);
803 addTransaction(5, {1,
false, 146},
false);
804 signalEgress(3,
false);
805 signalEgress(5,
true);
806 removeTransaction(1);
824 timer_.scheduleTimeout(&t, std::chrono::seconds(300));
825 addTransaction(1, {0,
false, 15});
826 addTransaction(3, {0,
false, 15});
828 removeTransaction(1);
833 updatePriority(1, {0,
false, 3});
847 q_.setMaxVirtualNodes(3);
848 for (
auto i = 1;
i <= 9;
i += 2) {
849 removeTransaction(
i);
866 EXPECT_EQ(nodes_,
IDList({{3, 20}, {9, 20}, {5, 20}, {7, 20}, {1, 20}}));
std::list< std::pair< HTTPCodec::StreamID, uint8_t >> IDList
std::list< folly::AsyncTimeout * > timeouts_
QueueTest(HHWheelTimer *timer=nullptr)
bool visitNode(HTTP2PriorityQueue &, HTTPCodec::StreamID id, HTTPTransaction *, double r)
std::vector< std::pair< HTTPTransaction *, double >> NextEgressResult
void timeoutExpired() noexceptoverride
#define EXPECT_EQ(val1, val2)
requires E e noexcept(noexcept(s.error(std::move(e))))
stop_watch< std::chrono::milliseconds > timer_
void updatePriority(HTTPCodec::StreamID id, http2::PriorityUpdate pri, uint64_t *depth=nullptr)
PolymorphicAction< internal::InvokeAction< FunctionImpl > > Invoke(FunctionImpl function_impl)
void nextEgress(bool spdyMode=false)
std::array< uint8_t, 32 > Random
void addTransaction(HTTPCodec::StreamID id, http2::PriorityUpdate pri, bool pnode=false, uint64_t *depth=nullptr)
void dumpBFS(const std::function< bool()> &stopFn)
std::mt19937 DefaultGenerator
int bind(NetworkSocket s, const sockaddr *name, socklen_t namelen)
#define EXPECT_CALL(obj, call)
const internal::AnythingMatcher _
void swap(SwapTrackingAlloc< T > &, SwapTrackingAlloc< T > &)
#define EXPECT_FALSE(condition)
void signalEgress(HTTPCodec::StreamID id, bool mark)
testing::NiceMock< MockTimeoutManager > timeoutManager_
std::map< HTTPCodec::StreamID, HTTP2PriorityQueue::Handle > handles_
void removeTransaction(HTTPCodec::StreamID id)
TEST_F(QueueTest, Rebuild)
#define EXPECT_GT(val1, val2)