OILS / test / common.sh View on Github | oilshell.org

279 lines, 177 significant
1# Usage:
2# source test/common.sh
3
4# Include guard.
5test -n "${__TEST_COMMON_SH:-}" && return
6readonly __TEST_COMMON_SH=1
7
8# Used by test/{gold,osh-usage,stateful,wild-runner}
9OSH=${OSH:-'bin/osh'}
10YSH=${YSH:-'bin/ysh'}
11
12# For xargs -P in spec-runner.sh, wild-runner.sh.
13# If we have 2 cores or less (as on CI machines), use them all. Otherwise save
14# 1 for multitasking.
15nproc=$(nproc)
16MAX_PROCS=${MAX_PROCS:-"$(( nproc <= 2 ? nproc : nproc - 1 ))"}
17
18# Like PYTHONPATH, but for running R scripts
19# Fallback in build/dev-shell.sh
20readonly R_PATH=~/R
21
22log() {
23 echo "$@" 1>&2
24}
25
26die() {
27 log "$@"
28 exit 1
29}
30
31fail() {
32 echo 'TEST FAILURE ' "$@"
33 exit 1
34}
35
36assert() {
37 ### Must be run with errexit off
38
39 if ! test "$@"; then
40 # note: it's extremely weird that we use -1 and 0, but that seems to be how
41 # bash works.
42 die "${BASH_SOURCE[-1]}:${BASH_LINENO[0]}: assert '$@' failed"
43 fi
44}
45
46run-task-with-status() {
47 ### Run a process and write a file with status and time
48
49 # Used by test/{spec,wild}-runner.sh
50
51 local out_file=$1
52 shift
53
54 benchmarks/time_.py \
55 --tsv \
56 --output $out_file \
57 -- "$@" || true # suppress failure
58
59 # TODO: Use rows like this in YSH
60 # '{"status": %x, "wall_secs": %e, "user_secs": %U, "kernel_secs": %S}' \
61}
62
63list-test-funcs() {
64 ### Shell funcs that start with 'test-' are cases that will pass or fail
65 compgen -A function | egrep '^test-'
66}
67
68run-test-funcs() {
69 ### EXIT on failure
70
71 # for correct error handling, and to mutate $i
72 #
73 # Note: when I ran $t rather than $0 t, I seemed to tickle a bash lastpipe bug like this:
74 # https://www.spinics.net/lists/dash/msg01918.html
75 # I got a 127 exit code with no explanation.
76 shopt -s lastpipe
77
78 local i=0
79 local status=0
80
81 list-test-funcs | while read -r t; do
82 echo "*** Running $t"
83
84 set +o errexit
85 $0 $t
86 status=$?
87 set -o errexit
88
89 if test $status -ne 0; then
90 log "FAIL $t"
91 exit 1
92 fi
93
94 log "OK $t"
95 i=$((i + 1))
96 done
97
98 echo
99 echo "$0: $i tests passed."
100}
101
102run-test-bin() {
103 ### Run a binary in _bin/ and log output to a file in _test/
104
105 # Compare with run-test-funcs
106 local bin=$1
107 local working_dir=${2:-}
108 local log_base_dir=${3:-'_test'} # used by test/unit.sh
109
110 local rel_path=${bin#'_bin/'} # for C++ only
111 local log_dir="$log_base_dir/$(dirname $rel_path)"
112 mkdir -p $REPO_ROOT/$log_dir # abs path
113
114 local name=$(basename $bin)
115 export LLVM_PROFILE_FILE="$REPO_ROOT/$log_dir/$name.profraw"
116
117 local log=$log_dir/$name.log
118 log "RUN $bin > $log"
119
120 if test -n "$working_dir"; then
121 pushd $working_dir
122 fi
123
124 set +o errexit
125 $REPO_ROOT/$bin > $REPO_ROOT/$log 2>&1
126 local status=$?
127 set -o errexit
128
129 if test -n "$working_dir"; then
130 popd
131 fi
132
133 if test $status -eq 0; then
134 log 'OK'
135 else
136 echo
137 echo "=== $REPO_ROOT/$log ==="
138 echo
139 cat $REPO_ROOT/$log
140 echo
141 log "FAIL: $bin with code $status"
142 return 1
143 fi
144}
145
146run-one-test() {
147 local rel_path=$1
148 local compiler=${2:-cxx}
149 local variant=${3:-dbg}
150
151 local bin=_bin/$compiler-$variant/$rel_path
152
153 ninja $bin
154
155 run-test-bin $bin
156}
157
158run-test-func() {
159 ### Similar to above
160 local func_name=$1
161 local log=$2
162 shift 2
163
164 mkdir -p $(dirname $log)
165 log "RUN $0 $func_name > $log"
166
167 set +o errexit
168
169 # Reinvoke $0 so errexit is on in the function
170 $0 $func_name "$@" > $log 2>&1
171 local status=$?
172
173 set -o errexit
174
175 if test $status -eq 0; then
176 log 'OK'
177 else
178 echo
179 cat $log
180 echo
181 log "FAIL: $func_name with code $status"
182 return 1
183 fi
184}
185
186# A quick and dirty function to show logs
187run-other-suite-for-release() {
188 local suite_name=$1
189 local func_name=$2
190
191 local out="_tmp/suite-logs/${suite_name}.txt"
192 mkdir -p $(dirname $out)
193
194 echo
195 echo "*** Running test suite '$suite_name' ***"
196 echo
197
198 # I want to handle errors in $func_name while NOT changing its semantics.
199 # This requires a separate shell interpreter starts with $0, not just a
200 # separate process. I came up with this fix in gold/errexit-confusion.sh.
201
202 local status=0
203
204 set +o errexit
205 time $0 $func_name >$out 2>&1
206 status=$? # pipefail makes this work.
207 set -o errexit
208
209 if test $status -eq 0; then
210 echo
211 log "Test suite '$suite_name' ran without errors. Wrote '$out'"
212 else
213 echo
214 die "Test suite '$suite_name' failed (running $func_name, wrote '$out')"
215 fi
216}
217
218date-and-git-info() {
219 date
220 echo
221
222 if test -d .git; then
223 local branch
224 branch=$(git rev-parse --abbrev-ref HEAD)
225 local hash
226 hash=$(git rev-parse $branch)
227
228 echo "oil repo: $hash on branch $branch"
229 else
230 echo "(not running from git repository)"
231 fi
232 echo
233}
234
235html-head() {
236 PYTHONPATH=. doctools/html_head.py "$@"
237}
238
239escape-html() {
240 # Annoying that & has to be escaped in substitution!
241 sed -e 's|&|\&amp;|g' -e 's|<|\&lt;|g' -e 's|>|\&gt;|g' "$@"
242}
243
244export-osh-cpp() {
245 ### Export $OSH var to value in tarball root, repo root
246
247 # Also build it with shell script, or Ninja
248
249 local tar_root=${1:-} # e.g. _tmp/native-tar-test
250 local variant=${2:-opt}
251
252 if test -n "$tar_root" && test -d "$tar_root"; then
253 log "Using binary in $tar_root"
254
255 OIL_VERSION=$(head -n 1 oil-version.txt)
256 local repo_like=$tar_root/oils-for-unix-$OIL_VERSION
257
258 pushd $repo_like
259 _build/oils.sh '' $variant SKIP_REBUILD
260 osh=$PWD/_bin/cxx-$variant-sh/osh
261 popd
262
263 else
264 osh=_bin/cxx-$variant/osh
265 ninja $osh
266 fi
267
268 # So we can find it
269 export OSH=$osh
270 log "Exported OSH=$OSH"
271}
272
273# Used by {mycpp,cpp}/TEST.sh
274can-compile-32-bit() {
275 # Try compiling a basic file
276 c++ -m32 -o /dev/null build/detect-cc.c
277}
278
279