face: improve UdpChannel test suite
Change-Id: I90124bf6701639ea38154a6e3e62918dfbcfa6dd
Refs: #3371
diff --git a/tests/daemon/face/udp-channel.t.cpp b/tests/daemon/face/udp-channel.t.cpp
index 447ec0d..8fccab1 100644
--- a/tests/daemon/face/udp-channel.t.cpp
+++ b/tests/daemon/face/udp-channel.t.cpp
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
- * Copyright (c) 2014-2015, Regents of the University of California,
+ * Copyright (c) 2014-2016, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -24,21 +24,179 @@
*/
#include "face/udp-channel.hpp"
+#include "face/transport.hpp"
+#include "tests/limited-io.hpp"
#include "tests/test-common.hpp"
+#include <boost/mpl/vector.hpp>
+
namespace nfd {
namespace tests {
BOOST_AUTO_TEST_SUITE(Face)
-BOOST_FIXTURE_TEST_SUITE(TestUdpChannel, BaseFixture)
using nfd::Face;
+namespace ip = boost::asio::ip;
-// TODO add the equivalent of these test cases from udp.t.cpp as of commit:65caf200924b28748037750449e28bcb548dbc9c
-// MultipleAccepts
-// ManualClose
-// IdleClose
+typedef boost::mpl::vector<ip::address_v4,
+ ip::address_v6> AddressTypes;
+
+class UdpChannelFixture : public BaseFixture
+{
+protected:
+ UdpChannelFixture()
+ : nextPort(7050)
+ {
+ }
+
+ unique_ptr<UdpChannel>
+ makeChannel(const ip::address& addr, uint16_t port = 0)
+ {
+ if (port == 0)
+ port = nextPort++;
+
+ return make_unique<UdpChannel>(udp::Endpoint(addr, port), time::seconds(2));
+ }
+
+ void
+ listen(const ip::address& addr)
+ {
+ listenerEp = udp::Endpoint(addr, 7030);
+ listenerChannel = makeChannel(addr, 7030);
+ listenerChannel->listen(
+ [this] (const shared_ptr<Face>& newFace) {
+ BOOST_REQUIRE(newFace != nullptr);
+ connectFaceClosedSignal(*newFace, [this] { limitedIo.afterOp(); });
+ listenerFaces.push_back(newFace);
+ limitedIo.afterOp();
+ },
+ [] (const std::string& reason) {
+ BOOST_FAIL(reason);
+ });
+ }
+
+ void
+ connect(UdpChannel& channel)
+ {
+ g_io.post([&] {
+ channel.connect(listenerEp, ndn::nfd::FACE_PERSISTENCY_PERSISTENT,
+ [this] (const shared_ptr<Face>& newFace) {
+ BOOST_REQUIRE(newFace != nullptr);
+ connectFaceClosedSignal(*newFace, [this] { limitedIo.afterOp(); });
+ clientFaces.push_back(newFace);
+ face::Transport::Packet pkt(ndn::encoding::makeStringBlock(300, "hello"));
+ newFace->getTransport()->send(std::move(pkt));
+ limitedIo.afterOp();
+ },
+ [] (const std::string& reason) {
+ BOOST_FAIL(reason);
+ });
+ });
+ }
+
+protected:
+ LimitedIo limitedIo;
+ udp::Endpoint listenerEp;
+ unique_ptr<UdpChannel> listenerChannel;
+ std::vector<shared_ptr<Face>> listenerFaces;
+ std::vector<shared_ptr<Face>> clientFaces;
+
+private:
+ uint16_t nextPort;
+};
+
+BOOST_FIXTURE_TEST_SUITE(TestUdpChannel, UdpChannelFixture)
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(Uri, A, AddressTypes)
+{
+ udp::Endpoint ep(A::loopback(), 7050);
+ auto channel = makeChannel(ep.address(), ep.port());
+ BOOST_CHECK_EQUAL(channel->getUri(), FaceUri(ep));
+}
+
+BOOST_AUTO_TEST_CASE(Listen)
+{
+ auto channel = makeChannel(ip::address_v4());
+ BOOST_CHECK_EQUAL(channel->isListening(), false);
+
+ channel->listen(nullptr, nullptr);
+ BOOST_CHECK_EQUAL(channel->isListening(), true);
+
+ // listen() is idempotent
+ BOOST_CHECK_NO_THROW(channel->listen(nullptr, nullptr));
+ BOOST_CHECK_EQUAL(channel->isListening(), true);
+}
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(MultipleAccepts, A, AddressTypes)
+{
+ this->listen(A::loopback());
+
+ BOOST_CHECK_EQUAL(listenerChannel->isListening(), true);
+ BOOST_CHECK_EQUAL(listenerChannel->size(), 0);
+
+ auto ch1 = makeChannel(A());
+ this->connect(*ch1);
+
+ BOOST_CHECK(limitedIo.run(2, time::seconds(1)) == LimitedIo::EXCEED_OPS);
+
+ BOOST_CHECK_EQUAL(listenerChannel->size(), 1);
+ BOOST_CHECK_EQUAL(ch1->size(), 1);
+ BOOST_CHECK_EQUAL(ch1->isListening(), false);
+
+ auto ch2 = makeChannel(A());
+ auto ch3 = makeChannel(A());
+ this->connect(*ch2);
+ this->connect(*ch3);
+
+ BOOST_CHECK(limitedIo.run(4, time::seconds(1)) == LimitedIo::EXCEED_OPS);
+
+ BOOST_CHECK_EQUAL(listenerChannel->size(), 3);
+ BOOST_CHECK_EQUAL(ch1->size(), 1);
+ BOOST_CHECK_EQUAL(ch2->size(), 1);
+ BOOST_CHECK_EQUAL(ch3->size(), 1);
+ BOOST_CHECK_EQUAL(clientFaces.size(), 3);
+
+ // check face persistency
+ for (const auto& face : listenerFaces) {
+ BOOST_CHECK_EQUAL(face->getPersistency(), ndn::nfd::FACE_PERSISTENCY_ON_DEMAND);
+ }
+ for (const auto& face : clientFaces) {
+ BOOST_CHECK_EQUAL(face->getPersistency(), ndn::nfd::FACE_PERSISTENCY_PERSISTENT);
+ }
+
+ // connect twice to the same endpoint
+ this->connect(*ch3);
+
+ BOOST_CHECK(limitedIo.run(1, time::seconds(1)) == LimitedIo::EXCEED_OPS);
+
+ BOOST_CHECK_EQUAL(listenerChannel->size(), 3);
+ BOOST_CHECK_EQUAL(ch1->size(), 1);
+ BOOST_CHECK_EQUAL(ch2->size(), 1);
+ BOOST_CHECK_EQUAL(ch3->size(), 1);
+ BOOST_CHECK_EQUAL(clientFaces.size(), 4);
+ BOOST_CHECK_EQUAL(clientFaces.at(2), clientFaces.at(3));
+}
+
+BOOST_AUTO_TEST_CASE(FaceClosure)
+{
+ this->listen(ip::address_v4::loopback());
+
+ auto clientChannel = makeChannel(ip::address_v4());
+ this->connect(*clientChannel);
+
+ BOOST_CHECK(limitedIo.run(2, time::seconds(1)) == LimitedIo::EXCEED_OPS);
+
+ BOOST_CHECK_EQUAL(listenerChannel->size(), 1);
+ BOOST_CHECK_EQUAL(clientChannel->size(), 1);
+
+ clientFaces.at(0)->close();
+
+ BOOST_CHECK(limitedIo.run(2, time::seconds(5)) == LimitedIo::EXCEED_OPS);
+
+ BOOST_CHECK_EQUAL(listenerChannel->size(), 0);
+ BOOST_CHECK_EQUAL(clientChannel->size(), 0);
+}
BOOST_AUTO_TEST_SUITE_END() // TestUdpChannel
BOOST_AUTO_TEST_SUITE_END() // Face