blob: 21804484bae38f26c938d4a6f723d762048f1f70 [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>
Ben Craig1684c422015-04-24 08:52:44 -050023#include <boost/bind.hpp>
Jim King5a3f8552016-04-05 12:17:51 -040024#include <boost/date_time/posix_time/ptime.hpp>
Jim King79c99112015-04-30 07:10:08 -040025#include <boost/foreach.hpp>
Ben Craig1684c422015-04-24 08:52:44 -050026#include <boost/format.hpp>
Konrad Grochowski24ea0bf2015-05-07 14:59:29 +020027#include <boost/make_shared.hpp>
Ben Craig1684c422015-04-24 08:52:44 -050028#include <boost/shared_ptr.hpp>
29#include <boost/thread.hpp>
Jim King79c99112015-04-30 07:10:08 -040030#include <thrift/server/TSimpleServer.h>
31#include <thrift/server/TThreadPoolServer.h>
Ben Craig1684c422015-04-24 08:52:44 -050032#include <thrift/server/TThreadedServer.h>
33#include <thrift/protocol/TBinaryProtocol.h>
34#include <thrift/transport/TServerSocket.h>
35#include <thrift/transport/TSocket.h>
36#include <thrift/transport/TTransport.h>
37#include "gen-cpp/ParentService.h"
Jim King5a3f8552016-04-05 12:17:51 -040038#include <string>
Ben Craig1684c422015-04-24 08:52:44 -050039#include <vector>
40
41using apache::thrift::concurrency::Guard;
42using apache::thrift::concurrency::Monitor;
43using apache::thrift::concurrency::Mutex;
44using apache::thrift::concurrency::Synchronized;
45using apache::thrift::protocol::TBinaryProtocol;
46using apache::thrift::protocol::TBinaryProtocolFactory;
47using apache::thrift::protocol::TProtocol;
48using apache::thrift::protocol::TProtocolFactory;
49using apache::thrift::transport::TServerSocket;
50using apache::thrift::transport::TServerTransport;
51using apache::thrift::transport::TSocket;
52using apache::thrift::transport::TTransport;
Jim King79c99112015-04-30 07:10:08 -040053using apache::thrift::transport::TTransportException;
Ben Craig1684c422015-04-24 08:52:44 -050054using apache::thrift::transport::TTransportFactory;
Jim King79c99112015-04-30 07:10:08 -040055using apache::thrift::server::TServer;
Ben Craig1684c422015-04-24 08:52:44 -050056using apache::thrift::server::TServerEventHandler;
Jim King79c99112015-04-30 07:10:08 -040057using apache::thrift::server::TSimpleServer;
58using apache::thrift::server::TThreadPoolServer;
Ben Craig1684c422015-04-24 08:52:44 -050059using apache::thrift::server::TThreadedServer;
60using apache::thrift::test::ParentServiceClient;
61using apache::thrift::test::ParentServiceIf;
Konrad Grochowski24ea0bf2015-05-07 14:59:29 +020062using apache::thrift::test::ParentServiceIfFactory;
63using apache::thrift::test::ParentServiceIfSingletonFactory;
Ben Craig1684c422015-04-24 08:52:44 -050064using apache::thrift::test::ParentServiceProcessor;
Konrad Grochowski24ea0bf2015-05-07 14:59:29 +020065using apache::thrift::test::ParentServiceProcessorFactory;
66using apache::thrift::TProcessor;
67using apache::thrift::TProcessorFactory;
Jim King79c99112015-04-30 07:10:08 -040068using boost::posix_time::milliseconds;
Ben Craig1684c422015-04-24 08:52:44 -050069
70/**
71 * preServe runs after listen() is successful, when we can connect
72 */
Konrad Grochowski1f6e3802015-05-18 18:10:06 +020073class TServerReadyEventHandler : public TServerEventHandler, public Monitor {
Ben Craig1684c422015-04-24 08:52:44 -050074public:
75 TServerReadyEventHandler() : isListening_(false), accepted_(0) {}
76 virtual ~TServerReadyEventHandler() {}
77 virtual void preServe() {
78 Synchronized sync(*this);
79 isListening_ = true;
80 notify();
81 }
82 virtual void* createContext(boost::shared_ptr<TProtocol> input,
83 boost::shared_ptr<TProtocol> output) {
84 Synchronized sync(*this);
85 ++accepted_;
86 notify();
87
88 (void)input;
89 (void)output;
90 return NULL;
91 }
92 bool isListening() const { return isListening_; }
93 uint64_t acceptedCount() const { return accepted_; }
Konrad Grochowski1f6e3802015-05-18 18:10:06 +020094
Ben Craig1684c422015-04-24 08:52:44 -050095private:
96 bool isListening_;
97 uint64_t accepted_;
98};
99
Jim King79c99112015-04-30 07:10:08 -0400100/**
101 * Reusing another generated test, just something to serve up
102 */
103class ParentHandler : public ParentServiceIf {
Ben Craig1684c422015-04-24 08:52:44 -0500104public:
105 ParentHandler() : generation_(0) {}
106
107 int32_t incrementGeneration() {
108 Guard g(mutex_);
109 return ++generation_;
110 }
111
112 int32_t getGeneration() {
113 Guard g(mutex_);
114 return generation_;
115 }
116
117 void addString(const std::string& s) {
118 Guard g(mutex_);
119 strings_.push_back(s);
120 }
121
122 void getStrings(std::vector<std::string>& _return) {
123 Guard g(mutex_);
124 _return = strings_;
125 }
126
ben-craigfae08e72015-07-15 11:34:47 -0500127 void getDataWait(std::string& _return, const int32_t length) {
Konrad Grochowski24ea0bf2015-05-07 14:59:29 +0200128 THRIFT_UNUSED_VARIABLE(_return);
129 THRIFT_UNUSED_VARIABLE(length);
Ben Craig1684c422015-04-24 08:52:44 -0500130 }
131
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200132 void onewayWait() {}
Ben Craig1684c422015-04-24 08:52:44 -0500133
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200134 void exceptionWait(const std::string& message) { THRIFT_UNUSED_VARIABLE(message); }
Ben Craig1684c422015-04-24 08:52:44 -0500135
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200136 void unexpectedExceptionWait(const std::string& message) { THRIFT_UNUSED_VARIABLE(message); }
Ben Craig1684c422015-04-24 08:52:44 -0500137
138protected:
139 Mutex mutex_;
140 int32_t generation_;
141 std::vector<std::string> strings_;
142};
143
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200144void autoSocketCloser(TSocket* pSock) {
Jim King79c99112015-04-30 07:10:08 -0400145 pSock->close();
146 delete pSock;
147}
148
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200149template <class TServerType>
John Sirois919752c2016-02-13 12:35:58 -0700150class TServerIntegrationTestFixture {
Ben Craig1684c422015-04-24 08:52:44 -0500151public:
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200152 TServerIntegrationTestFixture(const boost::shared_ptr<TProcessorFactory>& _processorFactory)
153 : pServer(new TServerType(_processorFactory,
154 boost::shared_ptr<TServerTransport>(
John Sirois919752c2016-02-13 12:35:58 -0700155 new TServerSocket("localhost", 0)),
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200156 boost::shared_ptr<TTransportFactory>(new TTransportFactory),
157 boost::shared_ptr<TProtocolFactory>(new TBinaryProtocolFactory))),
Jim King5a3f8552016-04-05 12:17:51 -0400158 pEventHandler(boost::shared_ptr<TServerReadyEventHandler>(new TServerReadyEventHandler)),
159 bStressDone(false),
160 bStressConnectionCount(0),
161 bStressRequestCount(0) {
Ben Craig1684c422015-04-24 08:52:44 -0500162 pServer->setServerEventHandler(pEventHandler);
163 }
164
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200165 TServerIntegrationTestFixture(const boost::shared_ptr<TProcessor>& _processor)
166 : pServer(
167 new TServerType(_processor,
168 boost::shared_ptr<TServerTransport>(new TServerSocket("localhost", 0)),
169 boost::shared_ptr<TTransportFactory>(new TTransportFactory),
170 boost::shared_ptr<TProtocolFactory>(new TBinaryProtocolFactory))),
Jim King5a3f8552016-04-05 12:17:51 -0400171 pEventHandler(boost::shared_ptr<TServerReadyEventHandler>(new TServerReadyEventHandler)),
172 bStressDone(false),
173 bStressConnectionCount(0),
174 bStressRequestCount(0) {
Konrad Grochowski24ea0bf2015-05-07 14:59:29 +0200175 pServer->setServerEventHandler(pEventHandler);
176 }
177
Ben Craig1684c422015-04-24 08:52:44 -0500178 void startServer() {
Jim King79c99112015-04-30 07:10:08 -0400179 pServerThread.reset(new boost::thread(boost::bind(&TServerType::serve, pServer.get())));
Ben Craig1684c422015-04-24 08:52:44 -0500180
181 // block until listen() completes so clients will be able to connect
182 Synchronized sync(*(pEventHandler.get()));
183 while (!pEventHandler->isListening()) {
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200184 pEventHandler->wait();
Ben Craig1684c422015-04-24 08:52:44 -0500185 }
186
Jim King5a3f8552016-04-05 12:17:51 -0400187 BOOST_TEST_MESSAGE(" server is listening");
Ben Craig1684c422015-04-24 08:52:44 -0500188 }
189
190 void blockUntilAccepted(uint64_t numAccepted) {
191 Synchronized sync(*(pEventHandler.get()));
192 while (pEventHandler->acceptedCount() < numAccepted) {
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200193 pEventHandler->wait();
Ben Craig1684c422015-04-24 08:52:44 -0500194 }
195
Jim King5a3f8552016-04-05 12:17:51 -0400196 BOOST_TEST_MESSAGE(boost::format(" server has accepted %1%") % numAccepted);
Ben Craig1684c422015-04-24 08:52:44 -0500197 }
198
199 void stopServer() {
Jim King79c99112015-04-30 07:10:08 -0400200 if (pServerThread) {
201 pServer->stop();
Jim King5a3f8552016-04-05 12:17:51 -0400202 BOOST_TEST_MESSAGE(" server stop completed");
Jim King79c99112015-04-30 07:10:08 -0400203
204 pServerThread->join();
Jim King5a3f8552016-04-05 12:17:51 -0400205 BOOST_TEST_MESSAGE(" server thread joined");
Jim King79c99112015-04-30 07:10:08 -0400206 pServerThread.reset();
207 }
Ben Craig1684c422015-04-24 08:52:44 -0500208 }
209
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200210 ~TServerIntegrationTestFixture() { stopServer(); }
Ben Craig1684c422015-04-24 08:52:44 -0500211
Jim King5a3f8552016-04-05 12:17:51 -0400212 /**
213 * Performs a baseline test where some clients are opened and issue a single operation
214 * and then disconnect at different intervals.
215 * \param[in] numToMake the number of concurrent clients
216 * \param[in] expectedHWM the high water mark we expect of concurrency
217 * \param[in] purpose a description of the test for logging purposes
218 */
219 void baseline(int64_t numToMake, int64_t expectedHWM, const std::string& purpose) {
220 BOOST_TEST_MESSAGE(boost::format("Testing %1%: %2% with %3% clients, expect %4% HWM")
221 % typeid(TServerType).name() % purpose % numToMake % expectedHWM);
Konrad Grochowski24ea0bf2015-05-07 14:59:29 +0200222
Jim King5a3f8552016-04-05 12:17:51 -0400223 startServer();
Ben Craig1684c422015-04-24 08:52:44 -0500224
Jim King79c99112015-04-30 07:10:08 -0400225 std::vector<boost::shared_ptr<TSocket> > holdSockets;
226 std::vector<boost::shared_ptr<boost::thread> > holdThreads;
227
228 for (int64_t i = 0; i < numToMake; ++i) {
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200229 boost::shared_ptr<TSocket> pClientSock(new TSocket("localhost", getServerPort()),
230 autoSocketCloser);
231 holdSockets.push_back(pClientSock);
232 boost::shared_ptr<TProtocol> pClientProtocol(new TBinaryProtocol(pClientSock));
233 ParentServiceClient client(pClientProtocol);
234 pClientSock->open();
235 client.incrementGeneration();
236 holdThreads.push_back(boost::shared_ptr<boost::thread>(
237 new boost::thread(boost::bind(&TServerIntegrationTestFixture::delayClose,
238 this,
239 pClientSock,
Jim King5a3f8552016-04-05 12:17:51 -0400240 milliseconds(10 * numToMake)))));
Jim King79c99112015-04-30 07:10:08 -0400241 }
242
243 BOOST_CHECK_EQUAL(expectedHWM, pServer->getConcurrentClientCountHWM());
Jim King5a3f8552016-04-05 12:17:51 -0400244
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200245 BOOST_FOREACH (boost::shared_ptr<boost::thread> pThread, holdThreads) { pThread->join(); }
Jim King79c99112015-04-30 07:10:08 -0400246 holdThreads.clear();
247 holdSockets.clear();
Jim King5a3f8552016-04-05 12:17:51 -0400248
249 stopServer();
250 }
251
252 /**
253 * Helper method used to close a connection after a delay.
254 * \param[in] toClose the connection to close
255 * \param[in] after the delay to impose
256 */
257 void delayClose(boost::shared_ptr<TTransport> toClose, boost::posix_time::time_duration after) {
258 boost::this_thread::sleep(after);
259 toClose->close();
260 }
261
262 /**
263 * \returns the server port number
264 */
265 int getServerPort() {
266 TServerSocket* pSock = dynamic_cast<TServerSocket*>(pServer->getServerTransport().get());
267 return pSock->getPort();
268 }
269
270 /**
271 * Performs a stress test by spawning threads that connect, do a number of operations
272 * and disconnect, then a random delay, then do it over again. This is done for a fixed
273 * period of time to test for concurrency correctness.
274 * \param[in] numToMake the number of concurrent clients
275 */
276 void stress(int64_t numToMake, const boost::posix_time::time_duration& duration) {
277 BOOST_TEST_MESSAGE(boost::format("Stress testing %1% with %2% clients for %3% seconds")
278 % typeid(TServerType).name() % numToMake % duration.total_seconds());
279
280 startServer();
281
282 std::vector<boost::shared_ptr<boost::thread> > holdThreads;
283 for (int64_t i = 0; i < numToMake; ++i) {
284 holdThreads.push_back(boost::shared_ptr<boost::thread>(
285 new boost::thread(boost::bind(&TServerIntegrationTestFixture::stressor, this))));
286 }
287
288 boost::this_thread::sleep(duration);
289 bStressDone = true;
290
291 BOOST_TEST_MESSAGE(boost::format(" serviced %1% connections (HWM %2%) totaling %3% requests")
292 % bStressConnectionCount % pServer->getConcurrentClientCountHWM() % bStressRequestCount);
293
294 BOOST_FOREACH (boost::shared_ptr<boost::thread> pThread, holdThreads) { pThread->join(); }
295 holdThreads.clear();
296
297 BOOST_CHECK(bStressRequestCount > 0);
298
299 stopServer();
300 }
301
302 /**
303 * Helper method to stress the system
304 */
305 void stressor() {
306 while (!bStressDone) {
307 boost::shared_ptr<TSocket> pSocket(new TSocket("localhost", getServerPort()), autoSocketCloser);
308 boost::shared_ptr<TProtocol> pProtocol(new TBinaryProtocol(pSocket));
309 ParentServiceClient client(pProtocol);
310 pSocket->open();
311 bStressConnectionCount.fetch_add(1, boost::memory_order_relaxed);
312 for (int i = 0; i < rand() % 1000; ++i) {
313 client.incrementGeneration();
314 bStressRequestCount.fetch_add(1, boost::memory_order_relaxed);
315 }
316 }
Jim King79c99112015-04-30 07:10:08 -0400317 }
318
319 boost::shared_ptr<TServerType> pServer;
Ben Craig1684c422015-04-24 08:52:44 -0500320 boost::shared_ptr<TServerReadyEventHandler> pEventHandler;
321 boost::shared_ptr<boost::thread> pServerThread;
Jim King5a3f8552016-04-05 12:17:51 -0400322 bool bStressDone;
323 boost::atomic_int64_t bStressConnectionCount;
324 boost::atomic_int64_t bStressRequestCount;
Ben Craig1684c422015-04-24 08:52:44 -0500325};
326
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200327template <class TServerType>
328class TServerIntegrationProcessorFactoryTestFixture
329 : public TServerIntegrationTestFixture<TServerType> {
Konrad Grochowski24ea0bf2015-05-07 14:59:29 +0200330public:
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200331 TServerIntegrationProcessorFactoryTestFixture()
332 : TServerIntegrationTestFixture<TServerType>(boost::make_shared<ParentServiceProcessorFactory>(
333 boost::make_shared<ParentServiceIfSingletonFactory>(
334 boost::make_shared<ParentHandler>()))) {}
Konrad Grochowski24ea0bf2015-05-07 14:59:29 +0200335};
Ben Craig1684c422015-04-24 08:52:44 -0500336
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200337template <class TServerType>
338class TServerIntegrationProcessorTestFixture : public TServerIntegrationTestFixture<TServerType> {
Konrad Grochowski24ea0bf2015-05-07 14:59:29 +0200339public:
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200340 TServerIntegrationProcessorTestFixture()
341 : TServerIntegrationTestFixture<TServerType>(
342 boost::make_shared<ParentServiceProcessor>(boost::make_shared<ParentHandler>())) {}
Konrad Grochowski24ea0bf2015-05-07 14:59:29 +0200343};
344
345BOOST_AUTO_TEST_SUITE(constructors)
346
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200347BOOST_FIXTURE_TEST_CASE(test_simple_factory,
348 TServerIntegrationProcessorFactoryTestFixture<TSimpleServer>) {
Jim King5a3f8552016-04-05 12:17:51 -0400349 baseline(3, 1, "factory");
Ben Craig1684c422015-04-24 08:52:44 -0500350}
351
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200352BOOST_FIXTURE_TEST_CASE(test_simple, TServerIntegrationProcessorTestFixture<TSimpleServer>) {
Jim King5a3f8552016-04-05 12:17:51 -0400353 baseline(3, 1, "processor");
Konrad Grochowski24ea0bf2015-05-07 14:59:29 +0200354}
355
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200356BOOST_FIXTURE_TEST_CASE(test_threaded_factory,
357 TServerIntegrationProcessorFactoryTestFixture<TThreadedServer>) {
Jim King5a3f8552016-04-05 12:17:51 -0400358 baseline(10, 10, "factory");
Jim King79c99112015-04-30 07:10:08 -0400359}
360
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200361BOOST_FIXTURE_TEST_CASE(test_threaded, TServerIntegrationProcessorTestFixture<TThreadedServer>) {
Jim King5a3f8552016-04-05 12:17:51 -0400362 baseline(10, 10, "processor");
Konrad Grochowski24ea0bf2015-05-07 14:59:29 +0200363}
364
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200365BOOST_FIXTURE_TEST_CASE(test_threaded_bound,
366 TServerIntegrationProcessorTestFixture<TThreadedServer>) {
367 pServer->setConcurrentClientLimit(4);
Jim King5a3f8552016-04-05 12:17:51 -0400368 baseline(10, 4, "limit by server framework");
369}
370
371BOOST_FIXTURE_TEST_CASE(test_threaded_stress,
372 TServerIntegrationProcessorFactoryTestFixture<TThreadedServer>) {
373 stress(10, boost::posix_time::seconds(3));
Jim King79c99112015-04-30 07:10:08 -0400374}
375
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200376BOOST_FIXTURE_TEST_CASE(test_threadpool_factory,
377 TServerIntegrationProcessorFactoryTestFixture<TThreadPoolServer>) {
378 pServer->getThreadManager()->threadFactory(
379 boost::shared_ptr<apache::thrift::concurrency::ThreadFactory>(
380 new apache::thrift::concurrency::PlatformThreadFactory));
381 pServer->getThreadManager()->start();
Jim King79c99112015-04-30 07:10:08 -0400382
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200383 // thread factory has 4 threads as a default
384 // thread factory however is a bad way to limit concurrent clients
385 // as accept() will be called to grab a 5th client socket, in this case
386 // and then the thread factory will block adding the thread to manage
387 // that client.
Jim King5a3f8552016-04-05 12:17:51 -0400388 baseline(10, 5, "limit by thread manager");
Jim King79c99112015-04-30 07:10:08 -0400389}
390
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200391BOOST_FIXTURE_TEST_CASE(test_threadpool,
392 TServerIntegrationProcessorTestFixture<TThreadPoolServer>) {
393 pServer->getThreadManager()->threadFactory(
394 boost::shared_ptr<apache::thrift::concurrency::ThreadFactory>(
395 new apache::thrift::concurrency::PlatformThreadFactory));
396 pServer->getThreadManager()->start();
Konrad Grochowski24ea0bf2015-05-07 14:59:29 +0200397
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200398 // thread factory has 4 threads as a default
399 // thread factory however is a bad way to limit concurrent clients
400 // as accept() will be called to grab a 5th client socket, in this case
401 // and then the thread factory will block adding the thread to manage
402 // that client.
Jim King5a3f8552016-04-05 12:17:51 -0400403 baseline(10, 5, "limit by thread manager");
Konrad Grochowski24ea0bf2015-05-07 14:59:29 +0200404}
405
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200406BOOST_FIXTURE_TEST_CASE(test_threadpool_bound,
407 TServerIntegrationProcessorTestFixture<TThreadPoolServer>) {
408 pServer->getThreadManager()->threadFactory(
409 boost::shared_ptr<apache::thrift::concurrency::ThreadFactory>(
410 new apache::thrift::concurrency::PlatformThreadFactory));
411 pServer->getThreadManager()->start();
412 pServer->setConcurrentClientLimit(4);
Jim King79c99112015-04-30 07:10:08 -0400413
Jim King5a3f8552016-04-05 12:17:51 -0400414 baseline(10, 4, "server framework connection limit");
415}
416
417BOOST_FIXTURE_TEST_CASE(test_threadpool_stress,
418 TServerIntegrationProcessorTestFixture<TThreadPoolServer>) {
419 pServer->getThreadManager()->threadFactory(
420 boost::shared_ptr<apache::thrift::concurrency::ThreadFactory>(
421 new apache::thrift::concurrency::PlatformThreadFactory));
422 pServer->getThreadManager()->start();
423
424 stress(10, boost::posix_time::seconds(3));
Jim King79c99112015-04-30 07:10:08 -0400425}
426
427BOOST_AUTO_TEST_SUITE_END()
428
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200429BOOST_FIXTURE_TEST_SUITE(TServerIntegrationTest,
430 TServerIntegrationProcessorTestFixture<TThreadedServer>)
Jim King79c99112015-04-30 07:10:08 -0400431
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200432BOOST_AUTO_TEST_CASE(test_stop_with_interruptable_clients_connected) {
433 // This tests THRIFT-2441 new behavior: stopping the server disconnects clients
Jim King5a3f8552016-04-05 12:17:51 -0400434 BOOST_TEST_MESSAGE("Testing stop with interruptable clients");
Jim King79c99112015-04-30 07:10:08 -0400435
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200436 startServer();
Ben Craig1684c422015-04-24 08:52:44 -0500437
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200438 boost::shared_ptr<TSocket> pClientSock1(new TSocket("localhost", getServerPort()),
439 autoSocketCloser);
440 pClientSock1->open();
Ben Craig1684c422015-04-24 08:52:44 -0500441
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200442 boost::shared_ptr<TSocket> pClientSock2(new TSocket("localhost", getServerPort()),
443 autoSocketCloser);
444 pClientSock2->open();
Ben Craig1684c422015-04-24 08:52:44 -0500445
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200446 // Ensure they have been accepted
447 blockUntilAccepted(2);
Ben Craig1684c422015-04-24 08:52:44 -0500448
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200449 // The test fixture destructor will force the sockets to disconnect
450 // Prior to THRIFT-2441, pServer->stop() would hang until clients disconnected
451 stopServer();
Ben Craig1684c422015-04-24 08:52:44 -0500452
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200453 // extra proof the server end disconnected the clients
454 uint8_t buf[1];
455 BOOST_CHECK_EQUAL(0, pClientSock1->read(&buf[0], 1)); // 0 = disconnected
456 BOOST_CHECK_EQUAL(0, pClientSock2->read(&buf[0], 1)); // 0 = disconnected
Ben Craig1684c422015-04-24 08:52:44 -0500457}
458
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200459BOOST_AUTO_TEST_CASE(test_stop_with_uninterruptable_clients_connected) {
460 // This tests pre-THRIFT-2441 behavior: stopping the server blocks until clients
461 // disconnect.
Jim King5a3f8552016-04-05 12:17:51 -0400462 BOOST_TEST_MESSAGE("Testing stop with uninterruptable clients");
Ben Craig1684c422015-04-24 08:52:44 -0500463
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200464 boost::dynamic_pointer_cast<TServerSocket>(pServer->getServerTransport())
465 ->setInterruptableChildren(false); // returns to pre-THRIFT-2441 behavior
Jim King79c99112015-04-30 07:10:08 -0400466
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200467 startServer();
Ben Craig1684c422015-04-24 08:52:44 -0500468
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200469 boost::shared_ptr<TSocket> pClientSock1(new TSocket("localhost", getServerPort()),
470 autoSocketCloser);
471 pClientSock1->open();
Ben Craig1684c422015-04-24 08:52:44 -0500472
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200473 boost::shared_ptr<TSocket> pClientSock2(new TSocket("localhost", getServerPort()),
474 autoSocketCloser);
475 pClientSock2->open();
Ben Craig1684c422015-04-24 08:52:44 -0500476
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200477 // Ensure they have been accepted
478 blockUntilAccepted(2);
Ben Craig1684c422015-04-24 08:52:44 -0500479
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200480 boost::thread t1(boost::bind(&TServerIntegrationTestFixture::delayClose,
481 this,
482 pClientSock1,
483 milliseconds(250)));
484 boost::thread t2(boost::bind(&TServerIntegrationTestFixture::delayClose,
485 this,
486 pClientSock2,
487 milliseconds(250)));
Ben Craig1684c422015-04-24 08:52:44 -0500488
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200489 // Once the clients disconnect the server will stop
490 stopServer();
Jim King5a3f8552016-04-05 12:17:51 -0400491 BOOST_CHECK(pServer->getConcurrentClientCountHWM() > 0);
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200492 t1.join();
493 t2.join();
Ben Craig1684c422015-04-24 08:52:44 -0500494}
Jim King79c99112015-04-30 07:10:08 -0400495
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200496BOOST_AUTO_TEST_CASE(test_concurrent_client_limit) {
497 startServer();
Jim King5a3f8552016-04-05 12:17:51 -0400498 BOOST_TEST_MESSAGE("Testing the concurrent client limit");
Jim King79c99112015-04-30 07:10:08 -0400499
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200500 BOOST_CHECK_EQUAL(INT64_MAX, pServer->getConcurrentClientLimit());
501 pServer->setConcurrentClientLimit(2);
502 BOOST_CHECK_EQUAL(0, pServer->getConcurrentClientCount());
503 BOOST_CHECK_EQUAL(2, pServer->getConcurrentClientLimit());
Jim King79c99112015-04-30 07:10:08 -0400504
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200505 boost::shared_ptr<TSocket> pClientSock1(new TSocket("localhost", getServerPort()),
506 autoSocketCloser);
507 pClientSock1->open();
508 blockUntilAccepted(1);
509 BOOST_CHECK_EQUAL(1, pServer->getConcurrentClientCount());
Jim King79c99112015-04-30 07:10:08 -0400510
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200511 boost::shared_ptr<TSocket> pClientSock2(new TSocket("localhost", getServerPort()),
512 autoSocketCloser);
513 pClientSock2->open();
514 blockUntilAccepted(2);
515 BOOST_CHECK_EQUAL(2, pServer->getConcurrentClientCount());
Jim King79c99112015-04-30 07:10:08 -0400516
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200517 // a third client cannot connect until one of the other two closes
518 boost::thread t2(boost::bind(&TServerIntegrationTestFixture::delayClose,
519 this,
520 pClientSock2,
521 milliseconds(250)));
522 boost::shared_ptr<TSocket> pClientSock3(new TSocket("localhost", getServerPort()),
523 autoSocketCloser);
524 pClientSock2->open();
525 blockUntilAccepted(2);
526 BOOST_CHECK_EQUAL(2, pServer->getConcurrentClientCount());
527 BOOST_CHECK_EQUAL(2, pServer->getConcurrentClientCountHWM());
Jim King79c99112015-04-30 07:10:08 -0400528
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200529 stopServer();
Jim King5a3f8552016-04-05 12:17:51 -0400530 BOOST_CHECK(pServer->getConcurrentClientCountHWM() > 0);
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200531 t2.join();
Jim King79c99112015-04-30 07:10:08 -0400532}
533
Ben Craig1684c422015-04-24 08:52:44 -0500534BOOST_AUTO_TEST_SUITE_END()