Skip to content

Commit

Permalink
[python] Enhancement of manual test using Cirque (#7122)
Browse files Browse the repository at this point in the history
* [python] Enhanced manual test

* Add avahi-utils

* update doc

* Fix elif and doc update

* Restyled by prettier-json

* Restyled by prettier-markdown

* Fix command

Co-authored-by: yunhanw <[email protected]>
Co-authored-by: Restyled.io <[email protected]>
  • Loading branch information
3 people authored and pull[bot] committed Jul 10, 2021
1 parent ebe85de commit 1003112
Show file tree
Hide file tree
Showing 8 changed files with 123 additions and 67 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,22 +15,17 @@ WORKDIR /app

RUN apt-get update \
&& apt-get install --no-install-recommends -y sudo git ca-certificates psmisc dhcpcd5 wpasupplicant wireless-tools \
&& apt-get install -y libglib2.0 avahi-daemon libavahi-client3 iproute2 \
gdb python3 python3-pip libcairo2-dev libjpeg-dev libgif-dev python3-dev \
&& apt-get install -y libglib2.0 avahi-daemon libavahi-client3 avahi-utils iproute2 \
&& ln -fs /usr/share/zoneinfo/UTC /etc/localtime \
&& git clone https://github.com/openthread/ot-br-posix . \
&& git checkout $OT_BR_POSIX_CHECKOUT \
&& git submodule update --init --depth=1 \
&& ./script/bootstrap \
&& ./script/setup \
&& chmod 644 /etc/bind/named.conf.options \
&& mv ./script /tmp \
&& mv ./etc /tmp \
&& find . -delete \
&& rm -rf /usr/include \
&& mv /tmp/script . \
&& mv /tmp/etc . \
&& apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false git ca-certificates \
&& apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false apt-utils build-essential psmisc ninja-build cmake wget ca-certificates \
&& apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false git psmisc \
&& apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false psmisc ninja-build cmake wget \
libreadline-dev libncurses-dev libcpputest-dev libdbus-1-dev libavahi-common-dev \
libavahi-client-dev libboost-dev libboost-filesystem-dev libboost-system-dev libjsoncpp-dev \
libnetfilter-queue-dev \
Expand Down
10 changes: 6 additions & 4 deletions scripts/tests/cirque_tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,9 @@ BOLD_RED_TEXT="\033[1;31m"
RESET_COLOR="\033[0m"

function __screen() {
if [[ "x$GITHUB_ACTION_RUN" != "x1" ]]; then
if [[ "x$GITHUB_ACTION_RUN" == "x1" ]]; then
"$@"
elif which screen; then
screen -dm "$@"
else
"$@"
Expand All @@ -55,7 +57,7 @@ function __screen() {
function __kill_grep() {
ps aux | grep "$1" | awk '{print $2}' | sort -k2 -rn |
while read -r pid; do
kill -2 "$pid"
kill -2 -"$pid"
done
}

Expand Down Expand Up @@ -146,11 +148,11 @@ function cirquetest_run_test() {
# Start Cirque flash server
export CURRENT_TEST="$1"
export DEVICE_LOG_DIR="$LOG_DIR/$CURRENT_TEST"/device_logs
shift
mkdir -p "$DEVICE_LOG_DIR"
__cirquetest_start_flask &
sleep 5
cd "$TEST_DIR"
./"$1.sh"
"$TEST_DIR/$CURRENT_TEST.sh" "$@"
exitcode=$?
__cirquetest_clean_flask
# TODO: Do docker system prune, we cannot filter which container
Expand Down
36 changes: 2 additions & 34 deletions src/test_driver/linux-cirque/ManualTest.sh
Original file line number Diff line number Diff line change
Expand Up @@ -24,42 +24,10 @@
# ./scripts/tests/cirque_tests.sh run_test ManualTest
# under CHIP checkout.

set -e
set -ex

SOURCE="${BASH_SOURCE[0]}"
SOURCE_DIR="$(cd -P "$(dirname "$SOURCE")" >/dev/null 2>&1 && pwd)"
REPO_DIR="$SOURCE_DIR/../../../"

chip_tool_dir=$REPO_DIR/examples/chip-tool
chip_light_dir=$REPO_DIR/examples/lighting-app/linux

function build_chip_tool() {
# These files should be successfully compiled elsewhere.
source "$REPO_DIR/scripts/activate.sh" >/dev/null
set -x
cd "$chip_tool_dir"
gn gen --check --fail-on-unused-args out/debug >/dev/null
run_ninja -C out/debug
docker build -t chip_tool -f Dockerfile . 2>&1
}

function build_chip_lighting() {
source "$REPO_DIR/scripts/activate.sh" >/dev/null
set -x
cd "$chip_light_dir"
gn gen --check --fail-on-unused-args out/debug
run_ninja -C out/debug
docker build -t chip_server -f Dockerfile . 2>&1
set +x
}

function main() {
pushd .
build_chip_tool
build_chip_lighting
popd
python3 "$SOURCE_DIR/test-manual.py"
}

source "$SOURCE_DIR"/shell-helpers.sh
main
python3 "$SOURCE_DIR/test-manual.py" "$@"
21 changes: 19 additions & 2 deletions src/test_driver/linux-cirque/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,15 @@ In Project CHIP, cirque is used for integration tests.
There is a script for running cirque tests, you can find it at
`scripts/tests/cirque_tests.sh`

## "Docker out of docker" setup

If you don't want cirque break your local environment, you can enter a
environment insider docker

```
integrations/docker/images/chip-build-cirque/run.sh --privileged --volume /dev/pts:/dev/pts --volume /tmp:/tmp -it -- bash
```

## Setting up cirque environment

After checkout, in your local project chip directory, run:
Expand Down Expand Up @@ -85,7 +94,14 @@ LOG_DIR=/some/log/directory scripts/tests/cirque_tests.sh run_test OnOffClusterT
You can run a ManualTest to setup test topology only:

```
scripts/tests/cirque_tests.sh run_test ManualTest
./scripts/tests/cirque_tests.sh run_test ManualTest -t <topology file>
```

The topology file is a JSON file, which contains the definition of each node in
the network.

```
./scripts/tests/cirque_tests.sh run_test ManualTest -t src/test_driver/linux-cirque/topologies/three_node_with_thread.json
```

It will print the container id in log, you can execute commands inside them.
Expand Down Expand Up @@ -115,4 +131,5 @@ It will print the container id in log, you can execute commands inside them.
After you finished you test, press `Ctrl-C` and it will clean up testing
environment.
Refer to `test-manual.py` and `ManualTest.sh` for detail.
Refer to `test-manual.py`, `ManualTest.sh`, and tolologies file under
`topologies` for detail.
11 changes: 7 additions & 4 deletions src/test_driver/linux-cirque/helper/CHIPTestBase.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ def __init__(self, cirque_url, device_config):
self.device_ids = []
self.devices = []
self.non_ap_devices = []
self.thread_devices = []
self.ap_devices = []

# The entrance of the whole test
Expand Down Expand Up @@ -198,7 +199,7 @@ def connect_to_thread_network(self):
this network.
'''
self.logger.info("Running commands to form default Thread network")
for device in self.non_ap_devices:
for device in self.thread_devices:
self.wait_for_device_output(device['id'], "Border router agent started.", 5)

otInitCommands = [
Expand All @@ -209,19 +210,19 @@ def connect_to_thread_network(self):
"ot-ctl thread start",
"ot-ctl dataset active", # Emit
]
for device in self.non_ap_devices:
for device in self.thread_devices:
# Set default openthread provisioning
for cmd in otInitCommands:
self.execute_device_cmd(device['id'], cmd)
self.logger.info("Waiting for Thread network to be formed...")
threadNetworkFormed = False
for i in range(30):
roles = list()
for device in self.non_ap_devices:
for device in self.thread_devices:
# We can only check the status of ot-agent by query its state.
reply = self.execute_device_cmd(device['id'], 'ot-ctl state')
roles.append(reply['output'].split()[0])
threadNetworkFormed = (roles.count('leader') == 1) and (roles.count('leader') + roles.count('router') + roles.count('child') == len(self.non_ap_devices))
threadNetworkFormed = (roles.count('leader') == 1) and (roles.count('leader') + roles.count('router') + roles.count('child') == len(self.thread_devices))
if threadNetworkFormed:
break
time.sleep(1)
Expand Down Expand Up @@ -348,6 +349,8 @@ def initialize_home(self):
self.device_ids = [device_id for device_id in self.device_config]
self.non_ap_devices = [device for device in self.device_config.values()
if device['type'] != 'wifi_ap']
self.thread_devices = [device for device in self.device_config.values()
if device['capability'].get('Thread', None) is not None]
self.ap_devices = [device for device in self.device_config.values()
if device['type'] == 'wifi_ap']

Expand Down
60 changes: 46 additions & 14 deletions src/test_driver/linux-cirque/test-manual.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
import os
import time
import sys
import json
from optparse import OptionParser, OptionValueError

from helper.CHIPTestBase import CHIPVirtualHome

Expand All @@ -30,20 +32,7 @@
# base_image: The image of the container.
# capability: A list of capability of the container, Thread+Interactive should fit in most cases.
# rcp_mode: This is used for Thread network setup, set it to True for CHIP.
DEVICE_CONFIG = {
'device0': {
'type': 'CHIP-Server',
'base_image': 'chip_server',
'capability': ['Thread', 'Interactive'],
'rcp_mode': True,
},
'device1': {
'type': 'CHIP-Tool',
'base_image': 'chip_tool',
'capability': ['Thread', 'Interactive'],
'rcp_mode': True,
}
}
DEVICE_CONFIG = {}

# Set this to True to set up a test thread network if you don't want to test network commissioning.
# Note: If you enable this, all devices MUST have Thread capability or the script may fail.
Expand All @@ -57,6 +46,7 @@
#############################################################

CIRQUE_URL = "http://localhost:5000"
CHIP_REPO = os.path.join(os.path.abspath(os.path.dirname(__file__)), "..", "..", "..")

logger = logging.getLogger('CHIPCirqueTest')
logger.setLevel(logging.INFO)
Expand Down Expand Up @@ -92,6 +82,48 @@ def wait_for_interrupt(self):
except KeyboardInterrupt:
self.logger.info("KeyboardInterrupt received, quit now")

def _parse_mount_dir(config):
for v in config.values():
if "Mount" not in v.get("capability", {}):
continue
_mount_pairs = v.get("mount_pairs", [])
for mount in _mount_pairs:
mount[0] = mount[0].format(chip_repo = CHIP_REPO)
mount[1] = mount[1].format(chip_repo = CHIP_REPO)
v["mount_pairs"] = _mount_pairs
return config

if __name__ == "__main__":
optParser = OptionParser()
optParser.add_option(
"-t",
"--topology",
action="store",
dest="topologyFile",
type='str',
default=None,
help="The topology to be set up by cirque framework.",
metavar="<timeout-second>",
)
optParser.add_option(
"--default-thread-network",
action="store_true",
dest="setupDefaultThreadNetwork",
default=False,
help="Setup default thread network to nodes that supports thread."
)

(options, remainingArgs) = optParser.parse_args(sys.argv[1:])

if not options.topologyFile:
raise Exception("Must specify a topology file!")

with open(options.topologyFile, "r") as fp:
config_operations = [_parse_mount_dir]
DEVICE_CONFIG = json.load(fp)
for op in config_operations:
DEVICE_CONFIG = op(DEVICE_CONFIG)

SETUP_TEST_THREAD_NETWORK = options.setupDefaultThreadNetwork

sys.exit(TestManually(DEVICE_CONFIG).run_test())
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"device0": {
"type": "CHIP-00",
"base_image": "connectedhomeip/chip-cirque-device-base",
"capability": ["Thread", "Interactive", "Mount"],
"mount_pairs": [["{chip_repo}", "{chip_repo}"]],
"rcp_mode": true
},
"device1": {
"type": "CHIP-01",
"base_image": "connectedhomeip/chip-cirque-device-base",
"capability": ["Thread", "Interactive", "Mount"],
"mount_pairs": [["{chip_repo}", "{chip_repo}"]],
"rcp_mode": true
},
"device2": {
"type": "CHIP-02",
"base_image": "connectedhomeip/chip-cirque-device-base",
"capability": ["Thread", "Interactive", "Mount"],
"mount_pairs": [["{chip_repo}", "{chip_repo}"]],
"rcp_mode": true
}
}
16 changes: 16 additions & 0 deletions src/test_driver/linux-cirque/topologies/two_node_with_thread.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"device0": {
"type": "CHIP-00",
"base_image": "connectedhomeip/chip-cirque-device-base",
"capability": ["Thread", "Interactive", "Mount"],
"mount_pairs": [["{chip_repo}", "{chip_repo}"]],
"rcp_mode": true
},
"device1": {
"type": "CHIP-01",
"base_image": "connectedhomeip/chip-cirque-device-base",
"capability": ["Thread", "Interactive", "Mount"],
"mount_pairs": [["{chip_repo}", "{chip_repo}"]],
"rcp_mode": true
}
}

0 comments on commit 1003112

Please sign in to comment.