e7587a8f53
A less well known edge case in the config format is that keys can be value-less, a shorthand syntax for "true" boolean keys. I.e. these two are equivalent as far as "--type=bool" is concerned: [a]key [a]key = true But as far as our parser is concerned the values for these two are NULL, and "true". I.e. for a sequence like: [a]key=x [a]key [a]key=y We get a "struct string_list" with "string" members with ".string" values of: { "x", NULL, "y" } This behavior goes back to the initial implementation of git_config_bool() in17712991a5
(Add ".git/config" file parser, 2005-10-10). When parts of the config_set API were tested for in [1] they didn't add coverage for 3/4 of the "(NULL)" cases handled in "t/helper/test-config.c". We'd test that case for "get_value", but not "get_value_multi", "configset_get_value" and "configset_get_value_multi". We now cover all of those cases, which in turn expose the details of how this part of the config API works. 1.4c715ebb96
(test-config: add tests for the config_set API, 2014-07-28) Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
351 lines
8.4 KiB
Bash
Executable File
351 lines
8.4 KiB
Bash
Executable File
#!/bin/sh
|
|
|
|
test_description='Test git config-set API in different settings'
|
|
|
|
TEST_PASSES_SANITIZE_LEAK=true
|
|
. ./test-lib.sh
|
|
|
|
# 'check_config get_* section.key value' verifies that the entry for
|
|
# section.key is 'value'
|
|
check_config () {
|
|
if test "$1" = expect_code
|
|
then
|
|
expect_code="$2" && shift && shift
|
|
else
|
|
expect_code=0
|
|
fi &&
|
|
op=$1 key=$2 && shift && shift &&
|
|
if test $# != 0
|
|
then
|
|
printf "%s\n" "$@"
|
|
fi >expect &&
|
|
test_expect_code $expect_code test-tool config "$op" "$key" >actual &&
|
|
test_cmp expect actual
|
|
}
|
|
|
|
test_expect_success 'setup default config' '
|
|
cat >.git/config <<-\EOF
|
|
[case]
|
|
penguin = very blue
|
|
Movie = BadPhysics
|
|
UPPERCASE = true
|
|
MixedCase = true
|
|
my =
|
|
foo
|
|
baz = sam
|
|
[Cores]
|
|
WhatEver = Second
|
|
baz = bar
|
|
[cores]
|
|
baz = bat
|
|
[CORES]
|
|
baz = ball
|
|
[my "Foo bAr"]
|
|
hi = mixed-case
|
|
[my "FOO BAR"]
|
|
hi = upper-case
|
|
[my "foo bar"]
|
|
hi = lower-case
|
|
[case]
|
|
baz = bat
|
|
baz = hask
|
|
[lamb]
|
|
chop = 65
|
|
head = none
|
|
[goat]
|
|
legs = 4
|
|
head = true
|
|
skin = false
|
|
nose = 1
|
|
horns
|
|
EOF
|
|
'
|
|
|
|
test_expect_success 'get value for a simple key' '
|
|
check_config get_value case.penguin "very blue"
|
|
'
|
|
|
|
test_expect_success 'get value for a key with value as an empty string' '
|
|
check_config get_value case.my ""
|
|
'
|
|
|
|
test_expect_success 'get value for a key with value as NULL' '
|
|
check_config get_value case.foo "(NULL)"
|
|
'
|
|
|
|
test_expect_success 'upper case key' '
|
|
check_config get_value case.UPPERCASE "true" &&
|
|
check_config get_value case.uppercase "true"
|
|
'
|
|
|
|
test_expect_success 'mixed case key' '
|
|
check_config get_value case.MixedCase "true" &&
|
|
check_config get_value case.MIXEDCASE "true" &&
|
|
check_config get_value case.mixedcase "true"
|
|
'
|
|
|
|
test_expect_success 'key and value with mixed case' '
|
|
check_config get_value case.Movie "BadPhysics"
|
|
'
|
|
|
|
test_expect_success 'key with case sensitive subsection' '
|
|
check_config get_value "my.Foo bAr.hi" "mixed-case" &&
|
|
check_config get_value "my.FOO BAR.hi" "upper-case" &&
|
|
check_config get_value "my.foo bar.hi" "lower-case"
|
|
'
|
|
|
|
test_expect_success 'key with case insensitive section header' '
|
|
check_config get_value cores.baz "ball" &&
|
|
check_config get_value Cores.baz "ball" &&
|
|
check_config get_value CORES.baz "ball" &&
|
|
check_config get_value coreS.baz "ball"
|
|
'
|
|
|
|
test_expect_success 'key with case insensitive section header & variable' '
|
|
check_config get_value CORES.BAZ "ball" &&
|
|
check_config get_value cores.baz "ball" &&
|
|
check_config get_value cores.BaZ "ball" &&
|
|
check_config get_value cOreS.bAz "ball"
|
|
'
|
|
|
|
test_expect_success 'find value with misspelled key' '
|
|
check_config expect_code 1 get_value "my.fOo Bar.hi" "Value not found for \"my.fOo Bar.hi\""
|
|
'
|
|
|
|
test_expect_success 'find value with the highest priority' '
|
|
check_config get_value case.baz "hask"
|
|
'
|
|
|
|
test_expect_success 'find integer value for a key' '
|
|
check_config get_int lamb.chop 65
|
|
'
|
|
|
|
test_expect_success 'find string value for a key' '
|
|
check_config get_string case.baz hask &&
|
|
check_config expect_code 1 get_string case.ba "Value not found for \"case.ba\""
|
|
'
|
|
|
|
test_expect_success 'check line error when NULL string is queried' '
|
|
test_expect_code 128 test-tool config get_string case.foo 2>result &&
|
|
test_i18ngrep "fatal: .*case\.foo.*\.git/config.*line 7" result
|
|
'
|
|
|
|
test_expect_success 'find integer if value is non parse-able' '
|
|
check_config expect_code 128 get_int lamb.head
|
|
'
|
|
|
|
test_expect_success 'find bool value for the entered key' '
|
|
check_config get_bool goat.head 1 &&
|
|
check_config get_bool goat.skin 0 &&
|
|
check_config get_bool goat.nose 1 &&
|
|
check_config get_bool goat.horns 1 &&
|
|
check_config get_bool goat.legs 1
|
|
'
|
|
|
|
test_expect_success 'find multiple values' '
|
|
check_config get_value_multi case.baz sam bat hask
|
|
'
|
|
|
|
test_NULL_in_multi () {
|
|
local op="$1" &&
|
|
local file="$2" &&
|
|
|
|
test_expect_success "$op: NULL value in config${file:+ in $file}" '
|
|
config="$file" &&
|
|
if test -z "$config"
|
|
then
|
|
config=.git/config &&
|
|
test_when_finished "mv $config.old $config" &&
|
|
mv "$config" "$config".old
|
|
fi &&
|
|
|
|
# Value-less in the middle of a list
|
|
cat >"$config" <<-\EOF &&
|
|
[a]key=x
|
|
[a]key
|
|
[a]key=y
|
|
EOF
|
|
case "$op" in
|
|
*_multi)
|
|
cat >expect <<-\EOF
|
|
x
|
|
(NULL)
|
|
y
|
|
EOF
|
|
;;
|
|
*)
|
|
cat >expect <<-\EOF
|
|
y
|
|
EOF
|
|
;;
|
|
esac &&
|
|
test-tool config "$op" a.key $file >actual &&
|
|
test_cmp expect actual &&
|
|
|
|
# Value-less at the end of a least
|
|
cat >"$config" <<-\EOF &&
|
|
[a]key=x
|
|
[a]key=y
|
|
[a]key
|
|
EOF
|
|
case "$op" in
|
|
*_multi)
|
|
cat >expect <<-\EOF
|
|
x
|
|
y
|
|
(NULL)
|
|
EOF
|
|
;;
|
|
*)
|
|
cat >expect <<-\EOF
|
|
(NULL)
|
|
EOF
|
|
;;
|
|
esac &&
|
|
test-tool config "$op" a.key $file >actual &&
|
|
test_cmp expect actual
|
|
'
|
|
}
|
|
|
|
test_NULL_in_multi "get_value_multi"
|
|
test_NULL_in_multi "configset_get_value" "my.config"
|
|
test_NULL_in_multi "configset_get_value_multi" "my.config"
|
|
|
|
test_expect_success 'find value from a configset' '
|
|
cat >config2 <<-\EOF &&
|
|
[case]
|
|
baz = lama
|
|
[my]
|
|
new = silk
|
|
[case]
|
|
baz = ball
|
|
EOF
|
|
echo silk >expect &&
|
|
test-tool config configset_get_value my.new config2 .git/config >actual &&
|
|
test_cmp expect actual
|
|
'
|
|
|
|
test_expect_success 'find value with highest priority from a configset' '
|
|
echo hask >expect &&
|
|
test-tool config configset_get_value case.baz config2 .git/config >actual &&
|
|
test_cmp expect actual
|
|
'
|
|
|
|
test_expect_success 'find value_list for a key from a configset' '
|
|
cat >expect <<-\EOF &&
|
|
lama
|
|
ball
|
|
sam
|
|
bat
|
|
hask
|
|
EOF
|
|
test-tool config configset_get_value_multi case.baz config2 .git/config >actual &&
|
|
test_cmp expect actual
|
|
'
|
|
|
|
test_expect_success 'proper error on non-existent files' '
|
|
echo "Error (-1) reading configuration file non-existent-file." >expect &&
|
|
test_expect_code 2 test-tool config configset_get_value foo.bar non-existent-file 2>actual &&
|
|
test_cmp expect actual
|
|
'
|
|
|
|
test_expect_success 'proper error on directory "files"' '
|
|
echo "Error (-1) reading configuration file a-directory." >expect &&
|
|
mkdir a-directory &&
|
|
test_expect_code 2 test-tool config configset_get_value foo.bar a-directory 2>output &&
|
|
grep "^warning:" output &&
|
|
grep "^Error" output >actual &&
|
|
test_cmp expect actual
|
|
'
|
|
|
|
test_expect_success POSIXPERM,SANITY 'proper error on non-accessible files' '
|
|
chmod -r .git/config &&
|
|
test_when_finished "chmod +r .git/config" &&
|
|
echo "Error (-1) reading configuration file .git/config." >expect &&
|
|
test_expect_code 2 test-tool config configset_get_value foo.bar .git/config 2>output &&
|
|
grep "^warning:" output &&
|
|
grep "^Error" output >actual &&
|
|
test_cmp expect actual
|
|
'
|
|
|
|
test_expect_success 'proper error on error in default config files' '
|
|
cp .git/config .git/config.old &&
|
|
test_when_finished "mv .git/config.old .git/config" &&
|
|
echo "[" >>.git/config &&
|
|
echo "fatal: bad config line 34 in file .git/config" >expect &&
|
|
test_expect_code 128 test-tool config get_value foo.bar 2>actual &&
|
|
test_cmp expect actual
|
|
'
|
|
|
|
test_expect_success 'proper error on error in custom config files' '
|
|
echo "[" >>syntax-error &&
|
|
echo "fatal: bad config line 1 in file syntax-error" >expect &&
|
|
test_expect_code 128 test-tool config configset_get_value foo.bar syntax-error 2>actual &&
|
|
test_cmp expect actual
|
|
'
|
|
|
|
test_expect_success 'check line errors for malformed values' '
|
|
mv .git/config .git/config.old &&
|
|
test_when_finished "mv .git/config.old .git/config" &&
|
|
cat >.git/config <<-\EOF &&
|
|
[alias]
|
|
br
|
|
EOF
|
|
test_expect_code 128 git br 2>result &&
|
|
test_i18ngrep "missing value for .alias\.br" result &&
|
|
test_i18ngrep "fatal: .*\.git/config" result &&
|
|
test_i18ngrep "fatal: .*line 2" result
|
|
'
|
|
|
|
test_expect_success 'error on modifying repo config without repo' '
|
|
nongit test_must_fail git config a.b c 2>err &&
|
|
test_i18ngrep "not in a git directory" err
|
|
'
|
|
|
|
cmdline_config="'foo.bar=from-cmdline'"
|
|
test_expect_success 'iteration shows correct origins' '
|
|
printf "[ignore]\n\tthis = please\n[foo]bar = from-repo\n" >.git/config &&
|
|
printf "[foo]\n\tbar = from-home\n" >.gitconfig &&
|
|
if test_have_prereq MINGW
|
|
then
|
|
# Use Windows path (i.e. *not* $HOME)
|
|
HOME_GITCONFIG=$(pwd)/.gitconfig
|
|
else
|
|
# Do not get fooled by symbolic links, i.e. $HOME != $(pwd)
|
|
HOME_GITCONFIG=$HOME/.gitconfig
|
|
fi &&
|
|
cat >expect <<-EOF &&
|
|
key=foo.bar
|
|
value=from-home
|
|
origin=file
|
|
name=$HOME_GITCONFIG
|
|
lno=2
|
|
scope=global
|
|
|
|
key=ignore.this
|
|
value=please
|
|
origin=file
|
|
name=.git/config
|
|
lno=2
|
|
scope=local
|
|
|
|
key=foo.bar
|
|
value=from-repo
|
|
origin=file
|
|
name=.git/config
|
|
lno=3
|
|
scope=local
|
|
|
|
key=foo.bar
|
|
value=from-cmdline
|
|
origin=command line
|
|
name=
|
|
lno=-1
|
|
scope=command
|
|
EOF
|
|
GIT_CONFIG_PARAMETERS=$cmdline_config test-tool config iterate >actual &&
|
|
test_cmp expect actual
|
|
'
|
|
|
|
test_done
|