openiotsdk_example.sh 13 KB

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