]> granicus.if.org Git - re2c/blob - run_tests.sh.in
Renamed misleadingly named parameter.
[re2c] / run_tests.sh.in
1 #!/usr/bin/env bash
2
3 # somewhat portable way to detect CPU count
4 detect_cpu_count () {
5     if [ "$CPUS" = "" ]; then
6         # Windows standard environment variable
7         CPUS="$NUMBER_OF_PROCESSORS"
8     fi
9     if [ "$CPUS" = "" ]; then
10         # Linux
11         CPUS=`getconf _NPROCESSORS_ONLN 2>/dev/null`
12     fi
13     if [ "$CPUS" = "" ]; then
14         # FreeBSD
15         CPUS=`getconf NPROCESSORS_ONLN 2>/dev/null`
16     fi
17     if [ "$CPUS" = "" ]; then
18         # nothing helped
19         CPUS="1"
20     fi
21 }
22
23 lc_run() {
24     LANG=C LC_ALL=C "$@"
25 }
26
27 re2c="./re2c"
28 diff_prog="diff"
29 valgrind=""
30 skeleton=0
31 keep_tmp_files=0
32 wine=""
33 threads=`detect_cpu_count; echo $CPUS`
34 tests=()
35 for arg in $*
36 do
37     case $arg in
38         "--valgrind" ) valgrind=`which valgrind` ;;
39         "--skeleton" ) skeleton=1 ;;
40         "--keep-tmp-files" ) keep_tmp_files=1 ;;
41         "--wine" )
42             wine=`which wine`
43             re2c="${re2c}.exe"
44             diff_prog="${diff_prog} -b" # ignore whitespace at the end of line
45             ;;
46         "-j"* )
47             number=${arg#-j}
48             number_pattern='^[0-9]+$'
49             if [[ $number =~ $number_pattern ]]
50             then
51                 threads=$number
52             fi
53             ;;
54         * ) tests[${#tests[@]}]="$arg" ;; # array is continuous (old bash lacks +=)
55     esac
56 done
57 echo "Running in ${threads} thread(s)"
58
59 if test ! -x "${re2c}"; then
60     echo "Cannot find re2c executable (${re2c})."
61     exit 1
62 fi
63
64 test_blddir="test_"`date +%y%m%d%H%M%S`
65 rm -rf $test_blddir && mkdir $test_blddir
66
67 # preserve directory structure unless given explicit args
68 if [ ${#tests[@]} -eq 0 ]; then
69     cp -R "@top_srcdir@/test/"* "@top_srcdir@/examples/"*  $test_blddir
70 else
71     for f in ${tests[@]}; do
72         cp $f ${f%.re}.c $test_blddir
73     done
74 fi
75
76 chmod -R u+w $test_blddir
77
78 find $test_blddir -type f \
79     ! -name '*.re' -a \
80     ! -name '*.c' -a \
81     ! -name '*.inc' \
82     -exec rm {} \;
83
84 # if not a debug build, remove all debug subdirs
85 $re2c --version | grep -q "debug" \
86     || find "$test_blddir" -type d -name debug | xargs rm -rf
87
88 tests=(`find $test_blddir -name '*.re' | sort`)
89
90 # set include paths, relative to build directory
91 cd $test_blddir \
92     && incpaths=$(find * -type d -exec echo "-I ../{}" \;) \
93     && cd ..
94
95 tests_per_thread=$((${#tests[@]} / threads + 1))
96 packs=()
97 for ((i = 0; i < threads; i++))
98 do
99     j=$((i * tests_per_thread))
100     packs[$i]=${tests[@]:j:tests_per_thread}
101 done
102
103 if test -n "${valgrind}"
104 then
105     valgrind_options=(
106         "-q"
107         "--track-origins=yes"
108         "--num-callers=50"
109         "--leak-check=full"
110         "--show-reachable=yes"
111         "--malloc-fill=0xa1"
112         "--free-fill=0xa1"
113         )
114     valgrind="${valgrind} ${valgrind_options[@]}"
115     echo $valgrind
116 fi
117
118 run_pack() {
119     local log="$1"
120     shift 1
121
122     local errcnt=0
123     for x in $*
124     do
125         cd $test_blddir
126
127         # remove prefix
128         local outx=${x:$((${#test_blddir} + 1))}
129         local outc="${outx%.re}.c"
130
131         # filename (dot short* (long arg?)*)? ext
132         # must keep to POSIX standard: no syntactic sugar like +,?, etc.
133         # if you change this regexp, try it with 'sed --posix'
134         local switches=`basename "$x" | lc_run sed \
135             -e 's/^[^.]*\.re$//g' \
136             -e 's/^[^.]*\.\(.*\)\.re$/\1/g' \
137             -e 's/^\([^-]\)/-\1/' \
138             -e 's/--\([^ (-]*\)/ --\1/g' \
139             -e 's/(\([^)]*\))/ \1/g'`
140         # check that flags do not contain uppercase letters:
141         # file extensions are case-insensitive on some platforms
142         printf "%s" "$switches" | lc_run grep -q "[A-Z]" \
143             && { echo "bad file extension: '$outx' (uppercase letters are not allowed)"; exit 1; }
144         local switches="$switches -o $outc --no-version --no-generation-date"
145         # enable warnings globally
146         local switches="$switches -W"
147
148         if [ $skeleton -eq 1 ]
149         then
150             rm -f "$outc"
151
152             local switches="$switches --skeleton -Werror-undefined-control-flow"
153
154             ${valgrind} ${wine} ../${re2c} $incpaths $switches "../$x" 2>"$outc.stderr"
155             local status=$(echo $?)
156             [ $status -eq 0 ] && { @CC@ -Wall -Wextra -o "$outc.out" "$outc" 2>>"$outc.stderr" || status=2; }
157             [ $status -eq 0 ] && { ./"$outc.out" 2>>"$outc.stderr" || status=3; }
158
159             case $status in
160                 0 ) local msg="OK" ;;
161                 1 ) local msg="OK (expected re2c error)" ;;
162                 2 ) local msg="FAIL (compilation error)" ;;
163                 3 ) local msg="FAIL (runtime error)" ;;
164                 * ) local msg="FAIL (unknown error)" ;;
165             esac
166             printf "%-25s $outx\n" "$msg"
167
168             if [ $status -le 1 ]; then
169                 [ $keep_tmp_files -eq 0 ] && rm -f "$outx" "$outc"{,.line*.{input,keys},.stderr,.out}
170             else
171                 local errcnt=$(($errcnt + 1))
172             fi
173         else
174             local c="${outx%.re}.c.orig"
175             mv "$outc" "$c"
176
177             # create sandbox
178             tmpdir="tmp_$log" \
179                 && mkdir "$tmpdir" \
180                 && cd "$tmpdir" \
181                 && mkdir -p `dirname "$outx"` \
182                 && cp "../../$x" "$outx"
183             # run re2c
184             $valgrind $wine ../../$re2c $incpaths $switches "$outx" 2>"$outc.stderr" 1>&2
185             # on windows output contains CR LF, cut CR to match test results
186             for f in "$outc" "$outc.stderr"; do
187                 [ -f "$f" ] \
188                     && cat "$f" | lc_run tr -d '\r' > "$f".mod \
189                     && mv "$f".mod "$f"
190             done
191             # paste all files dropped by re2c into output file
192             rm "$outx" && find . -type f \
193                 | lc_run sort \
194                 | xargs cat \
195                 >> "../$outc"
196             # cleanup sandbox
197             cd .. \
198                 && rm -rf "$tmpdir"
199
200             # compare results
201             local status=""
202             [ -z $status ] && status=`[ -f "$c" ] || echo "MISSING"`
203             [ -z $status ] && status=`$diff_prog "$c" "$outc" > "$outc.diff" || echo "FAIL"`
204             [ -z $status ] && status="OK"
205             if [ $status = "OK" ]
206             then
207                 rm "$outc" "$outc.diff" "$c" "$outx"
208             else
209                 local errcnt=$(($errcnt + 1))
210             fi
211
212             printf "%-10s $outx\n" "$status"
213         fi
214         cd ..
215     done
216     echo $errcnt > $log
217 }
218
219 cleanup() {
220     rm -f ${logs[@]}
221     kill ${wait_pids[@]}
222     wait ${wait_pids[@]}
223     printf "\nEh...\n"
224     exit 1
225 }
226
227 logs=()
228 wait_pids=()
229 trap cleanup INT
230 for ((i = 0; i < ${#packs[@]}; i++))
231 do
232     logs[$i]=`date +%y%m%d%H%M%S`_$i
233     run_pack ${logs[i]} ${packs[i]} &
234     wait_pids[${#wait_pids[@]}]=$! # array is continuous (old bash lacks +=)
235 done
236 wait ${wait_pids[@]}
237
238 errors=0
239 for ((i = 0; i < ${#logs[@]}; i++))
240 do
241     error=`cat ${logs[i]}`
242     errors=$((errors + error))
243     rm -f ${logs[i]}
244 done
245
246 # remove directories that are empty or contain only .inc files
247 for d in $(find $test_blddir -depth -type d)
248 do
249     [ -z "$(find $d -type f ! -name '*.inc')" ] && rm -rf "$d"
250 done
251
252 if [ $errors -eq 0 ]
253 then
254     echo "All ${#tests[@]} tests passed successfully."
255     exit 0
256 else
257     echo "Error: $errors out ${#tests[@]} tests failed."
258     exit 1
259 fi