blob: 53a6f577f67bf9720451ce9ee9b6ebf8b8c323d0 [file] [log] [blame]
Qiuhan Dingfb8c9e02015-01-30 14:04:55 -08001/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil -*- */
2/*
3 * Copyright (c) 2012-2014 University of California, Los Angeles
4 *
5 * This file is part of ChronoSync, synchronization library for distributed realtime
6 * applications for NDN.
7 *
8 * ChronoSync is free software: you can redistribute it and/or modify it under the terms
9 * of the GNU General Public License as published by the Free Software Foundation, either
10 * version 3 of the License, or (at your option) any later version.
11 *
12 * ChronoSync 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
14 * PURPOSE. See the GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along with
17 * ChronoSync, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20#include "logic.hpp"
21#include "../unit-test-time-fixture.hpp"
22#include <ndn-cxx/util/dummy-client-face.hpp>
23#include "boost-test.hpp"
24
25namespace chronosync {
26namespace test {
27
28using std::vector;
29using ndn::util::DummyClientFace;
30using ndn::util::makeDummyClientFace;
31
32class Handler
33{
34public:
35 Handler(DummyClientFace& face,
36 const Name& syncPrefix,
37 const Name& userPrefix)
38 : logic(face,
39 syncPrefix,
40 userPrefix,
41 bind(&Handler::onUpdate, this, _1))
42 {
43 }
44
45 void
46 onUpdate(const vector<MissingDataInfo>& v)
47 {
48 for (size_t i = 0; i < v.size(); i++) {
49 update(v[i].session, v[i].high, v[i].low);
50 }
51 }
52
53 void
54 update(const Name& p, const SeqNo& high, const SeqNo& low)
55 {
56 map[p] = high;
57 }
58
59 void
60 updateSeqNo(const SeqNo& seqNo)
61 {
62 logic.updateSeqNo(seqNo);
63 }
64
65 Logic logic;
66 std::map<Name, SeqNo> map;
67};
68
69class LogicFixture : public ndn::tests::UnitTestTimeFixture
70{
71public:
72 LogicFixture()
73 : syncPrefix("/ndn/broadcast/sync")
74 {
75 syncPrefix.appendVersion();
76 userPrefix[0] = Name("/user0");
77 userPrefix[1] = Name("/user1");
78 userPrefix[2] = Name("/user2");
79
80 faces[0] = makeDummyClientFace(ref(io), {true, true});
81 faces[1] = makeDummyClientFace(ref(io), {true, true});
82 faces[2] = makeDummyClientFace(ref(io), {true, true});
83
84 for (int i = 0; i < 3; i++) {
85 readInterestOffset[i] = 0;
86 readDataOffset[i] = 0;
87 }
88 }
89
90 void
91 passPacket()
92 {
93 for (int i = 0; i < 3; i++)
94 checkFace(i);
95 }
96
97 void
98 checkFace(int sender)
99 {
100 while (faces[sender]->sentInterests.size() > readInterestOffset[sender]) {
101 for (int i = 0; i < 3; i++) {
102 if (sender != i)
103 faces[i]->receive(faces[sender]->sentInterests[readInterestOffset[sender]]);
104 }
105 readInterestOffset[sender]++;
106 }
107 while (faces[sender]->sentDatas.size() > readDataOffset[sender]) {
108 for (int i = 0; i < 3; i++) {
109 if (sender != i)
110 faces[i]->receive(faces[sender]->sentDatas[readDataOffset[sender]]);
111 }
112 readDataOffset[sender]++;
113 }
114 }
115
116 Name syncPrefix;
117 Name userPrefix[3];
118
119 shared_ptr<DummyClientFace> faces[3];
120 shared_ptr<Handler> handler[3];
121
122 size_t readInterestOffset[3];
123 size_t readDataOffset[3];
124};
125
126BOOST_FIXTURE_TEST_SUITE(LogicTests, LogicFixture)
127
128void
129onUpdate(const vector<MissingDataInfo>& v)
130{
131}
132
133BOOST_AUTO_TEST_CASE(Constructor)
134{
135 Name syncPrefix("/ndn/broadcast/sync");
136 Name userPrefix("/user");
137 shared_ptr<DummyClientFace> face = makeDummyClientFace(ref(io), {true, true});
138 BOOST_REQUIRE_NO_THROW(Logic(ref(*face), syncPrefix, userPrefix,
139 bind(onUpdate, _1)));
140}
141
142BOOST_AUTO_TEST_CASE(TwoBasic)
143{
144 handler[0] = make_shared<Handler>(ref(*faces[0]), syncPrefix, userPrefix[0]);
145 advanceClocks(ndn::time::milliseconds(10), 10);
146
147 handler[1] = make_shared<Handler>(ref(*faces[1]), syncPrefix, userPrefix[1]);
148 advanceClocks(ndn::time::milliseconds(10), 10);
149
150 handler[0]->updateSeqNo(1);
151
152 for (int i = 0; i < 50; i++) {
153 advanceClocks(ndn::time::milliseconds(2), 10);
154 passPacket();
155 }
156 BOOST_CHECK_EQUAL(handler[1]->map[handler[0]->logic.getSessionName()], 1);
157 advanceClocks(ndn::time::milliseconds(10), 10);
158
159 handler[0]->updateSeqNo(2);
160
161 for (int i = 0; i < 50; i++) {
162 advanceClocks(ndn::time::milliseconds(2), 10);
163 passPacket();
164 }
165 BOOST_CHECK_EQUAL(handler[1]->map[handler[0]->logic.getSessionName()], 2);
166 advanceClocks(ndn::time::milliseconds(10), 10);
167
168 handler[1]->updateSeqNo(2);
169
170 for (int i = 0; i < 50; i++) {
171 advanceClocks(ndn::time::milliseconds(2), 10);
172 passPacket();
173 }
174 BOOST_CHECK_EQUAL(handler[0]->map[handler[1]->logic.getSessionName()], 2);
175}
176
177BOOST_AUTO_TEST_CASE(ThreeBasic)
178{
179 handler[0] = make_shared<Handler>(ref(*faces[0]), syncPrefix, userPrefix[0]);
180 advanceClocks(ndn::time::milliseconds(10), 10);
181
182 handler[1] = make_shared<Handler>(ref(*faces[1]), syncPrefix, userPrefix[1]);
183 advanceClocks(ndn::time::milliseconds(10), 10);
184
185 handler[2] = make_shared<Handler>(ref(*faces[2]), syncPrefix, userPrefix[2]);
186 advanceClocks(ndn::time::milliseconds(10), 20);
187
188 handler[0]->updateSeqNo(1);
189
190 for (int i = 0; i < 70; i++) {
191 advanceClocks(ndn::time::milliseconds(2), 10);
192 passPacket();
193 }
194 BOOST_CHECK_EQUAL(handler[1]->map[handler[0]->logic.getSessionName()], 1);
195 BOOST_CHECK_EQUAL(handler[2]->map[handler[0]->logic.getSessionName()], 1);
196
197 handler[1]->updateSeqNo(2);
198
199 for (int i = 0; i < 50; i++) {
200 advanceClocks(ndn::time::milliseconds(2), 10);
201 passPacket();
202 }
203 BOOST_CHECK_EQUAL(handler[0]->map[handler[1]->logic.getSessionName()], 2);
204 BOOST_CHECK_EQUAL(handler[2]->map[handler[1]->logic.getSessionName()], 2);
205
206 handler[2]->updateSeqNo(4);
207
208 for (int i = 0; i < 100; i++) {
209 advanceClocks(ndn::time::milliseconds(2), 10);
210 passPacket();
211 }
212 BOOST_CHECK_EQUAL(handler[0]->map[handler[2]->logic.getSessionName()], 4);
213 BOOST_CHECK_EQUAL(handler[1]->map[handler[2]->logic.getSessionName()], 4);
214}
215
216BOOST_AUTO_TEST_CASE(ResetRecover)
217{
218 handler[0] = make_shared<Handler>(ref(*faces[0]), syncPrefix, userPrefix[0]);
219 advanceClocks(ndn::time::milliseconds(10), 10);
220
221 handler[1] = make_shared<Handler>(ref(*faces[1]), syncPrefix, userPrefix[1]);
222 advanceClocks(ndn::time::milliseconds(10), 30);
223
224 handler[0]->updateSeqNo(1);
225
226 for (int i = 0; i < 50; i++) {
227 advanceClocks(ndn::time::milliseconds(2), 10);
228 passPacket();
229 }
230 BOOST_CHECK_EQUAL(handler[1]->map[handler[0]->logic.getSessionName()], 1);
231
232 handler[1]->updateSeqNo(2);
233
234 for (int i = 0; i < 50; i++) {
235 advanceClocks(ndn::time::milliseconds(2), 10);
236 passPacket();
237 }
238 BOOST_CHECK_EQUAL(handler[0]->map[handler[1]->logic.getSessionName()], 2);
239
240 advanceClocks(ndn::time::milliseconds(10), 10);
241 handler[2] = make_shared<Handler>(ref(*faces[2]), syncPrefix, userPrefix[2]);
242
243 for (int i = 0; i < 50; i++) {
244 advanceClocks(ndn::time::milliseconds(2), 10);
245 passPacket();
246 }
247 BOOST_CHECK_EQUAL(handler[1]->map[handler[0]->logic.getSessionName()], 1);
248 BOOST_CHECK_EQUAL(handler[0]->map[handler[1]->logic.getSessionName()], 2);
249
250 handler[2]->updateSeqNo(4);
251
252 for (int i = 0; i < 50; i++) {
253 advanceClocks(ndn::time::milliseconds(2), 10);
254 passPacket();
255 }
256 BOOST_CHECK_EQUAL(handler[1]->map[handler[2]->logic.getSessionName()], 4);
257 BOOST_CHECK_EQUAL(handler[0]->map[handler[2]->logic.getSessionName()], 4);
258}
259
260BOOST_AUTO_TEST_CASE(RecoverConflict)
261{
262 handler[0] = make_shared<Handler>(ref(*faces[0]), syncPrefix, userPrefix[0]);
263 advanceClocks(ndn::time::milliseconds(10), 10);
264
265 handler[1] = make_shared<Handler>(ref(*faces[1]), syncPrefix, userPrefix[1]);
266 advanceClocks(ndn::time::milliseconds(10), 10);
267
268 handler[2] = make_shared<Handler>(ref(*faces[2]), syncPrefix, userPrefix[2]);
269 advanceClocks(ndn::time::milliseconds(10), 30);
270
271 handler[0]->updateSeqNo(1);
272
273 for (int i = 0; i < 50; i++) {
274 advanceClocks(ndn::time::milliseconds(2), 10);
275 passPacket();
276 }
277 BOOST_CHECK_EQUAL(handler[1]->map[handler[0]->logic.getSessionName()], 1);
278 BOOST_CHECK_EQUAL(handler[2]->map[handler[0]->logic.getSessionName()], 1);
279
280 handler[1]->updateSeqNo(2);
281 handler[2]->updateSeqNo(4);
282
283 for (int i = 0; i < 75; i++) {
284 advanceClocks(ndn::time::milliseconds(2), 10);
285 passPacket();
286 }
287 BOOST_CHECK_EQUAL(handler[0]->map[handler[1]->logic.getSessionName()], 2);
288 BOOST_CHECK_EQUAL(handler[0]->map[handler[2]->logic.getSessionName()], 4);
289 BOOST_CHECK_EQUAL(handler[1]->map[handler[2]->logic.getSessionName()], 4);
290 BOOST_CHECK_EQUAL(handler[2]->map[handler[1]->logic.getSessionName()], 2);
291}
292
293BOOST_AUTO_TEST_CASE(MultipleUserUnderOneLogic)
294{
295 handler[0] = make_shared<Handler>(ref(*faces[0]), syncPrefix, userPrefix[0]);
296 advanceClocks(ndn::time::milliseconds(10), 10);
297
298 handler[1] = make_shared<Handler>(ref(*faces[1]), syncPrefix, userPrefix[2]);
299 advanceClocks(ndn::time::milliseconds(10), 10);
300
301 handler[0]->logic.addUserNode(userPrefix[1]);
302
303 for (int i = 0; i < 20; i++) {
304 advanceClocks(ndn::time::milliseconds(2), 10);
305 passPacket();
306 }
307
308 handler[0]->updateSeqNo(1);
309
310 for (int i = 0; i < 50; i++) {
311 advanceClocks(ndn::time::milliseconds(2), 10);
312 passPacket();
313 }
314 BOOST_CHECK_EQUAL(handler[1]->map[handler[0]->logic.getSessionName()], 1);
315
316 handler[0]->logic.updateSeqNo(2, userPrefix[1]);
317
318 for (int i = 0; i < 50; i++) {
319 advanceClocks(ndn::time::milliseconds(2), 10);
320 passPacket();
321 }
322 BOOST_CHECK_EQUAL(handler[1]->map[handler[0]->logic.getSessionName(userPrefix[1])], 2);
323
324 handler[1]->updateSeqNo(4);
325
326 for (int i = 0; i < 50; i++) {
327 advanceClocks(ndn::time::milliseconds(2), 10);
328 passPacket();
329 }
330 BOOST_CHECK_EQUAL(handler[0]->map[handler[1]->logic.getSessionName()], 4);
331
332 handler[0]->logic.removeUserNode(userPrefix[0]);
333
334 for (int i = 0; i < 100; i++) {
335 advanceClocks(ndn::time::milliseconds(2), 10);
336 passPacket();
337 }
338 BOOST_CHECK_EQUAL(handler[1]->logic.getSessionNames().size(), 2);
339}
340
341BOOST_AUTO_TEST_SUITE_END()
342
343} // namespace test
344} // namespace chronosync