Add nfdc and nfd-status integration test
refs: #1388
Change-Id: Ic9b181dfb333a9543b1d319e03713325d70c933e
diff --git a/test_nfdc/README.md b/test_nfdc/README.md
new file mode 100644
index 0000000..25f3d89
--- /dev/null
+++ b/test_nfdc/README.md
@@ -0,0 +1,66 @@
+Test Case - nfdc and nfd-status
+=====================
+
+## Topology ##
+A-B connected on same IPv4 subnet and same IPv6 subnet. Both are NDN nodes.
+
+Script is invoked on host A.
+multi-host.conf defines: CTRL_B, IP4_A1, IP6_A1, IP4_B1, IP6_B1
+
+
+## Description ##
+The script runs 3 test cases:
+A: Test nfdc create / add-nexthop / destroy test case
+B: Test nfdc add-nexthop / remove-nexthop test case
+C: Test nfdc register / unregister test case
+
+In case of a failure, the detailed log can be found under:
+A: test_nfdc/log/nfdc_test_A.log
+B: test_nfdc/log/nfdc_test_B.log
+C: test_nfdc/log/nfdc_test_C.log
+
+## Test case A: Test nfdc create / add-nexthop / destroy test case ##
+Start NFD on host A and B.
+On host A, run the following steps:
+
+1. Execute nfd-status. Check the existence of udp4/udp6/ether multicast faces.
+2. Invoke nfdc create tcp://$IP4_B1. Pause 2 seconds for connection establishment.
+3. Execute nfd-status. Check the existence of new tcp4 face.
+4. Invoke nfdc create tcp://[$IP6_B1]. Pause 2 seconds for connection establishment.
+5. Execute nfd-status. Check the existence of new tcp6 face.
+6. Invoke nfdc create udp://$IP4_B1. Pause 2 seconds for connection establishment.
+7. Execute nfd-status. Check the existence of new udp4 face.
+8. Invoke nfdc create udp://[$IP6_B1]. Pause 2 seconds for connection establishment.
+9. Execute nfd-status. Check the existence of new udp6 face.
+10. Invoke nfdc to add a nexthop for ndn:/test-nfdc with cost 24 toward FaceId created in step 3.
+11. Invoke nfdc to add a nexthop for ndn:/test-nfdc with cost 26 toward FaceId created in step 5.
+12. Invoke nfdc to add a nexthop for ndn:/test-nfdc with cost 14 toward FaceId created in step 7.
+13. Invoke nfdc to add a nexthop for ndn:/test-nfdc with cost 16 toward FaceId created in step 9.
+14. Execute nfd-status. Check the existence of ndn:/test-nfdc FIB entry, and the correctness of cost on nexthop records.
+15. Invoke nfdc to choose BroadcastStrategy for ndn:/ namespace.
+16. Invoke ndn-tlv-ping to send 100 Interests under ndn:/test-nfdc prefix.
+17. Pause 50ms before sending each Interest.
+18. Execute nfd-status. Verify NOutInterests counters of faces created in step 3,5,7,9 are greater than 60.
+19. On host B, execute nfd-status. Check the existence of tcp4, tcp6, udp4, udp6 faces with host A's address. Verify NInInterests counters for those faces are greater than 60.
+20. Invoke nfdc to destroy FaceIds created in step 3,5.
+21. Execute nfd-status. Check the non-existence of tcp4 and tcp6 faces.
+
+## Test case B: Test nfdc add-nexthop / remove-nexthop test case ##
+Start NFD on host A and B.
+On host A, run the following steps:
+
+1. Invoke nfdc add-nexthop -c 44 ndn:/test-nfdc udp4://$IP4_B1. Pause 2 seconds for connection establishment.
+2. Execute nfd-status. Check the existence of new udp4 face. Check the existence of ndn:/test-nfdc FIB entry, and the correctness of cost on nexthop records.
+3. Invoke nfdc to remove the nexthop for FaceId seen in step 3.
+4. Execute nfd-status. Check the non-existence of ndn:/test-nfdc FIB entry.
+
+## Test case C: Test nfdc register / unregister test case ##
+Start NFD on host A and B.
+On host A, run the following steps:
+1. run nrd on host A
+2. Invoke nfdc register -c 55 ndn:/test-nfdc udp4://$IP4_B1. Pause 2 seconds for connection establishment.
+3. Execute nfd-status. Check the existence of new udp4 face. Check the existence of ndn:/test-nfdc FIB entry, and the correctness of cost on nexthop records.
+4. Invoke nfdc to unregister the prefix ndn:/test-nfdc for FaceId seen in step 3.
+5. Execute nfd-status. Check the non-existence of ndn:/test-nfdc FIB entry.
+
+
diff --git a/test_nfdc/__init__.py b/test_nfdc/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test_nfdc/__init__.py
diff --git a/test_nfdc/include.sh b/test_nfdc/include.sh
new file mode 100755
index 0000000..5f1c491
--- /dev/null
+++ b/test_nfdc/include.sh
@@ -0,0 +1,120 @@
+#!/usr/bin/env bash
+NUM_OF_PINGS=10
+
+# clean up - kill nfd
+clean_up() {
+ r=$(ssh $CTRL_B "sudo killall nfd" 2>&1)
+ r=$(sudo killall nfd 2>&1)
+
+ if [[ $testCase == 'C' ]]; then
+ r=$(sudo killall nrd 2>&1)
+ fi
+}
+
+start_nfd() {
+ # start nfd on localhost
+ sudo nfd &> $workdir/logs/nfd.log &
+
+ # start nfd on hostB
+ ssh $CTRL_B "mkdir -p $workdir/logs ; sudo nfd &> $workdir/logs/nfd.log &\
+ sleep 2"
+ sleep 2
+}
+
+start_nrd() {
+ # start nfd on localhost
+ sudo nrd &> $workdir/logs/nrd.log &
+
+ sleep 2
+}
+
+
+check_nfd_status_counters() {
+ faceId=$1
+ faceUri=$2
+ counterType=$3
+ threshold=$4
+
+ outCounter=$(nfd-status | grep -iF 'faceid='$faceId' remote='$faceUri | grep -Po $counterType={[0-9]+ | sed 's/'$counterType'={//')
+
+
+ if [[ $outCounter -lt $threshold ]]; then
+ if [[ "out" = $counterType ]]; then
+ echo "nfd-status: out counter of face=$faceId is less than $threshold " >> $testLog
+ echo "nfd-status is:" >> $testLog
+ nfd-status >> $testLog
+ clean_up
+ fi
+ exit 2
+
+ fi
+
+}
+
+# check for the existence of the face
+# param list: $1 - face Id
+# $2 - face Uri
+check_nfd_status_face_existence() {
+ faceId=$1
+ faceUri=$2
+
+ # check for the existence of the face
+ # First, get the face line
+ # Second, extract the face id attached to the fetched line
+ face=$(nfd-status | grep -iF remote=$faceUri | grep -Po faceid=\[0-9\]+ | sed 's/faceid=//')
+
+ if [[ "none" != $faceId ]]; then
+ if [[ $face != $faceId ]]; then
+ echo "nfd-status: Failed to find face $faceId of $faceUri" >> $testLog
+ echo "nfd-status is:" >> $testLog
+ nfd-status >> $testLog
+ echo "-1"
+ else
+ echo $face
+ fi
+ else
+ echo $face
+ fi
+
+}
+
+
+# This function checks for the existence of a face and a fib entry
+# including nexthop records
+# param list: $1 - face Id
+# $2 - face Uri
+# $3 - prefix
+# $4 - cost
+check_nfd_status_correctness() {
+ faceId=$1
+ faceUri=$2
+ prefix=$3
+ cost=$4
+
+ face=$(check_nfd_status_face_existence $faceId $faceUri)
+ if [[ "-1" = $face ]]; then
+ clean_up
+ exit 2
+ fi
+
+ # check the existence of prefix FIB entry
+ fibEntry=$(nfd-status | grep $prefix)
+ if [[ -z "$fibEntry" ]]; then
+ echo "nfd-status: Failed to find $prefix in FIB table" >> $testLog
+ echo "nfd-status is:" >> $testLog
+ nfd-status >> $testLog
+ clean_up
+ exit 2
+ fi
+
+ # check the correctness of cost on nexthop records
+ fibEntryCost=$(echo $fibEntry | grep -Po 'faceid='$faceId'.\(cost=[0-9]+\)' | sed 's/faceid='$faceId' //' | sed 's/(cost=//' | sed 's/)//')
+
+ if [[ $cost != $fibEntryCost ]]; then
+ echo "nfd-status: nexthop records are incorrect, expected cost is $cost, cost in records $fibEntryCost" >> $testLog
+ echo "nfd-status is:" >> $testLog
+ nfd-status >> $testLog
+ clean_up
+ exit 2
+ fi
+}
\ No newline at end of file
diff --git a/test_nfdc/nfdc-test.sh b/test_nfdc/nfdc-test.sh
new file mode 100755
index 0000000..24966cd
--- /dev/null
+++ b/test_nfdc/nfdc-test.sh
@@ -0,0 +1,181 @@
+#!/usr/bin/env bash
+source ../multi-host.conf
+source include.sh
+workdir=$(pwd)
+mkdir -p $workdir/logs
+testCase=$1
+testLog=$workdir/logs/nfdc_test_$testCase.log
+
+echo "TEST START" > $testLog
+
+start_nfd
+
+# run test case A: test nfdc create / add-nexthop / destroy test case
+if [[ $testCase == 'A' ]]; then
+
+ # Check for the existence of mcast address udp4://224.0.23.170
+ udp4Mcast=$(nfd-status | grep udp4://224.0.23.170)
+ udp6Mcast=$(nfd-status | grep -iF udp6://[ff00)
+ ethv4=$(nfd-status | grep -iF ether://[01:00:5E:)
+ ethv6=$(nfd-status | grep -iF ether://[33:33:)
+
+ if [[ -z "$udp4Mcast" ]] && [[ -z "$udp6Mcast" ]] && [[ -z "$ethv4" ]] && [[ -z "$ethv6" ]]; then
+ echo "nfd-status: Failed to find udp4/udp6/ether multicast faces" >> $testLog
+ echo "nfd-status is:" >> $testLog
+ nfd-status >> $testLog
+ clean_up
+ exit 2
+ fi
+
+ # Invoke nfdc create tcp://$IP4_B1.
+ faceIdTcp4=$(nfdc create tcp4://$IP4_B1 | grep -Po 'FaceId: .*?,' | sed 's/FaceId: //' | sed 's/,//')
+ sleep 2
+ face=$(check_nfd_status_face_existence $faceIdTcp4 tcp4://$IP4_B1)
+ if [ "-1" = $face ]; then
+ clean_up
+ exit 2
+ fi
+
+ #compress IPv6
+ IP6_B1=$(python -c "import sys; import socket; result = socket.getaddrinfo('$IP6_B1', None); family, socktype, proto, canonname,(address, port, flow_info, scope_id) = result[0]; print address")
+
+ # Invoke nfdc create tcp://$IP6_B1.
+ faceIdTcp6=$(nfdc create tcp6://[$IP6_B1] | grep -Po 'FaceId: .*?,' | sed 's/FaceId: //' | sed 's/,//')
+ sleep 2
+ face=$(check_nfd_status_face_existence $faceIdTcp6 tcp6://[$IP6_B1])
+ if [ "-1" = $face ]; then
+ clean_up
+ exit 2
+ fi
+
+ # Invoke nfdc create udp://$IP4_B1.
+ faceIdUdp4=$(nfdc create udp4://$IP4_B1 | grep -Po 'FaceId: .*?,' | sed 's/FaceId: //' | sed 's/,//')
+ sleep 2
+
+ face=$(check_nfd_status_face_existence $faceIdUdp4 udp4://$IP4_B1)
+ if [ "-1" = $face ]; then
+ clean_up
+ exit 2
+ fi
+
+
+ # Invoke nfdc create udp://$IP6_B1.
+ faceIdUdp6=$(nfdc create udp6://[$IP6_B1] | grep -Po 'FaceId: .*?,' | sed 's/FaceId: //' | sed 's/,//')
+ sleep 2
+ face=$(check_nfd_status_face_existence $faceIdUdp6 udp6://[$IP6_B1])
+ if [ "-1" = $face ]; then
+ clean_up
+ exit 2
+ fi
+
+ # Invoke nfdc to add next hops
+ nfdc add-nexthop -c 24 ndn:/test-nfdc $faceIdTcp4
+ nfdc add-nexthop -c 26 ndn:/test-nfdc $faceIdTcp6
+ nfdc add-nexthop -c 14 ndn:/test-nfdc $faceIdUdp4
+ nfdc add-nexthop -c 16 ndn:/test-nfdc $faceIdUdp6
+
+ # check correctness of add-nexthop -c 24 ndn:/test-nfdc $faceIdTcp4
+ check_nfd_status_correctness $faceIdTcp4 tcp4://$IP4_B1 /test-nfdc 24
+
+ # check correctness of add-nexthop -c 26 ndn:/test-nfdc $faceIdTcp6
+ check_nfd_status_correctness $faceIdTcp6 tcp6://[$IP6_B1] /test-nfdc 26
+
+ # check correctness of add-nexthop -c 14 ndn:/test-nfdc $faceIdUdp4
+ check_nfd_status_correctness $faceIdUdp4 udp4://$IP4_B1 /test-nfdc 14
+
+ # check correctness of add-nexthop -c 16 ndn:/test-nfdc $faceIdUdp6
+ check_nfd_status_correctness $faceIdUdp6 udp6://[$IP6_B1] /test-nfdc 16
+
+ # Invoke nfdc to choose BroadcastStrategy for ndn:/ namespace.
+ nfdc set-strategy ndn:/ ndn:/localhost/nfd/strategy/broadcast
+
+ ndnping ndn:/test-nfdc -c $NUM_OF_PINGS
+
+ check_nfd_status_counters $faceIdTcp4 tcp4://$IP4_B1 out $NUM_OF_PINGS
+ check_nfd_status_counters $faceIdTcp6 tcp6://[$IP6_B1] out $NUM_OF_PINGS
+ check_nfd_status_counters $faceIdUdp4 udp4://$IP4_B1 out $NUM_OF_PINGS
+ check_nfd_status_counters $faceIdUdp6 udp6://[$IP6_B1] out $NUM_OF_PINGS
+
+ ssh $CTRL_B "$workdir/test-B.sh $workdir"
+ if [[ $? -ne 0 ]]; then
+ echo "Failed to verify correctness on node B" >> $testLog
+ clean_up
+ exit 3
+ fi
+
+ nfdc destroy $faceIdTcp4
+ echo "after nfdc destroy $faceIdTcp4" >> $testLog
+ face=$(check_nfd_status_face_existence $faceIdTcp4 tcp4://$IP4_B1)
+ if [ "-1" != $face ]; then
+ echo "face $faceIdTcp4 still exists after nfdc destory" >> $testLog
+ clean_up
+ exit 2
+ fi
+
+ nfdc destroy $faceIdTcp6
+ echo "after nfdc destroy $faceIdTcp6" >> $testLog
+ face=$(check_nfd_status_face_existence $faceIdTcp6 tcp6://[$IP6_B1])
+ if [ "-1" != $face ]; then
+ clean_up
+ exit 2
+ fi
+
+ clean_up
+
+# run test case B: nfdc add-nexthop / remove-nexthop test case
+elif [[ $testCase == 'B' ]]; then
+
+ # Invoke nfdc to add next hop
+ faceId=$(nfdc add-nexthop -c 44 ndn:/test-nfdc udp4://$IP4_B1 | grep -Po 'FaceId: .*?,' | sed 's/FaceId: //' | sed 's/,//')
+ if [[ "ERROR" == $faceId* ]]
+ then
+ echo "nfdc: Failed to add nexthop for $IP4_B1" >> $testLog
+ clean_up
+ exit 1
+ fi
+
+ check_nfd_status_correctness $faceId udp4://$IP4_B1 /test-nfdc 44
+
+ # invoke nfdc to remove the nexthop for created FaceId
+ removeNextHop=$(nfdc remove-nexthop ndn:/test-nfdc $faceId)
+
+ # check the existence of ndn:/test-nfdc FIB entry
+ fibEntry=$(nfd-status | grep /test-nfdc)
+ if [ ! -z "$fibEntry" ]; then
+ echo "nfd-status: Failed to delete ndn:/test-nfdc FIB entry" >> $testLog
+ clean_up
+ exit 2
+ fi
+ clean_up
+
+# run test case C: test nfdc register / unregister test case
+elif [[ $testCase == 'C' ]]; then
+
+ # run nrd
+ start_nrd
+
+ # Invoke nfdc register a new prefix
+ faceId=$(nfdc register -c 55 ndn:/test-nfdc udp4://$IP4_B1 | grep -Po 'FaceId: .*?,' | sed 's/FaceId: //' | sed 's/,//')
+ if [[ "ERROR" == $faceId* ]]; then
+ echo "nfdc: Failed to register ndn:/test-nfdc for $IP4_B1" >> $testLog
+ clean_up
+ exit 1
+ fi
+ check_nfd_status_correctness $faceId udp4://$IP4_B1 /test-nfdc 55
+
+ # Invoke nfdc to unregister the prefix
+ unregisterPrefix=$(nfdc unregister ndn:/test-nfdc $faceId)
+
+ # check the existence of ndn:/test-nfdc FIB entry
+ fibEntry=$(nfd-status | grep /test-nfdc)
+ if [ ! -z "$fibEntry" ]; then
+ echo "nfd-status: Failed to unregister prefix" >> $testLog
+ clean_up
+ exit 2
+ fi
+ clean_up
+fi
+
+clean_up
+exit 0
+
diff --git a/test_nfdc/test-B.sh b/test_nfdc/test-B.sh
new file mode 100755
index 0000000..fad09d0
--- /dev/null
+++ b/test_nfdc/test-B.sh
@@ -0,0 +1,50 @@
+#!/usr/bin/env bash
+workDir=$1
+source $workDir/../multi-host.conf
+source $workDir/include.sh
+
+#compress IPv6
+IP6_A1=$(python -c "import sys; import socket; result = socket.getaddrinfo('$IP6_A1', None); family, socktype, proto, canonname,(address, port, flow_info, scope_id) = result[0]; print address")
+
+remoteFaceIdUdp4=$(check_nfd_status_face_existence none udp4://$IP4_A1)
+if [[ -z "$remoteFaceIdUdp4" ]]; then
+ exit 3
+fi
+
+remoteFaceIdTcp4=$(check_nfd_status_face_existence none tcp4://$IP4_A1)
+if [[ -z "$remoteFaceIdTcp4" ]]; then
+ exit 3
+fi
+
+remoteFaceIdUdp6=$(check_nfd_status_face_existence none udp6://[$IP6_A1])
+if [[ -z "$remoteFaceIdUdp6" ]]; then
+ exit 3
+fi
+
+remoteFaceIdTcp6=$(check_nfd_status_face_existence none tcp6://[$IP6_A1])
+if [[ -z "$remoteFaceIdTcp6" ]]; then
+ exit 3
+fi
+
+check_nfd_status_counters $remoteFaceIdUdp4 udp4://$IP4_A1 'in' $NUM_OF_PINGS
+if [[ $? -ne 0 ]]; then
+ exit 3
+fi
+
+check_nfd_status_counters $remoteFaceIdTcp4 tcp4://$IP4_A1 'in' $NUM_OF_PINGS
+if [[ $? -ne 0 ]]; then
+ exit 3
+fi
+
+check_nfd_status_counters $remoteFaceIdUdp6 udp6://[$IP6_A1] 'in' $NUM_OF_PINGS
+if [[ $? -ne 0 ]]; then
+ exit 3
+fi
+
+check_nfd_status_counters $remoteFaceIdTcp6 tcp6://[$IP6_A1] 'in' $NUM_OF_PINGS
+if [[ $? -ne 0 ]]; then
+ exit 3
+fi
+
+
+exit 0
diff --git a/test_nfdc/test_nfdc.py b/test_nfdc/test_nfdc.py
new file mode 100644
index 0000000..79afcc4
--- /dev/null
+++ b/test_nfdc/test_nfdc.py
@@ -0,0 +1,48 @@
+#!/usr/bin/python2
+# -*- Mode:python; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+#
+# Copyright (C) 2014 Washington University in St. Louis
+# Author: Hila Ben Abraham <hila@wustl.edu>
+# See COPYING for copyright and distribution information.
+#
+
+import os
+import unittest
+import subprocess
+
+class test_nfdc(unittest.TestCase):
+ """Test case for testing nfdc and nfd-status applications"""
+
+ def setUp(self):
+ print "\nTesting nfdc and nfd-status"
+ print "*****************************"
+ os.chdir("test_nfdc")
+ os.system("mkdir -p logs")
+
+ def tearDown(self):
+ print "********************************"
+ os.chdir("..")
+
+ def test_nfdc_A(self):
+ print ">>> TEST CASE A: test nfdc create / add-nexthop / destroy test case <<<"
+ ret = subprocess.call(["./nfdc-test.sh A"], shell=True)
+ if ret != 0:
+ self.fail(" >> TEST CASE A FAILED")
+ else:
+ print ">> TEST CASE A PASSED SUCCESSFULLY"
+
+ def test_nfdc_B(self):
+ print ">>> TEST CASE B: test nfdc add-nexthop / remove-nexthop test case <<<"
+ ret = subprocess.call(["./nfdc-test.sh B"], shell=True)
+ if ret != 0:
+ self.fail(" >> TEST CASE B FAILED")
+ else:
+ print ">> TEST CASE B PASSED SUCCESSFULLY"
+
+ def test_nfdc_C(self):
+ print ">>> TEST CASE C: test nfdc register / unregister test case <<<"
+ ret = subprocess.call(["./nfdc-test.sh C"], shell=True)
+ if ret != 0:
+ self.fail(" >> TEST CASE C FAILED")
+ else:
+ print ">> TEST CASE C PASSED SUCCESSFULLY"
\ No newline at end of file