scripts: net: Add script for running sample tests

Add a script that sets up Docker networking and starts the net-tools
Docker container. If successful, run Zephyr with native_posix and
execute the appropriate net-tools container executable. The proper
net-tools executable and arguments is selected depending on the
basename of the sample directory. This script needs to be updated
if the net-tools Docker image is updated in some incompatible way.

The net-tools directory is assumed to exist at the same level as
the Zephyr base directory, but its location can be set using the
'-N' command line argument. Likewise, '-Z' sets the Zephyr top level
directory.

When stopping Zephyr, go through all child processes since running a
native posix or other variant of Zephyr may cause a hierarchy of
processes to be created.

Fixes: #19540

Signed-off-by: Patrik Flykt <patrik.flykt@intel.com>
This commit is contained in:
Patrik Flykt 2019-10-18 10:29:05 +03:00 committed by Anas Nashif
commit 65ffc71466
3 changed files with 499 additions and 0 deletions

View file

@ -361,6 +361,7 @@
/scripts/gen_kobject_list.py @andrewboie /scripts/gen_kobject_list.py @andrewboie
/scripts/gen_priv_stacks.py @andrewboie @agross-oss @ioannisg /scripts/gen_priv_stacks.py @andrewboie @agross-oss @ioannisg
/scripts/gen_syscalls.py @andrewboie /scripts/gen_syscalls.py @andrewboie
/scripts/net/ @jukkar @pfl
/scripts/process_gperf.py @andrewboie /scripts/process_gperf.py @andrewboie
/scripts/gen_relocate_app.py @wentongwu /scripts/gen_relocate_app.py @wentongwu
/scripts/sanity_chk/ @nashif /scripts/sanity_chk/ @nashif

64
scripts/net/README.txt Normal file
View file

@ -0,0 +1,64 @@
The shell script run-sample-tests.sh runs a few Zephyr samples against the
network test applications container provided by the 'net-tools'
Zephyr project, https://github.com/zephyrproject-rtos/net-tools.
Installation
************
As a prerequisite it is assumed that Docker is installed and that the
'net-tools' Docker container has been created, see the first bullet point
at the net-tools Docker README file
https://github.com/zephyrproject-rtos/net-tools/blob/master/README.docker.
In essence, the following needs to be done:
* Install Docker
* Check out the net-tools project from github or update it with west
* Change working directory to the net-tools repository
* Run './net-setup.sh --config docker.conf'
This runs a Docker image called 'net-tools' and sets up docker network
'net-tools0' on your local machine.
Using
*****
The scripts/net/run-sample-tests.sh shell script is meant to be run from the
relevant Zephyr network sample test directory. Currently the following two
samples are supported:
* samples/net/sockets/echo_client
* samples/net/sockets/echo_server
The applications to run in the net-tools Docker container are selected based
on the name of the sample directory, for echo_client the echo_server
application is started from the Docker container, and with echo_server
echo_client is started in the Docker container. When completed, the return
value, either from Zephyr or from the Docker container, is returned to the
script on Zephyr or Docker application termination. The return value is used
as a simple verdict whether the sample passed or failed.
The Docker container and a corresponding 'net-tools0' Docker network is started
by the script, as well as Zephyr using native_posix. IP addresses are assigned
to the Docker network, which is a Linux network bridge interface. The IP
addresses are set based on the sample being run.
* echo_client uses addresses 192.0.2.1 and 2001:db8::1
* echo_server uses addresses 192.0.2.2 and 2001:db8::2
* the Docker bridge interface uses addresses 192.0.2.254 and 2001:db8::254
Directories
***********
The sample test script tries to automatically figure out the Zephyr base
directory, which is assumed to be set by the ZEPHYR_BASE environment variable.
Should this not be the case, the directory can be set using '-Z' or
'--zephyr-dir' command line arguments. The sample test script also assumes
that the net-tools git repository containing the Docker networking setup file
'docker.conf' exists at the same directory level as the Zephyr base directory.
If the net tools are found elsewhere, the net-tools directory can be set with
the 'N' or '--net-tools-dir' command line argument.
Help is also available using the 'h' or '--help' argument.

434
scripts/net/run-sample-tests.sh Executable file
View file

@ -0,0 +1,434 @@
#!/bin/sh
# Copyright (c) 2019 Intel Corporation
# SPDX-License-Identifier: Apache-2.0
image=net-tools
name=net-tools
network=net-tools0
zephyr_pid=0
docker_pid=0
configuration=""
result=0
sample=""
check_dirs ()
{
local ret_zephyr=0
local ret_net_tools=0
if [ -z "$ZEPHYR_BASE" ]
then
echo '$ZEPHYR_BASE is unset' >&2
ret_zephyr=1
fi
if [ ! -d "$ZEPHYR_BASE" ]
then
echo '$ZEPHYR_BASE is set, but it is not a directory' >&2
ret_zephyr=1
fi
if [ -z "$NET_TOOLS_BASE" ]
then
local d
for d in "$ZEPHYR_BASE/../.." "$ZEPHYR_BASE/.."
do
local l
l="$d/net-tools"
if [ -d "$l" ]
then
NET_TOOLS_BASE="$l"
break
fi
done
fi
if [ $ret_zephyr -eq 0 ]
then
echo "\$ZEPHYR_BASE $ZEPHYR_BASE"
fi
if [ -z "$NET_TOOLS_BASE" ]
then
echo '$NET_TOOLS_BASE is unset, no net-tools found' >&2
ret_net_tools=1
fi
if [ ! -d "$NET_TOOLS_BASE" ]
then
echo '$NET_TOOLS_BASE set, but it is not a directory' >&2
ret_net_tools=1
fi
if [ $ret_net_tools -eq 0 ]
then
echo "\$NET_TOOLS_BASE $NET_TOOLS_BASE"
fi
if [ $ret_zephyr -ne 0 -o $ret_net_tools -ne 0 ]
then
return 1
fi
return 0
}
start_configuration ()
{
local bridge_interface=""
local addresses="--ip=192.0.2.2 --ip6=2001:db8::2"
if ! docker image ls | grep "$image" > /dev/null
then
echo "Docker image '$image' not found" >&2
return 1
fi
if ! docker network ls | grep "$network" > /dev/null
then
bridge_interface=$("$NET_TOOLS_BASE/net-setup.sh" \
--config "$NET_TOOLS_BASE/docker.conf" \
start 2>/dev/null | tail -1)
if [ $? != 0 ]
then
echo "Could not start Docker network '$network'" >&2
return 1
fi
echo "Started Docker network '$network' bridge interface" \
"'$bridge_interface'..."
fi
if [ -n "$*" ]
then
addresses="$*"
fi
if docker ps | grep "$name" > /dev/null
then
docker stop "$name"
fi
if docker run --hostname=$name --name=$name \
$addresses \
--rm -dit --network=$network $image > /dev/null
then
echo -n "Started Docker container '$name'"
if [ -n "$*" ]
then
echo -n " with extra arguments '$*'"
fi
echo "..."
else
echo "Could not start Docker container '$image'"
return 1
fi
}
stop_configuration ()
{
local bridge_interface=""
if docker ps | grep "$name" > /dev/null
then
docker stop "$name" > /dev/null
if [ $? -eq 0 ]
then
echo "Stopped Docker container '$name'..."
else
echo "Could not stop Docker container '$name'" >&2
fi
fi
bridge_interface=$(docker network ls | grep "$network" | cut -d " " -f 1)
if [ -n "$bridge_interface" ]
then
docker network rm "$network" > /dev/null
if [ $? -eq 0 ]
then
echo "Stopped Docker network '$network' bridge interface" \
"'br-$bridge_interface'..."
else
echo "Could not stop Docker network '$network'" >&2
fi
fi
}
start_zephyr ()
{
if [ -n "$*" ]
then
echo "Building Zephyr with additional arguments '$@'..." >&2
fi
rm -rf build && mkdir build && \
cmake -GNinja -DBOARD=native_posix -B build "$@" && \
ninja -C build
ninja -C build run &
zephyr_pid=$!
sleep 3
echo "Zephyr PID $zephyr_pid"
}
list_children () {
local pid="$(ps -o pid= --ppid "$1")"
for p in $pid
do
list_children $p
done
if [ -n "$pid" ]
then
echo -n "$pid "
fi
}
stop_zephyr ()
{
if [ "$zephyr_pid" -ne 0 ]
then
local zephyrs="$zephyr_pid $(list_children "$zephyr_pid")"
echo "Stopping Zephyr PIDs $zephyrs"
kill $zephyrs
fi
zephyr_pid=0
}
wait_zephyr ()
{
echo "Waiting for Zephyr $zephyr_pid..."
wait $zephyr_pid
zephyr_pid=0
}
docker_run ()
{
local test=""
local result=0
for test in "$@"
do
echo "Running '$test' in the container..."
docker container exec net-tools $test
result="$?"
if [ $result -ne 0 ]
then
return $result
fi
done
}
start_docker ()
{
docker_run "$@" &
docker_pid=$!
echo "Docker PID $docker_pid"
}
stop_docker ()
{
if [ "$docker_pid" -ne 0 ]
then
local dockers="$docker_pid $(list_children "$docker_pid")"
echo "Stopping Docker PIDs $dockers"
kill $dockers
fi
docker_pid=0
}
wait_docker ()
{
echo "Waiting for Docker $docker_pid..."
wait $docker_pid
docker_pid=0
}
docker_exec ()
{
local result=0
case "$1" in
echo_server)
start_configuration
start_zephyr
start_docker \
"/net-tools/echo-client -i eth0 192.0.2.1" \
"/net-tools/echo-client -i eth0 2001:db8::1"
wait_docker
result=$?
stop_zephyr
;;
echo_client)
start_configuration "--ip=192.0.2.1 --ip6=2001:db8::1"
start_docker \
"/net-tools/echo-server -i eth0"
start_zephyr "-DCONFIG_NET_SAMPLE_SEND_ITERATIONS=10"
wait_zephyr
result=$?
stop_docker
;;
coap_server)
start_configuration
start_zephyr
start_docker "/net-tools/libcoap/examples/etsi_coaptest.sh -i eth0 192.0.2.1"
wait $docker_pid
result=$?
stop_zephyr
;;
*)
echo "No sample test corresponding to directory '$1' found" >&2
return 1
;;
esac
return $result
}
run_test ()
{
local test="$(basename $(pwd))"
local result=0
if [ -n "$1" ]
then
source "$1"
result=$?
else
docker_exec "$test"
result=$?
fi
if [ $result -eq 0 ]
then
echo "Sample '$test' successful"
else
echo "Sample '$test' failed with return value '$result'"
fi
return $result
}
usage ()
{
echo "$0 [-Z <zephyr base directory>] [-N <net-tools base directory>]"
echo "\t[<test script>]"
echo "This script runs Zephyr sample tests using Docker container and"
echo "network implemented by the 'net-tools' subproject."
echo "-Z|--zephyr-dir <dir>\t\tset Zephyr base directory"
echo "-N|--net-tools-dir <dir>\tset net-tools directory"
echo "--start\t\t\t\tonly start Docker container and network and exit"
echo "--stop\t\t\t\tonly stop Docker container and network"
echo "<test script>\t\t\tsample script to run instead of test based on"
echo "\t\t\t\tcurrent directory"
echo "The automatically detected directories are:"
check_dirs
}
stop_sample_test () {
echo "Interrupted..." >&2
stop_zephyr
stop_docker
stop_configuration
exit 2
}
trap stop_sample_test ABRT INT HUP TERM
while test -n "$1"
do
case "$1" in
-Z|--zephyr-dir)
shift
ZEPHYR_BASE="$1"
;;
-N|--net-tools-dir)
shift
NET_TOOLS_BASE="$1"
;;
-h|--help)
usage
return 0
;;
--start)
if [ -n "$configuration" ]
then
echo "--start or --stop specified multiple times" >&2
return 1
fi
configuration=start_only
;;
--stop)
if [ -n "$configuration" ]
then
echo "--start or --stop specified multiple times" >&2
return 1
fi
configuration=stop_only
;;
-*)
echo "Argument '$1' not recognised" >&2
usage
return 0
;;
*)
if [ -n "$sample" ]
then
echo "Sample already specified" >&2
return 1
fi
sample="$1"
;;
esac
shift
done
check_dirs || exit $?
if [ -z "$configuration" -o "$configuration" = "start_only" ]
then
if [ "$configuration" = start_only ]
then
start_configuration
result=$?
else
run_test "$sample"
result=$?
fi
fi
if [ -z "$configuration" -o "$configuration" = stop_only ]
then
stop_configuration
fi
return $result