automatic prefix propagation test scenario

Change-Id: I515981054466f656602cc47ae02355ee264330fa
refs: #3218
diff --git a/test_auto_prefix_propagate/A.sh b/test_auto_prefix_propagate/A.sh
new file mode 100755
index 0000000..ab82d7f
--- /dev/null
+++ b/test_auto_prefix_propagate/A.sh
@@ -0,0 +1,191 @@
+#!/usr/bin/env bash
+defaultIdentity=
+repoDir="test-repo"
+repoConf="$repoDir/test.conf"
+repoDataPrefix='ndn:/Z'
+repoHost='localhost'
+repoPort='9527'
+nfdConf='host.nfd.conf'
+systemNfdConf='/usr/local/etc/ndn/nfd.conf'
+testLog='host.test.log'
+nfdLog='host.nfd.log'
+
+LOG() {
+    echo "[A] $1"
+    echo "[A] $1" >>$testLog
+}
+
+kill_process() {
+    # $1: name of process
+    if [[ $# -lt 1 ]]; then
+        echo "require name of process"
+        exit 1
+    fi
+
+    if pgrep -x $1 > /dev/null; then
+        sudo -b killall -w "$1" >>$testLog 2>&1
+    fi
+}
+
+delete_identity() {
+    # $1: name of identity
+    identity=$1 && identity=${identity#ndn:}
+    if [[ $(ndnsec-list | grep -c "$identity$") -gt 0 ]]; then
+        LOG " deleting identity $1"
+        ndnsec-delete $identity >>$testLog 2>&1
+    else
+        LOG " identity $identity does not exist"
+    fi
+}
+
+clean_up() {
+    LOG "Killing processeses"
+    kill_process "ndn-repo-ng"
+    kill_process "nfd"
+    kill_process "ndnpingserver"
+
+    LOG "Deleting repo data"
+    [[ -d $repoDir ]] && rm -rf $repoDir
+
+    LOG "Deleting identities"
+    delete_identity ndn:/Z
+    delete_identity ndn:/Z/A
+    delete_identity ndn:/Z/A/rib
+    delete_identity ndn:/Z/A/B/C
+    delete_identity ndn:/Z/A/B/C/D/E/rib
+    delete_identity ndn:/Z/F
+
+    if [[ -n "$defaultIdentity" ]]; then
+        if [[ $(ndnsec-list | grep -c "$defaultIdentity$") -gt 0 ]]; then
+            ndnsec-set-default $defaultIdentity
+        fi
+    else
+        r=$(ndnsec-list)
+        if [[ -n "$r" ]]; then
+            r=`echo "$r" | tr "\n" "-"`
+            r=${r%%-*} && r=${r#*/} && r="/$r"
+            ndnsec-set-default $r
+        fi
+    fi
+}
+
+create_identity() {
+    # $1: creating identity
+    # $2: signing identity
+    if [[ $# -gt 1 ]]; then
+        ndnsec-key-gen -n $1 > tmp.req
+        ndnsec-cert-gen -N "tmp" -s $2 -r tmp.req > tmp.cert; rm tmp.req
+        ndnsec-cert-install tmp.cert >>$testLog 2>&1
+        [[ -f tmp.cert ]] && rm tmp.cert
+    elif [[ $# -gt 0 ]]; then
+        ndnsec-key-gen -n $1 | ndnsec-cert-install - >>$testLog 2>&1
+    else
+        echo "require input identity"
+        exit 1
+    fi
+}
+
+publish_default_cert() {
+    # $1: name of identity
+    if [[ $# -lt 1 ]]; then
+        echo "require identity to publish cert"
+        exit 1
+    fi
+
+    if [[ "$1"x = "${1#${repoDataPrefix}}"x ]]; then
+        echo "can not publish $1 under $repoDataPrefix"
+        exit 1
+    fi
+
+    ndnsec-cert-dump -r -H $repoHost -P $repoPort -i $1
+}
+
+start_repo() {
+    LOG "create repo dir config file for repo"
+    [[ -d $repoDir ]] || mkdir -p $repoDir
+
+    echo "" > $repoConf # create repo conf file
+
+    infoedit -f $repoConf -s repo.data.prefix -v $repoDataPrefix
+    infoedit -f $repoConf -s repo.command.prefix -v ""
+    infoedit -f $repoConf -s repo.storage.method -v sqlite
+    infoedit -f $repoConf -s repo.storage.path -v $repoDir
+    infoedit -f $repoConf -s repo.storage.max-packets -v 100
+    infoedit -f $repoConf -s repo.tcp_bulk_insert.host -v $repoHost
+    infoedit -f $repoConf -s repo.tcp_bulk_insert.port -v $repoPort
+    infoedit -f $repoConf -s repo.validator.trust-anchor.type -v any
+
+    kill_process ndn-repo-ng
+    LOG "start repo-ng"
+    nohup ndn-repo-ng -c $repoConf >>$testLog 2>&1 &
+}
+
+start_nfd() {
+    LOG "create nfd conf file with auto_prefix_propagate section specified for test"
+    [[ ! -f $systemNfdConf ]] && LOG "can not find nfd config file" && exit 1
+
+    cp $systemNfdConf $nfdConf
+    infoedit -f $nfdConf -s rib.auto_prefix_propagate.cost -v 15
+    infoedit -f $nfdConf -s rib.auto_prefix_propagate.timeout -v 10000
+    infoedit -f $nfdConf -s rib.auto_prefix_propagate.base_retry_wait -v 50
+    infoedit -f $nfdConf -s rib.auto_prefix_propagate.max_retry_wait -v 3600
+    infoedit -f $nfdConf -s rib.auto_prefix_propagate.refresh_interval -v 15
+
+    kill_process nfd
+    LOG "start NFD"
+    sudo nohup nfd --config $nfdConf >>$nfdLog 2>&1 &
+}
+
+prepare_for_test() {
+    echo "Start test log on end host" >$testLog
+    echo "Start nfd log on end host" >$nfdLog
+
+    start_nfd && sleep 2
+
+    start_repo && sleep 2
+
+    defaultIdentity=$(ndnsec-get-default)
+
+    # create identities and publish their certificates
+    LOG "create identity /Z/A and publish its cert"
+    create_identity ndn:/Z/A
+    publish_default_cert ndn:/Z/A
+
+    LOG "create identity /Z/A/nrd and publish its cert"
+    create_identity ndn:/Z/A/rib ndn:/Z/A
+    publish_default_cert ndn:/Z/A/rib
+
+    LOG "create identity /Z/A/B/C and publish its cert"
+    create_identity ndn:/Z/A/B/C ndn:/Z/A
+    publish_default_cert ndn:/Z/A/B/C
+
+    LOG "create identity /Z/F and publish its cert"
+    create_identity ndn:/Z/F
+    publish_default_cert ndn:/Z/F
+}
+
+generate_anchor() {
+    certFile='auto-propagate.anchor.cert'
+    ndnsec-export -o $certFile $1 >>$testLog 2>&1
+    cert=$(cat $certFile) && rm $certFile
+    echo $cert
+}
+
+while getopts "a:cp" arg
+    do
+        case $arg in
+             a)
+                 generate_anchor $OPTARG
+                 ;;
+             c)
+                 clean_up
+                 ;;
+             p)
+                 prepare_for_test
+                 ;;
+             ?)
+                 echo "unknown argument"
+        exit 1
+        ;;
+        esac
+done
diff --git a/test_auto_prefix_propagate/B.sh b/test_auto_prefix_propagate/B.sh
new file mode 100755
index 0000000..4784a31
--- /dev/null
+++ b/test_auto_prefix_propagate/B.sh
@@ -0,0 +1,153 @@
+#!/usr/bin/env bash
+
+defaultIdentity=
+hubIdentity='/auto-prefix-propagate/hub'
+nfdConf='hub.nfd.conf'
+systemNfdConf='/usr/local/etc/ndn/nfd.conf'
+testLog='hub.test.log'
+nfdLog='hub.nfd.log'
+
+LOG() {
+    echo "[B] $1"
+    echo "[B] $1" >>$testLog
+}
+
+kill_process() {
+    # $1: name of process
+    if [[ $# -lt 1 ]]; then
+        echo "require process name"
+        exit 1
+    fi
+
+    if pgrep -x $1 > /dev/null; then
+        sudo -b killall -w "$1" >>$testLog 2>&1
+    fi
+}
+
+delete_identity() {
+    # $1: name of identity
+    if [[ $(ndnsec-list | grep -c "$1$") -gt 0 ]]; then
+        LOG " deleting identity $1!"
+        ndnsec-delete $1 >>$testLog 2>&1
+    else
+        LOG " identity $1 does not exist"
+    fi
+}
+
+clean_up() {
+    LOG "Killing NFD process!"
+    kill_process nfd
+    kill_process ndn-autoconfig-server
+
+    LOG "Deleting the hub identity"
+    delete_identity "$hubIdentity"
+
+    LOG "Reset the default identity"
+    if [[ -n "$defaultIdentity" ]]; then
+        if [[ $(ndnsec-list | grep -c "$defaultIdentity$") -gt 0 ]]; then
+            ndnsec-set-default $defaultIdentity
+        fi
+    else
+        r=$(ndnsec-list)
+        if [[ -n "$r" ]]; then
+            r=`echo "$r" | tr "\n" "-"`
+            r=${r%%-*} && r=${r#*/} && r="/$r"
+            ndnsec-set-default $r
+        fi
+    fi
+}
+
+prepare_for_test() {
+    echo "Start test log on remote hub" >$testLog
+    echo "Start nfd log on remote hub" >$nfdLog
+
+    LOG "Create hub identity as the default identity"
+    defaultIdentity=$(ndnsec-get-default)
+    ndnsec-key-gen $hubIdentity | ndnsec-cert-install - >>$testLog 2>&1
+
+    LOG "create nfd conf file with localhop_security section specified for test"
+    [[ ! -f $systemNfdConf ]] && LOG "can not find nfd config file" && exit 1
+
+    # copy the config file to the working directory
+    cp $systemNfdConf $nfdConf
+
+    # set UDP face timeout to 35 seconds
+    infoedit -f $nfdConf -s face_system.udp.idle_timeout -v 35
+
+    # insert a rule section to validate Interest
+    cat <<EOF | infoedit -f $nfdConf -a rib.localhop_security.rule
+id "NRD Prefix Registration Command Rule"
+for interest
+filter
+{
+   type name
+   regex ^[<localhop><localhost>]<nfd><rib>[<register><unregister>]<>$
+}
+checker
+{
+   type customized
+   sig-type rsa-sha256
+   key-locator
+   {
+      type name
+      regex ^[^<KEY>]*<KEY><>*[<ksk-.*>]<ID-CERT>$
+   }
+}
+EOF
+
+    #insert a rule section to validate Data
+    cat <<EOF | infoedit -f $nfdConf -a rib.localhop_security.rule
+id "NDN Testbed Hierarchy Rule"
+for data
+filter
+{
+  type name
+  regex ^[^<KEY>]*<KEY><>*[<ksk-.*>]<ID-CERT><>*$
+}
+checker
+{
+  type customized
+  sig-type rsa-sha256
+  key-locator
+  {
+    type name
+    regex ^[^<KEY>]*<KEY><>*[<ksk-.*>]<ID-CERT>$
+  }
+}
+EOF
+
+    #insert a trust-anchor section
+    cat <<EOF | infoedit -f $nfdConf -a rib.localhop_security.trust-anchor
+type file
+file-name anchor.cert
+EOF
+
+    #delete remote_register section
+    infoedit -f $nfdConf -d rib.auto_prefix_propagate
+
+    kill_process nfd
+    LOG "start NFD"
+    sudo -b nohup nfd --config $nfdConf >>$nfdLog 2>&1 &
+    sleep 2
+
+    LOG "set multicast strategy for ndn:/"
+    nfdc set-strategy ndn:/ ndn:/localhost/nfd/strategy/multicast >>$testLog 2>&1
+    LOG "set autoreg prefix to /Z"
+    nfd-autoreg --prefix=/Z >> $testLog 2>&1 &
+}
+
+while getopts "a:cp" arg
+    do
+        case $arg in
+             c)
+                 clean_up
+                 ;;
+             p)
+                 prepare_for_test
+                 ;;
+             ?)
+                 echo "unknown argument"
+        exit 1
+        ;;
+        esac
+done
diff --git a/test_auto_prefix_propagate/README.md b/test_auto_prefix_propagate/README.md
new file mode 100644
index 0000000..065918a
--- /dev/null
+++ b/test_auto_prefix_propagate/README.md
@@ -0,0 +1,69 @@
+Test Case - automatic prefix propagation test scenario
+=====================
+
+## Topology
+A--B
+
+A is a NDN host while B is the remote hub / gateway router.
+IPv4 udp tunnel is used.
+
+Script is invoked on host A. It can control B via ssh
+
+## Description
+The script test automatic prefix propagation procedure.
+In case of a failure, the detailed log can be found under:
+test_auto_prefix_propagate/logs/auto_prefix_propagate.log
+
+## Steps
+1. generate certificates on A for these identities, in RIB daemon's KeyChain:
+    ndn:/Z/A self-signed
+    ndn:/Z/A/nrd signed by ndn:/Z/A
+    ndn:/Z/A/B/C signed by ndn:/Z/A
+    ndn:/Z/F self-signed
+
+2. configure NFD on A:
+    enable automatic prefix propagation
+    set automatic prefix propagation refresh time to 15 seconds
+    put all certificates generated in step 1 except ndn:/Z/A into NFD's KeyChain
+
+3. configure NFD on B:
+    set UDP face timeout to 35 seconds
+    enable acceptance of prefix registration using ndn:/localhop/nfd/rib command prefix
+    make ndn:/Z/A the trust anchor for prefix registration using ndn:/localhop/nfd/rib command prefix
+    set multicast strategy for ndn:/
+
+4. start NFD on A,B
+
+5. start repo-ng on A to listen on ndn:/ prefix, and put all certificates generated in step 1 into this repo via TCP bulk insert protocol
+
+6. start nfd-autoreg --prefix=/Z on B
+
+7. execute nfdc on A to create a face toward B over UDP
+
+8. start ndnpingserver for ndn:/Z/A/G on A, defer 5 seconds
+9. inspect RIB on B, fail the test case if route for ndn:/Z/A toward A exists
+
+10. execute nfdc on A to register a route for ndn:/localhop/nfd on the
+face created in step 7, defer 5 seconds
+11. inspect RIB on B, fail the test case if route for ndn:/Z/A toward A does not exist
+
+12. start ndnpingserver for ndn:/Z/A/H on A, defer 5 seconds
+13. inspect RIB on B, fail the test case if route for ndn:/Z/A toward A does not exist
+
+14. stop ndnpingserver from step 8, defer 5 seconds
+15. inspect RIB on B, fail the test case if route for ndn:/Z/A toward A does not exist
+
+16. stop ndnpingserver from step 13, defer 5 seconds
+17. inspect RIB on B, fail the test case if route for ndn:/Z/A toward A exists
+
+18. start ndnpingserver for ndn:/Z/A/B/C/D on A, defer 5 seconds
+19. inspect RIB on B, fail the test case if route for ndn:/Z/A/B/C toward A exists, fail the test case if route for ndn:/Z/A toward A does not exist
+
+20. defer 80 seconds
+21. inspect RIB on B, fail the test case if route for ndn:/Z/A toward A does not exist
+
+22. start ndnpingserver for ndn:/Z/F/I on A, defer 5 seconds
+23. inspect RIB on B, fail the test case if route for ndn:/Z/F toward A exists
+
+## Return value
+PASS of all tests finished successfully.
diff --git a/test_auto_prefix_propagate/auto-prefix-propagate-test.sh b/test_auto_prefix_propagate/auto-prefix-propagate-test.sh
new file mode 100755
index 0000000..eb7e8db
--- /dev/null
+++ b/test_auto_prefix_propagate/auto-prefix-propagate-test.sh
@@ -0,0 +1,127 @@
+#!/usr/bin/env bash
+source ../multi-host.conf
+workDir=$(pwd)
+logDir=$workDir/logs
+hubIP=$CTRL_B
+testLog=$logDir/auto-prefix-propagate.log
+hostSh=A.sh
+hubSh=B.sh
+
+echo "TEST AUTOMATIC PREFIX PROPAGATE START" > $testLog
+
+LOG () {
+    echo $1; echo $1 >>$testLog
+}
+
+run_hub_cmd () {
+    ssh $hubIP "$1" 2>&1
+}
+
+run_scp_to_hub () {
+    scp $1 $hubIP:$workDir/$1 2>&1
+}
+
+set_hub_trust_anchor () {
+    LOG "set the trust anchor to $1 on the hub."
+    anchor=$(sh $hostSh -a $1)
+    echo $anchor > anchor.cert
+    run_scp_to_hub anchor.cert && rm anchor.cert
+}
+
+run_host_ping_server() {
+    ndnpingserver $1 >>$testLog 2>&1 &
+}
+
+end_test() {
+    scp $hubIP:$workDir/hub.nfd.log hub.nfd.log 2>&1
+    scp $hubIP:$workDir/hub.test.log hub.test.log 2>&1
+    cat host.nfd.log hub.nfd.log > nfd.log
+    cat host.test.log hub.test.log > test.log
+    cat nfd.log test.log >> $testLog
+
+    bash $hostSh -c && run_hub_cmd "cd $workDir && bash $hubSh -c"
+    run_hub_cmd "[[ -d $workDir ]] && sudo rm -rf $workDir"
+    rm *.log
+
+    [[ $# -gt 0 ]] && LOG "$1" && exit 1 || exit 0
+}
+
+inspect_hub_rib_exist() {
+    record=$(run_hub_cmd "nfd-status -r" | grep "$1 route")
+    if [[ -z "$record" ]]; then
+        end_test "Fail test $2"
+    fi
+}
+
+inspect_hub_rib_none() {
+    record=$(run_hub_cmd "nfd-status -r" | grep "$1 route")
+    if [[ ! -z "$record" ]]; then
+        end_test "Fail test $2. the matched record: $record"
+    fi
+}
+
+run_test() {
+    faceUri=udp4://$hubIP:6363
+    nfdc create $faceUri >> $testLog
+
+    defer_time=5
+
+    LOG "run test case: 1"
+    run_host_ping_server ndn:/Z/A/G && p1=$! && sleep $defer_time
+    inspect_hub_rib_none /Z/A "1: route of /Z/A exists, but propagation should not be active \
+as the /localhop/nfd prefix has not been registered to the local RIB now."
+
+    LOG "run test case: 2"
+    nfdc register ndn:/localhop/nfd $faceUri >> $testLog && sleep $defer_time
+    inspect_hub_rib_exist /Z/A "2: route of /Z/A does not exist, but it should exist because \
+automatic prefix propagation is active (/localhop/nfd prefix has been registered), Z/A/G is \
+present in local RIB and /Z/A has been configured as an identity in NFD's keychain."
+    inspect_hub_none /Z/A/G "2: route of /Z/A/G exists, but it should not exist because \
+/Z/A is shorter and should be adopted for propagation."
+
+    LOG "run test case: 3"
+    run_host_ping_server ndn:/Z/A/H && p2=$! && sleep $defer_time
+    inspect_hub_rib_exist /Z/A "3: route of /Z/A does not exist, but it should exist because \
+/Z/A has already been propagated."
+    inspect_hub_none /Z/A/H "3: route of /Z/A/H exists, but it should not exist because \
+/Z/A is shorter and should be adopted for propagation."
+
+    LOG "run test case: 4"
+    sudo kill $p1 1>> $testLog 2>&1 && sleep $defer_time
+    inspect_hub_rib_exist /Z/A "4: route of /Z/A was unregistered, it should be kept for \
+local RIB entry /Z/A/H."
+
+    LOG "run test case: 5"
+    sudo kill $p2 1>> $testLog 2>&1 && sleep $defer_time
+    inspect_hub_rib_none /Z/A "5: route of /Z/A still exists, but it should have been \
+automatically unregistered, because all /Z/H/* prefixes have been unregistered locally."
+
+    LOG "run test case: 6"
+    run_host_ping_server ndn:/Z/A/B/C/D && p3=$! && sleep $defer_time
+    inspect_hub_rib_none /Z/A/B/C "6: route of /Z/A/B/C exist, but it should not be \
+propagated because /Z/A is a better choice."
+    inspect_hub_rib_exist /Z/A "6: route of /Z/A does not exist, but it should have \
+been propagated."
+
+    LOG "run test case: 7"
+    sleep 80
+    inspect_hub_rib_exist /Z/A "7: route of /Z/A/ does not exist, it should have been \
+refreshed periodically."
+
+    LOG "run test case: 8"
+    run_host_ping_server ndn:/Z/F/I && sleep $defer_time
+    inspect_hub_rib_none /Z/F "8: route of /Z/F exist, but automatic prefix propagation \
+should not be active becuase there are no configured keys for the covering namespace."
+}
+
+LOG "set environment in the host."
+bash $hostSh -c -p
+
+LOG "set environment in the hub."
+run_hub_cmd "[[ -d $workDir ]] || mkdir -p $workDir"
+run_scp_to_hub $hubSh
+set_hub_trust_anchor ndn:/Z/A
+run_hub_cmd "cd $workDir && bash $hubSh -c -p"
+
+LOG "run test"
+run_test && end_test
diff --git a/test_auto_prefix_propagate/test_auto_prefix_propagate.py b/test_auto_prefix_propagate/test_auto_prefix_propagate.py
new file mode 100644
index 0000000..5819d1f
--- /dev/null
+++ b/test_auto_prefix_propagate/test_auto_prefix_propagate.py
@@ -0,0 +1,28 @@
+#!/usr/bin/python2
+
+import os
+import unittest
+import subprocess
+
+class test_auto_prefix_propagate(unittest.TestCase):
+    """Test case for testing NDN Automatic Prefix Propagation"""
+
+    def setUp(self):
+        print "\nTesting NDN automatic prefix propagation"
+        print "*****************************"
+        os.chdir("test_auto_prefix_propagate")
+        os.system("mkdir -p logs")
+
+    def tearDown(self):
+        print "********************************"
+        os.chdir("..")
+
+    def test_remote_register(self):
+        print ">>> test automatic prefix propagation <<<"
+
+        ret = subprocess.call(['./auto-prefix-propagate-test.sh'], shell=True)
+
+        if (ret != 0):
+            self.fail(" >> TEST AUTOMATIC PROPAGATE PROCEDURE FAILED")
+        else:
+            print ">> TEST AUTOMATIC PROPAGATE PROCEDURE PASSED SUCCESSFULLY"