summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLars Wirzenius <liw@liw.fi>2017-04-06 16:45:18 +0300
committerLars Wirzenius <liw@liw.fi>2017-04-06 16:58:49 +0300
commit91cb8199e6e27648d675a4832391d00a4da22821 (patch)
tree7248cf9aaffb4f661db19886f7db81eb2f85f576
parent0e3e5dd591c9d810ecb5a4d8f7aefdcab3ada9c0 (diff)
downloaddistix-91cb8199e6e27648d675a4832391d00a4da22821.tar.gz
Rewrite yarn IMPLEMENTS in Python
-rwxr-xr-xcheck10
-rw-r--r--yarns/900-implements.yarn200
-rw-r--r--yarns/lib.py69
3 files changed, 175 insertions, 104 deletions
diff --git a/check b/check
new file mode 100755
index 0000000..f4c6167
--- /dev/null
+++ b/check
@@ -0,0 +1,10 @@
+#!/bin/sh
+
+set -eu
+
+yarn yarns/*.yarn \
+ --shell python2 \
+ --shell-arg '' \
+ --shell-library yarns/lib.py \
+ --cd-datadir \
+ "$@"
diff --git a/yarns/900-implements.yarn b/yarns/900-implements.yarn
index 2931361..ab3c44c 100644
--- a/yarns/900-implements.yarn
+++ b/yarns/900-implements.yarn
@@ -20,108 +20,82 @@ we do this by keeping track ourselves of where the scenario wants to
be, and changing there when running various commands.
IMPLEMENTS WHEN user changes working directory to (\S+)
- printf "%s" "$MATCH_1" > "$DATADIR/cwd"
+ newdir = get_next_match()
+ olddir = vars['cwd'] or '.'
+ vars['cwd'] = os.path.abspath(os.path.join(datadir, olddir, newdir))
+ print os.listdir('.')
+ runcmd(['pwd'], cwd=vars['cwd'])
IMPLEMENTS WHEN user attempts to run distix ([^$]*)
-
- # Yarn sets $HOME to point at an empty temporary directory.
- # Set up a simple git config so tests can use git.
- git config --global user.email 'Tomjon <tomjon@example.com>'
- git config --global user.name 'Tomjon Tester'
-
- cd "$DATADIR"
- rm -f attempt.exit attempt.stdout attempt.stderr
- cd "$(cat cwd || echo .)"
- if "$SRCDIR/distix" --no-default-config --quiet \
- --log "$DATADIR/distix.log" \
- $MATCH_1 \
- > "$DATADIR/attempt.stdout" 2> "$DATADIR/attempt.stderr"
- then
- echo 0 > "$DATADIR/attempt.exit"
- else
- echo "$?" > "$DATADIR/attempt.exit"
- fi
+ args = get_next_match()
+ configure_git()
+ run_distix(args.split())
IMPLEMENTS WHEN user attempts to run distix show \$PREFIX
- # Yarn sets $HOME to point at an empty temporary directory.
- # Set up a simple git config so tests can use git.
- git config --global user.email 'Tomjon <tomjon@example.com>'
- git config --global user.name 'Tomjon Tester'
-
- cd "$DATADIR"
- rm -f attempt.exit attempt.stdout attempt.stderr
- cd "$(cat cwd || echo .)"
- if "$SRCDIR/distix" --no-default-config --quiet \
- --log "$DATADIR/distix.log" \
- show "$(cat "$DATADIR/tid-prefix")"\
- > "$DATADIR/attempt.stdout" 2> "$DATADIR/attempt.stderr"
- then
- echo 0 > "$DATADIR/attempt.exit"
- else
- echo "$?" > "$DATADIR/attempt.exit"
- fi
+ configure_git()
+ run_distix(['show', vars['tid-prefix']])
IMPLEMENTS WHEN user sets all tickets in (\S+) to (\S+)
- cd "$DATADIR/$MATCH_1"
-
- "$SRCDIR/distix" --no-default-config --quiet \
- --log "$DATADIR/distix.log" list |
- awk '/^ / { print $2 }' > "$DATADIR/tickets.list"
-
- cat "$DATADIR/tickets.list" |
- while read ticket
- do
- "$SRCDIR/distix" --no-default-config --quiet \
- --log "$DATADIR/distix.log" \
- set "$MATCH_2" "$ticket"
- done
+ repo = get_next_match()
+ keyvalue = get_next_match()
+ run_distix(['list'], cwd=repo)
+ list_output = vars['stdout']
+ tickets = [
+ line.split()[1]
+ for line in list_output.splitlines()
+ if line.startswith(' ')
+ ]
+ run_distix(['set', keyvalue] + tickets)
We also need steps for inspecting the results of attempting to run
distix.
IMPLEMENTS THEN attempt succeeded
- cat "$DATADIR/attempt.exit"
- cat "$DATADIR/attempt.stderr"
- if ! grep -Fx 0 "$DATADIR/attempt.exit"
- then
- echo "Attempt should have succeeded, but didn't" 1>&2
- exit 1
- fi
+ print 'stdout:', repr(vars['stdout'])
+ print 'stderr:', repr(vars['stderr'])
+ print 'exit:', vars['exit']
+ assert vars['exit'] == 0
IMPLEMENTS THEN output is "(.*)"
- cat "$DATADIR/attempt.stdout"
- printf "$MATCH_1" > "$DATADIR/temp-stdout"
- diff -u "$DATADIR/temp-stdout" "$DATADIR/attempt.stdout"
+ wanted = unescape(get_next_match())
+ output = vars['stdout']
+ print 'wanted:', repr(wanted)
+ print 'output:', repr(output)
+ assert wanted == unescape(vars['stdout'])
IMPLEMENTS THEN output matches "(.*)"
- cat "$DATADIR/attempt.stdout"
- grep -P -e "$MATCH_1" "$DATADIR/attempt.stdout"
+ import re
+ pattern = get_next_match().decode('utf8')
+ print 'stdout:', repr(vars['stdout'])
+ print 'pattern:', repr(pattern)
+ assert re.search(pattern, vars['stdout'], re.M) is not None
IMPLEMENTS THEN output doesn't match "(.*)"
- cat "$DATADIR/attempt.stdout"
- if grep -P -e "$MATCH_1" "$DATADIR/attempt.stdout"
- then
- echo "$DATADIR/attempt.stdout unexpected matches $MATCH_1" 1>&2
- exit 1
- fi
+ import re
+ pattern = get_next_match()
+ output = unicode(vars['stdout'], 'utf8')
+ print 'pattern:', repr(pattern)
+ print 'stdout:', repr(output)
+ assert re.search(pattern, output) is None
IMPLEMENTS THEN first ticket id is captured as \$TID
# We assume previous command run was distix list.
- # Each line starts with a full ticket id.
- awk 'NR == 2 { print $2; exit }' "$DATADIR/attempt.stdout" \
- > "$DATADIR/ticket-id-1"
+ list_output = vars['stdout']
+ tickets = [
+ line.split()[1]
+ for line in list_output.splitlines()
+ if line.startswith(' ')
+ ]
+ vars['tickets'] = tickets
+ vars['ticket-id-1'] = tickets[0]
IMPLEMENTS THEN attempt failed
- cat "$DATADIR/attempt.exit" # helps debugging scenarios
- if grep -Fx 0 "$DATADIR/attempt.exit"
- then
- echo "Attempt should have failed, but didn't" 1>&2
- exit 1
- fi
+ assert vars['exit'] != 0
IMPLEMENTS THEN error message matches (.*)
- cat "$DATADIR/attempt.stderr"
- grep -e "$MATCH_1" "$DATADIR/attempt.stderr"
+ import re
+ pattern = get_next_match()
+ assert re.search(pattern, vars['stderr']) is not None
File creation
@@ -131,7 +105,9 @@ We need to provide a way for scenarios to create files with known
content.
IMPLEMENTS GIVEN file (\S+) containing "(.*)"
- printf "$MATCH_2" > "$DATADIR/$MATCH_1"
+ filename = get_next_match()
+ content = get_next_match()
+ write_file(filename, unescape(content).encode('utf8'))
Maildir creation
@@ -140,14 +116,16 @@ Maildir creation
We need to create a maildir with mails in it.
IMPLEMENTS GIVEN maildir (\S+) containing a mail with subject "(.+)"
- dirname="$DATADIR/$MATCH_1"
- mkdir -p "$dirname/new" "$dirname/cur" "$dirname/tmp"
- cat <<EOF > "$dirname/new/message"
+ dirname = get_next_match()
+ subject = get_next_match()
+ mkmaildir(dirname)
+ mailfile = os.path.join(dirname, 'new', 'msg')
+ write_file(mailfile, """\
From: user@example.com
- Subject: $MATCH_2
+ Subject: {subject}
Message body goes here.
- EOF
+ """.format(subject=subject).encode('utf8'))
File tests
-----------
@@ -155,8 +133,8 @@ File tests
Does a file or directory exist?
IMPLEMENTS THEN (\S+) exists
- test -e "$DATADIR/$MATCH_1"
-
+ filename = get_next_match()
+ assert os.path.exists(filename)
Repository/ticket tests
-----------------------
@@ -164,18 +142,26 @@ Repository/ticket tests
How many tickets does a repository have?
IMPLEMENTS THEN repository (\S+) has (\d+) tickets?
- n="$(ls "$DATADIR/$MATCH_1/tickets" | wc -l)"
- [ "$n" = "$MATCH_2" ]
+ repo = get_next_match()
+ count = int(get_next_match())
+ ticketdir = os.path.join(repo, 'tickets')
+ assert len(os.listdir(ticketdir)) == count
How many copies of a given message does a repository have? In any
tickets?
IMPLEMENTS THEN repository (\S+) has one copy of message in (\S+)
- find "$DATADIR/$MATCH_1/tickets" -type f -exec md5sum '{}' + \
- > "$DATADIR/md5sums"
- msgsum="$(md5sum < "$DATADIR/$MATCH_2" | awk '{ print $1 }')"
- n="$(grep -c -e "$msgsum" "$DATADIR/md5sums" | wc -l)"
- [ "$n" = 1 ]
+ repo = get_next_match()
+ msgfile = get_next_match()
+ msg = cat_file(msgfile)
+ tickets = os.path.join(repo, 'tickets')
+ for dirname, subdirs, basenames in os.walk(repo):
+ for basename in basenames:
+ filename = os.path.join(dirname, basename)
+ candidate = cat_file(filename)
+ if candidate == msg:
+ sys.exit(0)
+ sys.exit(1)
Git operations
--------------
@@ -183,26 +169,32 @@ Git operations
Clone a repository.
IMPLEMENTS WHEN user clones (\S+) to (\S+)
- cd "$DATADIR"
- git clone "$MATCH_1" "$MATCH_2"
+ url = get_next_match()
+ dirname = get_next_match()
+ print repr(vars['cwd'])
+ print repr(vars._dict)
+ print runcmd(['pwd'])
+ print os.listdir('.')
+ print os.listdir(url)
+ print repr(['git', 'clone', url, dirname])
+ print runcmd(['git', 'clone', url, dirname])
+ print runcmd(['pwd'], cwd=dirname)
+
+
Check that everything is in git.
IMPLEMENTS THEN everything in (\S+) is committed to git
- cd "$DATADIR/$MATCH_1"
- if git status --short | grep .
- then
- echo "Not everything is in git" 1>&2
- exit 1
- fi
+ ex, out, err = runcmd(['git', 'status', '--short'])
+ print 'stdout:', repr(out)
+ assert out == ''
Ticket id manipulation
----------------------
IMPLEMENTS THEN ticket id \$TID 7-nybble prefix is \$PREFIX
- cut -c1-7 "$DATADIR/ticket-id-1" > "$DATADIR/tid-prefix"
+ vars['tid-prefix'] = vars['ticket-id-1'][:7]
IMPLEMENTS THEN output contains ticket id \$TID
- grep -f "$DATADIR/ticket-id-1" "$DATADIR/attempt.stdout"
-
+ assert vars['ticket-id-1'] in vars['stdout']
diff --git a/yarns/lib.py b/yarns/lib.py
new file mode 100644
index 0000000..45bcb03
--- /dev/null
+++ b/yarns/lib.py
@@ -0,0 +1,69 @@
+import os
+import sys
+
+import cliapp
+
+import yarnutils
+
+datadir = os.environ['DATADIR']
+srcdir = os.environ['SRCDIR']
+
+vars = yarnutils.Variables(datadir)
+
+
+
+_next_match = 1
+
+def get_next_match():
+ global _next_match
+ name = 'MATCH_{}'.format(_next_match)
+ _next_match += 1
+ return os.environ[name]
+
+
+def cat_file(filename):
+ with open(filename) as f:
+ return f.read()
+
+
+def write_file(filename, content):
+ with open(filename, 'w') as f:
+ f.write(content)
+
+
+def runcmd(argv, **kwargs):
+ if 'cwd' not in kwargs:
+ kwargs['cwd'] = vars['cwd']
+ return cliapp.runcmd_unchecked(argv, **kwargs)
+
+
+def configure_git():
+ # Yarn sets $HOME to point at an empty temporary directory.
+ # Set up a simple git config so tests can use git.
+ runcmd(['git', 'config', '--global', 'user.email', 'tomjon@example.com'])
+ runcmd(['git', 'config', '--global', 'user.name', 'Tomjon Tester'])
+
+
+def run_distix(args, cwd=None):
+ if cwd is None:
+ cwd = vars['cwd']
+
+ distix = os.path.join(srcdir, 'distix')
+ log_file = os.path.join(datadir, 'distix.log')
+ exit_code, out, err = runcmd(
+ [distix, '--no-default-config', '--quiet', '--log', log_file] +
+ args,
+ cwd=cwd)
+ vars['exit'] = exit_code
+ vars['stdout'] = out
+ vars['stderr'] = err
+
+
+def mkmaildir(dirname):
+ os.makedirs(dirname)
+ for subdir in ['cur', 'tmp', 'new']:
+ os.mkdir(os.path.join(dirname, subdir))
+
+
+def unescape(s):
+ return '\n'.join(s.split('\\n'))