test-config: add tests for the config_set API

Expose the `config_set` C API as a set of simple commands in order to facilitate testing. Add tests for the `config_set` API as well as for `git_config_get_*()` family for the usual config files. Signed-off-by: Matthieu Moy <Matthieu.Moy@imag.fr> Signed-off-by: Tanay Abhra <tanayabh@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Tanay Abhra committed Jul 28, 2014 at 03:10 UTC 4c715ebb96acc77008e9cbebc381738611c6006f
4 files changed +344
.gitignore
+1
@@ -178,6 +178,7 @@
178 /gitweb/static/gitweb.min.*
179 /test-chmtime
180 /test-ctype
181 +/test-config
182 /test-date
183 /test-delta
184 /test-dump-cache-tree
Makefile
+1
@@ -551,6 +551,7 @@ PROGRAMS += $(patsubst %.o,git-%$X,$(PROGRAM_OBJS))
551
552 TEST_PROGRAMS_NEED_X += test-chmtime
553 TEST_PROGRAMS_NEED_X += test-ctype
554 +TEST_PROGRAMS_NEED_X += test-config
555 TEST_PROGRAMS_NEED_X += test-date
556 TEST_PROGRAMS_NEED_X += test-delta
557 TEST_PROGRAMS_NEED_X += test-dump-cache-tree
t/t1308-config-set.sh new
+200
@@ -0,0 +1,200 @@
1 +#!/bin/sh
2 +
3 +test_description='Test git config-set API in different settings'
4 +
5 +. ./test-lib.sh
6 +
7 +# 'check_config get_* section.key value' verifies that the entry for
8 +# section.key is 'value'
9 +check_config () {
10 + if test "$1" = expect_code
11 + then
12 + expect_code="$2" && shift && shift
13 + else
14 + expect_code=0
15 + fi &&
16 + op=$1 key=$2 && shift && shift &&
17 + if test $# != 0
18 + then
19 + printf "%s\n" "$@"
20 + fi >expect &&
21 + test_expect_code $expect_code test-config "$op" "$key" >actual &&
22 + test_cmp expect actual
23 +}
24 +
25 +test_expect_success 'setup default config' '
26 + cat >.git/config <<\EOF
27 + [case]
28 + penguin = very blue
29 + Movie = BadPhysics
30 + UPPERCASE = true
31 + MixedCase = true
32 + my =
33 + foo
34 + baz = sam
35 + [Cores]
36 + WhatEver = Second
37 + baz = bar
38 + [cores]
39 + baz = bat
40 + [CORES]
41 + baz = ball
42 + [my "Foo bAr"]
43 + hi = mixed-case
44 + [my "FOO BAR"]
45 + hi = upper-case
46 + [my "foo bar"]
47 + hi = lower-case
48 + [case]
49 + baz = bat
50 + baz = hask
51 + [lamb]
52 + chop = 65
53 + head = none
54 + [goat]
55 + legs = 4
56 + head = true
57 + skin = false
58 + nose = 1
59 + horns
60 + EOF
61 +'
62 +
63 +test_expect_success 'get value for a simple key' '
64 + check_config get_value case.penguin "very blue"
65 +'
66 +
67 +test_expect_success 'get value for a key with value as an empty string' '
68 + check_config get_value case.my ""
69 +'
70 +
71 +test_expect_success 'get value for a key with value as NULL' '
72 + check_config get_value case.foo "(NULL)"
73 +'
74 +
75 +test_expect_success 'upper case key' '
76 + check_config get_value case.UPPERCASE "true" &&
77 + check_config get_value case.uppercase "true"
78 +'
79 +
80 +test_expect_success 'mixed case key' '
81 + check_config get_value case.MixedCase "true" &&
82 + check_config get_value case.MIXEDCASE "true" &&
83 + check_config get_value case.mixedcase "true"
84 +'
85 +
86 +test_expect_success 'key and value with mixed case' '
87 + check_config get_value case.Movie "BadPhysics"
88 +'
89 +
90 +test_expect_success 'key with case sensitive subsection' '
91 + check_config get_value "my.Foo bAr.hi" "mixed-case" &&
92 + check_config get_value "my.FOO BAR.hi" "upper-case" &&
93 + check_config get_value "my.foo bar.hi" "lower-case"
94 +'
95 +
96 +test_expect_success 'key with case insensitive section header' '
97 + check_config get_value cores.baz "ball" &&
98 + check_config get_value Cores.baz "ball" &&
99 + check_config get_value CORES.baz "ball" &&
100 + check_config get_value coreS.baz "ball"
101 +'
102 +
103 +test_expect_success 'key with case insensitive section header & variable' '
104 + check_config get_value CORES.BAZ "ball" &&
105 + check_config get_value cores.baz "ball" &&
106 + check_config get_value cores.BaZ "ball" &&
107 + check_config get_value cOreS.bAz "ball"
108 +'
109 +
110 +test_expect_success 'find value with misspelled key' '
111 + check_config expect_code 1 get_value "my.fOo Bar.hi" "Value not found for \"my.fOo Bar.hi\""
112 +'
113 +
114 +test_expect_success 'find value with the highest priority' '
115 + check_config get_value case.baz "hask"
116 +'
117 +
118 +test_expect_success 'find integer value for a key' '
119 + check_config get_int lamb.chop 65
120 +'
121 +
122 +test_expect_success 'find integer if value is non parse-able' '
123 + check_config expect_code 128 get_int lamb.head
124 +'
125 +
126 +test_expect_success 'find bool value for the entered key' '
127 + check_config get_bool goat.head 1 &&
128 + check_config get_bool goat.skin 0 &&
129 + check_config get_bool goat.nose 1 &&
130 + check_config get_bool goat.horns 1 &&
131 + check_config get_bool goat.legs 1
132 +'
133 +
134 +test_expect_success 'find multiple values' '
135 + check_config get_value_multi case.baz sam bat hask
136 +'
137 +
138 +test_expect_success 'find value from a configset' '
139 + cat >config2 <<-\EOF &&
140 + [case]
141 + baz = lama
142 + [my]
143 + new = silk
144 + [case]
145 + baz = ball
146 + EOF
147 + echo silk >expect &&
148 + test-config configset_get_value my.new config2 .git/config >actual &&
149 + test_cmp expect actual
150 +'
151 +
152 +test_expect_success 'find value with highest priority from a configset' '
153 + echo hask >expect &&
154 + test-config configset_get_value case.baz config2 .git/config >actual &&
155 + test_cmp expect actual
156 +'
157 +
158 +test_expect_success 'find value_list for a key from a configset' '
159 + cat >except <<-\EOF &&
160 + sam
161 + bat
162 + hask
163 + lama
164 + ball
165 + EOF
166 + test-config configset_get_value case.baz config2 .git/config >actual &&
167 + test_cmp expect actual
168 +'
169 +
170 +test_expect_success 'proper error on non-existent files' '
171 + echo "Error (-1) reading configuration file non-existent-file." >expect &&
172 + test_expect_code 2 test-config configset_get_value foo.bar non-existent-file 2>actual &&
173 + test_cmp expect actual
174 +'
175 +
176 +test_expect_success POSIXPERM,SANITY 'proper error on non-accessible files' '
177 + chmod -r .git/config &&
178 + test_when_finished "chmod +r .git/config" &&
179 + echo "Error (-1) reading configuration file .git/config." >expect &&
180 + test_expect_code 2 test-config configset_get_value foo.bar .git/config 2>actual &&
181 + test_cmp expect actual
182 +'
183 +
184 +test_expect_success 'proper error on error in default config files' '
185 + cp .git/config .git/config.old &&
186 + test_when_finished "mv .git/config.old .git/config" &&
187 + echo "[" >>.git/config &&
188 + echo "fatal: bad config file line 35 in .git/config" >expect &&
189 + test_expect_code 128 test-config get_value foo.bar 2>actual &&
190 + test_cmp expect actual
191 +'
192 +
193 +test_expect_success 'proper error on error in custom config files' '
194 + echo "[" >>syntax-error &&
195 + echo "fatal: bad config file line 1 in syntax-error" >expect &&
196 + test_expect_code 128 test-config configset_get_value foo.bar syntax-error 2>actual &&
197 + test_cmp expect actual
198 +'
199 +
200 +test_done
test-config.c new
+142
@@ -0,0 +1,142 @@
1 +#include "cache.h"
2 +#include "string-list.h"
3 +
4 +/*
5 + * This program exposes the C API of the configuration mechanism
6 + * as a set of simple commands in order to facilitate testing.
7 + *
8 + * Reads stdin and prints result of command to stdout:
9 + *
10 + * get_value -> prints the value with highest priority for the entered key
11 + *
12 + * get_value_multi -> prints all values for the entered key in increasing order
13 + * of priority
14 + *
15 + * get_int -> print integer value for the entered key or die
16 + *
17 + * get_bool -> print bool value for the entered key or die
18 + *
19 + * configset_get_value -> returns value with the highest priority for the entered key
20 + * from a config_set constructed from files entered as arguments.
21 + *
22 + * configset_get_value_multi -> returns value_list for the entered key sorted in
23 + * ascending order of priority from a config_set
24 + * constructed from files entered as arguments.
25 + *
26 + * Examples:
27 + *
28 + * To print the value with highest priority for key "foo.bAr Baz.rock":
29 + * test-config get_value "foo.bAr Baz.rock"
30 + *
31 + */
32 +
33 +
34 +int main(int argc, char **argv)
35 +{
36 + int i, val;
37 + const char *v;
38 + const struct string_list *strptr;
39 + struct config_set cs;
40 + git_configset_init(&cs);
41 +
42 + if (argc < 2) {
43 + fprintf(stderr, "Please, provide a command name on the command-line\n");
44 + goto exit1;
45 + } else if (argc == 3 && !strcmp(argv[1], "get_value")) {
46 + if (!git_config_get_value(argv[2], &v)) {
47 + if (!v)
48 + printf("(NULL)\n");
49 + else
50 + printf("%s\n", v);
51 + goto exit0;
52 + } else {
53 + printf("Value not found for \"%s\"\n", argv[2]);
54 + goto exit1;
55 + }
56 + } else if (argc == 3 && !strcmp(argv[1], "get_value_multi")) {
57 + strptr = git_config_get_value_multi(argv[2]);
58 + if (strptr) {
59 + for (i = 0; i < strptr->nr; i++) {
60 + v = strptr->items[i].string;
61 + if (!v)
62 + printf("(NULL)\n");
63 + else
64 + printf("%s\n", v);
65 + }
66 + goto exit0;
67 + } else {
68 + printf("Value not found for \"%s\"\n", argv[2]);
69 + goto exit1;
70 + }
71 + } else if (argc == 3 && !strcmp(argv[1], "get_int")) {
72 + if (!git_config_get_int(argv[2], &val)) {
73 + printf("%d\n", val);
74 + goto exit0;
75 + } else {
76 + printf("Value not found for \"%s\"\n", argv[2]);
77 + goto exit1;
78 + }
79 + } else if (argc == 3 && !strcmp(argv[1], "get_bool")) {
80 + if (!git_config_get_bool(argv[2], &val)) {
81 + printf("%d\n", val);
82 + goto exit0;
83 + } else {
84 + printf("Value not found for \"%s\"\n", argv[2]);
85 + goto exit1;
86 + }
87 + } else if (!strcmp(argv[1], "configset_get_value")) {
88 + for (i = 3; i < argc; i++) {
89 + int err;
90 + if ((err = git_configset_add_file(&cs, argv[i]))) {
91 + fprintf(stderr, "Error (%d) reading configuration file %s.\n", err, argv[i]);
92 + goto exit2;
93 + }
94 + }
95 + if (!git_configset_get_value(&cs, argv[2], &v)) {
96 + if (!v)
97 + printf("(NULL)\n");
98 + else
99 + printf("%s\n", v);
100 + goto exit0;
101 + } else {
102 + printf("Value not found for \"%s\"\n", argv[2]);
103 + goto exit1;
104 + }
105 + } else if (!strcmp(argv[1], "configset_get_value_multi")) {
106 + for (i = 3; i < argc; i++) {
107 + int err;
108 + if ((err = git_configset_add_file(&cs, argv[i]))) {
109 + fprintf(stderr, "Error (%d) reading configuration file %s.\n", err, argv[i]);
110 + goto exit2;
111 + }
112 + }
113 + strptr = git_configset_get_value_multi(&cs, argv[2]);
114 + if (strptr) {
115 + for (i = 0; i < strptr->nr; i++) {
116 + v = strptr->items[i].string;
117 + if (!v)
118 + printf("(NULL)\n");
119 + else
120 + printf("%s\n", v);
121 + }
122 + goto exit0;
123 + } else {
124 + printf("Value not found for \"%s\"\n", argv[2]);
125 + goto exit1;
126 + }
127 + }
128 +
129 + die("%s: Please check the syntax and the function name", argv[0]);
130 +
131 +exit0:
132 + git_configset_clear(&cs);
133 + return 0;
134 +
135 +exit1:
136 + git_configset_clear(&cs);
137 + return 1;
138 +
139 +exit2:
140 + git_configset_clear(&cs);
141 + return 2;
142 +}