Beispiel #1
0
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);
}
Beispiel #4
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_);
}
Beispiel #8
0
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);
}
Beispiel #15
0
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));
  }
}
Beispiel #20
0
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();
}
Beispiel #22
0
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);
  }
}