blob: 874f6f79fd6ceaecfab9b4655441b7d38d6cceca [file] [log] [blame]
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -05001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/*
Junxiao Shic5f5eb12023-08-11 08:05:23 +00003 * Copyright (c) 2014-2023, 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/full-producer.hpp"
21#include "PSync/consumer.hpp"
22#include "PSync/detail/state.hpp"
Davide Pesaventodb789562020-12-19 23:01:08 -050023#include "PSync/detail/util.hpp"
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -050024
Davide Pesavento5b3cf762020-04-03 16:20:04 -040025#include "tests/boost-test.hpp"
Davide Pesaventof91d1df2020-11-25 14:50:41 -050026#include "tests/io-fixture.hpp"
Davide Pesaventoc45a4ea2022-09-19 02:10:53 -040027#include "tests/key-chain-fixture.hpp"
Davide Pesavento5b3cf762020-04-03 16:20:04 -040028
Davide Pesaventoc45a4ea2022-09-19 02:10:53 -040029#include <array>
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -050030#include <ndn-cxx/util/dummy-client-face.hpp>
31
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -050032namespace psync {
33
Junxiao Shic5f5eb12023-08-11 08:05:23 +000034using ndn::Interest;
35using ndn::Name;
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -050036
Davide Pesaventoc45a4ea2022-09-19 02:10:53 -040037class FullSyncFixture : public tests::IoFixture, public tests::KeyChainFixture
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -050038{
Davide Pesavento5b3cf762020-04-03 16:20:04 -040039protected:
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -050040 void
41 addNode(int id)
42 {
Junxiao Shifadcde52022-02-28 00:38:45 +000043 BOOST_ASSERT(id >= 0 && id < MAX_NODES);
Junxiao Shifadcde52022-02-28 00:38:45 +000044 userPrefixes[id] = "/userPrefix" + std::to_string(id);
Junxiao Shic5f5eb12023-08-11 08:05:23 +000045 faces[id] = std::make_unique<ndn::DummyClientFace>(m_io, m_keyChain,
46 ndn::DummyClientFace::Options{true, true});
Junxiao Shi69bcaef2023-12-27 02:29:59 +000047 FullProducer::Options opts;
48 opts.ibfCount = 40;
49 nodes[id] = std::make_unique<FullProducer>(*faces[id], m_keyChain, syncPrefix, opts);
50 nodes[id]->addUserNode(userPrefixes[id]);
Junxiao Shifadcde52022-02-28 00:38:45 +000051 }
Davide Pesaventof91d1df2020-11-25 14:50:41 -050052
Junxiao Shifadcde52022-02-28 00:38:45 +000053 void
54 clearNodes()
55 {
Davide Pesavento03426ef2022-09-23 19:49:10 -040056 nodes = {};
57 faces = {};
58 userPrefixes = {};
Junxiao Shifadcde52022-02-28 00:38:45 +000059 }
60
61 /**
62 * @brief Return a user prefix in the form /userNode<id>-<i>.
63 * @param id update originator node index.
64 * @param i user prefix index.
65 */
Davide Pesavento03426ef2022-09-23 19:49:10 -040066 static Name
67 makeSubPrefix(int id, int i)
Junxiao Shifadcde52022-02-28 00:38:45 +000068 {
69 return "/userNode" + std::to_string(id) + "-" + std::to_string(i);
70 }
71
72 /**
73 * @brief Publish a batch of updates.
74 * @param id node index.
75 * @param min minimum user prefix index.
76 * @param min maximum user prefix index.
77 * @param seq update sequence number.
78 * @post nodes[id] has user nodes /userNode<id>-<i> āˆ€iāˆˆ[min,max] , with sequence number
79 * set to @p seq ; only one sync Data may be sent after the last update.
80 */
81 void
82 batchUpdate(int id, int min, int max, uint64_t seq)
83 {
84 FullProducer& node = *nodes.at(id);
85 for (int i = min; i <= max; i++) {
86 auto userPrefix = makeSubPrefix(id, i);
87 node.addUserNode(userPrefix);
88 if (i < max) {
89 node.updateSeqNo(userPrefix, seq);
90 }
91 else {
92 node.publishName(userPrefix, seq);
93 }
94 }
95 }
96
97 /**
98 * @brief Check sequence number on a batch of user prefixes.
99 * @param id node index where the check is performed.
100 * @param origin update originator node index for deriving user prefixes.
101 * @param min minimum user prefix index.
102 * @param max maximum user prefix index.
103 * @param seq expected sequence number.
104 */
105 void
Davide Pesaventoc407dee2022-07-21 23:56:05 -0400106 batchCheck(int id, int origin, int min, int max, std::optional<uint64_t> seq)
Junxiao Shifadcde52022-02-28 00:38:45 +0000107 {
108 uint64_t expected = seq.value_or(NOT_EXIST);
109 FullProducer& node = *nodes.at(id);
110 for (int i = min; i <= max; i++) {
111 auto userPrefix = makeSubPrefix(origin, i);
112 BOOST_TEST_CONTEXT("node=" << id << " userPrefix=" << userPrefix) {
113 BOOST_CHECK_EQUAL(node.getSeqNo(userPrefix).value_or(NOT_EXIST), expected);
114 }
115 }
116 }
117
118 struct IbfDecodeFailureCounts
119 {
120 size_t aboveThreshold = 0;
121 size_t belowThreshold = 0;
122 };
123
124 /**
125 * @brief Return the sum of IBF decode failure counters among created nodes.
126 */
127 IbfDecodeFailureCounts
128 countIbfDecodeFailures() const
129 {
130 IbfDecodeFailureCounts result;
131 for (const auto& node : nodes) {
132 if (node == nullptr) {
133 continue;
134 }
135 result.aboveThreshold += node->nIbfDecodeFailuresAboveThreshold;
136 result.belowThreshold += node->nIbfDecodeFailuresBelowThreshold;
137 }
138 return result;
139 }
140
141 /**
142 * @brief Repeat a test function until there are IBF decode failures.
143 * @param minTotalUpdates minimum totalUpdates parameter.
144 * @param maxTotalUpdates maximum totalUpdates parameter.
145 * @param f test function.
146 *
Davide Pesavento03426ef2022-09-23 19:49:10 -0400147 * This method searches for totalUpdates āˆˆ [minTotalUpdates,maxTotalUpdates] until
148 * there is at least one execution that caused an IBF decode failure above threshold.
149 * If such an execution never occurs within the range, the test case fails.
Junxiao Shifadcde52022-02-28 00:38:45 +0000150 *
151 * Current FullSync logic cannot reliably recover from an IBF decode failure below threshold.
152 * Hence, that condition is not tested.
153 */
154 void
Davide Pesavento03426ef2022-09-23 19:49:10 -0400155 searchIbfDecodeFailures(int minTotalUpdates, int maxTotalUpdates,
156 const std::function<void(int totalUpdates)>& f)
Junxiao Shifadcde52022-02-28 00:38:45 +0000157 {
158 bool hasAboveThreshold = false;
159 for (int totalUpdates = minTotalUpdates; totalUpdates <= maxTotalUpdates; ++totalUpdates) {
160 clearNodes();
161 BOOST_TEST_CONTEXT("totalUpdates=" << totalUpdates) {
162 f(totalUpdates);
163
164 auto cnt = countIbfDecodeFailures();
165 BOOST_TEST_MESSAGE("aboveThreshold=" << cnt.aboveThreshold << " "
166 "belowThreshold=" << cnt.belowThreshold);
167 hasAboveThreshold = hasAboveThreshold || cnt.aboveThreshold > 0;
168 if (hasAboveThreshold) {
169 return;
170 }
171 }
172 }
173 BOOST_TEST_FAIL("cannot find viable totalUpdates for IBF decode failures");
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -0500174 }
175
Davide Pesavento5b3cf762020-04-03 16:20:04 -0400176protected:
177 const Name syncPrefix = "/psync";
Davide Pesaventoc407dee2022-07-21 23:56:05 -0400178 static constexpr int MAX_NODES = 4;
Junxiao Shifadcde52022-02-28 00:38:45 +0000179 std::array<Name, MAX_NODES> userPrefixes;
Junxiao Shic5f5eb12023-08-11 08:05:23 +0000180 std::array<std::unique_ptr<ndn::DummyClientFace>, MAX_NODES> faces;
Davide Pesavento03426ef2022-09-23 19:49:10 -0400181 std::array<std::unique_ptr<FullProducer>, MAX_NODES> nodes;
Davide Pesaventoc407dee2022-07-21 23:56:05 -0400182 static constexpr uint64_t NOT_EXIST = std::numeric_limits<uint64_t>::max();
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -0500183};
184
Ashlesh Gawande6a5157f2019-12-09 11:49:07 -0600185BOOST_FIXTURE_TEST_SUITE(TestFullSync, FullSyncFixture)
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -0500186
187BOOST_AUTO_TEST_CASE(TwoNodesSimple)
188{
189 addNode(0);
190 addNode(1);
191
192 faces[0]->linkTo(*faces[1]);
Junxiao Shifadcde52022-02-28 00:38:45 +0000193 advanceClocks(10_ms);
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -0500194
195 nodes[0]->publishName(userPrefixes[0]);
Junxiao Shifadcde52022-02-28 00:38:45 +0000196 advanceClocks(10_ms, 100);
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -0500197
Junxiao Shifadcde52022-02-28 00:38:45 +0000198 BOOST_CHECK_EQUAL(nodes[0]->getSeqNo(userPrefixes[0]).value_or(NOT_EXIST), 1);
199 BOOST_CHECK_EQUAL(nodes[1]->getSeqNo(userPrefixes[0]).value_or(NOT_EXIST), 1);
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -0500200
201 nodes[1]->publishName(userPrefixes[1]);
Junxiao Shifadcde52022-02-28 00:38:45 +0000202 advanceClocks(10_ms, 100);
203 BOOST_CHECK_EQUAL(nodes[0]->getSeqNo(userPrefixes[1]).value_or(NOT_EXIST), 1);
204 BOOST_CHECK_EQUAL(nodes[1]->getSeqNo(userPrefixes[1]).value_or(NOT_EXIST), 1);
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -0500205
206 nodes[1]->publishName(userPrefixes[1]);
Junxiao Shifadcde52022-02-28 00:38:45 +0000207 advanceClocks(10_ms, 100);
208 BOOST_CHECK_EQUAL(nodes[0]->getSeqNo(userPrefixes[1]).value_or(NOT_EXIST), 2);
209 BOOST_CHECK_EQUAL(nodes[1]->getSeqNo(userPrefixes[1]).value_or(NOT_EXIST), 2);
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -0500210}
211
212BOOST_AUTO_TEST_CASE(TwoNodesForceSeqNo)
213{
214 addNode(0);
215 addNode(1);
216
217 faces[0]->linkTo(*faces[1]);
Junxiao Shifadcde52022-02-28 00:38:45 +0000218 advanceClocks(10_ms);
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -0500219
220 nodes[0]->publishName(userPrefixes[0], 3);
Junxiao Shifadcde52022-02-28 00:38:45 +0000221 advanceClocks(10_ms, 100);
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -0500222
Junxiao Shifadcde52022-02-28 00:38:45 +0000223 BOOST_CHECK_EQUAL(nodes[0]->getSeqNo(userPrefixes[0]).value_or(NOT_EXIST), 3);
224 BOOST_CHECK_EQUAL(nodes[1]->getSeqNo(userPrefixes[0]).value_or(NOT_EXIST), 3);
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -0500225}
226
227BOOST_AUTO_TEST_CASE(TwoNodesWithMultipleUserNodes)
228{
229 addNode(0);
230 addNode(1);
231
232 faces[0]->linkTo(*faces[1]);
Junxiao Shifadcde52022-02-28 00:38:45 +0000233 advanceClocks(10_ms);
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -0500234
Junxiao Shifadcde52022-02-28 00:38:45 +0000235 Name nodeZeroExtraUser("/userPrefix0-1");
236 Name nodeOneExtraUser("/userPrefix1-1");
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -0500237
238 nodes[0]->addUserNode(nodeZeroExtraUser);
239 nodes[1]->addUserNode(nodeOneExtraUser);
240
241 nodes[0]->publishName(userPrefixes[0]);
Junxiao Shifadcde52022-02-28 00:38:45 +0000242 advanceClocks(10_ms, 100);
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -0500243
Junxiao Shifadcde52022-02-28 00:38:45 +0000244 BOOST_CHECK_EQUAL(nodes[0]->getSeqNo(userPrefixes[0]).value_or(NOT_EXIST), 1);
245 BOOST_CHECK_EQUAL(nodes[1]->getSeqNo(userPrefixes[0]).value_or(NOT_EXIST), 1);
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -0500246
247 nodes[0]->publishName(nodeZeroExtraUser);
Junxiao Shifadcde52022-02-28 00:38:45 +0000248 advanceClocks(10_ms, 100);
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -0500249
Junxiao Shifadcde52022-02-28 00:38:45 +0000250 BOOST_CHECK_EQUAL(nodes[0]->getSeqNo(nodeZeroExtraUser).value_or(NOT_EXIST), 1);
251 BOOST_CHECK_EQUAL(nodes[1]->getSeqNo(nodeZeroExtraUser).value_or(NOT_EXIST), 1);
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -0500252
253 nodes[1]->publishName(nodeOneExtraUser);
Junxiao Shifadcde52022-02-28 00:38:45 +0000254 advanceClocks(10_ms, 100);
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -0500255
Junxiao Shifadcde52022-02-28 00:38:45 +0000256 BOOST_CHECK_EQUAL(nodes[0]->getSeqNo(nodeOneExtraUser).value_or(NOT_EXIST), 1);
257 BOOST_CHECK_EQUAL(nodes[1]->getSeqNo(nodeOneExtraUser).value_or(NOT_EXIST), 1);
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -0500258}
259
260BOOST_AUTO_TEST_CASE(MultipleNodes)
261{
262 for (int i = 0; i < 4; i++) {
263 addNode(i);
264 }
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -0500265 for (int i = 0; i < 3; i++) {
266 faces[i]->linkTo(*faces[i + 1]);
267 }
268
269 nodes[0]->publishName(userPrefixes[0]);
Junxiao Shifadcde52022-02-28 00:38:45 +0000270 advanceClocks(10_ms, 100);
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -0500271 for (int i = 0; i < 4; i++) {
Junxiao Shifadcde52022-02-28 00:38:45 +0000272 BOOST_CHECK_EQUAL(nodes[i]->getSeqNo(userPrefixes[0]).value_or(NOT_EXIST), 1);
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -0500273 }
274
275 nodes[1]->publishName(userPrefixes[1]);
Junxiao Shifadcde52022-02-28 00:38:45 +0000276 advanceClocks(10_ms, 100);
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -0500277 for (int i = 0; i < 4; i++) {
Junxiao Shifadcde52022-02-28 00:38:45 +0000278 BOOST_CHECK_EQUAL(nodes[i]->getSeqNo(userPrefixes[1]).value_or(NOT_EXIST), 1);
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -0500279 }
280
281 nodes[1]->publishName(userPrefixes[1]);
Junxiao Shifadcde52022-02-28 00:38:45 +0000282 advanceClocks(10_ms, 100);
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -0500283 for (int i = 0; i < 4; i++) {
Junxiao Shifadcde52022-02-28 00:38:45 +0000284 BOOST_CHECK_EQUAL(nodes[i]->getSeqNo(userPrefixes[1]).value_or(NOT_EXIST), 2);
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -0500285 }
286}
287
Davide Pesavento5b3cf762020-04-03 16:20:04 -0400288BOOST_AUTO_TEST_CASE(MultipleNodesSimultaneousPublish)
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -0500289{
290 for (int i = 0; i < 4; i++) {
291 addNode(i);
292 }
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -0500293 for (int i = 0; i < 3; i++) {
294 faces[i]->linkTo(*faces[i + 1]);
295 }
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -0500296 for (int i = 0; i < 4; i++) {
297 nodes[i]->publishName(userPrefixes[i]);
298 }
299
Junxiao Shifadcde52022-02-28 00:38:45 +0000300 advanceClocks(10_ms, 100);
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -0500301 for (int i = 0; i < 4; i++) {
302 for (int j = 0; j < 4; j++) {
Junxiao Shifadcde52022-02-28 00:38:45 +0000303 BOOST_CHECK_EQUAL(nodes[i]->getSeqNo(userPrefixes[j]).value_or(NOT_EXIST), 1);
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -0500304 }
305 }
306
307 for (int i = 0; i < 4; i++) {
308 nodes[i]->publishName(userPrefixes[i], 4);
309 }
310
Junxiao Shifadcde52022-02-28 00:38:45 +0000311 advanceClocks(10_ms, 100);
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -0500312 for (int i = 0; i < 4; i++) {
313 for (int j = 0; j < 4; j++) {
Junxiao Shifadcde52022-02-28 00:38:45 +0000314 BOOST_CHECK_EQUAL(nodes[i]->getSeqNo(userPrefixes[j]).value_or(NOT_EXIST), 4);
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -0500315 }
316 }
317}
318
319BOOST_AUTO_TEST_CASE(NetworkPartition)
320{
321 for (int i = 0; i < 4; i++) {
322 addNode(i);
323 }
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -0500324 for (int i = 0; i < 3; i++) {
325 faces[i]->linkTo(*faces[i + 1]);
326 }
327
328 nodes[0]->publishName(userPrefixes[0]);
Junxiao Shifadcde52022-02-28 00:38:45 +0000329 advanceClocks(10_ms, 100);
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -0500330 for (int i = 0; i < 4; i++) {
Junxiao Shifadcde52022-02-28 00:38:45 +0000331 BOOST_CHECK_EQUAL(nodes[i]->getSeqNo(userPrefixes[0]).value_or(NOT_EXIST), 1);
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -0500332 }
333
334 for (int i = 0; i < 3; i++) {
335 faces[i]->unlink();
336 }
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -0500337 faces[0]->linkTo(*faces[1]);
338 faces[2]->linkTo(*faces[3]);
339
340 nodes[0]->publishName(userPrefixes[0]);
Junxiao Shifadcde52022-02-28 00:38:45 +0000341 advanceClocks(10_ms, 100);
342 BOOST_CHECK_EQUAL(nodes[1]->getSeqNo(userPrefixes[0]).value_or(NOT_EXIST), 2);
343 BOOST_CHECK_EQUAL(nodes[2]->getSeqNo(userPrefixes[0]).value_or(NOT_EXIST), 1);
344 BOOST_CHECK_EQUAL(nodes[3]->getSeqNo(userPrefixes[0]).value_or(NOT_EXIST), 1);
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -0500345
346 nodes[1]->publishName(userPrefixes[1], 2);
Junxiao Shifadcde52022-02-28 00:38:45 +0000347 advanceClocks(10_ms, 100);
348 BOOST_CHECK_EQUAL(nodes[0]->getSeqNo(userPrefixes[1]).value_or(NOT_EXIST), 2);
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -0500349
350 nodes[2]->publishName(userPrefixes[2], 2);
Junxiao Shifadcde52022-02-28 00:38:45 +0000351 advanceClocks(10_ms, 100);
352 BOOST_CHECK_EQUAL(nodes[3]->getSeqNo(userPrefixes[2]).value_or(NOT_EXIST), 2);
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -0500353
354 nodes[3]->publishName(userPrefixes[3], 2);
Junxiao Shifadcde52022-02-28 00:38:45 +0000355 advanceClocks(10_ms, 100);
356 BOOST_CHECK_EQUAL(nodes[2]->getSeqNo(userPrefixes[3]).value_or(NOT_EXIST), 2);
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -0500357
Junxiao Shifadcde52022-02-28 00:38:45 +0000358 BOOST_CHECK_EQUAL(nodes[0]->getSeqNo(userPrefixes[3]).value_or(NOT_EXIST), NOT_EXIST);
359 BOOST_CHECK_EQUAL(nodes[1]->getSeqNo(userPrefixes[3]).value_or(NOT_EXIST), NOT_EXIST);
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -0500360
361 for (int i = 0; i < 3; i++) {
362 faces[i]->unlink();
363 }
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -0500364 for (int i = 0; i < 3; i++) {
365 faces[i]->linkTo(*faces[i + 1]);
366 }
367
Junxiao Shifadcde52022-02-28 00:38:45 +0000368 advanceClocks(10_ms, 100);
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -0500369 for (int i = 0; i < 4; i++) {
370 for (int j = 0; j < 4; j++) {
Junxiao Shifadcde52022-02-28 00:38:45 +0000371 BOOST_CHECK_EQUAL(nodes[i]->getSeqNo(userPrefixes[j]).value_or(NOT_EXIST), 2);
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -0500372 }
373 }
374}
375
376BOOST_AUTO_TEST_CASE(IBFOverflow)
377{
378 addNode(0);
379 addNode(1);
380
381 faces[0]->linkTo(*faces[1]);
Junxiao Shifadcde52022-02-28 00:38:45 +0000382 advanceClocks(10_ms);
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -0500383
384 // 50 > 40 (expected number of entries in IBF)
385 for (int i = 0; i < 50; i++) {
Junxiao Shifadcde52022-02-28 00:38:45 +0000386 nodes[0]->addUserNode(makeSubPrefix(0, i));
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -0500387 }
Junxiao Shifadcde52022-02-28 00:38:45 +0000388 batchUpdate(0, 0, 20, 1);
389 advanceClocks(10_ms, 100);
390 batchCheck(1, 0, 0, 20, 1);
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -0500391
Junxiao Shifadcde52022-02-28 00:38:45 +0000392 batchUpdate(0, 21, 49, 1);
393 advanceClocks(10_ms, 100);
394 batchCheck(1, 0, 21, 49, 1);
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -0500395}
396
397BOOST_AUTO_TEST_CASE(DiffIBFDecodeFailureSimple)
398{
Junxiao Shifadcde52022-02-28 00:38:45 +0000399 searchIbfDecodeFailures(46, 52, [this] (int totalUpdates) {
400 addNode(0);
401 addNode(1);
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -0500402
Junxiao Shifadcde52022-02-28 00:38:45 +0000403 faces[0]->linkTo(*faces[1]);
404 advanceClocks(10_ms);
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -0500405
Junxiao Shifadcde52022-02-28 00:38:45 +0000406 batchUpdate(0, 0, totalUpdates, 1);
407 advanceClocks(10_ms, 100);
408 batchCheck(1, 0, 0, totalUpdates, 1);
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -0500409
Junxiao Shifadcde52022-02-28 00:38:45 +0000410 BOOST_CHECK_EQUAL(nodes[0]->getSeqNo(userPrefixes[1]).value_or(NOT_EXIST), NOT_EXIST);
411 BOOST_CHECK_EQUAL(nodes[1]->getSeqNo(userPrefixes[0]).value_or(NOT_EXIST), NOT_EXIST);
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -0500412
Junxiao Shifadcde52022-02-28 00:38:45 +0000413 nodes[1]->publishName(userPrefixes[1]);
414 advanceClocks(10_ms, 100);
415 BOOST_CHECK_EQUAL(nodes[0]->getSeqNo(userPrefixes[1]).value_or(NOT_EXIST), 1);
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -0500416
Junxiao Shifadcde52022-02-28 00:38:45 +0000417 nodes[0]->publishName(userPrefixes[0]);
418 advanceClocks(10_ms, 100);
419 BOOST_CHECK_EQUAL(nodes[1]->getSeqNo(userPrefixes[0]).value_or(NOT_EXIST), 1);
420 });
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -0500421}
422
423BOOST_AUTO_TEST_CASE(DiffIBFDecodeFailureSimpleSegmentedRecovery)
424{
Junxiao Shifadcde52022-02-28 00:38:45 +0000425 searchIbfDecodeFailures(46, 52, [this] (int totalUpdates) {
426 addNode(0);
427 addNode(1);
428 faces[0]->linkTo(*faces[1]);
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -0500429
Junxiao Shifadcde52022-02-28 00:38:45 +0000430 advanceClocks(10_ms);
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -0500431
Junxiao Shifadcde52022-02-28 00:38:45 +0000432 batchUpdate(0, 0, totalUpdates, 1);
433 advanceClocks(10_ms, 100);
434 batchCheck(1, 0, 0, totalUpdates, 1);
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -0500435
Junxiao Shifadcde52022-02-28 00:38:45 +0000436 BOOST_CHECK_EQUAL(nodes[0]->getSeqNo(userPrefixes[1]).value_or(NOT_EXIST), NOT_EXIST);
437 BOOST_CHECK_EQUAL(nodes[1]->getSeqNo(userPrefixes[0]).value_or(NOT_EXIST), NOT_EXIST);
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -0500438
Junxiao Shifadcde52022-02-28 00:38:45 +0000439 nodes[1]->publishName(userPrefixes[1]);
440 advanceClocks(10_ms, 100);
441 BOOST_CHECK_EQUAL(nodes[0]->getSeqNo(userPrefixes[1]).value_or(NOT_EXIST), 1);
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -0500442
Junxiao Shifadcde52022-02-28 00:38:45 +0000443 nodes[0]->publishName(userPrefixes[0]);
444 advanceClocks(10_ms, 100);
445 BOOST_CHECK_EQUAL(nodes[1]->getSeqNo(userPrefixes[0]).value_or(NOT_EXIST), 1);
446 });
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -0500447}
448
449BOOST_AUTO_TEST_CASE(DiffIBFDecodeFailureMultipleNodes)
450{
Junxiao Shifadcde52022-02-28 00:38:45 +0000451 searchIbfDecodeFailures(46, 52, [this] (int totalUpdates) {
452 for (int i = 0; i < 4; i++) {
453 addNode(i);
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -0500454 }
Junxiao Shifadcde52022-02-28 00:38:45 +0000455 for (int i = 0; i < 3; i++) {
456 faces[i]->linkTo(*faces[i + 1]);
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -0500457 }
Junxiao Shifadcde52022-02-28 00:38:45 +0000458
459 batchUpdate(0, 0, totalUpdates, 1);
460 advanceClocks(10_ms, 100);
461 for (int i = 0; i < 4; i++) {
462 batchCheck(i, 0, 0, totalUpdates, 1);
463 }
464 });
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -0500465}
466
Ashlesh Gawande2e82df12018-12-08 21:42:29 -0600467BOOST_AUTO_TEST_CASE(DelayedSecondSegment)
468{
469 addNode(0);
470
Ashlesh Gawandee23b53b2020-02-16 13:47:38 -0800471 int i = 0;
Davide Pesaventodb789562020-12-19 23:01:08 -0500472 detail::State state;
Junxiao Shic5f5eb12023-08-11 08:05:23 +0000473 std::shared_ptr<ndn::Buffer> compressed;
Ashlesh Gawandee23b53b2020-02-16 13:47:38 -0800474 do {
Junxiao Shifadcde52022-02-28 00:38:45 +0000475 auto prefixToPublish = makeSubPrefix(0, i++);
Ashlesh Gawande2e82df12018-12-08 21:42:29 -0600476 nodes[0]->addUserNode(prefixToPublish);
477 nodes[0]->publishName(prefixToPublish);
Ashlesh Gawandee23b53b2020-02-16 13:47:38 -0800478
Davide Pesavento5b3cf762020-04-03 16:20:04 -0400479 state.addContent(Name(prefixToPublish).appendNumber(nodes[0]->m_prefixes[prefixToPublish]));
Ashlesh Gawandee23b53b2020-02-16 13:47:38 -0800480
481 auto block = state.wireEncode();
Davide Pesaventof6fd2fb2022-03-18 21:00:36 -0400482 compressed = detail::compress(nodes[0]->m_contentCompression, block);
Junxiao Shic5f5eb12023-08-11 08:05:23 +0000483 } while (compressed->size() < (ndn::MAX_NDN_PACKET_SIZE >> 1));
Ashlesh Gawande2e82df12018-12-08 21:42:29 -0600484
Junxiao Shifadcde52022-02-28 00:38:45 +0000485 advanceClocks(10_ms, 100);
Ashlesh Gawande2e82df12018-12-08 21:42:29 -0600486
487 Name syncInterestName(syncPrefix);
Davide Pesaventodb789562020-12-19 23:01:08 -0500488 detail::IBLT iblt(40, nodes[0]->m_ibltCompression);
Ashlesh Gawande2e82df12018-12-08 21:42:29 -0600489 iblt.appendToName(syncInterestName);
490
Davide Pesavento03426ef2022-09-23 19:49:10 -0400491 nodes[0]->onSyncInterest(syncPrefix, Interest(syncInterestName));
Ashlesh Gawande2e82df12018-12-08 21:42:29 -0600492
Junxiao Shifadcde52022-02-28 00:38:45 +0000493 advanceClocks(10_ms);
Ashlesh Gawande2e82df12018-12-08 21:42:29 -0600494
495 BOOST_CHECK_EQUAL(nodes[0]->m_segmentPublisher.m_ims.size(), 2);
496 // Expire contents from segmentPublisher
Junxiao Shifadcde52022-02-28 00:38:45 +0000497 advanceClocks(10_ms, 100);
Ashlesh Gawande2e82df12018-12-08 21:42:29 -0600498 BOOST_CHECK_EQUAL(nodes[0]->m_segmentPublisher.m_ims.size(), 0);
499
500 // Get data name from face and increase segment number to form next interest
Davide Pesavento5b3cf762020-04-03 16:20:04 -0400501 BOOST_REQUIRE(!faces[0]->sentData.empty());
Ashlesh Gawande2e82df12018-12-08 21:42:29 -0600502 Name dataName = faces[0]->sentData.front().getName();
Ashlesh Gawanded51690a2019-11-11 22:51:06 -0600503 Name interestName = dataName.getSubName(0, dataName.size() - 2);
Ashlesh Gawande2e82df12018-12-08 21:42:29 -0600504 interestName.appendSegment(1);
505 faces[0]->sentData.clear();
506
Davide Pesavento03426ef2022-09-23 19:49:10 -0400507 nodes[0]->onSyncInterest(syncPrefix, Interest(interestName));
Junxiao Shifadcde52022-02-28 00:38:45 +0000508 advanceClocks(10_ms);
Ashlesh Gawande2e82df12018-12-08 21:42:29 -0600509
510 // Should have repopulated SegmentPublisher
511 BOOST_CHECK_EQUAL(nodes[0]->m_segmentPublisher.m_ims.size(), 2);
512 // Should have received the second data segment this time
Davide Pesavento5b3cf762020-04-03 16:20:04 -0400513 BOOST_REQUIRE(!faces[0]->sentData.empty());
514 BOOST_CHECK_EQUAL(faces[0]->sentData.front().getName().at(-1).toSegment(), 1);
Ashlesh Gawande2e82df12018-12-08 21:42:29 -0600515}
516
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -0500517BOOST_AUTO_TEST_SUITE_END()
518
Ashlesh Gawanded51690a2019-11-11 22:51:06 -0600519} // namespace psync