blob: 9176690ee20d33c62242a9fff71ce9410efbe9de [file] [log] [blame]
Junxiao Shi7b6b79d2014-03-26 20:59:35 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
2/**
3 * Copyright (C) 2013 Regents of the University of California.
4 * See COPYING for copyright and distribution information.
5 */
6
7#include "management/nfd-controller.hpp"
8// Having a separate compilation unit is necessary to ensure .hpp can compile on its own.
9#include "management/nfd-control-response.hpp"
10
11#include "../transport/dummy-face.hpp"
12#include <boost/test/unit_test.hpp>
13
14namespace ndn {
15namespace nfd {
16
17BOOST_AUTO_TEST_SUITE(NfdController)
18
19class CommandFixture
20{
21protected:
22 CommandFixture()
23 : face(makeDummyFace())
24 , controller(*face)
25 , commandSucceedCallback(bind(&CommandFixture::onCommandSucceed, this, _1))
26 , commandFailCallback(bind(&CommandFixture::onCommandFail, this, _1, _2))
27 {
28 }
29
30private:
31 void
32 onCommandSucceed(const ControlParameters& parameters)
33 {
34 commandSucceedHistory.push_back(boost::make_tuple(parameters));
35 }
36
37 void
38 onCommandFail(uint32_t code, const std::string& reason)
39 {
40 commandFailHistory.push_back(boost::make_tuple(code, reason));
41 }
42
43protected:
44 shared_ptr<DummyFace> face;
45 Controller controller;
46 KeyChain keyChain;
47
48 Controller::CommandSucceedCallback commandSucceedCallback;
49 typedef boost::tuple<ControlParameters> CommandSucceedArgs;
50 std::vector<CommandSucceedArgs> commandSucceedHistory;
51
52 Controller::CommandFailCallback commandFailCallback;
53 typedef boost::tuple<uint32_t,std::string> CommandFailArgs;
54 std::vector<CommandFailArgs> commandFailHistory;
55};
56
57BOOST_FIXTURE_TEST_CASE(CommandSuccess, CommandFixture)
58{
59 ControlParameters parameters;
60 parameters.setUri("tcp://example.com");
61
62 BOOST_CHECK_NO_THROW(controller.start<FaceCreateCommand>(
63 parameters,
64 commandSucceedCallback,
65 commandFailCallback));
66 face->processEvents(time::milliseconds(1));
67
68 BOOST_REQUIRE_EQUAL(face->m_sentInterests.size(), 1);
69 const Interest& commandInterest = face->m_sentInterests[0];
70
71 FaceCreateCommand command;
72 BOOST_CHECK(command.getPrefix().isPrefixOf(commandInterest.getName()));
73 // 9 components: ndn:/localhost/nfd/face/create/<parameters>/<command Interest signature x4>
74 BOOST_REQUIRE_EQUAL(commandInterest.getName().size(), 9);
75 ControlParameters request;
76 // 4th component: <parameters>
77 BOOST_REQUIRE_NO_THROW(request.wireDecode(commandInterest.getName().at(4).blockFromValue()));
78 BOOST_CHECK_NO_THROW(command.validateRequest(request));
79 BOOST_CHECK_EQUAL(request.getUri(), parameters.getUri());
80
81 ControlParameters responseBody;
82 responseBody.setUri("tcp4://192.0.2.1:6363")
83 .setFaceId(22);
84 ControlResponse responsePayload(201, "created");
85 responsePayload.setBody(responseBody.wireEncode());
86
87 Data responseData(commandInterest.getName());
88 responseData.setContent(responsePayload.wireEncode());
89 keyChain.sign(responseData);
90 face->receive(responseData);
91 face->processEvents(time::milliseconds(1));
92
93 BOOST_CHECK_EQUAL(commandFailHistory.size(), 0);
94 BOOST_REQUIRE_EQUAL(commandSucceedHistory.size(), 1);
95 const ControlParameters& response = commandSucceedHistory[0].get<0>();
96 BOOST_CHECK_EQUAL(response.getUri(), responseBody.getUri());
97 BOOST_CHECK_EQUAL(response.getFaceId(), responseBody.getFaceId());
98}
99
100BOOST_FIXTURE_TEST_CASE(CommandInvalidRequest, CommandFixture)
101{
102 ControlParameters parameters;
103 parameters.setName("ndn:/should-not-have-this-field");
104 // Uri is missing
105
106 BOOST_CHECK_THROW(controller.start<FaceCreateCommand>(
107 parameters,
108 commandSucceedCallback,
109 commandFailCallback),
110 ControlCommand::ArgumentError);
111}
112
113BOOST_FIXTURE_TEST_CASE(CommandErrorCode, CommandFixture)
114{
115 ControlParameters parameters;
116 parameters.setUri("tcp://example.com");
117
118 BOOST_CHECK_NO_THROW(controller.start<FaceCreateCommand>(
119 parameters,
120 commandSucceedCallback,
121 commandFailCallback));
122 face->processEvents(time::milliseconds(1));
123
124 BOOST_REQUIRE_EQUAL(face->m_sentInterests.size(), 1);
125 const Interest& commandInterest = face->m_sentInterests[0];
126
127 ControlResponse responsePayload(401, "Not Authenticated");
128
129 Data responseData(commandInterest.getName());
130 responseData.setContent(responsePayload.wireEncode());
131 keyChain.sign(responseData);
132 face->receive(responseData);
133 face->processEvents(time::milliseconds(1));
134
135 BOOST_CHECK_EQUAL(commandSucceedHistory.size(), 0);
136 BOOST_REQUIRE_EQUAL(commandFailHistory.size(), 1);
137 BOOST_CHECK_EQUAL(commandFailHistory[0].get<0>(), 401);
138}
139
140BOOST_FIXTURE_TEST_CASE(CommandInvalidResponse, CommandFixture)
141{
142 ControlParameters parameters;
143 parameters.setUri("tcp://example.com");
144
145 BOOST_CHECK_NO_THROW(controller.start<FaceCreateCommand>(
146 parameters,
147 commandSucceedCallback,
148 commandFailCallback));
149 face->processEvents(time::milliseconds(1));
150
151 BOOST_REQUIRE_EQUAL(face->m_sentInterests.size(), 1);
152 const Interest& commandInterest = face->m_sentInterests[0];
153
154 ControlParameters responseBody;
155 responseBody.setUri("tcp4://192.0.2.1:6363")
156 .setName("ndn:/should-not-have-this-field");
157 // FaceId is missing
158 ControlResponse responsePayload(201, "created");
159 responsePayload.setBody(responseBody.wireEncode());
160
161 Data responseData(commandInterest.getName());
162 responseData.setContent(responsePayload.wireEncode());
163 keyChain.sign(responseData);
164 face->receive(responseData);
165 face->processEvents(time::milliseconds(1));
166
167 BOOST_CHECK_EQUAL(commandSucceedHistory.size(), 0);
168 BOOST_REQUIRE_EQUAL(commandFailHistory.size(), 1);
169}
170
171BOOST_AUTO_TEST_SUITE_END()
172
173} // namespace nfd
174} // namespace ndn