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

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