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" admin | GTT_PROTO=ssh $GTT runcommand \ testinstance adminkey as admin passwd \ >> $DATADIR/stdout 2>> $DATADIR/stderr printf "%s" gitano-bypass | 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 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" > $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" "$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]*),? clones ([^ ]+) as ([^ ]+)( with depth (\d+))? $GTT clone $MATCH_1 $MATCH_2 "$MATCH_3" "$MATCH_4" ${MATCH_5:+ --no-local --depth="$MATCH_6"} \ >$DATADIR/stdout 2>$DATADIR/stderr IMPLEMENTS WHEN ([a-z][a-z0-9]*),? using ([a-z][a-z0-9]*),? pushes ([^ ]+) to ([^ ]+) $GTT push $MATCH_1 $MATCH_2 "$MATCH_3" "$MATCH_4" 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")" \ >$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 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]*) ([^ ]+) cd "$($GTT clonelocation $MATCH_1 "$MATCH_2")" git 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" > $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" "$MATCH_3" | 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 | $GTT findtoken) $GTT runcommand $MATCH_1 $MATCH_2 user del $MATCH_3 $TOKEN IMPLEMENTS GIVEN ([a-z][a-z0-9]*),? using ([a-z][a-z0-9]*),? has patched gitano-admin with ([^ ]+) $GTT clone $MATCH_1 $MATCH_2 gitano-admin.git tmp-adminpatch $GTT rungit $MATCH_1 tmp-adminpatch apply --cached - <"testing/admin-patches/$MATCH_3" $GTT rungit $MATCH_1 tmp-adminpatch commit --allow-empty -m "Apply $MATCH_3 rules change" $GTT push $MATCH_1 $MATCH_2 tmp-adminpatch gitano-admin.git rm -r "$($GTT clonelocation $MATCH_1 tmp-adminpatch)" IMPLEMENTS WHEN ([a-z][a-z0-9]*),? using ([a-z][a-z0-9]*),? pushes an empty commit in ([^ ]+) $GTT rungit $MATCH_1 $MATCH_3 commit --allow-empty -m "Make an empty commit" $GTT push $MATCH_1 $MATCH_2 $MATCH_3 gitano-admin.git > $DATADIR/stdout 2>$DATADIR/stderr 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 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 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" IMPLEMENTS WHEN ([a-z][a-z0-9]*) ([a-z][a-z0-9]*) purges the latest deletion $GTT runcommand $MATCH_1 $MATCH_2 graveyard list >$DATADIR/stdout 2>$DATADIR/stderr reponame="$(head -n1 $DATADIR/stderr | cut -d' ' -f2)" $GTT runcommand $MATCH_1 $MATCH_2 graveyard purge "$reponame" Generic utility methods ----------------------- IMPLEMENTS WHEN ([a-z][a-z0-9]*) ([a-z][a-z0-9]*) runs ?(.*) if ! test -e $DATADIR/stdin; then touch $DATADIR/stdin; fi $GTT runcommand $MATCH_1 $MATCH_2 $MATCH_3 < $DATADIR/stdin > $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/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 "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" 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