1 dnl Copyright © 2021-2023 Nick Bowler
3 dnl License WTFPL2: Do What The Fuck You Want To Public License, version 2.
4 dnl This is free software: you are free to do what the fuck you want to.
5 dnl There is NO WARRANTY, to the extent permitted by law.
7 AT_BANNER([Script tests])
9 AT_SETUP([bake-config.awk])
10 AT_KEYWORDS([bake-config awk script scripts])
14 /* #undef HAVE_STUFF */
15 #define HAVE_OTHER_STUFF 1
16 /* #undef HAVE_CRAZY_STUFF */
22 #elif HAVE_CRAZY_STUFF
24 #elif HAVE_OTHER_STUFF
29 AT_CHECK([$AWK -f "$srcdir/scripts/bake-config.awk" cfg.h lib.h], [0],
30 [[#if 0 /* HAVE_STUFF */
32 #elif 0 /* HAVE_CRAZY_STUFF */
33 # define foo world /* hello */
34 #elif 1 /* HAVE_OTHER_STUFF */
41 m4_define([TEST_GEN_OPTIONS],
42 [AT_KEYWORDS([gen-options awk script scripts])dnl
43 AT_DATA([m4_default([$2], [options.def])], [$1])
44 AT_CHECK([$AWK -f "$srcdir/scripts/gen-options.awk" dnl
45 <m4_default([$2], [options.def]) >options.h])])
47 m4_define([TEST_GEN_OPTIONS_SAMPLE],
50 --option-with-flagval (&x, 5)
53 --option-with-optional-arg[=OPTIONAL]
56 -a, --option-with-sopt
58 -b, --option-with-sopt-and-arg=SOPTARG
59 -c, --option-with-sopt-and-optional-arg[=SOPTOPTIONAL]
60 --option-with-arg-and-val=ARGVAL (42)
61 --option-with-arg-and-flagval=ARGFLAGVAL (&a[1], 'x')
62 --option-with-optional-arg-and-val[=OPTIONALARGVAL] (54)
63 --option-with-optional-arg-and-flagval[=OPTIONALFLAGVAL] (0, 0)
66 that has a line randomly indented
75 AT_SETUP([gen-options.awk])
76 TEST_GEN_OPTIONS([TEST_GEN_OPTIONS_SAMPLE])
79 [[struct option { const char *name; int has_arg; int *flag; int val; };
85 [[#include "context.h"
88 static const char sopts[] = SOPT_STRING;
89 static const struct option opts[] = { LOPTS_INITIALIZER, {0} };
96 AT_CHECK([$CC -o test0$EXEEXT test0.c && ./test0$EXEEXT], [0], [], [ignore])
98 # test 1: long option names and help text
106 static const struct option opts[] = { LOPTS_INITIALIZER };
112 for (i = 0; i < sizeof opts / sizeof opts[0]; i++) {
113 struct lopt_help help = { "INVALID", "INVALID" };
115 if (!lopt_get_help(&opts[i], &help))
118 printf("--%s", opts[i].name);
120 printf("=%s", help.arg);
121 printf("\n%s", help.desc);
130 AT_DATA([lopthelp.awk],
135 if (sub(/\@:>@$/, "", $1))
136 sub(/\@<:@/, "", $1);
142 { sub(/^[ \t]*/, ""); }
146 $AWK -f lopthelp.awk options.def >expout
147 AT_CHECK([$CC -o test1$EXEEXT test1.c && ./test1$EXEEXT],
148 [0], [expout], [ignore])
150 # test 2: short option string
160 struct option lopts[] = {LOPTS_INITIALIZER};
163 for (i = 0; i < sizeof SOPT_STRING - 1; i++) {
164 if (SOPT_STRING[i] != ':') {
165 for (j = 0; j < sizeof lopts / sizeof lopts[0]; j++) {
166 if (lopts[j].val == SOPT_STRING[i]) {
167 printf("--%s ", lopts[j].name);
172 putchar(SOPT_STRING[i]);
173 if (SOPT_STRING[i+1] != ':')
180 AT_DATA([soptstr.awk],
185 sopt = substr($1, 2, 1);
186 arg = sub(/\@:>@$/, "", $2);
187 arg += sub(/\@<:@?=.*$/, "", $2);
189 print $2 " " sopt substr("::", 1, arg);
193 $AWK -f soptstr.awk options.def >expout
194 AT_CHECK([$CC -o test2$EXEEXT test2.c && ./test2$EXEEXT],
195 [0], [expout], [ignore])
199 AT_SETUP([gen-options.awk xgettext annotation])
200 TEST_GEN_OPTIONS([TEST_GEN_OPTIONS_SAMPLE])
202 # Check that all help strings are translatable
203 AT_DATA([messages.awk],
204 [[BEGIN { lines = -1; }
215 if (sub(/\@<:@?=.*/, "", $1)) {
216 arg = substr(tmp, index(tmp, "=")+1);
217 sub(/\@:>@$/, "", arg);
221 ctxt=("msgctxt \"" $1 "\" msgid");
224 print ctxt, ("\"" arg "\"");
228 { sub(/^[ \t]*/, ""); }
230 gsub(/"/, "\\\"", $0);
238 for (i = 0; i < lines; i++) {
239 nl = (i+1 < lines ? "\\n" : "");
240 printf(" \"%s%s\"", help[i], nl);
249 dnl Antique versions of xgettext which predate the pgettext/msgctx feature
250 dnl will produce an output po file with no msgctx lines. So try to spot
251 dnl that and skip the test with such versions.
252 AT_CHECK([xgettext --keyword=PN_:1c,2 options.h
253 test -f messages.po || exit 77
254 grep msgid messages.po >/dev/null &&
255 { grep msgctx messages.po >/dev/null || exit 77; }])
257 $AWK -f messages.awk options.def | LC_ALL=C sort >expout
258 AT_CHECK([sed -n '/^msgctxt/{
269 }' messages.po | LC_ALL=C sort], [0], [expout])
273 AT_SETUP([gen-options.awk packed format])
275 AT_DATA([test.c], [[#include <stdio.h>
276 struct option { const char *name; int has_arg; int *flag; int val; };
280 static unsigned opts[] = { LOPTS_PACKED_INITIALIZER };
288 #elif LOPT_PACK_BITS <= 8
290 #elif LOPT_PACK_BITS <= 16
292 #elif LOPT_PACK_BITS <= 32
299 for (i = 0; i < sizeof opts / sizeof opts[0]; i++) {
302 LOPT_UNPACK(o, opts[i]);
303 printf("--%s, %d, ", o.name, o.has_arg);
304 if (o.val > UCHAR_MAX)
305 printf("%d\n", o.val - UCHAR_MAX - 1);
307 printf("'%c'\n", o.val);
313 TEST_GEN_OPTIONS([[--single-option
315 AT_CHECK([$CC -o single$EXEEXT test.c && ./single$EXEEXT], [0],
317 --single-option, 0, 0
320 TEST_GEN_OPTIONS([[-a, --the-first-option
321 -b, --the-second-option=ARG
322 -c, --the-third-option[=ARG]
323 -d, --the-fourth-option
325 AT_CHECK([$CC -o 16bit$EXEEXT test.c && ./16bit$EXEEXT], [0],
327 --the-first-option, 0, 'a'
328 --the-second-option, 1, 'b'
329 --the-third-option, 2, 'c'
330 --the-fourth-option, 0, 'd'
335 AT_SETUP([gen-strtab.awk])
336 AT_KEYWORDS([gen-strtab awk script scripts])
361 AT_CHECK([$AWK -f "$srcdir/scripts/gen-strtab.awk" <test.def >test.h])
363 sed -n 's/^[[&]]\([[^ ]]*\).*/\1/p' test.def >identifiers
365 # test 0: sanity test
374 while read id; do AS_ECHO([' printf("%s\n---\n", strtab+'"$id"');']); done
375 AS_ECHO([' return 0;'])
377 } <identifiers >test0.c
379 AT_CHECK([$CC -o test0$EXEEXT test0.c && ./test0$EXEEXT], [0], [---
414 AT_SETUP([gen-strtab.awk @nozero option])
415 AT_KEYWORDS([gen-strtab awk script scripts])
420 AT_CHECK([$AWK -f "$srcdir/scripts/gen-strtab.awk" <test0.def >test0.h])
426 AT_CHECK([$AWK -f "$srcdir/scripts/gen-strtab.awk" <test1.def >test1.h])
431 int main(void) { printf("%d %s\n", hello, strtab+hello); return 0; }
433 AT_CHECK([$CC -DHEADER='"test0.h"' -o test0$EXEEXT test.c && ./test0$EXEEXT],
436 AT_CHECK([$CC -DHEADER='"test1.h"' -o test1$EXEEXT test.c && ./test1$EXEEXT],
442 AT_SETUP([gen-strtab.awk @macro option])
443 AT_KEYWORDS([gen-strtab awk script scripts])
451 AT_CHECK([$AWK -f "$srcdir/scripts/gen-strtab.awk" <test0.def >test0.h])
455 extern const char strtab[];
460 static const char mystrtab[] = STRTAB_INITIALIZER;
461 printf("%s\n%s\n%s\n", mystrtab+foo, mystrtab+bar, mystrtab+baz);
465 AT_CHECK([$CC -o test0$EXEEXT test0.c && ./test0$EXEEXT], [0],
473 AT_SETUP([gen-strtab.awk l10n options])
474 AT_KEYWORDS([gen-strtab awk script scripts])
476 AT_DATA([l10n.sed], dnl (
478 s/.*N_(\([^)]*\)).*/\1/p
486 AT_CHECK([$AWK -f "$srcdir/scripts/gen-strtab.awk" <test0.def >test0.h])
487 AT_CHECK([sed -n -f l10n.sed test0.h | LC_ALL=C sort], [0],
498 AT_CHECK([$AWK -f "$srcdir/scripts/gen-strtab.awk" <test1.def >test1.h])
499 AT_CHECK([sed -n -f l10n.sed test1.h], [0],
509 printf("%s %s %s\n", strtab+a, strtab+b, strtab+c);
514 AT_CHECK([$CC -DHEADER='"test0.h"' -o test0$EXEEXT test.c && ./test0$EXEEXT],
515 [0], [[hello world world goodbye
518 AT_CHECK([$CC -DHEADER='"test1.h"' -o test1$EXEEXT test.c && ./test1$EXEEXT],
519 [0], [[hello world world goodbye
525 AT_SETUP([gen-tree.awk])
526 AT_KEYWORDS([gen-tree awk script scripts])
553 AT_CHECK([$AWK -f "$srcdir/scripts/gen-tree.awk" <tree.def >tree.h])
559 struct tree { unsigned id, subtree; };
561 static const struct tree tree0[] = {
564 static const struct tree tree1[] = {
568 void print_subtree(const struct tree *root, unsigned offset, int depth)
570 const struct tree *node;
572 for (node = &root[offset]; node->id; node++) {
573 printf("%*s%s", 2*depth, "", &tree_strtab[node->id]);
575 printf(", %s_OFFSET\n", &tree_strtab[node->id]);
576 print_subtree(root, node->subtree, depth+1);
586 print_subtree(tree0, 0, 1);
588 print_subtree(tree1, 0, 1);
592 sed '/^#/d' tree.def >expout
593 AT_CHECK([$CC -o test0$EXEEXT test0.c && ./test0$EXEEXT], [0], [expout])
597 # Test the gen-tree features that avoid creating string labels for nodes.
598 AT_SETUP([gen-tree.awk @nostrtab option])
599 AT_KEYWORDS([gen-tree awk script scripts])
611 AT_CHECK([$AWK -f "$srcdir/scripts/gen-tree.awk" <tree.def >tree.h])
614 [[float tree_strtab = 0;
623 static struct { int num, offset; } root[] = { ROOT_INITIALIZER };
628 for (i = 0; i < sizeof root / sizeof root[0]; i++) {
629 printf("%d, %d\n", root[i].num, root[i].offset);
635 AT_CHECK([$CC -o test0$EXEEXT test0.c && ./test0$EXEEXT], [0],
654 AT_CHECK([$AWK -f "$srcdir/scripts/gen-tree.awk" <flat.def >flat.h])
656 sed -e 's/tree\.h/flat.h/' -e 's/ROOT/FLAT/' test0.c >test1.c
657 AT_CHECK([$CC -o test1$EXEEXT test1.c && ./test1$EXEEXT], [0],
667 AT_KEYWORDS([join awk script scripts])
669 JOIN="$AWK -f $srcdir/scripts/join.awk --"
696 AT_CHECK([$JOIN a b], [0],
707 AT_CHECK([$JOIN -v1 a b], [0],
715 AT_CHECK([$JOIN -v2 a b], [0],
722 AT_CHECK([$JOIN -v1 -v2 a b], [0],
734 AT_CHECK([$JOIN -a1 a b], [0],
750 AT_CHECK([$JOIN -a2 a b], [0],
765 AT_CHECK([$JOIN -a1 -a2 a b], [0],
785 AT_CHECK([$JOIN b a], [0],
796 AT_CHECK([$JOIN -v1 b a], [0],
803 AT_CHECK([$JOIN -v2 b a], [0],
811 AT_CHECK([$JOIN -v1 -v2 b a], [0],
823 AT_CHECK([$JOIN -a1 b a], [0],
838 AT_CHECK([$JOIN -a2 b a], [0],
854 AT_CHECK([$JOIN -a1 -a2 b a], [0],
874 AT_CHECK([echo wat | $JOIN -v1 - /dev/null], [0],
880 m4_divert_push([PREPARE_TESTS])dnl
882 $PERL -e 'my $x = 42; exit $x;'; test $? = 42 || exit 77
883 $PERL "$srcdir/scripts/fix-ltdl.pl" "$@"
886 $PERL -e 'my $x = 42; exit $x;'; test $? = 42 || exit 77
887 $PERL "$srcdir/scripts/fix-gnulib.pl" "$@"
894 "/^## begin gnulib module $arg/,/^## end gnulib module $arg/p" \
895 "$srcdir/tests/data/gnulib.mk"
898 m4_divert_pop([PREPARE_TESTS])
900 AT_SETUP([fix-gnulib.pl SED_HEADER variables])
901 AT_KEYWORDS([fix-gnulib perl script scripts])
903 test_gnulib_mk gen-header >test.mk.in
904 AT_CHECK([grep SED_HEADER test.mk.in >expout || exit 99])
905 AT_CHECK([test_fix_gnulib -i test.mk.in -o test.mk || exit
906 grep SED_HEADER test.mk], [0], [expout])
910 AT_SETUP([fix-gnulib.pl %reldir% substitution])
911 AT_KEYWORDS([fix-gnulib perl script scripts])
913 test_gnulib_mk sys_types >test.mk.in
914 AT_CHECK([grep '%reldir%' test.mk.in >/dev/null || exit 99])
916 sed -n <test.mk.in >expout '
920 /^## begin gnulib/,/^## end gnulib/!b
925 s|(srcdir)|(top_srcdir)|
927 s|BUILT_SOURCES|gnulib_core_headers|
935 AT_CHECK([test_fix_gnulib -i test.mk.in -o test.mk || exit
936 sed -n -e '/^## begin gnulib/,/^## end gnulib/p' \
937 -e '/CLEANFILES/p' test.mk],
942 AT_SETUP([fix-gnulib.pl warning removal])
943 AT_KEYWORDS([fix-gnulib perl script scripts])
945 AT_DATA([test.mk.in], [[
947 noinst_LTLIBRARIES += libgnu.la
948 libgnu_la_CFLAGS = $(AM_CFLAGS) $(GL_CFLAG_GNULIB_WARNINGS)
949 noinst_LIBRARIES += libgnu.a
950 libgnu_a_CFLAGS = $(AM_CFLAGS) $(GL_CFLAG_GNULIB_WARNINGS)
953 AT_CHECK([test_fix_gnulib -i test.mk.in -o test.mk || exit
954 sed -n '/^## test begin/,/^## test end/p' test.mk], [0], [## test begin
955 EXTRA_LTLIBRARIES += libgnu.la
956 EXTRA_LIBRARIES += libgnu.a
962 AT_SETUP([fix-gnulib.pl header directory creation])
963 AT_KEYWORDS([fix-gnulib perl script scripts])
965 AT_DATA([extract.sed],
981 test_gnulib_mk alloca-opt sys_types stddef >test.mk.in
982 AT_CHECK([test_fix_gnulib -i test.mk.in -o test.mk || exit
983 sed -n -f extract.sed test.mk], [0],
985 $(AM_V_GEN)$(MKDIR_P) lib
988 $(AM_V_GEN)$(MKDIR_P) lib/sys
991 $(AM_V_GEN)$(MKDIR_P) lib
997 dnl TEST_FIND_AUTOMAKE_VER([to-check], [test-action])
999 dnl For each whitespace-separated version token in to-check, check if we can
1000 dnl run the programs automake-VER and aclocal-VER. The special token 'default'
1001 dnl also checks the unversioned automake and aclocal (or, if set in the
1002 dnl environment, $AUTOMAKE and $ACLOCAL).
1004 dnl Then test-action is expanded such that shell variables $ac and $am refer to
1005 dnl the aclocal and automake programs, and $amver is the actual version
1006 dnl reported by --version. The action should do nothing if the version is
1007 dnl acceptable, or "continue" if the version is unacceptable.
1009 dnl If an acceptable version is found, the AUTOMAKE and ACLOCAL environment
1010 dnl variables are set accordingly. Otherwise, the test group is skipped.
1011 m4_define([TEST_FIND_AUTOMAKE],
1015 [default], [ac=${ACLOCAL-aclocal} am=${AUTOMAKE-automake}],
1016 [ac=aclocal-$am; am=automake-$am])
1017 amver=`$am --version | sed -n '1s/.* //p'`
1018 acver=`$ac --version | sed -n '1s/.* //p'`
1019 set x $amver $acver; shift; test x"$[]#" = x"2" || continue
1020 test x"$amver" = x"$acver" || continue
1024 AT_CHECK([$have_am || exit 77])
1025 AUTOMAKE=$am; export AUTOMAKE
1026 ACLOCAL=$ac; export ACLOCAL
1027 AT_CHECK([$ACLOCAL --version && $AUTOMAKE --version], [0], [stdout])
1030 m4_define([TEST_LTDL_LIBOBJ_MANGLING],
1031 [TEST_CONFIGURE_AC([[AM_INIT_AUTOMAKE([foreign subdir-objects])
1034 AC_SUBST([ltdl_LTLIBOBJS], [libltdl/test.lo])
1035 AC_CONFIG_FILES([Makefile])
1039 AT_DATA([ltdl.mk.in], [[
1040 AM_CPPFLAGS += -DSTRING=\"helloworld\"
1042 noinst_LTLIBRARIES = libltdl/libltdl.la
1043 libltdl_libltdl_la_SOURCES = libltdl/ltdl.c
1044 libltdl_libltdl_la_LIBADD = $(ltdl_LTLIBOBJS)
1045 libltdl_libltdl_la_DEPENDENCIES = $(ltdl_LTLIBOBJS)
1047 EXTRA_DIST += libltdl/test.c
1049 AT_DATA([Makefile.am], [[AM_CPPFLAGS =
1050 include $(top_srcdir)/ltdl.mk
1051 AM_LIBTOOLFLAGS = --quiet
1054 test_LDADD = libltdl/libltdl.la
1055 all-local: ; @printf '%s\n' $(AM_CPPFLAGS)
1057 AT_DATA([libltdl/test.c], [[#include <stdio.h>
1058 int foo(void) { printf("%s\n", STRING); return 0; }
1060 AT_DATA([libltdl/ltdl.c], [[int foo(void); int main(void) { return foo(); }
1063 AT_CHECK([test_fix_ltdl -i ltdl.mk.in -o ltdl.mk])
1064 libtoolize; TEST_AUTORECONF
1065 TEST_CONFIGURE([--disable-shared])
1066 AT_CHECK([make -s && ./test], [0], [
1070 AT_SETUP([fix-ltdl.pl LIBOBJ mangling (<automake-1.16)])
1071 AT_KEYWORDS([fix-ltdl perl script scripts])
1073 TEST_FIND_AUTOMAKE([default 1.10 1.11 1.12 1.13 1.14 1.15],
1074 [AS_VERSION_COMPARE(["$amver"], [1.16], [], [continue], [continue])])
1075 TEST_LTDL_LIBOBJ_MANGLING
1079 AT_SETUP([fix-ltdl.pl LIBOBJ mangling (>=automake-1.16)])
1080 AT_KEYWORDS([fix-ltdl perl script scripts])
1082 TEST_FIND_AUTOMAKE([default 1.16 1.17 1.18 1.19],
1083 [AS_VERSION_COMPARE(["$amver"], [1.16], [continue])])
1084 TEST_LTDL_LIBOBJ_MANGLING