13 # Common parameters for the 'make' during CI tests
14 MAKEFLAGS: "-j5 --no-keep-going"
16 # GitLab-CI environment
18 # more attempts for more robust
19 GET_SOURCES_ATTEMPTS: "10"
20 ARTIFACT_DOWNLOAD_ATTEMPTS: "10"
22 # We use get_sources.sh script to fetch the submodules and/or re-fetch the repo
23 # if it was corrupted (if submodule update fails this can happen)
25 GIT_SUBMODULE_STRATEGY: none
29 IDF_PATH: "$CI_PROJECT_DIR"
32 APPLY_BOT_FILTER_SCRIPT: "$CI_PROJECT_DIR/tools/ci/apply_bot_filter.py"
33 CHECKOUT_REF_SCRIPT: "$CI_PROJECT_DIR/tools/ci/checkout_project_ref.py"
35 # When 'fetch' strategy is used, Gitlab removes untracked files before checking out
36 # new revision. However if the new revision doesn't include some of the submodules
37 # which were present in the old revision, such submodule directories would not be
38 # removed by the checkout. This extra step ensures that these stale submodules
40 .git_clean_stale_submodules: &git_clean_stale_submodules >
41 find . -name '.git' -not -path './.git' -printf '%P\n'
44 grep -q {} .gitmodules
45 || (echo "Removing {}, has .git directory but not in .gitmodules file"
48 # before each job, we need to check if this job is filtered by bot stage/job filter
49 .apply_bot_filter: &apply_bot_filter
50 python $APPLY_BOT_FILTER_SCRIPT || exit 0
53 - *git_clean_stale_submodules
54 # apply bot filter in before script
59 - echo -n $GITLAB_KEY > ~/.ssh/id_rsa_base64
60 - base64 --decode --ignore-garbage ~/.ssh/id_rsa_base64 > ~/.ssh/id_rsa
61 - chmod 600 ~/.ssh/id_rsa
62 - echo -e "Host gitlab.espressif.cn\n\tStrictHostKeyChecking no\n" >> ~/.ssh/config
64 # Set IS_PRIVATE or IS_PUBLIC depending on if our branch is public or not
66 # (the same regular expressions are used to set these are used in 'only:' sections below
67 - source tools/ci/configure_ci_environment.sh
69 # fetch the submodules (& if necessary re-fetch repo) from gitlab
70 - time ./tools/ci/get-full-sources.sh
72 # used for check scripts which we want to run unconditionally
73 .do_nothing_before_no_filter:
74 before_script: &do_nothing_before_no_filter
75 - *git_clean_stale_submodules
77 # used for everything else where we want to do no prep, except for bot filter
79 before_script: &do_nothing_before
80 - *git_clean_stale_submodules
81 # apply bot filter in before script
83 - echo "Not setting up GitLab key, not fetching submodules"
84 - source tools/ci/configure_ci_environment.sh
86 .add_gitlab_key_before:
87 before_script: &add_gitlab_key_before
88 - *git_clean_stale_submodules
89 # apply bot filter in before script
91 - echo "Not fetching submodules"
92 - source tools/ci/configure_ci_environment.sh
96 - echo -n $GITLAB_KEY > ~/.ssh/id_rsa_base64
97 - base64 --decode --ignore-garbage ~/.ssh/id_rsa_base64 > ~/.ssh/id_rsa
98 - chmod 600 ~/.ssh/id_rsa
99 - echo -e "Host gitlab.espressif.cn\n\tStrictHostKeyChecking no\n" >> ~/.ssh/config
103 image: $CI_DOCKER_REGISTRY/esp32-ci-env$BOT_DOCKER_IMAGE_TAG
110 - git clone https://github.com/espressif/esp-idf-template.git
111 - cd esp-idf-template
112 # Try to use the same branch name for esp-idf-template that we're
113 # using on esp-idf. If it doesn't exist then just stick to the default
115 - python $CHECKOUT_REF_SCRIPT esp-idf-template
116 # Test debug build (default)
118 # Now test release build
120 - sed -i.bak -e's/CONFIG_OPTIMIZATION_LEVEL_DEBUG\=y/CONFIG_OPTIMIZATION_LEVEL_RELEASE=y/' sdkconfig
122 # Check if there are any stray printf/ets_printf references in WiFi libs
123 - cd ../components/esp32/lib
124 - test $(xtensa-esp32-elf-nm *.a | grep -w printf | wc -l) -eq 0
125 - test $(xtensa-esp32-elf-nm *.a | grep -w ets_printf | wc -l) -eq 0
128 .build_template: &build_template
130 image: $CI_DOCKER_REGISTRY/esp32-ci-env$BOT_DOCKER_IMAGE_TAG
137 .build_ssc_template: &build_ssc_template
144 SSC_CONFIG_FOLDER: "$CI_PROJECT_DIR/SSC/configs/ESP32_IDF"
146 - git clone $SSC_REPOSITORY
148 - python $CHECKOUT_REF_SCRIPT SSC
149 - MAKEFLAGS= ./ci_build_ssc.sh "${CI_JOB_NAME}" "${IDF_PATH}/.gitlab-ci.yml"
151 # don't forget to add to dependency to test_template when adding new build_ssc jobs
153 <<: *build_ssc_template
156 <<: *build_ssc_template
159 <<: *build_ssc_template
161 # If you want to add new build ssc jobs, please add it into dependencies of `assign_test` and `.test_template`
167 - tools/unit-test-app/output
168 - components/idf_test/unit_test/TestCaseAll.yml
169 - components/idf_test/unit_test/CIConfigs/*.yml
172 - cd tools/unit-test-app
173 - MAKEFLAGS= make help # make sure kconfig tools are built in single process
174 - make ut-clean-all-configs
175 - export EXTRA_CFLAGS="-Werror -Werror=deprecated-declarations"
176 - export EXTRA_CXXFLAGS=${EXTRA_CFLAGS}
177 - make ut-build-all-configs
178 - python tools/UnitTestParser.py
180 .build_examples_template: &build_examples_template
186 - build_examples/*/*/*/build/*.bin
187 - build_examples/*/*/*/build/*.elf
188 - build_examples/*/*/*/build/*.map
189 - build_examples/*/*/*/build/download.config
190 - build_examples/*/*/*/build/bootloader/*.bin
195 LOG_PATH: "$CI_PROJECT_DIR/log_examples"
197 # it's not possible to build 100% out-of-tree and have the "artifacts"
198 # mechanism work, but this is the next best thing
199 - rm -rf build_examples
200 - mkdir build_examples
202 # build some of examples
203 - mkdir -p ${LOG_PATH}
204 - ${IDF_PATH}/tools/ci/build_examples.sh "${CI_JOB_NAME}"
205 # and again, with cmake!
206 - rm -rf ../build_examples_cmake
207 - mkdir ../build_examples_cmake
208 - cd ../build_examples_cmake
209 - mkdir -p ${LOG_PATH}_cmake
210 - LOG_PATH=${LOG_PATH}_cmake ${IDF_PATH}/tools/ci/build_examples_cmake.sh "${CI_JOB_NAME}"
213 <<: *build_examples_template
216 <<: *build_examples_template
219 <<: *build_examples_template
222 <<: *build_examples_template
225 <<: *build_examples_template
228 <<: *build_examples_template
231 <<: *build_examples_template
234 <<: *build_examples_template
236 # If you want to add new build example jobs, please add it into dependencies of `.example_test_template`
240 image: $CI_DOCKER_REGISTRY/esp32-ci-env$BOT_DOCKER_IMAGE_TAG
246 # English version of documentation
247 - docs/en/doxygen-warning-log.txt
248 - docs/en/sphinx-warning-log.txt
249 - docs/en/sphinx-warning-log-sanitized.txt
250 - docs/en/_build/html
251 # Chinese version of documentation
252 - docs/zh_CN/doxygen-warning-log.txt
253 - docs/zh_CN/sphinx-warning-log.txt
254 - docs/zh_CN/sphinx-warning-log-sanitized.txt
255 - docs/zh_CN/_build/html
259 - ./check_lang_folder_sync.sh
263 - ../check_doc_warnings.sh
267 - ../check_doc_warnings.sh
271 image: $CI_DOCKER_REGISTRY/esp32-ci-env$BOT_DOCKER_IMAGE_TAG
273 tools/cmake/run_cmake_lint.sh
275 .host_test_template: &host_test_template
277 image: $CI_DOCKER_REGISTRY/esp32-ci-env$BOT_DOCKER_IMAGE_TAG
283 <<: *host_test_template
285 - cd components/nvs_flash/test_nvs_host
289 <<: *host_test_template
292 - components/nvs_flash/test_nvs_host/coverage_report
295 # This job takes a few hours to finish, so only run it on demand
297 BOT_NEEDS_TRIGGER_BY_NAME: 1
299 - cd components/nvs_flash/test_nvs_host
300 - make coverage_report
302 test_partition_table_on_host:
303 <<: *host_test_template
307 - cd components/partition_table/test_gen_esp32part_host
308 - ./gen_esp32part_tests.py
311 <<: *host_test_template
314 - components/wear_levelling/test_wl_host/coverage_report.zip
316 - cd components/wear_levelling/test_wl_host
320 <<: *host_test_template
322 - cd components/fatfs/test_fatfs_host/
325 .host_fuzzer_test_template: &host_fuzzer_test_template
327 image: $CI_DOCKER_REGISTRY/afl-fuzzer-test
334 - ${FUZZER_TEST_DIR}/out/crashes
335 - ${FUZZER_TEST_DIR}/fuzz_output.log
338 # can only be triggered
341 - export AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES=1 && export AFL_SKIP_CPUFREQ=1
342 - cd ${FUZZER_TEST_DIR}
343 # run AFL fuzzer for one hour
344 - ( ( make ${FUZZER_PARAMS} fuzz | tee fuzz_output.log | grep -v '\(Fuzzing test case\|Entering queue cycle\)' ) || pkill sleep ) &
345 - ( sleep 3600 || mkdir -p out/crashes/env_failed ) && pkill afl-fuz
346 # check no crashes found
347 - test -z "$(ls out/crashes/)" || exit 1
349 test_mdns_fuzzer_on_host:
350 <<: *host_fuzzer_test_template
352 BOT_NEEDS_TRIGGER_BY_NAME: 1
353 FUZZER_TEST_DIR: components/mdns/test_afl_fuzz_host
355 test_lwip_dns_fuzzer_on_host:
356 <<: *host_fuzzer_test_template
358 BOT_NEEDS_TRIGGER_BY_NAME: 1
359 FUZZER_TEST_DIR: components/lwip/test_afl_host
360 FUZZER_PARAMS: MODE=dns
362 test_lwip_dhcp_fuzzer_on_host:
363 <<: *host_fuzzer_test_template
365 BOT_NEEDS_TRIGGER_BY_NAME: 1
366 FUZZER_TEST_DIR: components/lwip/test_afl_host
367 FUZZER_PARAMS: MODE=dhcp_client
369 test_lwip_dhcps_fuzzer_on_host:
370 <<: *host_fuzzer_test_template
372 BOT_NEEDS_TRIGGER_BY_NAME: 1
373 FUZZER_TEST_DIR: components/lwip/test_afl_host
374 FUZZER_PARAMS: MODE=dhcp_server
377 <<: *host_test_template
379 - cd components/spiffs/test_spiffs_host/
382 test_multi_heap_on_host:
383 <<: *host_test_template
385 - cd components/heap/test_multi_heap_host
386 - ./test_all_configs.sh
389 <<: *host_test_template
391 - cd tools/kconfig_new/test
392 - ./test_confserver.py
395 <<: *host_test_template
397 - ${IDF_PATH}/tools/ci/test_configure_ci_environment.sh
398 - rm -rf test_build_system
399 - mkdir test_build_system
400 - cd test_build_system
401 - ${IDF_PATH}/tools/ci/test_build_system.sh
403 test_build_system_cmake:
404 <<: *host_test_template
406 - ${IDF_PATH}/tools/ci/test_configure_ci_environment.sh
407 - rm -rf test_build_system
408 - mkdir test_build_system
409 - cd test_build_system
410 - ${IDF_PATH}/tools/ci/test_build_system_cmake.sh
413 <<: *host_test_template
417 - tools/test_idf_monitor/outputs/*
420 - cd ${IDF_PATH}/tools/test_idf_monitor
421 - source /opt/pyenv/activate
422 - pyenv global 2.7.15
423 - ./run_test_idf_monitor.py
425 - ./run_test_idf_monitor.py
426 - pyenv global system
429 <<: *host_test_template
433 - tools/test_idf_size/output
434 - tools/test_idf_size/.coverage
437 - cd ${IDF_PATH}/tools/test_idf_size
438 - source /opt/pyenv/activate
439 - pyenv global 2.7.15
443 - pyenv global system
445 test_esp_err_to_name_on_host:
446 <<: *host_test_template
450 - components/esp32/esp_err_to_name.c
454 - source /opt/pyenv/activate
455 - pyenv global 2.7.15
456 - ./gen_esp_err_to_name.py
457 - git diff --exit-code -- ../components/esp32/esp_err_to_name.c || (echo 'Differences found. Please run gen_esp_err_to_name.py and commit the changes.'; exit 1)
459 - ./gen_esp_err_to_name.py
460 - git diff --exit-code -- ../components/esp32/esp_err_to_name.c || (echo 'Differences found between running under Python 2 and 3.'; exit 1)
461 - pyenv global system
465 image: $CI_DOCKER_REGISTRY/esp32-ci-env$BOT_DOCKER_IMAGE_TAG
471 - /^v\d+\.\d+(\.\d+)?($|-)/
474 before_script: *do_nothing_before
478 - echo -n $GH_PUSH_KEY > ~/.ssh/id_rsa_base64
479 - base64 --decode --ignore-garbage ~/.ssh/id_rsa_base64 > ~/.ssh/id_rsa
480 - chmod 600 ~/.ssh/id_rsa
481 - echo -e "Host github.com\n\tStrictHostKeyChecking no\n" >> ~/.ssh/config
482 - git remote remove github &>/dev/null || true
483 - git remote add github git@github.com:espressif/esp-idf.git
484 # Need separate push commands for tag builds and for branch builds
485 - "[ -n \"${CI_COMMIT_TAG}\" ] && git push github ${CI_COMMIT_TAG}"
486 - "[ -z \"${CI_COMMIT_TAG}\" ] && git push github ${CI_COMMIT_SHA}:refs/heads/${CI_COMMIT_REF_NAME}"
490 image: $CI_DOCKER_REGISTRY/esp32-ci-env$BOT_DOCKER_IMAGE_TAG
496 - /^v\d+\.\d+(\.\d+)?($|-)/
500 before_script: *do_nothing_before
504 - echo -n $DOCS_DEPLOY_KEY > ~/.ssh/id_rsa_base64
505 - base64 --decode --ignore-garbage ~/.ssh/id_rsa_base64 > ~/.ssh/id_rsa
506 - chmod 600 ~/.ssh/id_rsa
507 - echo -e "Host $DOCS_SERVER\n\tStrictHostKeyChecking no\n\tUser $DOCS_SERVER_USER\n" >> ~/.ssh/config
508 - export GIT_VER=$(git describe --always)
511 - tar czvf $GIT_VER.tar.gz $GIT_VER
512 - scp $GIT_VER.tar.gz $DOCS_SERVER:$DOCS_PATH/en
513 - ssh $DOCS_SERVER -x "cd $DOCS_PATH/en && tar xzvf $GIT_VER.tar.gz && rm -f latest && ln -s $GIT_VER latest"
514 - cd ../../zh_CN/_build/
516 - tar czvf $GIT_VER.tar.gz $GIT_VER
517 - scp $GIT_VER.tar.gz $DOCS_SERVER:$DOCS_PATH/zh_CN
518 - ssh $DOCS_SERVER -x "cd $DOCS_PATH/zh_CN && tar xzvf $GIT_VER.tar.gz && rm -f latest && ln -s $GIT_VER latest"
519 # add link to preview doc
520 - echo "[document preview][en] $CI_DOCKER_REGISTRY/docs/esp-idf/en/${GIT_VER}/index.html"
521 - echo "[document preview][zh_CN] $CI_DOCKER_REGISTRY/docs/esp-idf/zh_CN/${GIT_VER}/index.html"
525 image: $CI_DOCKER_REGISTRY/esp32-ci-env$BOT_DOCKER_IMAGE_TAG
529 # can only be triggered
533 - docs/_build/linkcheck
536 # must be triggered with CHECK_LINKS=Yes, otherwise exit without test
537 - test "$CHECK_LINKS" = "Yes" || exit 0
538 # can only run on master branch (otherwise the commit is not on Github yet)
539 - test "${CI_COMMIT_REF_NAME}" = "master" || exit 0
545 image: $CI_DOCKER_REGISTRY/esp32-ci-env$BOT_DOCKER_IMAGE_TAG
549 before_script: *do_nothing_before_no_filter
551 - tools/ci/check-line-endings.sh ${IDF_PATH}
555 image: $CI_DOCKER_REGISTRY/esp32-ci-env$BOT_DOCKER_IMAGE_TAG
559 before_script: *do_nothing_before_no_filter
562 - git log -n10 --oneline
563 # commit start with "WIP: " need to be squashed before merge
564 - 'git log --pretty=%s master.. -- | grep "^WIP: " && exit 1 || exit 0'
568 image: $CI_DOCKER_REGISTRY/esp32-ci-env$BOT_DOCKER_IMAGE_TAG
572 before_script: *do_nothing_before_no_filter
574 - tools/ci/check-executable.sh
576 check_examples_cmake_make:
578 image: $CI_DOCKER_REGISTRY/esp32-ci-env$BOT_DOCKER_IMAGE_TAG
584 - /^v\d+\.\d+(\.\d+)?($|-)/
586 before_script: *do_nothing_before
588 - tools/ci/check_examples_cmake_make.sh
590 check_submodule_sync:
592 image: $CI_DOCKER_REGISTRY/esp32-ci-env$BOT_DOCKER_IMAGE_TAG
598 before_script: *do_nothing_before_no_filter
600 # check if all submodules are correctly synced to public repostory
601 - git submodule update --init --recursive
606 image: $CI_DOCKER_REGISTRY/ubuntu-test-env
608 # gitlab ci do not support match job with RegEx or wildcard now in dependencies.
609 # we have a lot build example jobs. now we don't use dependencies, just download all artificats of build stage.
614 - build_esp_idf_tests
616 TEST_FW_PATH: "$CI_PROJECT_DIR/tools/tiny-test-fw"
617 EXAMPLE_CONFIG_OUTPUT_PATH: "$CI_PROJECT_DIR/examples/test_configs"
620 - components/idf_test/*/CIConfigs
621 - components/idf_test/*/TC.sqlite
622 - $EXAMPLE_CONFIG_OUTPUT_PATH
624 before_script: *add_gitlab_key_before
626 # assign example tests
627 - python $TEST_FW_PATH/CIAssignExampleTest.py $IDF_PATH/examples $IDF_PATH/.gitlab-ci.yml $EXAMPLE_CONFIG_OUTPUT_PATH
628 # assign unit test cases
629 - python $TEST_FW_PATH/CIAssignUnitTest.py $IDF_PATH/components/idf_test/unit_test/TestCaseAll.yml $IDF_PATH/.gitlab-ci.yml $IDF_PATH/components/idf_test/unit_test/CIConfigs
630 # clone test script to assign tests
631 - git clone $TEST_SCRIPT_REPOSITORY
632 - cd auto_test_script
633 - python $CHECKOUT_REF_SCRIPT auto_test_script
634 # assgin integration test cases
635 - python CIAssignTestCases.py -t $IDF_PATH/components/idf_test/integration_test -c $IDF_PATH/.gitlab-ci.yml -b $IDF_PATH/SSC/ssc_bin
637 .example_test_template: &example_test_template
638 stage: integration_test
643 - /^v\d+\.\d+(\.\d+)?($|-)/
662 TEST_FW_PATH: "$CI_PROJECT_DIR/tools/tiny-test-fw"
663 TEST_CASE_PATH: "$CI_PROJECT_DIR/examples"
664 CONFIG_FILE: "$CI_PROJECT_DIR/examples/test_configs/$CI_JOB_NAME.yml"
665 LOG_PATH: "$CI_PROJECT_DIR/TEST_LOGS"
666 ENV_FILE: "$CI_PROJECT_DIR/ci-test-runner-configs/$CI_RUNNER_DESCRIPTION/EnvConfig.yml"
668 # first test if config file exists, if not exist, exit 0
669 - test -e $CONFIG_FILE || exit 0
670 # clone test env configs
671 - git clone $TEST_ENV_CONFIG_REPOSITORY
672 - cd ci-test-runner-configs
673 - python $CHECKOUT_REF_SCRIPT ci-test-runner-configs
676 - python Runner.py $TEST_CASE_PATH -c $CONFIG_FILE -e $ENV_FILE
678 .unit_test_template: &unit_test_template
679 <<: *example_test_template
683 - build_esp_idf_tests
685 TEST_FW_PATH: "$CI_PROJECT_DIR/tools/tiny-test-fw"
686 TEST_CASE_PATH: "$CI_PROJECT_DIR/tools/unit-test-app"
687 CONFIG_FILE: "$CI_PROJECT_DIR/components/idf_test/unit_test/CIConfigs/$CI_JOB_NAME.yml"
688 LOG_PATH: "$CI_PROJECT_DIR/TEST_LOGS"
689 ENV_FILE: "$CI_PROJECT_DIR/ci-test-runner-configs/$CI_RUNNER_DESCRIPTION/EnvConfig.yml"
691 .test_template: &test_template
692 stage: integration_test
697 - /^v\d+\.\d+(\.\d+)?($|-)/
711 LOCAL_ENV_CONFIG_PATH: "$CI_PROJECT_DIR/ci-test-runner-configs/$CI_RUNNER_DESCRIPTION/ESP32_IDF"
712 LOG_PATH: "$CI_PROJECT_DIR/$CI_COMMIT_SHA"
713 TEST_CASE_FILE_PATH: "$CI_PROJECT_DIR/components/idf_test/integration_test"
714 MODULE_UPDATE_FILE: "$CI_PROJECT_DIR/components/idf_test/ModuleDefinition.yml"
715 CONFIG_FILE: "$CI_PROJECT_DIR/components/idf_test/integration_test/CIConfigs/$CI_JOB_NAME.yml"
716 before_script: *add_gitlab_key_before
718 # first test if config file exists, if not exist, exit 0
719 - test -e $CONFIG_FILE || exit 0
720 # clone local test env configs
721 - git clone $TEST_ENV_CONFIG_REPOSITORY
722 - cd ci-test-runner-configs
723 - python $CHECKOUT_REF_SCRIPT ci-test-runner-configs
725 - git clone $TEST_SCRIPT_REPOSITORY
726 - cd auto_test_script
727 - python $CHECKOUT_REF_SCRIPT auto_test_script
729 - python CIRunner.py -l "$LOG_PATH/$CI_JOB_NAME" -c $CONFIG_FILE -e $LOCAL_ENV_CONFIG_PATH -t $TEST_CASE_FILE_PATH -m $MODULE_UPDATE_FILE
743 # clone local test env configs
744 - git clone $TEST_ENV_CONFIG_REPOSITORY
745 - cd ci-test-runner-configs
746 - python $CHECKOUT_REF_SCRIPT ci-test-runner-configs
748 - git clone $TEST_SCRIPT_REPOSITORY
749 - cd auto_test_script
750 - git checkout ${CI_COMMIT_REF_NAME} || echo "Using default branch..."
752 - ./Tools/prepare_nvs_bin.sh
754 - python CIRunner.py -l "$LOG_PATH/$CI_JOB_NAME" -c $CONFIG_FILE -e $LOCAL_ENV_CONFIG_PATH -t $TEST_CASE_FILE_PATH -m $MODULE_UPDATE_FILE
757 <<: *example_test_template
763 <<: *example_test_template
769 <<: *example_test_template
775 <<: *example_test_template
781 <<: *unit_test_template
787 <<: *unit_test_template
793 <<: *unit_test_template
799 <<: *unit_test_template
805 <<: *unit_test_template
811 <<: *unit_test_template
817 <<: *unit_test_template
823 <<: *unit_test_template
829 <<: *unit_test_template
835 <<: *unit_test_template
841 <<: *unit_test_template
847 <<: *unit_test_template
853 <<: *unit_test_template
859 <<: *unit_test_template
865 <<: *unit_test_template
871 <<: *unit_test_template
877 <<: *unit_test_template
883 <<: *unit_test_template
889 <<: *unit_test_template
895 <<: *unit_test_template
901 <<: *unit_test_template
907 <<: *unit_test_template
913 <<: *unit_test_template
919 <<: *unit_test_template
925 <<: *unit_test_template
931 <<: *unit_test_template
937 <<: *unit_test_template
943 <<: *unit_test_template
949 <<: *unit_test_template
955 <<: *unit_test_template
961 <<: *unit_test_template
967 <<: *unit_test_template
973 <<: *unit_test_template
979 <<: *unit_test_template
985 <<: *unit_test_template
991 <<: *unit_test_template
997 <<: *unit_test_template
1003 <<: *unit_test_template
1009 <<: *unit_test_template
1015 <<: *unit_test_template
1021 <<: *unit_test_template
1027 <<: *unit_test_template
1033 <<: *unit_test_template
1040 <<: *unit_test_template
1047 <<: *unit_test_template
1054 <<: *unit_test_template
1061 <<: *unit_test_template
1068 <<: *unit_test_template
1075 <<: *unit_test_template
1082 <<: *unit_test_template
1089 <<: *unit_test_template
1096 <<: *unit_test_template
1103 <<: *unit_test_template
1110 <<: *unit_test_template
1117 <<: *unit_test_template
1124 <<: *unit_test_template
1130 <<: *unit_test_template
1136 <<: *unit_test_template
1142 <<: *unit_test_template
1149 <<: *unit_test_template
1155 <<: *unit_test_template
1161 <<: *unit_test_template
1167 <<: *unit_test_template
1174 <<: *unit_test_template
1180 <<: *unit_test_template
1186 <<: *unit_test_template
1192 <<: *unit_test_template
1199 <<: *unit_test_template
1205 <<: *unit_test_template
1211 <<: *unit_test_template
1217 <<: *unit_test_template
1224 <<: *unit_test_template
1230 <<: *unit_test_template
1236 <<: *unit_test_template
1242 <<: *unit_test_template