blob: aef46a3f627bdb957a94d8de510d2141ec4c4c17 [file] [log] [blame]
Alexander Afanasyev4abdbf12014-08-11 12:48:54 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
Junxiao Shi2bea5c42017-08-14 20:10:32 +00002/*
Davide Pesaventob5f8bcc2017-02-05 17:58:05 -05003 * Copyright (c) 2014-2017 Regents of the University of California,
Spyridon Mastorakis429634f2015-02-19 17:35:33 -08004 * 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.
Alexander Afanasyev4abdbf12014-08-11 12:48:54 -070010 *
11 * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
12 *
13 * ndn-cxx library is free software: you can redistribute it and/or modify it under the
14 * terms of the GNU Lesser General Public License as published by the Free Software
15 * Foundation, either version 3 of the License, or (at your option) any later version.
16 *
17 * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
18 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
19 * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
20 *
21 * You should have received copies of the GNU General Public License and GNU Lesser
22 * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
23 * <http://www.gnu.org/licenses/>.
24 *
25 * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
26 */
27
Alexander Afanasyev4abdbf12014-08-11 12:48:54 -070028#include "util/notification-subscriber.hpp"
Alexander Afanasyevd3a55b22014-11-18 19:23:28 -080029#include "util/dummy-client-face.hpp"
Alexander Afanasyev4abdbf12014-08-11 12:48:54 -070030
Teng Liangf8bf1b02016-07-17 11:54:19 -070031#include "boost-test.hpp"
Junxiao Shi2bea5c42017-08-14 20:10:32 +000032#include "make-interest-data.hpp"
33#include "simple-notification.hpp"
34#include "../identity-management-time-fixture.hpp"
Alexander Afanasyev4abdbf12014-08-11 12:48:54 -070035
36namespace ndn {
Junxiao Shia60d9362014-11-12 09:38:21 -070037namespace util {
Alexander Afanasyev4abdbf12014-08-11 12:48:54 -070038namespace tests {
39
Teng Liang93adaff2016-07-30 15:57:12 -070040using namespace ndn::tests;
Alexander Afanasyev4abdbf12014-08-11 12:48:54 -070041
Alexander Afanasyev80782e02017-01-04 13:16:54 -080042class NotificationSubscriberFixture : public IdentityManagementTimeFixture
Alexander Afanasyev4abdbf12014-08-11 12:48:54 -070043{
44public:
Teng Liang93adaff2016-07-30 15:57:12 -070045 NotificationSubscriberFixture()
Alexander Afanasyev4abdbf12014-08-11 12:48:54 -070046 : streamPrefix("ndn:/NotificationSubscriberTest")
Alexander Afanasyeve4f8c3b2016-06-23 16:03:48 -070047 , subscriberFace(io, m_keyChain)
Alexander Afanasyev9bdbb832015-12-30 12:54:22 -080048 , subscriber(subscriberFace, streamPrefix, time::seconds(1))
Teng Liang93adaff2016-07-30 15:57:12 -070049 , nextSendNotificationNo(0)
Alexander Afanasyev4abdbf12014-08-11 12:48:54 -070050 {
51 }
52
Teng Liang93adaff2016-07-30 15:57:12 -070053 /** \brief deliver one notification to subscriber
Alexander Afanasyev4abdbf12014-08-11 12:48:54 -070054 */
55 void
56 deliverNotification(const std::string& msg)
57 {
Alexander Afanasyev4abdbf12014-08-11 12:48:54 -070058 SimpleNotification notification(msg);
Alexander Afanasyev370d2602014-08-20 10:21:34 -050059
Teng Liang93adaff2016-07-30 15:57:12 -070060 Name dataName = streamPrefix;
61 dataName.appendSequenceNumber(nextSendNotificationNo);
62 Data data(dataName);
63 data.setContent(notification.wireEncode());
64 data.setFreshnessPeriod(time::seconds(1));
65 m_keyChain.sign(data);
Alexander Afanasyev370d2602014-08-20 10:21:34 -050066
Teng Liang93adaff2016-07-30 15:57:12 -070067 lastDeliveredSeqNo = nextSendNotificationNo;
Alexander Afanasyev4abdbf12014-08-11 12:48:54 -070068 lastNotification.setMessage("");
Teng Liang93adaff2016-07-30 15:57:12 -070069 ++nextSendNotificationNo;
70 subscriberFace.receive(data);
Alexander Afanasyev4abdbf12014-08-11 12:48:54 -070071 }
72
Teng Liangf8bf1b02016-07-17 11:54:19 -070073 /** \brief deliver a Nack to subscriber
74 */
75 void
76 deliverNack(const Interest& interest, const lp::NackReason& reason)
77 {
78 lp::Nack nack = makeNack(interest, reason);
79 subscriberFace.receive(nack);
80 }
81
Alexander Afanasyev4abdbf12014-08-11 12:48:54 -070082 void
83 afterNotification(const SimpleNotification& notification)
84 {
85 lastNotification = notification;
86 }
87
88 void
Teng Liangf8bf1b02016-07-17 11:54:19 -070089 afterNack(const lp::Nack& nack)
90 {
91 lastNack = nack;
92 }
93
94 void
Alexander Afanasyev4abdbf12014-08-11 12:48:54 -070095 afterTimeout()
96 {
97 hasTimeout = true;
98 }
99
100 void
101 afterDecodeError(const Data& data)
102 {
103 lastDecodeErrorData = data;
104 }
105
Teng Liang93adaff2016-07-30 15:57:12 -0700106 void
107 connectHandlers()
108 {
109 notificationConn = subscriber.onNotification.connect(
110 bind(&NotificationSubscriberFixture::afterNotification, this, _1));
Teng Liangf8bf1b02016-07-17 11:54:19 -0700111 nackConn = subscriber.onNack.connect(
112 bind(&NotificationSubscriberFixture::afterNack, this, _1));
Teng Liang93adaff2016-07-30 15:57:12 -0700113 subscriber.onTimeout.connect(
114 bind(&NotificationSubscriberFixture::afterTimeout, this));
115 subscriber.onDecodeError.connect(
116 bind(&NotificationSubscriberFixture::afterDecodeError, this, _1));
117 }
118
119 void
120 disconnectHandlers()
121 {
122 notificationConn.disconnect();
Teng Liangf8bf1b02016-07-17 11:54:19 -0700123 nackConn.disconnect();
Teng Liang93adaff2016-07-30 15:57:12 -0700124 }
125
Alexander Afanasyev4abdbf12014-08-11 12:48:54 -0700126 /** \return true if subscriberFace has an initial request (first sent Interest)
127 */
128 bool
129 hasInitialRequest() const
130 {
Alexander Afanasyev9bdbb832015-12-30 12:54:22 -0800131 if (subscriberFace.sentInterests.empty())
Teng Liang93adaff2016-07-30 15:57:12 -0700132 return false;
Alexander Afanasyev4abdbf12014-08-11 12:48:54 -0700133
Alexander Afanasyev9bdbb832015-12-30 12:54:22 -0800134 const Interest& interest = subscriberFace.sentInterests[0];
Alexander Afanasyev4abdbf12014-08-11 12:48:54 -0700135 return interest.getName() == streamPrefix &&
136 interest.getChildSelector() == 1 &&
137 interest.getMustBeFresh() &&
138 interest.getInterestLifetime() == subscriber.getInterestLifetime();
139 }
140
141 /** \return sequence number of the continuation request sent from subscriberFace
142 * or 0 if there's no such request as sole sent Interest
143 */
144 uint64_t
145 getRequestSeqNo() const
146 {
Alexander Afanasyev9bdbb832015-12-30 12:54:22 -0800147 if (subscriberFace.sentInterests.size() != 1)
Alexander Afanasyev4abdbf12014-08-11 12:48:54 -0700148 return 0;
149
Alexander Afanasyev9bdbb832015-12-30 12:54:22 -0800150 const Interest& interest = subscriberFace.sentInterests[0];
Alexander Afanasyev4abdbf12014-08-11 12:48:54 -0700151 const Name& name = interest.getName();
152 if (streamPrefix.isPrefixOf(name) &&
153 name.size() == streamPrefix.size() + 1 &&
154 interest.getInterestLifetime() == subscriber.getInterestLifetime())
155 return name[-1].toSequenceNumber();
156 else
157 return 0;
158 }
159
160protected:
161 Name streamPrefix;
Alexander Afanasyev9bdbb832015-12-30 12:54:22 -0800162 DummyClientFace subscriberFace;
Alexander Afanasyev4abdbf12014-08-11 12:48:54 -0700163 util::NotificationSubscriber<SimpleNotification> subscriber;
Junxiao Shi728873f2015-01-20 16:01:26 -0700164 util::signal::Connection notificationConn;
Teng Liangf8bf1b02016-07-17 11:54:19 -0700165 util::signal::Connection nackConn;
Teng Liang93adaff2016-07-30 15:57:12 -0700166 uint64_t nextSendNotificationNo;
Alexander Afanasyev4abdbf12014-08-11 12:48:54 -0700167 uint64_t lastDeliveredSeqNo;
Alexander Afanasyev4abdbf12014-08-11 12:48:54 -0700168 SimpleNotification lastNotification;
Teng Liangf8bf1b02016-07-17 11:54:19 -0700169 lp::Nack lastNack;
Alexander Afanasyev4abdbf12014-08-11 12:48:54 -0700170 bool hasTimeout;
171 Data lastDecodeErrorData;
172};
173
Teng Liang93adaff2016-07-30 15:57:12 -0700174BOOST_AUTO_TEST_SUITE(Util)
175BOOST_FIXTURE_TEST_SUITE(TestNotificationSubscriber, NotificationSubscriberFixture)
176
177BOOST_AUTO_TEST_CASE(StartStop)
Alexander Afanasyev4abdbf12014-08-11 12:48:54 -0700178{
179 BOOST_REQUIRE_EQUAL(subscriber.isRunning(), false);
180
181 // has no effect because onNotification has no handler
182 subscriber.start();
183 BOOST_REQUIRE_EQUAL(subscriber.isRunning(), false);
184
Teng Liang93adaff2016-07-30 15:57:12 -0700185 this->connectHandlers();
Alexander Afanasyev4abdbf12014-08-11 12:48:54 -0700186 subscriber.start();
Alexander Afanasyev4abdbf12014-08-11 12:48:54 -0700187 BOOST_REQUIRE_EQUAL(subscriber.isRunning(), true);
Teng Liang93adaff2016-07-30 15:57:12 -0700188 advanceClocks(time::milliseconds(1));
Alexander Afanasyev4abdbf12014-08-11 12:48:54 -0700189 BOOST_CHECK(this->hasInitialRequest());
190
Teng Liang93adaff2016-07-30 15:57:12 -0700191 subscriberFace.sentInterests.clear();
192 this->disconnectHandlers();
193 this->deliverNotification("n1");
194 BOOST_REQUIRE_EQUAL(subscriberFace.sentInterests.size(), 0);
195}
196
197BOOST_AUTO_TEST_CASE(Notifications)
198{
199 this->connectHandlers();
200 subscriber.start();
201 advanceClocks(time::milliseconds(1));
202
Alexander Afanasyev4abdbf12014-08-11 12:48:54 -0700203 // respond to initial request
Alexander Afanasyev9bdbb832015-12-30 12:54:22 -0800204 subscriberFace.sentInterests.clear();
Teng Liang93adaff2016-07-30 15:57:12 -0700205 this->deliverNotification("n1");
206 advanceClocks(time::milliseconds(1));
207 BOOST_CHECK_EQUAL(lastNotification.getMessage(), "n1");
208 BOOST_CHECK_EQUAL(this->getRequestSeqNo(), lastDeliveredSeqNo + 1);
209
210 // respond to continuation request
211 subscriberFace.sentInterests.clear();
Alexander Afanasyev4abdbf12014-08-11 12:48:54 -0700212 this->deliverNotification("n2");
Alexander Afanasyevd3a55b22014-11-18 19:23:28 -0800213 advanceClocks(time::milliseconds(1));
Alexander Afanasyev4abdbf12014-08-11 12:48:54 -0700214 BOOST_CHECK_EQUAL(lastNotification.getMessage(), "n2");
215 BOOST_CHECK_EQUAL(this->getRequestSeqNo(), lastDeliveredSeqNo + 1);
Teng Liang93adaff2016-07-30 15:57:12 -0700216}
Alexander Afanasyev4abdbf12014-08-11 12:48:54 -0700217
Teng Liangf8bf1b02016-07-17 11:54:19 -0700218BOOST_AUTO_TEST_CASE(Nack)
219{
220 this->connectHandlers();
221 subscriber.start();
222 advanceClocks(time::milliseconds(1));
223
224 // send the first Nack to initial request
225 BOOST_REQUIRE_EQUAL(subscriberFace.sentInterests.size(), 1);
226 Interest interest = subscriberFace.sentInterests[0];
227 subscriberFace.sentInterests.clear();
228 this->deliverNack(interest, lp::NackReason::CONGESTION);
229 advanceClocks(time::milliseconds(1));
230 BOOST_CHECK_EQUAL(lastNack.getReason(), lp::NackReason::CONGESTION);
231 BOOST_REQUIRE_EQUAL(this->hasInitialRequest(), false);
232 advanceClocks(time::milliseconds(300));
233 BOOST_REQUIRE_EQUAL(this->hasInitialRequest(), true);
234
235 // send the second Nack to initial request
236 BOOST_REQUIRE_EQUAL(subscriberFace.sentInterests.size(), 1);
237 interest = subscriberFace.sentInterests[0];
238 subscriberFace.sentInterests.clear();
239 this->deliverNack(interest, lp::NackReason::CONGESTION);
240 advanceClocks(time::milliseconds(301));
241 BOOST_REQUIRE_EQUAL(this->hasInitialRequest(), false);
242 advanceClocks(time::milliseconds(200));
243 BOOST_REQUIRE_EQUAL(this->hasInitialRequest(), true);
244
245 // send a notification to initial request
246 subscriberFace.sentInterests.clear();
247 this->deliverNotification("n1");
248 advanceClocks(time::milliseconds(1));
249
250 // send a Nack to subsequent request
251 BOOST_REQUIRE_EQUAL(subscriberFace.sentInterests.size(), 1);
252 interest = subscriberFace.sentInterests[0];
253 subscriberFace.sentInterests.clear();
254 this->deliverNack(interest, lp::NackReason::CONGESTION);
255 advanceClocks(time::milliseconds(1));
256 BOOST_CHECK_EQUAL(lastNack.getReason(), lp::NackReason::CONGESTION);
257 BOOST_REQUIRE_EQUAL(this->hasInitialRequest(), false);
258 advanceClocks(time::milliseconds(300));
259 BOOST_REQUIRE_EQUAL(this->hasInitialRequest(), true);
260}
261
Teng Liang93adaff2016-07-30 15:57:12 -0700262BOOST_AUTO_TEST_CASE(Timeout)
263{
264 this->connectHandlers();
265 subscriber.start();
Alexander Afanasyevd3a55b22014-11-18 19:23:28 -0800266 advanceClocks(time::milliseconds(1));
Alexander Afanasyev4abdbf12014-08-11 12:48:54 -0700267
Alexander Afanasyev9bdbb832015-12-30 12:54:22 -0800268 subscriberFace.sentInterests.clear();
Alexander Afanasyev4abdbf12014-08-11 12:48:54 -0700269 lastNotification.setMessage("");
Alexander Afanasyevd3a55b22014-11-18 19:23:28 -0800270 advanceClocks(subscriber.getInterestLifetime(), 2);
Alexander Afanasyev4abdbf12014-08-11 12:48:54 -0700271 BOOST_CHECK(lastNotification.getMessage().empty());
272 BOOST_CHECK_EQUAL(hasTimeout, true);
273 BOOST_CHECK(this->hasInitialRequest());
274
Teng Liang93adaff2016-07-30 15:57:12 -0700275 subscriberFace.sentInterests.clear();
276 this->deliverNotification("n1");
277 advanceClocks(time::milliseconds(1));
278 BOOST_CHECK_EQUAL(lastNotification.getMessage(), "n1");
279}
280
281BOOST_AUTO_TEST_CASE(SequenceError)
282{
283 this->connectHandlers();
284 subscriber.start();
285 advanceClocks(time::milliseconds(1));
286
Alexander Afanasyev4abdbf12014-08-11 12:48:54 -0700287 Name wrongName = streamPrefix;
288 wrongName.append("%07%07");
289 Data wrongData(wrongName);
Alexander Afanasyeve4f8c3b2016-06-23 16:03:48 -0700290 m_keyChain.sign(wrongData);
Alexander Afanasyev9bdbb832015-12-30 12:54:22 -0800291 subscriberFace.receive(wrongData);
292 subscriberFace.sentInterests.clear();
Alexander Afanasyev4abdbf12014-08-11 12:48:54 -0700293 lastNotification.setMessage("");
Alexander Afanasyevd3a55b22014-11-18 19:23:28 -0800294 advanceClocks(time::milliseconds(1));
Alexander Afanasyev4abdbf12014-08-11 12:48:54 -0700295 BOOST_CHECK(lastNotification.getMessage().empty());
296 BOOST_CHECK_EQUAL(lastDecodeErrorData.getName(), wrongName);
297 BOOST_CHECK(this->hasInitialRequest());
Teng Liang93adaff2016-07-30 15:57:12 -0700298}
Alexander Afanasyev4abdbf12014-08-11 12:48:54 -0700299
Teng Liang93adaff2016-07-30 15:57:12 -0700300BOOST_AUTO_TEST_CASE(PayloadError)
301{
302 this->connectHandlers();
303 subscriber.start();
304 advanceClocks(time::milliseconds(1));
305
Alexander Afanasyev9bdbb832015-12-30 12:54:22 -0800306 subscriberFace.sentInterests.clear();
Alexander Afanasyev4abdbf12014-08-11 12:48:54 -0700307 lastNotification.setMessage("");
308 this->deliverNotification("\x07n4");
Alexander Afanasyevd3a55b22014-11-18 19:23:28 -0800309 advanceClocks(time::milliseconds(1));
Alexander Afanasyev4abdbf12014-08-11 12:48:54 -0700310 BOOST_CHECK(lastNotification.getMessage().empty());
311 BOOST_CHECK(this->hasInitialRequest());
Alexander Afanasyev4abdbf12014-08-11 12:48:54 -0700312}
313
Teng Liang93adaff2016-07-30 15:57:12 -0700314BOOST_AUTO_TEST_SUITE_END() // TestNotificationSubscriber
315BOOST_AUTO_TEST_SUITE_END() // Util
Alexander Afanasyev4abdbf12014-08-11 12:48:54 -0700316
317} // namespace tests
Junxiao Shia60d9362014-11-12 09:38:21 -0700318} // namespace util
Alexander Afanasyev4abdbf12014-08-11 12:48:54 -0700319} // namespace ndn