xref: /aosp_15_r20/external/tink/kokoro/testutils/test_utils.sh (revision e7b1675dde1b92d52ec075b0a92829627f2c52a5)
1#!/bin/bash
2# Copyright 2022 Google LLC
3#
4# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
7#
8#      http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
15################################################################################
16
17# Set of utilities to run unit tests for bash scripts.
18#
19# Example usage:
20# From your test script:
21#   source some/path/to/test_utils.sh
22#
23#   # Test functions must be defined as follows:
24#   test_<Test Name>_<Test Case Name>() {
25#     # Do some ground work.
26#     # Run the test script.
27#     ./path/to/script_to_test <input1> <input2> ...
28#     ASSERT_CMD_SUCCEEDED
29#     ASSERT_FILE_EQUALS <file1> <file2>
30#   }
31#
32#   # Finds all the functions starting with `test_`, extracts test name and
33#   # test case, and run them.
34#   run_all_tests "$@"
35#
36
37# This is either set by Bazel or generated.
38: "${TEST_TMPDIR:="$(mktemp -td test.XXXXX)"}"
39readonly TEST_TMPDIR
40
41# Temporary directory for the testcase to use.
42TEST_CASE_TMPDIR=
43
44# Current test name.
45_CURRENT_TEST_SCOPE=
46
47# Current test case.
48_CURRENT_TEST_CASE=
49
50# True if at least one of the test cases terminated with an error.
51_HAS_ERROR="false"
52
53_print_testcase_failed_and_exit() {
54  echo "[   FAILED ] ${_CURRENT_TEST_SCOPE}.${_CURRENT_TEST_CASE}"
55  exit 1
56}
57
58#######################################
59# Starts a new test case.
60#
61# Globals:
62#   _CURRENT_TEST_SCOPE
63#   _CURRENT_TEST_CASE
64#######################################
65_start_test_case() {
66  echo "[ RUN      ] ${_CURRENT_TEST_SCOPE}.${_CURRENT_TEST_CASE}"
67  # Create a tmp dir for the test case.
68  TEST_CASE_TMPDIR="${TEST_TMPDIR}/${_CURRENT_TEST_SCOPE}/${_CURRENT_TEST_CASE}"
69  mkdir -p "${TEST_CASE_TMPDIR}"
70}
71
72#######################################
73# Ends a test case printing a success message.
74#
75# Globals:
76#   _CURRENT_TEST_SCOPE
77#   _CURRENT_TEST_CASE
78#######################################
79_end_test_case_with_success() {
80  test_case="$1"
81  echo "[       OK ] ${_CURRENT_TEST_SCOPE}.${_CURRENT_TEST_CASE}"
82}
83
84#######################################
85# Returns the list of tests defined in the test script.
86#
87# A test case is a function of the form:
88#     test_<Test Name>_<Test Case>
89#
90# This function returns all the functions starting with `test_`.
91#
92# Globals:
93#   None
94# Arguments:
95#   None
96#######################################
97_get_all_tests() {
98  declare -F |
99    while read line; do
100      case "${line}" in "declare -f test_"*)
101          echo "${line#declare -f }"
102        ;;
103      esac
104    done
105}
106
107#######################################
108# Runs a given test function.
109#
110# A test case is a function of the form:
111#     test_<Test Name>_<Test Case>
112#
113# This script extracts test name and test case from the name.
114#
115# Globals:
116#   _CURRENT_TEST_SCOPE
117# Arguments:
118#   None
119#######################################
120_do_run_test() {
121  test_function="$1"
122  IFS=_ read _CURRENT_TEST_SCOPE _CURRENT_TEST_CASE <<< "${test_function#test_}"
123  _start_test_case
124  (
125    # Make sure we exit only when assertions fail.
126    set +e
127    "${test_function}"
128  )
129  local -r result=$?
130  if (( $result == 0 )); then
131    _end_test_case_with_success
132  else
133    _HAS_ERROR="true"
134  fi
135}
136
137#######################################
138# Runs all the test cases defined in the test script file.
139# Globals:
140#   None
141# Arguments:
142#   None
143#
144#######################################
145run_all_tests() {
146  for test in $(_get_all_tests); do
147    _do_run_test "${test}"
148  done
149  # Make sure we return an error code for the failing test
150  if [[ "${_HAS_ERROR}" == "true" ]]; then
151    exit 1
152  fi
153}
154
155ASSERT_CMD_SUCCEEDED() {
156  if (( $? != 0 )); then
157      _print_testcase_failed_and_exit
158  fi
159}
160
161ASSERT_CMD_FAILED() {
162  if (( $? == 0 )); then
163      _print_testcase_failed_and_exit
164  fi
165}
166
167ASSERT_FILE_EQUALS() {
168  input_file="$1"
169  expected_file="$2"
170  if ! diff "${input_file}" "${expected_file}"; then
171    _print_testcase_failed_and_exit
172  fi
173}
174