github.com/status-im/status-go@v1.1.0/_assets/scripts/run_unit_tests.sh (about) 1 #!/usr/bin/env bash 2 set -o pipefail 3 4 GIT_ROOT=$(cd "${BASH_SOURCE%/*}" && git rev-parse --show-toplevel) 5 6 source "${GIT_ROOT}/_assets/scripts/colors.sh" 7 8 if [[ $UNIT_TEST_RERUN_FAILS == 'true' ]]; then 9 GOTESTSUM_EXTRAFLAGS="${GOTESTSUM_EXTRAFLAGS} --rerun-fails" 10 elif [[ $UNIT_TEST_FAILFAST == 'true' ]]; then 11 GOTEST_EXTRAFLAGS="${GOTEST_EXTRAFLAGS} -failfast" 12 fi 13 14 if [[ $UNIT_TEST_USE_DEVELOPMENT_LOGGER == 'false' ]]; then 15 if [[ -z $BUILD_TAGS ]]; then 16 BUILD_TAGS="test_silent" 17 else 18 BUILD_TAGS="${BUILD_TAGS},test_silent" 19 fi 20 fi 21 22 if [[ -z "${UNIT_TEST_COUNT}" ]]; then 23 UNIT_TEST_COUNT=1 24 fi 25 26 redirect_stdout() { 27 output_file=$1 28 29 if [[ "${CI}" == 'true' ]]; then 30 cat > "${output_file}"; 31 else 32 tee "${output_file}"; 33 fi 34 } 35 36 run_test_for_packages() { 37 local packages="$1" 38 local iteration="$2" 39 local count="$3" 40 local single_timeout="$4" 41 local log_message="$5" 42 43 local output_file="test_${iteration}.log" 44 local coverage_file="test_${iteration}.coverage.out" 45 local report_file="report_${iteration}.xml" 46 local rerun_report_file="report_rerun_fails_${iteration}.txt" 47 local exit_code_file="exit_code_${iteration}.txt" 48 local timeout="$(( single_timeout * count))m" 49 50 if [[ "${UNIT_TEST_DRY_RUN}" == 'true' ]]; then 51 echo -e "${GRN}Dry run ${iteration}. message:${RST} ${log_message}\n"\ 52 "${YLW}Dry run ${iteration}. packages:${RST} ${packages}\n"\ 53 "${YLW}Dry run ${iteration}. count:${RST} ${count}\n"\ 54 "${YLW}Dry run ${iteration}. timeout:${RST} ${timeout}" 55 return 0 56 fi 57 58 echo -e "${GRN}Testing:${RST} ${log_message}. Iteration ${iteration}. -test.count=${count}. Timeout: ${timeout}" 59 60 gotestsum_flags="${GOTESTSUM_EXTRAFLAGS}" 61 if [[ "${CI}" == 'true' ]]; then 62 gotestsum_flags="${gotestsum_flags} --junitfile=${report_file} --rerun-fails-report=${rerun_report_file}" 63 fi 64 65 # Prepare env variables for `test-with-coverage.sh` 66 export TEST_WITH_COVERAGE_PACKAGES="${packages}" 67 export TEST_WITH_COVERAGE_COUNT="${count}" 68 export TEST_WITH_COVERAGE_REPORTS_DIR="$(mktemp -d)" 69 70 # Cleanup previous coverage reports 71 rm -f "${TEST_WITH_COVERAGE_REPORTS_DIR}/coverage.out.rerun.*" 72 73 # Run tests 74 gotestsum --packages="${packages}" ${gotestsum_flags} --raw-command -- \ 75 ./_assets/scripts/test-with-coverage.sh \ 76 ${GOTEST_EXTRAFLAGS} \ 77 -timeout "${timeout}" \ 78 -tags "${BUILD_TAGS}" | \ 79 redirect_stdout "${output_file}" 80 81 local go_test_exit=$? 82 83 # Merge package coverage results 84 go run ./cmd/test-coverage-utils/gocovmerge.go ${TEST_WITH_COVERAGE_REPORTS_DIR}/coverage.out.rerun.* > ${coverage_file} 85 rm -f "${COVERAGE_REPORTS_DIR}/coverage.out.rerun.*" 86 87 echo "${go_test_exit}" > "${exit_code_file}" 88 if [[ "${go_test_exit}" -ne 0 ]]; then 89 if [[ "${CI}" == 'true' ]]; then 90 echo -e "${YLW}Failed, see the log:${RST} ${BLD}${output_file}${RST}" 91 fi 92 fi 93 94 return ${go_test_exit} 95 } 96 97 if [[ $UNIT_TEST_REPORT_CODECLIMATE == 'true' ]]; then 98 cc-test-reporter before-build 99 fi 100 101 rm -rf ./**/*.coverage.out 102 103 echo -e "${GRN}Testing HEAD:${RST} $(git rev-parse HEAD)" 104 105 DEFAULT_TIMEOUT_MINUTES=5 106 PROTOCOL_TIMEOUT_MINUTES=45 107 108 HAS_PROTOCOL_PACKAGE=true 109 if [[ $(echo "${UNIT_TEST_PACKAGES}" | grep -E '\s?\S+protocol\s+') == "" ]]; then 110 HAS_PROTOCOL_PACKAGE=false 111 fi 112 113 if [[ $HAS_PROTOCOL_PACKAGE == 'false' ]]; then 114 # This is the default single-line flow for testing all packages 115 # The `else` branch is temporary and will be removed once the `protocol` package runtime is optimized. 116 run_test_for_packages "${UNIT_TEST_PACKAGES}" "0" "${UNIT_TEST_COUNT}" "${DEFAULT_TIMEOUT_MINUTES}" "All packages" 117 else 118 # Spawn a process to test all packages except `protocol` 119 UNIT_TEST_PACKAGES_FILTERED=$(echo "${UNIT_TEST_PACKAGES}" | tr ' ' '\n' | grep -v '/protocol$' | tr '\n' ' ') 120 run_test_for_packages "${UNIT_TEST_PACKAGES_FILTERED}" "0" "${UNIT_TEST_COUNT}" "${DEFAULT_TIMEOUT_MINUTES}" "All packages except 'protocol'" & 121 122 # Spawn separate processes to run `protocol` package 123 for ((i=1; i<=UNIT_TEST_COUNT; i++)); do 124 run_test_for_packages github.com/status-im/status-go/protocol "${i}" 1 "${PROTOCOL_TIMEOUT_MINUTES}" "Only 'protocol' package" & 125 done 126 127 wait 128 fi 129 130 # When running in PRs (count=1), early exit if any test failed. 131 # When running nightly (count>1), generate test stats ant coverage reports anyway. 132 if [[ $UNIT_TEST_COUNT -eq 1 ]]; then 133 for exit_code_file in "${GIT_ROOT}"/exit_code_*.txt; do 134 read exit_code < "${exit_code_file}" 135 if [[ "${exit_code}" -ne 0 ]]; then 136 echo -e "${RED}Testing failed${RST}, exit code: ${exit_code}" 137 exit ${exit_code} 138 fi 139 done 140 fi 141 142 # Gather test coverage results 143 merged_coverage_report="coverage_merged.out" 144 final_coverage_report="c.out" # Name expected by cc-test-reporter 145 coverage_reports=$(find . -iname "*.coverage.out") 146 rm -f ${final_coverage_report} ${merged_coverage_report} 147 148 echo -e "${GRN}Gathering test coverage results: ${RST} output: ${merged_coverage_report}, input: ${coverage_reports}" 149 echo $coverage_reports | xargs go run ./cmd/test-coverage-utils/gocovmerge.go > ${merged_coverage_report} 150 151 # Filter out test coverage for packages in ./cmd 152 echo -e "${GRN}Filtering test coverage packages:${RST} ./cmd" 153 grep -v '^github.com/status-im/status-go/cmd/' ${merged_coverage_report} > ${final_coverage_report} 154 155 # Generate HTML coverage report 156 echo -e "${GRN}Generating HTML coverage report${RST}" 157 go tool cover -html ${final_coverage_report} -o test-coverage.html 158 159 # Upload coverage report to CodeClimate 160 if [[ $UNIT_TEST_REPORT_CODECLIMATE == 'true' ]]; then 161 echo -e "${GRN}Uploading coverage report to CodeClimate${RST}" 162 # https://docs.codeclimate.com/docs/jenkins#jenkins-ci-builds 163 GIT_COMMIT=$(git log | grep -m1 -oE '[^ ]+$') 164 cc-test-reporter format-coverage --prefix=github.com/status-im/status-go # To generate 'coverage/codeclimate.json' 165 cc-test-reporter after-build --prefix=github.com/status-im/status-go 166 fi 167 168 if [[ $UNIT_TEST_REPORT_CODECOV == 'true' ]]; then 169 echo -e "${GRN}Uploading coverage report to Codecov${RST}" 170 # https://docs.codeclimate.com/docs/jenkins#jenkins-ci-builds 171 codecov_report_files_args="" 172 for file in report_*.xml; do 173 codecov_report_files_args+="--file ${file} " 174 done 175 codecov do-upload --token "${CODECOV_TOKEN}" --report-type test_results ${codecov_report_files_args} 176 codecov --token "${CODECOV_TOKEN}" -f ${final_coverage_report} -F "unit" 177 fi 178 179 # Generate report with test stats 180 shopt -s globstar nullglob # Enable recursive globbing 181 if [[ "${UNIT_TEST_COUNT}" -gt 1 ]]; then 182 for exit_code_file in "${GIT_ROOT}"/**/exit_code_*.txt; do 183 read exit_code < "${exit_code_file}" 184 if [[ "${exit_code}" -ne 0 ]]; then 185 echo -e "${GRN}Generating test stats${RST}, exit code: ${exit_code}" 186 mkdir -p "${GIT_ROOT}/reports" 187 "${GIT_ROOT}/_assets/scripts/test_stats.py" | tee "${GIT_ROOT}/reports/test_stats.txt" 188 exit ${exit_code} 189 fi 190 done 191 fi 192 193 echo -e "${GRN}Testing finished${RST}"