diff options
Diffstat (limited to 'tests')
-rw-r--r-- | tests/.env | 13 | ||||
-rw-r--r-- | tests/2-nodes-hicn-light.yml | 65 | ||||
-rw-r--r-- | tests/2-nodes-vpp-bridge.yml | 107 | ||||
-rw-r--r-- | tests/2-nodes-vpp-memif-replication.yml | 143 | ||||
-rw-r--r-- | tests/2-nodes-vpp-memif.yml | 116 | ||||
-rw-r--r-- | tests/2-nodes.yml | 43 | ||||
-rw-r--r-- | tests/Dockerfile.ci | 5 | ||||
-rwxr-xr-x | tests/channel.sh | 22 | ||||
-rwxr-xr-x | tests/config.sh | 290 | ||||
-rw-r--r-- | tests/forwarder.robot | 45 | ||||
-rw-r--r-- | tests/functional-tests/2-nodes-hicn-light.robot | 24 | ||||
-rw-r--r-- | tests/functional-tests/2-nodes-vpp-bridge.robot | 24 | ||||
-rw-r--r-- | tests/functional-tests/2-nodes-vpp-memif-replication.robot | 23 | ||||
-rw-r--r-- | tests/functional-tests/2-nodes-vpp-memif.robot | 23 | ||||
-rw-r--r-- | tests/resources/libraries/robot/common.robot | 23 | ||||
-rw-r--r-- | tests/resources/libraries/robot/runtest.robot | 92 | ||||
-rw-r--r-- | tests/run-functional.sh | 40 | ||||
-rw-r--r-- | tests/test_forwarder.sh | 437 |
18 files changed, 1535 insertions, 0 deletions
diff --git a/tests/.env b/tests/.env new file mode 100644 index 000000000..35c861bda --- /dev/null +++ b/tests/.env @@ -0,0 +1,13 @@ +# Topologies +TOPOLOGY_2_NODES=2-nodes + +# Container names +TEST_LIGHT=hicn-light +TEST_VPP_BRIDGE=vpp-bridge +TEST_VPP_MEMIF=vpp-memif +TEST_VPP_MEMIF_REPLICATION=vpp-memif-replication + +# names +RTC_PRODUCER=b002::1 +RAAQM_PRODUCER=b002::2 +PING_PRODUCER=b002::3 diff --git a/tests/2-nodes-hicn-light.yml b/tests/2-nodes-hicn-light.yml new file mode 100644 index 000000000..e62a6c705 --- /dev/null +++ b/tests/2-nodes-hicn-light.yml @@ -0,0 +1,65 @@ +version: "3" +services: + client: + container_name: ${TEST_LIGHT}-client + command: + - | + if [ -d /workspace/build-dev ]; then + ninja -C /workspace/build-dev install + fi + + sudo ip link add br0 type bridge + sudo ip addr add 192.168.1.1/24 dev br0 + sudo ip link set eth0 master br0 + sudo ip link set eth0 up + sudo ip link set br0 up + sudo ip route add 192.168.1.2 via 192.168.1.1 dev br0 + tee -a /tmp/hicn-light.conf <<EOF + add listener udp local0 192.168.1.1 9199 br0 + add connection udp conn0 192.168.1.2 9199 192.168.1.1 9199 + add route conn0 b002::/64 1 + EOF + + rm -f /tmp/lite_client.log + + sudo hicn-light-daemon \ + --daemon \ + --log-file /tmp/lite_client.log \ + --config /tmp/hicn-light.conf --capacity 0 + + tail -f /dev/null + + server: + container_name: ${TEST_LIGHT}-server + command: + - | + if [ -d /workspace/build-dev ]; then + ninja -C /workspace/build-dev install + fi + + sudo ip link add br0 type bridge + sudo ip addr add 192.168.1.2/24 dev br0 + sudo ip link set eth0 master br0 + sudo ip link set eth0 up + sudo ip link set br0 up + + tee -a /tmp/hicn-light.conf <<EOF + add listener udp local0 192.168.1.2 9199 br0 + add connection udp conn0 192.168.1.1 9199 192.168.1.2 9199 + add route conn0 b002::/64 1 + EOF + + rm -f /tmp/lite_server.log + + sudo hicn-light-daemon \ + --daemon \ + --log-file /tmp/lite_server.log \ + --config /tmp/hicn-light.conf --capacity 0 + + sleep 4 + + hiperf -z hicnlightng_module -D -S -R -B 4000kbps ${RTC_PRODUCER}/128 + hiperf -z hicnlightng_module -D -S ${RAAQM_PRODUCER}/128 + hicn-ping-server -z hicnlightng_module -d -s 0 -n ${PING_PRODUCER}/128 + + tail -f /dev/null diff --git a/tests/2-nodes-vpp-bridge.yml b/tests/2-nodes-vpp-bridge.yml new file mode 100644 index 000000000..d9426844f --- /dev/null +++ b/tests/2-nodes-vpp-bridge.yml @@ -0,0 +1,107 @@ +version: "3" +services: + client: + container_name: ${TEST_VPP_BRIDGE}-client + volumes: + - ..:/workspace + command: + - | + if [ -d /workspace/build-dev ]; then + ninja -C /workspace/build-dev install + fi + + sudo ip link add br0 type bridge + sudo ip link set eth0 master br0 + sudo ip link set eth0 up + sudo ip link set br0 up + sudo mkdir -p /var/log/vpp + sudo tee /etc/vpp/startup.conf <<EOF + cpu { main-core 1 } + plugins { + path /usr/lib/x86_64-linux-gnu/vpp_plugins:/usr/lib/vpp_plugins + plugin default { disable } + plugin acl_plugin.so { enable } + plugin nat_plugin.so { enable } + plugin dhcp_plugin.so { enable } + plugin dpdk_plugin.so { enable } + plugin dns_plugin.so { enable } + plugin ping_plugin.so { enable } + plugin memif_plugin.so { enable } + plugin nsim_plugin.so { enable } + plugin hicn_plugin.so { enable } + } + + unix { + startup-config /etc/vpp/client-up.txt + cli-listen /run/vpp/cli.sock + log /var/log/vpp/vpp.log + } + EOF + + sudo tee /etc/vpp/client-up.txt <<EOF + create tap id 0 host-bridge br0 + set int state tap0 up + set int ip addr tap0 192.168.1.1/24 + set int ip addr tap0 2001::1/64 + ip route add b002::1/64 via 2001::2 tap0 + EOF + + sudo vpp -c /etc/vpp/startup.conf + sleep 5 + sudo vppctl hicn enable b002::1/64 + + tail -f /dev/null + + server: + container_name: ${TEST_VPP_BRIDGE}-server + volumes: + - ..:/workspace + command: + - | + if [ -d /workspace/build-dev ]; then + ninja -C /workspace/build-dev install + fi + + sudo ip link add br0 type bridge + sudo ip link set eth0 master br0 + sudo ip link set eth0 up + sudo ip link set br0 up + sudo mkdir -p /var/log/vpp + sudo tee /etc/vpp/startup.conf <<EOF + cpu { main-core 2 } + plugins { + path /usr/lib/x86_64-linux-gnu/vpp_plugins:/usr/lib/vpp_plugins + plugin default { disable } + plugin acl_plugin.so { enable } + plugin nat_plugin.so { enable } + plugin dhcp_plugin.so { enable } + plugin dpdk_plugin.so { enable } + plugin dns_plugin.so { enable } + plugin ping_plugin.so { enable } + plugin memif_plugin.so { enable } + plugin nsim_plugin.so { enable } + plugin hicn_plugin.so { enable } + } + unix { + startup-config /etc/vpp/server-up.txt + cli-listen /run/vpp/cli.sock + log /var/log/vpp/vpp.log + } + EOF + sudo tee /etc/vpp/server-up.txt <<EOF + create tap id 0 host-bridge br0 + set int state tap0 up + set int ip addr tap0 192.168.1.12/24 + set int ip addr tap0 2001::2/64 + EOF + + sudo vpp -c /etc/vpp/startup.conf + sleep 5 + + sudo hiperf -D -S -R -B 4000kbps -z memif_module ${RTC_PRODUCER}/128 + sleep 1 + sudo hiperf -D -S -z memif_module ${RAAQM_PRODUCER}/128 + sleep 1 + sudo hicn-ping-server -d -s 0 -n ${PING_PRODUCER}/128 -z memif_module + + tail -f /dev/null diff --git a/tests/2-nodes-vpp-memif-replication.yml b/tests/2-nodes-vpp-memif-replication.yml new file mode 100644 index 000000000..37f028dac --- /dev/null +++ b/tests/2-nodes-vpp-memif-replication.yml @@ -0,0 +1,143 @@ +version: "3" +services: + vpp_client_memif: + build: + context: .. + dockerfile: ${DOCKERFILE} + args: + BASE_IMAGE: ${BASE_IMAGE} + stdin_open: true + tty: true + working_dir: /workspace + container_name: ${TEST_VPP_MEMIF_REPLICATION}-client + hostname: client + volumes: + - /tmp/memif:/memif + - ..:/workspace + entrypoint: [/bin/bash, -c] + command: + - | + if [ -d /workspace/build-dev ]; then + ninja -C /workspace/build-dev install + fi + + sudo mkdir -p /var/log/vpp + sudo tee /etc/vpp/startup.conf <<EOF + cpu { main-core 1 } + buffers { buffers-per-numa 600000 } + plugins { + path /hicn-root/lib/vpp_plugins:/usr/lib/x86_64-linux-gnu/vpp_plugins:/usr/lib/vpp_plugins + plugin default { disable } + plugin acl_plugin.so { enable } + plugin nat_plugin.so { enable } + plugin dhcp_plugin.so { enable } + plugin dpdk_plugin.so { enable } + plugin dns_plugin.so { enable } + plugin ping_plugin.so { enable } + plugin memif_plugin.so { enable } + plugin nsim_plugin.so { enable } + plugin hicn_plugin.so { enable } + } + + unix { + startup-config /etc/vpp/client-up.txt + cli-listen /run/vpp/cli.sock + log /var/log/vpp/vpp.log + } + EOF + + sudo tee /etc/vpp/client-up.txt <<EOF + create memif socket id 1 filename /memif/memif1.sock + create interface memif id 0 socket-id 1 hw-addr aa:bb:cc:dd:ee:01 master + set int state memif1/0 up + set int ip addr memif1/0 192.168.1.1/24 + set int ip addr memif1/0 2001::1/64 + set ip neighbor memif1/0 2001::2 aa:bb:cc:dd:ee:02 static + ip route add b002::1/64 via 2001::2 memif1/0 + create interface memif id 1 socket-id 1 hw-addr aa:bb:bb:bb:ee:01 master + set int state memif1/1 up + set int ip addr memif1/1 192.168.2.1/24 + set int ip addr memif1/1 2002::1/64 + set ip neighbor memif1/1 2002::2 aa:bb:bb:bb:ee:02 static + ip route add b002::1/64 via 2002::2 memif1/1 + EOF + + sudo rm /memif/memif1.sock + + sudo vpp -c /etc/vpp/startup.conf + sleep 5 + + sudo vppctl hicn enable b002::1/64 + sudo vppctl hicn strategy set 2 prefix b002::/64 + + tail -f /dev/null + vpp_server_memif: + build: + context: .. + dockerfile: ${DOCKERFILE} + args: + BASE_IMAGE: ${BASE_IMAGE} + stdin_open: true + tty: true + working_dir: /workspace + container_name: ${TEST_VPP_MEMIF_REPLICATION}-server + hostname: server + volumes: + - /tmp/memif:/memif + - ..:/workspace + entrypoint: [/bin/bash, -c] + command: + - | + if [ -d /workspace/build-dev ]; then + ninja -C /workspace/build-dev install + fi + + sudo mkdir -p /var/log/vpp + sudo tee /etc/vpp/startup.conf <<EOF + cpu { main-core 2 } + buffers { buffers-per-numa 600000 } + + plugins { + path /hicn-root/lib/vpp_plugins:/usr/lib/x86_64-linux-gnu/vpp_plugins:/usr/lib/vpp_plugins + plugin default { disable } + plugin acl_plugin.so { enable } + plugin nat_plugin.so { enable } + plugin dhcp_plugin.so { enable } + plugin dpdk_plugin.so { enable } + plugin dns_plugin.so { enable } + plugin ping_plugin.so { enable } + plugin memif_plugin.so { enable } + plugin nsim_plugin.so { enable } + plugin hicn_plugin.so { enable } + } + unix { + startup-config /etc/vpp/server-up.txt + cli-listen /run/vpp/cli.sock + log /var/log/vpp/vpp.log + } + EOF + + sudo tee /etc/vpp/server-up.txt <<EOF + create memif socket id 1 filename /memif/memif1.sock + create interface memif id 0 socket-id 1 hw-addr aa:bb:cc:dd:ee:02 slave + set int state memif1/0 up + set int ip addr memif1/0 192.168.1.2/24 + set int ip addr memif1/0 2001::2/64 + set ip neighbor memif1/0 2001::1 aa:bb:cc:dd:ee:01 static + create interface memif id 1 socket-id 1 hw-addr aa:bb:bb:bb:ee:02 slave + set int state memif1/1 up + set int ip addr memif1/1 192.168.2.2/24 + set int ip addr memif1/1 2002::2/64 + set ip neighbor memif1/1 2002::1 aa:bb:bb:bb:ee:01 static + EOF + + sudo vpp -c /etc/vpp/startup.conf + sleep 10 + + sudo hiperf -D -S -R -B 4000kbps -z memif_module ${RTC_PRODUCER}/128 + sleep 5 + sudo hiperf -D -S -z memif_module ${RAAQM_PRODUCER}/128 + sleep 5 + sudo hicn-ping-server -d -s 0 -n ${PING_PRODUCER}/128 -z memif_module + + tail -f /dev/null diff --git a/tests/2-nodes-vpp-memif.yml b/tests/2-nodes-vpp-memif.yml new file mode 100644 index 000000000..034437dbc --- /dev/null +++ b/tests/2-nodes-vpp-memif.yml @@ -0,0 +1,116 @@ +version: "3" +services: + client: + container_name: ${TEST_VPP_MEMIF}-client + networks: [] + volumes: + - /tmp/memif:/memif + - ..:/workspace + command: + - | + if [ -d /workspace/build-dev ]; then + ninja -C /workspace/build-dev install + fi + + sudo mkdir -p /var/log/vpp + sudo tee /etc/vpp/startup.conf <<EOF + cpu { main-core 1 } + buffers { buffers-per-numa 600000 } + plugins { + path /usr/lib/x86_64-linux-gnu/vpp_plugins:/usr/lib/vpp_plugins + plugin default { disable } + plugin acl_plugin.so { enable } + plugin nat_plugin.so { enable } + plugin dhcp_plugin.so { enable } + plugin dpdk_plugin.so { enable } + plugin dns_plugin.so { enable } + plugin ping_plugin.so { enable } + plugin memif_plugin.so { enable } + plugin nsim_plugin.so { enable } + plugin hicn_plugin.so { enable } + } + + unix { + startup-config /etc/vpp/client-up.txt + cli-listen /run/vpp/cli.sock + log /var/log/vpp/vpp.log + } + EOF + + sudo tee /etc/vpp/client-up.txt <<EOF + comment { Creating memif } + create memif socket id 1 filename /memif/memif1.sock + create interface memif id 0 socket-id 1 mode ip master + set int state memif1/0 up + comment { Configuring memif } + set int ip addr memif1/0 192.168.1.1/24 + set int ip addr memif1/0 2001::1/64 + comment { Add route } + ip route add b002::1/64 via 2001::2 memif1/0 + EOF + + sudo rm /memif/memif1.sock + sudo vpp -c /etc/vpp/startup.conf + sleep 5 + + sudo vppctl hicn enable b002::1/64 + + tail -f /dev/null + + server: + container_name: ${TEST_VPP_MEMIF}-server + networks: [] + volumes: + - /tmp/memif:/memif + - ..:/workspace + command: + - | + if [ -d /workspace/build-dev ]; then + ninja -C /workspace/build-dev install + fi + + sudo mkdir -p /var/log/vpp + sudo tee /etc/vpp/startup.conf <<EOF + cpu { main-core 2 } + buffers { buffers-per-numa 600000 } + + plugins { + path /usr/lib/x86_64-linux-gnu/vpp_plugins:/usr/lib/vpp_plugins + plugin default { disable } + plugin acl_plugin.so { enable } + plugin nat_plugin.so { enable } + plugin dhcp_plugin.so { enable } + plugin dpdk_plugin.so { enable } + plugin dns_plugin.so { enable } + plugin ping_plugin.so { enable } + plugin memif_plugin.so { enable } + plugin nsim_plugin.so { enable } + plugin hicn_plugin.so { enable } + } + unix { + startup-config /etc/vpp/server-up.txt + cli-listen /run/vpp/cli.sock + log /var/log/vpp/vpp.log + } + EOF + + sudo tee /etc/vpp/server-up.txt <<EOF + comment { Creating memif } + create memif socket id 1 filename /memif/memif1.sock + create interface memif id 0 socket-id 1 mode ip slave + set int state memif1/0 up + comment { Configuring memif } + set int ip addr memif1/0 192.168.1.2/24 + set int ip addr memif1/0 2001::2/64 + EOF + + sudo vpp -c /etc/vpp/startup.conf + sleep 10 + + sudo hiperf -D -S -R -B 4000kbps -z memif_module ${RTC_PRODUCER}/128 + sleep 5 + sudo hiperf -D -S -z memif_module ${RAAQM_PRODUCER}/128 + sleep 5 + sudo hicn-ping-server -d -s 0 -n ${PING_PRODUCER}/128 -z memif_module + + tail -f /dev/null diff --git a/tests/2-nodes.yml b/tests/2-nodes.yml new file mode 100644 index 000000000..ce87e5876 --- /dev/null +++ b/tests/2-nodes.yml @@ -0,0 +1,43 @@ +version: "3" +services: + client: + build: + context: .. + dockerfile: ${DOCKERFILE} + args: + BASE_IMAGE: ${BASE_IMAGE} + privileged: true + stdin_open: true + hostname: client + tty: true + working_dir: /workspace + networks: + - kernel + volumes: + - ..:/workspace + entrypoint: [/bin/bash, -x, -c] + command: + - tail -f /dev/null + + server: + build: + context: .. + dockerfile: ${DOCKERFILE} + args: + BASE_IMAGE: ${BASE_IMAGE} + privileged: true + stdin_open: true + hostname: server + tty: true + working_dir: /workspace + networks: + - kernel + volumes: + - ..:/workspace + entrypoint: [/bin/bash, -x, -c] + command: + - tail -f /dev/null + +networks: + kernel: + driver: bridge diff --git a/tests/Dockerfile.ci b/tests/Dockerfile.ci new file mode 100644 index 000000000..29f2e9dac --- /dev/null +++ b/tests/Dockerfile.ci @@ -0,0 +1,5 @@ +ARG BASE_IMAGE + +FROM ${BASE_IMAGE} + +RUN sudo sed -i 's,secure_path="\(.*\)",secure_path="/hicn-root/bin:\1",' /etc/sudoers diff --git a/tests/channel.sh b/tests/channel.sh new file mode 100755 index 000000000..28a187e72 --- /dev/null +++ b/tests/channel.sh @@ -0,0 +1,22 @@ +#!/bin/bash + +set -e + +DEV=$2 +RATE=$3mbit +DELAY=$4ms +JITTER=$5ms +LOSS=$6 + +if [[ $1 -eq "set" ]]; then + tc qdisc add dev "$DEV" root handle 1:0 htb default 1 + tc class add dev "$DEV" parent 1:0 classid 1:1 htb rate "$RATE" + tc qdisc add dev "$DEV" parent 1:1 handle 2:0 netem delay "$DELAY" + "$JITTER" loss random "$LOSS" + echo "Dev: $DEV, rate: $RATE, delay: $DELAY, jitter: $JITTER, loss: $LOSS%" +elif [[ $1 -eq "change" ]]; then + tc qdisc change dev "$DEV" parent 1:1 handle 2:0 netem delay "$DELAY" "$JITTER" loss random "$LOSS" + echo "Dev: $DEV, rate: $RATE, delay: $DELAY, jitter: $JITTER, loss: $LOSS%" +else + echo "set or change" +fi diff --git a/tests/config.sh b/tests/config.sh new file mode 100755 index 000000000..bcd27e0b9 --- /dev/null +++ b/tests/config.sh @@ -0,0 +1,290 @@ +#!/usr/bin/env bash + +set -euo pipefail + +SCRIPT_PATH=$( + cd "$(dirname "${BASH_SOURCE}")" + pwd -P +) + +# Import test configurations and names +source ${SCRIPT_PATH}/.env + +set -a +DOCKERFILE=${DOCKERFILE:-Dockerfile.dev} +BASE_IMAGE=${BASE_IMAGE:-hicn} +BUILD_SOFTWARE=${BUILD_SOFTWARE:-1} +set +a + +HIPERF_CMD_RTC="hiperf -n 50 -C -H -R ${RTC_PRODUCER}" +HIPERF_CMD_MEMIF_RTC="${HIPERF_CMD_RTC} -z memif_module" +POSTPROCESS_COMMAND_RAAQM_RTC='tail -n +3 | \ + tr -s " " | \ + cut -f 4 -d " " | \ + sort -n | \ + tail -n 40 | \ + head -n 35 | \ + awk "BEGIN { \ + c=0; \ + s=0; \ + }{ \ + a[n++]=\$1; \ + s+=\$1; \ + } END { \ + print int(a[0]), int(a[n-1]), int(s/n) \ + }"' + +HIPERF_CMD_RAAQM="hiperf -n 50 -i 200 -C -H ${RAAQM_PRODUCER}" +HIPERF_CMD_CBR="${HIPERF_CMD_RAAQM} -W 350 -M 0" +HIPERF_CMD_MEMIF_RAAQM="${HIPERF_CMD_RAAQM} -z memif_module" +HIPERF_CMD_MEMIF_CBR="${HIPERF_CMD_CBR} -z memif_module" + +PING_CMD="hicn-ping-client -m 50 -i 200000 -n ${PING_PRODUCER}" +PING_CMD_MEMIF="${PING_CMD} -z memif_module" +POSTPROCESS_COMMAND_PING='grep trip | \ + cut -f 4 -d " " | \ + sort -n | \ + tail -n 40 | \ + head -n 35 | \ + awk "BEGIN { \ + c=0; \ + s=0; \ + }{ \ + a[n++]=\$1; \ + s+=\$1; \ + } END { \ + print int(a[0]), int(a[n-1]), int(s/n) \ + }"' + +declare -a topologies +declare -a configurations + +# Fill topology array using the same values in the .env file +for topology in $(compgen -A variable | grep TOPOLOGY_); do + topologies+=("${!topology}") +done + +# Fill configurations array using the same values in the .env file +for test in $(compgen -A variable | grep TEST_); do + configurations+=("${!test}") +done + +declare -A tests=( + ["hicn-light-rtc"]="${HIPERF_CMD_RTC} | tee >(>&2 cat) | ${POSTPROCESS_COMMAND_RAAQM_RTC}" + ["vpp-bridge-rtc"]="${HIPERF_CMD_MEMIF_RTC} | tee >(>&2 cat) | ${POSTPROCESS_COMMAND_RAAQM_RTC}" + ["vpp-memif-rtc"]="${HIPERF_CMD_MEMIF_RTC} | tee >(>&2 cat) | ${POSTPROCESS_COMMAND_RAAQM_RTC}" + ["vpp-memif-replication-rtc"]="${HIPERF_CMD_MEMIF_RTC} | tee >(>&2 cat) | ${POSTPROCESS_COMMAND_RAAQM_RTC}" + + ["hicn-light-requin"]="${HIPERF_CMD_RAAQM} | tee >(>&2 cat) | ${POSTPROCESS_COMMAND_RAAQM_RTC}" + ["vpp-bridge-requin"]="${HIPERF_CMD_MEMIF_RAAQM} | tee >(>&2 cat) | ${POSTPROCESS_COMMAND_RAAQM_RTC}" + ["vpp-memif-requin"]="${HIPERF_CMD_MEMIF_RAAQM} | tee >(>&2 cat) | ${POSTPROCESS_COMMAND_RAAQM_RTC}" + ["vpp-memif-replication-requin"]="${HIPERF_CMD_MEMIF_RAAQM} | tee >(>&2 cat) | ${POSTPROCESS_COMMAND_RAAQM_RTC}" + + ["hicn-light-cbr"]="${HIPERF_CMD_CBR} | tee >(>&2 cat) | ${POSTPROCESS_COMMAND_RAAQM_RTC}" + ["vpp-bridge-cbr"]="${HIPERF_CMD_MEMIF_CBR} | tee >(>&2 cat) | ${POSTPROCESS_COMMAND_RAAQM_RTC}" + ["vpp-memif-cbr"]="${HIPERF_CMD_MEMIF_CBR} | tee >(>&2 cat) | ${POSTPROCESS_COMMAND_RAAQM_RTC}" + ["vpp-memif-replication-cbr"]="${HIPERF_CMD_MEMIF_CBR} | tee >(>&2 cat) | ${POSTPROCESS_COMMAND_RAAQM_RTC}" + + ["hicn-light-latency"]="${PING_CMD} | tee >(>&2 cat) | ${POSTPROCESS_COMMAND_PING}" + ["vpp-bridge-latency"]="${PING_CMD_MEMIF} | tee >(>&2 cat) | ${POSTPROCESS_COMMAND_PING}" + ["vpp-memif-latency"]="${PING_CMD_MEMIF} | tee >(>&2 cat) | ${POSTPROCESS_COMMAND_PING}" + ["vpp-memif-replication-latency"]="${PING_CMD_MEMIF} | tee >(>&2 cat) | ${POSTPROCESS_COMMAND_PING}" +) + +declare -A link_model=( + ["500-0-0-0"]="500 0 0 0" + ["500-1-0-0"]="500 1 0 0" + ["500-5-0-0"]="500 5 0 0" + ["500-200-0-0"]="500 200 0 0" + ["100-1-0-0"]="100 1 0 0" + ["100-10-0-0"]="100 10 0 0" + ["100-15-0-0"]="100 15 0 0" + ["200-5-0-0"]="200 5 0 0" + ["300-5-0-0"]="300 5 0 0" + ["400-5-0-0"]="400 5 0 0" + ["1000-1-0-0"]="1000 1 0 0" + ["10-50-1-10"]="10 50 1 10" +) + +function topology_exists() { + [[ "${topologies[*]}" =~ ${1} ]] && return 0 || return 1 +} + +function test_exists() { + [[ "${!tests[*]}" =~ ${1} ]] && return 0 || return 1 +} + +function conf_exists() { + [[ "${configurations[*]}" =~ ${1} ]] && return 0 || return 1 +} + + +# test-name client/server link-model +function setchannel() { + if ! conf_exists "${1}"; then + error "Error: topology does not exist." + fi + + if ! test_exists "${1}"; then + error "Error: test does not exist." + fi + docker exec "${1}-${2}" bash -c "/workspace/tests/config.sh link set br0\ + ${link_model[${3}]}" +} +# test-name client/server link-model +function changechannel() { + if ! conf_exists "${1}"; then + error "Error: topology does not exist." + fi + + if ! test_exists "${1}"; then + error "Error: test does not exist." + fi + docker exec "${1}-${2}" bash -c "/workspace/tests/config.sh link change br0\ + ${link_model[${3}]}" +} + +# channel set/change dev rate delay jitter lossrate +function channel() { + DEV=${2} + RATE=${3}mbit + DELAY=${4}ms + JITTER=${5}ms + LOSS=${6} + if [[ $1 == set ]]; then + sudo tc qdisc add dev "${DEV}" root handle 1:0 htb default 1 + sudo tc class add dev "${DEV}" parent 1:0 classid 1:1 htb rate "$RATE" + sudo tc qdisc add dev "${DEV}" parent 1:1 handle 2:0 netem delay "${DELAY}" \ + "${JITTER}" loss random "${LOSS}" + echo "Dev: ${DEV}, rate: ${RATE}, delay: ${DELAY}, jitter: ${JITTER}, loss: ${LOSS}%" + elif [[ ${1} == change ]]; then + sudo tc qdisc change dev "$DEV" parent 1:1 handle 2:0 netem delay "$DELAY" \ + "${JITTER}" loss random "${LOSS}" + echo "Dev: ${DEV}, rate: ${RATE}, delay: ${DELAY}, jitter: ${JITTER}, loss: ${LOSS}%" + else + sudo tc qdisc del dev "${DEV}" root + echo "set or change" + fi +} +function error() { + echo >&2 "${@}" + return 1 +} + +function build() { + docker-compose -f build.yml build + docker-compose -f build.yml up --force-recreate --remove-orphans >/dev/null +} + +function setup() { + topology=${1} + conf=${2} + + if ! topology_exists "${topology}"; then + error "Error: topology does not exist." + fi + + if ! conf_exists "${conf}"; then + error "Error: topology does not exist." + fi + + docker-compose -f "${topology}".yml -f "${topology}-${conf}".yml build + docker-compose -f "${topology}".yml -f "${topology}-${conf}".yml up --remove-orphans --force-recreate -d + + sleep 10 +} + +function start() { + conf=${1} + test=${2} + + if ! conf_exists "${conf}"; then + error "Error: configuration does not exist." + fi + + TESTNAME="${conf}-${test}" + + if ! test_exists "${TESTNAME}"; then + error "Error: test does not exist." + fi + + docker exec "${1}"-client bash -c "/workspace/tests/config.sh runtest ${tests[${TESTNAME}]}" +} + +function stop() { + topology="${1}" + conf="${2}" + + if ! topology_exists "${topology}"; then + error "Error: topology does not exist." + fi + + if ! conf_exists "${conf}"; then + error "Error: tect configuration does not exist." + fi + + LOG_FILE="${SCRIPT_PATH}/${topology}-${conf}.log" + rm -f "${LOG_FILE}" + docker-compose -f "${topology}".yml -f "${topology}-${conf}".yml down || true +} + +function stopall() { + for topology in "${topologies[@]}"; do + for conf in "${configurations[@]}"; do + stop "${topology}" "${conf}" + done + done +} + +function runtest() { + echo "${@}" | sudo -i +} + +while (("${#}")); do + case "$1" in + 'build') + build + shift + ;; + 'link') + shift + channel "$@" + shift 6 + ;; + 'setchannel') + shift + setchannel "$@" + shift 4 + ;; + 'changechannel') + shift + changechannel "$@" + shift 4 + ;; + 'setup') + setup "${2}" "${3}" + shift 3 + ;; + 'start') + start "${2}" "${3}" + shift 3 + ;; + 'stop') + stop "${2}" "${3}" + shift 3 + ;; + 'stopall') + stopall + shift + ;; + 'runtest') + runtest "${@:2}" + break + ;; + *) + break + ;; + esac +done + +exit 0 diff --git a/tests/forwarder.robot b/tests/forwarder.robot new file mode 100644 index 000000000..60345dbb0 --- /dev/null +++ b/tests/forwarder.robot @@ -0,0 +1,45 @@ +*** Settings *** +Library Process +Test Template Run Test +Test Setup Setup +Test Teardown Teardown +Test Timeout 5 seconds + +*** Variables *** +${cmd} bash test_forwarder.sh + +*** Test Cases *** +# Commands +Add listener test_add_listener +Remove listener test_remove_listener +Remove non-existing listener test_remove_non_existing_listener +Add duplicated listener test_add_duplicated_listener +List listeners test_list_listeners +Commands from config file test_commands_from_config + +# Ping +Ping one packet test_ping_one_packet +Ping two packets test_ping_two_packets +Ping using CS test_ping_using_cs +Ping using CS different order test_ping_using_cs_different_order +Ping timeout test_ping_timeout +Ping aggregation test_ping_aggregation +Ping with CS store disabled test_ping_with_cs_store_disabled +Ping with CS serve disabled test_ping_with_cs_serve_disabled +Ping with eviction test_ping_with_eviction +Ping with zero data lifetime test_ping_with_zero_data_lifetime + +*** Keywords *** +Setup + ${result}= Run Process ${cmd} set_up shell=True + Log Many stdout: ${result.stdout} stderr: ${result.stderr} + +Teardown + ${result}= Run Process ${cmd} tear_down shell=True + Log Many stdout: ${result.stdout} stderr: ${result.stderr} + +Run Test + [Arguments] ${test_name} + ${result}= Run Process ${cmd} ${test_name} shell=True + Log Many stdout: ${result.stdout} stderr: ${result.stderr} + Should Be Equal As Integers ${result.rc} 0
\ No newline at end of file diff --git a/tests/functional-tests/2-nodes-hicn-light.robot b/tests/functional-tests/2-nodes-hicn-light.robot new file mode 100644 index 000000000..9aa5923a0 --- /dev/null +++ b/tests/functional-tests/2-nodes-hicn-light.robot @@ -0,0 +1,24 @@ +*** Settings *** +Resource resources/libraries/robot/runtest.robot +Resource resources/libraries/robot/common.robot +Suite Setup Run Keywords +... Build Topology 2-nodes hicn-light AND +... Check Environment +Suite Teardown Run Keywords +... Destroy Topology +Resource resources/libraries/robot/runtest.robot + +*** Test Cases *** + +Throughput Testing Raaqm Mobile + Run Throughput Test Raaqm hicn-light 200 500 400 + +Throughput Testing CBR Mobile + Run Throughput Test CBR hicn-light 200 500 400 + +RTC Testing Mobile + Run RTC Test hicn-light 4 4 4 + +Latency Testing Mobile + Set Link hicn-light 500 1 0 0 + Run Latency Test hicn-light 3000 3000 3000 diff --git a/tests/functional-tests/2-nodes-vpp-bridge.robot b/tests/functional-tests/2-nodes-vpp-bridge.robot new file mode 100644 index 000000000..83c8818ab --- /dev/null +++ b/tests/functional-tests/2-nodes-vpp-bridge.robot @@ -0,0 +1,24 @@ +*** Settings *** +Resource resources/libraries/robot/runtest.robot +Resource resources/libraries/robot/common.robot +Suite Setup Run Keywords +... Build Topology 2-nodes vpp-bridge AND +... Check Environment +Suite Teardown Run Keywords +... Destroy Topology +Resource resources/libraries/robot/runtest.robot + +*** Test Cases *** + +Throughput Testing Raaqm Server VPP bridge + Run Throughput Test Raaqm vpp-bridge 500 500 500 + +Throughput Testing CBR Server VPP bridge + Run Throughput Test CBR vpp-bridge 1000 1300 1200 + +RTC Testing Server VPP bridge + Run RTC Test vpp-bridge 4 4 4 + +Latency Testing Server VPP bridge + Set Link hicn-light 500 1 0 0 + Run Latency Test vpp-bridge 3000 3000 3000 diff --git a/tests/functional-tests/2-nodes-vpp-memif-replication.robot b/tests/functional-tests/2-nodes-vpp-memif-replication.robot new file mode 100644 index 000000000..8c13f4fb9 --- /dev/null +++ b/tests/functional-tests/2-nodes-vpp-memif-replication.robot @@ -0,0 +1,23 @@ +*** Settings *** +Resource resources/libraries/robot/runtest.robot +Resource resources/libraries/robot/common.robot +Suite Setup Run Keywords +... Build Topology 2-nodes vpp-memif-replication AND +... Check Environment +Suite Teardown Run Keywords +... Destroy Topology +Resource resources/libraries/robot/runtest.robot + +*** Test Cases *** + +Throughput Testing Raaqm Server VPP memif replication + Run Throughput Test Raaqm vpp-memif-replication 500 500 500 + +Throughput Testing CBR Server VPP memif + Run Throughput Test CBR vpp-memif-replication 2000 2000 2000 + +RTC Testing Server VPP memif replication + Run RTC Test vpp-memif-replication 4 4 4 + +Latency Testing Server VPP memif replication + Run Latency Test vpp-memif-replication 3000 3000 3000 diff --git a/tests/functional-tests/2-nodes-vpp-memif.robot b/tests/functional-tests/2-nodes-vpp-memif.robot new file mode 100644 index 000000000..1a69da787 --- /dev/null +++ b/tests/functional-tests/2-nodes-vpp-memif.robot @@ -0,0 +1,23 @@ +*** Settings *** +Resource resources/libraries/robot/runtest.robot +Resource resources/libraries/robot/common.robot +Suite Setup Run Keywords +... Build Topology 2-nodes vpp-memif AND +... Check Environment +Suite Teardown Run Keywords +... Destroy Topology +Resource resources/libraries/robot/runtest.robot + +*** Test Cases *** + +Throughput Testing Raaqm Server VPP memif + Run Throughput Test Raaqm vpp-memif 500 500 500 + +Throughput Testing CBR Server VPP memif + Run Throughput Test CBR vpp-memif 2000 2000 2000 + +RTC Testing Server VPP memif + Run RTC Test vpp-memif 4 4 4 + +Latency Testing Server VPP memif + Run Latency Test vpp-memif 3000 3000 3000 diff --git a/tests/resources/libraries/robot/common.robot b/tests/resources/libraries/robot/common.robot new file mode 100644 index 000000000..c1e3f20a4 --- /dev/null +++ b/tests/resources/libraries/robot/common.robot @@ -0,0 +1,23 @@ +*** Settings *** +Library OperatingSystem +Library Process +Library String + +*** Variables *** + +*** Keywords *** + +Build Topology + [Arguments] ${TEST_TOPOLOGY}=${NONE} ${TEST_CONFIGURATION}=${NONE} + Log to console Building topology ${TEST_TOPOLOGY} ${TEST_CONFIGURATION} + ${result_setup} = Run Process ${EXECDIR}/config.sh build setup ${TEST_TOPOLOGY} ${TEST_CONFIGURATION} + Log to console Done + Log Many stdout: ${result_setup.stdout} stderr: ${result_setup.stderr} + +Check Environment + ${result} = Run Process docker ps + Log Many stdout: ${result.stdout} stderr: ${result.stderr} + +Destroy Topology + ${result_teardown} = Run Process ${EXECDIR}/config.sh stopall + Log Many stdout: ${result_teardown.stdout} stderr: ${result_teardown.stderr} diff --git a/tests/resources/libraries/robot/runtest.robot b/tests/resources/libraries/robot/runtest.robot new file mode 100644 index 000000000..d5201d765 --- /dev/null +++ b/tests/resources/libraries/robot/runtest.robot @@ -0,0 +1,92 @@ +*** Settings *** +Library OperatingSystem +Library Process +Library String + +*** Variables *** + +*** Keywords *** + +Infra ${VALUE} + Run Process ${EXECDIR}/config.sh ${VALUE} + +Run Test + [Arguments] ${TEST_SETUP}=${NONE} ${TESTID}=${NONE} ${EXPECTED_MIN}=${NONE} ${EXPECTED_MAX}=${NONE} ${EXPECTED_AVG}=${NONE} + ${result_test} = Run Process ${EXECDIR}/config.sh start ${TEST_SETUP} ${TESTID} stdout=${TEMPDIR}/stdout.txt stderr=${TEMPDIR}/stderr.txt + Log Many stdout: ${result_test.stdout} stderr: ${result_test.stderr} + @{min_max_avg} = Split String ${result_test.stdout.strip()} + Log To Console Min Max Average Array: @{min_max_avg} + IF '${TESTID}' == 'rtc' + Should Be True ${min_max_avg}[0] == ${EXPECTED_MIN} msg="Min does not match (${min_max_avg}[0] != ${EXPECTED_MIN})" + Should Be True ${min_max_avg}[1] == ${EXPECTED_MAX} msg="Max does not match (${min_max_avg}[1] != ${EXPECTED_MAX})" + Should Be True ${min_max_avg}[2] == ${EXPECTED_AVG} msg="Avg does not match (${min_max_avg}[2] != ${EXPECTED_AVG})" + ELSE IF '${TESTID}' == 'requin' + Should Be True ${min_max_avg}[0] >= ${EXPECTED_MIN} msg="Min does not match (${min_max_avg}[0] < ${EXPECTED_MIN})" + Should Be True ${min_max_avg}[1] >= ${EXPECTED_MAX} msg="Max does not match (${min_max_avg}[1] < ${EXPECTED_MAX})" + Should Be True ${min_max_avg}[2] >= ${EXPECTED_AVG} msg="Avg does not match (${min_max_avg}[2] < ${EXPECTED_AVG})" + ELSE IF '${TESTID}' == 'latency' + Should Be True ${min_max_avg}[0] <= ${EXPECTED_MIN} msg="Min does not match (${min_max_avg}[0] > ${EXPECTED_MIN})" + Should Be True ${min_max_avg}[1] <= ${EXPECTED_MAX} msg="Max does not match (${min_max_avg}[1] > ${EXPECTED_MAX})" + Should Be True ${min_max_avg}[2] <= ${EXPECTED_AVG} msg="Avg does not match (${min_max_avg}[2] > ${EXPECTED_AVG})" + ELSE IF '${TESTID}' == 'cbr' + Should Be True ${min_max_avg}[0] >= ${EXPECTED_MIN} msg="Min does not match (${min_max_avg}[0] < ${EXPECTED_MIN})" + Should Be True ${min_max_avg}[1] >= ${EXPECTED_MAX} msg="Max does not match (${min_max_avg}[1] < ${EXPECTED_MAX})" + Should Be True ${min_max_avg}[2] >= ${EXPECTED_AVG} msg="Avg does not match (${min_max_avg}[2] < ${EXPECTED_AVG})" + ELSE + Fail "Provided Test ID does not exist" + END + +Set Link + [Documentation] Configure link rate/delay/jitter/loss + ... Arguments: + ... ${RATE} Rate of the link + ... ${DELAY} Delay of the link + ... ${JITTER} Jitter of the link + ... ${LOSS} Loss of the link + [Arguments] ${TEST_SETUP}=${NONE} + ... ${RATE}=${NONE} + ... ${DELAY}=${NONE} + ... ${JITTER}=${NONE} + ... ${LOSS}=${NONE} + ${result_link} = Run Process ${EXECDIR}/config.sh setchannel ${TEST_SETUP} server ${RATE}-${DELAY}-${JITTER}-${LOSS} + Log Many stdout: ${result_link.stdout} stderr: ${result_link.stderr} + +Run Latency Test + [Documentation] Run hicn-ping on the ${TEST_SETUP} topology and measure latency. + ... Arguments: + ... ${TEST_SETUP} The setup of the test. + ... ${EXPECTED_MIN} The expected min latency + ... ${EXPECTED_MAX} The expected max latency + ... ${EXPECTED_AVG} The expected avg latency + [Arguments] ${TEST_SETUP}=${NONE} ${EXPECTED_MIN}=${NONE} ${EXPECTED_MAX}=${NONE} ${EXPECTED_AVG}=${NONE} + Run Test ${TEST_SETUP} latency ${EXPECTED_MIN} ${EXPECTED_MAX} ${EXPECTED_AVG} + +Run Throughput Test Raaqm + [Documentation] Run hiperf on the ${TEST_SETUP} topology and measure throughput. + ... Arguments: + ... ${TEST_SETUP} The setup of the test. + ... ${EXPECTED_MIN} The expected min throughput + ... ${EXPECTED_MAX} The expected max throughput + ... ${EXPECTED_AVG} The expected avg throughput + [Arguments] ${TEST_SETUP}=${NONE} ${EXPECTED_MIN}=${NONE} ${EXPECTED_MAX}=${NONE} ${EXPECTED_AVG}=${NONE} + Run Test ${TEST_SETUP} requin ${EXPECTED_MIN} ${EXPECTED_MAX} ${EXPECTED_AVG} + +Run Throughput Test CBR + [Documentation] Run hiperf on the ${TEST_SETUP} topology and measure throughput. + ... Arguments: + ... ${TEST_SETUP} The setup of the test. + ... ${EXPECTED_MIN} The expected min throughput + ... ${EXPECTED_MAX} The expected max throughput + ... ${EXPECTED_AVG} The expected avg throughput + [Arguments] ${TEST_SETUP}=${NONE} ${EXPECTED_MIN}=${NONE} ${EXPECTED_MAX}=${NONE} ${EXPECTED_AVG}=${NONE} + Run Test ${TEST_SETUP} cbr ${EXPECTED_MIN} ${EXPECTED_MAX} ${EXPECTED_AVG} + +Run RTC Test + [Documentation] Run hiperf RTC on the ${TEST_SETUP} topology and check consumer syncs to producer bitrate. + ... Arguments: + ... ${TEST_SETUP} The setup of the test. + ... ${EXPECTED_MIN} The expected min bitrate + ... ${EXPECTED_MAX} The expected max bitrate + ... ${EXPECTED_AVG} The expected avg bitrate + [Arguments] ${TEST_SETUP}=${NONE} ${EXPECTED_MIN}=${NONE} ${EXPECTED_MAX}=${NONE} ${EXPECTED_AVG}=${NONE} + Run Test ${TEST_SETUP} rtc ${EXPECTED_MIN} ${EXPECTED_MAX} ${EXPECTED_AVG} diff --git a/tests/run-functional.sh b/tests/run-functional.sh new file mode 100644 index 000000000..b8dfbc437 --- /dev/null +++ b/tests/run-functional.sh @@ -0,0 +1,40 @@ +# Copyright (c) 2021 Cisco and/or its affiliates. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +SCRIPT_PATH=$( + cd "$(dirname "${BASH_SOURCE}")" + pwd -P +) + +pushd "${SCRIPT_PATH}" || exit 1 + +declare -a REPORTS + +for t in functional-tests/*; do + [[ -e "$t" ]] || break # handle the case of no test files + + test=$(basename "$t") + + robot --NoStatusRC \ + --outputdir report_"${test}" \ + -P ${PWD} functional-tests/"${test}" + + REPORTS+=(report_"${test}"/output.xml) +done + +rebot --output output.xml \ + -l log.html -r report.html \ + --nostatusrc \ + "${REPORTS[@]}" + +popd || exit 1 diff --git a/tests/test_forwarder.sh b/tests/test_forwarder.sh new file mode 100644 index 000000000..aba85d8d8 --- /dev/null +++ b/tests/test_forwarder.sh @@ -0,0 +1,437 @@ +#!/bin/bash + +############################################################################ +# CONSTANTS +############################################################################ +INTERFACE_CMD="ip route get 1 | grep -Po '(?<=(dev )).*(?= src| proto)'" +ADDRESS_CMD="ip route get 1 | sed -n '/src/{s/.*src *\([^ ]*\).*/\1/p;q}'" +CTRL_CMD="docker exec test-hicn \ + /hicn-build/build/build-root/bin/hicn-light-control" +PING_SERVER_CMD="docker exec -d test-hicn \ + /hicn-build/build/build-root/bin/hicn-ping-server \ + -z hicnlightng_module" +PING_CLIENT_CMD="docker exec test-hicn \ + /hicn-build/build/build-root/bin/hicn-ping-client \ + -z hicnlightng_module" +PING_CLIENT_DETACHED_CMD="docker exec -d test-hicn \ + /hicn-build/build/build-root/bin/hicn-ping-client \ + -z hicnlightng_module" +LISTENER_NAME="udp0" +CONN_NAME="conn0" +PREFIX="c001::/64" +COST=1 +FIVE_SECONDS=5000 + +############################################################################ +# UTILS +############################################################################ +set_up() { + docker build -t hicn-dev . + run_forwarder +} + +tear_down() { + docker stop --time 0 test-hicn +} + +get_address() { + echo $(docker exec test-hicn sh -c "${ADDRESS_CMD}") +} + +get_interface() { + echo $(docker exec test-hicn sh -c "${INTERFACE_CMD}") +} + +#--------------------------------------------------------------------------- +# Exec +#--------------------------------------------------------------------------- +run_forwarder() { + capacity=${1:-"100000"} + loglevel=${2:-"trace"} + config=${3:-""} + + config_file_arg="" + if [[ $config != "" ]]; then + config_file_arg="--config ${config}" + fi + + docker run --rm -d --name test-hicn \ + -v $(pwd)/..:/hicn-build \ + -e LD_LIBRARY_PATH=/hicn-build/build/build-root/lib \ + hicn-dev \ + /hicn-build/build/build-root/bin/hicn-light-daemon \ + --log ${loglevel} --capacity ${capacity} $config_file_arg +} + +exec_controller() { + command=$1 + + # Redirect stderr to stdout + output=$(${CTRL_CMD} ${command} 2>&1) + assert_exit_code + echo ${output} +} + +exec_ping_server() { + data_lifetime=${1:-""} + + lifetime_arg="" + if [[ $data_lifetime != "" ]]; then + lifetime_arg="-l ${data_lifetime}" + fi + + ${PING_SERVER_CMD} ${lifetime_arg} +} + +exec_ping_client() { + num_packets=$1 + + output=$(${PING_CLIENT_CMD} -m ${num_packets}) + assert_exit_code + echo ${output} +} + +exec_ping_client_detached() { + num_packets=$1 + interest_lifetime=$2 + + ${PING_CLIENT_DETACHED_CMD} -m ${num_packets} -l ${interest_lifetime} +} + +#--------------------------------------------------------------------------- +# Asserts +#--------------------------------------------------------------------------- +assert_exit_code() { + if [[ $? -ne 0 ]]; then + exit_with_failure + fi +} + +assert_forwarder() { + # Print forwarder logs for debug info + echo "******** Forwarder Logs ********" + docker logs test-hicn + echo "********************************" + + output=$(docker logs test-hicn) + if [[ $output == "" ]]; then + exit_with_failure + fi + + if [[ "${output}" == *"ERROR"* ]]; then + exit_with_failure + fi + + if [[ "${output}" == *"Aborted (core dumped)"* ]]; then + exit_with_failure + fi +} + +assert_ack() { + # Print controller logs for debug info + echo "******** Controller Logs ********" + echo $1 + echo "********************************" + + output=$1 + + if [[ "$output" == *"Error"* ]]; then + exit_with_failure + fi +} + +assert_nack() { + # Print controller logs for debug info + echo "******** Controller Logs ********" + echo $1 + echo "********************************" + + output=$1 + + if [[ "$output" != *"Error"* ]]; then + exit_with_failure + fi +} + +assert_ping_client() { + # Print ping client logs for debug info + echo "******** Ping Client Logs ********" + echo $1 + echo "********************************" + + ping_client_output=$1 + pkts_sent=$2 + pkts_recv=$3 + pkts_timeout=$4 + + match_str="Sent: ${pkts_sent} Received: ${pkts_recv} Timeouts: ${pkts_timeout}" + if [[ ! ${ping_client_output} == *"${match_str}"* ]]; then + exit_with_failure + fi +} + +assert_forwarder_stats() { + satisfied_from_cs=${1:-""} + no_route_in_fib=${2:-""} + aggregated=${3:-""} + + fwder_stats=$(docker logs test-hicn | grep "Forwarder: received" | tail -n 1) + + if [[ $satisfied_from_cs != "" && + "${fwder_stats}" != *"satisfied_from_cs = ${satisfied_from_cs}"* ]]; then + exit_with_failure + fi + + if [[ $no_route_in_fib != "" && + "${fwder_stats}" != *"no_route_in_fib = ${no_route_in_fib}"* ]]; then + exit_with_failure + fi + + if [[ $aggregated != "" && + "${fwder_stats}" != *"aggregated = ${aggregated}"* ]]; then + exit_with_failure + fi +} + +assert_pkt_cache_stats() { + total_size=${1:-""} + pit_size=${2:-""} + cs_size=${3:-""} + + pkt_cache_stats=$(docker logs test-hicn | grep "Packet cache:" | tail -n 1) + + if [[ $total_size != "" && + "${pkt_cache_stats}" != *"total size = ${total_size}"* ]]; then + exit_with_failure + fi + + if [[ $pit_size != "" && + "${pkt_cache_stats}" != *"PIT size = ${pit_size}"* ]]; then + exit_with_failure + fi + + if [[ $cs_size != "" && + "${pkt_cache_stats}" != *"CS size = ${cs_size}"* ]]; then + exit_with_failure + fi +} + +assert_cs_stats() { + evictions=${1:-""} + + cs_stats=$(docker logs test-hicn | grep "Content store:" | tail -n 1) + + if [[ $evictions != "" && + "${cs_stats}" != *"evictions = ${evictions}"* ]]; then + exit_with_failure + fi +} + +############################################################################ +# TEST SUITE +############################################################################ + +#--------------------------------------------------------------------------- +# Commands +#--------------------------------------------------------------------------- +test_add_listener() { + # Exec hicn-light-control command and capture its output + INTERFACE=$(get_interface) + ADDRESS=$(get_address) + command="add listener udp ${LISTENER_NAME} ${ADDRESS} 9695 ${INTERFACE}" + ctrl_output=$(exec_controller "${command}") + + # Check hicn-light-control and hicn-light-daemon outputs + assert_ack "$ctrl_output" + assert_forwarder +} + +test_remove_listener() { + INTERFACE=$(get_interface) + ADDRESS=$(get_address) + command="add listener udp ${LISTENER_NAME} ${ADDRESS} 9695 ${INTERFACE}" + ctrl_output=$(exec_controller "${command}") + assert_ack "$ctrl_output" + + command="remove listener udp0" + ctrl_output=$(exec_controller "${command}") + + assert_ack "$ctrl_output" + assert_forwarder +} + +test_remove_non_existing_listener() { + command="remove listener udp0" + ctrl_output=$(exec_controller "${command}") + + assert_nack "$ctrl_output" + assert_forwarder +} + +test_add_duplicated_listener() { + # Exec hicn-light-control command and capture its output + INTERFACE=$(get_interface) + ADDRESS=$(get_address) + command="add listener udp ${LISTENER_NAME} ${ADDRESS} 9695 ${INTERFACE}" + exec_controller "${command}" + ctrl_output=$(exec_controller "${command}") + + # Check hicn-light-control and hicn-light-daemon outputs + assert_nack "$ctrl_output" + assert_forwarder +} + +test_list_listeners() { + # Exec hicn-light-control command and capture its output + command="list listener" + ctrl_output=$(exec_controller "${command}") + + # Check hicn-light-control and hicn-light-daemon outputs + assert_forwarder + # Only the local listener should be present + [[ "${ctrl_output}" =~ "inet4://127.0.0.1:9695" ]] && return 0 || exit_with_failure +} + +test_commands_from_config() { + # Create config file + INTERFACE=$(get_interface) + ADDRESS=$(get_address) + echo "# Teset config file + add listener udp $LISTENER_NAME $ADDRESS 9695 ${INTERFACE} + add connection udp $CONN_NAME $ADDRESS 12345 $ADDRESS 9695 ${INTERFACE} + add route $CONN_NAME $PREFIX $COST + set strategy c001::/64 random + " >forwarder.conf + + # Restart the forwarder specifying the config file + tear_down + run_forwarder "" "" "/hicn-build/tests/forwarder.conf" + rm forwarder.conf + + # Check for errors in the output + assert_forwarder +} + +#--------------------------------------------------------------------------- +# Ping +#--------------------------------------------------------------------------- +test_ping_one_packet() { + # Exec hicn-ping-server + exec_ping_server + # Exec hicn-ping-client (w/ 1 packet) and capture its output + output=$(exec_ping_client 1) + + # Check hicn-ping-client (1 pkt sent, 1 pkt received, 0 timeouts) + # and hicn-light-daemon outputs + assert_ping_client "${output}" 1 1 0 + assert_forwarder +} + +test_ping_two_packets() { + exec_ping_server + output=$(exec_ping_client 2) + + assert_ping_client "${output}" 2 2 0 + assert_forwarder +} + +test_ping_using_cs() { + exec_ping_server + exec_ping_client 2 + output=$(exec_ping_client 1) + + assert_ping_client "${output}" 1 1 0 + assert_forwarder + assert_forwarder_stats 1 +} + +test_ping_using_cs_different_order() { + exec_ping_server + exec_ping_client 1 + output=$(exec_ping_client 2) + + assert_ping_client "${output}" 2 2 0 + assert_forwarder + assert_forwarder_stats 1 +} + +test_ping_timeout() { + # Send ping without the ping server being run + output=$(exec_ping_client 1) + + assert_ping_client "${output}" 1 0 1 + assert_forwarder + assert_forwarder_stats 0 1 +} + +test_ping_aggregation() { + # Send ping without server, waiting for a reply + exec_ping_client_detached 1 ${FIVE_SECONDS} + exec_ping_server + # This new ping interest will be aggregated with the previous one + # and the forwarder will reply to both ping clients + output=$(exec_ping_client 1) + + assert_ping_client "${output}" 1 1 0 + assert_forwarder + assert_forwarder_stats "" "" 1 +} + +test_ping_with_cs_store_disabled() { + command="store cache off" + exec_controller "${command}" + + exec_ping_server + exec_ping_client 1 + output=$(exec_ping_client 1) + + assert_ping_client "${output}" 1 1 0 + assert_forwarder + assert_forwarder_stats 0 "" "" + # The packet is not stored in the CS + assert_pkt_cache_stats "" "" 0 +} + +test_ping_with_cs_serve_disabled() { + command="serve cache off" + exec_controller "${command}" + + exec_ping_server + exec_ping_client 1 + output=$(exec_ping_client 1) + + assert_ping_client "${output}" 1 1 0 + assert_forwarder + assert_forwarder_stats 0 "" "" + # The packet is stored in the CS, but CS is not used + assert_pkt_cache_stats "" "" 1 +} + +test_ping_with_eviction() { + # Restart the forwarder with CS capacity = 1 + tear_down + run_forwarder 1 + + exec_ping_server + exec_ping_client 1 + output=$(exec_ping_client 2) + + assert_ping_client "${output}" 2 2 0 + assert_forwarder + # Check if eviction happened + assert_cs_stats 1 + assert_pkt_cache_stats "" "" 1 +} + +test_ping_with_zero_data_lifetime() { + exec_ping_server 0 + exec_ping_client 1 + output=$(exec_ping_client 1) + + assert_ping_client "${output}" 1 1 0 + assert_forwarder + # The data is not taken from the CS because expired + assert_forwarder_stats 0 "" "" +} + +"$@" |