blob: db72bccf7930ba504c157a75bb6d3afd16bf0502 [file] [log] [blame]
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2020, 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/internal-face.hpp"
#include "transport-test-common.hpp"
#include "tests/key-chain-fixture.hpp"
#include "tests/daemon/global-io-fixture.hpp"
namespace nfd {
namespace face {
namespace tests {
using namespace nfd::tests;
BOOST_AUTO_TEST_SUITE(Face)
class InternalFaceFixture : public GlobalIoTimeFixture, public KeyChainFixture
{
public:
InternalFaceFixture()
{
std::tie(forwarderFace, clientFace) = makeInternalFace(m_keyChain);
forwarderFace->afterReceiveInterest.connect(
[this] (const Interest& interest, const EndpointId&) { receivedInterests.push_back(interest); } );
forwarderFace->afterReceiveData.connect(
[this] (const Data& data, const EndpointId&) { receivedData.push_back(data); } );
forwarderFace->afterReceiveNack.connect(
[this] (const lp::Nack& nack, const EndpointId&) { receivedNacks.push_back(nack); } );
}
protected:
shared_ptr<nfd::Face> forwarderFace;
shared_ptr<ndn::Face> clientFace;
std::vector<Interest> receivedInterests;
std::vector<Data> receivedData;
std::vector<lp::Nack> receivedNacks;
};
BOOST_FIXTURE_TEST_SUITE(TestInternalFace, InternalFaceFixture)
BOOST_AUTO_TEST_CASE(TransportStaticProperties)
{
Transport* transport = forwarderFace->getTransport();
checkStaticPropertiesInitialized(*transport);
BOOST_CHECK_EQUAL(transport->getLocalUri(), FaceUri("internal://"));
BOOST_CHECK_EQUAL(transport->getRemoteUri(), FaceUri("internal://"));
BOOST_CHECK_EQUAL(transport->getScope(), ndn::nfd::FACE_SCOPE_LOCAL);
BOOST_CHECK_EQUAL(transport->getPersistency(), ndn::nfd::FACE_PERSISTENCY_PERMANENT);
BOOST_CHECK_EQUAL(transport->getLinkType(), ndn::nfd::LINK_TYPE_POINT_TO_POINT);
BOOST_CHECK_EQUAL(transport->getMtu(), MTU_UNLIMITED);
}
// note: "send" and "receive" in test case names refer to the direction seen on forwarderFace.
// i.e. "send" means transmission from forwarder to client,
// "receive" means transmission from client to forwarder.
BOOST_AUTO_TEST_CASE(ReceiveInterestTimeout)
{
auto interest = makeInterest("/TLETccRv");
interest->setInterestLifetime(100_ms);
bool hasTimeout = false;
clientFace->expressInterest(*interest,
bind([] { BOOST_ERROR("unexpected Data"); }),
bind([] { BOOST_ERROR("unexpected Nack"); }),
bind([&hasTimeout] { hasTimeout = true; }));
this->advanceClocks(1_ms, 10);
BOOST_REQUIRE_EQUAL(receivedInterests.size(), 1);
BOOST_CHECK_EQUAL(receivedInterests.back().getName(), "/TLETccRv");
this->advanceClocks(1_ms, 100);
BOOST_CHECK(hasTimeout);
}
BOOST_AUTO_TEST_CASE(ReceiveInterestSendData)
{
auto interest = makeInterest("/PQstEJGdL", true);
bool hasReceivedData = false;
clientFace->expressInterest(*interest,
[&hasReceivedData] (const Interest&, const Data& data) {
hasReceivedData = true;
BOOST_CHECK_EQUAL(data.getName(), "/PQstEJGdL/aI7oCrDXNX");
},
bind([] { BOOST_ERROR("unexpected Nack"); }),
bind([] { BOOST_ERROR("unexpected timeout"); }));
this->advanceClocks(1_ms, 10);
BOOST_REQUIRE_EQUAL(receivedInterests.size(), 1);
BOOST_CHECK_EQUAL(receivedInterests.back().getName(), "/PQstEJGdL");
forwarderFace->sendData(*makeData("/PQstEJGdL/aI7oCrDXNX"));
this->advanceClocks(1_ms, 10);
BOOST_CHECK(hasReceivedData);
}
BOOST_AUTO_TEST_CASE(ReceiveInterestSendNack)
{
auto interest = makeInterest("/1HrsRM1X");
bool hasReceivedNack = false;
clientFace->expressInterest(*interest,
bind([] { BOOST_ERROR("unexpected Data"); }),
[&hasReceivedNack] (const Interest&, const lp::Nack& nack) {
hasReceivedNack = true;
BOOST_CHECK_EQUAL(nack.getReason(), lp::NackReason::NO_ROUTE);
},
bind([] { BOOST_ERROR("unexpected timeout"); }));
this->advanceClocks(1_ms, 10);
BOOST_REQUIRE_EQUAL(receivedInterests.size(), 1);
BOOST_CHECK_EQUAL(receivedInterests.back().getName(), "/1HrsRM1X");
forwarderFace->sendNack(makeNack(*interest, lp::NackReason::NO_ROUTE));
this->advanceClocks(1_ms, 10);
BOOST_CHECK(hasReceivedNack);
}
BOOST_AUTO_TEST_CASE(SendInterestReceiveData)
{
bool hasDeliveredInterest = false;
clientFace->setInterestFilter("/Wpc8TnEeoF",
[this, &hasDeliveredInterest] (const ndn::InterestFilter&, const Interest& interest) {
hasDeliveredInterest = true;
BOOST_CHECK_EQUAL(interest.getName(), "/Wpc8TnEeoF/f6SzV8hD");
clientFace->put(*makeData("/Wpc8TnEeoF/f6SzV8hD/3uytUJCuIi"));
});
forwarderFace->sendInterest(*makeInterest("/Wpc8TnEeoF/f6SzV8hD", true));
this->advanceClocks(1_ms, 10);
BOOST_CHECK(hasDeliveredInterest);
BOOST_REQUIRE_EQUAL(receivedData.size(), 1);
BOOST_CHECK_EQUAL(receivedData.back().getName(), "/Wpc8TnEeoF/f6SzV8hD/3uytUJCuIi");
}
BOOST_AUTO_TEST_CASE(SendInterestReceiveNack)
{
auto interest = makeInterest("/4YgJKWcXN/5oaTe05o");
bool hasDeliveredInterest = false;
clientFace->setInterestFilter("/4YgJKWcXN",
[this, &hasDeliveredInterest] (const ndn::InterestFilter&, const Interest& interest) {
hasDeliveredInterest = true;
BOOST_CHECK_EQUAL(interest.getName(), "/4YgJKWcXN/5oaTe05o");
clientFace->put(makeNack(interest, lp::NackReason::NO_ROUTE));
});
forwarderFace->sendInterest(*interest);
this->advanceClocks(1_ms, 10);
BOOST_CHECK(hasDeliveredInterest);
BOOST_REQUIRE_EQUAL(receivedNacks.size(), 1);
BOOST_CHECK_EQUAL(receivedNacks.back().getReason(), lp::NackReason::NO_ROUTE);
}
BOOST_AUTO_TEST_CASE(CloseForwarderFace)
{
forwarderFace->close();
this->advanceClocks(1_ms, 10);
BOOST_CHECK_EQUAL(forwarderFace->getState(), FaceState::CLOSED);
forwarderFace.reset();
auto interest = makeInterest("/zpHsVesu0B");
interest->setInterestLifetime(100_ms);
bool hasTimeout = false;
clientFace->expressInterest(*interest,
bind([] { BOOST_ERROR("unexpected Data"); }),
bind([] { BOOST_ERROR("unexpected Nack"); }),
bind([&hasTimeout] { hasTimeout = true; }));
BOOST_CHECK_NO_THROW(this->advanceClocks(1_ms, 200));
BOOST_CHECK_EQUAL(receivedInterests.size(), 0);
BOOST_CHECK(hasTimeout);
}
BOOST_AUTO_TEST_CASE(CloseClientFace)
{
g_io.poll(); // #3248 workaround
clientFace.reset();
forwarderFace->sendInterest(*makeInterest("/aau42XQqb"));
BOOST_CHECK_NO_THROW(this->advanceClocks(1_ms, 10));
}
BOOST_AUTO_TEST_SUITE_END() // TestInternalFace
BOOST_AUTO_TEST_SUITE_END() // Face
} // namespace tests
} // namespace face
} // namespace nfd