Git fork

test-lib: allow test snippets as here-docs

Most test snippets are wrapped in single quotes, like:

test_expect_success 'some description' '
do_something
'

This sometimes makes the snippets awkward to write, because you can't
easily use single quotes within them. We sometimes work around this with
$SQ, or by loosening regexes to use "." instead of a literal quote, or
by using double quotes when we'd prefer to use single-quotes (and just
adding extra backslash-escapes to avoid interpolation).

This commit adds another option: feeding the snippet via the function's
stdin. This doesn't conflict with anything the snippet would want to do,
because we always redirect its stdin from /dev/null anyway (which we'll
continue to do).

A few notes on the implementation:

- it would be nice to push this down into test_run_, but we can't, as
test_expect_success and test_expect_failure want to see the actual
script content to report it for verbose-mode. A helper function
limits the amount of duplication in those callers here.

- The helper function is a little awkward to call, as you feed it the
name of the variable you want to set. The more natural thing in
shell would be command substitution like:

body=$(body_or_stdin "$2")

but that loses trailing whitespace. There are tricks around this,
like:

body=$(body_or_stdin "$2"; printf .)
body=${body%.}

but we'd prefer to keep such tricks in the helper, not in each
caller.

- I implemented the helper using a sequence of "read" calls. Together
with "-r" and unsetting the IFS, this preserves incoming whitespace.
An alternative is to use "cat" (which then requires the gross "."
trick above). But this saves us a process, which is probably a good
thing. The "read" builtin does use more read() syscalls than
necessary (one per byte), but that is almost certainly a win over a
separate process.

Both are probably slower than passing a single-quoted string, but
the difference is lost in the noise for a script that I converted as
an experiment.

- I handle test_expect_success and test_expect_failure here. If we
like this style, we could easily extend it to other spots (e.g.,
lazy_prereq bodies) on top of this patch.

- even though we are using "local", we have to be careful about our
variable names. Within test_expect_success, any variable we declare
with local will be seen as local by the test snippets themselves (so
it wouldn't persist between tests like normal variables would).

Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>

authored by

Jeff King and committed by
Junio C Hamano
1d133ae9 0c7d6302

+35 -5
+8
t/README
··· 906 906 'git-write-tree should be able to write an empty tree.' \ 907 907 'tree=$(git-write-tree)' 908 908 909 + If <script> is `-` (a single dash), then the script to run is read 910 + from stdin. This lets you more easily use single quotes within the 911 + script by using a here-doc. For example: 912 + 913 + test_expect_success 'output contains expected string' - <<\EOT 914 + grep "this string has 'quotes' in it" output 915 + EOT 916 + 909 917 If you supply three parameters the first will be taken to be a 910 918 prerequisite; see the test_set_prereq and test_have_prereq 911 919 documentation below:
+27 -5
t/test-lib-functions.sh
··· 872 872 BUG "'$test_prereq' does not look like a prereq" 873 873 } 874 874 875 + # assign the variable named by "$1" with the contents of "$2"; 876 + # if "$2" is "-", then read stdin into "$1" instead 877 + test_body_or_stdin () { 878 + if test "$2" != "-" 879 + then 880 + eval "$1=\$2" 881 + return 882 + fi 883 + 884 + # start with a newline, to match hanging newline from open-quote style 885 + eval "$1=\$LF" 886 + local test_line 887 + while IFS= read -r test_line 888 + do 889 + eval "$1=\${$1}\${test_line}\${LF}" 890 + done 891 + } 892 + 875 893 test_expect_failure () { 876 894 test_start_ "$@" 877 895 test "$#" = 3 && { test_prereq=$1; shift; } || test_prereq= ··· 881 899 export test_prereq 882 900 if ! test_skip "$@" 883 901 then 902 + local test_body 903 + test_body_or_stdin test_body "$2" 884 904 test -n "$test_skip_test_preamble" || 885 - say >&3 "checking known breakage of $TEST_NUMBER.$test_count '$1': $2" 886 - if test_run_ "$2" expecting_failure 905 + say >&3 "checking known breakage of $TEST_NUMBER.$test_count '$1': $test_body" 906 + if test_run_ "$test_body" expecting_failure 887 907 then 888 908 test_known_broken_ok_ "$1" 889 909 else ··· 902 922 export test_prereq 903 923 if ! test_skip "$@" 904 924 then 925 + local test_body 926 + test_body_or_stdin test_body "$2" 905 927 test -n "$test_skip_test_preamble" || 906 - say >&3 "expecting success of $TEST_NUMBER.$test_count '$1': $2" 907 - if test_run_ "$2" 928 + say >&3 "expecting success of $TEST_NUMBER.$test_count '$1': $test_body" 929 + if test_run_ "$test_body" 908 930 then 909 931 test_ok_ "$1" 910 932 else 911 - test_failure_ "$@" 933 + test_failure_ "$1" "$test_body" 912 934 fi 913 935 fi 914 936 test_finish_