tests: UnixStreamTransport test suite improvements

refs #3305

Change-Id: I6c6ca52a5e80266920ded811ff45fc568c3e59b9
diff --git a/tests/daemon/face/get-available-interface-ip.hpp b/tests/daemon/face/get-available-interface-ip.hpp
index feadabe..3a98632 100644
--- a/tests/daemon/face/get-available-interface-ip.hpp
+++ b/tests/daemon/face/get-available-interface-ip.hpp
@@ -50,7 +50,7 @@
 getAvailableInterfaceIp();
 
 template<>
-boost::asio::ip::address_v4
+inline boost::asio::ip::address_v4
 getAvailableInterfaceIp()
 {
   for (const auto& interface : listNetworkInterfaces()) {
@@ -68,7 +68,7 @@
 }
 
 template<>
-boost::asio::ip::address_v6
+inline boost::asio::ip::address_v6
 getAvailableInterfaceIp()
 {
   for (const auto& interface : listNetworkInterfaces()) {
diff --git a/tests/daemon/face/stream-transport.t.cpp b/tests/daemon/face/stream-transport.t.cpp
new file mode 100644
index 0000000..24b8b43
--- /dev/null
+++ b/tests/daemon/face/stream-transport.t.cpp
@@ -0,0 +1,170 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014-2015,  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 "tcp-transport-fixture.hpp"
+#include "unix-stream-transport-fixture.hpp"
+
+namespace nfd {
+namespace face {
+namespace tests {
+
+BOOST_AUTO_TEST_SUITE(Face)
+BOOST_AUTO_TEST_SUITE(TestStreamTransport)
+
+typedef boost::mpl::vector<TcpTransportFixture, UnixStreamTransportFixture> StreamTransportFixtures;
+
+BOOST_FIXTURE_TEST_CASE_TEMPLATE(Send, T, StreamTransportFixtures, T)
+{
+  this->initialize();
+
+  auto block1 = ndn::encoding::makeStringBlock(300, "hello");
+  this->transport->send(Transport::Packet{Block{block1}}); // make a copy of the block
+  BOOST_CHECK_EQUAL(this->transport->getCounters().nOutPackets, 1);
+  BOOST_CHECK_EQUAL(this->transport->getCounters().nOutBytes, block1.size());
+
+  auto block2 = ndn::encoding::makeStringBlock(301, "world");
+  this->transport->send(Transport::Packet{Block{block2}}); // make a copy of the block
+  BOOST_CHECK_EQUAL(this->transport->getCounters().nOutPackets, 2);
+  BOOST_CHECK_EQUAL(this->transport->getCounters().nOutBytes, block1.size() + block2.size());
+
+  std::vector<uint8_t> readBuf(block1.size() + block2.size());
+  boost::asio::async_read(this->remoteSocket, boost::asio::buffer(readBuf),
+    [this] (const boost::system::error_code& error, size_t) {
+      BOOST_REQUIRE_EQUAL(error, boost::system::errc::success);
+      this->limitedIo.afterOp();
+    });
+
+  BOOST_REQUIRE_EQUAL(this->limitedIo.run(1, time::seconds(1)), LimitedIo::EXCEED_OPS);
+
+  BOOST_CHECK_EQUAL_COLLECTIONS(readBuf.begin(), readBuf.begin() + block1.size(), block1.begin(), block1.end());
+  BOOST_CHECK_EQUAL_COLLECTIONS(readBuf.begin() + block1.size(), readBuf.end(),   block2.begin(), block2.end());
+  BOOST_CHECK_EQUAL(this->transport->getState(), TransportState::UP);
+}
+
+BOOST_FIXTURE_TEST_CASE_TEMPLATE(ReceiveNormal, T, StreamTransportFixtures, T)
+{
+  this->initialize();
+
+  Block pkt = ndn::encoding::makeStringBlock(300, "hello");
+  ndn::Buffer buf(pkt.begin(), pkt.end());
+  this->remoteWrite(buf);
+
+  BOOST_CHECK_EQUAL(this->transport->getCounters().nInPackets, 1);
+  BOOST_CHECK_EQUAL(this->transport->getCounters().nInBytes, pkt.size());
+  BOOST_CHECK_EQUAL(this->receivedPackets->size(), 1);
+  BOOST_CHECK_EQUAL(this->transport->getState(), TransportState::UP);
+}
+
+BOOST_FIXTURE_TEST_CASE_TEMPLATE(ReceiveMultipleSegments, T, StreamTransportFixtures, T)
+{
+  this->initialize();
+
+  Block pkt = ndn::encoding::makeStringBlock(300, "hello");
+  ndn::Buffer buf1(pkt.begin(), pkt.end() - 2);
+  ndn::Buffer buf2(pkt.end() - 2, pkt.end());
+
+  this->remoteWrite(buf1);
+
+  BOOST_CHECK_EQUAL(this->transport->getCounters().nInPackets, 0);
+  BOOST_CHECK_EQUAL(this->transport->getCounters().nInBytes, 0);
+  BOOST_CHECK_EQUAL(this->receivedPackets->size(), 0);
+  BOOST_CHECK_EQUAL(this->transport->getState(), TransportState::UP);
+
+  this->remoteWrite(buf2);
+
+  BOOST_CHECK_EQUAL(this->transport->getCounters().nInPackets, 1);
+  BOOST_CHECK_EQUAL(this->transport->getCounters().nInBytes, pkt.size());
+  BOOST_CHECK_EQUAL(this->receivedPackets->size(), 1);
+  BOOST_CHECK_EQUAL(this->transport->getState(), TransportState::UP);
+}
+
+BOOST_FIXTURE_TEST_CASE_TEMPLATE(ReceiveMultipleBlocks, T, StreamTransportFixtures, T)
+{
+  this->initialize();
+
+  Block pkt1 = ndn::encoding::makeStringBlock(300, "hello");
+  Block pkt2 = ndn::encoding::makeStringBlock(301, "world");
+  ndn::Buffer buf(pkt1.size() + pkt2.size());
+  std::copy(pkt1.begin(), pkt1.end(), buf.buf());
+  std::copy(pkt2.begin(), pkt2.end(), buf.buf() + pkt1.size());
+
+  this->remoteWrite(buf);
+
+  BOOST_CHECK_EQUAL(this->transport->getCounters().nInPackets, 2);
+  BOOST_CHECK_EQUAL(this->transport->getCounters().nInBytes, buf.size());
+  BOOST_CHECK_EQUAL(this->receivedPackets->size(), 2);
+  BOOST_CHECK_EQUAL(this->transport->getState(), TransportState::UP);
+}
+
+BOOST_FIXTURE_TEST_CASE_TEMPLATE(ReceiveTooLarge, T, StreamTransportFixtures, T)
+{
+  this->initialize();
+
+  std::vector<uint8_t> bytes(ndn::MAX_NDN_PACKET_SIZE + 1, 0);
+  Block pkt = ndn::encoding::makeBinaryBlock(300, bytes.data(), bytes.size());
+  ndn::Buffer buf(pkt.begin(), pkt.end());
+
+  this->remoteWrite(buf, false);
+
+  BOOST_CHECK_EQUAL(this->transport->getCounters().nInPackets, 0);
+  BOOST_CHECK_EQUAL(this->transport->getCounters().nInBytes, 0);
+  BOOST_CHECK_EQUAL(this->receivedPackets->size(), 0);
+  BOOST_CHECK_EQUAL(this->transport->getState(), TransportState::CLOSED);
+}
+
+BOOST_FIXTURE_TEST_CASE_TEMPLATE(Close, T, StreamTransportFixtures, T)
+{
+  this->initialize();
+
+  this->transport->close();
+  BOOST_CHECK_EQUAL(this->transport->getState(), TransportState::CLOSING);
+
+  this->g_io.poll();
+  BOOST_CHECK_EQUAL(this->transport->getState(), TransportState::CLOSED);
+}
+
+BOOST_FIXTURE_TEST_CASE_TEMPLATE(RemoteClose, T, StreamTransportFixtures, T)
+{
+  this->initialize();
+
+  this->transport->afterStateChange.connectSingleShot([this] (TransportState oldState, TransportState newState) {
+    BOOST_CHECK_EQUAL(oldState, TransportState::UP);
+    BOOST_CHECK_EQUAL(newState, TransportState::FAILED);
+    this->limitedIo.afterOp();
+  });
+
+  this->remoteSocket.close();
+  BOOST_REQUIRE_EQUAL(this->limitedIo.run(1, time::seconds(1)), LimitedIo::EXCEED_OPS);
+
+  this->g_io.poll();
+  BOOST_CHECK_EQUAL(this->transport->getState(), TransportState::CLOSED);
+}
+
+BOOST_AUTO_TEST_SUITE_END() // TestStreamTransport
+BOOST_AUTO_TEST_SUITE_END() // Face
+
+} // namespace tests
+} // namespace face
+} // namespace nfd
\ No newline at end of file
diff --git a/tests/daemon/face/tcp-transport-fixture.hpp b/tests/daemon/face/tcp-transport-fixture.hpp
new file mode 100644
index 0000000..03594a1
--- /dev/null
+++ b/tests/daemon/face/tcp-transport-fixture.hpp
@@ -0,0 +1,116 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014-2015,  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/>.
+ */
+
+#ifndef NFD_TESTS_DAEMON_FACE_TCP_TRANSPORT_FIXTURE_HPP
+#define NFD_TESTS_DAEMON_FACE_TCP_TRANSPORT_FIXTURE_HPP
+
+#include "face/tcp-transport.hpp"
+#include "face/lp-face.hpp"
+
+#include "dummy-receive-link-service.hpp"
+#include "get-available-interface-ip.hpp"
+#include "transport-test-common.hpp"
+
+#include "tests/limited-io.hpp"
+
+namespace nfd {
+namespace face {
+namespace tests {
+
+using namespace nfd::tests;
+namespace ip = boost::asio::ip;
+using ip::tcp;
+
+class TcpTransportFixture : public BaseFixture
+{
+protected:
+  TcpTransportFixture()
+    : transport(nullptr)
+    , remoteSocket(g_io)
+    , receivedPackets(nullptr)
+    , acceptor(g_io)
+  {
+  }
+
+  void
+  initialize(ip::address address = ip::address_v4::loopback())
+  {
+    tcp::endpoint remoteEp(address, 7070);
+    acceptor.open(remoteEp.protocol());
+    acceptor.set_option(tcp::acceptor::reuse_address(true));
+    acceptor.bind(remoteEp);
+    acceptor.listen(1);
+    acceptor.async_accept(remoteSocket, [this] (const boost::system::error_code& error) {
+      BOOST_REQUIRE_EQUAL(error, boost::system::errc::success);
+      limitedIo.afterOp();
+    });
+
+    tcp::socket sock(g_io);
+    sock.async_connect(remoteEp, [this] (const boost::system::error_code& error) {
+      BOOST_REQUIRE_EQUAL(error, boost::system::errc::success);
+      limitedIo.afterOp();
+    });
+
+    BOOST_REQUIRE_EQUAL(limitedIo.run(2, time::seconds(1)), LimitedIo::EXCEED_OPS);
+
+    localEp = sock.local_endpoint();
+    face = make_unique<LpFace>(make_unique<DummyReceiveLinkService>(),
+                               make_unique<TcpTransport>(std::move(sock),
+                                                         ndn::nfd::FACE_PERSISTENCY_PERSISTENT));
+    transport = static_cast<TcpTransport*>(face->getTransport());
+    receivedPackets = &static_cast<DummyReceiveLinkService*>(face->getLinkService())->receivedPackets;
+
+    BOOST_REQUIRE_EQUAL(transport->getState(), TransportState::UP);
+  }
+
+  void
+  remoteWrite(const ndn::Buffer& buf, bool needToCheck = true)
+  {
+    boost::asio::async_write(remoteSocket, boost::asio::buffer(buf),
+      [needToCheck] (const boost::system::error_code& error, size_t) {
+        if (needToCheck) {
+          BOOST_REQUIRE_EQUAL(error, boost::system::errc::success);
+        }
+      });
+    limitedIo.defer(time::milliseconds(50));
+  }
+
+protected:
+  LimitedIo limitedIo;
+  TcpTransport* transport;
+  tcp::endpoint localEp;
+  tcp::socket remoteSocket;
+  std::vector<Transport::Packet>* receivedPackets;
+
+private:
+  tcp::acceptor acceptor;
+  unique_ptr<LpFace> face;
+};
+
+} // namespace tests
+} // namespace face
+} // namespace nfd
+
+#endif // NFD_TESTS_DAEMON_FACE_TCP_TRANSPORT_FIXTURE_HPP
diff --git a/tests/daemon/face/tcp-transport.t.cpp b/tests/daemon/face/tcp-transport.t.cpp
index 873d6ca..3326908 100644
--- a/tests/daemon/face/tcp-transport.t.cpp
+++ b/tests/daemon/face/tcp-transport.t.cpp
@@ -23,84 +23,14 @@
  * NFD, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "face/tcp-transport.hpp"
-#include "face/lp-face.hpp"
-
-#include "dummy-receive-link-service.hpp"
-#include "get-available-interface-ip.hpp"
-#include "transport-test-common.hpp"
-
-#include "tests/limited-io.hpp"
+#include "tcp-transport-fixture.hpp"
 
 namespace nfd {
 namespace face {
 namespace tests {
 
-using namespace nfd::tests;
-namespace ip = boost::asio::ip;
-using ip::tcp;
-
 BOOST_AUTO_TEST_SUITE(Face)
 
-class TcpTransportFixture : public BaseFixture
-{
-protected:
-  TcpTransportFixture()
-    : transport(nullptr)
-    , remoteSocket(g_io)
-    , receivedPackets(nullptr)
-    , acceptor(g_io)
-  {
-  }
-
-  void
-  initialize(ip::address address = ip::address_v4::loopback())
-  {
-    tcp::endpoint remoteEp(address, 7070);
-    acceptor.open(remoteEp.protocol());
-    acceptor.set_option(tcp::acceptor::reuse_address(true));
-    acceptor.bind(remoteEp);
-    acceptor.listen(1);
-    acceptor.async_accept(remoteSocket, bind([]{}));
-
-    tcp::socket sock(g_io);
-    sock.async_connect(remoteEp, [this] (const boost::system::error_code& error) {
-      BOOST_REQUIRE_EQUAL(error, boost::system::errc::success);
-      limitedIo.afterOp();
-    });
-
-    BOOST_REQUIRE_EQUAL(limitedIo.run(1, time::seconds(1)), LimitedIo::EXCEED_OPS);
-
-    localEp = sock.local_endpoint();
-    face = make_unique<LpFace>(make_unique<DummyReceiveLinkService>(),
-                               make_unique<TcpTransport>(std::move(sock),
-                                                         ndn::nfd::FACE_PERSISTENCY_PERSISTENT));
-    transport = static_cast<TcpTransport*>(face->getTransport());
-    receivedPackets = &static_cast<DummyReceiveLinkService*>(face->getLinkService())->receivedPackets;
-
-    BOOST_REQUIRE_EQUAL(transport->getState(), TransportState::UP);
-  }
-
-  void
-  remoteWrite(const ndn::Buffer& buf)
-  {
-    // use write() because socket::send() does not guarantee that all data is written before returning
-    BOOST_REQUIRE_EQUAL(boost::asio::write(remoteSocket, boost::asio::buffer(buf)), buf.size());
-    limitedIo.defer(time::milliseconds(50));
-  }
-
-protected:
-  LimitedIo limitedIo;
-  TcpTransport* transport;
-  tcp::endpoint localEp;
-  tcp::socket remoteSocket;
-  std::vector<Transport::Packet>* receivedPackets;
-
-private:
-  tcp::acceptor acceptor;
-  unique_ptr<LpFace> face;
-};
-
 BOOST_FIXTURE_TEST_SUITE(TestTcpTransport, TcpTransportFixture)
 
 BOOST_AUTO_TEST_CASE(StaticPropertiesLocalIpv4)
@@ -167,133 +97,6 @@
   BOOST_CHECK_EQUAL(transport->getMtu(), MTU_UNLIMITED);
 }
 
-BOOST_AUTO_TEST_CASE(Send)
-{
-  initialize();
-
-  auto block1 = ndn::encoding::makeStringBlock(300, "hello");
-  transport->send(Transport::Packet{Block{block1}}); // make a copy of the block
-  BOOST_CHECK_EQUAL(transport->getCounters().nOutPackets, 1);
-  BOOST_CHECK_EQUAL(transport->getCounters().nOutBytes, block1.size());
-
-  auto block2 = ndn::encoding::makeStringBlock(301, "world");
-  transport->send(Transport::Packet{Block{block2}}); // make a copy of the block
-  BOOST_CHECK_EQUAL(transport->getCounters().nOutPackets, 2);
-  BOOST_CHECK_EQUAL(transport->getCounters().nOutBytes, block1.size() + block2.size());
-
-  std::vector<uint8_t> readBuf(block1.size() + block2.size());
-  boost::asio::async_read(remoteSocket, boost::asio::buffer(readBuf),
-    [this] (const boost::system::error_code& error, size_t) {
-      BOOST_REQUIRE_EQUAL(error, boost::system::errc::success);
-      limitedIo.afterOp();
-    });
-
-  BOOST_REQUIRE_EQUAL(limitedIo.run(1, time::seconds(1)), LimitedIo::EXCEED_OPS);
-
-  BOOST_CHECK_EQUAL_COLLECTIONS(readBuf.begin(), readBuf.begin() + block1.size(), block1.begin(), block1.end());
-  BOOST_CHECK_EQUAL_COLLECTIONS(readBuf.begin() + block1.size(), readBuf.end(),   block2.begin(), block2.end());
-  BOOST_CHECK_EQUAL(transport->getState(), TransportState::UP);
-}
-
-BOOST_AUTO_TEST_CASE(ReceiveNormal)
-{
-  initialize();
-
-  Block pkt = ndn::encoding::makeStringBlock(300, "hello");
-  ndn::Buffer buf(pkt.begin(), pkt.end());
-  remoteWrite(buf);
-
-  BOOST_CHECK_EQUAL(transport->getCounters().nInPackets, 1);
-  BOOST_CHECK_EQUAL(transport->getCounters().nInBytes, pkt.size());
-  BOOST_CHECK_EQUAL(receivedPackets->size(), 1);
-  BOOST_CHECK_EQUAL(transport->getState(), TransportState::UP);
-}
-
-BOOST_AUTO_TEST_CASE(ReceiveMultipleSegments)
-{
-  initialize();
-
-  Block pkt = ndn::encoding::makeStringBlock(300, "hello");
-  ndn::Buffer buf1(pkt.begin(), pkt.end() - 2);
-  ndn::Buffer buf2(pkt.end() - 2, pkt.end());
-
-  remoteWrite(buf1);
-
-  BOOST_CHECK_EQUAL(transport->getCounters().nInPackets, 0);
-  BOOST_CHECK_EQUAL(transport->getCounters().nInBytes, 0);
-  BOOST_CHECK_EQUAL(receivedPackets->size(), 0);
-  BOOST_CHECK_EQUAL(transport->getState(), TransportState::UP);
-
-  remoteWrite(buf2);
-
-  BOOST_CHECK_EQUAL(transport->getCounters().nInPackets, 1);
-  BOOST_CHECK_EQUAL(transport->getCounters().nInBytes, pkt.size());
-  BOOST_CHECK_EQUAL(receivedPackets->size(), 1);
-  BOOST_CHECK_EQUAL(transport->getState(), TransportState::UP);
-}
-
-BOOST_AUTO_TEST_CASE(ReceiveMultipleBlocks)
-{
-  initialize();
-
-  Block pkt1 = ndn::encoding::makeStringBlock(300, "hello");
-  Block pkt2 = ndn::encoding::makeStringBlock(301, "world");
-  ndn::Buffer buf(pkt1.size() + pkt2.size());
-  std::copy(pkt1.begin(), pkt1.end(), buf.buf());
-  std::copy(pkt2.begin(), pkt2.end(), buf.buf() + pkt1.size());
-
-  remoteWrite(buf);
-
-  BOOST_CHECK_EQUAL(transport->getCounters().nInPackets, 2);
-  BOOST_CHECK_EQUAL(transport->getCounters().nInBytes, buf.size());
-  BOOST_CHECK_EQUAL(receivedPackets->size(), 2);
-  BOOST_CHECK_EQUAL(transport->getState(), TransportState::UP);
-}
-
-BOOST_AUTO_TEST_CASE(ReceiveTooLarge)
-{
-  initialize();
-
-  std::vector<uint8_t> bytes(ndn::MAX_NDN_PACKET_SIZE + 1, 0);
-  Block pkt = ndn::encoding::makeBinaryBlock(300, bytes.data(), bytes.size());
-  ndn::Buffer buf(pkt.begin(), pkt.end());
-
-  remoteWrite(buf);
-
-  BOOST_CHECK_EQUAL(transport->getCounters().nInPackets, 0);
-  BOOST_CHECK_EQUAL(transport->getCounters().nInBytes, 0);
-  BOOST_CHECK_EQUAL(receivedPackets->size(), 0);
-  BOOST_CHECK_EQUAL(transport->getState(), TransportState::CLOSED);
-}
-
-BOOST_AUTO_TEST_CASE(Close)
-{
-  initialize();
-
-  transport->close();
-  BOOST_CHECK_EQUAL(transport->getState(), TransportState::CLOSING);
-
-  g_io.poll();
-  BOOST_CHECK_EQUAL(transport->getState(), TransportState::CLOSED);
-}
-
-BOOST_AUTO_TEST_CASE(RemoteClose)
-{
-  initialize();
-
-  transport->afterStateChange.connectSingleShot([this] (TransportState oldState, TransportState newState) {
-    BOOST_CHECK_EQUAL(oldState, TransportState::UP);
-    BOOST_CHECK_EQUAL(newState, TransportState::FAILED);
-    limitedIo.afterOp();
-  });
-
-  remoteSocket.close();
-  BOOST_REQUIRE_EQUAL(limitedIo.run(1, time::seconds(1)), LimitedIo::EXCEED_OPS);
-
-  g_io.poll();
-  BOOST_CHECK_EQUAL(transport->getState(), TransportState::CLOSED);
-}
-
 BOOST_AUTO_TEST_SUITE_END() // TestTcpTransport
 BOOST_AUTO_TEST_SUITE_END() // Face
 
diff --git a/tests/daemon/face/unix-stream-transport-fixture.hpp b/tests/daemon/face/unix-stream-transport-fixture.hpp
new file mode 100644
index 0000000..86c8af0
--- /dev/null
+++ b/tests/daemon/face/unix-stream-transport-fixture.hpp
@@ -0,0 +1,146 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014-2015,  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/>.
+ */
+
+#ifndef NFD_TESTS_DAEMON_FACE_UNIX_STREAM_TRANSPORT_FIXTURE_HPP
+#define NFD_TESTS_DAEMON_FACE_UNIX_STREAM_TRANSPORT_FIXTURE_HPP
+
+#include "face/unix-stream-transport.hpp"
+#include "face/lp-face.hpp"
+
+#include "dummy-receive-link-service.hpp"
+#include "transport-test-common.hpp"
+
+#include "tests/limited-io.hpp"
+
+#include <boost/filesystem.hpp>
+
+namespace nfd {
+namespace face {
+namespace tests {
+
+using namespace nfd::tests;
+typedef boost::asio::local::stream_protocol unix_stream;
+
+/** \brief automatically unlinks the socket file of a Unix stream acceptor
+ */
+class AcceptorWithCleanup : public unix_stream::acceptor
+{
+public:
+  explicit
+  AcceptorWithCleanup(boost::asio::io_service& io, const std::string& path = "")
+    : unix_stream::acceptor(io)
+  {
+    this->open();
+
+    if (path.empty()) {
+      this->bind("nfd-unix-stream-test." + to_string(time::system_clock::now().time_since_epoch().count()) + ".sock");
+    }
+    else {
+      this->bind(path);
+    }
+
+    this->listen(1);
+  }
+
+  ~AcceptorWithCleanup()
+  {
+    boost::system::error_code ec;
+
+    std::string path = this->local_endpoint(ec).path();
+    if (ec) {
+      return;
+    }
+
+    this->close(ec);
+    boost::filesystem::remove(path, ec);
+  }
+};
+
+class UnixStreamTransportFixture : public BaseFixture
+{
+protected:
+  UnixStreamTransportFixture()
+    : transport(nullptr)
+    , remoteSocket(g_io)
+    , receivedPackets(nullptr)
+    , acceptor(g_io)
+  {
+  }
+
+  void
+  initialize()
+  {
+    unix_stream::socket sock(g_io);
+    acceptor.async_accept(sock, [this] (const boost::system::error_code& error) {
+      BOOST_REQUIRE_EQUAL(error, boost::system::errc::success);
+      limitedIo.afterOp();
+    });
+
+    unix_stream::endpoint remoteEp(acceptor.local_endpoint());
+    remoteSocket.async_connect(remoteEp, [this] (const boost::system::error_code& error) {
+      BOOST_REQUIRE_EQUAL(error, boost::system::errc::success);
+      limitedIo.afterOp();
+    });
+
+    BOOST_REQUIRE_EQUAL(limitedIo.run(2, time::seconds(1)), LimitedIo::EXCEED_OPS);
+
+    localEp = sock.local_endpoint();
+    face = make_unique<LpFace>(make_unique<DummyReceiveLinkService>(),
+                                make_unique<UnixStreamTransport>(std::move(sock)));
+    transport = static_cast<UnixStreamTransport*>(face->getTransport());
+    receivedPackets = &static_cast<DummyReceiveLinkService*>(face->getLinkService())->receivedPackets;
+
+    BOOST_REQUIRE_EQUAL(transport->getState(), TransportState::UP);
+  }
+
+  void
+  remoteWrite(const ndn::Buffer& buf, bool needToCheck = true)
+  {
+    boost::asio::async_write(remoteSocket, boost::asio::buffer(buf),
+      [needToCheck] (const boost::system::error_code& error, size_t) {
+        if (needToCheck) {
+          BOOST_REQUIRE_EQUAL(error, boost::system::errc::success);
+        }
+      });
+    limitedIo.defer(time::milliseconds(50));
+  }
+
+protected:
+  LimitedIo limitedIo;
+  UnixStreamTransport* transport;
+  unix_stream::endpoint localEp;
+  unix_stream::socket remoteSocket;
+  std::vector<Transport::Packet>* receivedPackets;
+
+private:
+  AcceptorWithCleanup acceptor;
+  unique_ptr<LpFace> face;
+};
+
+} // namespace tests
+} // namespace face
+} // namespace nfd
+
+#endif // NFD_TESTS_DAEMON_FACE_UNIX_STREAM_TRANSPORT_FIXTURE_HPP
\ No newline at end of file
diff --git a/tests/daemon/face/unix-stream-transport.t.cpp b/tests/daemon/face/unix-stream-transport.t.cpp
index a74b760..2ff73be 100644
--- a/tests/daemon/face/unix-stream-transport.t.cpp
+++ b/tests/daemon/face/unix-stream-transport.t.cpp
@@ -23,81 +23,30 @@
  * NFD, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "face/unix-stream-transport.hpp"
-#include "transport-test-common.hpp"
-
-#include <boost/filesystem.hpp>
+#include "unix-stream-transport-fixture.hpp"
 
 namespace nfd {
 namespace face {
 namespace tests {
 
-using namespace nfd::tests;
-typedef boost::asio::local::stream_protocol unix_stream;
-
 BOOST_AUTO_TEST_SUITE(Face)
-BOOST_FIXTURE_TEST_SUITE(TestUnixStreamTransport, BaseFixture)
 
-/** \brief automatically unlinks the socket file of a Unix stream acceptor
- */
-class AcceptorWithCleanup : public unix_stream::acceptor
-{
-public:
-  AcceptorWithCleanup(const std::string& path = "")
-    : unix_stream::acceptor(getGlobalIoService())
-  {
-    this->open();
-    if (path.empty()) {
-      this->bind("unix-stream-acceptor." + to_string(time::system_clock::now().time_since_epoch().count()) + ".sock");
-    }
-    else {
-      this->bind(path);
-    }
-    this->listen(1);
-  }
-
-  ~AcceptorWithCleanup()
-  {
-    std::string path = this->local_endpoint().path();
-
-    boost::system::error_code ec;
-    this->close(ec);
-    boost::filesystem::remove(path, ec);
-  }
-};
-
-bool
-connectToAcceptor(unix_stream::acceptor& acceptor, unix_stream::socket& sock1, unix_stream::socket& sock2)
-{
-  bool isAccepted = false;
-  acceptor.async_accept(sock1, bind([&isAccepted] { isAccepted = true; }));
-
-  bool isConnected = false;
-  sock2.async_connect(acceptor.local_endpoint(), bind([&isConnected] { isConnected = true; }));
-
-  getGlobalIoService().poll();
-
-  return isAccepted && isConnected;
-}
+BOOST_FIXTURE_TEST_SUITE(TestUnixStreamTransport, UnixStreamTransportFixture)
 
 BOOST_AUTO_TEST_CASE(StaticProperties)
 {
-  AcceptorWithCleanup acceptor1;
-  unix_stream::socket sock1(getGlobalIoService());
-  unix_stream::socket sock2(getGlobalIoService());
-  BOOST_CHECK(connectToAcceptor(acceptor1, sock1, sock2));
+  initialize();
 
-  UnixStreamTransport transport(std::move(sock1));
-  checkStaticPropertiesInitialized(transport);
+  checkStaticPropertiesInitialized(*transport);
 
-  BOOST_CHECK_EQUAL(transport.getLocalUri().getScheme(), "unix");
-  BOOST_CHECK_EQUAL(transport.getLocalUri().getHost(), "");
-  BOOST_CHECK_EQUAL(transport.getLocalUri().getPath(), acceptor1.local_endpoint().path());
-  BOOST_CHECK_EQUAL(transport.getRemoteUri().getScheme(), "fd");
-  BOOST_CHECK_EQUAL(transport.getScope(), ndn::nfd::FACE_SCOPE_LOCAL);
-  BOOST_CHECK_EQUAL(transport.getPersistency(), ndn::nfd::FACE_PERSISTENCY_ON_DEMAND);
-  BOOST_CHECK_EQUAL(transport.getLinkType(), ndn::nfd::LINK_TYPE_POINT_TO_POINT);
-  BOOST_CHECK_EQUAL(transport.getMtu(), MTU_UNLIMITED);
+  BOOST_CHECK_EQUAL(transport->getLocalUri().getScheme(), "unix");
+  BOOST_CHECK_EQUAL(transport->getLocalUri().getHost(), "");
+  BOOST_CHECK_EQUAL(transport->getLocalUri().getPath(), localEp.path());
+  BOOST_CHECK_EQUAL(transport->getRemoteUri().getScheme(), "fd");
+  BOOST_CHECK_EQUAL(transport->getScope(), ndn::nfd::FACE_SCOPE_LOCAL);
+  BOOST_CHECK_EQUAL(transport->getPersistency(), ndn::nfd::FACE_PERSISTENCY_ON_DEMAND);
+  BOOST_CHECK_EQUAL(transport->getLinkType(), ndn::nfd::LINK_TYPE_POINT_TO_POINT);
+  BOOST_CHECK_EQUAL(transport->getMtu(), MTU_UNLIMITED);
 }
 
 BOOST_AUTO_TEST_SUITE_END() // TestUnixStreamTransport