tests+consumer+docs: Test case for AppDelayTracer and related bugfixes

Change-Id: I44a154f53350e140303795a9a8f824f913cc9a4c
Refs: #2764
diff --git a/tests/unit-tests/utils/tracers/ndn-app-delay-tracer.t.cpp b/tests/unit-tests/utils/tracers/ndn-app-delay-tracer.t.cpp
new file mode 100644
index 0000000..64e4aa9
--- /dev/null
+++ b/tests/unit-tests/utils/tracers/ndn-app-delay-tracer.t.cpp
@@ -0,0 +1,163 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2011-2015  Regents of the University of California.
+ *
+ * This file is part of ndnSIM. See AUTHORS for complete list of ndnSIM authors and
+ * contributors.
+ *
+ * ndnSIM 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.
+ *
+ * ndnSIM 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
+ * ndnSIM, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
+ **/
+
+#include "utils/tracers/ndn-app-delay-tracer.hpp"
+
+#include <boost/filesystem.hpp>
+#include <boost/test/output_test_stream.hpp>
+
+#include "../../tests-common.hpp"
+
+namespace ns3 {
+namespace ndn {
+
+const boost::filesystem::path TEST_TRACE = boost::filesystem::path(TEST_CONFIG_PATH) / "trace.txt";
+
+class AppDelayTracerFixture : public ScenarioHelperWithCleanupFixture
+{
+public:
+  AppDelayTracerFixture()
+  {
+    boost::filesystem::create_directories(TEST_CONFIG_PATH);
+
+    // setting default parameters for PointToPoint links and channels
+    Config::SetDefault("ns3::PointToPointNetDevice::DataRate", StringValue("10Mbps"));
+    Config::SetDefault("ns3::PointToPointChannel::Delay", StringValue("10ms"));
+    Config::SetDefault("ns3::DropTailQueue::MaxPackets", StringValue("20"));
+
+    createTopology({
+        {"1", "2"},
+        {"2", "3"}
+      });
+
+    addRoutes({
+        {"1", "2", "/prefix", 1},
+        {"2", "3", "/prefix", 1}
+      });
+
+    addApps({
+        {"1", "ns3::ndn::ConsumerCbr",
+            {{"Prefix", "/prefix"}, {"Frequency", "1"}},
+            "0s", "0.9s"}, // send just one packet
+        // Second consumer will capture effect of the bug #2764
+        {"2", "ns3::ndn::ConsumerCbr",
+            {{"Prefix", "/prefix"}, {"Frequency", "1"}},
+            "2s", "100s"},
+        {"3", "ns3::ndn::Producer",
+            {{"Prefix", "/prefix"}, {"PayloadSize", "1024"}},
+            "0s", "100s"}
+      });
+  }
+
+  ~AppDelayTracerFixture()
+  {
+    boost::filesystem::remove(TEST_TRACE);
+    AppDelayTracer::Destroy(); // additional cleanup
+  }
+};
+
+BOOST_FIXTURE_TEST_SUITE(UtilsTracersNdnAppDelayTracer, AppDelayTracerFixture)
+
+BOOST_AUTO_TEST_CASE(InstallAll)
+{
+  AppDelayTracer::InstallAll(TEST_TRACE.string());
+
+  Simulator::Stop(Seconds(4));
+  Simulator::Run();
+
+  AppDelayTracer::Destroy(); // to force log to be written
+
+  std::ifstream t(TEST_TRACE.string().c_str());
+  std::stringstream buffer;
+  buffer << t.rdbuf();
+
+  BOOST_CHECK_EQUAL(buffer.str(),
+    "Time	Node	AppId	SeqNo	Type	DelayS	DelayUS	RetxCount	HopCount\n"
+    "0.0417424	1	257	0	LastDelay	0.0417424	41742.4	1	2\n"
+    "0.0417424	1	257	0	FullDelay	0.0417424	41742.4	1	2\n"
+    "2	2	258	0	LastDelay	0	0	1	0\n"
+    "2	2	258	0	FullDelay	0	0	1	0\n"
+    "3.02087	2	258	1	LastDelay	0.0208712	20871.2	1	1\n"
+    "3.02087	2	258	1	FullDelay	0.0208712	20871.2	1	1\n");
+}
+
+BOOST_AUTO_TEST_CASE(InstallNodeContainer)
+{
+  NodeContainer nodes;
+  nodes.Add(getNode("1"));
+
+  AppDelayTracer::Install(nodes, TEST_TRACE.string());
+
+  Simulator::Stop(Seconds(4));
+  Simulator::Run();
+
+  AppDelayTracer::Destroy(); // to force log to be written
+
+  std::ifstream t(TEST_TRACE.string().c_str());
+  std::stringstream buffer;
+  buffer << t.rdbuf();
+
+  BOOST_CHECK_EQUAL(buffer.str(),
+    "Time	Node	AppId	SeqNo	Type	DelayS	DelayUS	RetxCount	HopCount\n"
+    "0.0417424	1	257	0	LastDelay	0.0417424	41742.4	1	2\n"
+    "0.0417424	1	257	0	FullDelay	0.0417424	41742.4	1	2\n");
+}
+
+BOOST_AUTO_TEST_CASE(InstallNode)
+{
+  AppDelayTracer::Install(getNode("2"), TEST_TRACE.string());
+
+  Simulator::Stop(Seconds(4));
+  Simulator::Run();
+
+  AppDelayTracer::Destroy(); // to force log to be written
+
+  std::ifstream t(TEST_TRACE.string().c_str());
+  std::stringstream buffer;
+  buffer << t.rdbuf();
+
+  BOOST_CHECK_EQUAL(buffer.str(),
+    "Time	Node	AppId	SeqNo	Type	DelayS	DelayUS	RetxCount	HopCount\n"
+    "2	2	258	0	LastDelay	0	0	1	0\n"
+    "2	2	258	0	FullDelay	0	0	1	0\n"
+    "3.02087	2	258	1	LastDelay	0.0208712	20871.2	1	1\n"
+    "3.02087	2	258	1	FullDelay	0.0208712	20871.2	1	1\n");
+}
+
+BOOST_AUTO_TEST_CASE(InstallNodeDumpStream)
+{
+  auto output = make_shared<boost::test_tools::output_test_stream>();
+  Ptr<AppDelayTracer> tracer = AppDelayTracer::Install(getNode("2"), output);
+
+  Simulator::Stop(Seconds(4));
+  Simulator::Run();
+
+  tracer = nullptr; // destroy tracer
+
+  BOOST_CHECK(output->is_equal(
+    "2	2	258	0	LastDelay	0	0	1	0\n"
+    "2	2	258	0	FullDelay	0	0	1	0\n"
+    "3.02087	2	258	1	LastDelay	0.0208712	20871.2	1	1\n"
+    "3.02087	2	258	1	FullDelay	0.0208712	20871.2	1	1\n"));
+}
+
+BOOST_AUTO_TEST_SUITE_END()
+
+} // namespace ndn
+} // namespace ns3