1 #!/usr/bin/ksh
2 #
3 #
4 # This file and its contents are supplied under the terms of the
5 # Common Development and Distribution License ("CDDL"), version 1.0.
6 # You may only use this file in accordance with the terms of version
7 # 1.0 of the CDDL.
8 #
9 # A full copy of the text of the CDDL should have accompanied this
10 # source. A copy of the CDDL is also available via the Internet at
11 # http://www.illumos.org/license/CDDL.
12 #
13
14 #
15 # Copyright (c) 2019, Joyent, Inc.
16 #
17
18 #
19 # Run all of the various CTF tests
20 #
21
22 unalias -a
23 #set -o xtrace
24
25 if [[ -z "$TMPDIR" ]]; then
26 TMPDIR="/tmp"
27 fi
28
29 ctf_arg0=$(basename $0)
30 ctf_root=$(cd $(dirname $0) && echo $PWD)
31 ctf_tests=
32 ctf_compiler="gcc"
33 ctf_convert="ctfconvert"
34 ctf_merge="ctfmerge"
35 ctf_debugflags="-gdwarf-2 "
36 ctf_mach32="-m32"
37 ctf_mach64="-m64"
38 ctf_32cflags="$ctf_mach32 $ctf_debugflags"
39 ctf_64cflags="$ctf_mach64 $ctf_debugflags"
40 ctf_temp="$TMPDIR/ctftest.$$.o"
41 ctf_makefile="Makefile.ctftest"
42 ctf_nerrs=0
43
44 usage()
45 {
46 typeset msg="$*"
47 [[ -z "$msg" ]] || echo "$msg" >&2
48 cat <<USAGE >&2
49 Usage: $ctf_arg0 [-c compiler] [-g flags] [-m ctfmerge] [-t ctfconvert]
50
51 Runs the CTF test suite
52
53 -c compiler Use the specified compiler, defaults to 'gcc'
54 on path.
55 -g flags Use flags to generate debug info. Defaults to
56 "-gdwarf-2".
57 -m ctfmerge Use the specified ctfmerge, defaults to
58 'ctfmerge' on path.
59 -t ctfconvert Use the specified ctfconvert, defaults to
60 'ctfconvert' on path.
61 USAGE
62 exit 2
63 }
64
65
66 test_fail()
67 {
68 typeset msg="$*"
69 [[ -z "$msg" ]] && msg="failed"
70 echo "TEST FAILED: $msg" >&2
71 ((ctf_nerrs++))
72 }
73
74 fatal()
75 {
76 typeset msg="$*"
77 [[ -z "$msg" ]] && msg="failed"
78 echo "$ctf_arg0: $msg" >&2
79 rm -f "$ctf_tmp32" "$ctf_temp64"
80 exit 1
81 }
82
83 check_env()
84 {
85 if which "$1" 2>/dev/null >/dev/null; then
86 return
87 fi
88
89 [[ -f "$1" ]] || fatal "failed to find tool $1"
90 }
91
92 announce()
93 {
94 cat << EOF
95 Beginning CTF tests with the following settings:
96 COMPILER: $(which $ctf_compiler)
97 CTFCONVERT: $(which $ctf_convert)
98 CTFMERGE: $(which $ctf_merge)
99 32-bit CFLAGS: $ctf_32cflags
100 64-bit CFLAGS: $ctf_64cflags
101
102 EOF
103 }
104
105 run_one()
106 {
107 typeset source=$1 checker=$2 flags=$3
108
109 if ! "$ctf_compiler" $flags -o "$ctf_temp" -c "$source"; then
110 test_fail "failed to compile $source with flags: $flags"
111 return
112 fi
113
114 if ! "$ctf_convert" "$ctf_temp"; then
115 test_fail "failed to convert CTF in $source"
116 return
117 fi
118
119 if ! "$checker" "$ctf_temp"; then
120 test_fail "check for $source, $checker, failed"
121 return
122 fi
123
124 echo "TEST PASSED: $source $flags"
125 }
126
127 #
128 # Perform a more complex build. The Makefile present will drive the
129 # building of the artifacts and the running of the tests based on the
130 # variables that we pass to it.
131 #
132 run_dir()
133 {
134 typeset dir outdir check32 check64 flags32 flags64
135
136 dir=$1
137 outdir="$TMPDIR/ctftest.$$-$(basename $d)"
138 check32=$2
139 flags32=$3
140 check64=$4
141 flags64=$5
142
143 if ! mkdir $outdir; then
144 fatal "failed to make temporary directory '$outdir'"
145 fi
146
147 if ! make -C $dir -f Makefile.ctftest \
148 BUILDDIR="$outdir" \
149 CC="$ctf_compiler" \
150 CFLAGS32="$ctf_mach32" \
151 CFLAGS64="$ctf_mach64" \
152 DEBUGFLAGS="$ctf_debugflags" \
153 CTFCONVERT="$ctf_convert" \
154 CTFMERGE="$ctf_merge" \
155 build 1>/dev/null; then
156 rm -rf $outdir
157 test_fail "failed to build $dir"
158 return
159 fi
160
161 if ! make -C $dir -f Makefile.ctftest \
162 BUILDDIR="$outdir" \
163 CHECK32="$check32" \
164 CHECK64="$check64" \
165 run-test 1>/dev/null; then
166 rm -rf $outdir
167 test_fail "failed to run tests for $dir"
168 return
169 fi
170
171 rm -rf $outdir
172 echo "TEST PASSED: $dir (dir)"
173 }
174
175 #
176 # Find all of the tests that exist and then try to run them all. Tests
177 # may either be a single file or a directory.
178 #
179 run_tests()
180 {
181 typeset t base check
182 ctf_tests=$(ls "$ctf_root"/*.c)
183 for t in $ctf_tests; do
184 base=$(basename "$t" .c)
185 check=$(echo "$base" | sed s/test-/check-/)
186 if [[ -f "$ctf_root/$check" ]]; then
187 run_one $t "$ctf_root/$check" "$ctf_32cflags"
188 run_one $t "$ctf_root/$check" "$ctf_64cflags"
189 elif [[ -f "$ctf_root/$check-32" && \
190 -f "$ctf_root/$check-64" ]]; then
191 run_one $t "$ctf_root/$check-32" "$ctf_32cflags"
192 run_one $t "$ctf_root/$check-64" "$ctf_64cflags"
193 else
194 test_fail "missing checker for $t"
195 fi
196 done
197
198 for d in $(find "$ctf_root" -maxdepth 1 -type d -name 'test-*'); do
199 [[ ! -f "$d/$ctf_makefile" ]] && continue
200 base=$(basename "$d")
201 check=$(echo "$base" | sed s/test-/check-/)
202 if [[ -f "$ctf_root/$check" ]]; then
203 run_dir $d "$ctf_root/$check" "$ctf_32cflags" \
204 "$ctf_root/$check" "$ctf_64cflags"
205 elif [[ -f "$ctf_root/$check-32" && \
206 -f "$ctf_root/$check-64" ]]; then
207 run_dir $d "$ctf_root/$check-32" "$ctf_32cflags" \
208 "$ctf_root/$check-64" "$ctf_64cflags"
209 else
210 test_fail "missing checker for $t"
211 fi
212 done
213 }
214
215 while getopts ":c:g:m:t:" c $@; do
216 case "$c" in
217 c)
218 ctf_compiler=$OPTARG
219 ;;
220 g)
221 ctf_debugflags=$OPTARG
222 ;;
223 m)
224 ctf_merge=$OPTARG
225 ;;
226 t)
227 ctf_convert=$OPTARG
228 ;;
229 :)
230 usage "option requires an argument -- $OPTARG"
231 ;;
232 *)
233 usage "invalid option -- $OPTARG"
234 ;;
235 esac
236 done
237
238 ctf_32cflags="$ctf_mach32 $ctf_debugflags"
239 ctf_64cflags="$ctf_mach64 $ctf_debugflags"
240
241 check_env "$ctf_compiler"
242 check_env "$ctf_convert"
243 check_env "$ctf_merge"
244 announce
245
246 run_tests
247
248 if [[ $ctf_nerrs -ne 0 ]]; then
249 if [[ $ctf_nerrs -eq 1 ]]; then
250 printf "\n%s: %u test failed\n" "$ctf_arg0" "$ctf_nerrs"
251 else
252 printf "\n%s: %u tests failed\n" "$ctf_arg0" "$ctf_nerrs"
253 fi
254 else
255 printf "\n%s: All tests passed successfully\n" "$ctf_arg0"
256 exit 0
257 fi