blob: 84982a0507a9a9763f469a4ba57d78f3d4080626 [file] [log] [blame]
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
* Copyright (c) 2013-2014 Regents of the University of California.
*
* This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
*
* ndn-cxx library is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later version.
*
* ndn-cxx library 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 Lesser General Public License for more details.
*
* You should have received copies of the GNU General Public License and GNU Lesser
* General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
* <http://www.gnu.org/licenses/>.
*
* See AUTHORS.md for complete list of ndn-cxx authors and contributors.
*/
#include "face.hpp"
#include "util/scheduler.hpp"
#include "security/key-chain.hpp"
#include "boost-test.hpp"
#include "util/dummy-client-face.hpp"
namespace ndn {
namespace tests {
using ndn::util::DummyClientFace;
using ndn::util::makeDummyClientFace;
class FacesFixture
{
public:
FacesFixture(bool enableRegistrationReply = true)
: nData(0)
, nTimeouts(0)
, nInInterests(0)
, nInInterests2(0)
, nRegSuccesses(0)
, nRegFailures(0)
, nUnregSuccesses(0)
, nUnregFailures(0)
{
DummyClientFace::Options options { true, enableRegistrationReply };
this->face = makeDummyClientFace(io, options);
}
void
onData()
{
++nData;
}
void
onTimeout()
{
++nTimeouts;
}
void
onInterest(Face& face,
const Name&, const Interest&)
{
++nInInterests;
}
void
onInterest2(Face& face,
const Name&, const Interest&)
{
++nInInterests2;
}
void
onInterestRegex(Face& face,
const InterestFilter&, const Interest&)
{
++nInInterests;
}
void
onInterestRegexError(Face& face,
const Name&, const Interest&)
{
BOOST_FAIL("InterestFilter::Error should have been triggered");
}
void
onRegSucceeded()
{
++nRegSuccesses;
}
void
onRegFailed()
{
++nRegFailures;
}
void
onUnregSucceeded()
{
++nUnregSuccesses;
}
void
onUnregFailed()
{
++nUnregFailures;
}
shared_ptr<Data>
makeData(const Name& name)
{
shared_ptr<Data> data = make_shared<Data>("/Hello/World/!");
static KeyChain keyChain;
keyChain.signWithSha256(*data);
return data;
}
boost::asio::io_service io;
shared_ptr<DummyClientFace> face;
uint32_t nData;
uint32_t nTimeouts;
uint32_t nInInterests;
uint32_t nInInterests2;
uint32_t nRegSuccesses;
uint32_t nRegFailures;
uint32_t nUnregSuccesses;
uint32_t nUnregFailures;
};
class FacesNoRegistrationReplyFixture : public FacesFixture
{
public:
FacesNoRegistrationReplyFixture()
: FacesFixture(false)
{
}
};
BOOST_FIXTURE_TEST_SUITE(TestFaces, FacesFixture)
BOOST_AUTO_TEST_CASE(ExpressInterestData)
{
face->expressInterest(Interest("/Hello/World", time::milliseconds(50)),
bind(&FacesFixture::onData, this),
bind(&FacesFixture::onTimeout, this));
BOOST_REQUIRE_NO_THROW(face->processEvents(time::milliseconds(-100)));
face->receive(*makeData("/Hello/World/!"));
BOOST_REQUIRE_NO_THROW(face->processEvents(time::milliseconds(200)));
BOOST_CHECK_EQUAL(nData, 1);
BOOST_CHECK_EQUAL(nTimeouts, 0);
}
BOOST_AUTO_TEST_CASE(ExpressInterestTimeout)
{
face->expressInterest(Interest("/Hello/World", time::milliseconds(50)),
bind(&FacesFixture::onData, this),
bind(&FacesFixture::onTimeout, this));
BOOST_REQUIRE_NO_THROW(face->processEvents(time::milliseconds(200)));
BOOST_CHECK_EQUAL(nData, 0);
BOOST_CHECK_EQUAL(nTimeouts, 1);
}
BOOST_AUTO_TEST_CASE(SetFilter)
{
face->setInterestFilter("/Hello/World",
bind(&FacesFixture::onInterest, this, ref(*face), _1, _2),
RegisterPrefixSuccessCallback(),
bind(&FacesFixture::onRegFailed, this));
BOOST_REQUIRE_NO_THROW(face->processEvents(time::milliseconds(-100)));
face->receive(Interest("/Hello/World/!"));
BOOST_REQUIRE_NO_THROW(face->processEvents(time::milliseconds(-100)));
BOOST_CHECK_EQUAL(nRegFailures, 0);
BOOST_CHECK_EQUAL(nInInterests, 1);
}
BOOST_FIXTURE_TEST_CASE(SetFilterFail, FacesNoRegistrationReplyFixture)
{
// don't enable registration reply
face->setInterestFilter("/Hello/World",
bind(&FacesFixture::onInterest, this, ref(*face), _1, _2),
RegisterPrefixSuccessCallback(),
bind(&FacesFixture::onRegFailed, this));
BOOST_REQUIRE_NO_THROW(face->processEvents(time::milliseconds(11000)));
BOOST_CHECK_EQUAL(nRegFailures, 1);
}
BOOST_AUTO_TEST_CASE(SetUnsetInterestFilter)
{
const RegisteredPrefixId* regPrefixId =
face->setInterestFilter(InterestFilter("/Hello/World"),
bind(&FacesFixture::onInterest, this,
ref(*face), _1, _2),
RegisterPrefixSuccessCallback(),
bind(&FacesFixture::onRegFailed, this));
BOOST_REQUIRE_NO_THROW(face->processEvents(time::milliseconds(100)));
face->receive(Interest("/Hello/World/!"));
BOOST_CHECK_EQUAL(nInInterests, 1);
BOOST_REQUIRE_NO_THROW(face->processEvents(time::milliseconds(100)));
face->receive(Interest("/Hello/World/!"));
BOOST_CHECK_EQUAL(nInInterests, 2);
face->unsetInterestFilter(regPrefixId);
BOOST_REQUIRE_NO_THROW(face->processEvents(time::milliseconds(100)));
face->receive(Interest("/Hello/World/!"));
BOOST_CHECK_EQUAL(nInInterests, 2);
BOOST_CHECK_NO_THROW(face->unsetInterestFilter(static_cast<const RegisteredPrefixId*>(0)));
BOOST_REQUIRE_NO_THROW(face->processEvents(time::milliseconds(100)));
BOOST_CHECK_NO_THROW(face->unsetInterestFilter(static_cast<const InterestFilterId*>(0)));
BOOST_REQUIRE_NO_THROW(face->processEvents(time::milliseconds(100)));
}
BOOST_AUTO_TEST_CASE(RegisterUnregisterPrefix)
{
const RegisteredPrefixId* regPrefixId =
face->registerPrefix("/Hello/World",
bind(&FacesFixture::onRegSucceeded, this),
bind(&FacesFixture::onRegFailed, this));
BOOST_REQUIRE_NO_THROW(face->processEvents(time::milliseconds(100)));
BOOST_CHECK_EQUAL(nRegFailures, 0);
BOOST_CHECK_EQUAL(nRegSuccesses, 1);
face->unregisterPrefix(regPrefixId,
bind(&FacesFixture::onUnregSucceeded, this),
bind(&FacesFixture::onUnregFailed, this));
BOOST_REQUIRE_NO_THROW(face->processEvents(time::milliseconds(100)));
BOOST_CHECK_EQUAL(nUnregFailures, 0);
BOOST_CHECK_EQUAL(nUnregSuccesses, 1);
}
BOOST_AUTO_TEST_CASE(SeTwoSimilarFilters)
{
face->setInterestFilter("/Hello/World",
bind(&FacesFixture::onInterest, this, ref(*face), _1, _2),
RegisterPrefixSuccessCallback(),
bind(&FacesFixture::onRegFailed, this));
face->setInterestFilter("/Hello",
bind(&FacesFixture::onInterest2, this, ref(*face), _1, _2),
RegisterPrefixSuccessCallback(),
bind(&FacesFixture::onRegFailed, this));
BOOST_REQUIRE_NO_THROW(face->processEvents(time::milliseconds(-100)));
face->receive(Interest("/Hello/World/!"));
BOOST_REQUIRE_NO_THROW(face->processEvents(time::milliseconds(-100)));
BOOST_CHECK_EQUAL(nRegFailures, 0);
BOOST_CHECK_EQUAL(nInInterests, 1);
BOOST_CHECK_EQUAL(nInInterests2, 1);
}
BOOST_AUTO_TEST_CASE(SetTwoDifferentFilters)
{
face->setInterestFilter("/Hello/World",
bind(&FacesFixture::onInterest, this, ref(*face), _1, _2),
RegisterPrefixSuccessCallback(),
bind(&FacesFixture::onRegFailed, this));
face->setInterestFilter("/Los/Angeles/Lakers",
bind(&FacesFixture::onInterest2, this, ref(*face), _1, _2),
RegisterPrefixSuccessCallback(),
bind(&FacesFixture::onRegFailed, this));
BOOST_REQUIRE_NO_THROW(face->processEvents(time::milliseconds(-100)));
face->receive(Interest("/Hello/World/!"));
BOOST_REQUIRE_NO_THROW(face->processEvents(time::milliseconds(-100)));
BOOST_CHECK_EQUAL(nRegFailures, 0);
BOOST_CHECK_EQUAL(nInInterests, 1);
BOOST_CHECK_EQUAL(nInInterests2, 0);
}
BOOST_AUTO_TEST_CASE(SetRegexFilterError)
{
face->setInterestFilter(InterestFilter("/Hello/World", "<><b><c>?"),
bind(&FacesFixture::onInterestRegexError, this,
ref(*face), _1, _2),
RegisterPrefixSuccessCallback(),
bind(&FacesFixture::onRegFailed, this));
BOOST_REQUIRE_NO_THROW(face->processEvents(time::milliseconds(-100)));
BOOST_REQUIRE_THROW(face->receive(Interest("/Hello/World/XXX/b/c")), InterestFilter::Error);
}
BOOST_AUTO_TEST_CASE(SetRegexFilter)
{
face->setInterestFilter(InterestFilter("/Hello/World", "<><b><c>?"),
bind(&FacesFixture::onInterestRegex, this,
ref(*face), _1, _2),
RegisterPrefixSuccessCallback(),
bind(&FacesFixture::onRegFailed, this));
BOOST_REQUIRE_NO_THROW(face->processEvents(time::milliseconds(-100)));
face->receive(Interest("/Hello/World/a")); // shouldn't match
BOOST_CHECK_EQUAL(nInInterests, 0);
face->receive(Interest("/Hello/World/a/b")); // should match
BOOST_CHECK_EQUAL(nInInterests, 1);
face->receive(Interest("/Hello/World/a/b/c")); // should match
BOOST_CHECK_EQUAL(nInInterests, 2);
face->receive(Interest("/Hello/World/a/b/d")); // should not match
BOOST_CHECK_EQUAL(nInInterests, 2);
}
BOOST_AUTO_TEST_CASE(SetRegexFilterAndRegister)
{
face->setInterestFilter(InterestFilter("/Hello/World", "<><b><c>?"),
bind(&FacesFixture::onInterestRegex, this,
ref(*face), _1, _2));
face->registerPrefix("/Hello/World",
bind(&FacesFixture::onRegSucceeded, this),
bind(&FacesFixture::onRegFailed, this));
BOOST_REQUIRE_NO_THROW(face->processEvents(time::milliseconds(100)));
BOOST_CHECK_EQUAL(nRegFailures, 0);
BOOST_CHECK_EQUAL(nRegSuccesses, 1);
face->receive(Interest("/Hello/World/a")); // shouldn't match
BOOST_CHECK_EQUAL(nInInterests, 0);
face->receive(Interest("/Hello/World/a/b")); // should match
BOOST_CHECK_EQUAL(nInInterests, 1);
face->receive(Interest("/Hello/World/a/b/c")); // should match
BOOST_CHECK_EQUAL(nInInterests, 2);
face->receive(Interest("/Hello/World/a/b/d")); // should not match
BOOST_CHECK_EQUAL(nInInterests, 2);
}
BOOST_AUTO_TEST_CASE(ProcessEvents)
{
face->processEvents(time::milliseconds(-1)); // io_service::reset()/poll() inside
face->registerPrefix("/Hello/World",
bind(&FacesFixture::onRegSucceeded, this),
bind(&FacesFixture::onRegFailed, this));
// io_service::poll() without reset
face->getIoService().poll();
BOOST_CHECK_EQUAL(nRegFailures, 0);
BOOST_CHECK_EQUAL(nRegSuccesses, 0);
face->processEvents(time::milliseconds(-1)); // io_service::reset()/poll() inside
BOOST_CHECK_EQUAL(nRegFailures, 0);
BOOST_CHECK_EQUAL(nRegSuccesses, 1);
}
BOOST_AUTO_TEST_SUITE_END()
} // tests
} // namespace ndn