openiotsdk_example.sh 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378
  1. #!/bin/bash
  2. #
  3. # Copyright (c) 2020 Project CHIP Authors
  4. #
  5. # Licensed under the Apache License, Version 2.0 (the "License");
  6. # you may not use this file except in compliance with the License.
  7. # You may obtain a copy of the License at
  8. #
  9. # http://www.apache.org/licenses/LICENSE-2.0
  10. #
  11. # Unless required by applicable law or agreed to in writing, software
  12. # distributed under the License is distributed on an "AS IS" BASIS,
  13. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. # See the License for the specific language governing permissions and
  15. # limitations under the License.
  16. #
  17. # Build and/or run Open IoT SDK examples.
  18. IS_TEST=0
  19. NAME="$(basename "$0")"
  20. HERE="$(dirname "$0")"
  21. CHIP_ROOT="$(realpath "$HERE"/../..)"
  22. COMMAND=build
  23. PLATFORM=corstone300
  24. CLEAN=0
  25. SCRATCH=0
  26. EXAMPLE_PATH=""
  27. BUILD_PATH=""
  28. TOOLCHAIN=arm-none-eabi-gcc
  29. DEBUG=false
  30. EXAMPLE=""
  31. FVP_BIN=FVP_Corstone_SSE-300_Ethos-U55
  32. GDB_PLUGIN="$FAST_MODEL_PLUGINS_PATH/GDBRemoteConnection.so"
  33. OIS_CONFIG="$CHIP_ROOT/config/openiotsdk"
  34. FVP_CONFIG_FILE="$OIS_CONFIG/fvp/cs300.conf"
  35. EXAMPLE_TEST_PATH="$CHIP_ROOT/src/test_driver/openiotsdk/integration-tests"
  36. TELNET_TERMINAL_PORT=5000
  37. FAILED_TESTS=0
  38. FVP_NETWORK="user"
  39. readarray -t TEST_NAMES <"$CHIP_ROOT"/src/test_driver/openiotsdk/unit-tests/testnames.txt
  40. function show_usage() {
  41. cat <<EOF
  42. Usage: $0 [options] example [test_name]
  43. Build, run or test the Open IoT SDK examples and unit-tests.
  44. Options:
  45. -h,--help Show this help
  46. -c,--clean Clean target build
  47. -s,--scratch Remove build directory at all before building
  48. -C,--command <command> Action to execute <build-run | run | test | build - default>
  49. -d,--debug <debug_enable> Build in debug mode <true | false - default>
  50. -p,--path <build_path> Build path <build_path - default is example_dir/build>
  51. -n,--network <network_name> FVP network interface name <network_name - default is "user" which means user network mode>
  52. Examples:
  53. shell
  54. lock-app
  55. unit-tests
  56. You can run individual test suites of unit tests by using their names [test_name] with the run command:
  57. EOF
  58. cat "$CHIP_ROOT"/src/test_driver/openiotsdk/unit-tests/testnames.txt
  59. echo ""
  60. cat <<EOF
  61. Or you can use all tests suites with <all> parameter as [test_name]
  62. The "test" command can be used for all supported examples expect the unit-tests.
  63. EOF
  64. }
  65. function build_with_cmake() {
  66. CMAKE="$(which cmake)"
  67. if [[ ! -f "$CMAKE" ]]; then
  68. echo "$NAME: cmake is not in PATH" >&2
  69. exit 1
  70. fi
  71. set -e
  72. mkdir -p "$BUILD_PATH"
  73. if [[ $CLEAN -ne 0 ]]; then
  74. echo "Clean build" >&2
  75. if compgen -G "$BUILD_PATH/CMake*" >/dev/null; then
  76. cmake --build "$BUILD_PATH" --target clean
  77. find "$BUILD_PATH" -name 'CMakeCache.txt' -delete
  78. fi
  79. fi
  80. if [[ $SCRATCH -ne 0 ]]; then
  81. echo "Remove building directory" >&2
  82. rm -rf "$BUILD_PATH"
  83. fi
  84. BUILD_OPTIONS=(-DCMAKE_SYSTEM_PROCESSOR=cortex-m55)
  85. if "$DEBUG"; then
  86. BUILD_OPTIONS+=(-DCMAKE_BUILD_TYPE=Debug)
  87. fi
  88. # Activate Matter environment
  89. source "$CHIP_ROOT"/scripts/activate.sh
  90. cmake -G Ninja -S "$EXAMPLE_PATH" -B "$BUILD_PATH" --toolchain="$TOOLCHAIN_PATH" "${BUILD_OPTIONS[@]}"
  91. cmake --build "$BUILD_PATH"
  92. }
  93. function run_fvp() {
  94. set -e
  95. # Check if FVP exists
  96. if ! [ -x "$(command -v "$FVP_BIN")" ]; then
  97. echo "Error: $FVP_BIN not installed." >&2
  98. exit 1
  99. fi
  100. if [[ $IS_TEST -eq 0 ]]; then
  101. EXAMPLE_EXE_PATH="$BUILD_PATH/chip-openiotsdk-$EXAMPLE-example.elf"
  102. else
  103. EXAMPLE_EXE_PATH="$BUILD_PATH/$EXAMPLE.elf"
  104. fi
  105. # Check if executable file exists
  106. if ! [ -f "$EXAMPLE_EXE_PATH" ]; then
  107. echo "Error: $EXAMPLE_EXE_PATH does not exist." >&2
  108. exit 1
  109. fi
  110. RUN_OPTIONS=(-C mps3_board.telnetterminal0.start_port="$TELNET_TERMINAL_PORT")
  111. RUN_OPTIONS+=(--quantum=25)
  112. if "$DEBUG"; then
  113. RUN_OPTIONS+=(--allow-debug-plugin --plugin "$GDB_PLUGIN")
  114. fi
  115. if [[ $FVP_NETWORK == "user" ]]; then
  116. RUN_OPTIONS+=(-C mps3_board.hostbridge.userNetworking=1)
  117. else
  118. RUN_OPTIONS+=(-C mps3_board.hostbridge.interfaceName="$FVP_NETWORK")
  119. fi
  120. echo "Running $EXAMPLE_EXE_PATH with options: ${RUN_OPTIONS[@]}"
  121. "$FVP_BIN" "${RUN_OPTIONS[@]}" -f "$FVP_CONFIG_FILE" --application "$EXAMPLE_EXE_PATH" >/dev/null 2>&1 &
  122. FVP_PID=$!
  123. sleep 1
  124. if [[ $IS_TEST -eq 1 ]]; then
  125. set +e
  126. expect <<EOF
  127. set timeout 1800
  128. set retcode -1
  129. spawn telnet localhost ${TELNET_TERMINAL_PORT}
  130. expect -re {Test status: (-?\d+)} {
  131. set retcode \$expect_out(1,string)
  132. }
  133. expect "Open IoT SDK unit-tests completed"
  134. set retcode [expr -1*\$retcode]
  135. exit \$retcode
  136. EOF
  137. RETCODE=$?
  138. FAILED_TESTS=$(expr "$FAILED_TESTS" + "$RETCODE")
  139. echo "$(jq '. += {($testname): {failed: $result}}' --arg testname "$EXAMPLE" --arg result "$RETCODE" "$EXAMPLE_PATH"/test_report.json)" >"$EXAMPLE_PATH"/test_report.json
  140. else
  141. telnet localhost "$TELNET_TERMINAL_PORT"
  142. fi
  143. # stop the fvp
  144. kill -9 "$FVP_PID" || true
  145. set -e
  146. sleep 1
  147. }
  148. function run_test() {
  149. EXAMPLE_EXE_PATH="$BUILD_PATH/chip-openiotsdk-$EXAMPLE-example.elf"
  150. # Check if executable file exists
  151. if ! [ -f "$EXAMPLE_EXE_PATH" ]; then
  152. echo "Error: $EXAMPLE_EXE_PATH does not exist." >&2
  153. exit 1
  154. fi
  155. # Check if FVP exists
  156. if ! [ -x "$(command -v "$FVP_BIN")" ]; then
  157. echo "Error: $FVP_BIN not installed." >&2
  158. exit 1
  159. fi
  160. # Activate Matter environment with pytest
  161. source "$CHIP_ROOT"/scripts/activate.sh
  162. # Check if pytest exists
  163. if ! [ -x "$(command -v pytest)" ]; then
  164. echo "Error: pytest not installed." >&2
  165. exit 1
  166. fi
  167. TEST_OPTIONS=()
  168. if [[ $FVP_NETWORK ]]; then
  169. TEST_OPTIONS+=(--networkInterface="$FVP_NETWORK")
  170. fi
  171. if [[ -f $EXAMPLE_TEST_PATH/$EXAMPLE/test_report.json ]]; then
  172. rm -rf "$EXAMPLE_TEST_PATH/$EXAMPLE"/test_report.json
  173. fi
  174. set +e
  175. pytest --json-report --json-report-summary --json-report-file="$EXAMPLE_TEST_PATH/$EXAMPLE"/test_report.json --binaryPath="$EXAMPLE_EXE_PATH" --fvp="$FVP_BIN" --fvpConfig="$FVP_CONFIG_FILE" "${TEST_OPTIONS[@]}" "$EXAMPLE_TEST_PATH/$EXAMPLE"/test_app.py
  176. set -e
  177. if [[ ! -f $EXAMPLE_TEST_PATH/$EXAMPLE/test_report.json ]]; then
  178. exit 1
  179. else
  180. if [[ $(jq '.summary | has("failed")' $EXAMPLE_TEST_PATH/$EXAMPLE/test_report.json) == true ]]; then
  181. FAILED_TESTS=$(jq '.summary.failed' "$EXAMPLE_TEST_PATH/$EXAMPLE"/test_report.json)
  182. fi
  183. fi
  184. }
  185. SHORT=C:,p:,d:,n:,c,s,h
  186. LONG=command:,path:,debug:,network:,clean,scratch,help
  187. OPTS=$(getopt -n build --options "$SHORT" --longoptions "$LONG" -- "$@")
  188. eval set -- "$OPTS"
  189. while :; do
  190. case "$1" in
  191. -h | --help)
  192. show_usage
  193. exit 0
  194. ;;
  195. -c | --clean)
  196. CLEAN=1
  197. shift
  198. ;;
  199. -s | --scratch)
  200. SCRATCH=1
  201. shift
  202. ;;
  203. -C | --command)
  204. COMMAND=$2
  205. shift 2
  206. ;;
  207. -d | --debug)
  208. DEBUG=$2
  209. shift 2
  210. ;;
  211. -p | --path)
  212. BUILD_PATH=$CHIP_ROOT/$2
  213. shift 2
  214. ;;
  215. -n | --network)
  216. FVP_NETWORK=$2
  217. shift 2
  218. ;;
  219. -* | --*)
  220. shift
  221. break
  222. ;;
  223. *)
  224. echo "Unexpected option: $1"
  225. show_usage
  226. exit 2
  227. ;;
  228. esac
  229. done
  230. if [[ $# -lt 1 ]]; then
  231. show_usage >&2
  232. exit 1
  233. fi
  234. case "$1" in
  235. shell | unit-tests | lock-app)
  236. EXAMPLE=$1
  237. ;;
  238. *)
  239. echo "Wrong example name"
  240. show_usage
  241. exit 2
  242. ;;
  243. esac
  244. if [[ "$EXAMPLE" == "unit-tests" ]]; then
  245. if [ ! -z "$2" ]; then
  246. if [[ " ${TEST_NAMES[*]} " =~ " $2 " ]]; then
  247. if [[ "$COMMAND" != *"run"* ]]; then
  248. echo "Test suites can only accept --command run"
  249. show_usage
  250. exit 2
  251. fi
  252. EXAMPLE=$2
  253. echo "Run specific unit test $EXAMPLE"
  254. elif [[ "$2" == "all" ]]; then
  255. echo "Use all unit tests"
  256. else
  257. echo " Wrong unit test name"
  258. show_usage
  259. exit 2
  260. fi
  261. else
  262. echo "Use all unit tests"
  263. fi
  264. IS_TEST=1
  265. fi
  266. case "$COMMAND" in
  267. build | run | test | build-run) ;;
  268. *)
  269. echo "Wrong command definition"
  270. show_usage
  271. exit 2
  272. ;;
  273. esac
  274. TOOLCHAIN_PATH="toolchains/toolchain-$TOOLCHAIN.cmake"
  275. if [[ $IS_TEST -eq 0 ]]; then
  276. EXAMPLE_PATH="$CHIP_ROOT/examples/$EXAMPLE/openiotsdk"
  277. else
  278. EXAMPLE_PATH="$CHIP_ROOT/src/test_driver/openiotsdk/unit-tests"
  279. if [[ -f $EXAMPLE_PATH/test_report.json ]]; then
  280. rm -rf "$EXAMPLE_PATH"/test_report.json
  281. fi
  282. echo "{}" >"$EXAMPLE_PATH"/test_report.json
  283. fi
  284. if [ -z "$BUILD_PATH" ]; then
  285. BUILD_PATH="$EXAMPLE_PATH/build"
  286. fi
  287. if [[ "$COMMAND" == *"build"* ]]; then
  288. build_with_cmake
  289. fi
  290. if [[ "$COMMAND" == *"run"* ]]; then
  291. # If user wants to run unit-tests we need to loop through all test names
  292. if [[ "$EXAMPLE" == "unit-tests" ]]; then
  293. if "$DEBUG"; then
  294. echo "You have to specify the test suites to run in debug mode"
  295. show_usage
  296. exit 2
  297. else
  298. for NAME in "${TEST_NAMES[@]}"; do
  299. EXAMPLE=$NAME
  300. echo "$EXAMPLE_PATH"
  301. echo "Run specific unit test $EXAMPLE"
  302. run_fvp
  303. done
  304. echo "Failed tests total: $FAILED_TESTS"
  305. fi
  306. else
  307. run_fvp
  308. fi
  309. fi
  310. if [[ "$COMMAND" == *"test"* ]]; then
  311. if [[ "$EXAMPLE" == "unit-tests" ]]; then
  312. echo "The test command can not be applied to the unit-tests example"
  313. show_usage
  314. exit 2
  315. else
  316. IS_TEST=1
  317. run_test
  318. fi
  319. fi
  320. if [[ $IS_TEST -eq 1 ]]; then
  321. exit "$FAILED_TESTS"
  322. fi