openiotsdk_example.sh 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428
  1. #!/bin/bash
  2. #
  3. # Copyright (c) 2022-2023 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. NAME="$(basename "$0")"
  19. HERE="$(dirname "$0")"
  20. CHIP_ROOT="$(realpath "$HERE"/../..)"
  21. COMMAND=build
  22. PLATFORM=corstone300
  23. CLEAN=0
  24. SCRATCH=0
  25. EXAMPLE_PATH=""
  26. BUILD_PATH=""
  27. TOOLCHAIN=arm-none-eabi-gcc
  28. DEBUG=false
  29. LWIP_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. TELNET_CONNECTION_PORT=""
  38. FAILED_TESTS=0
  39. IS_UNIT_TEST=0
  40. FVP_NETWORK="user"
  41. KVS_STORAGE_TYPE="tdb"
  42. KVS_STORAGE_FILE=""
  43. declare -A tdb_storage_param=([instance]=sram [memspace]=0 [address]=0x0 [size]=0x100000)
  44. declare -A ps_storage_param=([instance]=qspi_sram [memspace]=0 [address]=0x660000 [size]=0x12000)
  45. readarray -t SUPPORTED_APP_NAMES <"$CHIP_ROOT"/examples/platform/openiotsdk/supported_examples.txt
  46. SUPPORTED_APP_NAMES+=("unit-tests")
  47. readarray -t TEST_NAMES <"$CHIP_ROOT"/src/test_driver/openiotsdk/unit-tests/test_components.txt
  48. function show_usage() {
  49. cat <<EOF
  50. Usage: $0 [options] example [test_name]
  51. Build, run or test the Open IoT SDK examples and unit-tests.
  52. Options:
  53. -h,--help Show this help
  54. -c,--clean Clean target build
  55. -s,--scratch Remove build directory at all before building
  56. -C,--command <command> Action to execute <build-run | run | test | build - default>
  57. -d,--debug <debug_enable> Build in debug mode <true | false - default>
  58. -l,--lwipdebug <lwip_debug_enable> Build with LwIP debug logs support <true | false - default>
  59. -k,--kvsstore <kvs_storage_type> Select KVS storage type <ps | tdb - default>
  60. -p,--path <build_path> Build path <build_path - default is example_dir/build>
  61. -K,--kvsfile <kvs_storage_file> Path to KVS storage file which will be used to ensure persistence <kvs_storage_file - default is empty which means disable persistence>
  62. -n,--network <network_name> FVP network interface name <network_name - default is "user" which means user network mode>
  63. Examples:
  64. EOF
  65. for app in "${SUPPORTED_APP_NAMES[@]}"; do
  66. echo " $app"
  67. done
  68. cat <<EOF
  69. You run or test individual test suites of unit tests by using their names [test_name] with the specified command:
  70. EOF
  71. for test in "${TEST_NAMES[@]}"; do
  72. echo " $test"
  73. done
  74. cat <<EOF
  75. Use "test" command without a specific test name, runs all supported unit tests.
  76. EOF
  77. }
  78. function build_with_cmake() {
  79. CMAKE="$(which cmake)"
  80. if [[ ! -f "$CMAKE" ]]; then
  81. echo "$NAME: cmake is not in PATH" >&2
  82. exit 1
  83. fi
  84. set -e
  85. mkdir -p "$BUILD_PATH"
  86. if [[ $CLEAN -ne 0 ]]; then
  87. echo "Clean build" >&2
  88. if compgen -G "$BUILD_PATH/CMake*" >/dev/null; then
  89. cmake --build "$BUILD_PATH" --target clean
  90. find "$BUILD_PATH" -name 'CMakeCache.txt' -delete
  91. fi
  92. fi
  93. if [[ $SCRATCH -ne 0 ]]; then
  94. echo "Remove building directory" >&2
  95. rm -rf "$BUILD_PATH"
  96. fi
  97. BUILD_OPTIONS=(-DCMAKE_SYSTEM_PROCESSOR=cortex-m55)
  98. if "$DEBUG"; then
  99. BUILD_OPTIONS+=(-DCMAKE_BUILD_TYPE=Debug)
  100. else
  101. BUILD_OPTIONS+=(-DCMAKE_BUILD_TYPE=Release)
  102. fi
  103. if "$LWIP_DEBUG"; then
  104. BUILD_OPTIONS+=(-DCONFIG_CHIP_OPEN_IOT_SDK_LWIP_DEBUG=YES)
  105. fi
  106. if [[ $KVS_STORAGE_TYPE == "ps" ]]; then
  107. BUILD_OPTIONS+=(-DCONFIG_CHIP_OPEN_IOT_SDK_USE_PSA_PS=YES)
  108. fi
  109. cmake -G Ninja -S "$EXAMPLE_PATH" -B "$BUILD_PATH" --toolchain="$TOOLCHAIN_PATH" "${BUILD_OPTIONS[@]}"
  110. cmake --build "$BUILD_PATH"
  111. }
  112. function run_fvp() {
  113. set -e
  114. # Check if FVP exists
  115. if ! [ -x "$(command -v "$FVP_BIN")" ]; then
  116. echo "Error: $FVP_BIN not installed." >&2
  117. exit 1
  118. fi
  119. # Check if executable file exists
  120. if ! [ -f "$EXAMPLE_EXE_PATH" ]; then
  121. echo "Error: $EXAMPLE_EXE_PATH does not exist." >&2
  122. exit 1
  123. fi
  124. # Check if FVP GDB plugin file exists
  125. if "$DEBUG" && ! [ -f "$GDB_PLUGIN" ]; then
  126. echo "Error: $GDB_PLUGIN does not exist." >&2
  127. exit 1
  128. fi
  129. RUN_OPTIONS=(-C mps3_board.telnetterminal0.start_port="$TELNET_TERMINAL_PORT")
  130. RUN_OPTIONS+=(--quantum=25)
  131. if "$DEBUG"; then
  132. RUN_OPTIONS+=(--allow-debug-plugin --plugin "$GDB_PLUGIN")
  133. fi
  134. if [[ $FVP_NETWORK == "user" ]]; then
  135. RUN_OPTIONS+=(-C mps3_board.hostbridge.userNetworking=1)
  136. else
  137. RUN_OPTIONS+=(-C mps3_board.hostbridge.interfaceName="$FVP_NETWORK")
  138. fi
  139. if [ -n "$KVS_STORAGE_FILE" ]; then
  140. if [[ $KVS_STORAGE_TYPE == "ps" ]]; then
  141. declare -n storage_param=ps_storage_param
  142. else
  143. declare -n storage_param=tdb_storage_param
  144. fi
  145. if [ -f "$KVS_STORAGE_FILE" ]; then
  146. RUN_OPTIONS+=(--data "mps3_board.${storage_param[instance]}=$KVS_STORAGE_FILE@${storage_param[memspace]}:${storage_param[address]}")
  147. fi
  148. RUN_OPTIONS+=(--dump "mps3_board.${storage_param[instance]}=$KVS_STORAGE_FILE@${storage_param[memspace]}:${storage_param[address]},${storage_param[size]}")
  149. fi
  150. echo "Running $EXAMPLE_EXE_PATH with options: ${RUN_OPTIONS[@]}"
  151. # Run the FVP
  152. "$FVP_BIN" "${RUN_OPTIONS[@]}" -f "$FVP_CONFIG_FILE" --application "$EXAMPLE_EXE_PATH" 2>&1 >/tmp/FVP_run_$$ &
  153. FVP_PID=$!
  154. # Wait for FVP to start and exist the output file
  155. timeout=0
  156. while [ ! -e /tmp/FVP_run_$$ ]; do
  157. timeout=$((timeout + 1))
  158. if [ "$timeout" -ge 5 ]; then
  159. echo "Error: FVP start failed" >&2
  160. break
  161. fi
  162. sleep 1
  163. done
  164. while IFS= read -t 5 -r line; do
  165. if [[ $line == *"Listening for serial connection on port"* ]]; then
  166. TELNET_CONNECTION_PORT="${line##* }"
  167. break
  168. fi
  169. done </tmp/FVP_run_$$
  170. if [ -n "$TELNET_CONNECTION_PORT" ]; then
  171. # Connect FVP via telnet client
  172. telnet localhost "$TELNET_CONNECTION_PORT"
  173. else
  174. echo "Error: FVP start failed" >&2
  175. fi
  176. # Stop the FVP
  177. kill -SIGTERM "$FVP_PID"
  178. # Wait for the FVP stop
  179. while kill -0 "$FVP_PID"; do
  180. sleep 1
  181. done
  182. rm -rf /tmp/FVP_run_$$
  183. }
  184. function run_test() {
  185. # Check if executable file exists
  186. if ! [ -f "$EXAMPLE_EXE_PATH" ]; then
  187. echo "Error: $EXAMPLE_EXE_PATH does not exist." >&2
  188. exit 1
  189. fi
  190. # Check if FVP exists
  191. if ! [ -x "$(command -v "$FVP_BIN")" ]; then
  192. echo "Error: $FVP_BIN not installed." >&2
  193. exit 1
  194. fi
  195. # Check if pytest exists
  196. if ! [ -x "$(command -v pytest)" ]; then
  197. echo "Error: pytest not installed." >&2
  198. exit 1
  199. fi
  200. TEST_OPTIONS=()
  201. if [[ $FVP_NETWORK ]]; then
  202. TEST_OPTIONS+=(--networkInterface="$FVP_NETWORK")
  203. fi
  204. if [[ -f $EXAMPLE_TEST_PATH/test_report_$EXAMPLE.json ]]; then
  205. rm -rf "$EXAMPLE_TEST_PATH/test_report_$EXAMPLE".json
  206. fi
  207. set +e
  208. pytest --json-report --json-report-summary --json-report-file="$EXAMPLE_TEST_PATH"/test_report_"$EXAMPLE".json --binaryPath="$EXAMPLE_EXE_PATH" --fvp="$FVP_BIN" --fvpConfig="$FVP_CONFIG_FILE" "${TEST_OPTIONS[@]}" "$EXAMPLE_TEST_PATH"/test_app.py
  209. set -e
  210. if [[ ! -f $EXAMPLE_TEST_PATH/test_report_$EXAMPLE.json ]]; then
  211. exit 1
  212. else
  213. if [[ $(jq '.summary | has("failed")' $EXAMPLE_TEST_PATH/test_report_$EXAMPLE.json) == true ]]; then
  214. FAILED_TESTS=$((FAILED_TESTS + $(jq '.summary.failed' "$EXAMPLE_TEST_PATH"/test_report_"$EXAMPLE".json)))
  215. fi
  216. fi
  217. }
  218. SHORT=C:,p:,d:,l:,n:,k:,K:,c,s,h
  219. LONG=command:,path:,debug:,lwipdebug:,network:,kvsstore:,kvsfile:,clean,scratch,help
  220. OPTS=$(getopt -n build --options "$SHORT" --longoptions "$LONG" -- "$@")
  221. eval set -- "$OPTS"
  222. while :; do
  223. case "$1" in
  224. -h | --help)
  225. show_usage
  226. exit 0
  227. ;;
  228. -c | --clean)
  229. CLEAN=1
  230. shift
  231. ;;
  232. -s | --scratch)
  233. SCRATCH=1
  234. shift
  235. ;;
  236. -C | --command)
  237. COMMAND=$2
  238. shift 2
  239. ;;
  240. -d | --debug)
  241. DEBUG=$2
  242. shift 2
  243. ;;
  244. -l | --lwipdebug)
  245. LWIP_DEBUG=$2
  246. shift 2
  247. ;;
  248. -k | --kvsstore)
  249. KVS_STORAGE_TYPE=$2
  250. shift 2
  251. ;;
  252. -K | --kvsfile)
  253. KVS_STORAGE_FILE=$2
  254. shift 2
  255. ;;
  256. -p | --path)
  257. BUILD_PATH=$CHIP_ROOT/$2
  258. shift 2
  259. ;;
  260. -n | --network)
  261. FVP_NETWORK=$2
  262. shift 2
  263. ;;
  264. -* | --*)
  265. shift
  266. break
  267. ;;
  268. *)
  269. echo "Unexpected option: $1"
  270. show_usage
  271. exit 2
  272. ;;
  273. esac
  274. done
  275. if [[ $# -lt 1 ]]; then
  276. show_usage >&2
  277. exit 1
  278. fi
  279. EXAMPLE=$1
  280. if [[ ! " ${SUPPORTED_APP_NAMES[@]} " =~ " ${EXAMPLE} " ]]; then
  281. echo "Wrong example name"
  282. show_usage
  283. exit 2
  284. fi
  285. case "$COMMAND" in
  286. build | run | test | build-run) ;;
  287. *)
  288. echo "Wrong command definition"
  289. show_usage
  290. exit 2
  291. ;;
  292. esac
  293. if [[ "$EXAMPLE" == "unit-tests" ]]; then
  294. if [ ! -z "$2" ]; then
  295. if [[ " ${TEST_NAMES[*]} " =~ " $2 " ]]; then
  296. EXAMPLE=$2
  297. echo "Use specific unit test $EXAMPLE"
  298. elif [[ "$2" == "all" ]]; then
  299. echo "Use all unit tests"
  300. else
  301. echo " Wrong unit test name"
  302. show_usage
  303. exit 2
  304. fi
  305. else
  306. echo "Use all unit tests"
  307. fi
  308. EXAMPLE_PATH="$CHIP_ROOT/src/test_driver/openiotsdk/unit-tests"
  309. IS_UNIT_TEST=1
  310. else
  311. EXAMPLE_PATH="$CHIP_ROOT/examples/$EXAMPLE/openiotsdk"
  312. fi
  313. case "$KVS_STORAGE_TYPE" in
  314. ps | tdb) ;;
  315. *)
  316. echo "Wrong KVS storage type definition"
  317. show_usage
  318. exit 2
  319. ;;
  320. esac
  321. TOOLCHAIN_PATH="toolchains/toolchain-$TOOLCHAIN.cmake"
  322. if [ -z "$BUILD_PATH" ]; then
  323. BUILD_PATH="$EXAMPLE_PATH/build"
  324. fi
  325. # Activate Matter environment
  326. source "$CHIP_ROOT"/scripts/activate.sh
  327. if [[ $IS_UNIT_TEST -eq 0 ]]; then
  328. EXAMPLE_EXE_PATH="$BUILD_PATH/chip-openiotsdk-$EXAMPLE-example.elf"
  329. EXAMPLE_TEST_PATH+="/$EXAMPLE"
  330. else
  331. EXAMPLE_EXE_PATH="$BUILD_PATH/$EXAMPLE.elf"
  332. EXAMPLE_TEST_PATH+="/unit-tests"
  333. fi
  334. if [[ "$COMMAND" == *"build"* ]]; then
  335. build_with_cmake
  336. fi
  337. if [[ "$COMMAND" == *"run"* ]]; then
  338. if [[ "$EXAMPLE" == "unit-tests" ]]; then
  339. echo "You have to specify the test suites to run"
  340. show_usage
  341. exit 2
  342. else
  343. run_fvp
  344. fi
  345. fi
  346. if [[ "$COMMAND" == *"test"* ]]; then
  347. if [[ "$EXAMPLE" == "unit-tests" ]]; then
  348. for NAME in "${TEST_NAMES[@]}"; do
  349. EXAMPLE=$NAME
  350. EXAMPLE_EXE_PATH="$BUILD_PATH/$EXAMPLE.elf"
  351. echo "Test specific unit test $EXAMPLE"
  352. run_test
  353. done
  354. else
  355. run_test
  356. fi
  357. echo "Failed tests total: $FAILED_TESTS"
  358. exit "$FAILED_TESTS"
  359. fi