blob: ab235d5a4f77ec7c3b6b8bd2ca37c802dedaa2d4 [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
cyy7f8aef72019-01-06 10:05:50 +080021#include <atomic>
zeshuai0076b1cb302020-05-27 12:08:01 +080022#include <boost/test/unit_test.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>
cyy316723a2019-01-05 16:35:14 +080030#include <memory>
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;
cyy316723a2019-01-05 16:35:14 +080058using std::dynamic_pointer_cast;
59using std::make_shared;
60using std::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) {}
Sebastian Zenker042580f2019-01-29 15:48:12 +010077 ~TServerReadyEventHandler() override = default;
78 void preServe() override {
Ben Craig1684c422015-04-24 08:52:44 -050079 Synchronized sync(*this);
80 isListening_ = true;
81 notify();
82 }
Sebastian Zenker042580f2019-01-29 15:48:12 +010083 void* createContext(shared_ptr<TProtocol> input,
84 shared_ptr<TProtocol> output) override {
Ben Craig1684c422015-04-24 08:52:44 -050085 Synchronized sync(*this);
86 ++accepted_;
87 notify();
88
89 (void)input;
90 (void)output;
Sebastian Zenker042580f2019-01-29 15:48:12 +010091 return nullptr;
Ben Craig1684c422015-04-24 08:52:44 -050092 }
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
Sebastian Zenker042580f2019-01-29 15:48:12 +0100108 int32_t incrementGeneration() override {
Ben Craig1684c422015-04-24 08:52:44 -0500109 Guard g(mutex_);
110 return ++generation_;
111 }
112
Sebastian Zenker042580f2019-01-29 15:48:12 +0100113 int32_t getGeneration() override {
Ben Craig1684c422015-04-24 08:52:44 -0500114 Guard g(mutex_);
115 return generation_;
116 }
117
Sebastian Zenker042580f2019-01-29 15:48:12 +0100118 void addString(const std::string& s) override {
Ben Craig1684c422015-04-24 08:52:44 -0500119 Guard g(mutex_);
120 strings_.push_back(s);
121 }
122
Sebastian Zenker042580f2019-01-29 15:48:12 +0100123 void getStrings(std::vector<std::string>& _return) override {
Ben Craig1684c422015-04-24 08:52:44 -0500124 Guard g(mutex_);
125 _return = strings_;
126 }
127
Sebastian Zenker042580f2019-01-29 15:48:12 +0100128 void getDataWait(std::string& _return, const int32_t length) override {
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
Sebastian Zenker042580f2019-01-29 15:48:12 +0100133 void onewayWait() override {}
Ben Craig1684c422015-04-24 08:52:44 -0500134
Sebastian Zenker042580f2019-01-29 15:48:12 +0100135 void exceptionWait(const std::string& message) override { THRIFT_UNUSED_VARIABLE(message); }
Ben Craig1684c422015-04-24 08:52:44 -0500136
Sebastian Zenker042580f2019-01-29 15:48:12 +0100137 void unexpectedExceptionWait(const std::string& message) override { 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() {
cyy316723a2019-01-05 16:35:14 +0800180 pServerThread.reset(new boost::thread(std::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>(
cyy316723a2019-01-05 16:35:14 +0800238 new boost::thread(std::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() {
Sebastian Zenker042580f2019-01-29 15:48:12 +0100267 auto* pSock = dynamic_cast<TServerSocket*>(pServer->getServerTransport().get());
James E. King, III533405e2017-10-28 18:25:45 -0400268 if (!pSock) { throw std::logic_error("how come?"); }
Jim King5a3f8552016-04-05 12:17:51 -0400269 return pSock->getPort();
270 }
271
272 /**
273 * Performs a stress test by spawning threads that connect, do a number of operations
274 * and disconnect, then a random delay, then do it over again. This is done for a fixed
275 * period of time to test for concurrency correctness.
276 * \param[in] numToMake the number of concurrent clients
277 */
278 void stress(int64_t numToMake, const boost::posix_time::time_duration& duration) {
279 BOOST_TEST_MESSAGE(boost::format("Stress testing %1% with %2% clients for %3% seconds")
280 % typeid(TServerType).name() % numToMake % duration.total_seconds());
281
282 startServer();
283
James E. King, III82ae9572017-08-05 12:23:54 -0400284 std::vector<shared_ptr<boost::thread> > holdThreads;
Jim King5a3f8552016-04-05 12:17:51 -0400285 for (int64_t i = 0; i < numToMake; ++i) {
James E. King, III82ae9572017-08-05 12:23:54 -0400286 holdThreads.push_back(shared_ptr<boost::thread>(
cyy316723a2019-01-05 16:35:14 +0800287 new boost::thread(std::bind(&TServerIntegrationTestFixture::stressor, this))));
Jim King5a3f8552016-04-05 12:17:51 -0400288 }
289
290 boost::this_thread::sleep(duration);
291 bStressDone = true;
292
293 BOOST_TEST_MESSAGE(boost::format(" serviced %1% connections (HWM %2%) totaling %3% requests")
294 % bStressConnectionCount % pServer->getConcurrentClientCountHWM() % bStressRequestCount);
295
James E. King, III82ae9572017-08-05 12:23:54 -0400296 BOOST_FOREACH (shared_ptr<boost::thread> pThread, holdThreads) { pThread->join(); }
Jim King5a3f8552016-04-05 12:17:51 -0400297 holdThreads.clear();
298
299 BOOST_CHECK(bStressRequestCount > 0);
300
301 stopServer();
302 }
303
304 /**
305 * Helper method to stress the system
306 */
307 void stressor() {
James E. King, IIIdf899132016-11-12 15:16:30 -0500308 while (!bStressDone) {
James E. King, III82ae9572017-08-05 12:23:54 -0400309 shared_ptr<TSocket> pSocket(new TSocket("localhost", getServerPort()), autoSocketCloser);
310 shared_ptr<TProtocol> pProtocol(new TBinaryProtocol(pSocket));
Jim King5a3f8552016-04-05 12:17:51 -0400311 ParentServiceClient client(pProtocol);
312 pSocket->open();
cyy7f8aef72019-01-06 10:05:50 +0800313 bStressConnectionCount.fetch_add(1, std::memory_order_relaxed);
Jim King5a3f8552016-04-05 12:17:51 -0400314 for (int i = 0; i < rand() % 1000; ++i) {
James E. King, IIIdf899132016-11-12 15:16:30 -0500315 client.incrementGeneration();
cyy7f8aef72019-01-06 10:05:50 +0800316 bStressRequestCount.fetch_add(1, std::memory_order_relaxed);
Jim King5a3f8552016-04-05 12:17:51 -0400317 }
318 }
Jim King79c99112015-04-30 07:10:08 -0400319 }
320
James E. King, III82ae9572017-08-05 12:23:54 -0400321 shared_ptr<TServerType> pServer;
322 shared_ptr<TServerReadyEventHandler> pEventHandler;
323 shared_ptr<boost::thread> pServerThread;
cyy7f8aef72019-01-06 10:05:50 +0800324 std::atomic<bool> bStressDone;
325 std::atomic<int64_t> bStressConnectionCount;
326 std::atomic<int64_t> bStressRequestCount;
Ben Craig1684c422015-04-24 08:52:44 -0500327};
328
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200329template <class TServerType>
330class TServerIntegrationProcessorFactoryTestFixture
331 : public TServerIntegrationTestFixture<TServerType> {
Konrad Grochowski24ea0bf2015-05-07 14:59:29 +0200332public:
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200333 TServerIntegrationProcessorFactoryTestFixture()
James E. King, III82ae9572017-08-05 12:23:54 -0400334 : TServerIntegrationTestFixture<TServerType>(make_shared<ParentServiceProcessorFactory>(
335 make_shared<ParentServiceIfSingletonFactory>(
336 make_shared<ParentHandler>()))) {}
Konrad Grochowski24ea0bf2015-05-07 14:59:29 +0200337};
Ben Craig1684c422015-04-24 08:52:44 -0500338
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200339template <class TServerType>
340class TServerIntegrationProcessorTestFixture : public TServerIntegrationTestFixture<TServerType> {
Konrad Grochowski24ea0bf2015-05-07 14:59:29 +0200341public:
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200342 TServerIntegrationProcessorTestFixture()
343 : TServerIntegrationTestFixture<TServerType>(
James E. King, III82ae9572017-08-05 12:23:54 -0400344 make_shared<ParentServiceProcessor>(make_shared<ParentHandler>())) {}
Konrad Grochowski24ea0bf2015-05-07 14:59:29 +0200345};
346
347BOOST_AUTO_TEST_SUITE(constructors)
348
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200349BOOST_FIXTURE_TEST_CASE(test_simple_factory,
350 TServerIntegrationProcessorFactoryTestFixture<TSimpleServer>) {
Jim King5a3f8552016-04-05 12:17:51 -0400351 baseline(3, 1, "factory");
Ben Craig1684c422015-04-24 08:52:44 -0500352}
353
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200354BOOST_FIXTURE_TEST_CASE(test_simple, TServerIntegrationProcessorTestFixture<TSimpleServer>) {
Jim King5a3f8552016-04-05 12:17:51 -0400355 baseline(3, 1, "processor");
Konrad Grochowski24ea0bf2015-05-07 14:59:29 +0200356}
357
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200358BOOST_FIXTURE_TEST_CASE(test_threaded_factory,
359 TServerIntegrationProcessorFactoryTestFixture<TThreadedServer>) {
Jim King5a3f8552016-04-05 12:17:51 -0400360 baseline(10, 10, "factory");
Jim King79c99112015-04-30 07:10:08 -0400361}
362
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200363BOOST_FIXTURE_TEST_CASE(test_threaded, TServerIntegrationProcessorTestFixture<TThreadedServer>) {
Jim King5a3f8552016-04-05 12:17:51 -0400364 baseline(10, 10, "processor");
Konrad Grochowski24ea0bf2015-05-07 14:59:29 +0200365}
366
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200367BOOST_FIXTURE_TEST_CASE(test_threaded_bound,
368 TServerIntegrationProcessorTestFixture<TThreadedServer>) {
369 pServer->setConcurrentClientLimit(4);
Jim King5a3f8552016-04-05 12:17:51 -0400370 baseline(10, 4, "limit by server framework");
371}
372
373BOOST_FIXTURE_TEST_CASE(test_threaded_stress,
374 TServerIntegrationProcessorFactoryTestFixture<TThreadedServer>) {
375 stress(10, boost::posix_time::seconds(3));
Jim King79c99112015-04-30 07:10:08 -0400376}
377
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200378BOOST_FIXTURE_TEST_CASE(test_threadpool_factory,
379 TServerIntegrationProcessorFactoryTestFixture<TThreadPoolServer>) {
380 pServer->getThreadManager()->threadFactory(
James E. King, III82ae9572017-08-05 12:23:54 -0400381 shared_ptr<apache::thrift::concurrency::ThreadFactory>(
cyyca8af9b2019-01-11 22:13:12 +0800382 new apache::thrift::concurrency::ThreadFactory));
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200383 pServer->getThreadManager()->start();
Jim King79c99112015-04-30 07:10:08 -0400384
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200385 // thread factory has 4 threads as a default
386 // thread factory however is a bad way to limit concurrent clients
387 // as accept() will be called to grab a 5th client socket, in this case
388 // and then the thread factory will block adding the thread to manage
389 // that client.
Jim King5a3f8552016-04-05 12:17:51 -0400390 baseline(10, 5, "limit by thread manager");
Jim King79c99112015-04-30 07:10:08 -0400391}
392
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200393BOOST_FIXTURE_TEST_CASE(test_threadpool,
394 TServerIntegrationProcessorTestFixture<TThreadPoolServer>) {
395 pServer->getThreadManager()->threadFactory(
James E. King, III82ae9572017-08-05 12:23:54 -0400396 shared_ptr<apache::thrift::concurrency::ThreadFactory>(
cyyca8af9b2019-01-11 22:13:12 +0800397 new apache::thrift::concurrency::ThreadFactory));
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200398 pServer->getThreadManager()->start();
Konrad Grochowski24ea0bf2015-05-07 14:59:29 +0200399
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200400 // thread factory has 4 threads as a default
401 // thread factory however is a bad way to limit concurrent clients
402 // as accept() will be called to grab a 5th client socket, in this case
403 // and then the thread factory will block adding the thread to manage
404 // that client.
Jim King5a3f8552016-04-05 12:17:51 -0400405 baseline(10, 5, "limit by thread manager");
Konrad Grochowski24ea0bf2015-05-07 14:59:29 +0200406}
407
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200408BOOST_FIXTURE_TEST_CASE(test_threadpool_bound,
409 TServerIntegrationProcessorTestFixture<TThreadPoolServer>) {
410 pServer->getThreadManager()->threadFactory(
James E. King, III82ae9572017-08-05 12:23:54 -0400411 shared_ptr<apache::thrift::concurrency::ThreadFactory>(
cyyca8af9b2019-01-11 22:13:12 +0800412 new apache::thrift::concurrency::ThreadFactory));
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200413 pServer->getThreadManager()->start();
414 pServer->setConcurrentClientLimit(4);
Jim King79c99112015-04-30 07:10:08 -0400415
Jim King5a3f8552016-04-05 12:17:51 -0400416 baseline(10, 4, "server framework connection limit");
417}
418
419BOOST_FIXTURE_TEST_CASE(test_threadpool_stress,
420 TServerIntegrationProcessorTestFixture<TThreadPoolServer>) {
421 pServer->getThreadManager()->threadFactory(
James E. King, III82ae9572017-08-05 12:23:54 -0400422 shared_ptr<apache::thrift::concurrency::ThreadFactory>(
cyyca8af9b2019-01-11 22:13:12 +0800423 new apache::thrift::concurrency::ThreadFactory));
Jim King5a3f8552016-04-05 12:17:51 -0400424 pServer->getThreadManager()->start();
425
426 stress(10, boost::posix_time::seconds(3));
Jim King79c99112015-04-30 07:10:08 -0400427}
428
429BOOST_AUTO_TEST_SUITE_END()
430
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200431BOOST_FIXTURE_TEST_SUITE(TServerIntegrationTest,
432 TServerIntegrationProcessorTestFixture<TThreadedServer>)
Jim King79c99112015-04-30 07:10:08 -0400433
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200434BOOST_AUTO_TEST_CASE(test_stop_with_interruptable_clients_connected) {
435 // This tests THRIFT-2441 new behavior: stopping the server disconnects clients
Jim King5a3f8552016-04-05 12:17:51 -0400436 BOOST_TEST_MESSAGE("Testing stop with interruptable clients");
Jim King79c99112015-04-30 07:10:08 -0400437
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200438 startServer();
Ben Craig1684c422015-04-24 08:52:44 -0500439
James E. King, III82ae9572017-08-05 12:23:54 -0400440 shared_ptr<TSocket> pClientSock1(new TSocket("localhost", getServerPort()),
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200441 autoSocketCloser);
442 pClientSock1->open();
Ben Craig1684c422015-04-24 08:52:44 -0500443
James E. King, III82ae9572017-08-05 12:23:54 -0400444 shared_ptr<TSocket> pClientSock2(new TSocket("localhost", getServerPort()),
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200445 autoSocketCloser);
446 pClientSock2->open();
Ben Craig1684c422015-04-24 08:52:44 -0500447
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200448 // Ensure they have been accepted
449 blockUntilAccepted(2);
Ben Craig1684c422015-04-24 08:52:44 -0500450
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200451 // The test fixture destructor will force the sockets to disconnect
452 // Prior to THRIFT-2441, pServer->stop() would hang until clients disconnected
453 stopServer();
Ben Craig1684c422015-04-24 08:52:44 -0500454
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200455 // extra proof the server end disconnected the clients
456 uint8_t buf[1];
457 BOOST_CHECK_EQUAL(0, pClientSock1->read(&buf[0], 1)); // 0 = disconnected
458 BOOST_CHECK_EQUAL(0, pClientSock2->read(&buf[0], 1)); // 0 = disconnected
Ben Craig1684c422015-04-24 08:52:44 -0500459}
460
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200461BOOST_AUTO_TEST_CASE(test_stop_with_uninterruptable_clients_connected) {
462 // This tests pre-THRIFT-2441 behavior: stopping the server blocks until clients
463 // disconnect.
James E. King, IIIdf899132016-11-12 15:16:30 -0500464 BOOST_TEST_MESSAGE("Testing stop with uninterruptable clients");
Ben Craig1684c422015-04-24 08:52:44 -0500465
James E. King, III82ae9572017-08-05 12:23:54 -0400466 dynamic_pointer_cast<TServerSocket>(pServer->getServerTransport())
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200467 ->setInterruptableChildren(false); // returns to pre-THRIFT-2441 behavior
Jim King79c99112015-04-30 07:10:08 -0400468
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200469 startServer();
Ben Craig1684c422015-04-24 08:52:44 -0500470
James E. King, III82ae9572017-08-05 12:23:54 -0400471 shared_ptr<TSocket> pClientSock1(new TSocket("localhost", getServerPort()),
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200472 autoSocketCloser);
473 pClientSock1->open();
Ben Craig1684c422015-04-24 08:52:44 -0500474
James E. King, III82ae9572017-08-05 12:23:54 -0400475 shared_ptr<TSocket> pClientSock2(new TSocket("localhost", getServerPort()),
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200476 autoSocketCloser);
477 pClientSock2->open();
Ben Craig1684c422015-04-24 08:52:44 -0500478
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200479 // Ensure they have been accepted
480 blockUntilAccepted(2);
Ben Craig1684c422015-04-24 08:52:44 -0500481
cyy316723a2019-01-05 16:35:14 +0800482 boost::thread t1(std::bind(&TServerIntegrationTestFixture::delayClose,
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200483 this,
484 pClientSock1,
485 milliseconds(250)));
cyy316723a2019-01-05 16:35:14 +0800486 boost::thread t2(std::bind(&TServerIntegrationTestFixture::delayClose,
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200487 this,
488 pClientSock2,
489 milliseconds(250)));
Ben Craig1684c422015-04-24 08:52:44 -0500490
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200491 // Once the clients disconnect the server will stop
492 stopServer();
Jim King5a3f8552016-04-05 12:17:51 -0400493 BOOST_CHECK(pServer->getConcurrentClientCountHWM() > 0);
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200494 t1.join();
495 t2.join();
Ben Craig1684c422015-04-24 08:52:44 -0500496}
Jim King79c99112015-04-30 07:10:08 -0400497
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200498BOOST_AUTO_TEST_CASE(test_concurrent_client_limit) {
499 startServer();
Jim King5a3f8552016-04-05 12:17:51 -0400500 BOOST_TEST_MESSAGE("Testing the concurrent client limit");
Jim King79c99112015-04-30 07:10:08 -0400501
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200502 BOOST_CHECK_EQUAL(INT64_MAX, pServer->getConcurrentClientLimit());
503 pServer->setConcurrentClientLimit(2);
504 BOOST_CHECK_EQUAL(0, pServer->getConcurrentClientCount());
505 BOOST_CHECK_EQUAL(2, pServer->getConcurrentClientLimit());
Jim King79c99112015-04-30 07:10:08 -0400506
James E. King, III82ae9572017-08-05 12:23:54 -0400507 shared_ptr<TSocket> pClientSock1(new TSocket("localhost", getServerPort()),
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200508 autoSocketCloser);
509 pClientSock1->open();
510 blockUntilAccepted(1);
511 BOOST_CHECK_EQUAL(1, pServer->getConcurrentClientCount());
Jim King79c99112015-04-30 07:10:08 -0400512
James E. King, III82ae9572017-08-05 12:23:54 -0400513 shared_ptr<TSocket> pClientSock2(new TSocket("localhost", getServerPort()),
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200514 autoSocketCloser);
515 pClientSock2->open();
516 blockUntilAccepted(2);
517 BOOST_CHECK_EQUAL(2, pServer->getConcurrentClientCount());
Jim King79c99112015-04-30 07:10:08 -0400518
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200519 // a third client cannot connect until one of the other two closes
cyy316723a2019-01-05 16:35:14 +0800520 boost::thread t2(std::bind(&TServerIntegrationTestFixture::delayClose,
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200521 this,
522 pClientSock2,
523 milliseconds(250)));
James E. King, III82ae9572017-08-05 12:23:54 -0400524 shared_ptr<TSocket> pClientSock3(new TSocket("localhost", getServerPort()),
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200525 autoSocketCloser);
526 pClientSock2->open();
527 blockUntilAccepted(2);
528 BOOST_CHECK_EQUAL(2, pServer->getConcurrentClientCount());
529 BOOST_CHECK_EQUAL(2, pServer->getConcurrentClientCountHWM());
Jim King79c99112015-04-30 07:10:08 -0400530
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200531 stopServer();
Jim King5a3f8552016-04-05 12:17:51 -0400532 BOOST_CHECK(pServer->getConcurrentClientCountHWM() > 0);
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200533 t2.join();
Jim King79c99112015-04-30 07:10:08 -0400534}
535
Ben Craig1684c422015-04-24 08:52:44 -0500536BOOST_AUTO_TEST_SUITE_END()