git/t/t7008-grep-binary.sh
Ævar Arnfjörð Bjarmason 12fc32faa8 grep: prepare for testing binary regexes containing rx metacharacters
Add setup code needed for testing regexes that contain both binary
data and regex metacharacters.

The POSIX regcomp() function inherently can't support that, because it
takes a \0-delimited char *, but other regex engines APIs like PCRE v2
take a pattern/length pair, and are thus able to handle \0s in
patterns as well as any other character.

When kwset was imported in commit 9eceddeec6 ("Use kwset in grep",
2011-08-21) this limitation was fixed, but at the expense of
introducing the undocumented limitation that any pattern containing \0
implicitly becomes a fixed match (equivalent to -F having been
provided).

That's not something we'd like to keep in the future. The inability to
match patterns containing \0 is a leaky implementation detail.

So add tests as a first step towards changing that. In order to test
that \0-patterns can properly match as regexes the test string needs
to have some regex metacharacters in it.

There were other blind spots in the tests. The code around kwset
specially handles case-insensitive & non-ASCII data, but there were no
tests for this.

Fix all of that by amending the text being matched to contain both
regex metacharacters & non-ASCII data.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-05-21 08:25:37 +09:00

181 lines
4.1 KiB
Bash
Executable file

#!/bin/sh
test_description='git grep in binary files'
. ./test-lib.sh
nul_match () {
matches=$1
flags=$2
pattern=$3
pattern_human=$(echo "$pattern" | sed 's/Q/<NUL>/g')
if test "$matches" = 1
then
test_expect_success "git grep -f f $flags '$pattern_human' a" "
printf '$pattern' | q_to_nul >f &&
git grep -f f $flags a
"
elif test "$matches" = 0
then
test_expect_success "git grep -f f $flags '$pattern_human' a" "
printf '$pattern' | q_to_nul >f &&
test_must_fail git grep -f f $flags a
"
else
test_expect_success "PANIC: Test framework error. Unknown matches value $matches" 'false'
fi
}
test_expect_success 'setup' "
echo 'binaryQfileQm[*]cQ*æQð' | q_to_nul >a &&
git add a &&
git commit -m.
"
test_expect_success 'git grep ina a' '
echo Binary file a matches >expect &&
git grep ina a >actual &&
test_cmp expect actual
'
test_expect_success 'git grep -ah ina a' '
git grep -ah ina a >actual &&
test_cmp a actual
'
test_expect_success 'git grep -I ina a' '
: >expect &&
test_must_fail git grep -I ina a >actual &&
test_cmp expect actual
'
test_expect_success 'git grep -c ina a' '
echo a:1 >expect &&
git grep -c ina a >actual &&
test_cmp expect actual
'
test_expect_success 'git grep -l ina a' '
echo a >expect &&
git grep -l ina a >actual &&
test_cmp expect actual
'
test_expect_success 'git grep -L bar a' '
echo a >expect &&
git grep -L bar a >actual &&
test_cmp expect actual
'
test_expect_success 'git grep -q ina a' '
: >expect &&
git grep -q ina a >actual &&
test_cmp expect actual
'
test_expect_success 'git grep -F ile a' '
git grep -F ile a
'
test_expect_success 'git grep -Fi iLE a' '
git grep -Fi iLE a
'
# This test actually passes on platforms where regexec() supports the
# flag REG_STARTEND.
test_expect_success 'git grep ile a' '
git grep ile a
'
test_expect_failure 'git grep .fi a' '
git grep .fi a
'
nul_match 1 '-F' 'yQf'
nul_match 0 '-F' 'yQx'
nul_match 1 '-Fi' 'YQf'
nul_match 0 '-Fi' 'YQx'
nul_match 1 '' 'yQf'
nul_match 0 '' 'yQx'
test_expect_success 'grep respects binary diff attribute' '
echo text >t &&
git add t &&
echo t:text >expect &&
git grep text t >actual &&
test_cmp expect actual &&
echo "t -diff" >.gitattributes &&
echo "Binary file t matches" >expect &&
git grep text t >actual &&
test_cmp expect actual
'
test_expect_success 'grep --cached respects binary diff attribute' '
git grep --cached text t >actual &&
test_cmp expect actual
'
test_expect_success 'grep --cached respects binary diff attribute (2)' '
git add .gitattributes &&
rm .gitattributes &&
git grep --cached text t >actual &&
test_when_finished "git rm --cached .gitattributes" &&
test_when_finished "git checkout .gitattributes" &&
test_cmp expect actual
'
test_expect_success 'grep revision respects binary diff attribute' '
git commit -m new &&
echo "Binary file HEAD:t matches" >expect &&
git grep text HEAD -- t >actual &&
test_when_finished "git reset HEAD^" &&
test_cmp expect actual
'
test_expect_success 'grep respects not-binary diff attribute' '
echo binQary | q_to_nul >b &&
git add b &&
echo "Binary file b matches" >expect &&
git grep bin b >actual &&
test_cmp expect actual &&
echo "b diff" >.gitattributes &&
echo "b:binQary" >expect &&
git grep bin b >actual.raw &&
nul_to_q <actual.raw >actual &&
test_cmp expect actual
'
cat >nul_to_q_textconv <<'EOF'
#!/bin/sh
"$PERL_PATH" -pe 'y/\000/Q/' < "$1"
EOF
chmod +x nul_to_q_textconv
test_expect_success 'setup textconv filters' '
echo a diff=foo >.gitattributes &&
git config diff.foo.textconv "\"$(pwd)\""/nul_to_q_textconv
'
test_expect_success 'grep does not honor textconv' '
test_must_fail git grep Qfile
'
test_expect_success 'grep --textconv honors textconv' '
echo "a:binaryQfileQm[*]cQ*æQð" >expect &&
git grep --textconv Qfile >actual &&
test_cmp expect actual
'
test_expect_success 'grep --no-textconv does not honor textconv' '
test_must_fail git grep --no-textconv Qfile
'
test_expect_success 'grep --textconv blob honors textconv' '
echo "HEAD:a:binaryQfileQm[*]cQ*æQð" >expect &&
git grep --textconv Qfile HEAD:a >actual &&
test_cmp expect actual
'
test_done