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([gen-options.awk])
10 AT_KEYWORDS([gen-options awk script scripts])
12 AT_DATA([options.def],
15 --option-with-flagval (&x, 5)
18 --option-with-optional-arg[=OPTIONAL]
21 -a, --option-with-sopt
23 -b, --option-with-sopt-and-arg=SOPTARG
24 -c, --option-with-sopt-and-optional-arg[=SOPTOPTIONAL]
25 --option-with-arg-and-val=ARGVAL (42)
26 --option-with-arg-and-flagval=ARGFLAGVAL (&a[1], 'x')
27 --option-with-optional-arg-and-val[=OPTIONALARGVAL] (54)
28 --option-with-optional-arg-and-flagval[=OPTIONALFLAGVAL] (0, 0)
31 that has a line randomly indented
40 AT_CHECK([$AWK -f "$builddir/scripts/gen-options.awk" <options.def >options.h])
43 [[struct option { const char *name; int has_arg; int *flag; int val; };
49 [[#include "context.h"
52 static const char sopts[] = SOPT_STRING;
53 static const struct option opts[] = { LOPTS_INITIALIZER, {0} };
60 AT_CHECK([$CC -o test0$EXEEXT test0.c && ./test0$EXEEXT], [0], [], [ignore])
62 # test 1: long option names and help text
70 static const struct option opts[] = { LOPTS_INITIALIZER };
76 for (i = 0; i < sizeof opts / sizeof opts[0]; i++) {
77 struct lopt_help help = { "INVALID", "INVALID" };
79 if (!lopt_get_help(&opts[i], &help))
82 printf("--%s", opts[i].name);
84 printf("=%s", help.arg);
85 printf("\n%s", help.desc);
94 AT_DATA([lopthelp.awk],
99 if (sub(/\@:>@$/, "", $1))
100 sub(/\@<:@/, "", $1);
106 { sub(/^[ \t]*/, ""); }
110 $AWK -f lopthelp.awk options.def >expout
111 AT_CHECK([$CC -o test1$EXEEXT test1.c && ./test1$EXEEXT],
112 [0], [expout], [ignore])
114 # test 2: short option string
124 struct option lopts[] = {LOPTS_INITIALIZER};
127 for (i = 0; i < sizeof SOPT_STRING - 1; i++) {
128 if (SOPT_STRING[i] != ':') {
129 for (j = 0; j < sizeof lopts / sizeof lopts[0]; j++) {
130 if (lopts[j].val == SOPT_STRING[i]) {
131 printf("--%s ", lopts[j].name);
136 putchar(SOPT_STRING[i]);
137 if (SOPT_STRING[i+1] != ':')
144 AT_DATA([soptstr.awk],
149 sopt = substr($1, 2, 1);
150 arg = sub(/\@:>@$/, "", $2);
151 arg += sub(/\@<:@?=.*$/, "", $2);
153 print $2 " " sopt substr("::", 1, arg);
157 $AWK -f soptstr.awk options.def >expout
158 AT_CHECK([$CC -o test2$EXEEXT test2.c && ./test2$EXEEXT],
159 [0], [expout], [ignore])
161 # Check that all help strings are translatable
162 AT_DATA([messages.awk],
163 [[BEGIN { lines = -1; }
174 if (sub(/\@<:@?=.*/, "", $1)) {
175 arg = substr(tmp, index(tmp, "=")+1);
176 sub(/\@:>@$/, "", arg);
180 ctxt=("msgctxt \"" $1 "\" msgid");
183 print ctxt, ("\"" arg "\"");
187 { sub(/^[ \t]*/, ""); }
189 gsub(/"/, "\\\"", $0);
197 for (i = 0; i < lines; i++) {
198 nl = (i+1 < lines ? "\\n" : "");
199 printf(" \"%s%s\"", help[i], nl);
208 AT_CHECK([xgettext --keyword=PN_:1c,2 options.h
209 test -f messages.po || exit 77])
211 $AWK -f messages.awk options.def | LC_ALL=C sort >expout
212 AT_CHECK([sed -n '/^msgctxt/{
223 }' messages.po | LC_ALL=C sort], [0], [expout])
227 AT_SETUP([gen-options.awk packed format])
228 AT_KEYWORDS([gen-options awk script scripts])
230 AT_DATA([test.c], [[#include <stdio.h>
231 struct option { const char *name; int has_arg; int *flag; int val; };
235 static unsigned opts[] = { LOPTS_PACKED_INITIALIZER };
243 #elif LOPT_PACK_BITS <= 8
245 #elif LOPT_PACK_BITS <= 16
247 #elif LOPT_PACK_BITS <= 32
254 for (i = 0; i < sizeof opts / sizeof opts[0]; i++) {
257 LOPT_UNPACK(o, opts[i]);
258 printf("--%s, %d, ", o.name, o.has_arg);
259 if (o.val > UCHAR_MAX)
260 printf("%d\n", o.val - UCHAR_MAX - 1);
262 printf("'%c'\n", o.val);
268 AT_DATA([single.dat],
271 AT_CHECK([$AWK -f "$builddir/scripts/gen-options.awk" <single.dat >options.h])
272 AT_CHECK([$CC -o single$EXEEXT test.c && ./single$EXEEXT], [0],
274 --single-option, 0, 0
278 [[-a, --the-first-option
279 -b, --the-second-option=ARG
280 -c, --the-third-option[=ARG]
281 -d, --the-fourth-option
283 AT_CHECK([$AWK -f "$builddir/scripts/gen-options.awk" <16bit.dat >options.h])
284 AT_CHECK([$CC -o 16bit$EXEEXT test.c && ./16bit$EXEEXT], [0],
286 --the-first-option, 0, 'a'
287 --the-second-option, 1, 'b'
288 --the-third-option, 2, 'c'
289 --the-fourth-option, 0, 'd'
294 AT_SETUP([gen-strtab.awk])
295 AT_KEYWORDS([gen-strtab awk script scripts])
320 AT_CHECK([$AWK -f "$builddir/scripts/gen-strtab.awk" <test.def >test.h])
322 sed -n 's/^[[&]]\([[^ ]]*\).*/\1/p' test.def >identifiers
324 # test 0: sanity test
333 exec 3<identifiers 4>>test0.c
334 while read ident <&3; do
335 AS_ECHO([' printf("%s\n---\n", '"strtab+$ident);"]) >&4
337 AS_ECHO([' return 0;']) >&4
341 AT_CHECK([$CC -o test0$EXEEXT test0.c && ./test0$EXEEXT], [0], [---
376 AT_SETUP([gen-strtab.awk @nozero option])
377 AT_KEYWORDS([gen-strtab awk script scripts])
382 AT_CHECK([$AWK -f "$builddir/scripts/gen-strtab.awk" <test0.def >test0.h])
388 AT_CHECK([$AWK -f "$builddir/scripts/gen-strtab.awk" <test1.def >test1.h])
393 int main(void) { printf("%d %s\n", hello, strtab+hello); return 0; }
395 AT_CHECK([$CC -DHEADER='"test0.h"' -o test0$EXEEXT test.c && ./test0$EXEEXT],
398 AT_CHECK([$CC -DHEADER='"test1.h"' -o test1$EXEEXT test.c && ./test1$EXEEXT],
404 AT_SETUP([gen-strtab.awk @macro option])
405 AT_KEYWORDS([gen-strtab awk script scripts])
413 AT_CHECK([$AWK -f "$builddir/scripts/gen-strtab.awk" <test0.def >test0.h])
417 extern const char strtab[];
422 static const char mystrtab[] = STRTAB_INITIALIZER;
423 printf("%s\n%s\n%s\n", mystrtab+foo, mystrtab+bar, mystrtab+baz);
427 AT_CHECK([$CC -o test0$EXEEXT test0.c && ./test0$EXEEXT], [0],
435 AT_SETUP([gen-strtab.awk l10n options])
436 AT_KEYWORDS([gen-strtab awk script scripts])
438 AT_DATA([l10n.sed], dnl (
440 s/.*N_(\([^)]*\)).*/\1/p
448 AT_CHECK([$AWK -f "$builddir/scripts/gen-strtab.awk" <test0.def >test0.h])
449 AT_CHECK([sed -n -f l10n.sed test0.h | LC_ALL=C sort], [0],
460 AT_CHECK([$AWK -f "$builddir/scripts/gen-strtab.awk" <test1.def >test1.h])
461 AT_CHECK([sed -n -f l10n.sed test1.h], [0],
471 printf("%s %s %s\n", strtab+a, strtab+b, strtab+c);
476 AT_CHECK([$CC -DHEADER='"test0.h"' -o test0$EXEEXT test.c && ./test0$EXEEXT],
477 [0], [[hello world world goodbye
480 AT_CHECK([$CC -DHEADER='"test1.h"' -o test1$EXEEXT test.c && ./test1$EXEEXT],
481 [0], [[hello world world goodbye
487 AT_SETUP([gen-tree.awk])
488 AT_KEYWORDS([gen-tree awk script scripts])
515 AT_CHECK([$AWK -f "$builddir/scripts/gen-tree.awk" <tree.def >tree.h])
521 struct tree { unsigned id, subtree; };
523 static const struct tree tree0[] = {
526 static const struct tree tree1[] = {
530 void print_subtree(const struct tree *root, unsigned offset, int depth)
532 const struct tree *node;
534 for (node = &root[offset]; node->id; node++) {
535 printf("%*s%s", 2*depth, "", &tree_strtab[node->id]);
537 printf(", %s_OFFSET\n", &tree_strtab[node->id]);
538 print_subtree(root, node->subtree, depth+1);
548 print_subtree(tree0, 0, 1);
550 print_subtree(tree1, 0, 1);
554 sed '/^#/d' tree.def >expout
555 AT_CHECK([$CC -o test0$EXEEXT test0.c && ./test0$EXEEXT], [0], [expout])
559 # Test the gen-tree features that avoid creating string labels for nodes.
560 AT_SETUP([gen-tree.awk @nostrtab option])
561 AT_KEYWORDS([gen-tree awk script scripts])
573 AT_CHECK([$AWK -f "$builddir/scripts/gen-tree.awk" <tree.def >tree.h])
576 [[float tree_strtab = 0;
585 static struct { int num, offset; } root[] = { ROOT_INITIALIZER };
590 for (i = 0; i < sizeof root / sizeof root[0]; i++) {
591 printf("%d, %d\n", root[i].num, root[i].offset);
597 AT_CHECK([$CC -o test0$EXEEXT test0.c && ./test0$EXEEXT], [0],
616 AT_CHECK([$AWK -f "$builddir/scripts/gen-tree.awk" <flat.def >flat.h])
618 sed -e 's/tree\.h/flat.h/' -e 's/ROOT/FLAT/' test0.c >test1.c
619 AT_CHECK([$CC -o test1$EXEEXT test1.c && ./test1$EXEEXT], [0],
629 AT_KEYWORDS([join awk script scripts])
631 JOIN="$AWK -f $builddir/scripts/join.awk --"
658 AT_CHECK([$JOIN a b], [0],
669 AT_CHECK([$JOIN -v1 a b], [0],
677 AT_CHECK([$JOIN -v2 a b], [0],
684 AT_CHECK([$JOIN -v1 -v2 a b], [0],
696 AT_CHECK([$JOIN -a1 a b], [0],
712 AT_CHECK([$JOIN -a2 a b], [0],
727 AT_CHECK([$JOIN -a1 -a2 a b], [0],
747 AT_CHECK([$JOIN b a], [0],
758 AT_CHECK([$JOIN -v1 b a], [0],
765 AT_CHECK([$JOIN -v2 b a], [0],
773 AT_CHECK([$JOIN -v1 -v2 b a], [0],
785 AT_CHECK([$JOIN -a1 b a], [0],
800 AT_CHECK([$JOIN -a2 b a], [0],
816 AT_CHECK([$JOIN -a1 -a2 b a], [0],
836 AT_CHECK([echo wat | $JOIN -v1 - /dev/null], [0],
842 m4_divert_push([PREPARE_TESTS])dnl
844 $PERL -e 'my $x = 42; exit $x;'; test $? = 42 || exit 77
845 $PERL -f "$srcdir/scripts/fix-ltdl.pl" "$@"
848 $PERL -e 'my $x = 42; exit $x;'; test $? = 42 || exit 77
849 $PERL -f "$srcdir/scripts/fix-gnulib.pl" "$@"
855 sed -n -f - "$srcdir/tests/data/gnulib.mk" <<EOF
856 /^## begin gnulib module $arg/,/^## end gnulib module $arg/p
860 m4_divert_pop([PREPARE_TESTS])
862 AT_SETUP([fix-gnulib.pl SED_HEADER variables])
864 test_gnulib_mk gen-header >test.mk.in
865 AT_CHECK([grep SED_HEADER test.mk.in >expout || exit 99])
866 AT_CHECK([test_fix_gnulib -i test.mk.in -o test.mk || exit
867 grep SED_HEADER test.mk], [0], [expout])
871 AT_SETUP([fix-gnulib.pl %reldir% substitution])
873 test_gnulib_mk sys_types >test.mk.in
874 AT_CHECK([grep '%reldir%' test.mk.in >/dev/null || exit 99])
876 sed -n -f - test.mk.in >expout <<'EOF'
878 /^## begin gnulib/,/^## end gnulib/!b
880 s|(srcdir)|(top_srcdir)|
882 s|BUILT_SOURCES|gnulib_core_headers|
884 /^MOSTLYCLEANFILES/{h;b}
888 AT_CHECK([test_fix_gnulib -i test.mk.in -o test.mk || exit
889 sed -n -e '/^## begin gnulib/,/^## end gnulib/p' \
890 -e '/CLEANFILES/p' test.mk],
895 AT_SETUP([fix-gnulib.pl warning removal])
897 AT_DATA([test.mk.in], [[
899 noinst_LTLIBRARIES += libgnu.la
900 libgnu_la_CFLAGS = $(AM_CFLAGS) $(GL_CFLAG_GNULIB_WARNINGS)
901 noinst_LIBRARIES += libgnu.a
902 libgnu_a_CFLAGS = $(AM_CFLAGS) $(GL_CFLAG_GNULIB_WARNINGS)
905 AT_CHECK([test_fix_gnulib -i test.mk.in -o test.mk || exit
906 sed -n '/^## test begin/,/^## test end/p' test.mk], [0], [## test begin
907 EXTRA_LTLIBRARIES += libgnu.la
908 EXTRA_LIBRARIES += libgnu.a
914 AT_SETUP([fix-gnulib.pl header directory creation])
916 AT_DATA([extract.sed],
932 test_gnulib_mk alloca-opt sys_types stddef >test.mk.in
933 AT_CHECK([test_fix_gnulib -i test.mk.in -o test.mk || exit
934 sed -n -f extract.sed test.mk], [0],
936 $(AM_V_GEN)$(MKDIR_P) lib
939 $(AM_V_GEN)$(MKDIR_P) lib/sys
942 $(AM_V_GEN)$(MKDIR_P) lib
948 dnl TEST_FIND_AUTOMAKE_VER([to-check], [test-action])
950 dnl For each whitespace-separated version token in to-check, check if we can
951 dnl run the programs automake-VER and aclocal-VER. The special token 'default'
952 dnl also checks the unversioned automake and aclocal (or, if set in the
953 dnl environment, $AUTOMAKE and $ACLOCAL).
955 dnl Then test-action is expanded such that shell variables $ac and $am refer to
956 dnl the aclocal and automake programs, and $amver is the actual version
957 dnl reported by --version. The action should do nothing if the version is
958 dnl acceptable, or "continue" if the version is unacceptable.
960 dnl If an acceptable version is found, the AUTOMAKE and ACLOCAL environment
961 dnl variables are set accordingly. Otherwise, the test group is skipped.
962 m4_define([TEST_FIND_AUTOMAKE],
966 [default], [ac=${ACLOCAL-aclocal} am=${AUTOMAKE-automake}],
967 [ac=aclocal-$am; am=automake-$am])
968 amver=`$am --version | sed -n '1s/.* //p'`
969 acver=`$ac --version | sed -n '1s/.* //p'`
970 set x $amver $acver; shift; test x"$[]#" = x"2" || continue
971 test x"$amver" = x"$acver" || continue
975 AT_CHECK([$have_am || exit 77])
976 AUTOMAKE=$am; export AUTOMAKE
977 ACLOCAL=$ac; export ACLOCAL
978 AT_CHECK([$ACLOCAL --version && $AUTOMAKE --version], [0], [stdout])
981 m4_define([TEST_LTDL_LIBOBJ_MANGLING],
982 [TEST_CONFIGURE_AC([[AM_INIT_AUTOMAKE([foreign subdir-objects])
985 AC_SUBST([ltdl_LTLIBOBJS], [libltdl/test.lo])
986 AC_CONFIG_FILES([Makefile])
990 AT_DATA([ltdl.mk.in], [[
991 AM_CPPFLAGS += -DSTRING=\"helloworld\"
993 noinst_LTLIBRARIES = libltdl/libltdl.la
994 libltdl_libltdl_la_SOURCES = libltdl/ltdl.c
995 libltdl_libltdl_la_LIBADD = $(ltdl_LTLIBOBJS)
996 libltdl_libltdl_la_DEPENDENCIES = $(ltdl_LTLIBOBJS)
998 EXTRA_DIST += libltdl/test.c
1000 AT_DATA([Makefile.am], [[AM_CPPFLAGS =
1001 include $(top_srcdir)/ltdl.mk
1002 AM_LIBTOOLFLAGS = --quiet
1005 test_LDADD = libltdl/libltdl.la
1006 all-local: ; @printf '%s\n' $(AM_CPPFLAGS)
1008 AT_DATA([libltdl/test.c], [[#include <stdio.h>
1009 int foo(void) { printf("%s\n", STRING); return 0; }
1011 AT_DATA([libltdl/ltdl.c], [[int foo(void); int main(void) { return foo(); }
1014 AT_CHECK([test_fix_ltdl -i ltdl.mk.in -o ltdl.mk])
1015 libtoolize; TEST_AUTORECONF
1016 TEST_CONFIGURE([--disable-shared])
1017 AT_CHECK([make -s && ./test], [0], [
1021 AT_SETUP([fix-ltdl.pl LIBOBJ mangling (<automake-1.16)])
1023 TEST_FIND_AUTOMAKE([default 1.10 1.11 1.12 1.13 1.14 1.15],
1024 [AS_VERSION_COMPARE(["$amver"], [1.16], [], [continue], [continue])])
1025 TEST_LTDL_LIBOBJ_MANGLING
1029 AT_SETUP([fix-ltdl.pl LIBOBJ mangling (>=automake-1.16)])
1031 TEST_FIND_AUTOMAKE([default 1.16 1.17 1.18 1.19],
1032 [AS_VERSION_COMPARE(["$amver"], [1.16], [continue])])
1033 TEST_LTDL_LIBOBJ_MANGLING