test-interest-aggregation: test case to test NFD's interest aggregation

Change-Id: I7b84e0d77d285b4ef85a3b1850a0cc953cfc05b3
refs: #1384
diff --git a/library_helpers/process_manager.py b/library_helpers/process_manager.py
index 204d61d..ac53b0f 100644
--- a/library_helpers/process_manager.py
+++ b/library_helpers/process_manager.py
@@ -70,7 +70,7 @@
         self.processes[processKey].start()
 
     def killProcess(self, processKey):
-        if processKey not in self.results:
+        if processKey not in self.results and processKey in self.subprocesses:
             self.subprocesses[processKey].terminate()
 
     def hasProcessCompleted(self, processKey):
diff --git a/test_interest_aggregation/README.md b/test_interest_aggregation/README.md
new file mode 100644
index 0000000..bb4d2f3
--- /dev/null
+++ b/test_interest_aggregation/README.md
@@ -0,0 +1,21 @@
+Test Case - interest-aggregation
+================================
+
+## Objective ##
+
+To test NFD's interest aggregation on a single host.
+
+## Description ##
+
+This test case will run NFD, ndn-tlv-peek and ndn-traffic-server to check aggregation of interests by NFD. The following steps will be followed:
+
+1. Start NFD.
+2. Start ndn-traffic-server to serve ndn:/test-agg, with -d 2000 flag to delay response for 2000ms.
+3. Start two instances of ndn-tlv-peek to request ndn:/test-agg/A. Wait until they terminate. Fail if either is unanswered.
+4. Stop ndn-traffic-server. Fail if total served Interest does not equal 1.
+5. Start ndn-traffic-server to serve ndn:/test-agg, with -d 2000 flag to delay response for 2000ms.
+6. Start ndn-tlv-peek to request ndn:/test-agg/B ChildSelector=leftmost, and another instance to request ndn:/test-agg/B ChildSelector=rightmost. Wait until they terminate. Fail if either is unanswered.
+7. Stop ndn-traffic-server. Fail if total served Interest does not equal 2.
+8. Start ndn-traffic-server to serve ndn:/test-agg, with -d 2000 flag to delay response for 2000ms.
+9. Start ndn-tlv-peek to request ndn:/test-agg/C InterestLifetime=6000ms, and another instance to request ndn:/test-agg/C InterestLifetime=8000ms. Wait until they terminate. Fail if either is unanswered.
+10. Stop ndn-traffic-server. Fail if total served Interest does not equal 1.
diff --git a/test_interest_aggregation/__init__.py b/test_interest_aggregation/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test_interest_aggregation/__init__.py
diff --git a/test_interest_aggregation/test-traffic-server.conf b/test_interest_aggregation/test-traffic-server.conf
new file mode 100644
index 0000000..4fd7531
--- /dev/null
+++ b/test_interest_aggregation/test-traffic-server.conf
@@ -0,0 +1,2 @@
+Name=ndn:/test-agg
+ContentDelay=2000
diff --git a/test_interest_aggregation/test_interest_aggregation.py b/test_interest_aggregation/test_interest_aggregation.py
new file mode 100644
index 0000000..d1b4482
--- /dev/null
+++ b/test_interest_aggregation/test_interest_aggregation.py
@@ -0,0 +1,163 @@
+#!/usr/bin/python2
+# -*- Mode:python; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+#
+# Copyright (C) 2014 University of Arizona
+# Author: Jerald Paul Abraham <jeraldabraham@email.arizona.edu>
+# See COPYING for copyright and distribution information.
+#
+
+import os
+import time
+import unittest
+import process_manager
+
+class test_interest_aggregation(unittest.TestCase, process_manager.ProcessManager):
+    """Test case for testing interest aggregation"""
+
+    def setUp(self):
+        print "\nTesting Interest Aggregation"
+        print "****************************"
+        self.logFolder = "test_interest_aggregation/logs/"
+        if not os.path.exists(self.logFolder):
+            os.system("mkdir " + self.logFolder)
+
+    def tearDown(self):
+        self.killNfd()
+        self.killProcess("ndn-traffic-server-1")
+        self.killProcess("ndn-tlv-peek-1")
+        self.killProcess("ndn-tlv-peek-2")
+        self.killProcess("ndn-traffic-server-2")
+        self.killProcess("ndn-tlv-peek-3")
+        self.killProcess("ndn-tlv-peek-4")
+        self.killProcess("ndn-traffic-server-3")
+        self.killProcess("ndn-tlv-peek-5")
+        self.killProcess("ndn-tlv-peek-6")
+        self.cleanupProcesses()
+
+    def checkAndReportFailure(self, processKey, processName):
+        if self.hasProcessCompleted(processKey):
+            if self.getProcessReturnCode(processKey) != 0:
+                print self.getProcessOutput(processKey)
+                print self.getProcessError(processKey)
+                self.fail(">> TEST FAILED - received non-zero return code from " + processName)
+        else:
+            self.fail(">> TEST FAILED - " + processName + " failed to complete")
+
+
+    def checkServerReceiveCount(self, processKey, processName, expectedCount):
+        serverOutput = self.getProcessOutput(processKey).splitlines()
+        isTestSuccessful = False
+        receivedCount = 0
+        for logLine in serverOutput:
+            if "Total Interests Received" in logLine:
+                for value in logLine.split():
+                    if value.isdigit():
+                        receivedCount = int(value)
+                        break
+                if receivedCount == expectedCount:
+                    isTestSuccessful = True
+                break
+        if not isTestSuccessful:
+            self.fail(">> TEST FAILED - " + processName +
+                      " expected to receive only " + str(expectedCount) +
+                      " interest(s) but received " + str(receivedCount) + " interest(s)" )
+        else:
+            print "-> " + processName + " received " + str(receivedCount) + " interest(s)"
+
+    def test_aggregation(self):
+
+        #Start NFD
+        self.startNfd()
+        time.sleep(1)
+
+        #Start ndn-traffic-server to serve ndn:/test-agg, with content delay set to 2000ms
+        serverConfigurationFile = os.path.abspath(
+            "test_interest_aggregation/test-traffic-server.conf")
+        self.startProcess("ndn-traffic-server-1",
+            ["ndn-traffic-server", serverConfigurationFile],
+            "-> Starting Traffic Server 1 (Prefix=ndn:/test-agg, ContentDelay=2000ms)")
+        time.sleep(1)
+
+        #Start two instances of ndn-tlv-peek to request ndn:/test-agg/A. Wait until they
+        #terminate. Fail if either is unanswered.
+        peekOutputFile = os.path.abspath(self.logFolder + "test-peek-output-1.txt")
+        self.startProcess("ndn-tlv-peek-1",
+            ["ndn-tlv-peek", "ndn:/test-agg/A"],
+            "-> Starting Peek Client 1 (Prefix=ndn:/test-agg/A)",
+            outputFile=peekOutputFile)
+        peekOutputFile = os.path.abspath(self.logFolder + "test-peek-output-2.txt")
+        self.startProcess("ndn-tlv-peek-2",
+            ["ndn-tlv-peek", "ndn:/test-agg/A"],
+            "-> Starting Peek Client 2 (Prefix=ndn:/test-agg/A)",
+            outputFile=peekOutputFile)
+        self.waitForProcessCompletion("ndn-tlv-peek-1", 10)
+        self.waitForProcessCompletion("ndn-tlv-peek-2", 10)
+
+        #Stop ndn-traffic-server. Fail if total served Interest does not equal 1.
+        self.killProcess("ndn-traffic-server-1")
+        time.sleep(1)
+        print "-> Stopping Traffic Server 1"
+        self.checkAndReportFailure("ndn-tlv-peek-1", "Peek Client 1")
+        self.checkAndReportFailure("ndn-tlv-peek-2", "Peek Client 2")
+        self.checkServerReceiveCount("ndn-traffic-server-1", "Traffic Server 1", 1)
+
+        #Start ndn-traffic-server to serve ndn:/test-agg, with content delay set to 2000ms
+        self.startProcess("ndn-traffic-server-2",
+            ["ndn-traffic-server", serverConfigurationFile],
+            "-> Starting Traffic Server 2 (Prefix=ndn:/test-agg, ContentDelay=2000ms)")
+        time.sleep(1)
+
+        #Start ndn-tlv-peek to request ndn:/test-agg/B ChildSelector=leftmost, and another
+        #instance to request ndn:/test-agg/B ChildSelector=rightmost. Wait until they terminate.
+        #Fail if either is unanswered.
+        peekOutputFile = os.path.abspath(self.logFolder + "test-peek-output-3.txt")
+        self.startProcess("ndn-tlv-peek-3",
+            ["ndn-tlv-peek", "ndn:/test-agg/B"],
+            "-> Starting Peek Client 3 (Prefix=ndn:/test-agg/B, ChildSelector=leftmost)",
+            outputFile=peekOutputFile)
+        peekOutputFile = os.path.abspath(self.logFolder + "test-peek-output-4.txt")
+        self.startProcess("ndn-tlv-peek-4",
+            ["ndn-tlv-peek", "-r", "ndn:/test-agg/B"],
+            "-> Starting Peek Client 4 (Prefix=ndn:/test-agg/B, ChildSelector=rightmost)",
+            outputFile=peekOutputFile)
+        self.waitForProcessCompletion("ndn-tlv-peek-3", 10)
+        self.waitForProcessCompletion("ndn-tlv-peek-4", 10)
+
+        #Stop ndn-traffic-server. Fail if total served Interest does not equal 2.
+        self.killProcess("ndn-traffic-server-2")
+        time.sleep(1)
+        print "-> Stopping Traffic Server 2"
+        self.checkAndReportFailure("ndn-tlv-peek-3", "Peek Client 3")
+        self.checkAndReportFailure("ndn-tlv-peek-4", "Peek Client 4")
+        self.checkServerReceiveCount("ndn-traffic-server-2", "Traffic Server 2", 2)
+
+        #Start ndn-traffic-server to serve ndn:/test-agg, with content delay set to 2000ms
+        self.startProcess("ndn-traffic-server-3",
+            ["ndn-traffic-server", serverConfigurationFile],
+            "-> Starting Traffic Server 3 (Prefix=ndn:/test-agg, ContentDelay=2000ms)")
+        time.sleep(1)
+
+        #Start ndn-tlv-peek to request ndn:/test-agg/C InterestLifetime=6000ms, and another
+        #instance to request ndn:/test-agg/C. InterestLifetime=8000ms. Wait until they terminate.
+        #Fail if either is unanswered.
+        peekOutputFile = os.path.abspath(self.logFolder + "test-peek-output-5.txt")
+        self.startProcess("ndn-tlv-peek-5",
+            ["ndn-tlv-peek", "-l 6000", "ndn:/test-agg/C"],
+            "-> Starting Peek Client 5 (Prefix=ndn:/test-agg/C, InterestLifetime=6000ms)",
+            outputFile=peekOutputFile)
+        peekOutputFile = os.path.abspath(self.logFolder + "test-peek-output-6.txt")
+        self.startProcess("ndn-tlv-peek-6",
+            ["ndn-tlv-peek", "-l 8000", "ndn:/test-agg/C"],
+            "-> Starting Peek Client 6 (Prefix=ndn:/test-agg/C, InterestLifetime=8000ms)",
+            outputFile=peekOutputFile)
+        self.waitForProcessCompletion("ndn-tlv-peek-5", 10)
+        self.waitForProcessCompletion("ndn-tlv-peek-6", 10)
+
+        #Stop ndn-traffic-server. Fail if total served Interest does not equal 1.
+        self.killProcess("ndn-traffic-server-3")
+        time.sleep(1)
+        print "-> Stopping Traffic Server 3"
+        self.checkAndReportFailure("ndn-tlv-peek-5", "Peek Client 5")
+        self.checkAndReportFailure("ndn-tlv-peek-6", "Peek Client 6")
+        self.checkServerReceiveCount("ndn-traffic-server-3", "Traffic Server 3", 1)
+        print ">> TEST SUCCESSFUL"
diff --git a/test_ndnpeekpoke/README.md b/test_ndnpeekpoke/README.md
index 3f9b9d1..47150d9 100644
--- a/test_ndnpeekpoke/README.md
+++ b/test_ndnpeekpoke/README.md
@@ -7,6 +7,6 @@
 
 ## Description ##
 
-This test case will run the NFD, ndn-tlv-peek and ndn-tlv-poke binaries.
+This test case will run NFD, ndn-tlv-peek and ndn-tlv-poke.
 This will report SUCCESS if one interest/data is successfully exchanged between ndn-tlv-peek and ndn-tlv-poke.
 In all other scenarios, the test case will report FAILURE
diff --git a/test_ndnpeekpoke/test_ndnpeekpoke.py b/test_ndnpeekpoke/test_ndnpeekpoke.py
index 257cfbc..8e38c78 100644
--- a/test_ndnpeekpoke/test_ndnpeekpoke.py
+++ b/test_ndnpeekpoke/test_ndnpeekpoke.py
@@ -17,11 +17,13 @@
     def setUp(self):
         print "\nTesting ndn-tlv-peek & ndn-tlv-poke"
         print "***********************************"
+        os.system("mkdir test_ndnpeekpoke/logs/")
 
     def tearDown(self):
         self.killNfd()
         self.killProcess("ndn-tlv-poke")
         self.killProcess("ndn-tlv-peek")
+        os.system("rm -r test_ndnpeekpoke/logs/")
         self.cleanupProcesses()
 
     def test_peekpoke(self):
@@ -33,7 +35,7 @@
             "-> Starting Poke",
             inputFile=pokeInputFile)
         time.sleep(1)
-        peekOutputFile = os.path.abspath("/tmp/test-peek-output.txt")
+        peekOutputFile = os.path.abspath("test_ndnpeekpoke/logs/test-peek-output.txt")
         self.startProcess("ndn-tlv-peek",
             ["ndn-tlv-peek", "ndn:/test/peekpoke"],
             "-> Starting Peek",
diff --git a/test_ndntlvping/README.md b/test_ndntlvping/README.md
index 71daa36..7cbe8a4 100644
--- a/test_ndntlvping/README.md
+++ b/test_ndntlvping/README.md
@@ -7,6 +7,6 @@
 
 ## Description ##
 
-This test case will run the NFD, ndnping and ndnpingserver binaries.
+This test case will run NFD, ndnping and ndnpingserver.
 This will report SUCCESS if one ping interest/data is successfully exchanged between the ndnping and ndnpingserver.
 In all other scenarios, the test case will report FAILURE
diff --git a/test_ndntraffic/README.md b/test_ndntraffic/README.md
index 9baab20..531c651 100644
--- a/test_ndntraffic/README.md
+++ b/test_ndntraffic/README.md
@@ -7,6 +7,6 @@
 
 ## Description ##
 
-This test case will run the NFD, ndn-traffic and ndn-traffic-server binaries.
+This test case will run NFD, ndn-traffic and ndn-traffic-server.
 This will report SUCCESS if one interest/data is successfully exchanged without any data inconsistency between ndn-traffic and ndn-traffic-server.
 In all other scenarios, the test case will report FAILURE