mirror of
https://github.com/espressif/openthread.git
synced 2026-06-05 21:14:49 +00:00
05ad9803d8
This commit adds a new Nexus test that implements the test specification in test-1-4-PIC-TC-1.md. The test verifies Border Router functionality including: - DHCPv6-PD client to obtain OMR prefix - Advertising route to OMR prefix on AIL (Stub Router) - DNS recursive resolver for public internet addresses - Connectivity (ICMPv6, UDP, TCP/HTTP) to internet and local servers New files: - tests/nexus/test_1_4_PIC_TC_1.cpp: C++ test execution - tests/nexus/verify_1_4_PIC_TC_1.py: Python pcap verification Nexus platform enhancements: - Enabled DHCPv6-PD client in openthread-core-nexus-config.h - Implemented DHCPv6-PD platform APIs in nexus_infra_if.cpp - Added RDNSS option to RA in nexus_infra_if.cpp - Improved packet delivery on infrastructure interface in nexus_core.cpp - Fixed upstream DNS query matching in nexus_dns.cpp
352 lines
8.7 KiB
Bash
Executable File
352 lines
8.7 KiB
Bash
Executable File
#!/bin/bash
|
|
#
|
|
# Copyright (c) 2026, The OpenThread Authors.
|
|
# All rights reserved.
|
|
#
|
|
# Redistribution and use in source and binary forms, with or without
|
|
# modification, are permitted provided that the following conditions are met:
|
|
# 1. Redistributions of source code must retain the above copyright
|
|
# notice, this list of conditions and the following disclaimer.
|
|
# 2. Redistributions in binary form must reproduce the above copyright
|
|
# notice, this list of conditions and the following disclaimer in the
|
|
# documentation and/or other materials provided with the distribution.
|
|
# 3. Neither the name of the copyright holder nor the
|
|
# names of its contributors may be used to endorse or promote products
|
|
# derived from this software without specific prior written permission.
|
|
#
|
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
|
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
# POSSIBILITY OF SUCH DAMAGE.
|
|
#
|
|
|
|
set -euo pipefail
|
|
|
|
# Determine the temporary directory
|
|
TEMP_DIR="${TMPDIR:-/tmp}"
|
|
|
|
# Determine the repository root
|
|
REPO_ROOT="$(cd "$(dirname "$0")"/../.. && pwd)"
|
|
|
|
# Determine the build directory
|
|
if [[ -z ${top_builddir:-} ]]; then
|
|
BUILD_DIR="build"
|
|
else
|
|
BUILD_DIR="$top_builddir"
|
|
fi
|
|
if [[ $BUILD_DIR != /* ]]; then
|
|
BUILD_DIR="${REPO_ROOT}/${BUILD_DIR}"
|
|
fi
|
|
NEXUS_BIN_DIR="${BUILD_DIR}/tests/nexus"
|
|
|
|
# Default test list if no arguments are provided
|
|
DEFAULT_TESTS=(
|
|
"1_1_5_1_1"
|
|
"1_1_5_1_2"
|
|
"1_1_5_1_3"
|
|
"1_1_5_1_4"
|
|
"1_1_5_1_5"
|
|
"1_1_5_1_6"
|
|
"1_1_5_1_7"
|
|
"1_1_5_1_8"
|
|
"1_1_5_1_9"
|
|
"1_1_5_1_10"
|
|
"1_1_5_1_11"
|
|
"1_1_5_1_12"
|
|
"1_1_5_1_13"
|
|
"1_1_5_2_1"
|
|
"1_1_5_2_3"
|
|
"1_1_5_2_4"
|
|
"1_1_5_2_5"
|
|
"1_1_5_2_6"
|
|
"1_1_5_2_7"
|
|
"1_1_5_3_1"
|
|
"1_1_5_3_2"
|
|
"1_1_5_3_3"
|
|
"1_1_5_3_4"
|
|
"1_1_5_3_5"
|
|
"1_1_5_3_6"
|
|
"1_1_5_3_7"
|
|
"1_1_5_3_8"
|
|
"1_1_5_3_9"
|
|
"1_1_5_3_10"
|
|
"1_1_5_3_11"
|
|
"1_1_5_5_1"
|
|
"1_1_5_5_2"
|
|
"1_1_5_5_3"
|
|
"1_1_5_5_4_1"
|
|
"1_1_5_5_4_2"
|
|
"1_1_5_5_5"
|
|
"1_1_5_5_7"
|
|
"1_1_5_6_1"
|
|
"1_1_5_6_2"
|
|
"1_1_5_6_3"
|
|
"1_1_5_6_4"
|
|
"1_1_5_6_5"
|
|
"1_1_5_6_6"
|
|
"1_1_5_6_7"
|
|
"1_1_5_6_9"
|
|
"1_1_5_7_1"
|
|
"1_1_5_7_2"
|
|
"1_1_5_7_3"
|
|
"1_1_5_8_2"
|
|
"1_1_5_8_3"
|
|
"1_2_BBR_TC_3"
|
|
"1_1_5_8_4"
|
|
"1_1_6_1_1_A"
|
|
"1_1_6_1_1_B"
|
|
"1_1_6_1_2_A"
|
|
"1_1_6_1_2_B"
|
|
"1_1_6_1_3_A"
|
|
"1_1_6_1_3_B"
|
|
"1_1_6_1_4"
|
|
"1_1_6_1_5"
|
|
"1_1_6_1_6"
|
|
"1_1_6_1_7"
|
|
"1_1_6_2_1_A"
|
|
"1_1_6_2_1_B"
|
|
"1_1_6_2_2"
|
|
"1_1_6_3_1_A"
|
|
"1_1_6_3_1_B"
|
|
"1_1_6_3_2"
|
|
"1_1_6_4_1_A"
|
|
"1_1_6_4_1_B"
|
|
"1_1_6_4_2"
|
|
"1_1_6_5_1"
|
|
"1_1_6_5_2"
|
|
"1_1_6_5_3"
|
|
"1_1_6_6_1"
|
|
"1_1_6_6_2"
|
|
"1_1_7_1_1"
|
|
"1_1_7_1_2"
|
|
"1_1_7_1_3"
|
|
"1_1_7_1_4"
|
|
"1_1_7_1_5"
|
|
"1_1_7_1_6"
|
|
"1_1_7_1_7"
|
|
"1_1_7_1_8"
|
|
"1_1_8_1_1"
|
|
"1_1_8_1_2"
|
|
"1_1_8_1_6"
|
|
"1_1_8_2_1"
|
|
"1_1_8_2_2"
|
|
"1_1_8_3_1"
|
|
"1_1_9_2_1"
|
|
"1_1_9_2_2"
|
|
"1_1_9_2_3"
|
|
"1_1_9_2_4"
|
|
"1_1_9_2_5"
|
|
"1_1_9_2_6"
|
|
"1_1_9_2_7"
|
|
"1_1_9_2_8"
|
|
"1_1_9_2_9"
|
|
"1_1_9_2_10"
|
|
"1_1_9_2_11"
|
|
"1_1_9_2_12"
|
|
"1_1_9_2_13"
|
|
"1_1_9_2_14"
|
|
"1_1_9_2_15"
|
|
"1_1_9_2_16"
|
|
"1_1_9_2_17"
|
|
"1_1_9_2_18"
|
|
"1_1_9_2_19"
|
|
"1_2_LP_5_2_1"
|
|
"1_2_LP_5_3_1"
|
|
"1_2_LP_5_3_2"
|
|
"1_2_LP_5_3_3"
|
|
"1_2_LP_5_3_4"
|
|
"1_2_LP_5_3_5"
|
|
"1_2_LP_5_3_6"
|
|
"1_2_LP_5_3_7"
|
|
"1_2_LP_5_3_8"
|
|
"1_2_LP_7_1_1"
|
|
"1_2_LP_7_1_2"
|
|
"1_2_LP_7_2_1"
|
|
"1_2_LP_7_2_2"
|
|
"1_2_MATN_TC_1"
|
|
"1_2_MATN_TC_2"
|
|
"1_2_MATN_TC_3"
|
|
"1_2_MATN_TC_4"
|
|
"1_2_MATN_TC_5"
|
|
"1_2_MATN_TC_7"
|
|
"1_2_MATN_TC_9"
|
|
"1_2_MATN_TC_10"
|
|
"1_2_MATN_TC_12"
|
|
"1_2_MATN_TC_15"
|
|
"1_2_MATN_TC_16"
|
|
"1_2_MATN_TC_19"
|
|
"1_2_MATN_TC_20"
|
|
"1_2_MATN_TC_21"
|
|
"1_2_MATN_TC_22"
|
|
"1_2_MATN_TC_23"
|
|
"1_2_MATN_TC_26"
|
|
"1_2_BBR_TC_1"
|
|
"1_2_BBR_TC_2"
|
|
"1_2_BBR_TC_3"
|
|
"1_3_DBR_TC_1"
|
|
"1_3_DBR_TC_2"
|
|
"1_3_DBR_TC_3"
|
|
"1_3_DBR_TC_6"
|
|
"1_3_DBR_TC_7A"
|
|
"1_3_DBR_TC_7B"
|
|
"1_3_DBR_TC_7C"
|
|
"1_3_DBR_TC_8"
|
|
"1_3_DBR_TC_10"
|
|
"1_3_DPR_TC_1"
|
|
"1_3_DPR_TC_2"
|
|
"1_3_SRP_TC_1"
|
|
"1_3_SRP_TC_2"
|
|
"1_3_SRP_TC_3"
|
|
"1_3_SRP_TC_4"
|
|
"1_3_SRP_TC_5"
|
|
"1_3_SRP_TC_6"
|
|
"1_3_SRP_TC_8"
|
|
"1_3_SRP_TC_11"
|
|
"1_3_SRP_TC_12"
|
|
"1_3_SRP_TC_13"
|
|
"1_3_SRP_TC_15"
|
|
"1_3_SRPC_TC_1"
|
|
"1_3_SRPC_TC_4"
|
|
"1_3_SRPC_TC_5"
|
|
"1_3_SRPC_TC_7"
|
|
"1_3_GEN_TC_1"
|
|
"1_3_GEN_TC_2"
|
|
"1_3_DIAG_TC_1"
|
|
"1_3_DIAG_TC_2"
|
|
"1_4_TREL_TC_1"
|
|
"1_4_TREL_TC_2"
|
|
"1_4_TREL_TC_3"
|
|
"1_4_TREL_TC_4"
|
|
"1_4_TREL_TC_5"
|
|
"1_4_TREL_TC_6"
|
|
"1_4_DNS_TC_1"
|
|
"1_4_DNS_TC_3"
|
|
"1_4_DNS_TC_5"
|
|
"1_4_PIC_TC_1"
|
|
"1_4_CS_TC_3"
|
|
)
|
|
|
|
# Use provided arguments or the default test list
|
|
if [[ $# -eq 0 ]]; then
|
|
TESTS_TO_RUN=("${DEFAULT_TESTS[@]}")
|
|
else
|
|
TESTS_TO_RUN=("$@")
|
|
fi
|
|
|
|
failed_tests=()
|
|
|
|
run_test()
|
|
{
|
|
local test_full="$1"
|
|
# Strip 'nexus_' prefix if present
|
|
test_full="${test_full#nexus_}"
|
|
|
|
local test_base="${test_full%_[ABC]}"
|
|
local topology=""
|
|
if [[ $test_full != "$test_base" ]]; then
|
|
topology="${test_full##*_}"
|
|
fi
|
|
|
|
local test_name="nexus_${test_base}"
|
|
local json_file="test_${test_full}.json"
|
|
local pcap_file="test_${test_full}.pcapng"
|
|
local verify_script="${REPO_ROOT}/tests/nexus/verify_${test_base}.py"
|
|
local nexus_bin="${NEXUS_BIN_DIR}/${test_name}"
|
|
|
|
if [[ ! -x $nexus_bin ]]; then
|
|
printf "Error: %s not found or not executable in %s. Did you build the tests?\n" "$test_name" "$NEXUS_BIN_DIR" >&2
|
|
return 1
|
|
fi
|
|
|
|
# Create a temporary directory for test artifacts
|
|
local work_dir
|
|
work_dir=$(mktemp -d "${TEMP_DIR}/nexus_test_${test_full}.XXXXXX")
|
|
local log_file="${work_dir}/test.log"
|
|
|
|
printf "Running %-40s... " "$test_full"
|
|
|
|
# Run the Nexus C++ test and verification in a subshell to isolate the working directory
|
|
(
|
|
cd "$work_dir"
|
|
|
|
# 1. Run the Nexus C++ test
|
|
export OT_NEXUS_PCAP_FILE="$pcap_file"
|
|
if ! "$nexus_bin" "$topology" "$json_file"; then
|
|
printf "C++ test %s FAILED\n" "$test_full" >&2
|
|
exit 1
|
|
fi
|
|
|
|
# 2. Run the verification script if it exists
|
|
if [[ -f $verify_script ]]; then
|
|
printf "\n"
|
|
printf "Running verification script %s...\n" "$verify_script"
|
|
if [[ ! -f $json_file ]]; then
|
|
printf "Error: %s not generated by %s.\n" "$json_file" "$test_name" >&2
|
|
exit 1
|
|
fi
|
|
|
|
if ! python3 "$verify_script" "$json_file"; then
|
|
printf "Verification for %s FAILED\n" "$test_full" >&2
|
|
exit 1
|
|
fi
|
|
fi
|
|
) >"$log_file" 2>&1
|
|
|
|
local exit_code="$?"
|
|
|
|
if [[ $exit_code -eq 0 ]]; then
|
|
printf " PASSED\n"
|
|
if [[ -d $work_dir && $work_dir == "${TEMP_DIR}/"* ]]; then
|
|
rm -rf "$work_dir"
|
|
fi
|
|
return 0
|
|
else
|
|
printf " FAILED\n"
|
|
printf "========================================================================================\n"
|
|
cat "$log_file"
|
|
printf "========================================================================================\n"
|
|
printf "Artifacts preserved in: %s\n" "$work_dir"
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
expanded_tests=()
|
|
for t in "${TESTS_TO_RUN[@]}"; do
|
|
case "$t" in
|
|
1_1_6_1_1 | 1_1_6_1_2 | 1_1_6_1_3 | 1_1_6_1_6 | 1_1_6_2_1 | 1_1_6_2_2 | 1_1_6_3_1 | 1_1_6_3_2 | 1_1_6_4_1 | 1_1_6_4_2 | 1_1_6_5_1 | 1_1_6_5_2 | 1_1_6_5_3 | 1_1_6_6_1 | 1_1_6_6_2 | 1_1_9_2_1 | 1_1_9_2_3 | 1_1_9_2_4 | 1_1_9_2_19)
|
|
expanded_tests+=("${t}_A" "${t}_B")
|
|
;;
|
|
1_3_GEN_TC_1)
|
|
expanded_tests+=("${t}_A" "${t}_B" "${t}_C")
|
|
;;
|
|
*)
|
|
expanded_tests+=("$t")
|
|
;;
|
|
esac
|
|
done
|
|
|
|
for t in "${expanded_tests[@]}"; do
|
|
if ! run_test "$t"; then
|
|
failed_tests+=("$t")
|
|
fi
|
|
done
|
|
|
|
printf "========================================================================================\n"
|
|
if [[ ${#failed_tests[@]} -eq 0 ]]; then
|
|
printf "All tests passed successfully.\n"
|
|
exit 0
|
|
else
|
|
printf "The following tests FAILED:\n" >&2
|
|
for f in "${failed_tests[@]}"; do
|
|
printf " - %s\n" "$f" >&2
|
|
done
|
|
exit 1
|
|
fi
|