run-tests: try to use the default gcc and clang.
[darkhttpd] / devel / run-tests
1 #!/bin/bash
2 #
3 # Build a coverage-enabled darkhttpd, run unit tests and calculate coverage.
4 #
5 cd $(dirname $0)
6 declare -r DIR=tmp.httpd.tests
7 declare -r PORT=12346
8
9 if [ ! -e test.py ]; then
10         echo "fatal: can't find test.py. are you in the right directory?" >&2
11         exit 1
12 fi
13 if [[ -z "$CC" ]]; then
14   CC="$(which gcc)"
15 fi
16 if [[ -z "$CLANG" ]]; then
17   CLANG="$(which clang)"
18 fi
19
20 runtests() {
21   if [ -e $DIR ]; then
22     rm -rf $DIR || exit 1
23   fi
24   mkdir $DIR || exit 1
25   mkdir $DIR/forbidden || exit 1
26   chmod 0 $DIR/forbidden || exit 1
27   mkdir $DIR/unreadable || exit 1
28   chmod 0100 $DIR/unreadable || exit 1
29   rm -f darkhttpd.gcda test.out.log test.out.stdout test.out.stderr
30
31   echo "===> run usage statement"
32   # Early exit if we can't even survive usage.
33   ./a.out >/dev/null 2>>test.out.stderr || exit 1
34
35   echo "===> run tests against a basic instance (generates darkhttpd.gcda)"
36   ./a.out $DIR --port $PORT --log test.out.log \
37     >>test.out.stdout 2>>test.out.stderr &
38   PID=$!
39   kill -0 $PID || exit 1
40   python test.py
41   kill $PID
42   wait $PID
43
44   echo "===> run --forward tests"
45   ./a.out $DIR --port $PORT \
46     --forward example.com http://www.example.com \
47     --forward secure.example.com https://www.example.com/secure \
48     >>test.out.stdout 2>>test.out.stderr &
49   PID=$!
50   kill -0 $PID || exit 1
51   python test_forward.py
52   kill $PID
53   wait $PID
54
55   echo "===> run --forward-all tests"
56   ./a.out $DIR --port $PORT \
57     --forward example.com http://www.example.com \
58     --forward-all http://catchall.example.com \
59     >>test.out.stdout 2>>test.out.stderr &
60   PID=$!
61   kill -0 $PID || exit 1
62   python test_forward_all.py
63   kill $PID
64   wait $PID
65
66   echo "===> run --no-server-id tests"
67   ./a.out $DIR --port $PORT --no-server-id \
68     >>test.out.stdout 2>>test.out.stderr &
69   PID=$!
70   kill -0 $PID || exit 1
71   python test_server_id.py
72   kill $PID
73   wait $PID
74
75   echo "===> run mimemap tests"
76   echo "test/type1 a1" > $DIR/mimemap
77   echo "test/this-gets-replaced  ap2" >> $DIR/mimemap
78   echo "# this is a comment" >> $DIR/mimemap
79   printf "test/type3\\tapp3\r\n" >> $DIR/mimemap
80   echo "test/type2  ap2" >> $DIR/mimemap
81   ./a.out $DIR --port $PORT \
82     --mimetypes $DIR/mimemap \
83     --default-mimetype test/default \
84     >>test.out.stdout 2>>test.out.stderr &
85   PID=$!
86   kill -0 $PID || exit 1
87   python test_mimemap.py
88   kill $PID
89   wait $PID
90
91   echo "===> run --no-listing tests"
92   ./a.out $DIR --port $PORT --no-listing \
93     >>test.out.stdout 2>>test.out.stderr &
94   PID=$!
95   kill -0 $PID || exit 1
96   python test_no_listing.py
97   kill $PID
98   wait $PID
99
100   if [[ -s test.out.stderr ]]; then
101     echo "FAIL: stderr should have been empty."
102     exit 1
103   fi
104 }
105
106 # --- main ---
107
108 # Unit test.
109 echo "===> test_make_safe_uri"
110 $CC -g -O2 -fsanitize=address -fsanitize=undefined \
111   test_make_safe_uri.c -o test_make_safe_uri || exit 1
112 if ./test_make_safe_uri | egrep '^FAIL:'; then
113   echo test_make_safe_uri failed >&2
114   exit 1
115 fi
116
117 # Check that the code builds with various defines.
118 echo "===> building without -DDEBUG"
119 $CC -O2 -Wall ../darkhttpd.c || exit 1
120 echo "===> building with -DNO_IPV6"
121 $CC -O2 -Wall -DNO_IPV6 ../darkhttpd.c || exit 1
122
123 # Do coverage and sanitizers.
124 # -fsanitize=undefined produces stderr.
125 # -fsanitize=address produces stderr and crashes.
126 # -fsanitize=memory produces stderr and crashes.
127
128 # msan first.
129 if ! $CLANG -v 2>/dev/null; then
130   echo "***WARNING*** Can't find clang."
131   echo "Skipping memory sanitizer. Try setting the \$CLANG env var."
132 else
133   echo "===> building a.out for msan"
134   $CLANG -g -O2 -fsanitize=memory -DDEBUG -DAPBUF_INIT=1 \
135     ../darkhttpd.c || exit 1
136   (runtests) || {
137     echo "FAILED! stderr was:"
138     echo "---"
139     cat test.out.stderr
140     echo "---"
141     exit 1
142   }
143 fi
144
145 # asan and coverage next.
146 echo "===> building a.out and darkhttpd.gcno for coverage + asan + ubsan"
147 $CC -g -O2 -fprofile-arcs -ftest-coverage -fsanitize=address \
148   -fsanitize=undefined -DDEBUG -DAPBUF_INIT=1 ../darkhttpd.c || exit 1
149 (runtests) || {
150   echo "FAILED! stderr was:"
151   echo "---"
152   cat test.out.stderr
153   echo "---"
154   exit 1
155 }
156 echo "===> generating report"
157 gcov darkhttpd
158 rm -rf $DIR
159 rm -f darkhttpd.gcda darkhttpd.gcno a.out
160 echo "===> PASSED!"
161 echo "===> read the report: less darkhttpd.c.gcov"