threads / patch / 47493

patch, 6 partsincrease wildmatch test coverage

Subject: [PATCH 0/6] increase wildmatch test coverage

## tl;dr

73 messages between Dec 23, 2017 and Jan 30, 2018. Diffs are folded; open one to read it.

replies: 72people: 6as markdown or json

Ævar Arnfjörð Bjarmason· Dec 23, 2017, 21:30 UTC · lore

This increases the test coverage we have for wildmatch, and hopefully doesn't break anything, but see the fantastic hack that is 6/6 and form your own opinion.

The backstory of this is that back in June I posted an RFC series here to the list to refactor wildmatch() itself to no-op support precompiling patterns: https://public-inbox.org/git/20170622213810.14785-1-avarab@gmail.com/

The intent was to swap out wildmatch() to use PCRE as an engine, my performance tests reveal that that was probably a dumb idea.

We may still want something like those patches I submitted back in June, in particular we could rewrite wildmatch.c itself to precompile a pattern. if this makes it in I'll see about rebasing those on top, but I'm not in any rush with those.

But in writing up those initial patches (and some "use PCRE for this") that hasn't made it on the list, I discovered that I didn't have any faith in our wildmatch tests, it was easy to find case I could break and all tests would still pass.

This series fixes that, whatever we do with wildmatch in the future it'll be really nice to have this, since we now have exhaustive test coverage of wildmatch, both through the raw function as before (but as 5/6 there were holes in that), and more importantly by doing the same tests through ls-files, which is the interface users actually use, and as 6/6 reveals sometimes behaves differently than the underlying matching function.

Ævar Arnfjörð Bjarmason (6):
  wildmatch test: indent with tabs, not spaces
  wildmatch test: use more standard shell style
  wildmatch test: use a paranoia pattern from nul_match()
  wildmatch test: remove dead fnmatch() test code
  wildmatch test: perform all tests under all wildmatch() modes
  wildmatch test: create & test files on disk in addition to in-memory
 a[]b                      |   0
 t/helper/test-wildmatch.c |   2 +
 t/t3070-wildmatch.sh      | 802 ++++++++++++++++++++++++++++++++--------------
 3 files changed, 558 insertions(+), 246 deletions(-)
 create mode 100644 a[]b
-- 
2.15.1.424.g9478a66081
Ævar Arnfjörð Bjarmason· Dec 23, 2017, 21:30 UTC · re: Ævar Arnfjörð Bjarmason · lore

[PATCH 2/6] wildmatch test: use more standard shell style

Change the wildmatch test to use more standard shell style, usually we use "if test" not "if [".

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 t/t3070-wildmatch.sh | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)
Show changes to t/t3070-wildmatch.sh +6 −3
diff --git a/t/t3070-wildmatch.sh b/t/t3070-wildmatch.sh
index 27fa878f6e..4d589d1f9a 100755
--- a/t/t3070-wildmatch.sh
+++ b/t/t3070-wildmatch.sh
@@ -5,7 +5,8 @@ test_description='wildmatch tests'
 . ./test-lib.sh
 
 match() {
-	if [ $1 = 1 ]; then
+	if test "$1" = 1
+	then
 		test_expect_success "wildmatch:     match '$3' '$4'" "
 			test-wildmatch wildmatch '$3' '$4'
 		"
@@ -17,7 +18,8 @@ match() {
 }
 
 imatch() {
-	if [ $1 = 1 ]; then
+	if test "$1" = 1
+	then
 		test_expect_success "iwildmatch:    match '$2' '$3'" "
 			test-wildmatch iwildmatch '$2' '$3'
 		"
@@ -29,7 +31,8 @@ imatch() {
 }
 
 pathmatch() {
-	if [ $1 = 1 ]; then
+	if test "$1" = 1
+	then
 		test_expect_success "pathmatch:     match '$2' '$3'" "
 			test-wildmatch pathmatch '$2' '$3'
 		"
-- 
2.15.1.424.g9478a66081
Ævar Arnfjörð Bjarmason· Dec 23, 2017, 21:30 UTC · re: Ævar Arnfjörð Bjarmason · lore

[PATCH 1/6] wildmatch test: indent with tabs, not spaces

Replace the 4-width mixed space & tab indentation in this file with indentation with tabs as we do in most of the rest of our tests.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 t/t3070-wildmatch.sh | 54 ++++++++++++++++++++++++++--------------------------
 1 file changed, 27 insertions(+), 27 deletions(-)
Show changes to t/t3070-wildmatch.sh +27 −27
diff --git a/t/t3070-wildmatch.sh b/t/t3070-wildmatch.sh
index 163a14a1c2..27fa878f6e 100755
--- a/t/t3070-wildmatch.sh
+++ b/t/t3070-wildmatch.sh
@@ -5,39 +5,39 @@ test_description='wildmatch tests'
 . ./test-lib.sh
 
 match() {
-    if [ $1 = 1 ]; then
-	test_expect_success "wildmatch:     match '$3' '$4'" "
-	    test-wildmatch wildmatch '$3' '$4'
-	"
-    else
-	test_expect_success "wildmatch:  no match '$3' '$4'" "
-	    ! test-wildmatch wildmatch '$3' '$4'
-	"
-    fi
+	if [ $1 = 1 ]; then
+		test_expect_success "wildmatch:     match '$3' '$4'" "
+			test-wildmatch wildmatch '$3' '$4'
+		"
+	else
+		test_expect_success "wildmatch:  no match '$3' '$4'" "
+			! test-wildmatch wildmatch '$3' '$4'
+		"
+	fi
 }
 
 imatch() {
-    if [ $1 = 1 ]; then
-	test_expect_success "iwildmatch:    match '$2' '$3'" "
-	    test-wildmatch iwildmatch '$2' '$3'
-	"
-    else
-	test_expect_success "iwildmatch: no match '$2' '$3'" "
-	    ! test-wildmatch iwildmatch '$2' '$3'
-	"
-    fi
+	if [ $1 = 1 ]; then
+		test_expect_success "iwildmatch:    match '$2' '$3'" "
+			test-wildmatch iwildmatch '$2' '$3'
+		"
+	else
+		test_expect_success "iwildmatch: no match '$2' '$3'" "
+			! test-wildmatch iwildmatch '$2' '$3'
+		"
+	fi
 }
 
 pathmatch() {
-    if [ $1 = 1 ]; then
-	test_expect_success "pathmatch:     match '$2' '$3'" "
-	    test-wildmatch pathmatch '$2' '$3'
-	"
-    else
-	test_expect_success "pathmatch:  no match '$2' '$3'" "
-	    ! test-wildmatch pathmatch '$2' '$3'
-	"
-    fi
+	if [ $1 = 1 ]; then
+		test_expect_success "pathmatch:     match '$2' '$3'" "
+			test-wildmatch pathmatch '$2' '$3'
+		"
+	else
+		test_expect_success "pathmatch:  no match '$2' '$3'" "
+			! test-wildmatch pathmatch '$2' '$3'
+		"
+	fi
 }
 
 # Basic wildmat features
-- 
2.15.1.424.g9478a66081
Ævar Arnfjörð Bjarmason· Dec 23, 2017, 21:30 UTC · re: Ævar Arnfjörð Bjarmason · lore

[PATCH 3/6] wildmatch test: use a paranoia pattern from nul_match()

Use a pattern from the nul_match() function in t7008-grep-binary.sh to make sure that we don't just fall through to the "else" if there's an unknown parameter.

This is something I added in commit 77f6f4406f ("grep: add a test helper function for less verbose -f \0 tests", 2017-05-20) to grep tests, which were modeled on these wildmatch tests, and I'm now porting back to the original wildmatch tests.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 t/t3070-wildmatch.sh | 15 ++++++++++++---
 1 file changed, 12 insertions(+), 3 deletions(-)
Show changes to t/t3070-wildmatch.sh +12 −3
diff --git a/t/t3070-wildmatch.sh b/t/t3070-wildmatch.sh
index 4d589d1f9a..71d6ea0f56 100755
--- a/t/t3070-wildmatch.sh
+++ b/t/t3070-wildmatch.sh
@@ -10,10 +10,13 @@ match() {
 		test_expect_success "wildmatch:     match '$3' '$4'" "
 			test-wildmatch wildmatch '$3' '$4'
 		"
-	else
+	elif test "$1" = 0
+	then
 		test_expect_success "wildmatch:  no match '$3' '$4'" "
 			! test-wildmatch wildmatch '$3' '$4'
 		"
+	else
+		test_expect_success "PANIC: Test framework error. Unknown matches value $1" 'false'
 	fi
 }
 
@@ -23,10 +26,13 @@ imatch() {
 		test_expect_success "iwildmatch:    match '$2' '$3'" "
 			test-wildmatch iwildmatch '$2' '$3'
 		"
-	else
+	elif test "$1" = 0
+	then
 		test_expect_success "iwildmatch: no match '$2' '$3'" "
 			! test-wildmatch iwildmatch '$2' '$3'
 		"
+	else
+		test_expect_success "PANIC: Test framework error. Unknown matches value $1" 'false'
 	fi
 }
 
@@ -36,10 +42,13 @@ pathmatch() {
 		test_expect_success "pathmatch:     match '$2' '$3'" "
 			test-wildmatch pathmatch '$2' '$3'
 		"
-	else
+	elif test "$1" = 0
+	then
 		test_expect_success "pathmatch:  no match '$2' '$3'" "
 			! test-wildmatch pathmatch '$2' '$3'
 		"
+	else
+		test_expect_success "PANIC: Test framework error. Unknown matches value $1" 'false'
 	fi
 }
 
-- 
2.15.1.424.g9478a66081
Ævar Arnfjörð Bjarmason· Dec 23, 2017, 21:30 UTC · re: Ævar Arnfjörð Bjarmason · lore

[PATCH 4/6] wildmatch test: remove dead fnmatch() test code

Remove the unused fnmatch() test parameter from the wildmatch test. The code that used to test this was removed in 70a8fc999d ("stop using fnmatch (either native or compat)", 2014-02-15).

As a --word-diff shows the only change to the body of the tests is the removal of the second out of four parameters passed to match().

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 t/t3070-wildmatch.sh | 356 +++++++++++++++++++++++++--------------------------
 1 file changed, 178 insertions(+), 178 deletions(-)
Show changes to t/t3070-wildmatch.sh +178 −178
diff --git a/t/t3070-wildmatch.sh b/t/t3070-wildmatch.sh
index 71d6ea0f56..1624200a1e 100755
--- a/t/t3070-wildmatch.sh
+++ b/t/t3070-wildmatch.sh
@@ -7,13 +7,13 @@ test_description='wildmatch tests'
 match() {
 	if test "$1" = 1
 	then
-		test_expect_success "wildmatch:     match '$3' '$4'" "
-			test-wildmatch wildmatch '$3' '$4'
+		test_expect_success "wildmatch:     match '$2' '$3'" "
+			test-wildmatch wildmatch '$2' '$3'
 		"
 	elif test "$1" = 0
 	then
-		test_expect_success "wildmatch:  no match '$3' '$4'" "
-			! test-wildmatch wildmatch '$3' '$4'
+		test_expect_success "wildmatch:  no match '$2' '$3'" "
+			! test-wildmatch wildmatch '$2' '$3'
 		"
 	else
 		test_expect_success "PANIC: Test framework error. Unknown matches value $1" 'false'
@@ -53,176 +53,176 @@ pathmatch() {
 }
 
 # Basic wildmat features
-match 1 1 foo foo
-match 0 0 foo bar
-match 1 1 '' ""
-match 1 1 foo '???'
-match 0 0 foo '??'
-match 1 1 foo '*'
-match 1 1 foo 'f*'
-match 0 0 foo '*f'
-match 1 1 foo '*foo*'
-match 1 1 foobar '*ob*a*r*'
-match 1 1 aaaaaaabababab '*ab'
-match 1 1 'foo*' 'foo\*'
-match 0 0 foobar 'foo\*bar'
-match 1 1 'f\oo' 'f\\oo'
-match 1 1 ball '*[al]?'
-match 0 0 ten '[ten]'
-match 0 1 ten '**[!te]'
-match 0 0 ten '**[!ten]'
-match 1 1 ten 't[a-g]n'
-match 0 0 ten 't[!a-g]n'
-match 1 1 ton 't[!a-g]n'
-match 1 1 ton 't[^a-g]n'
-match 1 x 'a]b' 'a[]]b'
-match 1 x a-b 'a[]-]b'
-match 1 x 'a]b' 'a[]-]b'
-match 0 x aab 'a[]-]b'
-match 1 x aab 'a[]a-]b'
-match 1 1 ']' ']'
+match 1 foo foo
+match 0 foo bar
+match 1 '' ""
+match 1 foo '???'
+match 0 foo '??'
+match 1 foo '*'
+match 1 foo 'f*'
+match 0 foo '*f'
+match 1 foo '*foo*'
+match 1 foobar '*ob*a*r*'
+match 1 aaaaaaabababab '*ab'
+match 1 'foo*' 'foo\*'
+match 0 foobar 'foo\*bar'
+match 1 'f\oo' 'f\\oo'
+match 1 ball '*[al]?'
+match 0 ten '[ten]'
+match 0 ten '**[!te]'
+match 0 ten '**[!ten]'
+match 1 ten 't[a-g]n'
+match 0 ten 't[!a-g]n'
+match 1 ton 't[!a-g]n'
+match 1 ton 't[^a-g]n'
+match 1 'a]b' 'a[]]b'
+match 1 a-b 'a[]-]b'
+match 1 'a]b' 'a[]-]b'
+match 0 aab 'a[]-]b'
+match 1 aab 'a[]a-]b'
+match 1 ']' ']'
 
 # Extended slash-matching features
-match 0 0 'foo/baz/bar' 'foo*bar'
-match 0 0 'foo/baz/bar' 'foo**bar'
-match 0 1 'foobazbar' 'foo**bar'
-match 1 1 'foo/baz/bar' 'foo/**/bar'
-match 1 0 'foo/baz/bar' 'foo/**/**/bar'
-match 1 0 'foo/b/a/z/bar' 'foo/**/bar'
-match 1 0 'foo/b/a/z/bar' 'foo/**/**/bar'
-match 1 0 'foo/bar' 'foo/**/bar'
-match 1 0 'foo/bar' 'foo/**/**/bar'
-match 0 0 'foo/bar' 'foo?bar'
-match 0 0 'foo/bar' 'foo[/]bar'
-match 0 0 'foo/bar' 'foo[^a-z]bar'
-match 0 0 'foo/bar' 'f[^eiu][^eiu][^eiu][^eiu][^eiu]r'
-match 1 1 'foo-bar' 'f[^eiu][^eiu][^eiu][^eiu][^eiu]r'
-match 1 0 'foo' '**/foo'
-match 1 x 'XXX/foo' '**/foo'
-match 1 0 'bar/baz/foo' '**/foo'
-match 0 0 'bar/baz/foo' '*/foo'
-match 0 0 'foo/bar/baz' '**/bar*'
-match 1 0 'deep/foo/bar/baz' '**/bar/*'
-match 0 0 'deep/foo/bar/baz/' '**/bar/*'
-match 1 0 'deep/foo/bar/baz/' '**/bar/**'
-match 0 0 'deep/foo/bar' '**/bar/*'
-match 1 0 'deep/foo/bar/' '**/bar/**'
-match 0 0 'foo/bar/baz' '**/bar**'
-match 1 0 'foo/bar/baz/x' '*/bar/**'
-match 0 0 'deep/foo/bar/baz/x' '*/bar/**'
-match 1 0 'deep/foo/bar/baz/x' '**/bar/*/*'
+match 0 'foo/baz/bar' 'foo*bar'
+match 0 'foo/baz/bar' 'foo**bar'
+match 0 'foobazbar' 'foo**bar'
+match 1 'foo/baz/bar' 'foo/**/bar'
+match 1 'foo/baz/bar' 'foo/**/**/bar'
+match 1 'foo/b/a/z/bar' 'foo/**/bar'
+match 1 'foo/b/a/z/bar' 'foo/**/**/bar'
+match 1 'foo/bar' 'foo/**/bar'
+match 1 'foo/bar' 'foo/**/**/bar'
+match 0 'foo/bar' 'foo?bar'
+match 0 'foo/bar' 'foo[/]bar'
+match 0 'foo/bar' 'foo[^a-z]bar'
+match 0 'foo/bar' 'f[^eiu][^eiu][^eiu][^eiu][^eiu]r'
+match 1 'foo-bar' 'f[^eiu][^eiu][^eiu][^eiu][^eiu]r'
+match 1 'foo' '**/foo'
+match 1 'XXX/foo' '**/foo'
+match 1 'bar/baz/foo' '**/foo'
+match 0 'bar/baz/foo' '*/foo'
+match 0 'foo/bar/baz' '**/bar*'
+match 1 'deep/foo/bar/baz' '**/bar/*'
+match 0 'deep/foo/bar/baz/' '**/bar/*'
+match 1 'deep/foo/bar/baz/' '**/bar/**'
+match 0 'deep/foo/bar' '**/bar/*'
+match 1 'deep/foo/bar/' '**/bar/**'
+match 0 'foo/bar/baz' '**/bar**'
+match 1 'foo/bar/baz/x' '*/bar/**'
+match 0 'deep/foo/bar/baz/x' '*/bar/**'
+match 1 'deep/foo/bar/baz/x' '**/bar/*/*'
 
 # Various additional tests
-match 0 0 'acrt' 'a[c-c]st'
-match 1 1 'acrt' 'a[c-c]rt'
-match 0 0 ']' '[!]-]'
-match 1 x 'a' '[!]-]'
-match 0 0 '' '\'
-match 0 x '\' '\'
-match 0 x 'XXX/\' '*/\'
-match 1 x 'XXX/\' '*/\\'
-match 1 1 'foo' 'foo'
-match 1 1 '@foo' '@foo'
-match 0 0 'foo' '@foo'
-match 1 1 '[ab]' '\[ab]'
-match 1 1 '[ab]' '[[]ab]'
-match 1 x '[ab]' '[[:]ab]'
-match 0 x '[ab]' '[[::]ab]'
-match 1 x '[ab]' '[[:digit]ab]'
-match 1 x '[ab]' '[\[:]ab]'
-match 1 1 '?a?b' '\??\?b'
-match 1 1 'abc' '\a\b\c'
-match 0 0 'foo' ''
-match 1 0 'foo/bar/baz/to' '**/t[o]'
+match 0 'acrt' 'a[c-c]st'
+match 1 'acrt' 'a[c-c]rt'
+match 0 ']' '[!]-]'
+match 1 'a' '[!]-]'
+match 0 '' '\'
+match 0 '\' '\'
+match 0 'XXX/\' '*/\'
+match 1 'XXX/\' '*/\\'
+match 1 'foo' 'foo'
+match 1 '@foo' '@foo'
+match 0 'foo' '@foo'
+match 1 '[ab]' '\[ab]'
+match 1 '[ab]' '[[]ab]'
+match 1 '[ab]' '[[:]ab]'
+match 0 '[ab]' '[[::]ab]'
+match 1 '[ab]' '[[:digit]ab]'
+match 1 '[ab]' '[\[:]ab]'
+match 1 '?a?b' '\??\?b'
+match 1 'abc' '\a\b\c'
+match 0 'foo' ''
+match 1 'foo/bar/baz/to' '**/t[o]'
 
 # Character class tests
-match 1 x 'a1B' '[[:alpha:]][[:digit:]][[:upper:]]'
-match 0 x 'a' '[[:digit:][:upper:][:space:]]'
-match 1 x 'A' '[[:digit:][:upper:][:space:]]'
-match 1 x '1' '[[:digit:][:upper:][:space:]]'
-match 0 x '1' '[[:digit:][:upper:][:spaci:]]'
-match 1 x ' ' '[[:digit:][:upper:][:space:]]'
-match 0 x '.' '[[:digit:][:upper:][:space:]]'
-match 1 x '.' '[[:digit:][:punct:][:space:]]'
-match 1 x '5' '[[:xdigit:]]'
-match 1 x 'f' '[[:xdigit:]]'
-match 1 x 'D' '[[:xdigit:]]'
-match 1 x '_' '[[:alnum:][:alpha:][:blank:][:cntrl:][:digit:][:graph:][:lower:][:print:][:punct:][:space:][:upper:][:xdigit:]]'
-match 1 x '.' '[^[:alnum:][:alpha:][:blank:][:cntrl:][:digit:][:lower:][:space:][:upper:][:xdigit:]]'
-match 1 x '5' '[a-c[:digit:]x-z]'
-match 1 x 'b' '[a-c[:digit:]x-z]'
-match 1 x 'y' '[a-c[:digit:]x-z]'
-match 0 x 'q' '[a-c[:digit:]x-z]'
+match 1 'a1B' '[[:alpha:]][[:digit:]][[:upper:]]'
+match 0 'a' '[[:digit:][:upper:][:space:]]'
+match 1 'A' '[[:digit:][:upper:][:space:]]'
+match 1 '1' '[[:digit:][:upper:][:space:]]'
+match 0 '1' '[[:digit:][:upper:][:spaci:]]'
+match 1 ' ' '[[:digit:][:upper:][:space:]]'
+match 0 '.' '[[:digit:][:upper:][:space:]]'
+match 1 '.' '[[:digit:][:punct:][:space:]]'
+match 1 '5' '[[:xdigit:]]'
+match 1 'f' '[[:xdigit:]]'
+match 1 'D' '[[:xdigit:]]'
+match 1 '_' '[[:alnum:][:alpha:][:blank:][:cntrl:][:digit:][:graph:][:lower:][:print:][:punct:][:space:][:upper:][:xdigit:]]'
+match 1 '.' '[^[:alnum:][:alpha:][:blank:][:cntrl:][:digit:][:lower:][:space:][:upper:][:xdigit:]]'
+match 1 '5' '[a-c[:digit:]x-z]'
+match 1 'b' '[a-c[:digit:]x-z]'
+match 1 'y' '[a-c[:digit:]x-z]'
+match 0 'q' '[a-c[:digit:]x-z]'
 
 # Additional tests, including some malformed wildmats
-match 1 x ']' '[\\-^]'
-match 0 0 '[' '[\\-^]'
-match 1 x '-' '[\-_]'
-match 1 x ']' '[\]]'
-match 0 0 '\]' '[\]]'
-match 0 0 '\' '[\]]'
-match 0 0 'ab' 'a[]b'
-match 0 x 'a[]b' 'a[]b'
-match 0 x 'ab[' 'ab['
-match 0 0 'ab' '[!'
-match 0 0 'ab' '[-'
-match 1 1 '-' '[-]'
-match 0 0 '-' '[a-'
-match 0 0 '-' '[!a-'
-match 1 x '-' '[--A]'
-match 1 x '5' '[--A]'
-match 1 1 ' ' '[ --]'
-match 1 1 '$' '[ --]'
-match 1 1 '-' '[ --]'
-match 0 0 '0' '[ --]'
-match 1 x '-' '[---]'
-match 1 x '-' '[------]'
-match 0 0 'j' '[a-e-n]'
-match 1 x '-' '[a-e-n]'
-match 1 x 'a' '[!------]'
-match 0 0 '[' '[]-a]'
-match 1 x '^' '[]-a]'
-match 0 0 '^' '[!]-a]'
-match 1 x '[' '[!]-a]'
-match 1 1 '^' '[a^bc]'
-match 1 x '-b]' '[a-]b]'
-match 0 0 '\' '[\]'
-match 1 1 '\' '[\\]'
-match 0 0 '\' '[!\\]'
-match 1 1 'G' '[A-\\]'
-match 0 0 'aaabbb' 'b*a'
-match 0 0 'aabcaa' '*ba*'
-match 1 1 ',' '[,]'
-match 1 1 ',' '[\\,]'
-match 1 1 '\' '[\\,]'
-match 1 1 '-' '[,-.]'
-match 0 0 '+' '[,-.]'
-match 0 0 '-.]' '[,-.]'
-match 1 1 '2' '[\1-\3]'
-match 1 1 '3' '[\1-\3]'
-match 0 0 '4' '[\1-\3]'
-match 1 1 '\' '[[-\]]'
-match 1 1 '[' '[[-\]]'
-match 1 1 ']' '[[-\]]'
-match 0 0 '-' '[[-\]]'
+match 1 ']' '[\\-^]'
+match 0 '[' '[\\-^]'
+match 1 '-' '[\-_]'
+match 1 ']' '[\]]'
+match 0 '\]' '[\]]'
+match 0 '\' '[\]]'
+match 0 'ab' 'a[]b'
+match 0 'a[]b' 'a[]b'
+match 0 'ab[' 'ab['
+match 0 'ab' '[!'
+match 0 'ab' '[-'
+match 1 '-' '[-]'
+match 0 '-' '[a-'
+match 0 '-' '[!a-'
+match 1 '-' '[--A]'
+match 1 '5' '[--A]'
+match 1 ' ' '[ --]'
+match 1 '$' '[ --]'
+match 1 '-' '[ --]'
+match 0 '0' '[ --]'
+match 1 '-' '[---]'
+match 1 '-' '[------]'
+match 0 'j' '[a-e-n]'
+match 1 '-' '[a-e-n]'
+match 1 'a' '[!------]'
+match 0 '[' '[]-a]'
+match 1 '^' '[]-a]'
+match 0 '^' '[!]-a]'
+match 1 '[' '[!]-a]'
+match 1 '^' '[a^bc]'
+match 1 '-b]' '[a-]b]'
+match 0 '\' '[\]'
+match 1 '\' '[\\]'
+match 0 '\' '[!\\]'
+match 1 'G' '[A-\\]'
+match 0 'aaabbb' 'b*a'
+match 0 'aabcaa' '*ba*'
+match 1 ',' '[,]'
+match 1 ',' '[\\,]'
+match 1 '\' '[\\,]'
+match 1 '-' '[,-.]'
+match 0 '+' '[,-.]'
+match 0 '-.]' '[,-.]'
+match 1 '2' '[\1-\3]'
+match 1 '3' '[\1-\3]'
+match 0 '4' '[\1-\3]'
+match 1 '\' '[[-\]]'
+match 1 '[' '[[-\]]'
+match 1 ']' '[[-\]]'
+match 0 '-' '[[-\]]'
 
 # Test recursion and the abort code (use "wildtest -i" to see iteration counts)
-match 1 1 '-adobe-courier-bold-o-normal--12-120-75-75-m-70-iso8859-1' '-*-*-*-*-*-*-12-*-*-*-m-*-*-*'
-match 0 0 '-adobe-courier-bold-o-normal--12-120-75-75-X-70-iso8859-1' '-*-*-*-*-*-*-12-*-*-*-m-*-*-*'
-match 0 0 '-adobe-courier-bold-o-normal--12-120-75-75-/-70-iso8859-1' '-*-*-*-*-*-*-12-*-*-*-m-*-*-*'
-match 1 1 'XXX/adobe/courier/bold/o/normal//12/120/75/75/m/70/iso8859/1' 'XXX/*/*/*/*/*/*/12/*/*/*/m/*/*/*'
-match 0 0 'XXX/adobe/courier/bold/o/normal//12/120/75/75/X/70/iso8859/1' 'XXX/*/*/*/*/*/*/12/*/*/*/m/*/*/*'
-match 1 0 'abcd/abcdefg/abcdefghijk/abcdefghijklmnop.txt' '**/*a*b*g*n*t'
-match 0 0 'abcd/abcdefg/abcdefghijk/abcdefghijklmnop.txtz' '**/*a*b*g*n*t'
-match 0 x foo '*/*/*'
-match 0 x foo/bar '*/*/*'
-match 1 x foo/bba/arr '*/*/*'
-match 0 x foo/bb/aa/rr '*/*/*'
-match 1 x foo/bb/aa/rr '**/**/**'
-match 1 x abcXdefXghi '*X*i'
-match 0 x ab/cXd/efXg/hi '*X*i'
-match 1 x ab/cXd/efXg/hi '*/*X*/*/*i'
-match 1 x ab/cXd/efXg/hi '**/*X*/**/*i'
+match 1 '-adobe-courier-bold-o-normal--12-120-75-75-m-70-iso8859-1' '-*-*-*-*-*-*-12-*-*-*-m-*-*-*'
+match 0 '-adobe-courier-bold-o-normal--12-120-75-75-X-70-iso8859-1' '-*-*-*-*-*-*-12-*-*-*-m-*-*-*'
+match 0 '-adobe-courier-bold-o-normal--12-120-75-75-/-70-iso8859-1' '-*-*-*-*-*-*-12-*-*-*-m-*-*-*'
+match 1 'XXX/adobe/courier/bold/o/normal//12/120/75/75/m/70/iso8859/1' 'XXX/*/*/*/*/*/*/12/*/*/*/m/*/*/*'
+match 0 'XXX/adobe/courier/bold/o/normal//12/120/75/75/X/70/iso8859/1' 'XXX/*/*/*/*/*/*/12/*/*/*/m/*/*/*'
+match 1 'abcd/abcdefg/abcdefghijk/abcdefghijklmnop.txt' '**/*a*b*g*n*t'
+match 0 'abcd/abcdefg/abcdefghijk/abcdefghijklmnop.txtz' '**/*a*b*g*n*t'
+match 0 foo '*/*/*'
+match 0 foo/bar '*/*/*'
+match 1 foo/bba/arr '*/*/*'
+match 0 foo/bb/aa/rr '*/*/*'
+match 1 foo/bb/aa/rr '**/**/**'
+match 1 abcXdefXghi '*X*i'
+match 0 ab/cXd/efXg/hi '*X*i'
+match 1 ab/cXd/efXg/hi '*/*X*/*/*i'
+match 1 ab/cXd/efXg/hi '**/*X*/**/*i'
 
 pathmatch 1 foo foo
 pathmatch 0 foo fo
@@ -248,20 +248,20 @@ pathmatch 1 ab/cXd/efXg/hi '*/*X*/*/*i'
 pathmatch 1 ab/cXd/efXg/hi '*Xg*i'
 
 # Case-sensitivity features
-match 0 x 'a' '[A-Z]'
-match 1 x 'A' '[A-Z]'
-match 0 x 'A' '[a-z]'
-match 1 x 'a' '[a-z]'
-match 0 x 'a' '[[:upper:]]'
-match 1 x 'A' '[[:upper:]]'
-match 0 x 'A' '[[:lower:]]'
-match 1 x 'a' '[[:lower:]]'
-match 0 x 'A' '[B-Za]'
-match 1 x 'a' '[B-Za]'
-match 0 x 'A' '[B-a]'
-match 1 x 'a' '[B-a]'
-match 0 x 'z' '[Z-y]'
-match 1 x 'Z' '[Z-y]'
+match 0 'a' '[A-Z]'
+match 1 'A' '[A-Z]'
+match 0 'A' '[a-z]'
+match 1 'a' '[a-z]'
+match 0 'a' '[[:upper:]]'
+match 1 'A' '[[:upper:]]'
+match 0 'A' '[[:lower:]]'
+match 1 'a' '[[:lower:]]'
+match 0 'A' '[B-Za]'
+match 1 'a' '[B-Za]'
+match 0 'A' '[B-a]'
+match 1 'a' '[B-a]'
+match 0 'z' '[Z-y]'
+match 1 'Z' '[Z-y]'
 
 imatch 1 'a' '[A-Z]'
 imatch 1 'A' '[A-Z]'
-- 
2.15.1.424.g9478a66081
Ævar Arnfjörð Bjarmason· Dec 23, 2017, 21:30 UTC · re: Ævar Arnfjörð Bjarmason · lore

[PATCH 5/6] wildmatch test: perform all tests under all wildmatch() modes

Rewrite the wildmatch() test suite so that each test now tests all combinations of the wildmatch() WM_CASEFOLD and WM_PATHNAME flags.

Before this change some test inputs were not tested on e.g. WM_PATHNAME. Now the function is stress tested on all possible inputs, and for each input we declare what the result should be if the mode is case-insensitive, or pathname matching, or case-sensitive or not matching pathnames.

Also before this change, nothing was testing case-insensitive non-pathname matching, so I've added that to test-wildmatch.c and made use of it.

This yields a rather scary patch, but there are no functional changes here, just more test coverage. Some now-redundant tests were deleted as a result of this change, since they were now duplicating an earlier test.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 t/helper/test-wildmatch.c |   2 +
 t/t3070-wildmatch.sh      | 478 +++++++++++++++++++++++-----------------------
 2 files changed, 239 insertions(+), 241 deletions(-)
Show changes to 2 files +239 −241

t/helper/test-wildmatch.c, t/t3070-wildmatch.sh

diff --git a/t/helper/test-wildmatch.c b/t/helper/test-wildmatch.c
index 921d7b3e7e..66d33dfcfd 100644
--- a/t/helper/test-wildmatch.c
+++ b/t/helper/test-wildmatch.c
@@ -16,6 +16,8 @@ int cmd_main(int argc, const char **argv)
 		return !!wildmatch(argv[3], argv[2], WM_PATHNAME | WM_CASEFOLD);
 	else if (!strcmp(argv[1], "pathmatch"))
 		return !!wildmatch(argv[3], argv[2], 0);
+	else if (!strcmp(argv[1], "ipathmatch"))
+		return !!wildmatch(argv[3], argv[2], WM_CASEFOLD);
 	else
 		return 1;
 }
diff --git a/t/t3070-wildmatch.sh b/t/t3070-wildmatch.sh
index 1624200a1e..47b479e423 100755
--- a/t/t3070-wildmatch.sh
+++ b/t/t3070-wildmatch.sh
@@ -4,278 +4,274 @@ test_description='wildmatch tests'
 
 . ./test-lib.sh
 
-match() {
-	if test "$1" = 1
+wildtest() {
+	match_w_glob=$1
+	match_w_globi=$2
+	match_w_pathmatch=$3
+	match_w_pathmatchi=$4
+	text=$5
+	pattern=$6
+
+	if test "$match_w_glob" = 1
 	then
-		test_expect_success "wildmatch:     match '$2' '$3'" "
-			test-wildmatch wildmatch '$2' '$3'
+		test_expect_success "wildmatch:     match '$text' '$pattern'" "
+			test-wildmatch wildmatch '$text' '$pattern'
 		"
-	elif test "$1" = 0
+	elif test "$match_w_glob" = 0
 	then
-		test_expect_success "wildmatch:  no match '$2' '$3'" "
-			! test-wildmatch wildmatch '$2' '$3'
+		test_expect_success "wildmatch:  no match '$text' '$pattern'" "
+			! test-wildmatch wildmatch '$text' '$pattern'
 		"
 	else
-		test_expect_success "PANIC: Test framework error. Unknown matches value $1" 'false'
+		test_expect_success "PANIC: Test framework error. Unknown matches value $match_w_glob" 'false'
 	fi
-}
 
-imatch() {
-	if test "$1" = 1
+	if test "$match_w_globi" = 1
 	then
-		test_expect_success "iwildmatch:    match '$2' '$3'" "
-			test-wildmatch iwildmatch '$2' '$3'
+		test_expect_success "iwildmatch:    match '$text' '$pattern'" "
+			test-wildmatch iwildmatch '$text' '$pattern'
 		"
-	elif test "$1" = 0
+	elif test "$match_w_globi" = 0
 	then
-		test_expect_success "iwildmatch: no match '$2' '$3'" "
-			! test-wildmatch iwildmatch '$2' '$3'
+		test_expect_success "iwildmatch: no match '$text' '$pattern'" "
+			! test-wildmatch iwildmatch '$text' '$pattern'
 		"
 	else
-		test_expect_success "PANIC: Test framework error. Unknown matches value $1" 'false'
+		test_expect_success "PANIC: Test framework error. Unknown matches value $match_w_globi" 'false'
 	fi
-}
 
-pathmatch() {
-	if test "$1" = 1
+	if test "$match_w_pathmatch" = 1
 	then
-		test_expect_success "pathmatch:     match '$2' '$3'" "
-			test-wildmatch pathmatch '$2' '$3'
+		test_expect_success "pathmatch:     match '$text' '$pattern'" "
+			test-wildmatch pathmatch '$text' '$pattern'
 		"
-	elif test "$1" = 0
+	elif test "$match_w_pathmatch" = 0
 	then
-		test_expect_success "pathmatch:  no match '$2' '$3'" "
-			! test-wildmatch pathmatch '$2' '$3'
+		test_expect_success "pathmatch:  no match '$text' '$pattern'" "
+			! test-wildmatch pathmatch '$text' '$pattern'
 		"
 	else
-		test_expect_success "PANIC: Test framework error. Unknown matches value $1" 'false'
+		test_expect_success "PANIC: Test framework error. Unknown matches value $match_w_pathmatch" 'false'
+	fi
+
+	if test "$match_w_pathmatchi" = 1
+	then
+		test_expect_success "ipathmatch:    match '$text' '$pattern'" "
+			test-wildmatch ipathmatch '$text' '$pattern'
+		"
+	elif test "$match_w_pathmatchi" = 0
+	then
+		test_expect_success "ipathmatch: no match '$text' '$pattern'" "
+			! test-wildmatch ipathmatch '$text' '$pattern'
+		"
+	else
+		test_expect_success "PANIC: Test framework error. Unknown matches value $match_w_pathmatchi" 'false'
 	fi
 }
 
-# Basic wildmat features
-match 1 foo foo
-match 0 foo bar
-match 1 '' ""
-match 1 foo '???'
-match 0 foo '??'
-match 1 foo '*'
-match 1 foo 'f*'
-match 0 foo '*f'
-match 1 foo '*foo*'
-match 1 foobar '*ob*a*r*'
-match 1 aaaaaaabababab '*ab'
-match 1 'foo*' 'foo\*'
-match 0 foobar 'foo\*bar'
-match 1 'f\oo' 'f\\oo'
-match 1 ball '*[al]?'
-match 0 ten '[ten]'
-match 0 ten '**[!te]'
-match 0 ten '**[!ten]'
-match 1 ten 't[a-g]n'
-match 0 ten 't[!a-g]n'
-match 1 ton 't[!a-g]n'
-match 1 ton 't[^a-g]n'
-match 1 'a]b' 'a[]]b'
-match 1 a-b 'a[]-]b'
-match 1 'a]b' 'a[]-]b'
-match 0 aab 'a[]-]b'
-match 1 aab 'a[]a-]b'
-match 1 ']' ']'
+# Basic wildmatch features
+wildtest 1 1 1 1 foo foo
+wildtest 0 0 0 0 foo bar
+wildtest 1 1 1 1 '' ""
+wildtest 1 1 1 1 foo '???'
+wildtest 0 0 0 0 foo '??'
+wildtest 1 1 1 1 foo '*'
+wildtest 1 1 1 1 foo 'f*'
+wildtest 0 0 0 0 foo '*f'
+wildtest 1 1 1 1 foo '*foo*'
+wildtest 1 1 1 1 foobar '*ob*a*r*'
+wildtest 1 1 1 1 aaaaaaabababab '*ab'
+wildtest 1 1 1 1 'foo*' 'foo\*'
+wildtest 0 0 0 0 foobar 'foo\*bar'
+wildtest 1 1 1 1 'f\oo' 'f\\oo'
+wildtest 1 1 1 1 ball '*[al]?'
+wildtest 0 0 0 0 ten '[ten]'
+wildtest 0 0 1 1 ten '**[!te]'
+wildtest 0 0 0 0 ten '**[!ten]'
+wildtest 1 1 1 1 ten 't[a-g]n'
+wildtest 0 0 0 0 ten 't[!a-g]n'
+wildtest 1 1 1 1 ton 't[!a-g]n'
+wildtest 1 1 1 1 ton 't[^a-g]n'
+wildtest 1 1 1 1 'a]b' 'a[]]b'
+wildtest 1 1 1 1 a-b 'a[]-]b'
+wildtest 1 1 1 1 'a]b' 'a[]-]b'
+wildtest 0 0 0 0 aab 'a[]-]b'
+wildtest 1 1 1 1 aab 'a[]a-]b'
+wildtest 1 1 1 1 ']' ']'
 
 # Extended slash-matching features
-match 0 'foo/baz/bar' 'foo*bar'
-match 0 'foo/baz/bar' 'foo**bar'
-match 0 'foobazbar' 'foo**bar'
-match 1 'foo/baz/bar' 'foo/**/bar'
-match 1 'foo/baz/bar' 'foo/**/**/bar'
-match 1 'foo/b/a/z/bar' 'foo/**/bar'
-match 1 'foo/b/a/z/bar' 'foo/**/**/bar'
-match 1 'foo/bar' 'foo/**/bar'
-match 1 'foo/bar' 'foo/**/**/bar'
-match 0 'foo/bar' 'foo?bar'
-match 0 'foo/bar' 'foo[/]bar'
-match 0 'foo/bar' 'foo[^a-z]bar'
-match 0 'foo/bar' 'f[^eiu][^eiu][^eiu][^eiu][^eiu]r'
-match 1 'foo-bar' 'f[^eiu][^eiu][^eiu][^eiu][^eiu]r'
-match 1 'foo' '**/foo'
-match 1 'XXX/foo' '**/foo'
-match 1 'bar/baz/foo' '**/foo'
-match 0 'bar/baz/foo' '*/foo'
-match 0 'foo/bar/baz' '**/bar*'
-match 1 'deep/foo/bar/baz' '**/bar/*'
-match 0 'deep/foo/bar/baz/' '**/bar/*'
-match 1 'deep/foo/bar/baz/' '**/bar/**'
-match 0 'deep/foo/bar' '**/bar/*'
-match 1 'deep/foo/bar/' '**/bar/**'
-match 0 'foo/bar/baz' '**/bar**'
-match 1 'foo/bar/baz/x' '*/bar/**'
-match 0 'deep/foo/bar/baz/x' '*/bar/**'
-match 1 'deep/foo/bar/baz/x' '**/bar/*/*'
+wildtest 0 0 1 1 'foo/baz/bar' 'foo*bar'
+wildtest 0 0 1 1 'foo/baz/bar' 'foo**bar'
+wildtest 0 0 1 1 'foobazbar' 'foo**bar'
+wildtest 1 1 1 1 'foo/baz/bar' 'foo/**/bar'
+wildtest 1 1 0 0 'foo/baz/bar' 'foo/**/**/bar'
+wildtest 1 1 1 1 'foo/b/a/z/bar' 'foo/**/bar'
+wildtest 1 1 1 1 'foo/b/a/z/bar' 'foo/**/**/bar'
+wildtest 1 1 0 0 'foo/bar' 'foo/**/bar'
+wildtest 1 1 0 0 'foo/bar' 'foo/**/**/bar'
+wildtest 0 0 1 1 'foo/bar' 'foo?bar'
+wildtest 0 0 1 1 'foo/bar' 'foo[/]bar'
+wildtest 0 0 1 1 'foo/bar' 'foo[^a-z]bar'
+wildtest 0 0 1 1 'foo/bar' 'f[^eiu][^eiu][^eiu][^eiu][^eiu]r'
+wildtest 1 1 1 1 'foo-bar' 'f[^eiu][^eiu][^eiu][^eiu][^eiu]r'
+wildtest 1 1 0 0 'foo' '**/foo'
+wildtest 1 1 1 1 'XXX/foo' '**/foo'
+wildtest 1 1 1 1 'bar/baz/foo' '**/foo'
+wildtest 0 0 1 1 'bar/baz/foo' '*/foo'
+wildtest 0 0 1 1 'foo/bar/baz' '**/bar*'
+wildtest 1 1 1 1 'deep/foo/bar/baz' '**/bar/*'
+wildtest 0 0 1 1 'deep/foo/bar/baz/' '**/bar/*'
+wildtest 1 1 1 1 'deep/foo/bar/baz/' '**/bar/**'
+wildtest 0 0 0 0 'deep/foo/bar' '**/bar/*'
+wildtest 1 1 1 1 'deep/foo/bar/' '**/bar/**'
+wildtest 0 0 1 1 'foo/bar/baz' '**/bar**'
+wildtest 1 1 1 1 'foo/bar/baz/x' '*/bar/**'
+wildtest 0 0 1 1 'deep/foo/bar/baz/x' '*/bar/**'
+wildtest 1 1 1 1 'deep/foo/bar/baz/x' '**/bar/*/*'
 
 # Various additional tests
-match 0 'acrt' 'a[c-c]st'
-match 1 'acrt' 'a[c-c]rt'
-match 0 ']' '[!]-]'
-match 1 'a' '[!]-]'
-match 0 '' '\'
-match 0 '\' '\'
-match 0 'XXX/\' '*/\'
-match 1 'XXX/\' '*/\\'
-match 1 'foo' 'foo'
-match 1 '@foo' '@foo'
-match 0 'foo' '@foo'
-match 1 '[ab]' '\[ab]'
-match 1 '[ab]' '[[]ab]'
-match 1 '[ab]' '[[:]ab]'
-match 0 '[ab]' '[[::]ab]'
-match 1 '[ab]' '[[:digit]ab]'
-match 1 '[ab]' '[\[:]ab]'
-match 1 '?a?b' '\??\?b'
-match 1 'abc' '\a\b\c'
-match 0 'foo' ''
-match 1 'foo/bar/baz/to' '**/t[o]'
+wildtest 0 0 0 0 'acrt' 'a[c-c]st'
+wildtest 1 1 1 1 'acrt' 'a[c-c]rt'
+wildtest 0 0 0 0 ']' '[!]-]'
+wildtest 1 1 1 1 'a' '[!]-]'
+wildtest 0 0 0 0 '' '\'
+wildtest 0 0 0 0 '\' '\'
+wildtest 0 0 0 0 'XXX/\' '*/\'
+wildtest 1 1 1 1 'XXX/\' '*/\\'
+wildtest 1 1 1 1 'foo' 'foo'
+wildtest 1 1 1 1 '@foo' '@foo'
+wildtest 0 0 0 0 'foo' '@foo'
+wildtest 1 1 1 1 '[ab]' '\[ab]'
+wildtest 1 1 1 1 '[ab]' '[[]ab]'
+wildtest 1 1 1 1 '[ab]' '[[:]ab]'
+wildtest 0 0 0 0 '[ab]' '[[::]ab]'
+wildtest 1 1 1 1 '[ab]' '[[:digit]ab]'
+wildtest 1 1 1 1 '[ab]' '[\[:]ab]'
+wildtest 1 1 1 1 '?a?b' '\??\?b'
+wildtest 1 1 1 1 'abc' '\a\b\c'
+wildtest 0 0 0 0 'foo' ''
+wildtest 1 1 1 1 'foo/bar/baz/to' '**/t[o]'
 
 # Character class tests
-match 1 'a1B' '[[:alpha:]][[:digit:]][[:upper:]]'
-match 0 'a' '[[:digit:][:upper:][:space:]]'
-match 1 'A' '[[:digit:][:upper:][:space:]]'
-match 1 '1' '[[:digit:][:upper:][:space:]]'
-match 0 '1' '[[:digit:][:upper:][:spaci:]]'
-match 1 ' ' '[[:digit:][:upper:][:space:]]'
-match 0 '.' '[[:digit:][:upper:][:space:]]'
-match 1 '.' '[[:digit:][:punct:][:space:]]'
-match 1 '5' '[[:xdigit:]]'
-match 1 'f' '[[:xdigit:]]'
-match 1 'D' '[[:xdigit:]]'
-match 1 '_' '[[:alnum:][:alpha:][:blank:][:cntrl:][:digit:][:graph:][:lower:][:print:][:punct:][:space:][:upper:][:xdigit:]]'
-match 1 '.' '[^[:alnum:][:alpha:][:blank:][:cntrl:][:digit:][:lower:][:space:][:upper:][:xdigit:]]'
-match 1 '5' '[a-c[:digit:]x-z]'
-match 1 'b' '[a-c[:digit:]x-z]'
-match 1 'y' '[a-c[:digit:]x-z]'
-match 0 'q' '[a-c[:digit:]x-z]'
-
-# Additional tests, including some malformed wildmats
-match 1 ']' '[\\-^]'
-match 0 '[' '[\\-^]'
-match 1 '-' '[\-_]'
-match 1 ']' '[\]]'
-match 0 '\]' '[\]]'
-match 0 '\' '[\]]'
-match 0 'ab' 'a[]b'
-match 0 'a[]b' 'a[]b'
-match 0 'ab[' 'ab['
-match 0 'ab' '[!'
-match 0 'ab' '[-'
-match 1 '-' '[-]'
-match 0 '-' '[a-'
-match 0 '-' '[!a-'
-match 1 '-' '[--A]'
-match 1 '5' '[--A]'
-match 1 ' ' '[ --]'
-match 1 '$' '[ --]'
-match 1 '-' '[ --]'
-match 0 '0' '[ --]'
-match 1 '-' '[---]'
-match 1 '-' '[------]'
-match 0 'j' '[a-e-n]'
-match 1 '-' '[a-e-n]'
-match 1 'a' '[!------]'
-match 0 '[' '[]-a]'
-match 1 '^' '[]-a]'
-match 0 '^' '[!]-a]'
-match 1 '[' '[!]-a]'
-match 1 '^' '[a^bc]'
-match 1 '-b]' '[a-]b]'
-match 0 '\' '[\]'
-match 1 '\' '[\\]'
-match 0 '\' '[!\\]'
-match 1 'G' '[A-\\]'
-match 0 'aaabbb' 'b*a'
-match 0 'aabcaa' '*ba*'
-match 1 ',' '[,]'
-match 1 ',' '[\\,]'
-match 1 '\' '[\\,]'
-match 1 '-' '[,-.]'
-match 0 '+' '[,-.]'
-match 0 '-.]' '[,-.]'
-match 1 '2' '[\1-\3]'
-match 1 '3' '[\1-\3]'
-match 0 '4' '[\1-\3]'
-match 1 '\' '[[-\]]'
-match 1 '[' '[[-\]]'
-match 1 ']' '[[-\]]'
-match 0 '-' '[[-\]]'
+wildtest 1 1 1 1 'a1B' '[[:alpha:]][[:digit:]][[:upper:]]'
+wildtest 0 1 0 1 'a' '[[:digit:][:upper:][:space:]]'
+wildtest 1 1 1 1 'A' '[[:digit:][:upper:][:space:]]'
+wildtest 1 1 1 1 '1' '[[:digit:][:upper:][:space:]]'
+wildtest 0 0 0 0 '1' '[[:digit:][:upper:][:spaci:]]'
+wildtest 1 1 1 1 ' ' '[[:digit:][:upper:][:space:]]'
+wildtest 0 0 0 0 '.' '[[:digit:][:upper:][:space:]]'
+wildtest 1 1 1 1 '.' '[[:digit:][:punct:][:space:]]'
+wildtest 1 1 1 1 '5' '[[:xdigit:]]'
+wildtest 1 1 1 1 'f' '[[:xdigit:]]'
+wildtest 1 1 1 1 'D' '[[:xdigit:]]'
+wildtest 1 1 1 1 '_' '[[:alnum:][:alpha:][:blank:][:cntrl:][:digit:][:graph:][:lower:][:print:][:punct:][:space:][:upper:][:xdigit:]]'
+wildtest 1 1 1 1 '.' '[^[:alnum:][:alpha:][:blank:][:cntrl:][:digit:][:lower:][:space:][:upper:][:xdigit:]]'
+wildtest 1 1 1 1 '5' '[a-c[:digit:]x-z]'
+wildtest 1 1 1 1 'b' '[a-c[:digit:]x-z]'
+wildtest 1 1 1 1 'y' '[a-c[:digit:]x-z]'
+wildtest 0 0 0 0 'q' '[a-c[:digit:]x-z]'
 
-# Test recursion and the abort code (use "wildtest -i" to see iteration counts)
-match 1 '-adobe-courier-bold-o-normal--12-120-75-75-m-70-iso8859-1' '-*-*-*-*-*-*-12-*-*-*-m-*-*-*'
-match 0 '-adobe-courier-bold-o-normal--12-120-75-75-X-70-iso8859-1' '-*-*-*-*-*-*-12-*-*-*-m-*-*-*'
-match 0 '-adobe-courier-bold-o-normal--12-120-75-75-/-70-iso8859-1' '-*-*-*-*-*-*-12-*-*-*-m-*-*-*'
-match 1 'XXX/adobe/courier/bold/o/normal//12/120/75/75/m/70/iso8859/1' 'XXX/*/*/*/*/*/*/12/*/*/*/m/*/*/*'
-match 0 'XXX/adobe/courier/bold/o/normal//12/120/75/75/X/70/iso8859/1' 'XXX/*/*/*/*/*/*/12/*/*/*/m/*/*/*'
-match 1 'abcd/abcdefg/abcdefghijk/abcdefghijklmnop.txt' '**/*a*b*g*n*t'
-match 0 'abcd/abcdefg/abcdefghijk/abcdefghijklmnop.txtz' '**/*a*b*g*n*t'
-match 0 foo '*/*/*'
-match 0 foo/bar '*/*/*'
-match 1 foo/bba/arr '*/*/*'
-match 0 foo/bb/aa/rr '*/*/*'
-match 1 foo/bb/aa/rr '**/**/**'
-match 1 abcXdefXghi '*X*i'
-match 0 ab/cXd/efXg/hi '*X*i'
-match 1 ab/cXd/efXg/hi '*/*X*/*/*i'
-match 1 ab/cXd/efXg/hi '**/*X*/**/*i'
+# Additional tests, including some malformed wildmatch patterns
+wildtest 1 1 1 1 ']' '[\\-^]'
+wildtest 0 0 0 0 '[' '[\\-^]'
+wildtest 1 1 1 1 '-' '[\-_]'
+wildtest 1 1 1 1 ']' '[\]]'
+wildtest 0 0 0 0 '\]' '[\]]'
+wildtest 0 0 0 0 '\' '[\]]'
+wildtest 0 0 0 0 'ab' 'a[]b'
+wildtest 0 0 0 0 'a[]b' 'a[]b'
+wildtest 0 0 0 0 'ab[' 'ab['
+wildtest 0 0 0 0 'ab' '[!'
+wildtest 0 0 0 0 'ab' '[-'
+wildtest 1 1 1 1 '-' '[-]'
+wildtest 0 0 0 0 '-' '[a-'
+wildtest 0 0 0 0 '-' '[!a-'
+wildtest 1 1 1 1 '-' '[--A]'
+wildtest 1 1 1 1 '5' '[--A]'
+wildtest 1 1 1 1 ' ' '[ --]'
+wildtest 1 1 1 1 '$' '[ --]'
+wildtest 1 1 1 1 '-' '[ --]'
+wildtest 0 0 0 0 '0' '[ --]'
+wildtest 1 1 1 1 '-' '[---]'
+wildtest 1 1 1 1 '-' '[------]'
+wildtest 0 0 0 0 'j' '[a-e-n]'
+wildtest 1 1 1 1 '-' '[a-e-n]'
+wildtest 1 1 1 1 'a' '[!------]'
+wildtest 0 0 0 0 '[' '[]-a]'
+wildtest 1 1 1 1 '^' '[]-a]'
+wildtest 0 0 0 0 '^' '[!]-a]'
+wildtest 1 1 1 1 '[' '[!]-a]'
+wildtest 1 1 1 1 '^' '[a^bc]'
+wildtest 1 1 1 1 '-b]' '[a-]b]'
+wildtest 0 0 0 0 '\' '[\]'
+wildtest 1 1 1 1 '\' '[\\]'
+wildtest 0 0 0 0 '\' '[!\\]'
+wildtest 1 1 1 1 'G' '[A-\\]'
+wildtest 0 0 0 0 'aaabbb' 'b*a'
+wildtest 0 0 0 0 'aabcaa' '*ba*'
+wildtest 1 1 1 1 ',' '[,]'
+wildtest 1 1 1 1 ',' '[\\,]'
+wildtest 1 1 1 1 '\' '[\\,]'
+wildtest 1 1 1 1 '-' '[,-.]'
+wildtest 0 0 0 0 '+' '[,-.]'
+wildtest 0 0 0 0 '-.]' '[,-.]'
+wildtest 1 1 1 1 '2' '[\1-\3]'
+wildtest 1 1 1 1 '3' '[\1-\3]'
+wildtest 0 0 0 0 '4' '[\1-\3]'
+wildtest 1 1 1 1 '\' '[[-\]]'
+wildtest 1 1 1 1 '[' '[[-\]]'
+wildtest 1 1 1 1 ']' '[[-\]]'
+wildtest 0 0 0 0 '-' '[[-\]]'
 
-pathmatch 1 foo foo
-pathmatch 0 foo fo
-pathmatch 1 foo/bar foo/bar
-pathmatch 1 foo/bar 'foo/*'
-pathmatch 1 foo/bba/arr 'foo/*'
-pathmatch 1 foo/bba/arr 'foo/**'
-pathmatch 1 foo/bba/arr 'foo*'
-pathmatch 1 foo/bba/arr 'foo**'
-pathmatch 1 foo/bba/arr 'foo/*arr'
-pathmatch 1 foo/bba/arr 'foo/**arr'
-pathmatch 0 foo/bba/arr 'foo/*z'
-pathmatch 0 foo/bba/arr 'foo/**z'
-pathmatch 1 foo/bar 'foo?bar'
-pathmatch 1 foo/bar 'foo[/]bar'
-pathmatch 1 foo/bar 'foo[^a-z]bar'
-pathmatch 0 foo '*/*/*'
-pathmatch 0 foo/bar '*/*/*'
-pathmatch 1 foo/bba/arr '*/*/*'
-pathmatch 1 foo/bb/aa/rr '*/*/*'
-pathmatch 1 abcXdefXghi '*X*i'
-pathmatch 1 ab/cXd/efXg/hi '*/*X*/*/*i'
-pathmatch 1 ab/cXd/efXg/hi '*Xg*i'
+# Test recursion
+wildtest 1 1 1 1 '-adobe-courier-bold-o-normal--12-120-75-75-m-70-iso8859-1' '-*-*-*-*-*-*-12-*-*-*-m-*-*-*'
+wildtest 0 0 0 0 '-adobe-courier-bold-o-normal--12-120-75-75-X-70-iso8859-1' '-*-*-*-*-*-*-12-*-*-*-m-*-*-*'
+wildtest 0 0 0 0 '-adobe-courier-bold-o-normal--12-120-75-75-/-70-iso8859-1' '-*-*-*-*-*-*-12-*-*-*-m-*-*-*'
+wildtest 1 1 1 1 'XXX/adobe/courier/bold/o/normal//12/120/75/75/m/70/iso8859/1' 'XXX/*/*/*/*/*/*/12/*/*/*/m/*/*/*'
+wildtest 0 0 0 0 'XXX/adobe/courier/bold/o/normal//12/120/75/75/X/70/iso8859/1' 'XXX/*/*/*/*/*/*/12/*/*/*/m/*/*/*'
+wildtest 1 1 1 1 'abcd/abcdefg/abcdefghijk/abcdefghijklmnop.txt' '**/*a*b*g*n*t'
+wildtest 0 0 0 0 'abcd/abcdefg/abcdefghijk/abcdefghijklmnop.txtz' '**/*a*b*g*n*t'
+wildtest 0 0 0 0 foo '*/*/*'
+wildtest 0 0 0 0 foo/bar '*/*/*'
+wildtest 1 1 1 1 foo/bba/arr '*/*/*'
+wildtest 0 0 1 1 foo/bb/aa/rr '*/*/*'
+wildtest 1 1 1 1 foo/bb/aa/rr '**/**/**'
+wildtest 1 1 1 1 abcXdefXghi '*X*i'
+wildtest 0 0 1 1 ab/cXd/efXg/hi '*X*i'
+wildtest 1 1 1 1 ab/cXd/efXg/hi '*/*X*/*/*i'
+wildtest 1 1 1 1 ab/cXd/efXg/hi '**/*X*/**/*i'
 
-# Case-sensitivity features
-match 0 'a' '[A-Z]'
-match 1 'A' '[A-Z]'
-match 0 'A' '[a-z]'
-match 1 'a' '[a-z]'
-match 0 'a' '[[:upper:]]'
-match 1 'A' '[[:upper:]]'
-match 0 'A' '[[:lower:]]'
-match 1 'a' '[[:lower:]]'
-match 0 'A' '[B-Za]'
-match 1 'a' '[B-Za]'
-match 0 'A' '[B-a]'
-match 1 'a' '[B-a]'
-match 0 'z' '[Z-y]'
-match 1 'Z' '[Z-y]'
+# Extra pathmatch tests
+wildtest 0 0 0 0 foo fo
+wildtest 1 1 1 1 foo/bar foo/bar
+wildtest 1 1 1 1 foo/bar 'foo/*'
+wildtest 0 0 1 1 foo/bba/arr 'foo/*'
+wildtest 1 1 1 1 foo/bba/arr 'foo/**'
+wildtest 0 0 1 1 foo/bba/arr 'foo*'
+wildtest 0 0 1 1 foo/bba/arr 'foo**'
+wildtest 0 0 1 1 foo/bba/arr 'foo/*arr'
+wildtest 0 0 1 1 foo/bba/arr 'foo/**arr'
+wildtest 0 0 0 0 foo/bba/arr 'foo/*z'
+wildtest 0 0 0 0 foo/bba/arr 'foo/**z'
+wildtest 0 0 1 1 foo/bar 'foo?bar'
+wildtest 0 0 1 1 foo/bar 'foo[/]bar'
+wildtest 0 0 1 1 foo/bar 'foo[^a-z]bar'
+wildtest 0 0 1 1 ab/cXd/efXg/hi '*Xg*i'
 
-imatch 1 'a' '[A-Z]'
-imatch 1 'A' '[A-Z]'
-imatch 1 'A' '[a-z]'
-imatch 1 'a' '[a-z]'
-imatch 1 'a' '[[:upper:]]'
-imatch 1 'A' '[[:upper:]]'
-imatch 1 'A' '[[:lower:]]'
-imatch 1 'a' '[[:lower:]]'
-imatch 1 'A' '[B-Za]'
-imatch 1 'a' '[B-Za]'
-imatch 1 'A' '[B-a]'
-imatch 1 'a' '[B-a]'
-imatch 1 'z' '[Z-y]'
-imatch 1 'Z' '[Z-y]'
+# Extra case-sensitivity tests
+wildtest 0 1 0 1 'a' '[A-Z]'
+wildtest 1 1 1 1 'A' '[A-Z]'
+wildtest 0 1 0 1 'A' '[a-z]'
+wildtest 1 1 1 1 'a' '[a-z]'
+wildtest 0 1 0 1 'a' '[[:upper:]]'
+wildtest 1 1 1 1 'A' '[[:upper:]]'
+wildtest 0 1 0 1 'A' '[[:lower:]]'
+wildtest 1 1 1 1 'a' '[[:lower:]]'
+wildtest 0 1 0 1 'A' '[B-Za]'
+wildtest 1 1 1 1 'a' '[B-Za]'
+wildtest 0 1 0 1 'A' '[B-a]'
+wildtest 1 1 1 1 'a' '[B-a]'
+wildtest 0 1 0 1 'z' '[Z-y]'
+wildtest 1 1 1 1 'Z' '[Z-y]'
 
 test_done
-- 
2.15.1.424.g9478a66081
Ævar Arnfjörð Bjarmason· Dec 23, 2017, 21:30 UTC · re: Ævar Arnfjörð Bjarmason · lore

[PATCH 6/6] wildmatch test: create & test files on disk in addition to in-memory

There has never been any full roundtrip testing of what git-ls-files and other functions that use wildmatch() actually do, rather we've been satisfied with just testing the underlying C function.

Due to git-ls-files and friends having their own codepaths before they call wildmatch() there's sometimes differences in the behavior between the two, and even when we test for those (as with 9e4e8a64c2 ("pathspec: die on empty strings as pathspec", 2017-06-06)) there was no one place where you can review how these two modes differ.

Now there is. With this admittedly very verbose code that's mostly copy-pasted (it doesn't look worth the effort to me in clarity to factor this into functions) we now attempt to create a file called $haystack and match $needle against it for each pair of $needle and $haystack that we were passing to test-wildmatch.

If we can't create the file we skip the test. This ensures that we can run this on all platforms and not maintain some infinitely growing whitelist of e.g. platforms that don't support certain characters in filenames.

As a result of doing this we can now see the cases where these two ways of testing wildmatch differ:

 * Creating a file called 'a[]b' and running ls-files 'a[]b' will show
   that file, but wildmatch("a[]b", "a[]b") will not match
 * wildmatch() won't match a file called \ against \, but ls-files
   will.
 * `git --glob-pathspecs ls-files 'foo**'` will match a file
   'foo/bba/arr', but wildmatch won't, however pathmatch will.
   This seems like a bug to me, the two are otherwise equivalent as
   these tests show.

This also reveals the case discussed in 9e4e8a64c2 above, where '' is now an error as far as ls-files is concerned, but wildmatch() itself happily accepts it.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 a[]b                 |   0
 t/t3070-wildmatch.sh | 336 ++++++++++++++++++++++++++++++++++++++++++++++++---
 2 files changed, 319 insertions(+), 17 deletions(-)
 create mode 100644 a[]b
Show changes to 2 files +319 −17

a[]b, t/t3070-wildmatch.sh

diff --git a/a[]b b/a[]b
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/t/t3070-wildmatch.sh b/t/t3070-wildmatch.sh
index 47b479e423..d423bb01f3 100755
--- a/t/t3070-wildmatch.sh
+++ b/t/t3070-wildmatch.sh
@@ -4,31 +4,146 @@ test_description='wildmatch tests'
 
 . ./test-lib.sh
 
+create_test_file() {
+	file=$1
+
+	# `touch .` will succeed but obviously not do what we intend
+	# here.
+	test "$file" = "." && return 1
+	# We cannot create a file with an empty filename.
+	test "$file" = "" && return 1
+	# The tests that are testing that e.g. foo//bar is matched by
+	# foo/*/bar can't be tested on filesystems since there's no
+	# way we're getting a double slash.
+	echo "$file" | grep -q -F '//' && return 1
+	# When testing the difference between foo/bar and foo/bar/ we
+	# can't test the latter.
+	echo "$file" | grep -q -E '/$' && return 1
+
+	dirs=$(echo "$file" | sed -r 's!/[^/]+$!!')
+
+	# We touch "./$file" instead of "$file" because even an
+	# escaped "touch -- -" means something different.
+	if test "$file" != "$dirs"
+	then
+		mkdir -p -- "$dirs" 2>/dev/null &&
+		touch -- "./$file" 2>/dev/null &&
+		return 0
+	else
+		touch -- "./$file" 2>/dev/null &&
+		return 0
+	fi
+	return 1
+}
+
 wildtest() {
-	match_w_glob=$1
-	match_w_globi=$2
-	match_w_pathmatch=$3
-	match_w_pathmatchi=$4
-	text=$5
-	pattern=$6
+	if test "$#" = 6
+	then
+		# When test-wildmatch and git ls-files produce the same
+		# result.
+		match_w_glob=$1
+		match_f_w_glob=$match_w_glob
+		match_w_globi=$2
+		match_f_w_globi=$match_w_globi
+		match_w_pathmatch=$3
+		match_f_w_pathmatch=$match_w_pathmatch
+		match_w_pathmatchi=$4
+		match_f_w_pathmatchi=$match_w_pathmatchi
+		text=$5
+		pattern=$6
+	elif test "$#" = 10
+	then
+		match_w_glob=$1
+		match_w_globi=$2
+		match_w_pathmatch=$3
+		match_w_pathmatchi=$4
+		match_f_w_glob=$5
+		match_f_w_globi=$6
+		match_f_w_pathmatch=$7
+		match_f_w_pathmatchi=$8
+		text=$9
+		pattern=$10
+	fi
 
+	# $1: Case sensitive glob match: test-wildmatch
 	if test "$match_w_glob" = 1
 	then
-		test_expect_success "wildmatch:     match '$text' '$pattern'" "
+		test_expect_success "wildmatch: match '$text' '$pattern'" "
 			test-wildmatch wildmatch '$text' '$pattern'
 		"
 	elif test "$match_w_glob" = 0
 	then
-		test_expect_success "wildmatch:  no match '$text' '$pattern'" "
+		test_expect_success "wildmatch: no match '$text' '$pattern'" "
 			! test-wildmatch wildmatch '$text' '$pattern'
 		"
 	else
 		test_expect_success "PANIC: Test framework error. Unknown matches value $match_w_glob" 'false'
 	fi
 
+	# $1: Case sensitive glob match: ls-files
+	if test "$match_f_w_glob" = 'E'
+	then
+		if create_test_file "$text"
+		then
+			test_expect_success "wildmatch(ls): match dies on '$pattern' '$text'" "
+				test_when_finished \"
+					rm -rf -- * &&
+					git reset
+				\" &&
+				git add -A &&
+				>expect.err &&
+				printf '%s' '$text' >expect &&
+				test_must_fail git --glob-pathspecs ls-files -z -- '$pattern'
+			"
+		else
+			test_expect_failure "wildmatch(ls): match skip '$pattern' '$text'" 'false'
+		fi
+	elif test "$match_f_w_glob" = 1
+	then
+		if create_test_file "$text"
+		then
+			test_expect_success "wildmatch(ls): match '$pattern' '$text'" "
+				test_when_finished \"
+					rm -rf -- * &&
+					git reset
+				\" &&
+				git add -A &&
+				>expect.err &&
+				printf '%s' '$text' >expect &&
+				git --glob-pathspecs ls-files -z -- '$pattern' 2>actual.err | tr -d '\0' >actual &&
+				test_cmp expect.err actual.err &&
+				test_cmp expect actual
+			"
+		else
+			test_expect_failure "wildmatch(ls): match skip '$pattern' '$text'" 'false'
+		fi
+	elif test "$match_f_w_glob" = 0
+	then
+		if create_test_file "$text"
+		then
+			test_expect_success "wildmatch(ls): no match '$pattern' '$text'" "
+				test_when_finished \"
+					rm -rf -- * &&
+					git reset
+				\" &&
+				git add -A &&
+				>expect.err &&
+				>expect &&
+				git --glob-pathspecs ls-files -z -- '$pattern' 2>actual.err | tr -d '\0' >actual &&
+				test_cmp expect.err actual.err &&
+				test_cmp expect actual
+			"
+		else
+			test_expect_failure "wildmatch(ls): no match skip '$pattern' '$text'" 'false'
+		fi
+	else
+		test_expect_success "PANIC: Test framework error. Unknown matches value $match_f_w_glob" 'false'
+	fi
+
+	# $2: Case insensitive glob match: test-wildmatch
 	if test "$match_w_globi" = 1
 	then
-		test_expect_success "iwildmatch:    match '$text' '$pattern'" "
+		test_expect_success "iwildmatch: match '$text' '$pattern'" "
 			test-wildmatch iwildmatch '$text' '$pattern'
 		"
 	elif test "$match_w_globi" = 0
@@ -40,23 +155,145 @@ wildtest() {
 		test_expect_success "PANIC: Test framework error. Unknown matches value $match_w_globi" 'false'
 	fi
 
+	# $2: Case insensitive glob match: ls-files
+	if test "$match_f_w_globi" = 'E'
+	then
+		if create_test_file "$text"
+		then
+			test_expect_success "wildmatch(ls): match dies on '$pattern' '$text'" "
+				test_when_finished \"
+					rm -rf -- * &&
+					git reset
+				\" &&
+				git add -A &&
+				>expect.err &&
+				printf '%s' '$text' >expect &&
+				test_must_fail git --glob-pathspecs --icase-pathspecs ls-files -z -- '$pattern'
+			"
+		else
+			test_expect_failure "wildmatch(ls): match skip '$pattern' '$text'" 'false'
+		fi
+	elif test "$match_f_w_globi" = 1
+	then
+		if create_test_file "$text"
+		then
+			test_expect_success "wildmatch(ls): match '$pattern' '$text'" "
+				test_when_finished \"
+					rm -rf -- * &&
+					git reset
+				\" &&
+				git add -A &&
+				>expect.err &&
+				printf '%s' '$text' >expect &&
+				git --glob-pathspecs --icase-pathspecs ls-files -z -- '$pattern' 2>actual.err | tr -d '\0' >actual &&
+				test_cmp expect.err actual.err &&
+				test_cmp expect actual
+			"
+		else
+			test_expect_failure "wildmatch(ls): match skip '$pattern' '$text'" 'false'
+		fi
+	elif test "$match_f_w_globi" = 0
+	then
+		if create_test_file "$text"
+		then
+			test_expect_success "wildmatch(ls): no match '$pattern' '$text'" "
+				test_when_finished \"
+					rm -rf -- * &&
+					git reset
+				\" &&
+				git add -A &&
+				>expect.err &&
+				>expect &&
+				git --glob-pathspecs --icase-pathspecs ls-files -z -- '$pattern' 2>actual.err | tr -d '\0' >actual &&
+				test_cmp expect.err actual.err &&
+				test_cmp expect actual
+			"
+		else
+			test_expect_failure "wildmatch(ls): no match skip '$pattern' '$text'" 'false'
+		fi
+	else
+		test_expect_success "PANIC: Test framework error. Unknown matches value $match_f_w_globi" 'false'
+	fi
+
+	# $3: Case sensitive path match: test-wildmatch
 	if test "$match_w_pathmatch" = 1
 	then
-		test_expect_success "pathmatch:     match '$text' '$pattern'" "
+		test_expect_success "pathmatch: match '$text' '$pattern'" "
 			test-wildmatch pathmatch '$text' '$pattern'
 		"
 	elif test "$match_w_pathmatch" = 0
 	then
-		test_expect_success "pathmatch:  no match '$text' '$pattern'" "
+		test_expect_success "pathmatch: no match '$text' '$pattern'" "
 			! test-wildmatch pathmatch '$text' '$pattern'
 		"
 	else
 		test_expect_success "PANIC: Test framework error. Unknown matches value $match_w_pathmatch" 'false'
 	fi
 
+	# $4: Case sensitive path match: ls-files
+	if test "$match_f_w_pathmatch" = 'E'
+	then
+		if create_test_file "$text"
+		then
+			test_expect_success "pathmatch(ls): match dies on '$pattern' '$text'" "
+				test_when_finished \"
+					rm -rf -- * &&
+					git reset
+				\" &&
+				git add -A &&
+				>expect.err &&
+				printf '%s' '$text' >expect &&
+				test_must_fail git ls-files -z -- '$pattern'
+			"
+		else
+			test_expect_failure "pathmatch(ls): match skip '$pattern' '$text'" 'false'
+		fi
+	elif test "$match_f_w_pathmatch" = 1
+	then
+		if create_test_file "$text"
+		then
+			test_expect_success "pathmatch(ls): match '$pattern' '$text'" "
+				test_when_finished \"
+					rm -rf -- * &&
+					git reset
+				\" &&
+				git add -A &&
+				>expect.err &&
+				printf '%s' '$text' >expect &&
+				git ls-files -z -- '$pattern' 2>actual.err | tr -d '\0' >actual &&
+				test_cmp expect.err actual.err &&
+				test_cmp expect actual
+			"
+		else
+			test_expect_failure "pathmatch(ls): match skip '$pattern' '$text'" 'false'
+		fi
+	elif test "$match_f_w_pathmatch" = 0
+	then
+		if create_test_file "$text"
+		then
+			test_expect_success "pathmatch(ls): no match '$pattern' '$text'" "
+				test_when_finished \"
+					rm -rf -- * &&
+					git reset
+				\" &&
+				git add -A &&
+				>expect.err &&
+				>expect &&
+				git ls-files -z -- '$pattern' 2>actual.err | tr -d '\0' >actual &&
+				test_cmp expect.err actual.err &&
+				test_cmp expect actual
+			"
+		else
+			test_expect_failure "pathmatch(ls): no match skip '$pattern' '$text'" 'false'
+		fi
+	else
+		test_expect_success "PANIC: Test framework error. Unknown matches value $match_f_w_pathmatch" 'false'
+	fi
+
+	# $4: Case insensitive path match: test-wildmatch
 	if test "$match_w_pathmatchi" = 1
 	then
-		test_expect_success "ipathmatch:    match '$text' '$pattern'" "
+		test_expect_success "ipathmatch: match '$text' '$pattern'" "
 			test-wildmatch ipathmatch '$text' '$pattern'
 		"
 	elif test "$match_w_pathmatchi" = 0
@@ -67,6 +304,66 @@ wildtest() {
 	else
 		test_expect_success "PANIC: Test framework error. Unknown matches value $match_w_pathmatchi" 'false'
 	fi
+
+	# $4: Case insensitive path match: ls-files
+	if test "$match_f_w_pathmatchi" = 'E'
+	then
+		if create_test_file "$text"
+		then
+			test_expect_success "ipathmatch(ls): match dies on '$pattern' '$text'" "
+				test_when_finished \"
+					rm -rf -- * &&
+					git reset
+				\" &&
+				git add -A &&
+				>expect.err &&
+				printf '%s' '$text' >expect &&
+				test_must_fail git --icase-pathspecs ls-files -z -- '$pattern'
+			"
+		else
+			test_expect_failure "pathmatch(ls): match skip '$pattern' '$text'" 'false'
+		fi
+	elif test "$match_f_w_pathmatchi" = 1
+	then
+		if create_test_file "$text"
+		then
+			test_expect_success "ipathmatch(ls): match '$pattern' '$text'" "
+				test_when_finished \"
+					rm -rf -- * &&
+					git reset
+				\" &&
+				git add -A &&
+				>expect.err &&
+				printf '%s' '$text' >expect &&
+				git --icase-pathspecs ls-files -z -- '$pattern' 2>actual.err | tr -d '\0' >actual &&
+				test_cmp expect.err actual.err &&
+				test_cmp expect actual
+			"
+		else
+			test_expect_failure "pathmatch(ls): match skip '$pattern' '$text'" 'false'
+		fi
+	elif test "$match_f_w_pathmatchi" = 0
+	then
+		if create_test_file "$text"
+		then
+			test_expect_success "ipathmatch(ls): no match '$pattern' '$text'" "
+				test_when_finished \"
+					rm -rf -- * &&
+					git reset
+				\" &&
+				git add -A &&
+				>expect.err &&
+				>expect &&
+				git ls-files -z -- '$pattern' 2>actual.err | tr -d '\0' >actual &&
+				test_cmp expect.err actual.err &&
+				test_cmp expect actual
+			"
+		else
+			test_expect_failure "pathmatch(ls): no match skip '$pattern' '$text'" 'false'
+		fi
+	else
+		test_expect_success "PANIC: Test framework error. Unknown matches value $match_f_w_pathmatchi" 'false'
+	fi
 }
 
 # Basic wildmatch features
@@ -135,7 +432,8 @@ wildtest 1 1 1 1 'acrt' 'a[c-c]rt'
 wildtest 0 0 0 0 ']' '[!]-]'
 wildtest 1 1 1 1 'a' '[!]-]'
 wildtest 0 0 0 0 '' '\'
-wildtest 0 0 0 0 '\' '\'
+wildtest 0 0 0 0 \
+	 1 1 1 1 '\' '\'
 wildtest 0 0 0 0 'XXX/\' '*/\'
 wildtest 1 1 1 1 'XXX/\' '*/\\'
 wildtest 1 1 1 1 'foo' 'foo'
@@ -149,7 +447,8 @@ wildtest 1 1 1 1 '[ab]' '[[:digit]ab]'
 wildtest 1 1 1 1 '[ab]' '[\[:]ab]'
 wildtest 1 1 1 1 '?a?b' '\??\?b'
 wildtest 1 1 1 1 'abc' '\a\b\c'
-wildtest 0 0 0 0 'foo' ''
+wildtest 0 0 0 0 \
+	 E E E E 'foo' ''
 wildtest 1 1 1 1 'foo/bar/baz/to' '**/t[o]'
 
 # Character class tests
@@ -179,8 +478,10 @@ wildtest 1 1 1 1 ']' '[\]]'
 wildtest 0 0 0 0 '\]' '[\]]'
 wildtest 0 0 0 0 '\' '[\]]'
 wildtest 0 0 0 0 'ab' 'a[]b'
-wildtest 0 0 0 0 'a[]b' 'a[]b'
-wildtest 0 0 0 0 'ab[' 'ab['
+wildtest 0 0 0 0 \
+	 1 1 1 1 'a[]b' 'a[]b'
+wildtest 0 0 0 0 \
+	 1 1 1 1 'ab[' 'ab['
 wildtest 0 0 0 0 'ab' '[!'
 wildtest 0 0 0 0 'ab' '[-'
 wildtest 1 1 1 1 '-' '[-]'
@@ -248,7 +549,8 @@ wildtest 1 1 1 1 foo/bar 'foo/*'
 wildtest 0 0 1 1 foo/bba/arr 'foo/*'
 wildtest 1 1 1 1 foo/bba/arr 'foo/**'
 wildtest 0 0 1 1 foo/bba/arr 'foo*'
-wildtest 0 0 1 1 foo/bba/arr 'foo**'
+wildtest 0 0 1 1 \
+	 1 1 1 1 foo/bba/arr 'foo**'
 wildtest 0 0 1 1 foo/bba/arr 'foo/*arr'
 wildtest 0 0 1 1 foo/bba/arr 'foo/**arr'
 wildtest 0 0 0 0 foo/bba/arr 'foo/*z'
-- 
2.15.1.424.g9478a66081
Johannes Sixt· Dec 24, 2017, 09:24 UTC · re: Ævar Arnfjörð Bjarmason · lore

Re: [PATCH 6/6] wildmatch test: create & test files on disk in addition to in-memory

Am 23.12.2017 um 22:30 schrieb Ævar Arnfjörð Bjarmason:
Show 10 quoted lines
> Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
> ---
>   a[]b                 |   0
>   t/t3070-wildmatch.sh | 336 ++++++++++++++++++++++++++++++++++++++++++++++++---
>   2 files changed, 319 insertions(+), 17 deletions(-)
>   create mode 100644 a[]b
> 
> diff --git a/a[]b b/a[]b
> new file mode 100644
> index 0000000000..e69de29bb2
A big no-no! This file can't be created on Windows!
Show 25 quoted lines
> diff --git a/t/t3070-wildmatch.sh b/t/t3070-wildmatch.sh
> index 47b479e423..d423bb01f3 100755
> --- a/t/t3070-wildmatch.sh
> +++ b/t/t3070-wildmatch.sh
> @@ -4,31 +4,146 @@ test_description='wildmatch tests'
>   
>   . ./test-lib.sh
>   
> +create_test_file() {
> +	file=$1
> +
> +	# `touch .` will succeed but obviously not do what we intend
> +	# here.
> +	test "$file" = "." && return 1
> +	# We cannot create a file with an empty filename.
> +	test "$file" = "" && return 1
> +	# The tests that are testing that e.g. foo//bar is matched by
> +	# foo/*/bar can't be tested on filesystems since there's no
> +	# way we're getting a double slash.
> +	echo "$file" | grep -q -F '//' && return 1
> +	# When testing the difference between foo/bar and foo/bar/ we
> +	# can't test the latter.
> +	echo "$file" | grep -q -E '/$' && return 1
> +
> +	dirs=$(echo "$file" | sed -r 's!/[^/]+$!!')
Booh! Booh! So many fork()s! ;)
	case "$file" in
	*//*)
		# The tests that are testing that e.g. foo//bar is matched by
		# foo/*/bar can't be tested on filesystems since there's no
		# way we're getting a double slash.
		return 1;;
	*/)
		# When testing the difference between foo/bar and foo/bar/ we
		# can't test the latter.
		return 1;;
	esac
	dirs=${file%/*}
Show 65 quoted lines
> +
> +	# We touch "./$file" instead of "$file" because even an
> +	# escaped "touch -- -" means something different.
> +	if test "$file" != "$dirs"
> +	then
> +		mkdir -p -- "$dirs" 2>/dev/null &&
> +		touch -- "./$file" 2>/dev/null &&
> +		return 0
> +	else
> +		touch -- "./$file" 2>/dev/null &&
> +		return 0
> +	fi
> +	return 1
> +}
> +
>   wildtest() {
> -	match_w_glob=$1
> -	match_w_globi=$2
> -	match_w_pathmatch=$3
> -	match_w_pathmatchi=$4
> -	text=$5
> -	pattern=$6
> +	if test "$#" = 6
> +	then
> +		# When test-wildmatch and git ls-files produce the same
> +		# result.
> +		match_w_glob=$1
> +		match_f_w_glob=$match_w_glob
> +		match_w_globi=$2
> +		match_f_w_globi=$match_w_globi
> +		match_w_pathmatch=$3
> +		match_f_w_pathmatch=$match_w_pathmatch
> +		match_w_pathmatchi=$4
> +		match_f_w_pathmatchi=$match_w_pathmatchi
> +		text=$5
> +		pattern=$6
> +	elif test "$#" = 10
> +	then
> +		match_w_glob=$1
> +		match_w_globi=$2
> +		match_w_pathmatch=$3
> +		match_w_pathmatchi=$4
> +		match_f_w_glob=$5
> +		match_f_w_globi=$6
> +		match_f_w_pathmatch=$7
> +		match_f_w_pathmatchi=$8
> +		text=$9
> +		pattern=$10
> +	fi
>   
> +	# $1: Case sensitive glob match: test-wildmatch
>   	if test "$match_w_glob" = 1
>   	then
> -		test_expect_success "wildmatch:     match '$text' '$pattern'" "
> +		test_expect_success "wildmatch: match '$text' '$pattern'" "
>   			test-wildmatch wildmatch '$text' '$pattern'
>   		"
>   	elif test "$match_w_glob" = 0
>   	then
> -		test_expect_success "wildmatch:  no match '$text' '$pattern'" "
> +		test_expect_success "wildmatch: no match '$text' '$pattern'" "
>   			! test-wildmatch wildmatch '$text' '$pattern'
>   		"
>   	else
>   		test_expect_success "PANIC: Test framework error. Unknown matches value $match_w_glob" 'false'
I think you can write this as 'say ...; exit 1'. See t0000*.
Show 10 quoted lines
>   	fi
>   
> +	# $1: Case sensitive glob match: ls-files
> +	if test "$match_f_w_glob" = 'E'
> +	then
> +		if create_test_file "$text"
> +		then
> +			test_expect_success "wildmatch(ls): match dies on '$pattern' '$text'" "
> +				test_when_finished \"
> +					rm -rf -- * &&

Can we be a bit more careful with this rm -rf, please? There is only one similarly loose case in t/t7003-filter-branch.sh, and it is outside test_when_finished, i.e., it is well under control; this instance here inside test_when_finished is not.

Show 22 quoted lines
> +					git reset
> +				\" &&
> +				git add -A &&
> +				>expect.err &&
> +				printf '%s' '$text' >expect &&
> +				test_must_fail git --glob-pathspecs ls-files -z -- '$pattern'
> +			"
> +		else
> +			test_expect_failure "wildmatch(ls): match skip '$pattern' '$text'" 'false'
> +		fi
> +	elif test "$match_f_w_glob" = 1
> +	then
> +		if create_test_file "$text"
> +		then
> +			test_expect_success "wildmatch(ls): match '$pattern' '$text'" "
> +				test_when_finished \"
> +					rm -rf -- * &&
> +					git reset
> +				\" &&
> +				git add -A &&
> +				>expect.err &&
> +				printf '%s' '$text' >expect &&
There are no single-quotes in any $text instances, right?
> +				git --glob-pathspecs ls-files -z -- '$pattern' 2>actual.err | tr -d '\0' >actual &&

If possible, do not put git commands in the upstream of a pipe. It does not detect failures.

Unfortunately, printf '%s\0' foo is not portable. If it were, you could omit the tr invocation alltogether.

Show 6 quoted lines
> +				test_cmp expect.err actual.err &&
> +				test_cmp expect actual
> +			"
> +		else
> +			test_expect_failure "wildmatch(ls): match skip '$pattern' '$text'" 'false'
> +		fi
-- Hannes
Ævar Arnfjörð Bjarmason· Dec 24, 2017, 11:06 UTC · re: Johannes Sixt · lore

Re: [PATCH 6/6] wildmatch test: create & test files on disk in addition to in-memory

On Sun, Dec 24 2017, Johannes Sixt jotted:
Show 13 quoted lines
> Am 23.12.2017 um 22:30 schrieb Ævar Arnfjörð Bjarmason:
>> Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
>> ---
>>   a[]b                 |   0
>>   t/t3070-wildmatch.sh | 336 ++++++++++++++++++++++++++++++++++++++++++++++++---
>>   2 files changed, 319 insertions(+), 17 deletions(-)
>>   create mode 100644 a[]b
>>
>> diff --git a/a[]b b/a[]b
>> new file mode 100644
>> index 0000000000..e69de29bb2
>
> A big no-no! This file can't be created on Windows!
Urgh, that was a mistake of mine. Will be gone in v2.
Show 41 quoted lines
>> diff --git a/t/t3070-wildmatch.sh b/t/t3070-wildmatch.sh
>> index 47b479e423..d423bb01f3 100755
>> --- a/t/t3070-wildmatch.sh
>> +++ b/t/t3070-wildmatch.sh
>> @@ -4,31 +4,146 @@ test_description='wildmatch tests'
>>
>>   . ./test-lib.sh
>>
>> +create_test_file() {
>> +	file=$1
>> +
>> +	# `touch .` will succeed but obviously not do what we intend
>> +	# here.
>> +	test "$file" = "." && return 1
>> +	# We cannot create a file with an empty filename.
>> +	test "$file" = "" && return 1
>> +	# The tests that are testing that e.g. foo//bar is matched by
>> +	# foo/*/bar can't be tested on filesystems since there's no
>> +	# way we're getting a double slash.
>> +	echo "$file" | grep -q -F '//' && return 1
>> +	# When testing the difference between foo/bar and foo/bar/ we
>> +	# can't test the latter.
>> +	echo "$file" | grep -q -E '/$' && return 1
>> +
>> +	dirs=$(echo "$file" | sed -r 's!/[^/]+$!!')
>
> Booh! Booh! So many fork()s! ;)
>
> 	case "$file" in
> 	*//*)
> 		# The tests that are testing that e.g. foo//bar is matched by
> 		# foo/*/bar can't be tested on filesystems since there's no
> 		# way we're getting a double slash.
> 		return 1;;
> 	*/)
> 		# When testing the difference between foo/bar and foo/bar/ we
> 		# can't test the latter.
> 		return 1;;
> 	esac
>
> 	dirs=${file%/*}
Thanks. Will fix.
Show 67 quoted lines
>> +
>> +	# We touch "./$file" instead of "$file" because even an
>> +	# escaped "touch -- -" means something different.
>> +	if test "$file" != "$dirs"
>> +	then
>> +		mkdir -p -- "$dirs" 2>/dev/null &&
>> +		touch -- "./$file" 2>/dev/null &&
>> +		return 0
>> +	else
>> +		touch -- "./$file" 2>/dev/null &&
>> +		return 0
>> +	fi
>> +	return 1
>> +}
>> +
>>   wildtest() {
>> -	match_w_glob=$1
>> -	match_w_globi=$2
>> -	match_w_pathmatch=$3
>> -	match_w_pathmatchi=$4
>> -	text=$5
>> -	pattern=$6
>> +	if test "$#" = 6
>> +	then
>> +		# When test-wildmatch and git ls-files produce the same
>> +		# result.
>> +		match_w_glob=$1
>> +		match_f_w_glob=$match_w_glob
>> +		match_w_globi=$2
>> +		match_f_w_globi=$match_w_globi
>> +		match_w_pathmatch=$3
>> +		match_f_w_pathmatch=$match_w_pathmatch
>> +		match_w_pathmatchi=$4
>> +		match_f_w_pathmatchi=$match_w_pathmatchi
>> +		text=$5
>> +		pattern=$6
>> +	elif test "$#" = 10
>> +	then
>> +		match_w_glob=$1
>> +		match_w_globi=$2
>> +		match_w_pathmatch=$3
>> +		match_w_pathmatchi=$4
>> +		match_f_w_glob=$5
>> +		match_f_w_globi=$6
>> +		match_f_w_pathmatch=$7
>> +		match_f_w_pathmatchi=$8
>> +		text=$9
>> +		pattern=$10
>> +	fi
>>
>> +	# $1: Case sensitive glob match: test-wildmatch
>>   	if test "$match_w_glob" = 1
>>   	then
>> -		test_expect_success "wildmatch:     match '$text' '$pattern'" "
>> +		test_expect_success "wildmatch: match '$text' '$pattern'" "
>>   			test-wildmatch wildmatch '$text' '$pattern'
>>   		"
>>   	elif test "$match_w_glob" = 0
>>   	then
>> -		test_expect_success "wildmatch:  no match '$text' '$pattern'" "
>> +		test_expect_success "wildmatch: no match '$text' '$pattern'" "
>>   			! test-wildmatch wildmatch '$text' '$pattern'
>>   		"
>>   	else
>>   		test_expect_success "PANIC: Test framework error. Unknown matches value $match_w_glob" 'false'
>
> I think you can write this as 'say ...; exit 1'. See t0000*.
Thanks. Didn't see an existing idiom for this, will use that.
Show 15 quoted lines
>>   	fi
>>
>> +	# $1: Case sensitive glob match: ls-files
>> +	if test "$match_f_w_glob" = 'E'
>> +	then
>> +		if create_test_file "$text"
>> +		then
>> +			test_expect_success "wildmatch(ls): match dies on '$pattern' '$text'" "
>> +				test_when_finished \"
>> +					rm -rf -- * &&
>
> Can we be a bit more careful with this rm -rf, please?
> There is only one similarly loose case in t/t7003-filter-branch.sh,
> and it is outside test_when_finished, i.e., it is well under control;
> this instance here inside test_when_finished is not.

I can create the files inside some subfolder, cd to that and then run the ls-files there. It would also cover cases where we have pattern matching text that starts with ".".

Show 24 quoted lines
>> +					git reset
>> +				\" &&
>> +				git add -A &&
>> +				>expect.err &&
>> +				printf '%s' '$text' >expect &&
>> +				test_must_fail git --glob-pathspecs ls-files -z -- '$pattern'
>> +			"
>> +		else
>> +			test_expect_failure "wildmatch(ls): match skip '$pattern' '$text'" 'false'
>> +		fi
>> +	elif test "$match_f_w_glob" = 1
>> +	then
>> +		if create_test_file "$text"
>> +		then
>> +			test_expect_success "wildmatch(ls): match '$pattern' '$text'" "
>> +				test_when_finished \"
>> +					rm -rf -- * &&
>> +					git reset
>> +				\" &&
>> +				git add -A &&
>> +				>expect.err &&
>> +				printf '%s' '$text' >expect &&
>
> There are no single-quotes in any $text instances, right?
There's not, but maybe we should be more careful here and use here-docs.
>> +				git --glob-pathspecs ls-files -z -- '$pattern' 2>actual.err | tr -d '\0' >actual &&
>
> If possible, do not put git commands in the upstream of a pipe.
> It does not detect failures.
Thanks, will split these up.
Show 11 quoted lines
> Unfortunately, printf '%s\0' foo is not portable. If it were,
> you could omit the tr invocation alltogether.
>
>> +				test_cmp expect.err actual.err &&
>> +				test_cmp expect actual
>> +			"
>> +		else
>> +			test_expect_failure "wildmatch(ls): match skip '$pattern' '$text'" 'false'
>> +		fi
>
> -- Hannes
Johannes Sixt· Dec 24, 2017, 11:51 UTC · re: Ævar Arnfjörð Bjarmason · lore

Re: [PATCH 6/6] wildmatch test: create & test files on disk in addition to in-memory

Am 24.12.2017 um 12:06 schrieb Ævar Arnfjörð Bjarmason:
Show 7 quoted lines
> On Sun, Dec 24 2017, Johannes Sixt jotted:
>> Am 23.12.2017 um 22:30 schrieb Ævar Arnfjörð Bjarmason:
>>> +				printf '%s' '$text' >expect &&
>>
>> There are no single-quotes in any $text instances, right?
> 
> There's not, but maybe we should be more careful here and use here-docs.

Unless it is essential to test the single-quote case, we need not complicate the code. I just wanted to rise awareness. If a problematic test case is introduced, it will be noticed soon enough. It's not that we deal with unknown input here.

-- Hannes
Ævar Arnfjörð Bjarmason· Dec 25, 2017, 00:28 UTC · re: Ævar Arnfjörð Bjarmason · lore

[PATCH v2 0/7] increase wildmatch test coverage

This v2 addresses comments by Johannes Sixt in <8f4cdb23-8e2e-144a-1f70-99776b027166@kdbg.org> and there's osme other cleanups as noted below.

Ævar Arnfjörð Bjarmason (7):
  wildmatch test: indent with tabs, not spaces
  wildmatch test: use more standard shell style
No changes.
  wildmatch test: don't try to vertically align our output
NEW: Don't try to do whitespace alignment in the tests.
  wildmatch test: use a paranoia pattern from nul_match()

Explain in the commit message why we're not using say '...'; exit 1. I said I'd use this in <874logs7vi.fsf@evledraar.gmail.com>, but on further consideration it's a bad idea.

  wildmatch test: remove dead fnmatch() test code
  wildmatch test: perform all tests under all wildmatch() modes
Just changes to rebase them on the changes above.
  wildmatch test: create & test files on disk in addition to in-memory

Avoid some forking by using a case statement instead of if .. grep && return.

Add comments to the code to clarify what it's doing.

Factoro out the repetitive part of the tests into functions, making the patch shorter.

I didn't change the "rm -rf -- *" pattern Johannes was concerned about, because after looking at it it would be a pain to create some-test-subdir/ and only if some-test-subdir/$our_file gets created cd to it and then remove it afterwards, it's much easier not to change the directory. The test test_when_finished always runs in the directory the tests executed in, so I don't see how this is dangerous in practice.

I didn't move the "printf" pattern to here-docs as discussed in the thread.

 t/helper/test-wildmatch.c |   2 +
 t/t3070-wildmatch.sh      | 759 +++++++++++++++++++++++++++++++---------------
 2 files changed, 516 insertions(+), 245 deletions(-)
-- 
2.15.1.424.g9478a66081
Ævar Arnfjörð Bjarmason· Dec 25, 2017, 00:28 UTC · re: Ævar Arnfjörð Bjarmason · lore

[PATCH v2 1/7] wildmatch test: indent with tabs, not spaces

Replace the 4-width mixed space & tab indentation in this file with indentation with tabs as we do in most of the rest of our tests.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 t/t3070-wildmatch.sh | 54 ++++++++++++++++++++++++++--------------------------
 1 file changed, 27 insertions(+), 27 deletions(-)
Show changes to t/t3070-wildmatch.sh +27 −27
diff --git a/t/t3070-wildmatch.sh b/t/t3070-wildmatch.sh
index 163a14a1c2..27fa878f6e 100755
--- a/t/t3070-wildmatch.sh
+++ b/t/t3070-wildmatch.sh
@@ -5,39 +5,39 @@ test_description='wildmatch tests'
 . ./test-lib.sh
 
 match() {
-    if [ $1 = 1 ]; then
-	test_expect_success "wildmatch:     match '$3' '$4'" "
-	    test-wildmatch wildmatch '$3' '$4'
-	"
-    else
-	test_expect_success "wildmatch:  no match '$3' '$4'" "
-	    ! test-wildmatch wildmatch '$3' '$4'
-	"
-    fi
+	if [ $1 = 1 ]; then
+		test_expect_success "wildmatch:     match '$3' '$4'" "
+			test-wildmatch wildmatch '$3' '$4'
+		"
+	else
+		test_expect_success "wildmatch:  no match '$3' '$4'" "
+			! test-wildmatch wildmatch '$3' '$4'
+		"
+	fi
 }
 
 imatch() {
-    if [ $1 = 1 ]; then
-	test_expect_success "iwildmatch:    match '$2' '$3'" "
-	    test-wildmatch iwildmatch '$2' '$3'
-	"
-    else
-	test_expect_success "iwildmatch: no match '$2' '$3'" "
-	    ! test-wildmatch iwildmatch '$2' '$3'
-	"
-    fi
+	if [ $1 = 1 ]; then
+		test_expect_success "iwildmatch:    match '$2' '$3'" "
+			test-wildmatch iwildmatch '$2' '$3'
+		"
+	else
+		test_expect_success "iwildmatch: no match '$2' '$3'" "
+			! test-wildmatch iwildmatch '$2' '$3'
+		"
+	fi
 }
 
 pathmatch() {
-    if [ $1 = 1 ]; then
-	test_expect_success "pathmatch:     match '$2' '$3'" "
-	    test-wildmatch pathmatch '$2' '$3'
-	"
-    else
-	test_expect_success "pathmatch:  no match '$2' '$3'" "
-	    ! test-wildmatch pathmatch '$2' '$3'
-	"
-    fi
+	if [ $1 = 1 ]; then
+		test_expect_success "pathmatch:     match '$2' '$3'" "
+			test-wildmatch pathmatch '$2' '$3'
+		"
+	else
+		test_expect_success "pathmatch:  no match '$2' '$3'" "
+			! test-wildmatch pathmatch '$2' '$3'
+		"
+	fi
 }
 
 # Basic wildmat features
-- 
2.15.1.424.g9478a66081
Ævar Arnfjörð Bjarmason· Dec 25, 2017, 00:28 UTC · re: Ævar Arnfjörð Bjarmason · lore

[PATCH v2 2/7] wildmatch test: use more standard shell style

Change the wildmatch test to use more standard shell style, usually we use "if test" not "if [".

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 t/t3070-wildmatch.sh | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)
Show changes to t/t3070-wildmatch.sh +6 −3
diff --git a/t/t3070-wildmatch.sh b/t/t3070-wildmatch.sh
index 27fa878f6e..4d589d1f9a 100755
--- a/t/t3070-wildmatch.sh
+++ b/t/t3070-wildmatch.sh
@@ -5,7 +5,8 @@ test_description='wildmatch tests'
 . ./test-lib.sh
 
 match() {
-	if [ $1 = 1 ]; then
+	if test "$1" = 1
+	then
 		test_expect_success "wildmatch:     match '$3' '$4'" "
 			test-wildmatch wildmatch '$3' '$4'
 		"
@@ -17,7 +18,8 @@ match() {
 }
 
 imatch() {
-	if [ $1 = 1 ]; then
+	if test "$1" = 1
+	then
 		test_expect_success "iwildmatch:    match '$2' '$3'" "
 			test-wildmatch iwildmatch '$2' '$3'
 		"
@@ -29,7 +31,8 @@ imatch() {
 }
 
 pathmatch() {
-	if [ $1 = 1 ]; then
+	if test "$1" = 1
+	then
 		test_expect_success "pathmatch:     match '$2' '$3'" "
 			test-wildmatch pathmatch '$2' '$3'
 		"
-- 
2.15.1.424.g9478a66081
Ævar Arnfjörð Bjarmason· Dec 25, 2017, 00:28 UTC · re: Ævar Arnfjörð Bjarmason · lore

[PATCH v2 3/7] wildmatch test: don't try to vertically align our output

Don't try to vertically align the test output, which is futile anyway under the TAP output where we're going to be emitting a number for each test without aligning the test count.

This makes subsequent changes of mine where I'm not going to be aligning this output as I add new tests easier.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 t/t3070-wildmatch.sh | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)
Show changes to t/t3070-wildmatch.sh +5 −5
diff --git a/t/t3070-wildmatch.sh b/t/t3070-wildmatch.sh
index 4d589d1f9a..19ea64bba9 100755
--- a/t/t3070-wildmatch.sh
+++ b/t/t3070-wildmatch.sh
@@ -7,11 +7,11 @@ test_description='wildmatch tests'
 match() {
 	if test "$1" = 1
 	then
-		test_expect_success "wildmatch:     match '$3' '$4'" "
+		test_expect_success "wildmatch: match '$3' '$4'" "
 			test-wildmatch wildmatch '$3' '$4'
 		"
 	else
-		test_expect_success "wildmatch:  no match '$3' '$4'" "
+		test_expect_success "wildmatch: no match '$3' '$4'" "
 			! test-wildmatch wildmatch '$3' '$4'
 		"
 	fi
@@ -20,7 +20,7 @@ match() {
 imatch() {
 	if test "$1" = 1
 	then
-		test_expect_success "iwildmatch:    match '$2' '$3'" "
+		test_expect_success "iwildmatch: match '$2' '$3'" "
 			test-wildmatch iwildmatch '$2' '$3'
 		"
 	else
@@ -33,11 +33,11 @@ imatch() {
 pathmatch() {
 	if test "$1" = 1
 	then
-		test_expect_success "pathmatch:     match '$2' '$3'" "
+		test_expect_success "pathmatch: match '$2' '$3'" "
 			test-wildmatch pathmatch '$2' '$3'
 		"
 	else
-		test_expect_success "pathmatch:  no match '$2' '$3'" "
+		test_expect_success "pathmatch: no match '$2' '$3'" "
 			! test-wildmatch pathmatch '$2' '$3'
 		"
 	fi
-- 
2.15.1.424.g9478a66081
Ævar Arnfjörð Bjarmason· Dec 25, 2017, 00:28 UTC · re: Ævar Arnfjörð Bjarmason · lore

[PATCH v2 4/7] wildmatch test: use a paranoia pattern from nul_match()

Use a pattern from the nul_match() function in t7008-grep-binary.sh to make sure that we don't just fall through to the "else" if there's an unknown parameter.

This is something I added in commit 77f6f4406f ("grep: add a test helper function for less verbose -f \0 tests", 2017-05-20) to grep tests, which were modeled on these wildmatch tests, and I'm now porting back to the original wildmatch tests.

I am not using the "say '...'; exit 1" pattern from t0000-basic.sh because if I fail I want to run the rest of the tests (unless under -i), and doing this makes sure we do that and don't exit right away without fully reporting our errors.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 t/t3070-wildmatch.sh | 15 ++++++++++++---
 1 file changed, 12 insertions(+), 3 deletions(-)
Show changes to t/t3070-wildmatch.sh +12 −3
diff --git a/t/t3070-wildmatch.sh b/t/t3070-wildmatch.sh
index 19ea64bba9..9691d8eda3 100755
--- a/t/t3070-wildmatch.sh
+++ b/t/t3070-wildmatch.sh
@@ -10,10 +10,13 @@ match() {
 		test_expect_success "wildmatch: match '$3' '$4'" "
 			test-wildmatch wildmatch '$3' '$4'
 		"
-	else
+	elif test "$1" = 0
+	then
 		test_expect_success "wildmatch: no match '$3' '$4'" "
 			! test-wildmatch wildmatch '$3' '$4'
 		"
+	else
+		test_expect_success "PANIC: Test framework error. Unknown matches value $1" 'false'
 	fi
 }
 
@@ -23,10 +26,13 @@ imatch() {
 		test_expect_success "iwildmatch: match '$2' '$3'" "
 			test-wildmatch iwildmatch '$2' '$3'
 		"
-	else
+	elif test "$1" = 0
+	then
 		test_expect_success "iwildmatch: no match '$2' '$3'" "
 			! test-wildmatch iwildmatch '$2' '$3'
 		"
+	else
+		test_expect_success "PANIC: Test framework error. Unknown matches value $1" 'false'
 	fi
 }
 
@@ -36,10 +42,13 @@ pathmatch() {
 		test_expect_success "pathmatch: match '$2' '$3'" "
 			test-wildmatch pathmatch '$2' '$3'
 		"
-	else
+	elif test "$1" = 0
+	then
 		test_expect_success "pathmatch: no match '$2' '$3'" "
 			! test-wildmatch pathmatch '$2' '$3'
 		"
+	else
+		test_expect_success "PANIC: Test framework error. Unknown matches value $1" 'false'
 	fi
 }
 
-- 
2.15.1.424.g9478a66081
Ævar Arnfjörð Bjarmason· Dec 25, 2017, 00:28 UTC · re: Ævar Arnfjörð Bjarmason · lore

[PATCH v2 5/7] wildmatch test: remove dead fnmatch() test code

Remove the unused fnmatch() test parameter from the wildmatch test. The code that used to test this was removed in 70a8fc999d ("stop using fnmatch (either native or compat)", 2014-02-15).

As a --word-diff shows the only change to the body of the tests is the removal of the second out of four parameters passed to match().

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 t/t3070-wildmatch.sh | 356 +++++++++++++++++++++++++--------------------------
 1 file changed, 178 insertions(+), 178 deletions(-)
Show changes to t/t3070-wildmatch.sh +178 −178
diff --git a/t/t3070-wildmatch.sh b/t/t3070-wildmatch.sh
index 9691d8eda3..2f8a681c72 100755
--- a/t/t3070-wildmatch.sh
+++ b/t/t3070-wildmatch.sh
@@ -7,13 +7,13 @@ test_description='wildmatch tests'
 match() {
 	if test "$1" = 1
 	then
-		test_expect_success "wildmatch: match '$3' '$4'" "
-			test-wildmatch wildmatch '$3' '$4'
+		test_expect_success "wildmatch: match '$2' '$3'" "
+			test-wildmatch wildmatch '$2' '$3'
 		"
 	elif test "$1" = 0
 	then
-		test_expect_success "wildmatch: no match '$3' '$4'" "
-			! test-wildmatch wildmatch '$3' '$4'
+		test_expect_success "wildmatch: no match '$2' '$3'" "
+			! test-wildmatch wildmatch '$2' '$3'
 		"
 	else
 		test_expect_success "PANIC: Test framework error. Unknown matches value $1" 'false'
@@ -53,176 +53,176 @@ pathmatch() {
 }
 
 # Basic wildmat features
-match 1 1 foo foo
-match 0 0 foo bar
-match 1 1 '' ""
-match 1 1 foo '???'
-match 0 0 foo '??'
-match 1 1 foo '*'
-match 1 1 foo 'f*'
-match 0 0 foo '*f'
-match 1 1 foo '*foo*'
-match 1 1 foobar '*ob*a*r*'
-match 1 1 aaaaaaabababab '*ab'
-match 1 1 'foo*' 'foo\*'
-match 0 0 foobar 'foo\*bar'
-match 1 1 'f\oo' 'f\\oo'
-match 1 1 ball '*[al]?'
-match 0 0 ten '[ten]'
-match 0 1 ten '**[!te]'
-match 0 0 ten '**[!ten]'
-match 1 1 ten 't[a-g]n'
-match 0 0 ten 't[!a-g]n'
-match 1 1 ton 't[!a-g]n'
-match 1 1 ton 't[^a-g]n'
-match 1 x 'a]b' 'a[]]b'
-match 1 x a-b 'a[]-]b'
-match 1 x 'a]b' 'a[]-]b'
-match 0 x aab 'a[]-]b'
-match 1 x aab 'a[]a-]b'
-match 1 1 ']' ']'
+match 1 foo foo
+match 0 foo bar
+match 1 '' ""
+match 1 foo '???'
+match 0 foo '??'
+match 1 foo '*'
+match 1 foo 'f*'
+match 0 foo '*f'
+match 1 foo '*foo*'
+match 1 foobar '*ob*a*r*'
+match 1 aaaaaaabababab '*ab'
+match 1 'foo*' 'foo\*'
+match 0 foobar 'foo\*bar'
+match 1 'f\oo' 'f\\oo'
+match 1 ball '*[al]?'
+match 0 ten '[ten]'
+match 0 ten '**[!te]'
+match 0 ten '**[!ten]'
+match 1 ten 't[a-g]n'
+match 0 ten 't[!a-g]n'
+match 1 ton 't[!a-g]n'
+match 1 ton 't[^a-g]n'
+match 1 'a]b' 'a[]]b'
+match 1 a-b 'a[]-]b'
+match 1 'a]b' 'a[]-]b'
+match 0 aab 'a[]-]b'
+match 1 aab 'a[]a-]b'
+match 1 ']' ']'
 
 # Extended slash-matching features
-match 0 0 'foo/baz/bar' 'foo*bar'
-match 0 0 'foo/baz/bar' 'foo**bar'
-match 0 1 'foobazbar' 'foo**bar'
-match 1 1 'foo/baz/bar' 'foo/**/bar'
-match 1 0 'foo/baz/bar' 'foo/**/**/bar'
-match 1 0 'foo/b/a/z/bar' 'foo/**/bar'
-match 1 0 'foo/b/a/z/bar' 'foo/**/**/bar'
-match 1 0 'foo/bar' 'foo/**/bar'
-match 1 0 'foo/bar' 'foo/**/**/bar'
-match 0 0 'foo/bar' 'foo?bar'
-match 0 0 'foo/bar' 'foo[/]bar'
-match 0 0 'foo/bar' 'foo[^a-z]bar'
-match 0 0 'foo/bar' 'f[^eiu][^eiu][^eiu][^eiu][^eiu]r'
-match 1 1 'foo-bar' 'f[^eiu][^eiu][^eiu][^eiu][^eiu]r'
-match 1 0 'foo' '**/foo'
-match 1 x 'XXX/foo' '**/foo'
-match 1 0 'bar/baz/foo' '**/foo'
-match 0 0 'bar/baz/foo' '*/foo'
-match 0 0 'foo/bar/baz' '**/bar*'
-match 1 0 'deep/foo/bar/baz' '**/bar/*'
-match 0 0 'deep/foo/bar/baz/' '**/bar/*'
-match 1 0 'deep/foo/bar/baz/' '**/bar/**'
-match 0 0 'deep/foo/bar' '**/bar/*'
-match 1 0 'deep/foo/bar/' '**/bar/**'
-match 0 0 'foo/bar/baz' '**/bar**'
-match 1 0 'foo/bar/baz/x' '*/bar/**'
-match 0 0 'deep/foo/bar/baz/x' '*/bar/**'
-match 1 0 'deep/foo/bar/baz/x' '**/bar/*/*'
+match 0 'foo/baz/bar' 'foo*bar'
+match 0 'foo/baz/bar' 'foo**bar'
+match 0 'foobazbar' 'foo**bar'
+match 1 'foo/baz/bar' 'foo/**/bar'
+match 1 'foo/baz/bar' 'foo/**/**/bar'
+match 1 'foo/b/a/z/bar' 'foo/**/bar'
+match 1 'foo/b/a/z/bar' 'foo/**/**/bar'
+match 1 'foo/bar' 'foo/**/bar'
+match 1 'foo/bar' 'foo/**/**/bar'
+match 0 'foo/bar' 'foo?bar'
+match 0 'foo/bar' 'foo[/]bar'
+match 0 'foo/bar' 'foo[^a-z]bar'
+match 0 'foo/bar' 'f[^eiu][^eiu][^eiu][^eiu][^eiu]r'
+match 1 'foo-bar' 'f[^eiu][^eiu][^eiu][^eiu][^eiu]r'
+match 1 'foo' '**/foo'
+match 1 'XXX/foo' '**/foo'
+match 1 'bar/baz/foo' '**/foo'
+match 0 'bar/baz/foo' '*/foo'
+match 0 'foo/bar/baz' '**/bar*'
+match 1 'deep/foo/bar/baz' '**/bar/*'
+match 0 'deep/foo/bar/baz/' '**/bar/*'
+match 1 'deep/foo/bar/baz/' '**/bar/**'
+match 0 'deep/foo/bar' '**/bar/*'
+match 1 'deep/foo/bar/' '**/bar/**'
+match 0 'foo/bar/baz' '**/bar**'
+match 1 'foo/bar/baz/x' '*/bar/**'
+match 0 'deep/foo/bar/baz/x' '*/bar/**'
+match 1 'deep/foo/bar/baz/x' '**/bar/*/*'
 
 # Various additional tests
-match 0 0 'acrt' 'a[c-c]st'
-match 1 1 'acrt' 'a[c-c]rt'
-match 0 0 ']' '[!]-]'
-match 1 x 'a' '[!]-]'
-match 0 0 '' '\'
-match 0 x '\' '\'
-match 0 x 'XXX/\' '*/\'
-match 1 x 'XXX/\' '*/\\'
-match 1 1 'foo' 'foo'
-match 1 1 '@foo' '@foo'
-match 0 0 'foo' '@foo'
-match 1 1 '[ab]' '\[ab]'
-match 1 1 '[ab]' '[[]ab]'
-match 1 x '[ab]' '[[:]ab]'
-match 0 x '[ab]' '[[::]ab]'
-match 1 x '[ab]' '[[:digit]ab]'
-match 1 x '[ab]' '[\[:]ab]'
-match 1 1 '?a?b' '\??\?b'
-match 1 1 'abc' '\a\b\c'
-match 0 0 'foo' ''
-match 1 0 'foo/bar/baz/to' '**/t[o]'
+match 0 'acrt' 'a[c-c]st'
+match 1 'acrt' 'a[c-c]rt'
+match 0 ']' '[!]-]'
+match 1 'a' '[!]-]'
+match 0 '' '\'
+match 0 '\' '\'
+match 0 'XXX/\' '*/\'
+match 1 'XXX/\' '*/\\'
+match 1 'foo' 'foo'
+match 1 '@foo' '@foo'
+match 0 'foo' '@foo'
+match 1 '[ab]' '\[ab]'
+match 1 '[ab]' '[[]ab]'
+match 1 '[ab]' '[[:]ab]'
+match 0 '[ab]' '[[::]ab]'
+match 1 '[ab]' '[[:digit]ab]'
+match 1 '[ab]' '[\[:]ab]'
+match 1 '?a?b' '\??\?b'
+match 1 'abc' '\a\b\c'
+match 0 'foo' ''
+match 1 'foo/bar/baz/to' '**/t[o]'
 
 # Character class tests
-match 1 x 'a1B' '[[:alpha:]][[:digit:]][[:upper:]]'
-match 0 x 'a' '[[:digit:][:upper:][:space:]]'
-match 1 x 'A' '[[:digit:][:upper:][:space:]]'
-match 1 x '1' '[[:digit:][:upper:][:space:]]'
-match 0 x '1' '[[:digit:][:upper:][:spaci:]]'
-match 1 x ' ' '[[:digit:][:upper:][:space:]]'
-match 0 x '.' '[[:digit:][:upper:][:space:]]'
-match 1 x '.' '[[:digit:][:punct:][:space:]]'
-match 1 x '5' '[[:xdigit:]]'
-match 1 x 'f' '[[:xdigit:]]'
-match 1 x 'D' '[[:xdigit:]]'
-match 1 x '_' '[[:alnum:][:alpha:][:blank:][:cntrl:][:digit:][:graph:][:lower:][:print:][:punct:][:space:][:upper:][:xdigit:]]'
-match 1 x '.' '[^[:alnum:][:alpha:][:blank:][:cntrl:][:digit:][:lower:][:space:][:upper:][:xdigit:]]'
-match 1 x '5' '[a-c[:digit:]x-z]'
-match 1 x 'b' '[a-c[:digit:]x-z]'
-match 1 x 'y' '[a-c[:digit:]x-z]'
-match 0 x 'q' '[a-c[:digit:]x-z]'
+match 1 'a1B' '[[:alpha:]][[:digit:]][[:upper:]]'
+match 0 'a' '[[:digit:][:upper:][:space:]]'
+match 1 'A' '[[:digit:][:upper:][:space:]]'
+match 1 '1' '[[:digit:][:upper:][:space:]]'
+match 0 '1' '[[:digit:][:upper:][:spaci:]]'
+match 1 ' ' '[[:digit:][:upper:][:space:]]'
+match 0 '.' '[[:digit:][:upper:][:space:]]'
+match 1 '.' '[[:digit:][:punct:][:space:]]'
+match 1 '5' '[[:xdigit:]]'
+match 1 'f' '[[:xdigit:]]'
+match 1 'D' '[[:xdigit:]]'
+match 1 '_' '[[:alnum:][:alpha:][:blank:][:cntrl:][:digit:][:graph:][:lower:][:print:][:punct:][:space:][:upper:][:xdigit:]]'
+match 1 '.' '[^[:alnum:][:alpha:][:blank:][:cntrl:][:digit:][:lower:][:space:][:upper:][:xdigit:]]'
+match 1 '5' '[a-c[:digit:]x-z]'
+match 1 'b' '[a-c[:digit:]x-z]'
+match 1 'y' '[a-c[:digit:]x-z]'
+match 0 'q' '[a-c[:digit:]x-z]'
 
 # Additional tests, including some malformed wildmats
-match 1 x ']' '[\\-^]'
-match 0 0 '[' '[\\-^]'
-match 1 x '-' '[\-_]'
-match 1 x ']' '[\]]'
-match 0 0 '\]' '[\]]'
-match 0 0 '\' '[\]]'
-match 0 0 'ab' 'a[]b'
-match 0 x 'a[]b' 'a[]b'
-match 0 x 'ab[' 'ab['
-match 0 0 'ab' '[!'
-match 0 0 'ab' '[-'
-match 1 1 '-' '[-]'
-match 0 0 '-' '[a-'
-match 0 0 '-' '[!a-'
-match 1 x '-' '[--A]'
-match 1 x '5' '[--A]'
-match 1 1 ' ' '[ --]'
-match 1 1 '$' '[ --]'
-match 1 1 '-' '[ --]'
-match 0 0 '0' '[ --]'
-match 1 x '-' '[---]'
-match 1 x '-' '[------]'
-match 0 0 'j' '[a-e-n]'
-match 1 x '-' '[a-e-n]'
-match 1 x 'a' '[!------]'
-match 0 0 '[' '[]-a]'
-match 1 x '^' '[]-a]'
-match 0 0 '^' '[!]-a]'
-match 1 x '[' '[!]-a]'
-match 1 1 '^' '[a^bc]'
-match 1 x '-b]' '[a-]b]'
-match 0 0 '\' '[\]'
-match 1 1 '\' '[\\]'
-match 0 0 '\' '[!\\]'
-match 1 1 'G' '[A-\\]'
-match 0 0 'aaabbb' 'b*a'
-match 0 0 'aabcaa' '*ba*'
-match 1 1 ',' '[,]'
-match 1 1 ',' '[\\,]'
-match 1 1 '\' '[\\,]'
-match 1 1 '-' '[,-.]'
-match 0 0 '+' '[,-.]'
-match 0 0 '-.]' '[,-.]'
-match 1 1 '2' '[\1-\3]'
-match 1 1 '3' '[\1-\3]'
-match 0 0 '4' '[\1-\3]'
-match 1 1 '\' '[[-\]]'
-match 1 1 '[' '[[-\]]'
-match 1 1 ']' '[[-\]]'
-match 0 0 '-' '[[-\]]'
+match 1 ']' '[\\-^]'
+match 0 '[' '[\\-^]'
+match 1 '-' '[\-_]'
+match 1 ']' '[\]]'
+match 0 '\]' '[\]]'
+match 0 '\' '[\]]'
+match 0 'ab' 'a[]b'
+match 0 'a[]b' 'a[]b'
+match 0 'ab[' 'ab['
+match 0 'ab' '[!'
+match 0 'ab' '[-'
+match 1 '-' '[-]'
+match 0 '-' '[a-'
+match 0 '-' '[!a-'
+match 1 '-' '[--A]'
+match 1 '5' '[--A]'
+match 1 ' ' '[ --]'
+match 1 '$' '[ --]'
+match 1 '-' '[ --]'
+match 0 '0' '[ --]'
+match 1 '-' '[---]'
+match 1 '-' '[------]'
+match 0 'j' '[a-e-n]'
+match 1 '-' '[a-e-n]'
+match 1 'a' '[!------]'
+match 0 '[' '[]-a]'
+match 1 '^' '[]-a]'
+match 0 '^' '[!]-a]'
+match 1 '[' '[!]-a]'
+match 1 '^' '[a^bc]'
+match 1 '-b]' '[a-]b]'
+match 0 '\' '[\]'
+match 1 '\' '[\\]'
+match 0 '\' '[!\\]'
+match 1 'G' '[A-\\]'
+match 0 'aaabbb' 'b*a'
+match 0 'aabcaa' '*ba*'
+match 1 ',' '[,]'
+match 1 ',' '[\\,]'
+match 1 '\' '[\\,]'
+match 1 '-' '[,-.]'
+match 0 '+' '[,-.]'
+match 0 '-.]' '[,-.]'
+match 1 '2' '[\1-\3]'
+match 1 '3' '[\1-\3]'
+match 0 '4' '[\1-\3]'
+match 1 '\' '[[-\]]'
+match 1 '[' '[[-\]]'
+match 1 ']' '[[-\]]'
+match 0 '-' '[[-\]]'
 
 # Test recursion and the abort code (use "wildtest -i" to see iteration counts)
-match 1 1 '-adobe-courier-bold-o-normal--12-120-75-75-m-70-iso8859-1' '-*-*-*-*-*-*-12-*-*-*-m-*-*-*'
-match 0 0 '-adobe-courier-bold-o-normal--12-120-75-75-X-70-iso8859-1' '-*-*-*-*-*-*-12-*-*-*-m-*-*-*'
-match 0 0 '-adobe-courier-bold-o-normal--12-120-75-75-/-70-iso8859-1' '-*-*-*-*-*-*-12-*-*-*-m-*-*-*'
-match 1 1 'XXX/adobe/courier/bold/o/normal//12/120/75/75/m/70/iso8859/1' 'XXX/*/*/*/*/*/*/12/*/*/*/m/*/*/*'
-match 0 0 'XXX/adobe/courier/bold/o/normal//12/120/75/75/X/70/iso8859/1' 'XXX/*/*/*/*/*/*/12/*/*/*/m/*/*/*'
-match 1 0 'abcd/abcdefg/abcdefghijk/abcdefghijklmnop.txt' '**/*a*b*g*n*t'
-match 0 0 'abcd/abcdefg/abcdefghijk/abcdefghijklmnop.txtz' '**/*a*b*g*n*t'
-match 0 x foo '*/*/*'
-match 0 x foo/bar '*/*/*'
-match 1 x foo/bba/arr '*/*/*'
-match 0 x foo/bb/aa/rr '*/*/*'
-match 1 x foo/bb/aa/rr '**/**/**'
-match 1 x abcXdefXghi '*X*i'
-match 0 x ab/cXd/efXg/hi '*X*i'
-match 1 x ab/cXd/efXg/hi '*/*X*/*/*i'
-match 1 x ab/cXd/efXg/hi '**/*X*/**/*i'
+match 1 '-adobe-courier-bold-o-normal--12-120-75-75-m-70-iso8859-1' '-*-*-*-*-*-*-12-*-*-*-m-*-*-*'
+match 0 '-adobe-courier-bold-o-normal--12-120-75-75-X-70-iso8859-1' '-*-*-*-*-*-*-12-*-*-*-m-*-*-*'
+match 0 '-adobe-courier-bold-o-normal--12-120-75-75-/-70-iso8859-1' '-*-*-*-*-*-*-12-*-*-*-m-*-*-*'
+match 1 'XXX/adobe/courier/bold/o/normal//12/120/75/75/m/70/iso8859/1' 'XXX/*/*/*/*/*/*/12/*/*/*/m/*/*/*'
+match 0 'XXX/adobe/courier/bold/o/normal//12/120/75/75/X/70/iso8859/1' 'XXX/*/*/*/*/*/*/12/*/*/*/m/*/*/*'
+match 1 'abcd/abcdefg/abcdefghijk/abcdefghijklmnop.txt' '**/*a*b*g*n*t'
+match 0 'abcd/abcdefg/abcdefghijk/abcdefghijklmnop.txtz' '**/*a*b*g*n*t'
+match 0 foo '*/*/*'
+match 0 foo/bar '*/*/*'
+match 1 foo/bba/arr '*/*/*'
+match 0 foo/bb/aa/rr '*/*/*'
+match 1 foo/bb/aa/rr '**/**/**'
+match 1 abcXdefXghi '*X*i'
+match 0 ab/cXd/efXg/hi '*X*i'
+match 1 ab/cXd/efXg/hi '*/*X*/*/*i'
+match 1 ab/cXd/efXg/hi '**/*X*/**/*i'
 
 pathmatch 1 foo foo
 pathmatch 0 foo fo
@@ -248,20 +248,20 @@ pathmatch 1 ab/cXd/efXg/hi '*/*X*/*/*i'
 pathmatch 1 ab/cXd/efXg/hi '*Xg*i'
 
 # Case-sensitivity features
-match 0 x 'a' '[A-Z]'
-match 1 x 'A' '[A-Z]'
-match 0 x 'A' '[a-z]'
-match 1 x 'a' '[a-z]'
-match 0 x 'a' '[[:upper:]]'
-match 1 x 'A' '[[:upper:]]'
-match 0 x 'A' '[[:lower:]]'
-match 1 x 'a' '[[:lower:]]'
-match 0 x 'A' '[B-Za]'
-match 1 x 'a' '[B-Za]'
-match 0 x 'A' '[B-a]'
-match 1 x 'a' '[B-a]'
-match 0 x 'z' '[Z-y]'
-match 1 x 'Z' '[Z-y]'
+match 0 'a' '[A-Z]'
+match 1 'A' '[A-Z]'
+match 0 'A' '[a-z]'
+match 1 'a' '[a-z]'
+match 0 'a' '[[:upper:]]'
+match 1 'A' '[[:upper:]]'
+match 0 'A' '[[:lower:]]'
+match 1 'a' '[[:lower:]]'
+match 0 'A' '[B-Za]'
+match 1 'a' '[B-Za]'
+match 0 'A' '[B-a]'
+match 1 'a' '[B-a]'
+match 0 'z' '[Z-y]'
+match 1 'Z' '[Z-y]'
 
 imatch 1 'a' '[A-Z]'
 imatch 1 'A' '[A-Z]'
-- 
2.15.1.424.g9478a66081
Ævar Arnfjörð Bjarmason· Dec 25, 2017, 00:28 UTC · re: Ævar Arnfjörð Bjarmason · lore

[PATCH v2 6/7] wildmatch test: perform all tests under all wildmatch() modes

Rewrite the wildmatch() test suite so that each test now tests all combinations of the wildmatch() WM_CASEFOLD and WM_PATHNAME flags.

Before this change some test inputs were not tested on e.g. WM_PATHNAME. Now the function is stress tested on all possible inputs, and for each input we declare what the result should be if the mode is case-insensitive, or pathname matching, or case-sensitive or not matching pathnames.

Also before this change, nothing was testing case-insensitive non-pathname matching, so I've added that to test-wildmatch.c and made use of it.

This yields a rather scary patch, but there are no functional changes here, just more test coverage. Some now-redundant tests were deleted as a result of this change, since they were now duplicating an earlier test.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 t/helper/test-wildmatch.c |   2 +
 t/t3070-wildmatch.sh      | 478 +++++++++++++++++++++++-----------------------
 2 files changed, 239 insertions(+), 241 deletions(-)
Show changes to 2 files +239 −241

t/helper/test-wildmatch.c, t/t3070-wildmatch.sh

diff --git a/t/helper/test-wildmatch.c b/t/helper/test-wildmatch.c
index 921d7b3e7e..66d33dfcfd 100644
--- a/t/helper/test-wildmatch.c
+++ b/t/helper/test-wildmatch.c
@@ -16,6 +16,8 @@ int cmd_main(int argc, const char **argv)
 		return !!wildmatch(argv[3], argv[2], WM_PATHNAME | WM_CASEFOLD);
 	else if (!strcmp(argv[1], "pathmatch"))
 		return !!wildmatch(argv[3], argv[2], 0);
+	else if (!strcmp(argv[1], "ipathmatch"))
+		return !!wildmatch(argv[3], argv[2], WM_CASEFOLD);
 	else
 		return 1;
 }
diff --git a/t/t3070-wildmatch.sh b/t/t3070-wildmatch.sh
index 2f8a681c72..593b25b278 100755
--- a/t/t3070-wildmatch.sh
+++ b/t/t3070-wildmatch.sh
@@ -4,278 +4,274 @@ test_description='wildmatch tests'
 
 . ./test-lib.sh
 
-match() {
-	if test "$1" = 1
+wildtest() {
+	match_w_glob=$1
+	match_w_globi=$2
+	match_w_pathmatch=$3
+	match_w_pathmatchi=$4
+	text=$5
+	pattern=$6
+
+	if test "$match_w_glob" = 1
 	then
-		test_expect_success "wildmatch: match '$2' '$3'" "
-			test-wildmatch wildmatch '$2' '$3'
+		test_expect_success "wildmatch: match '$text' '$pattern'" "
+			test-wildmatch wildmatch '$text' '$pattern'
 		"
-	elif test "$1" = 0
+	elif test "$match_w_glob" = 0
 	then
-		test_expect_success "wildmatch: no match '$2' '$3'" "
-			! test-wildmatch wildmatch '$2' '$3'
+		test_expect_success "wildmatch: no match '$text' '$pattern'" "
+			! test-wildmatch wildmatch '$text' '$pattern'
 		"
 	else
-		test_expect_success "PANIC: Test framework error. Unknown matches value $1" 'false'
+		test_expect_success "PANIC: Test framework error. Unknown matches value $match_w_glob" 'false'
 	fi
-}
 
-imatch() {
-	if test "$1" = 1
+	if test "$match_w_globi" = 1
 	then
-		test_expect_success "iwildmatch: match '$2' '$3'" "
-			test-wildmatch iwildmatch '$2' '$3'
+		test_expect_success "iwildmatch: match '$text' '$pattern'" "
+			test-wildmatch iwildmatch '$text' '$pattern'
 		"
-	elif test "$1" = 0
+	elif test "$match_w_globi" = 0
 	then
-		test_expect_success "iwildmatch: no match '$2' '$3'" "
-			! test-wildmatch iwildmatch '$2' '$3'
+		test_expect_success "iwildmatch: no match '$text' '$pattern'" "
+			! test-wildmatch iwildmatch '$text' '$pattern'
 		"
 	else
-		test_expect_success "PANIC: Test framework error. Unknown matches value $1" 'false'
+		test_expect_success "PANIC: Test framework error. Unknown matches value $match_w_globi" 'false'
 	fi
-}
 
-pathmatch() {
-	if test "$1" = 1
+	if test "$match_w_pathmatch" = 1
 	then
-		test_expect_success "pathmatch: match '$2' '$3'" "
-			test-wildmatch pathmatch '$2' '$3'
+		test_expect_success "pathmatch: match '$text' '$pattern'" "
+			test-wildmatch pathmatch '$text' '$pattern'
 		"
-	elif test "$1" = 0
+	elif test "$match_w_pathmatch" = 0
 	then
-		test_expect_success "pathmatch: no match '$2' '$3'" "
-			! test-wildmatch pathmatch '$2' '$3'
+		test_expect_success "pathmatch: no match '$text' '$pattern'" "
+			! test-wildmatch pathmatch '$text' '$pattern'
 		"
 	else
-		test_expect_success "PANIC: Test framework error. Unknown matches value $1" 'false'
+		test_expect_success "PANIC: Test framework error. Unknown matches value $match_w_pathmatch" 'false'
+	fi
+
+	if test "$match_w_pathmatchi" = 1
+	then
+		test_expect_success "ipathmatch:    match '$text' '$pattern'" "
+			test-wildmatch ipathmatch '$text' '$pattern'
+		"
+	elif test "$match_w_pathmatchi" = 0
+	then
+		test_expect_success "ipathmatch: no match '$text' '$pattern'" "
+			! test-wildmatch ipathmatch '$text' '$pattern'
+		"
+	else
+		test_expect_success "PANIC: Test framework error. Unknown matches value $match_w_pathmatchi" 'false'
 	fi
 }
 
-# Basic wildmat features
-match 1 foo foo
-match 0 foo bar
-match 1 '' ""
-match 1 foo '???'
-match 0 foo '??'
-match 1 foo '*'
-match 1 foo 'f*'
-match 0 foo '*f'
-match 1 foo '*foo*'
-match 1 foobar '*ob*a*r*'
-match 1 aaaaaaabababab '*ab'
-match 1 'foo*' 'foo\*'
-match 0 foobar 'foo\*bar'
-match 1 'f\oo' 'f\\oo'
-match 1 ball '*[al]?'
-match 0 ten '[ten]'
-match 0 ten '**[!te]'
-match 0 ten '**[!ten]'
-match 1 ten 't[a-g]n'
-match 0 ten 't[!a-g]n'
-match 1 ton 't[!a-g]n'
-match 1 ton 't[^a-g]n'
-match 1 'a]b' 'a[]]b'
-match 1 a-b 'a[]-]b'
-match 1 'a]b' 'a[]-]b'
-match 0 aab 'a[]-]b'
-match 1 aab 'a[]a-]b'
-match 1 ']' ']'
+# Basic wildmatch features
+wildtest 1 1 1 1 foo foo
+wildtest 0 0 0 0 foo bar
+wildtest 1 1 1 1 '' ""
+wildtest 1 1 1 1 foo '???'
+wildtest 0 0 0 0 foo '??'
+wildtest 1 1 1 1 foo '*'
+wildtest 1 1 1 1 foo 'f*'
+wildtest 0 0 0 0 foo '*f'
+wildtest 1 1 1 1 foo '*foo*'
+wildtest 1 1 1 1 foobar '*ob*a*r*'
+wildtest 1 1 1 1 aaaaaaabababab '*ab'
+wildtest 1 1 1 1 'foo*' 'foo\*'
+wildtest 0 0 0 0 foobar 'foo\*bar'
+wildtest 1 1 1 1 'f\oo' 'f\\oo'
+wildtest 1 1 1 1 ball '*[al]?'
+wildtest 0 0 0 0 ten '[ten]'
+wildtest 0 0 1 1 ten '**[!te]'
+wildtest 0 0 0 0 ten '**[!ten]'
+wildtest 1 1 1 1 ten 't[a-g]n'
+wildtest 0 0 0 0 ten 't[!a-g]n'
+wildtest 1 1 1 1 ton 't[!a-g]n'
+wildtest 1 1 1 1 ton 't[^a-g]n'
+wildtest 1 1 1 1 'a]b' 'a[]]b'
+wildtest 1 1 1 1 a-b 'a[]-]b'
+wildtest 1 1 1 1 'a]b' 'a[]-]b'
+wildtest 0 0 0 0 aab 'a[]-]b'
+wildtest 1 1 1 1 aab 'a[]a-]b'
+wildtest 1 1 1 1 ']' ']'
 
 # Extended slash-matching features
-match 0 'foo/baz/bar' 'foo*bar'
-match 0 'foo/baz/bar' 'foo**bar'
-match 0 'foobazbar' 'foo**bar'
-match 1 'foo/baz/bar' 'foo/**/bar'
-match 1 'foo/baz/bar' 'foo/**/**/bar'
-match 1 'foo/b/a/z/bar' 'foo/**/bar'
-match 1 'foo/b/a/z/bar' 'foo/**/**/bar'
-match 1 'foo/bar' 'foo/**/bar'
-match 1 'foo/bar' 'foo/**/**/bar'
-match 0 'foo/bar' 'foo?bar'
-match 0 'foo/bar' 'foo[/]bar'
-match 0 'foo/bar' 'foo[^a-z]bar'
-match 0 'foo/bar' 'f[^eiu][^eiu][^eiu][^eiu][^eiu]r'
-match 1 'foo-bar' 'f[^eiu][^eiu][^eiu][^eiu][^eiu]r'
-match 1 'foo' '**/foo'
-match 1 'XXX/foo' '**/foo'
-match 1 'bar/baz/foo' '**/foo'
-match 0 'bar/baz/foo' '*/foo'
-match 0 'foo/bar/baz' '**/bar*'
-match 1 'deep/foo/bar/baz' '**/bar/*'
-match 0 'deep/foo/bar/baz/' '**/bar/*'
-match 1 'deep/foo/bar/baz/' '**/bar/**'
-match 0 'deep/foo/bar' '**/bar/*'
-match 1 'deep/foo/bar/' '**/bar/**'
-match 0 'foo/bar/baz' '**/bar**'
-match 1 'foo/bar/baz/x' '*/bar/**'
-match 0 'deep/foo/bar/baz/x' '*/bar/**'
-match 1 'deep/foo/bar/baz/x' '**/bar/*/*'
+wildtest 0 0 1 1 'foo/baz/bar' 'foo*bar'
+wildtest 0 0 1 1 'foo/baz/bar' 'foo**bar'
+wildtest 0 0 1 1 'foobazbar' 'foo**bar'
+wildtest 1 1 1 1 'foo/baz/bar' 'foo/**/bar'
+wildtest 1 1 0 0 'foo/baz/bar' 'foo/**/**/bar'
+wildtest 1 1 1 1 'foo/b/a/z/bar' 'foo/**/bar'
+wildtest 1 1 1 1 'foo/b/a/z/bar' 'foo/**/**/bar'
+wildtest 1 1 0 0 'foo/bar' 'foo/**/bar'
+wildtest 1 1 0 0 'foo/bar' 'foo/**/**/bar'
+wildtest 0 0 1 1 'foo/bar' 'foo?bar'
+wildtest 0 0 1 1 'foo/bar' 'foo[/]bar'
+wildtest 0 0 1 1 'foo/bar' 'foo[^a-z]bar'
+wildtest 0 0 1 1 'foo/bar' 'f[^eiu][^eiu][^eiu][^eiu][^eiu]r'
+wildtest 1 1 1 1 'foo-bar' 'f[^eiu][^eiu][^eiu][^eiu][^eiu]r'
+wildtest 1 1 0 0 'foo' '**/foo'
+wildtest 1 1 1 1 'XXX/foo' '**/foo'
+wildtest 1 1 1 1 'bar/baz/foo' '**/foo'
+wildtest 0 0 1 1 'bar/baz/foo' '*/foo'
+wildtest 0 0 1 1 'foo/bar/baz' '**/bar*'
+wildtest 1 1 1 1 'deep/foo/bar/baz' '**/bar/*'
+wildtest 0 0 1 1 'deep/foo/bar/baz/' '**/bar/*'
+wildtest 1 1 1 1 'deep/foo/bar/baz/' '**/bar/**'
+wildtest 0 0 0 0 'deep/foo/bar' '**/bar/*'
+wildtest 1 1 1 1 'deep/foo/bar/' '**/bar/**'
+wildtest 0 0 1 1 'foo/bar/baz' '**/bar**'
+wildtest 1 1 1 1 'foo/bar/baz/x' '*/bar/**'
+wildtest 0 0 1 1 'deep/foo/bar/baz/x' '*/bar/**'
+wildtest 1 1 1 1 'deep/foo/bar/baz/x' '**/bar/*/*'
 
 # Various additional tests
-match 0 'acrt' 'a[c-c]st'
-match 1 'acrt' 'a[c-c]rt'
-match 0 ']' '[!]-]'
-match 1 'a' '[!]-]'
-match 0 '' '\'
-match 0 '\' '\'
-match 0 'XXX/\' '*/\'
-match 1 'XXX/\' '*/\\'
-match 1 'foo' 'foo'
-match 1 '@foo' '@foo'
-match 0 'foo' '@foo'
-match 1 '[ab]' '\[ab]'
-match 1 '[ab]' '[[]ab]'
-match 1 '[ab]' '[[:]ab]'
-match 0 '[ab]' '[[::]ab]'
-match 1 '[ab]' '[[:digit]ab]'
-match 1 '[ab]' '[\[:]ab]'
-match 1 '?a?b' '\??\?b'
-match 1 'abc' '\a\b\c'
-match 0 'foo' ''
-match 1 'foo/bar/baz/to' '**/t[o]'
+wildtest 0 0 0 0 'acrt' 'a[c-c]st'
+wildtest 1 1 1 1 'acrt' 'a[c-c]rt'
+wildtest 0 0 0 0 ']' '[!]-]'
+wildtest 1 1 1 1 'a' '[!]-]'
+wildtest 0 0 0 0 '' '\'
+wildtest 0 0 0 0 '\' '\'
+wildtest 0 0 0 0 'XXX/\' '*/\'
+wildtest 1 1 1 1 'XXX/\' '*/\\'
+wildtest 1 1 1 1 'foo' 'foo'
+wildtest 1 1 1 1 '@foo' '@foo'
+wildtest 0 0 0 0 'foo' '@foo'
+wildtest 1 1 1 1 '[ab]' '\[ab]'
+wildtest 1 1 1 1 '[ab]' '[[]ab]'
+wildtest 1 1 1 1 '[ab]' '[[:]ab]'
+wildtest 0 0 0 0 '[ab]' '[[::]ab]'
+wildtest 1 1 1 1 '[ab]' '[[:digit]ab]'
+wildtest 1 1 1 1 '[ab]' '[\[:]ab]'
+wildtest 1 1 1 1 '?a?b' '\??\?b'
+wildtest 1 1 1 1 'abc' '\a\b\c'
+wildtest 0 0 0 0 'foo' ''
+wildtest 1 1 1 1 'foo/bar/baz/to' '**/t[o]'
 
 # Character class tests
-match 1 'a1B' '[[:alpha:]][[:digit:]][[:upper:]]'
-match 0 'a' '[[:digit:][:upper:][:space:]]'
-match 1 'A' '[[:digit:][:upper:][:space:]]'
-match 1 '1' '[[:digit:][:upper:][:space:]]'
-match 0 '1' '[[:digit:][:upper:][:spaci:]]'
-match 1 ' ' '[[:digit:][:upper:][:space:]]'
-match 0 '.' '[[:digit:][:upper:][:space:]]'
-match 1 '.' '[[:digit:][:punct:][:space:]]'
-match 1 '5' '[[:xdigit:]]'
-match 1 'f' '[[:xdigit:]]'
-match 1 'D' '[[:xdigit:]]'
-match 1 '_' '[[:alnum:][:alpha:][:blank:][:cntrl:][:digit:][:graph:][:lower:][:print:][:punct:][:space:][:upper:][:xdigit:]]'
-match 1 '.' '[^[:alnum:][:alpha:][:blank:][:cntrl:][:digit:][:lower:][:space:][:upper:][:xdigit:]]'
-match 1 '5' '[a-c[:digit:]x-z]'
-match 1 'b' '[a-c[:digit:]x-z]'
-match 1 'y' '[a-c[:digit:]x-z]'
-match 0 'q' '[a-c[:digit:]x-z]'
-
-# Additional tests, including some malformed wildmats
-match 1 ']' '[\\-^]'
-match 0 '[' '[\\-^]'
-match 1 '-' '[\-_]'
-match 1 ']' '[\]]'
-match 0 '\]' '[\]]'
-match 0 '\' '[\]]'
-match 0 'ab' 'a[]b'
-match 0 'a[]b' 'a[]b'
-match 0 'ab[' 'ab['
-match 0 'ab' '[!'
-match 0 'ab' '[-'
-match 1 '-' '[-]'
-match 0 '-' '[a-'
-match 0 '-' '[!a-'
-match 1 '-' '[--A]'
-match 1 '5' '[--A]'
-match 1 ' ' '[ --]'
-match 1 '$' '[ --]'
-match 1 '-' '[ --]'
-match 0 '0' '[ --]'
-match 1 '-' '[---]'
-match 1 '-' '[------]'
-match 0 'j' '[a-e-n]'
-match 1 '-' '[a-e-n]'
-match 1 'a' '[!------]'
-match 0 '[' '[]-a]'
-match 1 '^' '[]-a]'
-match 0 '^' '[!]-a]'
-match 1 '[' '[!]-a]'
-match 1 '^' '[a^bc]'
-match 1 '-b]' '[a-]b]'
-match 0 '\' '[\]'
-match 1 '\' '[\\]'
-match 0 '\' '[!\\]'
-match 1 'G' '[A-\\]'
-match 0 'aaabbb' 'b*a'
-match 0 'aabcaa' '*ba*'
-match 1 ',' '[,]'
-match 1 ',' '[\\,]'
-match 1 '\' '[\\,]'
-match 1 '-' '[,-.]'
-match 0 '+' '[,-.]'
-match 0 '-.]' '[,-.]'
-match 1 '2' '[\1-\3]'
-match 1 '3' '[\1-\3]'
-match 0 '4' '[\1-\3]'
-match 1 '\' '[[-\]]'
-match 1 '[' '[[-\]]'
-match 1 ']' '[[-\]]'
-match 0 '-' '[[-\]]'
+wildtest 1 1 1 1 'a1B' '[[:alpha:]][[:digit:]][[:upper:]]'
+wildtest 0 1 0 1 'a' '[[:digit:][:upper:][:space:]]'
+wildtest 1 1 1 1 'A' '[[:digit:][:upper:][:space:]]'
+wildtest 1 1 1 1 '1' '[[:digit:][:upper:][:space:]]'
+wildtest 0 0 0 0 '1' '[[:digit:][:upper:][:spaci:]]'
+wildtest 1 1 1 1 ' ' '[[:digit:][:upper:][:space:]]'
+wildtest 0 0 0 0 '.' '[[:digit:][:upper:][:space:]]'
+wildtest 1 1 1 1 '.' '[[:digit:][:punct:][:space:]]'
+wildtest 1 1 1 1 '5' '[[:xdigit:]]'
+wildtest 1 1 1 1 'f' '[[:xdigit:]]'
+wildtest 1 1 1 1 'D' '[[:xdigit:]]'
+wildtest 1 1 1 1 '_' '[[:alnum:][:alpha:][:blank:][:cntrl:][:digit:][:graph:][:lower:][:print:][:punct:][:space:][:upper:][:xdigit:]]'
+wildtest 1 1 1 1 '.' '[^[:alnum:][:alpha:][:blank:][:cntrl:][:digit:][:lower:][:space:][:upper:][:xdigit:]]'
+wildtest 1 1 1 1 '5' '[a-c[:digit:]x-z]'
+wildtest 1 1 1 1 'b' '[a-c[:digit:]x-z]'
+wildtest 1 1 1 1 'y' '[a-c[:digit:]x-z]'
+wildtest 0 0 0 0 'q' '[a-c[:digit:]x-z]'
 
-# Test recursion and the abort code (use "wildtest -i" to see iteration counts)
-match 1 '-adobe-courier-bold-o-normal--12-120-75-75-m-70-iso8859-1' '-*-*-*-*-*-*-12-*-*-*-m-*-*-*'
-match 0 '-adobe-courier-bold-o-normal--12-120-75-75-X-70-iso8859-1' '-*-*-*-*-*-*-12-*-*-*-m-*-*-*'
-match 0 '-adobe-courier-bold-o-normal--12-120-75-75-/-70-iso8859-1' '-*-*-*-*-*-*-12-*-*-*-m-*-*-*'
-match 1 'XXX/adobe/courier/bold/o/normal//12/120/75/75/m/70/iso8859/1' 'XXX/*/*/*/*/*/*/12/*/*/*/m/*/*/*'
-match 0 'XXX/adobe/courier/bold/o/normal//12/120/75/75/X/70/iso8859/1' 'XXX/*/*/*/*/*/*/12/*/*/*/m/*/*/*'
-match 1 'abcd/abcdefg/abcdefghijk/abcdefghijklmnop.txt' '**/*a*b*g*n*t'
-match 0 'abcd/abcdefg/abcdefghijk/abcdefghijklmnop.txtz' '**/*a*b*g*n*t'
-match 0 foo '*/*/*'
-match 0 foo/bar '*/*/*'
-match 1 foo/bba/arr '*/*/*'
-match 0 foo/bb/aa/rr '*/*/*'
-match 1 foo/bb/aa/rr '**/**/**'
-match 1 abcXdefXghi '*X*i'
-match 0 ab/cXd/efXg/hi '*X*i'
-match 1 ab/cXd/efXg/hi '*/*X*/*/*i'
-match 1 ab/cXd/efXg/hi '**/*X*/**/*i'
+# Additional tests, including some malformed wildmatch patterns
+wildtest 1 1 1 1 ']' '[\\-^]'
+wildtest 0 0 0 0 '[' '[\\-^]'
+wildtest 1 1 1 1 '-' '[\-_]'
+wildtest 1 1 1 1 ']' '[\]]'
+wildtest 0 0 0 0 '\]' '[\]]'
+wildtest 0 0 0 0 '\' '[\]]'
+wildtest 0 0 0 0 'ab' 'a[]b'
+wildtest 0 0 0 0 'a[]b' 'a[]b'
+wildtest 0 0 0 0 'ab[' 'ab['
+wildtest 0 0 0 0 'ab' '[!'
+wildtest 0 0 0 0 'ab' '[-'
+wildtest 1 1 1 1 '-' '[-]'
+wildtest 0 0 0 0 '-' '[a-'
+wildtest 0 0 0 0 '-' '[!a-'
+wildtest 1 1 1 1 '-' '[--A]'
+wildtest 1 1 1 1 '5' '[--A]'
+wildtest 1 1 1 1 ' ' '[ --]'
+wildtest 1 1 1 1 '$' '[ --]'
+wildtest 1 1 1 1 '-' '[ --]'
+wildtest 0 0 0 0 '0' '[ --]'
+wildtest 1 1 1 1 '-' '[---]'
+wildtest 1 1 1 1 '-' '[------]'
+wildtest 0 0 0 0 'j' '[a-e-n]'
+wildtest 1 1 1 1 '-' '[a-e-n]'
+wildtest 1 1 1 1 'a' '[!------]'
+wildtest 0 0 0 0 '[' '[]-a]'
+wildtest 1 1 1 1 '^' '[]-a]'
+wildtest 0 0 0 0 '^' '[!]-a]'
+wildtest 1 1 1 1 '[' '[!]-a]'
+wildtest 1 1 1 1 '^' '[a^bc]'
+wildtest 1 1 1 1 '-b]' '[a-]b]'
+wildtest 0 0 0 0 '\' '[\]'
+wildtest 1 1 1 1 '\' '[\\]'
+wildtest 0 0 0 0 '\' '[!\\]'
+wildtest 1 1 1 1 'G' '[A-\\]'
+wildtest 0 0 0 0 'aaabbb' 'b*a'
+wildtest 0 0 0 0 'aabcaa' '*ba*'
+wildtest 1 1 1 1 ',' '[,]'
+wildtest 1 1 1 1 ',' '[\\,]'
+wildtest 1 1 1 1 '\' '[\\,]'
+wildtest 1 1 1 1 '-' '[,-.]'
+wildtest 0 0 0 0 '+' '[,-.]'
+wildtest 0 0 0 0 '-.]' '[,-.]'
+wildtest 1 1 1 1 '2' '[\1-\3]'
+wildtest 1 1 1 1 '3' '[\1-\3]'
+wildtest 0 0 0 0 '4' '[\1-\3]'
+wildtest 1 1 1 1 '\' '[[-\]]'
+wildtest 1 1 1 1 '[' '[[-\]]'
+wildtest 1 1 1 1 ']' '[[-\]]'
+wildtest 0 0 0 0 '-' '[[-\]]'
 
-pathmatch 1 foo foo
-pathmatch 0 foo fo
-pathmatch 1 foo/bar foo/bar
-pathmatch 1 foo/bar 'foo/*'
-pathmatch 1 foo/bba/arr 'foo/*'
-pathmatch 1 foo/bba/arr 'foo/**'
-pathmatch 1 foo/bba/arr 'foo*'
-pathmatch 1 foo/bba/arr 'foo**'
-pathmatch 1 foo/bba/arr 'foo/*arr'
-pathmatch 1 foo/bba/arr 'foo/**arr'
-pathmatch 0 foo/bba/arr 'foo/*z'
-pathmatch 0 foo/bba/arr 'foo/**z'
-pathmatch 1 foo/bar 'foo?bar'
-pathmatch 1 foo/bar 'foo[/]bar'
-pathmatch 1 foo/bar 'foo[^a-z]bar'
-pathmatch 0 foo '*/*/*'
-pathmatch 0 foo/bar '*/*/*'
-pathmatch 1 foo/bba/arr '*/*/*'
-pathmatch 1 foo/bb/aa/rr '*/*/*'
-pathmatch 1 abcXdefXghi '*X*i'
-pathmatch 1 ab/cXd/efXg/hi '*/*X*/*/*i'
-pathmatch 1 ab/cXd/efXg/hi '*Xg*i'
+# Test recursion
+wildtest 1 1 1 1 '-adobe-courier-bold-o-normal--12-120-75-75-m-70-iso8859-1' '-*-*-*-*-*-*-12-*-*-*-m-*-*-*'
+wildtest 0 0 0 0 '-adobe-courier-bold-o-normal--12-120-75-75-X-70-iso8859-1' '-*-*-*-*-*-*-12-*-*-*-m-*-*-*'
+wildtest 0 0 0 0 '-adobe-courier-bold-o-normal--12-120-75-75-/-70-iso8859-1' '-*-*-*-*-*-*-12-*-*-*-m-*-*-*'
+wildtest 1 1 1 1 'XXX/adobe/courier/bold/o/normal//12/120/75/75/m/70/iso8859/1' 'XXX/*/*/*/*/*/*/12/*/*/*/m/*/*/*'
+wildtest 0 0 0 0 'XXX/adobe/courier/bold/o/normal//12/120/75/75/X/70/iso8859/1' 'XXX/*/*/*/*/*/*/12/*/*/*/m/*/*/*'
+wildtest 1 1 1 1 'abcd/abcdefg/abcdefghijk/abcdefghijklmnop.txt' '**/*a*b*g*n*t'
+wildtest 0 0 0 0 'abcd/abcdefg/abcdefghijk/abcdefghijklmnop.txtz' '**/*a*b*g*n*t'
+wildtest 0 0 0 0 foo '*/*/*'
+wildtest 0 0 0 0 foo/bar '*/*/*'
+wildtest 1 1 1 1 foo/bba/arr '*/*/*'
+wildtest 0 0 1 1 foo/bb/aa/rr '*/*/*'
+wildtest 1 1 1 1 foo/bb/aa/rr '**/**/**'
+wildtest 1 1 1 1 abcXdefXghi '*X*i'
+wildtest 0 0 1 1 ab/cXd/efXg/hi '*X*i'
+wildtest 1 1 1 1 ab/cXd/efXg/hi '*/*X*/*/*i'
+wildtest 1 1 1 1 ab/cXd/efXg/hi '**/*X*/**/*i'
 
-# Case-sensitivity features
-match 0 'a' '[A-Z]'
-match 1 'A' '[A-Z]'
-match 0 'A' '[a-z]'
-match 1 'a' '[a-z]'
-match 0 'a' '[[:upper:]]'
-match 1 'A' '[[:upper:]]'
-match 0 'A' '[[:lower:]]'
-match 1 'a' '[[:lower:]]'
-match 0 'A' '[B-Za]'
-match 1 'a' '[B-Za]'
-match 0 'A' '[B-a]'
-match 1 'a' '[B-a]'
-match 0 'z' '[Z-y]'
-match 1 'Z' '[Z-y]'
+# Extra pathmatch tests
+wildtest 0 0 0 0 foo fo
+wildtest 1 1 1 1 foo/bar foo/bar
+wildtest 1 1 1 1 foo/bar 'foo/*'
+wildtest 0 0 1 1 foo/bba/arr 'foo/*'
+wildtest 1 1 1 1 foo/bba/arr 'foo/**'
+wildtest 0 0 1 1 foo/bba/arr 'foo*'
+wildtest 0 0 1 1 foo/bba/arr 'foo**'
+wildtest 0 0 1 1 foo/bba/arr 'foo/*arr'
+wildtest 0 0 1 1 foo/bba/arr 'foo/**arr'
+wildtest 0 0 0 0 foo/bba/arr 'foo/*z'
+wildtest 0 0 0 0 foo/bba/arr 'foo/**z'
+wildtest 0 0 1 1 foo/bar 'foo?bar'
+wildtest 0 0 1 1 foo/bar 'foo[/]bar'
+wildtest 0 0 1 1 foo/bar 'foo[^a-z]bar'
+wildtest 0 0 1 1 ab/cXd/efXg/hi '*Xg*i'
 
-imatch 1 'a' '[A-Z]'
-imatch 1 'A' '[A-Z]'
-imatch 1 'A' '[a-z]'
-imatch 1 'a' '[a-z]'
-imatch 1 'a' '[[:upper:]]'
-imatch 1 'A' '[[:upper:]]'
-imatch 1 'A' '[[:lower:]]'
-imatch 1 'a' '[[:lower:]]'
-imatch 1 'A' '[B-Za]'
-imatch 1 'a' '[B-Za]'
-imatch 1 'A' '[B-a]'
-imatch 1 'a' '[B-a]'
-imatch 1 'z' '[Z-y]'
-imatch 1 'Z' '[Z-y]'
+# Extra case-sensitivity tests
+wildtest 0 1 0 1 'a' '[A-Z]'
+wildtest 1 1 1 1 'A' '[A-Z]'
+wildtest 0 1 0 1 'A' '[a-z]'
+wildtest 1 1 1 1 'a' '[a-z]'
+wildtest 0 1 0 1 'a' '[[:upper:]]'
+wildtest 1 1 1 1 'A' '[[:upper:]]'
+wildtest 0 1 0 1 'A' '[[:lower:]]'
+wildtest 1 1 1 1 'a' '[[:lower:]]'
+wildtest 0 1 0 1 'A' '[B-Za]'
+wildtest 1 1 1 1 'a' '[B-Za]'
+wildtest 0 1 0 1 'A' '[B-a]'
+wildtest 1 1 1 1 'a' '[B-a]'
+wildtest 0 1 0 1 'z' '[Z-y]'
+wildtest 1 1 1 1 'Z' '[Z-y]'
 
 test_done
-- 
2.15.1.424.g9478a66081
Junio C Hamano· Dec 28, 2017, 20:28 UTC · re: Ævar Arnfjörð Bjarmason · lore

Re: [PATCH v2 6/7] wildmatch test: perform all tests under all wildmatch() modes

Ævar Arnfjörð Bjarmason  <avarab@gmail.com> writes:
Show 8 quoted lines
> +	if test "$match_w_pathmatchi" = 1
> +	then
> +		test_expect_success "ipathmatch:    match '$text' '$pattern'" "
> +			test-wildmatch ipathmatch '$text' '$pattern'
> +		"
> +	elif test "$match_w_pathmatchi" = 0
> +	then
> +		test_expect_success "ipathmatch: no match '$text' '$pattern'" "
I somehow thought that you earlier decided not to SP align the test titles?

Not a big deal but aligning this one alone stood out and I ended up noticing it, so... ;-)

Ævar Arnfjörð Bjarmason· Dec 25, 2017, 00:28 UTC · re: Ævar Arnfjörð Bjarmason · lore

[PATCH v2 7/7] wildmatch test: create & test files on disk in addition to in-memory

There has never been any full roundtrip testing of what git-ls-files and other functions that use wildmatch() actually do, rather we've been satisfied with just testing the underlying C function.

Due to git-ls-files and friends having their own codepaths before they call wildmatch() there's sometimes differences in the behavior between the two, and even when we test for those (as with 9e4e8a64c2 ("pathspec: die on empty strings as pathspec", 2017-06-06)) there was no one place where you can review how these two modes differ.

Now there is. We now attempt to create a file called $haystack and match $needle against it for each pair of $needle and $haystack that we were passing to test-wildmatch.

If we can't create the file we skip the test. This ensures that we can run this on all platforms and not maintain some infinitely growing whitelist of e.g. platforms that don't support certain characters in filenames.

As a result of doing this we can now see the cases where these two ways of testing wildmatch differ:

 * Creating a file called 'a[]b' and running ls-files 'a[]b' will show
   that file, but wildmatch("a[]b", "a[]b") will not match
 * wildmatch() won't match a file called \ against \, but ls-files
   will.
 * `git --glob-pathspecs ls-files 'foo**'` will match a file
   'foo/bba/arr', but wildmatch won't, however pathmatch will.
   This seems like a bug to me, the two are otherwise equivalent as
   these tests show.

This also reveals the case discussed in 9e4e8a64c2 above, where '' is now an error as far as ls-files is concerned, but wildmatch() itself happily accepts it.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 t/t3070-wildmatch.sh | 285 ++++++++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 273 insertions(+), 12 deletions(-)
Show changes to t/t3070-wildmatch.sh +273 −12
diff --git a/t/t3070-wildmatch.sh b/t/t3070-wildmatch.sh
index 593b25b278..80d13b5b60 100755
--- a/t/t3070-wildmatch.sh
+++ b/t/t3070-wildmatch.sh
@@ -4,14 +4,95 @@ test_description='wildmatch tests'
 
 . ./test-lib.sh
 
+create_test_file() {
+	file=$1
+
+	case $file in
+	# `touch .` will succeed but obviously not do what we intend
+	# here.
+	".")
+		return 1
+		;;
+	# We cannot create a file with an empty filename.
+	"")
+		return 1
+		;;
+	# The tests that are testing that e.g. foo//bar is matched by
+	# foo/*/bar can't be tested on filesystems since there's no
+	# way we're getting a double slash.
+	*//*)
+		return 1
+		;;
+	# When testing the difference between foo/bar and foo/bar/ we
+	# can't test the latter.
+	*/)
+		return 1
+		;;
+	esac
+
+	# Turn foo/bar/baz into foo/bar to create foo/bar as a
+	# directory structure.
+	dirs=$(echo "$file" | sed -r 's!/[^/]+$!!')
+
+	# We touch "./$file" instead of "$file" because even an
+	# escaped "touch -- -" means get arguments from stdin.
+	if test "$file" != "$dirs"
+	then
+		mkdir -p -- "$dirs" &&
+		touch -- "./$file" &&
+		return 0
+	else
+		touch -- "./$file" &&
+		return 0
+	fi
+	return 1
+}
+
+wildtest_file_setup() {
+	test_when_finished "
+		rm -rf -- * &&
+		git reset
+	" &&
+	git add -A &&
+	>expect.err
+}
+
+wildtest_stdout_stderr_cmp() {
+	tr -d '\0' <actual.raw >actual &&
+	test_cmp expect.err actual.err &&
+	test_cmp expect actual
+}
+
 wildtest() {
-	match_w_glob=$1
-	match_w_globi=$2
-	match_w_pathmatch=$3
-	match_w_pathmatchi=$4
-	text=$5
-	pattern=$6
+	if test "$#" = 6
+	then
+		# When test-wildmatch and git ls-files produce the same
+		# result.
+		match_w_glob=$1
+		match_f_w_glob=$match_w_glob
+		match_w_globi=$2
+		match_f_w_globi=$match_w_globi
+		match_w_pathmatch=$3
+		match_f_w_pathmatch=$match_w_pathmatch
+		match_w_pathmatchi=$4
+		match_f_w_pathmatchi=$match_w_pathmatchi
+		text=$5
+		pattern=$6
+	elif test "$#" = 10
+	then
+		match_w_glob=$1
+		match_w_globi=$2
+		match_w_pathmatch=$3
+		match_w_pathmatchi=$4
+		match_f_w_glob=$5
+		match_f_w_globi=$6
+		match_f_w_pathmatch=$7
+		match_f_w_pathmatchi=$8
+		text=$9
+		pattern=$10
+	fi
 
+	# $1: Case sensitive glob match: test-wildmatch
 	if test "$match_w_glob" = 1
 	then
 		test_expect_success "wildmatch: match '$text' '$pattern'" "
@@ -26,6 +107,50 @@ wildtest() {
 		test_expect_success "PANIC: Test framework error. Unknown matches value $match_w_glob" 'false'
 	fi
 
+	# $1: Case sensitive glob match: ls-files
+	if test "$match_f_w_glob" = 'E'
+	then
+		if create_test_file "$text"
+		then
+			test_expect_success "wildmatch(ls): match dies on '$pattern' '$text'" "
+				wildtest_file_setup &&
+				printf '%s' '$text' >expect &&
+				test_must_fail git --glob-pathspecs ls-files -z -- '$pattern'
+			"
+		else
+			test_expect_failure "wildmatch(ls): match skip '$pattern' '$text'" 'false'
+		fi
+	elif test "$match_f_w_glob" = 1
+	then
+		if create_test_file "$text"
+		then
+			test_expect_success "wildmatch(ls): match '$pattern' '$text'" "
+				wildtest_file_setup &&
+				printf '%s' '$text' >expect &&
+				git --glob-pathspecs ls-files -z -- '$pattern' >actual.raw 2>actual.err &&
+				wildtest_stdout_stderr_cmp
+			"
+		else
+			test_expect_failure "wildmatch(ls): match skip '$pattern' '$text'" 'false'
+		fi
+	elif test "$match_f_w_glob" = 0
+	then
+		if create_test_file "$text"
+		then
+			test_expect_success "wildmatch(ls): no match '$pattern' '$text'" "
+				wildtest_file_setup &&
+				>expect &&
+				git --glob-pathspecs ls-files -z -- '$pattern' >actual.raw 2>actual.err &&
+				wildtest_stdout_stderr_cmp
+			"
+		else
+			test_expect_failure "wildmatch(ls): no match skip '$pattern' '$text'" 'false'
+		fi
+	else
+		test_expect_success "PANIC: Test framework error. Unknown matches value $match_f_w_glob" 'false'
+	fi
+
+	# $2: Case insensitive glob match: test-wildmatch
 	if test "$match_w_globi" = 1
 	then
 		test_expect_success "iwildmatch: match '$text' '$pattern'" "
@@ -40,6 +165,50 @@ wildtest() {
 		test_expect_success "PANIC: Test framework error. Unknown matches value $match_w_globi" 'false'
 	fi
 
+	# $2: Case insensitive glob match: ls-files
+	if test "$match_f_w_globi" = 'E'
+	then
+		if create_test_file "$text"
+		then
+			test_expect_success "wildmatch(ls): match dies on '$pattern' '$text'" "
+				wildtest_file_setup &&
+				printf '%s' '$text' >expect &&
+				test_must_fail git --glob-pathspecs --icase-pathspecs ls-files -z -- '$pattern'
+			"
+		else
+			test_expect_failure "wildmatch(ls): match skip '$pattern' '$text'" 'false'
+		fi
+	elif test "$match_f_w_globi" = 1
+	then
+		if create_test_file "$text"
+		then
+			test_expect_success "wildmatch(ls): match '$pattern' '$text'" "
+				wildtest_file_setup &&
+				printf '%s' '$text' >expect &&
+				git --glob-pathspecs --icase-pathspecs ls-files -z -- '$pattern' >actual.raw 2>actual.err &&
+				wildtest_stdout_stderr_cmp
+			"
+		else
+			test_expect_failure "wildmatch(ls): match skip '$pattern' '$text'" 'false'
+		fi
+	elif test "$match_f_w_globi" = 0
+	then
+		if create_test_file "$text"
+		then
+			test_expect_success "wildmatch(ls): no match '$pattern' '$text'" "
+				wildtest_file_setup &&
+				>expect &&
+				git --glob-pathspecs --icase-pathspecs ls-files -z -- '$pattern' >actual.raw 2>actual.err &&
+				wildtest_stdout_stderr_cmp
+			"
+		else
+			test_expect_failure "wildmatch(ls): no match skip '$pattern' '$text'" 'false'
+		fi
+	else
+		test_expect_success "PANIC: Test framework error. Unknown matches value $match_f_w_globi" 'false'
+	fi
+
+	# $3: Case sensitive path match: test-wildmatch
 	if test "$match_w_pathmatch" = 1
 	then
 		test_expect_success "pathmatch: match '$text' '$pattern'" "
@@ -54,9 +223,53 @@ wildtest() {
 		test_expect_success "PANIC: Test framework error. Unknown matches value $match_w_pathmatch" 'false'
 	fi
 
+	# $4: Case sensitive path match: ls-files
+	if test "$match_f_w_pathmatch" = 'E'
+	then
+		if create_test_file "$text"
+		then
+			test_expect_success "pathmatch(ls): match dies on '$pattern' '$text'" "
+				wildtest_file_setup &&
+				printf '%s' '$text' >expect &&
+				test_must_fail git ls-files -z -- '$pattern'
+			"
+		else
+			test_expect_failure "pathmatch(ls): match skip '$pattern' '$text'" 'false'
+		fi
+	elif test "$match_f_w_pathmatch" = 1
+	then
+		if create_test_file "$text"
+		then
+			test_expect_success "pathmatch(ls): match '$pattern' '$text'" "
+				wildtest_file_setup &&
+				printf '%s' '$text' >expect &&
+				git ls-files -z -- '$pattern' >actual.raw 2>actual.err &&
+				wildtest_stdout_stderr_cmp
+			"
+		else
+			test_expect_failure "pathmatch(ls): match skip '$pattern' '$text'" 'false'
+		fi
+	elif test "$match_f_w_pathmatch" = 0
+	then
+		if create_test_file "$text"
+		then
+			test_expect_success "pathmatch(ls): no match '$pattern' '$text'" "
+				wildtest_file_setup &&
+				>expect &&
+				git ls-files -z -- '$pattern' >actual.raw 2>actual.err &&
+				wildtest_stdout_stderr_cmp
+			"
+		else
+			test_expect_failure "pathmatch(ls): no match skip '$pattern' '$text'" 'false'
+		fi
+	else
+		test_expect_success "PANIC: Test framework error. Unknown matches value $match_f_w_pathmatch" 'false'
+	fi
+
+	# $4: Case insensitive path match: test-wildmatch
 	if test "$match_w_pathmatchi" = 1
 	then
-		test_expect_success "ipathmatch:    match '$text' '$pattern'" "
+		test_expect_success "ipathmatch: match '$text' '$pattern'" "
 			test-wildmatch ipathmatch '$text' '$pattern'
 		"
 	elif test "$match_w_pathmatchi" = 0
@@ -67,6 +280,49 @@ wildtest() {
 	else
 		test_expect_success "PANIC: Test framework error. Unknown matches value $match_w_pathmatchi" 'false'
 	fi
+
+	# $4: Case insensitive path match: ls-files
+	if test "$match_f_w_pathmatchi" = 'E'
+	then
+		if create_test_file "$text"
+		then
+			test_expect_success "ipathmatch(ls): match dies on '$pattern' '$text'" "
+				wildtest_file_setup &&
+				printf '%s' '$text' >expect &&
+				test_must_fail git --icase-pathspecs ls-files -z -- '$pattern'
+			"
+		else
+			test_expect_failure "pathmatch(ls): match skip '$pattern' '$text'" 'false'
+		fi
+	elif test "$match_f_w_pathmatchi" = 1
+	then
+		if create_test_file "$text"
+		then
+			test_expect_success "ipathmatch(ls): match '$pattern' '$text'" "
+				wildtest_file_setup &&
+				printf '%s' '$text' >expect &&
+				git --icase-pathspecs ls-files -z -- '$pattern' >actual.raw 2>actual.err &&
+				wildtest_stdout_stderr_cmp
+			"
+		else
+			test_expect_failure "pathmatch(ls): match skip '$pattern' '$text'" 'false'
+		fi
+	elif test "$match_f_w_pathmatchi" = 0
+	then
+		if create_test_file "$text"
+		then
+			test_expect_success "ipathmatch(ls): no match '$pattern' '$text'" "
+				wildtest_file_setup &&
+				>expect &&
+				git ls-files -z -- '$pattern' >actual.raw 2>actual.err &&
+				wildtest_stdout_stderr_cmp
+			"
+		else
+			test_expect_failure "pathmatch(ls): no match skip '$pattern' '$text'" 'false'
+		fi
+	else
+		test_expect_success "PANIC: Test framework error. Unknown matches value $match_f_w_pathmatchi" 'false'
+	fi
 }
 
 # Basic wildmatch features
@@ -135,7 +391,8 @@ wildtest 1 1 1 1 'acrt' 'a[c-c]rt'
 wildtest 0 0 0 0 ']' '[!]-]'
 wildtest 1 1 1 1 'a' '[!]-]'
 wildtest 0 0 0 0 '' '\'
-wildtest 0 0 0 0 '\' '\'
+wildtest 0 0 0 0 \
+	 1 1 1 1 '\' '\'
 wildtest 0 0 0 0 'XXX/\' '*/\'
 wildtest 1 1 1 1 'XXX/\' '*/\\'
 wildtest 1 1 1 1 'foo' 'foo'
@@ -149,7 +406,8 @@ wildtest 1 1 1 1 '[ab]' '[[:digit]ab]'
 wildtest 1 1 1 1 '[ab]' '[\[:]ab]'
 wildtest 1 1 1 1 '?a?b' '\??\?b'
 wildtest 1 1 1 1 'abc' '\a\b\c'
-wildtest 0 0 0 0 'foo' ''
+wildtest 0 0 0 0 \
+	 E E E E 'foo' ''
 wildtest 1 1 1 1 'foo/bar/baz/to' '**/t[o]'
 
 # Character class tests
@@ -179,8 +437,10 @@ wildtest 1 1 1 1 ']' '[\]]'
 wildtest 0 0 0 0 '\]' '[\]]'
 wildtest 0 0 0 0 '\' '[\]]'
 wildtest 0 0 0 0 'ab' 'a[]b'
-wildtest 0 0 0 0 'a[]b' 'a[]b'
-wildtest 0 0 0 0 'ab[' 'ab['
+wildtest 0 0 0 0 \
+	 1 1 1 1 'a[]b' 'a[]b'
+wildtest 0 0 0 0 \
+	 1 1 1 1 'ab[' 'ab['
 wildtest 0 0 0 0 'ab' '[!'
 wildtest 0 0 0 0 'ab' '[-'
 wildtest 1 1 1 1 '-' '[-]'
@@ -248,7 +508,8 @@ wildtest 1 1 1 1 foo/bar 'foo/*'
 wildtest 0 0 1 1 foo/bba/arr 'foo/*'
 wildtest 1 1 1 1 foo/bba/arr 'foo/**'
 wildtest 0 0 1 1 foo/bba/arr 'foo*'
-wildtest 0 0 1 1 foo/bba/arr 'foo**'
+wildtest 0 0 1 1 \
+	 1 1 1 1 foo/bba/arr 'foo**'
 wildtest 0 0 1 1 foo/bba/arr 'foo/*arr'
 wildtest 0 0 1 1 foo/bba/arr 'foo/**arr'
 wildtest 0 0 0 0 foo/bba/arr 'foo/*z'
-- 
2.15.1.424.g9478a66081
Johannes Sixt· Dec 25, 2017, 09:26 UTC · re: Ævar Arnfjörð Bjarmason · lore

Re: [PATCH v2 7/7] wildmatch test: create & test files on disk in addition to in-memory

Am 25.12.2017 um 01:28 schrieb Ævar Arnfjörð Bjarmason:
Show 25 quoted lines
> +create_test_file() {
> +	file=$1
> +
> +	case $file in
> +	# `touch .` will succeed but obviously not do what we intend
> +	# here.
> +	".")
> +		return 1
> +		;;
> +	# We cannot create a file with an empty filename.
> +	"")
> +		return 1
> +		;;
> +	# The tests that are testing that e.g. foo//bar is matched by
> +	# foo/*/bar can't be tested on filesystems since there's no
> +	# way we're getting a double slash.
> +	*//*)
> +		return 1
> +		;;
> +	# When testing the difference between foo/bar and foo/bar/ we
> +	# can't test the latter.
> +	*/)
> +		return 1
> +		;;
> +	esac
Nice!
> +
> +	# Turn foo/bar/baz into foo/bar to create foo/bar as a
> +	# directory structure.
> +	dirs=$(echo "$file" | sed -r 's!/[^/]+$!!')
	dirs=${file%/*}
should do the same without forking processes, no?
-- Hannes
Junio C Hamano· Dec 27, 2017, 19:07 UTC · re: Ævar Arnfjörð Bjarmason · lore

Re: [PATCH v2 7/7] wildmatch test: create & test files on disk in addition to in-memory

Ævar Arnfjörð Bjarmason  <avarab@gmail.com> writes:
> +	# Turn foo/bar/baz into foo/bar to create foo/bar as a
> +	# directory structure.
> +	dirs=$(echo "$file" | sed -r 's!/[^/]+$!!')
Let's not limit this script to GNUism systems.

You want to see if $file has a slash followed by one or more non-slash letters to the end and strip the whole thing. We further know that at this point $file does not end with a slash. So perhaps

	dirs=${file%/*}
is sufficient?
Thanks.
Adam Dinwoodie· Jan 3, 2018, 13:02 UTC · re: Ævar Arnfjörð Bjarmason · lore

Re: [PATCH v2 7/7] wildmatch test: create & test files on disk in addition to in-memory

On Monday 25 December 2017 at 12:28 am +0000, Ævar Arnfjörð Bjarmason wrote:
Show 40 quoted lines
> There has never been any full roundtrip testing of what git-ls-files
> and other functions that use wildmatch() actually do, rather we've
> been satisfied with just testing the underlying C function.
> 
> Due to git-ls-files and friends having their own codepaths before they
> call wildmatch() there's sometimes differences in the behavior between
> the two, and even when we test for those (as with
> 9e4e8a64c2 ("pathspec: die on empty strings as pathspec", 2017-06-06))
> there was no one place where you can review how these two modes
> differ.
> 
> Now there is. We now attempt to create a file called $haystack and
> match $needle against it for each pair of $needle and $haystack that
> we were passing to test-wildmatch.
> 
> If we can't create the file we skip the test. This ensures that we can
> run this on all platforms and not maintain some infinitely growing
> whitelist of e.g. platforms that don't support certain characters in
> filenames.
> 
> As a result of doing this we can now see the cases where these two
> ways of testing wildmatch differ:
> 
>  * Creating a file called 'a[]b' and running ls-files 'a[]b' will show
>    that file, but wildmatch("a[]b", "a[]b") will not match
> 
>  * wildmatch() won't match a file called \ against \, but ls-files
>    will.
> 
>  * `git --glob-pathspecs ls-files 'foo**'` will match a file
>    'foo/bba/arr', but wildmatch won't, however pathmatch will.
> 
>    This seems like a bug to me, the two are otherwise equivalent as
>    these tests show.
> 
> This also reveals the case discussed in 9e4e8a64c2 above, where '' is
> now an error as far as ls-files is concerned, but wildmatch() itself
> happily accepts it.
> 
> Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>

I'm seeing this test script failing on the pu branch as a result of this commit when building on Cygwin. Specifically, the test fails at 9d45e1ca4 ("Merge branch 'bw/oidmap-autoinit' into pu", 2017-12-28), and bisecting points the blame at 2ee0c785a ("wildmatch test: create & test files on disk in addition to in-memory", 2017-12-25).

I've copied the verbose error output for the first error below, and uploaded the full output, including verbose and trace output for the unexpectedly failing tests, at [0]. (With 42 failures among 1512 tests, there's a lot of it, so I didn't want to include it in an email.)

    expecting success:
                                    wildtest_file_setup &&
                                    printf '%s' '\' >expect &&
                                    git --glob-pathspecs ls-files -z -- '00' >actual.raw 2>actual.err &&
                                    wildtest_stdout_stderr_cmp
    
    ++ wildtest_file_setup
    ++ test_when_finished '
                    rm -rf -- * &&
                    git reset
            '
    ++ test 0 = 0
    ++ test_cleanup='{
                    rm -rf -- * &&
                    git reset
    
                    } && (exit "$eval_ret"); eval_ret=$?; :'
    ++ git add -A
    ++ printf %s '\'
    ++ git --glob-pathspecs ls-files -z -- 00
    ++ wildtest_stdout_stderr_cmp
    ++ tr -d '\0'
    ++ test_cmp expect.err actual.err
    ++ diff -u expect.err actual.err
    ++ test_cmp expect actual
    ++ diff -u expect actual
    --- expect      2018-01-03 12:43:11.116611200 +0000
    +++ actual      2018-01-03 12:43:11.216180400 +0000
    @@ -1 +0,0 @@
    -\
    \ No newline at end of file
    + test_eval_ret_=1
    + want_trace
    + test t = t
    + test t = t
    + set +x
    error: last command exited with $?=1
    ++ rm -rf -- actual actual.err actual.raw expect expect.err
    ++ git reset
    ++ exit 1
    ++ eval_ret=1
    ++ :
    + test_eval_ret_=0
    + want_trace
    + test t = t
    + test t = t
    + set +x
    not ok 490 - wildmatch(ls): match '00' '\'
    #
    #                                       wildtest_file_setup &&
    #                                       printf '%s' '\' >expect &&
    #                                       git --glob-pathspecs ls-files -z -- '00' >actual.raw 2>actual.err &&
    #                                       wildtest_stdout_stderr_cmp
    #

I'm digging into the failures myself now, but wanted to report the problem in the name of getting more eyes on it.

Adam
[0]: https://gist.github.com/me-and/04443bcb00e12436f0eacce079b56d02
Ævar Arnfjörð Bjarmason· Jan 3, 2018, 13:31 UTC · re: Adam Dinwoodie · lore

Re: [PATCH v2 7/7] wildmatch test: create & test files on disk in addition to in-memory

On Wed, Jan 03 2018, Adam Dinwoodie jotted:
Show 52 quoted lines
> On Monday 25 December 2017 at 12:28 am +0000, Ævar Arnfjörð Bjarmason wrote:
>> There has never been any full roundtrip testing of what git-ls-files
>> and other functions that use wildmatch() actually do, rather we've
>> been satisfied with just testing the underlying C function.
>>
>> Due to git-ls-files and friends having their own codepaths before they
>> call wildmatch() there's sometimes differences in the behavior between
>> the two, and even when we test for those (as with
>> 9e4e8a64c2 ("pathspec: die on empty strings as pathspec", 2017-06-06))
>> there was no one place where you can review how these two modes
>> differ.
>>
>> Now there is. We now attempt to create a file called $haystack and
>> match $needle against it for each pair of $needle and $haystack that
>> we were passing to test-wildmatch.
>>
>> If we can't create the file we skip the test. This ensures that we can
>> run this on all platforms and not maintain some infinitely growing
>> whitelist of e.g. platforms that don't support certain characters in
>> filenames.
>>
>> As a result of doing this we can now see the cases where these two
>> ways of testing wildmatch differ:
>>
>>  * Creating a file called 'a[]b' and running ls-files 'a[]b' will show
>>    that file, but wildmatch("a[]b", "a[]b") will not match
>>
>>  * wildmatch() won't match a file called \ against \, but ls-files
>>    will.
>>
>>  * `git --glob-pathspecs ls-files 'foo**'` will match a file
>>    'foo/bba/arr', but wildmatch won't, however pathmatch will.
>>
>>    This seems like a bug to me, the two are otherwise equivalent as
>>    these tests show.
>>
>> This also reveals the case discussed in 9e4e8a64c2 above, where '' is
>> now an error as far as ls-files is concerned, but wildmatch() itself
>> happily accepts it.
>>
>> Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
>
> I'm seeing this test script failing on the pu branch as a result of this
> commit when building on Cygwin.  Specifically, the test fails at
> 9d45e1ca4 ("Merge branch 'bw/oidmap-autoinit' into pu", 2017-12-28), and
> bisecting points the blame at 2ee0c785a ("wildmatch test: create & test
> files on disk in addition to in-memory", 2017-12-25).
>
> I've copied the verbose error output for the first error below, and
> uploaded the full output, including verbose and trace output for the
> unexpectedly failing tests, at [0].  (With 42 failures among 1512 tests,
> there's a lot of it, so I didn't want to include it in an email.)

Does the fixup above in <878tdm8k2d.fsf@evledraar.gmail.com> work for you, i.e. changing $10 in the script to ${10}?

I was waiting on Junio to see if he'd like to just squash that or if I should re-send.

Show 61 quoted lines
>     expecting success:
>                                     wildtest_file_setup &&
>                                     printf '%s' '\' >expect &&
>                                     git --glob-pathspecs ls-files -z -- '00' >actual.raw 2>actual.err &&
>                                     wildtest_stdout_stderr_cmp
>
>     ++ wildtest_file_setup
>     ++ test_when_finished '
>                     rm -rf -- * &&
>                     git reset
>             '
>     ++ test 0 = 0
>     ++ test_cleanup='{
>                     rm -rf -- * &&
>                     git reset
>
>                     } && (exit "$eval_ret"); eval_ret=$?; :'
>     ++ git add -A
>     ++ printf %s '\'
>     ++ git --glob-pathspecs ls-files -z -- 00
>     ++ wildtest_stdout_stderr_cmp
>     ++ tr -d '\0'
>     ++ test_cmp expect.err actual.err
>     ++ diff -u expect.err actual.err
>     ++ test_cmp expect actual
>     ++ diff -u expect actual
>     --- expect      2018-01-03 12:43:11.116611200 +0000
>     +++ actual      2018-01-03 12:43:11.216180400 +0000
>     @@ -1 +0,0 @@
>     -\
>     \ No newline at end of file
>     + test_eval_ret_=1
>     + want_trace
>     + test t = t
>     + test t = t
>     + set +x
>     error: last command exited with $?=1
>     ++ rm -rf -- actual actual.err actual.raw expect expect.err
>     ++ git reset
>     ++ exit 1
>     ++ eval_ret=1
>     ++ :
>     + test_eval_ret_=0
>     + want_trace
>     + test t = t
>     + test t = t
>     + set +x
>     not ok 490 - wildmatch(ls): match '00' '\'
>     #
>     #                                       wildtest_file_setup &&
>     #                                       printf '%s' '\' >expect &&
>     #                                       git --glob-pathspecs ls-files -z -- '00' >actual.raw 2>actual.err &&
>     #                                       wildtest_stdout_stderr_cmp
>     #
>
> I'm digging into the failures myself now, but wanted to report the
> problem in the name of getting more eyes on it.
>
> Adam
>
> [0]: https://gist.github.com/me-and/04443bcb00e12436f0eacce079b56d02
Adam Dinwoodie· Jan 3, 2018, 14:41 UTC · re: Ævar Arnfjörð Bjarmason · lore

Re: [PATCH v2 7/7] wildmatch test: create & test files on disk in addition to in-memory

On Wednesday 03 January 2018 at 02:31 pm +0100, Ævar Arnfjörð Bjarmason wrote:
Show 58 quoted lines
> 
> On Wed, Jan 03 2018, Adam Dinwoodie jotted:
> 
> > On Monday 25 December 2017 at 12:28 am +0000, Ævar Arnfjörð Bjarmason wrote:
> >> There has never been any full roundtrip testing of what git-ls-files
> >> and other functions that use wildmatch() actually do, rather we've
> >> been satisfied with just testing the underlying C function.
> >>
> >> Due to git-ls-files and friends having their own codepaths before they
> >> call wildmatch() there's sometimes differences in the behavior between
> >> the two, and even when we test for those (as with
> >> 9e4e8a64c2 ("pathspec: die on empty strings as pathspec", 2017-06-06))
> >> there was no one place where you can review how these two modes
> >> differ.
> >>
> >> Now there is. We now attempt to create a file called $haystack and
> >> match $needle against it for each pair of $needle and $haystack that
> >> we were passing to test-wildmatch.
> >>
> >> If we can't create the file we skip the test. This ensures that we can
> >> run this on all platforms and not maintain some infinitely growing
> >> whitelist of e.g. platforms that don't support certain characters in
> >> filenames.
> >>
> >> As a result of doing this we can now see the cases where these two
> >> ways of testing wildmatch differ:
> >>
> >>  * Creating a file called 'a[]b' and running ls-files 'a[]b' will show
> >>    that file, but wildmatch("a[]b", "a[]b") will not match
> >>
> >>  * wildmatch() won't match a file called \ against \, but ls-files
> >>    will.
> >>
> >>  * `git --glob-pathspecs ls-files 'foo**'` will match a file
> >>    'foo/bba/arr', but wildmatch won't, however pathmatch will.
> >>
> >>    This seems like a bug to me, the two are otherwise equivalent as
> >>    these tests show.
> >>
> >> This also reveals the case discussed in 9e4e8a64c2 above, where '' is
> >> now an error as far as ls-files is concerned, but wildmatch() itself
> >> happily accepts it.
> >>
> >> Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
> >
> > I'm seeing this test script failing on the pu branch as a result of this
> > commit when building on Cygwin.  Specifically, the test fails at
> > 9d45e1ca4 ("Merge branch 'bw/oidmap-autoinit' into pu", 2017-12-28), and
> > bisecting points the blame at 2ee0c785a ("wildmatch test: create & test
> > files on disk in addition to in-memory", 2017-12-25).
> >
> > I've copied the verbose error output for the first error below, and
> > uploaded the full output, including verbose and trace output for the
> > unexpectedly failing tests, at [0].  (With 42 failures among 1512 tests,
> > there's a lot of it, so I didn't want to include it in an email.)
> 
> Does the fixup above in <878tdm8k2d.fsf@evledraar.gmail.com> work for
> you, i.e. changing $10 in the script to ${10}?

This fixes some but not all of the failures: I'm now down from 42 to 24 failures.

Updated verbose test output is at https://gist.github.com/me-and/04443bcb00e12436f0eacce079b56d02

Thanks!
Adam
Ævar Arnfjörð Bjarmason· Jan 3, 2018, 19:14 UTC · re: Adam Dinwoodie · lore

Re: [PATCH v2 7/7] wildmatch test: create & test files on disk in addition to in-memory

On Wed, Jan 03 2018, Adam Dinwoodie jotted:
Show 65 quoted lines
> On Wednesday 03 January 2018 at 02:31 pm +0100, Ævar Arnfjörð Bjarmason wrote:
>>
>> On Wed, Jan 03 2018, Adam Dinwoodie jotted:
>>
>> > On Monday 25 December 2017 at 12:28 am +0000, Ævar Arnfjörð Bjarmason wrote:
>> >> There has never been any full roundtrip testing of what git-ls-files
>> >> and other functions that use wildmatch() actually do, rather we've
>> >> been satisfied with just testing the underlying C function.
>> >>
>> >> Due to git-ls-files and friends having their own codepaths before they
>> >> call wildmatch() there's sometimes differences in the behavior between
>> >> the two, and even when we test for those (as with
>> >> 9e4e8a64c2 ("pathspec: die on empty strings as pathspec", 2017-06-06))
>> >> there was no one place where you can review how these two modes
>> >> differ.
>> >>
>> >> Now there is. We now attempt to create a file called $haystack and
>> >> match $needle against it for each pair of $needle and $haystack that
>> >> we were passing to test-wildmatch.
>> >>
>> >> If we can't create the file we skip the test. This ensures that we can
>> >> run this on all platforms and not maintain some infinitely growing
>> >> whitelist of e.g. platforms that don't support certain characters in
>> >> filenames.
>> >>
>> >> As a result of doing this we can now see the cases where these two
>> >> ways of testing wildmatch differ:
>> >>
>> >>  * Creating a file called 'a[]b' and running ls-files 'a[]b' will show
>> >>    that file, but wildmatch("a[]b", "a[]b") will not match
>> >>
>> >>  * wildmatch() won't match a file called \ against \, but ls-files
>> >>    will.
>> >>
>> >>  * `git --glob-pathspecs ls-files 'foo**'` will match a file
>> >>    'foo/bba/arr', but wildmatch won't, however pathmatch will.
>> >>
>> >>    This seems like a bug to me, the two are otherwise equivalent as
>> >>    these tests show.
>> >>
>> >> This also reveals the case discussed in 9e4e8a64c2 above, where '' is
>> >> now an error as far as ls-files is concerned, but wildmatch() itself
>> >> happily accepts it.
>> >>
>> >> Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
>> >
>> > I'm seeing this test script failing on the pu branch as a result of this
>> > commit when building on Cygwin.  Specifically, the test fails at
>> > 9d45e1ca4 ("Merge branch 'bw/oidmap-autoinit' into pu", 2017-12-28), and
>> > bisecting points the blame at 2ee0c785a ("wildmatch test: create & test
>> > files on disk in addition to in-memory", 2017-12-25).
>> >
>> > I've copied the verbose error output for the first error below, and
>> > uploaded the full output, including verbose and trace output for the
>> > unexpectedly failing tests, at [0].  (With 42 failures among 1512 tests,
>> > there's a lot of it, so I didn't want to include it in an email.)
>>
>> Does the fixup above in <878tdm8k2d.fsf@evledraar.gmail.com> work for
>> you, i.e. changing $10 in the script to ${10}?
>
> This fixes some but not all of the failures: I'm now down from 42 to 24
> failures.
>
> Updated verbose test output is at
> https://gist.github.com/me-and/04443bcb00e12436f0eacce079b56d02

Thanks lot, looking through our own commit logs I believe the rest should be fixed by this (prior art in 6fd1106aa4), it would be great if you could test it, I don't have access to a Windows machine:

    diff --git a/t/t3070-wildmatch.sh b/t/t3070-wildmatch.sh
    index f985139b6f..5838fcb77d 100755
    --- a/t/t3070-wildmatch.sh
    +++ b/t/t3070-wildmatch.sh
    @@ -23,6 +23,15 @@ create_test_file() {
            *//*)
                    return 1
                    ;;
    +       # On Windows, \ in paths is silently converted to /, which
    +       # would result in the "touch" below working, but the test
    +       # itself failing.
    +       *\\*)
    +               if ! test_have_prereq BSLASHPSPEC
    +               then
    +                       return 1
    +               fi
    +               ;;
            # When testing the difference between foo/bar and foo/bar/ we
            # can't test the latter.
            */)
Adam Dinwoodie· Jan 4, 2018, 11:50 UTC · re: Ævar Arnfjörð Bjarmason · lore

Re: [PATCH v2 7/7] wildmatch test: create & test files on disk in addition to in-memory

On Wednesday 03 January 2018 at 08:14 pm +0100, Ævar Arnfjörð Bjarmason wrote:
Show 37 quoted lines
> 
> On Wed, Jan 03 2018, Adam Dinwoodie jotted:
> 
> > On Wednesday 03 January 2018 at 02:31 pm +0100, Ævar Arnfjörð Bjarmason wrote:
> >> Does the fixup above in <878tdm8k2d.fsf@evledraar.gmail.com> work for
> >> you, i.e. changing $10 in the script to ${10}?
> >
> > This fixes some but not all of the failures: I'm now down from 42 to 24
> > failures.
> >
> > Updated verbose test output is at
> > https://gist.github.com/me-and/04443bcb00e12436f0eacce079b56d02
> 
> Thanks lot, looking through our own commit logs I believe the rest
> should be fixed by this (prior art in 6fd1106aa4), it would be great if
> you could test it, I don't have access to a Windows machine:
> 
>     diff --git a/t/t3070-wildmatch.sh b/t/t3070-wildmatch.sh
>     index f985139b6f..5838fcb77d 100755
>     --- a/t/t3070-wildmatch.sh
>     +++ b/t/t3070-wildmatch.sh
>     @@ -23,6 +23,15 @@ create_test_file() {
>             *//*)
>                     return 1
>                     ;;
>     +       # On Windows, \ in paths is silently converted to /, which
>     +       # would result in the "touch" below working, but the test
>     +       # itself failing.
>     +       *\\*)
>     +               if ! test_have_prereq BSLASHPSPEC
>     +               then
>     +                       return 1
>     +               fi
>     +               ;;
>             # When testing the difference between foo/bar and foo/bar/ we
>             # can't test the latter.
>             */)
Confirmed this fixes all the outstanding test failures.  Thank you!
Ævar Arnfjörð Bjarmason· Jan 4, 2018, 19:26 UTC · re: Adam Dinwoodie · lore

[PATCH v4 0/7] increase wildmatch test coverage

This fixes errors in v3 that caused failures on bash & on Windows.
Ævar Arnfjörð Bjarmason (7):
  wildmatch test: indent with tabs, not spaces
  wildmatch test: use more standard shell style
  wildmatch test: don't try to vertically align our output
  wildmatch test: use a paranoia pattern from nul_match()
  wildmatch test: remove dead fnmatch() test code
  wildmatch test: perform all tests under all wildmatch() modes
No changes
  wildmatch test: create & test files on disk in addition to in-memory
Rephrase the commit message a bit.
Change $10 to ${10} for portability.

Skip tests that would create a file with "\" in the name on Windows (or rather, where we don't have the BSLASHPSPEC prereq).

 t/helper/test-wildmatch.c |   2 +
 t/t3070-wildmatch.sh      | 777 +++++++++++++++++++++++++++++++---------------
 2 files changed, 534 insertions(+), 245 deletions(-)
-- 
2.15.1.424.g9478a66081
Ævar Arnfjörð Bjarmason· Jan 4, 2018, 19:26 UTC · re: Ævar Arnfjörð Bjarmason · lore

[PATCH v4 1/7] wildmatch test: indent with tabs, not spaces

Replace the 4-width mixed space & tab indentation in this file with indentation with tabs as we do in most of the rest of our tests.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 t/t3070-wildmatch.sh | 54 ++++++++++++++++++++++++++--------------------------
 1 file changed, 27 insertions(+), 27 deletions(-)
Show changes to t/t3070-wildmatch.sh +27 −27
diff --git a/t/t3070-wildmatch.sh b/t/t3070-wildmatch.sh
index 163a14a1c2..27fa878f6e 100755
--- a/t/t3070-wildmatch.sh
+++ b/t/t3070-wildmatch.sh
@@ -5,39 +5,39 @@ test_description='wildmatch tests'
 . ./test-lib.sh
 
 match() {
-    if [ $1 = 1 ]; then
-	test_expect_success "wildmatch:     match '$3' '$4'" "
-	    test-wildmatch wildmatch '$3' '$4'
-	"
-    else
-	test_expect_success "wildmatch:  no match '$3' '$4'" "
-	    ! test-wildmatch wildmatch '$3' '$4'
-	"
-    fi
+	if [ $1 = 1 ]; then
+		test_expect_success "wildmatch:     match '$3' '$4'" "
+			test-wildmatch wildmatch '$3' '$4'
+		"
+	else
+		test_expect_success "wildmatch:  no match '$3' '$4'" "
+			! test-wildmatch wildmatch '$3' '$4'
+		"
+	fi
 }
 
 imatch() {
-    if [ $1 = 1 ]; then
-	test_expect_success "iwildmatch:    match '$2' '$3'" "
-	    test-wildmatch iwildmatch '$2' '$3'
-	"
-    else
-	test_expect_success "iwildmatch: no match '$2' '$3'" "
-	    ! test-wildmatch iwildmatch '$2' '$3'
-	"
-    fi
+	if [ $1 = 1 ]; then
+		test_expect_success "iwildmatch:    match '$2' '$3'" "
+			test-wildmatch iwildmatch '$2' '$3'
+		"
+	else
+		test_expect_success "iwildmatch: no match '$2' '$3'" "
+			! test-wildmatch iwildmatch '$2' '$3'
+		"
+	fi
 }
 
 pathmatch() {
-    if [ $1 = 1 ]; then
-	test_expect_success "pathmatch:     match '$2' '$3'" "
-	    test-wildmatch pathmatch '$2' '$3'
-	"
-    else
-	test_expect_success "pathmatch:  no match '$2' '$3'" "
-	    ! test-wildmatch pathmatch '$2' '$3'
-	"
-    fi
+	if [ $1 = 1 ]; then
+		test_expect_success "pathmatch:     match '$2' '$3'" "
+			test-wildmatch pathmatch '$2' '$3'
+		"
+	else
+		test_expect_success "pathmatch:  no match '$2' '$3'" "
+			! test-wildmatch pathmatch '$2' '$3'
+		"
+	fi
 }
 
 # Basic wildmat features
-- 
2.15.1.424.g9478a66081
Ævar Arnfjörð Bjarmason· Jan 4, 2018, 19:26 UTC · re: Ævar Arnfjörð Bjarmason · lore

[PATCH v4 2/7] wildmatch test: use more standard shell style

Change the wildmatch test to use more standard shell style, usually we use "if test" not "if [".

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 t/t3070-wildmatch.sh | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)
Show changes to t/t3070-wildmatch.sh +6 −3
diff --git a/t/t3070-wildmatch.sh b/t/t3070-wildmatch.sh
index 27fa878f6e..4d589d1f9a 100755
--- a/t/t3070-wildmatch.sh
+++ b/t/t3070-wildmatch.sh
@@ -5,7 +5,8 @@ test_description='wildmatch tests'
 . ./test-lib.sh
 
 match() {
-	if [ $1 = 1 ]; then
+	if test "$1" = 1
+	then
 		test_expect_success "wildmatch:     match '$3' '$4'" "
 			test-wildmatch wildmatch '$3' '$4'
 		"
@@ -17,7 +18,8 @@ match() {
 }
 
 imatch() {
-	if [ $1 = 1 ]; then
+	if test "$1" = 1
+	then
 		test_expect_success "iwildmatch:    match '$2' '$3'" "
 			test-wildmatch iwildmatch '$2' '$3'
 		"
@@ -29,7 +31,8 @@ imatch() {
 }
 
 pathmatch() {
-	if [ $1 = 1 ]; then
+	if test "$1" = 1
+	then
 		test_expect_success "pathmatch:     match '$2' '$3'" "
 			test-wildmatch pathmatch '$2' '$3'
 		"
-- 
2.15.1.424.g9478a66081
Ævar Arnfjörð Bjarmason· Jan 4, 2018, 19:26 UTC · re: Ævar Arnfjörð Bjarmason · lore

[PATCH v4 3/7] wildmatch test: don't try to vertically align our output

Don't try to vertically align the test output, which is futile anyway under the TAP output where we're going to be emitting a number for each test without aligning the test count.

This makes subsequent changes of mine where I'm not going to be aligning this output as I add new tests easier.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 t/t3070-wildmatch.sh | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)
Show changes to t/t3070-wildmatch.sh +5 −5
diff --git a/t/t3070-wildmatch.sh b/t/t3070-wildmatch.sh
index 4d589d1f9a..19ea64bba9 100755
--- a/t/t3070-wildmatch.sh
+++ b/t/t3070-wildmatch.sh
@@ -7,11 +7,11 @@ test_description='wildmatch tests'
 match() {
 	if test "$1" = 1
 	then
-		test_expect_success "wildmatch:     match '$3' '$4'" "
+		test_expect_success "wildmatch: match '$3' '$4'" "
 			test-wildmatch wildmatch '$3' '$4'
 		"
 	else
-		test_expect_success "wildmatch:  no match '$3' '$4'" "
+		test_expect_success "wildmatch: no match '$3' '$4'" "
 			! test-wildmatch wildmatch '$3' '$4'
 		"
 	fi
@@ -20,7 +20,7 @@ match() {
 imatch() {
 	if test "$1" = 1
 	then
-		test_expect_success "iwildmatch:    match '$2' '$3'" "
+		test_expect_success "iwildmatch: match '$2' '$3'" "
 			test-wildmatch iwildmatch '$2' '$3'
 		"
 	else
@@ -33,11 +33,11 @@ imatch() {
 pathmatch() {
 	if test "$1" = 1
 	then
-		test_expect_success "pathmatch:     match '$2' '$3'" "
+		test_expect_success "pathmatch: match '$2' '$3'" "
 			test-wildmatch pathmatch '$2' '$3'
 		"
 	else
-		test_expect_success "pathmatch:  no match '$2' '$3'" "
+		test_expect_success "pathmatch: no match '$2' '$3'" "
 			! test-wildmatch pathmatch '$2' '$3'
 		"
 	fi
-- 
2.15.1.424.g9478a66081
Ævar Arnfjörð Bjarmason· Jan 4, 2018, 19:26 UTC · re: Ævar Arnfjörð Bjarmason · lore

[PATCH v4 4/7] wildmatch test: use a paranoia pattern from nul_match()

Use a pattern from the nul_match() function in t7008-grep-binary.sh to make sure that we don't just fall through to the "else" if there's an unknown parameter.

This is something I added in commit 77f6f4406f ("grep: add a test helper function for less verbose -f \0 tests", 2017-05-20) to grep tests, which were modeled on these wildmatch tests, and I'm now porting back to the original wildmatch tests.

I am not using the "say '...'; exit 1" pattern from t0000-basic.sh because if I fail I want to run the rest of the tests (unless under -i), and doing this makes sure we do that and don't exit right away without fully reporting our errors.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 t/t3070-wildmatch.sh | 15 ++++++++++++---
 1 file changed, 12 insertions(+), 3 deletions(-)
Show changes to t/t3070-wildmatch.sh +12 −3
diff --git a/t/t3070-wildmatch.sh b/t/t3070-wildmatch.sh
index 19ea64bba9..9691d8eda3 100755
--- a/t/t3070-wildmatch.sh
+++ b/t/t3070-wildmatch.sh
@@ -10,10 +10,13 @@ match() {
 		test_expect_success "wildmatch: match '$3' '$4'" "
 			test-wildmatch wildmatch '$3' '$4'
 		"
-	else
+	elif test "$1" = 0
+	then
 		test_expect_success "wildmatch: no match '$3' '$4'" "
 			! test-wildmatch wildmatch '$3' '$4'
 		"
+	else
+		test_expect_success "PANIC: Test framework error. Unknown matches value $1" 'false'
 	fi
 }
 
@@ -23,10 +26,13 @@ imatch() {
 		test_expect_success "iwildmatch: match '$2' '$3'" "
 			test-wildmatch iwildmatch '$2' '$3'
 		"
-	else
+	elif test "$1" = 0
+	then
 		test_expect_success "iwildmatch: no match '$2' '$3'" "
 			! test-wildmatch iwildmatch '$2' '$3'
 		"
+	else
+		test_expect_success "PANIC: Test framework error. Unknown matches value $1" 'false'
 	fi
 }
 
@@ -36,10 +42,13 @@ pathmatch() {
 		test_expect_success "pathmatch: match '$2' '$3'" "
 			test-wildmatch pathmatch '$2' '$3'
 		"
-	else
+	elif test "$1" = 0
+	then
 		test_expect_success "pathmatch: no match '$2' '$3'" "
 			! test-wildmatch pathmatch '$2' '$3'
 		"
+	else
+		test_expect_success "PANIC: Test framework error. Unknown matches value $1" 'false'
 	fi
 }
 
-- 
2.15.1.424.g9478a66081
Ævar Arnfjörð Bjarmason· Jan 4, 2018, 19:26 UTC · re: Ævar Arnfjörð Bjarmason · lore

[PATCH v4 5/7] wildmatch test: remove dead fnmatch() test code

Remove the unused fnmatch() test parameter from the wildmatch test. The code that used to test this was removed in 70a8fc999d ("stop using fnmatch (either native or compat)", 2014-02-15).

As a --word-diff shows the only change to the body of the tests is the removal of the second out of four parameters passed to match().

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 t/t3070-wildmatch.sh | 356 +++++++++++++++++++++++++--------------------------
 1 file changed, 178 insertions(+), 178 deletions(-)
Show changes to t/t3070-wildmatch.sh +178 −178
diff --git a/t/t3070-wildmatch.sh b/t/t3070-wildmatch.sh
index 9691d8eda3..2f8a681c72 100755
--- a/t/t3070-wildmatch.sh
+++ b/t/t3070-wildmatch.sh
@@ -7,13 +7,13 @@ test_description='wildmatch tests'
 match() {
 	if test "$1" = 1
 	then
-		test_expect_success "wildmatch: match '$3' '$4'" "
-			test-wildmatch wildmatch '$3' '$4'
+		test_expect_success "wildmatch: match '$2' '$3'" "
+			test-wildmatch wildmatch '$2' '$3'
 		"
 	elif test "$1" = 0
 	then
-		test_expect_success "wildmatch: no match '$3' '$4'" "
-			! test-wildmatch wildmatch '$3' '$4'
+		test_expect_success "wildmatch: no match '$2' '$3'" "
+			! test-wildmatch wildmatch '$2' '$3'
 		"
 	else
 		test_expect_success "PANIC: Test framework error. Unknown matches value $1" 'false'
@@ -53,176 +53,176 @@ pathmatch() {
 }
 
 # Basic wildmat features
-match 1 1 foo foo
-match 0 0 foo bar
-match 1 1 '' ""
-match 1 1 foo '???'
-match 0 0 foo '??'
-match 1 1 foo '*'
-match 1 1 foo 'f*'
-match 0 0 foo '*f'
-match 1 1 foo '*foo*'
-match 1 1 foobar '*ob*a*r*'
-match 1 1 aaaaaaabababab '*ab'
-match 1 1 'foo*' 'foo\*'
-match 0 0 foobar 'foo\*bar'
-match 1 1 'f\oo' 'f\\oo'
-match 1 1 ball '*[al]?'
-match 0 0 ten '[ten]'
-match 0 1 ten '**[!te]'
-match 0 0 ten '**[!ten]'
-match 1 1 ten 't[a-g]n'
-match 0 0 ten 't[!a-g]n'
-match 1 1 ton 't[!a-g]n'
-match 1 1 ton 't[^a-g]n'
-match 1 x 'a]b' 'a[]]b'
-match 1 x a-b 'a[]-]b'
-match 1 x 'a]b' 'a[]-]b'
-match 0 x aab 'a[]-]b'
-match 1 x aab 'a[]a-]b'
-match 1 1 ']' ']'
+match 1 foo foo
+match 0 foo bar
+match 1 '' ""
+match 1 foo '???'
+match 0 foo '??'
+match 1 foo '*'
+match 1 foo 'f*'
+match 0 foo '*f'
+match 1 foo '*foo*'
+match 1 foobar '*ob*a*r*'
+match 1 aaaaaaabababab '*ab'
+match 1 'foo*' 'foo\*'
+match 0 foobar 'foo\*bar'
+match 1 'f\oo' 'f\\oo'
+match 1 ball '*[al]?'
+match 0 ten '[ten]'
+match 0 ten '**[!te]'
+match 0 ten '**[!ten]'
+match 1 ten 't[a-g]n'
+match 0 ten 't[!a-g]n'
+match 1 ton 't[!a-g]n'
+match 1 ton 't[^a-g]n'
+match 1 'a]b' 'a[]]b'
+match 1 a-b 'a[]-]b'
+match 1 'a]b' 'a[]-]b'
+match 0 aab 'a[]-]b'
+match 1 aab 'a[]a-]b'
+match 1 ']' ']'
 
 # Extended slash-matching features
-match 0 0 'foo/baz/bar' 'foo*bar'
-match 0 0 'foo/baz/bar' 'foo**bar'
-match 0 1 'foobazbar' 'foo**bar'
-match 1 1 'foo/baz/bar' 'foo/**/bar'
-match 1 0 'foo/baz/bar' 'foo/**/**/bar'
-match 1 0 'foo/b/a/z/bar' 'foo/**/bar'
-match 1 0 'foo/b/a/z/bar' 'foo/**/**/bar'
-match 1 0 'foo/bar' 'foo/**/bar'
-match 1 0 'foo/bar' 'foo/**/**/bar'
-match 0 0 'foo/bar' 'foo?bar'
-match 0 0 'foo/bar' 'foo[/]bar'
-match 0 0 'foo/bar' 'foo[^a-z]bar'
-match 0 0 'foo/bar' 'f[^eiu][^eiu][^eiu][^eiu][^eiu]r'
-match 1 1 'foo-bar' 'f[^eiu][^eiu][^eiu][^eiu][^eiu]r'
-match 1 0 'foo' '**/foo'
-match 1 x 'XXX/foo' '**/foo'
-match 1 0 'bar/baz/foo' '**/foo'
-match 0 0 'bar/baz/foo' '*/foo'
-match 0 0 'foo/bar/baz' '**/bar*'
-match 1 0 'deep/foo/bar/baz' '**/bar/*'
-match 0 0 'deep/foo/bar/baz/' '**/bar/*'
-match 1 0 'deep/foo/bar/baz/' '**/bar/**'
-match 0 0 'deep/foo/bar' '**/bar/*'
-match 1 0 'deep/foo/bar/' '**/bar/**'
-match 0 0 'foo/bar/baz' '**/bar**'
-match 1 0 'foo/bar/baz/x' '*/bar/**'
-match 0 0 'deep/foo/bar/baz/x' '*/bar/**'
-match 1 0 'deep/foo/bar/baz/x' '**/bar/*/*'
+match 0 'foo/baz/bar' 'foo*bar'
+match 0 'foo/baz/bar' 'foo**bar'
+match 0 'foobazbar' 'foo**bar'
+match 1 'foo/baz/bar' 'foo/**/bar'
+match 1 'foo/baz/bar' 'foo/**/**/bar'
+match 1 'foo/b/a/z/bar' 'foo/**/bar'
+match 1 'foo/b/a/z/bar' 'foo/**/**/bar'
+match 1 'foo/bar' 'foo/**/bar'
+match 1 'foo/bar' 'foo/**/**/bar'
+match 0 'foo/bar' 'foo?bar'
+match 0 'foo/bar' 'foo[/]bar'
+match 0 'foo/bar' 'foo[^a-z]bar'
+match 0 'foo/bar' 'f[^eiu][^eiu][^eiu][^eiu][^eiu]r'
+match 1 'foo-bar' 'f[^eiu][^eiu][^eiu][^eiu][^eiu]r'
+match 1 'foo' '**/foo'
+match 1 'XXX/foo' '**/foo'
+match 1 'bar/baz/foo' '**/foo'
+match 0 'bar/baz/foo' '*/foo'
+match 0 'foo/bar/baz' '**/bar*'
+match 1 'deep/foo/bar/baz' '**/bar/*'
+match 0 'deep/foo/bar/baz/' '**/bar/*'
+match 1 'deep/foo/bar/baz/' '**/bar/**'
+match 0 'deep/foo/bar' '**/bar/*'
+match 1 'deep/foo/bar/' '**/bar/**'
+match 0 'foo/bar/baz' '**/bar**'
+match 1 'foo/bar/baz/x' '*/bar/**'
+match 0 'deep/foo/bar/baz/x' '*/bar/**'
+match 1 'deep/foo/bar/baz/x' '**/bar/*/*'
 
 # Various additional tests
-match 0 0 'acrt' 'a[c-c]st'
-match 1 1 'acrt' 'a[c-c]rt'
-match 0 0 ']' '[!]-]'
-match 1 x 'a' '[!]-]'
-match 0 0 '' '\'
-match 0 x '\' '\'
-match 0 x 'XXX/\' '*/\'
-match 1 x 'XXX/\' '*/\\'
-match 1 1 'foo' 'foo'
-match 1 1 '@foo' '@foo'
-match 0 0 'foo' '@foo'
-match 1 1 '[ab]' '\[ab]'
-match 1 1 '[ab]' '[[]ab]'
-match 1 x '[ab]' '[[:]ab]'
-match 0 x '[ab]' '[[::]ab]'
-match 1 x '[ab]' '[[:digit]ab]'
-match 1 x '[ab]' '[\[:]ab]'
-match 1 1 '?a?b' '\??\?b'
-match 1 1 'abc' '\a\b\c'
-match 0 0 'foo' ''
-match 1 0 'foo/bar/baz/to' '**/t[o]'
+match 0 'acrt' 'a[c-c]st'
+match 1 'acrt' 'a[c-c]rt'
+match 0 ']' '[!]-]'
+match 1 'a' '[!]-]'
+match 0 '' '\'
+match 0 '\' '\'
+match 0 'XXX/\' '*/\'
+match 1 'XXX/\' '*/\\'
+match 1 'foo' 'foo'
+match 1 '@foo' '@foo'
+match 0 'foo' '@foo'
+match 1 '[ab]' '\[ab]'
+match 1 '[ab]' '[[]ab]'
+match 1 '[ab]' '[[:]ab]'
+match 0 '[ab]' '[[::]ab]'
+match 1 '[ab]' '[[:digit]ab]'
+match 1 '[ab]' '[\[:]ab]'
+match 1 '?a?b' '\??\?b'
+match 1 'abc' '\a\b\c'
+match 0 'foo' ''
+match 1 'foo/bar/baz/to' '**/t[o]'
 
 # Character class tests
-match 1 x 'a1B' '[[:alpha:]][[:digit:]][[:upper:]]'
-match 0 x 'a' '[[:digit:][:upper:][:space:]]'
-match 1 x 'A' '[[:digit:][:upper:][:space:]]'
-match 1 x '1' '[[:digit:][:upper:][:space:]]'
-match 0 x '1' '[[:digit:][:upper:][:spaci:]]'
-match 1 x ' ' '[[:digit:][:upper:][:space:]]'
-match 0 x '.' '[[:digit:][:upper:][:space:]]'
-match 1 x '.' '[[:digit:][:punct:][:space:]]'
-match 1 x '5' '[[:xdigit:]]'
-match 1 x 'f' '[[:xdigit:]]'
-match 1 x 'D' '[[:xdigit:]]'
-match 1 x '_' '[[:alnum:][:alpha:][:blank:][:cntrl:][:digit:][:graph:][:lower:][:print:][:punct:][:space:][:upper:][:xdigit:]]'
-match 1 x '.' '[^[:alnum:][:alpha:][:blank:][:cntrl:][:digit:][:lower:][:space:][:upper:][:xdigit:]]'
-match 1 x '5' '[a-c[:digit:]x-z]'
-match 1 x 'b' '[a-c[:digit:]x-z]'
-match 1 x 'y' '[a-c[:digit:]x-z]'
-match 0 x 'q' '[a-c[:digit:]x-z]'
+match 1 'a1B' '[[:alpha:]][[:digit:]][[:upper:]]'
+match 0 'a' '[[:digit:][:upper:][:space:]]'
+match 1 'A' '[[:digit:][:upper:][:space:]]'
+match 1 '1' '[[:digit:][:upper:][:space:]]'
+match 0 '1' '[[:digit:][:upper:][:spaci:]]'
+match 1 ' ' '[[:digit:][:upper:][:space:]]'
+match 0 '.' '[[:digit:][:upper:][:space:]]'
+match 1 '.' '[[:digit:][:punct:][:space:]]'
+match 1 '5' '[[:xdigit:]]'
+match 1 'f' '[[:xdigit:]]'
+match 1 'D' '[[:xdigit:]]'
+match 1 '_' '[[:alnum:][:alpha:][:blank:][:cntrl:][:digit:][:graph:][:lower:][:print:][:punct:][:space:][:upper:][:xdigit:]]'
+match 1 '.' '[^[:alnum:][:alpha:][:blank:][:cntrl:][:digit:][:lower:][:space:][:upper:][:xdigit:]]'
+match 1 '5' '[a-c[:digit:]x-z]'
+match 1 'b' '[a-c[:digit:]x-z]'
+match 1 'y' '[a-c[:digit:]x-z]'
+match 0 'q' '[a-c[:digit:]x-z]'
 
 # Additional tests, including some malformed wildmats
-match 1 x ']' '[\\-^]'
-match 0 0 '[' '[\\-^]'
-match 1 x '-' '[\-_]'
-match 1 x ']' '[\]]'
-match 0 0 '\]' '[\]]'
-match 0 0 '\' '[\]]'
-match 0 0 'ab' 'a[]b'
-match 0 x 'a[]b' 'a[]b'
-match 0 x 'ab[' 'ab['
-match 0 0 'ab' '[!'
-match 0 0 'ab' '[-'
-match 1 1 '-' '[-]'
-match 0 0 '-' '[a-'
-match 0 0 '-' '[!a-'
-match 1 x '-' '[--A]'
-match 1 x '5' '[--A]'
-match 1 1 ' ' '[ --]'
-match 1 1 '$' '[ --]'
-match 1 1 '-' '[ --]'
-match 0 0 '0' '[ --]'
-match 1 x '-' '[---]'
-match 1 x '-' '[------]'
-match 0 0 'j' '[a-e-n]'
-match 1 x '-' '[a-e-n]'
-match 1 x 'a' '[!------]'
-match 0 0 '[' '[]-a]'
-match 1 x '^' '[]-a]'
-match 0 0 '^' '[!]-a]'
-match 1 x '[' '[!]-a]'
-match 1 1 '^' '[a^bc]'
-match 1 x '-b]' '[a-]b]'
-match 0 0 '\' '[\]'
-match 1 1 '\' '[\\]'
-match 0 0 '\' '[!\\]'
-match 1 1 'G' '[A-\\]'
-match 0 0 'aaabbb' 'b*a'
-match 0 0 'aabcaa' '*ba*'
-match 1 1 ',' '[,]'
-match 1 1 ',' '[\\,]'
-match 1 1 '\' '[\\,]'
-match 1 1 '-' '[,-.]'
-match 0 0 '+' '[,-.]'
-match 0 0 '-.]' '[,-.]'
-match 1 1 '2' '[\1-\3]'
-match 1 1 '3' '[\1-\3]'
-match 0 0 '4' '[\1-\3]'
-match 1 1 '\' '[[-\]]'
-match 1 1 '[' '[[-\]]'
-match 1 1 ']' '[[-\]]'
-match 0 0 '-' '[[-\]]'
+match 1 ']' '[\\-^]'
+match 0 '[' '[\\-^]'
+match 1 '-' '[\-_]'
+match 1 ']' '[\]]'
+match 0 '\]' '[\]]'
+match 0 '\' '[\]]'
+match 0 'ab' 'a[]b'
+match 0 'a[]b' 'a[]b'
+match 0 'ab[' 'ab['
+match 0 'ab' '[!'
+match 0 'ab' '[-'
+match 1 '-' '[-]'
+match 0 '-' '[a-'
+match 0 '-' '[!a-'
+match 1 '-' '[--A]'
+match 1 '5' '[--A]'
+match 1 ' ' '[ --]'
+match 1 '$' '[ --]'
+match 1 '-' '[ --]'
+match 0 '0' '[ --]'
+match 1 '-' '[---]'
+match 1 '-' '[------]'
+match 0 'j' '[a-e-n]'
+match 1 '-' '[a-e-n]'
+match 1 'a' '[!------]'
+match 0 '[' '[]-a]'
+match 1 '^' '[]-a]'
+match 0 '^' '[!]-a]'
+match 1 '[' '[!]-a]'
+match 1 '^' '[a^bc]'
+match 1 '-b]' '[a-]b]'
+match 0 '\' '[\]'
+match 1 '\' '[\\]'
+match 0 '\' '[!\\]'
+match 1 'G' '[A-\\]'
+match 0 'aaabbb' 'b*a'
+match 0 'aabcaa' '*ba*'
+match 1 ',' '[,]'
+match 1 ',' '[\\,]'
+match 1 '\' '[\\,]'
+match 1 '-' '[,-.]'
+match 0 '+' '[,-.]'
+match 0 '-.]' '[,-.]'
+match 1 '2' '[\1-\3]'
+match 1 '3' '[\1-\3]'
+match 0 '4' '[\1-\3]'
+match 1 '\' '[[-\]]'
+match 1 '[' '[[-\]]'
+match 1 ']' '[[-\]]'
+match 0 '-' '[[-\]]'
 
 # Test recursion and the abort code (use "wildtest -i" to see iteration counts)
-match 1 1 '-adobe-courier-bold-o-normal--12-120-75-75-m-70-iso8859-1' '-*-*-*-*-*-*-12-*-*-*-m-*-*-*'
-match 0 0 '-adobe-courier-bold-o-normal--12-120-75-75-X-70-iso8859-1' '-*-*-*-*-*-*-12-*-*-*-m-*-*-*'
-match 0 0 '-adobe-courier-bold-o-normal--12-120-75-75-/-70-iso8859-1' '-*-*-*-*-*-*-12-*-*-*-m-*-*-*'
-match 1 1 'XXX/adobe/courier/bold/o/normal//12/120/75/75/m/70/iso8859/1' 'XXX/*/*/*/*/*/*/12/*/*/*/m/*/*/*'
-match 0 0 'XXX/adobe/courier/bold/o/normal//12/120/75/75/X/70/iso8859/1' 'XXX/*/*/*/*/*/*/12/*/*/*/m/*/*/*'
-match 1 0 'abcd/abcdefg/abcdefghijk/abcdefghijklmnop.txt' '**/*a*b*g*n*t'
-match 0 0 'abcd/abcdefg/abcdefghijk/abcdefghijklmnop.txtz' '**/*a*b*g*n*t'
-match 0 x foo '*/*/*'
-match 0 x foo/bar '*/*/*'
-match 1 x foo/bba/arr '*/*/*'
-match 0 x foo/bb/aa/rr '*/*/*'
-match 1 x foo/bb/aa/rr '**/**/**'
-match 1 x abcXdefXghi '*X*i'
-match 0 x ab/cXd/efXg/hi '*X*i'
-match 1 x ab/cXd/efXg/hi '*/*X*/*/*i'
-match 1 x ab/cXd/efXg/hi '**/*X*/**/*i'
+match 1 '-adobe-courier-bold-o-normal--12-120-75-75-m-70-iso8859-1' '-*-*-*-*-*-*-12-*-*-*-m-*-*-*'
+match 0 '-adobe-courier-bold-o-normal--12-120-75-75-X-70-iso8859-1' '-*-*-*-*-*-*-12-*-*-*-m-*-*-*'
+match 0 '-adobe-courier-bold-o-normal--12-120-75-75-/-70-iso8859-1' '-*-*-*-*-*-*-12-*-*-*-m-*-*-*'
+match 1 'XXX/adobe/courier/bold/o/normal//12/120/75/75/m/70/iso8859/1' 'XXX/*/*/*/*/*/*/12/*/*/*/m/*/*/*'
+match 0 'XXX/adobe/courier/bold/o/normal//12/120/75/75/X/70/iso8859/1' 'XXX/*/*/*/*/*/*/12/*/*/*/m/*/*/*'
+match 1 'abcd/abcdefg/abcdefghijk/abcdefghijklmnop.txt' '**/*a*b*g*n*t'
+match 0 'abcd/abcdefg/abcdefghijk/abcdefghijklmnop.txtz' '**/*a*b*g*n*t'
+match 0 foo '*/*/*'
+match 0 foo/bar '*/*/*'
+match 1 foo/bba/arr '*/*/*'
+match 0 foo/bb/aa/rr '*/*/*'
+match 1 foo/bb/aa/rr '**/**/**'
+match 1 abcXdefXghi '*X*i'
+match 0 ab/cXd/efXg/hi '*X*i'
+match 1 ab/cXd/efXg/hi '*/*X*/*/*i'
+match 1 ab/cXd/efXg/hi '**/*X*/**/*i'
 
 pathmatch 1 foo foo
 pathmatch 0 foo fo
@@ -248,20 +248,20 @@ pathmatch 1 ab/cXd/efXg/hi '*/*X*/*/*i'
 pathmatch 1 ab/cXd/efXg/hi '*Xg*i'
 
 # Case-sensitivity features
-match 0 x 'a' '[A-Z]'
-match 1 x 'A' '[A-Z]'
-match 0 x 'A' '[a-z]'
-match 1 x 'a' '[a-z]'
-match 0 x 'a' '[[:upper:]]'
-match 1 x 'A' '[[:upper:]]'
-match 0 x 'A' '[[:lower:]]'
-match 1 x 'a' '[[:lower:]]'
-match 0 x 'A' '[B-Za]'
-match 1 x 'a' '[B-Za]'
-match 0 x 'A' '[B-a]'
-match 1 x 'a' '[B-a]'
-match 0 x 'z' '[Z-y]'
-match 1 x 'Z' '[Z-y]'
+match 0 'a' '[A-Z]'
+match 1 'A' '[A-Z]'
+match 0 'A' '[a-z]'
+match 1 'a' '[a-z]'
+match 0 'a' '[[:upper:]]'
+match 1 'A' '[[:upper:]]'
+match 0 'A' '[[:lower:]]'
+match 1 'a' '[[:lower:]]'
+match 0 'A' '[B-Za]'
+match 1 'a' '[B-Za]'
+match 0 'A' '[B-a]'
+match 1 'a' '[B-a]'
+match 0 'z' '[Z-y]'
+match 1 'Z' '[Z-y]'
 
 imatch 1 'a' '[A-Z]'
 imatch 1 'A' '[A-Z]'
-- 
2.15.1.424.g9478a66081
Ævar Arnfjörð Bjarmason· Jan 4, 2018, 19:26 UTC · re: Ævar Arnfjörð Bjarmason · lore

[PATCH v4 6/7] wildmatch test: perform all tests under all wildmatch() modes

Rewrite the wildmatch() test suite so that each test now tests all combinations of the wildmatch() WM_CASEFOLD and WM_PATHNAME flags.

Before this change some test inputs were not tested on e.g. WM_PATHNAME. Now the function is stress tested on all possible inputs, and for each input we declare what the result should be if the mode is case-insensitive, or pathname matching, or case-sensitive or not matching pathnames.

Also before this change, nothing was testing case-insensitive non-pathname matching, so I've added that to test-wildmatch.c and made use of it.

This yields a rather scary patch, but there are no functional changes here, just more test coverage. Some now-redundant tests were deleted as a result of this change, since they were now duplicating an earlier test.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 t/helper/test-wildmatch.c |   2 +
 t/t3070-wildmatch.sh      | 478 +++++++++++++++++++++++-----------------------
 2 files changed, 239 insertions(+), 241 deletions(-)
Show changes to 2 files +239 −241

t/helper/test-wildmatch.c, t/t3070-wildmatch.sh

diff --git a/t/helper/test-wildmatch.c b/t/helper/test-wildmatch.c
index 921d7b3e7e..66d33dfcfd 100644
--- a/t/helper/test-wildmatch.c
+++ b/t/helper/test-wildmatch.c
@@ -16,6 +16,8 @@ int cmd_main(int argc, const char **argv)
 		return !!wildmatch(argv[3], argv[2], WM_PATHNAME | WM_CASEFOLD);
 	else if (!strcmp(argv[1], "pathmatch"))
 		return !!wildmatch(argv[3], argv[2], 0);
+	else if (!strcmp(argv[1], "ipathmatch"))
+		return !!wildmatch(argv[3], argv[2], WM_CASEFOLD);
 	else
 		return 1;
 }
diff --git a/t/t3070-wildmatch.sh b/t/t3070-wildmatch.sh
index 2f8a681c72..06db053ae2 100755
--- a/t/t3070-wildmatch.sh
+++ b/t/t3070-wildmatch.sh
@@ -4,278 +4,274 @@ test_description='wildmatch tests'
 
 . ./test-lib.sh
 
-match() {
-	if test "$1" = 1
+wildtest() {
+	match_w_glob=$1
+	match_w_globi=$2
+	match_w_pathmatch=$3
+	match_w_pathmatchi=$4
+	text=$5
+	pattern=$6
+
+	if test "$match_w_glob" = 1
 	then
-		test_expect_success "wildmatch: match '$2' '$3'" "
-			test-wildmatch wildmatch '$2' '$3'
+		test_expect_success "wildmatch: match '$text' '$pattern'" "
+			test-wildmatch wildmatch '$text' '$pattern'
 		"
-	elif test "$1" = 0
+	elif test "$match_w_glob" = 0
 	then
-		test_expect_success "wildmatch: no match '$2' '$3'" "
-			! test-wildmatch wildmatch '$2' '$3'
+		test_expect_success "wildmatch: no match '$text' '$pattern'" "
+			! test-wildmatch wildmatch '$text' '$pattern'
 		"
 	else
-		test_expect_success "PANIC: Test framework error. Unknown matches value $1" 'false'
+		test_expect_success "PANIC: Test framework error. Unknown matches value $match_w_glob" 'false'
 	fi
-}
 
-imatch() {
-	if test "$1" = 1
+	if test "$match_w_globi" = 1
 	then
-		test_expect_success "iwildmatch: match '$2' '$3'" "
-			test-wildmatch iwildmatch '$2' '$3'
+		test_expect_success "iwildmatch: match '$text' '$pattern'" "
+			test-wildmatch iwildmatch '$text' '$pattern'
 		"
-	elif test "$1" = 0
+	elif test "$match_w_globi" = 0
 	then
-		test_expect_success "iwildmatch: no match '$2' '$3'" "
-			! test-wildmatch iwildmatch '$2' '$3'
+		test_expect_success "iwildmatch: no match '$text' '$pattern'" "
+			! test-wildmatch iwildmatch '$text' '$pattern'
 		"
 	else
-		test_expect_success "PANIC: Test framework error. Unknown matches value $1" 'false'
+		test_expect_success "PANIC: Test framework error. Unknown matches value $match_w_globi" 'false'
 	fi
-}
 
-pathmatch() {
-	if test "$1" = 1
+	if test "$match_w_pathmatch" = 1
 	then
-		test_expect_success "pathmatch: match '$2' '$3'" "
-			test-wildmatch pathmatch '$2' '$3'
+		test_expect_success "pathmatch: match '$text' '$pattern'" "
+			test-wildmatch pathmatch '$text' '$pattern'
 		"
-	elif test "$1" = 0
+	elif test "$match_w_pathmatch" = 0
 	then
-		test_expect_success "pathmatch: no match '$2' '$3'" "
-			! test-wildmatch pathmatch '$2' '$3'
+		test_expect_success "pathmatch: no match '$text' '$pattern'" "
+			! test-wildmatch pathmatch '$text' '$pattern'
 		"
 	else
-		test_expect_success "PANIC: Test framework error. Unknown matches value $1" 'false'
+		test_expect_success "PANIC: Test framework error. Unknown matches value $match_w_pathmatch" 'false'
+	fi
+
+	if test "$match_w_pathmatchi" = 1
+	then
+		test_expect_success "ipathmatch: match '$text' '$pattern'" "
+			test-wildmatch ipathmatch '$text' '$pattern'
+		"
+	elif test "$match_w_pathmatchi" = 0
+	then
+		test_expect_success "ipathmatch: no match '$text' '$pattern'" "
+			! test-wildmatch ipathmatch '$text' '$pattern'
+		"
+	else
+		test_expect_success "PANIC: Test framework error. Unknown matches value $match_w_pathmatchi" 'false'
 	fi
 }
 
-# Basic wildmat features
-match 1 foo foo
-match 0 foo bar
-match 1 '' ""
-match 1 foo '???'
-match 0 foo '??'
-match 1 foo '*'
-match 1 foo 'f*'
-match 0 foo '*f'
-match 1 foo '*foo*'
-match 1 foobar '*ob*a*r*'
-match 1 aaaaaaabababab '*ab'
-match 1 'foo*' 'foo\*'
-match 0 foobar 'foo\*bar'
-match 1 'f\oo' 'f\\oo'
-match 1 ball '*[al]?'
-match 0 ten '[ten]'
-match 0 ten '**[!te]'
-match 0 ten '**[!ten]'
-match 1 ten 't[a-g]n'
-match 0 ten 't[!a-g]n'
-match 1 ton 't[!a-g]n'
-match 1 ton 't[^a-g]n'
-match 1 'a]b' 'a[]]b'
-match 1 a-b 'a[]-]b'
-match 1 'a]b' 'a[]-]b'
-match 0 aab 'a[]-]b'
-match 1 aab 'a[]a-]b'
-match 1 ']' ']'
+# Basic wildmatch features
+wildtest 1 1 1 1 foo foo
+wildtest 0 0 0 0 foo bar
+wildtest 1 1 1 1 '' ""
+wildtest 1 1 1 1 foo '???'
+wildtest 0 0 0 0 foo '??'
+wildtest 1 1 1 1 foo '*'
+wildtest 1 1 1 1 foo 'f*'
+wildtest 0 0 0 0 foo '*f'
+wildtest 1 1 1 1 foo '*foo*'
+wildtest 1 1 1 1 foobar '*ob*a*r*'
+wildtest 1 1 1 1 aaaaaaabababab '*ab'
+wildtest 1 1 1 1 'foo*' 'foo\*'
+wildtest 0 0 0 0 foobar 'foo\*bar'
+wildtest 1 1 1 1 'f\oo' 'f\\oo'
+wildtest 1 1 1 1 ball '*[al]?'
+wildtest 0 0 0 0 ten '[ten]'
+wildtest 0 0 1 1 ten '**[!te]'
+wildtest 0 0 0 0 ten '**[!ten]'
+wildtest 1 1 1 1 ten 't[a-g]n'
+wildtest 0 0 0 0 ten 't[!a-g]n'
+wildtest 1 1 1 1 ton 't[!a-g]n'
+wildtest 1 1 1 1 ton 't[^a-g]n'
+wildtest 1 1 1 1 'a]b' 'a[]]b'
+wildtest 1 1 1 1 a-b 'a[]-]b'
+wildtest 1 1 1 1 'a]b' 'a[]-]b'
+wildtest 0 0 0 0 aab 'a[]-]b'
+wildtest 1 1 1 1 aab 'a[]a-]b'
+wildtest 1 1 1 1 ']' ']'
 
 # Extended slash-matching features
-match 0 'foo/baz/bar' 'foo*bar'
-match 0 'foo/baz/bar' 'foo**bar'
-match 0 'foobazbar' 'foo**bar'
-match 1 'foo/baz/bar' 'foo/**/bar'
-match 1 'foo/baz/bar' 'foo/**/**/bar'
-match 1 'foo/b/a/z/bar' 'foo/**/bar'
-match 1 'foo/b/a/z/bar' 'foo/**/**/bar'
-match 1 'foo/bar' 'foo/**/bar'
-match 1 'foo/bar' 'foo/**/**/bar'
-match 0 'foo/bar' 'foo?bar'
-match 0 'foo/bar' 'foo[/]bar'
-match 0 'foo/bar' 'foo[^a-z]bar'
-match 0 'foo/bar' 'f[^eiu][^eiu][^eiu][^eiu][^eiu]r'
-match 1 'foo-bar' 'f[^eiu][^eiu][^eiu][^eiu][^eiu]r'
-match 1 'foo' '**/foo'
-match 1 'XXX/foo' '**/foo'
-match 1 'bar/baz/foo' '**/foo'
-match 0 'bar/baz/foo' '*/foo'
-match 0 'foo/bar/baz' '**/bar*'
-match 1 'deep/foo/bar/baz' '**/bar/*'
-match 0 'deep/foo/bar/baz/' '**/bar/*'
-match 1 'deep/foo/bar/baz/' '**/bar/**'
-match 0 'deep/foo/bar' '**/bar/*'
-match 1 'deep/foo/bar/' '**/bar/**'
-match 0 'foo/bar/baz' '**/bar**'
-match 1 'foo/bar/baz/x' '*/bar/**'
-match 0 'deep/foo/bar/baz/x' '*/bar/**'
-match 1 'deep/foo/bar/baz/x' '**/bar/*/*'
+wildtest 0 0 1 1 'foo/baz/bar' 'foo*bar'
+wildtest 0 0 1 1 'foo/baz/bar' 'foo**bar'
+wildtest 0 0 1 1 'foobazbar' 'foo**bar'
+wildtest 1 1 1 1 'foo/baz/bar' 'foo/**/bar'
+wildtest 1 1 0 0 'foo/baz/bar' 'foo/**/**/bar'
+wildtest 1 1 1 1 'foo/b/a/z/bar' 'foo/**/bar'
+wildtest 1 1 1 1 'foo/b/a/z/bar' 'foo/**/**/bar'
+wildtest 1 1 0 0 'foo/bar' 'foo/**/bar'
+wildtest 1 1 0 0 'foo/bar' 'foo/**/**/bar'
+wildtest 0 0 1 1 'foo/bar' 'foo?bar'
+wildtest 0 0 1 1 'foo/bar' 'foo[/]bar'
+wildtest 0 0 1 1 'foo/bar' 'foo[^a-z]bar'
+wildtest 0 0 1 1 'foo/bar' 'f[^eiu][^eiu][^eiu][^eiu][^eiu]r'
+wildtest 1 1 1 1 'foo-bar' 'f[^eiu][^eiu][^eiu][^eiu][^eiu]r'
+wildtest 1 1 0 0 'foo' '**/foo'
+wildtest 1 1 1 1 'XXX/foo' '**/foo'
+wildtest 1 1 1 1 'bar/baz/foo' '**/foo'
+wildtest 0 0 1 1 'bar/baz/foo' '*/foo'
+wildtest 0 0 1 1 'foo/bar/baz' '**/bar*'
+wildtest 1 1 1 1 'deep/foo/bar/baz' '**/bar/*'
+wildtest 0 0 1 1 'deep/foo/bar/baz/' '**/bar/*'
+wildtest 1 1 1 1 'deep/foo/bar/baz/' '**/bar/**'
+wildtest 0 0 0 0 'deep/foo/bar' '**/bar/*'
+wildtest 1 1 1 1 'deep/foo/bar/' '**/bar/**'
+wildtest 0 0 1 1 'foo/bar/baz' '**/bar**'
+wildtest 1 1 1 1 'foo/bar/baz/x' '*/bar/**'
+wildtest 0 0 1 1 'deep/foo/bar/baz/x' '*/bar/**'
+wildtest 1 1 1 1 'deep/foo/bar/baz/x' '**/bar/*/*'
 
 # Various additional tests
-match 0 'acrt' 'a[c-c]st'
-match 1 'acrt' 'a[c-c]rt'
-match 0 ']' '[!]-]'
-match 1 'a' '[!]-]'
-match 0 '' '\'
-match 0 '\' '\'
-match 0 'XXX/\' '*/\'
-match 1 'XXX/\' '*/\\'
-match 1 'foo' 'foo'
-match 1 '@foo' '@foo'
-match 0 'foo' '@foo'
-match 1 '[ab]' '\[ab]'
-match 1 '[ab]' '[[]ab]'
-match 1 '[ab]' '[[:]ab]'
-match 0 '[ab]' '[[::]ab]'
-match 1 '[ab]' '[[:digit]ab]'
-match 1 '[ab]' '[\[:]ab]'
-match 1 '?a?b' '\??\?b'
-match 1 'abc' '\a\b\c'
-match 0 'foo' ''
-match 1 'foo/bar/baz/to' '**/t[o]'
+wildtest 0 0 0 0 'acrt' 'a[c-c]st'
+wildtest 1 1 1 1 'acrt' 'a[c-c]rt'
+wildtest 0 0 0 0 ']' '[!]-]'
+wildtest 1 1 1 1 'a' '[!]-]'
+wildtest 0 0 0 0 '' '\'
+wildtest 0 0 0 0 '\' '\'
+wildtest 0 0 0 0 'XXX/\' '*/\'
+wildtest 1 1 1 1 'XXX/\' '*/\\'
+wildtest 1 1 1 1 'foo' 'foo'
+wildtest 1 1 1 1 '@foo' '@foo'
+wildtest 0 0 0 0 'foo' '@foo'
+wildtest 1 1 1 1 '[ab]' '\[ab]'
+wildtest 1 1 1 1 '[ab]' '[[]ab]'
+wildtest 1 1 1 1 '[ab]' '[[:]ab]'
+wildtest 0 0 0 0 '[ab]' '[[::]ab]'
+wildtest 1 1 1 1 '[ab]' '[[:digit]ab]'
+wildtest 1 1 1 1 '[ab]' '[\[:]ab]'
+wildtest 1 1 1 1 '?a?b' '\??\?b'
+wildtest 1 1 1 1 'abc' '\a\b\c'
+wildtest 0 0 0 0 'foo' ''
+wildtest 1 1 1 1 'foo/bar/baz/to' '**/t[o]'
 
 # Character class tests
-match 1 'a1B' '[[:alpha:]][[:digit:]][[:upper:]]'
-match 0 'a' '[[:digit:][:upper:][:space:]]'
-match 1 'A' '[[:digit:][:upper:][:space:]]'
-match 1 '1' '[[:digit:][:upper:][:space:]]'
-match 0 '1' '[[:digit:][:upper:][:spaci:]]'
-match 1 ' ' '[[:digit:][:upper:][:space:]]'
-match 0 '.' '[[:digit:][:upper:][:space:]]'
-match 1 '.' '[[:digit:][:punct:][:space:]]'
-match 1 '5' '[[:xdigit:]]'
-match 1 'f' '[[:xdigit:]]'
-match 1 'D' '[[:xdigit:]]'
-match 1 '_' '[[:alnum:][:alpha:][:blank:][:cntrl:][:digit:][:graph:][:lower:][:print:][:punct:][:space:][:upper:][:xdigit:]]'
-match 1 '.' '[^[:alnum:][:alpha:][:blank:][:cntrl:][:digit:][:lower:][:space:][:upper:][:xdigit:]]'
-match 1 '5' '[a-c[:digit:]x-z]'
-match 1 'b' '[a-c[:digit:]x-z]'
-match 1 'y' '[a-c[:digit:]x-z]'
-match 0 'q' '[a-c[:digit:]x-z]'
-
-# Additional tests, including some malformed wildmats
-match 1 ']' '[\\-^]'
-match 0 '[' '[\\-^]'
-match 1 '-' '[\-_]'
-match 1 ']' '[\]]'
-match 0 '\]' '[\]]'
-match 0 '\' '[\]]'
-match 0 'ab' 'a[]b'
-match 0 'a[]b' 'a[]b'
-match 0 'ab[' 'ab['
-match 0 'ab' '[!'
-match 0 'ab' '[-'
-match 1 '-' '[-]'
-match 0 '-' '[a-'
-match 0 '-' '[!a-'
-match 1 '-' '[--A]'
-match 1 '5' '[--A]'
-match 1 ' ' '[ --]'
-match 1 '$' '[ --]'
-match 1 '-' '[ --]'
-match 0 '0' '[ --]'
-match 1 '-' '[---]'
-match 1 '-' '[------]'
-match 0 'j' '[a-e-n]'
-match 1 '-' '[a-e-n]'
-match 1 'a' '[!------]'
-match 0 '[' '[]-a]'
-match 1 '^' '[]-a]'
-match 0 '^' '[!]-a]'
-match 1 '[' '[!]-a]'
-match 1 '^' '[a^bc]'
-match 1 '-b]' '[a-]b]'
-match 0 '\' '[\]'
-match 1 '\' '[\\]'
-match 0 '\' '[!\\]'
-match 1 'G' '[A-\\]'
-match 0 'aaabbb' 'b*a'
-match 0 'aabcaa' '*ba*'
-match 1 ',' '[,]'
-match 1 ',' '[\\,]'
-match 1 '\' '[\\,]'
-match 1 '-' '[,-.]'
-match 0 '+' '[,-.]'
-match 0 '-.]' '[,-.]'
-match 1 '2' '[\1-\3]'
-match 1 '3' '[\1-\3]'
-match 0 '4' '[\1-\3]'
-match 1 '\' '[[-\]]'
-match 1 '[' '[[-\]]'
-match 1 ']' '[[-\]]'
-match 0 '-' '[[-\]]'
+wildtest 1 1 1 1 'a1B' '[[:alpha:]][[:digit:]][[:upper:]]'
+wildtest 0 1 0 1 'a' '[[:digit:][:upper:][:space:]]'
+wildtest 1 1 1 1 'A' '[[:digit:][:upper:][:space:]]'
+wildtest 1 1 1 1 '1' '[[:digit:][:upper:][:space:]]'
+wildtest 0 0 0 0 '1' '[[:digit:][:upper:][:spaci:]]'
+wildtest 1 1 1 1 ' ' '[[:digit:][:upper:][:space:]]'
+wildtest 0 0 0 0 '.' '[[:digit:][:upper:][:space:]]'
+wildtest 1 1 1 1 '.' '[[:digit:][:punct:][:space:]]'
+wildtest 1 1 1 1 '5' '[[:xdigit:]]'
+wildtest 1 1 1 1 'f' '[[:xdigit:]]'
+wildtest 1 1 1 1 'D' '[[:xdigit:]]'
+wildtest 1 1 1 1 '_' '[[:alnum:][:alpha:][:blank:][:cntrl:][:digit:][:graph:][:lower:][:print:][:punct:][:space:][:upper:][:xdigit:]]'
+wildtest 1 1 1 1 '.' '[^[:alnum:][:alpha:][:blank:][:cntrl:][:digit:][:lower:][:space:][:upper:][:xdigit:]]'
+wildtest 1 1 1 1 '5' '[a-c[:digit:]x-z]'
+wildtest 1 1 1 1 'b' '[a-c[:digit:]x-z]'
+wildtest 1 1 1 1 'y' '[a-c[:digit:]x-z]'
+wildtest 0 0 0 0 'q' '[a-c[:digit:]x-z]'
 
-# Test recursion and the abort code (use "wildtest -i" to see iteration counts)
-match 1 '-adobe-courier-bold-o-normal--12-120-75-75-m-70-iso8859-1' '-*-*-*-*-*-*-12-*-*-*-m-*-*-*'
-match 0 '-adobe-courier-bold-o-normal--12-120-75-75-X-70-iso8859-1' '-*-*-*-*-*-*-12-*-*-*-m-*-*-*'
-match 0 '-adobe-courier-bold-o-normal--12-120-75-75-/-70-iso8859-1' '-*-*-*-*-*-*-12-*-*-*-m-*-*-*'
-match 1 'XXX/adobe/courier/bold/o/normal//12/120/75/75/m/70/iso8859/1' 'XXX/*/*/*/*/*/*/12/*/*/*/m/*/*/*'
-match 0 'XXX/adobe/courier/bold/o/normal//12/120/75/75/X/70/iso8859/1' 'XXX/*/*/*/*/*/*/12/*/*/*/m/*/*/*'
-match 1 'abcd/abcdefg/abcdefghijk/abcdefghijklmnop.txt' '**/*a*b*g*n*t'
-match 0 'abcd/abcdefg/abcdefghijk/abcdefghijklmnop.txtz' '**/*a*b*g*n*t'
-match 0 foo '*/*/*'
-match 0 foo/bar '*/*/*'
-match 1 foo/bba/arr '*/*/*'
-match 0 foo/bb/aa/rr '*/*/*'
-match 1 foo/bb/aa/rr '**/**/**'
-match 1 abcXdefXghi '*X*i'
-match 0 ab/cXd/efXg/hi '*X*i'
-match 1 ab/cXd/efXg/hi '*/*X*/*/*i'
-match 1 ab/cXd/efXg/hi '**/*X*/**/*i'
+# Additional tests, including some malformed wildmatch patterns
+wildtest 1 1 1 1 ']' '[\\-^]'
+wildtest 0 0 0 0 '[' '[\\-^]'
+wildtest 1 1 1 1 '-' '[\-_]'
+wildtest 1 1 1 1 ']' '[\]]'
+wildtest 0 0 0 0 '\]' '[\]]'
+wildtest 0 0 0 0 '\' '[\]]'
+wildtest 0 0 0 0 'ab' 'a[]b'
+wildtest 0 0 0 0 'a[]b' 'a[]b'
+wildtest 0 0 0 0 'ab[' 'ab['
+wildtest 0 0 0 0 'ab' '[!'
+wildtest 0 0 0 0 'ab' '[-'
+wildtest 1 1 1 1 '-' '[-]'
+wildtest 0 0 0 0 '-' '[a-'
+wildtest 0 0 0 0 '-' '[!a-'
+wildtest 1 1 1 1 '-' '[--A]'
+wildtest 1 1 1 1 '5' '[--A]'
+wildtest 1 1 1 1 ' ' '[ --]'
+wildtest 1 1 1 1 '$' '[ --]'
+wildtest 1 1 1 1 '-' '[ --]'
+wildtest 0 0 0 0 '0' '[ --]'
+wildtest 1 1 1 1 '-' '[---]'
+wildtest 1 1 1 1 '-' '[------]'
+wildtest 0 0 0 0 'j' '[a-e-n]'
+wildtest 1 1 1 1 '-' '[a-e-n]'
+wildtest 1 1 1 1 'a' '[!------]'
+wildtest 0 0 0 0 '[' '[]-a]'
+wildtest 1 1 1 1 '^' '[]-a]'
+wildtest 0 0 0 0 '^' '[!]-a]'
+wildtest 1 1 1 1 '[' '[!]-a]'
+wildtest 1 1 1 1 '^' '[a^bc]'
+wildtest 1 1 1 1 '-b]' '[a-]b]'
+wildtest 0 0 0 0 '\' '[\]'
+wildtest 1 1 1 1 '\' '[\\]'
+wildtest 0 0 0 0 '\' '[!\\]'
+wildtest 1 1 1 1 'G' '[A-\\]'
+wildtest 0 0 0 0 'aaabbb' 'b*a'
+wildtest 0 0 0 0 'aabcaa' '*ba*'
+wildtest 1 1 1 1 ',' '[,]'
+wildtest 1 1 1 1 ',' '[\\,]'
+wildtest 1 1 1 1 '\' '[\\,]'
+wildtest 1 1 1 1 '-' '[,-.]'
+wildtest 0 0 0 0 '+' '[,-.]'
+wildtest 0 0 0 0 '-.]' '[,-.]'
+wildtest 1 1 1 1 '2' '[\1-\3]'
+wildtest 1 1 1 1 '3' '[\1-\3]'
+wildtest 0 0 0 0 '4' '[\1-\3]'
+wildtest 1 1 1 1 '\' '[[-\]]'
+wildtest 1 1 1 1 '[' '[[-\]]'
+wildtest 1 1 1 1 ']' '[[-\]]'
+wildtest 0 0 0 0 '-' '[[-\]]'
 
-pathmatch 1 foo foo
-pathmatch 0 foo fo
-pathmatch 1 foo/bar foo/bar
-pathmatch 1 foo/bar 'foo/*'
-pathmatch 1 foo/bba/arr 'foo/*'
-pathmatch 1 foo/bba/arr 'foo/**'
-pathmatch 1 foo/bba/arr 'foo*'
-pathmatch 1 foo/bba/arr 'foo**'
-pathmatch 1 foo/bba/arr 'foo/*arr'
-pathmatch 1 foo/bba/arr 'foo/**arr'
-pathmatch 0 foo/bba/arr 'foo/*z'
-pathmatch 0 foo/bba/arr 'foo/**z'
-pathmatch 1 foo/bar 'foo?bar'
-pathmatch 1 foo/bar 'foo[/]bar'
-pathmatch 1 foo/bar 'foo[^a-z]bar'
-pathmatch 0 foo '*/*/*'
-pathmatch 0 foo/bar '*/*/*'
-pathmatch 1 foo/bba/arr '*/*/*'
-pathmatch 1 foo/bb/aa/rr '*/*/*'
-pathmatch 1 abcXdefXghi '*X*i'
-pathmatch 1 ab/cXd/efXg/hi '*/*X*/*/*i'
-pathmatch 1 ab/cXd/efXg/hi '*Xg*i'
+# Test recursion
+wildtest 1 1 1 1 '-adobe-courier-bold-o-normal--12-120-75-75-m-70-iso8859-1' '-*-*-*-*-*-*-12-*-*-*-m-*-*-*'
+wildtest 0 0 0 0 '-adobe-courier-bold-o-normal--12-120-75-75-X-70-iso8859-1' '-*-*-*-*-*-*-12-*-*-*-m-*-*-*'
+wildtest 0 0 0 0 '-adobe-courier-bold-o-normal--12-120-75-75-/-70-iso8859-1' '-*-*-*-*-*-*-12-*-*-*-m-*-*-*'
+wildtest 1 1 1 1 'XXX/adobe/courier/bold/o/normal//12/120/75/75/m/70/iso8859/1' 'XXX/*/*/*/*/*/*/12/*/*/*/m/*/*/*'
+wildtest 0 0 0 0 'XXX/adobe/courier/bold/o/normal//12/120/75/75/X/70/iso8859/1' 'XXX/*/*/*/*/*/*/12/*/*/*/m/*/*/*'
+wildtest 1 1 1 1 'abcd/abcdefg/abcdefghijk/abcdefghijklmnop.txt' '**/*a*b*g*n*t'
+wildtest 0 0 0 0 'abcd/abcdefg/abcdefghijk/abcdefghijklmnop.txtz' '**/*a*b*g*n*t'
+wildtest 0 0 0 0 foo '*/*/*'
+wildtest 0 0 0 0 foo/bar '*/*/*'
+wildtest 1 1 1 1 foo/bba/arr '*/*/*'
+wildtest 0 0 1 1 foo/bb/aa/rr '*/*/*'
+wildtest 1 1 1 1 foo/bb/aa/rr '**/**/**'
+wildtest 1 1 1 1 abcXdefXghi '*X*i'
+wildtest 0 0 1 1 ab/cXd/efXg/hi '*X*i'
+wildtest 1 1 1 1 ab/cXd/efXg/hi '*/*X*/*/*i'
+wildtest 1 1 1 1 ab/cXd/efXg/hi '**/*X*/**/*i'
 
-# Case-sensitivity features
-match 0 'a' '[A-Z]'
-match 1 'A' '[A-Z]'
-match 0 'A' '[a-z]'
-match 1 'a' '[a-z]'
-match 0 'a' '[[:upper:]]'
-match 1 'A' '[[:upper:]]'
-match 0 'A' '[[:lower:]]'
-match 1 'a' '[[:lower:]]'
-match 0 'A' '[B-Za]'
-match 1 'a' '[B-Za]'
-match 0 'A' '[B-a]'
-match 1 'a' '[B-a]'
-match 0 'z' '[Z-y]'
-match 1 'Z' '[Z-y]'
+# Extra pathmatch tests
+wildtest 0 0 0 0 foo fo
+wildtest 1 1 1 1 foo/bar foo/bar
+wildtest 1 1 1 1 foo/bar 'foo/*'
+wildtest 0 0 1 1 foo/bba/arr 'foo/*'
+wildtest 1 1 1 1 foo/bba/arr 'foo/**'
+wildtest 0 0 1 1 foo/bba/arr 'foo*'
+wildtest 0 0 1 1 foo/bba/arr 'foo**'
+wildtest 0 0 1 1 foo/bba/arr 'foo/*arr'
+wildtest 0 0 1 1 foo/bba/arr 'foo/**arr'
+wildtest 0 0 0 0 foo/bba/arr 'foo/*z'
+wildtest 0 0 0 0 foo/bba/arr 'foo/**z'
+wildtest 0 0 1 1 foo/bar 'foo?bar'
+wildtest 0 0 1 1 foo/bar 'foo[/]bar'
+wildtest 0 0 1 1 foo/bar 'foo[^a-z]bar'
+wildtest 0 0 1 1 ab/cXd/efXg/hi '*Xg*i'
 
-imatch 1 'a' '[A-Z]'
-imatch 1 'A' '[A-Z]'
-imatch 1 'A' '[a-z]'
-imatch 1 'a' '[a-z]'
-imatch 1 'a' '[[:upper:]]'
-imatch 1 'A' '[[:upper:]]'
-imatch 1 'A' '[[:lower:]]'
-imatch 1 'a' '[[:lower:]]'
-imatch 1 'A' '[B-Za]'
-imatch 1 'a' '[B-Za]'
-imatch 1 'A' '[B-a]'
-imatch 1 'a' '[B-a]'
-imatch 1 'z' '[Z-y]'
-imatch 1 'Z' '[Z-y]'
+# Extra case-sensitivity tests
+wildtest 0 1 0 1 'a' '[A-Z]'
+wildtest 1 1 1 1 'A' '[A-Z]'
+wildtest 0 1 0 1 'A' '[a-z]'
+wildtest 1 1 1 1 'a' '[a-z]'
+wildtest 0 1 0 1 'a' '[[:upper:]]'
+wildtest 1 1 1 1 'A' '[[:upper:]]'
+wildtest 0 1 0 1 'A' '[[:lower:]]'
+wildtest 1 1 1 1 'a' '[[:lower:]]'
+wildtest 0 1 0 1 'A' '[B-Za]'
+wildtest 1 1 1 1 'a' '[B-Za]'
+wildtest 0 1 0 1 'A' '[B-a]'
+wildtest 1 1 1 1 'a' '[B-a]'
+wildtest 0 1 0 1 'z' '[Z-y]'
+wildtest 1 1 1 1 'Z' '[Z-y]'
 
 test_done
-- 
2.15.1.424.g9478a66081
Ævar Arnfjörð Bjarmason· Jan 4, 2018, 19:26 UTC · re: Ævar Arnfjörð Bjarmason · lore

[PATCH v4 7/7] wildmatch test: create & test files on disk in addition to in-memory

There has never been any full roundtrip testing of what git-ls-files and other commands that use wildmatch() actually do, rather we've been satisfied with just testing the underlying C function.

Due to git-ls-files and friends having their own codepaths before they call wildmatch() there's sometimes differences in the behavior between the two. Even when we test for those (as with [1]), there was no one place where you can review how these two modes differ.

Now there is. We now attempt to create a file called $haystack and match $needle against it for each pair of $needle and $haystack that we were passing to test-wildmatch.

If we can't create the file we skip the test. This ensures that we can run this on all platforms and not maintain some infinitely growing whitelist of e.g. platforms that don't support certain characters in filenames.

As a result of doing this we can now see the cases where these two ways of testing wildmatch differ:

 * Creating a file called 'a[]b' and running ls-files 'a[]b' will show
   that file, but wildmatch("a[]b", "a[]b") will not match
 * wildmatch() won't match a file called \ against \, but ls-files
   will.
 * `git --glob-pathspecs ls-files 'foo**'` will match a file
   'foo/bba/arr', but wildmatch won't, however pathmatch will.
   This seems like a bug to me, the two are otherwise equivalent as
   these tests show.

This also reveals the case discussed in [1] above, where '' is now an error as far as ls-files is concerned, but wildmatch() itself happily accepts it.

1. 9e4e8a64c2 ("pathspec: die on empty strings as pathspec",
   2017-06-06)
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 t/t3070-wildmatch.sh | 301 +++++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 290 insertions(+), 11 deletions(-)
Show changes to t/t3070-wildmatch.sh +290 −11
diff --git a/t/t3070-wildmatch.sh b/t/t3070-wildmatch.sh
index 06db053ae2..f606f91acb 100755
--- a/t/t3070-wildmatch.sh
+++ b/t/t3070-wildmatch.sh
@@ -4,14 +4,113 @@ test_description='wildmatch tests'
 
 . ./test-lib.sh
 
+create_test_file() {
+	file=$1
+
+	case $file in
+	# `touch .` will succeed but obviously not do what we intend
+	# here.
+	".")
+		return 1
+		;;
+	# We cannot create a file with an empty filename.
+	"")
+		return 1
+		;;
+	# The tests that are testing that e.g. foo//bar is matched by
+	# foo/*/bar can't be tested on filesystems since there's no
+	# way we're getting a double slash.
+	*//*)
+		return 1
+		;;
+	# When testing the difference between foo/bar and foo/bar/ we
+	# can't test the latter.
+	*/)
+		return 1
+		;;
+	# On Windows, \ in paths is silently converted to /, which
+	# would result in the "touch" below working, but the test
+	# itself failing. See 6fd1106aa4 ("t3700: Skip a test with
+	# backslashes in pathspec", 2009-03-13) for prior art and
+	# details.
+	*\\*)
+		if ! test_have_prereq BSLASHPSPEC
+		then
+			return 1
+		fi
+		# NOTE: The ;;& bash extension is not portable, so
+		# this test needs to be at the end of the pattern
+		# list.
+		#
+		# If we want to add more conditional returns we either
+		# need a new case statement, or turn this whole thing
+		# into a series of "if" tests.
+		;;
+	esac
+
+	# Turn foo/bar/baz into foo/bar to create foo/bar as a
+	# directory structure.
+	dirs=${file%/*}
+
+	# We touch "./$file" instead of "$file" because even an
+	# escaped "touch -- -" means get arguments from stdin.
+	if test "$file" != "$dirs"
+	then
+		mkdir -p -- "$dirs" &&
+		touch -- "./$file" &&
+		return 0
+	else
+		touch -- "./$file" &&
+		return 0
+	fi
+	return 1
+}
+
+wildtest_file_setup() {
+	test_when_finished "
+		rm -rf -- * &&
+		git reset
+	" &&
+	git add -A &&
+	>expect.err
+}
+
+wildtest_stdout_stderr_cmp() {
+	tr -d '\0' <actual.raw >actual &&
+	test_cmp expect.err actual.err &&
+	test_cmp expect actual
+}
+
 wildtest() {
-	match_w_glob=$1
-	match_w_globi=$2
-	match_w_pathmatch=$3
-	match_w_pathmatchi=$4
-	text=$5
-	pattern=$6
+	if test "$#" = 6
+	then
+		# When test-wildmatch and git ls-files produce the same
+		# result.
+		match_w_glob=$1
+		match_f_w_glob=$match_w_glob
+		match_w_globi=$2
+		match_f_w_globi=$match_w_globi
+		match_w_pathmatch=$3
+		match_f_w_pathmatch=$match_w_pathmatch
+		match_w_pathmatchi=$4
+		match_f_w_pathmatchi=$match_w_pathmatchi
+		text=$5
+		pattern=$6
+	elif test "$#" = 10
+	then
+		match_w_glob=$1
+		match_w_globi=$2
+		match_w_pathmatch=$3
+		match_w_pathmatchi=$4
+		match_f_w_glob=$5
+		match_f_w_globi=$6
+		match_f_w_pathmatch=$7
+		match_f_w_pathmatchi=$8
+		text=$9
+		pattern=${10}
+	fi
 
+	# $1: Case sensitive glob match: test-wildmatch
 	if test "$match_w_glob" = 1
 	then
 		test_expect_success "wildmatch: match '$text' '$pattern'" "
@@ -26,6 +125,50 @@ wildtest() {
 		test_expect_success "PANIC: Test framework error. Unknown matches value $match_w_glob" 'false'
 	fi
 
+	# $1: Case sensitive glob match: ls-files
+	if test "$match_f_w_glob" = 'E'
+	then
+		if create_test_file "$text"
+		then
+			test_expect_success "wildmatch(ls): match dies on '$pattern' '$text'" "
+				wildtest_file_setup &&
+				printf '%s' '$text' >expect &&
+				test_must_fail git --glob-pathspecs ls-files -z -- '$pattern'
+			"
+		else
+			test_expect_failure "wildmatch(ls): match skip '$pattern' '$text'" 'false'
+		fi
+	elif test "$match_f_w_glob" = 1
+	then
+		if create_test_file "$text"
+		then
+			test_expect_success "wildmatch(ls): match '$pattern' '$text'" "
+				wildtest_file_setup &&
+				printf '%s' '$text' >expect &&
+				git --glob-pathspecs ls-files -z -- '$pattern' >actual.raw 2>actual.err &&
+				wildtest_stdout_stderr_cmp
+			"
+		else
+			test_expect_failure "wildmatch(ls): match skip '$pattern' '$text'" 'false'
+		fi
+	elif test "$match_f_w_glob" = 0
+	then
+		if create_test_file "$text"
+		then
+			test_expect_success "wildmatch(ls): no match '$pattern' '$text'" "
+				wildtest_file_setup &&
+				>expect &&
+				git --glob-pathspecs ls-files -z -- '$pattern' >actual.raw 2>actual.err &&
+				wildtest_stdout_stderr_cmp
+			"
+		else
+			test_expect_failure "wildmatch(ls): no match skip '$pattern' '$text'" 'false'
+		fi
+	else
+		test_expect_success "PANIC: Test framework error. Unknown matches value $match_f_w_glob" 'false'
+	fi
+
+	# $2: Case insensitive glob match: test-wildmatch
 	if test "$match_w_globi" = 1
 	then
 		test_expect_success "iwildmatch: match '$text' '$pattern'" "
@@ -40,6 +183,50 @@ wildtest() {
 		test_expect_success "PANIC: Test framework error. Unknown matches value $match_w_globi" 'false'
 	fi
 
+	# $2: Case insensitive glob match: ls-files
+	if test "$match_f_w_globi" = 'E'
+	then
+		if create_test_file "$text"
+		then
+			test_expect_success "iwildmatch(ls): match dies on '$pattern' '$text'" "
+				wildtest_file_setup &&
+				printf '%s' '$text' >expect &&
+				test_must_fail git --glob-pathspecs --icase-pathspecs ls-files -z -- '$pattern'
+			"
+		else
+			test_expect_failure "wildmatch(ls): match skip '$pattern' '$text'" 'false'
+		fi
+	elif test "$match_f_w_globi" = 1
+	then
+		if create_test_file "$text"
+		then
+			test_expect_success "iwildmatch(ls): match '$pattern' '$text'" "
+				wildtest_file_setup &&
+				printf '%s' '$text' >expect &&
+				git --glob-pathspecs --icase-pathspecs ls-files -z -- '$pattern' >actual.raw 2>actual.err &&
+				wildtest_stdout_stderr_cmp
+			"
+		else
+			test_expect_failure "iwildmatch(ls): match skip '$pattern' '$text'" 'false'
+		fi
+	elif test "$match_f_w_globi" = 0
+	then
+		if create_test_file "$text"
+		then
+			test_expect_success "iwildmatch(ls): no match '$pattern' '$text'" "
+				wildtest_file_setup &&
+				>expect &&
+				git --glob-pathspecs --icase-pathspecs ls-files -z -- '$pattern' >actual.raw 2>actual.err &&
+				wildtest_stdout_stderr_cmp
+			"
+		else
+			test_expect_failure "iwildmatch(ls): no match skip '$pattern' '$text'" 'false'
+		fi
+	else
+		test_expect_success "PANIC: Test framework error. Unknown matches value $match_f_w_globi" 'false'
+	fi
+
+	# $3: Case sensitive path match: test-wildmatch
 	if test "$match_w_pathmatch" = 1
 	then
 		test_expect_success "pathmatch: match '$text' '$pattern'" "
@@ -54,6 +241,50 @@ wildtest() {
 		test_expect_success "PANIC: Test framework error. Unknown matches value $match_w_pathmatch" 'false'
 	fi
 
+	# $4: Case sensitive path match: ls-files
+	if test "$match_f_w_pathmatch" = 'E'
+	then
+		if create_test_file "$text"
+		then
+			test_expect_success "pathmatch(ls): match dies on '$pattern' '$text'" "
+				wildtest_file_setup &&
+				printf '%s' '$text' >expect &&
+				test_must_fail git ls-files -z -- '$pattern'
+			"
+		else
+			test_expect_failure "pathmatch(ls): match skip '$pattern' '$text'" 'false'
+		fi
+	elif test "$match_f_w_pathmatch" = 1
+	then
+		if create_test_file "$text"
+		then
+			test_expect_success "pathmatch(ls): match '$pattern' '$text'" "
+				wildtest_file_setup &&
+				printf '%s' '$text' >expect &&
+				git ls-files -z -- '$pattern' >actual.raw 2>actual.err &&
+				wildtest_stdout_stderr_cmp
+			"
+		else
+			test_expect_failure "pathmatch(ls): match skip '$pattern' '$text'" 'false'
+		fi
+	elif test "$match_f_w_pathmatch" = 0
+	then
+		if create_test_file "$text"
+		then
+			test_expect_success "pathmatch(ls): no match '$pattern' '$text'" "
+				wildtest_file_setup &&
+				>expect &&
+				git ls-files -z -- '$pattern' >actual.raw 2>actual.err &&
+				wildtest_stdout_stderr_cmp
+			"
+		else
+			test_expect_failure "pathmatch(ls): no match skip '$pattern' '$text'" 'false'
+		fi
+	else
+		test_expect_success "PANIC: Test framework error. Unknown matches value $match_f_w_pathmatch" 'false'
+	fi
+
+	# $4: Case insensitive path match: test-wildmatch
 	if test "$match_w_pathmatchi" = 1
 	then
 		test_expect_success "ipathmatch: match '$text' '$pattern'" "
@@ -67,6 +298,49 @@ wildtest() {
 	else
 		test_expect_success "PANIC: Test framework error. Unknown matches value $match_w_pathmatchi" 'false'
 	fi
+
+	# $4: Case insensitive path match: ls-files
+	if test "$match_f_w_pathmatchi" = 'E'
+	then
+		if create_test_file "$text"
+		then
+			test_expect_success "ipathmatch(ls): match dies on '$pattern' '$text'" "
+				wildtest_file_setup &&
+				printf '%s' '$text' >expect &&
+				test_must_fail git --icase-pathspecs ls-files -z -- '$pattern'
+			"
+		else
+			test_expect_failure "pathmatch(ls): match skip '$pattern' '$text'" 'false'
+		fi
+	elif test "$match_f_w_pathmatchi" = 1
+	then
+		if create_test_file "$text"
+		then
+			test_expect_success "ipathmatch(ls): match '$pattern' '$text'" "
+				wildtest_file_setup &&
+				printf '%s' '$text' >expect &&
+				git --icase-pathspecs ls-files -z -- '$pattern' >actual.raw 2>actual.err &&
+				wildtest_stdout_stderr_cmp
+			"
+		else
+			test_expect_failure "ipathmatch(ls): match skip '$pattern' '$text'" 'false'
+		fi
+	elif test "$match_f_w_pathmatchi" = 0
+	then
+		if create_test_file "$text"
+		then
+			test_expect_success "ipathmatch(ls): no match '$pattern' '$text'" "
+				wildtest_file_setup &&
+				>expect &&
+				git ls-files -z -- '$pattern' >actual.raw 2>actual.err &&
+				wildtest_stdout_stderr_cmp
+			"
+		else
+			test_expect_failure "ipathmatch(ls): no match skip '$pattern' '$text'" 'false'
+		fi
+	else
+		test_expect_success "PANIC: Test framework error. Unknown matches value $match_f_w_pathmatchi" 'false'
+	fi
 }
 
 # Basic wildmatch features
@@ -135,7 +409,8 @@ wildtest 1 1 1 1 'acrt' 'a[c-c]rt'
 wildtest 0 0 0 0 ']' '[!]-]'
 wildtest 1 1 1 1 'a' '[!]-]'
 wildtest 0 0 0 0 '' '\'
-wildtest 0 0 0 0 '\' '\'
+wildtest 0 0 0 0 \
+	 1 1 1 1 '\' '\'
 wildtest 0 0 0 0 'XXX/\' '*/\'
 wildtest 1 1 1 1 'XXX/\' '*/\\'
 wildtest 1 1 1 1 'foo' 'foo'
@@ -149,7 +424,8 @@ wildtest 1 1 1 1 '[ab]' '[[:digit]ab]'
 wildtest 1 1 1 1 '[ab]' '[\[:]ab]'
 wildtest 1 1 1 1 '?a?b' '\??\?b'
 wildtest 1 1 1 1 'abc' '\a\b\c'
-wildtest 0 0 0 0 'foo' ''
+wildtest 0 0 0 0 \
+	 E E E E 'foo' ''
 wildtest 1 1 1 1 'foo/bar/baz/to' '**/t[o]'
 
 # Character class tests
@@ -179,8 +455,10 @@ wildtest 1 1 1 1 ']' '[\]]'
 wildtest 0 0 0 0 '\]' '[\]]'
 wildtest 0 0 0 0 '\' '[\]]'
 wildtest 0 0 0 0 'ab' 'a[]b'
-wildtest 0 0 0 0 'a[]b' 'a[]b'
-wildtest 0 0 0 0 'ab[' 'ab['
+wildtest 0 0 0 0 \
+	 1 1 1 1 'a[]b' 'a[]b'
+wildtest 0 0 0 0 \
+	 1 1 1 1 'ab[' 'ab['
 wildtest 0 0 0 0 'ab' '[!'
 wildtest 0 0 0 0 'ab' '[-'
 wildtest 1 1 1 1 '-' '[-]'
@@ -248,7 +526,8 @@ wildtest 1 1 1 1 foo/bar 'foo/*'
 wildtest 0 0 1 1 foo/bba/arr 'foo/*'
 wildtest 1 1 1 1 foo/bba/arr 'foo/**'
 wildtest 0 0 1 1 foo/bba/arr 'foo*'
-wildtest 0 0 1 1 foo/bba/arr 'foo**'
+wildtest 0 0 1 1 \
+	 1 1 1 1 foo/bba/arr 'foo**'
 wildtest 0 0 1 1 foo/bba/arr 'foo/*arr'
 wildtest 0 0 1 1 foo/bba/arr 'foo/**arr'
 wildtest 0 0 0 0 foo/bba/arr 'foo/*z'
-- 
2.15.1.424.g9478a66081
Johannes Schindelin· Jan 5, 2018, 16:41 UTC · re: Ævar Arnfjörð Bjarmason · lore

Re: [PATCH v4 7/7] wildmatch test: create & test files on disk in addition to in-memory

Hi Ævar,

I spent the last 3.5 hours chasing down a bug in your patch series that seems to be Windows specific, so please forgive me if the following might leak a bit of my frustration into the open...

On Thu, 4 Jan 2018, Ævar Arnfjörð Bjarmason wrote:
>  t/t3070-wildmatch.sh | 301 +++++++++++++++++++++++++++++++++++++++++++++++++--

Wow, this file is ugly. Sorry, that was an outburst, you did not deserve that, but I have to say that it is *really* hard to wrap your head around lines like this:

	wildtest 1 1 1 1 'foo*' 'foo\*'

What are those 1s supposed to mean? Granted, for you, the author of this line, it is easy.

The point, though, of regression tests is not only to catch regressions but also to make it easy to fix them. Not only for the test script's author, but for others, too (and your script is not even the best example we have for a script that needs hours to study before one can even hope to begin to see what is going wrong... I am looking at you, t0027, yes, you. You know why).

So then I go and see that the `wildtest` function has magic to handle both 6 and 10 parameters. And those parameters get assigned to variable names as intuitive as `match_f_w_pathmatchi`...

The next thing about the test script is this: calling it with -x is pretty much useless, because *so much* is happening outside of test_expect_success clauses (and is therefore *not* traced).

Of course I can debug this, but can't this be easier? And this is not even a regression after a couple of years, this is fresh from the start...

So here is the first bummer about your rather extensive test (which I think tests the same behavior over and over and over again, just with slight variations which however do not matter all that much... for example, it should be enough to verify *without* filenames that the globbing of wildmatch() works, and then a single test *with* a filename should suffice to verify that the connection between globbing and files works): it requires filenames that are illegal on Windows. Stars, question marks: forbidden.

Worse, since we have to use Unix shell scripts to perform our "platform-independent" tests, we have to rely on a Unix shell interpreter, and Git for Windows uses MSYS2's Bash, which means that we inherit most of Cygwin's behavior.

Now, Cygwin wants to be cute and allow those illegal filenames because (as is demonstrated here quite nicely) Unix programmers don't give one bit of a flying fish about portable filesystem requirements.

So Cygwin maps those illegal characters into a private Unicode page. Which means that Cygwin can read them alright, but no non-Cygwin program recognizes the stars and question marks and tabs and newlines. Including Git.

In short: the Unix shell script t3070 manages to write what it thinks is a file called 'foo*', but Git only sees 'foo<some-undisplayable-character>'.

I tried to address this problem with this patch:
-- snip --
Show changes to t/t3070-wildmatch.sh +19 −1
diff --git a/t/t3070-wildmatch.sh b/t/t3070-wildmatch.sh
index f606f91acbb..51dcb675e7b 100755
--- a/t/t3070-wildmatch.sh
+++ b/t/t3070-wildmatch.sh
@@ -4,6 +4,14 @@ test_description='wildmatch tests'
 
 . ./test-lib.sh
 
+if test_have_prereq !MINGW && touch -- 'a*b' 2>/dev/null
+then
+	test_set_prereq FILENAMESWITHSTARS
+else
+	say 'Your filesystem does not allow stars in filenames.'
+fi
+rm -f 'a*b'
+
 create_test_file() {
 	file=$1
 
@@ -28,6 +36,17 @@ create_test_file() {
 	*/)
 		return 1
 		;;
+	# On Windows, stars are not allowed in filenames. Git for Windows'
+	# Bash, however, is based on Cygwin which plays funny names with a
+	# private Unicode page to emulate stars in filenames. Meaning that
+	# the shell script will "succeed" to write the file, but Git will
+	# not see it. Nor any other, regular Windows process.
+	*\**|*\[*)
+		if ! test_have_prereq FILENAMESWITHSTARS
+		then
+			return 1
+		fi
+		;;
 	# On Windows, \ in paths is silently converted to /, which
 	# would result in the "touch" below working, but the test
 	# itself failing. See 6fd1106aa4 ("t3700: Skip a test with
-- snap --

This gets us further. But not by much:

fatal: Invalid path '\[ab]': No such file or directory

You see, any path starting with a backslash *is* an absolute path on
Windows. It is relative to the current drive.

This affects *quite* a few of the test cases you added.

And even if I just comment all of those out, I run into the next problem
where you try to create a file whose name consists of a single space,
which is also illegal on Windows.

These woes demonstrate one problem with the approach of overzealously
testing *everything*. You are kind of performing an integration test of
the wildmatch() functionality, the integration into ls-files, *and* of a
filesystem that behaves like the filesystems you are used to.

All you *should* want to test, though, is the wildmatch() functionality.
And *maybe* one or two tests verifying that this wildmatch() functionality
is actually hooked up into ls-files correctly.

You do not need to test that 'a*' matches the strings 'a', 'ab', 'abc',
'abcd', 'abcde', 'abcdef', etc. *and* filenames identical to those
strings. If we already verified (lightly) that wildmatch() *works*, then
we only have to make sure that ls-files uses wildmatch() correctly.
Everything else is useless expense of innocent electrons and neurons of
other developers.

Another problem with this approach (*extensive* testing of essentially the
same stuff over and over again) is what I mentioned earlier: these
tests are really hard to read, and it is even harder to debug test
failures.

And lastly, this approach of overzealously testing *everything* simply
takes *a lot of time* and also electricity. As a developer of patches who
runs the entire test suite before submitting every iteration of every
patch series, this affects me. Others, too, I guess, and they might just
skip the test suite as a consequence because it takes too long. Don't
sneer, you know that this is happening.

Needless to say, I am not enthused.

I would much rather have a lean and mean test script that tested things
lightly, in more of a unit test fashion: test wildmatch. Just wildmatch.
Not ls-files, no filesystem, no nothing. There is already
t/helper/test-wildmatch, for crying out loud. Just feed it test data
together with expected outcomes, will make things much easier to debug,
faster to execute, and be a lot easier to read and modify/fix.

Whatever you decide, in the current form this cannot go to master, as it
fails royally on Windows.

Ciao,
Dscho
Ævar Arnfjörð Bjarmason· Jan 5, 2018, 19:08 UTC · re: Johannes Schindelin · lore

Re: [PATCH v4 7/7] wildmatch test: create & test files on disk in addition to in-memory

On Fri, Jan 05 2018, Johannes Schindelin jotted:
> I spent the last 3.5 hours chasing down a bug in your patch series that
> seems to be Windows specific, so please forgive me if the following might
> leak a bit of my frustration into the open...
Thanks for looking into this.
Show 12 quoted lines
> On Thu, 4 Jan 2018, Ævar Arnfjörð Bjarmason wrote:
>
>>  t/t3070-wildmatch.sh | 301 +++++++++++++++++++++++++++++++++++++++++++++++++--
>
> Wow, this file is ugly. Sorry, that was an outburst, you did not deserve
> that, but I have to say that it is *really* hard to wrap your head around
> lines like this:
>
> 	wildtest 1 1 1 1 'foo*' 'foo\*'
>
> What are those 1s supposed to mean? Granted, for you, the author of this
> line, it is easy.

Just for some context, this line has looked very similar to this since feabcc173b ("Integrate wildmatch to git", 2012-10-15):

    match 1 1 'foo' 'foo'

It could be made less verbose at the expense of some complexity in wildmatch(), i.e.:

    match 1 'foo' 'foo'
Which would implicitly mean:
    match 1 1 1 1 'foo' 'foo'

But I thought it was more readable to maintain vertical alignment of the patterns, but I'm open to ideas on how to make this less shitty.

Show 14 quoted lines
> The point, though, of regression tests is not only to catch regressions
> but also to make it easy to fix them. Not only for the test script's
> author, but for others, too (and your script is not even the best example
> we have for a script that needs hours to study before one can even hope to
> begin to see what is going wrong... I am looking at you, t0027, yes, you.
> You know why).
>
> So then I go and see that the `wildtest` function has magic to handle both
> 6 and 10 parameters. And those parameters get assigned to variable names
> as intuitive as `match_f_w_pathmatchi`...
>
> The next thing about the test script is this: calling it with -x is pretty
> much useless, because *so much* is happening outside of
> test_expect_success clauses (and is therefore *not* traced).

Good point. I guess create_test_file() could create a file only if we can create the test file, and then we run the actual test as a condition of that. I.e. to move its logic into a test_expect_success() which would always succeed.

Show 11 quoted lines
> Of course I can debug this, but can't this be easier? And this is not even
> a regression after a couple of years, this is fresh from the start...
>
> So here is the first bummer about your rather extensive test (which I
> think tests the same behavior over and over and over again, just with
> slight variations which however do not matter all that much... for
> example, it should be enough to verify *without* filenames that the
> globbing of wildmatch() works, and then a single test *with* a filename
> should suffice to verify that the connection between globbing and files
> works): it requires filenames that are illegal on Windows. Stars, question
> marks: forbidden.

That's really not the case. The path match code is not simply taking a full path and a pattern and calling wildmatch(), if it was I'd agree that roundtrip testing like this on every single pattern would be completely pointless.

As noted in v1 (https://public-inbox.org/git/20171223213012.1962-1-avarab@gmail.com/) this series came out of my attempts to replace the underlying wildmatch engine, which after trying for a bit I found I was blocked by rather bad wildmatch test coverage.

I'd make code changes and some random other test would fail, but not t3070-wildmatch.sh, which later turned out to be a blindspot that this series rectifies.

A pattern like "t/**.sh" isn't just matched against a path like "t/test-lib.sh" internally, instead we peel off "t/" since we know it's a dir, and then try to match "**.sh" against "test-lib.sh".

As 7/7 shows there's several cases where the behavior is different, and without roundtrip testing like this there's no telling what other case might inadvertently be added in the future.

However, read on...
Show 18 quoted lines
> Worse, since we have to use Unix shell scripts to perform our
> "platform-independent" tests, we have to rely on a Unix shell interpreter,
> and Git for Windows uses MSYS2's Bash, which means that we inherit most of
> Cygwin's behavior.
>
> Now, Cygwin wants to be cute and allow those illegal filenames because (as
> is demonstrated here quite nicely) Unix programmers don't give one bit of
> a flying fish about portable filesystem requirements.
>
> So Cygwin maps those illegal characters into a private Unicode page. Which
> means that Cygwin can read them alright, but no non-Cygwin program
> recognizes the stars and question marks and tabs and newlines. Including
> Git.
>
> In short: the Unix shell script t3070 manages to write what it thinks is a
> file called 'foo*', but Git only sees 'foo<some-undisplayable-character>'.
>
> I tried to address this problem with this patch:

...I don't see any particular value in trying to do these full roundtrip tests on platforms like Windows. Perhaps we should just do these on a whitelist of POSIX systems for now, and leave expanding that list to some future step.

Show 41 quoted lines
> -- snip --
> diff --git a/t/t3070-wildmatch.sh b/t/t3070-wildmatch.sh
> index f606f91acbb..51dcb675e7b 100755
> --- a/t/t3070-wildmatch.sh
> +++ b/t/t3070-wildmatch.sh
> @@ -4,6 +4,14 @@ test_description='wildmatch tests'
>
>  . ./test-lib.sh
>
> +if test_have_prereq !MINGW && touch -- 'a*b' 2>/dev/null
> +then
> +	test_set_prereq FILENAMESWITHSTARS
> +else
> +	say 'Your filesystem does not allow stars in filenames.'
> +fi
> +rm -f 'a*b'
> +
>  create_test_file() {
>  	file=$1
>
> @@ -28,6 +36,17 @@ create_test_file() {
>  	*/)
>  		return 1
>  		;;
> +	# On Windows, stars are not allowed in filenames. Git for Windows'
> +	# Bash, however, is based on Cygwin which plays funny names with a
> +	# private Unicode page to emulate stars in filenames. Meaning that
> +	# the shell script will "succeed" to write the file, but Git will
> +	# not see it. Nor any other, regular Windows process.
> +	*\**|*\[*)
> +		if ! test_have_prereq FILENAMESWITHSTARS
> +		then
> +			return 1
> +		fi
> +		;;
>  	# On Windows, \ in paths is silently converted to /, which
>  	# would result in the "touch" below working, but the test
>  	# itself failing. See 6fd1106aa4 ("t3700: Skip a test with
> -- snap --
>
> This gets us further. But not by much:
Okey, that's very weird. So you can:
    touch "./*"; echo $?
And it'll return 0 but then the file won't exist?
How about this:
    touch "./*" && test -e "./*"; echo $?

I.e. could we more generally just test whether the file got created successfully? Does that work on Windows?

The reason this latest version stopped creating files with "\" in them unless under BSLASHPSPEC is because Cygwin would silently translate it, so it would create the file but it would actually mean something the tests didn't expect.

For anything else, such as stars not being allowed in filenames I was expecting that "touch" command to return an error, but if that's not the case maybe we need the "test -e" as well, unless I'm missing something here.

> fatal: Invalid path '\[ab]': No such file or directory
>
> You see, any path starting with a backslash *is* an absolute path on
> Windows. It is relative to the current drive.

Right, which I was trying to avoid by not actually creating \[ab], but "./\[ab]", is that the same filename on Windows?

Show 5 quoted lines
> This affects *quite* a few of the test cases you added.
>
> And even if I just comment all of those out, I run into the next problem
> where you try to create a file whose name consists of a single space,
> which is also illegal on Windows.
Okey, but ditto above about touch not catching it, does:
    touch "./ "; echo $?
Not return an error? Then how about:
    touch "./ " && test -e "./ "; echo $?
> These woes demonstrate one problem with the approach of overzealously
> testing *everything*[...]

I think the rest of this gets into topics I've covered above. I.e. that this increased test coverage has caught bugs.

Johannes Schindelin· Jan 5, 2018, 20:48 UTC · re: Ævar Arnfjörð Bjarmason · lore

Re: [PATCH v4 7/7] wildmatch test: create & test files on disk in addition to in-memory

Hi Ævar,
On Fri, 5 Jan 2018, Ævar Arnfjörð Bjarmason wrote:
Show 13 quoted lines
> On Fri, Jan 05 2018, Johannes Schindelin jotted:
> 
> > [...]
> >
> > In short: the Unix shell script t3070 manages to write what it thinks is a
> > file called 'foo*', but Git only sees 'foo<some-undisplayable-character>'.
> >
> > I tried to address this problem with this patch:
> 
> ...I don't see any particular value in trying to do these full roundtrip
> tests on platforms like Windows. Perhaps we should just do these on a
> whitelist of POSIX systems for now, and leave expanding that list to
> some future step.

I don't think so. Windows is already handled as a second-class citizen, as if nobody developed on it. As a consequence, only very few of the gazillions of Windows developers... develop Git. We could worsify the situation, of course, but why? Shouldn't we at least pretend to try the opposite?

Show 47 quoted lines
> > -- snip --
> > diff --git a/t/t3070-wildmatch.sh b/t/t3070-wildmatch.sh
> > index f606f91acbb..51dcb675e7b 100755
> > --- a/t/t3070-wildmatch.sh
> > +++ b/t/t3070-wildmatch.sh
> > @@ -4,6 +4,14 @@ test_description='wildmatch tests'
> >
> >  . ./test-lib.sh
> >
> > +if test_have_prereq !MINGW && touch -- 'a*b' 2>/dev/null
> > +then
> > +	test_set_prereq FILENAMESWITHSTARS
> > +else
> > +	say 'Your filesystem does not allow stars in filenames.'
> > +fi
> > +rm -f 'a*b'
> > +
> >  create_test_file() {
> >  	file=$1
> >
> > @@ -28,6 +36,17 @@ create_test_file() {
> >  	*/)
> >  		return 1
> >  		;;
> > +	# On Windows, stars are not allowed in filenames. Git for Windows'
> > +	# Bash, however, is based on Cygwin which plays funny names with a
> > +	# private Unicode page to emulate stars in filenames. Meaning that
> > +	# the shell script will "succeed" to write the file, but Git will
> > +	# not see it. Nor any other, regular Windows process.
> > +	*\**|*\[*)
> > +		if ! test_have_prereq FILENAMESWITHSTARS
> > +		then
> > +			return 1
> > +		fi
> > +		;;
> >  	# On Windows, \ in paths is silently converted to /, which
> >  	# would result in the "touch" below working, but the test
> >  	# itself failing. See 6fd1106aa4 ("t3700: Skip a test with
> > -- snap --
> >
> > This gets us further. But not by much:
> 
> Okey, that's very weird. So you can:
> 
>     touch "./*"; echo $?
> 
> And it'll return 0 but then the file won't exist?

Almost. The file exists, but it won't have the name '*'. It will have as name a Unicode character that is in a private page, not standardized by the Unicode specification.

> How about this:
> 
>     touch "./*" && test -e "./*"; echo $?

Would return 0. Why? Because *you are still in a Unix shell script, so the Cygwin cuteness still applies*.

> The reason this latest version stopped creating files with "\" in them
> unless under BSLASHPSPEC is because Cygwin would silently translate it,
> so it would create the file but it would actually mean something the
> tests didn't expect.

I understand that. And I would wish that the test would be designed in a more cross-platform-aware mindset.

> For anything else, such as stars not being allowed in filenames I was
> expecting that "touch" command to return an error, but if that's not the
> case maybe we need the "test -e" as well, unless I'm missing something
> here.

This is one of the many bad consequences of Git relying so much on Unix shell scripting. Despite what many, many, many Git developers think: shell scripting is not portable.

Cygwin does a good job of pretending that it is, and MSYS2 exacerbates that notion, but it comes back to haunt you right here and right now. The `touch` invocation will *report success*, but it will have done something different than you wanted. It's like the Thinking: Fast and Slow.

Show 7 quoted lines
> > fatal: Invalid path '\[ab]': No such file or directory
> >
> > You see, any path starting with a backslash *is* an absolute path on
> > Windows. It is relative to the current drive.
> 
> Right, which I was trying to avoid by not actually creating \[ab], but
> "./\[ab]", is that the same filename on Windows?

Whoops. I managed to copy-paste the *wrong* command's error message. Sorry about that. The correct one:

$ git --glob-pathspecs ls-files -z -- '\[ab]' fatal: \[ab]: '\[ab]' is outside repository

Note how it is Git reporting that you asked for a path that is outside? That's because it thinks you are referring to C:\[ab] (if your current directory is on the C: drive).

And it would be correct to complain on Windows: the `\[ab]` parameter refers to an absolute path.

Show 13 quoted lines
> > This affects *quite* a few of the test cases you added.
> >
> > And even if I just comment all of those out, I run into the next problem
> > where you try to create a file whose name consists of a single space,
> > which is also illegal on Windows.
> 
> Okey, but ditto above about touch not catching it, does:
> 
>     touch "./ "; echo $?
> 
> Not return an error? Then how about:
> 
>     touch "./ " && test -e "./ "; echo $?
Again: as long as you stay within the bounds of the Unix shell script (did
I point out enough yet how non-portable this design is? Even Subversion
knew better than to implement parts of its operations as Unix shell
scripts. I mean, for PoCing, okay, but for production code?) you fall prey
to Cygwin's emulation of POSIX-y filenames. As soon as you leave that
bubble (e.g. by calling git.exe), you're not going to see those illegal
file names, but the ones with the unprintable Unicode characters.
Show 5 quoted lines
> > These woes demonstrate one problem with the approach of overzealously
> > testing *everything*[...]
> 
> I think the rest of this gets into topics I've covered above. I.e. that
> this increased test coverage has caught bugs.

That's all good and dandy, but what about regressions? I know how much I will curse in your vague direction when I encounter the next wildmatch-related bug in, say, half a year and have to wade through the jungle of unintuitive tests in t3070.

Can't we do a lot better than this? Shouldn't it be a lot more obvious what the heck went wrong when running t3070 with -i -v -x?

Ciao, Johannes

Ævar Arnfjörð Bjarmason· Jan 5, 2018, 22:12 UTC · re: Johannes Schindelin · lore

[PATCH v4 8/7] wildmatch test: skip file creation tests on Windows proper

Skip the newly added file creation tests on Windows proper, these already work under Cygwin, but as that involves a significant emulation layer the results are different under Windows proper with MinGW.

Ideally we'd get exhaustive coverage for this area on all platforms, but having any increase in test coverage anywhere is a net improvement.

Particularly in this case where there's no reason to suspect (aside from perhaps odd edge case like \foo meaning C:\foo) that the actual pattern matching engine will behave differently on Windows. The tests can't be run due to limitations elsewhere.

The thread starting at https://public-inbox.org/git/?q=nycvar.QRO.7.76.6.1801051622010.1337%40wbunaarf-fpuvaqryva.tvgsbejvaqbjf.bet has more details about specific issues under Windows.

Reported-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
On Fri, Jan 05 2018, Johannes Schindelin jotted:
Show 23 quoted lines
> Hi Ævar,
>
> On Fri, 5 Jan 2018, Ævar Arnfjörð Bjarmason wrote:
>
>> On Fri, Jan 05 2018, Johannes Schindelin jotted:
>> 
>> > [...]
>> >
>> > In short: the Unix shell script t3070 manages to write what it thinks is a
>> > file called 'foo*', but Git only sees 'foo<some-undisplayable-character>'.
>> >
>> > I tried to address this problem with this patch:
>> 
>> ...I don't see any particular value in trying to do these full roundtrip
>> tests on platforms like Windows. Perhaps we should just do these on a
>> whitelist of POSIX systems for now, and leave expanding that list to
>> some future step.
>
> I don't think so. Windows is already handled as a second-class citizen, as
> if nobody developed on it. As a consequence, only very few of the
> gazillions of Windows developers... develop Git. We could worsify the
> situation, of course, but why? Shouldn't we at least pretend to try the
> opposite?

I don't think we should never test for this on MinGW, but given the increase in test coverage, and not making perfect the enemy of the good I think (as explained in the commit message above) that we're better off *starting* with just disabling these tests under MinGW, and then fixing that platform later.

Show 5 quoted lines
> [...]
> That's all good and dandy, but what about regressions? I know how much I
> will curse in your vague direction when I encounter the next
> wildmatch-related bug in, say, half a year and have to wade through the
> jungle of unintuitive tests in t3070.

If we have a new wildmatch-related bug we'll be a lot better off with exhaustive test coverage, even if we can only run those tests on *nix-like platforms.

> Can't we do a lot better than this? Shouldn't it be a lot more obvious
> what the heck went wrong when running t3070 with -i -v -x?

I had something closer to that in v1 in 20171223213012.1962-7-avarab@gmail.com, but trying again I didn't find a good way to compromise between -x readability and the entire patch basically not being the copy/pasted code all over again, and I think e.g. doing string interpolation into the test code would be even nastier.

 t/t3070-wildmatch.sh | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)
Show changes to t/t3070-wildmatch.sh +9 −1
diff --git a/t/t3070-wildmatch.sh b/t/t3070-wildmatch.sh
index f606f91acb..50a53e7a62 100755
--- a/t/t3070-wildmatch.sh
+++ b/t/t3070-wildmatch.sh
@@ -7,6 +7,14 @@ test_description='wildmatch tests'
 create_test_file() {
 	file=$1
 
+	# These tests limp along under Cygwin, but the failures on
+	# native Windows are still too many. Skip file tests there
+	# until they're sorted out.
+	if test_have_prereq MINGW
+	then
+		return 1
+	fi
+
 	case $file in
 	# `touch .` will succeed but obviously not do what we intend
 	# here.
@@ -28,7 +36,7 @@ create_test_file() {
 	*/)
 		return 1
 		;;
-	# On Windows, \ in paths is silently converted to /, which
+	# On Cygwin, \ in paths is silently converted to /, which
 	# would result in the "touch" below working, but the test
 	# itself failing. See 6fd1106aa4 ("t3700: Skip a test with
 	# backslashes in pathspec", 2009-03-13) for prior art and
-- 
2.15.1.424.g9478a66081
Junio C Hamano· Jan 5, 2018, 23:13 UTC · re: Ævar Arnfjörð Bjarmason · lore

Re: [PATCH v4 8/7] wildmatch test: skip file creation tests on Windows proper

Ævar Arnfjörð Bjarmason  <avarab@gmail.com> writes:
Show 21 quoted lines
> Skip the newly added file creation tests on Windows proper, these
> already work under Cygwin, but as that involves a significant
> emulation layer the results are different under Windows proper with
> MinGW.
> ...
> diff --git a/t/t3070-wildmatch.sh b/t/t3070-wildmatch.sh
> index f606f91acb..50a53e7a62 100755
> --- a/t/t3070-wildmatch.sh
> +++ b/t/t3070-wildmatch.sh
> @@ -7,6 +7,14 @@ test_description='wildmatch tests'
>  create_test_file() {
>  	file=$1
>  
> +	# These tests limp along under Cygwin, but the failures on
> +	# native Windows are still too many. Skip file tests there
> +	# until they're sorted out.
> +	if test_have_prereq MINGW
> +	then
> +		return 1
> +	fi
> +

That looks to be a nuclear option. For now it may be suffice, but somehow it feels that it goes directly against Dscho's wish to treat (or pretend to treat) Windows as first-class citizens and/or just like other platforms.

Johannes Schindelin· Jan 6, 2018, 12:51 UTC · re: Junio C Hamano · lore

Re: [PATCH v4 8/7] wildmatch test: skip file creation tests on Windows proper

Hi Junio,
On Fri, 5 Jan 2018, Junio C Hamano wrote:
Show 25 quoted lines
> Ævar Arnfjörð Bjarmason  <avarab@gmail.com> writes:
> 
> > Skip the newly added file creation tests on Windows proper, these
> > already work under Cygwin, but as that involves a significant
> > emulation layer the results are different under Windows proper with
> > MinGW.
> > ...
> > diff --git a/t/t3070-wildmatch.sh b/t/t3070-wildmatch.sh
> > index f606f91acb..50a53e7a62 100755
> > --- a/t/t3070-wildmatch.sh
> > +++ b/t/t3070-wildmatch.sh
> > @@ -7,6 +7,14 @@ test_description='wildmatch tests'
> >  create_test_file() {
> >  	file=$1
> >  
> > +	# These tests limp along under Cygwin, but the failures on
> > +	# native Windows are still too many. Skip file tests there
> > +	# until they're sorted out.
> > +	if test_have_prereq MINGW
> > +	then
> > +		return 1
> > +	fi
> > +
> 
> That looks to be a nuclear option.
Indeed:
	# still have 84 known breakage(s)
	# failed 52 among remaining 1428 test(s)
	1..1512

Let's just switch it off completely because 52 of those 1512 test cases break only on Windows? Pretty heavy-handed.

But do read on.
> For now it may be suffice, but somehow it feels that it goes directly
> against Dscho's wish to treat (or pretend to treat) Windows as
> first-class citizens and/or just like other platforms.

It not only goes against my wish to treat Windows as a normal citizen instead of like Rey's parents, it also goes against my wish to have a focused and meaningful test suite. Nobody likes to run tests that take too long. And look at this:

	...
	ok 1511 - ipathmatch: match 'Z' '[Z-y]'
	ok 1512 - ipathmatch(ls): match '[Z-y]' 'Z'
	# still have 84 known breakage(s)
	# failed 52 among remaining 1428 test(s)
	1..1512
	real    5m51.432s
	user    0m33.986s
	sys     2m13.162s
Yep. It takes *over eight minutes*.
And this is a *fast* machine.

Why? Because of the completely overboard testing of all kinds of *potential* breakages *at some point* in the future.

I understand that Ævar wants to increase test coverage. I am sympathetic to this cause.

But I completely disagree that increasing the test coverage beyond reason is a good thing. Tests *can* take too long, and they do, in practice, and the results are always problematic: every developer who has to deal with test suites that take too long... does not run them. As simple as that. And then you have *zero* test coverage. Pretty stupid, eh? And contrary to your intentions, too.

So yes, I think that it has been proven beyond any doubt that t3070 takes *waaaaaaaaaay* too long on Windows, for dubitable benefit.

I could see a reasonable compromise where
- an extensive test matrix is hidden behind an EXPENSIVE_WILDMATCH prereq,
- the test matrix would be written in a much more understandable way, i.e.
  using English words rather than "1"s. If need be, there could be blocks
  ("test this with case-sensitive matching", "skip case-sensitive matching",
  you get the idea),
- these magic skippings of certain test cases (where the (non-traced)
  `create_test_file()` function returns 1 for certain things) still would
  need to go away, in favor probably of prereqs and/or blocks where flags
  are set accordingly in a preamble,
- by default, i.e. without the EXPENSIVE_WILDMATCH prereq, it should test
  a *tiny* subset that is indicative of the most likely bugs.

As it is, I like 8/7 in the present form for all the wrong reasons: it protects me from the damage a full t3070 would do to me.

Ciao, Dscho

Ævar Arnfjörð Bjarmason· Jan 6, 2018, 13:32 UTC · re: Johannes Schindelin · lore

Re: [PATCH v4 8/7] wildmatch test: skip file creation tests on Windows proper

On Sat, Jan 06 2018, Johannes Schindelin jotted:
Show 38 quoted lines
> Hi Junio,
>
> On Fri, 5 Jan 2018, Junio C Hamano wrote:
>
>> Ævar Arnfjörð Bjarmason  <avarab@gmail.com> writes:
>>
>> > Skip the newly added file creation tests on Windows proper, these
>> > already work under Cygwin, but as that involves a significant
>> > emulation layer the results are different under Windows proper with
>> > MinGW.
>> > ...
>> > diff --git a/t/t3070-wildmatch.sh b/t/t3070-wildmatch.sh
>> > index f606f91acb..50a53e7a62 100755
>> > --- a/t/t3070-wildmatch.sh
>> > +++ b/t/t3070-wildmatch.sh
>> > @@ -7,6 +7,14 @@ test_description='wildmatch tests'
>> >  create_test_file() {
>> >  	file=$1
>> >
>> > +	# These tests limp along under Cygwin, but the failures on
>> > +	# native Windows are still too many. Skip file tests there
>> > +	# until they're sorted out.
>> > +	if test_have_prereq MINGW
>> > +	then
>> > +		return 1
>> > +	fi
>> > +
>>
>> That looks to be a nuclear option.
>
> Indeed:
>
> 	# still have 84 known breakage(s)
> 	# failed 52 among remaining 1428 test(s)
> 	1..1512
>
> Let's just switch it off completely because 52 of those 1512 test cases
> break only on Windows? Pretty heavy-handed.

Can you please provide me with the output of the test under -v -x -d from github.com:avar/git.git wildmatch-refactor-8 branch?

It has some improvements that should make things a bit faster for you, but also most of the logic is now in test_expect_success so -x is more helpful.

I should then be able to fix these 52 remaining cases (and at least 1 of them should be fixed already).

Show 50 quoted lines
> But do read on.
>
>> For now it may be suffice, but somehow it feels that it goes directly
>> against Dscho's wish to treat (or pretend to treat) Windows as
>> first-class citizens and/or just like other platforms.
>
> It not only goes against my wish to treat Windows as a normal citizen
> instead of like Rey's parents, it also goes against my wish to have a
> focused and meaningful test suite. Nobody likes to run tests that take too
> long. And look at this:
>
> 	...
> 	ok 1511 - ipathmatch: match 'Z' '[Z-y]'
> 	ok 1512 - ipathmatch(ls): match '[Z-y]' 'Z'
> 	# still have 84 known breakage(s)
> 	# failed 52 among remaining 1428 test(s)
> 	1..1512
>
> 	real    5m51.432s
> 	user    0m33.986s
> 	sys     2m13.162s
>
> Yep. It takes *over eight minutes*.
>
> And this is a *fast* machine.
>
> Why? Because of the completely overboard testing of all kinds of
> *potential* breakages *at some point* in the future.
>
> I understand that Ævar wants to increase test coverage. I am sympathetic
> to this cause.
>
> But I completely disagree that increasing the test coverage beyond reason
> is a good thing. Tests *can* take too long, and they do, in practice, and
> the results are always problematic: every developer who has to deal with
> test suites that take too long... does not run them. As simple as that.
> And then you have *zero* test coverage. Pretty stupid, eh? And contrary to
> your intentions, too.
>
> So yes, I think that it has been proven beyond any doubt that t3070 takes
> *waaaaaaaaaay* too long on Windows, for dubitable benefit.
>
> I could see a reasonable compromise where
>
> - an extensive test matrix is hidden behind an EXPENSIVE_WILDMATCH prereq,
>
> - the test matrix would be written in a much more understandable way, i.e.
>   using English words rather than "1"s. If need be, there could be blocks
>   ("test this with case-sensitive matching", "skip case-sensitive matching",
>   you get the idea),

I take your point with the readability of some of this stuff, and will get around to fixing that before the next submission.

> - these magic skippings of certain test cases (where the (non-traced)
>   `create_test_file()` function returns 1 for certain things) still would
>   need to go away, in favor probably of prereqs and/or blocks where flags
>   are set accordingly in a preamble,

This is a lot of work for dubious benefit. I'm not going to try to maintain some exhaustive mapping that's potentially going to be a hash 4-levels deep of:

    os.os_version.fs.vs_version
And that's before we'd get to the potential 6-level crazyness of:
    os.os_version.os_flags.fs.vs_version.fs_flags

It's way easier and more portable (even to OSs or FSs nobody's invented yet) to just test whether a file can be created, and if not skip the test.

As I explained in 20180105221222.28867-1-avarab@gmail.com the actual benefit of this test is that as much as possible is tested *somewhere*. There's no reason to suspect that e.g. Linux will overnight make the character ":" illegal in filenames and we'll be the only ones who notice it.

Since we don't treat ":" or any other character differently for the purposes of glob matching on Windows, but *do* treat the raw glob matching differently than calling wildmatch() directly, as the current tests do, I really don't see what the point of this exercises would be.

> - by default, i.e. without the EXPENSIVE_WILDMATCH prereq, it should test
>   a *tiny* subset that is indicative of the most likely bugs.
> As it is, I like 8/7 in the present form for all the wrong reasons: it
> protects me from the damage a full t3070 would do to me.

This test takes around 8 seconds to run on a 3.4GHz i7 on Linux, and around 4 seconds on a 2.6GHz i5 on my SSD laptop on Linux.

I agree that there should be some prerequisite to skip this on Windows by default since 6 minutes is clearly excessive (although I think you'll find it runs a bit faster in the branch above), but that should be something like:

    test_lazy_prereq EXPENSIVE_ON_WINDOWS '
            test -n "$GIT_TEST_LONG" || test_have_prereq !MINGW,!CYGWIN
    '

As the long runtime is not inherent to the test, but to excessive slowness caused by certain operations on certain platforms, or maybe it should be EXPENSIVE_ON_SLOW_FS or EXPENSIVE_IF_FORKING_IS_SLOW or if we'd like to generalize it.

Johannes Schindelin· Jan 6, 2018, 20:46 UTC · re: Ævar Arnfjörð Bjarmason · lore

Re: [PATCH v4 8/7] wildmatch test: skip file creation tests on Windows proper

Hi Ævar,
On Sat, 6 Jan 2018, Ævar Arnfjörð Bjarmason wrote:
> As I explained in 20180105221222.28867-1-avarab@gmail.com the actual
> benefit of this test is that as much as possible is tested
> *somewhere*.

And what I am trying to get across is that your tests are excessive. I do not see the benefit in running such an excessive, overzealous test.

You say that Linux will not overnight stop supporting colons in filenames, which kind of misses the point that the question is more about new platforms needing Git support with a *filesystem* that simply does not meet one of your many tests' expectations.

But what is equally true is that few changes are to be expected in the wildmatch code. And you know as well as I that it is possible to come up with a careful, small set of test cases that will most likely identify breakages.

After all, when there is a bug in some patch to the wildmatch machinery, you do not need 512 test cases to fail. A single failing test case is definitely enough.

I'll test the branch you indicated on Monday, just because you put effort into it.

But please note that it does not change the fact that an effective test suite requires a balance between the need to run fast (if *every* aspect of Git was tested as extensively as your current t3070, even on Linux it would take hours and hours to finish the test suite, making it stupidly expensive for everybody to run) and the need to catch regressions.

It is a well-established rule in effective DevOps that you want lean test suites. Actionable test suites. It is enough for *one* test to fail. When a test fails, it should be as easy to understand as possible what is going wrong. If there are no regressions, the test suite should be passing *fast*.

On Windows, it takes 70-90 minutes *on a fast* machine. That is a huge failure on our part: this is the test suite we designed "to be portable". All I am trying to do here is to prevent even more damage. I will appreciate any assistance to that end. I understand that most developers on this list simply don't care. And that's just too bad, because we could do a lot better. And we should, too.

Ciao, Johannes

Johannes Schindelin· Jan 8, 2018, 12:46 UTC · re: Ævar Arnfjörð Bjarmason · lore

Re: [PATCH v4 8/7] wildmatch test: skip file creation tests on Windows proper

Hi Ævar,
On Sat, 6 Jan 2018, Ævar Arnfjörð Bjarmason wrote:
> Can you please provide me with the output of the test under -v -x -d
> from github.com:avar/git.git wildmatch-refactor-8 branch?
With -v -x -i:
-- snip --
[...]
expecting success:
                                printf '%s' '?a?b' >expect &&
                                git --glob-pathspecs ls-files -z -- '\??\?b' >actual.raw 2>actual.err &&
        tr -d '\0' <actual.raw >actual &&
        >expect.err &&
        test_cmp expect.err actual.err &&
        test_cmp expect actual
++ printf %s '?a?b'
++ git --glob-pathspecs ls-files -z -- '\??\?b'
+ test_eval_ret_=128
+ want_trace
+ test t = t
+ test t = t
+ set +x
error: last command exited with $?=128
not ok 734 - wildmatch(ls): match '\??\?b' '?a?b'
#
#                                       printf '%s' '?a?b' >expect &&
#                                       git --glob-pathspecs ls-files -z
#                                       -- '\??\?b' >actual.raw
#                                       2>actual.err &&
#
#               tr -d '\0' <actual.raw >actual &&
#               >expect.err &&
#               test_cmp expect.err actual.err &&
#               test_cmp expect actual
#

real 2m9.127s user 0m10.026s sys 1m0.617s -- snap --

and

-- snip -- $ cat ./trash\ directory.t3070-wildmatch/actual.err fatal: Invalid path '/??': No such file or directory -- snap --

As to the speed:

-- snip -- # still have 144 known breakage(s) # failed 28 among remaining 1746 test(s) 1..1890

real 5m55.162s user 0m26.396s sys 2m34.152s -- snap --

... seems to be in the same ballpark. You are just leaning way too heavily on Unix shell scripting.

FWIW the breakages are:

-- snip -- not ok 734 - wildmatch(ls): match '\??\?b' '?a?b' # # printf '%s' '?a?b' >expect && # git --glob-pathspecs ls-files -z # -- '\??\?b' >actual.raw # 2>actual.err && # # tr -d '\0' <actual.raw >actual && # >expect.err && # test_cmp expect.err actual.err && # test_cmp expect actual # ok 735 - iwildmatch: match '?a?b' '\??\?b' not ok 736 - iwildmatch(ls): match '\??\?b' '?a?b' # # printf '%s' '?a?b' >expect && # git --glob-pathspecs # --icase-pathspecs ls-files -z -- # '\??\?b' >actual.raw 2>actual.err # && # # tr -d '\0' <actual.raw >actual && # >expect.err && # test_cmp expect.err actual.err && # test_cmp expect actual # ok 737 - pathmatch: match '?a?b' '\??\?b' not ok 738 - pathmatch(ls): match '\??\?b' '?a?b' # # printf '%s' '?a?b' >expect && # git ls-files -z -- '\??\?b' # >actual.raw 2>actual.err && # # tr -d '\0' <actual.raw >actual && # >expect.err && # test_cmp expect.err actual.err && # test_cmp expect actual # ok 739 - ipathmatch: match '?a?b' '\??\?b' not ok 740 - ipathmatch(ls): match '\??\?b' '?a?b' # # printf '%s' '?a?b' >expect && # git --icase-pathspecs ls-files -z # -- '\??\?b' >actual.raw # 2>actual.err && # # tr -d '\0' <actual.raw >actual && # >expect.err && # test_cmp expect.err actual.err && # test_cmp expect actual # ok 741 - cleanup after previous file test ok 742 - setup wildtest file test for abc ok 743 - wildmatch: match 'abc' '\a\b\c' not ok 744 - wildmatch(ls): match '\a\b\c' 'abc' # # printf '%s' 'abc' >expect && # git --glob-pathspecs ls-files -z # -- '\a\b\c' >actual.raw # 2>actual.err && # # tr -d '\0' <actual.raw >actual && # >expect.err && # test_cmp expect.err actual.err && # test_cmp expect actual # ok 745 - iwildmatch: match 'abc' '\a\b\c' not ok 746 - iwildmatch(ls): match '\a\b\c' 'abc' # # printf '%s' 'abc' >expect && # git --glob-pathspecs # --icase-pathspecs ls-files -z -- # '\a\b\c' >actual.raw 2>actual.err # && # # tr -d '\0' <actual.raw >actual && # >expect.err && # test_cmp expect.err actual.err && # test_cmp expect actual # ok 747 - pathmatch: match 'abc' '\a\b\c' not ok 748 - pathmatch(ls): match '\a\b\c' 'abc' # # printf '%s' 'abc' >expect && # git ls-files -z -- '\a\b\c' # >actual.raw 2>actual.err && # # tr -d '\0' <actual.raw >actual && # >expect.err && # test_cmp expect.err actual.err && # test_cmp expect actual # ok 749 - ipathmatch: match 'abc' '\a\b\c' not ok 750 - ipathmatch(ls): match '\a\b\c' 'abc' # # printf '%s' 'abc' >expect && # git --icase-pathspecs ls-files -z # -- '\a\b\c' >actual.raw # 2>actual.err && # # tr -d '\0' <actual.raw >actual && # >expect.err && # test_cmp expect.err actual.err && # test_cmp expect actual # [...] not ok 964 - wildmatch(ls): match '[\-_]' '-' # # printf '%s' '-' >expect && # git --glob-pathspecs ls-files -z # -- '[\-_]' >actual.raw # 2>actual.err && # # tr -d '\0' <actual.raw >actual && # >expect.err && # test_cmp expect.err actual.err && # test_cmp expect actual # ok 965 - iwildmatch: match '-' '[\-_]' not ok 966 - iwildmatch(ls): match '[\-_]' '-' # # printf '%s' '-' >expect && # git --glob-pathspecs # --icase-pathspecs ls-files -z -- # '[\-_]' >actual.raw 2>actual.err # && # # tr -d '\0' <actual.raw >actual && # >expect.err && # test_cmp expect.err actual.err && # test_cmp expect actual # ok 967 - pathmatch: match '-' '[\-_]' not ok 968 - pathmatch(ls): match '[\-_]' '-' # # printf '%s' '-' >expect && # git ls-files -z -- '[\-_]' # >actual.raw 2>actual.err && # # tr -d '\0' <actual.raw >actual && # >expect.err && # test_cmp expect.err actual.err && # test_cmp expect actual # ok 969 - ipathmatch: match '-' '[\-_]' not ok 970 - ipathmatch(ls): match '[\-_]' '-' # # printf '%s' '-' >expect && # git --icase-pathspecs ls-files -z # -- '[\-_]' >actual.raw # 2>actual.err && # # tr -d '\0' <actual.raw >actual && # >expect.err && # test_cmp expect.err actual.err && # test_cmp expect actual # ok 971 - cleanup after previous file test ok 972 - setup wildtest file test for ] ok 973 - wildmatch: match ']' '[\]]' not ok 974 - wildmatch(ls): match '[\]]' ']' # # printf '%s' ']' >expect && # git --glob-pathspecs ls-files -z # -- '[\]]' >actual.raw 2>actual.err # && # # tr -d '\0' <actual.raw >actual && # >expect.err && # test_cmp expect.err actual.err && # test_cmp expect actual # ok 975 - iwildmatch: match ']' '[\]]' not ok 976 - iwildmatch(ls): match '[\]]' ']' # # printf '%s' ']' >expect && # git --glob-pathspecs # --icase-pathspecs ls-files -z -- # '[\]]' >actual.raw 2>actual.err && # # tr -d '\0' <actual.raw >actual && # >expect.err && # test_cmp expect.err actual.err && # test_cmp expect actual # ok 977 - pathmatch: match ']' '[\]]' not ok 978 - pathmatch(ls): match '[\]]' ']' # # printf '%s' ']' >expect && # git ls-files -z -- '[\]]' # >actual.raw 2>actual.err && # # tr -d '\0' <actual.raw >actual && # >expect.err && # test_cmp expect.err actual.err && # test_cmp expect actual # ok 979 - ipathmatch: match ']' '[\]]' not ok 980 - ipathmatch(ls): match '[\]]' ']' # # printf '%s' ']' >expect && # git --icase-pathspecs ls-files -z # -- '[\]]' >actual.raw 2>actual.err # && # # tr -d '\0' <actual.raw >actual && # >expect.err && # test_cmp expect.err actual.err && # test_cmp expect actual # [...] not ok 1284 - wildmatch(ls): match '[A-\\]' 'G' # # printf '%s' 'G' >expect && # git --glob-pathspecs ls-files -z # -- '[A-\\]' >actual.raw # 2>actual.err && # # tr -d '\0' <actual.raw >actual && # >expect.err && # test_cmp expect.err actual.err && # test_cmp expect actual # ok 1285 - iwildmatch: match 'G' '[A-\\]' not ok 1286 - iwildmatch(ls): match '[A-\\]' 'G' # # printf '%s' 'G' >expect && # git --glob-pathspecs # --icase-pathspecs ls-files -z -- # '[A-\\]' >actual.raw 2>actual.err # && # # tr -d '\0' <actual.raw >actual && # >expect.err && # test_cmp expect.err actual.err && # test_cmp expect actual # ok 1287 - pathmatch: match 'G' '[A-\\]' not ok 1288 - pathmatch(ls): match '[A-\\]' 'G' # # printf '%s' 'G' >expect && # git ls-files -z -- '[A-\\]' # >actual.raw 2>actual.err && # # tr -d '\0' <actual.raw >actual && # >expect.err && # test_cmp expect.err actual.err && # test_cmp expect actual # ok 1289 - ipathmatch: match 'G' '[A-\\]' not ok 1290 - ipathmatch(ls): match '[A-\\]' 'G' # # printf '%s' 'G' >expect && # git --icase-pathspecs ls-files -z # -- '[A-\\]' >actual.raw # 2>actual.err && # # tr -d '\0' <actual.raw >actual && # >expect.err && # test_cmp expect.err actual.err && # test_cmp expect actual # [...] not ok 1374 - wildmatch(ls): match '[\1-\3]' '2' # # printf '%s' '2' >expect && # git --glob-pathspecs ls-files -z # -- '[\1-\3]' >actual.raw # 2>actual.err && # # tr -d '\0' <actual.raw >actual && # >expect.err && # test_cmp expect.err actual.err && # test_cmp expect actual # ok 1375 - iwildmatch: match '2' '[\1-\3]' not ok 1376 - iwildmatch(ls): match '[\1-\3]' '2' # # printf '%s' '2' >expect && # git --glob-pathspecs # --icase-pathspecs ls-files -z -- # '[\1-\3]' >actual.raw 2>actual.err # && # # tr -d '\0' <actual.raw >actual && # >expect.err && # test_cmp expect.err actual.err && # test_cmp expect actual # ok 1377 - pathmatch: match '2' '[\1-\3]' not ok 1378 - pathmatch(ls): match '[\1-\3]' '2' # # printf '%s' '2' >expect && # git ls-files -z -- '[\1-\3]' # >actual.raw 2>actual.err && # # tr -d '\0' <actual.raw >actual && # >expect.err && # test_cmp expect.err actual.err && # test_cmp expect actual # ok 1379 - ipathmatch: match '2' '[\1-\3]' not ok 1380 - ipathmatch(ls): match '[\1-\3]' '2' # # printf '%s' '2' >expect && # git --icase-pathspecs ls-files -z # -- '[\1-\3]' >actual.raw # 2>actual.err && # # tr -d '\0' <actual.raw >actual && # >expect.err && # test_cmp expect.err actual.err && # test_cmp expect actual # [...] not ok 1424 - wildmatch(ls): match '[[-\]]' ']' # # printf '%s' ']' >expect && # git --glob-pathspecs ls-files -z # -- '[[-\]]' >actual.raw # 2>actual.err && # # tr -d '\0' <actual.raw >actual && # >expect.err && # test_cmp expect.err actual.err && # test_cmp expect actual # ok 1425 - iwildmatch: match ']' '[[-\]]' not ok 1426 - iwildmatch(ls): match '[[-\]]' ']' # # printf '%s' ']' >expect && # git --glob-pathspecs # --icase-pathspecs ls-files -z -- # '[[-\]]' >actual.raw 2>actual.err # && # # tr -d '\0' <actual.raw >actual && # >expect.err && # test_cmp expect.err actual.err && # test_cmp expect actual # ok 1427 - pathmatch: match ']' '[[-\]]' not ok 1428 - pathmatch(ls): match '[[-\]]' ']' # # printf '%s' ']' >expect && # git ls-files -z -- '[[-\]]' # >actual.raw 2>actual.err && # # tr -d '\0' <actual.raw >actual && # >expect.err && # test_cmp expect.err actual.err && # test_cmp expect actual # ok 1429 - ipathmatch: match ']' '[[-\]]' not ok 1430 - ipathmatch(ls): match '[[-\]]' ']' # # printf '%s' ']' >expect && # git --icase-pathspecs ls-files -z # -- '[[-\]]' >actual.raw # 2>actual.err && # # tr -d '\0' <actual.raw >actual && # >expect.err && # test_cmp expect.err actual.err && # test_cmp expect actual # -- snap --

Ciao, Dscho

Junio C Hamano· Jan 8, 2018, 18:49 UTC · re: Ævar Arnfjörð Bjarmason · lore

Re: [PATCH v4 8/7] wildmatch test: skip file creation tests on Windows proper

Ævar Arnfjörð Bjarmason <avarab@gmail.com> writes:
Show 13 quoted lines
> I agree that there should be some prerequisite to skip this on Windows
> by default since 6 minutes is clearly excessive (although I think you'll
> find it runs a bit faster in the branch above), but that should be
> something like:
>
>     test_lazy_prereq EXPENSIVE_ON_WINDOWS '
>             test -n "$GIT_TEST_LONG" || test_have_prereq !MINGW,!CYGWIN
>     '
>
> As the long runtime is not inherent to the test, but to excessive
> slowness caused by certain operations on certain platforms, or maybe it
> should be EXPENSIVE_ON_SLOW_FS or EXPENSIVE_IF_FORKING_IS_SLOW or if
> we'd like to generalize it.

We already do skip overly long tests everywhere unless explicitly asked to run them, and the above sounds like a good way to go.

Duy Nguyen· Jan 7, 2018, 02:51 UTC · re: Johannes Schindelin · lore

Re: [PATCH v4 8/7] wildmatch test: skip file creation tests on Windows proper

On Sat, Jan 6, 2018 at 7:51 PM, Johannes Schindelin <Johannes.Schindelin@gmx.de> wrote:

Show 15 quoted lines
> Nobody likes to run tests that take too
> long. And look at this:
>
>         ...
>         ok 1511 - ipathmatch: match 'Z' '[Z-y]'
>         ok 1512 - ipathmatch(ls): match '[Z-y]' 'Z'
>         # still have 84 known breakage(s)
>         # failed 52 among remaining 1428 test(s)
>         1..1512
>
>         real    5m51.432s
>         user    0m33.986s
>         sys     2m13.162s
>
> Yep. It takes *over eight minutes*.

I suppose this is because the sheer number of test cases adds a lot of shell overhead on Windows. I wonder if it's better to rewrite this test in C instead. We start to do some more unit testing here and there and kind of abuse the sh-based test framework for this. Having a proper unit test framework would be good anyway since it's sometimes hard to create a specific scenario with high level commands.

-- 
Duy
Johannes Schindelin· Jan 8, 2018, 12:25 UTC · re: Duy Nguyen · lore

Re: [PATCH v4 8/7] wildmatch test: skip file creation tests on Windows proper

Hi Duy,
On Sun, 7 Jan 2018, Duy Nguyen wrote:
Show 24 quoted lines
> On Sat, Jan 6, 2018 at 7:51 PM, Johannes Schindelin
> <Johannes.Schindelin@gmx.de> wrote:
> > Nobody likes to run tests that take too
> > long. And look at this:
> >
> >         ...
> >         ok 1511 - ipathmatch: match 'Z' '[Z-y]'
> >         ok 1512 - ipathmatch(ls): match '[Z-y]' 'Z'
> >         # still have 84 known breakage(s)
> >         # failed 52 among remaining 1428 test(s)
> >         1..1512
> >
> >         real    5m51.432s
> >         user    0m33.986s
> >         sys     2m13.162s
> >
> > Yep. It takes *over eight minutes*.
> 
> I suppose this is because the sheer number of test cases adds a lot of
> shell overhead on Windows. I wonder if it's better to rewrite this
> test in C instead. We start to do some more unit testing here and
> there and kind of abuse the sh-based test framework for this. Having a
> proper unit test framework would be good anyway since it's sometimes
> hard to create a specific scenario with high level commands.

I agree that it would make a ton of sense to use a proper, portable test framework written in pure, portable C.

However, this ship has long sailed, hasn't it?

Of course, we do have useful stuff in t/helper/. And we have precedent for more sensible bulk testing that does not require sh to generate or provide lists of test data, see e.g. the basename/dirname tests. And we could organize t/helper/ better, including a refactoring to have a single binary rather than tons and tons of binaries that all link to libgit.a and take a lot of space (even with LZMA compression, the current test artifacts take about 90 megabyte!).

If I had the time I would write this up as a valuable GSoC project. Not that Junio cares. But I do.

Ciao, Dscho

Duy Nguyen· Jan 10, 2018, 09:07 UTC · re: Johannes Schindelin · lore

Re: [PATCH v4 8/7] wildmatch test: skip file creation tests on Windows proper

On Mon, Jan 08, 2018 at 01:25:04PM +0100, Johannes Schindelin wrote:
> I agree that it would make a ton of sense to use a proper, portable test
> framework written in pure, portable C.
> 
> However, this ship has long sailed, hasn't it?

If you meant converting the whole test suite, oh yeah that's not gonna happen. But it's still possible to have some tests written in C.

I played a bit with this. The assumption is if it's agreed that we can get something bare bone (but functional) in then we could start having more and more C-based unit tests in future and also improve the C framework to be on par with shell one on the side.

There are still some minor problems with my patch, and a bunch of optional features not supported. But the numbers looks unexpectedly promising. 0.7 seconds on the shell version and 0.03 on the C one.

One disadvantage of this though, if this kind of framework does not get popular, then any new test feature must be added at both places but it's a waste of time to support both. So...

Anyway here it is. t3071 is the same as t3070 (this is on master)
 Makefile                             |   2 +
 t/helper/test-3071-wildmatch.c (new) | 273 ++++++++++++++++++++++++++++++++++++++++++++++++++
 t/t3071-wildmatch.sh (new +x)        |   3 +
 test-lib.c (new)                     |  97 ++++++++++++++++++
 test-lib.h (new)                     |   5 +
-- 8< --
Show changes to 5 files +380 −2

Makefile, t/helper/test-3071-wildmatch.c, t/t3071-wildmatch.sh, test-lib.c, test-lib.h

diff --git a/Makefile b/Makefile
index 2a81ae22e9..567387b558 100644
--- a/Makefile
+++ b/Makefile
@@ -644,6 +644,7 @@ X =
 
 PROGRAMS += $(patsubst %.o,git-%$X,$(PROGRAM_OBJS))
 
+TEST_PROGRAMS_NEED_X += test-3071-wildmatch
 TEST_PROGRAMS_NEED_X += test-chmtime
 TEST_PROGRAMS_NEED_X += test-ctype
 TEST_PROGRAMS_NEED_X += test-config
@@ -895,6 +896,7 @@ LIB_OBJS += sub-process.o
 LIB_OBJS += symlinks.o
 LIB_OBJS += tag.o
 LIB_OBJS += tempfile.o
+LIB_OBJS += test-lib.o
 LIB_OBJS += tmp-objdir.o
 LIB_OBJS += trace.o
 LIB_OBJS += trailer.o
diff --git a/t/helper/test-3071-wildmatch.c b/t/helper/test-3071-wildmatch.c
new file mode 100644
index 0000000000..24a657202d
--- /dev/null
+++ b/t/helper/test-3071-wildmatch.c
@@ -0,0 +1,273 @@
+#include "cache.h"
+#include "test-lib.h"
+
+struct match_input {
+	int expect_true;
+	const char *text;
+	const char *pattern;
+};
+
+static struct match_input match_tests[] = {
+	/* Basic wildmatch features */
+	{ 1, "foo", "foo" },
+	{ 0, "foo", "bar" },
+	{ 1, "", "" },
+	{ 1, "foo", "???" },
+	{ 0, "foo", "??" },
+	{ 1, "foo", "*" },
+	{ 1, "foo", "f*" },
+	{ 0, "foo", "*f" },
+	{ 1, "foo", "*foo*" },
+	{ 1, "foobar", "*ob*a*r*" },
+	{ 1, "aaaaaaabababab", "*ab" },
+	{ 1, "foo*", "foo\\*" },
+	{ 0, "foobar", "foo\\*bar" },
+	{ 1, "f\\oo", "f\\\\oo" },
+	{ 1, "ball", "*[al]?" },
+	{ 0, "ten", "[ten]" },
+	{ 0, "ten", "**[!te]" },
+	{ 0, "ten", "**[!ten]" },
+	{ 1, "ten", "t[a-g]n" },
+	{ 0, "ten", "t[!a-g]n" },
+	{ 1, "ton", "t[!a-g]n" },
+	{ 1, "ton", "t[^a-g]n" },
+	{ 1, "a]b", "a[]]b" },
+	{ 1, "a-b", "a[]-]b" },
+	{ 1, "a]b", "a[]-]b" },
+	{ 0, "aab", "a[]-]b" },
+	{ 1, "aab", "a[]a-]b" },
+	{ 1, "]", "]" },
+
+	/* Extended slash-matching features */
+	{ 0, "foo/baz/bar", "foo*bar" },
+	{ 0, "foo/baz/bar", "foo**bar" },
+	{ 0, "foobazbar", "foo**bar" },
+	{ 1, "foo/baz/bar", "foo/**/bar" },
+	{ 1, "foo/baz/bar", "foo/**/**/bar" },
+	{ 1, "foo/b/a/z/bar", "foo/**/bar" },
+	{ 1, "foo/b/a/z/bar", "foo/**/**/bar" },
+	{ 1, "foo/bar", "foo/**/bar" },
+	{ 1, "foo/bar", "foo/**/**/bar" },
+	{ 0, "foo/bar", "foo?bar" },
+	{ 0, "foo/bar", "foo[/]bar" },
+	{ 0, "foo/bar", "foo[^a-z]bar" },
+	{ 0, "foo/bar", "f[^eiu][^eiu][^eiu][^eiu][^eiu]r" },
+	{ 1, "foo-bar", "f[^eiu][^eiu][^eiu][^eiu][^eiu]r" },
+	{ 1, "foo", "**/foo" },
+	{ 1, "XXX/foo", "**/foo" },
+	{ 1, "bar/baz/foo", "**/foo" },
+	{ 0, "bar/baz/foo", "*/foo" },
+	{ 0, "foo/bar/baz", "**/bar*" },
+	{ 1, "deep/foo/bar/baz", "**/bar/*" },
+	{ 0, "deep/foo/bar/baz/", "**/bar/*" },
+	{ 1, "deep/foo/bar/baz/", "**/bar/**" },
+	{ 0, "deep/foo/bar", "**/bar/*" },
+	{ 1, "deep/foo/bar/", "**/bar/**" },
+	{ 0, "foo/bar/baz", "**/bar**" },
+	{ 1, "foo/bar/baz/x", "*/bar/**" },
+	{ 0, "deep/foo/bar/baz/x", "*/bar/**" },
+	{ 1, "deep/foo/bar/baz/x", "**/bar/*/*" },
+
+	/* Various additional tests */
+	{ 0, "acrt", "a[c-c]st" },
+	{ 1, "acrt", "a[c-c]rt" },
+	{ 0, "]", "[!]-]" },
+	{ 1, "a", "[!]-]" },
+	{ 0, "", "\\" },
+	{ 0, "\\", "\\" },
+	{ 0, "XXX/\\", "*/\\" },
+	{ 1, "XXX/\\", "*/\\\\" },
+	{ 1, "foo", "foo" },
+	{ 1, "@foo", "@foo" },
+	{ 0, "foo", "@foo" },
+	{ 1, "[ab]", "\\[ab]" },
+	{ 1, "[ab]", "[[]ab]" },
+	{ 1, "[ab]", "[[:]ab]" },
+	{ 0, "[ab]", "[[::]ab]" },
+	{ 1, "[ab]", "[[:digit]ab]" },
+	{ 1, "[ab]", "[\\[:]ab]" },
+	{ 1, "?a?b", "\\??\\?b" },
+	{ 1, "abc", "\\a\\b\\c" },
+	{ 0, "foo", "" },
+	{ 1, "foo/bar/baz/to", "**/t[o]" },
+
+	/* Character class tests */
+	{ 1, "a1B", "[[:alpha:]][[:digit:]][[:upper:]]" },
+	{ 0, "a", "[[:digit:][:upper:][:space:]]" },
+	{ 1, "A", "[[:digit:][:upper:][:space:]]" },
+	{ 1, "1", "[[:digit:][:upper:][:space:]]" },
+	{ 0, "1", "[[:digit:][:upper:][:spaci:]]" },
+	{ 1, " ", "[[:digit:][:upper:][:space:]]" },
+	{ 0, ".", "[[:digit:][:upper:][:space:]]" },
+	{ 1, ".", "[[:digit:][:punct:][:space:]]" },
+	{ 1, "5", "[[:xdigit:]]" },
+	{ 1, "f", "[[:xdigit:]]" },
+	{ 1, "D", "[[:xdigit:]]" },
+	{ 1, "_", "[[:alnum:][:alpha:][:blank:][:cntrl:][:digit:][:graph:][:lower:][:print:][:punct:][:space:][:upper:][:xdigit:]]" },
+	{ 1, ".", "[^[:alnum:][:alpha:][:blank:][:cntrl:][:digit:][:lower:][:space:][:upper:][:xdigit:]]" },
+	{ 1, "5", "[a-c[:digit:]x-z]" },
+	{ 1, "b", "[a-c[:digit:]x-z]" },
+	{ 1, "y", "[a-c[:digit:]x-z]" },
+	{ 0, "q", "[a-c[:digit:]x-z]" },
+
+	/* Additional tests, including some malformed wildmats */
+	{ 1, "]", "[\\\\-^]" },
+	{ 0, "[", "[\\\\-^]" },
+	{ 1, "-", "[\\-_]" },
+	{ 1, "]", "[\\]]" },
+	{ 0, "\\]", "[\\]]" },
+	{ 0, "\\", "[\\]]" },
+	{ 0, "ab", "a[]b" },
+	{ 0, "a[]b", "a[]b" },
+	{ 0, "ab[", "ab[" },
+	{ 0, "ab", "[!" },
+	{ 0, "ab", "[-" },
+	{ 1, "-", "[-]" },
+	{ 0, "-", "[a-" },
+	{ 0, "-", "[!a-" },
+	{ 1, "-", "[--A]" },
+	{ 1, "5", "[--A]" },
+	{ 1, " ", "[ --]" },
+	{ 1, "$", "[ --]" },
+	{ 1, "-", "[ --]" },
+	{ 0, "0", "[ --]" },
+	{ 1, "-", "[---]" },
+	{ 1, "-", "[------]" },
+	{ 0, "j", "[a-e-n]" },
+	{ 1, "-", "[a-e-n]" },
+	{ 1, "a", "[!------]" },
+	{ 0, "[", "[]-a]" },
+	{ 1, "^", "[]-a]" },
+	{ 0, "^", "[!]-a]" },
+	{ 1, "[", "[!]-a]" },
+	{ 1, "^", "[a^bc]" },
+	{ 1, "-b]", "[a-]b]" },
+	{ 0, "\\", "[\\]" },
+	{ 1, "\\", "[\\\\]" },
+	{ 0, "\\", "[!\\\\]" },
+	{ 1, "G", "[A-\\\\]" },
+	{ 0, "aaabbb", "b*a" },
+	{ 0, "aabcaa", "*ba*" },
+	{ 1, ",", "[,]" },
+	{ 1, ",", "[\\\\,]" },
+	{ 1, "\\", "[\\\\,]" },
+	{ 1, "-", "[,-.]" },
+	{ 0, "+", "[,-.]" },
+	{ 0, "-.]", "[,-.]" },
+	{ 1, "2", "[\\1-\\3]" },
+	{ 1, "3", "[\\1-\\3]" },
+	{ 0, "4", "[\\1-\\3]" },
+	{ 1, "\\", "[[-\\]]" },
+	{ 1, "[", "[[-\\]]" },
+	{ 1, "]", "[[-\\]]" },
+	{ 0, "-", "[[-\\]]" },
+
+	/* Test recursion and the abort code (use "wildtest -i" to see iteration counts) */
+	{ 1, "-adobe-courier-bold-o-normal--12-120-75-75-m-70-iso8859-1", "-*-*-*-*-*-*-12-*-*-*-m-*-*-*" },
+	{ 0, "-adobe-courier-bold-o-normal--12-120-75-75-X-70-iso8859-1", "-*-*-*-*-*-*-12-*-*-*-m-*-*-*" },
+	{ 0, "-adobe-courier-bold-o-normal--12-120-75-75-/-70-iso8859-1", "-*-*-*-*-*-*-12-*-*-*-m-*-*-*" },
+	{ 1, "XXX/adobe/courier/bold/o/normal//12/120/75/75/m/70/iso8859/1", "XXX/*/*/*/*/*/*/12/*/*/*/m/*/*/*" },
+	{ 0, "XXX/adobe/courier/bold/o/normal//12/120/75/75/X/70/iso8859/1", "XXX/*/*/*/*/*/*/12/*/*/*/m/*/*/*" },
+	{ 1, "abcd/abcdefg/abcdefghijk/abcdefghijklmnop.txt", "**/*a*b*g*n*t" },
+	{ 0, "abcd/abcdefg/abcdefghijk/abcdefghijklmnop.txtz", "**/*a*b*g*n*t" },
+	{ 0, "foo", "*/*/*" },
+	{ 0, "foo/bar", "*/*/*" },
+	{ 1, "foo/bba/arr", "*/*/*" },
+	{ 0, "foo/bb/aa/rr", "*/*/*" },
+	{ 1, "foo/bb/aa/rr", "**/**/**" },
+	{ 1, "abcXdefXghi", "*X*i" },
+	{ 0, "ab/cXd/efXg/hi", "*X*i" },
+	{ 1, "ab/cXd/efXg/hi", "*/*X*/*/*i" },
+	{ 1, "ab/cXd/efXg/hi", "**/*X*/**/*i" },
+
+	/* Case-sensitivity features */
+	{ 0, "a", "[A-Z]" },
+	{ 1, "A", "[A-Z]" },
+	{ 0, "A", "[a-z]" },
+	{ 1, "a", "[a-z]" },
+	{ 0, "a", "[[:upper:]]" },
+	{ 1, "A", "[[:upper:]]" },
+	{ 0, "A", "[[:lower:]]" },
+	{ 1, "a", "[[:lower:]]" },
+	{ 0, "A", "[B-Za]" },
+	{ 1, "a", "[B-Za]" },
+	{ 0, "A", "[B-a]" },
+	{ 1, "a", "[B-a]" },
+	{ 0, "z", "[Z-y]" },
+	{ 1, "Z", "[Z-y]" },
+};
+
+static struct match_input pathmatch_tests[] = {
+	{ 1, "foo", "foo" },
+	{ 0, "foo", "fo" },
+	{ 1, "foo/bar", "foo/bar" },
+	{ 1, "foo/bar", "foo/*" },
+	{ 1, "foo/bba/arr", "foo/*" },
+	{ 1, "foo/bba/arr", "foo/**" },
+	{ 1, "foo/bba/arr", "foo*" },
+	{ 1, "foo/bba/arr", "foo**" },
+	{ 1, "foo/bba/arr", "foo/*arr" },
+	{ 1, "foo/bba/arr", "foo/**arr" },
+	{ 0, "foo/bba/arr", "foo/*z" },
+	{ 0, "foo/bba/arr", "foo/**z" },
+	{ 1, "foo/bar", "foo?bar" },
+	{ 1, "foo/bar", "foo[/]bar" },
+	{ 1, "foo/bar", "foo[^a-z]bar" },
+	{ 0, "foo", "*/*/*" },
+	{ 0, "foo/bar", "*/*/*" },
+	{ 1, "foo/bba/arr", "*/*/*" },
+	{ 1, "foo/bb/aa/rr", "*/*/*" },
+	{ 1, "abcXdefXghi", "*X*i" },
+	{ 1, "ab/cXd/efXg/hi", "*/*X*/*/*i" },
+	{ 1, "ab/cXd/efXg/hi", "*Xg*i" },
+};
+
+static struct match_input icase_match_tests[] = {
+	{ 1, "a", "[A-Z]" },
+	{ 1, "A", "[A-Z]" },
+	{ 1, "A", "[a-z]" },
+	{ 1, "a", "[a-z]" },
+	{ 1, "a", "[[:upper:]]" },
+	{ 1, "A", "[[:upper:]]" },
+	{ 1, "A", "[[:lower:]]" },
+	{ 1, "a", "[[:lower:]]" },
+	{ 1, "A", "[B-Za]" },
+	{ 1, "a", "[B-Za]" },
+	{ 1, "A", "[B-a]" },
+	{ 1, "a", "[B-a]" },
+	{ 1, "z", "[Z-y]" },
+	{ 1, "Z", "[Z-y]" },
+};
+
+static void test_match(const char *name,
+		       const struct match_input *input,
+		       unsigned flags)
+{
+	int ret;
+
+	start_test("%s:  %s match '%s' '%s'",
+		   name,
+		   input->expect_true ? "  " : "no",
+		   input->text, input->pattern);
+	ret = wildmatch(input->pattern, input->text, flags);
+	end_test(input->expect_true ? ret == 0 : ret != 0);
+}
+
+int cmd_main(int ac, const char **av)
+{
+	int i;
+
+	init_test_suite(ac, av);
+
+	for (i = 0; i < ARRAY_SIZE(match_tests); i++)
+		test_match("wildmatch", match_tests + i, WM_PATHNAME);
+
+	for (i = 0; i < ARRAY_SIZE(pathmatch_tests); i++)
+		test_match("pathmatch", pathmatch_tests + i, 0);
+
+	for (i = 0; i < ARRAY_SIZE(icase_match_tests); i++)
+		test_match("iwildmatch", icase_match_tests + i,
+			   WM_PATHNAME | WM_CASEFOLD);
+
+	all_tests_done();
+}
diff --git a/t/t3071-wildmatch.sh b/t/t3071-wildmatch.sh
new file mode 100755
index 0000000000..6e83b4d684
--- /dev/null
+++ b/t/t3071-wildmatch.sh
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+exec helper/test-3071-wildmatch t3071-wildmatch "$@"
diff --git a/test-lib.c b/test-lib.c
new file mode 100644
index 0000000000..8e8b7cd6df
--- /dev/null
+++ b/test-lib.c
@@ -0,0 +1,97 @@
+#include "cache.h"
+#include "test-lib.h"
+
+static int test_failure;
+static int test_count;
+static int test_fixed;
+static int test_broken;
+static int test_success;
+
+static const char *suite_name;
+static int harness_active;
+static char *test_name;
+
+void init_test_suite(int ac, const char **av)
+{
+	char cwd[PATH_MAX];
+
+	harness_active = getenv("HARNESS_ACTIVE") != NULL;
+	suite_name = av[1];
+
+	getcwd(cwd, sizeof(cwd));
+	setenv("TEST_DIRECTORY", cwd, 0);
+	setenv("TEST_OUTPUT_DIRECTORY", getenv("TEST_DIRECTORY"), 0);
+
+	ac--;
+	av++;
+
+	dup2(1, 3);
+}
+
+static int skip_test(void)
+{
+	return 0; /* not supported yet */
+}
+
+int start_test(const char *fmt, ...)
+{
+	va_list ap;
+
+	va_start(ap, fmt);
+	test_name = xstrvfmt(fmt, ap);
+	va_end(ap);
+	test_count++;
+
+	if (skip_test())
+		return 0;
+
+	return 1;
+}
+
+void end_test(int ok)
+{
+	if (ok) {
+		test_success++;
+		dprintf(3, "ok %d - %s\n", test_count, test_name);
+	} else {
+		test_failure++;
+		dprintf(3, "not ok %d - %s\n", test_count, test_name);
+	}
+
+	free(test_name);
+	test_name = NULL;
+
+	/* -i not supported yet */
+}
+
+void all_tests_done(void)
+{
+	if (!getenv("HARNESS_ACTIVE")) {
+		struct strbuf sb = STRBUF_INIT;
+		FILE *fp;
+
+		strbuf_addf(&sb, "mkdir -p %s/test-results",
+			    getenv("TEST_OUTPUT_DIRECTORY"));
+		system(sb.buf);
+		strbuf_release(&sb);
+
+		strbuf_addf(&sb, "%s/test-results/%s.counts",
+			    getenv("TEST_OUTPUT_DIRECTORY"),
+			    suite_name);
+		fp = fopen(sb.buf, "w");
+		strbuf_release(&sb);
+
+		fprintf(fp, "total %d\nsuccess %d\n"
+			"fixed %d\nbroken %d\nfailed %d\n\n",
+			test_count, test_success,
+			test_fixed, test_broken, test_failure);
+		fclose(fp);
+	}
+	if (test_failure) {
+		dprintf(3, "# failed %d among FIXME\n", test_failure);
+	} else {
+		dprintf(3, "# passed all FIXME\n");
+	}
+	dprintf(3, "1..%d\n", test_count);
+	exit(0);
+}
diff --git a/test-lib.h b/test-lib.h
new file mode 100644
index 0000000000..f8122c1719
--- /dev/null
+++ b/test-lib.h
@@ -0,0 +1,5 @@
+void init_test_suite(int ac, const char **av);
+void all_tests_done(void) NORETURN;
+
+int start_test(const char *fmt, ...);
+void end_test(int ok);
-- 8< --

--
Duy
Adam Dinwoodie· Jan 10, 2018, 10:38 UTC · re: Duy Nguyen · lore

Re: [PATCH v4 8/7] wildmatch test: skip file creation tests on Windows proper

On Wednesday 10 January 2018 at 04:07 pm +0700, Duy Nguyen wrote:
Show 17 quoted lines
> On Mon, Jan 08, 2018 at 01:25:04PM +0100, Johannes Schindelin wrote:
> > I agree that it would make a ton of sense to use a proper, portable test
> > framework written in pure, portable C.
> > 
> > However, this ship has long sailed, hasn't it?
> 
> If you meant converting the whole test suite, oh yeah that's not gonna
> happen. But it's still possible to have some tests written in C.
> 
> I played a bit with this. The assumption is if it's agreed that we can
> get something bare bone (but functional) in then we could start having
> more and more C-based unit tests in future and also improve the C
> framework to be on par with shell one on the side.
> 
> There are still some minor problems with my patch, and a bunch of
> optional features not supported. But the numbers looks unexpectedly
> promising. 0.7 seconds on the shell version and 0.03 on the C one.

I see even more promising results from a single run on one of my Cygwin systems: from 21.3 seconds for t3070 to 0.112 seconds for your t3071. I expect there's a similar improvement in Dscho's Git for Windows environment.

> One disadvantage of this though, if this kind of framework does not
> get popular, then any new test feature must be added at both places
> but it's a waste of time to support both. So...

I don't follow: if we end up implementing every test twice, as we have here, then I agree, but I don't think there's much value in doing that except as a proof of concept, as in this immediate discussion. The obvious-to-me way to do this would be following the precedent of the core code: gradually migrate things away from shell code to C code.

Adam
Duy Nguyen· Jan 10, 2018, 10:52 UTC · re: Adam Dinwoodie · lore

Re: [PATCH v4 8/7] wildmatch test: skip file creation tests on Windows proper

On Wed, Jan 10, 2018 at 5:38 PM, Adam Dinwoodie <adam@dinwoodie.org> wrote:
Show 9 quoted lines
>> One disadvantage of this though, if this kind of framework does not
>> get popular, then any new test feature must be added at both places
>> but it's a waste of time to support both. So...
>
> I don't follow: if we end up implementing every test twice, as we have
> here, then I agree, but I don't think there's much value in doing that
> except as a proof of concept, as in this immediate discussion.  The
> obvious-to-me way to do this would be following the precedent of the
> core code: gradually migrate things away from shell code to C code.

Not the tests themselves. Test features, like --valgrind, --debug, --verbose and that kind of stuff. These are handled by test-lib.sh. If we add support for --new-fancy-thing to test-lib.sh then we need some more code in test-lib.c as well.

-- 
Duy
Johannes Schindelin· Jan 10, 2018, 20:24 UTC · re: Duy Nguyen · lore

Re: [PATCH v4 8/7] wildmatch test: skip file creation tests on Windows proper

Hi Duy,
On Wed, 10 Jan 2018, Duy Nguyen wrote:
Show 8 quoted lines
> On Mon, Jan 08, 2018 at 01:25:04PM +0100, Johannes Schindelin wrote:
> > I agree that it would make a ton of sense to use a proper, portable test
> > framework written in pure, portable C.
> > 
> > However, this ship has long sailed, hasn't it?
> 
> If you meant converting the whole test suite, oh yeah that's not gonna
> happen. But it's still possible to have some tests written in C.
True.
> I played a bit with this. The assumption is if it's agreed that we can
> get something bare bone (but functional) in then we could start having
> more and more C-based unit tests in future and also improve the C
> framework to be on par with shell one on the side.

We can also start with something small that does not contend to replace the entire test suite, and evolve from there as we have time.

Your initial patch looks very good, I will give it a cursory review (only cursory because we are technically in a feature-freeze...)

Show 9 quoted lines
> diff --git a/Makefile b/Makefile
> index 2a81ae22e9..567387b558 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -644,6 +644,7 @@ X =
>  
>  PROGRAMS += $(patsubst %.o,git-%$X,$(PROGRAM_OBJS))
>  
> +TEST_PROGRAMS_NEED_X += test-3071-wildmatch

I guess I can always work on unifying those gazillion of test executables into a single one later.

For testing purposes, I have to bundle them (BusyBox-based MinGit is supposed to be stand-alone, yet I want to test it to verify that it works even if it ships only a subset of Git for Windows), and they dominate the payload of any prerelease, as you can see e.g. here: https://github.com/git-for-windows/git/releases/tag/v2.16.0-rc1.windows.1

Show 20 quoted lines
> diff --git a/t/helper/test-3071-wildmatch.c b/t/helper/test-3071-wildmatch.c
> new file mode 100644
> index 0000000000..24a657202d
> --- /dev/null
> +++ b/t/helper/test-3071-wildmatch.c
> @@ -0,0 +1,273 @@
> +#include "cache.h"
> +#include "test-lib.h"
> +
> +struct match_input {
> +	int expect_true;
> +	const char *text;
> +	const char *pattern;
> +};
> +
> +static struct match_input match_tests[] = {
> +	/* Basic wildmatch features */
> +	{ 1, "foo", "foo" },
> +	{ 0, "foo", "bar" },
> +	{ 1, "", "" },

These patterns share the "magic-ness" of Ævar's test cases... although your version is certainly more concise.

BTW IIRC Ævar explicitly said that he needs to use `ls-files` in order to test the interaction with the index, so that would probably take a little bit more work.

Show 9 quoted lines
> diff --git a/t/t3071-wildmatch.sh b/t/t3071-wildmatch.sh
> new file mode 100755
> index 0000000000..6e83b4d684
> --- /dev/null
> +++ b/t/t3071-wildmatch.sh
> @@ -0,0 +1,3 @@
> +#!/bin/sh
> +
> +exec helper/test-3071-wildmatch t3071-wildmatch "$@"
Should it not be `exec test-3071-wildmatch "${0%.sh}" "$@"`?
Show 7 quoted lines
> diff --git a/test-lib.c b/test-lib.c
> new file mode 100644
> index 0000000000..8e8b7cd6df
> --- /dev/null
> +++ b/test-lib.c
> @@ -0,0 +1,97 @@
> [...]
Lots of good stuff in there. Definitely a good start.

Ciao, Dscho

Duy Nguyen· Jan 11, 2018, 09:25 UTC · re: Johannes Schindelin · lore

Re: [PATCH v4 8/7] wildmatch test: skip file creation tests on Windows proper

On Thu, Jan 11, 2018 at 3:24 AM, Johannes Schindelin <Johannes.Schindelin@gmx.de> wrote:

Show 12 quoted lines
>> diff --git a/Makefile b/Makefile
>> index 2a81ae22e9..567387b558 100644
>> --- a/Makefile
>> +++ b/Makefile
>> @@ -644,6 +644,7 @@ X =
>>
>>  PROGRAMS += $(patsubst %.o,git-%$X,$(PROGRAM_OBJS))
>>
>> +TEST_PROGRAMS_NEED_X += test-3071-wildmatch
>
> I guess I can always work on unifying those gazillion of test executables
> into a single one later.

Oh yeah. I did notice your remark about disk consumption but this was a quick hack that I would not bother with it. For the record I'm slightly bothered with many test programs too, not due to disk size but because it increases link time (disk i/o probably also plays part in that). This may help another thing... at the end of the mail

Show 8 quoted lines
>> +static struct match_input match_tests[] = {
>> +     /* Basic wildmatch features */
>> +     { 1, "foo", "foo" },
>> +     { 0, "foo", "bar" },
>> +     { 1, "", "" },
>
> These patterns share the "magic-ness" of Ævar's test cases... although
> your version is certainly more concise.

Another thing will make me move away from this style is, you can't mark one test broken. In the end, we may have some macro that issue one match() call per line, very similar to how t3070 does now. Then we have more freedom in marking tests.

> BTW IIRC Ævar explicitly said that he needs to use `ls-files` in order to
> test the interaction with the index, so that would probably take a little
> bit more work.

Yeah, run_command() and stuff, not super hard (but then it opens up another aspect I didn't address in this quick hack: collecting output log of a test and only showing it when the test fails, could be tricker to do in C than shell.

Show 11 quoted lines
>> diff --git a/t/t3071-wildmatch.sh b/t/t3071-wildmatch.sh
>> new file mode 100755
>> index 0000000000..6e83b4d684
>> --- /dev/null
>> +++ b/t/t3071-wildmatch.sh
>> @@ -0,0 +1,3 @@
>> +#!/bin/sh
>> +
>> +exec helper/test-3071-wildmatch t3071-wildmatch "$@"
>
> Should it not be `exec test-3071-wildmatch "${0%.sh}" "$@"`?

No, test-lib.sh is required to set up $PATH properly so you can run test programs without path. This is another sticky point. Some integration with test-lib.sh is needed. I would like to have something like this

-- 8< -- cat >t3071-wildmatch-c.sh <<EOF #!/bin/sh . ./test-lib.sh EOF -- 8< --

and test-lib.sh will take care of finding the right program, passing the right test name as argument... (a single test program covering all test groups, rather than one binary per test group, would simplify things here). We need something though to let test-lib.sh know this is C-based not shell to activate this mode. The "-c" suffix in the file name is for that purpose, but maybe we will figure out something better later. If it's too magical, this would do

-- 8< -- cat >t3071-wildmatch.sh <<EOF #!/bin/sh

. ./test-lib.sh

exec_c_tests # new function defined in test-lib.sh EOF -- 8< --

-- 
Duy
Ævar Arnfjörð Bjarmason· Jan 30, 2018, 21:21 UTC · re: Ævar Arnfjörð Bjarmason · lore

[PATCH v5 00/10] increase wildmatch test coverage

v5 has been a long time coming (20 days since I said I'd re-roll this), but hopefully this is a version that works well for everyone, including Windows users. Changes:

Ævar Arnfjörð Bjarmason (10):
  wildmatch test: indent with tabs, not spaces
  wildmatch test: use more standard shell style
  wildmatch test: don't try to vertically align our output
  wildmatch test: use a paranoia pattern from nul_match()
  wildmatch test: remove dead fnmatch() test code
No changes.
  wildmatch test: use test_must_fail, not ! for test-wildmatch
NEW: Fix a tiny nit I spotted while re-rolling.
  wildmatch test: perform all tests under all wildmatch() modes

The testing of various wildmatch modes got factored into a function. It makes no difference to this patch, but makes a huge difference in readability to the follow-up patch.

Also I stopped renaming "match" to "wildtest", I can't remeber why I did that in the first place, but no point in doing that, and this makes things easier to review...

  wildmatch test: create & test files on disk in addition to in-memory
Almost entirely based on feedback from Johannes:

a) This is now much more friendly under -x, as little test code as possible outside actual tests.

b) Factored out into functions
c) Gave variables better names

d) Hopefully runs under Windows now without errors, due to a blacklist of filenames that aren't allowed on Windows. Commit message now mentions this.

e) This should be a lot faster than before, since I factored out the setup work being done for every test so it's only done

f) At this point I can't remember who/where this was pointed out, but it was observed that I was using a very dangerous looking `rm -rf -- *` pattern in the old test, turns out this could be replaced with a less scary `git clean -df`.

  test-lib: add an EXPENSIVE_ON_WINDOWS prerequisite
  wildmatch test: mark test as EXPENSIVE_ON_WINDOWS

Follow-up my 87mv1raz9p.fsf@evledraar.gmail.com from the v4 thread, and create an EXPENSIVE_ON_WINDOWS prerequisite, which is then used for the file tests so they're skipped on Windows by default.

Even though 8/10 should be faster now, and hopefully passes on Windows, I still expect it to be quite slow on Windows, so let's not run it there by default unless under GIT_TEST_LONG=1.

 t/helper/test-wildmatch.c |   2 +
 t/t3070-wildmatch.sh      | 655 +++++++++++++++++++++++++++++-----------------
 t/test-lib.sh             |   4 +
 3 files changed, 416 insertions(+), 245 deletions(-)
-- 
2.15.1.424.g9478a66081
Ævar Arnfjörð Bjarmason· Jan 30, 2018, 21:21 UTC · re: Ævar Arnfjörð Bjarmason · lore

[PATCH v5 01/10] wildmatch test: indent with tabs, not spaces

Replace the 4-width mixed space & tab indentation in this file with indentation with tabs as we do in most of the rest of our tests.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 t/t3070-wildmatch.sh | 54 ++++++++++++++++++++++++++--------------------------
 1 file changed, 27 insertions(+), 27 deletions(-)
Show changes to t/t3070-wildmatch.sh +27 −27
diff --git a/t/t3070-wildmatch.sh b/t/t3070-wildmatch.sh
index 163a14a1c2..27fa878f6e 100755
--- a/t/t3070-wildmatch.sh
+++ b/t/t3070-wildmatch.sh
@@ -5,39 +5,39 @@ test_description='wildmatch tests'
 . ./test-lib.sh
 
 match() {
-    if [ $1 = 1 ]; then
-	test_expect_success "wildmatch:     match '$3' '$4'" "
-	    test-wildmatch wildmatch '$3' '$4'
-	"
-    else
-	test_expect_success "wildmatch:  no match '$3' '$4'" "
-	    ! test-wildmatch wildmatch '$3' '$4'
-	"
-    fi
+	if [ $1 = 1 ]; then
+		test_expect_success "wildmatch:     match '$3' '$4'" "
+			test-wildmatch wildmatch '$3' '$4'
+		"
+	else
+		test_expect_success "wildmatch:  no match '$3' '$4'" "
+			! test-wildmatch wildmatch '$3' '$4'
+		"
+	fi
 }
 
 imatch() {
-    if [ $1 = 1 ]; then
-	test_expect_success "iwildmatch:    match '$2' '$3'" "
-	    test-wildmatch iwildmatch '$2' '$3'
-	"
-    else
-	test_expect_success "iwildmatch: no match '$2' '$3'" "
-	    ! test-wildmatch iwildmatch '$2' '$3'
-	"
-    fi
+	if [ $1 = 1 ]; then
+		test_expect_success "iwildmatch:    match '$2' '$3'" "
+			test-wildmatch iwildmatch '$2' '$3'
+		"
+	else
+		test_expect_success "iwildmatch: no match '$2' '$3'" "
+			! test-wildmatch iwildmatch '$2' '$3'
+		"
+	fi
 }
 
 pathmatch() {
-    if [ $1 = 1 ]; then
-	test_expect_success "pathmatch:     match '$2' '$3'" "
-	    test-wildmatch pathmatch '$2' '$3'
-	"
-    else
-	test_expect_success "pathmatch:  no match '$2' '$3'" "
-	    ! test-wildmatch pathmatch '$2' '$3'
-	"
-    fi
+	if [ $1 = 1 ]; then
+		test_expect_success "pathmatch:     match '$2' '$3'" "
+			test-wildmatch pathmatch '$2' '$3'
+		"
+	else
+		test_expect_success "pathmatch:  no match '$2' '$3'" "
+			! test-wildmatch pathmatch '$2' '$3'
+		"
+	fi
 }
 
 # Basic wildmat features
-- 
2.15.1.424.g9478a66081
Ævar Arnfjörð Bjarmason· Jan 30, 2018, 21:21 UTC · re: Ævar Arnfjörð Bjarmason · lore

[PATCH v5 02/10] wildmatch test: use more standard shell style

Change the wildmatch test to use more standard shell style, usually we use "if test" not "if [".

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 t/t3070-wildmatch.sh | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)
Show changes to t/t3070-wildmatch.sh +6 −3
diff --git a/t/t3070-wildmatch.sh b/t/t3070-wildmatch.sh
index 27fa878f6e..4d589d1f9a 100755
--- a/t/t3070-wildmatch.sh
+++ b/t/t3070-wildmatch.sh
@@ -5,7 +5,8 @@ test_description='wildmatch tests'
 . ./test-lib.sh
 
 match() {
-	if [ $1 = 1 ]; then
+	if test "$1" = 1
+	then
 		test_expect_success "wildmatch:     match '$3' '$4'" "
 			test-wildmatch wildmatch '$3' '$4'
 		"
@@ -17,7 +18,8 @@ match() {
 }
 
 imatch() {
-	if [ $1 = 1 ]; then
+	if test "$1" = 1
+	then
 		test_expect_success "iwildmatch:    match '$2' '$3'" "
 			test-wildmatch iwildmatch '$2' '$3'
 		"
@@ -29,7 +31,8 @@ imatch() {
 }
 
 pathmatch() {
-	if [ $1 = 1 ]; then
+	if test "$1" = 1
+	then
 		test_expect_success "pathmatch:     match '$2' '$3'" "
 			test-wildmatch pathmatch '$2' '$3'
 		"
-- 
2.15.1.424.g9478a66081
Ævar Arnfjörð Bjarmason· Jan 30, 2018, 21:21 UTC · re: Ævar Arnfjörð Bjarmason · lore

[PATCH v5 03/10] wildmatch test: don't try to vertically align our output

Don't try to vertically align the test output, which is futile anyway under the TAP output where we're going to be emitting a number for each test without aligning the test count.

This makes subsequent changes of mine where I'm not going to be aligning this output as I add new tests easier.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 t/t3070-wildmatch.sh | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)
Show changes to t/t3070-wildmatch.sh +5 −5
diff --git a/t/t3070-wildmatch.sh b/t/t3070-wildmatch.sh
index 4d589d1f9a..19ea64bba9 100755
--- a/t/t3070-wildmatch.sh
+++ b/t/t3070-wildmatch.sh
@@ -7,11 +7,11 @@ test_description='wildmatch tests'
 match() {
 	if test "$1" = 1
 	then
-		test_expect_success "wildmatch:     match '$3' '$4'" "
+		test_expect_success "wildmatch: match '$3' '$4'" "
 			test-wildmatch wildmatch '$3' '$4'
 		"
 	else
-		test_expect_success "wildmatch:  no match '$3' '$4'" "
+		test_expect_success "wildmatch: no match '$3' '$4'" "
 			! test-wildmatch wildmatch '$3' '$4'
 		"
 	fi
@@ -20,7 +20,7 @@ match() {
 imatch() {
 	if test "$1" = 1
 	then
-		test_expect_success "iwildmatch:    match '$2' '$3'" "
+		test_expect_success "iwildmatch: match '$2' '$3'" "
 			test-wildmatch iwildmatch '$2' '$3'
 		"
 	else
@@ -33,11 +33,11 @@ imatch() {
 pathmatch() {
 	if test "$1" = 1
 	then
-		test_expect_success "pathmatch:     match '$2' '$3'" "
+		test_expect_success "pathmatch: match '$2' '$3'" "
 			test-wildmatch pathmatch '$2' '$3'
 		"
 	else
-		test_expect_success "pathmatch:  no match '$2' '$3'" "
+		test_expect_success "pathmatch: no match '$2' '$3'" "
 			! test-wildmatch pathmatch '$2' '$3'
 		"
 	fi
-- 
2.15.1.424.g9478a66081
Ævar Arnfjörð Bjarmason· Jan 30, 2018, 21:21 UTC · re: Ævar Arnfjörð Bjarmason · lore

[PATCH v5 04/10] wildmatch test: use a paranoia pattern from nul_match()

Use a pattern from the nul_match() function in t7008-grep-binary.sh to make sure that we don't just fall through to the "else" if there's an unknown parameter.

This is something I added in commit 77f6f4406f ("grep: add a test helper function for less verbose -f \0 tests", 2017-05-20) to grep tests, which were modeled on these wildmatch tests, and I'm now porting back to the original wildmatch tests.

I am not using the "say '...'; exit 1" pattern from t0000-basic.sh because if I fail I want to run the rest of the tests (unless under -i), and doing this makes sure we do that and don't exit right away without fully reporting our errors.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 t/t3070-wildmatch.sh | 15 ++++++++++++---
 1 file changed, 12 insertions(+), 3 deletions(-)
Show changes to t/t3070-wildmatch.sh +12 −3
diff --git a/t/t3070-wildmatch.sh b/t/t3070-wildmatch.sh
index 19ea64bba9..9691d8eda3 100755
--- a/t/t3070-wildmatch.sh
+++ b/t/t3070-wildmatch.sh
@@ -10,10 +10,13 @@ match() {
 		test_expect_success "wildmatch: match '$3' '$4'" "
 			test-wildmatch wildmatch '$3' '$4'
 		"
-	else
+	elif test "$1" = 0
+	then
 		test_expect_success "wildmatch: no match '$3' '$4'" "
 			! test-wildmatch wildmatch '$3' '$4'
 		"
+	else
+		test_expect_success "PANIC: Test framework error. Unknown matches value $1" 'false'
 	fi
 }
 
@@ -23,10 +26,13 @@ imatch() {
 		test_expect_success "iwildmatch: match '$2' '$3'" "
 			test-wildmatch iwildmatch '$2' '$3'
 		"
-	else
+	elif test "$1" = 0
+	then
 		test_expect_success "iwildmatch: no match '$2' '$3'" "
 			! test-wildmatch iwildmatch '$2' '$3'
 		"
+	else
+		test_expect_success "PANIC: Test framework error. Unknown matches value $1" 'false'
 	fi
 }
 
@@ -36,10 +42,13 @@ pathmatch() {
 		test_expect_success "pathmatch: match '$2' '$3'" "
 			test-wildmatch pathmatch '$2' '$3'
 		"
-	else
+	elif test "$1" = 0
+	then
 		test_expect_success "pathmatch: no match '$2' '$3'" "
 			! test-wildmatch pathmatch '$2' '$3'
 		"
+	else
+		test_expect_success "PANIC: Test framework error. Unknown matches value $1" 'false'
 	fi
 }
 
-- 
2.15.1.424.g9478a66081
Ævar Arnfjörð Bjarmason· Jan 30, 2018, 21:21 UTC · re: Ævar Arnfjörð Bjarmason · lore

[PATCH v5 06/10] wildmatch test: use test_must_fail, not ! for test-wildmatch

Use of ! should be reserved for non-git programs that are assumed not to fail, see README. With this change only t/t0110-urlmatch-normalization.sh is still using this anti-pattern.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 t/t3070-wildmatch.sh | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)
Show changes to t/t3070-wildmatch.sh +3 −3
diff --git a/t/t3070-wildmatch.sh b/t/t3070-wildmatch.sh
index 2f8a681c72..fe0e5103a3 100755
--- a/t/t3070-wildmatch.sh
+++ b/t/t3070-wildmatch.sh
@@ -13,7 +13,7 @@ match() {
 	elif test "$1" = 0
 	then
 		test_expect_success "wildmatch: no match '$2' '$3'" "
-			! test-wildmatch wildmatch '$2' '$3'
+			test_must_fail test-wildmatch wildmatch '$2' '$3'
 		"
 	else
 		test_expect_success "PANIC: Test framework error. Unknown matches value $1" 'false'
@@ -29,7 +29,7 @@ imatch() {
 	elif test "$1" = 0
 	then
 		test_expect_success "iwildmatch: no match '$2' '$3'" "
-			! test-wildmatch iwildmatch '$2' '$3'
+			test_must_fail test-wildmatch iwildmatch '$2' '$3'
 		"
 	else
 		test_expect_success "PANIC: Test framework error. Unknown matches value $1" 'false'
@@ -45,7 +45,7 @@ pathmatch() {
 	elif test "$1" = 0
 	then
 		test_expect_success "pathmatch: no match '$2' '$3'" "
-			! test-wildmatch pathmatch '$2' '$3'
+			test_must_fail test-wildmatch pathmatch '$2' '$3'
 		"
 	else
 		test_expect_success "PANIC: Test framework error. Unknown matches value $1" 'false'
-- 
2.15.1.424.g9478a66081
Ævar Arnfjörð Bjarmason· Jan 30, 2018, 21:21 UTC · re: Ævar Arnfjörð Bjarmason · lore

[PATCH v5 05/10] wildmatch test: remove dead fnmatch() test code

Remove the unused fnmatch() test parameter from the wildmatch test. The code that used to test this was removed in 70a8fc999d ("stop using fnmatch (either native or compat)", 2014-02-15).

As a --word-diff shows the only change to the body of the tests is the removal of the second out of four parameters passed to match().

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 t/t3070-wildmatch.sh | 356 +++++++++++++++++++++++++--------------------------
 1 file changed, 178 insertions(+), 178 deletions(-)
Show changes to t/t3070-wildmatch.sh +178 −178
diff --git a/t/t3070-wildmatch.sh b/t/t3070-wildmatch.sh
index 9691d8eda3..2f8a681c72 100755
--- a/t/t3070-wildmatch.sh
+++ b/t/t3070-wildmatch.sh
@@ -7,13 +7,13 @@ test_description='wildmatch tests'
 match() {
 	if test "$1" = 1
 	then
-		test_expect_success "wildmatch: match '$3' '$4'" "
-			test-wildmatch wildmatch '$3' '$4'
+		test_expect_success "wildmatch: match '$2' '$3'" "
+			test-wildmatch wildmatch '$2' '$3'
 		"
 	elif test "$1" = 0
 	then
-		test_expect_success "wildmatch: no match '$3' '$4'" "
-			! test-wildmatch wildmatch '$3' '$4'
+		test_expect_success "wildmatch: no match '$2' '$3'" "
+			! test-wildmatch wildmatch '$2' '$3'
 		"
 	else
 		test_expect_success "PANIC: Test framework error. Unknown matches value $1" 'false'
@@ -53,176 +53,176 @@ pathmatch() {
 }
 
 # Basic wildmat features
-match 1 1 foo foo
-match 0 0 foo bar
-match 1 1 '' ""
-match 1 1 foo '???'
-match 0 0 foo '??'
-match 1 1 foo '*'
-match 1 1 foo 'f*'
-match 0 0 foo '*f'
-match 1 1 foo '*foo*'
-match 1 1 foobar '*ob*a*r*'
-match 1 1 aaaaaaabababab '*ab'
-match 1 1 'foo*' 'foo\*'
-match 0 0 foobar 'foo\*bar'
-match 1 1 'f\oo' 'f\\oo'
-match 1 1 ball '*[al]?'
-match 0 0 ten '[ten]'
-match 0 1 ten '**[!te]'
-match 0 0 ten '**[!ten]'
-match 1 1 ten 't[a-g]n'
-match 0 0 ten 't[!a-g]n'
-match 1 1 ton 't[!a-g]n'
-match 1 1 ton 't[^a-g]n'
-match 1 x 'a]b' 'a[]]b'
-match 1 x a-b 'a[]-]b'
-match 1 x 'a]b' 'a[]-]b'
-match 0 x aab 'a[]-]b'
-match 1 x aab 'a[]a-]b'
-match 1 1 ']' ']'
+match 1 foo foo
+match 0 foo bar
+match 1 '' ""
+match 1 foo '???'
+match 0 foo '??'
+match 1 foo '*'
+match 1 foo 'f*'
+match 0 foo '*f'
+match 1 foo '*foo*'
+match 1 foobar '*ob*a*r*'
+match 1 aaaaaaabababab '*ab'
+match 1 'foo*' 'foo\*'
+match 0 foobar 'foo\*bar'
+match 1 'f\oo' 'f\\oo'
+match 1 ball '*[al]?'
+match 0 ten '[ten]'
+match 0 ten '**[!te]'
+match 0 ten '**[!ten]'
+match 1 ten 't[a-g]n'
+match 0 ten 't[!a-g]n'
+match 1 ton 't[!a-g]n'
+match 1 ton 't[^a-g]n'
+match 1 'a]b' 'a[]]b'
+match 1 a-b 'a[]-]b'
+match 1 'a]b' 'a[]-]b'
+match 0 aab 'a[]-]b'
+match 1 aab 'a[]a-]b'
+match 1 ']' ']'
 
 # Extended slash-matching features
-match 0 0 'foo/baz/bar' 'foo*bar'
-match 0 0 'foo/baz/bar' 'foo**bar'
-match 0 1 'foobazbar' 'foo**bar'
-match 1 1 'foo/baz/bar' 'foo/**/bar'
-match 1 0 'foo/baz/bar' 'foo/**/**/bar'
-match 1 0 'foo/b/a/z/bar' 'foo/**/bar'
-match 1 0 'foo/b/a/z/bar' 'foo/**/**/bar'
-match 1 0 'foo/bar' 'foo/**/bar'
-match 1 0 'foo/bar' 'foo/**/**/bar'
-match 0 0 'foo/bar' 'foo?bar'
-match 0 0 'foo/bar' 'foo[/]bar'
-match 0 0 'foo/bar' 'foo[^a-z]bar'
-match 0 0 'foo/bar' 'f[^eiu][^eiu][^eiu][^eiu][^eiu]r'
-match 1 1 'foo-bar' 'f[^eiu][^eiu][^eiu][^eiu][^eiu]r'
-match 1 0 'foo' '**/foo'
-match 1 x 'XXX/foo' '**/foo'
-match 1 0 'bar/baz/foo' '**/foo'
-match 0 0 'bar/baz/foo' '*/foo'
-match 0 0 'foo/bar/baz' '**/bar*'
-match 1 0 'deep/foo/bar/baz' '**/bar/*'
-match 0 0 'deep/foo/bar/baz/' '**/bar/*'
-match 1 0 'deep/foo/bar/baz/' '**/bar/**'
-match 0 0 'deep/foo/bar' '**/bar/*'
-match 1 0 'deep/foo/bar/' '**/bar/**'
-match 0 0 'foo/bar/baz' '**/bar**'
-match 1 0 'foo/bar/baz/x' '*/bar/**'
-match 0 0 'deep/foo/bar/baz/x' '*/bar/**'
-match 1 0 'deep/foo/bar/baz/x' '**/bar/*/*'
+match 0 'foo/baz/bar' 'foo*bar'
+match 0 'foo/baz/bar' 'foo**bar'
+match 0 'foobazbar' 'foo**bar'
+match 1 'foo/baz/bar' 'foo/**/bar'
+match 1 'foo/baz/bar' 'foo/**/**/bar'
+match 1 'foo/b/a/z/bar' 'foo/**/bar'
+match 1 'foo/b/a/z/bar' 'foo/**/**/bar'
+match 1 'foo/bar' 'foo/**/bar'
+match 1 'foo/bar' 'foo/**/**/bar'
+match 0 'foo/bar' 'foo?bar'
+match 0 'foo/bar' 'foo[/]bar'
+match 0 'foo/bar' 'foo[^a-z]bar'
+match 0 'foo/bar' 'f[^eiu][^eiu][^eiu][^eiu][^eiu]r'
+match 1 'foo-bar' 'f[^eiu][^eiu][^eiu][^eiu][^eiu]r'
+match 1 'foo' '**/foo'
+match 1 'XXX/foo' '**/foo'
+match 1 'bar/baz/foo' '**/foo'
+match 0 'bar/baz/foo' '*/foo'
+match 0 'foo/bar/baz' '**/bar*'
+match 1 'deep/foo/bar/baz' '**/bar/*'
+match 0 'deep/foo/bar/baz/' '**/bar/*'
+match 1 'deep/foo/bar/baz/' '**/bar/**'
+match 0 'deep/foo/bar' '**/bar/*'
+match 1 'deep/foo/bar/' '**/bar/**'
+match 0 'foo/bar/baz' '**/bar**'
+match 1 'foo/bar/baz/x' '*/bar/**'
+match 0 'deep/foo/bar/baz/x' '*/bar/**'
+match 1 'deep/foo/bar/baz/x' '**/bar/*/*'
 
 # Various additional tests
-match 0 0 'acrt' 'a[c-c]st'
-match 1 1 'acrt' 'a[c-c]rt'
-match 0 0 ']' '[!]-]'
-match 1 x 'a' '[!]-]'
-match 0 0 '' '\'
-match 0 x '\' '\'
-match 0 x 'XXX/\' '*/\'
-match 1 x 'XXX/\' '*/\\'
-match 1 1 'foo' 'foo'
-match 1 1 '@foo' '@foo'
-match 0 0 'foo' '@foo'
-match 1 1 '[ab]' '\[ab]'
-match 1 1 '[ab]' '[[]ab]'
-match 1 x '[ab]' '[[:]ab]'
-match 0 x '[ab]' '[[::]ab]'
-match 1 x '[ab]' '[[:digit]ab]'
-match 1 x '[ab]' '[\[:]ab]'
-match 1 1 '?a?b' '\??\?b'
-match 1 1 'abc' '\a\b\c'
-match 0 0 'foo' ''
-match 1 0 'foo/bar/baz/to' '**/t[o]'
+match 0 'acrt' 'a[c-c]st'
+match 1 'acrt' 'a[c-c]rt'
+match 0 ']' '[!]-]'
+match 1 'a' '[!]-]'
+match 0 '' '\'
+match 0 '\' '\'
+match 0 'XXX/\' '*/\'
+match 1 'XXX/\' '*/\\'
+match 1 'foo' 'foo'
+match 1 '@foo' '@foo'
+match 0 'foo' '@foo'
+match 1 '[ab]' '\[ab]'
+match 1 '[ab]' '[[]ab]'
+match 1 '[ab]' '[[:]ab]'
+match 0 '[ab]' '[[::]ab]'
+match 1 '[ab]' '[[:digit]ab]'
+match 1 '[ab]' '[\[:]ab]'
+match 1 '?a?b' '\??\?b'
+match 1 'abc' '\a\b\c'
+match 0 'foo' ''
+match 1 'foo/bar/baz/to' '**/t[o]'
 
 # Character class tests
-match 1 x 'a1B' '[[:alpha:]][[:digit:]][[:upper:]]'
-match 0 x 'a' '[[:digit:][:upper:][:space:]]'
-match 1 x 'A' '[[:digit:][:upper:][:space:]]'
-match 1 x '1' '[[:digit:][:upper:][:space:]]'
-match 0 x '1' '[[:digit:][:upper:][:spaci:]]'
-match 1 x ' ' '[[:digit:][:upper:][:space:]]'
-match 0 x '.' '[[:digit:][:upper:][:space:]]'
-match 1 x '.' '[[:digit:][:punct:][:space:]]'
-match 1 x '5' '[[:xdigit:]]'
-match 1 x 'f' '[[:xdigit:]]'
-match 1 x 'D' '[[:xdigit:]]'
-match 1 x '_' '[[:alnum:][:alpha:][:blank:][:cntrl:][:digit:][:graph:][:lower:][:print:][:punct:][:space:][:upper:][:xdigit:]]'
-match 1 x '.' '[^[:alnum:][:alpha:][:blank:][:cntrl:][:digit:][:lower:][:space:][:upper:][:xdigit:]]'
-match 1 x '5' '[a-c[:digit:]x-z]'
-match 1 x 'b' '[a-c[:digit:]x-z]'
-match 1 x 'y' '[a-c[:digit:]x-z]'
-match 0 x 'q' '[a-c[:digit:]x-z]'
+match 1 'a1B' '[[:alpha:]][[:digit:]][[:upper:]]'
+match 0 'a' '[[:digit:][:upper:][:space:]]'
+match 1 'A' '[[:digit:][:upper:][:space:]]'
+match 1 '1' '[[:digit:][:upper:][:space:]]'
+match 0 '1' '[[:digit:][:upper:][:spaci:]]'
+match 1 ' ' '[[:digit:][:upper:][:space:]]'
+match 0 '.' '[[:digit:][:upper:][:space:]]'
+match 1 '.' '[[:digit:][:punct:][:space:]]'
+match 1 '5' '[[:xdigit:]]'
+match 1 'f' '[[:xdigit:]]'
+match 1 'D' '[[:xdigit:]]'
+match 1 '_' '[[:alnum:][:alpha:][:blank:][:cntrl:][:digit:][:graph:][:lower:][:print:][:punct:][:space:][:upper:][:xdigit:]]'
+match 1 '.' '[^[:alnum:][:alpha:][:blank:][:cntrl:][:digit:][:lower:][:space:][:upper:][:xdigit:]]'
+match 1 '5' '[a-c[:digit:]x-z]'
+match 1 'b' '[a-c[:digit:]x-z]'
+match 1 'y' '[a-c[:digit:]x-z]'
+match 0 'q' '[a-c[:digit:]x-z]'
 
 # Additional tests, including some malformed wildmats
-match 1 x ']' '[\\-^]'
-match 0 0 '[' '[\\-^]'
-match 1 x '-' '[\-_]'
-match 1 x ']' '[\]]'
-match 0 0 '\]' '[\]]'
-match 0 0 '\' '[\]]'
-match 0 0 'ab' 'a[]b'
-match 0 x 'a[]b' 'a[]b'
-match 0 x 'ab[' 'ab['
-match 0 0 'ab' '[!'
-match 0 0 'ab' '[-'
-match 1 1 '-' '[-]'
-match 0 0 '-' '[a-'
-match 0 0 '-' '[!a-'
-match 1 x '-' '[--A]'
-match 1 x '5' '[--A]'
-match 1 1 ' ' '[ --]'
-match 1 1 '$' '[ --]'
-match 1 1 '-' '[ --]'
-match 0 0 '0' '[ --]'
-match 1 x '-' '[---]'
-match 1 x '-' '[------]'
-match 0 0 'j' '[a-e-n]'
-match 1 x '-' '[a-e-n]'
-match 1 x 'a' '[!------]'
-match 0 0 '[' '[]-a]'
-match 1 x '^' '[]-a]'
-match 0 0 '^' '[!]-a]'
-match 1 x '[' '[!]-a]'
-match 1 1 '^' '[a^bc]'
-match 1 x '-b]' '[a-]b]'
-match 0 0 '\' '[\]'
-match 1 1 '\' '[\\]'
-match 0 0 '\' '[!\\]'
-match 1 1 'G' '[A-\\]'
-match 0 0 'aaabbb' 'b*a'
-match 0 0 'aabcaa' '*ba*'
-match 1 1 ',' '[,]'
-match 1 1 ',' '[\\,]'
-match 1 1 '\' '[\\,]'
-match 1 1 '-' '[,-.]'
-match 0 0 '+' '[,-.]'
-match 0 0 '-.]' '[,-.]'
-match 1 1 '2' '[\1-\3]'
-match 1 1 '3' '[\1-\3]'
-match 0 0 '4' '[\1-\3]'
-match 1 1 '\' '[[-\]]'
-match 1 1 '[' '[[-\]]'
-match 1 1 ']' '[[-\]]'
-match 0 0 '-' '[[-\]]'
+match 1 ']' '[\\-^]'
+match 0 '[' '[\\-^]'
+match 1 '-' '[\-_]'
+match 1 ']' '[\]]'
+match 0 '\]' '[\]]'
+match 0 '\' '[\]]'
+match 0 'ab' 'a[]b'
+match 0 'a[]b' 'a[]b'
+match 0 'ab[' 'ab['
+match 0 'ab' '[!'
+match 0 'ab' '[-'
+match 1 '-' '[-]'
+match 0 '-' '[a-'
+match 0 '-' '[!a-'
+match 1 '-' '[--A]'
+match 1 '5' '[--A]'
+match 1 ' ' '[ --]'
+match 1 '$' '[ --]'
+match 1 '-' '[ --]'
+match 0 '0' '[ --]'
+match 1 '-' '[---]'
+match 1 '-' '[------]'
+match 0 'j' '[a-e-n]'
+match 1 '-' '[a-e-n]'
+match 1 'a' '[!------]'
+match 0 '[' '[]-a]'
+match 1 '^' '[]-a]'
+match 0 '^' '[!]-a]'
+match 1 '[' '[!]-a]'
+match 1 '^' '[a^bc]'
+match 1 '-b]' '[a-]b]'
+match 0 '\' '[\]'
+match 1 '\' '[\\]'
+match 0 '\' '[!\\]'
+match 1 'G' '[A-\\]'
+match 0 'aaabbb' 'b*a'
+match 0 'aabcaa' '*ba*'
+match 1 ',' '[,]'
+match 1 ',' '[\\,]'
+match 1 '\' '[\\,]'
+match 1 '-' '[,-.]'
+match 0 '+' '[,-.]'
+match 0 '-.]' '[,-.]'
+match 1 '2' '[\1-\3]'
+match 1 '3' '[\1-\3]'
+match 0 '4' '[\1-\3]'
+match 1 '\' '[[-\]]'
+match 1 '[' '[[-\]]'
+match 1 ']' '[[-\]]'
+match 0 '-' '[[-\]]'
 
 # Test recursion and the abort code (use "wildtest -i" to see iteration counts)
-match 1 1 '-adobe-courier-bold-o-normal--12-120-75-75-m-70-iso8859-1' '-*-*-*-*-*-*-12-*-*-*-m-*-*-*'
-match 0 0 '-adobe-courier-bold-o-normal--12-120-75-75-X-70-iso8859-1' '-*-*-*-*-*-*-12-*-*-*-m-*-*-*'
-match 0 0 '-adobe-courier-bold-o-normal--12-120-75-75-/-70-iso8859-1' '-*-*-*-*-*-*-12-*-*-*-m-*-*-*'
-match 1 1 'XXX/adobe/courier/bold/o/normal//12/120/75/75/m/70/iso8859/1' 'XXX/*/*/*/*/*/*/12/*/*/*/m/*/*/*'
-match 0 0 'XXX/adobe/courier/bold/o/normal//12/120/75/75/X/70/iso8859/1' 'XXX/*/*/*/*/*/*/12/*/*/*/m/*/*/*'
-match 1 0 'abcd/abcdefg/abcdefghijk/abcdefghijklmnop.txt' '**/*a*b*g*n*t'
-match 0 0 'abcd/abcdefg/abcdefghijk/abcdefghijklmnop.txtz' '**/*a*b*g*n*t'
-match 0 x foo '*/*/*'
-match 0 x foo/bar '*/*/*'
-match 1 x foo/bba/arr '*/*/*'
-match 0 x foo/bb/aa/rr '*/*/*'
-match 1 x foo/bb/aa/rr '**/**/**'
-match 1 x abcXdefXghi '*X*i'
-match 0 x ab/cXd/efXg/hi '*X*i'
-match 1 x ab/cXd/efXg/hi '*/*X*/*/*i'
-match 1 x ab/cXd/efXg/hi '**/*X*/**/*i'
+match 1 '-adobe-courier-bold-o-normal--12-120-75-75-m-70-iso8859-1' '-*-*-*-*-*-*-12-*-*-*-m-*-*-*'
+match 0 '-adobe-courier-bold-o-normal--12-120-75-75-X-70-iso8859-1' '-*-*-*-*-*-*-12-*-*-*-m-*-*-*'
+match 0 '-adobe-courier-bold-o-normal--12-120-75-75-/-70-iso8859-1' '-*-*-*-*-*-*-12-*-*-*-m-*-*-*'
+match 1 'XXX/adobe/courier/bold/o/normal//12/120/75/75/m/70/iso8859/1' 'XXX/*/*/*/*/*/*/12/*/*/*/m/*/*/*'
+match 0 'XXX/adobe/courier/bold/o/normal//12/120/75/75/X/70/iso8859/1' 'XXX/*/*/*/*/*/*/12/*/*/*/m/*/*/*'
+match 1 'abcd/abcdefg/abcdefghijk/abcdefghijklmnop.txt' '**/*a*b*g*n*t'
+match 0 'abcd/abcdefg/abcdefghijk/abcdefghijklmnop.txtz' '**/*a*b*g*n*t'
+match 0 foo '*/*/*'
+match 0 foo/bar '*/*/*'
+match 1 foo/bba/arr '*/*/*'
+match 0 foo/bb/aa/rr '*/*/*'
+match 1 foo/bb/aa/rr '**/**/**'
+match 1 abcXdefXghi '*X*i'
+match 0 ab/cXd/efXg/hi '*X*i'
+match 1 ab/cXd/efXg/hi '*/*X*/*/*i'
+match 1 ab/cXd/efXg/hi '**/*X*/**/*i'
 
 pathmatch 1 foo foo
 pathmatch 0 foo fo
@@ -248,20 +248,20 @@ pathmatch 1 ab/cXd/efXg/hi '*/*X*/*/*i'
 pathmatch 1 ab/cXd/efXg/hi '*Xg*i'
 
 # Case-sensitivity features
-match 0 x 'a' '[A-Z]'
-match 1 x 'A' '[A-Z]'
-match 0 x 'A' '[a-z]'
-match 1 x 'a' '[a-z]'
-match 0 x 'a' '[[:upper:]]'
-match 1 x 'A' '[[:upper:]]'
-match 0 x 'A' '[[:lower:]]'
-match 1 x 'a' '[[:lower:]]'
-match 0 x 'A' '[B-Za]'
-match 1 x 'a' '[B-Za]'
-match 0 x 'A' '[B-a]'
-match 1 x 'a' '[B-a]'
-match 0 x 'z' '[Z-y]'
-match 1 x 'Z' '[Z-y]'
+match 0 'a' '[A-Z]'
+match 1 'A' '[A-Z]'
+match 0 'A' '[a-z]'
+match 1 'a' '[a-z]'
+match 0 'a' '[[:upper:]]'
+match 1 'A' '[[:upper:]]'
+match 0 'A' '[[:lower:]]'
+match 1 'a' '[[:lower:]]'
+match 0 'A' '[B-Za]'
+match 1 'a' '[B-Za]'
+match 0 'A' '[B-a]'
+match 1 'a' '[B-a]'
+match 0 'z' '[Z-y]'
+match 1 'Z' '[Z-y]'
 
 imatch 1 'a' '[A-Z]'
 imatch 1 'A' '[A-Z]'
-- 
2.15.1.424.g9478a66081
Ævar Arnfjörð Bjarmason· Jan 30, 2018, 21:21 UTC · re: Ævar Arnfjörð Bjarmason · lore

[PATCH v5 07/10] wildmatch test: perform all tests under all wildmatch() modes

Rewrite the wildmatch() test suite so that each test now tests all combinations of the wildmatch() WM_CASEFOLD and WM_PATHNAME flags.

Before this change some test inputs were not tested on e.g. WM_PATHNAME. Now the function is stress tested on all possible inputs, and for each input we declare what the result should be if the mode is case-insensitive, or pathname matching, or case-sensitive or not matching pathnames.

Also before this change, nothing was testing case-insensitive non-pathname matching, so I've added that to test-wildmatch.c and made use of it.

This yields a rather scary patch, but there are no functional changes here, just more test coverage. Some now-redundant tests were deleted as a result of this change, since they were now duplicating an earlier test.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 t/helper/test-wildmatch.c |   2 +
 t/t3070-wildmatch.sh      | 478 ++++++++++++++++++++++------------------------
 2 files changed, 228 insertions(+), 252 deletions(-)
Show changes to 2 files +228 −252

t/helper/test-wildmatch.c, t/t3070-wildmatch.sh

diff --git a/t/helper/test-wildmatch.c b/t/helper/test-wildmatch.c
index 921d7b3e7e..66d33dfcfd 100644
--- a/t/helper/test-wildmatch.c
+++ b/t/helper/test-wildmatch.c
@@ -16,6 +16,8 @@ int cmd_main(int argc, const char **argv)
 		return !!wildmatch(argv[3], argv[2], WM_PATHNAME | WM_CASEFOLD);
 	else if (!strcmp(argv[1], "pathmatch"))
 		return !!wildmatch(argv[3], argv[2], 0);
+	else if (!strcmp(argv[1], "ipathmatch"))
+		return !!wildmatch(argv[3], argv[2], WM_CASEFOLD);
 	else
 		return 1;
 }
diff --git a/t/t3070-wildmatch.sh b/t/t3070-wildmatch.sh
index fe0e5103a3..3e75cb0cbe 100755
--- a/t/t3070-wildmatch.sh
+++ b/t/t3070-wildmatch.sh
@@ -4,278 +4,252 @@ test_description='wildmatch tests'
 
 . ./test-lib.sh
 
-match() {
-	if test "$1" = 1
-	then
-		test_expect_success "wildmatch: match '$2' '$3'" "
-			test-wildmatch wildmatch '$2' '$3'
-		"
-	elif test "$1" = 0
-	then
-		test_expect_success "wildmatch: no match '$2' '$3'" "
-			test_must_fail test-wildmatch wildmatch '$2' '$3'
-		"
-	else
-		test_expect_success "PANIC: Test framework error. Unknown matches value $1" 'false'
-	fi
-}
+match_with_function() {
+	text=$1
+	pattern=$2
+	match_expect=$3
+	match_function=$4
 
-imatch() {
-	if test "$1" = 1
+	if test "$match_expect" = 1
 	then
-		test_expect_success "iwildmatch: match '$2' '$3'" "
-			test-wildmatch iwildmatch '$2' '$3'
+		test_expect_success "$match_function: match '$text' '$pattern'" "
+			test-wildmatch $match_function '$text' '$pattern'
 		"
-	elif test "$1" = 0
+	elif test "$match_expect" = 0
 	then
-		test_expect_success "iwildmatch: no match '$2' '$3'" "
-			test_must_fail test-wildmatch iwildmatch '$2' '$3'
+		test_expect_success "$match_function: no match '$text' '$pattern'" "
+			test_must_fail test-wildmatch $match_function '$text' '$pattern'
 		"
 	else
-		test_expect_success "PANIC: Test framework error. Unknown matches value $1" 'false'
+		test_expect_success "PANIC: Test framework error. Unknown matches value $match_expect" 'false'
 	fi
+
 }
 
-pathmatch() {
-	if test "$1" = 1
-	then
-		test_expect_success "pathmatch: match '$2' '$3'" "
-			test-wildmatch pathmatch '$2' '$3'
-		"
-	elif test "$1" = 0
-	then
-		test_expect_success "pathmatch: no match '$2' '$3'" "
-			test_must_fail test-wildmatch pathmatch '$2' '$3'
-		"
-	else
-		test_expect_success "PANIC: Test framework error. Unknown matches value $1" 'false'
-	fi
+match() {
+	match_glob=$1
+	match_iglob=$2
+	match_pathmatch=$3
+	match_pathmatchi=$4
+	text=$5
+	pattern=$6
+
+	# $1: Case sensitive glob match: test-wildmatch & ls-files
+	match_with_function "$text" "$pattern" $match_glob "wildmatch"
+
+	# $2: Case insensitive glob match: test-wildmatch & ls-files
+	match_with_function "$text" "$pattern" $match_iglob "iwildmatch"
+
+	# $3: Case sensitive path match: test-wildmatch & ls-files
+	match_with_function "$text" "$pattern" $match_pathmatch "pathmatch"
+
+	# $4: Case insensitive path match: test-wildmatch & ls-files
+	match_with_function "$text" "$pattern" $match_pathmatchi "ipathmatch"
 }
 
-# Basic wildmat features
-match 1 foo foo
-match 0 foo bar
-match 1 '' ""
-match 1 foo '???'
-match 0 foo '??'
-match 1 foo '*'
-match 1 foo 'f*'
-match 0 foo '*f'
-match 1 foo '*foo*'
-match 1 foobar '*ob*a*r*'
-match 1 aaaaaaabababab '*ab'
-match 1 'foo*' 'foo\*'
-match 0 foobar 'foo\*bar'
-match 1 'f\oo' 'f\\oo'
-match 1 ball '*[al]?'
-match 0 ten '[ten]'
-match 0 ten '**[!te]'
-match 0 ten '**[!ten]'
-match 1 ten 't[a-g]n'
-match 0 ten 't[!a-g]n'
-match 1 ton 't[!a-g]n'
-match 1 ton 't[^a-g]n'
-match 1 'a]b' 'a[]]b'
-match 1 a-b 'a[]-]b'
-match 1 'a]b' 'a[]-]b'
-match 0 aab 'a[]-]b'
-match 1 aab 'a[]a-]b'
-match 1 ']' ']'
+# Basic wildmatch features
+match 1 1 1 1 foo foo
+match 0 0 0 0 foo bar
+match 1 1 1 1 '' ""
+match 1 1 1 1 foo '???'
+match 0 0 0 0 foo '??'
+match 1 1 1 1 foo '*'
+match 1 1 1 1 foo 'f*'
+match 0 0 0 0 foo '*f'
+match 1 1 1 1 foo '*foo*'
+match 1 1 1 1 foobar '*ob*a*r*'
+match 1 1 1 1 aaaaaaabababab '*ab'
+match 1 1 1 1 'foo*' 'foo\*'
+match 0 0 0 0 foobar 'foo\*bar'
+match 1 1 1 1 'f\oo' 'f\\oo'
+match 1 1 1 1 ball '*[al]?'
+match 0 0 0 0 ten '[ten]'
+match 0 0 1 1 ten '**[!te]'
+match 0 0 0 0 ten '**[!ten]'
+match 1 1 1 1 ten 't[a-g]n'
+match 0 0 0 0 ten 't[!a-g]n'
+match 1 1 1 1 ton 't[!a-g]n'
+match 1 1 1 1 ton 't[^a-g]n'
+match 1 1 1 1 'a]b' 'a[]]b'
+match 1 1 1 1 a-b 'a[]-]b'
+match 1 1 1 1 'a]b' 'a[]-]b'
+match 0 0 0 0 aab 'a[]-]b'
+match 1 1 1 1 aab 'a[]a-]b'
+match 1 1 1 1 ']' ']'
 
 # Extended slash-matching features
-match 0 'foo/baz/bar' 'foo*bar'
-match 0 'foo/baz/bar' 'foo**bar'
-match 0 'foobazbar' 'foo**bar'
-match 1 'foo/baz/bar' 'foo/**/bar'
-match 1 'foo/baz/bar' 'foo/**/**/bar'
-match 1 'foo/b/a/z/bar' 'foo/**/bar'
-match 1 'foo/b/a/z/bar' 'foo/**/**/bar'
-match 1 'foo/bar' 'foo/**/bar'
-match 1 'foo/bar' 'foo/**/**/bar'
-match 0 'foo/bar' 'foo?bar'
-match 0 'foo/bar' 'foo[/]bar'
-match 0 'foo/bar' 'foo[^a-z]bar'
-match 0 'foo/bar' 'f[^eiu][^eiu][^eiu][^eiu][^eiu]r'
-match 1 'foo-bar' 'f[^eiu][^eiu][^eiu][^eiu][^eiu]r'
-match 1 'foo' '**/foo'
-match 1 'XXX/foo' '**/foo'
-match 1 'bar/baz/foo' '**/foo'
-match 0 'bar/baz/foo' '*/foo'
-match 0 'foo/bar/baz' '**/bar*'
-match 1 'deep/foo/bar/baz' '**/bar/*'
-match 0 'deep/foo/bar/baz/' '**/bar/*'
-match 1 'deep/foo/bar/baz/' '**/bar/**'
-match 0 'deep/foo/bar' '**/bar/*'
-match 1 'deep/foo/bar/' '**/bar/**'
-match 0 'foo/bar/baz' '**/bar**'
-match 1 'foo/bar/baz/x' '*/bar/**'
-match 0 'deep/foo/bar/baz/x' '*/bar/**'
-match 1 'deep/foo/bar/baz/x' '**/bar/*/*'
+match 0 0 1 1 'foo/baz/bar' 'foo*bar'
+match 0 0 1 1 'foo/baz/bar' 'foo**bar'
+match 0 0 1 1 'foobazbar' 'foo**bar'
+match 1 1 1 1 'foo/baz/bar' 'foo/**/bar'
+match 1 1 0 0 'foo/baz/bar' 'foo/**/**/bar'
+match 1 1 1 1 'foo/b/a/z/bar' 'foo/**/bar'
+match 1 1 1 1 'foo/b/a/z/bar' 'foo/**/**/bar'
+match 1 1 0 0 'foo/bar' 'foo/**/bar'
+match 1 1 0 0 'foo/bar' 'foo/**/**/bar'
+match 0 0 1 1 'foo/bar' 'foo?bar'
+match 0 0 1 1 'foo/bar' 'foo[/]bar'
+match 0 0 1 1 'foo/bar' 'foo[^a-z]bar'
+match 0 0 1 1 'foo/bar' 'f[^eiu][^eiu][^eiu][^eiu][^eiu]r'
+match 1 1 1 1 'foo-bar' 'f[^eiu][^eiu][^eiu][^eiu][^eiu]r'
+match 1 1 0 0 'foo' '**/foo'
+match 1 1 1 1 'XXX/foo' '**/foo'
+match 1 1 1 1 'bar/baz/foo' '**/foo'
+match 0 0 1 1 'bar/baz/foo' '*/foo'
+match 0 0 1 1 'foo/bar/baz' '**/bar*'
+match 1 1 1 1 'deep/foo/bar/baz' '**/bar/*'
+match 0 0 1 1 'deep/foo/bar/baz/' '**/bar/*'
+match 1 1 1 1 'deep/foo/bar/baz/' '**/bar/**'
+match 0 0 0 0 'deep/foo/bar' '**/bar/*'
+match 1 1 1 1 'deep/foo/bar/' '**/bar/**'
+match 0 0 1 1 'foo/bar/baz' '**/bar**'
+match 1 1 1 1 'foo/bar/baz/x' '*/bar/**'
+match 0 0 1 1 'deep/foo/bar/baz/x' '*/bar/**'
+match 1 1 1 1 'deep/foo/bar/baz/x' '**/bar/*/*'
 
 # Various additional tests
-match 0 'acrt' 'a[c-c]st'
-match 1 'acrt' 'a[c-c]rt'
-match 0 ']' '[!]-]'
-match 1 'a' '[!]-]'
-match 0 '' '\'
-match 0 '\' '\'
-match 0 'XXX/\' '*/\'
-match 1 'XXX/\' '*/\\'
-match 1 'foo' 'foo'
-match 1 '@foo' '@foo'
-match 0 'foo' '@foo'
-match 1 '[ab]' '\[ab]'
-match 1 '[ab]' '[[]ab]'
-match 1 '[ab]' '[[:]ab]'
-match 0 '[ab]' '[[::]ab]'
-match 1 '[ab]' '[[:digit]ab]'
-match 1 '[ab]' '[\[:]ab]'
-match 1 '?a?b' '\??\?b'
-match 1 'abc' '\a\b\c'
-match 0 'foo' ''
-match 1 'foo/bar/baz/to' '**/t[o]'
+match 0 0 0 0 'acrt' 'a[c-c]st'
+match 1 1 1 1 'acrt' 'a[c-c]rt'
+match 0 0 0 0 ']' '[!]-]'
+match 1 1 1 1 'a' '[!]-]'
+match 0 0 0 0 '' '\'
+match 0 0 0 0 '\' '\'
+match 0 0 0 0 'XXX/\' '*/\'
+match 1 1 1 1 'XXX/\' '*/\\'
+match 1 1 1 1 'foo' 'foo'
+match 1 1 1 1 '@foo' '@foo'
+match 0 0 0 0 'foo' '@foo'
+match 1 1 1 1 '[ab]' '\[ab]'
+match 1 1 1 1 '[ab]' '[[]ab]'
+match 1 1 1 1 '[ab]' '[[:]ab]'
+match 0 0 0 0 '[ab]' '[[::]ab]'
+match 1 1 1 1 '[ab]' '[[:digit]ab]'
+match 1 1 1 1 '[ab]' '[\[:]ab]'
+match 1 1 1 1 '?a?b' '\??\?b'
+match 1 1 1 1 'abc' '\a\b\c'
+match 0 0 0 0 'foo' ''
+match 1 1 1 1 'foo/bar/baz/to' '**/t[o]'
 
 # Character class tests
-match 1 'a1B' '[[:alpha:]][[:digit:]][[:upper:]]'
-match 0 'a' '[[:digit:][:upper:][:space:]]'
-match 1 'A' '[[:digit:][:upper:][:space:]]'
-match 1 '1' '[[:digit:][:upper:][:space:]]'
-match 0 '1' '[[:digit:][:upper:][:spaci:]]'
-match 1 ' ' '[[:digit:][:upper:][:space:]]'
-match 0 '.' '[[:digit:][:upper:][:space:]]'
-match 1 '.' '[[:digit:][:punct:][:space:]]'
-match 1 '5' '[[:xdigit:]]'
-match 1 'f' '[[:xdigit:]]'
-match 1 'D' '[[:xdigit:]]'
-match 1 '_' '[[:alnum:][:alpha:][:blank:][:cntrl:][:digit:][:graph:][:lower:][:print:][:punct:][:space:][:upper:][:xdigit:]]'
-match 1 '.' '[^[:alnum:][:alpha:][:blank:][:cntrl:][:digit:][:lower:][:space:][:upper:][:xdigit:]]'
-match 1 '5' '[a-c[:digit:]x-z]'
-match 1 'b' '[a-c[:digit:]x-z]'
-match 1 'y' '[a-c[:digit:]x-z]'
-match 0 'q' '[a-c[:digit:]x-z]'
-
-# Additional tests, including some malformed wildmats
-match 1 ']' '[\\-^]'
-match 0 '[' '[\\-^]'
-match 1 '-' '[\-_]'
-match 1 ']' '[\]]'
-match 0 '\]' '[\]]'
-match 0 '\' '[\]]'
-match 0 'ab' 'a[]b'
-match 0 'a[]b' 'a[]b'
-match 0 'ab[' 'ab['
-match 0 'ab' '[!'
-match 0 'ab' '[-'
-match 1 '-' '[-]'
-match 0 '-' '[a-'
-match 0 '-' '[!a-'
-match 1 '-' '[--A]'
-match 1 '5' '[--A]'
-match 1 ' ' '[ --]'
-match 1 '$' '[ --]'
-match 1 '-' '[ --]'
-match 0 '0' '[ --]'
-match 1 '-' '[---]'
-match 1 '-' '[------]'
-match 0 'j' '[a-e-n]'
-match 1 '-' '[a-e-n]'
-match 1 'a' '[!------]'
-match 0 '[' '[]-a]'
-match 1 '^' '[]-a]'
-match 0 '^' '[!]-a]'
-match 1 '[' '[!]-a]'
-match 1 '^' '[a^bc]'
-match 1 '-b]' '[a-]b]'
-match 0 '\' '[\]'
-match 1 '\' '[\\]'
-match 0 '\' '[!\\]'
-match 1 'G' '[A-\\]'
-match 0 'aaabbb' 'b*a'
-match 0 'aabcaa' '*ba*'
-match 1 ',' '[,]'
-match 1 ',' '[\\,]'
-match 1 '\' '[\\,]'
-match 1 '-' '[,-.]'
-match 0 '+' '[,-.]'
-match 0 '-.]' '[,-.]'
-match 1 '2' '[\1-\3]'
-match 1 '3' '[\1-\3]'
-match 0 '4' '[\1-\3]'
-match 1 '\' '[[-\]]'
-match 1 '[' '[[-\]]'
-match 1 ']' '[[-\]]'
-match 0 '-' '[[-\]]'
+match 1 1 1 1 'a1B' '[[:alpha:]][[:digit:]][[:upper:]]'
+match 0 1 0 1 'a' '[[:digit:][:upper:][:space:]]'
+match 1 1 1 1 'A' '[[:digit:][:upper:][:space:]]'
+match 1 1 1 1 '1' '[[:digit:][:upper:][:space:]]'
+match 0 0 0 0 '1' '[[:digit:][:upper:][:spaci:]]'
+match 1 1 1 1 ' ' '[[:digit:][:upper:][:space:]]'
+match 0 0 0 0 '.' '[[:digit:][:upper:][:space:]]'
+match 1 1 1 1 '.' '[[:digit:][:punct:][:space:]]'
+match 1 1 1 1 '5' '[[:xdigit:]]'
+match 1 1 1 1 'f' '[[:xdigit:]]'
+match 1 1 1 1 'D' '[[:xdigit:]]'
+match 1 1 1 1 '_' '[[:alnum:][:alpha:][:blank:][:cntrl:][:digit:][:graph:][:lower:][:print:][:punct:][:space:][:upper:][:xdigit:]]'
+match 1 1 1 1 '.' '[^[:alnum:][:alpha:][:blank:][:cntrl:][:digit:][:lower:][:space:][:upper:][:xdigit:]]'
+match 1 1 1 1 '5' '[a-c[:digit:]x-z]'
+match 1 1 1 1 'b' '[a-c[:digit:]x-z]'
+match 1 1 1 1 'y' '[a-c[:digit:]x-z]'
+match 0 0 0 0 'q' '[a-c[:digit:]x-z]'
 
-# Test recursion and the abort code (use "wildtest -i" to see iteration counts)
-match 1 '-adobe-courier-bold-o-normal--12-120-75-75-m-70-iso8859-1' '-*-*-*-*-*-*-12-*-*-*-m-*-*-*'
-match 0 '-adobe-courier-bold-o-normal--12-120-75-75-X-70-iso8859-1' '-*-*-*-*-*-*-12-*-*-*-m-*-*-*'
-match 0 '-adobe-courier-bold-o-normal--12-120-75-75-/-70-iso8859-1' '-*-*-*-*-*-*-12-*-*-*-m-*-*-*'
-match 1 'XXX/adobe/courier/bold/o/normal//12/120/75/75/m/70/iso8859/1' 'XXX/*/*/*/*/*/*/12/*/*/*/m/*/*/*'
-match 0 'XXX/adobe/courier/bold/o/normal//12/120/75/75/X/70/iso8859/1' 'XXX/*/*/*/*/*/*/12/*/*/*/m/*/*/*'
-match 1 'abcd/abcdefg/abcdefghijk/abcdefghijklmnop.txt' '**/*a*b*g*n*t'
-match 0 'abcd/abcdefg/abcdefghijk/abcdefghijklmnop.txtz' '**/*a*b*g*n*t'
-match 0 foo '*/*/*'
-match 0 foo/bar '*/*/*'
-match 1 foo/bba/arr '*/*/*'
-match 0 foo/bb/aa/rr '*/*/*'
-match 1 foo/bb/aa/rr '**/**/**'
-match 1 abcXdefXghi '*X*i'
-match 0 ab/cXd/efXg/hi '*X*i'
-match 1 ab/cXd/efXg/hi '*/*X*/*/*i'
-match 1 ab/cXd/efXg/hi '**/*X*/**/*i'
+# Additional tests, including some malformed wildmatch patterns
+match 1 1 1 1 ']' '[\\-^]'
+match 0 0 0 0 '[' '[\\-^]'
+match 1 1 1 1 '-' '[\-_]'
+match 1 1 1 1 ']' '[\]]'
+match 0 0 0 0 '\]' '[\]]'
+match 0 0 0 0 '\' '[\]]'
+match 0 0 0 0 'ab' 'a[]b'
+match 0 0 0 0 'a[]b' 'a[]b'
+match 0 0 0 0 'ab[' 'ab['
+match 0 0 0 0 'ab' '[!'
+match 0 0 0 0 'ab' '[-'
+match 1 1 1 1 '-' '[-]'
+match 0 0 0 0 '-' '[a-'
+match 0 0 0 0 '-' '[!a-'
+match 1 1 1 1 '-' '[--A]'
+match 1 1 1 1 '5' '[--A]'
+match 1 1 1 1 ' ' '[ --]'
+match 1 1 1 1 '$' '[ --]'
+match 1 1 1 1 '-' '[ --]'
+match 0 0 0 0 '0' '[ --]'
+match 1 1 1 1 '-' '[---]'
+match 1 1 1 1 '-' '[------]'
+match 0 0 0 0 'j' '[a-e-n]'
+match 1 1 1 1 '-' '[a-e-n]'
+match 1 1 1 1 'a' '[!------]'
+match 0 0 0 0 '[' '[]-a]'
+match 1 1 1 1 '^' '[]-a]'
+match 0 0 0 0 '^' '[!]-a]'
+match 1 1 1 1 '[' '[!]-a]'
+match 1 1 1 1 '^' '[a^bc]'
+match 1 1 1 1 '-b]' '[a-]b]'
+match 0 0 0 0 '\' '[\]'
+match 1 1 1 1 '\' '[\\]'
+match 0 0 0 0 '\' '[!\\]'
+match 1 1 1 1 'G' '[A-\\]'
+match 0 0 0 0 'aaabbb' 'b*a'
+match 0 0 0 0 'aabcaa' '*ba*'
+match 1 1 1 1 ',' '[,]'
+match 1 1 1 1 ',' '[\\,]'
+match 1 1 1 1 '\' '[\\,]'
+match 1 1 1 1 '-' '[,-.]'
+match 0 0 0 0 '+' '[,-.]'
+match 0 0 0 0 '-.]' '[,-.]'
+match 1 1 1 1 '2' '[\1-\3]'
+match 1 1 1 1 '3' '[\1-\3]'
+match 0 0 0 0 '4' '[\1-\3]'
+match 1 1 1 1 '\' '[[-\]]'
+match 1 1 1 1 '[' '[[-\]]'
+match 1 1 1 1 ']' '[[-\]]'
+match 0 0 0 0 '-' '[[-\]]'
 
-pathmatch 1 foo foo
-pathmatch 0 foo fo
-pathmatch 1 foo/bar foo/bar
-pathmatch 1 foo/bar 'foo/*'
-pathmatch 1 foo/bba/arr 'foo/*'
-pathmatch 1 foo/bba/arr 'foo/**'
-pathmatch 1 foo/bba/arr 'foo*'
-pathmatch 1 foo/bba/arr 'foo**'
-pathmatch 1 foo/bba/arr 'foo/*arr'
-pathmatch 1 foo/bba/arr 'foo/**arr'
-pathmatch 0 foo/bba/arr 'foo/*z'
-pathmatch 0 foo/bba/arr 'foo/**z'
-pathmatch 1 foo/bar 'foo?bar'
-pathmatch 1 foo/bar 'foo[/]bar'
-pathmatch 1 foo/bar 'foo[^a-z]bar'
-pathmatch 0 foo '*/*/*'
-pathmatch 0 foo/bar '*/*/*'
-pathmatch 1 foo/bba/arr '*/*/*'
-pathmatch 1 foo/bb/aa/rr '*/*/*'
-pathmatch 1 abcXdefXghi '*X*i'
-pathmatch 1 ab/cXd/efXg/hi '*/*X*/*/*i'
-pathmatch 1 ab/cXd/efXg/hi '*Xg*i'
+# Test recursion
+match 1 1 1 1 '-adobe-courier-bold-o-normal--12-120-75-75-m-70-iso8859-1' '-*-*-*-*-*-*-12-*-*-*-m-*-*-*'
+match 0 0 0 0 '-adobe-courier-bold-o-normal--12-120-75-75-X-70-iso8859-1' '-*-*-*-*-*-*-12-*-*-*-m-*-*-*'
+match 0 0 0 0 '-adobe-courier-bold-o-normal--12-120-75-75-/-70-iso8859-1' '-*-*-*-*-*-*-12-*-*-*-m-*-*-*'
+match 1 1 1 1 'XXX/adobe/courier/bold/o/normal//12/120/75/75/m/70/iso8859/1' 'XXX/*/*/*/*/*/*/12/*/*/*/m/*/*/*'
+match 0 0 0 0 'XXX/adobe/courier/bold/o/normal//12/120/75/75/X/70/iso8859/1' 'XXX/*/*/*/*/*/*/12/*/*/*/m/*/*/*'
+match 1 1 1 1 'abcd/abcdefg/abcdefghijk/abcdefghijklmnop.txt' '**/*a*b*g*n*t'
+match 0 0 0 0 'abcd/abcdefg/abcdefghijk/abcdefghijklmnop.txtz' '**/*a*b*g*n*t'
+match 0 0 0 0 foo '*/*/*'
+match 0 0 0 0 foo/bar '*/*/*'
+match 1 1 1 1 foo/bba/arr '*/*/*'
+match 0 0 1 1 foo/bb/aa/rr '*/*/*'
+match 1 1 1 1 foo/bb/aa/rr '**/**/**'
+match 1 1 1 1 abcXdefXghi '*X*i'
+match 0 0 1 1 ab/cXd/efXg/hi '*X*i'
+match 1 1 1 1 ab/cXd/efXg/hi '*/*X*/*/*i'
+match 1 1 1 1 ab/cXd/efXg/hi '**/*X*/**/*i'
 
-# Case-sensitivity features
-match 0 'a' '[A-Z]'
-match 1 'A' '[A-Z]'
-match 0 'A' '[a-z]'
-match 1 'a' '[a-z]'
-match 0 'a' '[[:upper:]]'
-match 1 'A' '[[:upper:]]'
-match 0 'A' '[[:lower:]]'
-match 1 'a' '[[:lower:]]'
-match 0 'A' '[B-Za]'
-match 1 'a' '[B-Za]'
-match 0 'A' '[B-a]'
-match 1 'a' '[B-a]'
-match 0 'z' '[Z-y]'
-match 1 'Z' '[Z-y]'
+# Extra pathmatch tests
+match 0 0 0 0 foo fo
+match 1 1 1 1 foo/bar foo/bar
+match 1 1 1 1 foo/bar 'foo/*'
+match 0 0 1 1 foo/bba/arr 'foo/*'
+match 1 1 1 1 foo/bba/arr 'foo/**'
+match 0 0 1 1 foo/bba/arr 'foo*'
+match 0 0 1 1 foo/bba/arr 'foo**'
+match 0 0 1 1 foo/bba/arr 'foo/*arr'
+match 0 0 1 1 foo/bba/arr 'foo/**arr'
+match 0 0 0 0 foo/bba/arr 'foo/*z'
+match 0 0 0 0 foo/bba/arr 'foo/**z'
+match 0 0 1 1 foo/bar 'foo?bar'
+match 0 0 1 1 foo/bar 'foo[/]bar'
+match 0 0 1 1 foo/bar 'foo[^a-z]bar'
+match 0 0 1 1 ab/cXd/efXg/hi '*Xg*i'
 
-imatch 1 'a' '[A-Z]'
-imatch 1 'A' '[A-Z]'
-imatch 1 'A' '[a-z]'
-imatch 1 'a' '[a-z]'
-imatch 1 'a' '[[:upper:]]'
-imatch 1 'A' '[[:upper:]]'
-imatch 1 'A' '[[:lower:]]'
-imatch 1 'a' '[[:lower:]]'
-imatch 1 'A' '[B-Za]'
-imatch 1 'a' '[B-Za]'
-imatch 1 'A' '[B-a]'
-imatch 1 'a' '[B-a]'
-imatch 1 'z' '[Z-y]'
-imatch 1 'Z' '[Z-y]'
+# Extra case-sensitivity tests
+match 0 1 0 1 'a' '[A-Z]'
+match 1 1 1 1 'A' '[A-Z]'
+match 0 1 0 1 'A' '[a-z]'
+match 1 1 1 1 'a' '[a-z]'
+match 0 1 0 1 'a' '[[:upper:]]'
+match 1 1 1 1 'A' '[[:upper:]]'
+match 0 1 0 1 'A' '[[:lower:]]'
+match 1 1 1 1 'a' '[[:lower:]]'
+match 0 1 0 1 'A' '[B-Za]'
+match 1 1 1 1 'a' '[B-Za]'
+match 0 1 0 1 'A' '[B-a]'
+match 1 1 1 1 'a' '[B-a]'
+match 0 1 0 1 'z' '[Z-y]'
+match 1 1 1 1 'Z' '[Z-y]'
 
 test_done
-- 
2.15.1.424.g9478a66081
Ævar Arnfjörð Bjarmason· Jan 30, 2018, 21:21 UTC · re: Ævar Arnfjörð Bjarmason · lore

[PATCH v5 09/10] test-lib: add an EXPENSIVE_ON_WINDOWS prerequisite

Add an EXPENSIVE_ON_WINDOWS prerequisite to mark those tests which are very expensive to run on Windows, but cheap elsewhere.

Certain tests that heavily stress the filesystem or run a lot of shell commands are disproportionately expensive on Windows, this prerequisite will later be used by a tests that runs in 4-8 seconds on a modern Linux system, but takes almost 10 minutes on Windows.

There's no reason to skip such tests by default on other platforms, but Windows users shouldn't need to wait around while they finish.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 t/test-lib.sh | 4 ++++
 1 file changed, 4 insertions(+)
Show changes to t/test-lib.sh +4 −0
diff --git a/t/test-lib.sh b/t/test-lib.sh
index 9a0a21f49a..a2703c7d36 100644
--- a/t/test-lib.sh
+++ b/t/test-lib.sh
@@ -1132,6 +1132,10 @@ test_lazy_prereq EXPENSIVE '
 	test -n "$GIT_TEST_LONG"
 '
 
+test_lazy_prereq EXPENSIVE_ON_WINDOWS '
+	test_have_prereq EXPENSIVE || test_have_prereq !MINGW,!CYGWIN
+'
+
 test_lazy_prereq USR_BIN_TIME '
 	test -x /usr/bin/time
 '
-- 
2.15.1.424.g9478a66081
Ævar Arnfjörð Bjarmason· Jan 30, 2018, 21:21 UTC · re: Ævar Arnfjörð Bjarmason · lore

[PATCH v5 10/10] wildmatch test: mark test as EXPENSIVE_ON_WINDOWS

Mark the newly added test which creates test files on-disk as EXPENSIVE_ON_WINDOWS. According to [1] it takes almost ten minutes to run this test file on Windows after this recent change, but just a few seconds on Linux as noted in my [2].

This could be done faster by exiting earlier, however by using this pattern we'll emit "skip" lines for each skipped test, making it clear we're not running a lot of them in the TAP output, at the cost of some overhead.

1. nycvar.QRO.7.76.6.1801061337020.1337@wbunaarf-fpuvaqryva.tvgsbejvaqbjf.bet
   (https://public-inbox.org/git/nycvar.QRO.7.76.6.1801061337020.1337@wbunaarf-fpuvaqryva.tvgsbejvaqbjf.bet/)
2. 87mv1raz9p.fsf@evledraar.gmail.com
   (https://public-inbox.org/git/87mv1raz9p.fsf@evledraar.gmail.com/)
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 t/t3070-wildmatch.sh | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)
Show changes to t/t3070-wildmatch.sh +8 −8
diff --git a/t/t3070-wildmatch.sh b/t/t3070-wildmatch.sh
index bd11e5acb0..c1fc6ca730 100755
--- a/t/t3070-wildmatch.sh
+++ b/t/t3070-wildmatch.sh
@@ -109,36 +109,36 @@ match_with_ls_files() {
 	then
 		if test -e .git/created_test_file
 		then
-			test_expect_success "$match_function (via ls-files): match dies on '$pattern' '$text'" "
+			test_expect_success EXPENSIVE_ON_WINDOWS "$match_function (via ls-files): match dies on '$pattern' '$text'" "
 				printf '%s' '$text' >expect &&
 				test_must_fail git$ls_files_args ls-files -z -- '$pattern'
 			"
 		else
-			test_expect_failure "$match_function (via ls-files): match skip '$pattern' '$text'" 'false'
+			test_expect_failure EXPENSIVE_ON_WINDOWS "$match_function (via ls-files): match skip '$pattern' '$text'" 'false'
 		fi
 	elif test "$match_expect" = 1
 	then
 		if test -e .git/created_test_file
 		then
-			test_expect_success "$match_function (via ls-files): match '$pattern' '$text'" "
+			test_expect_success EXPENSIVE_ON_WINDOWS "$match_function (via ls-files): match '$pattern' '$text'" "
 				printf '%s' '$text' >expect &&
 				git$ls_files_args ls-files -z -- '$pattern' >actual.raw 2>actual.err &&
 				$match_stdout_stderr_cmp
 			"
 		else
-			test_expect_failure "$match_function (via ls-files): match skip '$pattern' '$text'" 'false'
+			test_expect_failure EXPENSIVE_ON_WINDOWS "$match_function (via ls-files): match skip '$pattern' '$text'" 'false'
 		fi
 	elif test "$match_expect" = 0
 	then
 		if test -e .git/created_test_file
 		then
-			test_expect_success "$match_function (via ls-files): no match '$pattern' '$text'" "
+			test_expect_success EXPENSIVE_ON_WINDOWS "$match_function (via ls-files): no match '$pattern' '$text'" "
 				>expect &&
 				git$ls_files_args ls-files -z -- '$pattern' >actual.raw 2>actual.err &&
 				$match_stdout_stderr_cmp
 			"
 		else
-			test_expect_failure "$match_function (via ls-files): no match skip '$pattern' '$text'" 'false'
+			test_expect_failure EXPENSIVE_ON_WINDOWS "$match_function (via ls-files): no match skip '$pattern' '$text'" 'false'
 		fi
 	else
 		test_expect_success "PANIC: Test framework error. Unknown matches value $match_expect" 'false'
@@ -174,7 +174,7 @@ match() {
 		pattern=${10}
 	fi
 
-	test_expect_success 'cleanup after previous file test' '
+	test_expect_success EXPENSIVE_ON_WINDOWS 'cleanup after previous file test' '
 		if test -e .git/created_test_file
 		then
 			git reset &&
@@ -184,7 +184,7 @@ match() {
 
 	printf '%s' "$text" >.git/expected_test_file
 
-	test_expect_success "setup match file test for $text" '
+	test_expect_success EXPENSIVE_ON_WINDOWS "setup match file test for $text" '
 		file=$(cat .git/expected_test_file) &&
 		if should_create_test_file "$file"
 		then
-- 
2.15.1.424.g9478a66081
Ævar Arnfjörð Bjarmason· Jan 30, 2018, 21:21 UTC · re: Ævar Arnfjörð Bjarmason · lore

[PATCH v5 08/10] wildmatch test: create & test files on disk in addition to in-memory

There has never been any full roundtrip testing of what git-ls-files and other commands that use wildmatch() actually do, rather we've been satisfied with just testing the underlying C function.

Due to git-ls-files and friends having their own codepaths before they call wildmatch() there's sometimes differences in the behavior between the two. Even when we test for those (as with [1]), there was no one place where you can review how these two modes differ.

Now there is. We now attempt to create a file called $haystack and match $needle against it for each pair of $needle and $haystack that we were passing to test-wildmatch.

If we can't create the file we skip the test. This ensures that we can run this on all platforms and not maintain some infinitely growing whitelist of e.g. platforms that don't support certain characters in filenames.

A notable exception to this is Windows, where due to the reasons explained in [2] the shellscript emulation layer might fake the creation of a file such as "*", and "test -e" for it will succeed since it just got created with some character that maps to "*", but git ls-files won't be fooled by this.

Thus we need to skip creating certain filenames entirely on Windows, the list here might be overly aggressive. I don't have access to a Windows system to test this.

As a result of doing these tests we can now see the cases where these two ways of testing wildmatch differ:

 * Creating a file called 'a[]b' and running ls-files 'a[]b' will show
   that file, but wildmatch("a[]b", "a[]b") will not match
 * wildmatch() won't match a file called \ against \, but ls-files
   will.
 * `git --glob-pathspecs ls-files 'foo**'` will match a file
   'foo/bba/arr', but wildmatch won't, however pathmatch will.
   This seems like a bug to me, the two are otherwise equivalent as
   these tests show.

This also reveals the case discussed in [1], since 2.16.0 '' is now an error as far as ls-files is concerned, but wildmatch() itself happily accepts it.

1. 9e4e8a64c2 ("pathspec: die on empty strings as pathspec",
   2017-06-06)
2. nycvar.QRO.7.76.6.1801052133380.1337@wbunaarf-fpuvaqryva.tvgsbejvaqbjf.bet
   (https://public-inbox.org/git/?q=nycvar.QRO.7.76.6.1801052133380.1337%40wbunaarf-fpuvaqryva.tvgsbejvaqbjf.bet)
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 t/t3070-wildmatch.sh | 201 ++++++++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 190 insertions(+), 11 deletions(-)
Show changes to t/t3070-wildmatch.sh +190 −11
diff --git a/t/t3070-wildmatch.sh b/t/t3070-wildmatch.sh
index 3e75cb0cbe..bd11e5acb0 100755
--- a/t/t3070-wildmatch.sh
+++ b/t/t3070-wildmatch.sh
@@ -4,6 +4,72 @@ test_description='wildmatch tests'
 
 . ./test-lib.sh
 
+should_create_test_file() {
+	file=$1
+
+	case $file in
+	# `touch .` will succeed but obviously not do what we intend
+	# here.
+	".")
+		return 1
+		;;
+	# We cannot create a file with an empty filename.
+	"")
+		return 1
+		;;
+	# The tests that are testing that e.g. foo//bar is matched by
+	# foo/*/bar can't be tested on filesystems since there's no
+	# way we're getting a double slash.
+	*//*)
+		return 1
+		;;
+	# When testing the difference between foo/bar and foo/bar/ we
+	# can't test the latter.
+	*/)
+		return 1
+		;;
+	# On Windows, \ in paths is silently converted to /, which
+	# would result in the "touch" below working, but the test
+	# itself failing. See 6fd1106aa4 ("t3700: Skip a test with
+	# backslashes in pathspec", 2009-03-13) for prior art and
+	# details.
+	*\\*)
+		if ! test_have_prereq BSLASHPSPEC
+		then
+			return 1
+		fi
+		# NOTE: The ;;& bash extension is not portable, so
+		# this test needs to be at the end of the pattern
+		# list.
+		#
+		# If we want to add more conditional returns we either
+		# need a new case statement, or turn this whole thing
+		# into a series of "if" tests.
+		;;
+	esac
+
+
+	# On Windows proper (i.e. not Cygwin) many file names which
+	# under Cygwin would be emulated don't work.
+	if test_have_prereq MINGW
+	then
+		case $file in
+		" ")
+			# Files called " " are forbidden on Windows
+			return 1
+			;;
+		*\<*|*\>*|*:*|*\"*|*\|*|*\?*|*\**)
+			# Files with various special characters aren't
+			# allowed on Windows. Sourced from
+			# https://stackoverflow.com/a/31976060
+			return 1
+			;;
+		esac
+	fi
+
+	return 0
+}
+
 match_with_function() {
 	text=$1
 	pattern=$2
@@ -26,25 +92,133 @@ match_with_function() {
 
 }
 
+match_with_ls_files() {
+	text=$1
+	pattern=$2
+	match_expect=$3
+	match_function=$4
+	ls_files_args=$5
+
+	match_stdout_stderr_cmp="
+		tr -d '\0' <actual.raw >actual &&
+		>expect.err &&
+		test_cmp expect.err actual.err &&
+		test_cmp expect actual"
+
+	if test "$match_expect" = 'E'
+	then
+		if test -e .git/created_test_file
+		then
+			test_expect_success "$match_function (via ls-files): match dies on '$pattern' '$text'" "
+				printf '%s' '$text' >expect &&
+				test_must_fail git$ls_files_args ls-files -z -- '$pattern'
+			"
+		else
+			test_expect_failure "$match_function (via ls-files): match skip '$pattern' '$text'" 'false'
+		fi
+	elif test "$match_expect" = 1
+	then
+		if test -e .git/created_test_file
+		then
+			test_expect_success "$match_function (via ls-files): match '$pattern' '$text'" "
+				printf '%s' '$text' >expect &&
+				git$ls_files_args ls-files -z -- '$pattern' >actual.raw 2>actual.err &&
+				$match_stdout_stderr_cmp
+			"
+		else
+			test_expect_failure "$match_function (via ls-files): match skip '$pattern' '$text'" 'false'
+		fi
+	elif test "$match_expect" = 0
+	then
+		if test -e .git/created_test_file
+		then
+			test_expect_success "$match_function (via ls-files): no match '$pattern' '$text'" "
+				>expect &&
+				git$ls_files_args ls-files -z -- '$pattern' >actual.raw 2>actual.err &&
+				$match_stdout_stderr_cmp
+			"
+		else
+			test_expect_failure "$match_function (via ls-files): no match skip '$pattern' '$text'" 'false'
+		fi
+	else
+		test_expect_success "PANIC: Test framework error. Unknown matches value $match_expect" 'false'
+	fi
+}
+
 match() {
-	match_glob=$1
-	match_iglob=$2
-	match_pathmatch=$3
-	match_pathmatchi=$4
-	text=$5
-	pattern=$6
+	if test "$#" = 6
+	then
+		# When test-wildmatch and git ls-files produce the same
+		# result.
+		match_glob=$1
+		match_file_glob=$match_glob
+		match_iglob=$2
+		match_file_iglob=$match_iglob
+		match_pathmatch=$3
+		match_file_pathmatch=$match_pathmatch
+		match_pathmatchi=$4
+		match_file_pathmatchi=$match_pathmatchi
+		text=$5
+		pattern=$6
+	elif test "$#" = 10
+	then
+		match_glob=$1
+		match_iglob=$2
+		match_pathmatch=$3
+		match_pathmatchi=$4
+		match_file_glob=$5
+		match_file_iglob=$6
+		match_file_pathmatch=$7
+		match_file_pathmatchi=$8
+		text=$9
+		pattern=${10}
+	fi
+
+	test_expect_success 'cleanup after previous file test' '
+		if test -e .git/created_test_file
+		then
+			git reset &&
+			git clean -df
+		fi
+	'
+
+	printf '%s' "$text" >.git/expected_test_file
+
+	test_expect_success "setup match file test for $text" '
+		file=$(cat .git/expected_test_file) &&
+		if should_create_test_file "$file"
+		then
+			dirs=${file%/*}
+			if test "$file" != "$dirs"
+			then
+				mkdir -p -- "$dirs" &&
+				touch -- "./$text"
+			else
+				touch -- "./$file"
+			fi &&
+			git add -A &&
+			printf "%s" "$file" >.git/created_test_file
+		elif test -e .git/created_test_file
+		then
+			rm .git/created_test_file
+		fi
+	'
 
 	# $1: Case sensitive glob match: test-wildmatch & ls-files
 	match_with_function "$text" "$pattern" $match_glob "wildmatch"
+	match_with_ls_files "$text" "$pattern" $match_file_glob "wildmatch" " --glob-pathspecs"
 
 	# $2: Case insensitive glob match: test-wildmatch & ls-files
 	match_with_function "$text" "$pattern" $match_iglob "iwildmatch"
+	match_with_ls_files "$text" "$pattern" $match_file_iglob "iwildmatch" " --glob-pathspecs --icase-pathspecs"
 
 	# $3: Case sensitive path match: test-wildmatch & ls-files
 	match_with_function "$text" "$pattern" $match_pathmatch "pathmatch"
+	match_with_ls_files "$text" "$pattern" $match_file_pathmatch "pathmatch" ""
 
 	# $4: Case insensitive path match: test-wildmatch & ls-files
 	match_with_function "$text" "$pattern" $match_pathmatchi "ipathmatch"
+	match_with_ls_files "$text" "$pattern" $match_file_pathmatchi "ipathmatch" " --icase-pathspecs"
 }
 
 # Basic wildmatch features
@@ -113,7 +287,8 @@ match 1 1 1 1 'acrt' 'a[c-c]rt'
 match 0 0 0 0 ']' '[!]-]'
 match 1 1 1 1 'a' '[!]-]'
 match 0 0 0 0 '' '\'
-match 0 0 0 0 '\' '\'
+match 0 0 0 0 \
+      1 1 1 1 '\' '\'
 match 0 0 0 0 'XXX/\' '*/\'
 match 1 1 1 1 'XXX/\' '*/\\'
 match 1 1 1 1 'foo' 'foo'
@@ -127,7 +302,8 @@ match 1 1 1 1 '[ab]' '[[:digit]ab]'
 match 1 1 1 1 '[ab]' '[\[:]ab]'
 match 1 1 1 1 '?a?b' '\??\?b'
 match 1 1 1 1 'abc' '\a\b\c'
-match 0 0 0 0 'foo' ''
+match 0 0 0 0 \
+      E E E E 'foo' ''
 match 1 1 1 1 'foo/bar/baz/to' '**/t[o]'
 
 # Character class tests
@@ -157,8 +333,10 @@ match 1 1 1 1 ']' '[\]]'
 match 0 0 0 0 '\]' '[\]]'
 match 0 0 0 0 '\' '[\]]'
 match 0 0 0 0 'ab' 'a[]b'
-match 0 0 0 0 'a[]b' 'a[]b'
-match 0 0 0 0 'ab[' 'ab['
+match 0 0 0 0 \
+      1 1 1 1 'a[]b' 'a[]b'
+match 0 0 0 0 \
+      1 1 1 1 'ab[' 'ab['
 match 0 0 0 0 'ab' '[!'
 match 0 0 0 0 'ab' '[-'
 match 1 1 1 1 '-' '[-]'
@@ -226,7 +404,8 @@ match 1 1 1 1 foo/bar 'foo/*'
 match 0 0 1 1 foo/bba/arr 'foo/*'
 match 1 1 1 1 foo/bba/arr 'foo/**'
 match 0 0 1 1 foo/bba/arr 'foo*'
-match 0 0 1 1 foo/bba/arr 'foo**'
+match 0 0 1 1 \
+      1 1 1 1 foo/bba/arr 'foo**'
 match 0 0 1 1 foo/bba/arr 'foo/*arr'
 match 0 0 1 1 foo/bba/arr 'foo/**arr'
 match 0 0 0 0 foo/bba/arr 'foo/*z'
-- 
2.15.1.424.g9478a66081
Junio C Hamano· Dec 28, 2017, 22:48 UTC · re: Ævar Arnfjörð Bjarmason · lore

Re: [PATCH v2 0/7] increase wildmatch test coverage

Ævar Arnfjörð Bjarmason  <avarab@gmail.com> writes:
> This v2 addresses comments by Johannes Sixt in
> <8f4cdb23-8e2e-144a-1f70-99776b027166@kdbg.org> and there's osme other
> cleanups as noted below.

One thing I found "interesting" (because it is usually the other way around) is that about two dozens of the tests in this fail when your shell is bash and all of them pass when your shell is dash.

Ævar Arnfjörð Bjarmason· Dec 28, 2017, 23:49 UTC · re: Junio C Hamano · lore

Re: [PATCH v2 0/7] increase wildmatch test coverage

On Thu, Dec 28 2017, Junio C. Hamano jotted:
Show 9 quoted lines
> Ævar Arnfjörð Bjarmason  <avarab@gmail.com> writes:
>
>> This v2 addresses comments by Johannes Sixt in
>> <8f4cdb23-8e2e-144a-1f70-99776b027166@kdbg.org> and there's osme other
>> cleanups as noted below.
>
> One thing I found "interesting" (because it is usually the other way
> around) is that about two dozens of the tests in this fail when your
> shell is bash and all of them pass when your shell is dash.

I sent out v3 before seeing this. I can reproduce this and will send a v4 with a fix.

Ævar Arnfjörð Bjarmason· Dec 28, 2017, 23:28 UTC · re: Ævar Arnfjörð Bjarmason · lore

[PATCH v3 0/7] increase wildmatch test coverage

Fixes issues noted since v2 and one I spotted myself, notes below:
Ævar Arnfjörð Bjarmason (7):
  wildmatch test: indent with tabs, not spaces
  wildmatch test: use more standard shell style
  wildmatch test: don't try to vertically align our output
  wildmatch test: use a paranoia pattern from nul_match()
  wildmatch test: remove dead fnmatch() test code
No changes.
  wildmatch test: perform all tests under all wildmatch() modes

Fix vertical alignment of new test (that was just changed back later in v2).

  wildmatch test: create & test files on disk in addition to in-memory
* Use ${file%/*} instead of forking for finding the dir part of a path
* Consistently name tests, e.g. I had some called wildmatch and
  wildmatch(ls), but then iwildmatch and wildmatch(ls) again, now it's
  iwildmatch(ls) in the second case.
 t/helper/test-wildmatch.c |   2 +
 t/t3070-wildmatch.sh      | 759 +++++++++++++++++++++++++++++++---------------
 2 files changed, 516 insertions(+), 245 deletions(-)
-- 
2.15.1.424.g9478a66081
Ævar Arnfjörð Bjarmason· Dec 28, 2017, 23:28 UTC · re: Ævar Arnfjörð Bjarmason · lore

[PATCH v3 1/7] wildmatch test: indent with tabs, not spaces

Replace the 4-width mixed space & tab indentation in this file with indentation with tabs as we do in most of the rest of our tests.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 t/t3070-wildmatch.sh | 54 ++++++++++++++++++++++++++--------------------------
 1 file changed, 27 insertions(+), 27 deletions(-)
Show changes to t/t3070-wildmatch.sh +27 −27
diff --git a/t/t3070-wildmatch.sh b/t/t3070-wildmatch.sh
index 163a14a1c2..27fa878f6e 100755
--- a/t/t3070-wildmatch.sh
+++ b/t/t3070-wildmatch.sh
@@ -5,39 +5,39 @@ test_description='wildmatch tests'
 . ./test-lib.sh
 
 match() {
-    if [ $1 = 1 ]; then
-	test_expect_success "wildmatch:     match '$3' '$4'" "
-	    test-wildmatch wildmatch '$3' '$4'
-	"
-    else
-	test_expect_success "wildmatch:  no match '$3' '$4'" "
-	    ! test-wildmatch wildmatch '$3' '$4'
-	"
-    fi
+	if [ $1 = 1 ]; then
+		test_expect_success "wildmatch:     match '$3' '$4'" "
+			test-wildmatch wildmatch '$3' '$4'
+		"
+	else
+		test_expect_success "wildmatch:  no match '$3' '$4'" "
+			! test-wildmatch wildmatch '$3' '$4'
+		"
+	fi
 }
 
 imatch() {
-    if [ $1 = 1 ]; then
-	test_expect_success "iwildmatch:    match '$2' '$3'" "
-	    test-wildmatch iwildmatch '$2' '$3'
-	"
-    else
-	test_expect_success "iwildmatch: no match '$2' '$3'" "
-	    ! test-wildmatch iwildmatch '$2' '$3'
-	"
-    fi
+	if [ $1 = 1 ]; then
+		test_expect_success "iwildmatch:    match '$2' '$3'" "
+			test-wildmatch iwildmatch '$2' '$3'
+		"
+	else
+		test_expect_success "iwildmatch: no match '$2' '$3'" "
+			! test-wildmatch iwildmatch '$2' '$3'
+		"
+	fi
 }
 
 pathmatch() {
-    if [ $1 = 1 ]; then
-	test_expect_success "pathmatch:     match '$2' '$3'" "
-	    test-wildmatch pathmatch '$2' '$3'
-	"
-    else
-	test_expect_success "pathmatch:  no match '$2' '$3'" "
-	    ! test-wildmatch pathmatch '$2' '$3'
-	"
-    fi
+	if [ $1 = 1 ]; then
+		test_expect_success "pathmatch:     match '$2' '$3'" "
+			test-wildmatch pathmatch '$2' '$3'
+		"
+	else
+		test_expect_success "pathmatch:  no match '$2' '$3'" "
+			! test-wildmatch pathmatch '$2' '$3'
+		"
+	fi
 }
 
 # Basic wildmat features
-- 
2.15.1.424.g9478a66081
Ævar Arnfjörð Bjarmason· Dec 28, 2017, 23:28 UTC · re: Ævar Arnfjörð Bjarmason · lore

[PATCH v3 3/7] wildmatch test: don't try to vertically align our output

Don't try to vertically align the test output, which is futile anyway under the TAP output where we're going to be emitting a number for each test without aligning the test count.

This makes subsequent changes of mine where I'm not going to be aligning this output as I add new tests easier.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 t/t3070-wildmatch.sh | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)
Show changes to t/t3070-wildmatch.sh +5 −5
diff --git a/t/t3070-wildmatch.sh b/t/t3070-wildmatch.sh
index 4d589d1f9a..19ea64bba9 100755
--- a/t/t3070-wildmatch.sh
+++ b/t/t3070-wildmatch.sh
@@ -7,11 +7,11 @@ test_description='wildmatch tests'
 match() {
 	if test "$1" = 1
 	then
-		test_expect_success "wildmatch:     match '$3' '$4'" "
+		test_expect_success "wildmatch: match '$3' '$4'" "
 			test-wildmatch wildmatch '$3' '$4'
 		"
 	else
-		test_expect_success "wildmatch:  no match '$3' '$4'" "
+		test_expect_success "wildmatch: no match '$3' '$4'" "
 			! test-wildmatch wildmatch '$3' '$4'
 		"
 	fi
@@ -20,7 +20,7 @@ match() {
 imatch() {
 	if test "$1" = 1
 	then
-		test_expect_success "iwildmatch:    match '$2' '$3'" "
+		test_expect_success "iwildmatch: match '$2' '$3'" "
 			test-wildmatch iwildmatch '$2' '$3'
 		"
 	else
@@ -33,11 +33,11 @@ imatch() {
 pathmatch() {
 	if test "$1" = 1
 	then
-		test_expect_success "pathmatch:     match '$2' '$3'" "
+		test_expect_success "pathmatch: match '$2' '$3'" "
 			test-wildmatch pathmatch '$2' '$3'
 		"
 	else
-		test_expect_success "pathmatch:  no match '$2' '$3'" "
+		test_expect_success "pathmatch: no match '$2' '$3'" "
 			! test-wildmatch pathmatch '$2' '$3'
 		"
 	fi
-- 
2.15.1.424.g9478a66081
Ævar Arnfjörð Bjarmason· Dec 28, 2017, 23:28 UTC · re: Ævar Arnfjörð Bjarmason · lore

[PATCH v3 2/7] wildmatch test: use more standard shell style

Change the wildmatch test to use more standard shell style, usually we use "if test" not "if [".

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 t/t3070-wildmatch.sh | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)
Show changes to t/t3070-wildmatch.sh +6 −3
diff --git a/t/t3070-wildmatch.sh b/t/t3070-wildmatch.sh
index 27fa878f6e..4d589d1f9a 100755
--- a/t/t3070-wildmatch.sh
+++ b/t/t3070-wildmatch.sh
@@ -5,7 +5,8 @@ test_description='wildmatch tests'
 . ./test-lib.sh
 
 match() {
-	if [ $1 = 1 ]; then
+	if test "$1" = 1
+	then
 		test_expect_success "wildmatch:     match '$3' '$4'" "
 			test-wildmatch wildmatch '$3' '$4'
 		"
@@ -17,7 +18,8 @@ match() {
 }
 
 imatch() {
-	if [ $1 = 1 ]; then
+	if test "$1" = 1
+	then
 		test_expect_success "iwildmatch:    match '$2' '$3'" "
 			test-wildmatch iwildmatch '$2' '$3'
 		"
@@ -29,7 +31,8 @@ imatch() {
 }
 
 pathmatch() {
-	if [ $1 = 1 ]; then
+	if test "$1" = 1
+	then
 		test_expect_success "pathmatch:     match '$2' '$3'" "
 			test-wildmatch pathmatch '$2' '$3'
 		"
-- 
2.15.1.424.g9478a66081
Ævar Arnfjörð Bjarmason· Dec 28, 2017, 23:28 UTC · re: Ævar Arnfjörð Bjarmason · lore

[PATCH v3 6/7] wildmatch test: perform all tests under all wildmatch() modes

Rewrite the wildmatch() test suite so that each test now tests all combinations of the wildmatch() WM_CASEFOLD and WM_PATHNAME flags.

Before this change some test inputs were not tested on e.g. WM_PATHNAME. Now the function is stress tested on all possible inputs, and for each input we declare what the result should be if the mode is case-insensitive, or pathname matching, or case-sensitive or not matching pathnames.

Also before this change, nothing was testing case-insensitive non-pathname matching, so I've added that to test-wildmatch.c and made use of it.

This yields a rather scary patch, but there are no functional changes here, just more test coverage. Some now-redundant tests were deleted as a result of this change, since they were now duplicating an earlier test.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 t/helper/test-wildmatch.c |   2 +
 t/t3070-wildmatch.sh      | 478 +++++++++++++++++++++++-----------------------
 2 files changed, 239 insertions(+), 241 deletions(-)
Show changes to 2 files +239 −241

t/helper/test-wildmatch.c, t/t3070-wildmatch.sh

diff --git a/t/helper/test-wildmatch.c b/t/helper/test-wildmatch.c
index 921d7b3e7e..66d33dfcfd 100644
--- a/t/helper/test-wildmatch.c
+++ b/t/helper/test-wildmatch.c
@@ -16,6 +16,8 @@ int cmd_main(int argc, const char **argv)
 		return !!wildmatch(argv[3], argv[2], WM_PATHNAME | WM_CASEFOLD);
 	else if (!strcmp(argv[1], "pathmatch"))
 		return !!wildmatch(argv[3], argv[2], 0);
+	else if (!strcmp(argv[1], "ipathmatch"))
+		return !!wildmatch(argv[3], argv[2], WM_CASEFOLD);
 	else
 		return 1;
 }
diff --git a/t/t3070-wildmatch.sh b/t/t3070-wildmatch.sh
index 2f8a681c72..06db053ae2 100755
--- a/t/t3070-wildmatch.sh
+++ b/t/t3070-wildmatch.sh
@@ -4,278 +4,274 @@ test_description='wildmatch tests'
 
 . ./test-lib.sh
 
-match() {
-	if test "$1" = 1
+wildtest() {
+	match_w_glob=$1
+	match_w_globi=$2
+	match_w_pathmatch=$3
+	match_w_pathmatchi=$4
+	text=$5
+	pattern=$6
+
+	if test "$match_w_glob" = 1
 	then
-		test_expect_success "wildmatch: match '$2' '$3'" "
-			test-wildmatch wildmatch '$2' '$3'
+		test_expect_success "wildmatch: match '$text' '$pattern'" "
+			test-wildmatch wildmatch '$text' '$pattern'
 		"
-	elif test "$1" = 0
+	elif test "$match_w_glob" = 0
 	then
-		test_expect_success "wildmatch: no match '$2' '$3'" "
-			! test-wildmatch wildmatch '$2' '$3'
+		test_expect_success "wildmatch: no match '$text' '$pattern'" "
+			! test-wildmatch wildmatch '$text' '$pattern'
 		"
 	else
-		test_expect_success "PANIC: Test framework error. Unknown matches value $1" 'false'
+		test_expect_success "PANIC: Test framework error. Unknown matches value $match_w_glob" 'false'
 	fi
-}
 
-imatch() {
-	if test "$1" = 1
+	if test "$match_w_globi" = 1
 	then
-		test_expect_success "iwildmatch: match '$2' '$3'" "
-			test-wildmatch iwildmatch '$2' '$3'
+		test_expect_success "iwildmatch: match '$text' '$pattern'" "
+			test-wildmatch iwildmatch '$text' '$pattern'
 		"
-	elif test "$1" = 0
+	elif test "$match_w_globi" = 0
 	then
-		test_expect_success "iwildmatch: no match '$2' '$3'" "
-			! test-wildmatch iwildmatch '$2' '$3'
+		test_expect_success "iwildmatch: no match '$text' '$pattern'" "
+			! test-wildmatch iwildmatch '$text' '$pattern'
 		"
 	else
-		test_expect_success "PANIC: Test framework error. Unknown matches value $1" 'false'
+		test_expect_success "PANIC: Test framework error. Unknown matches value $match_w_globi" 'false'
 	fi
-}
 
-pathmatch() {
-	if test "$1" = 1
+	if test "$match_w_pathmatch" = 1
 	then
-		test_expect_success "pathmatch: match '$2' '$3'" "
-			test-wildmatch pathmatch '$2' '$3'
+		test_expect_success "pathmatch: match '$text' '$pattern'" "
+			test-wildmatch pathmatch '$text' '$pattern'
 		"
-	elif test "$1" = 0
+	elif test "$match_w_pathmatch" = 0
 	then
-		test_expect_success "pathmatch: no match '$2' '$3'" "
-			! test-wildmatch pathmatch '$2' '$3'
+		test_expect_success "pathmatch: no match '$text' '$pattern'" "
+			! test-wildmatch pathmatch '$text' '$pattern'
 		"
 	else
-		test_expect_success "PANIC: Test framework error. Unknown matches value $1" 'false'
+		test_expect_success "PANIC: Test framework error. Unknown matches value $match_w_pathmatch" 'false'
+	fi
+
+	if test "$match_w_pathmatchi" = 1
+	then
+		test_expect_success "ipathmatch: match '$text' '$pattern'" "
+			test-wildmatch ipathmatch '$text' '$pattern'
+		"
+	elif test "$match_w_pathmatchi" = 0
+	then
+		test_expect_success "ipathmatch: no match '$text' '$pattern'" "
+			! test-wildmatch ipathmatch '$text' '$pattern'
+		"
+	else
+		test_expect_success "PANIC: Test framework error. Unknown matches value $match_w_pathmatchi" 'false'
 	fi
 }
 
-# Basic wildmat features
-match 1 foo foo
-match 0 foo bar
-match 1 '' ""
-match 1 foo '???'
-match 0 foo '??'
-match 1 foo '*'
-match 1 foo 'f*'
-match 0 foo '*f'
-match 1 foo '*foo*'
-match 1 foobar '*ob*a*r*'
-match 1 aaaaaaabababab '*ab'
-match 1 'foo*' 'foo\*'
-match 0 foobar 'foo\*bar'
-match 1 'f\oo' 'f\\oo'
-match 1 ball '*[al]?'
-match 0 ten '[ten]'
-match 0 ten '**[!te]'
-match 0 ten '**[!ten]'
-match 1 ten 't[a-g]n'
-match 0 ten 't[!a-g]n'
-match 1 ton 't[!a-g]n'
-match 1 ton 't[^a-g]n'
-match 1 'a]b' 'a[]]b'
-match 1 a-b 'a[]-]b'
-match 1 'a]b' 'a[]-]b'
-match 0 aab 'a[]-]b'
-match 1 aab 'a[]a-]b'
-match 1 ']' ']'
+# Basic wildmatch features
+wildtest 1 1 1 1 foo foo
+wildtest 0 0 0 0 foo bar
+wildtest 1 1 1 1 '' ""
+wildtest 1 1 1 1 foo '???'
+wildtest 0 0 0 0 foo '??'
+wildtest 1 1 1 1 foo '*'
+wildtest 1 1 1 1 foo 'f*'
+wildtest 0 0 0 0 foo '*f'
+wildtest 1 1 1 1 foo '*foo*'
+wildtest 1 1 1 1 foobar '*ob*a*r*'
+wildtest 1 1 1 1 aaaaaaabababab '*ab'
+wildtest 1 1 1 1 'foo*' 'foo\*'
+wildtest 0 0 0 0 foobar 'foo\*bar'
+wildtest 1 1 1 1 'f\oo' 'f\\oo'
+wildtest 1 1 1 1 ball '*[al]?'
+wildtest 0 0 0 0 ten '[ten]'
+wildtest 0 0 1 1 ten '**[!te]'
+wildtest 0 0 0 0 ten '**[!ten]'
+wildtest 1 1 1 1 ten 't[a-g]n'
+wildtest 0 0 0 0 ten 't[!a-g]n'
+wildtest 1 1 1 1 ton 't[!a-g]n'
+wildtest 1 1 1 1 ton 't[^a-g]n'
+wildtest 1 1 1 1 'a]b' 'a[]]b'
+wildtest 1 1 1 1 a-b 'a[]-]b'
+wildtest 1 1 1 1 'a]b' 'a[]-]b'
+wildtest 0 0 0 0 aab 'a[]-]b'
+wildtest 1 1 1 1 aab 'a[]a-]b'
+wildtest 1 1 1 1 ']' ']'
 
 # Extended slash-matching features
-match 0 'foo/baz/bar' 'foo*bar'
-match 0 'foo/baz/bar' 'foo**bar'
-match 0 'foobazbar' 'foo**bar'
-match 1 'foo/baz/bar' 'foo/**/bar'
-match 1 'foo/baz/bar' 'foo/**/**/bar'
-match 1 'foo/b/a/z/bar' 'foo/**/bar'
-match 1 'foo/b/a/z/bar' 'foo/**/**/bar'
-match 1 'foo/bar' 'foo/**/bar'
-match 1 'foo/bar' 'foo/**/**/bar'
-match 0 'foo/bar' 'foo?bar'
-match 0 'foo/bar' 'foo[/]bar'
-match 0 'foo/bar' 'foo[^a-z]bar'
-match 0 'foo/bar' 'f[^eiu][^eiu][^eiu][^eiu][^eiu]r'
-match 1 'foo-bar' 'f[^eiu][^eiu][^eiu][^eiu][^eiu]r'
-match 1 'foo' '**/foo'
-match 1 'XXX/foo' '**/foo'
-match 1 'bar/baz/foo' '**/foo'
-match 0 'bar/baz/foo' '*/foo'
-match 0 'foo/bar/baz' '**/bar*'
-match 1 'deep/foo/bar/baz' '**/bar/*'
-match 0 'deep/foo/bar/baz/' '**/bar/*'
-match 1 'deep/foo/bar/baz/' '**/bar/**'
-match 0 'deep/foo/bar' '**/bar/*'
-match 1 'deep/foo/bar/' '**/bar/**'
-match 0 'foo/bar/baz' '**/bar**'
-match 1 'foo/bar/baz/x' '*/bar/**'
-match 0 'deep/foo/bar/baz/x' '*/bar/**'
-match 1 'deep/foo/bar/baz/x' '**/bar/*/*'
+wildtest 0 0 1 1 'foo/baz/bar' 'foo*bar'
+wildtest 0 0 1 1 'foo/baz/bar' 'foo**bar'
+wildtest 0 0 1 1 'foobazbar' 'foo**bar'
+wildtest 1 1 1 1 'foo/baz/bar' 'foo/**/bar'
+wildtest 1 1 0 0 'foo/baz/bar' 'foo/**/**/bar'
+wildtest 1 1 1 1 'foo/b/a/z/bar' 'foo/**/bar'
+wildtest 1 1 1 1 'foo/b/a/z/bar' 'foo/**/**/bar'
+wildtest 1 1 0 0 'foo/bar' 'foo/**/bar'
+wildtest 1 1 0 0 'foo/bar' 'foo/**/**/bar'
+wildtest 0 0 1 1 'foo/bar' 'foo?bar'
+wildtest 0 0 1 1 'foo/bar' 'foo[/]bar'
+wildtest 0 0 1 1 'foo/bar' 'foo[^a-z]bar'
+wildtest 0 0 1 1 'foo/bar' 'f[^eiu][^eiu][^eiu][^eiu][^eiu]r'
+wildtest 1 1 1 1 'foo-bar' 'f[^eiu][^eiu][^eiu][^eiu][^eiu]r'
+wildtest 1 1 0 0 'foo' '**/foo'
+wildtest 1 1 1 1 'XXX/foo' '**/foo'
+wildtest 1 1 1 1 'bar/baz/foo' '**/foo'
+wildtest 0 0 1 1 'bar/baz/foo' '*/foo'
+wildtest 0 0 1 1 'foo/bar/baz' '**/bar*'
+wildtest 1 1 1 1 'deep/foo/bar/baz' '**/bar/*'
+wildtest 0 0 1 1 'deep/foo/bar/baz/' '**/bar/*'
+wildtest 1 1 1 1 'deep/foo/bar/baz/' '**/bar/**'
+wildtest 0 0 0 0 'deep/foo/bar' '**/bar/*'
+wildtest 1 1 1 1 'deep/foo/bar/' '**/bar/**'
+wildtest 0 0 1 1 'foo/bar/baz' '**/bar**'
+wildtest 1 1 1 1 'foo/bar/baz/x' '*/bar/**'
+wildtest 0 0 1 1 'deep/foo/bar/baz/x' '*/bar/**'
+wildtest 1 1 1 1 'deep/foo/bar/baz/x' '**/bar/*/*'
 
 # Various additional tests
-match 0 'acrt' 'a[c-c]st'
-match 1 'acrt' 'a[c-c]rt'
-match 0 ']' '[!]-]'
-match 1 'a' '[!]-]'
-match 0 '' '\'
-match 0 '\' '\'
-match 0 'XXX/\' '*/\'
-match 1 'XXX/\' '*/\\'
-match 1 'foo' 'foo'
-match 1 '@foo' '@foo'
-match 0 'foo' '@foo'
-match 1 '[ab]' '\[ab]'
-match 1 '[ab]' '[[]ab]'
-match 1 '[ab]' '[[:]ab]'
-match 0 '[ab]' '[[::]ab]'
-match 1 '[ab]' '[[:digit]ab]'
-match 1 '[ab]' '[\[:]ab]'
-match 1 '?a?b' '\??\?b'
-match 1 'abc' '\a\b\c'
-match 0 'foo' ''
-match 1 'foo/bar/baz/to' '**/t[o]'
+wildtest 0 0 0 0 'acrt' 'a[c-c]st'
+wildtest 1 1 1 1 'acrt' 'a[c-c]rt'
+wildtest 0 0 0 0 ']' '[!]-]'
+wildtest 1 1 1 1 'a' '[!]-]'
+wildtest 0 0 0 0 '' '\'
+wildtest 0 0 0 0 '\' '\'
+wildtest 0 0 0 0 'XXX/\' '*/\'
+wildtest 1 1 1 1 'XXX/\' '*/\\'
+wildtest 1 1 1 1 'foo' 'foo'
+wildtest 1 1 1 1 '@foo' '@foo'
+wildtest 0 0 0 0 'foo' '@foo'
+wildtest 1 1 1 1 '[ab]' '\[ab]'
+wildtest 1 1 1 1 '[ab]' '[[]ab]'
+wildtest 1 1 1 1 '[ab]' '[[:]ab]'
+wildtest 0 0 0 0 '[ab]' '[[::]ab]'
+wildtest 1 1 1 1 '[ab]' '[[:digit]ab]'
+wildtest 1 1 1 1 '[ab]' '[\[:]ab]'
+wildtest 1 1 1 1 '?a?b' '\??\?b'
+wildtest 1 1 1 1 'abc' '\a\b\c'
+wildtest 0 0 0 0 'foo' ''
+wildtest 1 1 1 1 'foo/bar/baz/to' '**/t[o]'
 
 # Character class tests
-match 1 'a1B' '[[:alpha:]][[:digit:]][[:upper:]]'
-match 0 'a' '[[:digit:][:upper:][:space:]]'
-match 1 'A' '[[:digit:][:upper:][:space:]]'
-match 1 '1' '[[:digit:][:upper:][:space:]]'
-match 0 '1' '[[:digit:][:upper:][:spaci:]]'
-match 1 ' ' '[[:digit:][:upper:][:space:]]'
-match 0 '.' '[[:digit:][:upper:][:space:]]'
-match 1 '.' '[[:digit:][:punct:][:space:]]'
-match 1 '5' '[[:xdigit:]]'
-match 1 'f' '[[:xdigit:]]'
-match 1 'D' '[[:xdigit:]]'
-match 1 '_' '[[:alnum:][:alpha:][:blank:][:cntrl:][:digit:][:graph:][:lower:][:print:][:punct:][:space:][:upper:][:xdigit:]]'
-match 1 '.' '[^[:alnum:][:alpha:][:blank:][:cntrl:][:digit:][:lower:][:space:][:upper:][:xdigit:]]'
-match 1 '5' '[a-c[:digit:]x-z]'
-match 1 'b' '[a-c[:digit:]x-z]'
-match 1 'y' '[a-c[:digit:]x-z]'
-match 0 'q' '[a-c[:digit:]x-z]'
-
-# Additional tests, including some malformed wildmats
-match 1 ']' '[\\-^]'
-match 0 '[' '[\\-^]'
-match 1 '-' '[\-_]'
-match 1 ']' '[\]]'
-match 0 '\]' '[\]]'
-match 0 '\' '[\]]'
-match 0 'ab' 'a[]b'
-match 0 'a[]b' 'a[]b'
-match 0 'ab[' 'ab['
-match 0 'ab' '[!'
-match 0 'ab' '[-'
-match 1 '-' '[-]'
-match 0 '-' '[a-'
-match 0 '-' '[!a-'
-match 1 '-' '[--A]'
-match 1 '5' '[--A]'
-match 1 ' ' '[ --]'
-match 1 '$' '[ --]'
-match 1 '-' '[ --]'
-match 0 '0' '[ --]'
-match 1 '-' '[---]'
-match 1 '-' '[------]'
-match 0 'j' '[a-e-n]'
-match 1 '-' '[a-e-n]'
-match 1 'a' '[!------]'
-match 0 '[' '[]-a]'
-match 1 '^' '[]-a]'
-match 0 '^' '[!]-a]'
-match 1 '[' '[!]-a]'
-match 1 '^' '[a^bc]'
-match 1 '-b]' '[a-]b]'
-match 0 '\' '[\]'
-match 1 '\' '[\\]'
-match 0 '\' '[!\\]'
-match 1 'G' '[A-\\]'
-match 0 'aaabbb' 'b*a'
-match 0 'aabcaa' '*ba*'
-match 1 ',' '[,]'
-match 1 ',' '[\\,]'
-match 1 '\' '[\\,]'
-match 1 '-' '[,-.]'
-match 0 '+' '[,-.]'
-match 0 '-.]' '[,-.]'
-match 1 '2' '[\1-\3]'
-match 1 '3' '[\1-\3]'
-match 0 '4' '[\1-\3]'
-match 1 '\' '[[-\]]'
-match 1 '[' '[[-\]]'
-match 1 ']' '[[-\]]'
-match 0 '-' '[[-\]]'
+wildtest 1 1 1 1 'a1B' '[[:alpha:]][[:digit:]][[:upper:]]'
+wildtest 0 1 0 1 'a' '[[:digit:][:upper:][:space:]]'
+wildtest 1 1 1 1 'A' '[[:digit:][:upper:][:space:]]'
+wildtest 1 1 1 1 '1' '[[:digit:][:upper:][:space:]]'
+wildtest 0 0 0 0 '1' '[[:digit:][:upper:][:spaci:]]'
+wildtest 1 1 1 1 ' ' '[[:digit:][:upper:][:space:]]'
+wildtest 0 0 0 0 '.' '[[:digit:][:upper:][:space:]]'
+wildtest 1 1 1 1 '.' '[[:digit:][:punct:][:space:]]'
+wildtest 1 1 1 1 '5' '[[:xdigit:]]'
+wildtest 1 1 1 1 'f' '[[:xdigit:]]'
+wildtest 1 1 1 1 'D' '[[:xdigit:]]'
+wildtest 1 1 1 1 '_' '[[:alnum:][:alpha:][:blank:][:cntrl:][:digit:][:graph:][:lower:][:print:][:punct:][:space:][:upper:][:xdigit:]]'
+wildtest 1 1 1 1 '.' '[^[:alnum:][:alpha:][:blank:][:cntrl:][:digit:][:lower:][:space:][:upper:][:xdigit:]]'
+wildtest 1 1 1 1 '5' '[a-c[:digit:]x-z]'
+wildtest 1 1 1 1 'b' '[a-c[:digit:]x-z]'
+wildtest 1 1 1 1 'y' '[a-c[:digit:]x-z]'
+wildtest 0 0 0 0 'q' '[a-c[:digit:]x-z]'
 
-# Test recursion and the abort code (use "wildtest -i" to see iteration counts)
-match 1 '-adobe-courier-bold-o-normal--12-120-75-75-m-70-iso8859-1' '-*-*-*-*-*-*-12-*-*-*-m-*-*-*'
-match 0 '-adobe-courier-bold-o-normal--12-120-75-75-X-70-iso8859-1' '-*-*-*-*-*-*-12-*-*-*-m-*-*-*'
-match 0 '-adobe-courier-bold-o-normal--12-120-75-75-/-70-iso8859-1' '-*-*-*-*-*-*-12-*-*-*-m-*-*-*'
-match 1 'XXX/adobe/courier/bold/o/normal//12/120/75/75/m/70/iso8859/1' 'XXX/*/*/*/*/*/*/12/*/*/*/m/*/*/*'
-match 0 'XXX/adobe/courier/bold/o/normal//12/120/75/75/X/70/iso8859/1' 'XXX/*/*/*/*/*/*/12/*/*/*/m/*/*/*'
-match 1 'abcd/abcdefg/abcdefghijk/abcdefghijklmnop.txt' '**/*a*b*g*n*t'
-match 0 'abcd/abcdefg/abcdefghijk/abcdefghijklmnop.txtz' '**/*a*b*g*n*t'
-match 0 foo '*/*/*'
-match 0 foo/bar '*/*/*'
-match 1 foo/bba/arr '*/*/*'
-match 0 foo/bb/aa/rr '*/*/*'
-match 1 foo/bb/aa/rr '**/**/**'
-match 1 abcXdefXghi '*X*i'
-match 0 ab/cXd/efXg/hi '*X*i'
-match 1 ab/cXd/efXg/hi '*/*X*/*/*i'
-match 1 ab/cXd/efXg/hi '**/*X*/**/*i'
+# Additional tests, including some malformed wildmatch patterns
+wildtest 1 1 1 1 ']' '[\\-^]'
+wildtest 0 0 0 0 '[' '[\\-^]'
+wildtest 1 1 1 1 '-' '[\-_]'
+wildtest 1 1 1 1 ']' '[\]]'
+wildtest 0 0 0 0 '\]' '[\]]'
+wildtest 0 0 0 0 '\' '[\]]'
+wildtest 0 0 0 0 'ab' 'a[]b'
+wildtest 0 0 0 0 'a[]b' 'a[]b'
+wildtest 0 0 0 0 'ab[' 'ab['
+wildtest 0 0 0 0 'ab' '[!'
+wildtest 0 0 0 0 'ab' '[-'
+wildtest 1 1 1 1 '-' '[-]'
+wildtest 0 0 0 0 '-' '[a-'
+wildtest 0 0 0 0 '-' '[!a-'
+wildtest 1 1 1 1 '-' '[--A]'
+wildtest 1 1 1 1 '5' '[--A]'
+wildtest 1 1 1 1 ' ' '[ --]'
+wildtest 1 1 1 1 '$' '[ --]'
+wildtest 1 1 1 1 '-' '[ --]'
+wildtest 0 0 0 0 '0' '[ --]'
+wildtest 1 1 1 1 '-' '[---]'
+wildtest 1 1 1 1 '-' '[------]'
+wildtest 0 0 0 0 'j' '[a-e-n]'
+wildtest 1 1 1 1 '-' '[a-e-n]'
+wildtest 1 1 1 1 'a' '[!------]'
+wildtest 0 0 0 0 '[' '[]-a]'
+wildtest 1 1 1 1 '^' '[]-a]'
+wildtest 0 0 0 0 '^' '[!]-a]'
+wildtest 1 1 1 1 '[' '[!]-a]'
+wildtest 1 1 1 1 '^' '[a^bc]'
+wildtest 1 1 1 1 '-b]' '[a-]b]'
+wildtest 0 0 0 0 '\' '[\]'
+wildtest 1 1 1 1 '\' '[\\]'
+wildtest 0 0 0 0 '\' '[!\\]'
+wildtest 1 1 1 1 'G' '[A-\\]'
+wildtest 0 0 0 0 'aaabbb' 'b*a'
+wildtest 0 0 0 0 'aabcaa' '*ba*'
+wildtest 1 1 1 1 ',' '[,]'
+wildtest 1 1 1 1 ',' '[\\,]'
+wildtest 1 1 1 1 '\' '[\\,]'
+wildtest 1 1 1 1 '-' '[,-.]'
+wildtest 0 0 0 0 '+' '[,-.]'
+wildtest 0 0 0 0 '-.]' '[,-.]'
+wildtest 1 1 1 1 '2' '[\1-\3]'
+wildtest 1 1 1 1 '3' '[\1-\3]'
+wildtest 0 0 0 0 '4' '[\1-\3]'
+wildtest 1 1 1 1 '\' '[[-\]]'
+wildtest 1 1 1 1 '[' '[[-\]]'
+wildtest 1 1 1 1 ']' '[[-\]]'
+wildtest 0 0 0 0 '-' '[[-\]]'
 
-pathmatch 1 foo foo
-pathmatch 0 foo fo
-pathmatch 1 foo/bar foo/bar
-pathmatch 1 foo/bar 'foo/*'
-pathmatch 1 foo/bba/arr 'foo/*'
-pathmatch 1 foo/bba/arr 'foo/**'
-pathmatch 1 foo/bba/arr 'foo*'
-pathmatch 1 foo/bba/arr 'foo**'
-pathmatch 1 foo/bba/arr 'foo/*arr'
-pathmatch 1 foo/bba/arr 'foo/**arr'
-pathmatch 0 foo/bba/arr 'foo/*z'
-pathmatch 0 foo/bba/arr 'foo/**z'
-pathmatch 1 foo/bar 'foo?bar'
-pathmatch 1 foo/bar 'foo[/]bar'
-pathmatch 1 foo/bar 'foo[^a-z]bar'
-pathmatch 0 foo '*/*/*'
-pathmatch 0 foo/bar '*/*/*'
-pathmatch 1 foo/bba/arr '*/*/*'
-pathmatch 1 foo/bb/aa/rr '*/*/*'
-pathmatch 1 abcXdefXghi '*X*i'
-pathmatch 1 ab/cXd/efXg/hi '*/*X*/*/*i'
-pathmatch 1 ab/cXd/efXg/hi '*Xg*i'
+# Test recursion
+wildtest 1 1 1 1 '-adobe-courier-bold-o-normal--12-120-75-75-m-70-iso8859-1' '-*-*-*-*-*-*-12-*-*-*-m-*-*-*'
+wildtest 0 0 0 0 '-adobe-courier-bold-o-normal--12-120-75-75-X-70-iso8859-1' '-*-*-*-*-*-*-12-*-*-*-m-*-*-*'
+wildtest 0 0 0 0 '-adobe-courier-bold-o-normal--12-120-75-75-/-70-iso8859-1' '-*-*-*-*-*-*-12-*-*-*-m-*-*-*'
+wildtest 1 1 1 1 'XXX/adobe/courier/bold/o/normal//12/120/75/75/m/70/iso8859/1' 'XXX/*/*/*/*/*/*/12/*/*/*/m/*/*/*'
+wildtest 0 0 0 0 'XXX/adobe/courier/bold/o/normal//12/120/75/75/X/70/iso8859/1' 'XXX/*/*/*/*/*/*/12/*/*/*/m/*/*/*'
+wildtest 1 1 1 1 'abcd/abcdefg/abcdefghijk/abcdefghijklmnop.txt' '**/*a*b*g*n*t'
+wildtest 0 0 0 0 'abcd/abcdefg/abcdefghijk/abcdefghijklmnop.txtz' '**/*a*b*g*n*t'
+wildtest 0 0 0 0 foo '*/*/*'
+wildtest 0 0 0 0 foo/bar '*/*/*'
+wildtest 1 1 1 1 foo/bba/arr '*/*/*'
+wildtest 0 0 1 1 foo/bb/aa/rr '*/*/*'
+wildtest 1 1 1 1 foo/bb/aa/rr '**/**/**'
+wildtest 1 1 1 1 abcXdefXghi '*X*i'
+wildtest 0 0 1 1 ab/cXd/efXg/hi '*X*i'
+wildtest 1 1 1 1 ab/cXd/efXg/hi '*/*X*/*/*i'
+wildtest 1 1 1 1 ab/cXd/efXg/hi '**/*X*/**/*i'
 
-# Case-sensitivity features
-match 0 'a' '[A-Z]'
-match 1 'A' '[A-Z]'
-match 0 'A' '[a-z]'
-match 1 'a' '[a-z]'
-match 0 'a' '[[:upper:]]'
-match 1 'A' '[[:upper:]]'
-match 0 'A' '[[:lower:]]'
-match 1 'a' '[[:lower:]]'
-match 0 'A' '[B-Za]'
-match 1 'a' '[B-Za]'
-match 0 'A' '[B-a]'
-match 1 'a' '[B-a]'
-match 0 'z' '[Z-y]'
-match 1 'Z' '[Z-y]'
+# Extra pathmatch tests
+wildtest 0 0 0 0 foo fo
+wildtest 1 1 1 1 foo/bar foo/bar
+wildtest 1 1 1 1 foo/bar 'foo/*'
+wildtest 0 0 1 1 foo/bba/arr 'foo/*'
+wildtest 1 1 1 1 foo/bba/arr 'foo/**'
+wildtest 0 0 1 1 foo/bba/arr 'foo*'
+wildtest 0 0 1 1 foo/bba/arr 'foo**'
+wildtest 0 0 1 1 foo/bba/arr 'foo/*arr'
+wildtest 0 0 1 1 foo/bba/arr 'foo/**arr'
+wildtest 0 0 0 0 foo/bba/arr 'foo/*z'
+wildtest 0 0 0 0 foo/bba/arr 'foo/**z'
+wildtest 0 0 1 1 foo/bar 'foo?bar'
+wildtest 0 0 1 1 foo/bar 'foo[/]bar'
+wildtest 0 0 1 1 foo/bar 'foo[^a-z]bar'
+wildtest 0 0 1 1 ab/cXd/efXg/hi '*Xg*i'
 
-imatch 1 'a' '[A-Z]'
-imatch 1 'A' '[A-Z]'
-imatch 1 'A' '[a-z]'
-imatch 1 'a' '[a-z]'
-imatch 1 'a' '[[:upper:]]'
-imatch 1 'A' '[[:upper:]]'
-imatch 1 'A' '[[:lower:]]'
-imatch 1 'a' '[[:lower:]]'
-imatch 1 'A' '[B-Za]'
-imatch 1 'a' '[B-Za]'
-imatch 1 'A' '[B-a]'
-imatch 1 'a' '[B-a]'
-imatch 1 'z' '[Z-y]'
-imatch 1 'Z' '[Z-y]'
+# Extra case-sensitivity tests
+wildtest 0 1 0 1 'a' '[A-Z]'
+wildtest 1 1 1 1 'A' '[A-Z]'
+wildtest 0 1 0 1 'A' '[a-z]'
+wildtest 1 1 1 1 'a' '[a-z]'
+wildtest 0 1 0 1 'a' '[[:upper:]]'
+wildtest 1 1 1 1 'A' '[[:upper:]]'
+wildtest 0 1 0 1 'A' '[[:lower:]]'
+wildtest 1 1 1 1 'a' '[[:lower:]]'
+wildtest 0 1 0 1 'A' '[B-Za]'
+wildtest 1 1 1 1 'a' '[B-Za]'
+wildtest 0 1 0 1 'A' '[B-a]'
+wildtest 1 1 1 1 'a' '[B-a]'
+wildtest 0 1 0 1 'z' '[Z-y]'
+wildtest 1 1 1 1 'Z' '[Z-y]'
 
 test_done
-- 
2.15.1.424.g9478a66081
Ævar Arnfjörð Bjarmason· Dec 28, 2017, 23:28 UTC · re: Ævar Arnfjörð Bjarmason · lore

[PATCH v3 4/7] wildmatch test: use a paranoia pattern from nul_match()

Use a pattern from the nul_match() function in t7008-grep-binary.sh to make sure that we don't just fall through to the "else" if there's an unknown parameter.

This is something I added in commit 77f6f4406f ("grep: add a test helper function for less verbose -f \0 tests", 2017-05-20) to grep tests, which were modeled on these wildmatch tests, and I'm now porting back to the original wildmatch tests.

I am not using the "say '...'; exit 1" pattern from t0000-basic.sh because if I fail I want to run the rest of the tests (unless under -i), and doing this makes sure we do that and don't exit right away without fully reporting our errors.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 t/t3070-wildmatch.sh | 15 ++++++++++++---
 1 file changed, 12 insertions(+), 3 deletions(-)
Show changes to t/t3070-wildmatch.sh +12 −3
diff --git a/t/t3070-wildmatch.sh b/t/t3070-wildmatch.sh
index 19ea64bba9..9691d8eda3 100755
--- a/t/t3070-wildmatch.sh
+++ b/t/t3070-wildmatch.sh
@@ -10,10 +10,13 @@ match() {
 		test_expect_success "wildmatch: match '$3' '$4'" "
 			test-wildmatch wildmatch '$3' '$4'
 		"
-	else
+	elif test "$1" = 0
+	then
 		test_expect_success "wildmatch: no match '$3' '$4'" "
 			! test-wildmatch wildmatch '$3' '$4'
 		"
+	else
+		test_expect_success "PANIC: Test framework error. Unknown matches value $1" 'false'
 	fi
 }
 
@@ -23,10 +26,13 @@ imatch() {
 		test_expect_success "iwildmatch: match '$2' '$3'" "
 			test-wildmatch iwildmatch '$2' '$3'
 		"
-	else
+	elif test "$1" = 0
+	then
 		test_expect_success "iwildmatch: no match '$2' '$3'" "
 			! test-wildmatch iwildmatch '$2' '$3'
 		"
+	else
+		test_expect_success "PANIC: Test framework error. Unknown matches value $1" 'false'
 	fi
 }
 
@@ -36,10 +42,13 @@ pathmatch() {
 		test_expect_success "pathmatch: match '$2' '$3'" "
 			test-wildmatch pathmatch '$2' '$3'
 		"
-	else
+	elif test "$1" = 0
+	then
 		test_expect_success "pathmatch: no match '$2' '$3'" "
 			! test-wildmatch pathmatch '$2' '$3'
 		"
+	else
+		test_expect_success "PANIC: Test framework error. Unknown matches value $1" 'false'
 	fi
 }
 
-- 
2.15.1.424.g9478a66081
Ævar Arnfjörð Bjarmason· Dec 28, 2017, 23:28 UTC · re: Ævar Arnfjörð Bjarmason · lore

[PATCH v3 5/7] wildmatch test: remove dead fnmatch() test code

Remove the unused fnmatch() test parameter from the wildmatch test. The code that used to test this was removed in 70a8fc999d ("stop using fnmatch (either native or compat)", 2014-02-15).

As a --word-diff shows the only change to the body of the tests is the removal of the second out of four parameters passed to match().

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 t/t3070-wildmatch.sh | 356 +++++++++++++++++++++++++--------------------------
 1 file changed, 178 insertions(+), 178 deletions(-)
Show changes to t/t3070-wildmatch.sh +178 −178
diff --git a/t/t3070-wildmatch.sh b/t/t3070-wildmatch.sh
index 9691d8eda3..2f8a681c72 100755
--- a/t/t3070-wildmatch.sh
+++ b/t/t3070-wildmatch.sh
@@ -7,13 +7,13 @@ test_description='wildmatch tests'
 match() {
 	if test "$1" = 1
 	then
-		test_expect_success "wildmatch: match '$3' '$4'" "
-			test-wildmatch wildmatch '$3' '$4'
+		test_expect_success "wildmatch: match '$2' '$3'" "
+			test-wildmatch wildmatch '$2' '$3'
 		"
 	elif test "$1" = 0
 	then
-		test_expect_success "wildmatch: no match '$3' '$4'" "
-			! test-wildmatch wildmatch '$3' '$4'
+		test_expect_success "wildmatch: no match '$2' '$3'" "
+			! test-wildmatch wildmatch '$2' '$3'
 		"
 	else
 		test_expect_success "PANIC: Test framework error. Unknown matches value $1" 'false'
@@ -53,176 +53,176 @@ pathmatch() {
 }
 
 # Basic wildmat features
-match 1 1 foo foo
-match 0 0 foo bar
-match 1 1 '' ""
-match 1 1 foo '???'
-match 0 0 foo '??'
-match 1 1 foo '*'
-match 1 1 foo 'f*'
-match 0 0 foo '*f'
-match 1 1 foo '*foo*'
-match 1 1 foobar '*ob*a*r*'
-match 1 1 aaaaaaabababab '*ab'
-match 1 1 'foo*' 'foo\*'
-match 0 0 foobar 'foo\*bar'
-match 1 1 'f\oo' 'f\\oo'
-match 1 1 ball '*[al]?'
-match 0 0 ten '[ten]'
-match 0 1 ten '**[!te]'
-match 0 0 ten '**[!ten]'
-match 1 1 ten 't[a-g]n'
-match 0 0 ten 't[!a-g]n'
-match 1 1 ton 't[!a-g]n'
-match 1 1 ton 't[^a-g]n'
-match 1 x 'a]b' 'a[]]b'
-match 1 x a-b 'a[]-]b'
-match 1 x 'a]b' 'a[]-]b'
-match 0 x aab 'a[]-]b'
-match 1 x aab 'a[]a-]b'
-match 1 1 ']' ']'
+match 1 foo foo
+match 0 foo bar
+match 1 '' ""
+match 1 foo '???'
+match 0 foo '??'
+match 1 foo '*'
+match 1 foo 'f*'
+match 0 foo '*f'
+match 1 foo '*foo*'
+match 1 foobar '*ob*a*r*'
+match 1 aaaaaaabababab '*ab'
+match 1 'foo*' 'foo\*'
+match 0 foobar 'foo\*bar'
+match 1 'f\oo' 'f\\oo'
+match 1 ball '*[al]?'
+match 0 ten '[ten]'
+match 0 ten '**[!te]'
+match 0 ten '**[!ten]'
+match 1 ten 't[a-g]n'
+match 0 ten 't[!a-g]n'
+match 1 ton 't[!a-g]n'
+match 1 ton 't[^a-g]n'
+match 1 'a]b' 'a[]]b'
+match 1 a-b 'a[]-]b'
+match 1 'a]b' 'a[]-]b'
+match 0 aab 'a[]-]b'
+match 1 aab 'a[]a-]b'
+match 1 ']' ']'
 
 # Extended slash-matching features
-match 0 0 'foo/baz/bar' 'foo*bar'
-match 0 0 'foo/baz/bar' 'foo**bar'
-match 0 1 'foobazbar' 'foo**bar'
-match 1 1 'foo/baz/bar' 'foo/**/bar'
-match 1 0 'foo/baz/bar' 'foo/**/**/bar'
-match 1 0 'foo/b/a/z/bar' 'foo/**/bar'
-match 1 0 'foo/b/a/z/bar' 'foo/**/**/bar'
-match 1 0 'foo/bar' 'foo/**/bar'
-match 1 0 'foo/bar' 'foo/**/**/bar'
-match 0 0 'foo/bar' 'foo?bar'
-match 0 0 'foo/bar' 'foo[/]bar'
-match 0 0 'foo/bar' 'foo[^a-z]bar'
-match 0 0 'foo/bar' 'f[^eiu][^eiu][^eiu][^eiu][^eiu]r'
-match 1 1 'foo-bar' 'f[^eiu][^eiu][^eiu][^eiu][^eiu]r'
-match 1 0 'foo' '**/foo'
-match 1 x 'XXX/foo' '**/foo'
-match 1 0 'bar/baz/foo' '**/foo'
-match 0 0 'bar/baz/foo' '*/foo'
-match 0 0 'foo/bar/baz' '**/bar*'
-match 1 0 'deep/foo/bar/baz' '**/bar/*'
-match 0 0 'deep/foo/bar/baz/' '**/bar/*'
-match 1 0 'deep/foo/bar/baz/' '**/bar/**'
-match 0 0 'deep/foo/bar' '**/bar/*'
-match 1 0 'deep/foo/bar/' '**/bar/**'
-match 0 0 'foo/bar/baz' '**/bar**'
-match 1 0 'foo/bar/baz/x' '*/bar/**'
-match 0 0 'deep/foo/bar/baz/x' '*/bar/**'
-match 1 0 'deep/foo/bar/baz/x' '**/bar/*/*'
+match 0 'foo/baz/bar' 'foo*bar'
+match 0 'foo/baz/bar' 'foo**bar'
+match 0 'foobazbar' 'foo**bar'
+match 1 'foo/baz/bar' 'foo/**/bar'
+match 1 'foo/baz/bar' 'foo/**/**/bar'
+match 1 'foo/b/a/z/bar' 'foo/**/bar'
+match 1 'foo/b/a/z/bar' 'foo/**/**/bar'
+match 1 'foo/bar' 'foo/**/bar'
+match 1 'foo/bar' 'foo/**/**/bar'
+match 0 'foo/bar' 'foo?bar'
+match 0 'foo/bar' 'foo[/]bar'
+match 0 'foo/bar' 'foo[^a-z]bar'
+match 0 'foo/bar' 'f[^eiu][^eiu][^eiu][^eiu][^eiu]r'
+match 1 'foo-bar' 'f[^eiu][^eiu][^eiu][^eiu][^eiu]r'
+match 1 'foo' '**/foo'
+match 1 'XXX/foo' '**/foo'
+match 1 'bar/baz/foo' '**/foo'
+match 0 'bar/baz/foo' '*/foo'
+match 0 'foo/bar/baz' '**/bar*'
+match 1 'deep/foo/bar/baz' '**/bar/*'
+match 0 'deep/foo/bar/baz/' '**/bar/*'
+match 1 'deep/foo/bar/baz/' '**/bar/**'
+match 0 'deep/foo/bar' '**/bar/*'
+match 1 'deep/foo/bar/' '**/bar/**'
+match 0 'foo/bar/baz' '**/bar**'
+match 1 'foo/bar/baz/x' '*/bar/**'
+match 0 'deep/foo/bar/baz/x' '*/bar/**'
+match 1 'deep/foo/bar/baz/x' '**/bar/*/*'
 
 # Various additional tests
-match 0 0 'acrt' 'a[c-c]st'
-match 1 1 'acrt' 'a[c-c]rt'
-match 0 0 ']' '[!]-]'
-match 1 x 'a' '[!]-]'
-match 0 0 '' '\'
-match 0 x '\' '\'
-match 0 x 'XXX/\' '*/\'
-match 1 x 'XXX/\' '*/\\'
-match 1 1 'foo' 'foo'
-match 1 1 '@foo' '@foo'
-match 0 0 'foo' '@foo'
-match 1 1 '[ab]' '\[ab]'
-match 1 1 '[ab]' '[[]ab]'
-match 1 x '[ab]' '[[:]ab]'
-match 0 x '[ab]' '[[::]ab]'
-match 1 x '[ab]' '[[:digit]ab]'
-match 1 x '[ab]' '[\[:]ab]'
-match 1 1 '?a?b' '\??\?b'
-match 1 1 'abc' '\a\b\c'
-match 0 0 'foo' ''
-match 1 0 'foo/bar/baz/to' '**/t[o]'
+match 0 'acrt' 'a[c-c]st'
+match 1 'acrt' 'a[c-c]rt'
+match 0 ']' '[!]-]'
+match 1 'a' '[!]-]'
+match 0 '' '\'
+match 0 '\' '\'
+match 0 'XXX/\' '*/\'
+match 1 'XXX/\' '*/\\'
+match 1 'foo' 'foo'
+match 1 '@foo' '@foo'
+match 0 'foo' '@foo'
+match 1 '[ab]' '\[ab]'
+match 1 '[ab]' '[[]ab]'
+match 1 '[ab]' '[[:]ab]'
+match 0 '[ab]' '[[::]ab]'
+match 1 '[ab]' '[[:digit]ab]'
+match 1 '[ab]' '[\[:]ab]'
+match 1 '?a?b' '\??\?b'
+match 1 'abc' '\a\b\c'
+match 0 'foo' ''
+match 1 'foo/bar/baz/to' '**/t[o]'
 
 # Character class tests
-match 1 x 'a1B' '[[:alpha:]][[:digit:]][[:upper:]]'
-match 0 x 'a' '[[:digit:][:upper:][:space:]]'
-match 1 x 'A' '[[:digit:][:upper:][:space:]]'
-match 1 x '1' '[[:digit:][:upper:][:space:]]'
-match 0 x '1' '[[:digit:][:upper:][:spaci:]]'
-match 1 x ' ' '[[:digit:][:upper:][:space:]]'
-match 0 x '.' '[[:digit:][:upper:][:space:]]'
-match 1 x '.' '[[:digit:][:punct:][:space:]]'
-match 1 x '5' '[[:xdigit:]]'
-match 1 x 'f' '[[:xdigit:]]'
-match 1 x 'D' '[[:xdigit:]]'
-match 1 x '_' '[[:alnum:][:alpha:][:blank:][:cntrl:][:digit:][:graph:][:lower:][:print:][:punct:][:space:][:upper:][:xdigit:]]'
-match 1 x '.' '[^[:alnum:][:alpha:][:blank:][:cntrl:][:digit:][:lower:][:space:][:upper:][:xdigit:]]'
-match 1 x '5' '[a-c[:digit:]x-z]'
-match 1 x 'b' '[a-c[:digit:]x-z]'
-match 1 x 'y' '[a-c[:digit:]x-z]'
-match 0 x 'q' '[a-c[:digit:]x-z]'
+match 1 'a1B' '[[:alpha:]][[:digit:]][[:upper:]]'
+match 0 'a' '[[:digit:][:upper:][:space:]]'
+match 1 'A' '[[:digit:][:upper:][:space:]]'
+match 1 '1' '[[:digit:][:upper:][:space:]]'
+match 0 '1' '[[:digit:][:upper:][:spaci:]]'
+match 1 ' ' '[[:digit:][:upper:][:space:]]'
+match 0 '.' '[[:digit:][:upper:][:space:]]'
+match 1 '.' '[[:digit:][:punct:][:space:]]'
+match 1 '5' '[[:xdigit:]]'
+match 1 'f' '[[:xdigit:]]'
+match 1 'D' '[[:xdigit:]]'
+match 1 '_' '[[:alnum:][:alpha:][:blank:][:cntrl:][:digit:][:graph:][:lower:][:print:][:punct:][:space:][:upper:][:xdigit:]]'
+match 1 '.' '[^[:alnum:][:alpha:][:blank:][:cntrl:][:digit:][:lower:][:space:][:upper:][:xdigit:]]'
+match 1 '5' '[a-c[:digit:]x-z]'
+match 1 'b' '[a-c[:digit:]x-z]'
+match 1 'y' '[a-c[:digit:]x-z]'
+match 0 'q' '[a-c[:digit:]x-z]'
 
 # Additional tests, including some malformed wildmats
-match 1 x ']' '[\\-^]'
-match 0 0 '[' '[\\-^]'
-match 1 x '-' '[\-_]'
-match 1 x ']' '[\]]'
-match 0 0 '\]' '[\]]'
-match 0 0 '\' '[\]]'
-match 0 0 'ab' 'a[]b'
-match 0 x 'a[]b' 'a[]b'
-match 0 x 'ab[' 'ab['
-match 0 0 'ab' '[!'
-match 0 0 'ab' '[-'
-match 1 1 '-' '[-]'
-match 0 0 '-' '[a-'
-match 0 0 '-' '[!a-'
-match 1 x '-' '[--A]'
-match 1 x '5' '[--A]'
-match 1 1 ' ' '[ --]'
-match 1 1 '$' '[ --]'
-match 1 1 '-' '[ --]'
-match 0 0 '0' '[ --]'
-match 1 x '-' '[---]'
-match 1 x '-' '[------]'
-match 0 0 'j' '[a-e-n]'
-match 1 x '-' '[a-e-n]'
-match 1 x 'a' '[!------]'
-match 0 0 '[' '[]-a]'
-match 1 x '^' '[]-a]'
-match 0 0 '^' '[!]-a]'
-match 1 x '[' '[!]-a]'
-match 1 1 '^' '[a^bc]'
-match 1 x '-b]' '[a-]b]'
-match 0 0 '\' '[\]'
-match 1 1 '\' '[\\]'
-match 0 0 '\' '[!\\]'
-match 1 1 'G' '[A-\\]'
-match 0 0 'aaabbb' 'b*a'
-match 0 0 'aabcaa' '*ba*'
-match 1 1 ',' '[,]'
-match 1 1 ',' '[\\,]'
-match 1 1 '\' '[\\,]'
-match 1 1 '-' '[,-.]'
-match 0 0 '+' '[,-.]'
-match 0 0 '-.]' '[,-.]'
-match 1 1 '2' '[\1-\3]'
-match 1 1 '3' '[\1-\3]'
-match 0 0 '4' '[\1-\3]'
-match 1 1 '\' '[[-\]]'
-match 1 1 '[' '[[-\]]'
-match 1 1 ']' '[[-\]]'
-match 0 0 '-' '[[-\]]'
+match 1 ']' '[\\-^]'
+match 0 '[' '[\\-^]'
+match 1 '-' '[\-_]'
+match 1 ']' '[\]]'
+match 0 '\]' '[\]]'
+match 0 '\' '[\]]'
+match 0 'ab' 'a[]b'
+match 0 'a[]b' 'a[]b'
+match 0 'ab[' 'ab['
+match 0 'ab' '[!'
+match 0 'ab' '[-'
+match 1 '-' '[-]'
+match 0 '-' '[a-'
+match 0 '-' '[!a-'
+match 1 '-' '[--A]'
+match 1 '5' '[--A]'
+match 1 ' ' '[ --]'
+match 1 '$' '[ --]'
+match 1 '-' '[ --]'
+match 0 '0' '[ --]'
+match 1 '-' '[---]'
+match 1 '-' '[------]'
+match 0 'j' '[a-e-n]'
+match 1 '-' '[a-e-n]'
+match 1 'a' '[!------]'
+match 0 '[' '[]-a]'
+match 1 '^' '[]-a]'
+match 0 '^' '[!]-a]'
+match 1 '[' '[!]-a]'
+match 1 '^' '[a^bc]'
+match 1 '-b]' '[a-]b]'
+match 0 '\' '[\]'
+match 1 '\' '[\\]'
+match 0 '\' '[!\\]'
+match 1 'G' '[A-\\]'
+match 0 'aaabbb' 'b*a'
+match 0 'aabcaa' '*ba*'
+match 1 ',' '[,]'
+match 1 ',' '[\\,]'
+match 1 '\' '[\\,]'
+match 1 '-' '[,-.]'
+match 0 '+' '[,-.]'
+match 0 '-.]' '[,-.]'
+match 1 '2' '[\1-\3]'
+match 1 '3' '[\1-\3]'
+match 0 '4' '[\1-\3]'
+match 1 '\' '[[-\]]'
+match 1 '[' '[[-\]]'
+match 1 ']' '[[-\]]'
+match 0 '-' '[[-\]]'
 
 # Test recursion and the abort code (use "wildtest -i" to see iteration counts)
-match 1 1 '-adobe-courier-bold-o-normal--12-120-75-75-m-70-iso8859-1' '-*-*-*-*-*-*-12-*-*-*-m-*-*-*'
-match 0 0 '-adobe-courier-bold-o-normal--12-120-75-75-X-70-iso8859-1' '-*-*-*-*-*-*-12-*-*-*-m-*-*-*'
-match 0 0 '-adobe-courier-bold-o-normal--12-120-75-75-/-70-iso8859-1' '-*-*-*-*-*-*-12-*-*-*-m-*-*-*'
-match 1 1 'XXX/adobe/courier/bold/o/normal//12/120/75/75/m/70/iso8859/1' 'XXX/*/*/*/*/*/*/12/*/*/*/m/*/*/*'
-match 0 0 'XXX/adobe/courier/bold/o/normal//12/120/75/75/X/70/iso8859/1' 'XXX/*/*/*/*/*/*/12/*/*/*/m/*/*/*'
-match 1 0 'abcd/abcdefg/abcdefghijk/abcdefghijklmnop.txt' '**/*a*b*g*n*t'
-match 0 0 'abcd/abcdefg/abcdefghijk/abcdefghijklmnop.txtz' '**/*a*b*g*n*t'
-match 0 x foo '*/*/*'
-match 0 x foo/bar '*/*/*'
-match 1 x foo/bba/arr '*/*/*'
-match 0 x foo/bb/aa/rr '*/*/*'
-match 1 x foo/bb/aa/rr '**/**/**'
-match 1 x abcXdefXghi '*X*i'
-match 0 x ab/cXd/efXg/hi '*X*i'
-match 1 x ab/cXd/efXg/hi '*/*X*/*/*i'
-match 1 x ab/cXd/efXg/hi '**/*X*/**/*i'
+match 1 '-adobe-courier-bold-o-normal--12-120-75-75-m-70-iso8859-1' '-*-*-*-*-*-*-12-*-*-*-m-*-*-*'
+match 0 '-adobe-courier-bold-o-normal--12-120-75-75-X-70-iso8859-1' '-*-*-*-*-*-*-12-*-*-*-m-*-*-*'
+match 0 '-adobe-courier-bold-o-normal--12-120-75-75-/-70-iso8859-1' '-*-*-*-*-*-*-12-*-*-*-m-*-*-*'
+match 1 'XXX/adobe/courier/bold/o/normal//12/120/75/75/m/70/iso8859/1' 'XXX/*/*/*/*/*/*/12/*/*/*/m/*/*/*'
+match 0 'XXX/adobe/courier/bold/o/normal//12/120/75/75/X/70/iso8859/1' 'XXX/*/*/*/*/*/*/12/*/*/*/m/*/*/*'
+match 1 'abcd/abcdefg/abcdefghijk/abcdefghijklmnop.txt' '**/*a*b*g*n*t'
+match 0 'abcd/abcdefg/abcdefghijk/abcdefghijklmnop.txtz' '**/*a*b*g*n*t'
+match 0 foo '*/*/*'
+match 0 foo/bar '*/*/*'
+match 1 foo/bba/arr '*/*/*'
+match 0 foo/bb/aa/rr '*/*/*'
+match 1 foo/bb/aa/rr '**/**/**'
+match 1 abcXdefXghi '*X*i'
+match 0 ab/cXd/efXg/hi '*X*i'
+match 1 ab/cXd/efXg/hi '*/*X*/*/*i'
+match 1 ab/cXd/efXg/hi '**/*X*/**/*i'
 
 pathmatch 1 foo foo
 pathmatch 0 foo fo
@@ -248,20 +248,20 @@ pathmatch 1 ab/cXd/efXg/hi '*/*X*/*/*i'
 pathmatch 1 ab/cXd/efXg/hi '*Xg*i'
 
 # Case-sensitivity features
-match 0 x 'a' '[A-Z]'
-match 1 x 'A' '[A-Z]'
-match 0 x 'A' '[a-z]'
-match 1 x 'a' '[a-z]'
-match 0 x 'a' '[[:upper:]]'
-match 1 x 'A' '[[:upper:]]'
-match 0 x 'A' '[[:lower:]]'
-match 1 x 'a' '[[:lower:]]'
-match 0 x 'A' '[B-Za]'
-match 1 x 'a' '[B-Za]'
-match 0 x 'A' '[B-a]'
-match 1 x 'a' '[B-a]'
-match 0 x 'z' '[Z-y]'
-match 1 x 'Z' '[Z-y]'
+match 0 'a' '[A-Z]'
+match 1 'A' '[A-Z]'
+match 0 'A' '[a-z]'
+match 1 'a' '[a-z]'
+match 0 'a' '[[:upper:]]'
+match 1 'A' '[[:upper:]]'
+match 0 'A' '[[:lower:]]'
+match 1 'a' '[[:lower:]]'
+match 0 'A' '[B-Za]'
+match 1 'a' '[B-Za]'
+match 0 'A' '[B-a]'
+match 1 'a' '[B-a]'
+match 0 'z' '[Z-y]'
+match 1 'Z' '[Z-y]'
 
 imatch 1 'a' '[A-Z]'
 imatch 1 'A' '[A-Z]'
-- 
2.15.1.424.g9478a66081
Ævar Arnfjörð Bjarmason· Dec 28, 2017, 23:28 UTC · re: Ævar Arnfjörð Bjarmason · lore

[PATCH v3 7/7] wildmatch test: create & test files on disk in addition to in-memory

There has never been any full roundtrip testing of what git-ls-files and other functions that use wildmatch() actually do, rather we've been satisfied with just testing the underlying C function.

Due to git-ls-files and friends having their own codepaths before they call wildmatch() there's sometimes differences in the behavior between the two, and even when we test for those (as with 9e4e8a64c2 ("pathspec: die on empty strings as pathspec", 2017-06-06)) there was no one place where you can review how these two modes differ.

Now there is. We now attempt to create a file called $haystack and match $needle against it for each pair of $needle and $haystack that we were passing to test-wildmatch.

If we can't create the file we skip the test. This ensures that we can run this on all platforms and not maintain some infinitely growing whitelist of e.g. platforms that don't support certain characters in filenames.

As a result of doing this we can now see the cases where these two ways of testing wildmatch differ:

 * Creating a file called 'a[]b' and running ls-files 'a[]b' will show
   that file, but wildmatch("a[]b", "a[]b") will not match
 * wildmatch() won't match a file called \ against \, but ls-files
   will.
 * `git --glob-pathspecs ls-files 'foo**'` will match a file
   'foo/bba/arr', but wildmatch won't, however pathmatch will.
   This seems like a bug to me, the two are otherwise equivalent as
   these tests show.

This also reveals the case discussed in 9e4e8a64c2 above, where '' is now an error as far as ls-files is concerned, but wildmatch() itself happily accepts it.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 t/t3070-wildmatch.sh | 283 +++++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 272 insertions(+), 11 deletions(-)
Show changes to t/t3070-wildmatch.sh +272 −11
diff --git a/t/t3070-wildmatch.sh b/t/t3070-wildmatch.sh
index 06db053ae2..d7aa7eb5fe 100755
--- a/t/t3070-wildmatch.sh
+++ b/t/t3070-wildmatch.sh
@@ -4,14 +4,95 @@ test_description='wildmatch tests'
 
 . ./test-lib.sh
 
+create_test_file() {
+	file=$1
+
+	case $file in
+	# `touch .` will succeed but obviously not do what we intend
+	# here.
+	".")
+		return 1
+		;;
+	# We cannot create a file with an empty filename.
+	"")
+		return 1
+		;;
+	# The tests that are testing that e.g. foo//bar is matched by
+	# foo/*/bar can't be tested on filesystems since there's no
+	# way we're getting a double slash.
+	*//*)
+		return 1
+		;;
+	# When testing the difference between foo/bar and foo/bar/ we
+	# can't test the latter.
+	*/)
+		return 1
+		;;
+	esac
+
+	# Turn foo/bar/baz into foo/bar to create foo/bar as a
+	# directory structure.
+	dirs=${file%/*}
+
+	# We touch "./$file" instead of "$file" because even an
+	# escaped "touch -- -" means get arguments from stdin.
+	if test "$file" != "$dirs"
+	then
+		mkdir -p -- "$dirs" &&
+		touch -- "./$file" &&
+		return 0
+	else
+		touch -- "./$file" &&
+		return 0
+	fi
+	return 1
+}
+
+wildtest_file_setup() {
+	test_when_finished "
+		rm -rf -- * &&
+		git reset
+	" &&
+	git add -A &&
+	>expect.err
+}
+
+wildtest_stdout_stderr_cmp() {
+	tr -d '\0' <actual.raw >actual &&
+	test_cmp expect.err actual.err &&
+	test_cmp expect actual
+}
+
 wildtest() {
-	match_w_glob=$1
-	match_w_globi=$2
-	match_w_pathmatch=$3
-	match_w_pathmatchi=$4
-	text=$5
-	pattern=$6
+	if test "$#" = 6
+	then
+		# When test-wildmatch and git ls-files produce the same
+		# result.
+		match_w_glob=$1
+		match_f_w_glob=$match_w_glob
+		match_w_globi=$2
+		match_f_w_globi=$match_w_globi
+		match_w_pathmatch=$3
+		match_f_w_pathmatch=$match_w_pathmatch
+		match_w_pathmatchi=$4
+		match_f_w_pathmatchi=$match_w_pathmatchi
+		text=$5
+		pattern=$6
+	elif test "$#" = 10
+	then
+		match_w_glob=$1
+		match_w_globi=$2
+		match_w_pathmatch=$3
+		match_w_pathmatchi=$4
+		match_f_w_glob=$5
+		match_f_w_globi=$6
+		match_f_w_pathmatch=$7
+		match_f_w_pathmatchi=$8
+		text=$9
+		pattern=$10
+	fi
 
+	# $1: Case sensitive glob match: test-wildmatch
 	if test "$match_w_glob" = 1
 	then
 		test_expect_success "wildmatch: match '$text' '$pattern'" "
@@ -26,6 +107,50 @@ wildtest() {
 		test_expect_success "PANIC: Test framework error. Unknown matches value $match_w_glob" 'false'
 	fi
 
+	# $1: Case sensitive glob match: ls-files
+	if test "$match_f_w_glob" = 'E'
+	then
+		if create_test_file "$text"
+		then
+			test_expect_success "wildmatch(ls): match dies on '$pattern' '$text'" "
+				wildtest_file_setup &&
+				printf '%s' '$text' >expect &&
+				test_must_fail git --glob-pathspecs ls-files -z -- '$pattern'
+			"
+		else
+			test_expect_failure "wildmatch(ls): match skip '$pattern' '$text'" 'false'
+		fi
+	elif test "$match_f_w_glob" = 1
+	then
+		if create_test_file "$text"
+		then
+			test_expect_success "wildmatch(ls): match '$pattern' '$text'" "
+				wildtest_file_setup &&
+				printf '%s' '$text' >expect &&
+				git --glob-pathspecs ls-files -z -- '$pattern' >actual.raw 2>actual.err &&
+				wildtest_stdout_stderr_cmp
+			"
+		else
+			test_expect_failure "wildmatch(ls): match skip '$pattern' '$text'" 'false'
+		fi
+	elif test "$match_f_w_glob" = 0
+	then
+		if create_test_file "$text"
+		then
+			test_expect_success "wildmatch(ls): no match '$pattern' '$text'" "
+				wildtest_file_setup &&
+				>expect &&
+				git --glob-pathspecs ls-files -z -- '$pattern' >actual.raw 2>actual.err &&
+				wildtest_stdout_stderr_cmp
+			"
+		else
+			test_expect_failure "wildmatch(ls): no match skip '$pattern' '$text'" 'false'
+		fi
+	else
+		test_expect_success "PANIC: Test framework error. Unknown matches value $match_f_w_glob" 'false'
+	fi
+
+	# $2: Case insensitive glob match: test-wildmatch
 	if test "$match_w_globi" = 1
 	then
 		test_expect_success "iwildmatch: match '$text' '$pattern'" "
@@ -40,6 +165,50 @@ wildtest() {
 		test_expect_success "PANIC: Test framework error. Unknown matches value $match_w_globi" 'false'
 	fi
 
+	# $2: Case insensitive glob match: ls-files
+	if test "$match_f_w_globi" = 'E'
+	then
+		if create_test_file "$text"
+		then
+			test_expect_success "iwildmatch(ls): match dies on '$pattern' '$text'" "
+				wildtest_file_setup &&
+				printf '%s' '$text' >expect &&
+				test_must_fail git --glob-pathspecs --icase-pathspecs ls-files -z -- '$pattern'
+			"
+		else
+			test_expect_failure "wildmatch(ls): match skip '$pattern' '$text'" 'false'
+		fi
+	elif test "$match_f_w_globi" = 1
+	then
+		if create_test_file "$text"
+		then
+			test_expect_success "iwildmatch(ls): match '$pattern' '$text'" "
+				wildtest_file_setup &&
+				printf '%s' '$text' >expect &&
+				git --glob-pathspecs --icase-pathspecs ls-files -z -- '$pattern' >actual.raw 2>actual.err &&
+				wildtest_stdout_stderr_cmp
+			"
+		else
+			test_expect_failure "iwildmatch(ls): match skip '$pattern' '$text'" 'false'
+		fi
+	elif test "$match_f_w_globi" = 0
+	then
+		if create_test_file "$text"
+		then
+			test_expect_success "iwildmatch(ls): no match '$pattern' '$text'" "
+				wildtest_file_setup &&
+				>expect &&
+				git --glob-pathspecs --icase-pathspecs ls-files -z -- '$pattern' >actual.raw 2>actual.err &&
+				wildtest_stdout_stderr_cmp
+			"
+		else
+			test_expect_failure "iwildmatch(ls): no match skip '$pattern' '$text'" 'false'
+		fi
+	else
+		test_expect_success "PANIC: Test framework error. Unknown matches value $match_f_w_globi" 'false'
+	fi
+
+	# $3: Case sensitive path match: test-wildmatch
 	if test "$match_w_pathmatch" = 1
 	then
 		test_expect_success "pathmatch: match '$text' '$pattern'" "
@@ -54,6 +223,50 @@ wildtest() {
 		test_expect_success "PANIC: Test framework error. Unknown matches value $match_w_pathmatch" 'false'
 	fi
 
+	# $4: Case sensitive path match: ls-files
+	if test "$match_f_w_pathmatch" = 'E'
+	then
+		if create_test_file "$text"
+		then
+			test_expect_success "pathmatch(ls): match dies on '$pattern' '$text'" "
+				wildtest_file_setup &&
+				printf '%s' '$text' >expect &&
+				test_must_fail git ls-files -z -- '$pattern'
+			"
+		else
+			test_expect_failure "pathmatch(ls): match skip '$pattern' '$text'" 'false'
+		fi
+	elif test "$match_f_w_pathmatch" = 1
+	then
+		if create_test_file "$text"
+		then
+			test_expect_success "pathmatch(ls): match '$pattern' '$text'" "
+				wildtest_file_setup &&
+				printf '%s' '$text' >expect &&
+				git ls-files -z -- '$pattern' >actual.raw 2>actual.err &&
+				wildtest_stdout_stderr_cmp
+			"
+		else
+			test_expect_failure "pathmatch(ls): match skip '$pattern' '$text'" 'false'
+		fi
+	elif test "$match_f_w_pathmatch" = 0
+	then
+		if create_test_file "$text"
+		then
+			test_expect_success "pathmatch(ls): no match '$pattern' '$text'" "
+				wildtest_file_setup &&
+				>expect &&
+				git ls-files -z -- '$pattern' >actual.raw 2>actual.err &&
+				wildtest_stdout_stderr_cmp
+			"
+		else
+			test_expect_failure "pathmatch(ls): no match skip '$pattern' '$text'" 'false'
+		fi
+	else
+		test_expect_success "PANIC: Test framework error. Unknown matches value $match_f_w_pathmatch" 'false'
+	fi
+
+	# $4: Case insensitive path match: test-wildmatch
 	if test "$match_w_pathmatchi" = 1
 	then
 		test_expect_success "ipathmatch: match '$text' '$pattern'" "
@@ -67,6 +280,49 @@ wildtest() {
 	else
 		test_expect_success "PANIC: Test framework error. Unknown matches value $match_w_pathmatchi" 'false'
 	fi
+
+	# $4: Case insensitive path match: ls-files
+	if test "$match_f_w_pathmatchi" = 'E'
+	then
+		if create_test_file "$text"
+		then
+			test_expect_success "ipathmatch(ls): match dies on '$pattern' '$text'" "
+				wildtest_file_setup &&
+				printf '%s' '$text' >expect &&
+				test_must_fail git --icase-pathspecs ls-files -z -- '$pattern'
+			"
+		else
+			test_expect_failure "pathmatch(ls): match skip '$pattern' '$text'" 'false'
+		fi
+	elif test "$match_f_w_pathmatchi" = 1
+	then
+		if create_test_file "$text"
+		then
+			test_expect_success "ipathmatch(ls): match '$pattern' '$text'" "
+				wildtest_file_setup &&
+				printf '%s' '$text' >expect &&
+				git --icase-pathspecs ls-files -z -- '$pattern' >actual.raw 2>actual.err &&
+				wildtest_stdout_stderr_cmp
+			"
+		else
+			test_expect_failure "ipathmatch(ls): match skip '$pattern' '$text'" 'false'
+		fi
+	elif test "$match_f_w_pathmatchi" = 0
+	then
+		if create_test_file "$text"
+		then
+			test_expect_success "ipathmatch(ls): no match '$pattern' '$text'" "
+				wildtest_file_setup &&
+				>expect &&
+				git ls-files -z -- '$pattern' >actual.raw 2>actual.err &&
+				wildtest_stdout_stderr_cmp
+			"
+		else
+			test_expect_failure "ipathmatch(ls): no match skip '$pattern' '$text'" 'false'
+		fi
+	else
+		test_expect_success "PANIC: Test framework error. Unknown matches value $match_f_w_pathmatchi" 'false'
+	fi
 }
 
 # Basic wildmatch features
@@ -135,7 +391,8 @@ wildtest 1 1 1 1 'acrt' 'a[c-c]rt'
 wildtest 0 0 0 0 ']' '[!]-]'
 wildtest 1 1 1 1 'a' '[!]-]'
 wildtest 0 0 0 0 '' '\'
-wildtest 0 0 0 0 '\' '\'
+wildtest 0 0 0 0 \
+	 1 1 1 1 '\' '\'
 wildtest 0 0 0 0 'XXX/\' '*/\'
 wildtest 1 1 1 1 'XXX/\' '*/\\'
 wildtest 1 1 1 1 'foo' 'foo'
@@ -149,7 +406,8 @@ wildtest 1 1 1 1 '[ab]' '[[:digit]ab]'
 wildtest 1 1 1 1 '[ab]' '[\[:]ab]'
 wildtest 1 1 1 1 '?a?b' '\??\?b'
 wildtest 1 1 1 1 'abc' '\a\b\c'
-wildtest 0 0 0 0 'foo' ''
+wildtest 0 0 0 0 \
+	 E E E E 'foo' ''
 wildtest 1 1 1 1 'foo/bar/baz/to' '**/t[o]'
 
 # Character class tests
@@ -179,8 +437,10 @@ wildtest 1 1 1 1 ']' '[\]]'
 wildtest 0 0 0 0 '\]' '[\]]'
 wildtest 0 0 0 0 '\' '[\]]'
 wildtest 0 0 0 0 'ab' 'a[]b'
-wildtest 0 0 0 0 'a[]b' 'a[]b'
-wildtest 0 0 0 0 'ab[' 'ab['
+wildtest 0 0 0 0 \
+	 1 1 1 1 'a[]b' 'a[]b'
+wildtest 0 0 0 0 \
+	 1 1 1 1 'ab[' 'ab['
 wildtest 0 0 0 0 'ab' '[!'
 wildtest 0 0 0 0 'ab' '[-'
 wildtest 1 1 1 1 '-' '[-]'
@@ -248,7 +508,8 @@ wildtest 1 1 1 1 foo/bar 'foo/*'
 wildtest 0 0 1 1 foo/bba/arr 'foo/*'
 wildtest 1 1 1 1 foo/bba/arr 'foo/**'
 wildtest 0 0 1 1 foo/bba/arr 'foo*'
-wildtest 0 0 1 1 foo/bba/arr 'foo**'
+wildtest 0 0 1 1 \
+	 1 1 1 1 foo/bba/arr 'foo**'
 wildtest 0 0 1 1 foo/bba/arr 'foo/*arr'
 wildtest 0 0 1 1 foo/bba/arr 'foo/**arr'
 wildtest 0 0 0 0 foo/bba/arr 'foo/*z'
-- 
2.15.1.424.g9478a66081
Ævar Arnfjörð Bjarmason· Dec 29, 2017, 00:16 UTC · re: Ævar Arnfjörð Bjarmason · lore

Re: [PATCH v3 7/7] wildmatch test: create & test files on disk in addition to in-memory

On Thu, Dec 28 2017, Ævar Arnfjörð Bjarmason jotted:
> +		pattern=$10

Junio, in lie of me spamming the list too much, do you mind squashing this into this (if no further issues arise):

Show changes to t/t3070-wildmatch.sh +1 −1
diff --git a/t/t3070-wildmatch.sh b/t/t3070-wildmatch.sh
index d7aa7eb5fe..f985139b6f 100755
--- a/t/t3070-wildmatch.sh
+++ b/t/t3070-wildmatch.sh
@@ -89,7 +89,7 @@ wildtest() {
                match_f_w_pathmatch=$7
                match_f_w_pathmatchi=$8
                text=$9
-               pattern=$10
+               pattern=${10}
        fi

        # $1: Case sensitive glob match: test-wildmatch

With this the tests pass on both bash & dash.

← back to recent threads