2 * Copyright 2015 Facebook, Inc.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 #include "folly/wangle/bootstrap/ServerBootstrap.h"
18 #include "folly/wangle/bootstrap/ClientBootstrap.h"
19 #include "folly/wangle/channel/ChannelHandler.h"
21 #include <glog/logging.h>
22 #include <gtest/gtest.h>
23 #include <boost/thread.hpp>
25 using namespace folly::wangle;
26 using namespace folly;
28 typedef ChannelPipeline<IOBufQueue&, std::unique_ptr<IOBuf>> Pipeline;
30 typedef ServerBootstrap<Pipeline> TestServer;
31 typedef ClientBootstrap<Pipeline> TestClient;
33 class TestClientPipelineFactory : public PipelineFactory<Pipeline> {
35 Pipeline* newPipeline(std::shared_ptr<AsyncSocket> sock) {
38 // We probably aren't connected immedately, check after a small delay
39 EventBaseManager::get()->getEventBase()->tryRunAfterDelay([sock](){
40 CHECK(sock->readable());
46 class TestPipelineFactory : public PipelineFactory<Pipeline> {
48 Pipeline* newPipeline(std::shared_ptr<AsyncSocket> sock) {
50 return new Pipeline();
52 std::atomic<int> pipelines{0};
55 TEST(Bootstrap, Basic) {
60 TEST(Bootstrap, ServerWithPipeline) {
62 server.childPipeline(std::make_shared<TestPipelineFactory>());
67 TEST(Bootstrap, ClientServerTest) {
69 auto factory = std::make_shared<TestPipelineFactory>();
70 server.childPipeline(factory);
72 auto base = EventBaseManager::get()->getEventBase();
74 SocketAddress address;
75 server.getSockets()[0]->getAddress(&address);
78 client.pipelineFactory(std::make_shared<TestClientPipelineFactory>());
79 client.connect(address);
83 CHECK(factory->pipelines == 1);
86 TEST(Bootstrap, ClientConnectionManagerTest) {
87 // Create a single IO thread, and verify that
88 // client connections are pooled properly
91 auto factory = std::make_shared<TestPipelineFactory>();
92 server.childPipeline(factory);
93 server.group(std::make_shared<IOThreadPoolExecutor>(1));
95 auto base = EventBaseManager::get()->getEventBase();
97 SocketAddress address;
98 server.getSockets()[0]->getAddress(&address);
101 client.pipelineFactory(std::make_shared<TestClientPipelineFactory>());
103 client.connect(address);
106 client2.pipelineFactory(std::make_shared<TestClientPipelineFactory>());
107 client2.connect(address);
112 CHECK(factory->pipelines == 2);
115 TEST(Bootstrap, ServerAcceptGroupTest) {
116 // Verify that server is using the accept IO group
119 auto factory = std::make_shared<TestPipelineFactory>();
120 server.childPipeline(factory);
121 server.group(std::make_shared<IOThreadPoolExecutor>(1), nullptr);
124 SocketAddress address;
125 server.getSockets()[0]->getAddress(&address);
127 boost::barrier barrier(2);
128 auto thread = std::thread([&](){
130 client.pipelineFactory(std::make_shared<TestClientPipelineFactory>());
131 client.connect(address);
132 EventBaseManager::get()->getEventBase()->loop();
139 CHECK(factory->pipelines == 1);
142 TEST(Bootstrap, ServerAcceptGroup2Test) {
143 // Verify that server is using the accept IO group
145 // Check if reuse port is supported, if not, don't run this test
148 auto serverSocket = AsyncServerSocket::newSocket(&base);
149 serverSocket->bind(0);
150 serverSocket->listen(0);
151 serverSocket->startAccepting();
152 serverSocket->setReusePortEnabled(true);
153 serverSocket->stopAccepting();
155 LOG(INFO) << "Reuse port probably not supported";
160 auto factory = std::make_shared<TestPipelineFactory>();
161 server.childPipeline(factory);
162 server.group(std::make_shared<IOThreadPoolExecutor>(4), nullptr);
165 SocketAddress address;
166 server.getSockets()[0]->getAddress(&address);
169 client.pipelineFactory(std::make_shared<TestClientPipelineFactory>());
171 client.connect(address);
172 EventBaseManager::get()->getEventBase()->loop();
176 CHECK(factory->pipelines == 1);
179 TEST(Bootstrap, SharedThreadPool) {
180 // Check if reuse port is supported, if not, don't run this test
183 auto serverSocket = AsyncServerSocket::newSocket(&base);
184 serverSocket->bind(0);
185 serverSocket->listen(0);
186 serverSocket->startAccepting();
187 serverSocket->setReusePortEnabled(true);
188 serverSocket->stopAccepting();
190 LOG(INFO) << "Reuse port probably not supported";
194 auto pool = std::make_shared<IOThreadPoolExecutor>(2);
197 auto factory = std::make_shared<TestPipelineFactory>();
198 server.childPipeline(factory);
199 server.group(pool, pool);
203 SocketAddress address;
204 server.getSockets()[0]->getAddress(&address);
207 client.pipelineFactory(std::make_shared<TestClientPipelineFactory>());
208 client.connect(address);
211 client2.pipelineFactory(std::make_shared<TestClientPipelineFactory>());
212 client2.connect(address);
215 client3.pipelineFactory(std::make_shared<TestClientPipelineFactory>());
216 client3.connect(address);
219 client4.pipelineFactory(std::make_shared<TestClientPipelineFactory>());
220 client4.connect(address);
223 client5.pipelineFactory(std::make_shared<TestClientPipelineFactory>());
224 client5.connect(address);
226 EventBaseManager::get()->getEventBase()->loop();
229 CHECK(factory->pipelines == 5);
232 TEST(Bootstrap, ExistingSocket) {
234 auto factory = std::make_shared<TestPipelineFactory>();
235 server.childPipeline(factory);
236 folly::AsyncServerSocket::UniquePtr socket(new AsyncServerSocket);
237 server.bind(std::move(socket));