diff options
Diffstat (limited to 'yarns.webapp/900-implementations.yarn')
-rw-r--r-- | yarns.webapp/900-implementations.yarn | 119 |
1 files changed, 119 insertions, 0 deletions
diff --git a/yarns.webapp/900-implementations.yarn b/yarns.webapp/900-implementations.yarn new file mode 100644 index 0000000..7bfb6bb --- /dev/null +++ b/yarns.webapp/900-implementations.yarn @@ -0,0 +1,119 @@ +Implementations +=============== + +This chapter includes IMPLEMENTS sections for the various steps used +in scenarios. + +Managing a WEBAPP instance +-------------------------- + +We're testing a web application (convenivently named WEBAPP, though +the executable is `lorry-controller-webapp`), so we need to be able to +start it and stop it in scenarios. We start it as a background +process, and keep its PID in `$DATADIR/webapp.pid`. When it's time to +kill it, we kill the process with the PID in that file. This is not +perfect, though it's good enough for our purposes. It doesn't handle +running multiple instances at the same time, which we don't need, and +doens't handle the case of the process dying and the kernel re-using +the PID for something else, which is quite unlikely. + +Start an instance of the WEBAPP, using a random port. Record the PID +and the port. Listen only on localhost. We use `start-stop-daemon` to +start the process, so that it can keep running in the background, +but the shell doesn't wait for it to terminate. This way, WEBAPP will +be running until it crashes or is explicitly killed. + + IMPLEMENTS GIVEN a running WEBAPP + # Pick a random port beyond 1024 (i.e., an unreserved one). + port=0 + while [ "$port" -le 1024 ] + do + port=$RANDOM + done + echo "$port" > "$DATADIR/webapp.port" + + start-stop-daemon -S -x "$SRCDIR/lorry-controller-webapp" \ + -b -p "$DATADIR/webapp.pid" -m --verbose \ + -- \ + --statedb "$DATADIR/webapp.db" \ + --log-level debug \ + --log "$DATADIR/webapp.log" \ + --debug-host 127.0.0.1 \ + --debug-port "$port" + + # Wait for the WEBAPP to actually be ready, i.e., that it's + # listening on its assigned port. + "$SRCDIR/test-wait-for-port" 127.0.0.1 "$port" + +Kill the running WEBAPP, using the recorded PID. We need to do this +both as a WHEN and a FINALLY step. + + IMPLEMENTS WHEN WEBAPP is terminated + kill_daemon_using_pid_file "$DATADIR/webapp.pid" + + IMPLEMENTS FINALLY WEBAPP terminates + kill_daemon_using_pid_file "$DATADIR/webapp.pid" + +Also test that WEBAPP isn't running. + + IMPLEMENTS THEN WEBAPP isn't running + pid=$(head -n1 "$DATADIR/webapp.pid") + if kill -0 "$pid" + then + echo "process $pid is still running, but should'nt be" 1>&2 + exit 1 + fi + +Making and analysing GET requests +--------------------------------- + +Simple HTTP GET requests are simple. We make the request, and capture +the response: HTTP status code, response headers, response body. + +We make the request using the `curl` command line program, which makes +capturing the response quite convenient. + +HTTP requests can be made by various entities. For now, we assume +they're all made by the admin. + +We check that the HTTP status indicates success, so that every +scenario doesn't need ot check that separately. + + IMPLEMENTS WHEN admin makes request GET (\S+) + rm -f "$DATADIR/response.headers" + rm -f "$DATADIR/response.body" + port=$(cat "$DATADIR/webapp.port") + curl \ + -D "$DATADIR/response.headers" \ + -o "$DATADIR/response.body" \ + --silent --show-error \ + "http://127.0.0.1:$port$MATCH_1" + cat "$DATADIR/response.headers" + cat "$DATADIR/response.body" + head -n1 "$DATADIR/response.headers" | grep '^HTTP/1\.[01] 200 ' + +Check the Content-Type of the response is JSON. + + IMPLEMENTS THEN response is JSON + cat "$DATADIR/response.headers" + grep -i '^Content-Type: application/json' "$DATADIR/response.headers" + +A JSON response can then be queried further. The JSON is expected to +be a dict, so that values are accessed by name from the dict. The +value is expresssed as a Python value in the step. + + IMPLEMENTS THEN response has (\S+) set to (\S+) + cat "$DATADIR/response.body" + python -c " + import json, os, sys + data = json.load(sys.stdin) + key = os.environ['MATCH_1'] + expected = eval(os.environ['MATCH_2']) # I feel dirty and evil. + value = data[key] + if value != expected: + sys.stderr.write( + 'Key {key} has value {value}, but ' + '{expected} was expected'.format( + key=key, value=value, expected=expected)) + sys.exit(1) + " < "$DATADIR/response.body" |