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

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