blob: 67f1c3e595648d347acbee757a05b49ad83c94d6 [file] [log] [blame]
Qiuhan Dingfb8c9e02015-01-30 14:04:55 -08001/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil -*- */
2/*
Davide Pesavento8663ed12022-07-23 03:04:27 -04003 * Copyright (c) 2012-2022 University of California, Los Angeles
Qiuhan Dingfb8c9e02015-01-30 14:04:55 -08004 *
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 "socket.hpp"
Ashlesh Gawande08784d42017-09-06 23:40:21 -050021
Davide Pesaventofae9def2019-01-29 14:34:33 -050022#include "tests/boost-test.hpp"
23#include "tests/unit-test-time-fixture.hpp"
Ashlesh Gawande08784d42017-09-06 23:40:21 -050024
25#include <ndn-cxx/util/dummy-client-face.hpp>
Qiuhan Dingfb8c9e02015-01-30 14:04:55 -080026
27namespace chronosync {
28namespace test {
29
30using std::string;
Qiuhan Dingfb8c9e02015-01-30 14:04:55 -080031using ndn::util::DummyClientFace;
Qiuhan Dingfb8c9e02015-01-30 14:04:55 -080032
Qiuhan Dingfb8c9e02015-01-30 14:04:55 -080033/**
34 * @brief Emulate an app that use the Socket class
35 *
36 * The app has two types of data set: one is simply string while the other is integer array.
37 * For each type of data set, the app has a specific fetching strategy.
38 */
39class SocketTestApp : noncopyable
40{
41public:
42 SocketTestApp(const Name& syncPrefix,
43 const Name& userPrefix,
44 DummyClientFace& face,
45 bool isNum)
46 : sum(0)
47 , socket(syncPrefix,
48 userPrefix,
49 face,
50 isNum ? bind(&SocketTestApp::fetchNumbers, this, _1) :
Davide Pesavento8663ed12022-07-23 03:04:27 -040051 bind(&SocketTestApp::fetchAll, this, _1),
Alexander Afanasyevbf5bc6c2018-02-19 11:26:09 -050052 Logic::DEFAULT_NAME,
53 Logic::DEFAULT_VALIDATOR,
54 Logic::DEFAULT_SYNC_INTEREST_LIFETIME,
55 name::Component::fromEscapedString("override"))
Qiuhan Dingfb8c9e02015-01-30 14:04:55 -080056 {
57 }
58
59 void
Ashlesh Gawande08784d42017-09-06 23:40:21 -050060 set(const Data& dataPacket)
Qiuhan Dingfb8c9e02015-01-30 14:04:55 -080061 {
62 // std::cerr << "set Data" << std::endl;
Ashlesh Gawande08784d42017-09-06 23:40:21 -050063 Name dataName(dataPacket.getName());
64 string str2(reinterpret_cast<const char*>(dataPacket.getContent().value()),
65 dataPacket.getContent().value_size());
Davide Pesavento8663ed12022-07-23 03:04:27 -040066 data.emplace(dataName, str2);
Qiuhan Dingfb8c9e02015-01-30 14:04:55 -080067 }
68
69 void
70 set(Name name, const char* buf, int len)
71 {
72 string str2(buf, len);
Davide Pesavento8663ed12022-07-23 03:04:27 -040073 data.emplace(name, str2);
Qiuhan Dingfb8c9e02015-01-30 14:04:55 -080074 }
75
76 void
Ashlesh Gawande08784d42017-09-06 23:40:21 -050077 setNum(const Data& dataPacket)
Qiuhan Dingfb8c9e02015-01-30 14:04:55 -080078 {
79 // std::cerr << "setNum Data" << std::endl;
Ashlesh Gawande08784d42017-09-06 23:40:21 -050080 size_t n = dataPacket.getContent().value_size() / 4;
81 const uint32_t* numbers = reinterpret_cast<const uint32_t*>(dataPacket.getContent().value());
Qiuhan Dingfb8c9e02015-01-30 14:04:55 -080082 for (size_t i = 0; i < n; i++) {
83 sum += numbers[i];
84 }
85 }
86
87 void
88 setNum(Name name, const uint8_t* buf, int len)
89 {
90 BOOST_ASSERT(len >= 4);
91
92 int n = len / 4;
93 const uint32_t* numbers = reinterpret_cast<const uint32_t*>(buf);
94 for (int i = 0; i < n; i++) {
95 sum += numbers[i];
96 }
97 }
98
99 void
Davide Pesaventofae9def2019-01-29 14:34:33 -0500100 fetchAll(const std::vector<MissingDataInfo>& v)
Qiuhan Dingfb8c9e02015-01-30 14:04:55 -0800101 {
102 // std::cerr << "fetchAll" << std::endl;
Yingdi Yu372697f2015-02-09 14:42:39 -0800103 for (size_t i = 0; i < v.size(); i++) {
Qiuhan Dingfb8c9e02015-01-30 14:04:55 -0800104 for(SeqNo s = v[i].low; s <= v[i].high; ++s) {
Ashlesh Gawande08784d42017-09-06 23:40:21 -0500105 socket.fetchData(v[i].session, s, [this] (const Data& dataPacket) {
Qiuhan Dingfb8c9e02015-01-30 14:04:55 -0800106 this->set(dataPacket);
107 });
108 }
109 }
110 }
111
112 void
Davide Pesaventofae9def2019-01-29 14:34:33 -0500113 fetchNumbers(const std::vector<MissingDataInfo>& v)
Qiuhan Dingfb8c9e02015-01-30 14:04:55 -0800114 {
115 // std::cerr << "fetchNumbers" << std::endl;
Yingdi Yu372697f2015-02-09 14:42:39 -0800116 for (size_t i = 0; i < v.size(); i++) {
Qiuhan Dingfb8c9e02015-01-30 14:04:55 -0800117 for(SeqNo s = v[i].low; s <= v[i].high; ++s) {
Ashlesh Gawande08784d42017-09-06 23:40:21 -0500118 socket.fetchData(v[i].session, s, [this] (const Data& dataPacket) {
Qiuhan Dingfb8c9e02015-01-30 14:04:55 -0800119 this->setNum(dataPacket);
120 });
121 }
122 }
123 }
124
125 string
126 toString()
127 {
128 string str = "\n";
Davide Pesaventofae9def2019-01-29 14:34:33 -0500129 for (auto it = data.begin(); it != data.end(); ++it) {
Qiuhan Dingfb8c9e02015-01-30 14:04:55 -0800130 str += "<";
131 str += it->first.toUri();
132 str += "|";
133 str += it->second;
134 str += ">";
135 str += "\n";
136 }
137
138 return str;
139 }
140
Junxiao Shi0c7f56a2016-07-14 15:27:14 +0000141public:
Davide Pesavento8663ed12022-07-23 03:04:27 -0400142 std::map<Name, string> data;
Qiuhan Dingfb8c9e02015-01-30 14:04:55 -0800143 uint32_t sum;
144 Socket socket;
145};
146
147class SocketFixture : public ndn::tests::UnitTestTimeFixture
148{
149public:
150 SocketFixture()
151 : syncPrefix("/ndn/broadcast/sync")
152 {
153 syncPrefix.appendVersion();
154 userPrefix[0] = Name("/user0");
155 userPrefix[1] = Name("/user1");
156 userPrefix[2] = Name("/user2");
157
Junxiao Shi0c7f56a2016-07-14 15:27:14 +0000158 faces[0].reset(new DummyClientFace(io, {true, true}));
159 faces[1].reset(new DummyClientFace(io, {true, true}));
160 faces[2].reset(new DummyClientFace(io, {true, true}));
Qiuhan Dingfb8c9e02015-01-30 14:04:55 -0800161
162 for (int i = 0; i < 3; i++) {
163 readInterestOffset[i] = 0;
164 readDataOffset[i] = 0;
165 }
166 }
167
168 void
169 passPacket()
170 {
171 for (int i = 0; i < 3; i++)
172 checkFace(i);
173 }
174
175 void
176 checkFace(int sender)
177 {
178 while (faces[sender]->sentInterests.size() > readInterestOffset[sender]) {
179 for (int i = 0; i < 3; i++) {
180 if (sender != i)
181 faces[i]->receive(faces[sender]->sentInterests[readInterestOffset[sender]]);
182 }
183 readInterestOffset[sender]++;
184 }
Junxiao Shi0c7f56a2016-07-14 15:27:14 +0000185 while (faces[sender]->sentData.size() > readDataOffset[sender]) {
Qiuhan Dingfb8c9e02015-01-30 14:04:55 -0800186 for (int i = 0; i < 3; i++) {
187 if (sender != i)
Junxiao Shi0c7f56a2016-07-14 15:27:14 +0000188 faces[i]->receive(faces[sender]->sentData[readDataOffset[sender]]);
Qiuhan Dingfb8c9e02015-01-30 14:04:55 -0800189 }
190 readDataOffset[sender]++;
191 }
192 }
193
194 void
195 createSocket(size_t idx, bool isNum)
196 {
Davide Pesavento8663ed12022-07-23 03:04:27 -0400197 app[idx] = make_shared<SocketTestApp>(syncPrefix, userPrefix[idx], std::ref(*faces[idx]), isNum);
Qiuhan Dingfb8c9e02015-01-30 14:04:55 -0800198 sessionName[idx] = app[idx]->socket.getLogic().getSessionName();
199 }
200
201 void
202 publishAppData(size_t idx, const string& data)
203 {
204 app[idx]->socket.publishData(reinterpret_cast<const uint8_t*>(data.c_str()), data.size(),
205 ndn::time::milliseconds(1000));
206 }
207
208 void
Ashlesh Gawande8d1347a2017-04-03 19:10:28 -0500209 publishAppData(size_t idx, const string& data, SeqNo seqNo)
210 {
211 app[idx]->socket.publishData(reinterpret_cast<const uint8_t*>(data.c_str()), data.size(),
212 ndn::time::milliseconds(1000), seqNo);
213 }
214
215 void
Qiuhan Dingfb8c9e02015-01-30 14:04:55 -0800216 setAppData(size_t idx, SeqNo seqNo, const string& data)
217 {
218 Name dataName = sessionName[idx];
219 dataName.appendNumber(seqNo);
220 app[idx]->set(dataName, data.c_str(), data.size());
221 }
222
223 void
224 publishAppNum(size_t idx, const uint8_t* buf, size_t size)
225 {
226 app[idx]->socket.publishData(buf, size, ndn::time::milliseconds(1000));
227 }
228
229 void
230 setAppNum(size_t idx, SeqNo seqNo, const uint8_t* buf, size_t size)
231 {
232 Name dataName = sessionName[idx];
233 dataName.appendNumber(seqNo);
234 app[idx]->setNum(dataName, buf, size);
235 }
236
Junxiao Shi0c7f56a2016-07-14 15:27:14 +0000237public:
Qiuhan Dingfb8c9e02015-01-30 14:04:55 -0800238 Name syncPrefix;
239 Name userPrefix[3];
240 Name sessionName[3];
241
Junxiao Shi0c7f56a2016-07-14 15:27:14 +0000242 std::unique_ptr<DummyClientFace> faces[3];
Qiuhan Dingfb8c9e02015-01-30 14:04:55 -0800243 shared_ptr<SocketTestApp> app[3];
244
245 size_t readInterestOffset[3];
246 size_t readDataOffset[3];
247};
248
Qiuhan Dingfb8c9e02015-01-30 14:04:55 -0800249BOOST_FIXTURE_TEST_SUITE(SocketTests, SocketFixture)
250
251BOOST_AUTO_TEST_CASE(BasicData)
252{
253 createSocket(0, false);
254 advanceClocks(ndn::time::milliseconds(10), 5);
255 createSocket(1, false);
256 advanceClocks(ndn::time::milliseconds(10), 5);
257 createSocket(2, false);
258 advanceClocks(ndn::time::milliseconds(10), 5);
259
260 string data0 = "Very funny Scotty, now beam down my clothes";
261 publishAppData(0, data0);
262
263 for (int i = 0; i < 50; i++) {
264 advanceClocks(ndn::time::milliseconds(2), 10);
265 passPacket();
266 }
267 setAppData(0, 1, data0);
268
269 advanceClocks(ndn::time::milliseconds(10), 1);
270 BOOST_CHECK_EQUAL(app[0]->toString(), app[1]->toString());
271 BOOST_CHECK_EQUAL(app[0]->toString(), app[2]->toString());
272
273 string data1 = "Yes, give me that ketchup";
274 string data2 = "Don't look conspicuous, it draws fire";
275 publishAppData(0, data1);
276 advanceClocks(ndn::time::milliseconds(10), 1);
277 publishAppData(0, data2);
278
279 for (int i = 0; i < 50; i++) {
280 advanceClocks(ndn::time::milliseconds(2), 10);
281 passPacket();
282 }
283 setAppData(0, 2, data1);
284 advanceClocks(ndn::time::milliseconds(10), 1);
285 setAppData(0, 3, data2);
286
287 advanceClocks(ndn::time::milliseconds(10), 1);
288 BOOST_CHECK_EQUAL(app[0]->toString(), app[1]->toString());
289 BOOST_CHECK_EQUAL(app[0]->toString(), app[2]->toString());
290
291 string data3 = "You surf the Internet, I surf the real world";
292 string data4 = "I got a fortune cookie once that said 'You like Chinese food'";
293 string data5 = "Real men wear pink. Why? Because their wives make them";
294 publishAppData(2, data3);
295 advanceClocks(ndn::time::milliseconds(10), 2);
296 publishAppData(1, data4);
297 advanceClocks(ndn::time::milliseconds(10), 1);
298 publishAppData(1, data5);
299
300 for (int i = 0; i < 100; i++) {
301 advanceClocks(ndn::time::milliseconds(2), 10);
302 passPacket();
303 }
304 setAppData(2, 1, data3);
305 advanceClocks(ndn::time::milliseconds(10), 1);
306 setAppData(1, 1, data4);
307 advanceClocks(ndn::time::milliseconds(10), 1);
308 setAppData(1, 2, data5);
309
310 advanceClocks(ndn::time::milliseconds(10), 7);
311 BOOST_CHECK_EQUAL(app[0]->toString(), app[1]->toString());
312 BOOST_CHECK_EQUAL(app[0]->toString(), app[2]->toString());
313
314 string data6 = "Shakespeare says: 'Prose before hos.'";
315 string data7 = "Pick good people, talent never wears out";
316 publishAppData(0, data6);
317 publishAppData(1, data7);
318
319 for (int i = 0; i < 100; i++) {
320 advanceClocks(ndn::time::milliseconds(2), 10);
321 passPacket();
322 }
323 setAppData(0, 4, data6);
324 setAppData(1, 3, data7);
325
326 BOOST_CHECK_EQUAL(app[0]->toString(), app[1]->toString());
327 BOOST_CHECK_EQUAL(app[0]->toString(), app[2]->toString());
Alexander Afanasyevbf5bc6c2018-02-19 11:26:09 -0500328
329 BOOST_CHECK_EQUAL(sessionName[0], Name("/user0/override"));
330 BOOST_CHECK_EQUAL(sessionName[1], Name("/user1/override"));
Qiuhan Dingfb8c9e02015-01-30 14:04:55 -0800331}
332
333BOOST_AUTO_TEST_CASE(BasicNumber)
334{
335 createSocket(0, true);
336 advanceClocks(ndn::time::milliseconds(10), 5);
337 createSocket(1, true);
338 advanceClocks(ndn::time::milliseconds(10), 5);
339
340 uint32_t num1[5] = {0, 1, 2, 3, 4};
341 uint8_t* buf1 = reinterpret_cast<uint8_t*>(num1);
342 size_t size1 = sizeof(num1);
343 publishAppNum(0, buf1, size1);
344 advanceClocks(ndn::time::milliseconds(10), 5);
345 setAppNum(0, 0, buf1, size1);
346
347 for (int i = 0; i < 100; i++) {
348 advanceClocks(ndn::time::milliseconds(2), 10);
349 passPacket();
350 }
351 BOOST_CHECK_EQUAL(app[0]->sum, app[1]->sum);
352 BOOST_CHECK_EQUAL(app[1]->sum, 10);
353
354 uint32_t num2[5] = {9, 7, 2, 1, 1};
355 uint8_t* buf2 = reinterpret_cast<uint8_t*>(num2);
356 size_t size2 = sizeof(num2);
357 publishAppNum(1, buf2, size2);
358 setAppNum(1, 0, buf2, size2);
359
360 for (int i = 0; i < 50; i++) {
361 advanceClocks(ndn::time::milliseconds(2), 10);
362 passPacket();
363 }
364 BOOST_CHECK_EQUAL(app[0]->sum, app[1]->sum);
365 BOOST_CHECK_EQUAL(app[1]->sum, 30);
366}
367
Ashlesh Gawande8d1347a2017-04-03 19:10:28 -0500368BOOST_AUTO_TEST_CASE(BasicDataWithAppSeq)
369{
370 createSocket(0, false);
371 advanceClocks(ndn::time::milliseconds(10), 5);
372 createSocket(1, false);
373 advanceClocks(ndn::time::milliseconds(10), 5);
374 createSocket(2, false);
375 advanceClocks(ndn::time::milliseconds(10), 5);
376
377 string data0 = "Very funny Scotty, now beam down my clothes";
378 publishAppData(0, data0, 100);
379
380 for (int i = 0; i < 50; i++) {
381 advanceClocks(ndn::time::milliseconds(2), 10);
382 passPacket();
383 }
384 setAppData(0, 100, data0);
385
386 advanceClocks(ndn::time::milliseconds(10), 1);
387 BOOST_CHECK_EQUAL(app[0]->toString(), app[1]->toString());
388 BOOST_CHECK_EQUAL(app[0]->toString(), app[2]->toString());
389
390 string data1 = "Yes, give me that ketchup";
391 string data2 = "Don't look conspicuous, it draws fire";
392 publishAppData(0, data1, 200);
393 advanceClocks(ndn::time::milliseconds(10), 1);
394 publishAppData(0, data2, 300);
395
396 for (int i = 0; i < 50; i++) {
397 advanceClocks(ndn::time::milliseconds(2), 10);
398 passPacket();
399 }
400 setAppData(0, 200, data1);
401 advanceClocks(ndn::time::milliseconds(10), 1);
402 setAppData(0, 300, data2);
403
404 advanceClocks(ndn::time::milliseconds(10), 1);
405 BOOST_CHECK_EQUAL(app[0]->toString(), app[1]->toString());
406 BOOST_CHECK_EQUAL(app[0]->toString(), app[2]->toString());
407
408 string data3 = "You surf the Internet, I surf the real world";
409 string data4 = "I got a fortune cookie once that said 'You like Chinese food'";
410 string data5 = "Real men wear pink. Why? Because their wives make them";
411 publishAppData(2, data3, 100);
412 advanceClocks(ndn::time::milliseconds(10), 2);
413 publishAppData(1, data4, 100);
414 advanceClocks(ndn::time::milliseconds(10), 1);
415 publishAppData(1, data5, 200);
416
417 for (int i = 0; i < 100; i++) {
418 advanceClocks(ndn::time::milliseconds(2), 10);
419 passPacket();
420 }
421 setAppData(2, 100, data3);
422 advanceClocks(ndn::time::milliseconds(10), 1);
423 setAppData(1, 100, data4);
424 advanceClocks(ndn::time::milliseconds(10), 1);
425 setAppData(1, 200, data5);
426
427 advanceClocks(ndn::time::milliseconds(10), 7);
428 BOOST_CHECK_EQUAL(app[0]->toString(), app[1]->toString());
429 BOOST_CHECK_EQUAL(app[0]->toString(), app[2]->toString());
430
431 string data6 = "Shakespeare says: 'Prose before hos.'";
432 string data7 = "Pick good people, talent never wears out";
433 publishAppData(0, data6, 500);
434 publishAppData(1, data7, 300);
435
436 for (int i = 0; i < 100; i++) {
437 advanceClocks(ndn::time::milliseconds(2), 10);
438 passPacket();
439 }
440 setAppData(0, 500, data6);
441 setAppData(1, 300, data7);
442
443 BOOST_CHECK_EQUAL(app[0]->toString(), app[1]->toString());
444 BOOST_CHECK_EQUAL(app[0]->toString(), app[2]->toString());
445}
446
Qiuhan Dingfb8c9e02015-01-30 14:04:55 -0800447BOOST_AUTO_TEST_SUITE_END()
448
449} // namespace test
450} // namespace chronosync