73 Commits

Author SHA1 Message Date
Thomas Levine
61315d377e remote 2016-04-08 07:32:01 +00:00
Thomas Levine
7daa85cd32 remote host names 2016-04-08 07:08:05 +00:00
Thomas Levine
90b2f93de6 output format to support remotes 2016-04-08 06:56:22 +00:00
Thomas Levine
fa432b5c09 remote testing proposal 2016-04-07 12:38:23 +00:00
Thomas Levine
236b8f86c2 dep proposal 2016-04-07 12:32:19 +00:00
Thomas Levine
74e9d95f77 fixtures idea 2016-04-07 12:20:31 +00:00
Thomas Levine
0395ebb5b2 comment the line in tap 2016-04-07 05:19:47 +00:00
Thomas Levine
cebf0d3add update format tests 2016-04-07 05:18:56 +00:00
Thomas Levine
123f04270b md5 format 2016-04-07 03:55:43 +00:00
Thomas Levine
82c81822d3 mktemp templates 2016-04-07 03:51:01 +00:00
Thomas Levine
9fe6058fbf Automatic commit with j 2016-04-07 03:46:38 +00:00
Thomas Levine
e58ae17704 supporting no rsync 2016-04-07 03:41:33 +00:00
Thomas Levine
367ae3f2b1 tests to write 2016-04-07 03:25:45 +00:00
Thomas Levine
5ffd065317 solaris 2016-04-07 03:23:19 +00:00
Thomas Levine
c0239915a2 error 2016-04-07 03:20:39 +00:00
Thomas Levine
b339c5f98e wrong flag 2016-04-07 03:17:08 +00:00
Thomas Levine
92d40c9ff1 DISABLE_CYCLING 2016-04-07 03:13:42 +00:00
Thomas Levine
24ecd302cd document environment variables 2016-04-07 03:12:10 +00:00
Thomas Levine
135c24fd72 hpux exit codes 2016-04-07 03:03:07 +00:00
Thomas Levine
c219f0a0e6 shorter output 2016-04-07 02:54:30 +00:00
Thomas Levine
adf8dc3562 epoch 2016-04-07 02:52:40 +00:00
Thomas Levine
969340bfd6 bugs 2016-04-07 02:52:38 +00:00
Thomas Levine
a484300263 oops 2016-04-07 02:48:58 +00:00
Thomas Levine
e8d946cc5c switch debug to set -x 2016-04-07 02:47:55 +00:00
Thomas Levine
81c4cdeac0 oops 2016-04-07 02:44:22 +00:00
Thomas Levine
b79045c6ee refactor mktemp 2016-04-07 02:42:29 +00:00
Thomas Levine
c6061b377b alternative ways of getting a seconds counter 2016-04-07 02:39:28 +00:00
Thomas Levine
539027db59 find the next bug 2016-04-07 01:59:28 +00:00
Thomas Levine
5e2ecab592 mktemp 2016-04-07 01:58:34 +00:00
Thomas Levine
efe3af6f87 new version 2016-04-07 00:25:32 +00:00
Thomas Levine
f244c22055 another bug 2016-04-07 00:24:52 +00:00
Thomas Levine
2cdd3ec049 fix hpux rsync path 2016-04-07 00:24:06 +00:00
Thomas Levine
6744b2cb4a more on bugs 2016-04-07 00:16:09 +00:00
Thomas Levine
6e32dab0b7 bugs 2016-04-07 00:11:41 +00:00
Thomas Levine
bb3876f334 oops 2016-04-07 00:06:44 +00:00
Thomas Levine
0dc6e01fbc that alias approach was invalid 2016-04-07 00:06:02 +00:00
Thomas Levine
ca71678522 md5 2016-04-07 00:02:11 +00:00
Thomas Levine
9b4f14c937 note on MirBSD 2016-04-06 23:58:58 +00:00
Thomas Levine
27592e58ac untested md5 handler 2016-04-06 23:58:26 +00:00
Thomas Levine
42c09b775b openbsd bug 2016-04-06 23:50:46 +00:00
Thomas Levine
2923d3a8b0 more systems 2016-04-06 23:45:44 +00:00
Thomas Levine
12f458a933 wrong port 2016-04-06 23:26:42 +00:00
Thomas Levine
6c217acae8 oops 2016-04-06 23:21:04 +00:00
Thomas Levine
6a7e58c944 all flags as flags 2016-04-06 23:18:38 +00:00
Thomas Levine
32ac65cf3e more data in filename 2016-04-06 23:14:25 +00:00
Thomas Levine
d1c8f78585 todo 2016-04-06 21:43:18 +00:00
Thomas Levine
132e1695db HISTORY 2016-04-04 21:42:02 +00:00
Thomas Levine
d67185ce25 don't use /dev/stderr 2016-04-04 21:37:47 +00:00
Thomas Levine
16988c48a9 simpler check 2016-04-04 21:29:51 +00:00
Thomas Levine
ddb74d43d8 longer shell list 2016-04-04 21:21:24 +00:00
Thomas Levine
04c4f54789 strange name so we don't have conflicts 2016-04-04 21:10:37 +00:00
Thomas Levine
552d7d0dbc record test command in makefile 2016-04-04 21:07:29 +00:00
Thomas Levine
00c99773d0 run cross-os tests in series
because i sometimes run them on weak computers
2016-04-04 21:04:05 +00:00
Thomas Levine
7899657971 simpler cross-os tests 2016-04-04 20:59:21 +00:00
Thomas Levine
2ee965d2ae start on cross-os tests 2016-04-04 20:55:14 +00:00
Thomas Levine
fdb0b1b3ea LC_COLLATE rather than LC_ALL 2016-04-04 19:15:00 +00:00
Thomas Levine
db3dd1c662 typos 2016-04-04 01:22:05 +00:00
Thomas Levine
a9e0f856fb error message text 2016-04-04 01:17:58 +00:00
Thomas Levine
72f0700598 fixing timeout flag 2016-04-04 01:16:51 +00:00
Thomas Levine
a486a6f296 check timeout error message 2016-04-04 01:07:29 +00:00
Thomas Levine
a9ba8e79d3 suppress timeout errors 2016-04-04 01:04:04 +00:00
Thomas Levine
586f46600a assert that there is no timeout output 2016-04-04 01:03:05 +00:00
Thomas Levine
940cd549ab more timeout tests 2016-04-04 00:58:37 +00:00
Thomas Levine
cd7f773d58 fix debug 2016-04-04 00:42:08 +00:00
Thomas Levine
0de2c3264a version in readme 2016-04-04 00:24:54 +00:00
Thomas Levine
fc51c34019 debug messages 2016-04-01 19:52:34 +00:00
Thomas Levine
c61d31fcea docs 2016-04-01 19:43:02 +00:00
Thomas Levine
6275c28ebf update history 2016-04-01 18:25:53 +00:00
Thomas Levine
b0a7a8b07a remove out-of-date windows screenshots 2016-04-01 18:24:59 +00:00
Thomas Levine
f7ffd82893 fix name 2016-04-01 18:21:26 +00:00
Thomas Levine
a5ffad0446 Automatic commit with j 2016-04-01 18:21:01 +00:00
Thomas Levine
b402f466b5 package for nongnu 2016-04-01 18:20:00 +00:00
Thomas Levine
7a34da0906 packaging 2016-04-01 18:19:28 +00:00
41 changed files with 516 additions and 59 deletions

16
HISTORY
View File

@@ -1,10 +1,18 @@
HISTORY
=======
Version 0.1.0-rc1
Version 0.1.0
---------------------
This release includes breaking changes.
### Cross-OS testing
I have started testing Urchin across multiple operating systems.
This gives access to more shells, as some shels are easier to install on
certain operating systems.
With this cross-OS test suite, I have extended support to more shells.
A later version of Urchin could include a remote testing feature.
### Test root directory
We introduce a concept of the root directory of a test suite.
Such a concept is important in case you want to run subsets of your
@@ -72,7 +80,7 @@ might look for the dependency and then skip if it does not see the dependency.
It might look like this.
#!/bin/sh
if which inkscape; then
if ! which inkscape; then
exit 3 # status code 3 for skip
fi
inkscape blah blah ...
@@ -171,10 +179,6 @@ set as an environment variable, and the latter was set with the -s flag..
Urchin now uses the -s flag for both of these settings, and it mostly ignores
the exported TEST_SHELL variable.
Urchin also inspects the shebang line differently. Previously, Urchin would
vary the shells with which a test is run if the shebang line either was absent
or was #!/bin/sh. Now it varies the shell only if the shebang line is absent.
If you pass -n/--disable-cycling, Urchin will invoke tests ordinarily and will
only set the TEST_SHELL variable if it does not exist. If the TEST_SHELL
variable is absent, it will be set to /bin/sh.

8
Makefile Normal file
View File

@@ -0,0 +1,8 @@
.PHONY: test install
test:
./urchin tests
./urchin -s sh -v ./cross-os-tests
install:
cp ./urchin /usr/bin

215
TODO
View File

@@ -63,3 +63,218 @@ bash
Alternatives
--------------
JSON.sh test suite
Running in multiple environments
-----------------------------------
Setup for other environments includes the following.
* Installing packages
* `touch .zshrc`
* Copy urchin and tests
Fixtures
------------
I want to change the way that fixtures are done.
Instead of using setup, teardown, &c., use ordinary programs from within
your tests. For example.
# tests/.fixtures/tmp-dir
tmp=$(mktemp -d)
cd $tmp
@$
code=$?
cd /
rm -Rf $tmp
exit $code
# tests/blah
../.fixtures/tmp-dir 'blah blah blah'
It's best if I can wrap a bunch of commands in braces or paratheses
rather than just one command. Is there a nice way to do that?
Once I have this new way, I guess I might as well keep the old way.
I think the setup, teardown thing can be easier if you only have simple
fixtures. And since I'm going to keep it, I'm going to add another one.
* setup_dir runs once for the present directory.
* setup_children runs once for each child.
* setup_file runs once for each file descendent.
The present `setup` is renamed to `setup_children`, and the new
`setup_file` runs on each file (not directory) that is a child,
grandchild, great-grandchild, and so on.
Dependency checking
----------------------
You might want to skip tests based on dependencies. Currently you can
conditionally skip tests one at a time by exiting with code 3. I want to
be able to skip an entire directory.
So we add a new magic file called `dep`. If it exists, it is run before
everything else in the directory.
* If it exits with code 0, tests continue as if dep did not exist.
* If it exits with code 3, all tests in the directory are marked as
skipped.
* If it exits with code 1, all tests in the directory are marked as
failed. To make the implementation easier, I'll probably treat the
directory as a single test in this case.
A note on magic files
-------------------------
It is nice to have access to things like setup and dep (magic files)
once in a while, but you need to be doing rather substantial testing
before they make your test suite simpler; the documentation should
strongly recommend writing your tests without magic files and then
refactoring and only then considering moving things to magic files.
Remote testing
----------------
In order to test Urchin across multiple operating systems, I have
already added tests in Urchin's test suite that run Urchin tests in
remote servers. I would like to move this to Urchin itself so that
Urchin can test other things on remote servers.
Urchin's output presently looks like this.
Cycling with the following shells: sh bash dash mksh zsh
Running tests at 2016-04-07T12:33:49
Flags/
> --timeout output
. bash (0 seconds)
. dash (0 seconds)
. mksh (0 seconds)
. sh (0 seconds)
. zsh (0 seconds)
Done, took 1 second.
5 tests passed.
0 tests skipped.
0 tests failed.
After the change, the output should look like this.
Cycling with the following shells: sh dash mksh
Running tests at 2016-04-07T12:33:49
Flags/
> --timeout output
. dash on localhost (0 seconds)
. dash on localhost:8080 (0 seconds)
. dash on tlevine@hpux.polarhome.com (0 seconds)
. mksh on localhost (0 seconds)
. mksh on tlevine@hpux.polarhome.com (0 seconds)
. sh on localhost (0 seconds)
. sh on localhost:8080 (0 seconds)
. sh on tlevine@hpux.polarhome.com (0 seconds)
Done, took 1 second.
8 tests passed.
0 tests skipped.
0 tests failed.
This is just how the output should look; the tests run in whatever order
makes sense.
Bugs
-------
Both md5sum and md5 should be supported.
Trouble logging in to hpux, irix, miros, netbsd, tru64, qnx, ....
$ rsync -e 'ssh -p 785' urchin tlevine@hpux.polarhome.com:.blah
HP-UX hpux.polarhome.com B.11.11 U 9000/785 (ta)
Welcome to HPUX/PA... member of polarhome.com realm
bash: rsync: command not found
rsync: connection unexpectedly closed (0 bytes received so far) [sender]
rsync error: remote command not found (code 127) at io.c(226)
[sender=3.1.1]
OpenIndiana grep does not support -q
I get `/urchin: syntax error at line 84: \`}' unexpected` on
unixware and solaris.
mktemp
> tlevine@hpux.polarhome.com -p 785
F sh (8 seconds)
|
| HP-UX hpux.polarhome.com B.11.11 U 9000/785 (ta)
| Welcome to HPUX/PA... member of polarhome.com realm
|
|
| HP-UX hpux.polarhome.com B.11.11 U 9000/785 (ta)
| Welcome to HPUX/PA... member of polarhome.com realm
|
| mktemp: option requires an argument -- d
| ./urchin[96]: /tmp/tlevinea21441/log: Cannot create the specified file.
date
tlevine@hpux64$ ./urchin tests/ -n -vv
date: bad format character - s
So I need a portable seconds-from epoch
I also need to handle when no arguments are passed to urchin.
Exit code is wrong for which on HP-UX
## `$(...)`
Solaris doesn't support `$(...)`; you need `\`...\`` instead.
tlevine@solaris$ ./urchin --run-in-series tests/Errors/
./urchin: syntax error at line 84: `tmp=$' unexpected
I use this a lot.
$ grep -c '\$(' urchin
52
Darn
Update tests to support
* md5
* rsync
* mktemp
* epoch
* Report cycling by default
* New format for reporting cycling
Support systems without rsync
BSD mktemp
| NetBSD 6.1.3
| Welcome to NetBSD ...member of polarhome.com realm
|
| Usage: mktemp [-dqu] [-p <tmpdir>] {-t prefix | template ...}
| mkdir: : No such file or directory
| ./urchin: cannot create /log: permission denied
NetBSD
md5: unknown option -- q
usage: cksum [-n] [-a algorithm [-ptx] [-s string]] [-o 1|2]
[file ... | -c [-w] [sumfile]]

14
cross-os-tests/.run Executable file
View File

@@ -0,0 +1,14 @@
params="$(basename "${0}")"
hostname="$(echo "${params}" | cut -d\ -f1)"
if echo "${params}" | grep -q \ ; then
flags="$(echo "${params}" | cut -d\ -f2-)"
fi
urchin_dir=.urchin-cross-shell-test
rsync --archive -e "ssh ${flags}" $RSYNC_FLAGS \
../urchin ../tests "${hostname}":"${urchin_dir}" ||
scp -r ${flags} ../urchin ../tests "${hostname}":"${urchin_dir}"
ssh "${hostname}" ${flags} \
"cd ${urchin_dir} && ./urchin --run-in-series tests"

View File

@@ -0,0 +1,2 @@
#!/bin/sh
. ./.run

View File

@@ -0,0 +1,3 @@
#!/bin/sh
# apt-get install bash dash ksh posh pdksh mksh yash zsh
. ./.run

View File

@@ -0,0 +1,2 @@
#!/bin/sh
. ./.run

View File

@@ -0,0 +1,2 @@
#!/bin/sh
. ./.run

View File

@@ -0,0 +1,2 @@
#!/bin/sh
. ./.run

View File

@@ -0,0 +1,2 @@
#!/bin/sh
. ./.run

View File

@@ -0,0 +1,2 @@
#!/bin/sh
. ./.run

View File

@@ -0,0 +1,3 @@
#!/bin/sh
RSYNC_FLAGS='--rsync-path=/usr/local/bin/rsync'
. ./.run

View File

@@ -0,0 +1,2 @@
#!/bin/sh
. ./.run

View File

@@ -0,0 +1,3 @@
#!/bin/sh
# SSH public key needs to be in ~/.etc/ssh/authorized_keys
. ./.run

View File

@@ -0,0 +1,2 @@
#!/bin/sh
. ./.run

View File

@@ -0,0 +1,2 @@
#!/bin/sh
. ./.run

View File

@@ -0,0 +1,2 @@
#!/bin/sh
. ./.run

View File

@@ -0,0 +1,2 @@
#!/bin/sh
. ./.run

View File

@@ -0,0 +1,2 @@
#!/bin/sh
. ./.run

View File

@@ -0,0 +1,2 @@
#!/bin/sh
. ./.run

View File

@@ -0,0 +1,2 @@
#!/bin/sh
. ./.run

View File

@@ -0,0 +1,2 @@
#!/bin/sh
. ./.run

View File

@@ -0,0 +1,2 @@
#!/bin/sh
. ./.run

View File

@@ -0,0 +1,2 @@
#!/bin/sh
. ./.run

View File

@@ -0,0 +1,2 @@
#!/bin/sh
. ./.run

View File

@@ -0,0 +1,2 @@
#!/bin/sh
. ./.run

View File

@@ -0,0 +1,2 @@
#!/bin/sh
. ./.run

1
packages/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
*.tar.gz

11
packages/nongnu.sh Executable file
View File

@@ -0,0 +1,11 @@
#!/bin/sh
name=urchin-$(../urchin --version)
tmp=$(mktemp -d)
mkdir $tmp/$name
cp ../urchin ../readme.md ../AUTHORS ../COPYING $tmp/$name
cd $tmp
tar czf $name.tar.gz $name
cd - > /dev/null
mv $tmp/$name.tar.gz .
rm -R $tmp

View File

@@ -51,7 +51,7 @@ Urchin is contained in a single file, so you can install it by copying it to a
directory in your `PATH`. For example, you can run the following as root.
cd /usr/local/bin
wget https://raw.githubusercontent.com/tlevine/urchin/v0.0.6/urchin
wget https://raw.githubusercontent.com/tlevine/urchin/v0.1.0-rc3/urchin
chmod +x urchin
Urchin can be installed with npm too.

View File

@@ -0,0 +1,2 @@
../../urchin -T aoeu .testsuite 2>&1 | grep Bad
../../urchin -T .testsuite 2>&1 | grep Bad

View File

@@ -1,3 +1 @@
set -e
$TEST_SHELL ../../urchin --shell sh .slow-tests
! $TEST_SHELL ../../urchin --shell sh --timeout 0.3 .slow-tests

4
tests/Flags/--timeout output Executable file
View File

@@ -0,0 +1,4 @@
$TEST_SHELL ../../urchin --shell sh --timeout 0.3 .slow-tests 2>&1 |
grep -v -- --timeout |
grep timeout
test $? = 1

1
tests/Flags/--timeout success Executable file
View File

@@ -0,0 +1 @@
$TEST_SHELL ../../urchin --shell sh .slow-tests --timeout 1000

View File

@@ -1,3 +1,3 @@
$TEST_SHELL ../../urchin -v -s sh -t .testsuite/ |
sed -e 1d -e /second/d > $tmp
sed -e 1,2\ d -e /second/d > $tmp
diff $tmp .tap-output-expectation

View File

@@ -0,0 +1,5 @@
lines=$(
$TEST_SHELL ../../urchin -v -s sh -t .testsuite/ |
tee $tmp | grep -v '^#' | wc -l)
cat $tmp
test $lines -eq 4

View File

@@ -1,3 +1,3 @@
$TEST_SHELL ../../urchin -vv -s sh .testsuite/ |
sed -e 1d -e 's/. seconds\?/1 second/' > $tmp
sed -e 1,2\ d -e 's/. seconds\?/1 second/' > $tmp
diff $tmp .urchin-output-expectation

View File

@@ -1,3 +1,3 @@
$TEST_SHELL ../../urchin --pretty -vv --shell sh .testsuite/ |
sed -e 1d -e 's/. seconds\?/1 second/' > $tmp
sed -e 1,2\ d -e 's/. seconds\?/1 second/' > $tmp
diff $tmp .urchin-output-expectation-color

239
urchin
View File

@@ -51,13 +51,52 @@ set -e
# Kill subprocesses on interrupt.
trap "kill -$$; exit" HUP INT TERM
DEFAULT_SHELLS='sh bash dash mksh zsh'
DEFAULT_SHELLS='
sh
bash
dash
ksh
posh
pdksh
mksh
yash
zsh
'
if [ -n "${ZSH_VERSION}" ]; then
# avoid "no matches found: *" error when directories are empty
setopt NULL_GLOB
emulate sh
fi
epoch_date() {
date +%s
}
epoch_pax() {
# Based on http://stackoverflow.com/a/7262588/407226
tmp="$(mktemp_file)"
echo "ibase=8;$({ pax -wx cpio "${tmp}"; echo; } | cut -c 48-59)" | bc
rm "${tmp}"
}
mktemp_dir() {
# Support HP-UX mktemp that has wrong exit codes and
# can't make directories.
tmp=$(mktemp /tmp/urchin.XXXXXXXX)
if test -f "${tmp}"; then
rm "${tmp}"
fi
mkdir "${tmp}"
echo "${tmp}"
}
mktemp_file() {
tmp=$(mktemp /tmp/urchin.XXXXXXXX)
if ! test -f "${tmp}"; then
> "${tmp}"
fi
echo "${tmp}"
}
validate_test_arg() {
# Must be a file or directory
if [ ! -e "${1}" ]; then
@@ -81,20 +120,53 @@ validate_test_arg() {
}
# All temporary files go here
urchin_tmp=$(mktemp -d)
urchin_tmp=$(mktemp_dir)
> "${urchin_tmp}/log"
urchin_exit() {
rm -Rf "${urchin_tmp}"
exit "$@"
}
if which md5 1> /dev/null 2> /dev/null; then
urchin_md5=md5
elif which md5sum 1> /dev/null 2> /dev/null; then
urchin_md5=md5sum
else
echo Could not find MD5 hash command >&2
urchin_exit 1
fi
if epoch_date 2>&1 > /dev/null; then
epoch=epoch_date
elif epoch_pax 2>&1 > /dev/null; then
epoch=epoch_pax
else
echo I could not find a seconds counter. >&2
urchin_exit 1
fi
stdout_file() {
the_test="${1}"
the_shell="${2}"
host="${3}"
x="${urchin_tmp}/stdout$(fullpath "$the_test")"
mkdir -p "${x}"
echo "${x}/$(echo "${the_shell}" | md5sum | cut -d\ -f1)"
if test -n "${host}"; then
# This assumes the tests ran on a remote and have been copied.
x="${urchin_tmp}/remote/${host}/stdout${the_test}"
else
# This can be run during the tests.
x="${urchin_tmp}/stdout$(fullpath "$the_test")"
mkdir -p "${x}"
fi
case "${urchin_md5}" in
md5sum) y=$(echo "${the_shell}" | md5sum | cut -d\ -f1) ;;
md5) y=$(echo "${the_shell}" | md5 | sed 's/.* //') ;;
*) echo md5 command is not configured >&2; urchin_exit 1;;
esac
echo "${x}/${y}"
}
# Expand relative paths
@@ -137,7 +209,7 @@ urchin_root() {
}
# Urchin version number
VERSION=0.1.0-rc2
VERSION=0.1.1-unstable
indent() {
level="${1}"
@@ -181,7 +253,9 @@ recurse() {
run_in_series_dir=false
fi
if test -f setup_dir; then . ./setup_dir; fi
if test -f setup_dir; then
. ./setup_dir
fi
for test in *; do
if test "${test}" = '*' && ! test -e "${test}"; then
@@ -195,13 +269,17 @@ recurse() {
if "${run_in_series}" || "${run_in_series_dir}"; then
if wait "${!}"; then exit_code=0; else exit_code="${?}"; fi
if "${exit_on_not_ok}" && test "${exit_code}" -ne 0; then
if test -f teardown_dir; then . ./teardown_dir; fi
if test -f teardown_dir; then
. ./teardown_dir
fi
return 1
fi
fi
done
wait
if test -f teardown_dir; then . ./teardown_dir; fi
if test -f teardown_dir; then
. ./teardown_dir
fi
)
elif [ -f "${potential_test}" ]; then
cd -- "$(dirname -- "${potential_test}")"
@@ -210,10 +288,12 @@ recurse() {
# that reflects the specified or implied shell to use for shell-code tests.
while read the_test_shell; do
(
if test -f setup; then . ./setup; fi
if test -f setup; then
. ./setup
fi
# Run the test
start=$(date +%s)
start=$("${epoch}")
set +e
{
if "${cycle_shell}"; then
@@ -235,9 +315,11 @@ recurse() {
} > "$(stdout_file "${potential_test}" "${the_test_shell}")" 2>&1
exit_code="${?}"
set -e
finish=$(date +%s)
finish=$("${epoch}")
if test -f teardown; then . ./teardown; fi
if test -f teardown; then
. ./teardown
fi
if [ "${exit_code}" -eq 0 ]; then
result=ok
@@ -256,14 +338,16 @@ recurse() {
if "${run_in_series}"; then
if wait "${!}"; then exit_code=0; else exit_code="${?}"; fi
if "${exit_on_not_ok}" && test "${exit_code}" -ne 0; then
if test -f teardown_dir; then . ./teardown_dir; fi
if test -f teardown_dir; then
. ./teardown_dir
fi
return 1
fi
fi
done < "${shell_list}"
wait
else
echo "${potential_test}: Neither file nor directory!?" > /dev/stderr
echo "${potential_test}: Neither file nor directory!?" >&2
fi
else
# Shell is ''
@@ -278,24 +362,31 @@ report_outcome() {
start="${4}"
finish="${5}"
host="${6}"
if test -n "${host}"; then
onhost=" on ${host}"
fi
escaped_root="$(fullpath "${root}" | sed 's/\//\\\//g')"
elapsed=$(($finish - $start))
if "${tap_format}"; then
printf \#\
fi
if "${print_margins}" || "${tap_format}"; then
echo Running tests at $(date +%Y-%m-%dT%H:%M:%S)
if $tap_format; then printf \#\ ; fi
echo Ran tests at $(date +%Y-%m-%dT%H:%M:%S) with the following shells:
if $tap_format; then printf \#\ ; fi
cat "${shell_list}" | tr '\n' \
echo
fi
for number in n oks skips not_oks; do
eval "${number}=0"
done
# Use a temporary file rather than a pipe because a pipe starts a sub-shell
# and thus makes the above variables local.
sorted_log_file=$(mktemp)
cat "${log_file}" | LC_ALL=POSIX sort > "${sorted_log_file}"
sorted_log_file=$(mktemp_file)
cat "${log_file}" | LC_COLLATE=C sort > "${sorted_log_file}"
while read line; do
abspath=$(echo "${line}" | cut -f1)
@@ -327,13 +418,13 @@ report_outcome() {
fi
if test -z "${the_shell}"; then
the_shell='File is not executable.'
the_shell='File is not executable'
fi
echo "${not}ok $n - ${path} (${the_shell}) ${skip}"
echo "${not}ok $n - ${path} (${the_shell}${onhost}) ${skip}"
if { test "${result}" = not_ok && "${print_not_ok_stdout}"; } ||
{ test "${result}" = ok && "${print_ok_stdout}"; }; then
echo '# ------------ Begin output ------------'
sed 's/^/# /' "$(stdout_file "${abspath}" "${the_shell}")"
sed 's/^/# /' "$(stdout_file "${abspath}" "${the_shell}" "${host}")"
echo '# ------------ End output ------------'
fi
echo "# Previous test took ${file_elapsed} seconds."
@@ -356,7 +447,7 @@ report_outcome() {
else
printf "${success_mark} "
fi
echo "${the_shell} ("${file_elapsed}" $(plural second $file_elapsed))"
echo "${the_shell}${onhost} (${file_elapsed} $(plural second $file_elapsed))"
fi
;;
not_ok)
@@ -367,23 +458,23 @@ report_outcome() {
else
printf "${fail_mark} "
fi
echo "${the_shell} ("${file_elapsed}" $(plural second $file_elapsed))"
echo "${the_shell}${onhost} (${file_elapsed} $(plural second $file_elapsed))"
fi
;;
skip)
if "${print_ok}"; then
header
if test -z "${the_shell}"; then
echo ' (File is not executable.)'
echo " (File is not executable${onhost}.)"
else
echo " ${the_shell} ("${file_elapsed}" $(plural second $file_elapsed))"
echo " ${the_shell}${onhost} (${file_elapsed} $(plural second $file_elapsed))"
fi
fi
;;
esac
if { test "${result}" = not_ok && "${print_not_ok_stdout}"; } ||
{ test "${result}" = ok && "${print_ok_stdout}"; }; then
sed 's/^/ | /' "$(stdout_file "${abspath}" "${the_shell}")"
sed 's/^/ | /' "$(stdout_file "${abspath}" "${the_shell}" "${host}")"
fi
fi
@@ -450,8 +541,8 @@ The following flags affect how Urchin processes tests.
-b, --run-in-series Run tests in series. The default is to run tests
in parallel where possible.
-e, --exit-on-fail Stop running if any single test fails.
This is useful if you are running something
configuration files with Urchin.
This can be useful if you are running something
other than test files with Urchin.
-T, --timeout <seconds> Kill a test if it runs for longer than the
specified duration. The default is no timeout.
-f, --force Force running even if the test directory's name
@@ -464,6 +555,8 @@ effect when combined with --tap.
-p, --pretty Print results in color and with fancy symbols.
-t, --tap Format output in Test Anything Protocol (TAP)
And these options affect how much is printed.
-q, --quiet Print nothing to stdout;
the only output is the exit code.
(default verbosity) Print names of failed tests and counts
@@ -471,14 +564,21 @@ effect when combined with --tap.
-v Print stdout from failing tests.
-vv Print names of passed tests.
-vvv, --verbose Print stdout from all tests.
-vvvv, --debug Print debugging messages (XXX not implemented)
-vvvv, --debug Run with set -x.
The remaining flags provide information about urchin.
-h, --help Display this help.
--version Display the version number.
Go to https://github.com/tlevine/urchin for documentation on writing tests.
Urchin recognizes certain environment variables.
TEST_SHELL This is sometimes over-ridden; see -s.
RUN_IN_SERIES Set this to true to have the same effect as
-b/--run-in-series. This is helpful if you are
calling urchin inside an urchin test suite.
Go to https://thomaslevine.com/!/urchin/ for documentation on writing tests.
EOF
}
@@ -504,9 +604,13 @@ validate_strings() {
}
main() {
argv="$@"
cycle_shell=true
shell_list="${urchin_tmp}"/shell_list
test_arg_list="${urchin_tmp}"/test_list
> "${test_arg_list}"
remotes_list="${urchin_tmp}"/remotes
run_in_series=false
force=false
exit_on_not_ok=false
@@ -537,14 +641,23 @@ main() {
validate_strings "${shell_for_sh_tests}" 'Shell paths'
if echo "${shell_for_sh_tests}" | grep -q \ ; then
echo "Warning: It is best if shell paths contain no spaces so that
you don't need to quote the TEST_SHELL variable." > /dev/stderr
you don't need to quote the TEST_SHELL variable." >&2
fi
echo "${shell_for_sh_tests}" >> "${shell_list}"
;;
-n|--disable-cycling) cycle_shell=false;;
-t|--tap) tap_format=true;;
-T|--timeout) shift; urchin_timeout="${1}" ;;
-T|--timeout)
shift
urchin_timeout="${1}"
if ! {
echo "${urchin_timeout}" |
grep '[0-9][0-9.]*\(s\|m\|h\|d\|\)'
}; then
echo Bad timeout argument: "${urchin_timeout}" >&2
urchin_exit 1
fi ;;
-p|--pretty) print_in_color=true;;
-q|--quiet) print_not_ok=false
@@ -555,7 +668,10 @@ main() {
-vvv|--verbose)print_not_ok_stdout=true
print_ok=true;
print_ok_stdout=true;;
-vvvv|--debug) echo 'Not implemented' > /dev/stderr && exit 1;;
-vvvv|--debug) print_not_ok_stdout=true
print_ok=true;
print_ok_stdout=true
set -x;;
-h|--help) urchin_help
urchin_exit 0;;
@@ -569,6 +685,9 @@ main() {
esac
shift
done
if "${RUN_IN_SERIES}" 2> /dev/null; then
run_in_series=true
fi
if $print_in_color; then
success_mark=✓
@@ -588,7 +707,7 @@ main() {
if ! test -f "${shell_list}"; then
if $cycle_shell; then
for shell in $DEFAULT_SHELLS; do
if which $shell > /dev/null; then
if which $shell 1> /dev/null 2> /dev/null; then
echo $shell >> "$shell_list"
fi
done
@@ -599,9 +718,9 @@ main() {
if test -n "${urchin_timeout}"; then
# Choose the timeout command
if timeout -t 0 true; then
if timeout -t 0 true 2> /dev/null; then
TIMEOUT="timeout -t ${urchin_timeout}"
elif timeout 0 true; then
elif timeout 0 true 2> /dev/null; then
TIMEOUT="timeout ${urchin_timeout}"
else
echo I couldn\'t figure out how to use your version of timeout >&2
@@ -615,7 +734,7 @@ main() {
fi
# -------------------- REALLY RUN -------------------- #
start=$(date +%s)
start=$("${epoch}")
# 1 test file or folder to run
# 2 urchin root
@@ -625,16 +744,42 @@ main() {
recurse "$(fullpath "${seed}")" "${root}" "${cycle_shell}" \
"${TEST_SHELL}" || break
done < "${test_arg_list}"
finish=$(date +%s)
finish=$("${epoch}")
test $(cat "${urchin_tmp}"/log | wc -l) -gt 0 || {
echo 'No tests found' > /dev/stderr
if test $(cat "${urchin_tmp}"/log | wc -l) -eq 0; then
echo 'No tests found' >&2
urchin_exit 1
}
fi
report_outcome "${root}" "${tap_format}" "${urchin_tmp}"/log "${start}" \
"${finish}"
urchin_exit "${?}"
if test -n "${RUNNING_ON_REMOTE}"; then
echo "${urchin_tmp}"
elif test -f "${remotes_list}"; then
while read remote; do
remote_main $remote "${argv}"
done < "${remotes_list}"
else
report_outcome "${root}" "${tap_format}" "${urchin_tmp}"/log \
"${start}" "${finish}"
urchin_exit "${?}"
fi
}
remote_main() {
hostname="${1}"; shift
flags="${1}"; shift
urchin_dir=.urchin-cross-shell-test
rsync --archive -e "ssh ${flags}"
../urchin ../tests "${hostname}":"${urchin_dir}" ||
scp -r ${flags} ../urchin ../tests "${hostname}":"${urchin_dir}"
remote_tmp="$(ssh "${hostname}" ${flags} "cd ${urchin_dir} && ./urchin $@")"
remotedir="${hostname}":"${remote_tmp}"
localdir="${urchin_tmp}/remote/${host}"
rsync --archive -e "ssh ${flags}" "${remotedir}" "${localdir}" ||
scp -r ${flags} "${remotedir}"
}
test -n "${TESTING_URCHIN_INTERNALS}" || main "$@"

Binary file not shown.

Before

Width:  |  Height:  |  Size: 99 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 115 KiB