| #!/bin/bash |
| # |
| # Copyright (c) 2020, 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. |
| # |
| # Test build and run otbr dbus server |
| # |
| |
| set -euxo pipefail |
| |
| OTBR_DBUS_SERVER_CONF=otbr-test-agent.conf |
| readonly OTBR_DBUS_SERVER_CONF |
| |
| on_exit() |
| { |
| local status=$? |
| |
| sudo systemctl stop test-otbr-agent || true |
| if [[ -v LEADER_PID ]]; then |
| kill "$LEADER_PID" || true |
| fi |
| if [[ -v CHILD_PID ]]; then |
| kill "$CHILD_PID" || true |
| fi |
| sudo killall dbus-monitor || true |
| sudo rm "/etc/dbus-1/system.d/${OTBR_DBUS_SERVER_CONF}" || true |
| |
| sed -n "/$TEST_HELLO/,\$p" /var/log/syslog | grep 'ot-cli\|otbr' |
| |
| return "${status}" |
| } |
| |
| ot_ctl() |
| { |
| sudo "${CMAKE_BINARY_DIR}"/third_party/openthread/repo/src/posix/ot-ctl "$@" |
| } |
| |
| otbr_factoryreset() |
| { |
| ot_ctl factoryreset |
| timeout 2 bash -c "while ! ot_ctl state; do sleep 1; done" |
| } |
| |
| scan_meshcop_service() |
| { |
| if command -v dns-sd; then |
| timeout 5 dns-sd -Z _meshcop._udp local. || true |
| else |
| avahi-browse -aprt || true |
| fi |
| } |
| |
| update_meshcop_txt_and_check() |
| { |
| sudo gdbus call --system --dest io.openthread.BorderRouter.wpan0 --method=io.openthread.BorderRouter.UpdateVendorMeshCopTxtEntries --object-path /io/openthread/BorderRouter/wpan0 "[('nn',[97])]" || true |
| sleep 5 |
| service="$(scan_meshcop_service)" |
| grep --binary-files=text "nn=OpenThread" <<<"${service}" |
| |
| sudo gdbus call --system --dest io.openthread.BorderRouter.wpan0 --method=io.openthread.BorderRouter.UpdateVendorMeshCopTxtEntries --object-path /io/openthread/BorderRouter/wpan0 "[('vn',[118,101,110,100,111,114])]" |
| sleep 5 |
| service="$(scan_meshcop_service)" |
| grep --binary-files=text "vn=vendor" <<<"${service}" |
| |
| sudo gdbus call --system --dest io.openthread.BorderRouter.wpan0 --method=io.openthread.BorderRouter.UpdateVendorMeshCopTxtEntries --object-path /io/openthread/BorderRouter/wpan0 "[]" |
| sleep 5 |
| service="$(scan_meshcop_service)" |
| grep --binary-files=text "vn=OpenThread" <<<"${service}" |
| |
| sudo gdbus call --system --dest io.openthread.BorderRouter.wpan0 --method=io.openthread.BorderRouter.UpdateVendorMeshCopTxtEntries --object-path /io/openthread/BorderRouter/wpan0 "[('A',[97,98,99]),('B',[49,50])]" |
| sleep 5 |
| service="$(scan_meshcop_service)" |
| grep --binary-files=text "A=abc" <<<"${service}" |
| grep --binary-files=text "B=12" <<<"${service}" |
| |
| sudo gdbus call --system --dest io.openthread.BorderRouter.wpan0 --method=io.openthread.BorderRouter.Reset --object-path /io/openthread/BorderRouter/wpan0 |
| sleep 5 |
| service="$(scan_meshcop_service)" |
| grep --binary-files=text "A=abc" <<<"${service}" |
| grep --binary-files=text "B=12" <<<"${service}" |
| |
| sudo gdbus call --system --dest io.openthread.BorderRouter.wpan0 --method=io.openthread.BorderRouter.UpdateVendorMeshCopTxtEntries --object-path /io/openthread/BorderRouter/wpan0 "[('A',[97,99]),('B',[49,50])]" |
| sleep 5 |
| service="$(scan_meshcop_service)" |
| grep --binary-files=text "A=ac" <<<"${service}" |
| grep --binary-files=text "B=12" <<<"${service}" |
| } |
| |
| test_get_properties() |
| { |
| local ot_version |
| local rcp_version |
| local thread_version |
| |
| ot_version=$(ot_ctl version | grep -oE '^OPENTHREAD.*$' | tr -d '\r\n') |
| rcp_version=$(ot_ctl rcp version | grep -oE '^OPENTHREAD.*$' | tr -d '\r\n') |
| thread_version=$(ot_ctl thread version | grep -oE '^[0-9]+' | tr -d '\r\n') |
| |
| local property_names="array:string:" |
| property_names+="OtHostVersion," |
| property_names+="OtRcpVersion," |
| property_names+="ThreadVersion," |
| property_names+="Uptime," |
| property_names+="RadioCoexMetrics," |
| property_names+="RadioSpinelMetrics," |
| property_names+="RcpInterfaceMetrics" |
| local result_pattern="\s+variant\s+string\s+\"${ot_version}\"" |
| result_pattern+="\s+variant\s+string\s+\"${rcp_version}\"" |
| result_pattern+="\s+variant\s+uint16\s+${thread_version}" |
| result_pattern+="\s+variant\s+uint64\s+\d+" # Uptime |
| result_pattern+="\s+variant\s+struct\s+{(\s+uint32\s+\d+){18}\s+boolean\s+(true|false)\s+}" # RadioCoexMetrics |
| result_pattern+="\s+variant\s+struct\s+{(\s+uint32\s+\d+){4}\s+}" # RadioSpinelMetrics |
| result_pattern+="\s+variant\s+struct\s+{\s+byte\s+\d+(\s+uint64\s+\d+){7}\s+}" # RcpInterfaceMetrics |
| sudo dbus-send --system --dest=io.openthread.BorderRouter.wpan0 --print-reply \ |
| /io/openthread/BorderRouter/wpan0 \ |
| io.openthread.BorderRouter.GetProperties \ |
| "${property_names}" \ |
| | grep -oPz "${result_pattern}" |
| } |
| |
| otbr_agent_service_start() |
| { |
| local -r EXIT_CODE_SHOULD_RESTART=7 |
| |
| sudo systemd-run --collect --no-ask-password -u test-otbr-agent -p "RestartForceExitStatus=$EXIT_CODE_SHOULD_RESTART" "${CMAKE_BINARY_DIR}"/src/agent/otbr-agent -d7 -I wpan0 "spinel+hdlc+forkpty://$(command -v ot-rcp)?forkpty-arg=1" |
| timeout 2 bash -c "while ! ot_ctl state; do sleep 1; done" |
| } |
| |
| suite_setup() |
| { |
| TEST_HELLO="$(basename "$0") started at $(date +%s)" |
| logger "$TEST_HELLO" |
| [[ -f /etc/dbus-1/system.d/"${OTBR_DBUS_SERVER_CONF}" ]] || { |
| local CONFIG_FILE_PATH="third_party/openthread/repo/src/posix/platform" |
| mkdir -p "${PWD}/${CONFIG_FILE_PATH}" && cp "${PROJECT_SOURCE_DIR}/${CONFIG_FILE_PATH}/openthread.conf.example" "${PWD}/${CONFIG_FILE_PATH}" |
| |
| sudo rm -rf tmp |
| sudo install -m 644 "${CMAKE_BINARY_DIR}"/src/agent/otbr-agent.conf /etc/dbus-1/system.d/"${OTBR_DBUS_SERVER_CONF}" |
| sudo service dbus reload |
| } |
| trap on_exit EXIT |
| |
| sudo systemctl start avahi-daemon |
| |
| export -f ot_ctl |
| } |
| |
| test_ready_signal() |
| { |
| # Because we do want to run the command as root but redirect as the normal user. |
| # shellcheck disable=SC2024 |
| sudo expect <<EOF |
| spawn dbus-monitor --system path=/io/openthread/BorderRouter/wpan0,member=Ready |
| set dbus_monitor \$spawn_id |
| spawn ${CMAKE_BINARY_DIR}/src/agent/otbr-agent -d7 -I wpan0 spinel+hdlc+forkpty://$(command -v ot-rcp)?forkpty-arg=1 |
| set spawn_id \$dbus_monitor |
| expect { |
| "member=Ready" { exit } |
| timeout { error "Failed to find Ready signal\n" } |
| } |
| EOF |
| } |
| |
| main() |
| { |
| suite_setup |
| |
| sudo "${CMAKE_BINARY_DIR}"/src/agent/otbr-agent -d7 -I wpan0 --radio-version "spinel+hdlc+forkpty://$(command -v ot-rcp)?forkpty-arg=1" | grep "OPENTHREAD" |
| |
| test_ready_signal |
| |
| otbr_agent_service_start |
| |
| otbr_factoryreset |
| |
| test_get_properties |
| |
| ot_ctl ifconfig up |
| ot_ctl thread start |
| |
| update_meshcop_txt_and_check |
| |
| otbr_factoryreset |
| |
| sudo dbus-send --system --dest=io.openthread.BorderRouter.wpan0 \ |
| --type=method_call --print-reply /io/openthread/BorderRouter/wpan0 \ |
| org.freedesktop.DBus.Introspectable.Introspect | grep JoinerStart |
| (sudo dbus-send --system --dest=io.openthread.BorderRouter.wpan0 \ |
| --type=method_call --print-reply /io/openthread/BorderRouter/wpan0 \ |
| io.openthread.BorderRouter.JoinerStart \ |
| string:ABCDEF string:mock string:mock \ |
| string:mock string:mock string:mock 2>&1 || true) | grep NotFound |
| |
| # Verify Eui64 property. 0x18b4300000000001 = 1780100529276321793 |
| sudo dbus-send --system --dest=io.openthread.BorderRouter.wpan0 --print-reply /io/openthread/BorderRouter/wpan0 org.freedesktop.DBus.Properties.Get string:io.openthread.BorderRouter string:Eui64 \ |
| | grep '1780100529276321793' |
| |
| # The ot-cli-ftd node is used to test Thread attach. |
| expect <<EOF & |
| spawn ot-cli-ftd 3 |
| send "panid 0x7890\r\n" |
| expect "Done" |
| send "networkname Test1\r\n" |
| expect "Done" |
| send "channel 15\r\n" |
| expect "Done" |
| send "ifconfig up\r\n" |
| expect "Done" |
| send "thread start\r\n" |
| expect "Done" |
| sleep 12 |
| send "state\r\n" |
| expect "leader" |
| expect "Done" |
| send "commissioner start\r\n" |
| expect "Commissioner: active" |
| send "commissioner joiner add * ABCDEF\r\n" |
| expect "Done" |
| expect "Joiner end" |
| send "commissioner stop\r\n" |
| set timeout -1 |
| expect eof |
| EOF |
| LEADER_PID=$! |
| |
| # The ot-cli-mtd node is used to test the child and neighbor table. |
| expect <<EOF & |
| spawn ot-cli-mtd 2 |
| send "panid 0x3456\r\n" |
| expect "Done" |
| send "networkkey 00112233445566778899aabbccddeeff\r\n" |
| expect "Done" |
| send "networkname Test\r\n" |
| expect "Done" |
| send "channel 11\r\n" |
| expect "Done" |
| send "ifconfig up\r\n" |
| expect "Done" |
| send "thread start\r\n" |
| expect "Done" |
| set timeout -1 |
| expect eof |
| EOF |
| CHILD_PID=$! |
| |
| sleep 12 |
| ot_ctl routerselectionjitter 1 |
| sudo dbus-send --system --dest=io.openthread.BorderRouter.wpan0 \ |
| --type=method_call --print-reply /io/openthread/BorderRouter/wpan0 \ |
| io.openthread.BorderRouter.JoinerStart \ |
| string:ABCDEF string:mock string:mock \ |
| string:mock string:mock string:mock |
| sleep 10 |
| ot_ctl state | grep router |
| |
| result_pattern="array\s+\[\s+variant\s+array\s+\[\s+struct\s+{\s+" |
| result_pattern+="uint64\s+\d+\s+" |
| result_pattern+="uint32\s+\d+\s+" |
| result_pattern+="uint16\s+\d+\s+" |
| result_pattern+="uint32\s+\d+\s+" |
| result_pattern+="uint32\s+\d+\s+" |
| result_pattern+="byte\s+\d+\s+" |
| result_pattern+="byte\s+\d+\s+" |
| result_pattern+="byte\s+\d+\s+" |
| result_pattern+="uint16\s+\d+\s+" |
| result_pattern+="uint16\s+\d+\s+" |
| result_pattern+="uint16\s+\d+\s+" |
| result_pattern+="boolean\s+(true|false)\s+" |
| result_pattern+="boolean\s+(true|false)\s+" |
| result_pattern+="boolean\s+(true|false)\s+" |
| result_pattern+="boolean\s+(true|false)\s+" |
| result_pattern+="}\s+\]\s+\]" |
| sudo dbus-send --system --dest=io.openthread.BorderRouter.wpan0 --print-reply \ |
| /io/openthread/BorderRouter/wpan0 \ |
| io.openthread.BorderRouter.GetProperties \ |
| "array:string:NeighborTable" \ |
| | grep -oPz "${result_pattern}" |
| |
| sudo dbus-send --system --dest=io.openthread.BorderRouter.wpan0 \ |
| --type=method_call --print-reply /io/openthread/BorderRouter/wpan0 \ |
| io.openthread.BorderRouter.Detach |
| ot_ctl state | grep disabled |
| |
| otbr_factoryreset |
| |
| sudo "${CMAKE_BINARY_DIR}"/tests/dbus/otbr-test-dbus-client |
| |
| otbr_factoryreset |
| |
| sudo dbus-send --system --dest=io.openthread.BorderRouter.wpan0 \ |
| --type=method_call --print-reply /io/openthread/BorderRouter/wpan0 \ |
| io.openthread.BorderRouter.Attach \ |
| array:byte: \ |
| uint16:0xffff \ |
| string:OpenThread \ |
| uint64:0xffffffffffffffff \ |
| array:byte: \ |
| uint32:0xffffffff |
| |
| local dataset="0x0e,0x08,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x03,0x00,0x00,0x18," |
| dataset+="0x35,0x06,0x00,0x04,0x00,0x1f,0xff,0xe0,0x02,0x08,0xef,0x18,0xe6,0xa1,0xf3,0xd6," |
| dataset+="0x86,0xc4,0x07,0x08,0xfd,0x16,0x72,0x24,0xc2,0x4e,0x16,0x00,0x05,0x10,0xbe,0x3b," |
| dataset+="0xd2,0x44,0xae,0x6d,0x99,0x70,0x20,0xa8,0x82,0xa2,0x4a,0x80,0x40,0xe2,0x03,0x0f," |
| dataset+="0x4f,0x70,0x65,0x6e,0x54,0x68,0x72,0x65,0x61,0x64,0x2d,0x30,0x36,0x62,0x37,0x01," |
| dataset+="0x02,0x06,0xb7,0x04,0x10,0xf9,0xc9,0x1b,0x11,0x45,0x02,0x54,0x67,0xbf,0x11,0xed," |
| dataset+="0xf9,0x01,0x1a,0x58,0x12,0x0c,0x04,0x02,0xa0,0xff,0xf8" |
| |
| sudo dbus-send --system --dest=io.openthread.BorderRouter.wpan0 \ |
| --type=method_call --print-reply /io/openthread/BorderRouter/wpan0 \ |
| io.openthread.BorderRouter.AttachAllNodesTo \ |
| "array:byte:${dataset}" \ |
| | grep "int64 300000" |
| |
| ot_ctl dataset pending | grep "Active Timestamp: 2" |
| |
| sleep 310 |
| |
| ot_ctl dataset active | grep "Active Timestamp: 2" |
| ot_ctl networkkey | grep be3bd244ae6d997020a882a24a8040e2 |
| |
| otbr_factoryreset |
| |
| sudo dbus-send --system --dest=io.openthread.BorderRouter.wpan0 \ |
| --type=method_call --print-reply /io/openthread/BorderRouter/wpan0 \ |
| io.openthread.BorderRouter.AttachAllNodesTo \ |
| "array:byte:${dataset}" \ |
| | grep "int64 0" |
| ot_ctl state | grep "leader" |
| |
| ot_ctl factoryreset |
| sleep 1 |
| |
| sudo dbus-send --system --dest=io.openthread.BorderRouter.wpan0 \ |
| --type=method_call --print-reply /io/openthread/BorderRouter/wpan0 \ |
| io.openthread.BorderRouter.Attach \ |
| array:byte: \ |
| uint16:0xffff \ |
| string:OpenThread \ |
| uint64:0xffffffffffffffff \ |
| array:byte: \ |
| uint32:0xffffffff |
| |
| ot_ctl state | grep "leader" |
| ot_ctl thread stop |
| ot_ctl state | grep "disabled" |
| ot_ctl dataset active | grep "Done" |
| |
| sudo dbus-send --system --dest=io.openthread.BorderRouter.wpan0 \ |
| --type=method_call --print-reply /io/openthread/BorderRouter/wpan0 \ |
| io.openthread.BorderRouter.AttachAllNodesTo \ |
| "array:byte:${dataset}" \ |
| | grep "int64 300000" |
| |
| ot_ctl state | grep "leader" |
| ot_ctl dataset pending | grep "Active Timestamp: 2" |
| |
| sleep 310 |
| |
| ot_ctl dataset active | grep "Active Timestamp: 2" |
| ot_ctl networkkey | grep be3bd244ae6d997020a882a24a8040e2 |
| |
| ot_ctl dataset init new |
| ot_ctl dataset commit pending |
| |
| sudo dbus-send --system --dest=io.openthread.BorderRouter.wpan0 \ |
| --type=method_call --print-reply /io/openthread/BorderRouter/wpan0 \ |
| io.openthread.BorderRouter.LeaveNetwork |
| sleep 10 |
| |
| ot_ctl state | grep disabled |
| ot_ctl dataset active | grep NotFound |
| ot_ctl dataset pending | grep NotFound |
| } |
| |
| main "$@" |