• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/bin/bash
2#
3#  Copyright (c) 2018, The OpenThread Authors.
4#  All rights reserved.
5#
6#  Redistribution and use in source and binary forms, with or without
7#  modification, are permitted provided that the following conditions are met:
8#  1. Redistributions of source code must retain the above copyright
9#     notice, this list of conditions and the following disclaimer.
10#  2. Redistributions in binary form must reproduce the above copyright
11#     notice, this list of conditions and the following disclaimer in the
12#     documentation and/or other materials provided with the distribution.
13#  3. Neither the name of the copyright holder nor the
14#     names of its contributors may be used to endorse or promote products
15#     derived from this software without specific prior written permission.
16#
17#  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18#  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19#  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20#  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
21#  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22#  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23#  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24#  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25#  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26#  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27#  POSSIBILITY OF SUCH DAMAGE.
28#
29
30set -e
31set -x
32
33die()
34{
35    echo " *** ERROR: " "$*"
36    exit 1
37}
38
39at_exit()
40{
41    EXIT_CODE=$?
42
43    sudo killall expect || true
44    sudo killall ot-ctl || true
45    sudo killall ot-daemon || true
46    sudo killall ot-cli || true
47    sudo killall ot-rcp || true
48    sudo killall socat || true
49
50    exit $EXIT_CODE
51}
52
53wait_for_socat()
54{
55    if [[ "$(head -n2 "$SOCAT_OUTPUT" | wc -l | tr -d ' ')" == 2 ]]; then
56        RADIO_PTY=$(head -n1 "$SOCAT_OUTPUT" | grep -o '/dev/.\+')
57        CORE_PTY=$(head -n2 "$SOCAT_OUTPUT" | tail -n1 | grep -o '/dev/.\+')
58        return 0
59    else
60        echo 'Still waiting for socat'
61    fi
62    return 1
63}
64
65wait_for_leader()
66{
67    if grep -q leader "$OT_OUTPUT"; then
68        return 0
69    else
70        echo 'Still waiting for leader'
71    fi
72    return 1
73}
74
75timeout_run()
76{
77    local count="$1"
78    local exit_code
79    shift 1
80
81    while [[ $count != 0 && $exit_code != 0 ]]; do
82        count=$((count - 1))
83        "$@" && return 0 || exit_code=$?
84        sleep 1
85    done
86
87    return $exit_code
88}
89
90do_build()
91{
92    ./script/cmake-build simulation
93    ./script/cmake-build posix -DOT_PLATFORM_NETIF=1 -DOT_PLATFORM_UDP=1 -DOT_UDP_FORWARD=0 -DOT_POSIX_MAX_POWER_TABLE=1 -DOT_DAEMON="${OT_DAEMON}" -DOT_READLINE="${OT_READLINE}"
94}
95
96do_check()
97{
98    trap at_exit INT TERM EXIT
99
100    sudo rm -rf tmp
101
102    SOCAT_OUTPUT=/tmp/ot-socat
103    OT_OUTPUT=/tmp/ot-output
104    socat -d -d pty,raw,echo=0 pty,raw,echo=0 >/dev/null 2>$SOCAT_OUTPUT &
105    timeout_run 10 wait_for_socat
106    echo 'RADIO_PTY' "$RADIO_PTY"
107    echo 'CORE_PTY' "$CORE_PTY"
108
109    RADIO_NCP_PATH="$PWD/build/simulation/examples/apps/ncp/ot-rcp"
110
111    # shellcheck disable=SC2094
112    $RADIO_NCP_PATH 1 >"$RADIO_PTY" <"$RADIO_PTY" &
113
114    # Cover setting a valid network interface name.
115    readonly VALID_NETIF_NAME="wan$(date +%H%M%S)"
116
117    RADIO_URL="spinel+hdlc+uart://${CORE_PTY}?region=US&max-power-table=11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26"
118
119    if [[ ${OT_DAEMON} == 'on' ]]; then
120        sudo -E "$PWD/build/posix/src/posix/ot-daemon" -d7 -v -I "${VALID_NETIF_NAME}" "${RADIO_URL}" 2>&1 | tee "${OT_OUTPUT}" &
121        sleep 3
122        # macOS cannot explicitly set network interface name
123        NETIF_NAME=$(grep -o 'Thread interface: .\+' "${OT_OUTPUT}" | cut -d: -f2 | tr -d ' \r\n')
124        OT_CTL_PATH="$PWD/build/posix/src/posix/ot-ctl"
125        if [[ ${OT_DAEMON_ALLOW_ALL} == 1 ]]; then
126            OT_CTL=("${OT_CTL_PATH}")
127        else
128            OT_CTL=(sudo "${OT_CTL_PATH}")
129        fi
130        "${OT_CTL[@]}" -I "${NETIF_NAME}" panid 0xface | grep 'Done' || die 'failed to set panid with ot-ctl'
131
132        # verify supports options in OpenThread commands without separator --
133        "${OT_CTL[@]}" -I "${NETIF_NAME}" pskc -p 123456 | grep 'Done' || die 'unable to set pskc'
134
135        # verify this reset and factoryreset end immediately
136        "${OT_CTL[@]}" -I "${NETIF_NAME}" reset
137        # sleep a while for daemon ready
138        sleep 2
139        "${OT_CTL[@]}" -I "${NETIF_NAME}" factoryreset
140        # sleep a while for daemon ready
141        sleep 2
142
143        readonly OPENTHREAD_CONFIG_CLI_MAX_LINE_LENGTH=640
144        local -r kMaxStringLength="$((OPENTHREAD_CONFIG_CLI_MAX_LINE_LENGTH - 1))"
145
146        # verify success if command length doesn't exceed the limit
147        for len in $(seq 1 ${kMaxStringLength}); do
148            "${OT_CTL[@]}" -I "${NETIF_NAME}" "$(printf '1%.0s' $(seq 1 "${len}"))"
149        done
150
151        # verify failure if command length exceeds the limit
152        len=${OPENTHREAD_CONFIG_CLI_MAX_LINE_LENGTH}
153        if "${OT_CTL[@]}" -I "${NETIF_NAME}" "$(printf '1%.0s' $(seq 1 "${len}"))"; then
154            die
155        fi
156        OT_CLI_CMD="${OT_CTL[*]} -I ${NETIF_NAME}"
157    else
158        OT_CLI="$PWD/build/posix/src/posix/ot-cli"
159        sudo "${OT_CLI}" -I "${VALID_NETIF_NAME}" -n "${RADIO_URL}"
160
161        # Cover setting a too long(max is 15 characters) network interface name.
162        # Expect exit code to be 2(OT_EXIT_INVALID_ARGUMENTS).
163        readonly INVALID_NETIF_NAME="wan0123456789123"
164        sudo "${OT_CLI}" -I "${INVALID_NETIF_NAME}" -n "${RADIO_URL}" || test $? = 2
165
166        OT_CLI_CMD="$PWD/build/posix/src/posix/ot-cli ${RADIO_URL}"
167    fi
168
169    sudo expect <<EOF | tee "${OT_OUTPUT}" &
170spawn ${OT_CLI_CMD}
171expect_after {
172    timeout { error }
173}
174send "region\r\n"
175expect "US"
176expect "Done"
177send "panid 0xface\r\n"
178expect "Done"
179send "routerselectionjitter 1\r\n"
180expect "Done"
181send "ifconfig up\r\n"
182expect "Done"
183send "thread start\r\n"
184expect "Done"
185sleep 10
186send "state\r\n"
187expect "leader"
188expect "Done"
189send "extaddr\r\n"
190expect "Done"
191send "dataset active\r\n"
192expect "Done"
193send "ipaddr\r\n"
194expect "Done"
195send "coex\r\n"
196expect "Done"
197send "coap start\r\n"
198expect "Done"
199send "coap resource TestResource\r\n"
200expect "Done"
201send "coap set TestContent\r\n"
202expect "Done"
203set timeout -1
204expect eof
205EOF
206
207    sleep 5
208
209    # wait until the node becomes leader
210    timeout_run 10 wait_for_leader
211
212    # wait coap service start
213    sleep 5
214
215    netstat -an | grep -q 5683 || die 'Application CoAP port is not available!'
216
217    extaddr=$(grep -ao -A +1 'extaddr' $OT_OUTPUT | tail -n1 | tr -d '\r\n\0')
218    echo "Extended address is: ${extaddr}"
219
220    prefix=$(grep -ao 'Mesh Local Prefix: [0-9a-f:]\+' $OT_OUTPUT | cut -d: -f2- | tr -d ' \r\n')
221    LEADER_ALOC="${prefix}ff:fe00:fc00"
222
223    # skip testing CoAP for https://github.com/openthread/openthread/issues/6363
224    [[ $OSTYPE == "linux-gnu"* ]] || return 0
225
226    if [[ ${OT_DAEMON} == 'on' ]]; then
227        sudo killall -9 expect || true
228        sudo killall -9 ot-ctl || true
229        NETIF_INDEX=$(ip link show "${NETIF_NAME}" | cut -f 1 -d ":" | head -n 1)
230        sudo PATH="$(dirname "${OT_CTL_PATH}"):${PATH}" \
231            python3 "$PWD/tests/scripts/misc/test_multicast_join.py" "${NETIF_INDEX}" "${NETIF_NAME}" \
232            || die 'multicast group join failed'
233    fi
234
235    # Retrievie test resource through application CoAP
236    coap_response=$(coap-client -B 5 -m GET "coap://[${LEADER_ALOC}]:5683/TestResource")
237    echo "CoAP response is: ${coap_response}"
238
239    # Verify CoAP response contains the test content
240    if [[ ${coap_response} == *TestContent* ]]; then
241        echo 'Success'
242    else
243        die 'Failed to access application CoAP'
244    fi
245
246    # Retrievie extended address through network diagnostic get
247    coap_response=$(echo -n '120100' | xxd -r -p | coap-client -B 5 -m POST "coap://[${LEADER_ALOC}]:61631/d/dg" -f-)
248
249    # Verify Tmf CoAP is blocked
250    if [[ -z ${coap_response} ]]; then
251        die 'Tmf is not blocked'
252    fi
253}
254
255main()
256{
257    if [[ $# == 0 ]]; then
258        do_build
259        do_check
260        return 0
261    fi
262
263    while [[ $# != 0 ]]; do
264        case $1 in
265            build)
266                do_build
267                ;;
268            check)
269                do_check
270                ;;
271            *)
272                echo "Unknown action: $1"
273                return 1
274                ;;
275        esac
276        shift
277    done
278}
279
280main "$@"
281