blob: b37276939b2a4072fdd51fd3baaafdbcb4e44bf7 [file] [log] [blame]
Junxiao Shi9b0d3e92014-02-15 12:27:12 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
Alexander Afanasyev319f2c82015-01-07 14:56:53 -08003 * 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.
Alexander Afanasyev9bcbc7c2014-04-06 19:37:37 -070010 *
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/>.
Junxiao Shic099ddb2014-12-25 20:53:20 -070024 */
Junxiao Shi9b0d3e92014-02-15 12:27:12 -070025
26#include "face/ndnlp-sequence-generator.hpp"
27#include "face/ndnlp-slicer.hpp"
Junxiao Shid6dcd2c2014-02-16 14:49:54 -070028#include "face/ndnlp-partial-message-store.hpp"
Junxiao Shi9b0d3e92014-02-15 12:27:12 -070029
Junxiao Shid9ee45c2014-02-27 15:38:11 -070030#include "tests/test-common.hpp"
Junxiao Shi9b0d3e92014-02-15 12:27:12 -070031
Davide Pesavento1bdef282014-04-08 20:59:50 +020032#include <boost/scoped_array.hpp>
33
Junxiao Shi9b0d3e92014-02-15 12:27:12 -070034namespace nfd {
Spyridon Mastorakisd0381c02015-02-19 10:29:41 -080035namespace ndnlp {
Junxiao Shid9ee45c2014-02-27 15:38:11 -070036namespace tests {
Junxiao Shi9b0d3e92014-02-15 12:27:12 -070037
Spyridon Mastorakisd0381c02015-02-19 10:29:41 -080038using namespace nfd::tests;
39
Junxiao Shid9ee45c2014-02-27 15:38:11 -070040BOOST_FIXTURE_TEST_SUITE(FaceNdnlp, BaseFixture)
Junxiao Shi9b0d3e92014-02-15 12:27:12 -070041
42BOOST_AUTO_TEST_CASE(SequenceBlock)
43{
44 ndnlp::SequenceBlock sb(0x8000, 2);
45 BOOST_CHECK_EQUAL(sb.count(), 2);
46 BOOST_CHECK_EQUAL(sb[0], 0x8000);
47 BOOST_CHECK_EQUAL(sb[1], 0x8001);
48 BOOST_CHECK_THROW(sb[2], std::out_of_range);
49}
50
51// sequence number can safely wrap around
52BOOST_AUTO_TEST_CASE(SequenceBlockWrap)
53{
54 ndnlp::SequenceBlock sb(std::numeric_limits<uint64_t>::max(), 2);
55 BOOST_CHECK_EQUAL(sb[0], std::numeric_limits<uint64_t>::max());
56 BOOST_CHECK_EQUAL(sb[1], std::numeric_limits<uint64_t>::min());
57 BOOST_CHECK_EQUAL(sb[1] - sb[0], 1);
58}
59
60BOOST_AUTO_TEST_CASE(SequenceGenerator)
61{
62 ndnlp::SequenceGenerator seqgen;
Junxiao Shidf3b4382014-02-23 11:28:21 -070063
Junxiao Shi9b0d3e92014-02-15 12:27:12 -070064 ndnlp::SequenceBlock sb1 = seqgen.nextBlock(2);
65 BOOST_CHECK_EQUAL(sb1.count(), 2);
66
67 ndnlp::SequenceBlock sb2 = seqgen.nextBlock(1);
68 BOOST_CHECK_NE(sb1[0], sb2[0]);
69 BOOST_CHECK_NE(sb1[1], sb2[0]);
70}
71
Junxiao Shia37405d2015-01-26 10:50:58 -070072// slice a Block to one fragment
Junxiao Shi9b0d3e92014-02-15 12:27:12 -070073BOOST_AUTO_TEST_CASE(Slice1)
74{
75 uint8_t blockValue[60];
76 memset(blockValue, 0xcc, sizeof(blockValue));
77 Block block = ndn::dataBlock(0x01, blockValue, sizeof(blockValue));
Junxiao Shidf3b4382014-02-23 11:28:21 -070078
Junxiao Shi9b0d3e92014-02-15 12:27:12 -070079 ndnlp::Slicer slicer(9000);
80 ndnlp::PacketArray pa = slicer.slice(block);
Junxiao Shidf3b4382014-02-23 11:28:21 -070081
Junxiao Shi9b0d3e92014-02-15 12:27:12 -070082 BOOST_REQUIRE_EQUAL(pa->size(), 1);
Junxiao Shidf3b4382014-02-23 11:28:21 -070083
Junxiao Shi9b0d3e92014-02-15 12:27:12 -070084 const Block& pkt = pa->at(0);
85 BOOST_CHECK_EQUAL(pkt.type(), static_cast<uint32_t>(tlv::NdnlpData));
86 pkt.parse();
Junxiao Shidf3b4382014-02-23 11:28:21 -070087
Junxiao Shi9b0d3e92014-02-15 12:27:12 -070088 const Block::element_container& elements = pkt.elements();
89 BOOST_REQUIRE_EQUAL(elements.size(), 2);
Junxiao Shidf3b4382014-02-23 11:28:21 -070090
Junxiao Shi9b0d3e92014-02-15 12:27:12 -070091 const Block& sequenceElement = elements[0];
92 BOOST_CHECK_EQUAL(sequenceElement.type(), static_cast<uint32_t>(tlv::NdnlpSequence));
93 BOOST_REQUIRE_EQUAL(sequenceElement.value_size(), sizeof(uint64_t));
Junxiao Shidf3b4382014-02-23 11:28:21 -070094
Junxiao Shi9b0d3e92014-02-15 12:27:12 -070095 const Block& payloadElement = elements[1];
96 BOOST_CHECK_EQUAL(payloadElement.type(), static_cast<uint32_t>(tlv::NdnlpPayload));
97 size_t payloadSize = payloadElement.value_size();
98 BOOST_CHECK_EQUAL(payloadSize, block.size());
Junxiao Shidf3b4382014-02-23 11:28:21 -070099
Junxiao Shi9b0d3e92014-02-15 12:27:12 -0700100 BOOST_CHECK_EQUAL_COLLECTIONS(payloadElement.value_begin(), payloadElement.value_end(),
101 block.begin(), block.end());
102}
103
Junxiao Shia37405d2015-01-26 10:50:58 -0700104// slice a Block to four fragments
Junxiao Shid6dcd2c2014-02-16 14:49:54 -0700105BOOST_AUTO_TEST_CASE(Slice4)
Junxiao Shi9b0d3e92014-02-15 12:27:12 -0700106{
107 uint8_t blockValue[5050];
108 memset(blockValue, 0xcc, sizeof(blockValue));
109 Block block = ndn::dataBlock(0x01, blockValue, sizeof(blockValue));
Junxiao Shidf3b4382014-02-23 11:28:21 -0700110
Junxiao Shi9b0d3e92014-02-15 12:27:12 -0700111 ndnlp::Slicer slicer(1500);
112 ndnlp::PacketArray pa = slicer.slice(block);
Junxiao Shidf3b4382014-02-23 11:28:21 -0700113
Junxiao Shi9b0d3e92014-02-15 12:27:12 -0700114 BOOST_REQUIRE_EQUAL(pa->size(), 4);
Junxiao Shidf3b4382014-02-23 11:28:21 -0700115
Junxiao Shi9b0d3e92014-02-15 12:27:12 -0700116 uint64_t seq0 = 0xdddd;
Junxiao Shidf3b4382014-02-23 11:28:21 -0700117
Junxiao Shi9b0d3e92014-02-15 12:27:12 -0700118 size_t totalPayloadSize = 0;
Junxiao Shidf3b4382014-02-23 11:28:21 -0700119
Junxiao Shi9b0d3e92014-02-15 12:27:12 -0700120 for (size_t i = 0; i < 4; ++i) {
121 const Block& pkt = pa->at(i);
122 BOOST_CHECK_EQUAL(pkt.type(), static_cast<uint32_t>(tlv::NdnlpData));
123 pkt.parse();
Junxiao Shidf3b4382014-02-23 11:28:21 -0700124
Junxiao Shi9b0d3e92014-02-15 12:27:12 -0700125 const Block::element_container& elements = pkt.elements();
126 BOOST_REQUIRE_EQUAL(elements.size(), 4);
Junxiao Shidf3b4382014-02-23 11:28:21 -0700127
Junxiao Shi9b0d3e92014-02-15 12:27:12 -0700128 const Block& sequenceElement = elements[0];
129 BOOST_CHECK_EQUAL(sequenceElement.type(), static_cast<uint32_t>(tlv::NdnlpSequence));
130 BOOST_REQUIRE_EQUAL(sequenceElement.value_size(), sizeof(uint64_t));
131 uint64_t seq = be64toh(*reinterpret_cast<const uint64_t*>(
132 &*sequenceElement.value_begin()));
133 if (i == 0) {
134 seq0 = seq;
135 }
136 BOOST_CHECK_EQUAL(seq, seq0 + i);
Junxiao Shidf3b4382014-02-23 11:28:21 -0700137
Junxiao Shi9b0d3e92014-02-15 12:27:12 -0700138 const Block& fragIndexElement = elements[1];
139 BOOST_CHECK_EQUAL(fragIndexElement.type(), static_cast<uint32_t>(tlv::NdnlpFragIndex));
Junxiao Shidf3b4382014-02-23 11:28:21 -0700140 uint64_t fragIndex = ndn::readNonNegativeInteger(fragIndexElement);
Junxiao Shi9b0d3e92014-02-15 12:27:12 -0700141 BOOST_CHECK_EQUAL(fragIndex, i);
Junxiao Shidf3b4382014-02-23 11:28:21 -0700142
Junxiao Shi9b0d3e92014-02-15 12:27:12 -0700143 const Block& fragCountElement = elements[2];
144 BOOST_CHECK_EQUAL(fragCountElement.type(), static_cast<uint32_t>(tlv::NdnlpFragCount));
Junxiao Shidf3b4382014-02-23 11:28:21 -0700145 uint64_t fragCount = ndn::readNonNegativeInteger(fragCountElement);
Junxiao Shi9b0d3e92014-02-15 12:27:12 -0700146 BOOST_CHECK_EQUAL(fragCount, 4);
Junxiao Shidf3b4382014-02-23 11:28:21 -0700147
Junxiao Shi9b0d3e92014-02-15 12:27:12 -0700148 const Block& payloadElement = elements[3];
149 BOOST_CHECK_EQUAL(payloadElement.type(), static_cast<uint32_t>(tlv::NdnlpPayload));
150 size_t payloadSize = payloadElement.value_size();
151 totalPayloadSize += payloadSize;
152 }
Junxiao Shidf3b4382014-02-23 11:28:21 -0700153
Junxiao Shi9b0d3e92014-02-15 12:27:12 -0700154 BOOST_CHECK_EQUAL(totalPayloadSize, block.size());
155}
156
Junxiao Shia37405d2015-01-26 10:50:58 -0700157class ReassembleFixture : protected UnitTestTimeFixture
Junxiao Shid6dcd2c2014-02-16 14:49:54 -0700158{
159protected:
160 ReassembleFixture()
Junxiao Shia37405d2015-01-26 10:50:58 -0700161 : slicer(1500)
162 , pms(time::milliseconds(100))
Junxiao Shid6dcd2c2014-02-16 14:49:54 -0700163 {
Junxiao Shia37405d2015-01-26 10:50:58 -0700164 pms.onReceive.connect([this] (const Block& block) {
165 received.push_back(block);
Junxiao Shic099ddb2014-12-25 20:53:20 -0700166 });
Junxiao Shid6dcd2c2014-02-16 14:49:54 -0700167 }
168
169 Block
170 makeBlock(size_t valueLength)
171 {
Davide Pesavento1bdef282014-04-08 20:59:50 +0200172 boost::scoped_array<uint8_t> blockValue(new uint8_t[valueLength]);
173 memset(blockValue.get(), 0xcc, valueLength);
174 return ndn::dataBlock(0x01, blockValue.get(), valueLength);
Junxiao Shid6dcd2c2014-02-16 14:49:54 -0700175 }
Junxiao Shidf3b4382014-02-23 11:28:21 -0700176
Junxiao Shi083f7782015-02-21 12:06:26 -0700177 void
178 receiveNdnlpData(const Block& block)
179 {
180 bool isOk = false;
181 ndnlp::NdnlpData pkt;
182 std::tie(isOk, pkt) = ndnlp::NdnlpData::fromBlock(block);
183 BOOST_REQUIRE(isOk);
184 pms.receive(pkt);
185 }
186
Junxiao Shid6dcd2c2014-02-16 14:49:54 -0700187protected:
Junxiao Shia37405d2015-01-26 10:50:58 -0700188 ndnlp::Slicer slicer;
189 ndnlp::PartialMessageStore pms;
190
191 static const time::nanoseconds IDLE_DURATION;
Junxiao Shid6dcd2c2014-02-16 14:49:54 -0700192
193 // received network layer packets
Junxiao Shia37405d2015-01-26 10:50:58 -0700194 std::vector<Block> received;
Junxiao Shid6dcd2c2014-02-16 14:49:54 -0700195};
196
Junxiao Shia37405d2015-01-26 10:50:58 -0700197// reassemble one fragment into one Block
Junxiao Shid6dcd2c2014-02-16 14:49:54 -0700198BOOST_FIXTURE_TEST_CASE(Reassemble1, ReassembleFixture)
199{
200 Block block = makeBlock(60);
Junxiao Shia37405d2015-01-26 10:50:58 -0700201 ndnlp::PacketArray pa = slicer.slice(block);
Junxiao Shid6dcd2c2014-02-16 14:49:54 -0700202 BOOST_REQUIRE_EQUAL(pa->size(), 1);
Junxiao Shidf3b4382014-02-23 11:28:21 -0700203
Junxiao Shia37405d2015-01-26 10:50:58 -0700204 BOOST_CHECK_EQUAL(received.size(), 0);
Junxiao Shi083f7782015-02-21 12:06:26 -0700205 this->receiveNdnlpData(pa->at(0));
Junxiao Shidf3b4382014-02-23 11:28:21 -0700206
Junxiao Shia37405d2015-01-26 10:50:58 -0700207 BOOST_REQUIRE_EQUAL(received.size(), 1);
208 BOOST_CHECK_EQUAL_COLLECTIONS(received.at(0).begin(), received.at(0).end(),
209 block.begin(), block.end());
Junxiao Shid6dcd2c2014-02-16 14:49:54 -0700210}
211
Junxiao Shia37405d2015-01-26 10:50:58 -0700212// reassemble four and two fragments into two Blocks
Junxiao Shid6dcd2c2014-02-16 14:49:54 -0700213BOOST_FIXTURE_TEST_CASE(Reassemble4and2, ReassembleFixture)
214{
215 Block block = makeBlock(5050);
Junxiao Shia37405d2015-01-26 10:50:58 -0700216 ndnlp::PacketArray pa = slicer.slice(block);
Junxiao Shid6dcd2c2014-02-16 14:49:54 -0700217 BOOST_REQUIRE_EQUAL(pa->size(), 4);
Junxiao Shidf3b4382014-02-23 11:28:21 -0700218
Junxiao Shid6dcd2c2014-02-16 14:49:54 -0700219 Block block2 = makeBlock(2000);
Junxiao Shia37405d2015-01-26 10:50:58 -0700220 ndnlp::PacketArray pa2 = slicer.slice(block2);
Junxiao Shid6dcd2c2014-02-16 14:49:54 -0700221 BOOST_REQUIRE_EQUAL(pa2->size(), 2);
Junxiao Shidf3b4382014-02-23 11:28:21 -0700222
Junxiao Shia37405d2015-01-26 10:50:58 -0700223 BOOST_CHECK_EQUAL(received.size(), 0);
Junxiao Shi083f7782015-02-21 12:06:26 -0700224 this->receiveNdnlpData(pa->at(0));
Junxiao Shia37405d2015-01-26 10:50:58 -0700225 BOOST_CHECK_EQUAL(received.size(), 0);
226 this->advanceClocks(time::milliseconds(40));
Junxiao Shidf3b4382014-02-23 11:28:21 -0700227
Junxiao Shi083f7782015-02-21 12:06:26 -0700228 this->receiveNdnlpData(pa->at(1));
Junxiao Shia37405d2015-01-26 10:50:58 -0700229 BOOST_CHECK_EQUAL(received.size(), 0);
230 this->advanceClocks(time::milliseconds(40));
231
Junxiao Shi083f7782015-02-21 12:06:26 -0700232 this->receiveNdnlpData(pa2->at(1));
Junxiao Shia37405d2015-01-26 10:50:58 -0700233 BOOST_CHECK_EQUAL(received.size(), 0);
234 this->advanceClocks(time::milliseconds(40));
235
Junxiao Shi083f7782015-02-21 12:06:26 -0700236 this->receiveNdnlpData(pa->at(1));
Junxiao Shia37405d2015-01-26 10:50:58 -0700237 BOOST_CHECK_EQUAL(received.size(), 0);
238 this->advanceClocks(time::milliseconds(40));
239
Junxiao Shi083f7782015-02-21 12:06:26 -0700240 this->receiveNdnlpData(pa2->at(0));
Junxiao Shia37405d2015-01-26 10:50:58 -0700241 BOOST_CHECK_EQUAL(received.size(), 1);
242 this->advanceClocks(time::milliseconds(40));
243
Junxiao Shi083f7782015-02-21 12:06:26 -0700244 this->receiveNdnlpData(pa->at(3));
Junxiao Shia37405d2015-01-26 10:50:58 -0700245 BOOST_CHECK_EQUAL(received.size(), 1);
246 this->advanceClocks(time::milliseconds(40));
247
Junxiao Shi083f7782015-02-21 12:06:26 -0700248 this->receiveNdnlpData(pa->at(2));
Junxiao Shia37405d2015-01-26 10:50:58 -0700249
250 BOOST_REQUIRE_EQUAL(received.size(), 2);
251 BOOST_CHECK_EQUAL_COLLECTIONS(received.at(1).begin(), received.at(1).end(),
252 block.begin(), block.end());
253 BOOST_CHECK_EQUAL_COLLECTIONS(received.at(0).begin(), received.at(0).end(),
254 block2.begin(), block2.end());
255}
256
257// reassemble four fragments into one Block, but another two fragments are expired
258BOOST_FIXTURE_TEST_CASE(ReassembleTimeout, ReassembleFixture)
259{
260 Block block = makeBlock(5050);
261 ndnlp::PacketArray pa = slicer.slice(block);
262 BOOST_REQUIRE_EQUAL(pa->size(), 4);
263
264 Block block2 = makeBlock(2000);
265 ndnlp::PacketArray pa2 = slicer.slice(block2);
266 BOOST_REQUIRE_EQUAL(pa2->size(), 2);
267
268 BOOST_CHECK_EQUAL(received.size(), 0);
Junxiao Shi083f7782015-02-21 12:06:26 -0700269 this->receiveNdnlpData(pa->at(0));
Junxiao Shia37405d2015-01-26 10:50:58 -0700270 BOOST_CHECK_EQUAL(received.size(), 0);
271 this->advanceClocks(time::milliseconds(40));
272
Junxiao Shi083f7782015-02-21 12:06:26 -0700273 this->receiveNdnlpData(pa->at(1));
Junxiao Shia37405d2015-01-26 10:50:58 -0700274 BOOST_CHECK_EQUAL(received.size(), 0);
275 this->advanceClocks(time::milliseconds(40));
276
Junxiao Shi083f7782015-02-21 12:06:26 -0700277 this->receiveNdnlpData(pa2->at(1));
Junxiao Shia37405d2015-01-26 10:50:58 -0700278 BOOST_CHECK_EQUAL(received.size(), 0);
279 this->advanceClocks(time::milliseconds(40));
280
Junxiao Shi083f7782015-02-21 12:06:26 -0700281 this->receiveNdnlpData(pa->at(1));
Junxiao Shia37405d2015-01-26 10:50:58 -0700282 BOOST_CHECK_EQUAL(received.size(), 0);
283 this->advanceClocks(time::milliseconds(40));
284
Junxiao Shi083f7782015-02-21 12:06:26 -0700285 this->receiveNdnlpData(pa->at(3));
Junxiao Shia37405d2015-01-26 10:50:58 -0700286 BOOST_CHECK_EQUAL(received.size(), 0);
287 this->advanceClocks(time::milliseconds(40));
288
Junxiao Shi083f7782015-02-21 12:06:26 -0700289 this->receiveNdnlpData(pa->at(2));
Junxiao Shia37405d2015-01-26 10:50:58 -0700290 BOOST_CHECK_EQUAL(received.size(), 1);
291 this->advanceClocks(time::milliseconds(40));
292
Junxiao Shi083f7782015-02-21 12:06:26 -0700293 this->receiveNdnlpData(pa2->at(0)); // last fragment was received 160ms ago, expired
Junxiao Shia37405d2015-01-26 10:50:58 -0700294 BOOST_CHECK_EQUAL(received.size(), 1);
295 this->advanceClocks(time::milliseconds(40));
296
297 BOOST_REQUIRE_EQUAL(received.size(), 1);
298 BOOST_CHECK_EQUAL_COLLECTIONS(received.at(0).begin(), received.at(0).end(),
299 block.begin(), block.end());
Junxiao Shid6dcd2c2014-02-16 14:49:54 -0700300}
301
Junxiao Shi9b0d3e92014-02-15 12:27:12 -0700302BOOST_AUTO_TEST_SUITE_END()
303
Junxiao Shid9ee45c2014-02-27 15:38:11 -0700304} // namespace tests
Spyridon Mastorakisd0381c02015-02-19 10:29:41 -0800305} // namespace ndnlp
Junxiao Shi9b0d3e92014-02-15 12:27:12 -0700306} // namespace nfd