blob: f530771e66171bff786fe779a6a0eae82c59243f [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"
36#include "TestPortFixture.h"
37#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;
58using apache::thrift::test::ParentServiceClient;
59using apache::thrift::test::ParentServiceIf;
Konrad Grochowski24ea0bf2015-05-07 14:59:29 +020060using apache::thrift::test::ParentServiceIfFactory;
61using apache::thrift::test::ParentServiceIfSingletonFactory;
Ben Craig1684c422015-04-24 08:52:44 -050062using apache::thrift::test::ParentServiceProcessor;
Konrad Grochowski24ea0bf2015-05-07 14:59:29 +020063using apache::thrift::test::ParentServiceProcessorFactory;
64using apache::thrift::TProcessor;
65using apache::thrift::TProcessorFactory;
Jim King79c99112015-04-30 07:10:08 -040066using boost::posix_time::milliseconds;
Ben Craig1684c422015-04-24 08:52:44 -050067
68/**
69 * preServe runs after listen() is successful, when we can connect
70 */
Konrad Grochowski1f6e3802015-05-18 18:10:06 +020071class TServerReadyEventHandler : public TServerEventHandler, public Monitor {
Ben Craig1684c422015-04-24 08:52:44 -050072public:
73 TServerReadyEventHandler() : isListening_(false), accepted_(0) {}
74 virtual ~TServerReadyEventHandler() {}
75 virtual void preServe() {
76 Synchronized sync(*this);
77 isListening_ = true;
78 notify();
79 }
80 virtual void* createContext(boost::shared_ptr<TProtocol> input,
81 boost::shared_ptr<TProtocol> output) {
82 Synchronized sync(*this);
83 ++accepted_;
84 notify();
85
86 (void)input;
87 (void)output;
88 return NULL;
89 }
90 bool isListening() const { return isListening_; }
91 uint64_t acceptedCount() const { return accepted_; }
Konrad Grochowski1f6e3802015-05-18 18:10:06 +020092
Ben Craig1684c422015-04-24 08:52:44 -050093private:
94 bool isListening_;
95 uint64_t accepted_;
96};
97
Jim King79c99112015-04-30 07:10:08 -040098/**
99 * Reusing another generated test, just something to serve up
100 */
101class ParentHandler : public ParentServiceIf {
Ben Craig1684c422015-04-24 08:52:44 -0500102public:
103 ParentHandler() : generation_(0) {}
104
105 int32_t incrementGeneration() {
106 Guard g(mutex_);
107 return ++generation_;
108 }
109
110 int32_t getGeneration() {
111 Guard g(mutex_);
112 return generation_;
113 }
114
115 void addString(const std::string& s) {
116 Guard g(mutex_);
117 strings_.push_back(s);
118 }
119
120 void getStrings(std::vector<std::string>& _return) {
121 Guard g(mutex_);
122 _return = strings_;
123 }
124
ben-craigfae08e72015-07-15 11:34:47 -0500125 void getDataWait(std::string& _return, const int32_t length) {
Konrad Grochowski24ea0bf2015-05-07 14:59:29 +0200126 THRIFT_UNUSED_VARIABLE(_return);
127 THRIFT_UNUSED_VARIABLE(length);
Ben Craig1684c422015-04-24 08:52:44 -0500128 }
129
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200130 void onewayWait() {}
Ben Craig1684c422015-04-24 08:52:44 -0500131
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200132 void exceptionWait(const std::string& message) { THRIFT_UNUSED_VARIABLE(message); }
Ben Craig1684c422015-04-24 08:52:44 -0500133
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200134 void unexpectedExceptionWait(const std::string& message) { THRIFT_UNUSED_VARIABLE(message); }
Ben Craig1684c422015-04-24 08:52:44 -0500135
136protected:
137 Mutex mutex_;
138 int32_t generation_;
139 std::vector<std::string> strings_;
140};
141
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200142void autoSocketCloser(TSocket* pSock) {
Jim King79c99112015-04-30 07:10:08 -0400143 pSock->close();
144 delete pSock;
145}
146
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200147template <class TServerType>
148class TServerIntegrationTestFixture : public TestPortFixture {
Ben Craig1684c422015-04-24 08:52:44 -0500149public:
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200150 TServerIntegrationTestFixture(const boost::shared_ptr<TProcessorFactory>& _processorFactory)
151 : pServer(new TServerType(_processorFactory,
152 boost::shared_ptr<TServerTransport>(
153 new TServerSocket("localhost", m_serverPort)),
154 boost::shared_ptr<TTransportFactory>(new TTransportFactory),
155 boost::shared_ptr<TProtocolFactory>(new TBinaryProtocolFactory))),
156 pEventHandler(boost::shared_ptr<TServerReadyEventHandler>(new TServerReadyEventHandler)) {
Ben Craig1684c422015-04-24 08:52:44 -0500157 pServer->setServerEventHandler(pEventHandler);
158 }
159
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200160 TServerIntegrationTestFixture(const boost::shared_ptr<TProcessor>& _processor)
161 : pServer(
162 new TServerType(_processor,
163 boost::shared_ptr<TServerTransport>(new TServerSocket("localhost", 0)),
164 boost::shared_ptr<TTransportFactory>(new TTransportFactory),
165 boost::shared_ptr<TProtocolFactory>(new TBinaryProtocolFactory))),
166 pEventHandler(boost::shared_ptr<TServerReadyEventHandler>(new TServerReadyEventHandler)) {
Konrad Grochowski24ea0bf2015-05-07 14:59:29 +0200167 pServer->setServerEventHandler(pEventHandler);
168 }
169
Ben Craig1684c422015-04-24 08:52:44 -0500170 void startServer() {
Jim King79c99112015-04-30 07:10:08 -0400171 pServerThread.reset(new boost::thread(boost::bind(&TServerType::serve, pServer.get())));
Ben Craig1684c422015-04-24 08:52:44 -0500172
173 // block until listen() completes so clients will be able to connect
174 Synchronized sync(*(pEventHandler.get()));
175 while (!pEventHandler->isListening()) {
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200176 pEventHandler->wait();
Ben Craig1684c422015-04-24 08:52:44 -0500177 }
178
Konrad Grochowskie9bdb412015-09-25 20:17:36 +0200179 BOOST_TEST_MESSAGE("server is listening");
Ben Craig1684c422015-04-24 08:52:44 -0500180 }
181
182 void blockUntilAccepted(uint64_t numAccepted) {
183 Synchronized sync(*(pEventHandler.get()));
184 while (pEventHandler->acceptedCount() < numAccepted) {
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200185 pEventHandler->wait();
Ben Craig1684c422015-04-24 08:52:44 -0500186 }
187
Konrad Grochowskie9bdb412015-09-25 20:17:36 +0200188 BOOST_TEST_MESSAGE(boost::format("server has accepted %1%") % numAccepted);
Ben Craig1684c422015-04-24 08:52:44 -0500189 }
190
191 void stopServer() {
Jim King79c99112015-04-30 07:10:08 -0400192 if (pServerThread) {
193 pServer->stop();
Konrad Grochowskie9bdb412015-09-25 20:17:36 +0200194 BOOST_TEST_MESSAGE("server stop completed");
Jim King79c99112015-04-30 07:10:08 -0400195
196 pServerThread->join();
Konrad Grochowskie9bdb412015-09-25 20:17:36 +0200197 BOOST_TEST_MESSAGE("server thread joined");
Jim King79c99112015-04-30 07:10:08 -0400198 pServerThread.reset();
199 }
Ben Craig1684c422015-04-24 08:52:44 -0500200 }
201
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200202 ~TServerIntegrationTestFixture() { stopServer(); }
Ben Craig1684c422015-04-24 08:52:44 -0500203
Konrad Grochowski24ea0bf2015-05-07 14:59:29 +0200204 int getServerPort() {
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200205 TServerSocket* pSock = dynamic_cast<TServerSocket*>(pServer->getServerTransport().get());
Konrad Grochowski24ea0bf2015-05-07 14:59:29 +0200206 return pSock->getPort();
207 }
208
Jim King79c99112015-04-30 07:10:08 -0400209 void delayClose(boost::shared_ptr<TTransport> toClose, boost::posix_time::time_duration after) {
210 boost::this_thread::sleep(after);
Ben Craig1684c422015-04-24 08:52:44 -0500211 toClose->close();
212 }
213
Jim King79c99112015-04-30 07:10:08 -0400214 void baseline(int64_t numToMake, int64_t expectedHWM) {
215 startServer();
216 std::vector<boost::shared_ptr<TSocket> > holdSockets;
217 std::vector<boost::shared_ptr<boost::thread> > holdThreads;
218
219 for (int64_t i = 0; i < numToMake; ++i) {
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200220 boost::shared_ptr<TSocket> pClientSock(new TSocket("localhost", getServerPort()),
221 autoSocketCloser);
222 holdSockets.push_back(pClientSock);
223 boost::shared_ptr<TProtocol> pClientProtocol(new TBinaryProtocol(pClientSock));
224 ParentServiceClient client(pClientProtocol);
225 pClientSock->open();
226 client.incrementGeneration();
227 holdThreads.push_back(boost::shared_ptr<boost::thread>(
228 new boost::thread(boost::bind(&TServerIntegrationTestFixture::delayClose,
229 this,
230 pClientSock,
231 milliseconds(100 * numToMake)))));
Jim King79c99112015-04-30 07:10:08 -0400232 }
233
234 BOOST_CHECK_EQUAL(expectedHWM, pServer->getConcurrentClientCountHWM());
235 stopServer();
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200236 BOOST_FOREACH (boost::shared_ptr<boost::thread> pThread, holdThreads) { pThread->join(); }
Jim King79c99112015-04-30 07:10:08 -0400237 holdThreads.clear();
238 holdSockets.clear();
239 }
240
241 boost::shared_ptr<TServerType> pServer;
Ben Craig1684c422015-04-24 08:52:44 -0500242 boost::shared_ptr<TServerReadyEventHandler> pEventHandler;
243 boost::shared_ptr<boost::thread> pServerThread;
244};
245
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200246template <class TServerType>
247class TServerIntegrationProcessorFactoryTestFixture
248 : public TServerIntegrationTestFixture<TServerType> {
Konrad Grochowski24ea0bf2015-05-07 14:59:29 +0200249public:
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200250 TServerIntegrationProcessorFactoryTestFixture()
251 : TServerIntegrationTestFixture<TServerType>(boost::make_shared<ParentServiceProcessorFactory>(
252 boost::make_shared<ParentServiceIfSingletonFactory>(
253 boost::make_shared<ParentHandler>()))) {}
Konrad Grochowski24ea0bf2015-05-07 14:59:29 +0200254};
Ben Craig1684c422015-04-24 08:52:44 -0500255
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200256template <class TServerType>
257class TServerIntegrationProcessorTestFixture : public TServerIntegrationTestFixture<TServerType> {
Konrad Grochowski24ea0bf2015-05-07 14:59:29 +0200258public:
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200259 TServerIntegrationProcessorTestFixture()
260 : TServerIntegrationTestFixture<TServerType>(
261 boost::make_shared<ParentServiceProcessor>(boost::make_shared<ParentHandler>())) {}
Konrad Grochowski24ea0bf2015-05-07 14:59:29 +0200262};
263
264BOOST_AUTO_TEST_SUITE(constructors)
265
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200266BOOST_FIXTURE_TEST_CASE(test_simple_factory,
267 TServerIntegrationProcessorFactoryTestFixture<TSimpleServer>) {
268 baseline(3, 1);
Ben Craig1684c422015-04-24 08:52:44 -0500269}
270
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200271BOOST_FIXTURE_TEST_CASE(test_simple, TServerIntegrationProcessorTestFixture<TSimpleServer>) {
272 baseline(3, 1);
Konrad Grochowski24ea0bf2015-05-07 14:59:29 +0200273}
274
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200275BOOST_FIXTURE_TEST_CASE(test_threaded_factory,
276 TServerIntegrationProcessorFactoryTestFixture<TThreadedServer>) {
277 baseline(10, 10);
Jim King79c99112015-04-30 07:10:08 -0400278}
279
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200280BOOST_FIXTURE_TEST_CASE(test_threaded, TServerIntegrationProcessorTestFixture<TThreadedServer>) {
281 baseline(10, 10);
Konrad Grochowski24ea0bf2015-05-07 14:59:29 +0200282}
283
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200284BOOST_FIXTURE_TEST_CASE(test_threaded_bound,
285 TServerIntegrationProcessorTestFixture<TThreadedServer>) {
286 pServer->setConcurrentClientLimit(4);
287 baseline(10, 4);
Jim King79c99112015-04-30 07:10:08 -0400288}
289
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200290BOOST_FIXTURE_TEST_CASE(test_threadpool_factory,
291 TServerIntegrationProcessorFactoryTestFixture<TThreadPoolServer>) {
292 pServer->getThreadManager()->threadFactory(
293 boost::shared_ptr<apache::thrift::concurrency::ThreadFactory>(
294 new apache::thrift::concurrency::PlatformThreadFactory));
295 pServer->getThreadManager()->start();
Jim King79c99112015-04-30 07:10:08 -0400296
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200297 // thread factory has 4 threads as a default
298 // thread factory however is a bad way to limit concurrent clients
299 // as accept() will be called to grab a 5th client socket, in this case
300 // and then the thread factory will block adding the thread to manage
301 // that client.
302 baseline(10, 5);
Jim King79c99112015-04-30 07:10:08 -0400303}
304
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200305BOOST_FIXTURE_TEST_CASE(test_threadpool,
306 TServerIntegrationProcessorTestFixture<TThreadPoolServer>) {
307 pServer->getThreadManager()->threadFactory(
308 boost::shared_ptr<apache::thrift::concurrency::ThreadFactory>(
309 new apache::thrift::concurrency::PlatformThreadFactory));
310 pServer->getThreadManager()->start();
Konrad Grochowski24ea0bf2015-05-07 14:59:29 +0200311
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200312 // thread factory has 4 threads as a default
313 // thread factory however is a bad way to limit concurrent clients
314 // as accept() will be called to grab a 5th client socket, in this case
315 // and then the thread factory will block adding the thread to manage
316 // that client.
317 baseline(10, 5);
Konrad Grochowski24ea0bf2015-05-07 14:59:29 +0200318}
319
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200320BOOST_FIXTURE_TEST_CASE(test_threadpool_bound,
321 TServerIntegrationProcessorTestFixture<TThreadPoolServer>) {
322 pServer->getThreadManager()->threadFactory(
323 boost::shared_ptr<apache::thrift::concurrency::ThreadFactory>(
324 new apache::thrift::concurrency::PlatformThreadFactory));
325 pServer->getThreadManager()->start();
326 pServer->setConcurrentClientLimit(4);
Jim King79c99112015-04-30 07:10:08 -0400327
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200328 baseline(10, 4);
Jim King79c99112015-04-30 07:10:08 -0400329}
330
331BOOST_AUTO_TEST_SUITE_END()
332
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200333BOOST_FIXTURE_TEST_SUITE(TServerIntegrationTest,
334 TServerIntegrationProcessorTestFixture<TThreadedServer>)
Jim King79c99112015-04-30 07:10:08 -0400335
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200336BOOST_AUTO_TEST_CASE(test_stop_with_interruptable_clients_connected) {
337 // This tests THRIFT-2441 new behavior: stopping the server disconnects clients
Jim King79c99112015-04-30 07:10:08 -0400338
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200339 startServer();
Ben Craig1684c422015-04-24 08:52:44 -0500340
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200341 boost::shared_ptr<TSocket> pClientSock1(new TSocket("localhost", getServerPort()),
342 autoSocketCloser);
343 pClientSock1->open();
Ben Craig1684c422015-04-24 08:52:44 -0500344
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200345 boost::shared_ptr<TSocket> pClientSock2(new TSocket("localhost", getServerPort()),
346 autoSocketCloser);
347 pClientSock2->open();
Ben Craig1684c422015-04-24 08:52:44 -0500348
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200349 // Ensure they have been accepted
350 blockUntilAccepted(2);
Ben Craig1684c422015-04-24 08:52:44 -0500351
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200352 // The test fixture destructor will force the sockets to disconnect
353 // Prior to THRIFT-2441, pServer->stop() would hang until clients disconnected
354 stopServer();
Ben Craig1684c422015-04-24 08:52:44 -0500355
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200356 // extra proof the server end disconnected the clients
357 uint8_t buf[1];
358 BOOST_CHECK_EQUAL(0, pClientSock1->read(&buf[0], 1)); // 0 = disconnected
359 BOOST_CHECK_EQUAL(0, pClientSock2->read(&buf[0], 1)); // 0 = disconnected
Ben Craig1684c422015-04-24 08:52:44 -0500360}
361
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200362BOOST_AUTO_TEST_CASE(test_stop_with_uninterruptable_clients_connected) {
363 // This tests pre-THRIFT-2441 behavior: stopping the server blocks until clients
364 // disconnect.
Ben Craig1684c422015-04-24 08:52:44 -0500365
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200366 boost::dynamic_pointer_cast<TServerSocket>(pServer->getServerTransport())
367 ->setInterruptableChildren(false); // returns to pre-THRIFT-2441 behavior
Jim King79c99112015-04-30 07:10:08 -0400368
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200369 startServer();
Ben Craig1684c422015-04-24 08:52:44 -0500370
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200371 boost::shared_ptr<TSocket> pClientSock1(new TSocket("localhost", getServerPort()),
372 autoSocketCloser);
373 pClientSock1->open();
Ben Craig1684c422015-04-24 08:52:44 -0500374
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200375 boost::shared_ptr<TSocket> pClientSock2(new TSocket("localhost", getServerPort()),
376 autoSocketCloser);
377 pClientSock2->open();
Ben Craig1684c422015-04-24 08:52:44 -0500378
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200379 // Ensure they have been accepted
380 blockUntilAccepted(2);
Ben Craig1684c422015-04-24 08:52:44 -0500381
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200382 boost::thread t1(boost::bind(&TServerIntegrationTestFixture::delayClose,
383 this,
384 pClientSock1,
385 milliseconds(250)));
386 boost::thread t2(boost::bind(&TServerIntegrationTestFixture::delayClose,
387 this,
388 pClientSock2,
389 milliseconds(250)));
Ben Craig1684c422015-04-24 08:52:44 -0500390
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200391 // Once the clients disconnect the server will stop
392 stopServer();
393 t1.join();
394 t2.join();
Ben Craig1684c422015-04-24 08:52:44 -0500395}
Jim King79c99112015-04-30 07:10:08 -0400396
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200397BOOST_AUTO_TEST_CASE(test_concurrent_client_limit) {
398 startServer();
Jim King79c99112015-04-30 07:10:08 -0400399
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200400 BOOST_CHECK_EQUAL(INT64_MAX, pServer->getConcurrentClientLimit());
401 pServer->setConcurrentClientLimit(2);
402 BOOST_CHECK_EQUAL(0, pServer->getConcurrentClientCount());
403 BOOST_CHECK_EQUAL(2, pServer->getConcurrentClientLimit());
Jim King79c99112015-04-30 07:10:08 -0400404
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200405 boost::shared_ptr<TSocket> pClientSock1(new TSocket("localhost", getServerPort()),
406 autoSocketCloser);
407 pClientSock1->open();
408 blockUntilAccepted(1);
409 BOOST_CHECK_EQUAL(1, pServer->getConcurrentClientCount());
Jim King79c99112015-04-30 07:10:08 -0400410
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200411 boost::shared_ptr<TSocket> pClientSock2(new TSocket("localhost", getServerPort()),
412 autoSocketCloser);
413 pClientSock2->open();
414 blockUntilAccepted(2);
415 BOOST_CHECK_EQUAL(2, pServer->getConcurrentClientCount());
Jim King79c99112015-04-30 07:10:08 -0400416
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200417 // a third client cannot connect until one of the other two closes
418 boost::thread t2(boost::bind(&TServerIntegrationTestFixture::delayClose,
419 this,
420 pClientSock2,
421 milliseconds(250)));
422 boost::shared_ptr<TSocket> pClientSock3(new TSocket("localhost", getServerPort()),
423 autoSocketCloser);
424 pClientSock2->open();
425 blockUntilAccepted(2);
426 BOOST_CHECK_EQUAL(2, pServer->getConcurrentClientCount());
427 BOOST_CHECK_EQUAL(2, pServer->getConcurrentClientCountHWM());
Jim King79c99112015-04-30 07:10:08 -0400428
Konrad Grochowski1f6e3802015-05-18 18:10:06 +0200429 stopServer();
430 t2.join();
Jim King79c99112015-04-30 07:10:08 -0400431}
432
Ben Craig1684c422015-04-24 08:52:44 -0500433BOOST_AUTO_TEST_SUITE_END()