TEST(ThriftServer, IdleTimeoutAfterTest) { ScopedServerThread sst(getServer()); TEventBase base; std::shared_ptr<TAsyncSocket> socket( TAsyncSocket::newSocket(&base, *sst.getAddress())); auto client_channel = HeaderClientChannel::newChannel(socket); auto client_channelp = client_channel.get(); CloseChecker checker; client_channel->setCloseCallback(&checker); TestServiceAsyncClient client(std::move(client_channel)); std::string ret; client.sync_sendResponse(ret, 20); EXPECT_FALSE(checker.getClosed()); base.tryRunAfterDelay([&base](){ base.terminateLoopSoon(); }, 200); base.loopForever(); EXPECT_TRUE(checker.getClosed()); client_channelp->setCloseCallback(nullptr); }
/** * Test SSL server accept timeout with cache path */ TEST(TAsyncSSLSocketTest, SSLServerCacheCloseTest) { // Start listening on a local port WriteCallbackBase writeCallback; ReadCallback readCallback(&writeCallback); HandshakeCallback handshakeCallback(&readCallback, HandshakeCallback::EXPECT_ERROR); SSLServerAsyncCacheAcceptCallback acceptCallback(&handshakeCallback); TestSSLAsyncCacheServer server(&acceptCallback, 500); // Set up SSL client TEventBase eventBase; std::shared_ptr<SSLClient> client(new SSLClient(&eventBase, server.getAddress(), 2, 100)); client->connect(); EventBaseAborter eba(&eventBase, 3000); eventBase.loop(); server.getEventBase().runInEventBaseThread([&handshakeCallback]{ handshakeCallback.closeSocket();}); // give time for the cache lookup to come back and find it closed usleep(500000); EXPECT_EQ(server.getAsyncCallbacks(), 1); EXPECT_EQ(server.getAsyncLookups(), 1); EXPECT_EQ(client->getErrors(), 1); EXPECT_EQ(client->getMiss(), 1); EXPECT_EQ(client->getHit(), 0); cerr << "SSLServerCacheCloseTest test completed" << endl; }
/* * Test some timeouts that are scheduled on one timeout set, then moved to * another timeout set. */ TEST(TAsyncTimeoutSetTest, SwitchTimeoutSet) { TEventBase eventBase; StackTimeoutSet ts10(&eventBase, milliseconds(10)); StackTimeoutSet ts5(&eventBase, milliseconds(5)); TestTimeout t1(&ts5, &ts10, &ts5); TestTimeout t2(&ts10, &ts10, &ts5); TestTimeout t3(&ts5, &ts5, &ts10, &ts5); ts5.scheduleTimeout(&t1); TimePoint start; eventBase.loop(); TimePoint end; ASSERT_EQ(t1.timestamps.size(), 3); ASSERT_EQ(t2.timestamps.size(), 3); ASSERT_EQ(t3.timestamps.size(), 4); T_CHECK_TIMEOUT(start, t1.timestamps[0], milliseconds(5)); T_CHECK_TIMEOUT(t1.timestamps[0], t1.timestamps[1], milliseconds(10)); T_CHECK_TIMEOUT(t1.timestamps[1], t1.timestamps[2], milliseconds(5)); T_CHECK_TIMEOUT(start, t2.timestamps[0], milliseconds(10)); T_CHECK_TIMEOUT(t2.timestamps[0], t2.timestamps[1], milliseconds(10)); T_CHECK_TIMEOUT(t2.timestamps[1], t2.timestamps[2], milliseconds(5)); T_CHECK_TIMEOUT(start, t3.timestamps[0], milliseconds(5)); T_CHECK_TIMEOUT(t3.timestamps[0], t3.timestamps[1], milliseconds(5)); T_CHECK_TIMEOUT(t3.timestamps[1], t3.timestamps[2], milliseconds(10)); T_CHECK_TIMEOUT(t3.timestamps[2], t3.timestamps[3], milliseconds(5)); // 10ms fudge factor to account for loaded machines T_CHECK_TIMEOUT(start, end, milliseconds(25), milliseconds(10)); }
/** * 1. Client does not send TLSEXT_HOSTNAME in client hello. * 2. Server does not send back TLSEXT_HOSTNAME in server hello. */ TEST(TAsyncSSLSocketTest, SNITestClientHelloNoHostname) { TEventBase eventBase; std::shared_ptr<SSLContext> clientCtx(new SSLContext); std::shared_ptr<SSLContext> dfServerCtx(new SSLContext); // Use the same SSLContext to continue the handshake after // tlsext_hostname match. std::shared_ptr<SSLContext> hskServerCtx(dfServerCtx); const std::string serverExpectedServerName("xyz.newdev.facebook.com"); int fds[2]; getfds(fds); getctx(clientCtx, dfServerCtx); TAsyncSSLSocket::UniquePtr clientSock( new TAsyncSSLSocket(clientCtx, &eventBase, fds[0], false)); TAsyncSSLSocket::UniquePtr serverSock( new TAsyncSSLSocket(dfServerCtx, &eventBase, fds[1], true)); SNIClient client(std::move(clientSock)); SNIServer server(std::move(serverSock), dfServerCtx, hskServerCtx, serverExpectedServerName); eventBase.loop(); EXPECT_TRUE(!client.serverNameMatch); EXPECT_TRUE(!server.serverNameMatch); }
/** * Test SSL client socket timeout */ TEST(TAsyncSSLSocketTest, SSLClientTimeoutTest) { // Start listening on a local port EmptyReadCallback readCallback; HandshakeCallback handshakeCallback(&readCallback, HandshakeCallback::EXPECT_ERROR); HandshakeTimeoutCallback acceptCallback(&handshakeCallback); TestSSLServer server(&acceptCallback); // Set up SSL client TEventBase eventBase; std::shared_ptr<SSLClient> client(new SSLClient(&eventBase, server.getAddress(), 1, 10)); client->connect(true /* write before connect completes */); EventBaseAborter eba(&eventBase, 3000); eventBase.loop(); usleep(100000); // This is checking that the connectError callback precedes any queued // writeError callbacks. This matches TAsyncSocket's behavior EXPECT_EQ(client->getWriteAfterConnectErrors(), 1); EXPECT_EQ(client->getErrors(), 1); EXPECT_EQ(client->getMiss(), 0); EXPECT_EQ(client->getHit(), 0); cerr << "SSLClientTimeoutTest test completed" << endl; }
TEST(TAsyncSSLSocketTest, NpnTestNoOverlap) { TEventBase eventBase; std::shared_ptr<SSLContext> clientCtx(new SSLContext); std::shared_ptr<SSLContext> serverCtx(new SSLContext);; int fds[2]; getfds(fds); getctx(clientCtx, serverCtx); clientCtx->setAdvertisedNextProtocols({"blub"}); serverCtx->setAdvertisedNextProtocols({"foo","bar","baz"}); TAsyncSSLSocket::UniquePtr clientSock( new TAsyncSSLSocket(clientCtx, &eventBase, fds[0], false)); TAsyncSSLSocket::UniquePtr serverSock( new TAsyncSSLSocket(serverCtx, &eventBase, fds[1], true)); NpnClient client(std::move(clientSock)); NpnServer server(std::move(serverSock)); eventBase.loop(); EXPECT_TRUE(client.nextProtoLength != 0); EXPECT_EQ(client.nextProtoLength, server.nextProtoLength); EXPECT_EQ(memcmp(client.nextProto, server.nextProto, server.nextProtoLength), 0); string selected((const char*)client.nextProto, client.nextProtoLength); EXPECT_EQ(selected.compare("blub"), 0); }
TEST(TAsyncSSLSocketTest, NpnTestUnset) { // Identical to above test, except that we want unset NPN before // looping. TEventBase eventBase; std::shared_ptr<SSLContext> clientCtx(new SSLContext); std::shared_ptr<SSLContext> serverCtx(new SSLContext);; int fds[2]; getfds(fds); getctx(clientCtx, serverCtx); clientCtx->setAdvertisedNextProtocols({"blub","baz"}); serverCtx->setAdvertisedNextProtocols({"foo","bar","baz"}); TAsyncSSLSocket::UniquePtr clientSock( new TAsyncSSLSocket(clientCtx, &eventBase, fds[0], false)); TAsyncSSLSocket::UniquePtr serverSock( new TAsyncSSLSocket(serverCtx, &eventBase, fds[1], true)); // unsetting NPN for any of [client, server] is enought to make NPN not // work clientCtx->unsetNextProtocols(); NpnClient client(std::move(clientSock)); NpnServer server(std::move(serverSock)); eventBase.loop(); EXPECT_TRUE(client.nextProtoLength == 0); EXPECT_TRUE(server.nextProtoLength == 0); EXPECT_TRUE(client.nextProto == nullptr); EXPECT_TRUE(server.nextProto == nullptr); }
TEST(ThriftServer, OnewayFutureClientTest) { using std::chrono::steady_clock; ScopedServerThread sst(getServer()); TEventBase base; std::shared_ptr<TAsyncSocket> socket( TAsyncSocket::newSocket(&base, *sst.getAddress())); FutureServiceAsyncClient client( std::unique_ptr<HeaderClientChannel, apache::thrift::async::TDelayedDestruction::Destructor>( new HeaderClientChannel(socket))); auto future = client.future_noResponse(1000); steady_clock::time_point sent = steady_clock::now(); // wait for future to finish. base.loop(); steady_clock::time_point waited = steady_clock::now(); future.value(); steady_clock::time_point got = steady_clock::now(); steady_clock::duration waitTime = waited - sent; steady_clock::duration gotTime = got - waited; int factor = 1; EXPECT_GE(waitTime, factor * gotTime); }
/** * Test SSL server accept timeout with cache path */ TEST(TAsyncSSLSocketTest, SSLServerAsyncCacheTimeoutTest) { // Start listening on a local port WriteCallbackBase writeCallback; ReadCallback readCallback(&writeCallback); HandshakeCallback handshakeCallback(&readCallback); SSLServerAsyncCacheAcceptCallback acceptCallback(&handshakeCallback, 50); TestSSLAsyncCacheServer server(&acceptCallback); // Set up SSL client TEventBase eventBase; std::shared_ptr<SSLClient> client(new SSLClient(&eventBase, server.getAddress(), 2)); client->connect(); EventBaseAborter eba(&eventBase, 3000); eventBase.loop(); EXPECT_EQ(server.getAsyncCallbacks(), 1); EXPECT_EQ(server.getAsyncLookups(), 1); EXPECT_EQ(client->getErrors(), 1); EXPECT_EQ(client->getMiss(), 1); EXPECT_EQ(client->getHit(), 0); cerr << "SSLServerAsyncCacheTimeoutTest test completed" << endl; }
/** * Verify that specifying that no validation should be performed allows an * otherwise-invalid certificate to be accepted and doesn't fire the validation * callback. */ TEST(TAsyncSSLSocketTest, SSLHandshakeValidationSkip) { TEventBase eventBase; auto clientCtx = std::make_shared<SSLContext>(); auto dfServerCtx = std::make_shared<SSLContext>(); int fds[2]; getfds(fds); getctx(clientCtx, dfServerCtx); clientCtx->setVerificationOption(SSLContext::SSLVerifyPeerEnum::NO_VERIFY); dfServerCtx->setVerificationOption(SSLContext::SSLVerifyPeerEnum::NO_VERIFY); TAsyncSSLSocket::UniquePtr clientSock( new TAsyncSSLSocket(clientCtx, &eventBase, fds[0], false)); TAsyncSSLSocket::UniquePtr serverSock( new TAsyncSSLSocket(dfServerCtx, &eventBase, fds[1], true)); SSLHandshakeClient client(std::move(clientSock), false, false); SSLHandshakeServer server(std::move(serverSock), false, false); eventBase.loop(); EXPECT_TRUE(!client.handshakeVerify_); EXPECT_TRUE(client.handshakeSuccess_); EXPECT_TRUE(!client.handshakeError_); EXPECT_TRUE(!server.handshakeVerify_); EXPECT_TRUE(server.handshakeSuccess_); EXPECT_TRUE(!server.handshakeError_); }
// Test if multiple requests are pending in a queue, for security to establish, // then we flow RequestContext correctly with each request. void runRequestContextTest(bool failSecurity) { ScopedServerThread sst(getServer()); TEventBase base; auto channel = getClientChannel(&base, *sst.getAddress(), failSecurity); TestServiceAsyncClient client(std::move(channel)); Countdown c(2, [&base](){base.terminateLoopSoon();}); // Send first request with a unique RequestContext. This would trigger // security. Rest of the request would queue behind it. folly::RequestContext::create(); folly::RequestContext::get()->setContextData("first", nullptr); client.sendResponse([&base,&client,&c](ClientReceiveState&& state) { EXPECT_TRUE(folly::RequestContext::get()->hasContextData("first")); c.down(); }, 10); // Send another request with a unique RequestContext. This request would // queue behind the first one inside HeaderClientChannel. folly::RequestContext::create(); folly::RequestContext::get()->setContextData("second", nullptr); client.sendResponse([&base,&client,&c](ClientReceiveState&& state) { EXPECT_FALSE(folly::RequestContext::get()->hasContextData("first")); EXPECT_TRUE(folly::RequestContext::get()->hasContextData("second")); c.down(); }, 10); // Now start looping the eventbase to guarantee that all the above requests // would always queue. base.loopForever(); }
void AsyncCpp2Test(bool enable_security) { apache::thrift::TestThriftServerFactory<TestInterface> factory; ScopedServerThread sst(factory.create()); TEventBase base; std::shared_ptr<TAsyncSocket> socket( TAsyncSocket::newSocket(&base, *sst.getAddress())); auto client_channel = HeaderClientChannel::newChannel(socket); if (enable_security) { client_channel->setSecurityPolicy(THRIFT_SECURITY_PERMITTED); client_channel->setSaslClient(std::unique_ptr<SaslClient>( new StubSaslClient(socket->getEventBase()) )); } TestServiceAsyncClient client(std::move(client_channel)); boost::polymorphic_downcast<HeaderClientChannel*>( client.getChannel())->setTimeout(10000); client.sendResponse([&](ClientReceiveState&& state) { std::string response; try { TestServiceAsyncClient::recv_sendResponse( response, state); } catch(const std::exception& ex) { } EXPECT_EQ(response, "test64"); }, 64); base.loop(); }
TEST(Duplex, DuplexTest) { enum {START=1, COUNT=10, INTERVAL=5}; ScopedServerThread sst(getServer()); TEventBase base; std::shared_ptr<TAsyncSocket> socket( TAsyncSocket::newSocket(&base, *sst.getAddress())); auto duplexChannel = std::make_shared<DuplexChannel>(DuplexChannel::Who::CLIENT, socket); DuplexServiceAsyncClient client(duplexChannel->getClientChannel()); bool success = false; ThriftServer clients_server(duplexChannel->getServerChannel()); clients_server.setInterface(std::make_shared<DuplexClientInterface>( START, COUNT, success)); clients_server.serve(); client.registerForUpdates([](ClientReceiveState&& state) { EXPECT_FALSE(state.isException()); bool res = DuplexServiceAsyncClient::recv_registerForUpdates(state); EXPECT_TRUE(res); }, START, COUNT, INTERVAL); // fail on time out base.tryRunAfterDelay([] {EXPECT_TRUE(false);}, 5000); base.loopForever(); EXPECT_TRUE(success); }
TEST(ThriftServer, CallbackOrderingTest) { apache::thrift::TestThriftServerFactory<TestInterface> factory; auto server = factory.create(); auto serverHandler = std::make_shared<TestServerEventHandler>(); TProcessorBase::addProcessorEventHandlerFactory(serverHandler); server->setServerEventHandler(serverHandler); ScopedServerThread sst(server); TEventBase base; std::shared_ptr<TAsyncSocket> socket( TAsyncSocket::newSocket(&base, *sst.getAddress())); TestServiceAsyncClient client( std::unique_ptr<HeaderClientChannel, apache::thrift::async::TDelayedDestruction::Destructor>( new HeaderClientChannel(socket))); client.noResponse([](ClientReceiveState&& state){}, 10000); base.tryRunAfterDelay([&](){ socket->closeNow(); }, 1); base.tryRunAfterDelay([&](){ base.terminateLoopSoon(); }, 20); base.loopForever(); serverHandler->check(); TProcessorBase::removeProcessorEventHandlerFactory(serverHandler); }
int main(int argc, char **argv) { TEventBase base; int port = 8082; std::shared_ptr<TAsyncSocket> socket( TAsyncSocket::newSocket(&base, "127.0.0.1", port)); auto client_channel = HeaderClientChannel::newChannel(socket); CalculatorAsyncClient client(std::move(client_channel)); folly::wangle::Future<int64_t> f = client.future_add(2, 3); f.then( [](Try<int64_t>&& t) { std::cout << "Result = " << t.value() << std::endl; } ); // Run a single iteration of the event loop, in reality, this would be a // nearly infinite loop, where we stop the looping when the client should terminate base.loopForever(); }
TEST(ThriftServer, useExistingSocketAndConnectionIdleTimeout) { // This is ConnectionIdleTimeoutTest, but with an existing socket apache::thrift::TestThriftServerFactory<TestInterface> factory; auto server = factory.create(); TAsyncServerSocket::UniquePtr serverSocket(new TAsyncServerSocket); serverSocket->bind(0); server->useExistingSocket(std::move(serverSocket)); server->setIdleTimeout(std::chrono::milliseconds(20)); apache::thrift::util::ScopedServerThread st(server); TEventBase base; std::shared_ptr<TAsyncSocket> socket( TAsyncSocket::newSocket(&base, *st.getAddress())); TestServiceAsyncClient client( std::unique_ptr<HeaderClientChannel, apache::thrift::async::TDelayedDestruction::Destructor>( new HeaderClientChannel(socket))); std::string response; client.sync_sendResponse(response, 200); EXPECT_EQ(response, "test200"); base.loop(); }
/** * Test requireClientCert with no client cert */ TEST(TAsyncSSLSocketTest, NoClientCertHandshakeError) { TEventBase eventBase; auto clientCtx = std::make_shared<SSLContext>(); auto serverCtx = std::make_shared<SSLContext>(); serverCtx->setVerificationOption( SSLContext::SSLVerifyPeerEnum::VERIFY_REQ_CLIENT_CERT); serverCtx->ciphers("ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH"); serverCtx->loadPrivateKey("thrift/lib/cpp/test/ssl/tests-key.pem"); serverCtx->loadCertificate("thrift/lib/cpp/test/ssl/tests-cert.pem"); serverCtx->loadTrustedCertificates("thrift/lib/cpp/test/ssl/ca-cert.pem"); serverCtx->loadClientCAList("thrift/lib/cpp/test/ssl/ca-cert.pem"); clientCtx->setVerificationOption(SSLContext::SSLVerifyPeerEnum::NO_VERIFY); clientCtx->ciphers("ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH"); int fds[2]; getfds(fds); TAsyncSSLSocket::UniquePtr clientSock( new TAsyncSSLSocket(clientCtx, &eventBase, fds[0], false)); TAsyncSSLSocket::UniquePtr serverSock( new TAsyncSSLSocket(serverCtx, &eventBase, fds[1], true)); SSLHandshakeClient client(std::move(clientSock), false, false); SSLHandshakeServer server(std::move(serverSock), false, false); eventBase.loop(); EXPECT_FALSE(server.handshakeVerify_); EXPECT_FALSE(server.handshakeSuccess_); EXPECT_TRUE(server.handshakeError_); }
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()); }
/** * Verify that the options in SSLContext can be overridden in * sslConnect/Accept.i.e specifying that no validation should be performed * allows an otherwise-invalid certificate to be accepted and doesn't fire * the validation callback. */ TEST(TAsyncSSLSocketTest, OverrideSSLCtxDisableVerify) { TEventBase eventBase; auto clientCtx = std::make_shared<SSLContext>(); auto dfServerCtx = std::make_shared<SSLContext>(); int fds[2]; getfds(fds); getctx(clientCtx, dfServerCtx); clientCtx->setVerificationOption(SSLContext::SSLVerifyPeerEnum::VERIFY); dfServerCtx->setVerificationOption(SSLContext::SSLVerifyPeerEnum::VERIFY); TAsyncSSLSocket::UniquePtr clientSock( new TAsyncSSLSocket(clientCtx, &eventBase, fds[0], false)); TAsyncSSLSocket::UniquePtr serverSock( new TAsyncSSLSocket(dfServerCtx, &eventBase, fds[1], true)); SSLHandshakeClientNoVerify client(std::move(clientSock), false, false); clientCtx->loadTrustedCertificates("thrift/lib/cpp/test/ssl/ca-cert.pem"); SSLHandshakeServerNoVerify server(std::move(serverSock), false, false); eventBase.loop(); EXPECT_TRUE(!client.handshakeVerify_); EXPECT_TRUE(client.handshakeSuccess_); EXPECT_TRUE(!client.handshakeError_); EXPECT_TRUE(!server.handshakeVerify_); EXPECT_TRUE(server.handshakeSuccess_); EXPECT_TRUE(!server.handshakeError_); }
void TEventServer::stop() { // TODO: We really need a memory fence or some locking here to ensure that // the compiler doesn't optimize out eventBase. In practice, most users will // only call stop() when the server is actually serving, so this shouldn't be // much of an issue. TEventBase* eventBase = serveEventBase_; if (eventBase) { eventBase->terminateLoopSoon(); } }
TEST(ThriftServer, OverloadTest) { const int numThreads = 1; const int queueSize = 10; apache::thrift::TestThriftServerFactory<TestInterface> factory; { auto tm = concurrency::ThreadManager::newSimpleThreadManager( numThreads, 0, false, queueSize); tm->threadFactory(std::make_shared<concurrency::PosixThreadFactory>()); tm->start(); factory.useSimpleThreadManager(false).useThreadManager(tm); } ScopedServerThread sst(factory.create()); TEventBase base; std::shared_ptr<TAsyncSocket> socket( TAsyncSocket::newSocket(&base, *sst.getAddress())); TestServiceAsyncClient client( std::unique_ptr<HeaderClientChannel, apache::thrift::async::TDelayedDestruction::Destructor>( new HeaderClientChannel(socket))); std::string response; boost::polymorphic_downcast<HeaderClientChannel*>( client.getChannel())->setTimeout(500); auto tval = 10000; int too_full = 0; int exception_headers = 0; auto lambda = [&](ClientReceiveState&& state) { std::string response; auto headers = state.header()->getHeaders(); if (headers.size() > 0) { EXPECT_EQ(headers["ex"], kQueueOverloadedErrorCode); exception_headers++; } auto ew = TestServiceAsyncClient::recv_wrapped_sendResponse(response, state); if (ew) { usleep(tval); // Wait for large task to finish too_full++; } }; // Fill up the server's request buffer client.sendResponse(lambda, tval); for (int i = 0; i < numThreads + queueSize; i++) { client.sendResponse(lambda, 0); } base.loop(); // We expect one 'too full' exception (queue size is 2, one being worked on) // And three timeouts EXPECT_EQ(too_full, 1); EXPECT_EQ(exception_headers, 1); }
void runTest(std::function<void(HeaderClientChannel* channel)> setup) { ScopedServerThread sst(getServer()); TEventBase base; auto channel = getClientChannel(&base, *sst.getAddress()); setup(channel.get()); TestServiceAsyncClient client(std::move(channel)); Countdown c(3, [&base](){base.terminateLoopSoon();}); client.sendResponse([&base,&client,&c](ClientReceiveState&& state) { EXPECT_FALSE(state.isException()); EXPECT_TRUE(state.isSecurityActive()); std::string res; try { TestServiceAsyncClient::recv_sendResponse(res, state); } catch(const std::exception&) { EXPECT_TRUE(false); } EXPECT_EQ(res, "10"); c.down(); }, 10); // fail on time out base.tryRunAfterDelay([] {EXPECT_TRUE(false);}, 5000); base.tryRunAfterDelay([&client,&base,&c] { client.sendResponse([&base,&c](ClientReceiveState&& state) { EXPECT_FALSE(state.isException()); EXPECT_TRUE(state.isSecurityActive()); std::string res; try { TestServiceAsyncClient::recv_sendResponse(res, state); } catch(const std::exception&) { EXPECT_TRUE(false); } EXPECT_EQ(res, "10"); c.down(); }, 10); client.sendResponse([&base,&c](ClientReceiveState&& state) { EXPECT_FALSE(state.isException()); EXPECT_TRUE(state.isSecurityActive()); std::string res; try { TestServiceAsyncClient::recv_sendResponse(res, state); } catch(const std::exception&) { EXPECT_TRUE(false); } EXPECT_EQ(res, "10"); c.down(); }, 10); }, 1); base.loopForever(); }
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(); }); } }
TEST(ThriftServer, GetLoadTest) { apache::thrift::TestThriftServerFactory<TestInterface> factory; auto serv = factory.create(); ScopedServerThread sst(serv); TEventBase base; std::shared_ptr<TAsyncSocket> socket( TAsyncSocket::newSocket(&base, *sst.getAddress())); TestServiceAsyncClient client( std::unique_ptr<HeaderClientChannel, apache::thrift::async::TDelayedDestruction::Destructor>( new HeaderClientChannel(socket))); auto header_channel = boost::polymorphic_downcast<HeaderClientChannel*>( client.getChannel()); RpcOptions rpcOptions; rpcOptions.setWriteHeader("load", "thrift.active_requests"); auto callback = std::unique_ptr<RequestCallback>( new FunctionReplyCallback([&](ClientReceiveState&& state) { std::string response; auto headers = state.header()->getHeaders(); auto load = headers.find("load"); EXPECT_NE(load, headers.end()); EXPECT_EQ(load->second, "0"); TestServiceAsyncClient::recv_wrapped_sendResponse(response, state); EXPECT_EQ(response, "test64"); })); client.sendResponse(rpcOptions, std::move(callback), 64); base.loop(); serv->setGetLoad([&](std::string counter){ EXPECT_EQ(counter, "thrift.active_requests"); return 1; }); rpcOptions.setWriteHeader("load", "thrift.active_requests"); callback = std::unique_ptr<RequestCallback>( new FunctionReplyCallback([&](ClientReceiveState&& state) { std::string response; auto headers = state.header()->getHeaders(); auto load = headers.find("load"); EXPECT_NE(load, headers.end()); EXPECT_EQ(load->second, "1"); TestServiceAsyncClient::recv_wrapped_sendResponse(response, state); EXPECT_EQ(response, "test64"); })); client.sendResponse(rpcOptions, std::move(callback), 64); base.loop(); }
int main() { TEventBase base; const int ports[] = { 9090, 9091, 9092, 9093, 9094 }; const char *hosts[] = {"127.0.0.1", "127.0.0.1", "127.0.0.1", "127.0.0.1", "127.0.0.1"}; unsigned char* images[5]; int cur_pos = 0; std::vector<std::shared_ptr<TAsyncSocket>> sockets; std::vector<std::shared_ptr<aobench::cpp2::AobenchServiceAsyncClient>> clients; for (int i = 0; i < 5; ++i) { std::shared_ptr<TAsyncSocket> socket( TAsyncSocket::newSocket(&base, hosts[i], ports[i])); sockets.push_back(socket); auto client_channel = HeaderClientChannel::newChannel(socket); auto client = std::make_shared<aobench::cpp2::AobenchServiceAsyncClient>(std::move(client_channel)); clients.push_back(client); client->render( [&](ClientReceiveState&& state) { std::string result; fprintf(stderr, "received\n"); try { aobench::cpp2::AobenchServiceAsyncClient::recv_render(result, state); unsigned char* img = new unsigned char [result.size()]; for (int i = 0; i < static_cast<int>(result.size()); ++i) { img[i] = static_cast<unsigned char>(result[i]); } images[cur_pos] = img; ++cur_pos; if (cur_pos == 5) { saveppm_sum("ao.ppm", 256, 256, images, 5); for (int i = 0; i < 5; ++i) { delete[] images[i]; } fprintf(stderr, "accumulated\n"); } } catch(const std::exception& ex) { fprintf(stderr, "exception thrown %s\n", ex.what()); } }, 256, 256, 2); } fprintf(stderr, "started\n"); base.loop(); fprintf(stderr, "finished\n"); }
TEST(ThriftServer, IdleTimeoutTest) { ScopedServerThread sst(getServer()); TEventBase base; std::shared_ptr<TAsyncSocket> socket( TAsyncSocket::newSocket(&base, *sst.getAddress())); auto client_channel = HeaderClientChannel::newChannel(socket); CloseChecker checker; client_channel->setCloseCallback(&checker); base.tryRunAfterDelay([&base](){ base.terminateLoopSoon(); }, 100); base.loopForever(); EXPECT_TRUE(checker.getClosed()); client_channel->setCloseCallback(nullptr); }
TEST(ThriftServer, IdleTimeoutTest) { TEventBase base; auto port = Server::get(getServer)->getAddress().getPort(); std::shared_ptr<TAsyncSocket> socket( TAsyncSocket::newSocket(&base, "127.0.0.1", port)); auto client_channel = HeaderClientChannel::newChannel(socket); CloseChecker checker; client_channel->setCloseCallback(&checker); base.runAfterDelay([&base](){ base.terminateLoopSoon(); }, 100); base.loopForever(); EXPECT_TRUE(checker.getClosed()); }
void QueueTest::putMessages() { TEventBase eventBase; QueueConsumer consumer; QueueConsumer consumer2; consumer.fn = [&](int msg) { // Stop consuming after we receive a message with value 0, and start // consumer2 if (msg == 0) { consumer.stopConsuming(); consumer2.startConsuming(&eventBase, &queue); } }; consumer2.fn = [&](int msg) { // Stop consuming after we receive a message with value 0 if (msg == 0) { consumer2.stopConsuming(); } }; consumer.startConsuming(&eventBase, &queue); list<int> msgList = { 1, 2, 3, 4 }; vector<int> msgVector = { 5, 0, 9, 8, 7, 6, 7, 7, 8, 8, 2, 9, 6, 6, 10, 2, 0 }; // Call putMessages() several times to add messages to the queue queue.putMessages(msgList.begin(), msgList.end()); queue.putMessages(msgVector.begin() + 2, msgVector.begin() + 4); // Test sending 17 messages, the pipe-based queue calls write in 16 byte // chunks queue.putMessages(msgVector.begin(), msgVector.end()); // Loop until the consumer has stopped eventBase.loop(); vector<int> expectedMessages = { 1, 2, 3, 4, 9, 8, 7, 5, 0 }; vector<int> expectedMessages2 = { 9, 8, 7, 6, 7, 7, 8, 8, 2, 9, 6, 10, 2, 0 }; BOOST_CHECK_EQUAL(expectedMessages.size(), consumer.messages.size()); for (unsigned int idx = 0; idx < expectedMessages.size(); ++idx) { BOOST_CHECK_EQUAL(expectedMessages[idx], consumer.messages.at(idx)); } BOOST_CHECK_EQUAL(expectedMessages2.size(), consumer2.messages.size()); for (unsigned int idx = 0; idx < expectedMessages2.size(); ++idx) { BOOST_CHECK_EQUAL(expectedMessages2[idx], consumer2.messages.at(idx)); } }
TEST(ThriftServer, ShutdownSocketSetTest) { apache::thrift::TestThriftServerFactory<TestInterface> factory; auto server = factory.create(); ScopedServerThread sst(server); TEventBase base; ReadCallbackTest cb; std::shared_ptr<TAsyncSocket> socket2( TAsyncSocket::newSocket(&base, *sst.getAddress())); socket2->setReadCallback(&cb); base.tryRunAfterDelay([&](){ server->immediateShutdown(true); }, 10); base.tryRunAfterDelay([&](){ base.terminateLoopSoon(); }, 30); base.loopForever(); EXPECT_EQ(cb.eof, true); }
TEST(HeaderClientChannel, LongResponse) { std::unique_ptr<ScopedServerThread> serverThread = createHttpServer(); TEventBase eb; const TSocketAddress* addr = serverThread->getAddress(); std::shared_ptr<TAsyncSocket> socket = TAsyncSocket::newSocket(&eb, *addr); std::unique_ptr<HeaderClientChannel, TDelayedDestruction::Destructor> channel( new HeaderClientChannel(socket)); channel->getHeader()->useAsHttpClient("127.0.0.1", "meh"); TestServiceAsyncClient client(std::move(channel)); client.serializationTest( [] (apache::thrift::ClientReceiveState&& state) { EXPECT_TRUE(state.exception() == nullptr); std::string res; TestServiceAsyncClient::recv_serializationTest(res, state); EXPECT_EQ(res, string(4096, 'a')); }, true); eb.loop(); }