Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[python] Enhancement of manual test using Cirque #7122

Merged
merged 8 commits into from
Jun 8, 2021
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 \
gdb python3 python3-pip libcairo2-dev libjpeg-dev libgif-dev python3-dev \
&& apt-get install -y libglib2.0 avahi-daemon libavahi-client3 avahi-utils \
&& 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
}
}