From ad91ac3b9c697357d1f89b806589e0533e2ed87a Mon Sep 17 00:00:00 2001 From: Yakun Xu Date: Wed, 3 Feb 2021 13:50:18 +0800 Subject: [PATCH] [posix] enable expect tests on macOS (#5384) This commit enables expect tests on macOS, also includes the following required changes: * Fixed bound to interface issue on macOS. * Added ability to configure scan period, because macOS environment on GitHub Actions is much slower. --- .github/workflows/posix.yml | 22 ++++++ script/test | 75 ++++++++++++------- src/core/config/mac.h | 10 +++ src/core/mac/mac.hpp | 2 +- src/posix/platform/udp.cpp | 5 +- tests/scripts/expect/_common.exp | 39 ++++++---- tests/scripts/expect/_multinode.exp | 2 +- .../scripts/expect/posix-rcp-restoration.exp | 3 + tests/scripts/expect/tun-sntp.exp | 8 +- 9 files changed, 112 insertions(+), 54 deletions(-) diff --git a/.github/workflows/posix.yml b/.github/workflows/posix.yml index 0f1f5502c..13745f080 100644 --- a/.github/workflows/posix.yml +++ b/.github/workflows/posix.yml @@ -40,6 +40,28 @@ jobs: GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}" if: "github.ref != 'refs/heads/master'" + macOS: + runs-on: macos-10.15 + env: + CFLAGS: -DCLI_COAP_SECURE_USE_COAP_DEFAULT_HANDLER=1 -DOPENTHREAD_CONFIG_MLE_MAX_CHILDREN=15 -DOPENTHREAD_CONFIG_MAC_SCAN_DURATION=500 + CXXFLAGS: -DCLI_COAP_SECURE_USE_COAP_DEFAULT_HANDLER=1 -DOPENTHREAD_CONFIG_MLE_MAX_CHILDREN=15 -DOPENTHREAD_CONFIG_MAC_SCAN_DURATION=500 + CC: clang + CXX: clang++ + steps: + - uses: actions/checkout@v2 + - name: Bootstrap + run: | + brew install ninja + - name: Run RCP Mode + run: | + OT_OPTIONS='-DOT_READLINE=OFF -DOT_APP_NCP=OFF' OT_NODE_TYPE=rcp-cli ./script/test build expect + - name: Run Native IP Mode + run: | + brew install dnsmasq + echo 'listen-address=::1' | sudo tee $(brew --prefix)/etc/dnsmasq.conf + sudo brew services start dnsmasq + host ipv6.google.com ::1 + OT_OPTIONS=-DOT_READLINE=OFF OT_NATIVE_IP=1 OT_NODE_TYPE=rcp-cli ./script/test clean build expect posix-cli: runs-on: ubuntu-20.04 diff --git a/script/test b/script/test index b2156d243..c25730e8c 100755 --- a/script/test +++ b/script/test @@ -37,6 +37,7 @@ readonly OT_SRCDIR="${PWD}" readonly COLOR_PASS='\033[0;32m' readonly COLOR_FAIL='\033[0;31m' +readonly COLOR_SKIP='\033[0;33m' readonly COLOR_NONE='\033[0m' readonly OT_NODE_TYPE="${OT_NODE_TYPE:-cli}" @@ -290,6 +291,43 @@ do_pktverify() python3 ./tests/scripts/thread-cert/pktverify/verify.py "$1" } +ot_exec_expect_script() +{ + local log_file="tmp/log_expect" + local script="$1" + + echo -e "\n${COLOR_PASS}EXEC${COLOR_NONE} ${script}" + sudo killall ot-rcp || true + sudo killall ot-cli || true + sudo killall ot-cli-ftd || true + sudo killall ot-cli-mtd || true + sudo rm -rf tmp + mkdir tmp + { + if [[ ${OT_NATIVE_IP} == 1 ]]; then + sudo -E expect -df "${script}" 2>"${log_file}" + else + expect -df "${script}" 2>"${log_file}" + fi + } || { + local EXIT_CODE=$? + + # The exit status 77 for skipping is inherited from automake's test driver for script-based testsuites + if [[ ${EXIT_CODE} == 77 ]]; then + echo -e "\n${COLOR_SKIP}SKIP${COLOR_NONE} ${script}" + return 0 + else + echo -e "\n${COLOR_FAIL}FAIL${COLOR_NONE} ${script}" + cat "${log_file}" >&2 + return "${EXIT_CODE}" + fi + } + echo -e "\n${COLOR_PASS}PASS${COLOR_NONE} ${script}" + if [[ ${VERBOSE} == 1 ]]; then + cat "${log_file}" >&2 + fi +} + do_expect() { local test_patterns @@ -306,33 +344,13 @@ do_expect() test_patterns=(-name 'cli-*.exp' -o -name 'simulation-*.exp') fi - local log_file="tmp/log_expect" - while read -r script; do - sudo rm -rf tmp - mkdir tmp - { - if [[ ${OT_NATIVE_IP} == 1 ]]; then - sudo -E expect -df "${script}" 2>"${log_file}" - else - expect -df "${script}" 2>"${log_file}" - fi - } || { - local exit_code=$? - cat "${log_file}" >&2 - echo -e "${COLOR_FAIL}FAIL${COLOR_NONE} ${script}" - exit "${exit_code}" - } - if [[ ${VERBOSE} == 1 ]]; then - cat "${log_file}" >&2 - fi - echo -e "${COLOR_PASS}PASS${COLOR_NONE} ${script}" - done < <( - if [[ $# != 0 ]]; then - for script in "$@"; do echo ${script}; done - else - find tests/scripts/expect -type f -executable \( "${test_patterns[@]}" \) - fi - ) + export -f ot_exec_expect_script + + if [[ $# != 0 ]]; then + for script in "$@"; do bash -c "ot_exec_expect_script ${script}"; done + else + find tests/scripts/expect -type f -perm "$([[ $OSTYPE == darwin* ]] && echo '+' || echo '/')"111 \( "${test_patterns[@]}" \) -exec bash -c 'ot_exec_expect_script "$1"' _ {} \; + fi exit 0 } @@ -348,7 +366,8 @@ ENVIRONMENTS: The default is 'cli'. OT_NATIVE_IP 1 to enable platform UDP and netif on POSIX platform. The default is 0. VERBOSE 1 to build or test verbosely. The default is 0. - VIRTUAL_TIME 1 for virtual time, otherwise real time. The default is 1. + VIRTUAL_TIME 1 for virtual time, otherwise real time. The default value is 0 when running expect tests, + otherwise default value is 1. THREAD_VERSION 1.1 for Thread 1.1 stack, 1.2 for Thread 1.2 stack. The default is 1.1. INTER_OP 1 to build 1.1 together. Only works when THREAD_VERSION is 1.2. The default is 0. INTER_OP_BBR 1 to build bbr version together. Only works when THREAD_VERSION is 1.2. The default is 1. diff --git a/src/core/config/mac.h b/src/core/config/mac.h index 7ab7b87b8..22a68c258 100644 --- a/src/core/config/mac.h +++ b/src/core/config/mac.h @@ -407,4 +407,14 @@ #define OPENTHREAD_CONFIG_CSL_RECEIVE_TIME_AHEAD 2 #endif +/** + * @def OPENTHREAD_CONFIG_MAC_SCAN_DURATION + * + * This setting configures the default scan duration in milliseconds. + * + */ +#ifndef OPENTHREAD_CONFIG_MAC_SCAN_DURATION +#define OPENTHREAD_CONFIG_MAC_SCAN_DURATION 300 +#endif + #endif // CONFIG_MAC_H_ diff --git a/src/core/mac/mac.hpp b/src/core/mac/mac.hpp index caa413b63..511565163 100644 --- a/src/core/mac/mac.hpp +++ b/src/core/mac/mac.hpp @@ -79,7 +79,7 @@ enum kDataPollTimeout = 100, ///< Timeout for receiving Data Frame (milliseconds). kSleepDelay = 300, ///< Max sleep delay when frame is pending (milliseconds). - kScanDurationDefault = 300, ///< Default interval between channels (milliseconds). + kScanDurationDefault = OPENTHREAD_CONFIG_MAC_SCAN_DURATION, ///< Default interval between channels (milliseconds). kMaxCsmaBackoffsDirect = OPENTHREAD_CONFIG_MAC_MAX_CSMA_BACKOFFS_DIRECT, ///< macMaxCsmaBackoffs for direct transmissions diff --git a/src/posix/platform/udp.cpp b/src/posix/platform/udp.cpp index 027990afd..96b3b978a 100644 --- a/src/posix/platform/udp.cpp +++ b/src/posix/platform/udp.cpp @@ -323,7 +323,7 @@ otError otPlatUdpBindToNetif(otUdpSocket *aUdpSocket, otNetifIdentifier aNetifId VerifyOrExit(setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, &gNetifName, strlen(gNetifName)) == 0, error = OT_ERROR_FAILED); #else // __NetBSD__ || __FreeBSD__ || __APPLE__ - VerifyOrExit(setsockopt(fd, IPPROTO_IP, IP_BOUND_IF, &gNetifIndex, sizeof(gNetifIndex)) == 0, + VerifyOrExit(setsockopt(fd, IPPROTO_IPV6, IPV6_BOUND_IF, &gNetifIndex, sizeof(gNetifIndex)) == 0, error = OT_ERROR_FAILED); #endif // __linux__ break; @@ -335,7 +335,8 @@ otError otPlatUdpBindToNetif(otUdpSocket *aUdpSocket, otNetifIdentifier aNetifId VerifyOrExit(setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, gBackboneNetifName, strlen(gBackboneNetifName)) == 0, error = OT_ERROR_FAILED); #else // __NetBSD__ || __FreeBSD__ || __APPLE__ - VerifyOrExit(setsockopt(fd, IPPROTO_IP, IP_BOUND_IF, &gBackboneNetifIndex, sizeof(gBackboneNetifIndex)) == 0, + VerifyOrExit(setsockopt(fd, IPPROTO_IPV6, IPV6_BOUND_IF, &gBackboneNetifIndex, sizeof(gBackboneNetifIndex)) == + 0, error = OT_ERROR_FAILED); #endif // __linux__ #else diff --git a/tests/scripts/expect/_common.exp b/tests/scripts/expect/_common.exp index f68380b82..c97f211ac 100644 --- a/tests/scripts/expect/_common.exp +++ b/tests/scripts/expect/_common.exp @@ -27,8 +27,15 @@ # POSSIBILITY OF SUCH DAMAGE. # +proc skip_on_macos {} { + set OSTYPE [lindex $::tcl_platform(os) 0] + + if { $OSTYPE == "Darwin" } { + exit 77 + } +} + proc wait_for {command success {failure {[\r\n]FAILURE_NOT_EXPECTED[\r\n]}}} { - set result 0 set timeout 1 for {set i 0} {$i < 20} {incr i} { if {$command != ""} { @@ -37,22 +44,17 @@ proc wait_for {command success {failure {[\r\n]FAILURE_NOT_EXPECTED[\r\n]}}} { expect { -re $success { - set result 1 + return 0 } -re $failure { - error "Got failure in wait_for" + fail "Failed due to '$failure' found" } timeout { # Do nothing } } - if {$result == 1} { - break - } - } - if {$result == 0} { - error "Timed out in wait_for" } + fail "Failed due to '$success' not found" } proc expect_line {line} { @@ -107,7 +109,7 @@ proc spawn_node {id {type ""} {radio_url ""}} { } expect_after { - timeout { error "Timed out" } + timeout { fail "Timed out" } } set spawn_ids($id) $spawn_id @@ -123,12 +125,6 @@ proc switch_node {id} { set spawn_id $spawn_ids($id) } -proc dispose_node {id} { - switch_node $id - send "\x04" - expect eof -} - proc setup_leader {} { send "dataset init new\n" expect_line "Done" @@ -144,6 +140,12 @@ proc setup_leader {} { expect_line "Done" } +proc dispose_node {id} { + switch_node $id + send "\x04" + expect eof +} + proc dispose_all {} { global spawn_ids set max_node [array size spawn_ids] @@ -188,4 +190,9 @@ proc setup_default_network {} { expect_line "Done" } +proc fail {message} { + dispose_all + error $message +} + set timeout 10 diff --git a/tests/scripts/expect/_multinode.exp b/tests/scripts/expect/_multinode.exp index ee568e387..9170c3fa5 100644 --- a/tests/scripts/expect/_multinode.exp +++ b/tests/scripts/expect/_multinode.exp @@ -77,7 +77,7 @@ proc setup_node {node {mode "r"} {role "child"}} { expect_line "Done" send "joiner start $::JOINER_PSK\n" expect_line "Done" - wait_for "" "Join success" + wait_for "" "Join success" "Join failed" send "thread start\n" expect_line "Done" wait_for "state" $role diff --git a/tests/scripts/expect/posix-rcp-restoration.exp b/tests/scripts/expect/posix-rcp-restoration.exp index 25c23f4c6..c0dac4c24 100755 --- a/tests/scripts/expect/posix-rcp-restoration.exp +++ b/tests/scripts/expect/posix-rcp-restoration.exp @@ -31,6 +31,9 @@ source "tests/scripts/expect/_common.exp" source "tests/scripts/expect/_multinode.exp" +# The expect on macOS doesn't support `try` or `file tempfile`. +skip_on_macos + file tempfile socat_out set socat_pid [exec socat -d -d pty,raw,echo=0 pty,raw,echo=0 >/dev/null 2>$socat_out &] while {true} { diff --git a/tests/scripts/expect/tun-sntp.exp b/tests/scripts/expect/tun-sntp.exp index e45d77c12..a72439004 100755 --- a/tests/scripts/expect/tun-sntp.exp +++ b/tests/scripts/expect/tun-sntp.exp @@ -27,14 +27,10 @@ # POSSIBILITY OF SUCH DAMAGE. # -set OSTYPE [lindex $tcl_platform(os) 0] - -if { $OSTYPE == "Darwin" } { - exit 77 -} - source "tests/scripts/expect/_common.exp" +skip_on_macos + spawn_node 1 send "panid 0xface\n"