ndnping: recognize and trace Nack

Change-Id: If47877892c75ae0849375f36430a66e02fb7a608
refs: #3335
diff --git a/tests/ping/client/ping.t.cpp b/tests/ping/client/ping.t.cpp
index 9f9eeb9..e39c65a 100644
--- a/tests/ping/client/ping.t.cpp
+++ b/tests/ping/client/ping.t.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /**
- * Copyright (c) 2014-2015,  Arizona Board of Regents.
+ * Copyright (c) 2014-2016,  Arizona Board of Regents.
  *
  * This file is part of ndn-tools (Named Data Networking Essential Tools).
  * See AUTHORS.md for complete list of ndn-tools authors and contributors.
@@ -31,86 +31,64 @@
 
 BOOST_AUTO_TEST_SUITE(PingClientPing)
 
-class SequenceNumberIncrementFixture : public UnitTestTimeFixture
+BOOST_FIXTURE_TEST_CASE(Basic, UnitTestTimeFixture)
 {
-protected:
-  SequenceNumberIncrementFixture()
-    : face(util::makeDummyClientFace(io, {false, true}))
-    , pingOptions(makeOptions())
-    , ping(*face, pingOptions)
-    , numPings(0)
-    , lastPingSeq(pingOptions.startSeq)
-  {
-    ping.afterResponse.connect(bind(&SequenceNumberIncrementFixture::onResponse, this, _1));
-    ping.afterTimeout.connect(bind(&SequenceNumberIncrementFixture::onTimeout, this, _1));
-  }
-
-public:
-  void
-  onResponse(uint64_t seq)
-  {
-    numPings++;
-    lastPingSeq = seq;
-    if (numPings == maxPings) {
-      face->shutdown();
-      io.stop();
-    }
-  }
-
-  void
-  onTimeout(uint64_t seq)
-  {
-    numPings++;
-    lastPingSeq = seq;
-    if (numPings == maxPings) {
-      face->shutdown();
-      io.stop();
-    }
-  }
-
-private:
-  static Options
-  makeOptions()
-  {
-    Options opt;
-    opt.prefix = "ndn:/test-prefix";
-    opt.shouldAllowStaleData = false;
-    opt.shouldGenerateRandomSeq = false;
-    opt.shouldPrintTimestamp = false;
-    opt.nPings = 4;
-    opt.interval = time::milliseconds(100);
-    opt.timeout = time::milliseconds(1000);
-    opt.startSeq = 1000;
-    return opt;
-  }
-
-protected:
-  boost::asio::io_service io;
-  shared_ptr<util::DummyClientFace> face;
   Options pingOptions;
-  Ping ping;
-  uint32_t numPings;
-  uint32_t maxPings;
-  uint64_t lastPingSeq;
-  KeyChain keyChain;
-};
+  pingOptions.prefix = "ndn:/test-prefix";
+  pingOptions.shouldAllowStaleData = false;
+  pingOptions.shouldGenerateRandomSeq = false;
+  pingOptions.shouldPrintTimestamp = false;
+  pingOptions.nPings = 4;
+  pingOptions.interval = time::milliseconds(100);
+  pingOptions.timeout = time::milliseconds(2000);
+  pingOptions.startSeq = 1000;
 
-BOOST_FIXTURE_TEST_CASE(SequenceNumberIncrement, SequenceNumberIncrementFixture)
-{
-  maxPings = 4;
+  boost::asio::io_service io;
+  util::DummyClientFace face(io, {true, true});
+  Ping ping(face, pingOptions);
+
+  int nFinishSignals = 0;
+  std::vector<uint64_t> dataSeqs;
+  std::vector<uint64_t> nackSeqs;
+  std::vector<uint64_t> timeoutSeqs;
+
+  ping.afterData.connect(bind([&] (uint64_t seq) { dataSeqs.push_back(seq); }, _1));
+  ping.afterNack.connect(bind([&] (uint64_t seq) { nackSeqs.push_back(seq); }, _1));
+  ping.afterTimeout.connect(bind([&] (uint64_t seq) { timeoutSeqs.push_back(seq); }, _1));
+  ping.afterFinish.connect(bind([&] {
+    BOOST_REQUIRE_EQUAL(dataSeqs.size(), 2);
+    BOOST_REQUIRE_EQUAL(nackSeqs.size(), 1);
+    BOOST_REQUIRE_EQUAL(timeoutSeqs.size(), 1);
+
+    BOOST_CHECK_EQUAL(dataSeqs[0], 1000);
+    BOOST_CHECK_EQUAL(nackSeqs[0], 1001);
+    BOOST_CHECK_EQUAL(dataSeqs[1], 1002);
+    BOOST_CHECK_EQUAL(timeoutSeqs[0], 1003);
+
+    nFinishSignals++;
+  }));
+
   ping.start();
 
-  this->advanceClocks(io, time::milliseconds(1), 400);
+  this->advanceClocks(io, time::milliseconds(1), 500);
+  BOOST_REQUIRE_EQUAL(face.sentInterests.size(), 4);
 
-  face->receive(*makeData("ndn:/test-prefix/ping/1000"));
-  face->receive(*makeData("ndn:/test-prefix/ping/1001"));
-  face->receive(*makeData("ndn:/test-prefix/ping/1002"));
-  face->receive(*makeData("ndn:/test-prefix/ping/1003"));
+  face.receive(*makeData("ndn:/test-prefix/ping/1000"));
 
-  io.run();
+  lp::Nack nack(face.sentInterests[1]);
+  nack.setReason(lp::NackReason::DUPLICATE);
+  face.receive(nack);
 
-  BOOST_REQUIRE_EQUAL(1003, lastPingSeq);
-  BOOST_REQUIRE_EQUAL(4, numPings);
+  face.receive(*makeData("ndn:/test-prefix/ping/1002"));
+
+  this->advanceClocks(io, time::milliseconds(100), 20);
+
+  // ndn:/test-prefix/ping/1003 is unanswered and will timeout
+
+  BOOST_CHECK_EQUAL(nFinishSignals, 1);
+
+  face.shutdown();
+  io.stop();
 }
 
 BOOST_AUTO_TEST_SUITE_END()