Commit | Line | Data |
---|---|---|
abdabab5 MJ |
1 | #!/bin/bash |
2 | ||
3 | # Copyright (c) 2019 Michael Jeanson <mjeanson@efficios.com> | |
4 | # Copyright (C) 2019 Philippe Proulx <pproulx@efficios.com> | |
5 | # | |
6 | # This program is free software; you can redistribute it and/or modify | |
7 | # it under the terms of the GNU General Public License as published by | |
8 | # the Free Software Foundation; under version 2 of the License. | |
9 | # | |
10 | # This program is distributed in the hope that it will be useful, | |
11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
13 | # GNU General Public License for more details. | |
14 | # | |
15 | # You should have received a copy of the GNU General Public License along | |
16 | # with this program; if not, write to the Free Software Foundation, Inc., | |
17 | # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | |
18 | ||
19 | # This file is meant to be sourced at the start of shell script-based tests. | |
20 | ||
21 | ||
22 | # Error out when encountering an undefined variable | |
23 | set -u | |
24 | ||
d3f71134 MJ |
25 | # If "readlink -f" is available, get a resolved absolute path to the |
26 | # tests source dir, otherwise make do with a relative path. | |
abdabab5 | 27 | scriptdir="$(dirname "${BASH_SOURCE[0]}")" |
d3f71134 MJ |
28 | if readlink -f "." >/dev/null 2>&1; then |
29 | testsdir=$(readlink -f "$scriptdir/..") | |
30 | else | |
31 | testsdir="$scriptdir/.." | |
32 | fi | |
abdabab5 | 33 | |
d660133b JR |
34 | # The OS on which we are running. See [1] for possible values of 'uname -s'. |
35 | # We do a bit of translation to ease our life down the road for comparison. | |
36 | # Export it so that called executables can use it. | |
37 | # [1] https://en.wikipedia.org/wiki/Uname#Examples | |
38 | if [ "x${BT_OS_TYPE:-}" = "x" ]; then | |
39 | BT_OS_TYPE="$(uname -s)" | |
40 | case "$BT_OS_TYPE" in | |
41 | MINGW*) | |
42 | BT_OS_TYPE="mingw" | |
43 | ;; | |
44 | Darwin) | |
45 | BT_OS_TYPE="darwin" | |
46 | ;; | |
47 | Linux) | |
48 | BT_OS_TYPE="linux" | |
49 | ;; | |
5200c954 JR |
50 | CYGWIN*) |
51 | BT_OS_TYPE="cygwin" | |
52 | ;; | |
d660133b JR |
53 | *) |
54 | BT_OS_TYPE="unsupported" | |
55 | ;; | |
56 | esac | |
57 | fi | |
58 | export BT_OS_TYPE | |
59 | ||
abdabab5 MJ |
60 | # Allow overriding the source and build directories |
61 | if [ "x${BT_TESTS_SRCDIR:-}" = "x" ]; then | |
d3f71134 | 62 | BT_TESTS_SRCDIR="$testsdir" |
abdabab5 MJ |
63 | fi |
64 | export BT_TESTS_SRCDIR | |
65 | ||
66 | if [ "x${BT_TESTS_BUILDDIR:-}" = "x" ]; then | |
d3f71134 | 67 | BT_TESTS_BUILDDIR="$testsdir" |
abdabab5 MJ |
68 | fi |
69 | export BT_TESTS_BUILDDIR | |
70 | ||
71 | # By default, it will not source tap.sh. If you to tap output directly from | |
72 | # the test script, define the 'SH_TAP' variable to '1' before sourcing this | |
73 | # script. | |
74 | if [ "x${SH_TAP:-}" = x1 ]; then | |
8c083b3e | 75 | # shellcheck source=./tap/tap.sh |
abdabab5 MJ |
76 | . "${BT_TESTS_SRCDIR}/utils/tap/tap.sh" |
77 | fi | |
78 | ||
79 | # Allow overriding the babeltrace2 executables | |
80 | if [ "x${BT_TESTS_BT2_BIN:-}" = "x" ]; then | |
f090979c | 81 | BT_TESTS_BT2_BIN="$BT_TESTS_BUILDDIR/../src/cli/babeltrace2" |
d660133b | 82 | if [ "$BT_OS_TYPE" = "mingw" ]; then |
a8a11adb JR |
83 | BT_TESTS_BT2_BIN="${BT_TESTS_BT2_BIN}.exe" |
84 | fi | |
abdabab5 MJ |
85 | fi |
86 | export BT_TESTS_BT2_BIN | |
87 | ||
abdabab5 MJ |
88 | # TODO: Remove when bindings/python/bt2/test_plugin.py is fixed |
89 | BT_PLUGINS_PATH="${BT_TESTS_BUILDDIR}/../src/plugins" | |
90 | ||
91 | # Allow overriding the babeltrace2 plugin path | |
92 | if [ "x${BT_TESTS_BABELTRACE_PLUGIN_PATH:-}" = "x" ]; then | |
93 | BT_TESTS_BABELTRACE_PLUGIN_PATH="${BT_PLUGINS_PATH}/ctf:${BT_PLUGINS_PATH}/utils:${BT_PLUGINS_PATH}/text" | |
94 | fi | |
95 | ||
7b783015 MJ |
96 | if [ "x${BT_TESTS_PROVIDER_DIR:-}" = "x" ]; then |
97 | BT_TESTS_PROVIDER_DIR="${BT_TESTS_BUILDDIR}/../src/python-plugin-provider/.libs" | |
98 | fi | |
99 | ||
abdabab5 MJ |
100 | # Allow overriding the babeltrace2 executables |
101 | if [ "x${BT_TESTS_PYTHONPATH:-}" = "x" ]; then | |
102 | BT_TESTS_PYTHONPATH="${BT_TESTS_BUILDDIR}/../src/bindings/python/bt2/build/build_lib" | |
103 | fi | |
104 | ||
105 | ||
106 | ### External Tools ### | |
107 | if [ "x${BT_TESTS_AWK_BIN:-}" = "x" ]; then | |
108 | BT_TESTS_AWK_BIN="awk" | |
109 | fi | |
110 | export BT_TESTS_AWK_BIN | |
111 | ||
112 | if [ "x${BT_TESTS_GREP_BIN:-}" = "x" ]; then | |
113 | BT_TESTS_GREP_BIN="grep" | |
114 | fi | |
115 | export BT_TESTS_GREP_BIN | |
116 | ||
117 | if [ "x${BT_TESTS_PYTHON_BIN:-}" = "x" ]; then | |
118 | BT_TESTS_PYTHON_BIN="python3" | |
119 | fi | |
120 | export BT_TESTS_PYTHON_BIN | |
121 | ||
4b2d0d1f MJ |
122 | if [ "x${BT_TESTS_PYTHON_CONFIG_BIN:-}" = "x" ]; then |
123 | BT_TESTS_PYTHON_CONFIG_BIN="python3-config" | |
124 | fi | |
da387343 | 125 | export BT_TESTS_PYTHON_CONFIG_BIN |
4b2d0d1f | 126 | |
abdabab5 MJ |
127 | if [ "x${BT_TESTS_SED_BIN:-}" = "x" ]; then |
128 | BT_TESTS_SED_BIN="sed" | |
129 | fi | |
130 | export BT_TESTS_SED_BIN | |
131 | ||
132 | ||
133 | # Data files path | |
134 | BT_TESTS_DATADIR="${BT_TESTS_SRCDIR}/data" | |
135 | BT_CTF_TRACES_PATH="${BT_TESTS_DATADIR}/ctf-traces" | |
abdabab5 | 136 | |
5fd7382f SM |
137 | # Run the Babeltrace CLI, redirecting stdout and stderr to specified files. |
138 | # | |
139 | # $1: file to redirect stdout to | |
140 | # $2: file to redirect stderr to | |
141 | # remaining args: arguments to pass to the CLI | |
142 | # | |
143 | # Return the exit code of the CLI. | |
144 | ||
145 | bt_cli() { | |
146 | local stdout_file="$1" | |
147 | local stderr_file="$2" | |
148 | shift 2 | |
149 | local args=("$@") | |
150 | ||
151 | run_python_bt2 "$BT_TESTS_BT2_BIN" "${args[@]}" 1>"$stdout_file" 2>"$stderr_file" | |
152 | } | |
abdabab5 MJ |
153 | |
154 | ### Diff Functions ### | |
155 | ||
5b4aa960 SM |
156 | # Check the differences between two files (typically some expected output vs |
157 | # some actual output). If there are differences, print the diff to stderr. | |
d8f6e7fb | 158 | # |
5b4aa960 SM |
159 | # $1: file 1 (expected) |
160 | # $2: file 2 (actual) | |
d8f6e7fb | 161 | # |
5b4aa960 | 162 | # Return 0 if there's no difference, and 1 if there are. |
d8f6e7fb | 163 | # |
5b4aa960 SM |
164 | # Note that this function modifies the actual output file ($2) _in-place_ to |
165 | # remove any \r character. | |
166 | ||
d8f6e7fb | 167 | bt_diff() { |
5b4aa960 SM |
168 | local expected_file="$1" |
169 | local actual_file="$2" | |
170 | shift 2 | |
d8f6e7fb | 171 | local args=("$@") |
d8f6e7fb MJ |
172 | local ret=0 |
173 | local temp_diff | |
174 | ||
175 | temp_diff="$(mktemp -t diff.XXXXXX)" | |
176 | ||
177 | # Strip any \r present due to Windows (\n -> \r\n). | |
178 | # "diff --string-trailing-cr" is not used since it is not present on | |
179 | # Solaris. | |
5b4aa960 | 180 | "$BT_TESTS_SED_BIN" -i 's/\r//g' "$actual_file" |
d8f6e7fb | 181 | |
5b4aa960 SM |
182 | if ! diff -u "$expected_file" "$actual_file" > "$temp_diff"; then |
183 | echo "ERROR: for '${args[*]}': output does not match:" >&2 | |
d8f6e7fb MJ |
184 | cat "$temp_diff" >&2 |
185 | ret=1 | |
186 | fi | |
187 | ||
188 | rm -f "$temp_diff" | |
189 | ||
190 | return $ret | |
191 | } | |
192 | ||
ca5f1044 FD |
193 | # Checks the difference between: |
194 | # | |
195 | # 1. What the CLI outputs on its standard output when given the arguments | |
196 | # "$@" (excluding the first two arguments). | |
197 | # 2. The file with path "$1". | |
198 | # | |
199 | # And the difference between: | |
200 | # | |
201 | # 1. What the CLI outputs on its standard error when given the arguments | |
202 | # "$@" (excluding the first two arguments). | |
203 | # 2. The file with path "$2". | |
abdabab5 MJ |
204 | # |
205 | # Returns 0 if there's no difference, and 1 if there is, also printing | |
206 | # said difference to the standard error. | |
207 | bt_diff_cli() { | |
ca5f1044 FD |
208 | local expected_stdout_file="$1" |
209 | local expected_stderr_file="$2" | |
210 | shift 2 | |
b241db8f MJ |
211 | local args=("$@") |
212 | ||
ca5f1044 FD |
213 | local temp_stdout_output_file |
214 | local temp_stderr_output_file | |
abdabab5 | 215 | local ret=0 |
5b4aa960 SM |
216 | local ret_stdout |
217 | local ret_stderr | |
abdabab5 | 218 | |
d8f6e7fb MJ |
219 | temp_stdout_output_file="$(mktemp -t actual_stdout.XXXXXX)" |
220 | temp_stderr_output_file="$(mktemp -t actual_stderr.XXXXXX)" | |
abdabab5 | 221 | |
ca5f1044 | 222 | # Run the CLI to get a detailed file. |
5fd7382f | 223 | bt_cli "$temp_stdout_output_file" "$temp_stderr_output_file" "${args[@]}" |
ca5f1044 | 224 | |
5b4aa960 SM |
225 | bt_diff "$expected_stdout_file" "$temp_stdout_output_file" "${args[@]}" |
226 | ret_stdout=$? | |
227 | bt_diff "$expected_stderr_file" "$temp_stderr_output_file" "${args[@]}" | |
228 | ret_stderr=$? | |
229 | ||
230 | if ((ret_stdout != 0 || ret_stderr != 0)); then | |
231 | ret=1 | |
232 | fi | |
ca5f1044 | 233 | |
d8f6e7fb | 234 | rm -f "$temp_stdout_output_file" "$temp_stderr_output_file" |
abdabab5 | 235 | |
d8f6e7fb MJ |
236 | return $ret |
237 | } | |
238 | ||
239 | # Checks the difference between: | |
240 | # | |
241 | # 1. What the CLI outputs on its standard output when given the arguments | |
242 | # "$@" (excluding the first two arguments), sorted with the default "sort". | |
243 | # 2. The file with path "$1". | |
244 | # | |
245 | # And the difference between: | |
246 | # | |
247 | # 1. What the CLI outputs on its standard error when given the arguments | |
248 | # "$@" (excluding the first two arguments). | |
249 | # 2. The file with path "$2". | |
250 | # | |
251 | # Returns 0 if there's no difference, and 1 if there is, also printing | |
252 | # said difference to the standard error. | |
253 | bt_diff_cli_sorted() { | |
254 | local expected_stdout_file="$1" | |
255 | local expected_stderr_file="$2" | |
256 | shift 2 | |
257 | local args=("$@") | |
258 | ||
259 | local temp_stdout_output_file | |
260 | local temp_stderr_output_file | |
261 | local ret=0 | |
5b4aa960 SM |
262 | local ret_stdout |
263 | local ret_stderr | |
d8f6e7fb MJ |
264 | |
265 | temp_stdout_output_file="$(mktemp -t actual_stdout.XXXXXX)" | |
266 | temp_stderr_output_file="$(mktemp -t actual_stderr.XXXXXX)" | |
267 | ||
268 | # Run the CLI to get a detailed file. | |
5fd7382f | 269 | bt_cli "$temp_stdout_output_file" "$temp_stderr_output_file" "${args[@]}" |
d8f6e7fb MJ |
270 | |
271 | # Sort the stdout file, use a subshell to do it in-place | |
272 | # shellcheck disable=SC2005 | |
273 | echo "$(LC_ALL=C sort "$temp_stdout_output_file")" > "$temp_stdout_output_file" | |
274 | ||
5b4aa960 SM |
275 | bt_diff "$expected_stdout_file" "$temp_stdout_output_file" "${args[@]}" |
276 | ret_stdout=$? | |
277 | bt_diff "$expected_stderr_file" "$temp_stderr_output_file" "${args[@]}" | |
278 | ret_stderr=$? | |
279 | ||
280 | if ((ret_stdout != 0 || ret_stderr != 0)); then | |
281 | ret=1 | |
282 | fi | |
abdabab5 | 283 | |
d8f6e7fb | 284 | rm -f "$temp_stdout_output_file" "$temp_stderr_output_file" |
abdabab5 MJ |
285 | |
286 | return $ret | |
287 | } | |
288 | ||
b241db8f MJ |
289 | # Checks the difference between the content of the file with path "$1" |
290 | # and the output of the CLI when called on the directory path "$2" with | |
291 | # the arguments '-c sink.text.details' and the rest of the arguments to | |
292 | # this function. | |
abdabab5 MJ |
293 | # |
294 | # Returns 0 if there's no difference, and 1 if there is, also printing | |
295 | # said difference to the standard error. | |
296 | bt_diff_details_ctf_single() { | |
ca5f1044 | 297 | local expected_stdout_file="$1" |
b241db8f MJ |
298 | local trace_dir="$2" |
299 | shift 2 | |
300 | local extra_details_args=("$@") | |
ca5f1044 | 301 | expected_stderr_file="/dev/null" |
abdabab5 MJ |
302 | |
303 | # Compare using the CLI with `sink.text.details` | |
ca5f1044 | 304 | bt_diff_cli "$expected_stdout_file" "$expected_stderr_file" "$trace_dir" "-c" "sink.text.details" "${extra_details_args[@]}" |
abdabab5 MJ |
305 | } |
306 | ||
307 | # Calls bt_diff_details_ctf_single(), except that "$1" is the path to a | |
308 | # program which generates the CTF trace to compare to. The program "$1" | |
309 | # receives the path to a temporary, empty directory where to write the | |
310 | # CTF trace as its first argument. | |
311 | bt_diff_details_ctf_gen_single() { | |
312 | local ctf_gen_prog_path="$1" | |
ca5f1044 | 313 | local expected_stdout_file="$2" |
b241db8f MJ |
314 | shift 2 |
315 | local extra_details_args=("$@") | |
abdabab5 MJ |
316 | |
317 | local temp_trace_dir | |
318 | local ret | |
319 | ||
320 | temp_trace_dir="$(mktemp -d)" | |
321 | ||
322 | # Run the CTF trace generator program to get a CTF trace | |
323 | if ! "$ctf_gen_prog_path" "$temp_trace_dir" 2>/dev/null; then | |
324 | echo "ERROR: \"$ctf_gen_prog_path\" \"$temp_trace_dir\" failed" >&2 | |
325 | rm -rf "$temp_trace_dir" | |
326 | return 1 | |
327 | fi | |
328 | ||
329 | # Compare using the CLI with `sink.text.details` | |
ca5f1044 | 330 | bt_diff_details_ctf_single "$expected_stdout_file" "$temp_trace_dir" "${extra_details_args[@]}" |
abdabab5 MJ |
331 | ret=$? |
332 | rm -rf "$temp_trace_dir" | |
333 | return $ret | |
334 | } | |
335 | ||
336 | ||
337 | ### Functions ### | |
338 | ||
339 | check_coverage() { | |
340 | coverage run "$@" | |
341 | } | |
342 | ||
343 | # Execute a shell command in the appropriate environment to have access to the | |
344 | # bt2 Python bindings. | |
345 | run_python_bt2() { | |
4b2d0d1f MJ |
346 | local env_args |
347 | ||
348 | env_args=( | |
349 | "BABELTRACE_PYTHON_BT2_NO_TRACEBACK=1" \ | |
350 | "BABELTRACE_PLUGIN_PATH=${BT_TESTS_BABELTRACE_PLUGIN_PATH}" \ | |
351 | "LIBBABELTRACE2_PLUGIN_PROVIDER_DIR=${BT_TESTS_PROVIDER_DIR}" \ | |
352 | "BT_CTF_TRACES_PATH=${BT_CTF_TRACES_PATH}" \ | |
353 | "BT_PLUGINS_PATH=${BT_PLUGINS_PATH}" \ | |
354 | "PYTHONPATH=${BT_TESTS_PYTHONPATH}:${BT_TESTS_SRCDIR}/utils/python" | |
355 | ) | |
abdabab5 | 356 | |
2e3c8ba5 SM |
357 | local main_lib_path="${BT_TESTS_BUILDDIR}/../src/lib/.libs" |
358 | ||
abdabab5 | 359 | # Set the library search path so the python interpreter can load libbabeltrace2 |
5200c954 | 360 | if [ "$BT_OS_TYPE" = "mingw" ] || [ "$BT_OS_TYPE" = "cygwin" ]; then |
4b2d0d1f | 361 | env_args+=("PATH=${main_lib_path}:${PATH:-}") |
d660133b | 362 | elif [ "$BT_OS_TYPE" = "darwin" ]; then |
4b2d0d1f | 363 | env_args+=("DYLD_LIBRARY_PATH=${main_lib_path}:${DYLD_LIBRARY_PATH:-}") |
abdabab5 | 364 | else |
4b2d0d1f MJ |
365 | env_args+=("LD_LIBRARY_PATH=${main_lib_path}:${LD_LIBRARY_PATH:-}") |
366 | fi | |
367 | ||
368 | # On Windows, an embedded Python interpreter needs a way to locate the path | |
369 | # to it's internal modules, set the prefix from python-config to the | |
370 | # PYTHONHOME variable. | |
371 | if [ "$BT_OS_TYPE" = "mingw" ]; then | |
372 | env_args+=("PYTHONHOME=$($BT_TESTS_PYTHON_CONFIG_BIN --prefix)") | |
abdabab5 MJ |
373 | fi |
374 | ||
4b2d0d1f | 375 | env "${env_args[@]}" "$@" |
abdabab5 MJ |
376 | } |
377 | ||
378 | # Set the environment and run python tests in the directory. | |
379 | # | |
380 | # $1 : The directory containing the python test scripts | |
381 | # $2 : The pattern to match python test script names (optional) | |
abdabab5 MJ |
382 | run_python_bt2_test() { |
383 | local test_dir="$1" | |
541308b8 | 384 | local test_pattern="${2:-'*'}" # optional, if none default to "*" |
abdabab5 MJ |
385 | |
386 | local ret | |
387 | local test_runner_args=() | |
388 | ||
389 | test_runner_args+=("$test_dir") | |
390 | if [ "x${test_pattern}" != "x" ]; then | |
391 | test_runner_args+=("${test_pattern}") | |
392 | fi | |
393 | ||
394 | if test "x${BT_TESTS_COVERAGE:-}" = "x1"; then | |
395 | python_exec="check_coverage" | |
396 | else | |
397 | python_exec="${BT_TESTS_PYTHON_BIN}" | |
398 | fi | |
399 | ||
400 | run_python_bt2 \ | |
401 | "${python_exec}" \ | |
402 | "${BT_TESTS_SRCDIR}/utils/python/testrunner.py" \ | |
541308b8 FD |
403 | --pattern "$test_pattern" \ |
404 | "$test_dir" \ | |
405 | ||
abdabab5 MJ |
406 | ret=$? |
407 | ||
408 | if test "x${BT_TESTS_COVERAGE_REPORT:-}" = "x1"; then | |
409 | coverage report -m | |
410 | fi | |
411 | ||
412 | if test "x${BT_TESTS_COVERAGE_HTML:-}" = "x1"; then | |
413 | coverage html | |
414 | fi | |
415 | ||
416 | return $ret | |
417 | } |