blob: aa2c7a79a587461e0d0377a9447445a5be926e8e [file] [log] [blame]
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
* Copyright (c) 2014-2015, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
* Washington University in St. Louis,
* Beijing Institute of Technology,
* The University of Memphis.
*
* This file is part of NFD (Named Data Networking Forwarding Daemon).
* See AUTHORS.md for complete list of NFD authors and contributors.
*
* NFD is free software: you can redistribute it and/or modify it under the terms
* of the GNU General Public License as published by the Free Software Foundation,
* either version 3 of the License, or (at your option) any later version.
*
* NFD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
*/
#include "face/generic-link-service.hpp"
#include "face/lp-face.hpp"
#include "dummy-transport.hpp"
#include "tests/test-common.hpp"
namespace nfd {
namespace face {
namespace tests {
using namespace nfd::tests;
BOOST_AUTO_TEST_SUITE(Face)
class GenericLinkServiceFixture : public BaseFixture
{
protected:
GenericLinkServiceFixture()
: service(nullptr)
, transport(nullptr)
{
this->initialize(GenericLinkService::Options());
// By default, GenericLinkService is created with default options.
// Test cases may invoke .initialize with alternate options.
}
void
initialize(const GenericLinkService::Options& options)
{
face.reset(new LpFace(make_unique<GenericLinkService>(options),
make_unique<DummyTransport>()));
service = static_cast<GenericLinkService*>(face->getLinkService());
transport = static_cast<DummyTransport*>(face->getTransport());
face->afterReceiveInterest.connect(
[this] (const Interest& interest) { receivedInterests.push_back(interest); });
face->afterReceiveData.connect(
[this] (const Data& data) { receivedData.push_back(data); });
face->afterReceiveNack.connect(
[this] (const lp::Nack& nack) { receivedNacks.push_back(nack); });
}
protected:
unique_ptr<LpFace> face;
GenericLinkService* service;
DummyTransport* transport;
std::vector<Interest> receivedInterests;
std::vector<Data> receivedData;
std::vector<lp::Nack> receivedNacks;
};
BOOST_FIXTURE_TEST_SUITE(TestGenericLinkService, GenericLinkServiceFixture)
BOOST_AUTO_TEST_SUITE(SimpleSendReceive) // send and receive without other fields
BOOST_AUTO_TEST_CASE(SendInterest)
{
// Initialize with Options that disables all services
GenericLinkService::Options options;
options.allowLocalFields = false;
initialize(options);
shared_ptr<Interest> interest1 = makeInterest("/localhost/test");
face->sendInterest(*interest1);
BOOST_REQUIRE_EQUAL(transport->sentPackets.size(), 1);
BOOST_CHECK(transport->sentPackets.back().packet == interest1->wireEncode());
}
BOOST_AUTO_TEST_CASE(SendData)
{
// Initialize with Options that disables all services
GenericLinkService::Options options;
options.allowLocalFields = false;
initialize(options);
shared_ptr<Data> data1 = makeData("/localhost/test");
face->sendData(*data1);
BOOST_REQUIRE_EQUAL(transport->sentPackets.size(), 1);
BOOST_CHECK(transport->sentPackets.back().packet == data1->wireEncode());
}
BOOST_AUTO_TEST_CASE(SendNack)
{
// Initialize with Options that disables all services
GenericLinkService::Options options;
options.allowLocalFields = false;
initialize(options);
lp::Nack nack1 = makeNack("/localhost/test", 323, lp::NackReason::NO_ROUTE);
face->sendNack(nack1);
BOOST_REQUIRE_EQUAL(transport->sentPackets.size(), 1);
lp::Packet nack1pkt;
BOOST_REQUIRE_NO_THROW(nack1pkt.wireDecode(transport->sentPackets.back().packet));
BOOST_CHECK_EQUAL(nack1pkt.has<lp::NackField>(), true);
BOOST_CHECK_EQUAL(nack1pkt.has<lp::FragmentField>(), true);
}
BOOST_AUTO_TEST_CASE(ReceiveBareInterest)
{
// Initialize with Options that disables all services
GenericLinkService::Options options;
options.allowLocalFields = false;
initialize(options);
shared_ptr<Interest> interest1 = makeInterest("/23Rd9hEiR");
transport->receivePacket(interest1->wireEncode());
BOOST_REQUIRE_EQUAL(receivedInterests.size(), 1);
BOOST_CHECK_EQUAL(receivedInterests.back(), *interest1);
}
BOOST_AUTO_TEST_CASE(ReceiveInterest)
{
// Initialize with Options that disables all services
GenericLinkService::Options options;
options.allowLocalFields = false;
initialize(options);
shared_ptr<Interest> interest1 = makeInterest("/23Rd9hEiR");
lp::Packet lpPacket;
lpPacket.set<lp::FragmentField>(std::make_pair(
interest1->wireEncode().begin(), interest1->wireEncode().end()));
lpPacket.set<lp::SequenceField>(0); // force LpPacket encoding
transport->receivePacket(lpPacket.wireEncode());
BOOST_REQUIRE_EQUAL(receivedInterests.size(), 1);
BOOST_CHECK_EQUAL(receivedInterests.back(), *interest1);
}
BOOST_AUTO_TEST_CASE(ReceiveBareData)
{
// Initialize with Options that disables all services
GenericLinkService::Options options;
options.allowLocalFields = false;
initialize(options);
shared_ptr<Data> data1 = makeData("/12345678");
transport->receivePacket(data1->wireEncode());
BOOST_REQUIRE_EQUAL(receivedData.size(), 1);
BOOST_CHECK_EQUAL(receivedData.back(), *data1);
}
BOOST_AUTO_TEST_CASE(ReceiveData)
{
// Initialize with Options that disables all services
GenericLinkService::Options options;
options.allowLocalFields = false;
initialize(options);
shared_ptr<Data> data1 = makeData("/12345689");
lp::Packet lpPacket;
lpPacket.set<lp::FragmentField>(std::make_pair(
data1->wireEncode().begin(), data1->wireEncode().end()));
lpPacket.set<lp::SequenceField>(0); // force LpPacket encoding
transport->receivePacket(lpPacket.wireEncode());
BOOST_REQUIRE_EQUAL(receivedData.size(), 1);
BOOST_CHECK_EQUAL(receivedData.back(), *data1);
}
BOOST_AUTO_TEST_CASE(ReceiveNack)
{
// Initialize with Options that disables all services
GenericLinkService::Options options;
options.allowLocalFields = false;
initialize(options);
lp::Nack nack1 = makeNack("/localhost/test", 323, lp::NackReason::NO_ROUTE);
lp::Packet lpPacket;
lpPacket.set<lp::FragmentField>(std::make_pair(
nack1.getInterest().wireEncode().begin(), nack1.getInterest().wireEncode().end()));
lpPacket.set<lp::NackField>(nack1.getHeader());
transport->receivePacket(lpPacket.wireEncode());
BOOST_REQUIRE_EQUAL(receivedNacks.size(), 1);
}
BOOST_AUTO_TEST_SUITE_END() // SimpleSendReceive
BOOST_AUTO_TEST_SUITE(Fragmentation)
BOOST_AUTO_TEST_CASE(ReassemblyDisabledDropFragIndex)
{
// TODO#3171 Initialize with Options that disables reassembly
shared_ptr<Interest> interest = makeInterest("/IgFe6NvH");
lp::Packet packet(interest->wireEncode());
packet.set<lp::FragIndexField>(140);
transport->receivePacket(packet.wireEncode());
BOOST_CHECK(receivedInterests.empty());
}
BOOST_AUTO_TEST_CASE(ReassemblyDisabledDropFragCount)
{
// TODO#3171 Initialize with Options that disables reassembly
shared_ptr<Interest> interest = makeInterest("/SeGmEjvIVX");
lp::Packet packet(interest->wireEncode());
packet.set<lp::FragCountField>(276);
transport->receivePacket(packet.wireEncode());
BOOST_CHECK(receivedInterests.empty());
}
BOOST_AUTO_TEST_SUITE_END() // Fragmentation
BOOST_AUTO_TEST_SUITE(LocalFields)
BOOST_AUTO_TEST_CASE(ReceiveNextHopFaceId)
{
// Initialize with Options that enables local fields
GenericLinkService::Options options;
options.allowLocalFields = true;
initialize(options);
shared_ptr<Interest> interest = makeInterest("/12345678");
lp::Packet packet(interest->wireEncode());
packet.set<lp::NextHopFaceIdField>(1000);
transport->receivePacket(packet.wireEncode());
BOOST_REQUIRE_EQUAL(receivedInterests.size(), 1);
BOOST_REQUIRE(receivedInterests.back().getLocalControlHeader().hasNextHopFaceId());
BOOST_CHECK_EQUAL(receivedInterests.back().getNextHopFaceId(), 1000);
}
BOOST_AUTO_TEST_CASE(ReceiveNextHopFaceIdDisabled)
{
// Initialize with Options that disables local fields
GenericLinkService::Options options;
options.allowLocalFields = false;
initialize(options);
shared_ptr<Interest> interest = makeInterest("/12345678");
lp::Packet packet(interest->wireEncode());
packet.set<lp::NextHopFaceIdField>(1000);
transport->receivePacket(packet.wireEncode());
BOOST_CHECK(receivedInterests.empty());
}
BOOST_AUTO_TEST_CASE(ReceiveNextHopFaceIdDropData)
{
// Initialize with Options that enables local fields
GenericLinkService::Options options;
options.allowLocalFields = true;
initialize(options);
shared_ptr<Data> data = makeData("/12345678");
lp::Packet packet(data->wireEncode());
packet.set<lp::NextHopFaceIdField>(1000);
transport->receivePacket(packet.wireEncode());
BOOST_CHECK(receivedData.empty());
}
BOOST_AUTO_TEST_CASE(ReceiveNextHopFaceIdDropNack)
{
// Initialize with Options that enables local fields
GenericLinkService::Options options;
options.allowLocalFields = true;
initialize(options);
lp::Nack nack = makeNack("/localhost/test", 123, lp::NackReason::NO_ROUTE);
lp::Packet packet;
packet.set<lp::FragmentField>(std::make_pair(
nack.getInterest().wireEncode().begin(), nack.getInterest().wireEncode().end()));
packet.set<lp::NackField>(nack.getHeader());
packet.set<lp::NextHopFaceIdField>(1000);
transport->receivePacket(packet.wireEncode());
BOOST_CHECK(receivedNacks.empty());
}
BOOST_AUTO_TEST_CASE(ReceiveCacheControl)
{
// Initialize with Options that enables local fields
GenericLinkService::Options options;
options.allowLocalFields = true;
initialize(options);
shared_ptr<Data> data = makeData("/12345678");
lp::Packet packet(data->wireEncode());
lp::CachePolicy policy;
policy.setPolicy(lp::CachePolicyType::NO_CACHE);
packet.set<lp::CachePolicyField>(policy);
transport->receivePacket(packet.wireEncode());
BOOST_REQUIRE_EQUAL(receivedData.size(), 1);
BOOST_REQUIRE(receivedData.back().getLocalControlHeader().hasCachingPolicy());
BOOST_CHECK_EQUAL(receivedData.back().getCachingPolicy(),
ndn::nfd::LocalControlHeader::CachingPolicy::NO_CACHE);
}
BOOST_AUTO_TEST_CASE(ReceiveCacheControlDisabled)
{
// Initialize with Options that disables local fields
GenericLinkService::Options options;
options.allowLocalFields = false;
initialize(options);
shared_ptr<Data> data = makeData("/12345678");
lp::Packet packet(data->wireEncode());
lp::CachePolicy policy;
policy.setPolicy(lp::CachePolicyType::NO_CACHE);
packet.set<lp::CachePolicyField>(policy);
transport->receivePacket(packet.wireEncode());
BOOST_REQUIRE_EQUAL(receivedData.size(), 1);
BOOST_CHECK(!receivedData.back().getLocalControlHeader().hasCachingPolicy());
}
BOOST_AUTO_TEST_CASE(ReceiveCacheControlDropInterest)
{
// Initialize with Options that enables local fields
GenericLinkService::Options options;
options.allowLocalFields = true;
initialize(options);
shared_ptr<Interest> interest = makeInterest("/12345678");
lp::Packet packet(interest->wireEncode());
lp::CachePolicy policy;
policy.setPolicy(lp::CachePolicyType::NO_CACHE);
packet.set<lp::CachePolicyField>(policy);
transport->receivePacket(packet.wireEncode());
BOOST_CHECK(receivedInterests.empty());
}
BOOST_AUTO_TEST_CASE(ReceiveCacheControlDropNack)
{
// Initialize with Options that enables local fields
GenericLinkService::Options options;
options.allowLocalFields = true;
initialize(options);
lp::Nack nack = makeNack("/localhost/test", 123, lp::NackReason::NO_ROUTE);
lp::Packet packet(nack.getInterest().wireEncode());
packet.set<lp::NackField>(nack.getHeader());
lp::CachePolicy policy;
policy.setPolicy(lp::CachePolicyType::NO_CACHE);
packet.set<lp::CachePolicyField>(policy);
transport->receivePacket(packet.wireEncode());
BOOST_CHECK(receivedNacks.empty());
}
BOOST_AUTO_TEST_CASE(SendIncomingFaceId)
{
// Initialize with Options that enables local fields
GenericLinkService::Options options;
options.allowLocalFields = true;
initialize(options);
shared_ptr<Interest> interest = makeInterest("/12345678");
interest->setIncomingFaceId(1000);
face->sendInterest(*interest);
BOOST_REQUIRE_EQUAL(transport->sentPackets.size(), 1);
lp::Packet sent(transport->sentPackets.back().packet);
BOOST_REQUIRE(sent.has<lp::IncomingFaceIdField>());
BOOST_CHECK_EQUAL(sent.get<lp::IncomingFaceIdField>(), 1000);
}
BOOST_AUTO_TEST_CASE(SendIncomingFaceIdDisabled)
{
// Initialize with Options that disables local fields
GenericLinkService::Options options;
options.allowLocalFields = false;
initialize(options);
shared_ptr<Interest> interest = makeInterest("/12345678");
interest->setIncomingFaceId(1000);
face->sendInterest(*interest);
BOOST_REQUIRE_EQUAL(transport->sentPackets.size(), 1);
lp::Packet sent(transport->sentPackets.back().packet);
BOOST_CHECK(!sent.has<lp::IncomingFaceIdField>());
}
BOOST_AUTO_TEST_CASE(ReceiveIncomingFaceIdIgnoreInterest)
{
// Initialize with Options that enables local fields
GenericLinkService::Options options;
options.allowLocalFields = true;
initialize(options);
shared_ptr<Interest> interest = makeInterest("/12345678");
lp::Packet packet(interest->wireEncode());
packet.set<lp::IncomingFaceIdField>(1000);
transport->receivePacket(packet.wireEncode());
BOOST_REQUIRE_EQUAL(receivedInterests.size(), 1);
BOOST_CHECK(!receivedInterests.back().getLocalControlHeader().hasIncomingFaceId());
}
BOOST_AUTO_TEST_CASE(ReceiveIncomingFaceIdIgnoreData)
{
// Initialize with Options that enables local fields
GenericLinkService::Options options;
options.allowLocalFields = true;
initialize(options);
shared_ptr<Data> data = makeData("/z1megUh9Bj");
lp::Packet packet(data->wireEncode());
packet.set<lp::IncomingFaceIdField>(1000);
transport->receivePacket(packet.wireEncode());
BOOST_REQUIRE_EQUAL(receivedData.size(), 1);
BOOST_CHECK(!receivedData.back().getLocalControlHeader().hasIncomingFaceId());
}
BOOST_AUTO_TEST_CASE(ReceiveIncomingFaceIdIgnoreNack)
{
// Initialize with Options that enables local fields
GenericLinkService::Options options;
options.allowLocalFields = true;
initialize(options);
lp::Nack nack = makeNack("/TPAhdiHz", 278, lp::NackReason::CONGESTION);
lp::Packet packet(nack.getInterest().wireEncode());
packet.set<lp::NackField>(nack.getHeader());
packet.set<lp::IncomingFaceIdField>(1000);
transport->receivePacket(packet.wireEncode());
BOOST_REQUIRE_EQUAL(receivedNacks.size(), 1);
BOOST_CHECK(!receivedNacks.back().getLocalControlHeader().hasIncomingFaceId());
}
BOOST_AUTO_TEST_SUITE_END() // LocalFields
BOOST_AUTO_TEST_SUITE_END() // TestGenericLinkService
BOOST_AUTO_TEST_SUITE_END() // Face
} // namespace tests
} // namespace face
} // namespace nfd