blob: 5b62d4e974d1ff03a4c8b02bff69f8e0ff4e4557 [file] [log] [blame]
Eric Newberry4c3e6b82015-11-10 16:48:42 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
3 * Copyright (c) 2014-2015, Regents of the University of California,
4 * Arizona Board of Regents,
5 * Colorado State University,
6 * University Pierre & Marie Curie, Sorbonne University,
7 * Washington University in St. Louis,
8 * Beijing Institute of Technology,
9 * The University of Memphis.
10 *
11 * This file is part of NFD (Named Data Networking Forwarding Daemon).
12 * See AUTHORS.md for complete list of NFD authors and contributors.
13 *
14 * NFD is free software: you can redistribute it and/or modify it under the terms
15 * of the GNU General Public License as published by the Free Software Foundation,
16 * either version 3 of the License, or (at your option) any later version.
17 *
18 * NFD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
19 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
20 * PURPOSE. See the GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License along with
23 * NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
24 */
25
26#include "face/lp-reassembler.hpp"
27
28#include "tests/test-common.hpp"
29
30namespace nfd {
31namespace face {
32namespace tests {
33
34using namespace nfd::tests;
35
36BOOST_AUTO_TEST_SUITE(Face)
37
38class LpReassemblerFixture : public UnitTestTimeFixture
39{
40public:
41 LpReassemblerFixture()
42 {
43 reassembler.beforeTimeout.connect(
44 [this] (Transport::EndpointId remoteEp, size_t nDroppedFragments) {
45 timeoutHistory.push_back(std::make_tuple(remoteEp, nDroppedFragments));
46 });
47 }
48
49public:
50 LpReassembler reassembler;
51 std::vector<std::tuple<Transport::EndpointId, size_t>> timeoutHistory;
52
53 static const uint8_t data[10];
54};
55
56const uint8_t LpReassemblerFixture::data[10] = {
57 0x06, 0x08, // Data
58 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
59};
60
61BOOST_FIXTURE_TEST_SUITE(TestLpReassembler, LpReassemblerFixture)
62
63BOOST_AUTO_TEST_SUITE(SingleFragment)
64
65BOOST_AUTO_TEST_CASE(Normal)
66{
67 ndn::Buffer dataBuffer(data, sizeof(data));
68
69 lp::Packet received;
70 received.add<lp::FragmentField>(std::make_pair(dataBuffer.begin(), dataBuffer.end()));
71 received.add<lp::FragIndexField>(0);
72 received.add<lp::FragCountField>(1);
73 received.add<lp::SequenceField>(1000);
74 received.add<lp::NextHopFaceIdField>(200);
75
76 bool isComplete = false;
77 Block netPacket;
78 lp::Packet packet;
79 std::tie(isComplete, netPacket, packet) = reassembler.receiveFragment(0, received);
80
81 BOOST_REQUIRE(isComplete);
82 BOOST_CHECK(packet.has<lp::NextHopFaceIdField>());
83 BOOST_CHECK_EQUAL_COLLECTIONS(data, data + sizeof(data), netPacket.begin(), netPacket.end());
84 BOOST_CHECK_EQUAL(reassembler.size(), 0);
85}
86
87BOOST_AUTO_TEST_CASE(OmitFragIndex)
88{
89 ndn::Buffer dataBuffer(data, sizeof(data));
90
91 lp::Packet received;
92 received.add<lp::FragmentField>(std::make_pair(dataBuffer.begin(), dataBuffer.end()));
93 received.add<lp::FragCountField>(1);
94 received.add<lp::SequenceField>(1000);
95 received.add<lp::NextHopFaceIdField>(200);
96
97 bool isComplete = false;
98 Block netPacket;
99 lp::Packet packet;
100 std::tie(isComplete, netPacket, packet) = reassembler.receiveFragment(0, received);
101
102 BOOST_REQUIRE(isComplete);
103 BOOST_CHECK(packet.has<lp::NextHopFaceIdField>());
104 BOOST_CHECK_EQUAL_COLLECTIONS(data, data + sizeof(data), netPacket.begin(), netPacket.end());
105}
106
107BOOST_AUTO_TEST_CASE(OmitFragCount)
108{
109 ndn::Buffer dataBuffer(data, sizeof(data));
110
111 lp::Packet received;
112 received.add<lp::FragmentField>(std::make_pair(dataBuffer.begin(), dataBuffer.end()));
113 received.add<lp::FragIndexField>(0);
114 received.add<lp::SequenceField>(1000);
115 received.add<lp::NextHopFaceIdField>(200);
116
117 bool isComplete = false;
118 Block netPacket;
119 lp::Packet packet;
120 std::tie(isComplete, netPacket, packet) = reassembler.receiveFragment(0, received);
121
122 BOOST_REQUIRE(isComplete);
123 BOOST_CHECK(packet.has<lp::NextHopFaceIdField>());
124 BOOST_CHECK_EQUAL_COLLECTIONS(data, data + sizeof(data), netPacket.begin(), netPacket.end());
125}
126
127BOOST_AUTO_TEST_CASE(OmitFragIndexAndFragCount)
128{
129 ndn::Buffer dataBuffer(data, sizeof(data));
130
131 lp::Packet received;
132 received.add<lp::FragmentField>(std::make_pair(dataBuffer.begin(), dataBuffer.end()));
133 received.add<lp::SequenceField>(1000);
134 received.add<lp::NextHopFaceIdField>(200);
135
136 bool isComplete = false;
137 Block netPacket;
138 lp::Packet packet;
139 std::tie(isComplete, netPacket, packet) = reassembler.receiveFragment(0, received);
140
141 BOOST_REQUIRE(isComplete);
142 BOOST_CHECK(packet.has<lp::NextHopFaceIdField>());
143 BOOST_CHECK_EQUAL_COLLECTIONS(data, data + sizeof(data), netPacket.begin(), netPacket.end());
144}
145
146BOOST_AUTO_TEST_SUITE_END() // SingleFragment
147
148BOOST_AUTO_TEST_SUITE(MultiFragment)
149
150BOOST_AUTO_TEST_CASE(Normal)
151{
152 ndn::Buffer data1Buffer(data, 4);
153 ndn::Buffer data2Buffer(data + 4, 4);
154 ndn::Buffer data3Buffer(data + 8, 2);
155
156 lp::Packet received1;
157 received1.add<lp::FragmentField>(std::make_pair(data1Buffer.begin(), data1Buffer.end()));
158 received1.add<lp::FragIndexField>(0);
159 received1.add<lp::FragCountField>(3);
160 received1.add<lp::SequenceField>(1000);
161 received1.add<lp::NextHopFaceIdField>(200);
162
163 lp::Packet received2;
164 received2.add<lp::FragmentField>(std::make_pair(data2Buffer.begin(), data2Buffer.end()));
165 received2.add<lp::FragIndexField>(1);
166 received2.add<lp::FragCountField>(3);
167 received2.add<lp::SequenceField>(1001);
168
169 lp::Packet received3;
170 received3.add<lp::FragmentField>(std::make_pair(data3Buffer.begin(), data3Buffer.end()));
171 received3.add<lp::FragIndexField>(2);
172 received3.add<lp::FragCountField>(3);
173 received3.add<lp::SequenceField>(1002);
174
175 bool isComplete = false;
176 Block netPacket;
177 lp::Packet packet;
178
179 std::tie(isComplete, std::ignore, std::ignore) = reassembler.receiveFragment(0, received1);
180 BOOST_REQUIRE(!isComplete);
181 BOOST_CHECK_EQUAL(reassembler.size(), 1);
182
183 std::tie(isComplete, std::ignore, std::ignore) = reassembler.receiveFragment(0, received2);
184 BOOST_REQUIRE(!isComplete);
185 BOOST_CHECK_EQUAL(reassembler.size(), 1);
186
187 std::tie(isComplete, netPacket, packet) = reassembler.receiveFragment(0, received3);
188 BOOST_REQUIRE(isComplete);
189 BOOST_CHECK(packet.has<lp::NextHopFaceIdField>());
190 BOOST_CHECK_EQUAL_COLLECTIONS(data, data + sizeof(data), netPacket.begin(), netPacket.end());
191 BOOST_CHECK_EQUAL(reassembler.size(), 0);
192}
193
194BOOST_AUTO_TEST_CASE(OmitFragIndex0)
195{
196 ndn::Buffer data1Buffer(data, 4);
197 ndn::Buffer data2Buffer(data + 4, 4);
198 ndn::Buffer data3Buffer(data + 8, 2);
199
200 lp::Packet received1;
201 received1.add<lp::FragmentField>(std::make_pair(data1Buffer.begin(), data1Buffer.end()));
202 received1.add<lp::FragCountField>(3);
203 received1.add<lp::SequenceField>(1000);
204 received1.add<lp::NextHopFaceIdField>(200);
205
206 lp::Packet received2;
207 received2.add<lp::FragmentField>(std::make_pair(data2Buffer.begin(), data2Buffer.end()));
208 received2.add<lp::FragIndexField>(1);
209 received2.add<lp::FragCountField>(3);
210 received2.add<lp::SequenceField>(1001);
211
212 lp::Packet received3;
213 received3.add<lp::FragmentField>(std::make_pair(data3Buffer.begin(), data3Buffer.end()));
214 received3.add<lp::FragIndexField>(2);
215 received3.add<lp::FragCountField>(3);
216 received3.add<lp::SequenceField>(1002);
217
218 bool isComplete = false;
219 Block netPacket;
220 lp::Packet packet;
221
222 std::tie(isComplete, std::ignore, std::ignore) = reassembler.receiveFragment(0, received1);
223 BOOST_REQUIRE(!isComplete);
224
225 std::tie(isComplete, std::ignore, std::ignore) = reassembler.receiveFragment(0, received2);
226 BOOST_REQUIRE(!isComplete);
227
228 std::tie(isComplete, netPacket, packet) = reassembler.receiveFragment(0, received3);
229 BOOST_REQUIRE(isComplete);
230 BOOST_CHECK(packet.has<lp::NextHopFaceIdField>());
231 BOOST_CHECK_EQUAL_COLLECTIONS(data, data + sizeof(data), netPacket.begin(), netPacket.end());
232}
233
234BOOST_AUTO_TEST_CASE(OutOfOrder)
235{
236 ndn::Buffer data0Buffer(data, 4);
237 ndn::Buffer data1Buffer(data + 4, 4);
238 ndn::Buffer data2Buffer(data + 8, 2);
239
240 lp::Packet frag0;
241 frag0.add<lp::FragmentField>(std::make_pair(data0Buffer.begin(), data0Buffer.end()));
242 frag0.add<lp::FragIndexField>(0);
243 frag0.add<lp::FragCountField>(3);
244 frag0.add<lp::SequenceField>(1000);
245 frag0.add<lp::NextHopFaceIdField>(200);
246
247 lp::Packet frag1;
248 frag1.add<lp::FragmentField>(std::make_pair(data1Buffer.begin(), data1Buffer.end()));
249 frag1.add<lp::FragIndexField>(1);
250 frag1.add<lp::FragCountField>(3);
251 frag1.add<lp::SequenceField>(1001);
252
253 lp::Packet frag2;
254 frag2.add<lp::FragmentField>(std::make_pair(data2Buffer.begin(), data2Buffer.end()));
255 frag2.add<lp::FragIndexField>(2);
256 frag2.add<lp::FragCountField>(3);
257 frag2.add<lp::SequenceField>(1002);
258
259 bool isComplete = false;
260
261 std::tie(isComplete, std::ignore, std::ignore) = reassembler.receiveFragment(0, frag2);
262 BOOST_REQUIRE(!isComplete);
263
264 std::tie(isComplete, std::ignore, std::ignore) = reassembler.receiveFragment(0, frag0);
265 BOOST_REQUIRE(!isComplete);
266
267 std::tie(isComplete, std::ignore, std::ignore) = reassembler.receiveFragment(0, frag1);
268 BOOST_REQUIRE(isComplete);
269}
270
271BOOST_AUTO_TEST_CASE(Duplicate)
272{
273 ndn::Buffer data0Buffer(data, 5);
274
275 lp::Packet frag0;
276 frag0.add<lp::FragmentField>(std::make_pair(data0Buffer.begin(), data0Buffer.end()));
277 frag0.add<lp::FragIndexField>(0);
278 frag0.add<lp::FragCountField>(2);
279 frag0.add<lp::SequenceField>(1000);
280
281 bool isComplete = false;
282
283 std::tie(isComplete, std::ignore, std::ignore) = reassembler.receiveFragment(0, frag0);
284 BOOST_REQUIRE(!isComplete);
285
286 std::tie(isComplete, std::ignore, std::ignore) = reassembler.receiveFragment(1, frag0);
287 BOOST_REQUIRE(!isComplete);
288}
289
290BOOST_AUTO_TEST_CASE(Timeout)
291{
292 ndn::Buffer data1Buffer(data, 5);
293 ndn::Buffer data2Buffer(data + 5, 5);
294
295 lp::Packet received1;
296 received1.add<lp::FragmentField>(std::make_pair(data1Buffer.begin(), data1Buffer.end()));
297 received1.add<lp::FragIndexField>(0);
298 received1.add<lp::FragCountField>(2);
299 received1.add<lp::SequenceField>(1000);
300 received1.add<lp::NextHopFaceIdField>(200);
301
302 lp::Packet received2;
303 received2.add<lp::FragmentField>(std::make_pair(data2Buffer.begin(), data2Buffer.end()));
304 received2.add<lp::FragIndexField>(1);
305 received2.add<lp::FragCountField>(2);
306 received2.add<lp::SequenceField>(1001);
307
308 const Transport::EndpointId REMOTE_EP = 11028;
309 bool isComplete = false;
310 std::tie(isComplete, std::ignore, std::ignore) = reassembler.receiveFragment(REMOTE_EP, received1);
311 BOOST_REQUIRE(!isComplete);
312 BOOST_CHECK_EQUAL(reassembler.size(), 1);
313 BOOST_CHECK(timeoutHistory.empty());
314
315 advanceClocks(time::milliseconds(1), 600);
316 BOOST_CHECK_EQUAL(reassembler.size(), 0);
317 BOOST_REQUIRE_EQUAL(timeoutHistory.size(), 1);
318 BOOST_CHECK_EQUAL(std::get<0>(timeoutHistory.back()), REMOTE_EP);
319 BOOST_CHECK_EQUAL(std::get<1>(timeoutHistory.back()), 1);
320
321 std::tie(isComplete, std::ignore, std::ignore) = reassembler.receiveFragment(REMOTE_EP, received2);
322 BOOST_REQUIRE(!isComplete);
323}
324
325BOOST_AUTO_TEST_CASE(MissingSequence)
326{
327 ndn::Buffer data1Buffer(data, 4);
328 ndn::Buffer data2Buffer(data + 4, 4);
329 ndn::Buffer data3Buffer(data + 8, 2);
330
331 lp::Packet received1;
332 received1.add<lp::FragmentField>(std::make_pair(data1Buffer.begin(), data1Buffer.end()));
333 received1.add<lp::FragIndexField>(0);
334 received1.add<lp::FragCountField>(3);
335 received1.add<lp::SequenceField>(1000);
336 received1.add<lp::NextHopFaceIdField>(200);
337
338 lp::Packet received2;
339 received2.add<lp::FragmentField>(std::make_pair(data2Buffer.begin(), data2Buffer.end()));
340 received2.add<lp::FragIndexField>(1);
341 received2.add<lp::FragCountField>(3);
342
343 lp::Packet received3;
344 received3.add<lp::FragmentField>(std::make_pair(data3Buffer.begin(), data3Buffer.end()));
345 received3.add<lp::FragIndexField>(2);
346 received3.add<lp::FragCountField>(3);
347 received3.add<lp::SequenceField>(1002);
348
349 bool isComplete = false;
350
351 std::tie(isComplete, std::ignore, std::ignore) = reassembler.receiveFragment(0, received1);
352 BOOST_REQUIRE(!isComplete);
353
354 std::tie(isComplete, std::ignore, std::ignore) = reassembler.receiveFragment(0, received2);
355 BOOST_REQUIRE(!isComplete);
356
357 std::tie(isComplete, std::ignore, std::ignore) = reassembler.receiveFragment(0, received3);
358 BOOST_REQUIRE(!isComplete);
359
360 advanceClocks(time::milliseconds(1), 600);
361
362 std::tie(isComplete, std::ignore, std::ignore) = reassembler.receiveFragment(0, received2);
363 BOOST_REQUIRE(!isComplete);
364}
365
366BOOST_AUTO_TEST_CASE(FragCountOverLimit)
367{
368 ndn::Buffer data1Buffer(data, sizeof(data));
369
370 lp::Packet received1;
371 received1.add<lp::FragmentField>(std::make_pair(data1Buffer.begin(), data1Buffer.end()));
372 received1.add<lp::FragIndexField>(0);
373 received1.add<lp::FragCountField>(256);
374 received1.add<lp::SequenceField>(1000);
375 received1.add<lp::NextHopFaceIdField>(200);
376
377 bool isComplete = false;
378
379 std::tie(isComplete, std::ignore, std::ignore) = reassembler.receiveFragment(0, received1);
380 BOOST_REQUIRE(!isComplete);
381}
382
383BOOST_AUTO_TEST_CASE(MissingFragCount)
384{
385 ndn::Buffer data1Buffer(data, 4);
386 ndn::Buffer data2Buffer(data + 4, 4);
387 ndn::Buffer data3Buffer(data + 8, 2);
388
389 lp::Packet received1;
390 received1.add<lp::FragmentField>(std::make_pair(data1Buffer.begin(), data1Buffer.end()));
391 received1.add<lp::FragIndexField>(0);
392 received1.add<lp::FragCountField>(3);
393 received1.add<lp::SequenceField>(1000);
394 received1.add<lp::NextHopFaceIdField>(200);
395
396 lp::Packet received2;
397 received2.add<lp::FragmentField>(std::make_pair(data2Buffer.begin(), data2Buffer.end()));
398 received2.add<lp::FragIndexField>(1);
399 received2.add<lp::FragCountField>(50);
400 received2.add<lp::SequenceField>(1001);
401
402 lp::Packet received3;
403 received3.add<lp::FragmentField>(std::make_pair(data3Buffer.begin(), data3Buffer.end()));
404 received3.add<lp::FragIndexField>(2);
405 received3.add<lp::FragCountField>(3);
406 received3.add<lp::SequenceField>(1002);
407
408 bool isComplete = false;
409
410 std::tie(isComplete, std::ignore, std::ignore) = reassembler.receiveFragment(0, received1);
411 BOOST_REQUIRE(!isComplete);
412
413 std::tie(isComplete, std::ignore, std::ignore) = reassembler.receiveFragment(0, received2);
414 BOOST_REQUIRE(!isComplete);
415
416 std::tie(isComplete, std::ignore, std::ignore) = reassembler.receiveFragment(0, received3);
417 BOOST_REQUIRE(!isComplete);
418}
419
420BOOST_AUTO_TEST_CASE(OverFragCount)
421{
422 LpReassembler::Options options;
423 options.nMaxFragments = 2;
424 reassembler.setOptions(options);
425
426 ndn::Buffer data1Buffer(data, 4);
427 ndn::Buffer data2Buffer(data + 4, 4);
428 ndn::Buffer data3Buffer(data + 8, 2);
429
430 lp::Packet received1;
431 received1.add<lp::FragmentField>(std::make_pair(data1Buffer.begin(), data1Buffer.end()));
432 received1.add<lp::FragIndexField>(0);
433 received1.add<lp::FragCountField>(3);
434 received1.add<lp::SequenceField>(1000);
435 received1.add<lp::NextHopFaceIdField>(200);
436
437 lp::Packet received2;
438 received2.add<lp::FragmentField>(std::make_pair(data2Buffer.begin(), data2Buffer.end()));
439 received2.add<lp::FragIndexField>(1);
440 received2.add<lp::FragCountField>(3);
441 received2.add<lp::SequenceField>(1001);
442
443 lp::Packet received3;
444 received3.add<lp::FragmentField>(std::make_pair(data3Buffer.begin(), data3Buffer.end()));
445 received3.add<lp::FragIndexField>(2);
446 received3.add<lp::FragCountField>(3);
447 received3.add<lp::SequenceField>(1002);
448
449 bool isComplete = false;
450
451 std::tie(isComplete, std::ignore, std::ignore) = reassembler.receiveFragment(0, received1);
452 BOOST_REQUIRE(!isComplete);
453
454 std::tie(isComplete, std::ignore, std::ignore) = reassembler.receiveFragment(0, received2);
455 BOOST_REQUIRE(!isComplete);
456
457 std::tie(isComplete, std::ignore, std::ignore) = reassembler.receiveFragment(0, received3);
458 BOOST_REQUIRE(!isComplete);
459}
460
461BOOST_AUTO_TEST_SUITE_END() // MultiFragment
462
463BOOST_AUTO_TEST_CASE(MultiRemoteEndpoints)
464{
465 ndn::Buffer data1Buffer(data, 5);
466 ndn::Buffer data2Buffer(data + 5, 5);
467
468 lp::Packet frag1_1;
469 frag1_1.add<lp::FragmentField>(std::make_pair(data1Buffer.begin(), data1Buffer.end()));
470 frag1_1.add<lp::FragIndexField>(0);
471 frag1_1.add<lp::FragCountField>(2);
472 frag1_1.add<lp::SequenceField>(2000);
473 frag1_1.add<lp::NextHopFaceIdField>(200);
474
475 lp::Packet frag1_2;
476 frag1_2.add<lp::FragmentField>(std::make_pair(data2Buffer.begin(), data2Buffer.end()));
477 frag1_2.add<lp::FragIndexField>(1);
478 frag1_2.add<lp::FragCountField>(2);
479 frag1_2.add<lp::SequenceField>(2001);
480
481 lp::Packet frag2_1;
482 frag2_1.add<lp::FragmentField>(std::make_pair(data1Buffer.begin(), data1Buffer.end()));
483 frag2_1.add<lp::FragIndexField>(0);
484 frag2_1.add<lp::FragCountField>(2);
485 frag2_1.add<lp::SequenceField>(2000);
486 frag2_1.add<lp::NextHopFaceIdField>(200);
487
488 lp::Packet frag2_2;
489 frag2_2.add<lp::FragmentField>(std::make_pair(data2Buffer.begin(), data2Buffer.end()));
490 frag2_2.add<lp::FragIndexField>(1);
491 frag2_2.add<lp::FragCountField>(2);
492 frag2_2.add<lp::SequenceField>(2001);
493
494 bool isComplete = false;
495
496 std::tie(isComplete, std::ignore, std::ignore) = reassembler.receiveFragment(1, frag1_1);
497 BOOST_REQUIRE(!isComplete);
498 BOOST_CHECK_EQUAL(reassembler.size(), 1);
499
500 std::tie(isComplete, std::ignore, std::ignore) = reassembler.receiveFragment(2, frag2_2);
501 BOOST_REQUIRE(!isComplete);
502 BOOST_CHECK_EQUAL(reassembler.size(), 2);
503
504 std::tie(isComplete, std::ignore, std::ignore) = reassembler.receiveFragment(1, frag1_2);
505 BOOST_REQUIRE(isComplete);
506 BOOST_CHECK_EQUAL(reassembler.size(), 1);
507
508 std::tie(isComplete, std::ignore, std::ignore) = reassembler.receiveFragment(2, frag2_1);
509 BOOST_REQUIRE(isComplete);
510 BOOST_CHECK_EQUAL(reassembler.size(), 0);
511}
512
513BOOST_AUTO_TEST_SUITE_END() // TestLpReassembler
514BOOST_AUTO_TEST_SUITE_END() // Face
515
516} // namespace tests
517} // namespace face
518} // namespace nfd