TEST(RequestContext, SimpleTest) { TEventBase base; EXPECT_FALSE(RequestContext::create()); EXPECT_TRUE(RequestContext::create()); EXPECT_TRUE(RequestContext::get() != nullptr); EXPECT_EQ(nullptr, RequestContext::get()->getContextData("test")); RequestContext::get()->setContextData( "test", std::unique_ptr<TestData>(new TestData(10))); base.runInEventBaseThread([&](){ EXPECT_TRUE(RequestContext::get() != nullptr); auto data = dynamic_cast<TestData*>( RequestContext::get()->getContextData("test"))->data_; EXPECT_EQ(10, data); base.terminateLoopSoon(); }); auto th = std::thread([&](){ base.loopForever(); }); th.join(); EXPECT_TRUE(RequestContext::get() != nullptr); auto a = dynamic_cast<TestData*>( RequestContext::get()->getContextData("test")); auto data = a->data_; EXPECT_EQ(10, data); RequestContext::setContext(std::shared_ptr<RequestContext>()); // There should always be a default context EXPECT_TRUE(nullptr != RequestContext::get()); }
void async_tm_update(unique_ptr<HandlerCallback<int32_t>> callback, int32_t currentIndex) override { auto callbackp = callback.release(); EXPECT_EQ(currentIndex, expectIndex_); expectIndex_++; TEventBase *eb = callbackp->getEventBase(); callbackp->resultInThread(currentIndex); if (expectIndex_ == lastIndex_) { success_ = true; eb->runInEventBaseThread([eb] { eb->terminateLoopSoon(); }); } }
void QueueTest::multiConsumer() { uint32_t numConsumers = 8; int numMessages = 10000; // Create several consumers each running in their own TEventBase thread vector<QueueConsumer> consumers(numConsumers); vector<ScopedEventBaseThread> threads(numConsumers); for (uint32_t consumerIdx = 0; consumerIdx < numConsumers; ++consumerIdx) { QueueConsumer* consumer = &consumers[consumerIdx]; consumer->fn = [consumer, consumerIdx, this](int value) { // Treat 0 as a signal to stop. if (value == 0) { consumer->stopConsuming(); // Put a message on the terminationQueue to indicate we have stopped terminationQueue.putMessage(consumerIdx); } }; TEventBase* eventBase = threads[consumerIdx].getEventBase(); eventBase->runInEventBaseThread([eventBase, consumer, this] { consumer->startConsuming(eventBase, &queue); }); } // Now add a number of messages from this thread // Start at 1 rather than 0, since 0 is the signal to stop. for (int n = 1; n < numMessages; ++n) { queue.putMessage(n); } // Now add a 0 for each consumer, to signal them to stop for (int n = 0; n < numConsumers; ++n) { queue.putMessage(0); } // Wait until we get notified that all of the consumers have stopped // We use a separate notification queue for this. QueueConsumer terminationConsumer; vector<uint32_t> consumersStopped(numConsumers, 0); uint32_t consumersRemaining = numConsumers; terminationConsumer.fn = [&](int consumerIdx) { --consumersRemaining; if (consumersRemaining == 0) { terminationConsumer.stopConsuming(); } BOOST_REQUIRE(consumerIdx >= 0); BOOST_REQUIRE(consumerIdx < numConsumers); ++consumersStopped[consumerIdx]; }; TEventBase eventBase; terminationConsumer.startConsuming(&eventBase, &terminationQueue); eventBase.loop(); // Verify that we saw exactly 1 stop message for each consumer for (uint32_t n = 0; n < numConsumers; ++n) { BOOST_CHECK_EQUAL(consumersStopped[n], 1); } // Validate that every message sent to the main queue was received exactly // once. vector<int> messageCount(numMessages, 0); for (uint32_t n = 0; n < numConsumers; ++n) { for (int msg : consumers[n].messages) { BOOST_REQUIRE(msg >= 0); BOOST_REQUIRE(msg < numMessages); ++messageCount[msg]; } } // 0 is the signal to stop, and should have been received once by each // consumer BOOST_CHECK_EQUAL(messageCount[0], numConsumers); // All other messages should have been received exactly once for (int n = 1; n < numMessages; ++n) { BOOST_CHECK_EQUAL(messageCount[n], 1); } }