Provide initial regress tests for the complex option parsing that is needed
authorjsing <jsing@openbsd.org>
Sun, 28 Dec 2014 14:01:33 +0000 (14:01 +0000)
committerjsing <jsing@openbsd.org>
Sun, 28 Dec 2014 14:01:33 +0000 (14:01 +0000)
for openssl(1), which is also variable in behaviour between applications
(and currently inconsistent).

regress/usr.bin/openssl/Makefile
regress/usr.bin/openssl/options/Makefile [new file with mode: 0644]
regress/usr.bin/openssl/options/optionstest.c [new file with mode: 0644]

index 800e2fd..994e195 100644 (file)
@@ -1,4 +1,6 @@
-#      $OpenBSD: Makefile,v 1.1 2014/08/26 17:50:07 jsing Exp $
+#      $OpenBSD: Makefile,v 1.2 2014/12/28 14:01:33 jsing Exp $
+
+SUBDIR= options
 
 CLEANFILES+= testdsa.key testdsa.pem rsakey.pem rsacert.pem dsa512.pem
 
diff --git a/regress/usr.bin/openssl/options/Makefile b/regress/usr.bin/openssl/options/Makefile
new file mode 100644 (file)
index 0000000..ba3857a
--- /dev/null
@@ -0,0 +1,17 @@
+#      $OpenBSD: Makefile,v 1.1 2014/12/28 14:01:33 jsing Exp $
+
+PROG=  optionstest
+SRCS=  optionstest.c
+
+LDADD= -lcrypto -lssl
+DPADD= ${LIBCRYPTO} ${LIBSSL}
+
+OSSLSRC= ${.CURDIR}/../../../../usr.bin/openssl/
+CFLAGS+= -I${OSSLSRC}
+
+.PATH: ${OSSLSRC}
+SRCS+= apps.c
+
+CFLAGS+= -Werror
+
+.include <bsd.regress.mk>
diff --git a/regress/usr.bin/openssl/options/optionstest.c b/regress/usr.bin/openssl/options/optionstest.c
new file mode 100644 (file)
index 0000000..8df208d
--- /dev/null
@@ -0,0 +1,219 @@
+/*     $OpenBSD: optionstest.c,v 1.1 2014/12/28 14:01:33 jsing Exp $   */
+/*
+ * Copyright (c) 2014 Joel Sing <jsing@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <openssl/bio.h>
+#include <openssl/conf.h>
+
+#include "apps.h"
+
+/* Needed to keep apps.c happy... */
+BIO *bio_err;
+CONF *config;
+
+static int argfunc(struct option *opt, char *arg);
+
+static struct {
+       char *arg;
+       int flag;
+} test_config;
+
+static struct option test_options[] = {
+       {
+               .name = "arg",
+               .type = OPTION_ARG,
+               .opt.arg = &test_config.arg,
+       },
+       {
+               .name = "argfunc",
+               .type = OPTION_ARG_FUNC,
+               .func = argfunc,
+       },
+       {
+               .name = "flag",
+               .type = OPTION_FLAG,
+               .opt.flag = &test_config.flag,
+       },
+       { NULL },
+};
+
+char *args1[] = { "opts" };
+char *args2[] = { "opts", "-arg", "arg", "-flag" };
+char *args3[] = { "opts", "-arg", "arg", "-flag", "unnamed" };
+char *args4[] = { "opts", "-arg", "arg", "unnamed", "-flag" };
+char *args5[] = { "opts", "unnamed1", "-arg", "arg", "-flag", "unnamed2" };
+char *args6[] = { "opts", "-argfunc", "arg", "-flag" };
+
+struct options_test {
+       int argc;
+       char **argv;
+       enum {
+               OPTIONS_TEST_NONE,
+               OPTIONS_TEST_UNNAMED,
+       } type;
+       char *unnamed;
+       int used;
+       int want;
+       char *wantarg;
+       int wantflag;
+};
+
+struct options_test options_tests[] = {
+       {
+               /* No arguments (only program name). */
+               .argc = 1,
+               .argv = args1,
+               .type = OPTIONS_TEST_NONE,
+               .want = 0,
+               .wantarg = NULL,
+               .wantflag = 0,
+       },
+       {
+               /* Named arguments (unnamed not permitted). */
+               .argc = 4,
+               .argv = args2,
+               .type = OPTIONS_TEST_NONE,
+               .want = 0,
+               .wantarg = "arg",
+               .wantflag = 1,
+       },
+       {
+               /* Named arguments (unnamed permitted). */
+               .argc = 4,
+               .argv = args2,
+               .type = OPTIONS_TEST_UNNAMED,
+               .unnamed = NULL,
+               .want = 0,
+               .wantarg = "arg",
+               .wantflag = 1,
+       },
+       {
+               /* Named and single unnamed (unnamed not permitted). */
+               .argc = 5,
+               .argv = args3,
+               .type = OPTIONS_TEST_NONE,
+               .want = 1,
+       },
+       {
+               /* Named and single unnamed (unnamed permitted). */
+               .argc = 5,
+               .argv = args3,
+               .type = OPTIONS_TEST_UNNAMED,
+               .unnamed = "unnamed",
+               .want = 0,
+               .wantarg = "arg",
+               .wantflag = 1,
+       },
+       {
+               /* Named and single unnamed (different sequence). */
+               .argc = 5,
+               .argv = args4,
+               .type = OPTIONS_TEST_UNNAMED,
+               .unnamed = "unnamed",
+               .want = 0,
+               .wantarg = "arg",
+               .wantflag = 1,
+       },
+       {
+               /* Multiple unnamed arguments (retain last). */
+               .argc = 6,
+               .argv = args5,
+               .type = OPTIONS_TEST_UNNAMED,
+               .unnamed = "unnamed2",
+               .want = 0,
+               .wantarg = "arg",
+               .wantflag = 1,
+       },
+       {
+               /* Function. */
+               .argc = 4,
+               .argv = args6,
+               .type = OPTIONS_TEST_NONE,
+               .want = 0,
+               .wantarg = "arg",
+               .wantflag = 1,
+       },
+};
+
+#define N_OPTIONS_TESTS \
+    (sizeof(options_tests) / sizeof(*options_tests))
+
+int
+argfunc(struct option *opt, char *arg)
+{
+       test_config.arg = arg;
+       return (0);
+}
+
+static int
+do_options_test(int test_no, struct options_test *ot)
+{
+       char *unnamed = NULL;
+       char **arg = NULL;
+       int ret;
+
+       if (ot->type == OPTIONS_TEST_UNNAMED)
+               arg = &unnamed;
+
+       memset(&test_config, 0, sizeof(test_config));
+       ret = options_parse(ot->argc, ot->argv, test_options, arg);
+       if (ret != ot->want) {
+               fprintf(stderr, "FAIL: test %i options_parse() returned %i, "
+                   "want %i\n", test_no, ret, ot->want);
+               return (1);
+       }
+       if (ret != 0)
+               return (0);
+
+       if ((test_config.arg != NULL || ot->wantarg != NULL) &&
+           (test_config.arg == NULL || ot->wantarg == NULL ||
+            strcmp(test_config.arg, ot->wantarg) != 0)) {
+               fprintf(stderr, "FAIL: test %i got arg '%s', want '%s'\n",
+                   test_no, test_config.arg, ot->wantarg);
+               return (1);
+       }
+       if (test_config.flag != ot->wantflag) {
+               fprintf(stderr, "FAIL: test %i got flag %i, want %i\n",
+                   test_no, test_config.flag, ot->wantflag);
+               return (1);
+       }
+       if (ot->type == OPTIONS_TEST_UNNAMED &&
+           (unnamed != NULL || ot->unnamed != NULL) &&
+           (unnamed == NULL || ot->unnamed == NULL ||
+            strcmp(unnamed, ot->unnamed) != 0)) {
+               fprintf(stderr, "FAIL: test %i got unnamed '%s', want '%s'\n",
+                   test_no, unnamed, ot->unnamed);
+               return (1);
+       }
+
+       return (0);
+}
+
+int
+main(int argc, char **argv)
+{
+       int failed = 0;
+       size_t i;
+
+       for (i = 0; i < N_OPTIONS_TESTS; i++)
+               failed += do_options_test(i, &options_tests[i]);
+
+       return (failed);
+}