face: improve UnixStreamChannel test suite
Change-Id: I41eaa3c7d1dea9effdc2e597926b110c9a703084
Refs: #3372
diff --git a/tests/daemon/face/unix-stream-channel.t.cpp b/tests/daemon/face/unix-stream-channel.t.cpp
index 86caa8d..6d523ff 100644
--- a/tests/daemon/face/unix-stream-channel.t.cpp
+++ b/tests/daemon/face/unix-stream-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,18 +25,156 @@
#include "face/unix-stream-channel.hpp"
+#include "tests/limited-io.hpp"
#include "tests/test-common.hpp"
+#include <boost/filesystem.hpp>
+#include <fstream>
+
namespace nfd {
namespace tests {
BOOST_AUTO_TEST_SUITE(Face)
-BOOST_FIXTURE_TEST_SUITE(TestUnixStreamChannel, BaseFixture)
-// TODO add the equivalent of these test cases from unix-stream.t.cpp as of commit:65caf200924b28748037750449e28bcb548dbc9c
-// MultipleAccepts
+using nfd::Face;
+namespace fs = boost::filesystem;
+namespace local = boost::asio::local;
-// TODO add a test case to check a failed face is removed from the channel
+class UnixStreamChannelFixture : public BaseFixture
+{
+protected:
+ UnixStreamChannelFixture()
+ : listenerEp("nfd-test-unix-stream-channel.sock")
+ {
+ }
+
+ unique_ptr<UnixStreamChannel>
+ makeChannel()
+ {
+ return make_unique<UnixStreamChannel>(listenerEp);
+ }
+
+ void
+ listen()
+ {
+ listenerChannel = makeChannel();
+ 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(local::stream_protocol::socket& client)
+ {
+ client.async_connect(listenerEp,
+ [this] (const boost::system::error_code& error) {
+ BOOST_REQUIRE_EQUAL(error, boost::system::errc::success);
+ limitedIo.afterOp();
+ });
+ }
+
+protected:
+ LimitedIo limitedIo;
+ unix_stream::Endpoint listenerEp;
+ unique_ptr<UnixStreamChannel> listenerChannel;
+ std::vector<shared_ptr<Face>> listenerFaces;
+};
+
+BOOST_FIXTURE_TEST_SUITE(TestUnixStreamChannel, UnixStreamChannelFixture)
+
+BOOST_AUTO_TEST_CASE(Listen)
+{
+ auto channel = makeChannel();
+ 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(MultipleAccepts)
+{
+ this->listen();
+
+ BOOST_CHECK_EQUAL(listenerChannel->isListening(), true);
+ BOOST_CHECK_EQUAL(listenerFaces.size(), 0);
+
+ local::stream_protocol::socket client1(g_io);
+ this->connect(client1);
+
+ BOOST_CHECK_EQUAL(limitedIo.run(2, time::seconds(1)), LimitedIo::EXCEED_OPS);
+ BOOST_CHECK_EQUAL(listenerFaces.size(), 1);
+
+ local::stream_protocol::socket client2(g_io);
+ local::stream_protocol::socket client3(g_io);
+ this->connect(client2);
+ this->connect(client3);
+
+ BOOST_CHECK_EQUAL(limitedIo.run(4, time::seconds(1)), LimitedIo::EXCEED_OPS);
+ BOOST_CHECK_EQUAL(listenerFaces.size(), 3);
+
+ // check face persistency
+ for (const auto& face : listenerFaces) {
+ BOOST_CHECK_EQUAL(face->getPersistency(), ndn::nfd::FACE_PERSISTENCY_ON_DEMAND);
+ }
+}
+
+BOOST_AUTO_TEST_CASE(SocketFile)
+{
+ fs::path socketPath(listenerEp.path());
+ fs::remove(socketPath);
+
+ auto channel = makeChannel();
+ BOOST_CHECK_EQUAL(fs::symlink_status(socketPath).type(), fs::file_not_found);
+
+ channel->listen(nullptr, nullptr);
+ auto status = fs::symlink_status(socketPath);
+ BOOST_CHECK_EQUAL(status.type(), fs::socket_file);
+ BOOST_CHECK_EQUAL(status.permissions(), fs::owner_read | fs::group_read | fs::others_read |
+ fs::owner_write | fs::group_write | fs::others_write);
+
+ channel.reset();
+ BOOST_CHECK_EQUAL(fs::symlink_status(socketPath).type(), fs::file_not_found);
+}
+
+BOOST_AUTO_TEST_CASE(ExistingStaleSocketFile)
+{
+ fs::path socketPath(listenerEp.path());
+ fs::remove(socketPath);
+
+ local::stream_protocol::acceptor acceptor(g_io, listenerEp);
+ acceptor.close();
+ BOOST_CHECK_EQUAL(fs::symlink_status(socketPath).type(), fs::socket_file);
+
+ auto channel = makeChannel();
+ BOOST_CHECK_NO_THROW(channel->listen(nullptr, nullptr));
+ BOOST_CHECK_EQUAL(fs::symlink_status(socketPath).type(), fs::socket_file);
+}
+
+BOOST_AUTO_TEST_CASE(ExistingRegularFile)
+{
+ fs::path socketPath(listenerEp.path());
+ fs::remove(socketPath);
+
+ std::ofstream f(listenerEp.path());
+ f.close();
+
+ auto channel = makeChannel();
+ BOOST_CHECK_THROW(channel->listen(nullptr, nullptr), UnixStreamChannel::Error);
+
+ fs::remove(socketPath);
+}
BOOST_AUTO_TEST_SUITE_END() // TestUnixStreamChannel
BOOST_AUTO_TEST_SUITE_END() // Face