1 dnl Copyright © 2021-2024 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 1>&2 && ./test0$EXEEXT],
99 # test 1: long option names and help text
107 static const struct option opts[] = { LOPTS_INITIALIZER };
113 for (i = 0; i < sizeof opts / sizeof opts[0]; i++) {
114 struct lopt_help help = { "INVALID", "INVALID" };
116 if (!lopt_get_help(&opts[i], &help))
119 printf("--%s", opts[i].name);
121 printf("=%s", help.arg);
122 printf("\n%s", help.desc);
131 AT_DATA([lopthelp.awk],
136 if (sub(/\@:>@$/, "", $1))
137 sub(/\@<:@/, "", $1);
143 { sub(/^[ \t]*/, ""); }
147 $AWK -f lopthelp.awk options.def >expout
148 AT_CHECK([$CC -o test1$EXEEXT test1.c 1>&2 && ./test1$EXEEXT],
149 [0], [expout], [ignore])
151 # test 2: short option string
161 struct option lopts[] = {LOPTS_INITIALIZER};
164 for (i = 0; i < sizeof SOPT_STRING - 1; i++) {
165 if (SOPT_STRING[i] != ':') {
166 for (j = 0; j < sizeof lopts / sizeof lopts[0]; j++) {
167 if (lopts[j].val == SOPT_STRING[i]) {
168 printf("--%s ", lopts[j].name);
173 putchar(SOPT_STRING[i]);
174 if (SOPT_STRING[i+1] != ':')
181 AT_DATA([soptstr.awk],
186 sopt = substr($1, 2, 1);
187 arg = sub(/\@:>@$/, "", $2);
188 arg += sub(/\@<:@?=.*$/, "", $2);
190 print $2 " " sopt substr("::", 1, arg);
194 $AWK -f soptstr.awk options.def >expout
195 AT_CHECK([$CC -o test2$EXEEXT test2.c 1>&2 && ./test2$EXEEXT],
196 [0], [expout], [ignore])
200 AT_SETUP([gen-options.awk xgettext annotation])
201 TEST_GEN_OPTIONS([TEST_GEN_OPTIONS_SAMPLE])
203 # Check that all help strings are translatable
204 AT_DATA([messages.awk],
205 [[BEGIN { lines = -1; }
216 if (sub(/\@<:@?=.*/, "", $1)) {
217 arg = substr(tmp, index(tmp, "=")+1);
218 sub(/\@:>@$/, "", arg);
222 ctxt=("msgctxt \"" $1 "\" msgid");
225 print ctxt, ("\"" arg "\"");
229 { sub(/^[ \t]*/, ""); }
231 gsub(/"/, "\\\"", $0);
239 for (i = 0; i < lines; i++) {
240 nl = (i+1 < lines ? "\\n" : "");
241 printf(" \"%s%s\"", help[i], nl);
250 dnl Antique versions of xgettext which predate the pgettext/msgctx feature
251 dnl will produce an output po file with no msgctx lines. So try to spot
252 dnl that and skip the test with such versions.
253 AT_CHECK([xgettext --keyword=PN_:1c,2 options.h
254 test -f messages.po || exit 77
255 grep msgid messages.po >/dev/null &&
256 { grep msgctx messages.po >/dev/null || exit 77; }])
258 $AWK -f messages.awk options.def | LC_ALL=C sort >expout
259 AT_CHECK([sed -n '/^msgctxt/{
270 }' messages.po | LC_ALL=C sort], [0], [expout])
274 AT_SETUP([gen-options.awk packed format])
276 AT_DATA([test.c], [[#include <stdio.h>
277 struct option { const char *name; int has_arg; int *flag; int val; };
281 static unsigned opts[] = { LOPTS_PACKED_INITIALIZER };
289 #elif LOPT_PACK_BITS <= 8
291 #elif LOPT_PACK_BITS <= 16
293 #elif LOPT_PACK_BITS <= 32
300 for (i = 0; i < sizeof opts / sizeof opts[0]; i++) {
303 LOPT_UNPACK(o, opts[i]);
304 printf("--%s, %d, ", o.name, o.has_arg);
305 if (o.val > UCHAR_MAX)
306 printf("%d\n", o.val - UCHAR_MAX - 1);
308 printf("'%c'\n", o.val);
314 TEST_GEN_OPTIONS([[--single-option
316 AT_CHECK([$CC -o single$EXEEXT test.c 1>&2 && ./single$EXEEXT], [0],
318 --single-option, 0, 0
321 TEST_GEN_OPTIONS([[-a, --the-first-option
322 -b, --the-second-option=ARG
323 -c, --the-third-option[=ARG]
324 -d, --the-fourth-option
326 AT_CHECK([$CC -o 16bit$EXEEXT test.c 1>&2 && ./16bit$EXEEXT], [0],
328 --the-first-option, 0, 'a'
329 --the-second-option, 1, 'b'
330 --the-third-option, 2, 'c'
331 --the-fourth-option, 0, 'd'
336 AT_SETUP([gen-strtab.awk])
337 AT_KEYWORDS([gen-strtab awk script scripts])
360 &k with nontrivial whitespace
363 AT_CHECK([$AWK -f "$srcdir/scripts/gen-strtab.awk" <test.def >test.h])
365 sed -n 's/^[[&]]\([[^ ]]*\).*/\1/p' test.def >identifiers
367 # test 0: sanity test
376 while read id; do AS_ECHO([' printf("%s\n---\n", strtab+'"$id"');']); done
377 AS_ECHO([' return 0;'])
379 } <identifiers >test0.c
381 AT_CHECK([$CC -o test0$EXEEXT test0.c 1>&2 && ./test0$EXEEXT], [0], [---
412 with nontrivial whitespace
418 AT_SETUP([gen-strtab.awk @nozero option])
419 AT_KEYWORDS([gen-strtab awk script scripts])
424 AT_CHECK([$AWK -f "$srcdir/scripts/gen-strtab.awk" <test0.def >test0.h])
430 AT_CHECK([$AWK -f "$srcdir/scripts/gen-strtab.awk" <test1.def >test1.h])
435 int main(void) { printf("%d %s\n", hello, strtab+hello); return 0; }
437 AT_CHECK([$CC -DHEADER='"test0.h"' -o test0$EXEEXT test.c 1>&2 &&
438 ./test0$EXEEXT], [0], [[0 hello
440 AT_CHECK([$CC -DHEADER='"test1.h"' -o test1$EXEEXT test.c 1>&2 &&
441 ./test1$EXEEXT], [0], [[1 hello
446 AT_SETUP([gen-strtab.awk @macro option])
447 AT_KEYWORDS([gen-strtab awk script scripts])
455 AT_CHECK([$AWK -f "$srcdir/scripts/gen-strtab.awk" <test0.def >test0.h])
459 extern const char strtab[];
464 static const char mystrtab[] = STRTAB_INITIALIZER;
465 printf("%s\n%s\n%s\n", mystrtab+foo, mystrtab+bar, mystrtab+baz);
469 AT_CHECK([$CC -o test0$EXEEXT test0.c 1>&2 && ./test0$EXEEXT], [0],
477 AT_SETUP([gen-strtab.awk l10n options])
478 AT_KEYWORDS([gen-strtab awk script scripts])
480 AT_DATA([l10n.sed], dnl (
482 s/.*N_(\([^)]*\)).*/\1/p
490 AT_CHECK([$AWK -f "$srcdir/scripts/gen-strtab.awk" <test0.def >test0.h])
491 AT_CHECK([sed -n -f l10n.sed test0.h | LC_ALL=C sort], [0],
502 AT_CHECK([$AWK -f "$srcdir/scripts/gen-strtab.awk" <test1.def >test1.h])
503 AT_CHECK([sed -n -f l10n.sed test1.h], [0],
513 printf("%s %s %s\n", strtab+a, strtab+b, strtab+c);
518 AT_CHECK([$CC -DHEADER='"test0.h"' -o test0$EXEEXT test.c 1>&2 &&
519 ./test0$EXEEXT], [0], [[hello world world goodbye
522 AT_CHECK([$CC -DHEADER='"test1.h"' -o test1$EXEEXT test.c 1>&2 &&
523 ./test1$EXEEXT], [0], [[hello world world goodbye
529 AT_SETUP([gen-tree.awk])
530 AT_KEYWORDS([gen-tree awk script scripts])
557 AT_CHECK([$AWK -f "$srcdir/scripts/gen-tree.awk" <tree.def >tree.h])
563 struct tree { unsigned id, subtree; };
565 static const struct tree tree0[] = {
568 static const struct tree tree1[] = {
572 void print_subtree(const struct tree *root, unsigned offset, int depth)
574 const struct tree *node;
576 for (node = &root[offset]; node->id; node++) {
577 printf("%*s%s", 2*depth, "", &tree_strtab[node->id]);
579 printf(", %s_OFFSET\n", &tree_strtab[node->id]);
580 print_subtree(root, node->subtree, depth+1);
590 print_subtree(tree0, 0, 1);
592 print_subtree(tree1, 0, 1);
596 sed '/^#/d' tree.def >expout
597 AT_CHECK([$CC -o test0$EXEEXT test0.c 1>&2 && ./test0$EXEEXT],
598 [0], [expout], [ignore])
602 # Test the gen-tree features that avoid creating string labels for nodes.
603 AT_SETUP([gen-tree.awk @nostrtab option])
604 AT_KEYWORDS([gen-tree awk script scripts])
616 AT_CHECK([$AWK -f "$srcdir/scripts/gen-tree.awk" <tree.def >tree.h])
619 [[float tree_strtab = 0;
628 static struct { int num, offset; } root[] = { ROOT_INITIALIZER };
633 for (i = 0; i < sizeof root / sizeof root[0]; i++) {
634 printf("%d, %d\n", root[i].num, root[i].offset);
640 AT_CHECK([$CC -o test0$EXEEXT test0.c 1>&2 && ./test0$EXEEXT], [0],
659 AT_CHECK([$AWK -f "$srcdir/scripts/gen-tree.awk" <flat.def >flat.h])
661 sed -e 's/tree\.h/flat.h/' -e 's/ROOT/FLAT/' test0.c >test1.c
662 AT_CHECK([$CC -o test1$EXEEXT test1.c 1>&2 && ./test1$EXEEXT], [0],
672 AT_KEYWORDS([join awk script scripts])
674 JOIN="$AWK -f $srcdir/scripts/join.awk --"
701 AT_CHECK([$JOIN a b], [0],
712 AT_CHECK([$JOIN -v1 a b], [0],
720 AT_CHECK([$JOIN -v2 a b], [0],
727 AT_CHECK([$JOIN -v1 -v2 a b], [0],
739 AT_CHECK([$JOIN -a1 a b], [0],
755 AT_CHECK([$JOIN -a2 a b], [0],
770 AT_CHECK([$JOIN -a1 -a2 a b], [0],
790 AT_CHECK([$JOIN b a], [0],
801 AT_CHECK([$JOIN -v1 b a], [0],
808 AT_CHECK([$JOIN -v2 b a], [0],
816 AT_CHECK([$JOIN -v1 -v2 b a], [0],
828 AT_CHECK([$JOIN -a1 b a], [0],
843 AT_CHECK([$JOIN -a2 b a], [0],
859 AT_CHECK([$JOIN -a1 -a2 b a], [0],
879 AT_CHECK([echo wat | $JOIN -v1 - /dev/null], [0],
885 m4_divert_push([PREPARE_TESTS])dnl
887 $PERL -e 'my $x = 42; exit $x;'; test $? = 42 || exit 77
888 $PERL "$srcdir/scripts/fix-ltdl.pl" "$@"
891 $PERL -e 'my $x = 42; exit $x;'; test $? = 42 || exit 77
892 $PERL "$srcdir/scripts/fix-gnulib.pl" "$@"
899 "/^## begin gnulib module $arg/,/^## end gnulib module $arg/p" \
900 "$srcdir/tests/data/gnulib.mk"
903 m4_divert_pop([PREPARE_TESTS])
905 AT_SETUP([fix-gnulib.pl SED_HEADER variables])
906 AT_KEYWORDS([fix-gnulib perl script scripts])
908 test_gnulib_mk gen-header >test.mk.in
909 AT_CHECK([grep SED_HEADER test.mk.in >expout || exit 99])
910 AT_CHECK([test_fix_gnulib -i test.mk.in -o test.mk || exit
911 grep SED_HEADER test.mk], [0], [expout])
915 AT_SETUP([fix-gnulib.pl warning removal])
916 AT_KEYWORDS([fix-gnulib perl script scripts])
918 AT_DATA([test.mk.in], [[
920 noinst_LTLIBRARIES += libgnu.la
921 libgnu_la_CFLAGS = $(AM_CFLAGS) $(GL_CFLAG_GNULIB_WARNINGS)
922 noinst_LIBRARIES += libgnu.a
923 libgnu_a_CFLAGS = $(AM_CFLAGS) $(GL_CFLAG_GNULIB_WARNINGS)
926 AT_CHECK([test_fix_gnulib -i test.mk.in -o test.mk || exit
927 sed -n '/^## test begin/,/^## test end/p' test.mk], [0], [## test begin
928 EXTRA_LTLIBRARIES += libgnu.la
929 EXTRA_LIBRARIES += libgnu.a
935 AT_SETUP([fix-gnulib.pl header directory creation])
936 AT_KEYWORDS([fix-gnulib perl script scripts])
938 AT_DATA([extract.awk],
939 [[$0 !~ /^\t/ && $1 ~ /:$/ {
942 for (i = 2; i <= NF; i++) {
943 if ($i ~ /am__dirstamp/)
944 target = target " " $i;
950 target != "" && sub(/[$][({](AM_V_GEN|gl_V_at)[})].*$/, "[OK]") {
957 test_gnulib_mk alloca-opt sys_types stddef >test.mk.in
958 AT_CHECK([test_fix_gnulib -i test.mk.in -o test.mk || exit
959 $AWK -f extract.awk test.mk], [0],
960 [[lib/alloca.h: lib/$(am__dirstamp) [OK]
961 lib/sys/types.h: lib/sys/$(am__dirstamp) [OK]
962 lib/stddef.h: lib/$(am__dirstamp) [OK]
967 dnl TEST_FIND_AUTOMAKE_VER([to-check], [test-action])
969 dnl For each whitespace-separated version token in to-check, check if we can
970 dnl run the programs automake-VER and aclocal-VER. The special token 'default'
971 dnl also checks the unversioned automake and aclocal (or, if set in the
972 dnl environment, $AUTOMAKE and $ACLOCAL).
974 dnl Then test-action is expanded such that shell variables $ac and $am refer to
975 dnl the aclocal and automake programs, and $amver is the actual version
976 dnl reported by --version. The action should do nothing if the version is
977 dnl acceptable, or "continue" if the version is unacceptable.
979 dnl If an acceptable version is found, the AUTOMAKE and ACLOCAL environment
980 dnl variables are set accordingly. Otherwise, the test group is skipped.
981 m4_define([TEST_FIND_AUTOMAKE],
985 [default], [ac=${ACLOCAL-aclocal} am=${AUTOMAKE-automake}],
986 [ac=aclocal-$am; am=automake-$am])
987 amver=`$am --version | sed -n '1s/.* //p'`
988 acver=`$ac --version | sed -n '1s/.* //p'`
989 set x $amver $acver; shift; test x"$[]#" = x"2" || continue
990 test x"$amver" = x"$acver" || continue
994 AT_CHECK([$have_am || exit 77])
995 AUTOMAKE=$am; export AUTOMAKE
996 ACLOCAL=$ac; export ACLOCAL
997 AT_CHECK([$ACLOCAL --version && $AUTOMAKE --version], [0], [stdout])
1000 m4_define([TEST_LTDL_LIBOBJ_MANGLING],
1001 [TEST_CONFIGURE_AC([[AM_INIT_AUTOMAKE([foreign subdir-objects])
1004 AC_SUBST([ltdl_LTLIBOBJS], [libltdl/test.lo])
1005 AC_CONFIG_FILES([Makefile])
1009 AT_DATA([ltdl.mk.in], [[
1010 AM_CPPFLAGS += -DSTRING=\"helloworld\"
1012 noinst_LTLIBRARIES = libltdl/libltdl.la
1013 libltdl_libltdl_la_SOURCES = libltdl/ltdl.c
1014 libltdl_libltdl_la_LIBADD = $(ltdl_LTLIBOBJS)
1015 libltdl_libltdl_la_DEPENDENCIES = $(ltdl_LTLIBOBJS)
1017 EXTRA_DIST += libltdl/test.c
1019 AT_DATA([Makefile.am], [[AM_CPPFLAGS =
1020 include $(top_srcdir)/ltdl.mk
1021 AM_LIBTOOLFLAGS = --quiet
1024 test_LDADD = libltdl/libltdl.la
1025 all-local: ; @printf '%s\n' $(AM_CPPFLAGS)
1027 AT_DATA([libltdl/test.c], [[#include <stdio.h>
1028 int foo(void) { printf("%s\n", STRING); return 0; }
1030 AT_DATA([libltdl/ltdl.c], [[int foo(void); int main(void) { return foo(); }
1033 AT_CHECK([test_fix_ltdl -i ltdl.mk.in -o ltdl.mk])
1034 libtoolize; TEST_AUTORECONF
1035 TEST_CONFIGURE([--disable-shared])
1036 AT_CHECK([make -s && ./test], [0], [
1040 AT_SETUP([fix-ltdl.pl LIBOBJ mangling (<automake-1.16)])
1041 AT_KEYWORDS([fix-ltdl perl script scripts])
1043 TEST_FIND_AUTOMAKE([default 1.10 1.11 1.12 1.13 1.14 1.15],
1044 [AS_VERSION_COMPARE(["$amver"], [1.16], [], [continue], [continue])])
1045 TEST_LTDL_LIBOBJ_MANGLING
1049 AT_SETUP([fix-ltdl.pl LIBOBJ mangling (>=automake-1.16)])
1050 AT_KEYWORDS([fix-ltdl perl script scripts])
1052 TEST_FIND_AUTOMAKE([default 1.16 1.17 1.18 1.19],
1053 [AS_VERSION_COMPARE(["$amver"], [1.16], [continue])])
1054 TEST_LTDL_LIBOBJ_MANGLING