blob: 81ea7072bd68121a654af7d0a6b45f43ffe4969a [file] [log] [blame]
Junxiao Shi38f4ce92016-08-04 10:01:52 +00001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
Junxiao Shi1f481fa2017-01-26 15:14:43 +00003 * Copyright (c) 2014-2017, Regents of the University of California,
Junxiao Shi38f4ce92016-08-04 10:01:52 +00004 * 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
Junxiao Shi331ade72016-08-19 14:07:19 +000026#include "nfdc/face-module.hpp"
Junxiao Shi1d7fef52017-02-02 05:33:14 +000027#include <ndn-cxx/mgmt/nfd/face-query-filter.hpp>
Junxiao Shi38f4ce92016-08-04 10:01:52 +000028
Junxiao Shi1f481fa2017-01-26 15:14:43 +000029#include "execute-command-fixture.hpp"
30#include "status-fixture.hpp"
Junxiao Shi38f4ce92016-08-04 10:01:52 +000031
32namespace nfd {
33namespace tools {
Junxiao Shi331ade72016-08-19 14:07:19 +000034namespace nfdc {
Junxiao Shi38f4ce92016-08-04 10:01:52 +000035namespace tests {
36
Junxiao Shi1d7fef52017-02-02 05:33:14 +000037using ndn::nfd::FaceQueryFilter;
38
Junxiao Shi331ade72016-08-19 14:07:19 +000039BOOST_AUTO_TEST_SUITE(Nfdc)
Junxiao Shi1f481fa2017-01-26 15:14:43 +000040BOOST_AUTO_TEST_SUITE(TestFaceModule)
41
42BOOST_FIXTURE_TEST_SUITE(ShowCommand, ExecuteCommandFixture)
43
Junxiao Shi1f481fa2017-01-26 15:14:43 +000044const std::string NORMAL_OUTPUT = std::string(R"TEXT(
45 faceid=256
46 remote=udp4://84.67.35.111:6363
47 local=udp4://79.91.49.215:6363
48counters={in={28975i 28232d 212n 13307258B} out={19525i 30993d 1038n 6231946B}}
49 flags={non-local on-demand point-to-point}
50)TEXT").substr(1);
51
52BOOST_AUTO_TEST_CASE(Normal)
53{
54 this->processInterest = [this] (const Interest& interest) {
Junxiao Shi8f803f22017-02-10 03:04:28 +000055 BOOST_CHECK_EQUAL(interest.getName().size(), 5);
56 FaceQueryFilter filter(interest.getName().at(4).blockFromValue());
57 BOOST_CHECK_EQUAL(filter, FaceQueryFilter().setFaceId(256));
Junxiao Shi1f481fa2017-01-26 15:14:43 +000058
59 FaceStatus payload;
60 payload.setFaceId(256)
61 .setRemoteUri("udp4://84.67.35.111:6363")
62 .setLocalUri("udp4://79.91.49.215:6363")
63 .setFaceScope(ndn::nfd::FACE_SCOPE_NON_LOCAL)
64 .setFacePersistency(ndn::nfd::FACE_PERSISTENCY_ON_DEMAND)
65 .setLinkType(ndn::nfd::LINK_TYPE_POINT_TO_POINT)
66 .setNInInterests(28975)
67 .setNInDatas(28232)
68 .setNInNacks(212)
69 .setNOutInterests(19525)
70 .setNOutDatas(30993)
71 .setNOutNacks(1038)
72 .setNInBytes(13307258)
73 .setNOutBytes(6231946);
74
Junxiao Shi8f803f22017-02-10 03:04:28 +000075 this->sendDataset(interest.getName(), payload);
Junxiao Shi1f481fa2017-01-26 15:14:43 +000076 };
77
78 this->execute("face show 256");
79 BOOST_CHECK_EQUAL(exitCode, 0);
80 BOOST_CHECK(out.is_equal(NORMAL_OUTPUT));
81 BOOST_CHECK(err.is_empty());
82}
83
84BOOST_AUTO_TEST_CASE(NotFound)
85{
86 this->processInterest = [this] (const Interest& interest) {
87 this->sendEmptyDataset(interest.getName());
88 };
89
90 this->execute("face show 256");
91 BOOST_CHECK_EQUAL(exitCode, 3);
92 BOOST_CHECK(out.is_empty());
Junxiao Shi8f803f22017-02-10 03:04:28 +000093 BOOST_CHECK(err.is_equal("Face not found\n"));
Junxiao Shi1f481fa2017-01-26 15:14:43 +000094}
95
96BOOST_AUTO_TEST_CASE(Error)
97{
98 this->processInterest = nullptr; // no response
99
100 this->execute("face show 256");
101 BOOST_CHECK_EQUAL(exitCode, 1);
102 BOOST_CHECK(out.is_empty());
Junxiao Shi8f803f22017-02-10 03:04:28 +0000103 BOOST_CHECK(err.is_equal("Error 10060 when querying face: Timeout\n"));
Junxiao Shi1f481fa2017-01-26 15:14:43 +0000104}
105
106BOOST_AUTO_TEST_SUITE_END() // ShowCommand
Junxiao Shi38f4ce92016-08-04 10:01:52 +0000107
Junxiao Shi1d7fef52017-02-02 05:33:14 +0000108BOOST_FIXTURE_TEST_SUITE(CreateCommand, ExecuteCommandFixture)
109
110BOOST_AUTO_TEST_CASE(Normal)
111{
112 this->processInterest = [this] (const Interest& interest) {
113 ControlParameters req = MOCK_NFD_MGMT_REQUIRE_LAST_COMMAND_IS("/localhost/nfd/faces/create");
114 BOOST_REQUIRE(req.hasUri());
115 BOOST_CHECK_EQUAL(req.getUri(), "udp4://159.242.33.78:6363");
116 BOOST_REQUIRE(req.hasFacePersistency());
117 BOOST_CHECK_EQUAL(req.getFacePersistency(), FacePersistency::FACE_PERSISTENCY_PERSISTENT);
118
119 ControlParameters resp;
120 resp.setFaceId(2130)
Junxiao Shi1d7fef52017-02-02 05:33:14 +0000121 .setFacePersistency(FacePersistency::FACE_PERSISTENCY_PERSISTENT);
122 this->succeedCommand(resp);
123 };
124
125 this->execute("face create udp://159.242.33.78");
126 BOOST_CHECK_EQUAL(exitCode, 0);
127 BOOST_CHECK(out.is_equal("face-created id=2130 remote=udp4://159.242.33.78:6363 persistency=persistent\n"));
128 BOOST_CHECK(err.is_empty());
129}
130
131BOOST_AUTO_TEST_CASE(Error)
132{
133 this->processInterest = nullptr; // no response
134
135 this->execute("face create udp://159.242.33.78");
136 BOOST_CHECK_EQUAL(exitCode, 1);
137 BOOST_CHECK(out.is_empty());
138 BOOST_CHECK(err.is_equal("Error 10060 when creating face: request timed out\n"));
139}
140
141BOOST_AUTO_TEST_SUITE_END() // CreateCommand
142
Junxiao Shi05dd4442017-02-06 22:50:07 +0000143BOOST_FIXTURE_TEST_SUITE(DestroyCommand, ExecuteCommandFixture)
144
145BOOST_AUTO_TEST_CASE(NormalByFaceId)
146{
147 this->processInterest = [this] (const Interest& interest) {
148 if (Name("/localhost/nfd/faces/query").isPrefixOf(interest.getName())) {
149 BOOST_CHECK_EQUAL(interest.getName().size(), 5);
150 FaceQueryFilter filter(interest.getName().at(4).blockFromValue());
Junxiao Shi8f803f22017-02-10 03:04:28 +0000151 BOOST_CHECK_EQUAL(filter, FaceQueryFilter().setFaceId(10156));
Junxiao Shi05dd4442017-02-06 22:50:07 +0000152
153 FaceStatus faceStatus;
154 faceStatus.setFaceId(10156)
155 .setLocalUri("tcp4://151.26.163.27:22967")
156 .setRemoteUri("tcp4://198.57.27.40:6363")
157 .setFacePersistency(FacePersistency::FACE_PERSISTENCY_PERSISTENT);
158 this->sendDataset(interest.getName(), faceStatus);
159 return;
160 }
161
162 ControlParameters req = MOCK_NFD_MGMT_REQUIRE_LAST_COMMAND_IS("/localhost/nfd/faces/destroy");
163 BOOST_REQUIRE(req.hasFaceId());
164 BOOST_CHECK_EQUAL(req.getFaceId(), 10156);
165
166 ControlParameters resp;
167 resp.setFaceId(10156);
168 this->succeedCommand(resp);
169 };
170
171 this->execute("face destroy 10156");
172 BOOST_CHECK_EQUAL(exitCode, 0);
173 BOOST_CHECK(out.is_equal("face-destroyed id=10156 local=tcp4://151.26.163.27:22967 "
174 "remote=tcp4://198.57.27.40:6363 persistency=persistent\n"));
175 BOOST_CHECK(err.is_empty());
176}
177
178BOOST_AUTO_TEST_CASE(NormalByFaceUri)
179{
180 this->processInterest = [this] (const Interest& interest) {
181 if (Name("/localhost/nfd/faces/query").isPrefixOf(interest.getName())) {
182 BOOST_CHECK_EQUAL(interest.getName().size(), 5);
183 FaceQueryFilter filter(interest.getName().at(4).blockFromValue());
Junxiao Shi8f803f22017-02-10 03:04:28 +0000184 BOOST_CHECK_EQUAL(filter, FaceQueryFilter().setRemoteUri("tcp4://32.121.182.82:6363"));
Junxiao Shi05dd4442017-02-06 22:50:07 +0000185
186 FaceStatus faceStatus;
187 faceStatus.setFaceId(2249)
188 .setLocalUri("tcp4://30.99.87.98:31414")
189 .setRemoteUri("tcp4://32.121.182.82:6363")
190 .setFacePersistency(FacePersistency::FACE_PERSISTENCY_PERSISTENT);
191 this->sendDataset(interest.getName(), faceStatus);
192 return;
193 }
194
195 ControlParameters req = MOCK_NFD_MGMT_REQUIRE_LAST_COMMAND_IS("/localhost/nfd/faces/destroy");
196 BOOST_REQUIRE(req.hasFaceId());
197 BOOST_CHECK_EQUAL(req.getFaceId(), 2249);
198
199 ControlParameters resp;
200 resp.setFaceId(2249);
201 this->succeedCommand(resp);
202 };
203
204 this->execute("face destroy tcp://32.121.182.82");
205 BOOST_CHECK_EQUAL(exitCode, 0);
206 BOOST_CHECK(out.is_equal("face-destroyed id=2249 local=tcp4://30.99.87.98:31414 "
207 "remote=tcp4://32.121.182.82:6363 persistency=persistent\n"));
208 BOOST_CHECK(err.is_empty());
209}
210
211BOOST_AUTO_TEST_CASE(FaceNotExist)
212{
213 this->processInterest = [this] (const Interest& interest) {
214 BOOST_CHECK(Name("/localhost/nfd/faces/query").isPrefixOf(interest.getName()));
215 this->sendEmptyDataset(interest.getName());
216 };
217
218 this->execute("face destroy 23728");
219 BOOST_CHECK_EQUAL(exitCode, 3);
220 BOOST_CHECK(out.is_empty());
221 BOOST_CHECK(err.is_equal("Face not found\n"));
222}
223
224BOOST_AUTO_TEST_CASE(Ambiguous)
225{
226 this->processInterest = [this] (const Interest& interest) {
227 BOOST_CHECK(Name("/localhost/nfd/faces/query").isPrefixOf(interest.getName()));
228
229 FaceStatus faceStatus1, faceStatus2;
230 faceStatus1.setFaceId(6720)
231 .setLocalUri("udp4://202.83.168.28:56363")
232 .setRemoteUri("udp4://225.131.75.231:56363")
233 .setFacePersistency(FacePersistency::FACE_PERSISTENCY_PERMANENT);
234 faceStatus2.setFaceId(31066)
235 .setLocalUri("udp4://25.90.26.32:56363")
236 .setRemoteUri("udp4://225.131.75.231:56363")
237 .setFacePersistency(FacePersistency::FACE_PERSISTENCY_PERMANENT);
238 this->sendDataset(interest.getName(), faceStatus1, faceStatus2);
239 };
240
241 this->execute("face destroy udp4://225.131.75.231:56363");
242 BOOST_CHECK_EQUAL(exitCode, 5);
243 BOOST_CHECK(out.is_empty());
244 BOOST_CHECK(err.is_equal("Multiple faces match specified remote FaceUri. "
245 "Re-run the command with a FaceId: "
246 "6720 (local=udp4://202.83.168.28:56363), "
247 "31066 (local=udp4://25.90.26.32:56363)\n"));
248}
249
250BOOST_AUTO_TEST_CASE(ErrorCanonization)
251{
252 this->execute("face destroy udp6://32.38.164.64:10445");
253 BOOST_CHECK_EQUAL(exitCode, 4);
254 BOOST_CHECK(out.is_empty());
255 BOOST_CHECK(err.is_equal("Error during remote FaceUri canonization: "
256 "No endpoints match the specified address selector\n"));
257}
258
259BOOST_AUTO_TEST_CASE(ErrorDataset)
260{
261 this->processInterest = nullptr; // no response to dataset or command
262
263 this->execute("face destroy udp://159.242.33.78");
264 BOOST_CHECK_EQUAL(exitCode, 1);
265 BOOST_CHECK(out.is_empty());
266 BOOST_CHECK(err.is_equal("Error 10060 when querying face: Timeout\n"));
267}
268
269BOOST_AUTO_TEST_CASE(ErrorCommand)
270{
271 this->processInterest = [this] (const Interest& interest) {
272 if (Name("/localhost/nfd/faces/query").isPrefixOf(interest.getName())) {
273 FaceStatus faceStatus;
274 faceStatus.setFaceId(17757)
275 .setLocalUri("tcp4://27.65.24.30:19187")
276 .setRemoteUri("tcp4://70.47.27.77:6363")
277 .setFacePersistency(FacePersistency::FACE_PERSISTENCY_PERSISTENT);
278 this->sendDataset(interest.getName(), faceStatus);
279 return;
280 }
281
282 MOCK_NFD_MGMT_REQUIRE_LAST_COMMAND_IS("/localhost/nfd/faces/destroy");
283 // no response to command
284 };
285
286 this->execute("face destroy 17757");
287 BOOST_CHECK_EQUAL(exitCode, 1);
288 BOOST_CHECK(out.is_empty());
289 BOOST_CHECK(err.is_equal("Error 10060 when destroying face: request timed out\n"));
290}
291
292BOOST_AUTO_TEST_SUITE_END() // DestroyCommand
293
Junxiao Shi38f4ce92016-08-04 10:01:52 +0000294const std::string STATUS_XML = stripXmlSpaces(R"XML(
295 <faces>
296 <face>
297 <faceId>134</faceId>
298 <remoteUri>udp4://233.252.0.4:6363</remoteUri>
299 <localUri>udp4://192.0.2.1:6363</localUri>
300 <faceScope>non-local</faceScope>
301 <facePersistency>permanent</facePersistency>
302 <linkType>multi-access</linkType>
Eric Newberry6d932e82016-11-24 05:05:43 +0000303 <flags/>
Junxiao Shi38f4ce92016-08-04 10:01:52 +0000304 <packetCounters>
305 <incomingPackets>
306 <nInterests>22562</nInterests>
307 <nDatas>22031</nDatas>
308 <nNacks>63</nNacks>
309 </incomingPackets>
310 <outgoingPackets>
311 <nInterests>30121</nInterests>
312 <nDatas>20940</nDatas>
313 <nNacks>1218</nNacks>
314 </outgoingPackets>
315 </packetCounters>
316 <byteCounters>
317 <incomingBytes>2522915</incomingBytes>
318 <outgoingBytes>1353592</outgoingBytes>
319 </byteCounters>
320 </face>
321 <face>
322 <faceId>745</faceId>
323 <remoteUri>fd://75</remoteUri>
324 <localUri>unix:///var/run/nfd.sock</localUri>
325 <faceScope>local</faceScope>
326 <facePersistency>on-demand</facePersistency>
327 <linkType>point-to-point</linkType>
Eric Newberry6d932e82016-11-24 05:05:43 +0000328 <flags>
329 <localFieldsEnabled/>
330 </flags>
Junxiao Shi38f4ce92016-08-04 10:01:52 +0000331 <packetCounters>
332 <incomingPackets>
333 <nInterests>18998</nInterests>
334 <nDatas>26701</nDatas>
335 <nNacks>147</nNacks>
336 </incomingPackets>
337 <outgoingPackets>
338 <nInterests>34779</nInterests>
339 <nDatas>17028</nDatas>
340 <nNacks>1176</nNacks>
341 </outgoingPackets>
342 </packetCounters>
343 <byteCounters>
344 <incomingBytes>4672308</incomingBytes>
345 <outgoingBytes>8957187</outgoingBytes>
346 </byteCounters>
347 </face>
348 </faces>
349)XML");
350
351const std::string STATUS_TEXT =
352 "Faces:\n"
353 " faceid=134 remote=udp4://233.252.0.4:6363 local=udp4://192.0.2.1:6363"
354 " counters={in={22562i 22031d 63n 2522915B} out={30121i 20940d 1218n 1353592B}}"
Junxiao Shi1f481fa2017-01-26 15:14:43 +0000355 " flags={non-local permanent multi-access}\n"
Junxiao Shi38f4ce92016-08-04 10:01:52 +0000356 " faceid=745 remote=fd://75 local=unix:///var/run/nfd.sock"
357 " counters={in={18998i 26701d 147n 4672308B} out={34779i 17028d 1176n 8957187B}}"
Junxiao Shi1f481fa2017-01-26 15:14:43 +0000358 " flags={local on-demand point-to-point local-fields}\n";
Junxiao Shi38f4ce92016-08-04 10:01:52 +0000359
Junxiao Shi1f481fa2017-01-26 15:14:43 +0000360BOOST_FIXTURE_TEST_CASE(Status, StatusFixture<FaceModule>)
Junxiao Shi38f4ce92016-08-04 10:01:52 +0000361{
362 this->fetchStatus();
363 FaceStatus payload1;
364 payload1.setFaceId(134)
365 .setRemoteUri("udp4://233.252.0.4:6363")
366 .setLocalUri("udp4://192.0.2.1:6363")
367 .setFaceScope(ndn::nfd::FACE_SCOPE_NON_LOCAL)
368 .setFacePersistency(ndn::nfd::FACE_PERSISTENCY_PERMANENT)
369 .setLinkType(ndn::nfd::LINK_TYPE_MULTI_ACCESS)
370 .setNInInterests(22562)
371 .setNInDatas(22031)
372 .setNInNacks(63)
373 .setNOutInterests(30121)
374 .setNOutDatas(20940)
375 .setNOutNacks(1218)
376 .setNInBytes(2522915)
377 .setNOutBytes(1353592);
378 FaceStatus payload2;
379 payload2.setFaceId(745)
380 .setRemoteUri("fd://75")
381 .setLocalUri("unix:///var/run/nfd.sock")
382 .setFaceScope(ndn::nfd::FACE_SCOPE_LOCAL)
383 .setFacePersistency(ndn::nfd::FACE_PERSISTENCY_ON_DEMAND)
384 .setLinkType(ndn::nfd::LINK_TYPE_POINT_TO_POINT)
Eric Newberry6d932e82016-11-24 05:05:43 +0000385 .setFlagBit(ndn::nfd::BIT_LOCAL_FIELDS_ENABLED, true)
Junxiao Shi38f4ce92016-08-04 10:01:52 +0000386 .setNInInterests(18998)
387 .setNInDatas(26701)
388 .setNInNacks(147)
389 .setNOutInterests(34779)
390 .setNOutDatas(17028)
391 .setNOutNacks(1176)
392 .setNInBytes(4672308)
393 .setNOutBytes(8957187);
394 this->sendDataset("/localhost/nfd/faces/list", payload1, payload2);
395 this->prepareStatusOutput();
396
397 BOOST_CHECK(statusXml.is_equal(STATUS_XML));
398 BOOST_CHECK(statusText.is_equal(STATUS_TEXT));
399}
400
401BOOST_AUTO_TEST_SUITE_END() // TestFaceModule
Junxiao Shi331ade72016-08-19 14:07:19 +0000402BOOST_AUTO_TEST_SUITE_END() // Nfdc
Junxiao Shi38f4ce92016-08-04 10:01:52 +0000403
404} // namespace tests
Junxiao Shi331ade72016-08-19 14:07:19 +0000405} // namespace nfdc
Junxiao Shi38f4ce92016-08-04 10:01:52 +0000406} // namespace tools
407} // namespace nfd