blob: 993ebc2f95eb763d510e624c6e5b54d35e84fcdb [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;
Weiwei Liu93606232016-02-26 16:32:11 -070094 websocket::Client::connection_ptr 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 {
135 serverHdl = hdl;
136 limitedIo.afterOp();
137 }
138
139 void
140 serverHandleClose()
141 {
142 if (transport == nullptr) {
143 return;
144 }
145
146 transport->close();
147 limitedIo.afterOp();
148 }
149
150 void
151 serverHandleMessage(websocket::Server::message_ptr msg)
152 {
153 if (transport == nullptr) {
154 return;
155 }
156
157 transport->receiveMessage(msg->get_payload());
158 limitedIo.afterOp();
159 }
160
161 void
162 serverHandlePong()
163 {
164 if (transport == nullptr) {
165 return;
166 }
167
168 transport->handlePong();
169 limitedIo.afterOp();
170 }
171
172 void
173 serverHandlePongTimeout()
174 {
175 if (transport == nullptr) {
176 return;
177 }
178
179 transport->handlePongTimeout();
180 limitedIo.afterOp();
181 }
182
183 void
184 clientHandleOpen(websocketpp::connection_hdl hdl)
185 {
186 clientHdl = hdl;
187 limitedIo.afterOp();
188 }
189
190 void
191 clientHandleMessage(websocket::Client::message_ptr msg)
192 {
193 clientReceivedMessages.push_back(msg->get_payload());
194 limitedIo.afterOp();
195 }
196
197 bool
198 clientHandlePing()
199 {
200 limitedIo.afterOp();
201 return clientShouldPong;
202 }
203
204public:
205 LimitedIo limitedIo;
206
207 websocket::Server server;
208 websocketpp::connection_hdl serverHdl;
Junxiao Shicde37ad2015-12-24 01:02:05 -0700209 unique_ptr<Face> face;
Yukai Tu2d6d5632015-10-26 11:06:02 -0700210 WebSocketTransport* transport;
211 std::vector<Transport::Packet>* serverReceivedPackets;
212
213 websocket::Client client;
214 websocketpp::connection_hdl clientHdl;
215 bool clientShouldPong;
216 std::vector<std::string> clientReceivedMessages;
217};
218
219BOOST_FIXTURE_TEST_SUITE(TestWebSocketTransport, SingleWebSocketFixture)
220
Weiwei Liu93606232016-02-26 16:32:11 -0700221BOOST_AUTO_TEST_CASE(StaticPropertiesLocalIpv4)
Yukai Tu2d6d5632015-10-26 11:06:02 -0700222{
Davide Pesaventoeee53aa2016-04-11 17:20:21 +0200223 auto address = getTestIp<ip::address_v4>(LoopbackAddress::Yes);
224 SKIP_IF_IP_UNAVAILABLE(address);
225 this->endToEndInitialize(ip::tcp::endpoint(address, 20070));
226
Yukai Tu2d6d5632015-10-26 11:06:02 -0700227 checkStaticPropertiesInitialized(*transport);
228
229 BOOST_CHECK_EQUAL(transport->getLocalUri(), FaceUri("ws://127.0.0.1:20070"));
230 BOOST_CHECK_EQUAL(transport->getRemoteUri().getScheme(), "wsclient");
231 BOOST_CHECK_EQUAL(transport->getRemoteUri().getHost(), "127.0.0.1");
232 BOOST_CHECK_EQUAL(transport->getRemoteUri().getPath(), "");
233 BOOST_CHECK_EQUAL(transport->getScope(), ndn::nfd::FACE_SCOPE_LOCAL);
234 BOOST_CHECK_EQUAL(transport->getPersistency(), ndn::nfd::FACE_PERSISTENCY_ON_DEMAND);
235 BOOST_CHECK_EQUAL(transport->getLinkType(), ndn::nfd::LINK_TYPE_POINT_TO_POINT);
236 BOOST_CHECK_EQUAL(transport->getMtu(), MTU_UNLIMITED);
237}
238
Weiwei Liu93606232016-02-26 16:32:11 -0700239BOOST_AUTO_TEST_CASE(StaticPropertiesNonLocalIpv4)
240{
Davide Pesaventoeee53aa2016-04-11 17:20:21 +0200241 auto address = getTestIp<ip::address_v4>(LoopbackAddress::No);
Weiwei Liu93606232016-02-26 16:32:11 -0700242 SKIP_IF_IP_UNAVAILABLE(address);
Davide Pesaventoeee53aa2016-04-11 17:20:21 +0200243 this->endToEndInitialize(ip::tcp::endpoint(address, 20070));
Weiwei Liu93606232016-02-26 16:32:11 -0700244
Weiwei Liu93606232016-02-26 16:32:11 -0700245 checkStaticPropertiesInitialized(*transport);
246
247 BOOST_CHECK_EQUAL(transport->getLocalUri(), FaceUri("ws://" + address.to_string() + ":20070"));
248 BOOST_CHECK_EQUAL(transport->getRemoteUri().getScheme(), "wsclient");
249 BOOST_CHECK_EQUAL(transport->getRemoteUri().getHost(), address.to_string());
250 BOOST_CHECK_EQUAL(transport->getRemoteUri().getPath(), "");
251 BOOST_CHECK_EQUAL(transport->getScope(), ndn::nfd::FACE_SCOPE_NON_LOCAL);
252 BOOST_CHECK_EQUAL(transport->getPersistency(), ndn::nfd::FACE_PERSISTENCY_ON_DEMAND);
253 BOOST_CHECK_EQUAL(transport->getLinkType(), ndn::nfd::LINK_TYPE_POINT_TO_POINT);
254 BOOST_CHECK_EQUAL(transport->getMtu(), MTU_UNLIMITED);
255}
256
Eric Newberry4a4ccfe2016-07-21 22:51:04 -0700257BOOST_AUTO_TEST_CASE(StaticPropertiesLocalIpv4MappedIpv6)
258{
259 auto address4 = getTestIp<ip::address_v4>(LoopbackAddress::Yes);
260 SKIP_IF_IP_UNAVAILABLE(address4);
261 auto address6 = ip::address_v6::v4_mapped(address4);
262 BOOST_REQUIRE(address6.is_v4_mapped());
263 this->endToEndInitialize(ip::tcp::endpoint(address6, 20070));
264
265 checkStaticPropertiesInitialized(*transport);
266
267 BOOST_CHECK_EQUAL(transport->getLocalUri().getScheme(), "ws");
268 BOOST_CHECK_EQUAL(transport->getLocalUri().getHost(), "::ffff:127.0.0.1");
269 BOOST_CHECK_EQUAL(transport->getLocalUri().getPort(), "20070");
270 BOOST_CHECK_EQUAL(transport->getLocalUri().getPath(), "");
271 BOOST_CHECK_EQUAL(transport->getRemoteUri().getScheme(), "wsclient");
272 BOOST_CHECK_EQUAL(transport->getRemoteUri().getHost(), "::ffff:127.0.0.1");
273 BOOST_CHECK_EQUAL(transport->getRemoteUri().getPath(), "");
274 BOOST_CHECK_EQUAL(transport->getScope(), ndn::nfd::FACE_SCOPE_LOCAL);
275 BOOST_CHECK_EQUAL(transport->getPersistency(), ndn::nfd::FACE_PERSISTENCY_ON_DEMAND);
276 BOOST_CHECK_EQUAL(transport->getLinkType(), ndn::nfd::LINK_TYPE_POINT_TO_POINT);
277 BOOST_CHECK_EQUAL(transport->getMtu(), MTU_UNLIMITED);
278}
279
Yukai Tu2d6d5632015-10-26 11:06:02 -0700280BOOST_AUTO_TEST_CASE(PingPong)
281{
Davide Pesaventoeee53aa2016-04-11 17:20:21 +0200282 auto address = getTestIp<ip::address_v4>();
283 SKIP_IF_IP_UNAVAILABLE(address);
284 this->endToEndInitialize(ip::tcp::endpoint(address, 20070),
285 time::milliseconds(500), time::milliseconds(300));
Yukai Tu2d6d5632015-10-26 11:06:02 -0700286
287 BOOST_CHECK_EQUAL(limitedIo.run(2, // clientHandlePing, serverHandlePong
288 time::milliseconds(1500)), LimitedIo::EXCEED_OPS);
Weiwei Liu93606232016-02-26 16:32:11 -0700289
Yukai Tu2d6d5632015-10-26 11:06:02 -0700290 BOOST_CHECK_EQUAL(transport->getState(), TransportState::UP);
Junxiao Shi57df2882015-11-11 06:12:35 -0700291 BOOST_CHECK_EQUAL(transport->getCounters().nOutPings, 1);
292 BOOST_CHECK_EQUAL(transport->getCounters().nInPongs, 1);
Yukai Tu2d6d5632015-10-26 11:06:02 -0700293
294 this->clientShouldPong = false;
295 BOOST_CHECK_EQUAL(limitedIo.run(2, // clientHandlePing, serverHandlePongTimeout
Weiwei Liu93606232016-02-26 16:32:11 -0700296 time::seconds(2)), LimitedIo::EXCEED_OPS);
297
Yukai Tu2d6d5632015-10-26 11:06:02 -0700298 BOOST_CHECK_MESSAGE(transport->getState() == TransportState::FAILED ||
299 transport->getState() == TransportState::CLOSED,
300 "expect FAILED or CLOSED state, actual state=" << transport->getState());
Junxiao Shi57df2882015-11-11 06:12:35 -0700301 BOOST_CHECK_EQUAL(transport->getCounters().nOutPings, 2);
302 BOOST_CHECK_EQUAL(transport->getCounters().nInPongs, 1);
Yukai Tu2d6d5632015-10-26 11:06:02 -0700303}
304
305BOOST_AUTO_TEST_CASE(Send)
306{
Davide Pesaventoeee53aa2016-04-11 17:20:21 +0200307 auto address = getTestIp<ip::address_v4>();
308 SKIP_IF_IP_UNAVAILABLE(address);
309 this->endToEndInitialize(ip::tcp::endpoint(address, 20070));
Yukai Tu2d6d5632015-10-26 11:06:02 -0700310
311 Block pkt1 = ndn::encoding::makeStringBlock(300, "hello");
312 transport->send(Transport::Packet(Block(pkt1)));
313 BOOST_CHECK_EQUAL(limitedIo.run(1, // clientHandleMessage
Weiwei Liu93606232016-02-26 16:32:11 -0700314 time::seconds(1)), LimitedIo::EXCEED_OPS);
Yukai Tu2d6d5632015-10-26 11:06:02 -0700315
316 Block pkt2 = ndn::encoding::makeStringBlock(301, "world!");
317 transport->send(Transport::Packet(Block(pkt2)));
318 BOOST_CHECK_EQUAL(limitedIo.run(1, // clientHandleMessage
Weiwei Liu93606232016-02-26 16:32:11 -0700319 time::seconds(1)), LimitedIo::EXCEED_OPS);
Yukai Tu2d6d5632015-10-26 11:06:02 -0700320
321 BOOST_REQUIRE_EQUAL(clientReceivedMessages.size(), 2);
322 BOOST_CHECK_EQUAL_COLLECTIONS(
323 reinterpret_cast<const uint8_t*>(clientReceivedMessages[0].data()),
324 reinterpret_cast<const uint8_t*>(clientReceivedMessages[0].data()) + clientReceivedMessages[0].size(),
325 pkt1.begin(), pkt1.end());
326 BOOST_CHECK_EQUAL_COLLECTIONS(
327 reinterpret_cast<const uint8_t*>(clientReceivedMessages[1].data()),
328 reinterpret_cast<const uint8_t*>(clientReceivedMessages[1].data()) + clientReceivedMessages[1].size(),
329 pkt2.begin(), pkt2.end());
330}
331
Weiwei Liu93606232016-02-26 16:32:11 -0700332BOOST_AUTO_TEST_CASE(ReceiveNormal)
Yukai Tu2d6d5632015-10-26 11:06:02 -0700333{
Davide Pesaventoeee53aa2016-04-11 17:20:21 +0200334 auto address = getTestIp<ip::address_v4>();
335 SKIP_IF_IP_UNAVAILABLE(address);
336 this->endToEndInitialize(ip::tcp::endpoint(address, 20070));
Yukai Tu2d6d5632015-10-26 11:06:02 -0700337
338 Block pkt1 = ndn::encoding::makeStringBlock(300, "hello");
339 client.send(clientHdl, pkt1.wire(), pkt1.size(), websocketpp::frame::opcode::binary);
340 BOOST_CHECK_EQUAL(limitedIo.run(1, // serverHandleMessage
Weiwei Liu93606232016-02-26 16:32:11 -0700341 time::seconds(1)), LimitedIo::EXCEED_OPS);
Yukai Tu2d6d5632015-10-26 11:06:02 -0700342
343 Block pkt2 = ndn::encoding::makeStringBlock(301, "world!");
344 client.send(clientHdl, pkt2.wire(), pkt2.size(), websocketpp::frame::opcode::binary);
345 BOOST_CHECK_EQUAL(limitedIo.run(1, // serverHandleMessage
Weiwei Liu93606232016-02-26 16:32:11 -0700346 time::seconds(1)), LimitedIo::EXCEED_OPS);
Yukai Tu2d6d5632015-10-26 11:06:02 -0700347
348 BOOST_REQUIRE_EQUAL(serverReceivedPackets->size(), 2);
349 BOOST_CHECK(serverReceivedPackets->at(0).packet == pkt1);
350 BOOST_CHECK(serverReceivedPackets->at(1).packet == pkt2);
351 BOOST_CHECK_EQUAL(serverReceivedPackets->at(0).remoteEndpoint, serverReceivedPackets->at(1).remoteEndpoint);
352}
353
354BOOST_AUTO_TEST_CASE(ReceiveMalformed)
355{
Davide Pesaventoeee53aa2016-04-11 17:20:21 +0200356 auto address = getTestIp<ip::address_v4>();
357 SKIP_IF_IP_UNAVAILABLE(address);
358 this->endToEndInitialize(ip::tcp::endpoint(address, 20070));
Yukai Tu2d6d5632015-10-26 11:06:02 -0700359
360 Block pkt1 = ndn::encoding::makeStringBlock(300, "hello");
361 client.send(clientHdl, pkt1.wire(), pkt1.size() - 1, // truncated
362 websocketpp::frame::opcode::binary);
363 BOOST_CHECK_EQUAL(limitedIo.run(1, // serverHandleMessage
Weiwei Liu93606232016-02-26 16:32:11 -0700364 time::seconds(1)), LimitedIo::EXCEED_OPS);
Yukai Tu2d6d5632015-10-26 11:06:02 -0700365
366 // bad packet is dropped
367 BOOST_CHECK_EQUAL(transport->getState(), TransportState::UP);
368 BOOST_CHECK_EQUAL(serverReceivedPackets->size(), 0);
369
370 Block pkt2 = ndn::encoding::makeStringBlock(301, "world!");
371 client.send(clientHdl, pkt2.wire(), pkt2.size(), websocketpp::frame::opcode::binary);
372 BOOST_CHECK_EQUAL(limitedIo.run(1, // serverHandleMessage
Weiwei Liu93606232016-02-26 16:32:11 -0700373 time::seconds(1)), LimitedIo::EXCEED_OPS);
Yukai Tu2d6d5632015-10-26 11:06:02 -0700374
375 // next valid packet is still received normally
376 BOOST_REQUIRE_EQUAL(serverReceivedPackets->size(), 1);
377 BOOST_CHECK(serverReceivedPackets->at(0).packet == pkt2);
378}
379
Weiwei Liu93606232016-02-26 16:32:11 -0700380BOOST_AUTO_TEST_CASE(Close)
381{
Davide Pesaventoeee53aa2016-04-11 17:20:21 +0200382 auto address = getTestIp<ip::address_v4>();
383 SKIP_IF_IP_UNAVAILABLE(address);
384 this->endToEndInitialize(ip::tcp::endpoint(address, 20070));
Weiwei Liu93606232016-02-26 16:32:11 -0700385
386 int nStateChanges = 0;
387 transport->afterStateChange.connect(
388 [&nStateChanges] (TransportState oldState, TransportState newState) {
389 switch (nStateChanges) {
390 case 0:
391 BOOST_CHECK_EQUAL(oldState, TransportState::UP);
392 BOOST_CHECK_EQUAL(newState, TransportState::CLOSING);
393 break;
394 case 1:
395 BOOST_CHECK_EQUAL(oldState, TransportState::CLOSING);
396 BOOST_CHECK_EQUAL(newState, TransportState::CLOSED);
397 break;
398 default:
399 BOOST_CHECK(false);
400 }
401 nStateChanges++;
402 });
403
404 transport->close();
405 BOOST_CHECK_EQUAL(nStateChanges, 2);
406}
407
408BOOST_AUTO_TEST_CASE(RemoteClose)
409{
Davide Pesaventoeee53aa2016-04-11 17:20:21 +0200410 auto address = getTestIp<ip::address_v4>();
411 SKIP_IF_IP_UNAVAILABLE(address);
412 this->endToEndInitialize(ip::tcp::endpoint(address, 20070));
Weiwei Liu93606232016-02-26 16:32:11 -0700413
414 int nStateChanges = 0;
415 transport->afterStateChange.connect(
416 [&nStateChanges] (TransportState oldState, TransportState newState) {
417 switch (nStateChanges) {
418 case 0:
419 BOOST_CHECK_EQUAL(oldState, TransportState::UP);
420 BOOST_CHECK_EQUAL(newState, TransportState::CLOSING);
421 break;
422 case 1:
423 BOOST_CHECK_EQUAL(oldState, TransportState::CLOSING);
424 BOOST_CHECK_EQUAL(newState, TransportState::CLOSED);
425 break;
426 default:
427 BOOST_CHECK(false);
428 }
429 nStateChanges++;
430 });
431
432 client.close(clientHdl, websocketpp::close::status::going_away, "");
433 BOOST_CHECK_EQUAL(limitedIo.run(1, // serverHandleClose
434 time::seconds(1)), LimitedIo::EXCEED_OPS);
435
436 BOOST_CHECK_EQUAL(nStateChanges, 2);
437}
438
Yukai Tu2d6d5632015-10-26 11:06:02 -0700439BOOST_AUTO_TEST_SUITE_END() // TestWebSocketTransport
440BOOST_AUTO_TEST_SUITE_END() // Face
441
442} // namespace tests
443} // namespace face
444} // namespace nfd