cirque_tests.sh 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. #!/usr/bin/env 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. # Don't warn about unreachable commands in this file:
  18. # shellcheck disable=SC2317
  19. SOURCE=${BASH_SOURCE[0]}
  20. SOURCE_DIR=$(cd "$(dirname "$SOURCE")" >/dev/null 2>&1 && pwd)
  21. REPO_DIR=$SOURCE_DIR/../../
  22. TEST_DIR=$REPO_DIR/src/test_driver/linux-cirque
  23. LOG_DIR=${LOG_DIR:-$(mktemp -d)}
  24. GITHUB_ACTION_RUN=${GITHUB_ACTION_RUN:-"0"}
  25. # The image build will clone its own ot-br-posix checkout due to limitations of git submodule.
  26. # Using the same ot-br-posix version as chip
  27. OPENTHREAD=$REPO_DIR/third_party/openthread/repo
  28. OPENTHREAD_CHECKOUT=$(cd "$REPO_DIR" && git rev-parse :third_party/openthread/repo)
  29. OT_BR_POSIX_CHECKOUT=$(cd "$REPO_DIR" && git rev-parse :third_party/ot-br-posix/repo)
  30. CIRQUE_CACHE_PATH=${GITHUB_CACHE_PATH:-"/tmp/cirque-cache/"}
  31. OT_SIMULATION_CACHE="$CIRQUE_CACHE_PATH/ot-simulation-cmake.tgz"
  32. OT_SIMULATION_CACHE_STAMP_FILE="$CIRQUE_CACHE_PATH/ot-simulation.commit"
  33. # Append test name here to add more tests for run_all_tests
  34. CIRQUE_TESTS=(
  35. "EchoTest"
  36. "EchoOverTcpTest"
  37. "FailsafeTest"
  38. "MobileDeviceTest"
  39. "CommissioningTest"
  40. "InteractionModelTest"
  41. "SplitCommissioningTest"
  42. "CommissioningFailureTest"
  43. "CommissioningFailureOnReportTest"
  44. "PythonCommissioningTest"
  45. "CommissioningWindowTest"
  46. )
  47. BOLD_GREEN_TEXT="\033[1;32m"
  48. BOLD_YELLOW_TEXT="\033[1;33m"
  49. BOLD_RED_TEXT="\033[1;31m"
  50. RESET_COLOR="\033[0m"
  51. function __cirquetest_start_flask() {
  52. echo 'Start Flask'
  53. cd "$REPO_DIR"/third_party/cirque/repo
  54. # When running the ManualTests, if Ctrl-C is send to the shell, it will stop flask as well.
  55. # This is not expected. Start a new session to prevent it from receiving signals
  56. setsid bash -c 'FLASK_APP=cirque/restservice/service.py \
  57. PATH="'"$PATH"'":"'"$REPO_DIR"'"/third_party/openthread/repo/build/simulation/examples/apps/ncp/ \
  58. python3 -m flask run >"'"$LOG_DIR"'"/"'"$CURRENT_TEST"'"/flask.log 2>&1' &
  59. FLASK_PID=$!
  60. echo "Flask running in backgroud with pid $FLASK_PID"
  61. }
  62. function __cirquetest_clean_flask() {
  63. echo "Cleanup Flask pid $FLASK_PID"
  64. kill -SIGTERM -"$FLASK_PID"
  65. mv "$LOG_DIR/$CURRENT_TEST"/flask.log "$LOG_DIR/$CURRENT_TEST"/flask.log.old
  66. cat "$LOG_DIR/$CURRENT_TEST"/flask.log.old | sed 's/\\n/\n/g' | sed 's/\\t/ /g' >"$LOG_DIR/$CURRENT_TEST"/flask.log
  67. rm "$LOG_DIR/$CURRENT_TEST"/flask.log.old
  68. }
  69. function __cirquetest_build_ot() {
  70. echo -e "[$BOLD_YELLOW_TEXT""INFO""$RESET_COLOR] Cache miss, build openthread simulation."
  71. script/cmake-build simulation -DOT_THREAD_VERSION=1.2 -DOT_MTD=OFF -DOT_FTD=OFF -DWEB_GUI=0 -DNETWORK_MANAGER=0 -DREST_API=0 -DNAT64=0
  72. mkdir -p "$(dirname "$OT_SIMULATION_CACHE")"
  73. tar czf "$OT_SIMULATION_CACHE" build
  74. echo "$OPENTHREAD_CHECKOUT" >"$OT_SIMULATION_CACHE_STAMP_FILE"
  75. }
  76. function __cirquetest_build_ot_lazy() {
  77. pushd .
  78. cd "$REPO_DIR"/third_party/openthread/repo
  79. ([[ -f "$OT_SIMULATION_CACHE_STAMP_FILE" ]] &&
  80. [[ "$(cat "$OT_SIMULATION_CACHE_STAMP_FILE")" = "$OPENTHREAD_CHECKOUT" ]] &&
  81. [[ -f "$OT_SIMULATION_CACHE" ]] &&
  82. tar zxf "$OT_SIMULATION_CACHE") ||
  83. __cirquetest_build_ot
  84. popd
  85. }
  86. function __cirquetest_self_hash() {
  87. shasum "$SOURCE" | awk '{ print $1 }'
  88. }
  89. function cirquetest_cachekey() {
  90. echo "$("$REPO_DIR"/integrations/docker/images/stage-2/chip-cirque-device-base/cachekey.sh).openthread.$OPENTHREAD_CHECKOUT.cirque_test.$(__cirquetest_self_hash)"
  91. }
  92. function cirquetest_cachekeyhash() {
  93. cirquetest_cachekey | shasum | awk '{ print $1 }'
  94. }
  95. function cirquetest_bootstrap() {
  96. set -ex
  97. cd "$REPO_DIR"/third_party/cirque/repo
  98. pip3 uninstall -y setuptools
  99. pip3 install setuptools==65.7.0
  100. pip3 install pycodestyle==2.5.0 wheel
  101. make NO_GRPC=1 install -j
  102. git config --global --add safe.directory /home/runner/work/connectedhomeip/connectedhomeip
  103. "$REPO_DIR"/integrations/docker/images/stage-2/chip-cirque-device-base/build.sh --build-arg OT_BR_POSIX_CHECKOUT="$OT_BR_POSIX_CHECKOUT"
  104. __cirquetest_build_ot_lazy
  105. pip3 install -r requirements_nogrpc.txt
  106. }
  107. function cirquetest_run_test() {
  108. # Start Cirque flash server
  109. export CURRENT_TEST="$1"
  110. export DEVICE_LOG_DIR="$LOG_DIR/$CURRENT_TEST"/device_logs
  111. shift
  112. mkdir -p "$DEVICE_LOG_DIR"
  113. __cirquetest_start_flask
  114. sleep 5
  115. CHIP_CIRQUE_BASE_IMAGE="ghcr.io/project-chip/chip-cirque-device-base" "$TEST_DIR/$CURRENT_TEST.py" "$@"
  116. exitcode=$?
  117. __cirquetest_clean_flask
  118. # TODO: Do docker system prune, we cannot filter which container
  119. # is created by cirque now. This will be implemented later. Currently, only do this on CI
  120. # After test finished, the container is perserved and networks will not be deleted
  121. # This is useful when running tests on local workstation, but not for CI.
  122. if [[ "$CLEANUP_DOCKER_FOR_CI" = "1" ]]; then
  123. echo "Do docker container and network prune"
  124. # TODO: Filter cirque containers ?
  125. if ! grep docker.sock /proc/1/mountinfo; then
  126. docker ps -aq | xargs docker stop >/dev/null 2>&1
  127. fi
  128. docker container prune -f >/dev/null 2>&1
  129. docker network prune -f >/dev/null 2>&1
  130. fi
  131. echo "Test log can be found at $DEVICE_LOG_DIR"
  132. return "$exitcode"
  133. }
  134. function cirquetest_run_all_tests() {
  135. # shellharden requires quotes around variables, which will break for-each loops
  136. # This is the workaround
  137. echo "Logs will be stored at $LOG_DIR"
  138. test_pass=1
  139. mkdir -p "$LOG_DIR"
  140. for test_name in "${CIRQUE_TESTS[@]}"; do
  141. echo "[ RUN] $test_name"
  142. if cirquetest_run_test "$test_name" >"$LOG_DIR/$test_name.log" 2>&1; then
  143. echo -e "[$BOLD_GREEN_TEXT""PASS""$RESET_COLOR] $test_name"
  144. else
  145. echo -e "[$BOLD_RED_TEXT""FAIL""$RESET_COLOR] $test_name (Exitcode: $exitcode)"
  146. test_pass=0
  147. fi
  148. done
  149. if [[ "$GITHUB_ACTION_RUN" = "1" ]]; then
  150. echo -e "[$BOLD_YELLOW_TEXT""INFO""$RESET_COLOR] Logs will be uploaded to artifacts."
  151. fi
  152. if ((test_pass)); then
  153. echo -e "[$BOLD_GREEN_TEXT""PASS""$RESET_COLOR] Test finished, test log can be found at $LOG_DIR"
  154. return 0
  155. else
  156. echo -e "[$BOLD_RED_TEXT""FAIL""$RESET_COLOR] Test failed, test log can be found at $LOG_DIR"
  157. return 1
  158. fi
  159. }
  160. subcommand=$1
  161. shift
  162. case $subcommand in
  163. *)
  164. cirquetest_"$subcommand" "$@"
  165. exitcode=$?
  166. if ((exitcode == 127)); then
  167. echo "Unknown command: $subcommand" >&2
  168. fi
  169. exit "$exitcode"
  170. ;;
  171. esac