Compare commits
	
		
			1 Commits
		
	
	
		
			urchin-roo
			...
			more-shell
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | 7126872a8b | 
							
								
								
									
										26
									
								
								HISTORY
									
									
									
									
									
								
							
							
						
						
									
										26
									
								
								HISTORY
									
									
									
									
									
								
							| @@ -1,29 +1,6 @@ | |||||||
| HISTORY | HISTORY | ||||||
| ======= | ======= | ||||||
|  |  | ||||||
| Version 0.0.7 |  | ||||||
| --------------------- |  | ||||||
|  |  | ||||||
| The Molly-guard is now more accepting. For example, you no longer need to |  | ||||||
| pass -f in this case: https://github.com/creationix/nvm/issues/357 |  | ||||||
|  |  | ||||||
| Previously, tests were run if they were executable and were otherwise marked |  | ||||||
| as skipped. Now, an executable script can indicate that it is skipped by |  | ||||||
| exiting with code 3.  For example, if a test requires some dependancy, it |  | ||||||
| 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 |  | ||||||
|       exit 3 # status code 3 for skip |  | ||||||
|     fi |  | ||||||
|     inkscape blah blah ... |  | ||||||
|  |  | ||||||
| I chose status code 3 sort of arbitrarily at first, but it turns out that it |  | ||||||
| would the appropriate status code if these tests were Nagios plugins, as the |  | ||||||
| concept of skipping a test is similar to the Nagios concept of unknown service |  | ||||||
| status (https://nagios-plugins.org/doc/guidelines.html#AEN78). |  | ||||||
|  |  | ||||||
| Version 0.0.6 | Version 0.0.6 | ||||||
| --------------------- | --------------------- | ||||||
|  |  | ||||||
| @@ -37,9 +14,6 @@ Version 0.0.6 | |||||||
| * Remove the undocumented, experimental -x flag now that shall exists. | * Remove the undocumented, experimental -x flag now that shall exists. | ||||||
| * Display version number with the -v flag. | * Display version number with the -v flag. | ||||||
| * Document why Urchin is called "Urchin" | * Document why Urchin is called "Urchin" | ||||||
| * Update TODO |  | ||||||
| * Support mksh (Change a printf command.) |  | ||||||
| * Make long lines shorter. |  | ||||||
|  |  | ||||||
| These changes are made somewhat separately in the branches "exit-on-fail", | These changes are made somewhat separately in the branches "exit-on-fail", | ||||||
| "remove-urchin-x", "tap", and "update-readme". They are rebased into one | "remove-urchin-x", "tap", and "update-readme". They are rebased into one | ||||||
|   | |||||||
| @@ -1,5 +1,3 @@ | |||||||
| Copyright (c) 2013, 2014, 2015, 2016 Thomas Levine |  | ||||||
| Copyright (c) 2014, Michael Klement |  | ||||||
| Copyright (c) 2012, ScraperWiki Limited | Copyright (c) 2012, ScraperWiki Limited | ||||||
| All rights reserved. | All rights reserved. | ||||||
| 
 | 
 | ||||||
							
								
								
									
										164
									
								
								TODO
									
									
									
									
									
								
							
							
						
						
									
										164
									
								
								TODO
									
									
									
									
									
								
							| @@ -1,164 +0,0 @@ | |||||||
| Things I want |  | ||||||
| ============= |  | ||||||
|  |  | ||||||
| Test speed |  | ||||||
| ------------- |  | ||||||
| Make tests run faster. |  | ||||||
| https://github.com/bike-barn/hermit/issues/62 |  | ||||||
|  |  | ||||||
| First, easier thing is probably to run tests in parallel. |  | ||||||
|  |  | ||||||
| Second, also easier thing is to tell people to save things to RAM rather than |  | ||||||
| disk whenever they can. |  | ||||||
|  |  | ||||||
| Third, harder thing is to put the test suite in RAM automatically. Maybe the |  | ||||||
| whole test directory, which includes fixtures, gets copied to a tmpfs if one |  | ||||||
| exists. |  | ||||||
|  |  | ||||||
| Hmm or maybe there's a compromise: Tell people to mount /tmp as a tmpfs so |  | ||||||
| that temp files are fast. Maybe allow people to set some other directory as |  | ||||||
| the temporary file place, in case they want a different tmpfs location. |  | ||||||
|  |  | ||||||
| In order to run things in parallel, we have to change how we do the |  | ||||||
| stdout_file. I think it's easiest to create separate files for each test and |  | ||||||
| to save them in testroot/.urchin/stdout/$filename. The test root would be |  | ||||||
| defined as the closest ancestor containing a .urchin directory. |  | ||||||
|  |  | ||||||
| Options |  | ||||||
| ------------- |  | ||||||
| I want long options. For example, there's presently -f and -e. |  | ||||||
| I want to make them -f|--force and -e|--exit. |  | ||||||
|  |  | ||||||
| Environment variables |  | ||||||
| ------------- |  | ||||||
| Do something to make it easier to debug environment variables, because that is |  | ||||||
| often confusing. |  | ||||||
| https://github.com/creationix/nvm/issues/719 |  | ||||||
| https://github.com/creationix/nvm/issues/589 |  | ||||||
|  |  | ||||||
| Documenting that people should run "env" when their tests fail might be good |  | ||||||
| enough. |  | ||||||
|  |  | ||||||
| Licensing and copyright |  | ||||||
| ------------------------ |  | ||||||
| * Reference all owners and years in the Copyright file |  | ||||||
| * Consider copyleft licenses |  | ||||||
| * Add license notices to other files if necessary |  | ||||||
|  |  | ||||||
| Packaging |  | ||||||
| ------------ |  | ||||||
| Package for package managers. |  | ||||||
|  |  | ||||||
| * I want NixOS, of course. |  | ||||||
| * Debian is probably the big one. |  | ||||||
|  |  | ||||||
| Other interesting package managers |  | ||||||
|  |  | ||||||
| * Update the npm package |  | ||||||
| * Homebrew (for Mac) |  | ||||||
|  |  | ||||||
| Windows |  | ||||||
| ---------- |  | ||||||
| Try running Urchin in Windows somehow. Interpreters include |  | ||||||
|  |  | ||||||
| * CygWin (https://www.cygwin.com/) |  | ||||||
| * MSYS (http://mingw.org/wiki/msys) |  | ||||||
| * GNU on Windows (https://github.com/bmatzelle/gow/wiki) |  | ||||||
| * Git for Windows (https://git-scm.com/download/win) |  | ||||||
| * win-bash (http://win-bash.sourceforge.net/) |  | ||||||
|  |  | ||||||
| Consider copyleft licenses |  | ||||||
| ---------- |  | ||||||
| ScraperWiki owns the original version of Urchin (Thomas Levine did the early |  | ||||||
| work as part of his work for ScraperWiki.) and originally licensed it under an |  | ||||||
| MIT-style license. Other people made changes after this original ScraperWiki |  | ||||||
| version. As of January 2016, they are just Thomas Levine (when he wasn't |  | ||||||
| working for ScraperWiki) and Michael Klement. |  | ||||||
|  |  | ||||||
| The original license was MIT just because that's what ScraperWiki put on |  | ||||||
| everything. Should we change the license? |  | ||||||
|  |  | ||||||
| The MIT-style license grants pretty much all rights. It says that you need |  | ||||||
| to attribute when you redistribute source code, but you don't |  | ||||||
| necessarily have to redistribute source code. |  | ||||||
|  |  | ||||||
| A copyleft license adds the restriction that modified versions of the |  | ||||||
| code need to be licensed under the same license. GNU licenses in |  | ||||||
| particular require that source code be released if non-source versions are |  | ||||||
| released, and the different GNU licenses differ in what how the |  | ||||||
| non-source version is defined. (The original, GPL, discusses compiled |  | ||||||
| binaries.) Copyleft doesn't mean anything specific for commercial use. |  | ||||||
|  |  | ||||||
| MIT-licensed code can be modified and then licensed as GPL, because MIT |  | ||||||
| license allows that, but GPL code can't be modified as MIT, because MIT |  | ||||||
| doesn't allow that. And if we get all of the authors to agree on it, we |  | ||||||
| can always add whatever crazy license we want, regardless of what we |  | ||||||
| have already. |  | ||||||
|  |  | ||||||
| The distinction between MIT-style and GNU-something might matter quite little |  | ||||||
| in the case of Urchin. |  | ||||||
|  |  | ||||||
| 1. Urchin is written in an interpreted language (shell), so it might be |  | ||||||
|    hard to distribute usefully without providing the source code. |  | ||||||
| 2. Urchin just runs tests; it doesn't get compiled with the rest of the |  | ||||||
|    code (also because it's in shell). Thus, I think a GPL license on |  | ||||||
|    Urchin wouldn't infect the code being tested. |  | ||||||
|  |  | ||||||
| This is as far as I have gotten with contemplating license changes. For now |  | ||||||
| we're sticking with the original MIT-style license, but it's easy to change |  | ||||||
| licenses later. |  | ||||||
|  |  | ||||||
| Nagios plugins |  | ||||||
| ----------------- |  | ||||||
| It would be cool to run Nagios plugins with Urchin. This is already possible, |  | ||||||
| actually, but it might be worth giving some special thought to it. |  | ||||||
| https://nagios-plugins.org/doc/guidelines.html |  | ||||||
|  |  | ||||||
| Source setup and teardown |  | ||||||
| -------------------- |  | ||||||
| If setup and teardown are sourced instead of executed, maybe we can more |  | ||||||
| cleanly create and teardown temporary files. |  | ||||||
|  |  | ||||||
|     ( |  | ||||||
|       . ./setup |  | ||||||
|       ./$thetestfile |  | ||||||
|       . ./teardown |  | ||||||
|     ) |  | ||||||
|  |  | ||||||
| On the other hand, this could just be sourced explicitly in the test file, |  | ||||||
| without the special setup and teardown feature. |  | ||||||
|  |  | ||||||
| Run on a file |  | ||||||
| ---------------- |  | ||||||
| Presently you can run urchin only on a directory. |  | ||||||
| It would be neat if you could run it on a file as well. |  | ||||||
|  |  | ||||||
| This occurred to me when I wanted to run |  | ||||||
|  |  | ||||||
|     urchin test/fast/Unit\ tests/nvm_ls_current |  | ||||||
|  |  | ||||||
| on the nvm tests. I wound up running this instead. |  | ||||||
|  |  | ||||||
|     urchin test/fast/Unit\ tests/ | grep nvm_ls_current |  | ||||||
|  |  | ||||||
| The Molly guard would be assessed, and the corresponding setup, setup_dir, |  | ||||||
| teardown, and teardown_dir files would be run in the appropriate order. |  | ||||||
|  |  | ||||||
| In order to know how far up the tree to evaluate the setup, &c. files, |  | ||||||
| I think it would make sense to require that a ".urchin" file be placed in the |  | ||||||
| root of the tests. Urchin would keep going up until it sees this file, and it |  | ||||||
| would evaluate the appropriate setup, &c. files from there down to the |  | ||||||
| particular test file of interest. We would also use this for testing |  | ||||||
| directtories more correctly. |  | ||||||
|  |  | ||||||
| Running automated tasks |  | ||||||
| ------------------------- |  | ||||||
| Urchin might be appropriate for if you have lots of tasks that you want to run |  | ||||||
| periodically; add an urchin call to your crontab, and call all of your other |  | ||||||
| tasks with urchin. Here are some features that might make urchin better for |  | ||||||
| this sort of thing. |  | ||||||
|                                                        |  | ||||||
| * Time how long each test/job takes |  | ||||||
| * Optionally kill tests/jobs after a specific timeout threshold |  | ||||||
| * Send output of different tests/jobs to different files for each file |  | ||||||
|   descriptor (STDOUT, STDERR) |  | ||||||
| @@ -1,9 +1,2 @@ | |||||||
| Totally different syntax and similar features, plus TAP output | Totally different syntax and similar features, plus TAP output | ||||||
| https://github.com/sstephenson/bats | https://github.com/sstephenson/bats | ||||||
|  |  | ||||||
| Relatively similar interface |  | ||||||
| https://github.com/mlafeldt/sharness |  | ||||||
|  |  | ||||||
| Lists of alternatives |  | ||||||
| https://thomaslevine.com/!/shell-testing/ |  | ||||||
| https://github.com/mlafeldt/sharness#alternatives |  | ||||||
|   | |||||||
| @@ -36,7 +36,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. | directory in your `PATH`. For example, you can run the following as root. | ||||||
|  |  | ||||||
|     cd /usr/local/bin |     cd /usr/local/bin | ||||||
|     wget https://raw.githubusercontent.com/tlevine/urchin/v0.0.6/urchin |     wget https://raw.github.com/tlevine/urchin/master/urchin | ||||||
|     chmod +x urchin |     chmod +x urchin | ||||||
|  |  | ||||||
| Urchin can be installed with npm too. | Urchin can be installed with npm too. | ||||||
| @@ -169,3 +169,9 @@ It does something similar, but the interface may be more intuitive. | |||||||
| ## Alternatives to Urchin | ## Alternatives to Urchin | ||||||
| Alternatives to Urchin are discussed in | Alternatives to Urchin are discussed in | ||||||
| [this blog post](https://blog.scraperwiki.com/2012/12/how-to-test-shell-scripts/). | [this blog post](https://blog.scraperwiki.com/2012/12/how-to-test-shell-scripts/). | ||||||
|  |  | ||||||
|  | ## Ideas for new features | ||||||
|  |  | ||||||
|  | * Support [Nagios plugins](https://nagios-plugins.org/doc/guidelines.html) | ||||||
|  | * Stop running if a test fails so one can use Urchin as a | ||||||
|  |     [setup framework](https://github.com/tlevine/urchin/issues/16). | ||||||
|   | |||||||
							
								
								
									
										2
									
								
								tests/.urchin/.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								tests/.urchin/.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -1,2 +0,0 @@ | |||||||
| * |  | ||||||
| !.gitignore |  | ||||||
| @@ -1,6 +0,0 @@ | |||||||
| #!/bin/sh |  | ||||||
|  |  | ||||||
| observed=$(../../urchin "$1" .testsuite/a/b) |  | ||||||
| expected=.testsuite/a/b/../.. |  | ||||||
|  |  | ||||||
| test "$observed" = "$expected" |  | ||||||
| @@ -1,2 +0,0 @@ | |||||||
| * |  | ||||||
| !.gitignore |  | ||||||
| @@ -1 +0,0 @@ | |||||||
| #!/usr/bin/env true |  | ||||||
| @@ -1,2 +0,0 @@ | |||||||
| #!/bin/sh |  | ||||||
| ../../urchin --root .testsuite/a/b/c/testcase |  | ||||||
| @@ -1,2 +0,0 @@ | |||||||
| #!/bin/sh |  | ||||||
| ./.meta-assess --root |  | ||||||
| @@ -1,2 +0,0 @@ | |||||||
| #!/bin/sh |  | ||||||
| ./.meta-assess -r |  | ||||||
| @@ -1,2 +0,0 @@ | |||||||
| #!/bin/sh |  | ||||||
| ../../urchin --root /bin 2>&1 | grep "'/bin/.urchin'" |  | ||||||
| @@ -1,2 +0,0 @@ | |||||||
| #!/bin/sh |  | ||||||
| ! ../../urchin --root .testsuite/a/not-a-file |  | ||||||
| @@ -0,0 +1,3 @@ | |||||||
|  | #!/bin/sh | ||||||
|  |  | ||||||
|  | exit 0 | ||||||
| @@ -1 +0,0 @@ | |||||||
| #!/usr/bin/env true |  | ||||||
| @@ -1 +1,3 @@ | |||||||
| #!/usr/bin/env true | #!/bin/sh | ||||||
|  |  | ||||||
|  | exit 0 | ||||||
|   | |||||||
| @@ -1,3 +0,0 @@ | |||||||
| #!/bin/sh |  | ||||||
|  |  | ||||||
| ../../urchin .foo/test/bar |  | ||||||
| @@ -1,5 +1,3 @@ | |||||||
| #!/bin/sh | #!/bin/sh | ||||||
|  |  | ||||||
| tmp=$(mktemp -d)/blah | ! ../../urchin ./.chainsaw | ||||||
| echo '#!/usr/bin/env true' > $tmp |  | ||||||
| ! ../../urchin $tmp |  | ||||||
|   | |||||||
| @@ -1,4 +0,0 @@ | |||||||
| #!/bin/sh |  | ||||||
|  |  | ||||||
| I_AM_SOURCING_URCHIN_IN_A_TEST=true . ../../urchin |  | ||||||
| test $(get_stdout_file t) = aoeu |  | ||||||
| @@ -1 +0,0 @@ | |||||||
| exit 1 |  | ||||||
| @@ -1 +0,0 @@ | |||||||
| exit 3 |  | ||||||
| @@ -1 +0,0 @@ | |||||||
| exit 0 |  | ||||||
| @@ -1 +0,0 @@ | |||||||
| test $(../../urchin -t .test/ | grep -c SKIP) -eq 1 |  | ||||||
							
								
								
									
										144
									
								
								urchin
									
									
									
									
									
								
							
							
						
						
									
										144
									
								
								urchin
									
									
									
									
									
								
							| @@ -1,84 +1,22 @@ | |||||||
| #!/bin/sh | #!/bin/sh | ||||||
|  |  | ||||||
| # This file is part of urchin. It is subject to the license terms in the | # Make sure that CDPATH isn't set, as it causes `cd` to behave unpredictably - notably, it can produce output, | ||||||
| # COPYING file found in the top-level directory of this distribution or at | # which breaks fullpath(). | ||||||
| # https://raw.githubusercontent.com/tlevine/urchin/master/COPYING |  | ||||||
|  |  | ||||||
| # No part of urchin, including this file, may be copied, modified, propagated, |  | ||||||
| # or distributed except according to the terms contained in the COPYING file. |  | ||||||
|  |  | ||||||
| set +e |  | ||||||
|  |  | ||||||
| # Make sure that CDPATH isn't set, as it causes `cd` to behave unpredictably - |  | ||||||
| # notably, it can produce output, which breaks fullpath(). |  | ||||||
| unset CDPATH | unset CDPATH | ||||||
|  |  | ||||||
| # Urchin version number | # Urchin version number | ||||||
| VERSION=0.0.6 | VERSION=0.0.6 | ||||||
|  |  | ||||||
| urchin_root() { | fullpath() { | ||||||
|   # Call recursively but remember the original argument. |   ( | ||||||
|   current="$(remove_trailing_slash "$1")" |     cd -- "$1" | ||||||
|   if test -n "$2"; then |     pwd | ||||||
|     orig="$2" |   ) | ||||||
|   else |  | ||||||
|     orig="$1" |  | ||||||
|   fi |  | ||||||
|  |  | ||||||
|   if test "$(readlink -f -- "$1")" = /; then |  | ||||||
|     # Stop traversing upwards at / |  | ||||||
|     if test -d "$orig"; then |  | ||||||
|       origdir="$orig" |  | ||||||
|     else |  | ||||||
|       origdir=$(dirname "$orig") |  | ||||||
|     fi |  | ||||||
|     echo "You need to create the .urchin directory in the root of your tests, |  | ||||||
| maybe like this: |  | ||||||
|  |  | ||||||
|   mkdir '$(readlink -f -- "$(remove_trailing_slash "$origdir")")/.urchin' |  | ||||||
| " >&2 |  | ||||||
|     return 1 |  | ||||||
|   elif ! test -e "$current"; then |  | ||||||
|     echo "$current: No such file or directory">&2 |  | ||||||
|     return 1 |  | ||||||
|   elif test -f "$current"; then |  | ||||||
|     urchin_root "$(dirname "$current")" "$orig" |  | ||||||
|   elif test -d "$current"/.urchin; then |  | ||||||
|     remove_trailing_slash "$current" |  | ||||||
|   elif test "$current" != . && test "$current" != .. && |  | ||||||
|     echo "$current" | grep '^\.' && > /dev/null; then |  | ||||||
|     # Stop traversing upwards at hidden directories. |  | ||||||
|     urchin_root / "$orig" |  | ||||||
|   else |  | ||||||
|     urchin_root "$current"/.. "$orig" |  | ||||||
|   fi |  | ||||||
| } | } | ||||||
|  |  | ||||||
| indent() { | indent() { | ||||||
|   level="$1" |   level="$1" | ||||||
|   if test "$level" -gt 0; then |  | ||||||
|   printf "%$((2 * ${level}))s" |   printf "%$((2 * ${level}))s" | ||||||
|   fi |  | ||||||
| } |  | ||||||
|  |  | ||||||
| remove_trailing_slash() { |  | ||||||
|   echo "$1" | sed s/\\/$// |  | ||||||
| } |  | ||||||
|  |  | ||||||
| escape_slashes() { |  | ||||||
|   echo "$1" | sed s+/+\\\\/+g |  | ||||||
| } |  | ||||||
|  |  | ||||||
| get_stdout_file() { |  | ||||||
|   root="$(readlink -f -- "$(urchin_root "$1")")" |  | ||||||
|   test_file="$(readlink -f -- "$1")" |  | ||||||
|   eroot="$(escape_slashes "$root")" |  | ||||||
|   base="$(echo "$test_file" | sed "s/^$eroot/$eroot\/.urchin/")" |  | ||||||
|   if test -d "$1"; then |  | ||||||
|     echo "$base"/.index |  | ||||||
|   else |  | ||||||
|     echo "$base" |  | ||||||
|   fi |  | ||||||
| } | } | ||||||
|  |  | ||||||
| recurse() { | recurse() { | ||||||
| @@ -86,15 +24,11 @@ recurse() { | |||||||
|   indent_level="$2" |   indent_level="$2" | ||||||
|   shell_for_sh_tests="$3" |   shell_for_sh_tests="$3" | ||||||
|  |  | ||||||
|   [ "$potential_test" = '.urchin' ] && return |  | ||||||
|   [ "$potential_test" = 'setup_dir' ] && return |   [ "$potential_test" = 'setup_dir' ] && return | ||||||
|   [ "$potential_test" = 'teardown_dir' ] && return |   [ "$potential_test" = 'teardown_dir' ] && return | ||||||
|   [ "$potential_test" = 'setup' ] && return |   [ "$potential_test" = 'setup' ] && return | ||||||
|   [ "$potential_test" = 'teardown' ] && return |   [ "$potential_test" = 'teardown' ] && return | ||||||
|  |  | ||||||
|   stdout_file="$(get_stdout_file "$potential_test")" |  | ||||||
|   mkdir -p "$(dirname "$stdout_file")" |  | ||||||
|  |  | ||||||
|   [ $indent_level -eq 0 ] && : > "$stdout_file" |   [ $indent_level -eq 0 ] && : > "$stdout_file" | ||||||
|  |  | ||||||
|   if [ -d "$potential_test" ] |   if [ -d "$potential_test" ] | ||||||
| @@ -122,10 +56,8 @@ recurse() { | |||||||
|         [ -f setup ] && [ -x setup ] && ./setup >> "$stdout_file" |         [ -f setup ] && [ -x setup ] && ./setup >> "$stdout_file" | ||||||
|  |  | ||||||
|         # $2 instead of $indent_level so it doesn't clash |         # $2 instead of $indent_level so it doesn't clash | ||||||
|         set +e |         recurse "${test}" $(( $2 + 1 )) "$shell_for_sh_tests" | ||||||
|         recurse "${test}" "$(( $2 + 1 ))" "$shell_for_sh_tests" |  | ||||||
|         exit_code=$? |         exit_code=$? | ||||||
|         set -e |  | ||||||
|  |  | ||||||
|         if $exit_on_fail && test $exit_code -ne 0; then |         if $exit_on_fail && test $exit_code -ne 0; then | ||||||
|           [ -f teardown ] && [ -x teardown ] && ./teardown >> "$stdout_file" |           [ -f teardown ] && [ -x teardown ] && ./teardown >> "$stdout_file" | ||||||
| @@ -160,8 +92,6 @@ recurse() { | |||||||
|       [ -f teardown ] && [ -x teardown ] && ./teardown >> "$stdout_file" |       [ -f teardown ] && [ -x teardown ] && ./teardown >> "$stdout_file" | ||||||
|       if [ $exit_code -eq 0 ]; then |       if [ $exit_code -eq 0 ]; then | ||||||
|         result=success |         result=success | ||||||
|       elif [ $exit_code -eq 3 ]; then |  | ||||||
|         result=skip |  | ||||||
|       else |       else | ||||||
|         result=fail |         result=fail | ||||||
|       fi |       fi | ||||||
| @@ -201,10 +131,7 @@ recurse() { | |||||||
|           # On fail, print a red '✗' |           # On fail, print a red '✗' | ||||||
|           printf '\033[31m✗ \033[0m' |           printf '\033[31m✗ \033[0m' | ||||||
|           printf '%s\n' "${potential_test}" |           printf '%s\n' "${potential_test}" | ||||||
|  |           printf '\033[31m' # Print output captured from failed test in red. | ||||||
|           # Print output captured from failed test in red. |  | ||||||
|           printf '\033[31m' |  | ||||||
|  |  | ||||||
|           cat "$stdout_file" |           cat "$stdout_file" | ||||||
|           printf '\033[0m' |           printf '\033[0m' | ||||||
|         ;; |         ;; | ||||||
| @@ -218,16 +145,12 @@ recurse() { | |||||||
|       return 1 |       return 1 | ||||||
|     fi |     fi | ||||||
|   fi |   fi | ||||||
|  |   [ $indent_level -eq 0 ] && rm "$stdout_file" | ||||||
| } | } | ||||||
|  |  | ||||||
| has_sh_or_no_shebang_line() { | has_sh_or_no_shebang_line() { | ||||||
|   # no shebang line at all |   head -n 1 "$1" | grep -vqE '^#!' && return 0 # no shebang line at all | ||||||
|   head -n 1 "$1" | grep -vqE '^#!' && return 0 |   head -n 1 "$1" | grep -qE '^#![[:blank:]]*/bin/sh($|[[:blank:]])' && return 0  # shebang line is '#!/bin/sh' or legal variations thereof | ||||||
|  |  | ||||||
|   # shebang line is '#!/bin/sh' or legal variations thereof |  | ||||||
|   head -n 1 "$1" | grep -qE '^#![[:blank:]]*/bin/sh($|[[:blank:]])' && |  | ||||||
|     return 0   |  | ||||||
|  |  | ||||||
|   return 1 |   return 1 | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -247,7 +170,6 @@ $USAGE | |||||||
|             contain the word "test". |             contain the word "test". | ||||||
| -t          Format output in Test Anything Protocol (TAP) | -t          Format output in Test Anything Protocol (TAP) | ||||||
| -h, --help  This help. | -h, --help  This help. | ||||||
| -r, --root  Print the Urchin root for a particular file or directory. |  | ||||||
| -v          Display the version number. | -v          Display the version number. | ||||||
|  |  | ||||||
| Go to https://github.com/tlevine/urchin for documentation on writing tests. | Go to https://github.com/tlevine/urchin for documentation on writing tests. | ||||||
| @@ -268,11 +190,12 @@ plural () { | |||||||
| } | } | ||||||
|  |  | ||||||
| urchin_go() { | urchin_go() { | ||||||
|  |   rm -f "$logfile" | ||||||
|   if "$tap_format"; then |   if "$tap_format"; then | ||||||
|     printf \#\  |     printf \#\  | ||||||
|   fi |   fi | ||||||
|   echo Running tests at $(date +%Y-%m-%dT%H:%M:%S) |   echo Running tests at $(date +%Y-%m-%dT%H:%M:%S) | ||||||
|   start="$(date +%s)" |   start=$(date +%s) | ||||||
|  |  | ||||||
|   # Determine the environment variable to define for test scripts |   # Determine the environment variable to define for test scripts | ||||||
|   # that reflects the specified or implied shell to use for shell-code tests. |   # that reflects the specified or implied shell to use for shell-code tests. | ||||||
| @@ -287,10 +210,7 @@ urchin_go() { | |||||||
|     TEST_SHELL='/bin/sh' |     TEST_SHELL='/bin/sh' | ||||||
|   fi |   fi | ||||||
|  |  | ||||||
|   # 1 test folder |   recurse "$1" 0 "$2"  # test folder -- indentation level -- [shell to invoke test scripts with] | ||||||
|   # 2 indentation level |  | ||||||
|   # 3 shell to invoke test scripts with |  | ||||||
|   recurse "$1" 0 "$2" |  | ||||||
|  |  | ||||||
|   finish=$(date +%s) |   finish=$(date +%s) | ||||||
|   elapsed=$(($finish - $start)) |   elapsed=$(($finish - $start)) | ||||||
| @@ -305,14 +225,11 @@ urchin_go() { | |||||||
|     echo "Done, took $elapsed $(plural second $elapsed)." |     echo "Done, took $elapsed $(plural second $elapsed)." | ||||||
|     printf '%s\n' "$passed $(plural test "$passed") passed." |     printf '%s\n' "$passed $(plural test "$passed") passed." | ||||||
|     printf '%s\n' "$skipped $(plural test "$skipped") skipped." |     printf '%s\n' "$skipped $(plural test "$skipped") skipped." | ||||||
|  |     [ $failed -gt 0 ] && printf '\033[31m' || printf '\033[32m' # If tests failed, print the message in red, otherwise in green. | ||||||
|     # If tests failed, print the message in red, otherwise in green. |  | ||||||
|     [ $failed -gt 0 ] && printf '\033[31m' || printf '\033[32m' |  | ||||||
|  |  | ||||||
|     printf '%s\n' "$failed $(plural test "$failed") failed." |     printf '%s\n' "$failed $(plural test "$failed") failed." | ||||||
|     printf '\033[m' |     printf '\033[m' | ||||||
|   fi |   fi | ||||||
| # rm -f "$logfile" |   rm -f "$logfile" | ||||||
|   test -z "$failed" || test "$failed" -eq '0' |   test -z "$failed" || test "$failed" -eq '0' | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -328,7 +245,6 @@ urchin_molly_guard() { | |||||||
|   exit 1 |   exit 1 | ||||||
| } | } | ||||||
|  |  | ||||||
| if test -z "$I_AM_SOURCING_URCHIN_IN_A_TEST"; then |  | ||||||
| shell_for_sh_tests= | shell_for_sh_tests= | ||||||
| force=false | force=false | ||||||
| exit_on_fail=false | exit_on_fail=false | ||||||
| @@ -338,18 +254,11 @@ if test -z "$I_AM_SOURCING_URCHIN_IN_A_TEST"; then | |||||||
|     case "$1" in |     case "$1" in | ||||||
|         -e) exit_on_fail=true;; |         -e) exit_on_fail=true;; | ||||||
|         -f) force=true;; |         -f) force=true;; | ||||||
|           -r|--root) |  | ||||||
|             shift |  | ||||||
|             urchin_root "$1" |  | ||||||
|             exit;; |  | ||||||
|         -s) |         -s) | ||||||
|           shift |           shift | ||||||
|           shell_for_sh_tests=$1 |           shell_for_sh_tests=$1 | ||||||
|             which "$shell_for_sh_tests" > /dev/null || { |           which "$shell_for_sh_tests" >/dev/null || { echo "Cannot find specified shell: '$shell_for_sh_tests'" >&2; urchin_help >&2; exit 2; } | ||||||
|               echo "Cannot find specified shell: '$shell_for_sh_tests'" >&2 |           ;; | ||||||
|               urchin_help >&2 |  | ||||||
|               exit 11 |  | ||||||
|             } ;; |  | ||||||
|         -t) tap_format=true;; |         -t) tap_format=true;; | ||||||
|         -h|--help) urchin_help |         -h|--help) urchin_help | ||||||
|           exit 0;; |           exit 0;; | ||||||
| @@ -367,18 +276,17 @@ if test -z "$I_AM_SOURCING_URCHIN_IN_A_TEST"; then | |||||||
|   then |   then | ||||||
|   [ -n "$1" ] && [ ! -d "$1" ] && echo "Not a directory: '$1'" >&2 |   [ -n "$1" ] && [ ! -d "$1" ] && echo "Not a directory: '$1'" >&2 | ||||||
|   echo "$USAGE" >&2 |   echo "$USAGE" >&2 | ||||||
|     exit 11 |   exit 2 | ||||||
| fi | fi | ||||||
|  |  | ||||||
|  | # Constants | ||||||
|  | logfile=$(fullpath "$1")/.urchin.log | ||||||
|  | stdout_file=$(fullpath "$1")/.urchin_stdout | ||||||
|  |  | ||||||
| # Run or present the Molly guard. | # Run or present the Molly guard. | ||||||
|   if ! urchin_root "$1" > /dev/null; then | if basename "$(fullpath "$1")" | grep -Fi 'test' > /dev/null || $force | ||||||
|     exit 1 |   then | ||||||
|   elif basename "$(readlink -f -- "$(urchin_root "$1")")" | |  | ||||||
|     grep -Fi 'test' > /dev/null || $force; then |  | ||||||
|     logfile="$(readlink -f -- "$(urchin_root "$1")/.urchin/.log")" |  | ||||||
|     printf '' > "$logfile" |  | ||||||
|   urchin_go "$1" "$shell_for_sh_tests" |   urchin_go "$1" "$shell_for_sh_tests" | ||||||
| else | else | ||||||
|   urchin_molly_guard |   urchin_molly_guard | ||||||
| fi | fi | ||||||
| fi |  | ||||||
|   | |||||||
										
											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