#!/usr/bin/env bash set -eu -o pipefail ############################################################################# # Functions that implement steps. {{ functions }} ############################################################################# # Helper code generated by Subplot. # Simple dictionary abstraction. All values are stored in files so # they can more easily be inspected. dict_new() { local name="$1" rm -rf "$name" mkdir "$name" } dict_has() { local name="$1" local key="$2" local f="$name/$key" test -e "$f" } dict_get() { local name="$1" local key="$2" local f="$name/$key" cat "$f" } dict_get_default() { local name="$1" local key="$2" local default="$3" local f="$name/$key" if [ -e "$f" ] then cat "$f" else echo "$default" fi } dict_set() { local name="$1" local key="$2" local value="$3" local f="$name/$key" echo "$value" > "$f" } dict_keys() { local name="$1" ls -1 "$name" } # A context abstraction using dictionaries. ctx_new() { dict_new _ctx } ctx_set() { dict_set _ctx "$1" "$2" } ctx_get() { dict_get _ctx "$1" } # Store step captures for calling the corresponding functions. cap_new() { dict_new _cap } cap_set() { dict_set _cap "$1" "$2" } cap_get() { dict_get _cap "$1" } # Store files embedded in the markdown input. files_new() { dict_new _files } files_set() { dict_set _files "$1" "$2" } files_get() { dict_get _files "$1" } # Decode a base64 encoded string. decode_base64() { echo "$1" | base64 -d } # Check two values for equality and give error if they are not equal assert_eq() { if ! diff -u <(echo "$1") <(echo "$2") then echo "expected values to be identical, but they're not" exit 1 fi } # Check first value contains second value. assert_contains() { if ! echo "$1" | grep -F "$2" > /dev/null then echo "expected first value to contain second value" exit 1 fi } # Remember where we started from. The step functions may need to refer # to files there. srcdir="$(pwd)" echo "srcdir $srcdir" # Create a new temporary directory and chdir there. This allows step # functions to create new files in the current working directory # without having to be so careful. _datadir="$(mktemp -d)" echo "datadir $_datadir" cd "$_datadir" # Store test data files that were embedded in the source document. # Base64 encoding is used to allow arbitrary data. files_new {% for file in files %} # {{ file.filename }} filename="$(decode_base64 '{{ file.filename | base64 }}')" contents="$(decode_base64 '{{ file.contents | base64 }}')" files_set "$filename" "$contents" {% endfor %} ############################################################################# # Code to implement the scenarios. {% for scenario in scenarios %} ###################################### # Scenario: {{ scenario.title }} scenario_{{ loop.index }}() { local title scendir step name text ret cleanups steps declare -a cleanups declare -a steps title="$(decode_base64 '{{ scenario.title | base64 }}')" echo "scenario: $title" scendir="$(mktemp -d -p "$_datadir")" cd "$scendir" export HOME="$scendir" ctx_new cleanups[0]='' steps[0]='' ret=0 {% for step in scenario.steps %} if [ "$ret" = 0 ] then # Step: {{ step.text }} step="{{ step.kind | lower }} $(decode_base64 '{{ step.text | base64 }}')" echo " step: $step" cap_new {% for part in step.parts %}{% if part.CapturedText is defined -%} name="$(decode_base64 '{{ part.CapturedText.name | base64 }}')" text="$(decode_base64 '{{ part.CapturedText.text | base64 }}')" cap_set "$name" "$text" {% endif -%} {% endfor -%} if {{ step.function }} then cleanup='{{ step.cleanup }}' if [ "$cleanup" != "" ] then {% raw %} i=${#cleanups} cleanups[$i]="$cleanup" steps[$i]="$step" {% endraw %} fi else ret=$? fi fi {% endfor %} {% raw %} echo "${!cleanups[*]}" | tr ' ' '\n' | tac | while read i do step="${steps[$i]}" func="${cleanups[$i]}" echo " cleanup: $step" $func done {% endraw %} return $ret } {% endfor %} ############################################################################# # Make the environment minimal. unset $(env | sed 's/=.*//') export PATH=/bin:/usr/bin export SHELL=/bin/sh export HOME=/ # Will be set to datadir for each scenario. ############################################################################# # Run the scenarios. if [ "$#" = 0 ] then {% for scenario in scenarios %} scenario_{{ loop.index }}{% endfor %} else for pattern in "$@" do pattern="$(echo "$pattern" | tr A-Z a-z)" {% for scenario in scenarios %} if echo "{{ scenario.title | lower }}" | grep -F -e "$pattern" > /dev/null then scenario_{{ loop.index }} fi {% endfor %} done fi ############################################################################# # Clean up temporary directory and report success. rm -rf "$_datadir" echo "OK, all scenarios finished successfully"