Blob


1 #!/bin/sh
3 set -e
5 ggflags=
7 # usage: config <global config> <stuff for localhost>
8 # generates a configuration file reg.conf
9 config() {
10 cat <<EOF > reg.conf
11 ipv6 off
12 port 10965
13 $1
14 server "localhost" {
15 cert "$PWD/cert.pem"
16 key "$PWD/key.pem"
17 root "$PWD/testdata"
18 $2
19 }
20 EOF
21 }
23 checkconf() {
24 ./../gmid -n -c reg.conf
25 }
27 # usage: get <path>
28 # return the body of the request on stdout
29 get() {
30 ./../gg -b $ggflags "gemini://localhost:10965/$1"
31 }
33 # usage: head <path>
34 # return the meta response line on stdout
35 head() {
36 ./../gg -h $ggflags "gemini://localhost:10965/$1"
37 }
39 # usage: raw <path>
40 # return both header and body
41 raw() {
42 ./../gg $ggflags "gemini://localhost:10965/$1"
43 }
45 run() {
46 # filter out logs for GET requests
47 (./../gmid -f -c reg.conf 2>&1 | grep -v GET) >&2 &
48 pid=$!
49 # give gmid time to bind the port, otherwise we end up
50 # executing gg when gmid isn't ready yet.
51 sleep 1
52 }
54 # usage: check [exit-message]
55 # check if gmid is still running
56 check() {
57 if ! ps $pid >/dev/null; then
58 echo ${1:-"gmid crashed?"}
59 exit 1
60 fi
61 }
63 restart() {
64 pkill -SIGHUP gmid
65 sleep 1
66 }
68 # quit gmid
69 quit() {
70 pkill gmid || true
71 wait || true
72 }
74 count() {
75 wc -l | xargs
76 }
78 # usage: eq a b errmsg
79 # if a and b aren't equal strings, exit with errmsg
80 eq() {
81 if ! [ "$1" = "$2" ]; then
82 echo "$3: \"$1\" not equal \"$2\""
83 exit 1
84 fi
85 }
87 onexit() {
88 rm -f bigfile bigfile.sha
89 quit
90 }
92 # tests
94 trap 'onexit' INT TERM EXIT
96 endl=`printf "\r\n"`
97 lf=`echo`
99 config "" ""
100 checkconf
101 run
103 eq "$(head /)" "20 text/gemini" "Unexpected head for /"
104 eq "$(get /)" "# hello world$ln" "Unexpected body for /"
105 echo OK GET /
107 eq "$(head /foo)" "51 not found" "Unexpected head /foo"
108 eq "$(get /foo)" "" "Unexpected body /foo"
109 echo OK GET /foo
111 # should redirect if asked for a directory but without the trailing /
112 eq "$(head /dir)" "30 /dir/" "Unexpected redirect for /dir"
113 eq "$(get /dir)" "" "Unexpected body for redirect"
114 echo OK GET /dir
116 # 51 for a directory without index.gmi
117 eq "$(head /dir/)" "51 not found" "Unexpected head for /"
118 eq "$(get /dir/)" "" "Unexpected body for error"
119 echo OK GET /dir/
121 eq "$(head /dir/foo.gmi)" "20 text/gemini" "Unexpected head for /dir/foo.gmi"
122 eq "$(get /dir/foo.gmi)" "# hello world$ln" "Unexpected body for /dir/foo.gmi"
123 echo OK GET /dir/foo.gmi
125 # try a big file
126 eq "$(head /bigfile)" "20 application/octet-stream" "Unexpected head for /bigfile"
127 get /bigfile > bigfile
128 ./sha bigfile bigfile.sha
129 eq "$(cat bigfile.sha)" "$(cat testdata/bigfile.sha)" "Unexpected sha for /bigfile"
130 echo OK GET /bigfile
132 # shouldn't be executing cgi scripts
133 eq "$(head /hello)" "20 application/octet-stream" "Unexpected head for /hello"
134 echo OK GET /hello
136 check "should be running"
138 # try with custom mime
139 config 'mime "text/x-funny-text" "gmi"' 'default type "application/x-trash"'
140 checkconf
141 restart
143 eq "$(head /)" "20 text/x-funny-text" "Unexpected head for /"
144 echo OK GET / with custom mime
146 eq "$(head /hello)" "20 application/x-trash" "Unexpected head for /hello"
147 echo OK GET /hello with custom mime
149 check "should be running"
151 # try with custom lang
152 config '' 'lang "it"'
153 checkconf
154 restart
156 eq "$(head /)" "20 text/gemini; lang=it" "Unexpected head for /"
157 echo OK GET / with custom lang
159 check "should be running"
161 # try with CGI scripts
162 config '' 'cgi "*"'
163 checkconf
164 restart
166 eq "$(head /hello)" "20 text/gemini" "Unexpected head for /hello"
167 eq "$(get /hello)" "# hello world$ln" "Unexpected body for /hello"
168 echo OK GET /hello with cgi
170 eq "$(head /slow)" "20 text/gemini" "Unexpected head for /slow"
171 eq "$(get /slow)" "# hello world$ln" "Unexpected body for /slow"
172 echo OK GET /slow with cgi
174 eq "$(head /err)" "42 CGI error" "Unexpected head for /err"
175 eq "$(get /err)" "" "Unexpected body for /err"
176 echo OK GET /err with cgi
178 eq "$(raw /invalid | wc -c | xargs)" 2048 "Unexpected body for /invalid"
179 echo OK GET /invalid with cgi
181 # try a big file
182 eq "$(head /serve-bigfile)" "20 application/octet-stream" "Unexpected head for /serve-bigfile"
183 get /bigfile > bigfile
184 ./sha bigfile bigfile.sha
185 eq "$(cat bigfile.sha)" "$(cat testdata/bigfile.sha)" "Unexpected sha for /serve-bigfile"
186 echo OK GET /serve-bigfile with cgi
188 # ensure we split the query correctly
189 eq "$(get /env | awk /^-/ | count)" 1 "Unexpected number of arguments"
190 eq "$(get /env?foo | awk /^-/ | count)" 2 "Unexpected number of arguments"
191 eq "$(get /env?foo+bar | awk /^-/ | count)" 3 "Unexpected number of arguments"
192 eq "$(get /env?foo+bar=5 | awk /^-/ | count)" 1 "Unexpected number of arguments"
193 eq "$(get /env?foo+bar%3d5 | awk /^-/ | count)" 3 "Unexpected number of arguments"
195 check "should be running"
197 config '' 'index "foo.gmi"'
198 checkconf
199 restart
201 eq "$(head /dir/)" "20 text/gemini" "Unexpected head for /"
202 eq "$(get /dir/)" "# hello world$ln" "Unexpected body for error"
203 echo OK GET /dir/ with custom index
205 check "should be running"
207 config '' 'location "/dir/" { default type "text/plain" index "hello" }'
208 checkconf
209 restart
211 eq "$(head /dir/hello)" "20 text/plain" "Unexpected head for /"
212 echo OK GET /dir/hello with location and default type
214 eq "$(head /dir/)" "20 text/plain" "Unexpected head for /dir/"
215 eq "$(get /dir/|tail -1)" 'echo "# hello world"' "Unexpected body for /dir/"
216 echo OK GET /dir/ with location and custom index
218 check "should be running"
220 config '' 'location "/dir/" { auto index on }'
221 checkconf
222 restart
224 eq "$(head /)" "20 text/gemini" "Unexpected head for /"
225 eq "$(get /)" "# hello world$ln" "Unexpected body for /"
226 echo OK GET / with auto index
228 eq "$(head /dir)" "30 /dir/" "Unexpected head for /dir"
229 eq "$(head /dir/)" "20 text/gemini" "Unexpected head for /dir/"
230 eq "$(get /dir/|wc -l|xargs)" "5" "Unexpected body for /dir/"
231 echo OK GET /dir/ with auto index on
233 check "should be running"
235 # test block return and strip
237 config '' 'location "*" { block }'
238 checkconf
239 restart
241 eq "$(head /)" "40 temporary failure" "Unexpected head for /"
242 eq "$(get /)" "" "Unexpected body for /"
243 echo OK GET / with block
245 eq "$(head /nonexists)" "40 temporary failure" "Unexpected head for /nonexists"
246 eq "$(get /nonexists)" "" "Unexpected body for /nonexists"
247 echo OK GET /nonexists with block
249 check "should be running"
251 config '' '
252 location "/dir" {
253 strip 1
254 block return 40 "%% %p %q %P %N test"
256 location "*" {
257 strip 99
258 block return 40 "%% %p %q %P %N test"
259 }'
260 checkconf
261 restart
263 eq "$(head /dir/foo.gmi)" "40 % /foo.gmi 10965 localhost test"
264 echo OK GET /dir/foo.gmi with strip and block
266 eq "$(head /bigfile)" "40 % 10965 localhost test"
267 echo OK GET /bigfile with strip and block
269 check "should be running"
271 # test the entrypoint
273 config '' 'entrypoint "/env"'
274 checkconf
275 restart
277 eq "$(head /foo/bar)" "20 text/plain; lang=en" "Unknown head for /foo/bar"
278 eq "$(get /foo/bar|grep PATH_INFO)" "PATH_INFO=/foo/bar" "Unexpected PATH_INFO"
279 echo OK GET /foo/bar with entrypoint
281 # test with require ca
283 config '' 'require client ca "'$PWD'/testca.pem"'
284 checkconf
285 restart
287 eq "$(head /)" "60 client certificate required" "Unexpected head for /"
288 echo OK GET / without client certificate
290 ggflags="-C valid.crt -K valid.key"
291 eq "$(head /)" "20 text/gemini" "Unexpected head for /"
292 echo OK GET / with valid client certificate
294 ggflags="-C invalid.cert.pem -K invalid.key.pem"
295 eq "$(head /)" "61 certificate not authorised" "Unexpected head for /"
296 echo OK GET / with invalid client certificate
298 ggflags=''
300 quit