blob: 2d5835adeac3ef8159d0b71ce3d92e4fe4947907 [file] [log] [blame]
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -05001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/*
Ashlesh Gawande6a5157f2019-12-09 11:49:07 -06003 * Copyright (c) 2014-2020, The University of Memphis
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -05004 *
5 * This file is part of PSync.
6 * See AUTHORS.md for complete list of PSync authors and contributors.
7 *
8 * PSync is free software: you can redistribute it and/or modify it under the terms
Ashlesh Gawande0cf4b602019-01-18 15:58:17 -06009 * of the GNU Lesser General Public License as published by the Free Software Foundation,
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -050010 * either version 3 of the License, or (at your option) any later version.
11 *
12 * PSync is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
13 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
Ashlesh Gawande0cf4b602019-01-18 15:58:17 -060014 * PURPOSE. See the GNU Lesser General Public License for more details.
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -050015 *
Ashlesh Gawande0cf4b602019-01-18 15:58:17 -060016 * You should have received a copy of the GNU Lesser General Public License along with
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -050017 * PSync, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
18 **/
19
Ashlesh Gawande78b94ad2018-12-13 15:29:19 -060020#include "PSync/partial-producer.hpp"
21#include "PSync/consumer.hpp"
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -050022
Davide Pesavento5b3cf762020-04-03 16:20:04 -040023#include "tests/boost-test.hpp"
24#include "tests/unit-test-time-fixture.hpp"
25
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -050026#include <ndn-cxx/name.hpp>
27#include <ndn-cxx/util/dummy-client-face.hpp>
28
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -050029namespace psync {
30
31using namespace ndn;
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -050032
33class PartialSyncFixture : public tests::UnitTestTimeFixture
34{
35public:
36 PartialSyncFixture()
Davide Pesavento5b3cf762020-04-03 16:20:04 -040037 : face(io, {true, true})
38 , syncPrefix("psync")
39 , userPrefix("testUser-0")
40 , numHelloDataRcvd(0)
41 , numSyncDataRcvd(0)
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -050042 {
43 producer = make_shared<PartialProducer>(40, face, syncPrefix, userPrefix);
44 addUserNodes("testUser", 10);
45 }
46
Ashlesh Gawandeec43b362018-08-01 15:15:01 -050047 ~PartialSyncFixture()
48 {
49 for (auto consumer : consumers) {
50 if (consumer) {
51 consumer->stop();
52 }
53 }
54 }
55
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -050056 void
Davide Pesavento5b3cf762020-04-03 16:20:04 -040057 addConsumer(int id, const std::vector<std::string>& subscribeTo, bool linkToProducer = true)
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -050058 {
Davide Pesavento5b3cf762020-04-03 16:20:04 -040059 consumerFaces[id] = std::make_shared<util::DummyClientFace>(io, util::DummyClientFace::Options{true, true});
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -050060
Ashlesh Gawandeec43b362018-08-01 15:15:01 -050061 if (linkToProducer) {
62 face.linkTo(*consumerFaces[id]);
63 }
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -050064
Davide Pesavento5b3cf762020-04-03 16:20:04 -040065 consumers[id] = std::make_shared<Consumer>(syncPrefix, *consumerFaces[id],
Ashlesh Gawandecbdc0122020-07-13 21:13:00 -070066 [&, id] (const auto& availableSubs)
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -050067 {
68 numHelloDataRcvd++;
Ashlesh Gawandedeb73f82018-08-09 11:08:02 -050069 BOOST_CHECK(checkSubList(availableSubs));
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -050070
71 checkIBFUpdated(id);
72
73 for (const auto& sub : subscribeTo) {
Ashlesh Gawandecbdc0122020-07-13 21:13:00 -070074 auto it = availableSubs.find(sub);
75 consumers[id]->addSubscription(sub, it->second);
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -050076 }
77 consumers[id]->sendSyncInterest();
78 },
Ashlesh Gawandecbdc0122020-07-13 21:13:00 -070079 [&, id] (const auto& updates) {
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -050080 numSyncDataRcvd++;
81
82 checkIBFUpdated(id);
83
84 for (const auto& update : updates) {
85 BOOST_CHECK(consumers[id]->isSubscribed(update.prefix));
86 BOOST_CHECK_EQUAL(oldSeqMap.at(update.prefix) + 1, update.lowSeq);
87 BOOST_CHECK_EQUAL(producer->m_prefixes.at(update.prefix), update.highSeq);
88 BOOST_CHECK_EQUAL(consumers[id]->getSeqNo(update.prefix).value(), update.highSeq);
89 }
90 }, 40, 0.001);
91
92 advanceClocks(ndn::time::milliseconds(10));
93 }
94
95 void
96 checkIBFUpdated(int id)
97 {
98 Name emptyName;
99 producer->m_iblt.appendToName(emptyName);
100 BOOST_CHECK_EQUAL(consumers[id]->m_iblt, emptyName);
101 }
102
103 bool
Ashlesh Gawandecbdc0122020-07-13 21:13:00 -0700104 checkSubList(const std::map<Name, uint64_t>& availableSubs) const
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -0500105 {
Davide Pesavento5b3cf762020-04-03 16:20:04 -0400106 for (const auto& prefix : producer->m_prefixes) {
Ashlesh Gawandecbdc0122020-07-13 21:13:00 -0700107 auto it = availableSubs.find(prefix.first);
108 if (it == availableSubs.end()) {
Ashlesh Gawandedeb73f82018-08-09 11:08:02 -0500109 return false;
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -0500110 }
111 }
112 return true;
113 }
114
115 void
116 addUserNodes(const std::string& prefix, int numOfUserNodes)
117 {
118 // zeroth is added through constructor
119 for (int i = 1; i < numOfUserNodes; i++) {
120 producer->addUserNode(prefix + "-" + to_string(i));
121 }
122 }
123
124 void
125 publishUpdateFor(const std::string& prefix)
126 {
127 oldSeqMap = producer->m_prefixes;
128 producer->publishName(prefix);
129 advanceClocks(ndn::time::milliseconds(10));
130 }
131
132 void
133 updateSeqFor(const std::string& prefix, uint64_t seq)
134 {
135 oldSeqMap = producer->m_prefixes;
136 producer->updateSeqNo(prefix, seq);
137 }
138
139 util::DummyClientFace face;
140 Name syncPrefix;
141 Name userPrefix;
142
143 shared_ptr<PartialProducer> producer;
144 std::map <ndn::Name, uint64_t> oldSeqMap;
145
146 shared_ptr<Consumer> consumers[3];
147 shared_ptr<util::DummyClientFace> consumerFaces[3];
148 int numHelloDataRcvd;
149 int numSyncDataRcvd;
150};
151
Ashlesh Gawande6a5157f2019-12-09 11:49:07 -0600152BOOST_FIXTURE_TEST_SUITE(TestPartialSync, PartialSyncFixture)
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -0500153
154BOOST_AUTO_TEST_CASE(Simple)
155{
Davide Pesavento5b3cf762020-04-03 16:20:04 -0400156 std::vector<std::string> subscribeTo{"testUser-2", "testUser-4", "testUser-6"};
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -0500157 addConsumer(0, subscribeTo);
158
159 consumers[0]->sendHelloInterest();
160 advanceClocks(ndn::time::milliseconds(10));
161 BOOST_CHECK_EQUAL(numHelloDataRcvd, 1);
162
163 publishUpdateFor("testUser-2");
164 BOOST_CHECK_EQUAL(numSyncDataRcvd, 1);
165 publishUpdateFor("testUser-3");
166 BOOST_CHECK_EQUAL(numSyncDataRcvd, 1);
167 publishUpdateFor("testUser-2");
168 BOOST_CHECK_EQUAL(numSyncDataRcvd, 2);
169}
170
171BOOST_AUTO_TEST_CASE(MissedUpdate)
172{
Davide Pesavento5b3cf762020-04-03 16:20:04 -0400173 std::vector<std::string> subscribeTo{"testUser-2", "testUser-4", "testUser-6"};
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -0500174 addConsumer(0, subscribeTo);
175
176 consumers[0]->sendHelloInterest();
177 advanceClocks(ndn::time::milliseconds(10));
178 BOOST_CHECK_EQUAL(numHelloDataRcvd, 1);
179
180 updateSeqFor("testUser-2", 3);
181 BOOST_CHECK_EQUAL(numSyncDataRcvd, 0);
182
183 // The sync interest sent after hello will timeout
184 advanceClocks(ndn::time::milliseconds(1000));
185 BOOST_CHECK_EQUAL(numSyncDataRcvd, 0);
186
187 // Next sync interest will bring back the sync data
Ashlesh Gawandeec43b362018-08-01 15:15:01 -0500188 advanceClocks(ndn::time::milliseconds(1500));
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -0500189 BOOST_CHECK_EQUAL(numSyncDataRcvd, 1);
190}
191
192BOOST_AUTO_TEST_CASE(LateSubscription)
193{
Davide Pesavento5b3cf762020-04-03 16:20:04 -0400194 std::vector<std::string> subscribeTo{"testUser-2", "testUser-4", "testUser-6"};
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -0500195 addConsumer(0, subscribeTo);
196
197 consumers[0]->sendHelloInterest();
198 advanceClocks(ndn::time::milliseconds(10));
199
200 BOOST_CHECK_EQUAL(numHelloDataRcvd, 1);
201 publishUpdateFor("testUser-2");
202 BOOST_CHECK_EQUAL(numSyncDataRcvd, 1);
203
Ashlesh Gawandecbdc0122020-07-13 21:13:00 -0700204 consumers[0]->addSubscription("testUser-3", 0);
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -0500205 consumers[0]->sendSyncInterest();
206 publishUpdateFor("testUser-3");
207 BOOST_CHECK_EQUAL(numSyncDataRcvd, 2);
208}
209
210BOOST_AUTO_TEST_CASE(ConsumerSyncTimeout)
211{
Davide Pesavento5b3cf762020-04-03 16:20:04 -0400212 std::vector<std::string> subscribeTo{"testUser-2", "testUser-4", "testUser-6"};
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -0500213 addConsumer(0, subscribeTo);
214
215 consumers[0]->sendHelloInterest();
216 BOOST_CHECK_EQUAL(producer->m_pendingEntries.size(), 0);
217 advanceClocks(ndn::time::milliseconds(10));
218 BOOST_CHECK_EQUAL(producer->m_pendingEntries.size(), 1);
219 advanceClocks(ndn::time::milliseconds(10), 100);
220 BOOST_CHECK_EQUAL(producer->m_pendingEntries.size(), 0);
221 advanceClocks(ndn::time::milliseconds(10), 100);
222
223 int numSyncInterests = 0;
224 for (const auto& interest : consumerFaces[0]->sentInterests) {
225 if (interest.getName().getSubName(0, 2) == Name("/psync/sync")) {
226 numSyncInterests++;
227 }
228 }
229 BOOST_CHECK_EQUAL(numSyncInterests, 2);
230 BOOST_CHECK_EQUAL(numSyncDataRcvd, 0);
231}
232
233BOOST_AUTO_TEST_CASE(MultipleConsumersWithSameSubList)
234{
Davide Pesavento5b3cf762020-04-03 16:20:04 -0400235 std::vector<std::string> subscribeTo{"testUser-2", "testUser-4", "testUser-6"};
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -0500236 addConsumer(0, subscribeTo);
237 addConsumer(1, subscribeTo);
238 addConsumer(2, subscribeTo);
239
240 consumers[0]->sendHelloInterest();
241 consumers[1]->sendHelloInterest();
242 consumers[2]->sendHelloInterest();
243 advanceClocks(ndn::time::milliseconds(10));
244
245 BOOST_CHECK_EQUAL(numHelloDataRcvd, 3);
246
247 publishUpdateFor("testUser-2");
248 BOOST_CHECK_EQUAL(numSyncDataRcvd, 3);
249
250 publishUpdateFor("testUser-3");
251 BOOST_CHECK_EQUAL(numSyncDataRcvd, 3);
252}
253
254BOOST_AUTO_TEST_CASE(MultipleConsumersWithDifferentSubList)
255{
Davide Pesavento5b3cf762020-04-03 16:20:04 -0400256 std::vector<std::string> subscribeTo{"testUser-2", "testUser-4", "testUser-6"};
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -0500257 addConsumer(0, subscribeTo);
258
Davide Pesavento5b3cf762020-04-03 16:20:04 -0400259 std::vector<std::string> subscribeTo1{"testUser-1", "testUser-3", "testUser-5"};
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -0500260 addConsumer(1, subscribeTo1);
261
Davide Pesavento5b3cf762020-04-03 16:20:04 -0400262 std::vector<std::string> subscribeTo2{"testUser-2", "testUser-3"};
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -0500263 addConsumer(2, subscribeTo2);
264
265 consumers[0]->sendHelloInterest();
266 consumers[1]->sendHelloInterest();
267 consumers[2]->sendHelloInterest();
268 advanceClocks(ndn::time::milliseconds(10));
269
270 BOOST_CHECK_EQUAL(numHelloDataRcvd, 3);
271
272 publishUpdateFor("testUser-2");
273 BOOST_CHECK_EQUAL(numSyncDataRcvd, 2);
274
275 numSyncDataRcvd = 0;
276 publishUpdateFor("testUser-3");
277 BOOST_CHECK_EQUAL(numSyncDataRcvd, 2);
278}
279
280BOOST_AUTO_TEST_CASE(ReplicatedProducer)
281{
Davide Pesavento5b3cf762020-04-03 16:20:04 -0400282 std::vector<std::string> subscribeTo{"testUser-2", "testUser-4", "testUser-6"};
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -0500283 addConsumer(0, subscribeTo);
284
285 consumers[0]->sendHelloInterest();
286 advanceClocks(ndn::time::milliseconds(10));
287 BOOST_CHECK_EQUAL(numHelloDataRcvd, 1);
288
289 publishUpdateFor("testUser-2");
290 BOOST_CHECK_EQUAL(numSyncDataRcvd, 1);
291
292 // Link to first producer goes down
293 face.unlink();
294
295 util::DummyClientFace face2(io, {true, true});
296 PartialProducer replicatedProducer(40, face2, syncPrefix, userPrefix);
297 for (int i = 1; i < 10; i++) {
298 replicatedProducer.addUserNode("testUser-" + to_string(i));
299 }
300 advanceClocks(ndn::time::milliseconds(10));
301 replicatedProducer.publishName("testUser-2");
302 // Link to a replicated producer comes up
303 face2.linkTo(*consumerFaces[0]);
304
305 BOOST_CHECK_EQUAL(face2.sentData.size(), 0);
306
307 // Update in first producer as well so consumer on sync data
308 // callback checks still pass
309 publishUpdateFor("testUser-2");
310 replicatedProducer.publishName("testUser-2");
311 advanceClocks(ndn::time::milliseconds(15), 100);
312 BOOST_CHECK_EQUAL(numSyncDataRcvd, 2);
313 BOOST_CHECK_EQUAL(face2.sentData.size(), 1);
314}
315
316BOOST_AUTO_TEST_CASE(ApplicationNack)
317{
318 // 50 is more than expected number of entries of 40 in the producer's IBF
319 addUserNodes("testUser", 50);
320
Davide Pesavento5b3cf762020-04-03 16:20:04 -0400321 std::vector<std::string> subscribeTo{"testUser-2", "testUser-4", "testUser-6"};
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -0500322 addConsumer(0, subscribeTo);
323
324 consumers[0]->sendHelloInterest();
325 advanceClocks(ndn::time::milliseconds(10));
326 BOOST_CHECK_EQUAL(numHelloDataRcvd, 1);
327
328 publishUpdateFor("testUser-2");
329 BOOST_CHECK_EQUAL(numSyncDataRcvd, 1);
330
331 oldSeqMap = producer->m_prefixes;
332 for (int i = 0; i < 50; i++) {
333 ndn::Name prefix("testUser-" + to_string(i));
334 producer->updateSeqNo(prefix, producer->getSeqNo(prefix).value() + 1);
335 }
336 // Next sync interest should trigger the nack
337 advanceClocks(ndn::time::milliseconds(15), 100);
338
Ashlesh Gawandea9296472018-08-04 08:21:39 -0500339 // Application should have been notified that new data is available
340 // from the hello itself.
341 BOOST_CHECK_EQUAL(numSyncDataRcvd, 2);
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -0500342
343 bool nackRcvd = false;
344 for (const auto& data : face.sentData) {
345 if (data.getContentType() == ndn::tlv::ContentType_Nack) {
346 nackRcvd = true;
347 break;
348 }
349 }
350 BOOST_CHECK(nackRcvd);
351
Ashlesh Gawandea9296472018-08-04 08:21:39 -0500352 publishUpdateFor("testUser-4");
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -0500353 advanceClocks(ndn::time::milliseconds(10));
Ashlesh Gawandea9296472018-08-04 08:21:39 -0500354 BOOST_CHECK_EQUAL(numSyncDataRcvd, 3);
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -0500355}
356
Ashlesh Gawandeec43b362018-08-01 15:15:01 -0500357BOOST_AUTO_TEST_CASE(SegmentedHello)
358{
Davide Pesavento5b3cf762020-04-03 16:20:04 -0400359 std::vector<std::string> subscribeTo{"testUser-2", "testUser-4", "testUser-6"};
Ashlesh Gawandeec43b362018-08-01 15:15:01 -0500360 addConsumer(0, subscribeTo);
361
362 addUserNodes("testUser", 400);
363
364 consumers[0]->sendHelloInterest();
365 advanceClocks(ndn::time::milliseconds(10));
366 BOOST_CHECK_EQUAL(numHelloDataRcvd, 1);
Ashlesh Gawande2e82df12018-12-08 21:42:29 -0600367
368 // Simulate sending delayed interest for second segment
Davide Pesavento5b3cf762020-04-03 16:20:04 -0400369 BOOST_REQUIRE(!face.sentData.empty());
Ashlesh Gawande2e82df12018-12-08 21:42:29 -0600370 Name dataName = face.sentData.back().getName();
371 face.sentData.clear();
372 BOOST_CHECK_EQUAL(producer->m_segmentPublisher.m_ims.size(), 2);
373
374 advanceClocks(ndn::time::milliseconds(1000));
375 BOOST_CHECK_EQUAL(producer->m_segmentPublisher.m_ims.size(), 0);
376
377 producer->onHelloInterest(consumers[0]->m_helloInterestPrefix, Interest(dataName));
378 advanceClocks(ndn::time::milliseconds(10));
379 BOOST_CHECK_EQUAL(producer->m_segmentPublisher.m_ims.size(), 2);
Davide Pesavento5b3cf762020-04-03 16:20:04 -0400380 BOOST_REQUIRE(!face.sentData.empty());
381 BOOST_CHECK_EQUAL(face.sentData.front().getName().at(-1).toSegment(), 1);
Ashlesh Gawandeec43b362018-08-01 15:15:01 -0500382}
383
384BOOST_AUTO_TEST_CASE(SegmentedSync)
385{
386 ndn::Name longNameToExceedDataSize;
387 for (int i = 0; i < 100; i++) {
388 longNameToExceedDataSize.append("test-" + std::to_string(i));
389 }
390 addUserNodes(longNameToExceedDataSize.toUri(), 10);
391
Davide Pesavento5b3cf762020-04-03 16:20:04 -0400392 std::vector<std::string> subscribeTo;
Ashlesh Gawandeec43b362018-08-01 15:15:01 -0500393 for (int i = 1; i < 10; i++) {
394 subscribeTo.push_back(longNameToExceedDataSize.toUri() + "-" + to_string(i));
395 }
396 addConsumer(0, subscribeTo);
397
398 consumers[0]->sendHelloInterest();
399 advanceClocks(ndn::time::milliseconds(10));
400 BOOST_CHECK_EQUAL(numHelloDataRcvd, 1);
401
Ashlesh Gawande2e82df12018-12-08 21:42:29 -0600402 // To be used later to simulate sending delayed segmented interest
403 ndn::Name syncInterestName(consumers[0]->m_syncInterestPrefix);
404 consumers[0]->m_bloomFilter.appendToName(syncInterestName);
405 syncInterestName.append(consumers[0]->m_iblt);
406 syncInterestName.appendVersion();
407 syncInterestName.appendSegment(1);
408
Ashlesh Gawandeec43b362018-08-01 15:15:01 -0500409 oldSeqMap = producer->m_prefixes;
410 for (int i = 1; i < 10; i++) {
411 producer->updateSeqNo(longNameToExceedDataSize.toUri() + "-" + to_string(i), 1);
412 }
413
414 advanceClocks(ndn::time::milliseconds(1000));
415 BOOST_CHECK_EQUAL(numSyncDataRcvd, 0);
416
417 advanceClocks(ndn::time::milliseconds(1500));
418 BOOST_CHECK_EQUAL(numSyncDataRcvd, 1);
Ashlesh Gawande2e82df12018-12-08 21:42:29 -0600419
420 // Simulate sending delayed interest for second segment
421 face.sentData.clear();
422 consumerFaces[0]->sentData.clear();
423
424 BOOST_CHECK_EQUAL(producer->m_segmentPublisher.m_ims.size(), 2);
425
426 advanceClocks(ndn::time::milliseconds(2000));
427 BOOST_CHECK_EQUAL(producer->m_segmentPublisher.m_ims.size(), 0);
428
429 producer->onSyncInterest(consumers[0]->m_syncInterestPrefix, Interest(syncInterestName));
430 advanceClocks(ndn::time::milliseconds(10));
431 BOOST_CHECK_EQUAL(producer->m_segmentPublisher.m_ims.size(), 2);
Davide Pesavento5b3cf762020-04-03 16:20:04 -0400432 BOOST_REQUIRE(!face.sentData.empty());
433 BOOST_CHECK_EQUAL(face.sentData.front().getName().at(-1).toSegment(), 1);
Ashlesh Gawandeec43b362018-08-01 15:15:01 -0500434}
435
Ashlesh Gawandecbdc0122020-07-13 21:13:00 -0700436BOOST_AUTO_TEST_CASE(DelayedSubscription) // #5122
437{
438 publishUpdateFor("testUser-2");
439 std::vector<std::string> subscribeTo{"testUser-2", "testUser-4"};
440 addConsumer(0, subscribeTo);
441
442 consumers[0]->sendHelloInterest();
443 advanceClocks(ndn::time::milliseconds(10));
444 BOOST_CHECK_EQUAL(numHelloDataRcvd, 1);
445
446 // Application came up late and subscribed to testUser-2
447 // after Producer had already published the first update.
448 // So by default Consumer will let the application know that
449 // the prefix it subscribed to has already some updates
450 BOOST_CHECK_EQUAL(numSyncDataRcvd, 1);
451}
452
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -0500453BOOST_AUTO_TEST_SUITE_END()
454
Ashlesh Gawande6a5157f2019-12-09 11:49:07 -0600455} // namespace psync