blob: ce1cbd32e2737429393c3e5730d058f90df359ed [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>
22#include <boost/bind.hpp>
Jim King79c99112015-04-30 07:10:08 -040023#include <boost/foreach.hpp>
Ben Craig1684c422015-04-24 08:52:44 -050024#include <boost/format.hpp>
Konrad Grochowski24ea0bf2015-05-07 14:59:29 +020025#include <boost/make_shared.hpp>
Ben Craig1684c422015-04-24 08:52:44 -050026#include <boost/shared_ptr.hpp>
27#include <boost/thread.hpp>
Jim King79c99112015-04-30 07:10:08 -040028#include <thrift/server/TSimpleServer.h>
29#include <thrift/server/TThreadPoolServer.h>
Ben Craig1684c422015-04-24 08:52:44 -050030#include <thrift/server/TThreadedServer.h>
31#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"
Ben Craig1684c422015-04-24 08:52:44 -050036#include <vector>
37
38using apache::thrift::concurrency::Guard;
39using apache::thrift::concurrency::Monitor;
40using apache::thrift::concurrency::Mutex;
41using apache::thrift::concurrency::Synchronized;
42using apache::thrift::protocol::TBinaryProtocol;
43using apache::thrift::protocol::TBinaryProtocolFactory;
44using apache::thrift::protocol::TProtocol;
45using apache::thrift::protocol::TProtocolFactory;
46using apache::thrift::transport::TServerSocket;
47using apache::thrift::transport::TServerTransport;
48using apache::thrift::transport::TSocket;
49using apache::thrift::transport::TTransport;
Jim King79c99112015-04-30 07:10:08 -040050using apache::thrift::transport::TTransportException;
Ben Craig1684c422015-04-24 08:52:44 -050051using apache::thrift::transport::TTransportFactory;
Jim King79c99112015-04-30 07:10:08 -040052using apache::thrift::server::TServer;
Ben Craig1684c422015-04-24 08:52:44 -050053using apache::thrift::server::TServerEventHandler;
Jim King79c99112015-04-30 07:10:08 -040054using apache::thrift::server::TSimpleServer;
55using apache::thrift::server::TThreadPoolServer;
Ben Craig1684c422015-04-24 08:52:44 -050056using apache::thrift::server::TThreadedServer;
57using apache::thrift::test::ParentServiceClient;
58using apache::thrift::test::ParentServiceIf;
Konrad Grochowski24ea0bf2015-05-07 14:59:29 +020059using apache::thrift::test::ParentServiceIfFactory;
60using apache::thrift::test::ParentServiceIfSingletonFactory;
Ben Craig1684c422015-04-24 08:52:44 -050061using apache::thrift::test::ParentServiceProcessor;
Konrad Grochowski24ea0bf2015-05-07 14:59:29 +020062using apache::thrift::test::ParentServiceProcessorFactory;
63using apache::thrift::TProcessor;
64using apache::thrift::TProcessorFactory;
Jim King79c99112015-04-30 07:10:08 -040065using boost::posix_time::milliseconds;
Ben Craig1684c422015-04-24 08:52:44 -050066
67/**
68 * preServe runs after listen() is successful, when we can connect
69 */
Konrad Grochowski1f6e3802015-05-18 18:10:06 +020070class TServerReadyEventHandler : public TServerEventHandler, public Monitor {
Ben Craig1684c422015-04-24 08:52:44 -050071public:
72 TServerReadyEventHandler() : isListening_(false), accepted_(0) {}
73 virtual ~TServerReadyEventHandler() {}
74 virtual void preServe() {
75 Synchronized sync(*this);
76 isListening_ = true;
77 notify();
78 }
79 virtual void* createContext(boost::shared_ptr<TProtocol> input,
80 boost::shared_ptr<TProtocol> output) {
81 Synchronized sync(*this);
82 ++accepted_;
83 notify();
84
85 (void)input;
86 (void)output;
87 return NULL;
88 }
89 bool isListening() const { return isListening_; }
90 uint64_t acceptedCount() const { return accepted_; }
Konrad Grochowski1f6e3802015-05-18 18:10:06 +020091
Ben Craig1684c422015-04-24 08:52:44 -050092private:
93 bool isListening_;
94 uint64_t accepted_;
95};
96
Jim King79c99112015-04-30 07:10:08 -040097/**
98 * Reusing another generated test, just something to serve up
99 */
100class ParentHandler : public ParentServiceIf {
Ben Craig1684c422015-04-24 08:52:44 -0500101public:
102 ParentHandler() : generation_(0) {}
103
104 int32_t incrementGeneration() {
105 Guard g(mutex_);
106 return ++generation_;
107 }
108
109 int32_t getGeneration() {
110 Guard g(mutex_);
111 return generation_;
112 }
113
114 void addString(const std::string& s) {
115 Guard g(mutex_);
116 strings_.push_back(s);
117 }
118
119 void getStrings(std::vector<std::string>& _return) {
120 Guard g(mutex_);
121 _return = strings_;
122 }
123
ben-craigfae08e72015-07-15 11:34:47 -0500124 void getDataWait(std::string& _return, const int32_t length) {
Konrad Grochowski24ea0bf2015-05-07 14:59:29 +0200125 THRIFT_UNUSED_VARIABLE(_return);
126 THRIFT_UNUSED_VARIABLE(length);
Ben Craig1684c422015-04-24 08:52:44 -0500127 }
128
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200129 void onewayWait() {}
Ben Craig1684c422015-04-24 08:52:44 -0500130
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200131 void exceptionWait(const std::string& message) { THRIFT_UNUSED_VARIABLE(message); }
Ben Craig1684c422015-04-24 08:52:44 -0500132
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200133 void unexpectedExceptionWait(const std::string& message) { THRIFT_UNUSED_VARIABLE(message); }
Ben Craig1684c422015-04-24 08:52:44 -0500134
135protected:
136 Mutex mutex_;
137 int32_t generation_;
138 std::vector<std::string> strings_;
139};
140
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200141void autoSocketCloser(TSocket* pSock) {
Jim King79c99112015-04-30 07:10:08 -0400142 pSock->close();
143 delete pSock;
144}
145
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200146template <class TServerType>
John Sirois919752c2016-02-13 12:35:58 -0700147class TServerIntegrationTestFixture {
Ben Craig1684c422015-04-24 08:52:44 -0500148public:
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200149 TServerIntegrationTestFixture(const boost::shared_ptr<TProcessorFactory>& _processorFactory)
150 : pServer(new TServerType(_processorFactory,
151 boost::shared_ptr<TServerTransport>(
John Sirois919752c2016-02-13 12:35:58 -0700152 new TServerSocket("localhost", 0)),
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200153 boost::shared_ptr<TTransportFactory>(new TTransportFactory),
154 boost::shared_ptr<TProtocolFactory>(new TBinaryProtocolFactory))),
155 pEventHandler(boost::shared_ptr<TServerReadyEventHandler>(new TServerReadyEventHandler)) {
Ben Craig1684c422015-04-24 08:52:44 -0500156 pServer->setServerEventHandler(pEventHandler);
157 }
158
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200159 TServerIntegrationTestFixture(const boost::shared_ptr<TProcessor>& _processor)
160 : pServer(
161 new TServerType(_processor,
162 boost::shared_ptr<TServerTransport>(new TServerSocket("localhost", 0)),
163 boost::shared_ptr<TTransportFactory>(new TTransportFactory),
164 boost::shared_ptr<TProtocolFactory>(new TBinaryProtocolFactory))),
165 pEventHandler(boost::shared_ptr<TServerReadyEventHandler>(new TServerReadyEventHandler)) {
Konrad Grochowski24ea0bf2015-05-07 14:59:29 +0200166 pServer->setServerEventHandler(pEventHandler);
167 }
168
Ben Craig1684c422015-04-24 08:52:44 -0500169 void startServer() {
Jim King79c99112015-04-30 07:10:08 -0400170 pServerThread.reset(new boost::thread(boost::bind(&TServerType::serve, pServer.get())));
Ben Craig1684c422015-04-24 08:52:44 -0500171
172 // block until listen() completes so clients will be able to connect
173 Synchronized sync(*(pEventHandler.get()));
174 while (!pEventHandler->isListening()) {
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200175 pEventHandler->wait();
Ben Craig1684c422015-04-24 08:52:44 -0500176 }
177
Konrad Grochowskie9bdb412015-09-25 20:17:36 +0200178 BOOST_TEST_MESSAGE("server is listening");
Ben Craig1684c422015-04-24 08:52:44 -0500179 }
180
181 void blockUntilAccepted(uint64_t numAccepted) {
182 Synchronized sync(*(pEventHandler.get()));
183 while (pEventHandler->acceptedCount() < numAccepted) {
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200184 pEventHandler->wait();
Ben Craig1684c422015-04-24 08:52:44 -0500185 }
186
Konrad Grochowskie9bdb412015-09-25 20:17:36 +0200187 BOOST_TEST_MESSAGE(boost::format("server has accepted %1%") % numAccepted);
Ben Craig1684c422015-04-24 08:52:44 -0500188 }
189
190 void stopServer() {
Jim King79c99112015-04-30 07:10:08 -0400191 if (pServerThread) {
192 pServer->stop();
Konrad Grochowskie9bdb412015-09-25 20:17:36 +0200193 BOOST_TEST_MESSAGE("server stop completed");
Jim King79c99112015-04-30 07:10:08 -0400194
195 pServerThread->join();
Konrad Grochowskie9bdb412015-09-25 20:17:36 +0200196 BOOST_TEST_MESSAGE("server thread joined");
Jim King79c99112015-04-30 07:10:08 -0400197 pServerThread.reset();
198 }
Ben Craig1684c422015-04-24 08:52:44 -0500199 }
200
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200201 ~TServerIntegrationTestFixture() { stopServer(); }
Ben Craig1684c422015-04-24 08:52:44 -0500202
Konrad Grochowski24ea0bf2015-05-07 14:59:29 +0200203 int getServerPort() {
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200204 TServerSocket* pSock = dynamic_cast<TServerSocket*>(pServer->getServerTransport().get());
Konrad Grochowski24ea0bf2015-05-07 14:59:29 +0200205 return pSock->getPort();
206 }
207
Jim King79c99112015-04-30 07:10:08 -0400208 void delayClose(boost::shared_ptr<TTransport> toClose, boost::posix_time::time_duration after) {
209 boost::this_thread::sleep(after);
Ben Craig1684c422015-04-24 08:52:44 -0500210 toClose->close();
211 }
212
Jim King79c99112015-04-30 07:10:08 -0400213 void baseline(int64_t numToMake, int64_t expectedHWM) {
214 startServer();
215 std::vector<boost::shared_ptr<TSocket> > holdSockets;
216 std::vector<boost::shared_ptr<boost::thread> > holdThreads;
217
218 for (int64_t i = 0; i < numToMake; ++i) {
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200219 boost::shared_ptr<TSocket> pClientSock(new TSocket("localhost", getServerPort()),
220 autoSocketCloser);
221 holdSockets.push_back(pClientSock);
222 boost::shared_ptr<TProtocol> pClientProtocol(new TBinaryProtocol(pClientSock));
223 ParentServiceClient client(pClientProtocol);
224 pClientSock->open();
225 client.incrementGeneration();
226 holdThreads.push_back(boost::shared_ptr<boost::thread>(
227 new boost::thread(boost::bind(&TServerIntegrationTestFixture::delayClose,
228 this,
229 pClientSock,
230 milliseconds(100 * numToMake)))));
Jim King79c99112015-04-30 07:10:08 -0400231 }
232
233 BOOST_CHECK_EQUAL(expectedHWM, pServer->getConcurrentClientCountHWM());
234 stopServer();
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200235 BOOST_FOREACH (boost::shared_ptr<boost::thread> pThread, holdThreads) { pThread->join(); }
Jim King79c99112015-04-30 07:10:08 -0400236 holdThreads.clear();
237 holdSockets.clear();
238 }
239
240 boost::shared_ptr<TServerType> pServer;
Ben Craig1684c422015-04-24 08:52:44 -0500241 boost::shared_ptr<TServerReadyEventHandler> pEventHandler;
242 boost::shared_ptr<boost::thread> pServerThread;
243};
244
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200245template <class TServerType>
246class TServerIntegrationProcessorFactoryTestFixture
247 : public TServerIntegrationTestFixture<TServerType> {
Konrad Grochowski24ea0bf2015-05-07 14:59:29 +0200248public:
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200249 TServerIntegrationProcessorFactoryTestFixture()
250 : TServerIntegrationTestFixture<TServerType>(boost::make_shared<ParentServiceProcessorFactory>(
251 boost::make_shared<ParentServiceIfSingletonFactory>(
252 boost::make_shared<ParentHandler>()))) {}
Konrad Grochowski24ea0bf2015-05-07 14:59:29 +0200253};
Ben Craig1684c422015-04-24 08:52:44 -0500254
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200255template <class TServerType>
256class TServerIntegrationProcessorTestFixture : public TServerIntegrationTestFixture<TServerType> {
Konrad Grochowski24ea0bf2015-05-07 14:59:29 +0200257public:
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200258 TServerIntegrationProcessorTestFixture()
259 : TServerIntegrationTestFixture<TServerType>(
260 boost::make_shared<ParentServiceProcessor>(boost::make_shared<ParentHandler>())) {}
Konrad Grochowski24ea0bf2015-05-07 14:59:29 +0200261};
262
263BOOST_AUTO_TEST_SUITE(constructors)
264
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200265BOOST_FIXTURE_TEST_CASE(test_simple_factory,
266 TServerIntegrationProcessorFactoryTestFixture<TSimpleServer>) {
267 baseline(3, 1);
Ben Craig1684c422015-04-24 08:52:44 -0500268}
269
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200270BOOST_FIXTURE_TEST_CASE(test_simple, TServerIntegrationProcessorTestFixture<TSimpleServer>) {
271 baseline(3, 1);
Konrad Grochowski24ea0bf2015-05-07 14:59:29 +0200272}
273
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200274BOOST_FIXTURE_TEST_CASE(test_threaded_factory,
275 TServerIntegrationProcessorFactoryTestFixture<TThreadedServer>) {
276 baseline(10, 10);
Jim King79c99112015-04-30 07:10:08 -0400277}
278
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200279BOOST_FIXTURE_TEST_CASE(test_threaded, TServerIntegrationProcessorTestFixture<TThreadedServer>) {
280 baseline(10, 10);
Konrad Grochowski24ea0bf2015-05-07 14:59:29 +0200281}
282
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200283BOOST_FIXTURE_TEST_CASE(test_threaded_bound,
284 TServerIntegrationProcessorTestFixture<TThreadedServer>) {
285 pServer->setConcurrentClientLimit(4);
286 baseline(10, 4);
Jim King79c99112015-04-30 07:10:08 -0400287}
288
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200289BOOST_FIXTURE_TEST_CASE(test_threadpool_factory,
290 TServerIntegrationProcessorFactoryTestFixture<TThreadPoolServer>) {
291 pServer->getThreadManager()->threadFactory(
292 boost::shared_ptr<apache::thrift::concurrency::ThreadFactory>(
293 new apache::thrift::concurrency::PlatformThreadFactory));
294 pServer->getThreadManager()->start();
Jim King79c99112015-04-30 07:10:08 -0400295
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200296 // thread factory has 4 threads as a default
297 // thread factory however is a bad way to limit concurrent clients
298 // as accept() will be called to grab a 5th client socket, in this case
299 // and then the thread factory will block adding the thread to manage
300 // that client.
301 baseline(10, 5);
Jim King79c99112015-04-30 07:10:08 -0400302}
303
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200304BOOST_FIXTURE_TEST_CASE(test_threadpool,
305 TServerIntegrationProcessorTestFixture<TThreadPoolServer>) {
306 pServer->getThreadManager()->threadFactory(
307 boost::shared_ptr<apache::thrift::concurrency::ThreadFactory>(
308 new apache::thrift::concurrency::PlatformThreadFactory));
309 pServer->getThreadManager()->start();
Konrad Grochowski24ea0bf2015-05-07 14:59:29 +0200310
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200311 // thread factory has 4 threads as a default
312 // thread factory however is a bad way to limit concurrent clients
313 // as accept() will be called to grab a 5th client socket, in this case
314 // and then the thread factory will block adding the thread to manage
315 // that client.
316 baseline(10, 5);
Konrad Grochowski24ea0bf2015-05-07 14:59:29 +0200317}
318
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200319BOOST_FIXTURE_TEST_CASE(test_threadpool_bound,
320 TServerIntegrationProcessorTestFixture<TThreadPoolServer>) {
321 pServer->getThreadManager()->threadFactory(
322 boost::shared_ptr<apache::thrift::concurrency::ThreadFactory>(
323 new apache::thrift::concurrency::PlatformThreadFactory));
324 pServer->getThreadManager()->start();
325 pServer->setConcurrentClientLimit(4);
Jim King79c99112015-04-30 07:10:08 -0400326
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200327 baseline(10, 4);
Jim King79c99112015-04-30 07:10:08 -0400328}
329
330BOOST_AUTO_TEST_SUITE_END()
331
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200332BOOST_FIXTURE_TEST_SUITE(TServerIntegrationTest,
333 TServerIntegrationProcessorTestFixture<TThreadedServer>)
Jim King79c99112015-04-30 07:10:08 -0400334
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200335BOOST_AUTO_TEST_CASE(test_stop_with_interruptable_clients_connected) {
336 // This tests THRIFT-2441 new behavior: stopping the server disconnects clients
Jim King79c99112015-04-30 07:10:08 -0400337
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200338 startServer();
Ben Craig1684c422015-04-24 08:52:44 -0500339
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200340 boost::shared_ptr<TSocket> pClientSock1(new TSocket("localhost", getServerPort()),
341 autoSocketCloser);
342 pClientSock1->open();
Ben Craig1684c422015-04-24 08:52:44 -0500343
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200344 boost::shared_ptr<TSocket> pClientSock2(new TSocket("localhost", getServerPort()),
345 autoSocketCloser);
346 pClientSock2->open();
Ben Craig1684c422015-04-24 08:52:44 -0500347
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200348 // Ensure they have been accepted
349 blockUntilAccepted(2);
Ben Craig1684c422015-04-24 08:52:44 -0500350
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200351 // The test fixture destructor will force the sockets to disconnect
352 // Prior to THRIFT-2441, pServer->stop() would hang until clients disconnected
353 stopServer();
Ben Craig1684c422015-04-24 08:52:44 -0500354
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200355 // extra proof the server end disconnected the clients
356 uint8_t buf[1];
357 BOOST_CHECK_EQUAL(0, pClientSock1->read(&buf[0], 1)); // 0 = disconnected
358 BOOST_CHECK_EQUAL(0, pClientSock2->read(&buf[0], 1)); // 0 = disconnected
Ben Craig1684c422015-04-24 08:52:44 -0500359}
360
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200361BOOST_AUTO_TEST_CASE(test_stop_with_uninterruptable_clients_connected) {
362 // This tests pre-THRIFT-2441 behavior: stopping the server blocks until clients
363 // disconnect.
Ben Craig1684c422015-04-24 08:52:44 -0500364
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200365 boost::dynamic_pointer_cast<TServerSocket>(pServer->getServerTransport())
366 ->setInterruptableChildren(false); // returns to pre-THRIFT-2441 behavior
Jim King79c99112015-04-30 07:10:08 -0400367
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200368 startServer();
Ben Craig1684c422015-04-24 08:52:44 -0500369
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200370 boost::shared_ptr<TSocket> pClientSock1(new TSocket("localhost", getServerPort()),
371 autoSocketCloser);
372 pClientSock1->open();
Ben Craig1684c422015-04-24 08:52:44 -0500373
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200374 boost::shared_ptr<TSocket> pClientSock2(new TSocket("localhost", getServerPort()),
375 autoSocketCloser);
376 pClientSock2->open();
Ben Craig1684c422015-04-24 08:52:44 -0500377
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200378 // Ensure they have been accepted
379 blockUntilAccepted(2);
Ben Craig1684c422015-04-24 08:52:44 -0500380
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200381 boost::thread t1(boost::bind(&TServerIntegrationTestFixture::delayClose,
382 this,
383 pClientSock1,
384 milliseconds(250)));
385 boost::thread t2(boost::bind(&TServerIntegrationTestFixture::delayClose,
386 this,
387 pClientSock2,
388 milliseconds(250)));
Ben Craig1684c422015-04-24 08:52:44 -0500389
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200390 // Once the clients disconnect the server will stop
391 stopServer();
392 t1.join();
393 t2.join();
Ben Craig1684c422015-04-24 08:52:44 -0500394}
Jim King79c99112015-04-30 07:10:08 -0400395
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200396BOOST_AUTO_TEST_CASE(test_concurrent_client_limit) {
397 startServer();
Jim King79c99112015-04-30 07:10:08 -0400398
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200399 BOOST_CHECK_EQUAL(INT64_MAX, pServer->getConcurrentClientLimit());
400 pServer->setConcurrentClientLimit(2);
401 BOOST_CHECK_EQUAL(0, pServer->getConcurrentClientCount());
402 BOOST_CHECK_EQUAL(2, pServer->getConcurrentClientLimit());
Jim King79c99112015-04-30 07:10:08 -0400403
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200404 boost::shared_ptr<TSocket> pClientSock1(new TSocket("localhost", getServerPort()),
405 autoSocketCloser);
406 pClientSock1->open();
407 blockUntilAccepted(1);
408 BOOST_CHECK_EQUAL(1, pServer->getConcurrentClientCount());
Jim King79c99112015-04-30 07:10:08 -0400409
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200410 boost::shared_ptr<TSocket> pClientSock2(new TSocket("localhost", getServerPort()),
411 autoSocketCloser);
412 pClientSock2->open();
413 blockUntilAccepted(2);
414 BOOST_CHECK_EQUAL(2, pServer->getConcurrentClientCount());
Jim King79c99112015-04-30 07:10:08 -0400415
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200416 // a third client cannot connect until one of the other two closes
417 boost::thread t2(boost::bind(&TServerIntegrationTestFixture::delayClose,
418 this,
419 pClientSock2,
420 milliseconds(250)));
421 boost::shared_ptr<TSocket> pClientSock3(new TSocket("localhost", getServerPort()),
422 autoSocketCloser);
423 pClientSock2->open();
424 blockUntilAccepted(2);
425 BOOST_CHECK_EQUAL(2, pServer->getConcurrentClientCount());
426 BOOST_CHECK_EQUAL(2, pServer->getConcurrentClientCountHWM());
Jim King79c99112015-04-30 07:10:08 -0400427
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200428 stopServer();
429 t2.join();
Jim King79c99112015-04-30 07:10:08 -0400430}
431
Ben Craig1684c422015-04-24 08:52:44 -0500432BOOST_AUTO_TEST_SUITE_END()