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])
359 &k with nontrivial whitespace
362 AT_CHECK([$AWK -f "$srcdir/scripts/gen-strtab.awk" <test.def >test.h])
364 sed -n 's/^[[&]]\([[^ ]]*\).*/\1/p' test.def >identifiers
366 # test 0: sanity test
375 while read id; do AS_ECHO([' printf("%s\n---\n", strtab+'"$id"');']); done
376 AS_ECHO([' return 0;'])
378 } <identifiers >test0.c
380 AT_CHECK([$CC -o test0$EXEEXT test0.c && ./test0$EXEEXT], [0], [---
411 with nontrivial whitespace
417 AT_SETUP([gen-strtab.awk @nozero option])
418 AT_KEYWORDS([gen-strtab awk script scripts])
423 AT_CHECK([$AWK -f "$srcdir/scripts/gen-strtab.awk" <test0.def >test0.h])
429 AT_CHECK([$AWK -f "$srcdir/scripts/gen-strtab.awk" <test1.def >test1.h])
434 int main(void) { printf("%d %s\n", hello, strtab+hello); return 0; }
436 AT_CHECK([$CC -DHEADER='"test0.h"' -o test0$EXEEXT test.c && ./test0$EXEEXT],
439 AT_CHECK([$CC -DHEADER='"test1.h"' -o test1$EXEEXT test.c && ./test1$EXEEXT],
445 AT_SETUP([gen-strtab.awk @macro option])
446 AT_KEYWORDS([gen-strtab awk script scripts])
454 AT_CHECK([$AWK -f "$srcdir/scripts/gen-strtab.awk" <test0.def >test0.h])
458 extern const char strtab[];
463 static const char mystrtab[] = STRTAB_INITIALIZER;
464 printf("%s\n%s\n%s\n", mystrtab+foo, mystrtab+bar, mystrtab+baz);
468 AT_CHECK([$CC -o test0$EXEEXT test0.c && ./test0$EXEEXT], [0],
476 AT_SETUP([gen-strtab.awk l10n options])
477 AT_KEYWORDS([gen-strtab awk script scripts])
479 AT_DATA([l10n.sed], dnl (
481 s/.*N_(\([^)]*\)).*/\1/p
489 AT_CHECK([$AWK -f "$srcdir/scripts/gen-strtab.awk" <test0.def >test0.h])
490 AT_CHECK([sed -n -f l10n.sed test0.h | LC_ALL=C sort], [0],
501 AT_CHECK([$AWK -f "$srcdir/scripts/gen-strtab.awk" <test1.def >test1.h])
502 AT_CHECK([sed -n -f l10n.sed test1.h], [0],
512 printf("%s %s %s\n", strtab+a, strtab+b, strtab+c);
517 AT_CHECK([$CC -DHEADER='"test0.h"' -o test0$EXEEXT test.c && ./test0$EXEEXT],
518 [0], [[hello world world goodbye
521 AT_CHECK([$CC -DHEADER='"test1.h"' -o test1$EXEEXT test.c && ./test1$EXEEXT],
522 [0], [[hello world world goodbye
528 AT_SETUP([gen-tree.awk])
529 AT_KEYWORDS([gen-tree awk script scripts])
556 AT_CHECK([$AWK -f "$srcdir/scripts/gen-tree.awk" <tree.def >tree.h])
562 struct tree { unsigned id, subtree; };
564 static const struct tree tree0[] = {
567 static const struct tree tree1[] = {
571 void print_subtree(const struct tree *root, unsigned offset, int depth)
573 const struct tree *node;
575 for (node = &root[offset]; node->id; node++) {
576 printf("%*s%s", 2*depth, "", &tree_strtab[node->id]);
578 printf(", %s_OFFSET\n", &tree_strtab[node->id]);
579 print_subtree(root, node->subtree, depth+1);
589 print_subtree(tree0, 0, 1);
591 print_subtree(tree1, 0, 1);
595 sed '/^#/d' tree.def >expout
596 AT_CHECK([$CC -o test0$EXEEXT test0.c && ./test0$EXEEXT], [0], [expout])
600 # Test the gen-tree features that avoid creating string labels for nodes.
601 AT_SETUP([gen-tree.awk @nostrtab option])
602 AT_KEYWORDS([gen-tree awk script scripts])
614 AT_CHECK([$AWK -f "$srcdir/scripts/gen-tree.awk" <tree.def >tree.h])
617 [[float tree_strtab = 0;
626 static struct { int num, offset; } root[] = { ROOT_INITIALIZER };
631 for (i = 0; i < sizeof root / sizeof root[0]; i++) {
632 printf("%d, %d\n", root[i].num, root[i].offset);
638 AT_CHECK([$CC -o test0$EXEEXT test0.c && ./test0$EXEEXT], [0],
657 AT_CHECK([$AWK -f "$srcdir/scripts/gen-tree.awk" <flat.def >flat.h])
659 sed -e 's/tree\.h/flat.h/' -e 's/ROOT/FLAT/' test0.c >test1.c
660 AT_CHECK([$CC -o test1$EXEEXT test1.c && ./test1$EXEEXT], [0],
670 AT_KEYWORDS([join awk script scripts])
672 JOIN="$AWK -f $srcdir/scripts/join.awk --"
699 AT_CHECK([$JOIN a b], [0],
710 AT_CHECK([$JOIN -v1 a b], [0],
718 AT_CHECK([$JOIN -v2 a b], [0],
725 AT_CHECK([$JOIN -v1 -v2 a b], [0],
737 AT_CHECK([$JOIN -a1 a b], [0],
753 AT_CHECK([$JOIN -a2 a b], [0],
768 AT_CHECK([$JOIN -a1 -a2 a b], [0],
788 AT_CHECK([$JOIN b a], [0],
799 AT_CHECK([$JOIN -v1 b a], [0],
806 AT_CHECK([$JOIN -v2 b a], [0],
814 AT_CHECK([$JOIN -v1 -v2 b a], [0],
826 AT_CHECK([$JOIN -a1 b a], [0],
841 AT_CHECK([$JOIN -a2 b a], [0],
857 AT_CHECK([$JOIN -a1 -a2 b a], [0],
877 AT_CHECK([echo wat | $JOIN -v1 - /dev/null], [0],
883 m4_divert_push([PREPARE_TESTS])dnl
885 $PERL -e 'my $x = 42; exit $x;'; test $? = 42 || exit 77
886 $PERL "$srcdir/scripts/fix-ltdl.pl" "$@"
889 $PERL -e 'my $x = 42; exit $x;'; test $? = 42 || exit 77
890 $PERL "$srcdir/scripts/fix-gnulib.pl" "$@"
897 "/^## begin gnulib module $arg/,/^## end gnulib module $arg/p" \
898 "$srcdir/tests/data/gnulib.mk"
901 m4_divert_pop([PREPARE_TESTS])
903 AT_SETUP([fix-gnulib.pl SED_HEADER variables])
904 AT_KEYWORDS([fix-gnulib perl script scripts])
906 test_gnulib_mk gen-header >test.mk.in
907 AT_CHECK([grep SED_HEADER test.mk.in >expout || exit 99])
908 AT_CHECK([test_fix_gnulib -i test.mk.in -o test.mk || exit
909 grep SED_HEADER test.mk], [0], [expout])
913 AT_SETUP([fix-gnulib.pl warning removal])
914 AT_KEYWORDS([fix-gnulib perl script scripts])
916 AT_DATA([test.mk.in], [[
918 noinst_LTLIBRARIES += libgnu.la
919 libgnu_la_CFLAGS = $(AM_CFLAGS) $(GL_CFLAG_GNULIB_WARNINGS)
920 noinst_LIBRARIES += libgnu.a
921 libgnu_a_CFLAGS = $(AM_CFLAGS) $(GL_CFLAG_GNULIB_WARNINGS)
924 AT_CHECK([test_fix_gnulib -i test.mk.in -o test.mk || exit
925 sed -n '/^## test begin/,/^## test end/p' test.mk], [0], [## test begin
926 EXTRA_LTLIBRARIES += libgnu.la
927 EXTRA_LIBRARIES += libgnu.a
933 AT_SETUP([fix-gnulib.pl header directory creation])
934 AT_KEYWORDS([fix-gnulib perl script scripts])
936 AT_DATA([extract.awk],
937 [[$0 !~ /^\t/ && $1 ~ /:$/ {
940 for (i = 2; i <= NF; i++) {
941 if ($i ~ /am__dirstamp/)
942 target = target " " $i;
948 target != "" && sub(/[$][({](AM_V_GEN|gl_V_at)[})].*$/, "[OK]") {
955 test_gnulib_mk alloca-opt sys_types stddef >test.mk.in
956 AT_CHECK([test_fix_gnulib -i test.mk.in -o test.mk || exit
957 $AWK -f extract.awk test.mk], [0],
958 [[lib/alloca.h: lib/$(am__dirstamp) [OK]
959 lib/sys/types.h: lib/sys/$(am__dirstamp) [OK]
960 lib/stddef.h: lib/$(am__dirstamp) [OK]
965 dnl TEST_FIND_AUTOMAKE_VER([to-check], [test-action])
967 dnl For each whitespace-separated version token in to-check, check if we can
968 dnl run the programs automake-VER and aclocal-VER. The special token 'default'
969 dnl also checks the unversioned automake and aclocal (or, if set in the
970 dnl environment, $AUTOMAKE and $ACLOCAL).
972 dnl Then test-action is expanded such that shell variables $ac and $am refer to
973 dnl the aclocal and automake programs, and $amver is the actual version
974 dnl reported by --version. The action should do nothing if the version is
975 dnl acceptable, or "continue" if the version is unacceptable.
977 dnl If an acceptable version is found, the AUTOMAKE and ACLOCAL environment
978 dnl variables are set accordingly. Otherwise, the test group is skipped.
979 m4_define([TEST_FIND_AUTOMAKE],
983 [default], [ac=${ACLOCAL-aclocal} am=${AUTOMAKE-automake}],
984 [ac=aclocal-$am; am=automake-$am])
985 amver=`$am --version | sed -n '1s/.* //p'`
986 acver=`$ac --version | sed -n '1s/.* //p'`
987 set x $amver $acver; shift; test x"$[]#" = x"2" || continue
988 test x"$amver" = x"$acver" || continue
992 AT_CHECK([$have_am || exit 77])
993 AUTOMAKE=$am; export AUTOMAKE
994 ACLOCAL=$ac; export ACLOCAL
995 AT_CHECK([$ACLOCAL --version && $AUTOMAKE --version], [0], [stdout])
998 m4_define([TEST_LTDL_LIBOBJ_MANGLING],
999 [TEST_CONFIGURE_AC([[AM_INIT_AUTOMAKE([foreign subdir-objects])
1002 AC_SUBST([ltdl_LTLIBOBJS], [libltdl/test.lo])
1003 AC_CONFIG_FILES([Makefile])
1007 AT_DATA([ltdl.mk.in], [[
1008 AM_CPPFLAGS += -DSTRING=\"helloworld\"
1010 noinst_LTLIBRARIES = libltdl/libltdl.la
1011 libltdl_libltdl_la_SOURCES = libltdl/ltdl.c
1012 libltdl_libltdl_la_LIBADD = $(ltdl_LTLIBOBJS)
1013 libltdl_libltdl_la_DEPENDENCIES = $(ltdl_LTLIBOBJS)
1015 EXTRA_DIST += libltdl/test.c
1017 AT_DATA([Makefile.am], [[AM_CPPFLAGS =
1018 include $(top_srcdir)/ltdl.mk
1019 AM_LIBTOOLFLAGS = --quiet
1022 test_LDADD = libltdl/libltdl.la
1023 all-local: ; @printf '%s\n' $(AM_CPPFLAGS)
1025 AT_DATA([libltdl/test.c], [[#include <stdio.h>
1026 int foo(void) { printf("%s\n", STRING); return 0; }
1028 AT_DATA([libltdl/ltdl.c], [[int foo(void); int main(void) { return foo(); }
1031 AT_CHECK([test_fix_ltdl -i ltdl.mk.in -o ltdl.mk])
1032 libtoolize; TEST_AUTORECONF
1033 TEST_CONFIGURE([--disable-shared])
1034 AT_CHECK([make -s && ./test], [0], [
1038 AT_SETUP([fix-ltdl.pl LIBOBJ mangling (<automake-1.16)])
1039 AT_KEYWORDS([fix-ltdl perl script scripts])
1041 TEST_FIND_AUTOMAKE([default 1.10 1.11 1.12 1.13 1.14 1.15],
1042 [AS_VERSION_COMPARE(["$amver"], [1.16], [], [continue], [continue])])
1043 TEST_LTDL_LIBOBJ_MANGLING
1047 AT_SETUP([fix-ltdl.pl LIBOBJ mangling (>=automake-1.16)])
1048 AT_KEYWORDS([fix-ltdl perl script scripts])
1050 TEST_FIND_AUTOMAKE([default 1.16 1.17 1.18 1.19],
1051 [AS_VERSION_COMPARE(["$amver"], [1.16], [continue])])
1052 TEST_LTDL_LIBOBJ_MANGLING