blob: 8442480530d4ac2fe03a9c95d5bc0419674e5969 [file] [log] [blame]
Yukai Tu2d6d5632015-10-26 11:06:02 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
Weiwei Liu93606232016-02-26 16:32:11 -07003 * Copyright (c) 2014-2016, Regents of the University of California,
Yukai Tu2d6d5632015-10-26 11:06:02 -07004 * Arizona Board of Regents,
5 * Colorado State University,
6 * University Pierre & Marie Curie, Sorbonne University,
7 * Washington University in St. Louis,
8 * Beijing Institute of Technology,
9 * The University of Memphis.
10 *
11 * This file is part of NFD (Named Data Networking Forwarding Daemon).
12 * See AUTHORS.md for complete list of NFD authors and contributors.
13 *
14 * NFD is free software: you can redistribute it and/or modify it under the terms
15 * of the GNU General Public License as published by the Free Software Foundation,
16 * either version 3 of the License, or (at your option) any later version.
17 *
18 * NFD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
19 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
20 * PURPOSE. See the GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License along with
23 * NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
24 */
25
26#include "face/websocket-transport.hpp"
Junxiao Shicde37ad2015-12-24 01:02:05 -070027#include "face/face.hpp"
Yukai Tu2d6d5632015-10-26 11:06:02 -070028
Davide Pesaventoeee53aa2016-04-11 17:20:21 +020029#include "dummy-receive-link-service.hpp"
30#include "test-ip.hpp"
31#include "transport-test-common.hpp"
Yukai Tu2d6d5632015-10-26 11:06:02 -070032#include "tests/limited-io.hpp"
33
34namespace nfd {
35namespace face {
36namespace tests {
37
38using namespace nfd::tests;
39namespace ip = boost::asio::ip;
40
41BOOST_AUTO_TEST_SUITE(Face)
42
Junxiao Shicde37ad2015-12-24 01:02:05 -070043using nfd::Face;
44
Yukai Tu2d6d5632015-10-26 11:06:02 -070045/** \brief a fixture that accepts a single WebSocket connection from a client
46 */
47class SingleWebSocketFixture : public BaseFixture
48{
49public:
50 SingleWebSocketFixture()
51 : transport(nullptr)
52 , serverReceivedPackets(nullptr)
53 , clientShouldPong(true)
54 {
55 }
56
57 /** \brief initialize server and start listening
58 */
59 void
60 serverListen(const ip::tcp::endpoint& ep,
Weiwei Liu93606232016-02-26 16:32:11 -070061 const time::milliseconds& pongTimeout = time::seconds(1))
Yukai Tu2d6d5632015-10-26 11:06:02 -070062 {
63 server.clear_access_channels(websocketpp::log::alevel::all);
64 server.clear_error_channels(websocketpp::log::elevel::all);
65
66 server.init_asio(&g_io);
67 server.set_open_handler(bind(&SingleWebSocketFixture::serverHandleOpen, this, _1));
68 server.set_close_handler(bind(&SingleWebSocketFixture::serverHandleClose, this));
69 server.set_message_handler(bind(&SingleWebSocketFixture::serverHandleMessage, this, _2));
70 server.set_pong_handler(bind(&SingleWebSocketFixture::serverHandlePong, this));
71 server.set_pong_timeout_handler(bind(&SingleWebSocketFixture::serverHandlePongTimeout, this));
72 server.set_pong_timeout(pongTimeout.count());
73
74 server.set_reuse_addr(true);
75
76 server.listen(ep);
77 server.start_accept();
78 }
79
80 /** \brief initialize client and connect to server
81 */
82 void
83 clientConnect(const std::string& uri)
84 {
85 client.clear_access_channels(websocketpp::log::alevel::all);
86 client.clear_error_channels(websocketpp::log::elevel::all);
87
88 client.init_asio(&g_io);
89 client.set_open_handler(bind(&SingleWebSocketFixture::clientHandleOpen, this, _1));
90 client.set_message_handler(bind(&SingleWebSocketFixture::clientHandleMessage, this, _2));
91 client.set_ping_handler(bind(&SingleWebSocketFixture::clientHandlePing, this));
92
93 websocketpp::lib::error_code ec;
Davide Pesavento3495b802016-09-19 02:36:59 +020094 auto con = client.get_connection(uri, ec);
Davide Pesaventoeee53aa2016-04-11 17:20:21 +020095 BOOST_REQUIRE_EQUAL(ec, websocketpp::lib::error_code());
Yukai Tu2d6d5632015-10-26 11:06:02 -070096
97 client.connect(con);
98 }
99
100 void
Weiwei Liu93606232016-02-26 16:32:11 -0700101 makeFace(const time::milliseconds& pingInterval = time::seconds(10))
Yukai Tu2d6d5632015-10-26 11:06:02 -0700102 {
Junxiao Shicde37ad2015-12-24 01:02:05 -0700103 face = make_unique<Face>(
Yukai Tu2d6d5632015-10-26 11:06:02 -0700104 make_unique<DummyReceiveLinkService>(),
105 make_unique<WebSocketTransport>(serverHdl, ref(server), pingInterval));
106 transport = static_cast<WebSocketTransport*>(face->getTransport());
107 serverReceivedPackets = &static_cast<DummyReceiveLinkService*>(face->getLinkService())->receivedPackets;
108 }
109
110 /** \brief initialize both server and client, and have each other connected, create Transport
111 */
112 void
113 endToEndInitialize(const ip::tcp::endpoint& ep,
Weiwei Liu93606232016-02-26 16:32:11 -0700114 const time::milliseconds& pingInterval = time::seconds(10),
115 const time::milliseconds& pongTimeout = time::seconds(1))
Yukai Tu2d6d5632015-10-26 11:06:02 -0700116 {
117 this->serverListen(ep, pongTimeout);
Eric Newberry4a4ccfe2016-07-21 22:51:04 -0700118 std::string uri;
119 if (ep.address().is_v6()) {
120 uri = "ws://[" + ep.address().to_string() + "]:" + to_string(ep.port());
121 }
122 else {
123 uri = "ws://" + ep.address().to_string() + ":" + to_string(ep.port());
124 }
Yukai Tu2d6d5632015-10-26 11:06:02 -0700125 this->clientConnect(uri);
126 BOOST_REQUIRE_EQUAL(limitedIo.run(2, // serverHandleOpen, clientHandleOpen
127 time::seconds(1)), LimitedIo::EXCEED_OPS);
128 this->makeFace(pingInterval);
129 }
130
131private:
132 void
133 serverHandleOpen(websocketpp::connection_hdl hdl)
134 {
Davide Pesavento3495b802016-09-19 02:36:59 +0200135 websocketpp::lib::error_code ec;
136 auto con = server.get_con_from_hdl(hdl, ec);
137 BOOST_REQUIRE_EQUAL(ec, websocketpp::lib::error_code());
138 BOOST_REQUIRE(con);
139 remoteEp = con->get_socket().remote_endpoint();
140
Yukai Tu2d6d5632015-10-26 11:06:02 -0700141 serverHdl = hdl;
142 limitedIo.afterOp();
143 }
144
145 void
146 serverHandleClose()
147 {
148 if (transport == nullptr) {
149 return;
150 }
151
152 transport->close();
153 limitedIo.afterOp();
154 }
155
156 void
157 serverHandleMessage(websocket::Server::message_ptr msg)
158 {
159 if (transport == nullptr) {
160 return;
161 }
162
163 transport->receiveMessage(msg->get_payload());
164 limitedIo.afterOp();
165 }
166
167 void
168 serverHandlePong()
169 {
170 if (transport == nullptr) {
171 return;
172 }
173
174 transport->handlePong();
175 limitedIo.afterOp();
176 }
177
178 void
179 serverHandlePongTimeout()
180 {
181 if (transport == nullptr) {
182 return;
183 }
184
185 transport->handlePongTimeout();
186 limitedIo.afterOp();
187 }
188
189 void
190 clientHandleOpen(websocketpp::connection_hdl hdl)
191 {
192 clientHdl = hdl;
193 limitedIo.afterOp();
194 }
195
196 void
197 clientHandleMessage(websocket::Client::message_ptr msg)
198 {
199 clientReceivedMessages.push_back(msg->get_payload());
200 limitedIo.afterOp();
201 }
202
203 bool
204 clientHandlePing()
205 {
206 limitedIo.afterOp();
207 return clientShouldPong;
208 }
209
210public:
211 LimitedIo limitedIo;
212
213 websocket::Server server;
214 websocketpp::connection_hdl serverHdl;
Davide Pesavento3495b802016-09-19 02:36:59 +0200215 ip::tcp::endpoint remoteEp;
Junxiao Shicde37ad2015-12-24 01:02:05 -0700216 unique_ptr<Face> face;
Yukai Tu2d6d5632015-10-26 11:06:02 -0700217 WebSocketTransport* transport;
218 std::vector<Transport::Packet>* serverReceivedPackets;
219
220 websocket::Client client;
221 websocketpp::connection_hdl clientHdl;
222 bool clientShouldPong;
223 std::vector<std::string> clientReceivedMessages;
224};
225
226BOOST_FIXTURE_TEST_SUITE(TestWebSocketTransport, SingleWebSocketFixture)
227
Weiwei Liu93606232016-02-26 16:32:11 -0700228BOOST_AUTO_TEST_CASE(StaticPropertiesLocalIpv4)
Yukai Tu2d6d5632015-10-26 11:06:02 -0700229{
Davide Pesaventoeee53aa2016-04-11 17:20:21 +0200230 auto address = getTestIp<ip::address_v4>(LoopbackAddress::Yes);
231 SKIP_IF_IP_UNAVAILABLE(address);
Davide Pesavento3495b802016-09-19 02:36:59 +0200232 ip::tcp::endpoint ep(address, 20070);
233 this->endToEndInitialize(ep);
Davide Pesaventoeee53aa2016-04-11 17:20:21 +0200234
Yukai Tu2d6d5632015-10-26 11:06:02 -0700235 checkStaticPropertiesInitialized(*transport);
236
Davide Pesavento3495b802016-09-19 02:36:59 +0200237 BOOST_CHECK_EQUAL(transport->getLocalUri(), FaceUri(ep, "ws"));
238 BOOST_CHECK_EQUAL(transport->getRemoteUri(), FaceUri(remoteEp, "wsclient"));
Yukai Tu2d6d5632015-10-26 11:06:02 -0700239 BOOST_CHECK_EQUAL(transport->getScope(), ndn::nfd::FACE_SCOPE_LOCAL);
240 BOOST_CHECK_EQUAL(transport->getPersistency(), ndn::nfd::FACE_PERSISTENCY_ON_DEMAND);
241 BOOST_CHECK_EQUAL(transport->getLinkType(), ndn::nfd::LINK_TYPE_POINT_TO_POINT);
242 BOOST_CHECK_EQUAL(transport->getMtu(), MTU_UNLIMITED);
243}
244
Weiwei Liu93606232016-02-26 16:32:11 -0700245BOOST_AUTO_TEST_CASE(StaticPropertiesNonLocalIpv4)
246{
Davide Pesaventoeee53aa2016-04-11 17:20:21 +0200247 auto address = getTestIp<ip::address_v4>(LoopbackAddress::No);
Weiwei Liu93606232016-02-26 16:32:11 -0700248 SKIP_IF_IP_UNAVAILABLE(address);
Davide Pesavento3495b802016-09-19 02:36:59 +0200249 ip::tcp::endpoint ep(address, 20070);
250 this->endToEndInitialize(ep);
Weiwei Liu93606232016-02-26 16:32:11 -0700251
Weiwei Liu93606232016-02-26 16:32:11 -0700252 checkStaticPropertiesInitialized(*transport);
253
Davide Pesavento3495b802016-09-19 02:36:59 +0200254 BOOST_CHECK_EQUAL(transport->getLocalUri(), FaceUri(ep, "ws"));
255 BOOST_CHECK_EQUAL(transport->getRemoteUri(), FaceUri(remoteEp, "wsclient"));
Weiwei Liu93606232016-02-26 16:32:11 -0700256 BOOST_CHECK_EQUAL(transport->getScope(), ndn::nfd::FACE_SCOPE_NON_LOCAL);
257 BOOST_CHECK_EQUAL(transport->getPersistency(), ndn::nfd::FACE_PERSISTENCY_ON_DEMAND);
258 BOOST_CHECK_EQUAL(transport->getLinkType(), ndn::nfd::LINK_TYPE_POINT_TO_POINT);
259 BOOST_CHECK_EQUAL(transport->getMtu(), MTU_UNLIMITED);
260}
261
Eric Newberry4a4ccfe2016-07-21 22:51:04 -0700262BOOST_AUTO_TEST_CASE(StaticPropertiesLocalIpv4MappedIpv6)
263{
264 auto address4 = getTestIp<ip::address_v4>(LoopbackAddress::Yes);
265 SKIP_IF_IP_UNAVAILABLE(address4);
266 auto address6 = ip::address_v6::v4_mapped(address4);
267 BOOST_REQUIRE(address6.is_v4_mapped());
Davide Pesavento3495b802016-09-19 02:36:59 +0200268 ip::tcp::endpoint ep(address6, 20070);
269 this->endToEndInitialize(ep);
Eric Newberry4a4ccfe2016-07-21 22:51:04 -0700270
271 checkStaticPropertiesInitialized(*transport);
272
Davide Pesavento3495b802016-09-19 02:36:59 +0200273 BOOST_CHECK_EQUAL(transport->getLocalUri(), FaceUri(ep, "ws"));
274 BOOST_CHECK_EQUAL(transport->getRemoteUri(), FaceUri(remoteEp, "wsclient"));
Eric Newberry4a4ccfe2016-07-21 22:51:04 -0700275 BOOST_CHECK_EQUAL(transport->getScope(), ndn::nfd::FACE_SCOPE_LOCAL);
276 BOOST_CHECK_EQUAL(transport->getPersistency(), ndn::nfd::FACE_PERSISTENCY_ON_DEMAND);
277 BOOST_CHECK_EQUAL(transport->getLinkType(), ndn::nfd::LINK_TYPE_POINT_TO_POINT);
278 BOOST_CHECK_EQUAL(transport->getMtu(), MTU_UNLIMITED);
279}
280
Yukai Tu2d6d5632015-10-26 11:06:02 -0700281BOOST_AUTO_TEST_CASE(PingPong)
282{
Davide Pesaventoeee53aa2016-04-11 17:20:21 +0200283 auto address = getTestIp<ip::address_v4>();
284 SKIP_IF_IP_UNAVAILABLE(address);
285 this->endToEndInitialize(ip::tcp::endpoint(address, 20070),
286 time::milliseconds(500), time::milliseconds(300));
Yukai Tu2d6d5632015-10-26 11:06:02 -0700287
288 BOOST_CHECK_EQUAL(limitedIo.run(2, // clientHandlePing, serverHandlePong
289 time::milliseconds(1500)), LimitedIo::EXCEED_OPS);
Weiwei Liu93606232016-02-26 16:32:11 -0700290
Yukai Tu2d6d5632015-10-26 11:06:02 -0700291 BOOST_CHECK_EQUAL(transport->getState(), TransportState::UP);
Junxiao Shi57df2882015-11-11 06:12:35 -0700292 BOOST_CHECK_EQUAL(transport->getCounters().nOutPings, 1);
293 BOOST_CHECK_EQUAL(transport->getCounters().nInPongs, 1);
Yukai Tu2d6d5632015-10-26 11:06:02 -0700294
295 this->clientShouldPong = false;
296 BOOST_CHECK_EQUAL(limitedIo.run(2, // clientHandlePing, serverHandlePongTimeout
Weiwei Liu93606232016-02-26 16:32:11 -0700297 time::seconds(2)), LimitedIo::EXCEED_OPS);
298
Yukai Tu2d6d5632015-10-26 11:06:02 -0700299 BOOST_CHECK_MESSAGE(transport->getState() == TransportState::FAILED ||
300 transport->getState() == TransportState::CLOSED,
301 "expect FAILED or CLOSED state, actual state=" << transport->getState());
Junxiao Shi57df2882015-11-11 06:12:35 -0700302 BOOST_CHECK_EQUAL(transport->getCounters().nOutPings, 2);
303 BOOST_CHECK_EQUAL(transport->getCounters().nInPongs, 1);
Yukai Tu2d6d5632015-10-26 11:06:02 -0700304}
305
306BOOST_AUTO_TEST_CASE(Send)
307{
Davide Pesaventoeee53aa2016-04-11 17:20:21 +0200308 auto address = getTestIp<ip::address_v4>();
309 SKIP_IF_IP_UNAVAILABLE(address);
310 this->endToEndInitialize(ip::tcp::endpoint(address, 20070));
Yukai Tu2d6d5632015-10-26 11:06:02 -0700311
312 Block pkt1 = ndn::encoding::makeStringBlock(300, "hello");
313 transport->send(Transport::Packet(Block(pkt1)));
314 BOOST_CHECK_EQUAL(limitedIo.run(1, // clientHandleMessage
Weiwei Liu93606232016-02-26 16:32:11 -0700315 time::seconds(1)), LimitedIo::EXCEED_OPS);
Yukai Tu2d6d5632015-10-26 11:06:02 -0700316
317 Block pkt2 = ndn::encoding::makeStringBlock(301, "world!");
318 transport->send(Transport::Packet(Block(pkt2)));
319 BOOST_CHECK_EQUAL(limitedIo.run(1, // clientHandleMessage
Weiwei Liu93606232016-02-26 16:32:11 -0700320 time::seconds(1)), LimitedIo::EXCEED_OPS);
Yukai Tu2d6d5632015-10-26 11:06:02 -0700321
322 BOOST_REQUIRE_EQUAL(clientReceivedMessages.size(), 2);
323 BOOST_CHECK_EQUAL_COLLECTIONS(
324 reinterpret_cast<const uint8_t*>(clientReceivedMessages[0].data()),
325 reinterpret_cast<const uint8_t*>(clientReceivedMessages[0].data()) + clientReceivedMessages[0].size(),
326 pkt1.begin(), pkt1.end());
327 BOOST_CHECK_EQUAL_COLLECTIONS(
328 reinterpret_cast<const uint8_t*>(clientReceivedMessages[1].data()),
329 reinterpret_cast<const uint8_t*>(clientReceivedMessages[1].data()) + clientReceivedMessages[1].size(),
330 pkt2.begin(), pkt2.end());
331}
332
Weiwei Liu93606232016-02-26 16:32:11 -0700333BOOST_AUTO_TEST_CASE(ReceiveNormal)
Yukai Tu2d6d5632015-10-26 11:06:02 -0700334{
Davide Pesaventoeee53aa2016-04-11 17:20:21 +0200335 auto address = getTestIp<ip::address_v4>();
336 SKIP_IF_IP_UNAVAILABLE(address);
337 this->endToEndInitialize(ip::tcp::endpoint(address, 20070));
Yukai Tu2d6d5632015-10-26 11:06:02 -0700338
339 Block pkt1 = ndn::encoding::makeStringBlock(300, "hello");
340 client.send(clientHdl, pkt1.wire(), pkt1.size(), websocketpp::frame::opcode::binary);
341 BOOST_CHECK_EQUAL(limitedIo.run(1, // serverHandleMessage
Weiwei Liu93606232016-02-26 16:32:11 -0700342 time::seconds(1)), LimitedIo::EXCEED_OPS);
Yukai Tu2d6d5632015-10-26 11:06:02 -0700343
344 Block pkt2 = ndn::encoding::makeStringBlock(301, "world!");
345 client.send(clientHdl, pkt2.wire(), pkt2.size(), websocketpp::frame::opcode::binary);
346 BOOST_CHECK_EQUAL(limitedIo.run(1, // serverHandleMessage
Weiwei Liu93606232016-02-26 16:32:11 -0700347 time::seconds(1)), LimitedIo::EXCEED_OPS);
Yukai Tu2d6d5632015-10-26 11:06:02 -0700348
349 BOOST_REQUIRE_EQUAL(serverReceivedPackets->size(), 2);
350 BOOST_CHECK(serverReceivedPackets->at(0).packet == pkt1);
351 BOOST_CHECK(serverReceivedPackets->at(1).packet == pkt2);
352 BOOST_CHECK_EQUAL(serverReceivedPackets->at(0).remoteEndpoint, serverReceivedPackets->at(1).remoteEndpoint);
353}
354
355BOOST_AUTO_TEST_CASE(ReceiveMalformed)
356{
Davide Pesaventoeee53aa2016-04-11 17:20:21 +0200357 auto address = getTestIp<ip::address_v4>();
358 SKIP_IF_IP_UNAVAILABLE(address);
359 this->endToEndInitialize(ip::tcp::endpoint(address, 20070));
Yukai Tu2d6d5632015-10-26 11:06:02 -0700360
361 Block pkt1 = ndn::encoding::makeStringBlock(300, "hello");
362 client.send(clientHdl, pkt1.wire(), pkt1.size() - 1, // truncated
363 websocketpp::frame::opcode::binary);
364 BOOST_CHECK_EQUAL(limitedIo.run(1, // serverHandleMessage
Weiwei Liu93606232016-02-26 16:32:11 -0700365 time::seconds(1)), LimitedIo::EXCEED_OPS);
Yukai Tu2d6d5632015-10-26 11:06:02 -0700366
367 // bad packet is dropped
368 BOOST_CHECK_EQUAL(transport->getState(), TransportState::UP);
369 BOOST_CHECK_EQUAL(serverReceivedPackets->size(), 0);
370
371 Block pkt2 = ndn::encoding::makeStringBlock(301, "world!");
372 client.send(clientHdl, pkt2.wire(), pkt2.size(), websocketpp::frame::opcode::binary);
373 BOOST_CHECK_EQUAL(limitedIo.run(1, // serverHandleMessage
Weiwei Liu93606232016-02-26 16:32:11 -0700374 time::seconds(1)), LimitedIo::EXCEED_OPS);
Yukai Tu2d6d5632015-10-26 11:06:02 -0700375
376 // next valid packet is still received normally
377 BOOST_REQUIRE_EQUAL(serverReceivedPackets->size(), 1);
378 BOOST_CHECK(serverReceivedPackets->at(0).packet == pkt2);
379}
380
Weiwei Liu93606232016-02-26 16:32:11 -0700381BOOST_AUTO_TEST_CASE(Close)
382{
Davide Pesaventoeee53aa2016-04-11 17:20:21 +0200383 auto address = getTestIp<ip::address_v4>();
384 SKIP_IF_IP_UNAVAILABLE(address);
385 this->endToEndInitialize(ip::tcp::endpoint(address, 20070));
Weiwei Liu93606232016-02-26 16:32:11 -0700386
387 int nStateChanges = 0;
388 transport->afterStateChange.connect(
389 [&nStateChanges] (TransportState oldState, TransportState newState) {
390 switch (nStateChanges) {
391 case 0:
392 BOOST_CHECK_EQUAL(oldState, TransportState::UP);
393 BOOST_CHECK_EQUAL(newState, TransportState::CLOSING);
394 break;
395 case 1:
396 BOOST_CHECK_EQUAL(oldState, TransportState::CLOSING);
397 BOOST_CHECK_EQUAL(newState, TransportState::CLOSED);
398 break;
399 default:
400 BOOST_CHECK(false);
401 }
402 nStateChanges++;
403 });
404
405 transport->close();
406 BOOST_CHECK_EQUAL(nStateChanges, 2);
407}
408
409BOOST_AUTO_TEST_CASE(RemoteClose)
410{
Davide Pesaventoeee53aa2016-04-11 17:20:21 +0200411 auto address = getTestIp<ip::address_v4>();
412 SKIP_IF_IP_UNAVAILABLE(address);
413 this->endToEndInitialize(ip::tcp::endpoint(address, 20070));
Weiwei Liu93606232016-02-26 16:32:11 -0700414
415 int nStateChanges = 0;
416 transport->afterStateChange.connect(
417 [&nStateChanges] (TransportState oldState, TransportState newState) {
418 switch (nStateChanges) {
419 case 0:
420 BOOST_CHECK_EQUAL(oldState, TransportState::UP);
421 BOOST_CHECK_EQUAL(newState, TransportState::CLOSING);
422 break;
423 case 1:
424 BOOST_CHECK_EQUAL(oldState, TransportState::CLOSING);
425 BOOST_CHECK_EQUAL(newState, TransportState::CLOSED);
426 break;
427 default:
428 BOOST_CHECK(false);
429 }
430 nStateChanges++;
431 });
432
433 client.close(clientHdl, websocketpp::close::status::going_away, "");
434 BOOST_CHECK_EQUAL(limitedIo.run(1, // serverHandleClose
435 time::seconds(1)), LimitedIo::EXCEED_OPS);
436
437 BOOST_CHECK_EQUAL(nStateChanges, 2);
438}
439
Yukai Tu2d6d5632015-10-26 11:06:02 -0700440BOOST_AUTO_TEST_SUITE_END() // TestWebSocketTransport
441BOOST_AUTO_TEST_SUITE_END() // Face
442
443} // namespace tests
444} // namespace face
445} // namespace nfd