diff --git a/08-interop/compile_contiki.sh b/08-interop/compile_contiki.sh new file mode 100755 index 0000000..b4454c1 --- /dev/null +++ b/08-interop/compile_contiki.sh @@ -0,0 +1,29 @@ +#!/bin/bash + +cd /tmp + +# Clone Contiki-NG +git clone https://github.com/contiki-ng/contiki-ng.git; cd contiki-ng || \ +cd contiki-ng; git pull +git submodule update --init --recursive + +# Pull the Contiki-NG Docker image +docker pull contiker/contiki-ng + +# Add the `shell` service to the `examples/hello-world` application. +if ! grep -q "MODULES += os/services/shell" examples/hello-world/Makefile; then + sed -i '/all: $(CONTIKI_PROJECT)/a\\nMODULES += os/services/shell\n' examples/hello-world/Makefile +fi + + +# Compile the `examples/hello-world` application for the nRF52840 platform. +export CNG_PATH=/tmp/contiki-ng +docker run \ + --privileged \ + --sysctl net.ipv6.conf.all.disable_ipv6=0 \ + --mount type=bind,source=$CNG_PATH,destination=/home/user/contiki-ng \ + -e DISPLAY=$DISPLAY \ + -v /tmp/.X11-unix:/tmp/.X11-unix \ + -v /dev/bus/usb:/dev/bus/usb \ + contiker/contiki-ng \ + make -C examples/hello-world TARGET=nrf52840 hello-world diff --git a/08-interop/test_spec08.py b/08-interop/test_spec08.py old mode 100644 new mode 100755 index dae060e..b69826e --- a/08-interop/test_spec08.py +++ b/08-interop/test_spec08.py @@ -1,5 +1,6 @@ import re import sys +import subprocess import pexpect.replwrap import pytest @@ -49,6 +50,36 @@ def test_task01(riot_ctrl, log_nodes): assert res["stats"]["packet_loss"] < 1 +@pytest.mark.flaky(reruns=1, reruns_delay=30) +@pytest.mark.iotlab_creds +# nodes passed to riot_ctrl fixture +@pytest.mark.parametrize( + 'nodes', [pytest.param(['nrf52840dk', 'nrf52840dk'])], indirect=['nodes'] +) +def test_task03(riot_ctrl): + # run `./compile_contiki.sh` relative to this file + subprocess.check_call(["./compile_contiki.sh"], cwd=__file__[:__file__.rfind("/")]) + + gnrc_node, contiki_node = ( + riot_ctrl(0, GNRC_APP, Shell), + riot_ctrl(1, 'examples/hello-world', riotctrl.shell.ShellInteraction, extras={"BINFILE": "/tmp/contiki-ng/examples/hello-world/build/nrf52840/dk/hello-world.nrf52840"}), + ) + + gnrc_netif, gnrc_addr = lladdr(gnrc_node.ifconfig_list()) + + # get the address of the contiki node, ie a substring after "-- " + res = contiki_node.cmd("ip-addr") + contiki_addr = res[res.find("-- ") + 3:] + + gnrc_node.ifconfig_set(gnrc_netif, "pan_id", "abcd") + + res = contiki_node.cmd(f"ping {gnrc_addr}") + assert f"Received ping reply from {gnrc_addr}" in res + + res = ping6(gnrc_node, contiki_addr, 3, 12, 1) + assert res['stats']['packet_loss'] < 10 + + @pytest.mark.flaky(reruns=3, reruns_delay=30) @pytest.mark.iotlab_creds # nodes passed to riot_ctrl fixture diff --git a/conftest.py b/conftest.py index a3bc5e8..e6b1861 100644 --- a/conftest.py +++ b/conftest.py @@ -303,7 +303,7 @@ def nodes(local, request, boards, iotlab_site): RUNNING_EXPERIMENTS.remove(exp) -def update_env(node, modules=None, cflags=None, port=None, termflags=None): +def update_env(node, modules=None, cflags=None, port=None, termflags=None, extras=None): node.env['QUIETER'] = '1' if not isinstance(modules, str) and isinstance(modules, Iterable): node.env['USEMODULE'] = ' '.join(str(m) for m in modules) @@ -322,6 +322,8 @@ def update_env(node, modules=None, cflags=None, port=None, termflags=None): node.env['PORT'] = port if termflags is not None: node.env['TERMFLAGS'] = termflags + if extras is not None: + node.env.update(extras) @pytest.fixture @@ -342,12 +344,13 @@ def ctrl( cflags=None, port=None, termflags=None, + extras=None, ): if board_type is not None: node = next(n for n in nodes if n.board() == board_type) else: node = nodes[nodes_idx] - update_env(node, modules, cflags, port, termflags) + update_env(node, modules, cflags, port, termflags, extras) # if the nodes are not logged, there is no sense in logging to a file # so check if nodes are logged as well as if they should be logged to a # file @@ -366,8 +369,11 @@ def ctrl( # need to access private member here isn't possible otherwise sadly :( # pylint: disable=W0212 node._application_directory = os.path.join(riotbase, application_dir) + flash_cmd = "flash" + if "BINFILE" in node.env: + flash_cmd = "flash-only" node.make_run( - ['flash'], + [flash_cmd], check=True, stdout=None if log_nodes else subprocess.DEVNULL, stderr=None if log_nodes else subprocess.DEVNULL,