route-expiration-test: Add route expiration test

refs: #1717

Change-Id: If8901d086b7f54ae6fbf42a2168bc4967ed9bc58
diff --git a/test_route_expiration/README.md b/test_route_expiration/README.md
new file mode 100644
index 0000000..8642bc3
--- /dev/null
+++ b/test_route_expiration/README.md
@@ -0,0 +1,33 @@
+# Route expiration test scenario
+
+Test that routes in the RIB expire when expected
+
+1.  Start NFD (including RIB Daemon) on A,B,C
+
+2.  Add the following routes on A:
+      ndn:/P , nexthop=hostB, expiration=10s
+      ndn:/P , nexthop=hostC, expiration=20s
+      ndn:/Q , nexthop=hostB, expiration=20s
+      ndn:/R , nexthop=hostC, expiration=10s
+      ndn:/S , nexthop=hostB, expiration=3600s
+
+3.  Delay 5 seconds; run nfd-status on A to inspect RIB
+    Expected routes:
+      ndn:/P (hostB expires in 3-8s, hostC expires in 13-18s)
+      ndn:/Q (hostB expires in 13-18s)
+      ndn:/R (hostC expires in 3-8s)
+      ndn:/S (hostB expires in >3000s)
+
+4.  Delay 10 seconds; run nfd-status on A to inspect RIB
+    Expected routes:
+      ndn:/P (hostC expires in 3-8s)
+      ndn:/Q (hostB expires in 3-8s)
+      ndn:/R : entry does not exist
+      ndn:/S (hostB expires in >3000s)
+
+5.  Delay 8 seconds; run nfd-status on A to inspect RIB
+    Expected routes:
+      ndn:/P : entry does not exist
+      ndn:/Q : entry does not exist
+      ndn:/R : entry does not exist
+      ndn:/S (hostB expires in >3000s)
diff --git a/test_route_expiration/include.sh b/test_route_expiration/include.sh
new file mode 100644
index 0000000..047a8d3
--- /dev/null
+++ b/test_route_expiration/include.sh
@@ -0,0 +1,86 @@
+#!/usr/bin/env bash
+
+source ../multi-host.conf
+
+start_nfd() {
+  sudo nfd &> $workdir/logs/nfd.log &
+  ssh $CTRL_B "sudo nfd &"
+  sleep 2
+}
+
+start_nrd() {
+  sudo nrd &> $workdir/logs/nrd.log &
+  ssh $CTRL_B "sudo nrd &"
+  sleep 2
+}
+
+set_up() {
+  workdir=$(pwd)
+  mkdir -p $workdir/logs
+
+  start_nfd
+  start_nrd
+}
+
+clean_up() {
+  nfd-stop
+  exit 0
+}
+
+register() {
+  name=$1
+  expirationPeriod=$2
+  nextHop=$3
+
+  result=$(nfdc register -e $(($expirationPeriod * 1000)) $name udp4://$nextHop | grep -o 'FaceId: [0-9]*' | sed s/'FaceId: '//)
+  echo $result
+}
+
+is_expiration_period_correct() {
+  name=$1
+  nextHop=$2
+  lowerBound=$3
+  upperBound=$4
+
+  expirationPeriod=$(nfd-status -r | grep -iF ''$name'' | grep -o 'faceid='$nextHop' ([a-zA-Z0-9 =]*)' |\
+                     grep -o 'expires=[0-9]*' | sed 's/'expires='//')
+
+  if [[ "$expirationPeriod" -lt $lowerBound || "$expirationPeriod" -gt $upperBound ]]; then
+    echo $name "has an expiration period of $expirationPeriod seconds which is not between the expected $lowerBound-$upperBound seconds"
+    exit 1
+  else
+    echo $name "has a correct expiration period between $lowerBound and $upperBound seconds"
+  fi
+}
+
+expect_entry_does_not_exist() {
+  name=$1
+
+  count=$(nfd-status -r | grep -c ' $name ')
+
+  if [[ $count -gt 0 ]]; then
+    echo $name "exists past its expected expiration period."
+    exit 2
+  else
+    echo $name "has expired successfully"
+  fi
+}
+
+expect_route_does_not_exist() {
+  name=$1
+  faceId=$2
+
+  count=$(nfd-status -r | grep -iF ''$name'' | grep -c 'faceid='$faceId'')
+
+  if [[ $count -gt 0 ]]; then
+    echo "Route for $name with FaceId: $faceId exists past its expected expiration period."
+    exit 2
+  else
+    echo "Route for $name with FaceId: $faceId has expired successfully"
+  fi
+}
+
+sleep_for_seconds() {
+  echo -e "Sleeping for $1 seconds...\n"
+  sleep $1
+}
\ No newline at end of file
diff --git a/test_route_expiration/route-expiration-test.sh b/test_route_expiration/route-expiration-test.sh
new file mode 100755
index 0000000..42361a5
--- /dev/null
+++ b/test_route_expiration/route-expiration-test.sh
@@ -0,0 +1,41 @@
+#!/usr/bin/env bash
+
+source include.sh
+
+HOST_B=$IP4_B1
+HOST_C=$IP4_C1
+
+set_up
+
+echo "Registering routes..."
+
+P_TO_B_FACE=$(register "/P" 10 $HOST_B)
+P_TO_C_FACE=$(register "/P" 20 $HOST_C)
+Q_TO_B_FACE=$(register "/Q" 20 $HOST_B)
+R_TO_C_FACE=$(register "/R" 10 $HOST_C)
+S_TO_B_FACE=$(register "/S" 3600 $HOST_B)
+
+sleep_for_seconds 5
+
+is_expiration_period_correct "/P" $P_TO_B_FACE 3 8
+is_expiration_period_correct "/P" $P_TO_C_FACE 13 18
+is_expiration_period_correct "/Q" $Q_TO_B_FACE 13 18
+is_expiration_period_correct "/R" $R_TO_C_FACE 3 8
+is_expiration_period_correct "/S" $S_TO_B_FACE 3000 3600
+
+sleep_for_seconds 10
+
+is_expiration_period_correct "/P" $P_TO_C_FACE 3 8
+expect_route_does_not_exist  "/P" $P_TO_B_FACE
+is_expiration_period_correct "/Q" $Q_TO_B_FACE 3 8
+expect_entry_does_not_exist  "/R"
+is_expiration_period_correct "/S" $S_TO_B_FACE 3000 3600
+
+sleep_for_seconds 8
+
+expect_entry_does_not_exist  "/P"
+expect_entry_does_not_exist  "/Q"
+expect_entry_does_not_exist  "/R"
+is_expiration_period_correct "/S" $S_TO_B_FACE 3000 3600
+
+clean_up
diff --git a/test_route_expiration/test_route_expiration.py b/test_route_expiration/test_route_expiration.py
new file mode 100644
index 0000000..bef4309
--- /dev/null
+++ b/test_route_expiration/test_route_expiration.py
@@ -0,0 +1,31 @@
+#!/usr/bin/python2
+# -*- Mode:python; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+#
+# Copyright (C) 2014 The University of Memphis
+# Author: Vince Lehman <vslehman@memphis.edu>
+# See COPYING for copyright and distribution information.
+#
+
+import os
+import unittest
+import subprocess
+
+class test_route_expiration(unittest.TestCase):
+    """Test case for NRD route expiration"""
+
+    def setUp(self):
+        print "\nTesting NRD route expiration"
+        print "***********"
+        os.chdir("test_route_expiration")
+
+    def tearDown(self):
+        print "***********"
+        os.chdir("..")
+
+    def test_nrd(self):
+        ret = subprocess.call(["./route-expiration-test.sh"], shell=True)
+
+        if ret != 0:
+            self.fail("NRD route expiration test FAILED")
+        else:
+            print "NRD route expiration test PASSED"