]> git.draconx.ca Git - cdecl99.git/commitdiff
tests: Add sanity check for truncated output.
authorNick Bowler <nbowler@draconx.ca>
Wed, 25 Oct 2023 01:21:49 +0000 (21:21 -0400)
committerNick Bowler <nbowler@draconx.ca>
Thu, 26 Oct 2023 01:25:32 +0000 (21:25 -0400)
Nothing really verifies that output truncation of the cdecl_declare
and cdecl_explain functions actually works as expected.

Add a new test program and a couple invocations to at least cover
the basic functionality.

Makefile.am
t/.gitignore
t/crossparse.c
t/rendertest.c [new file with mode: 0644]
t/testlib.c
tests/internal.at

index e7cfb6bc232c1b84b0911a965f38a13df6291dff..4af8e9a01c3febd3fe7f6f790a6ba260e921f308 100644 (file)
@@ -100,6 +100,10 @@ t_rng_test_LDADD = $(TEST_LIBS)
 $(t_rng_test_OBJECTS): $(gnulib_headers)
 EXTRA_DIST += t/xos256p.c
 
+check_PROGRAMS += t/rendertest
+t_rendertest_LDADD = $(TEST_LIBS)
+$(t_rendertest_OBJECTS): $(gnulib_headers)
+
 src/error.lo: src/errmsg.h
 src/keywords.lo: src/parse.h
 src/output.lo: src/parse.h src/specstr.h
index 9da329431ffcbc08f5982e444708ee246b6c50ce..f6bb37d1ebd4ee72a8dc6860da4d4a1beaf65d9a 100644 (file)
@@ -2,5 +2,6 @@
 /crossparse
 /normalize
 /randomdecl
+/rendertest
 /rng-test
 /typegen.h
index 520b08a6009fee64d279b602a8749469202c9908..630e02e05c0417e6b4cca4b224adef56cd3b826a 100644 (file)
@@ -45,8 +45,6 @@ static void print_usage(FILE *f)
 
 static void print_help(void)
 {
-       const struct option *opt;
-
        print_usage(stdout);
        puts("Test that libcdecl can parse its own output.\n");
        test_print_options(lopts);
diff --git a/t/rendertest.c b/t/rendertest.c
new file mode 100644 (file)
index 0000000..93574e2
--- /dev/null
@@ -0,0 +1,142 @@
+/*
+ * Helper to verify the output rendering routines.
+ * Copyright © 2023 Nick Bowler
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <getopt.h>
+#include <assert.h>
+
+#include <cdecl.h>
+#include "test.h"
+
+#define PROGNAME "outbuf"
+static const char *progname = PROGNAME;
+static const char sopts[] = "n:ECVH";
+static const struct option lopts[] = {
+       { "count",   1, NULL, 'n' },
+       { "cdecl",   0, NULL, 'C' },
+       { "english", 0, NULL, 'E' },
+       { "version", 0, NULL, 'V' },
+       { "help",    0, NULL, 'H' },
+       { 0 }
+};
+
+static void print_usage(FILE *f)
+{
+       fprintf(f, "Usage: %s [options]\n", progname);
+}
+
+static void print_help(void)
+{
+       print_usage(stdout);
+       puts("Helper application to test output rendering.\n");
+       test_print_options(lopts);
+}
+
+enum { MODE_CDECL, MODE_ENGLISH };
+
+static int do_test(char *line, unsigned long n, int mode)
+{
+       struct cdecl *decl;
+       size_t rc;
+
+       if (mode)
+               decl = cdecl_parse_english(line);
+       else
+               decl = cdecl_parse_decl(line);
+
+       if (!decl) {
+               fprintf(stderr, "%s: %s\n", progname, cdecl_get_error()->str);
+               fprintf(stderr, "%s: the failed input was: %s\n",
+                               progname, line);
+               return -1;
+       }
+
+       memset(line, '\a', n+1);
+       if (mode)
+               rc = cdecl_explain(line, n, decl);
+       else
+               rc = cdecl_declare(line, n, decl);
+
+       if (n && ( rc < n ? line[rc] : line[n-1] ) != '\0') {
+               fprintf(stderr, "%s: output is not 0-terminated\n", progname);
+               return -1;
+       }
+
+       if (line[n] != '\a') {
+               fprintf(stderr, "%s: output overflow\n", progname);
+               return -1;
+       }
+
+       printf("%lu %.*s\n", (unsigned long)rc, -(n>0), line);
+       cdecl_free(decl);
+       return 0;
+}
+
+int main(int argc, char **argv)
+{
+       int opt, mode = MODE_CDECL, ret = EXIT_SUCCESS;
+       unsigned long n = 60;
+       char *line;
+       size_t sz;
+
+       if (argc > 0)
+               progname = argv[0];
+
+       while ((opt = getopt_long(argc, argv, sopts, lopts, NULL)) != -1) {
+               switch (opt) {
+               case 'C':
+                       mode = MODE_CDECL;
+                       break;
+               case 'E':
+                       mode = MODE_ENGLISH;
+                       break;
+               case 'n':
+                       if (!strict_strtoul(&n, optarg, 0) || n > (size_t)-2) {
+                               fprintf(stderr, "%s: invalid count: %s\n",
+                                       progname, optarg);
+                               return EXIT_FAILURE;
+                       }
+                       break;
+               case 'V':
+                       test_print_version(PROGNAME);
+                       return EXIT_SUCCESS;
+               case 'H':
+                       print_help();
+                       return EXIT_SUCCESS;
+               default:
+                       print_usage(stderr);
+                       return EXIT_FAILURE;
+               }
+       }
+
+       line = malloc_nofail((sz = n+1));
+       while (getline(&line, &sz, stdin) >= 0) {
+               char *c = strchr(line, '\n');
+               if (c)
+                       *c = '\0';
+
+               if (do_test(line, n, mode) < 0)
+                       ret = EXIT_FAILURE;
+       }
+
+       free(line);
+       return ret;
+}
index fdb9d3b5f83dd10e419a368400ec90d01d403022..8edb423bb5004c776140ce096d5c08b5a475a7b4 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  Miscellaneous functions used by the cdecl99 test suite.
- *  Copyright © 2011-2012, 2021-2022 Nick Bowler
+ *  Copyright © 2011-2012, 2021-2023 Nick Bowler
  *
  *  This program is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -92,7 +92,7 @@ bool strict_strtoul(unsigned long *val, const char *str, int base)
 void test_print_version(const char *program)
 {
        printf("%s (%s) %s\n", program, PACKAGE_NAME, PACKAGE_VERSION);
-       puts("Copyright (C) 2022 Nick Bowler.");
+       puts("Copyright (C) 2023 Nick Bowler.");
        puts("License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>.");
        puts("This is free software: you are free to change and redistribute it.");
        puts("There is NO WARRANTY, to the extent permitted by law.");
index 9012c156d1d21314a2dafa8dc4e98474d503e95d..1ae6f994a78829ae287639325b1eecdade3a0cf5 100644 (file)
@@ -73,3 +73,41 @@ AT_CLEANUP
 
 TEST_TAP_SIMPLE([cdecl__err sanity], [cdeclerr],
   [TEST_NEED_PROGRAM([cdeclerr])], [libcdecl internal])
+
+AT_SETUP([cdecl_declare truncation])
+
+AT_DATA([input],
+[[int hello_world
+int x[1234567890]
+]])
+
+AT_CHECK([rendertest -n 0 <input], [0],
+[[15 @&t@
+17 @&t@
+]])
+
+AT_CHECK([rendertest -n 10 <input], [0],
+[[15 int hello
+17 int x@<:@123
+]])
+
+AT_CLEANUP
+
+AT_SETUP([cdecl_explain truncation])
+
+AT_DATA([input],
+[[declare x as int
+type array 123456789 of int
+]])
+
+AT_CHECK([rendertest --english -n 0 <input], [0],
+[[16 @&t@
+27 @&t@
+]])
+
+AT_CHECK([rendertest --english -n 15 <input], [0],
+[[16 declare x as i
+27 type array 123
+]])
+
+AT_CLEANUP