diff options
Diffstat (limited to 'tests/optionstest.c')
-rw-r--r-- | tests/optionstest.c | 380 |
1 files changed, 380 insertions, 0 deletions
diff --git a/tests/optionstest.c b/tests/optionstest.c new file mode 100644 index 0000000..0cedfe6 --- /dev/null +++ b/tests/optionstest.c | |||
@@ -0,0 +1,380 @@ | |||
1 | /* $OpenBSD: optionstest.c,v 1.8 2015/01/22 05:48:00 doug Exp $ */ | ||
2 | /* | ||
3 | * Copyright (c) 2014 Joel Sing <jsing@openbsd.org> | ||
4 | * | ||
5 | * Permission to use, copy, modify, and distribute this software for any | ||
6 | * purpose with or without fee is hereby granted, provided that the above | ||
7 | * copyright notice and this permission notice appear in all copies. | ||
8 | * | ||
9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
10 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
11 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
12 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
13 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
14 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
16 | */ | ||
17 | |||
18 | #include <stdio.h> | ||
19 | #include <stdlib.h> | ||
20 | #include <string.h> | ||
21 | |||
22 | #include <openssl/bio.h> | ||
23 | #include <openssl/conf.h> | ||
24 | |||
25 | #include <apps.h> | ||
26 | |||
27 | /* Needed to keep apps.c happy... */ | ||
28 | BIO *bio_err; | ||
29 | CONF *config; | ||
30 | |||
31 | static int argfunc(char *arg); | ||
32 | static int defaultarg(int argc, char **argv, int *argsused); | ||
33 | static int multiarg(int argc, char **argv, int *argsused); | ||
34 | |||
35 | static struct { | ||
36 | char *arg; | ||
37 | int flag; | ||
38 | } test_config; | ||
39 | |||
40 | static struct option test_options[] = { | ||
41 | { | ||
42 | .name = "arg", | ||
43 | .argname = "argname", | ||
44 | .type = OPTION_ARG, | ||
45 | .opt.arg = &test_config.arg, | ||
46 | }, | ||
47 | { | ||
48 | .name = "argfunc", | ||
49 | .argname = "argname", | ||
50 | .type = OPTION_ARG_FUNC, | ||
51 | .opt.argfunc = argfunc, | ||
52 | }, | ||
53 | { | ||
54 | .name = "flag", | ||
55 | .type = OPTION_FLAG, | ||
56 | .opt.flag = &test_config.flag, | ||
57 | }, | ||
58 | { | ||
59 | .name = "multiarg", | ||
60 | .type = OPTION_ARGV_FUNC, | ||
61 | .opt.argvfunc = multiarg, | ||
62 | }, | ||
63 | { | ||
64 | .name = NULL, | ||
65 | .type = OPTION_ARGV_FUNC, | ||
66 | .opt.argvfunc = defaultarg, | ||
67 | }, | ||
68 | { NULL }, | ||
69 | }; | ||
70 | |||
71 | char *args1[] = { "opts" }; | ||
72 | char *args2[] = { "opts", "-arg", "arg", "-flag" }; | ||
73 | char *args3[] = { "opts", "-arg", "arg", "-flag", "unnamed" }; | ||
74 | char *args4[] = { "opts", "-arg", "arg", "unnamed", "-flag" }; | ||
75 | char *args5[] = { "opts", "unnamed1", "-arg", "arg", "-flag", "unnamed2" }; | ||
76 | char *args6[] = { "opts", "-argfunc", "arg", "-flag" }; | ||
77 | char *args7[] = { "opts", "-arg", "arg", "-flag", "-", "-unnamed" }; | ||
78 | char *args8[] = { "opts", "-arg", "arg", "-flag", "file1", "file2", "file3" }; | ||
79 | char *args9[] = { "opts", "-arg", "arg", "-flag", "file1", "-file2", "file3" }; | ||
80 | char *args10[] = { "opts", "-arg", "arg", "-flag", "-", "file1", "file2" }; | ||
81 | char *args11[] = { "opts", "-arg", "arg", "-flag", "-", "-file1", "-file2" }; | ||
82 | char *args12[] = { "opts", "-multiarg", "arg1", "arg2", "-flag", "unnamed" }; | ||
83 | char *args13[] = { "opts", "-multiargz", "arg1", "arg2", "-flagz", "unnamed" }; | ||
84 | |||
85 | struct options_test { | ||
86 | int argc; | ||
87 | char **argv; | ||
88 | enum { | ||
89 | OPTIONS_TEST_NONE, | ||
90 | OPTIONS_TEST_UNNAMED, | ||
91 | OPTIONS_TEST_ARGSUSED, | ||
92 | } type; | ||
93 | char *unnamed; | ||
94 | int used; | ||
95 | int want; | ||
96 | char *wantarg; | ||
97 | int wantflag; | ||
98 | }; | ||
99 | |||
100 | struct options_test options_tests[] = { | ||
101 | { | ||
102 | /* Test 1 - No arguments (only program name). */ | ||
103 | .argc = 1, | ||
104 | .argv = args1, | ||
105 | .type = OPTIONS_TEST_NONE, | ||
106 | .want = 0, | ||
107 | .wantarg = NULL, | ||
108 | .wantflag = 0, | ||
109 | }, | ||
110 | { | ||
111 | /* Test 2 - Named arguments (unnamed not permitted). */ | ||
112 | .argc = 4, | ||
113 | .argv = args2, | ||
114 | .type = OPTIONS_TEST_NONE, | ||
115 | .want = 0, | ||
116 | .wantarg = "arg", | ||
117 | .wantflag = 1, | ||
118 | }, | ||
119 | { | ||
120 | /* Test 3 - Named arguments (unnamed permitted). */ | ||
121 | .argc = 4, | ||
122 | .argv = args2, | ||
123 | .type = OPTIONS_TEST_UNNAMED, | ||
124 | .unnamed = NULL, | ||
125 | .want = 0, | ||
126 | .wantarg = "arg", | ||
127 | .wantflag = 1, | ||
128 | }, | ||
129 | { | ||
130 | /* Test 4 - Named and single unnamed (unnamed not permitted). */ | ||
131 | .argc = 5, | ||
132 | .argv = args3, | ||
133 | .type = OPTIONS_TEST_NONE, | ||
134 | .want = 1, | ||
135 | }, | ||
136 | { | ||
137 | /* Test 5 - Named and single unnamed (unnamed permitted). */ | ||
138 | .argc = 5, | ||
139 | .argv = args3, | ||
140 | .type = OPTIONS_TEST_UNNAMED, | ||
141 | .unnamed = "unnamed", | ||
142 | .want = 0, | ||
143 | .wantarg = "arg", | ||
144 | .wantflag = 1, | ||
145 | }, | ||
146 | { | ||
147 | /* Test 6 - Named and single unnamed (different sequence). */ | ||
148 | .argc = 5, | ||
149 | .argv = args4, | ||
150 | .type = OPTIONS_TEST_UNNAMED, | ||
151 | .unnamed = "unnamed", | ||
152 | .want = 0, | ||
153 | .wantarg = "arg", | ||
154 | .wantflag = 1, | ||
155 | }, | ||
156 | { | ||
157 | /* Test 7 - Multiple unnamed arguments (should fail). */ | ||
158 | .argc = 6, | ||
159 | .argv = args5, | ||
160 | .type = OPTIONS_TEST_UNNAMED, | ||
161 | .want = 1, | ||
162 | }, | ||
163 | { | ||
164 | /* Test 8 - Function. */ | ||
165 | .argc = 4, | ||
166 | .argv = args6, | ||
167 | .type = OPTIONS_TEST_NONE, | ||
168 | .want = 0, | ||
169 | .wantarg = "arg", | ||
170 | .wantflag = 1, | ||
171 | }, | ||
172 | { | ||
173 | /* Test 9 - Named and single unnamed (hyphen separated). */ | ||
174 | .argc = 6, | ||
175 | .argv = args7, | ||
176 | .type = OPTIONS_TEST_UNNAMED, | ||
177 | .unnamed = "-unnamed", | ||
178 | .want = 0, | ||
179 | .wantarg = "arg", | ||
180 | .wantflag = 1, | ||
181 | }, | ||
182 | { | ||
183 | /* Test 10 - Named and multiple unnamed. */ | ||
184 | .argc = 7, | ||
185 | .argv = args8, | ||
186 | .used = 4, | ||
187 | .type = OPTIONS_TEST_ARGSUSED, | ||
188 | .want = 0, | ||
189 | .wantarg = "arg", | ||
190 | .wantflag = 1, | ||
191 | }, | ||
192 | { | ||
193 | /* Test 11 - Named and multiple unnamed. */ | ||
194 | .argc = 7, | ||
195 | .argv = args9, | ||
196 | .used = 4, | ||
197 | .type = OPTIONS_TEST_ARGSUSED, | ||
198 | .want = 0, | ||
199 | .wantarg = "arg", | ||
200 | .wantflag = 1, | ||
201 | }, | ||
202 | { | ||
203 | /* Test 12 - Named and multiple unnamed. */ | ||
204 | .argc = 7, | ||
205 | .argv = args10, | ||
206 | .used = 5, | ||
207 | .type = OPTIONS_TEST_ARGSUSED, | ||
208 | .want = 0, | ||
209 | .wantarg = "arg", | ||
210 | .wantflag = 1, | ||
211 | }, | ||
212 | { | ||
213 | /* Test 13 - Named and multiple unnamed. */ | ||
214 | .argc = 7, | ||
215 | .argv = args11, | ||
216 | .used = 5, | ||
217 | .type = OPTIONS_TEST_ARGSUSED, | ||
218 | .want = 0, | ||
219 | .wantarg = "arg", | ||
220 | .wantflag = 1, | ||
221 | }, | ||
222 | { | ||
223 | /* Test 14 - Named only. */ | ||
224 | .argc = 4, | ||
225 | .argv = args2, | ||
226 | .used = 4, | ||
227 | .type = OPTIONS_TEST_ARGSUSED, | ||
228 | .want = 0, | ||
229 | .wantarg = "arg", | ||
230 | .wantflag = 1, | ||
231 | }, | ||
232 | { | ||
233 | /* Test 15 - Multiple argument callback. */ | ||
234 | .argc = 6, | ||
235 | .argv = args12, | ||
236 | .unnamed = "unnamed", | ||
237 | .type = OPTIONS_TEST_UNNAMED, | ||
238 | .want = 0, | ||
239 | .wantarg = NULL, | ||
240 | .wantflag = 1, | ||
241 | }, | ||
242 | { | ||
243 | /* Test 16 - Multiple argument callback. */ | ||
244 | .argc = 6, | ||
245 | .argv = args12, | ||
246 | .used = 5, | ||
247 | .type = OPTIONS_TEST_ARGSUSED, | ||
248 | .want = 0, | ||
249 | .wantarg = NULL, | ||
250 | .wantflag = 1, | ||
251 | }, | ||
252 | { | ||
253 | /* Test 17 - Default callback. */ | ||
254 | .argc = 6, | ||
255 | .argv = args13, | ||
256 | .unnamed = "unnamed", | ||
257 | .type = OPTIONS_TEST_UNNAMED, | ||
258 | .want = 0, | ||
259 | .wantarg = NULL, | ||
260 | .wantflag = 1, | ||
261 | }, | ||
262 | { | ||
263 | /* Test 18 - Default callback. */ | ||
264 | .argc = 6, | ||
265 | .argv = args13, | ||
266 | .used = 5, | ||
267 | .type = OPTIONS_TEST_ARGSUSED, | ||
268 | .want = 0, | ||
269 | .wantarg = NULL, | ||
270 | .wantflag = 1, | ||
271 | }, | ||
272 | }; | ||
273 | |||
274 | #define N_OPTIONS_TESTS \ | ||
275 | (sizeof(options_tests) / sizeof(*options_tests)) | ||
276 | |||
277 | static int | ||
278 | argfunc(char *arg) | ||
279 | { | ||
280 | test_config.arg = arg; | ||
281 | return (0); | ||
282 | } | ||
283 | |||
284 | static int | ||
285 | defaultarg(int argc, char **argv, int *argsused) | ||
286 | { | ||
287 | if (argc < 1) | ||
288 | return (1); | ||
289 | |||
290 | if (strcmp(argv[0], "-multiargz") == 0) { | ||
291 | if (argc < 3) | ||
292 | return (1); | ||
293 | *argsused = 3; | ||
294 | return (0); | ||
295 | } else if (strcmp(argv[0], "-flagz") == 0) { | ||
296 | test_config.flag = 1; | ||
297 | *argsused = 1; | ||
298 | return (0); | ||
299 | } | ||
300 | |||
301 | return (1); | ||
302 | } | ||
303 | |||
304 | static int | ||
305 | multiarg(int argc, char **argv, int *argsused) | ||
306 | { | ||
307 | if (argc < 3) | ||
308 | return (1); | ||
309 | |||
310 | *argsused = 3; | ||
311 | return (0); | ||
312 | } | ||
313 | |||
314 | static int | ||
315 | do_options_test(int test_no, struct options_test *ot) | ||
316 | { | ||
317 | int *argsused = NULL; | ||
318 | char *unnamed = NULL; | ||
319 | char **arg = NULL; | ||
320 | int used = 0; | ||
321 | int ret; | ||
322 | |||
323 | if (ot->type == OPTIONS_TEST_UNNAMED) | ||
324 | arg = &unnamed; | ||
325 | else if (ot->type == OPTIONS_TEST_ARGSUSED) | ||
326 | argsused = &used; | ||
327 | |||
328 | memset(&test_config, 0, sizeof(test_config)); | ||
329 | ret = options_parse(ot->argc, ot->argv, test_options, arg, argsused); | ||
330 | if (ret != ot->want) { | ||
331 | fprintf(stderr, "FAIL: test %i options_parse() returned %i, " | ||
332 | "want %i\n", test_no, ret, ot->want); | ||
333 | return (1); | ||
334 | } | ||
335 | if (ret != 0) | ||
336 | return (0); | ||
337 | |||
338 | if ((test_config.arg != NULL || ot->wantarg != NULL) && | ||
339 | (test_config.arg == NULL || ot->wantarg == NULL || | ||
340 | strcmp(test_config.arg, ot->wantarg) != 0)) { | ||
341 | fprintf(stderr, "FAIL: test %i got arg '%s', want '%s'\n", | ||
342 | test_no, test_config.arg, ot->wantarg); | ||
343 | return (1); | ||
344 | } | ||
345 | if (test_config.flag != ot->wantflag) { | ||
346 | fprintf(stderr, "FAIL: test %i got flag %i, want %i\n", | ||
347 | test_no, test_config.flag, ot->wantflag); | ||
348 | return (1); | ||
349 | } | ||
350 | if (ot->type == OPTIONS_TEST_UNNAMED && | ||
351 | (unnamed != NULL || ot->unnamed != NULL) && | ||
352 | (unnamed == NULL || ot->unnamed == NULL || | ||
353 | strcmp(unnamed, ot->unnamed) != 0)) { | ||
354 | fprintf(stderr, "FAIL: test %i got unnamed '%s', want '%s'\n", | ||
355 | test_no, unnamed, ot->unnamed); | ||
356 | return (1); | ||
357 | } | ||
358 | if (ot->type == OPTIONS_TEST_ARGSUSED && used != ot->used) { | ||
359 | fprintf(stderr, "FAIL: test %i got used %i, want %i\n", | ||
360 | test_no, used, ot->used); | ||
361 | return (1); | ||
362 | } | ||
363 | |||
364 | return (0); | ||
365 | } | ||
366 | |||
367 | int | ||
368 | main(int argc, char **argv) | ||
369 | { | ||
370 | int failed = 0; | ||
371 | size_t i; | ||
372 | |||
373 | for (i = 0; i < N_OPTIONS_TESTS; i++) { | ||
374 | printf("Test %d%s\n", (int)(i + 1), options_tests[i].want == 0 ? | ||
375 | "" : " is expected to complain"); | ||
376 | failed += do_options_test(i + 1, &options_tests[i]); | ||
377 | } | ||
378 | |||
379 | return (failed); | ||
380 | } | ||