Compare commits
89 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
fae4c7025e | ||
|
539027db59 | ||
|
5e2ecab592 | ||
|
efe3af6f87 | ||
|
f244c22055 | ||
|
2cdd3ec049 | ||
|
6744b2cb4a | ||
|
6e32dab0b7 | ||
|
bb3876f334 | ||
|
0dc6e01fbc | ||
|
ca71678522 | ||
|
9b4f14c937 | ||
|
27592e58ac | ||
|
42c09b775b | ||
|
2923d3a8b0 | ||
|
12f458a933 | ||
|
6c217acae8 | ||
|
6a7e58c944 | ||
|
32ac65cf3e | ||
|
d1c8f78585 | ||
|
132e1695db | ||
|
d67185ce25 | ||
|
16988c48a9 | ||
|
ddb74d43d8 | ||
|
04c4f54789 | ||
|
552d7d0dbc | ||
|
00c99773d0 | ||
|
7899657971 | ||
|
2ee965d2ae | ||
|
fdb0b1b3ea | ||
|
db3dd1c662 | ||
|
a9e0f856fb | ||
|
72f0700598 | ||
|
a486a6f296 | ||
|
a9ba8e79d3 | ||
|
586f46600a | ||
|
940cd549ab | ||
|
cd7f773d58 | ||
|
0de2c3264a | ||
|
fc51c34019 | ||
|
c61d31fcea | ||
|
6275c28ebf | ||
|
b0a7a8b07a | ||
|
f7ffd82893 | ||
|
a5ffad0446 | ||
|
b402f466b5 | ||
|
7a34da0906 | ||
|
3ebe974202 | ||
|
a957ca9065 | ||
|
3122b2cc63 | ||
|
4f7541b1fd | ||
|
5b2ab72ee1 | ||
|
73035208d3 | ||
|
64530e8920 | ||
|
e66551f50f | ||
|
d42079ef38 | ||
|
5c24879dd8 | ||
|
9ea757722a | ||
|
72ea60bb8d | ||
|
edda2a0e90 | ||
|
3c5593c812 | ||
|
ce9273abfc | ||
|
406e5c360c | ||
|
cac691805c | ||
|
635bcc83f2 | ||
|
1abba45a39 | ||
|
79ebe8e3f2 | ||
|
e4b2a4e7ea | ||
|
da10808f2a | ||
|
3e83e2cb30 | ||
|
2b4444dbed | ||
|
5604ec97d6 | ||
|
8ecea33c16 | ||
|
dd12693da1 | ||
|
9f76434bfc | ||
|
c96c2d2157 | ||
|
9b4c502d25 | ||
|
74651bd169 | ||
|
a7c44cab70 | ||
|
5cbafb2a78 | ||
|
406d6f43f8 | ||
|
1a4b8674ea | ||
|
6a0e9f3e64 | ||
|
5ab6a53961 | ||
|
edec12c2c0 | ||
|
8b9747a997 | ||
|
5864d81f55 | ||
|
5cd182ff8f | ||
|
de8bda1b32 |
31
HISTORY
31
HISTORY
@@ -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
|
||||
@@ -12,18 +20,18 @@ test suite, as we need to know how far up to apply the setup
|
||||
and teardown files.
|
||||
|
||||
The Urchin root directory is determined by moving higher in the directory
|
||||
tree in search of a file named `.urchin`.
|
||||
tree in search of a file named `.urchin_root`.
|
||||
The closest directory that contains such a file is considered the root.
|
||||
In the following filesystem, for example, `/a/b/c` would be the root.
|
||||
|
||||
mkdir -p /a/b/c/d
|
||||
touch /a/b/c/d/e
|
||||
chmod +x /a/b/c/d/e
|
||||
touch /a/b/c/.urchin
|
||||
touch /a/b/c/.urchin_root
|
||||
urchin /a/b/c/d
|
||||
|
||||
There are two situations in which we would stop looking without having
|
||||
found a `.urchin` file.
|
||||
found a `.urchin_root` file.
|
||||
|
||||
1. The system root, `/`, because we can't go any higher
|
||||
2. A directory that starts with a dot, because an urchin call on a higher
|
||||
@@ -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 ...
|
||||
@@ -97,6 +105,13 @@ turned on.
|
||||
|
||||
Parallel processing and shell cycling are both enabled by default.
|
||||
|
||||
You may want make only some directories run in series, you can create
|
||||
".urchin_dir" files in those directories.
|
||||
If .urchin_dir contains the phrase "series", run that directory in series
|
||||
rather than in parallel.
|
||||
This is helpful when directories actually need to run in series
|
||||
and also when running all your tests in parallel crashes your computer.
|
||||
|
||||
### Options
|
||||
Long options are now available for all command line flags.
|
||||
For example, the `-s` flag is now available as `--shell` as well.
|
||||
@@ -164,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.
|
||||
@@ -229,7 +240,7 @@ other Urchin call), and the test suite is recursively descended. Setup and
|
||||
teardown files are sourced, and everything but the specified test file is
|
||||
otherwise ignored.
|
||||
|
||||
If you don't explicitly specify the Urchin root with a .urchin file, we
|
||||
If you don't explicitly specify the Urchin root with a .urchin_root file, we
|
||||
consider the test suite root directory to be the parent of the file that
|
||||
you ran Urchin on.
|
||||
|
||||
|
8
Makefile
Normal file
8
Makefile
Normal file
@@ -0,0 +1,8 @@
|
||||
.PHONY: test install
|
||||
|
||||
test:
|
||||
./urchin tests
|
||||
./urchin -s sh -v ./cross-os-tests
|
||||
|
||||
install:
|
||||
cp ./urchin /usr/bin
|
82
SORTING
82
SORTING
@@ -1,5 +1,67 @@
|
||||
On the criteria for ordering
|
||||
==============================
|
||||
|
||||
I was confused by the documentation for sort's "-d" flag. This confusion
|
||||
relates to GNU coreutil's locale-specific sort. [^]
|
||||
|
||||
Below I discuss sort order differences between different implementations
|
||||
of sort and of sh "*" for my particular environments.
|
||||
|
||||
Sorting with sort
|
||||
------------
|
||||
Consider the following two sort commands.
|
||||
|
||||
printf '@ b\n- d\n? a\n~ c\n! e\n' | sort
|
||||
printf '@ b\n- d\n? a\n~ c\n! e\n' | sort -d
|
||||
|
||||
With BusyBox v1.23.2 on NixOS 15.09, the first of these commands returns
|
||||
ASCIIbetical order,
|
||||
|
||||
! e
|
||||
- d
|
||||
? a
|
||||
@ b
|
||||
~ c
|
||||
|
||||
and the second returns dictionary order.
|
||||
|
||||
? a
|
||||
@ b
|
||||
~ c
|
||||
- d
|
||||
! e
|
||||
|
||||
With GNU coreutils version 8.24 on NixOS, both commands return
|
||||
dictionary order. The same is true for GNU coreutils version 8.23 on
|
||||
Debian Wheezy.
|
||||
|
||||
? a
|
||||
@ b
|
||||
~ c
|
||||
- d
|
||||
! e
|
||||
|
||||
IEEE Std 1003.1, 2013 Edition [^^] specifies that the "-d" flag should
|
||||
enable dictionary order. All of these versions of sort have clear
|
||||
documentation about the order that should be returned when the "-d" flag
|
||||
is set, (See --help, man, or info.) and the implementations match the
|
||||
documentation as far as I can tell.
|
||||
|
||||
I have found no explicit documentation from any relevant source as to
|
||||
what the default sort order should be. On the other hand, they all
|
||||
suggest that "-d" produces an order different from the default order.
|
||||
|
||||
In GNU coreutils 8.24, for example, "-d" is a direction to "consider
|
||||
only blanks and alphanumeric characters". It lacks any mention that the
|
||||
"-d" flag has no effect or that it is the default. Furthermore, on my
|
||||
first reading, I took it to mean that the default is to consider all
|
||||
characters and that "-d" limits the considered characters to blanks and
|
||||
alphanumeric characters.
|
||||
|
||||
|
||||
Sorting in *
|
||||
-------------
|
||||
I think this is related to the order returned by "*" in sh.
|
||||
The following sh code creates several files in a directory and then
|
||||
calls "*", listing them in order.
|
||||
|
||||
@@ -8,7 +70,8 @@ calls "*", listing them in order.
|
||||
done
|
||||
for file in *; do echo "$file"; done
|
||||
|
||||
On one computer, running FreeBSD, the order is apparently ASCIIbetical.
|
||||
On one computer, running FreeBSD, the order is apparently
|
||||
ASCIIbetical.
|
||||
|
||||
! e
|
||||
- d
|
||||
@@ -16,7 +79,7 @@ On one computer, running FreeBSD, the order is apparently ASCIIbetical.
|
||||
@ b
|
||||
~ c
|
||||
|
||||
On another computer, running NixOS, the following commands print results
|
||||
On two GNU systems, running NixOS and Debian, respectively, output is
|
||||
in dictionary order. I'm not exactly sure what dictionary order is, but
|
||||
it is something like sorting on the alphabetical characters before
|
||||
sorting on the rest of the line.
|
||||
@@ -27,16 +90,9 @@ sorting on the rest of the line.
|
||||
- d
|
||||
! e
|
||||
|
||||
While I don't really know what dictionary order is, I was able to determine
|
||||
(I don't really know what dictionary order is, I was able to determine
|
||||
that the above results are in dictionary order because of my investigation of
|
||||
incompatible implementations of sort. Consider the following two sort
|
||||
commands.
|
||||
incompatible implementations of sort.)
|
||||
|
||||
printf '@ b\n- d\n? a\n~ c\n! e\n' | sort
|
||||
printf '@ b\n- d\n? a\n~ c\n! e\n' | sort -d
|
||||
|
||||
With BSD sort, the first of these commands print ASCIIbetical order and
|
||||
the second prints dictionary order. With GNU sort, both print dictionary
|
||||
order.
|
||||
|
||||
How annoying.
|
||||
[^] https://www.gnu.org/software/coreutils/faq/coreutils-faq.html#Sort-does-not-sort-in-normal-order_0021
|
||||
[^^] http://pubs.opengroup.org/onlinepubs/9699919799/
|
||||
|
74
TODO
74
TODO
@@ -26,11 +26,14 @@ Windows
|
||||
Try running Urchin in Windows somehow. Interpreters include
|
||||
|
||||
* CygWin (https://www.cygwin.com/)
|
||||
* https://cygwin.com/setup-x86.exe
|
||||
* MSYS (http://mingw.org/wiki/msys)
|
||||
* GNU on Windows (https://github.com/bmatzelle/gow/wiki)
|
||||
* Git for Windows (https://git-scm.com/download/win)
|
||||
* https://github.com/git-for-windows/git/releases/download/v2.7.2.windows.1/Git-2.7.2-32-bit.exe
|
||||
* win-bash (http://win-bash.sourceforge.net/)
|
||||
|
||||
|
||||
shall
|
||||
----------
|
||||
Add shall to my NYC*BUG talk.
|
||||
@@ -46,15 +49,68 @@ List some shell linters somewhere.
|
||||
* checkbashisms
|
||||
|
||||
|
||||
Set parallel and series
|
||||
----------
|
||||
I want to be able to make only some directories run in series.
|
||||
|
||||
* Rename .urchin to .urchin_root.
|
||||
* Look for a .urchin_dir file.
|
||||
* If .urchin_dir contains "series", run that directory in series rather
|
||||
than in parallel.
|
||||
|
||||
Rename to something other than "test"?
|
||||
----------
|
||||
Maybe wait until I have a use for this.
|
||||
|
||||
More sort alternatives
|
||||
-----------
|
||||
awk
|
||||
https://stackoverflow.com/questions/20250937/sorting-lines-in-a-file-alphabetically-using-awk-and-or-sed
|
||||
bash
|
||||
https://stackoverflow.com/questions/7442417/how-to-sort-an-array-in-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
|
||||
|
||||
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
|
||||
|
||||
|
13
cross-os-tests/.run
Executable file
13
cross-os-tests/.run
Executable file
@@ -0,0 +1,13 @@
|
||||
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}"
|
||||
ssh "${hostname}" ${flags} \
|
||||
"cd ${urchin_dir} && ./urchin --run-in-series tests"
|
2
cross-os-tests/tlevine@centos.polarhome.com -p 925
Executable file
2
cross-os-tests/tlevine@centos.polarhome.com -p 925
Executable file
@@ -0,0 +1,2 @@
|
||||
#!/bin/sh
|
||||
. ./.run
|
3
cross-os-tests/tlevine@dada.pink
Executable file
3
cross-os-tests/tlevine@dada.pink
Executable file
@@ -0,0 +1,3 @@
|
||||
#!/bin/sh
|
||||
# apt-get install bash dash ksh posh pdksh mksh yash zsh
|
||||
. ./.run
|
2
cross-os-tests/tlevine@debian-ppc.polarhome.com -p 625
Executable file
2
cross-os-tests/tlevine@debian-ppc.polarhome.com -p 625
Executable file
@@ -0,0 +1,2 @@
|
||||
#!/bin/sh
|
||||
. ./.run
|
2
cross-os-tests/tlevine@debian.polarhome.com -p 755
Executable file
2
cross-os-tests/tlevine@debian.polarhome.com -p 755
Executable file
@@ -0,0 +1,2 @@
|
||||
#!/bin/sh
|
||||
. ./.run
|
2
cross-os-tests/tlevine@dragonfly.polarhome.com -p 915
Executable file
2
cross-os-tests/tlevine@dragonfly.polarhome.com -p 915
Executable file
@@ -0,0 +1,2 @@
|
||||
#!/bin/sh
|
||||
. ./.run
|
2
cross-os-tests/tlevine@freebsd.polarhome.com -p 715
Executable file
2
cross-os-tests/tlevine@freebsd.polarhome.com -p 715
Executable file
@@ -0,0 +1,2 @@
|
||||
#!/bin/sh
|
||||
. ./.run
|
2
cross-os-tests/tlevine@hpux-ia64.polarhome.com -p 965
Executable file
2
cross-os-tests/tlevine@hpux-ia64.polarhome.com -p 965
Executable file
@@ -0,0 +1,2 @@
|
||||
#!/bin/sh
|
||||
. ./.run
|
3
cross-os-tests/tlevine@hpux.polarhome.com -p 785
Executable file
3
cross-os-tests/tlevine@hpux.polarhome.com -p 785
Executable file
@@ -0,0 +1,3 @@
|
||||
#!/bin/sh
|
||||
RSYNC_FLAGS='--rsync-path=/usr/local/bin/rsync'
|
||||
. ./.run
|
2
cross-os-tests/tlevine@irix.polarhome.com -p 825
Executable file
2
cross-os-tests/tlevine@irix.polarhome.com -p 825
Executable file
@@ -0,0 +1,2 @@
|
||||
#!/bin/sh
|
||||
. ./.run
|
3
cross-os-tests/tlevine@miros.polarhome.com -p 935
Executable file
3
cross-os-tests/tlevine@miros.polarhome.com -p 935
Executable file
@@ -0,0 +1,3 @@
|
||||
#!/bin/sh
|
||||
# SSH public key needs to be in ~/.etc/ssh/authorized_keys
|
||||
. ./.run
|
2
cross-os-tests/tlevine@netbsd.polarhome.com -p 745
Executable file
2
cross-os-tests/tlevine@netbsd.polarhome.com -p 745
Executable file
@@ -0,0 +1,2 @@
|
||||
#!/bin/sh
|
||||
. ./.run
|
2
cross-os-tests/tlevine@openbsd.polarhome.com -p 735
Executable file
2
cross-os-tests/tlevine@openbsd.polarhome.com -p 735
Executable file
@@ -0,0 +1,2 @@
|
||||
#!/bin/sh
|
||||
. ./.run
|
2
cross-os-tests/tlevine@openindiana.polarhome.com -p 845
Executable file
2
cross-os-tests/tlevine@openindiana.polarhome.com -p 845
Executable file
@@ -0,0 +1,2 @@
|
||||
#!/bin/sh
|
||||
. ./.run
|
2
cross-os-tests/tlevine@pidora.polarhome.com -p 615
Executable file
2
cross-os-tests/tlevine@pidora.polarhome.com -p 615
Executable file
@@ -0,0 +1,2 @@
|
||||
#!/bin/sh
|
||||
. ./.run
|
2
cross-os-tests/tlevine@qnx.polarhome.com -p 815
Executable file
2
cross-os-tests/tlevine@qnx.polarhome.com -p 815
Executable file
@@ -0,0 +1,2 @@
|
||||
#!/bin/sh
|
||||
. ./.run
|
2
cross-os-tests/tlevine@raspbian.polarhome.com -p 975
Executable file
2
cross-os-tests/tlevine@raspbian.polarhome.com -p 975
Executable file
@@ -0,0 +1,2 @@
|
||||
#!/bin/sh
|
||||
. ./.run
|
2
cross-os-tests/tlevine@redhat.polarhome.com -p 795
Executable file
2
cross-os-tests/tlevine@redhat.polarhome.com -p 795
Executable file
@@ -0,0 +1,2 @@
|
||||
#!/bin/sh
|
||||
. ./.run
|
2
cross-os-tests/tlevine@scosysv.polarhome.com -p 895
Executable file
2
cross-os-tests/tlevine@scosysv.polarhome.com -p 895
Executable file
@@ -0,0 +1,2 @@
|
||||
#!/bin/sh
|
||||
. ./.run
|
2
cross-os-tests/tlevine@solaris-x86.polarhome.com -p 865
Executable file
2
cross-os-tests/tlevine@solaris-x86.polarhome.com -p 865
Executable file
@@ -0,0 +1,2 @@
|
||||
#!/bin/sh
|
||||
. ./.run
|
2
cross-os-tests/tlevine@solaris.polarhome.com -p 725
Executable file
2
cross-os-tests/tlevine@solaris.polarhome.com -p 725
Executable file
@@ -0,0 +1,2 @@
|
||||
#!/bin/sh
|
||||
. ./.run
|
2
cross-os-tests/tlevine@tru64.polarhome.com -p 835
Executable file
2
cross-os-tests/tlevine@tru64.polarhome.com -p 835
Executable file
@@ -0,0 +1,2 @@
|
||||
#!/bin/sh
|
||||
. ./.run
|
2
cross-os-tests/tlevine@ubuntu.polarhome.com -p 885
Executable file
2
cross-os-tests/tlevine@ubuntu.polarhome.com -p 885
Executable file
@@ -0,0 +1,2 @@
|
||||
#!/bin/sh
|
||||
. ./.run
|
2
cross-os-tests/tlevine@unixware.polarhome.com -p 905
Executable file
2
cross-os-tests/tlevine@unixware.polarhome.com -p 905
Executable file
@@ -0,0 +1,2 @@
|
||||
#!/bin/sh
|
||||
. ./.run
|
1
packages/.gitignore
vendored
Normal file
1
packages/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
*.tar.gz
|
11
packages/nongnu.sh
Executable file
11
packages/nongnu.sh
Executable 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
|
55
readme.md
55
readme.md
@@ -43,25 +43,15 @@ Urchin depends on the following programs.
|
||||
* timeout
|
||||
* sort
|
||||
|
||||
All of the above programs are usually included on base BSD installations.
|
||||
On GNU systems it should be sufficient to install the busybox package.
|
||||
|
||||
Urchin uses sort to format its output. GNU sort (as of GNU coreutils version
|
||||
8.24) lacks the ability to sort in lexicographic order, and this feature is
|
||||
necessary for the output to look right. If your version of sort lacks this
|
||||
feature, Urchin will try to use one of the following tools for sorting.
|
||||
|
||||
If no acceptable sorting program is available, Urchin will print a warning
|
||||
and use the incomplete sort that is installed on your system. This is not a
|
||||
big deal; if your test files all start with alphanumeric letters, the output
|
||||
should look fine.
|
||||
Vanilla installations of modern BSD and GNU systems usually include all
|
||||
of these programs.
|
||||
|
||||
## Install
|
||||
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.
|
||||
@@ -118,14 +108,36 @@ Files are only run if they are executable, and files beginning with `.` are
|
||||
ignored. Thus, fixtures and libraries can be included sloppily within the test
|
||||
directory tree. The test passes if the file exits 0; otherwise, it fails.
|
||||
|
||||
Tests files and subdirectories are run in ASCIIbetical order within each
|
||||
directory; that is,
|
||||
urchin looks for files within a directory in the following manner.
|
||||
urchin looks for files within a directory in the following manner,
|
||||
|
||||
for file in *; do
|
||||
do_something_with_test_file $file
|
||||
done
|
||||
|
||||
so files are run in whatever order `*` produces. The order is
|
||||
configured in your environment, at least in
|
||||
[GNU systems](https://www.gnu.org/software/coreutils/faq/coreutils-faq.html#Sort-does-not-sort-in-normal-order_0021).
|
||||
Other systems may ignore the locales configured in the environment and
|
||||
always produce ASCIIbetical order.
|
||||
|
||||
Results are always printed in ASCIIbetical order, regardless of what
|
||||
order the tests ran in.
|
||||
|
||||
Below you can see how the locale can affect the order.
|
||||
|
||||
$ printf '!c\n@a\n~b\n' | LC_COLLATE=C sort
|
||||
!c
|
||||
@a
|
||||
~b
|
||||
$ printf '!c\n@a\n~b\n' | LC_COLLATE=en_US.UTF-8 sort
|
||||
@a
|
||||
~b
|
||||
!c
|
||||
$ printf '!c\n@a\n~b\n' | sort -d
|
||||
@a
|
||||
~b
|
||||
!c
|
||||
|
||||
### Writing cross-shell compatibility tests for testing shell code
|
||||
|
||||
While you could write your test scripts to explicitly invoke the functionality
|
||||
@@ -179,14 +191,9 @@ shell.)
|
||||
|
||||
Note that only test scripts that either have no shebang line at all or
|
||||
have shebang line `#!/bin/sh` are invoked with the specified shell.
|
||||
This allows non-shell test scripts or test scripts for specific
|
||||
shells to coexist with those whose invocation should be controlled by `-s`.
|
||||
|
||||
To test with multiple shells in sequence, use something like:
|
||||
|
||||
for shell in sh bash ksh zsh; do
|
||||
urchin -s $shell ./tests
|
||||
done
|
||||
This allows non-shell test scripts or test scripts for other languages
|
||||
or for specific shells to coexist with those whose invocation should be
|
||||
controlled by `-s`.
|
||||
|
||||
## References
|
||||
|
||||
|
1
tests/.urchin_dir
Normal file
1
tests/.urchin_dir
Normal file
@@ -0,0 +1 @@
|
||||
series
|
@@ -1,6 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
# This script should run with /bin/sh
|
||||
# regardless of whether -s or -n is passed.
|
||||
|
||||
ps -o pid,comm,args | grep $$ | grep /bin/sh
|
@@ -0,0 +1,6 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Assuming that urchin was invoked with `-s bash`,
|
||||
# this script should be being run with bash.
|
||||
|
||||
ps -o pid,comm,args | grep $$ | grep .special-shell
|
@@ -1 +1 @@
|
||||
! $TEST_SHELL ../../urchin ../Flags/Urchin\ format|grep -- --color
|
||||
! $TEST_SHELL ../../urchin ../Flags/Urchin\ format|grep -- --pretty
|
||||
|
2
tests/Flags/--timeout error message
Executable file
2
tests/Flags/--timeout error message
Executable file
@@ -0,0 +1,2 @@
|
||||
../../urchin -T aoeu .testsuite 2>&1 | grep Bad
|
||||
../../urchin -T .testsuite 2>&1 | grep Bad
|
@@ -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
4
tests/Flags/--timeout output
Executable 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
1
tests/Flags/--timeout success
Executable file
@@ -0,0 +1 @@
|
||||
$TEST_SHELL ../../urchin --shell sh .slow-tests --timeout 1000
|
@@ -1,7 +1,7 @@
|
||||
#!/bin/sh
|
||||
set -e
|
||||
|
||||
! $TEST_SHELL ../../urchin --run-in-series --exit-on-fail \
|
||||
! $TEST_SHELL ../../urchin -vv --run-in-series --exit-on-fail \
|
||||
./.test_-e,--exit-on-fail > $tmp
|
||||
|
||||
grep '1 should run.' $tmp
|
||||
|
@@ -1,11 +1,11 @@
|
||||
|
||||
./
|
||||
> a
|
||||
✗ sh (1 second)
|
||||
# This is stdout from a.
|
||||
F sh (1 second)
|
||||
| This is stdout from a.
|
||||
./
|
||||
> b
|
||||
✓ sh (1 second)
|
||||
. sh (1 second)
|
||||
./
|
||||
> c
|
||||
(File is not executable.)
|
||||
|
@@ -2,7 +2,7 @@
|
||||
./
|
||||
> a
|
||||
[31m✗ [0msh (1 second)
|
||||
# This is stdout from a.
|
||||
| This is stdout from a.
|
||||
./
|
||||
> b
|
||||
[32m✓ [0msh (1 second)
|
||||
|
@@ -1,3 +1,3 @@
|
||||
$TEST_SHELL ../../urchin -s sh -t .testsuite/ |
|
||||
$TEST_SHELL ../../urchin -v -s sh -t .testsuite/ |
|
||||
sed -e 1d -e /second/d > $tmp
|
||||
diff $tmp .tap-output-expectation
|
||||
|
@@ -1,3 +1,3 @@
|
||||
$TEST_SHELL ../../urchin --color -vv --shell sh .testsuite/ |
|
||||
$TEST_SHELL ../../urchin --pretty -vv --shell sh .testsuite/ |
|
||||
sed -e 1d -e 's/. seconds\?/1 second/' > $tmp
|
||||
diff $tmp .urchin-output-expectation-color
|
||||
|
3
tests/Internals/has_shebang_line/.run
Executable file
3
tests/Internals/has_shebang_line/.run
Executable file
@@ -0,0 +1,3 @@
|
||||
echo "$1" > $tmp
|
||||
TESTING_URCHIN_INTERNALS=true . ../../../urchin
|
||||
has_shebang_line $tmp
|
1
tests/Internals/has_shebang_line/bash
Executable file
1
tests/Internals/has_shebang_line/bash
Executable file
@@ -0,0 +1 @@
|
||||
./.run '#!/bin/bash'
|
1
tests/Internals/has_shebang_line/empty
Executable file
1
tests/Internals/has_shebang_line/empty
Executable file
@@ -0,0 +1 @@
|
||||
! ./.run ''
|
5
tests/Internals/has_shebang_line/empty-line
Executable file
5
tests/Internals/has_shebang_line/empty-line
Executable file
@@ -0,0 +1,5 @@
|
||||
! ./.run '
|
||||
|
||||
|
||||
|
||||
'
|
1
tests/Internals/has_shebang_line/env
Executable file
1
tests/Internals/has_shebang_line/env
Executable file
@@ -0,0 +1 @@
|
||||
./.run '#!/usr/bin/env true'
|
1
tests/Internals/has_shebang_line/setup
Normal file
1
tests/Internals/has_shebang_line/setup
Normal file
@@ -0,0 +1 @@
|
||||
export tmp=$(mktemp)
|
1
tests/Internals/has_shebang_line/sh
Executable file
1
tests/Internals/has_shebang_line/sh
Executable file
@@ -0,0 +1 @@
|
||||
! ./.run '#!/bin/sh'
|
1
tests/Internals/has_shebang_line/teardown
Normal file
1
tests/Internals/has_shebang_line/teardown
Normal file
@@ -0,0 +1 @@
|
||||
rm -R "$tmp"
|
@@ -1,4 +0,0 @@
|
||||
set -e
|
||||
TESTING_URCHIN_INTERNALS=true . ../../urchin
|
||||
unsorted='@ b\n- d\n? a\n~ c\n! e\n'
|
||||
test $(printf "${unsorted}" | sort_python | cut -d\ -f2|tr -d '\n') = edabc
|
3
tests/Setup and Teardown/.test/setup count a
Executable file
3
tests/Setup and Teardown/.test/setup count a
Executable file
@@ -0,0 +1,3 @@
|
||||
#!/bin/sh
|
||||
|
||||
[ $(grep -c 'setup has run' $log) -eq '1' ]
|
3
tests/Setup and Teardown/.test/setup count b
Executable file
3
tests/Setup and Teardown/.test/setup count b
Executable file
@@ -0,0 +1,3 @@
|
||||
#!/bin/sh
|
||||
|
||||
[ $(grep -c 'setup has run' $log) -eq '2' ]
|
@@ -1,3 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
[ $(grep -c 'setup has run' $log) -gt '2' ]
|
@@ -1,3 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
[ $(grep -c 'setup has run' $log) -gt '2' ]
|
256
urchin
256
urchin
@@ -51,7 +51,17 @@ 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
|
||||
@@ -70,7 +80,7 @@ validate_test_arg() {
|
||||
root="$(urchin_root "${1}")"
|
||||
if ! {
|
||||
basename "$(fullpath "${root}")" |
|
||||
grep -i 'test' > /dev/null || "${force}"
|
||||
grep -qi 'test' || "${force}"
|
||||
}; then
|
||||
echo 'The root directory of the tests that you are running urchin on
|
||||
does not contain the word "test", so I am not running,
|
||||
@@ -80,28 +90,45 @@ validate_test_arg() {
|
||||
fi
|
||||
}
|
||||
|
||||
sort_python() {
|
||||
python -c 'import sys
|
||||
for line in sorted(sys.stdin.readlines()):
|
||||
sys.stdout.write(line)
|
||||
'
|
||||
}
|
||||
|
||||
# All temporary files go here
|
||||
urchin_tmp=$(mktemp -d)
|
||||
urchin_tmp=$(mktemp)
|
||||
|
||||
# Support HP-UX mktemp that has wrong exit codes and
|
||||
# can't make directories.
|
||||
if test -f "${urchin_tmp}"; then
|
||||
rm "${urchin_tmp}"
|
||||
fi
|
||||
mkdir "${urchin_tmp}"
|
||||
|
||||
> "${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
|
||||
|
||||
|
||||
stdout_file() {
|
||||
the_test="${1}"
|
||||
the_shell="${2}"
|
||||
|
||||
x="${urchin_tmp}/stdout$(fullpath "$the_test")"
|
||||
mkdir -p "${x}"
|
||||
echo "${x}/$(echo "${the_shell}" | md5sum | cut -d\ -f1)"
|
||||
case "${urchin_md5}" in
|
||||
md5sum) y=$(echo "${the_shell}" | md5sum | cut -d\ -f1) ;;
|
||||
md5) y=$(echo "${the_shell}" | md5 -q) ;;
|
||||
*) echo md5 command is not configured >&2; urchin_exit 1;;
|
||||
esac
|
||||
echo "${x}/${y}"
|
||||
}
|
||||
|
||||
# Expand relative paths
|
||||
@@ -124,7 +151,7 @@ urchin_root() {
|
||||
|
||||
abscurrent="$(fullpath "${1}")"
|
||||
if test "${abscurrent}" = / ||
|
||||
basename "${abscurrent}" | grep '^\.' > /dev/null; then
|
||||
basename "${abscurrent}" | grep -q '^\.' ; then
|
||||
# Stop traversing upwards at / and at hidden directories.
|
||||
if test -d "${orig}"; then
|
||||
echo "${orig}"
|
||||
@@ -136,7 +163,7 @@ urchin_root() {
|
||||
return 1
|
||||
elif test -f "${current}"; then
|
||||
urchin_root "$(dirname -- "${current}")" "${orig}"
|
||||
elif test -f "${current}"/.urchin; then
|
||||
elif test -f "${current}"/.urchin_root; then
|
||||
remove_trailing_slash "${current}"
|
||||
else
|
||||
urchin_root "${current}"/.. "${orig}"
|
||||
@@ -144,7 +171,7 @@ urchin_root() {
|
||||
}
|
||||
|
||||
# Urchin version number
|
||||
VERSION=0.1.0-rc1
|
||||
VERSION=0.1.1-unstable
|
||||
|
||||
indent() {
|
||||
level="${1}"
|
||||
@@ -159,14 +186,18 @@ recurse() {
|
||||
cycle_shell="${3}"
|
||||
TEST_SHELL="${4}"
|
||||
|
||||
if $print_debug; then
|
||||
echo Entered directory "${PWD}"
|
||||
fi
|
||||
|
||||
for ignore in setup_dir teardown_dir setup teardown; do
|
||||
if test "$(basename "${potential_test}")" = "${ignore}"; then
|
||||
return
|
||||
fi
|
||||
done
|
||||
|
||||
if echo "${requested_path}" | grep "^${potential_test}" > /dev/null ||
|
||||
echo "${potential_test}" | grep "^${requested_path}" > /dev/null; then
|
||||
if echo "${requested_path}" | grep -q "^${potential_test}" ||
|
||||
echo "${potential_test}" | grep -q "^${requested_path}" ; then
|
||||
if test "$(dirname "${potential_test}")" = \
|
||||
"$(dirname "${requested_path}")" &&
|
||||
test "${potential_test}" != "${requested_path}"; then
|
||||
@@ -182,7 +213,18 @@ recurse() {
|
||||
if [ -d "${potential_test}" ]; then
|
||||
(
|
||||
cd -- "${potential_test}"
|
||||
if test -f setup_dir; then . ./setup_dir; fi
|
||||
if test -f .urchin_dir && grep -q series .urchin_dir ; then
|
||||
run_in_series_dir=true
|
||||
else
|
||||
run_in_series_dir=false
|
||||
fi
|
||||
|
||||
if test -f setup_dir; then
|
||||
if $print_debug; then
|
||||
echo Sourcing "${PWD}/setup_dir"
|
||||
fi
|
||||
. ./setup_dir
|
||||
fi
|
||||
|
||||
for test in *; do
|
||||
if test "${test}" = '*' && ! test -e "${test}"; then
|
||||
@@ -190,37 +232,47 @@ recurse() {
|
||||
break
|
||||
fi
|
||||
|
||||
(
|
||||
if test -f setup; then . ./setup; fi
|
||||
if recurse "${requested_path}" "${test}" "${cycle_shell}" \
|
||||
"${TEST_SHELL}"; then
|
||||
exit_code=0
|
||||
else
|
||||
exit_code="${?}"
|
||||
fi
|
||||
if test -f teardown; then . ./teardown; fi
|
||||
exit "${exit_code}"
|
||||
) &
|
||||
recurse "${requested_path}" "${test}" "${cycle_shell}" \
|
||||
"${TEST_SHELL}" &
|
||||
|
||||
if "${run_in_series}"; then
|
||||
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
|
||||
if $print_debug; then
|
||||
echo Sourcing "${PWD}/teardown_dir"
|
||||
fi
|
||||
. ./teardown_dir
|
||||
fi
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
done
|
||||
wait
|
||||
if test -f teardown_dir; then . ./teardown_dir; fi
|
||||
if test -f teardown_dir; then
|
||||
if $print_debug; then
|
||||
echo Sourcing "${PWD}/teardown_dir"
|
||||
fi
|
||||
. ./teardown_dir
|
||||
fi
|
||||
)
|
||||
elif [ -f "${potential_test}" ]; then
|
||||
cd -- "$(dirname -- "${potential_test}")"
|
||||
|
||||
if $print_debug; then
|
||||
echo Running "${potential_test}"
|
||||
fi
|
||||
|
||||
# Determine the environment variable to define for test scripts
|
||||
# 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
|
||||
if $print_debug; then
|
||||
echo Sourcing "${PWD}/setup"
|
||||
fi
|
||||
. ./setup
|
||||
fi
|
||||
|
||||
# Run the test
|
||||
start=$(date +%s)
|
||||
@@ -247,7 +299,12 @@ recurse() {
|
||||
set -e
|
||||
finish=$(date +%s)
|
||||
|
||||
if test -f teardown; then . ./setup; fi
|
||||
if test -f teardown; then
|
||||
if $print_debug; then
|
||||
echo Sourcing "${PWD}/teardown"
|
||||
fi
|
||||
. ./teardown
|
||||
fi
|
||||
|
||||
if [ "${exit_code}" -eq 0 ]; then
|
||||
result=ok
|
||||
@@ -266,14 +323,19 @@ 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
|
||||
if $print_debug; then
|
||||
echo Sourcing "${PWD}/teardown_dir"
|
||||
fi
|
||||
. ./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 ''
|
||||
@@ -285,11 +347,9 @@ report_outcome() {
|
||||
root="${1}"
|
||||
tap_format="${2}"
|
||||
log_file="${3}"
|
||||
start="${4}"
|
||||
finish="${5}"
|
||||
elapsed="${4}"
|
||||
|
||||
escaped_root="$(fullpath "${root}" | sed 's/\//\\\//g')"
|
||||
elapsed=$(($finish - $start))
|
||||
|
||||
if "${tap_format}"; then
|
||||
printf \#\
|
||||
@@ -305,7 +365,7 @@ report_outcome() {
|
||||
# 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}" | "${sort}" > "${sorted_log_file}"
|
||||
cat "${log_file}" | LC_COLLATE=C sort > "${sorted_log_file}"
|
||||
|
||||
while read line; do
|
||||
abspath=$(echo "${line}" | cut -f1)
|
||||
@@ -356,15 +416,15 @@ report_outcome() {
|
||||
printf "$(dirname -- "${path}")/\n> $(basename -- "${path}")\n"
|
||||
fi
|
||||
}
|
||||
|
||||
case "${result}" in
|
||||
ok)
|
||||
if "${print_ok}"; then
|
||||
header
|
||||
# On success, print a green '✓'
|
||||
if "${print_in_color}"; then
|
||||
printf '\033[32m✓ \033[0m'
|
||||
printf "\033[32m${success_mark} \033[0m"
|
||||
else
|
||||
printf '✓ '
|
||||
printf "${success_mark} "
|
||||
fi
|
||||
echo "${the_shell} ("${file_elapsed}" $(plural second $file_elapsed))"
|
||||
fi
|
||||
@@ -372,11 +432,10 @@ report_outcome() {
|
||||
not_ok)
|
||||
if "${print_not_ok}"; then
|
||||
header
|
||||
# On not_ok, print a red '✗'
|
||||
if "${print_in_color}"; then
|
||||
printf '\033[31m✗ \033[0m'
|
||||
printf "\033[31m${fail_mark} \033[0m"
|
||||
else
|
||||
printf '✗ '
|
||||
printf "${fail_mark} "
|
||||
fi
|
||||
echo "${the_shell} ("${file_elapsed}" $(plural second $file_elapsed))"
|
||||
fi
|
||||
@@ -394,7 +453,7 @@ report_outcome() {
|
||||
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}")"
|
||||
fi
|
||||
fi
|
||||
|
||||
@@ -424,10 +483,10 @@ report_outcome() {
|
||||
}
|
||||
|
||||
has_shebang_line() {
|
||||
head -n 1 "${1}" | grep -qE '^#!'
|
||||
head -n 1 "${1}" | grep -v '^#!/bin/sh$' | grep -q '^#!'
|
||||
}
|
||||
|
||||
USAGE="usage: $0 [<options>] <test directory>"
|
||||
USAGE="usage: $0 [options]... [test file or directory]..."
|
||||
|
||||
urchin_help() {
|
||||
cat <<EOF
|
||||
@@ -442,8 +501,8 @@ particular test file once per shell.
|
||||
On each run,
|
||||
|
||||
1. The TEST_SHELL environment variable is set to the particular shell.
|
||||
2. If the test file lacks a shebang line, the test script is also
|
||||
executed in that shell.
|
||||
2. If the test file lacks a shebang line or has a shebang line of
|
||||
"#!/bin/sh", the test script is also executed in that shell.
|
||||
|
||||
The following flags affect how this multiple-shell testing is handled.
|
||||
|
||||
@@ -461,8 +520,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
|
||||
@@ -472,9 +531,11 @@ These options affect how results are formatted. Options -q, and -v
|
||||
have no effect when combined with --tap. -vv, -vvv, and -vvvv do have
|
||||
effect when combined with --tap.
|
||||
|
||||
-c, --color Print results in color.
|
||||
-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
|
||||
@@ -482,14 +543,14 @@ 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 Print debugging messages.
|
||||
|
||||
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.
|
||||
Go to https://thomaslevine.com/!/urchin/ for documentation on writing tests.
|
||||
|
||||
EOF
|
||||
}
|
||||
@@ -529,6 +590,7 @@ main() {
|
||||
print_not_ok=true
|
||||
print_ok_stdout=false
|
||||
print_not_ok_stdout=false
|
||||
print_debug=false
|
||||
while [ "${#}" -gt 0 ]
|
||||
do
|
||||
case "${1}" in
|
||||
@@ -546,17 +608,26 @@ main() {
|
||||
}
|
||||
|
||||
validate_strings "${shell_for_sh_tests}" 'Shell paths'
|
||||
if echo "${shell_for_sh_tests}" | grep \ > /dev/null; then
|
||||
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}" ;;
|
||||
-c|--color) print_in_color=true;;
|
||||
-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
|
||||
print_margins=false;;
|
||||
@@ -566,7 +637,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
|
||||
print_debug=true;;
|
||||
|
||||
-h|--help) urchin_help
|
||||
urchin_exit 0;;
|
||||
@@ -581,6 +655,14 @@ main() {
|
||||
shift
|
||||
done
|
||||
|
||||
if $print_in_color; then
|
||||
success_mark=✓
|
||||
fail_mark=✗
|
||||
else
|
||||
success_mark=.
|
||||
fail_mark=F
|
||||
fi
|
||||
|
||||
# -------------------- VALIDATE INPUT -------------------- #
|
||||
if ! "${cycle_shell}" && test -f "${shell_list}"; then
|
||||
echo "The -n/--disable-cycling and -s/--shell options clash with each other." >&2
|
||||
@@ -591,7 +673,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
|
||||
@@ -600,30 +682,19 @@ main() {
|
||||
fi
|
||||
fi
|
||||
|
||||
# Warn about strange sort commands
|
||||
weird_string='@ b\n- d\n? a\n~ c\n! e\n'
|
||||
sort_result="$(printf "${weird_string}" | sort | cut -d\ -f2 | tr -d '\n')"
|
||||
if test "${sort_result}" = edacb; then
|
||||
sort=sort
|
||||
else
|
||||
if which python > /dev/null; then
|
||||
sort=sort_python
|
||||
else
|
||||
echo 'Your version of sort sorts in dictionary order (-d) by default.
|
||||
Depending on how you name your tests, your Urchin output may look strange.
|
||||
If this is a problem, install BusyBox or BSD coreutils.' >&2
|
||||
sort=sort
|
||||
fi
|
||||
if $print_debug; then
|
||||
echo Cycling with the following shells:
|
||||
cat "${shell_list}"
|
||||
fi
|
||||
|
||||
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 to use your version of timeout >&2
|
||||
echo I couldn\'t figure out how to use your version of timeout >&2
|
||||
urchin_exit 1
|
||||
fi
|
||||
fi
|
||||
@@ -634,22 +705,23 @@ main() {
|
||||
fi
|
||||
|
||||
# -------------------- REALLY RUN -------------------- #
|
||||
start=$(date +%s)
|
||||
elapsed=$({
|
||||
time {
|
||||
# 1 test file or folder to run
|
||||
# 2 urchin root
|
||||
# 3 Should we cycle shells?
|
||||
# 4 TEST_SHELL
|
||||
while read seed; do
|
||||
recurse "$(fullpath "${seed}")" "${root}" "${cycle_shell}" \
|
||||
"${TEST_SHELL}" || break
|
||||
done < "${test_arg_list}"
|
||||
}
|
||||
} 3>&1 1>&2 2>&3 3>& | grep ^real | cut -f 2)
|
||||
|
||||
# 1 test file or folder to run
|
||||
# 2 urchin root
|
||||
# 3 Should we cycle shells?
|
||||
# 4 TEST_SHELL
|
||||
while read seed; do
|
||||
recurse "$(fullpath "${seed}")" "${root}" "${cycle_shell}" \
|
||||
"${TEST_SHELL}" || break
|
||||
done < "${test_arg_list}"
|
||||
finish=$(date +%s)
|
||||
|
||||
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}"
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 99 KiB |
Binary file not shown.
Before Width: | Height: | Size: 115 KiB |
Reference in New Issue
Block a user