face: improve TcpChannel test suite
Change-Id: I751eb58d5b794bc6ba6f77c065fe6616cfc07ced
Refs: #3370
diff --git a/tests/daemon/face/tcp-channel.t.cpp b/tests/daemon/face/tcp-channel.t.cpp
index 816761d..040dc45 100644
--- a/tests/daemon/face/tcp-channel.t.cpp
+++ b/tests/daemon/face/tcp-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,
@@ -25,17 +25,192 @@
#include "face/tcp-channel.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(TestTcpChannel, BaseFixture)
-// TODO add the equivalent of these test cases from tcp.t.cpp as of commit:65caf200924b28748037750449e28bcb548dbc9c
-// MultipleAccepts
-// FaceClosing
+using nfd::Face;
+namespace ip = boost::asio::ip;
+
+typedef boost::mpl::vector<ip::address_v4,
+ ip::address_v6> AddressTypes;
+
+class TcpChannelFixture : public BaseFixture
+{
+protected:
+ TcpChannelFixture()
+ : nextPort(7050)
+ {
+ }
+
+ unique_ptr<TcpChannel>
+ makeChannel(const ip::address& addr, uint16_t port = 0)
+ {
+ if (port == 0)
+ port = nextPort++;
+
+ return make_unique<TcpChannel>(tcp::Endpoint(addr, port));
+ }
+
+ void
+ listen(const ip::address& addr)
+ {
+ listenerEp = tcp::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();
+ },
+ [this] (const std::string& reason) {
+ BOOST_FAIL(reason);
+ limitedIo.afterOp();
+ });
+ }
+
+ void
+ connect(TcpChannel& channel)
+ {
+ channel.connect(listenerEp,
+ [this] (const shared_ptr<Face>& newFace) {
+ BOOST_REQUIRE(newFace != nullptr);
+ connectFaceClosedSignal(*newFace, [this] { limitedIo.afterOp(); });
+ clientFaces.push_back(newFace);
+ limitedIo.afterOp();
+ },
+ [this] (const std::string& reason) {
+ BOOST_FAIL(reason);
+ limitedIo.afterOp();
+ });
+ }
+
+protected:
+ LimitedIo limitedIo;
+ tcp::Endpoint listenerEp;
+ unique_ptr<TcpChannel> listenerChannel;
+ std::vector<shared_ptr<Face>> listenerFaces;
+ std::vector<shared_ptr<Face>> clientFaces;
+
+private:
+ uint16_t nextPort;
+};
+
+BOOST_FIXTURE_TEST_SUITE(TestTcpChannel, TcpChannelFixture)
+
+BOOST_AUTO_TEST_CASE_TEMPLATE(Uri, A, AddressTypes)
+{
+ tcp::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_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_TEMPLATE(ConnectTimeout, A, AddressTypes)
+{
+ auto channel = makeChannel(A());
+
+ channel->connect(tcp::Endpoint(A::loopback(), 7040),
+ [this] (const shared_ptr<Face>&) {
+ BOOST_FAIL("Connect succeeded when it should have failed");
+ this->limitedIo.afterOp();
+ },
+ [this] (const std::string& reason) {
+ BOOST_CHECK_EQUAL(reason.empty(), false);
+ this->limitedIo.afterOp();
+ },
+ time::seconds(1));
+
+ BOOST_CHECK(limitedIo.run(1, time::seconds(2)) == LimitedIo::EXCEED_OPS);
+ BOOST_CHECK_EQUAL(channel->size(), 0);
+}
+
+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(1)) == LimitedIo::EXCEED_OPS);
+
+ BOOST_CHECK_EQUAL(listenerChannel->size(), 0);
+ BOOST_CHECK_EQUAL(clientChannel->size(), 0);
+}
BOOST_AUTO_TEST_SUITE_END() // TestTcpChannel
BOOST_AUTO_TEST_SUITE_END() // Face