xref: /openbsd-src/regress/usr.bin/openssl/options/optionstest.c (revision e4ba687df1aa5ad979549161b254b79fc024d7e2)
1*e4ba687dSkettenis /*	$OpenBSD: optionstest.c,v 1.9 2017/04/16 14:40:47 kettenis Exp $	*/
24f3aca57Sjsing /*
34f3aca57Sjsing  * Copyright (c) 2014 Joel Sing <jsing@openbsd.org>
44f3aca57Sjsing  *
54f3aca57Sjsing  * Permission to use, copy, modify, and distribute this software for any
64f3aca57Sjsing  * purpose with or without fee is hereby granted, provided that the above
74f3aca57Sjsing  * copyright notice and this permission notice appear in all copies.
84f3aca57Sjsing  *
94f3aca57Sjsing  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
104f3aca57Sjsing  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
114f3aca57Sjsing  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
124f3aca57Sjsing  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
134f3aca57Sjsing  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
144f3aca57Sjsing  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
154f3aca57Sjsing  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
164f3aca57Sjsing  */
174f3aca57Sjsing 
184f3aca57Sjsing #include <stdio.h>
194f3aca57Sjsing #include <stdlib.h>
204f3aca57Sjsing #include <string.h>
214f3aca57Sjsing 
224f3aca57Sjsing #include <openssl/bio.h>
234f3aca57Sjsing #include <openssl/conf.h>
244f3aca57Sjsing 
254f3aca57Sjsing #include "apps.h"
264f3aca57Sjsing 
274f3aca57Sjsing /* Needed to keep apps.c happy... */
284f3aca57Sjsing BIO *bio_err;
294f3aca57Sjsing CONF *config;
304f3aca57Sjsing 
318ed0003cSjsing static int argfunc(char *arg);
32acd043e0Sjsing static int defaultarg(int argc, char **argv, int *argsused);
33b0c07505Sjsing static int multiarg(int argc, char **argv, int *argsused);
344f3aca57Sjsing 
354f3aca57Sjsing static struct {
364f3aca57Sjsing 	char *arg;
374f3aca57Sjsing 	int flag;
384f3aca57Sjsing } test_config;
394f3aca57Sjsing 
404f3aca57Sjsing static struct option test_options[] = {
414f3aca57Sjsing 	{
424f3aca57Sjsing 		.name = "arg",
43859b5814Sjsing 		.argname = "argname",
444f3aca57Sjsing 		.type = OPTION_ARG,
454f3aca57Sjsing 		.opt.arg = &test_config.arg,
464f3aca57Sjsing 	},
474f3aca57Sjsing 	{
484f3aca57Sjsing 		.name = "argfunc",
49859b5814Sjsing 		.argname = "argname",
504f3aca57Sjsing 		.type = OPTION_ARG_FUNC,
518ed0003cSjsing 		.opt.argfunc = argfunc,
524f3aca57Sjsing 	},
534f3aca57Sjsing 	{
544f3aca57Sjsing 		.name = "flag",
554f3aca57Sjsing 		.type = OPTION_FLAG,
564f3aca57Sjsing 		.opt.flag = &test_config.flag,
574f3aca57Sjsing 	},
58b0c07505Sjsing 	{
59b0c07505Sjsing 		.name = "multiarg",
60b0c07505Sjsing 		.type = OPTION_ARGV_FUNC,
61b0c07505Sjsing 		.opt.argvfunc = multiarg,
62b0c07505Sjsing 	},
63acd043e0Sjsing 	{
64acd043e0Sjsing 		.name = NULL,
65acd043e0Sjsing 		.type = OPTION_ARGV_FUNC,
66acd043e0Sjsing 		.opt.argvfunc = defaultarg,
67acd043e0Sjsing 	},
684f3aca57Sjsing 	{ NULL },
694f3aca57Sjsing };
704f3aca57Sjsing 
714f3aca57Sjsing char *args1[] = { "opts" };
724f3aca57Sjsing char *args2[] = { "opts", "-arg", "arg", "-flag" };
734f3aca57Sjsing char *args3[] = { "opts", "-arg", "arg", "-flag", "unnamed" };
744f3aca57Sjsing char *args4[] = { "opts", "-arg", "arg", "unnamed", "-flag" };
754f3aca57Sjsing char *args5[] = { "opts", "unnamed1", "-arg", "arg", "-flag", "unnamed2" };
764f3aca57Sjsing char *args6[] = { "opts", "-argfunc", "arg", "-flag" };
775736f113Sjsing char *args7[] = { "opts", "-arg", "arg", "-flag", "-", "-unnamed" };
785736f113Sjsing char *args8[] = { "opts", "-arg", "arg", "-flag", "file1", "file2", "file3" };
795736f113Sjsing char *args9[] = { "opts", "-arg", "arg", "-flag", "file1", "-file2", "file3" };
805736f113Sjsing char *args10[] = { "opts", "-arg", "arg", "-flag", "-", "file1", "file2" };
815736f113Sjsing char *args11[] = { "opts", "-arg", "arg", "-flag", "-", "-file1", "-file2" };
82b0c07505Sjsing char *args12[] = { "opts", "-multiarg", "arg1", "arg2", "-flag", "unnamed" };
83acd043e0Sjsing char *args13[] = { "opts", "-multiargz", "arg1", "arg2", "-flagz", "unnamed" };
844f3aca57Sjsing 
854f3aca57Sjsing struct options_test {
864f3aca57Sjsing 	int argc;
874f3aca57Sjsing 	char **argv;
884f3aca57Sjsing 	enum {
894f3aca57Sjsing 		OPTIONS_TEST_NONE,
904f3aca57Sjsing 		OPTIONS_TEST_UNNAMED,
9193d5edbbSjsing 		OPTIONS_TEST_ARGSUSED,
924f3aca57Sjsing 	} type;
934f3aca57Sjsing 	char *unnamed;
944f3aca57Sjsing 	int used;
954f3aca57Sjsing 	int want;
964f3aca57Sjsing 	char *wantarg;
974f3aca57Sjsing 	int wantflag;
984f3aca57Sjsing };
994f3aca57Sjsing 
1004f3aca57Sjsing struct options_test options_tests[] = {
1014f3aca57Sjsing 	{
1025736f113Sjsing 		/* Test 1 - No arguments (only program name). */
1034f3aca57Sjsing 		.argc = 1,
1044f3aca57Sjsing 		.argv = args1,
1054f3aca57Sjsing 		.type = OPTIONS_TEST_NONE,
1064f3aca57Sjsing 		.want = 0,
1074f3aca57Sjsing 		.wantarg = NULL,
1084f3aca57Sjsing 		.wantflag = 0,
1094f3aca57Sjsing 	},
1104f3aca57Sjsing 	{
1115736f113Sjsing 		/* Test 2 - Named arguments (unnamed not permitted). */
1124f3aca57Sjsing 		.argc = 4,
1134f3aca57Sjsing 		.argv = args2,
1144f3aca57Sjsing 		.type = OPTIONS_TEST_NONE,
1154f3aca57Sjsing 		.want = 0,
1164f3aca57Sjsing 		.wantarg = "arg",
1174f3aca57Sjsing 		.wantflag = 1,
1184f3aca57Sjsing 	},
1194f3aca57Sjsing 	{
1205736f113Sjsing 		/* Test 3 - Named arguments (unnamed permitted). */
1214f3aca57Sjsing 		.argc = 4,
1224f3aca57Sjsing 		.argv = args2,
1234f3aca57Sjsing 		.type = OPTIONS_TEST_UNNAMED,
1244f3aca57Sjsing 		.unnamed = NULL,
1254f3aca57Sjsing 		.want = 0,
1264f3aca57Sjsing 		.wantarg = "arg",
1274f3aca57Sjsing 		.wantflag = 1,
1284f3aca57Sjsing 	},
1294f3aca57Sjsing 	{
1305736f113Sjsing 		/* Test 4 - Named and single unnamed (unnamed not permitted). */
1314f3aca57Sjsing 		.argc = 5,
1324f3aca57Sjsing 		.argv = args3,
1334f3aca57Sjsing 		.type = OPTIONS_TEST_NONE,
1344f3aca57Sjsing 		.want = 1,
1354f3aca57Sjsing 	},
1364f3aca57Sjsing 	{
1375736f113Sjsing 		/* Test 5 - Named and single unnamed (unnamed permitted). */
1384f3aca57Sjsing 		.argc = 5,
1394f3aca57Sjsing 		.argv = args3,
1404f3aca57Sjsing 		.type = OPTIONS_TEST_UNNAMED,
1414f3aca57Sjsing 		.unnamed = "unnamed",
1424f3aca57Sjsing 		.want = 0,
1434f3aca57Sjsing 		.wantarg = "arg",
1444f3aca57Sjsing 		.wantflag = 1,
1454f3aca57Sjsing 	},
1464f3aca57Sjsing 	{
1475736f113Sjsing 		/* Test 6 - Named and single unnamed (different sequence). */
1484f3aca57Sjsing 		.argc = 5,
1494f3aca57Sjsing 		.argv = args4,
1504f3aca57Sjsing 		.type = OPTIONS_TEST_UNNAMED,
1514f3aca57Sjsing 		.unnamed = "unnamed",
1524f3aca57Sjsing 		.want = 0,
1534f3aca57Sjsing 		.wantarg = "arg",
1544f3aca57Sjsing 		.wantflag = 1,
1554f3aca57Sjsing 	},
1564f3aca57Sjsing 	{
1575736f113Sjsing 		/* Test 7 - Multiple unnamed arguments (should fail). */
1584f3aca57Sjsing 		.argc = 6,
1594f3aca57Sjsing 		.argv = args5,
1604f3aca57Sjsing 		.type = OPTIONS_TEST_UNNAMED,
161859b5814Sjsing 		.want = 1,
1624f3aca57Sjsing 	},
1634f3aca57Sjsing 	{
1645736f113Sjsing 		/* Test 8 - Function. */
1654f3aca57Sjsing 		.argc = 4,
1664f3aca57Sjsing 		.argv = args6,
1674f3aca57Sjsing 		.type = OPTIONS_TEST_NONE,
1684f3aca57Sjsing 		.want = 0,
1694f3aca57Sjsing 		.wantarg = "arg",
1704f3aca57Sjsing 		.wantflag = 1,
1714f3aca57Sjsing 	},
17293d5edbbSjsing 	{
1735736f113Sjsing 		/* Test 9 - Named and single unnamed (hyphen separated). */
1745736f113Sjsing 		.argc = 6,
17593d5edbbSjsing 		.argv = args7,
1765736f113Sjsing 		.type = OPTIONS_TEST_UNNAMED,
1775736f113Sjsing 		.unnamed = "-unnamed",
17893d5edbbSjsing 		.want = 0,
17993d5edbbSjsing 		.wantarg = "arg",
18093d5edbbSjsing 		.wantflag = 1,
18193d5edbbSjsing 	},
18293d5edbbSjsing 	{
1835736f113Sjsing 		/* Test 10 - Named and multiple unnamed. */
18493d5edbbSjsing 		.argc = 7,
18593d5edbbSjsing 		.argv = args8,
18693d5edbbSjsing 		.used = 4,
18793d5edbbSjsing 		.type = OPTIONS_TEST_ARGSUSED,
18893d5edbbSjsing 		.want = 0,
18993d5edbbSjsing 		.wantarg = "arg",
19093d5edbbSjsing 		.wantflag = 1,
19193d5edbbSjsing 	},
19293d5edbbSjsing 	{
1935736f113Sjsing 		/* Test 11 - Named and multiple unnamed. */
1945736f113Sjsing 		.argc = 7,
1955736f113Sjsing 		.argv = args9,
1965736f113Sjsing 		.used = 4,
1975736f113Sjsing 		.type = OPTIONS_TEST_ARGSUSED,
1985736f113Sjsing 		.want = 0,
1995736f113Sjsing 		.wantarg = "arg",
2005736f113Sjsing 		.wantflag = 1,
2015736f113Sjsing 	},
2025736f113Sjsing 	{
2035736f113Sjsing 		/* Test 12 - Named and multiple unnamed. */
2045736f113Sjsing 		.argc = 7,
2055736f113Sjsing 		.argv = args10,
2065736f113Sjsing 		.used = 5,
2075736f113Sjsing 		.type = OPTIONS_TEST_ARGSUSED,
2085736f113Sjsing 		.want = 0,
2095736f113Sjsing 		.wantarg = "arg",
2105736f113Sjsing 		.wantflag = 1,
2115736f113Sjsing 	},
2125736f113Sjsing 	{
2135736f113Sjsing 		/* Test 13 - Named and multiple unnamed. */
2145736f113Sjsing 		.argc = 7,
2155736f113Sjsing 		.argv = args11,
2165736f113Sjsing 		.used = 5,
2175736f113Sjsing 		.type = OPTIONS_TEST_ARGSUSED,
2185736f113Sjsing 		.want = 0,
2195736f113Sjsing 		.wantarg = "arg",
2205736f113Sjsing 		.wantflag = 1,
2215736f113Sjsing 	},
2225736f113Sjsing 	{
2235736f113Sjsing 		/* Test 14 - Named only. */
22493d5edbbSjsing 		.argc = 4,
22593d5edbbSjsing 		.argv = args2,
22693d5edbbSjsing 		.used = 4,
22793d5edbbSjsing 		.type = OPTIONS_TEST_ARGSUSED,
22893d5edbbSjsing 		.want = 0,
22993d5edbbSjsing 		.wantarg = "arg",
23093d5edbbSjsing 		.wantflag = 1,
23193d5edbbSjsing 	},
232b0c07505Sjsing 	{
233b0c07505Sjsing 		/* Test 15 - Multiple argument callback. */
234b0c07505Sjsing 		.argc = 6,
235b0c07505Sjsing 		.argv = args12,
236b0c07505Sjsing 		.unnamed = "unnamed",
237b0c07505Sjsing 		.type = OPTIONS_TEST_UNNAMED,
238b0c07505Sjsing 		.want = 0,
239b0c07505Sjsing 		.wantarg = NULL,
240b0c07505Sjsing 		.wantflag = 1,
241b0c07505Sjsing 	},
242b0c07505Sjsing 	{
243b0c07505Sjsing 		/* Test 16 - Multiple argument callback. */
244b0c07505Sjsing 		.argc = 6,
245b0c07505Sjsing 		.argv = args12,
246b0c07505Sjsing 		.used = 5,
247b0c07505Sjsing 		.type = OPTIONS_TEST_ARGSUSED,
248b0c07505Sjsing 		.want = 0,
249b0c07505Sjsing 		.wantarg = NULL,
250b0c07505Sjsing 		.wantflag = 1,
251b0c07505Sjsing 	},
252acd043e0Sjsing 	{
253acd043e0Sjsing 		/* Test 17 - Default callback. */
254acd043e0Sjsing 		.argc = 6,
255acd043e0Sjsing 		.argv = args13,
256acd043e0Sjsing 		.unnamed = "unnamed",
257acd043e0Sjsing 		.type = OPTIONS_TEST_UNNAMED,
258acd043e0Sjsing 		.want = 0,
259acd043e0Sjsing 		.wantarg = NULL,
260acd043e0Sjsing 		.wantflag = 1,
261acd043e0Sjsing 	},
262acd043e0Sjsing 	{
263acd043e0Sjsing 		/* Test 18 - Default callback. */
264acd043e0Sjsing 		.argc = 6,
265acd043e0Sjsing 		.argv = args13,
266acd043e0Sjsing 		.used = 5,
267acd043e0Sjsing 		.type = OPTIONS_TEST_ARGSUSED,
268acd043e0Sjsing 		.want = 0,
269acd043e0Sjsing 		.wantarg = NULL,
270acd043e0Sjsing 		.wantflag = 1,
271acd043e0Sjsing 	},
2724f3aca57Sjsing };
2734f3aca57Sjsing 
2744f3aca57Sjsing #define N_OPTIONS_TESTS \
2754f3aca57Sjsing     (sizeof(options_tests) / sizeof(*options_tests))
2764f3aca57Sjsing 
27793d5edbbSjsing static int
argfunc(char * arg)2788ed0003cSjsing argfunc(char *arg)
2794f3aca57Sjsing {
2804f3aca57Sjsing 	test_config.arg = arg;
2814f3aca57Sjsing 	return (0);
2824f3aca57Sjsing }
2834f3aca57Sjsing 
2844f3aca57Sjsing static int
defaultarg(int argc,char ** argv,int * argsused)285acd043e0Sjsing defaultarg(int argc, char **argv, int *argsused)
286acd043e0Sjsing {
287acd043e0Sjsing 	if (argc < 1)
288acd043e0Sjsing 		return (1);
289acd043e0Sjsing 
290acd043e0Sjsing 	if (strcmp(argv[0], "-multiargz") == 0) {
291acd043e0Sjsing 		if (argc < 3)
292acd043e0Sjsing 			return (1);
293acd043e0Sjsing 		*argsused = 3;
294acd043e0Sjsing 		return (0);
295acd043e0Sjsing 	} else if (strcmp(argv[0], "-flagz") == 0) {
296acd043e0Sjsing 		test_config.flag = 1;
297acd043e0Sjsing 		*argsused = 1;
298acd043e0Sjsing 		return (0);
299acd043e0Sjsing 	}
300acd043e0Sjsing 
301acd043e0Sjsing 	return (1);
302acd043e0Sjsing }
303acd043e0Sjsing 
304acd043e0Sjsing static int
multiarg(int argc,char ** argv,int * argsused)305b0c07505Sjsing multiarg(int argc, char **argv, int *argsused)
306b0c07505Sjsing {
307b0c07505Sjsing 	if (argc < 3)
308b0c07505Sjsing 		return (1);
309b0c07505Sjsing 
310b0c07505Sjsing 	*argsused = 3;
311b0c07505Sjsing 	return (0);
312b0c07505Sjsing }
313b0c07505Sjsing 
314b0c07505Sjsing static int
do_options_test(int test_no,struct options_test * ot)3154f3aca57Sjsing do_options_test(int test_no, struct options_test *ot)
3164f3aca57Sjsing {
31793d5edbbSjsing 	int *argsused = NULL;
3184f3aca57Sjsing 	char *unnamed = NULL;
3194f3aca57Sjsing 	char **arg = NULL;
32093d5edbbSjsing 	int used = 0;
3214f3aca57Sjsing 	int ret;
3224f3aca57Sjsing 
3234f3aca57Sjsing 	if (ot->type == OPTIONS_TEST_UNNAMED)
3244f3aca57Sjsing 		arg = &unnamed;
32593d5edbbSjsing 	else if (ot->type == OPTIONS_TEST_ARGSUSED)
32693d5edbbSjsing 		argsused = &used;
3274f3aca57Sjsing 
3284f3aca57Sjsing 	memset(&test_config, 0, sizeof(test_config));
32993d5edbbSjsing 	ret = options_parse(ot->argc, ot->argv, test_options, arg, argsused);
3304f3aca57Sjsing 	if (ret != ot->want) {
3314f3aca57Sjsing 		fprintf(stderr, "FAIL: test %i options_parse() returned %i, "
3324f3aca57Sjsing 		    "want %i\n", test_no, ret, ot->want);
3334f3aca57Sjsing 		return (1);
3344f3aca57Sjsing 	}
3354f3aca57Sjsing 	if (ret != 0)
3364f3aca57Sjsing 		return (0);
3374f3aca57Sjsing 
3384f3aca57Sjsing 	if ((test_config.arg != NULL || ot->wantarg != NULL) &&
3394f3aca57Sjsing 	    (test_config.arg == NULL || ot->wantarg == NULL ||
3404f3aca57Sjsing 	     strcmp(test_config.arg, ot->wantarg) != 0)) {
3414f3aca57Sjsing 		fprintf(stderr, "FAIL: test %i got arg '%s', want '%s'\n",
3424f3aca57Sjsing 		    test_no, test_config.arg, ot->wantarg);
3434f3aca57Sjsing 		return (1);
3444f3aca57Sjsing 	}
3454f3aca57Sjsing 	if (test_config.flag != ot->wantflag) {
3464f3aca57Sjsing 		fprintf(stderr, "FAIL: test %i got flag %i, want %i\n",
3474f3aca57Sjsing 		    test_no, test_config.flag, ot->wantflag);
3484f3aca57Sjsing 		return (1);
3494f3aca57Sjsing 	}
3504f3aca57Sjsing 	if (ot->type == OPTIONS_TEST_UNNAMED &&
3514f3aca57Sjsing 	    (unnamed != NULL || ot->unnamed != NULL) &&
3524f3aca57Sjsing 	    (unnamed == NULL || ot->unnamed == NULL ||
3534f3aca57Sjsing 	     strcmp(unnamed, ot->unnamed) != 0)) {
3544f3aca57Sjsing 		fprintf(stderr, "FAIL: test %i got unnamed '%s', want '%s'\n",
3554f3aca57Sjsing 		    test_no, unnamed, ot->unnamed);
3564f3aca57Sjsing 		return (1);
3574f3aca57Sjsing 	}
35893d5edbbSjsing 	if (ot->type == OPTIONS_TEST_ARGSUSED && used != ot->used) {
35993d5edbbSjsing 		fprintf(stderr, "FAIL: test %i got used %i, want %i\n",
36093d5edbbSjsing 		    test_no, used, ot->used);
36193d5edbbSjsing 		return (1);
36293d5edbbSjsing 	}
3634f3aca57Sjsing 
3644f3aca57Sjsing 	return (0);
3654f3aca57Sjsing }
3664f3aca57Sjsing 
3674f3aca57Sjsing int
main(int argc,char ** argv)3684f3aca57Sjsing main(int argc, char **argv)
3694f3aca57Sjsing {
3704f3aca57Sjsing 	int failed = 0;
3714f3aca57Sjsing 	size_t i;
3724f3aca57Sjsing 
3735c32ba37Sdoug 	for (i = 0; i < N_OPTIONS_TESTS; i++) {
374*e4ba687dSkettenis 		printf("Test %zu%s\n", (i + 1), options_tests[i].want == 0 ?
3755c32ba37Sdoug 		    "" : " is expected to complain");
3765736f113Sjsing 		failed += do_options_test(i + 1, &options_tests[i]);
3775c32ba37Sdoug 	}
3784f3aca57Sjsing 
3794f3aca57Sjsing 	return (failed);
3804f3aca57Sjsing }
381