Test library for Gitano ======================= When running tests under yarn, for each scenario, we are provided with a temporary working directory called `$DATADIR` which is a fresh directory for each scenario being run. Within that base, we can set up any number of fake SSH keys, a fake Gitano instance, fake users, and use them to make clones, do pushes etc. Nearly all of the implementations rely on a tool in the testing directory called `gitano-test-tool` the path to which is available as `$GTT`. For ease of testing, the fake user who gets to "own" the Gitano instance will be called `testinstance` and the keyset which they get to use in order to access the repository will be called `adminkey`. This is important when it comes to cloning, pushing, etc. General instance management --------------------------- IMPLEMENTS GIVEN a standard instance $GTT createunixuser testinstance $GTT createsshkey testinstance adminkey $GTT createsshkey testinstance bypasskey $GTT setupstandard testinstance adminkey bypasskey if [ "$GTT_PROTO" = http ]; then printf "%s" $($GTT getpasswd testinstance) | GTT_PROTO=ssh $GTT runcommand \ testinstance adminkey as admin passwd \ >> "$DATADIR/stdout" 2>> "$DATADIR/stderr" printf "%s" $($GTT getpasswd testinstance) | GTT_PROTO=ssh $GTT runcommand \ testinstance bypasskey as gitano-bypass passwd \ >> "$DATADIR/stdout" 2>> "$DATADIR/stderr" fi IMPLEMENTS FINALLY the instance is torn down $GTT teardownstandard Managing the fake unix users ---------------------------- The `gitano-test-tool` utility helps us manage fake UNIX users and give them SSH keys. Sometimes it's helpful to be able to work with these... IMPLEMENTS GIVEN a unix user called ([a-z][a-z0-9]*) $GTT createunixuser "$MATCH_1" IMPLEMENTS GIVEN ([a-z][a-z0-9]*) has keys called ([a-z][a-z0-9]*) $GTT createsshkey "$MATCH_1" "$MATCH_2" IMPLEMENTS GIVEN ([a-z][a-z0-9]*) has keys called ([a-z][a-z0-9]*) of type ([a-z][a-z0-9]*) $GTT createsshkey "$MATCH_1" "$MATCH_2" "$MATCH_3" IMPLEMENTS WHEN ([a-z][a-z0-9]*) uses their ssh public key called ([a-z][a-z0-9]*) as stdin cp "$DATADIR/user-home-$MATCH_1/.ssh/$MATCH_2.pub" "$DATADIR/stdin" A lot of tests need a user which isn't `gitano-admin` to work with, this GIVEN rolls up the creation of a unix user, allocation of an SSH key, and creation of the user inside Gitano. IMPLEMENTS GIVEN ([a-z][a-z0-9]*),? using ([a-z][a-z0-9_-]*),? adds a new user ([a-z][a-z0-9_-]*), with a key called ([a-z][a-z0-9_-]*) $GTT createunixuser "$MATCH_3" $GTT createsshkey "$MATCH_3" "$MATCH_4" $GTT runcommand "$MATCH_1" "$MATCH_2" \ user add "$MATCH_3" "$MATCH_3"@testinstance "$MATCH_3's real name" < "/dev/null" > "$DATADIR/stdout" 2> "$DATADIR/stderr" $GTT runcommand "$MATCH_1" "$MATCH_2" \ as "$MATCH_3" sshkey add default < \ "$($GTT pubkeyfilename "$MATCH_3" "$MATCH_4")" >> "$DATADIR/stdout" 2>> "$DATADIR/stderr" if [ "$GTT_PROTO" = http ]; then printf "%s" $($GTT getpasswd "$MATCH_3") | GTT_PROTO=ssh $GTT runcommand \ "$MATCH_1" "$MATCH_2" as "$MATCH_3" passwd \ >> "$DATADIR/stdout" 2>> "$DATADIR/stderr" fi Repository access ----------------- IMPLEMENTS WHEN ([a-z][a-z0-9]*),? using ([a-z][a-z0-9]*),? (expecting failure,? )?clones ([^ ]+) as ([^ ]+)( with depth (\d+))? if $GTT clone "$MATCH_1" "$MATCH_2" "$MATCH_4" "$MATCH_5" ${MATCH_6:+ --no-local --depth="$MATCH_7"} \ >"$DATADIR/stdout" 2>"$DATADIR/stderr"; then test "$MATCH_3" = "" fi IMPLEMENTS WHEN ([a-z][a-z0-9]*),? using ([a-z][a-z0-9]*),? (expecting failure,? )?(force.)?pushes ([^ ]+) to ([^ ]+) if $GTT push "$MATCH_1" "$MATCH_2" "$MATCH_5" "$MATCH_6" ${MATCH_4:+--force} \ >"$DATADIR/stdout" 2>"$DATADIR/stderr"; then test "$MATCH_3" = "" fi IMPLEMENTS WHEN ([a-z][a-z0-9]*),? using ([a-z][a-z0-9]*),? (expecting failure,? )?destroys ([^ ]+) using the (.+) token if $GTT runcommand "$MATCH_1" "$MATCH_2" \ destroy "$MATCH_4" "$(cat "$DATADIR/saved-tokens/$MATCH_5")" \ < /dev/null >"$DATADIR/stdout" 2>"$DATADIR/stderr"; then test "$MATCH_3" = "" fi Server-side repository checking for behind-the-scenes work ---------------------------------------------------------- IMPLEMENTS THEN server-side ([^ ]+) file ([^ ]+) contains (.+) cd "$($GTT serverlocation "$MATCH_1")" grep -q "$MATCH_3" "$MATCH_2" IMPLEMENTS THEN server-side ([^ ]+) file ([^ ]+) exists cd "$($GTT serverlocation "$MATCH_1")" test -e "$MATCH_2" IMPLEMENTS THEN server-side ([^ ]+) has identical refs to ([^ ]+) bash -c 'diff -u <(git ls-remote -ht "$($GTT serverlocation "$MATCH_1")" | sort -k2) <(git ls-remote -ht "$($GTT serverlocation "$MATCH_2")" | sort -k2)' IMPLEMENTS THEN server-side ([^ ]+) has no missing objects cd "$($GTT serverlocation "$MATCH_1")".git git fsck IMPLEMENTS WHEN server-side ([^ ]+) reads git object (.+) cd "$($GTT serverlocation "$MATCH_1")".git git cat-file -p "$MATCH_2" >"$DATADIR/stdout" 2>"$DATADIR/stderr" Clone manipulation ------------------ IMPLEMENTS THEN ([a-z][a-z0-9]*) has a clone of ([^ ]+) $GTT cloneexists "$MATCH_1" "$MATCH_2" IMPLEMENTS WHEN git pull happens in ([a-z][a-z0-9]*) ([^ ]+) $GTT rungit "$MATCH_1" "$MATCH_2" pull IMPLEMENTS THEN ([a-z][a-z0-9]*) ([^ ]+) has a file called (.+) cd "$($GTT clonelocation "$MATCH_1" "$MATCH_2")" test -r "$MATCH_3" IMPLEMENTS THEN ([a-z][a-z0-9]*) ([^ ]+) has no file called (.+) set -x cd "$($GTT clonelocation "$MATCH_1" "$MATCH_2")" if test -r "$MATCH_3"; then false; else true; fi IMPLEMENTS WHEN ([a-z][a-z0-9]*) ([a-z][a-z0-9]*) uses git archive to extract the tree of ([a-z][a-z0-9-]*) ([a-z][a-z0-9]*) to ([a-z][a-z0-9]*) mkdir -p "$DATADIR/$MATCH_5" $GTT gitarchive "$MATCH_1" "$MATCH_2" "$MATCH_3" "$MATCH_4" | tar -C "$DATADIR/$MATCH_5" -x rsync manipulation ------------------ IMPLEMENTS ASSUMING rsync is possible test "x$GTT_PROTO" = "xssh" IMPLEMENTS WHEN ([a-z][a-z0-9]*) ([a-z][a-z0-9]*) rsync'?s (.*) to (.*) rsync -I --rsh="$GTT rsh \"$MATCH_1\" \"$MATCH_2\"" "$DATADIR/$MATCH_3" "dummy:$MATCH_4/$MATCH_3" IMPLEMENTS WHEN ([a-z][a-z0-9]*) ([a-z][a-z0-9]*) rsync'?s (.*) from (.*) rsync -I --rsh="$GTT rsh \"$MATCH_1\" \"$MATCH_2\"" "dummy:$MATCH_4/$MATCH_3" "$DATADIR/$MATCH_3" Admin repo manipulation ----------------------- IMPLEMENTS WHEN ([a-z][a-z0-9]*),? using ([a-z][a-z0-9]*),? adds user ([a-z][a-z0-9]*),? using ([a-z][a-z0-9]*) ([a-z][a-z0-9]*) $GTT runcommand "$MATCH_1" "$MATCH_2" \ user add "$MATCH_3" "$MATCH_3"@testinstance "$MATCH_3's real name" < "/dev/null" > "$DATADIR/stdout" 2> "$DATADIR/stderr" $GTT runcommand "$MATCH_1" "$MATCH_2" \ as "$MATCH_3" sshkey add default < \ "$($GTT pubkeyfilename "$MATCH_4" "$MATCH_5")" >> "$DATADIR/stdout" 2>> "$DATADIR/stderr" if [ "$GTT_PROTO" = http ]; then printf "%s" $($GTT getpasswd "$MATCH_4") | GTT_PROTO=ssh $GTT runcommand \ "$MATCH_1" "$MATCH_2" as "$MATCH_3" passwd \ >> "$DATADIR/stdout" 2>> "$DATADIR/stderr" fi IMPLEMENTS WHEN ([a-z][a-z0-9]*),? using ([a-z][a-z0-9]*),? deletes user ([a-z][a-z0-9]*) TOKEN="$($GTT runcommand "$MATCH_1" "$MATCH_2" user del "$MATCH_3" 2>&1 < /dev/null | $GTT findtoken)" $GTT runcommand "$MATCH_1" "$MATCH_2" user del "$MATCH_3" $TOKEN "$DATADIR/stdout" 2>"$DATADIR/stderr" IMPLEMENTS GIVEN ([a-z][a-z0-9]*),? using ([a-z][a-z0-9]*),? has patched gitano-admin with (the reverse of )?([^ ]+) $GTT clone "$MATCH_1" "$MATCH_2" gitano-admin.git tmp-adminpatch \ >"$DATADIR/stdout" 2>"$DATADIR/stderr" if test "$MATCH_3" = ""; then $GTT rungit "$MATCH_1" tmp-adminpatch apply -v --cached - <"testing/admin-patches/$MATCH_4" \ >>"$DATADIR/stdout" 2>>"$DATADIR/stderr" else $GTT rungit "$MATCH_1" tmp-adminpatch apply -v --cached --reverse - <"testing/admin-patches/$MATCH_4" \ >>"$DATADIR/stdout" 2>>"$DATADIR/stderr" fi $GTT rungit "$MATCH_1" tmp-adminpatch diff --cached \ >>"$DATADIR/stdout" 2>>"$DATADIR/stderr" $GTT rungit "$MATCH_1" tmp-adminpatch commit --allow-empty -m "Apply $MATCH_4 rules change" \ >>"$DATADIR/stdout" 2>>"$DATADIR/stderr" $GTT rungit "$MATCH_1" tmp-adminpatch show HEAD \ >>"$DATADIR/stdout" 2>>"$DATADIR/stderr" $GTT push "$MATCH_1" "$MATCH_2" tmp-adminpatch gitano-admin.git \ >>"$DATADIR/stdout" 2>>"$DATADIR/stderr" rm -r "$($GTT clonelocation "$MATCH_1" tmp-adminpatch)" \ >>"$DATADIR/stdout" 2>>"$DATADIR/stderr" IMPLEMENTS WHEN ([a-z][a-z0-9]*),? using ([a-z][a-z0-9]*),? (expecting failure,? )?pushes an empty commit in ([^ ]+) $GTT rungit "$MATCH_1" "$MATCH_4" commit --allow-empty -m "Make an empty commit" if $GTT push "$MATCH_1" "$MATCH_2" "$MATCH_4" "$MATCH_4".git > "$DATADIR/stdout" 2>"$DATADIR/stderr"; then test "$MATCH_3" = "" fi IMPLEMENTS WHEN ([a-z][a-z0-9]*) (applies|reverts) ([^ ]+) in ([^ ]+) if test "$MATCH_2" = "applies"; then $GTT rungit "$MATCH_1" "$MATCH_4" apply --cached - <"testing/content-patches/$MATCH_3" \ >"$DATADIR/stdout" 2>"$DATADIR/stderr" else $GTT rungit "$MATCH_1" "$MATCH_4" apply --cached --reverse - <"testing/content-patches/$MATCH_3" \ >"$DATADIR/stdout" 2>"$DATADIR/stderr" fi $GTT rungit "$MATCH_1" "$MATCH_4" commit --allow-empty -m "Apply $MATCH_3 content change" \ >>"$DATADIR/stdout" 2>>"$DATADIR/stderr" IMPLEMENTS WHEN ([a-z][a-z0-9]*) amends ([^ ]+) with (.+) $GTT rungit "$MATCH_1" "$MATCH_2" commit --amend -m "$MATCH_3" Specific commands ----------------- IMPLEMENTS GIVEN ([a-z][a-z0-9]*) ([a-z][a-z0-9]*) has copied ([^ ]+) to ([^ ]+) $GTT runcommand "$MATCH_1" "$MATCH_2" copy "$MATCH_3" "$MATCH_4" "$DATADIR/stdout" 2>"$DATADIR/stderr" IMPLEMENTS GIVEN ([a-z][a-z0-9]*) ([a-z][a-z0-9]*) has set the owner of ([^ ]+) to ([a-z][a-z0-9]*) $GTT runcommand "$MATCH_1" "$MATCH_2" config "$MATCH_3" set project.owner "$MATCH_4" "$DATADIR/stdout" 2>"$DATADIR/stderr" IMPLEMENTS WHEN ([a-z][a-z0-9]*) ([a-z][a-z0-9]*) restores the latest deletion to (.+) $GTT runcommand "$MATCH_1" "$MATCH_2" graveyard list "$DATADIR/stdout" 2>"$DATADIR/stderr" reponame="$(head -n1 "$DATADIR/stdout" | cut -d' ' -f2)" $GTT runcommand "$MATCH_1" "$MATCH_2" graveyard restore "$reponame" "$MATCH_3" "$DATADIR/stdout" 2>"$DATADIR/stderr" reponame="$(head -n1 "$DATADIR/stderr" | cut -d' ' -f2)" $GTT runcommand "$MATCH_1" "$MATCH_2" graveyard purge "$reponame" "$DATADIR/stdout" 2> "$DATADIR/stderr" rm -f "$DATADIR/stdin" IMPLEMENTS WHEN ([a-z][a-z0-9]*) ([a-z][a-z0-9]*),? expecting failure,? runs ?(.*) if ! test -e "$DATADIR/stdin"; then touch "$DATADIR/stdin"; fi if $GTT runcommand "$MATCH_1" "$MATCH_2" $MATCH_3 < "$DATADIR/stdin" > "$DATADIR/stdout" 2> "$DATADIR/stderr"; then false fi rm -f "$DATADIR/stdin" IMPLEMENTS GIVEN ([^ ]+) contains (.+) printf %s "$MATCH_2" >"$DATADIR/$MATCH_1" IMPLEMENTS THEN ([^ ]+) contains (.+) grep -q "$MATCH_2" "$DATADIR/$MATCH_1" IMPLEMENTS THEN the output contains (.+) grep -q "$MATCH_1" "$DATADIR/stdout" "$DATADIR/stderr" IMPLEMENTS THEN ([^ ]+) does not contain (.+) if grep -q "$MATCH_2" "$DATADIR/$MATCH_1"; then false; else true; fi IMPLEMENTS THEN the output does not contain (.+) if grep -q "$MATCH_1" "$DATADIR/stdout" "$DATADIR/stderr"; then false; else true; fi IMPLEMENTS THEN ([^ ]+) is empty if grep -q . "$DATADIR/$MATCH_1"; then false; fi IMPLEMENTS THEN ([^ ]+) is not empty grep -q . "$DATADIR/$MATCH_1" IMPLEMENTS THEN the output is empty if grep -q . "$DATADIR/stdout" "$DATADIR/stderr"; then false; else true; fi IMPLEMENTS THEN the output is not empty grep -q . "$DATADIR/stdout" "$DATADIR/stderr" IMPLEMENTS GIVEN the token is saved as (.+) mkdir -p "$DATADIR/saved-tokens" cat "$DATADIR/stdout" "$DATADIR/stderr" | $GTT findtoken >"$DATADIR/saved-tokens/$MATCH_1" IMPLEMENTS THEN failure ensues cd "$DATADIR" echo "FIND:" find . echo "KEYS:" cat user-home-testinstance/.ssh/authorized_keys echo "IN": if test -r stdin; then cat stdin; fi echo "OUT": if test -r stdout; then cat stdout; fi echo "ERR": if test -r stderr; then cat stderr; fi echo "LASTPROG:" cat last-program /bin/false IMPLEMENTS ASSUMING gitano is being accessed over ([^ ]+) test "$GTT_PROTO" = "$MATCH_1" IMPLEMENTS GIVEN ([^ ]+) is in the environment set to (.+) $GTT setenv "$MATCH_1" "$MATCH_2" IMPLEMENTS GIVEN ([^ ]+) is not in the environment $GTT unsetenv "$MATCH_1" GPG Keyring related helpers --------------------------- Since the test suite runs with a `GNUPG_HOME` set up for us which the test tool can access, these implementations use that `GNUPG_HOME` rather than one inside `DATADIR`. IMPLEMENTS GIVEN gpg key ([0-9A-Fa-f]+) on stdin $GTT gpg --armor --export "$MATCH_1" > "$DATADIR/stdin"