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(); }
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(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); }
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(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); }
/** * 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 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(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(); }
/** * 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_); }
/** * 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; }
/** * 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 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 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(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(TEventBase& evb, LoadTestCobClient& client) { // Test sending a few requests to the server TestCallback callback; client.add(std::bind(&TestCallback::addDone, &callback, std::placeholders::_1), 9, 12); evb.loop(); BOOST_CHECK(callback.done); BOOST_CHECK_EQUAL(callback.addResult, 21); callback.reset(); string testData; randomizeString(&testData, 3*1024); client.echo(std::bind(&TestCallback::echoDone, &callback, std::placeholders::_1), testData); evb.loop(); BOOST_CHECK(callback.done); BOOST_CHECK(callback.echoResult == testData); callback.reset(); randomizeString(&testData, 1024*1024); client.echo(std::bind(&TestCallback::echoDone, &callback, std::placeholders::_1), testData); evb.loop(); BOOST_CHECK(callback.done); BOOST_CHECK(callback.echoResult == testData); callback.reset(); client.add(std::bind(&TestCallback::addDone, &callback, std::placeholders::_1), 321, 987); evb.loop(); BOOST_CHECK(callback.done); BOOST_CHECK_EQUAL(callback.addResult, 1308); }
TEST(HeaderClientChannelHttpTest, SimpleTest) { 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.sendResponse( [] (apache::thrift::ClientReceiveState&& state) { if (state.exception()) { try { std::rethrow_exception(state.exception()); } catch (const std::exception& e) { LOG(INFO) << e.what(); } } EXPECT_TRUE(state.exception() == nullptr); std::string res; TestServiceAsyncClient::recv_sendResponse(res, state); EXPECT_EQ(res, "test24"); }, 24); eb.loop(); client.eventBaseAsync( [] (apache::thrift::ClientReceiveState&& state) { EXPECT_TRUE(state.exception() == nullptr); std::string res; TestServiceAsyncClient::recv_eventBaseAsync(res, state); EXPECT_EQ(res, "hello world"); }); eb.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"); }
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, poolExecutorTest) { auto exe = std::make_shared<MyExecutor>(); apache::thrift::TestThriftServerFactory<TestInterface> factory; factory .useSimpleThreadManager(false) .useThreadManager(std::make_shared< apache::thrift::concurrency::ThreadManagerExecutorAdapter>(exe)); ScopedServerThread sst(factory.create()); TEventBase eb; TestServiceAsyncClient client( HeaderClientChannel::newChannel( TAsyncSocket::newSocket( &eb, *sst.getAddress()))); std::string response; client.sync_echoRequest(response, "test"); eb.loop(); EXPECT_EQ(1, exe->calls); }
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(); }
TEST(ThriftServer, BadSendTest) { apache::thrift::TestThriftServerFactory<TestInterface> factory; 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))); client.sendResponse( std::unique_ptr<RequestCallback>(new Callback), 64); socket->shutdownWriteNow(); base.loop(); std::string response; EXPECT_THROW(client.sync_sendResponse(response, 64), TTransportException); }
/** * Test SSL client socket session re-use */ TEST(TAsyncSSLSocketTest, SSLClientTestReuse) { // Start listening on a local port WriteCallbackBase writeCallback; ReadCallback readCallback(&writeCallback); HandshakeCallback handshakeCallback(&readCallback); SSLServerAcceptCallbackDelay acceptCallback(&handshakeCallback); TestSSLServer server(&acceptCallback); // Set up SSL client TEventBase eventBase; std::shared_ptr<SSLClient> client(new SSLClient(&eventBase, server.getAddress(), 10)); client->connect(); EventBaseAborter eba(&eventBase, 3000); eventBase.loop(); EXPECT_EQ(client->getMiss(), 1); EXPECT_EQ(client->getHit(), 9); cerr << "SSLClientTestReuse test completed" << endl; }
/** * Verify Client Ciphers obtained using SSL MSG Callback. */ TEST(TAsyncSSLSocketTest, SSLParseClientHelloSuccess) { TEventBase eventBase; auto clientCtx = std::make_shared<SSLContext>(); auto serverCtx = std::make_shared<SSLContext>(); serverCtx->setVerificationOption(SSLContext::SSLVerifyPeerEnum::VERIFY); serverCtx->ciphers("RSA:!SHA:!NULL:!SHA256@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::VERIFY); clientCtx->ciphers("RC4-SHA:AES128-SHA:AES256-SHA:RC4-MD5"); clientCtx->loadPrivateKey("thrift/lib/cpp/test/ssl/tests-key.pem"); clientCtx->loadCertificate("thrift/lib/cpp/test/ssl/tests-cert.pem"); clientCtx->loadTrustedCertificates("thrift/lib/cpp/test/ssl/ca-cert.pem"); 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), true, true); SSLHandshakeServerParseClientHello server(std::move(serverSock), true, true); eventBase.loop(); EXPECT_EQ(server.clientCiphers_, "RC4-SHA:AES128-SHA:AES256-SHA:RC4-MD5:00ff"); 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(TAsyncSSLSocketTest, RandomizedNpnTest) { // Probability that this test will fail is 2^-64, which could be considered // as negligible. const int kTries = 64; std::set<string> selectedProtocols; for (int i = 0; i < kTries; ++i) { TEventBase eventBase; std::shared_ptr<SSLContext> clientCtx = std::make_shared<SSLContext>(); std::shared_ptr<SSLContext> serverCtx = std::make_shared<SSLContext>(); int fds[2]; getfds(fds); getctx(clientCtx, serverCtx); clientCtx->setAdvertisedNextProtocols({"foo", "bar", "baz"}); serverCtx->setRandomizedAdvertisedNextProtocols({{1, {"foo"}}, {1, {"bar"}}}); 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); selectedProtocols.insert(selected); } EXPECT_EQ(selectedProtocols.size(), 2); }
/* * Test destroying a TAsyncTimeoutSet with timeouts outstanding */ TEST(TAsyncTimeoutSetTest, DestroyTimeoutSet) { TEventBase eventBase; TAsyncTimeoutSet::UniquePtr ts5(new TAsyncTimeoutSet( &eventBase, milliseconds(5))); TAsyncTimeoutSet::UniquePtr ts10(new TAsyncTimeoutSet( &eventBase, milliseconds(10))); TestTimeout t5_1(ts5.get()); TestTimeout t5_2(ts5.get()); TestTimeout t5_3(ts5.get()); TestTimeout t10_1(ts10.get()); TestTimeout t10_2(ts10.get()); // Have t5_1 destroy ts10 t5_1.fn = [&] { ts10.reset(); }; // Have t5_2 destroy ts5 // Note that this will call destroy() on ts5 inside ts5's timeoutExpired() // method. t5_2.fn = [&] { ts5.reset(); }; TimePoint start; eventBase.loop(); TimePoint end; ASSERT_EQ(t5_1.timestamps.size(), 1); T_CHECK_TIMEOUT(start, t5_1.timestamps[0], milliseconds(5)); ASSERT_EQ(t5_2.timestamps.size(), 1); T_CHECK_TIMEOUT(start, t5_2.timestamps[0], milliseconds(5)); ASSERT_EQ(t5_3.timestamps.size(), 0); ASSERT_EQ(t10_1.timestamps.size(), 0); ASSERT_EQ(t10_2.timestamps.size(), 0); T_CHECK_TIMEOUT(start, end, milliseconds(5)); }
void QueueTest::sendOne() { // Create a notification queue and a callback in this thread TEventBase eventBase; QueueConsumer consumer; consumer.fn = [&](int) { // Stop consuming after we receive 1 message consumer.stopConsuming(); }; consumer.startConsuming(&eventBase, &queue); // Start a new TEventBase thread to put a message on our queue ScopedEventBaseThread t1; t1.getEventBase()->runInEventBaseThread([&] { queue.putMessage(5); }); // Loop until we receive the message eventBase.loop(); const auto& messages = consumer.messages; BOOST_CHECK_EQUAL(messages.size(), 1); BOOST_CHECK_EQUAL(messages.at(0), 5); }
/* * Test firing some simple timeouts that are fired once and never rescheduled */ TEST(TAsyncTimeoutSetTest, FireOnce) { TEventBase eventBase; StackTimeoutSet ts10(&eventBase, milliseconds(10)); StackTimeoutSet ts5(&eventBase, milliseconds(5)); const TAsyncTimeoutSet::Callback* nullCallback = nullptr; ASSERT_EQ(ts10.front(), nullCallback); ASSERT_EQ(ts5.front(), nullCallback); TestTimeout t1; TestTimeout t2; TestTimeout t3; ts5.scheduleTimeout(&t1); ts5.scheduleTimeout(&t2); ts10.scheduleTimeout(&t3); ASSERT_EQ(ts10.front(), &t3); ASSERT_EQ(ts5.front(), &t1); TimePoint start; eventBase.loop(); TimePoint end; ASSERT_EQ(t1.timestamps.size(), 1); ASSERT_EQ(t2.timestamps.size(), 1); ASSERT_EQ(t3.timestamps.size(), 1); ASSERT_EQ(ts10.front(), nullCallback); ASSERT_EQ(ts5.front(), nullCallback); T_CHECK_TIMEOUT(start, t1.timestamps[0], milliseconds(5)); T_CHECK_TIMEOUT(start, t2.timestamps[0], milliseconds(5)); T_CHECK_TIMEOUT(start, t3.timestamps[0], milliseconds(10)); T_CHECK_TIMEOUT(start, end, milliseconds(10)); }
/** * Test SSL server accept timeout with cache path */ TEST(TAsyncSSLSocketTest, SSLServerTimeoutTest) { // Start listening on a local port WriteCallbackBase writeCallback; ReadCallback readCallback(&writeCallback); EmptyReadCallback clientReadCallback; HandshakeCallback handshakeCallback(&readCallback); SSLServerAcceptCallback acceptCallback(&handshakeCallback, 50); TestSSLAsyncCacheServer server(&acceptCallback); // Set up SSL client TEventBase eventBase; // only do a TCP connect std::shared_ptr<TAsyncSocket> sock = TAsyncSocket::newSocket(&eventBase); sock->connect(nullptr, server.getAddress()); clientReadCallback.tcpSocket_ = sock; sock->setReadCallback(&clientReadCallback); EventBaseAborter eba(&eventBase, 3000); eventBase.loop(); EXPECT_EQ(readCallback.state, STATE_WAITING); cerr << "SSLServerTimeoutTest test completed" << endl; }
void QueueTest::maxReadAtOnce() { // Add 100 messages to the queue for (int n = 0; n < 100; ++n) { queue.putMessage(n); } TEventBase eventBase; // Record how many messages were processed each loop iteration. uint32_t messagesThisLoop = 0; std::vector<uint32_t> messagesPerLoop; std::function<void()> loopFinished = [&] { // Record the current number of messages read this loop messagesPerLoop.push_back(messagesThisLoop); // Reset messagesThisLoop to 0 for the next loop messagesThisLoop = 0; // To prevent use-after-free bugs when eventBase destructs, // prevent calling runInLoop any more after the test is finished. // 55 == number of times loop should run. if (messagesPerLoop.size() != 55) { // Reschedule ourself to run at the end of the next loop eventBase.runInLoop(loopFinished); } }; // Schedule the first call to loopFinished eventBase.runInLoop(loopFinished); QueueConsumer consumer; // Read the first 50 messages 10 at a time. consumer.setMaxReadAtOnce(10); consumer.fn = [&](int value) { ++messagesThisLoop; // After 50 messages, drop to reading only 1 message at a time. if (value == 50) { consumer.setMaxReadAtOnce(1); } // Terminate the loop when we reach the end of the messages. if (value == 99) { eventBase.terminateLoopSoon(); } }; consumer.startConsuming(&eventBase, &queue); // Run the event loop until the consumer terminates it eventBase.loop(); // The consumer should have read all 100 messages in order BOOST_CHECK_EQUAL(consumer.messages.size(), 100); for (int n = 0; n < 100; ++n) { BOOST_CHECK_EQUAL(consumer.messages.at(n), n); } // Currently TEventBase happens to still run the loop callbacks even after // terminateLoopSoon() is called. However, we don't really want to depend on // this behavior. In case this ever changes in the future, add // messagesThisLoop to messagesPerLoop in loop callback isn't invoked for the // last loop iteration. if (messagesThisLoop > 0) { messagesPerLoop.push_back(messagesThisLoop); messagesThisLoop = 0; } // For the first 5 loops it should have read 10 messages each time. // After that it should have read 1 messages per loop for the next 50 loops. BOOST_CHECK_EQUAL(messagesPerLoop.size(), 55); for (int n = 0; n < 5; ++n) { BOOST_CHECK_EQUAL(messagesPerLoop.at(n), 10); } for (int n = 5; n < 55; ++n) { BOOST_CHECK_EQUAL(messagesPerLoop.at(n), 1); } }