blob: 9913091de1716b35666dd8c2ba4b02c8a62322bf [file] [log] [blame]
Qiuhan Dingfb8c9e02015-01-30 14:04:55 -08001/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil -*- */
2/*
Davide Pesavento30c41ec2024-02-12 17:36:35 -05003 * Copyright (c) 2012-2024 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
Davide Pesavento30c41ec2024-02-12 17:36:35 -050027namespace chronosync::tests {
Qiuhan Dingfb8c9e02015-01-30 14:04:55 -080028
29using std::string;
Qiuhan Dingfb8c9e02015-01-30 14:04:55 -080030
Qiuhan Dingfb8c9e02015-01-30 14:04:55 -080031/**
32 * @brief Emulate an app that use the Socket class
33 *
34 * The app has two types of data set: one is simply string while the other is integer array.
35 * For each type of data set, the app has a specific fetching strategy.
36 */
37class SocketTestApp : noncopyable
38{
39public:
40 SocketTestApp(const Name& syncPrefix,
41 const Name& userPrefix,
Davide Pesavento48dbab62023-08-12 16:06:52 -040042 ndn::DummyClientFace& face,
Qiuhan Dingfb8c9e02015-01-30 14:04:55 -080043 bool isNum)
44 : sum(0)
45 , socket(syncPrefix,
46 userPrefix,
47 face,
48 isNum ? bind(&SocketTestApp::fetchNumbers, this, _1) :
Davide Pesavento8663ed12022-07-23 03:04:27 -040049 bind(&SocketTestApp::fetchAll, this, _1),
Alexander Afanasyevbf5bc6c2018-02-19 11:26:09 -050050 Logic::DEFAULT_NAME,
51 Logic::DEFAULT_VALIDATOR,
52 Logic::DEFAULT_SYNC_INTEREST_LIFETIME,
Davide Pesavento30c41ec2024-02-12 17:36:35 -050053 name::Component::fromUri("override"))
Qiuhan Dingfb8c9e02015-01-30 14:04:55 -080054 {
55 }
56
57 void
Ashlesh Gawande08784d42017-09-06 23:40:21 -050058 set(const Data& dataPacket)
Qiuhan Dingfb8c9e02015-01-30 14:04:55 -080059 {
60 // std::cerr << "set Data" << std::endl;
Ashlesh Gawande08784d42017-09-06 23:40:21 -050061 Name dataName(dataPacket.getName());
62 string str2(reinterpret_cast<const char*>(dataPacket.getContent().value()),
63 dataPacket.getContent().value_size());
Davide Pesavento8663ed12022-07-23 03:04:27 -040064 data.emplace(dataName, str2);
Qiuhan Dingfb8c9e02015-01-30 14:04:55 -080065 }
66
67 void
68 set(Name name, const char* buf, int len)
69 {
70 string str2(buf, len);
Davide Pesavento8663ed12022-07-23 03:04:27 -040071 data.emplace(name, str2);
Qiuhan Dingfb8c9e02015-01-30 14:04:55 -080072 }
73
74 void
Ashlesh Gawande08784d42017-09-06 23:40:21 -050075 setNum(const Data& dataPacket)
Qiuhan Dingfb8c9e02015-01-30 14:04:55 -080076 {
77 // std::cerr << "setNum Data" << std::endl;
Ashlesh Gawande08784d42017-09-06 23:40:21 -050078 size_t n = dataPacket.getContent().value_size() / 4;
79 const uint32_t* numbers = reinterpret_cast<const uint32_t*>(dataPacket.getContent().value());
Qiuhan Dingfb8c9e02015-01-30 14:04:55 -080080 for (size_t i = 0; i < n; i++) {
81 sum += numbers[i];
82 }
83 }
84
85 void
86 setNum(Name name, const uint8_t* buf, int len)
87 {
88 BOOST_ASSERT(len >= 4);
89
90 int n = len / 4;
91 const uint32_t* numbers = reinterpret_cast<const uint32_t*>(buf);
92 for (int i = 0; i < n; i++) {
93 sum += numbers[i];
94 }
95 }
96
97 void
Davide Pesaventofae9def2019-01-29 14:34:33 -050098 fetchAll(const std::vector<MissingDataInfo>& v)
Qiuhan Dingfb8c9e02015-01-30 14:04:55 -080099 {
100 // std::cerr << "fetchAll" << std::endl;
Yingdi Yu372697f2015-02-09 14:42:39 -0800101 for (size_t i = 0; i < v.size(); i++) {
Qiuhan Dingfb8c9e02015-01-30 14:04:55 -0800102 for(SeqNo s = v[i].low; s <= v[i].high; ++s) {
Ashlesh Gawande08784d42017-09-06 23:40:21 -0500103 socket.fetchData(v[i].session, s, [this] (const Data& dataPacket) {
Qiuhan Dingfb8c9e02015-01-30 14:04:55 -0800104 this->set(dataPacket);
105 });
106 }
107 }
108 }
109
110 void
Davide Pesaventofae9def2019-01-29 14:34:33 -0500111 fetchNumbers(const std::vector<MissingDataInfo>& v)
Qiuhan Dingfb8c9e02015-01-30 14:04:55 -0800112 {
113 // std::cerr << "fetchNumbers" << std::endl;
Yingdi Yu372697f2015-02-09 14:42:39 -0800114 for (size_t i = 0; i < v.size(); i++) {
Qiuhan Dingfb8c9e02015-01-30 14:04:55 -0800115 for(SeqNo s = v[i].low; s <= v[i].high; ++s) {
Ashlesh Gawande08784d42017-09-06 23:40:21 -0500116 socket.fetchData(v[i].session, s, [this] (const Data& dataPacket) {
Qiuhan Dingfb8c9e02015-01-30 14:04:55 -0800117 this->setNum(dataPacket);
118 });
119 }
120 }
121 }
122
123 string
124 toString()
125 {
126 string str = "\n";
Davide Pesaventofae9def2019-01-29 14:34:33 -0500127 for (auto it = data.begin(); it != data.end(); ++it) {
Qiuhan Dingfb8c9e02015-01-30 14:04:55 -0800128 str += "<";
129 str += it->first.toUri();
130 str += "|";
131 str += it->second;
132 str += ">";
133 str += "\n";
134 }
135
136 return str;
137 }
138
Junxiao Shi0c7f56a2016-07-14 15:27:14 +0000139public:
Davide Pesavento8663ed12022-07-23 03:04:27 -0400140 std::map<Name, string> data;
Qiuhan Dingfb8c9e02015-01-30 14:04:55 -0800141 uint32_t sum;
142 Socket socket;
143};
144
145class SocketFixture : public ndn::tests::UnitTestTimeFixture
146{
147public:
148 SocketFixture()
149 : syncPrefix("/ndn/broadcast/sync")
150 {
151 syncPrefix.appendVersion();
152 userPrefix[0] = Name("/user0");
153 userPrefix[1] = Name("/user1");
154 userPrefix[2] = Name("/user2");
155
Davide Pesavento48dbab62023-08-12 16:06:52 -0400156 faces[0].reset(new ndn::DummyClientFace(io, {true, true}));
157 faces[1].reset(new ndn::DummyClientFace(io, {true, true}));
158 faces[2].reset(new ndn::DummyClientFace(io, {true, true}));
Qiuhan Dingfb8c9e02015-01-30 14:04:55 -0800159
160 for (int i = 0; i < 3; i++) {
161 readInterestOffset[i] = 0;
162 readDataOffset[i] = 0;
163 }
164 }
165
166 void
167 passPacket()
168 {
169 for (int i = 0; i < 3; i++)
170 checkFace(i);
171 }
172
173 void
174 checkFace(int sender)
175 {
176 while (faces[sender]->sentInterests.size() > readInterestOffset[sender]) {
177 for (int i = 0; i < 3; i++) {
178 if (sender != i)
179 faces[i]->receive(faces[sender]->sentInterests[readInterestOffset[sender]]);
180 }
181 readInterestOffset[sender]++;
182 }
Junxiao Shi0c7f56a2016-07-14 15:27:14 +0000183 while (faces[sender]->sentData.size() > readDataOffset[sender]) {
Qiuhan Dingfb8c9e02015-01-30 14:04:55 -0800184 for (int i = 0; i < 3; i++) {
185 if (sender != i)
Junxiao Shi0c7f56a2016-07-14 15:27:14 +0000186 faces[i]->receive(faces[sender]->sentData[readDataOffset[sender]]);
Qiuhan Dingfb8c9e02015-01-30 14:04:55 -0800187 }
188 readDataOffset[sender]++;
189 }
190 }
191
192 void
193 createSocket(size_t idx, bool isNum)
194 {
Davide Pesavento8663ed12022-07-23 03:04:27 -0400195 app[idx] = make_shared<SocketTestApp>(syncPrefix, userPrefix[idx], std::ref(*faces[idx]), isNum);
Qiuhan Dingfb8c9e02015-01-30 14:04:55 -0800196 sessionName[idx] = app[idx]->socket.getLogic().getSessionName();
197 }
198
199 void
200 publishAppData(size_t idx, const string& data)
201 {
202 app[idx]->socket.publishData(reinterpret_cast<const uint8_t*>(data.c_str()), data.size(),
203 ndn::time::milliseconds(1000));
204 }
205
206 void
Ashlesh Gawande8d1347a2017-04-03 19:10:28 -0500207 publishAppData(size_t idx, const string& data, SeqNo seqNo)
208 {
209 app[idx]->socket.publishData(reinterpret_cast<const uint8_t*>(data.c_str()), data.size(),
210 ndn::time::milliseconds(1000), seqNo);
211 }
212
213 void
Qiuhan Dingfb8c9e02015-01-30 14:04:55 -0800214 setAppData(size_t idx, SeqNo seqNo, const string& data)
215 {
216 Name dataName = sessionName[idx];
217 dataName.appendNumber(seqNo);
218 app[idx]->set(dataName, data.c_str(), data.size());
219 }
220
221 void
222 publishAppNum(size_t idx, const uint8_t* buf, size_t size)
223 {
224 app[idx]->socket.publishData(buf, size, ndn::time::milliseconds(1000));
225 }
226
227 void
228 setAppNum(size_t idx, SeqNo seqNo, const uint8_t* buf, size_t size)
229 {
230 Name dataName = sessionName[idx];
231 dataName.appendNumber(seqNo);
232 app[idx]->setNum(dataName, buf, size);
233 }
234
Junxiao Shi0c7f56a2016-07-14 15:27:14 +0000235public:
Qiuhan Dingfb8c9e02015-01-30 14:04:55 -0800236 Name syncPrefix;
237 Name userPrefix[3];
238 Name sessionName[3];
239
Davide Pesavento48dbab62023-08-12 16:06:52 -0400240 std::unique_ptr<ndn::DummyClientFace> faces[3];
Qiuhan Dingfb8c9e02015-01-30 14:04:55 -0800241 shared_ptr<SocketTestApp> app[3];
242
243 size_t readInterestOffset[3];
244 size_t readDataOffset[3];
245};
246
Qiuhan Dingfb8c9e02015-01-30 14:04:55 -0800247BOOST_FIXTURE_TEST_SUITE(SocketTests, SocketFixture)
248
249BOOST_AUTO_TEST_CASE(BasicData)
250{
251 createSocket(0, false);
252 advanceClocks(ndn::time::milliseconds(10), 5);
253 createSocket(1, false);
254 advanceClocks(ndn::time::milliseconds(10), 5);
255 createSocket(2, false);
256 advanceClocks(ndn::time::milliseconds(10), 5);
257
258 string data0 = "Very funny Scotty, now beam down my clothes";
259 publishAppData(0, data0);
260
261 for (int i = 0; i < 50; i++) {
262 advanceClocks(ndn::time::milliseconds(2), 10);
263 passPacket();
264 }
265 setAppData(0, 1, data0);
266
267 advanceClocks(ndn::time::milliseconds(10), 1);
268 BOOST_CHECK_EQUAL(app[0]->toString(), app[1]->toString());
269 BOOST_CHECK_EQUAL(app[0]->toString(), app[2]->toString());
270
271 string data1 = "Yes, give me that ketchup";
272 string data2 = "Don't look conspicuous, it draws fire";
273 publishAppData(0, data1);
274 advanceClocks(ndn::time::milliseconds(10), 1);
275 publishAppData(0, data2);
276
277 for (int i = 0; i < 50; i++) {
278 advanceClocks(ndn::time::milliseconds(2), 10);
279 passPacket();
280 }
281 setAppData(0, 2, data1);
282 advanceClocks(ndn::time::milliseconds(10), 1);
283 setAppData(0, 3, data2);
284
285 advanceClocks(ndn::time::milliseconds(10), 1);
286 BOOST_CHECK_EQUAL(app[0]->toString(), app[1]->toString());
287 BOOST_CHECK_EQUAL(app[0]->toString(), app[2]->toString());
288
289 string data3 = "You surf the Internet, I surf the real world";
290 string data4 = "I got a fortune cookie once that said 'You like Chinese food'";
291 string data5 = "Real men wear pink. Why? Because their wives make them";
292 publishAppData(2, data3);
293 advanceClocks(ndn::time::milliseconds(10), 2);
294 publishAppData(1, data4);
295 advanceClocks(ndn::time::milliseconds(10), 1);
296 publishAppData(1, data5);
297
298 for (int i = 0; i < 100; i++) {
299 advanceClocks(ndn::time::milliseconds(2), 10);
300 passPacket();
301 }
302 setAppData(2, 1, data3);
303 advanceClocks(ndn::time::milliseconds(10), 1);
304 setAppData(1, 1, data4);
305 advanceClocks(ndn::time::milliseconds(10), 1);
306 setAppData(1, 2, data5);
307
308 advanceClocks(ndn::time::milliseconds(10), 7);
309 BOOST_CHECK_EQUAL(app[0]->toString(), app[1]->toString());
310 BOOST_CHECK_EQUAL(app[0]->toString(), app[2]->toString());
311
312 string data6 = "Shakespeare says: 'Prose before hos.'";
313 string data7 = "Pick good people, talent never wears out";
314 publishAppData(0, data6);
315 publishAppData(1, data7);
316
317 for (int i = 0; i < 100; i++) {
318 advanceClocks(ndn::time::milliseconds(2), 10);
319 passPacket();
320 }
321 setAppData(0, 4, data6);
322 setAppData(1, 3, data7);
323
324 BOOST_CHECK_EQUAL(app[0]->toString(), app[1]->toString());
325 BOOST_CHECK_EQUAL(app[0]->toString(), app[2]->toString());
Alexander Afanasyevbf5bc6c2018-02-19 11:26:09 -0500326
327 BOOST_CHECK_EQUAL(sessionName[0], Name("/user0/override"));
328 BOOST_CHECK_EQUAL(sessionName[1], Name("/user1/override"));
Qiuhan Dingfb8c9e02015-01-30 14:04:55 -0800329}
330
331BOOST_AUTO_TEST_CASE(BasicNumber)
332{
333 createSocket(0, true);
334 advanceClocks(ndn::time::milliseconds(10), 5);
335 createSocket(1, true);
336 advanceClocks(ndn::time::milliseconds(10), 5);
337
338 uint32_t num1[5] = {0, 1, 2, 3, 4};
339 uint8_t* buf1 = reinterpret_cast<uint8_t*>(num1);
340 size_t size1 = sizeof(num1);
341 publishAppNum(0, buf1, size1);
342 advanceClocks(ndn::time::milliseconds(10), 5);
343 setAppNum(0, 0, buf1, size1);
344
345 for (int i = 0; i < 100; i++) {
346 advanceClocks(ndn::time::milliseconds(2), 10);
347 passPacket();
348 }
349 BOOST_CHECK_EQUAL(app[0]->sum, app[1]->sum);
350 BOOST_CHECK_EQUAL(app[1]->sum, 10);
351
352 uint32_t num2[5] = {9, 7, 2, 1, 1};
353 uint8_t* buf2 = reinterpret_cast<uint8_t*>(num2);
354 size_t size2 = sizeof(num2);
355 publishAppNum(1, buf2, size2);
356 setAppNum(1, 0, buf2, size2);
357
358 for (int i = 0; i < 50; i++) {
359 advanceClocks(ndn::time::milliseconds(2), 10);
360 passPacket();
361 }
362 BOOST_CHECK_EQUAL(app[0]->sum, app[1]->sum);
363 BOOST_CHECK_EQUAL(app[1]->sum, 30);
364}
365
Ashlesh Gawande8d1347a2017-04-03 19:10:28 -0500366BOOST_AUTO_TEST_CASE(BasicDataWithAppSeq)
367{
368 createSocket(0, false);
369 advanceClocks(ndn::time::milliseconds(10), 5);
370 createSocket(1, false);
371 advanceClocks(ndn::time::milliseconds(10), 5);
372 createSocket(2, false);
373 advanceClocks(ndn::time::milliseconds(10), 5);
374
375 string data0 = "Very funny Scotty, now beam down my clothes";
376 publishAppData(0, data0, 100);
377
378 for (int i = 0; i < 50; i++) {
379 advanceClocks(ndn::time::milliseconds(2), 10);
380 passPacket();
381 }
382 setAppData(0, 100, data0);
383
384 advanceClocks(ndn::time::milliseconds(10), 1);
385 BOOST_CHECK_EQUAL(app[0]->toString(), app[1]->toString());
386 BOOST_CHECK_EQUAL(app[0]->toString(), app[2]->toString());
387
388 string data1 = "Yes, give me that ketchup";
389 string data2 = "Don't look conspicuous, it draws fire";
390 publishAppData(0, data1, 200);
391 advanceClocks(ndn::time::milliseconds(10), 1);
392 publishAppData(0, data2, 300);
393
394 for (int i = 0; i < 50; i++) {
395 advanceClocks(ndn::time::milliseconds(2), 10);
396 passPacket();
397 }
398 setAppData(0, 200, data1);
399 advanceClocks(ndn::time::milliseconds(10), 1);
400 setAppData(0, 300, data2);
401
402 advanceClocks(ndn::time::milliseconds(10), 1);
403 BOOST_CHECK_EQUAL(app[0]->toString(), app[1]->toString());
404 BOOST_CHECK_EQUAL(app[0]->toString(), app[2]->toString());
405
406 string data3 = "You surf the Internet, I surf the real world";
407 string data4 = "I got a fortune cookie once that said 'You like Chinese food'";
408 string data5 = "Real men wear pink. Why? Because their wives make them";
409 publishAppData(2, data3, 100);
410 advanceClocks(ndn::time::milliseconds(10), 2);
411 publishAppData(1, data4, 100);
412 advanceClocks(ndn::time::milliseconds(10), 1);
413 publishAppData(1, data5, 200);
414
415 for (int i = 0; i < 100; i++) {
416 advanceClocks(ndn::time::milliseconds(2), 10);
417 passPacket();
418 }
419 setAppData(2, 100, data3);
420 advanceClocks(ndn::time::milliseconds(10), 1);
421 setAppData(1, 100, data4);
422 advanceClocks(ndn::time::milliseconds(10), 1);
423 setAppData(1, 200, data5);
424
425 advanceClocks(ndn::time::milliseconds(10), 7);
426 BOOST_CHECK_EQUAL(app[0]->toString(), app[1]->toString());
427 BOOST_CHECK_EQUAL(app[0]->toString(), app[2]->toString());
428
429 string data6 = "Shakespeare says: 'Prose before hos.'";
430 string data7 = "Pick good people, talent never wears out";
431 publishAppData(0, data6, 500);
432 publishAppData(1, data7, 300);
433
434 for (int i = 0; i < 100; i++) {
435 advanceClocks(ndn::time::milliseconds(2), 10);
436 passPacket();
437 }
438 setAppData(0, 500, data6);
439 setAppData(1, 300, data7);
440
441 BOOST_CHECK_EQUAL(app[0]->toString(), app[1]->toString());
442 BOOST_CHECK_EQUAL(app[0]->toString(), app[2]->toString());
443}
444
Qiuhan Dingfb8c9e02015-01-30 14:04:55 -0800445BOOST_AUTO_TEST_SUITE_END()
446
Davide Pesavento30c41ec2024-02-12 17:36:35 -0500447} // namespace chronosync::tests