blob: 12657d4c3c44067ec125af9d77b43a784ba977d3 [file] [log] [blame]
Ben Craig1684c422015-04-24 08:52:44 -05001/*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
19
20#define BOOST_TEST_MODULE TServerIntegrationTest
21#include <boost/test/auto_unit_test.hpp>
Jim King5a3f8552016-04-05 12:17:51 -040022#include <boost/atomic.hpp>
Jim King5a3f8552016-04-05 12:17:51 -040023#include <boost/date_time/posix_time/ptime.hpp>
Jim King79c99112015-04-30 07:10:08 -040024#include <boost/foreach.hpp>
Ben Craig1684c422015-04-24 08:52:44 -050025#include <boost/format.hpp>
Ben Craig1684c422015-04-24 08:52:44 -050026#include <boost/thread.hpp>
Jim King79c99112015-04-30 07:10:08 -040027#include <thrift/server/TSimpleServer.h>
28#include <thrift/server/TThreadPoolServer.h>
Ben Craig1684c422015-04-24 08:52:44 -050029#include <thrift/server/TThreadedServer.h>
James E. King, III82ae9572017-08-05 12:23:54 -040030#include <thrift/stdcxx.h>
Ben Craig1684c422015-04-24 08:52:44 -050031#include <thrift/protocol/TBinaryProtocol.h>
32#include <thrift/transport/TServerSocket.h>
33#include <thrift/transport/TSocket.h>
34#include <thrift/transport/TTransport.h>
35#include "gen-cpp/ParentService.h"
Jim King5a3f8552016-04-05 12:17:51 -040036#include <string>
Ben Craig1684c422015-04-24 08:52:44 -050037#include <vector>
38
39using apache::thrift::concurrency::Guard;
40using apache::thrift::concurrency::Monitor;
41using apache::thrift::concurrency::Mutex;
42using apache::thrift::concurrency::Synchronized;
43using apache::thrift::protocol::TBinaryProtocol;
44using apache::thrift::protocol::TBinaryProtocolFactory;
45using apache::thrift::protocol::TProtocol;
46using apache::thrift::protocol::TProtocolFactory;
47using apache::thrift::transport::TServerSocket;
48using apache::thrift::transport::TServerTransport;
49using apache::thrift::transport::TSocket;
50using apache::thrift::transport::TTransport;
Jim King79c99112015-04-30 07:10:08 -040051using apache::thrift::transport::TTransportException;
Ben Craig1684c422015-04-24 08:52:44 -050052using apache::thrift::transport::TTransportFactory;
Jim King79c99112015-04-30 07:10:08 -040053using apache::thrift::server::TServer;
Ben Craig1684c422015-04-24 08:52:44 -050054using apache::thrift::server::TServerEventHandler;
Jim King79c99112015-04-30 07:10:08 -040055using apache::thrift::server::TSimpleServer;
56using apache::thrift::server::TThreadPoolServer;
Ben Craig1684c422015-04-24 08:52:44 -050057using apache::thrift::server::TThreadedServer;
James E. King, III82ae9572017-08-05 12:23:54 -040058using apache::thrift::stdcxx::dynamic_pointer_cast;
59using apache::thrift::stdcxx::make_shared;
60using apache::thrift::stdcxx::shared_ptr;
Ben Craig1684c422015-04-24 08:52:44 -050061using apache::thrift::test::ParentServiceClient;
62using apache::thrift::test::ParentServiceIf;
Konrad Grochowski24ea0bf2015-05-07 14:59:29 +020063using apache::thrift::test::ParentServiceIfFactory;
64using apache::thrift::test::ParentServiceIfSingletonFactory;
Ben Craig1684c422015-04-24 08:52:44 -050065using apache::thrift::test::ParentServiceProcessor;
Konrad Grochowski24ea0bf2015-05-07 14:59:29 +020066using apache::thrift::test::ParentServiceProcessorFactory;
67using apache::thrift::TProcessor;
68using apache::thrift::TProcessorFactory;
Jim King79c99112015-04-30 07:10:08 -040069using boost::posix_time::milliseconds;
Ben Craig1684c422015-04-24 08:52:44 -050070
71/**
72 * preServe runs after listen() is successful, when we can connect
73 */
Konrad Grochowski1f6e3802015-05-18 18:10:06 +020074class TServerReadyEventHandler : public TServerEventHandler, public Monitor {
Ben Craig1684c422015-04-24 08:52:44 -050075public:
76 TServerReadyEventHandler() : isListening_(false), accepted_(0) {}
77 virtual ~TServerReadyEventHandler() {}
78 virtual void preServe() {
79 Synchronized sync(*this);
80 isListening_ = true;
81 notify();
82 }
James E. King, III82ae9572017-08-05 12:23:54 -040083 virtual void* createContext(shared_ptr<TProtocol> input,
84 shared_ptr<TProtocol> output) {
Ben Craig1684c422015-04-24 08:52:44 -050085 Synchronized sync(*this);
86 ++accepted_;
87 notify();
88
89 (void)input;
90 (void)output;
91 return NULL;
92 }
93 bool isListening() const { return isListening_; }
94 uint64_t acceptedCount() const { return accepted_; }
Konrad Grochowski1f6e3802015-05-18 18:10:06 +020095
Ben Craig1684c422015-04-24 08:52:44 -050096private:
97 bool isListening_;
98 uint64_t accepted_;
99};
100
Jim King79c99112015-04-30 07:10:08 -0400101/**
102 * Reusing another generated test, just something to serve up
103 */
104class ParentHandler : public ParentServiceIf {
Ben Craig1684c422015-04-24 08:52:44 -0500105public:
106 ParentHandler() : generation_(0) {}
107
108 int32_t incrementGeneration() {
109 Guard g(mutex_);
110 return ++generation_;
111 }
112
113 int32_t getGeneration() {
114 Guard g(mutex_);
115 return generation_;
116 }
117
118 void addString(const std::string& s) {
119 Guard g(mutex_);
120 strings_.push_back(s);
121 }
122
123 void getStrings(std::vector<std::string>& _return) {
124 Guard g(mutex_);
125 _return = strings_;
126 }
127
ben-craigfae08e72015-07-15 11:34:47 -0500128 void getDataWait(std::string& _return, const int32_t length) {
Konrad Grochowski24ea0bf2015-05-07 14:59:29 +0200129 THRIFT_UNUSED_VARIABLE(_return);
130 THRIFT_UNUSED_VARIABLE(length);
Ben Craig1684c422015-04-24 08:52:44 -0500131 }
132
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200133 void onewayWait() {}
Ben Craig1684c422015-04-24 08:52:44 -0500134
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200135 void exceptionWait(const std::string& message) { THRIFT_UNUSED_VARIABLE(message); }
Ben Craig1684c422015-04-24 08:52:44 -0500136
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200137 void unexpectedExceptionWait(const std::string& message) { THRIFT_UNUSED_VARIABLE(message); }
Ben Craig1684c422015-04-24 08:52:44 -0500138
139protected:
140 Mutex mutex_;
141 int32_t generation_;
142 std::vector<std::string> strings_;
143};
144
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200145void autoSocketCloser(TSocket* pSock) {
Jim King79c99112015-04-30 07:10:08 -0400146 pSock->close();
147 delete pSock;
148}
149
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200150template <class TServerType>
John Sirois919752c2016-02-13 12:35:58 -0700151class TServerIntegrationTestFixture {
Ben Craig1684c422015-04-24 08:52:44 -0500152public:
James E. King, III82ae9572017-08-05 12:23:54 -0400153 TServerIntegrationTestFixture(const shared_ptr<TProcessorFactory>& _processorFactory)
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200154 : pServer(new TServerType(_processorFactory,
James E. King, III82ae9572017-08-05 12:23:54 -0400155 shared_ptr<TServerTransport>(
John Sirois919752c2016-02-13 12:35:58 -0700156 new TServerSocket("localhost", 0)),
James E. King, III82ae9572017-08-05 12:23:54 -0400157 shared_ptr<TTransportFactory>(new TTransportFactory),
158 shared_ptr<TProtocolFactory>(new TBinaryProtocolFactory))),
159 pEventHandler(shared_ptr<TServerReadyEventHandler>(new TServerReadyEventHandler)),
James E. King, IIIdf899132016-11-12 15:16:30 -0500160 bStressDone(false),
161 bStressConnectionCount(0),
162 bStressRequestCount(0) {
Ben Craig1684c422015-04-24 08:52:44 -0500163 pServer->setServerEventHandler(pEventHandler);
164 }
165
James E. King, III82ae9572017-08-05 12:23:54 -0400166 TServerIntegrationTestFixture(const shared_ptr<TProcessor>& _processor)
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200167 : pServer(
168 new TServerType(_processor,
James E. King, III82ae9572017-08-05 12:23:54 -0400169 shared_ptr<TServerTransport>(new TServerSocket("localhost", 0)),
170 shared_ptr<TTransportFactory>(new TTransportFactory),
171 shared_ptr<TProtocolFactory>(new TBinaryProtocolFactory))),
172 pEventHandler(shared_ptr<TServerReadyEventHandler>(new TServerReadyEventHandler)),
Jim King5a3f8552016-04-05 12:17:51 -0400173 bStressDone(false),
James E. King, IIIdf899132016-11-12 15:16:30 -0500174 bStressConnectionCount(0),
175 bStressRequestCount(0) {
Konrad Grochowski24ea0bf2015-05-07 14:59:29 +0200176 pServer->setServerEventHandler(pEventHandler);
177 }
178
Ben Craig1684c422015-04-24 08:52:44 -0500179 void startServer() {
James E. King, III82ae9572017-08-05 12:23:54 -0400180 pServerThread.reset(new boost::thread(apache::thrift::stdcxx::bind(&TServerType::serve, pServer.get())));
Ben Craig1684c422015-04-24 08:52:44 -0500181
182 // block until listen() completes so clients will be able to connect
183 Synchronized sync(*(pEventHandler.get()));
184 while (!pEventHandler->isListening()) {
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200185 pEventHandler->wait();
Ben Craig1684c422015-04-24 08:52:44 -0500186 }
187
Jim King5a3f8552016-04-05 12:17:51 -0400188 BOOST_TEST_MESSAGE(" server is listening");
Ben Craig1684c422015-04-24 08:52:44 -0500189 }
190
191 void blockUntilAccepted(uint64_t numAccepted) {
192 Synchronized sync(*(pEventHandler.get()));
193 while (pEventHandler->acceptedCount() < numAccepted) {
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200194 pEventHandler->wait();
Ben Craig1684c422015-04-24 08:52:44 -0500195 }
196
Jim King5a3f8552016-04-05 12:17:51 -0400197 BOOST_TEST_MESSAGE(boost::format(" server has accepted %1%") % numAccepted);
Ben Craig1684c422015-04-24 08:52:44 -0500198 }
199
200 void stopServer() {
Jim King79c99112015-04-30 07:10:08 -0400201 if (pServerThread) {
202 pServer->stop();
Jim King5a3f8552016-04-05 12:17:51 -0400203 BOOST_TEST_MESSAGE(" server stop completed");
Jim King79c99112015-04-30 07:10:08 -0400204
205 pServerThread->join();
Jim King5a3f8552016-04-05 12:17:51 -0400206 BOOST_TEST_MESSAGE(" server thread joined");
Jim King79c99112015-04-30 07:10:08 -0400207 pServerThread.reset();
208 }
Ben Craig1684c422015-04-24 08:52:44 -0500209 }
210
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200211 ~TServerIntegrationTestFixture() { stopServer(); }
Ben Craig1684c422015-04-24 08:52:44 -0500212
Jim King5a3f8552016-04-05 12:17:51 -0400213 /**
214 * Performs a baseline test where some clients are opened and issue a single operation
215 * and then disconnect at different intervals.
216 * \param[in] numToMake the number of concurrent clients
217 * \param[in] expectedHWM the high water mark we expect of concurrency
218 * \param[in] purpose a description of the test for logging purposes
219 */
220 void baseline(int64_t numToMake, int64_t expectedHWM, const std::string& purpose) {
James E. King, IIIdf899132016-11-12 15:16:30 -0500221 BOOST_TEST_MESSAGE(boost::format("Testing %1%: %2% with %3% clients, expect %4% HWM")
222 % typeid(TServerType).name() % purpose % numToMake % expectedHWM);
Konrad Grochowski24ea0bf2015-05-07 14:59:29 +0200223
James E. King, IIIdf899132016-11-12 15:16:30 -0500224 startServer();
Ben Craig1684c422015-04-24 08:52:44 -0500225
James E. King, III82ae9572017-08-05 12:23:54 -0400226 std::vector<shared_ptr<TSocket> > holdSockets;
227 std::vector<shared_ptr<boost::thread> > holdThreads;
Jim King79c99112015-04-30 07:10:08 -0400228
229 for (int64_t i = 0; i < numToMake; ++i) {
James E. King, III82ae9572017-08-05 12:23:54 -0400230 shared_ptr<TSocket> pClientSock(new TSocket("localhost", getServerPort()),
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200231 autoSocketCloser);
232 holdSockets.push_back(pClientSock);
James E. King, III82ae9572017-08-05 12:23:54 -0400233 shared_ptr<TProtocol> pClientProtocol(new TBinaryProtocol(pClientSock));
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200234 ParentServiceClient client(pClientProtocol);
235 pClientSock->open();
236 client.incrementGeneration();
James E. King, III82ae9572017-08-05 12:23:54 -0400237 holdThreads.push_back(shared_ptr<boost::thread>(
238 new boost::thread(apache::thrift::stdcxx::bind(&TServerIntegrationTestFixture::delayClose,
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200239 this,
240 pClientSock,
Jim King5a3f8552016-04-05 12:17:51 -0400241 milliseconds(10 * numToMake)))));
Jim King79c99112015-04-30 07:10:08 -0400242 }
243
244 BOOST_CHECK_EQUAL(expectedHWM, pServer->getConcurrentClientCountHWM());
Jim King5a3f8552016-04-05 12:17:51 -0400245
James E. King, III82ae9572017-08-05 12:23:54 -0400246 BOOST_FOREACH (shared_ptr<boost::thread> pThread, holdThreads) { pThread->join(); }
Jim King79c99112015-04-30 07:10:08 -0400247 holdThreads.clear();
248 holdSockets.clear();
Jim King5a3f8552016-04-05 12:17:51 -0400249
250 stopServer();
251 }
252
253 /**
254 * Helper method used to close a connection after a delay.
255 * \param[in] toClose the connection to close
256 * \param[in] after the delay to impose
257 */
James E. King, III82ae9572017-08-05 12:23:54 -0400258 void delayClose(shared_ptr<TTransport> toClose, boost::posix_time::time_duration after) {
Jim King5a3f8552016-04-05 12:17:51 -0400259 boost::this_thread::sleep(after);
260 toClose->close();
261 }
262
263 /**
264 * \returns the server port number
265 */
266 int getServerPort() {
267 TServerSocket* pSock = dynamic_cast<TServerSocket*>(pServer->getServerTransport().get());
268 return pSock->getPort();
269 }
270
271 /**
272 * Performs a stress test by spawning threads that connect, do a number of operations
273 * and disconnect, then a random delay, then do it over again. This is done for a fixed
274 * period of time to test for concurrency correctness.
275 * \param[in] numToMake the number of concurrent clients
276 */
277 void stress(int64_t numToMake, const boost::posix_time::time_duration& duration) {
278 BOOST_TEST_MESSAGE(boost::format("Stress testing %1% with %2% clients for %3% seconds")
279 % typeid(TServerType).name() % numToMake % duration.total_seconds());
280
281 startServer();
282
James E. King, III82ae9572017-08-05 12:23:54 -0400283 std::vector<shared_ptr<boost::thread> > holdThreads;
Jim King5a3f8552016-04-05 12:17:51 -0400284 for (int64_t i = 0; i < numToMake; ++i) {
James E. King, III82ae9572017-08-05 12:23:54 -0400285 holdThreads.push_back(shared_ptr<boost::thread>(
286 new boost::thread(apache::thrift::stdcxx::bind(&TServerIntegrationTestFixture::stressor, this))));
Jim King5a3f8552016-04-05 12:17:51 -0400287 }
288
289 boost::this_thread::sleep(duration);
290 bStressDone = true;
291
292 BOOST_TEST_MESSAGE(boost::format(" serviced %1% connections (HWM %2%) totaling %3% requests")
293 % bStressConnectionCount % pServer->getConcurrentClientCountHWM() % bStressRequestCount);
294
James E. King, III82ae9572017-08-05 12:23:54 -0400295 BOOST_FOREACH (shared_ptr<boost::thread> pThread, holdThreads) { pThread->join(); }
Jim King5a3f8552016-04-05 12:17:51 -0400296 holdThreads.clear();
297
298 BOOST_CHECK(bStressRequestCount > 0);
299
300 stopServer();
301 }
302
303 /**
304 * Helper method to stress the system
305 */
306 void stressor() {
James E. King, IIIdf899132016-11-12 15:16:30 -0500307 while (!bStressDone) {
James E. King, III82ae9572017-08-05 12:23:54 -0400308 shared_ptr<TSocket> pSocket(new TSocket("localhost", getServerPort()), autoSocketCloser);
309 shared_ptr<TProtocol> pProtocol(new TBinaryProtocol(pSocket));
Jim King5a3f8552016-04-05 12:17:51 -0400310 ParentServiceClient client(pProtocol);
311 pSocket->open();
312 bStressConnectionCount.fetch_add(1, boost::memory_order_relaxed);
313 for (int i = 0; i < rand() % 1000; ++i) {
James E. King, IIIdf899132016-11-12 15:16:30 -0500314 client.incrementGeneration();
Jim King5a3f8552016-04-05 12:17:51 -0400315 bStressRequestCount.fetch_add(1, boost::memory_order_relaxed);
316 }
317 }
Jim King79c99112015-04-30 07:10:08 -0400318 }
319
James E. King, III82ae9572017-08-05 12:23:54 -0400320 shared_ptr<TServerType> pServer;
321 shared_ptr<TServerReadyEventHandler> pEventHandler;
322 shared_ptr<boost::thread> pServerThread;
James E. King, III237a3942017-08-12 13:04:55 -0700323 boost::atomic<bool> bStressDone;
Jim King5a3f8552016-04-05 12:17:51 -0400324 boost::atomic_int64_t bStressConnectionCount;
325 boost::atomic_int64_t bStressRequestCount;
Ben Craig1684c422015-04-24 08:52:44 -0500326};
327
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200328template <class TServerType>
329class TServerIntegrationProcessorFactoryTestFixture
330 : public TServerIntegrationTestFixture<TServerType> {
Konrad Grochowski24ea0bf2015-05-07 14:59:29 +0200331public:
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200332 TServerIntegrationProcessorFactoryTestFixture()
James E. King, III82ae9572017-08-05 12:23:54 -0400333 : TServerIntegrationTestFixture<TServerType>(make_shared<ParentServiceProcessorFactory>(
334 make_shared<ParentServiceIfSingletonFactory>(
335 make_shared<ParentHandler>()))) {}
Konrad Grochowski24ea0bf2015-05-07 14:59:29 +0200336};
Ben Craig1684c422015-04-24 08:52:44 -0500337
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200338template <class TServerType>
339class TServerIntegrationProcessorTestFixture : public TServerIntegrationTestFixture<TServerType> {
Konrad Grochowski24ea0bf2015-05-07 14:59:29 +0200340public:
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200341 TServerIntegrationProcessorTestFixture()
342 : TServerIntegrationTestFixture<TServerType>(
James E. King, III82ae9572017-08-05 12:23:54 -0400343 make_shared<ParentServiceProcessor>(make_shared<ParentHandler>())) {}
Konrad Grochowski24ea0bf2015-05-07 14:59:29 +0200344};
345
346BOOST_AUTO_TEST_SUITE(constructors)
347
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200348BOOST_FIXTURE_TEST_CASE(test_simple_factory,
349 TServerIntegrationProcessorFactoryTestFixture<TSimpleServer>) {
Jim King5a3f8552016-04-05 12:17:51 -0400350 baseline(3, 1, "factory");
Ben Craig1684c422015-04-24 08:52:44 -0500351}
352
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200353BOOST_FIXTURE_TEST_CASE(test_simple, TServerIntegrationProcessorTestFixture<TSimpleServer>) {
Jim King5a3f8552016-04-05 12:17:51 -0400354 baseline(3, 1, "processor");
Konrad Grochowski24ea0bf2015-05-07 14:59:29 +0200355}
356
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200357BOOST_FIXTURE_TEST_CASE(test_threaded_factory,
358 TServerIntegrationProcessorFactoryTestFixture<TThreadedServer>) {
Jim King5a3f8552016-04-05 12:17:51 -0400359 baseline(10, 10, "factory");
Jim King79c99112015-04-30 07:10:08 -0400360}
361
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200362BOOST_FIXTURE_TEST_CASE(test_threaded, TServerIntegrationProcessorTestFixture<TThreadedServer>) {
Jim King5a3f8552016-04-05 12:17:51 -0400363 baseline(10, 10, "processor");
Konrad Grochowski24ea0bf2015-05-07 14:59:29 +0200364}
365
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200366BOOST_FIXTURE_TEST_CASE(test_threaded_bound,
367 TServerIntegrationProcessorTestFixture<TThreadedServer>) {
368 pServer->setConcurrentClientLimit(4);
Jim King5a3f8552016-04-05 12:17:51 -0400369 baseline(10, 4, "limit by server framework");
370}
371
372BOOST_FIXTURE_TEST_CASE(test_threaded_stress,
373 TServerIntegrationProcessorFactoryTestFixture<TThreadedServer>) {
374 stress(10, boost::posix_time::seconds(3));
Jim King79c99112015-04-30 07:10:08 -0400375}
376
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200377BOOST_FIXTURE_TEST_CASE(test_threadpool_factory,
378 TServerIntegrationProcessorFactoryTestFixture<TThreadPoolServer>) {
379 pServer->getThreadManager()->threadFactory(
James E. King, III82ae9572017-08-05 12:23:54 -0400380 shared_ptr<apache::thrift::concurrency::ThreadFactory>(
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200381 new apache::thrift::concurrency::PlatformThreadFactory));
382 pServer->getThreadManager()->start();
Jim King79c99112015-04-30 07:10:08 -0400383
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200384 // thread factory has 4 threads as a default
385 // thread factory however is a bad way to limit concurrent clients
386 // as accept() will be called to grab a 5th client socket, in this case
387 // and then the thread factory will block adding the thread to manage
388 // that client.
Jim King5a3f8552016-04-05 12:17:51 -0400389 baseline(10, 5, "limit by thread manager");
Jim King79c99112015-04-30 07:10:08 -0400390}
391
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200392BOOST_FIXTURE_TEST_CASE(test_threadpool,
393 TServerIntegrationProcessorTestFixture<TThreadPoolServer>) {
394 pServer->getThreadManager()->threadFactory(
James E. King, III82ae9572017-08-05 12:23:54 -0400395 shared_ptr<apache::thrift::concurrency::ThreadFactory>(
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200396 new apache::thrift::concurrency::PlatformThreadFactory));
397 pServer->getThreadManager()->start();
Konrad Grochowski24ea0bf2015-05-07 14:59:29 +0200398
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200399 // thread factory has 4 threads as a default
400 // thread factory however is a bad way to limit concurrent clients
401 // as accept() will be called to grab a 5th client socket, in this case
402 // and then the thread factory will block adding the thread to manage
403 // that client.
Jim King5a3f8552016-04-05 12:17:51 -0400404 baseline(10, 5, "limit by thread manager");
Konrad Grochowski24ea0bf2015-05-07 14:59:29 +0200405}
406
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200407BOOST_FIXTURE_TEST_CASE(test_threadpool_bound,
408 TServerIntegrationProcessorTestFixture<TThreadPoolServer>) {
409 pServer->getThreadManager()->threadFactory(
James E. King, III82ae9572017-08-05 12:23:54 -0400410 shared_ptr<apache::thrift::concurrency::ThreadFactory>(
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200411 new apache::thrift::concurrency::PlatformThreadFactory));
412 pServer->getThreadManager()->start();
413 pServer->setConcurrentClientLimit(4);
Jim King79c99112015-04-30 07:10:08 -0400414
Jim King5a3f8552016-04-05 12:17:51 -0400415 baseline(10, 4, "server framework connection limit");
416}
417
418BOOST_FIXTURE_TEST_CASE(test_threadpool_stress,
419 TServerIntegrationProcessorTestFixture<TThreadPoolServer>) {
420 pServer->getThreadManager()->threadFactory(
James E. King, III82ae9572017-08-05 12:23:54 -0400421 shared_ptr<apache::thrift::concurrency::ThreadFactory>(
Jim King5a3f8552016-04-05 12:17:51 -0400422 new apache::thrift::concurrency::PlatformThreadFactory));
423 pServer->getThreadManager()->start();
424
425 stress(10, boost::posix_time::seconds(3));
Jim King79c99112015-04-30 07:10:08 -0400426}
427
428BOOST_AUTO_TEST_SUITE_END()
429
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200430BOOST_FIXTURE_TEST_SUITE(TServerIntegrationTest,
431 TServerIntegrationProcessorTestFixture<TThreadedServer>)
Jim King79c99112015-04-30 07:10:08 -0400432
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200433BOOST_AUTO_TEST_CASE(test_stop_with_interruptable_clients_connected) {
434 // This tests THRIFT-2441 new behavior: stopping the server disconnects clients
Jim King5a3f8552016-04-05 12:17:51 -0400435 BOOST_TEST_MESSAGE("Testing stop with interruptable clients");
Jim King79c99112015-04-30 07:10:08 -0400436
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200437 startServer();
Ben Craig1684c422015-04-24 08:52:44 -0500438
James E. King, III82ae9572017-08-05 12:23:54 -0400439 shared_ptr<TSocket> pClientSock1(new TSocket("localhost", getServerPort()),
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200440 autoSocketCloser);
441 pClientSock1->open();
Ben Craig1684c422015-04-24 08:52:44 -0500442
James E. King, III82ae9572017-08-05 12:23:54 -0400443 shared_ptr<TSocket> pClientSock2(new TSocket("localhost", getServerPort()),
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200444 autoSocketCloser);
445 pClientSock2->open();
Ben Craig1684c422015-04-24 08:52:44 -0500446
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200447 // Ensure they have been accepted
448 blockUntilAccepted(2);
Ben Craig1684c422015-04-24 08:52:44 -0500449
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200450 // The test fixture destructor will force the sockets to disconnect
451 // Prior to THRIFT-2441, pServer->stop() would hang until clients disconnected
452 stopServer();
Ben Craig1684c422015-04-24 08:52:44 -0500453
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200454 // extra proof the server end disconnected the clients
455 uint8_t buf[1];
456 BOOST_CHECK_EQUAL(0, pClientSock1->read(&buf[0], 1)); // 0 = disconnected
457 BOOST_CHECK_EQUAL(0, pClientSock2->read(&buf[0], 1)); // 0 = disconnected
Ben Craig1684c422015-04-24 08:52:44 -0500458}
459
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200460BOOST_AUTO_TEST_CASE(test_stop_with_uninterruptable_clients_connected) {
461 // This tests pre-THRIFT-2441 behavior: stopping the server blocks until clients
462 // disconnect.
James E. King, IIIdf899132016-11-12 15:16:30 -0500463 BOOST_TEST_MESSAGE("Testing stop with uninterruptable clients");
Ben Craig1684c422015-04-24 08:52:44 -0500464
James E. King, III82ae9572017-08-05 12:23:54 -0400465 dynamic_pointer_cast<TServerSocket>(pServer->getServerTransport())
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200466 ->setInterruptableChildren(false); // returns to pre-THRIFT-2441 behavior
Jim King79c99112015-04-30 07:10:08 -0400467
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200468 startServer();
Ben Craig1684c422015-04-24 08:52:44 -0500469
James E. King, III82ae9572017-08-05 12:23:54 -0400470 shared_ptr<TSocket> pClientSock1(new TSocket("localhost", getServerPort()),
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200471 autoSocketCloser);
472 pClientSock1->open();
Ben Craig1684c422015-04-24 08:52:44 -0500473
James E. King, III82ae9572017-08-05 12:23:54 -0400474 shared_ptr<TSocket> pClientSock2(new TSocket("localhost", getServerPort()),
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200475 autoSocketCloser);
476 pClientSock2->open();
Ben Craig1684c422015-04-24 08:52:44 -0500477
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200478 // Ensure they have been accepted
479 blockUntilAccepted(2);
Ben Craig1684c422015-04-24 08:52:44 -0500480
James E. King, III82ae9572017-08-05 12:23:54 -0400481 boost::thread t1(apache::thrift::stdcxx::bind(&TServerIntegrationTestFixture::delayClose,
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200482 this,
483 pClientSock1,
484 milliseconds(250)));
James E. King, III82ae9572017-08-05 12:23:54 -0400485 boost::thread t2(apache::thrift::stdcxx::bind(&TServerIntegrationTestFixture::delayClose,
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200486 this,
487 pClientSock2,
488 milliseconds(250)));
Ben Craig1684c422015-04-24 08:52:44 -0500489
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200490 // Once the clients disconnect the server will stop
491 stopServer();
Jim King5a3f8552016-04-05 12:17:51 -0400492 BOOST_CHECK(pServer->getConcurrentClientCountHWM() > 0);
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200493 t1.join();
494 t2.join();
Ben Craig1684c422015-04-24 08:52:44 -0500495}
Jim King79c99112015-04-30 07:10:08 -0400496
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200497BOOST_AUTO_TEST_CASE(test_concurrent_client_limit) {
498 startServer();
Jim King5a3f8552016-04-05 12:17:51 -0400499 BOOST_TEST_MESSAGE("Testing the concurrent client limit");
Jim King79c99112015-04-30 07:10:08 -0400500
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200501 BOOST_CHECK_EQUAL(INT64_MAX, pServer->getConcurrentClientLimit());
502 pServer->setConcurrentClientLimit(2);
503 BOOST_CHECK_EQUAL(0, pServer->getConcurrentClientCount());
504 BOOST_CHECK_EQUAL(2, pServer->getConcurrentClientLimit());
Jim King79c99112015-04-30 07:10:08 -0400505
James E. King, III82ae9572017-08-05 12:23:54 -0400506 shared_ptr<TSocket> pClientSock1(new TSocket("localhost", getServerPort()),
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200507 autoSocketCloser);
508 pClientSock1->open();
509 blockUntilAccepted(1);
510 BOOST_CHECK_EQUAL(1, pServer->getConcurrentClientCount());
Jim King79c99112015-04-30 07:10:08 -0400511
James E. King, III82ae9572017-08-05 12:23:54 -0400512 shared_ptr<TSocket> pClientSock2(new TSocket("localhost", getServerPort()),
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200513 autoSocketCloser);
514 pClientSock2->open();
515 blockUntilAccepted(2);
516 BOOST_CHECK_EQUAL(2, pServer->getConcurrentClientCount());
Jim King79c99112015-04-30 07:10:08 -0400517
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200518 // a third client cannot connect until one of the other two closes
James E. King, III82ae9572017-08-05 12:23:54 -0400519 boost::thread t2(apache::thrift::stdcxx::bind(&TServerIntegrationTestFixture::delayClose,
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200520 this,
521 pClientSock2,
522 milliseconds(250)));
James E. King, III82ae9572017-08-05 12:23:54 -0400523 shared_ptr<TSocket> pClientSock3(new TSocket("localhost", getServerPort()),
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200524 autoSocketCloser);
525 pClientSock2->open();
526 blockUntilAccepted(2);
527 BOOST_CHECK_EQUAL(2, pServer->getConcurrentClientCount());
528 BOOST_CHECK_EQUAL(2, pServer->getConcurrentClientCountHWM());
Jim King79c99112015-04-30 07:10:08 -0400529
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200530 stopServer();
Jim King5a3f8552016-04-05 12:17:51 -0400531 BOOST_CHECK(pServer->getConcurrentClientCountHWM() > 0);
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200532 t2.join();
Jim King79c99112015-04-30 07:10:08 -0400533}
534
Ben Craig1684c422015-04-24 08:52:44 -0500535BOOST_AUTO_TEST_SUITE_END()