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 # pick out interesting bits from the definitions file
95 sed -n '/^-/s/^.*--\([[^\= @<:@]]*\).*$/\1/p' options.def >options
97 s/[[^=]]*\(=[[^@:>@ ]]*\).*$/\1/
101 }' options.def >argnames
103 AS_ECHO(["-"]) | sed -n '1s/^-.*//p
121 s/[[^\n]][[^\n]]*/\\"&\\"/g
126 ' options.def - >helptext
128 exec 3<options 4<argnames 5<helptext 6>expout
129 while read opt <&3 && read arg <&4 && read help <&5; do
130 if test ${arg:+y}; then
131 AS_ECHO(["--$opt=$arg"]) >&6
133 AS_ECHO(["--$opt"]) >&6
135 eval "set x $help"; shift
138 AS_ECHO(["$arg"]) >&6
141 exec 3<&- 4<&- 5<&- 6>&-
143 AT_CHECK([$CC -o test1$EXEEXT test1.c && ./test1$EXEEXT],
144 [0], [expout], [ignore])
146 # test 2: short option string
156 struct option lopts[] = {LOPTS_INITIALIZER};
159 for (i = 0; i < sizeof SOPT_STRING - 1; i++) {
160 if (SOPT_STRING[i] != ':') {
161 for (j = 0; j < sizeof lopts / sizeof lopts[0]; j++) {
162 if (lopts[j].val == SOPT_STRING[i]) {
163 printf("--%s ", lopts[j].name);
168 putchar(SOPT_STRING[i]);
169 if (SOPT_STRING[i+1] != ':')
179 s/^-\([[^-]]\)[[^:]]*/\1/p
181 }' options.def >sopts
183 exec 3<options 4<sopts 5>expout
184 while read lopt <&3 && read sopt <&4; do
185 if test ${sopt:+y}; then
186 AS_ECHO(["--$lopt $sopt"]) >&5
191 AT_CHECK([$CC -o test2$EXEEXT test2.c && ./test2$EXEEXT],
192 [0], [expout], [ignore])
194 # Check that all help strings are translatable
195 sed 's/\([[^\\]]\\\)" /\1\\n\\" /g' helptext >help-po
196 exec 3<options 4<argnames 5<help-po 6>expected.po
197 while read opt <&3 && read arg <&4 && read help <&5; do
198 if test ${arg:+y}; then
199 AS_ECHO(["msgctxt \"$opt\" msgid \"$arg\""]) >&6
201 AS_ECHO(["msgctxt \"$opt\" msgid${help:+ }$help"]) >&6
203 exec 3<&- 4<&- 5<&- 6>&-
205 AT_CHECK([xgettext --keyword=PN_:1c,2 options.h
206 test -f messages.po || exit 77])
208 LC_ALL=C sort expected.po >expout
209 AT_CHECK([sed -n '/^msgctxt/{
220 }' messages.po | LC_ALL=C sort], [0], [expout])
224 AT_SETUP([gen-options.awk packed format])
225 AT_KEYWORDS([gen-options awk script scripts])
227 AT_DATA([test.c], [[#include <stdio.h>
228 struct option { const char *name; int has_arg; int *flag; int val; };
232 static unsigned opts[] = { LOPTS_PACKED_INITIALIZER };
240 #elif LOPT_PACK_BITS <= 8
242 #elif LOPT_PACK_BITS <= 16
244 #elif LOPT_PACK_BITS <= 32
251 for (i = 0; i < sizeof opts / sizeof opts[0]; i++) {
254 LOPT_UNPACK(o, opts[i]);
255 printf("--%s, %d, ", o.name, o.has_arg);
256 if (o.val > UCHAR_MAX)
257 printf("%d\n", o.val - UCHAR_MAX - 1);
259 printf("'%c'\n", o.val);
265 AT_DATA([single.dat],
268 AT_CHECK([$AWK -f "$builddir/scripts/gen-options.awk" <single.dat >options.h])
269 AT_CHECK([$CC -o single$EXEEXT test.c && ./single$EXEEXT], [0],
271 --single-option, 0, 0
275 [[-a, --the-first-option
276 -b, --the-second-option=ARG
277 -c, --the-third-option[=ARG]
278 -d, --the-fourth-option
280 AT_CHECK([$AWK -f "$builddir/scripts/gen-options.awk" <16bit.dat >options.h])
281 AT_CHECK([$CC -o 16bit$EXEEXT test.c && ./16bit$EXEEXT], [0],
283 --the-first-option, 0, 'a'
284 --the-second-option, 1, 'b'
285 --the-third-option, 2, 'c'
286 --the-fourth-option, 0, 'd'
291 AT_SETUP([gen-strtab.awk])
292 AT_KEYWORDS([gen-strtab awk script scripts])
317 AT_CHECK([$AWK -f "$builddir/scripts/gen-strtab.awk" <test.def >test.h])
319 sed -n 's/^[[&]]\([[^ ]]*\).*/\1/p' test.def >identifiers
321 # test 0: sanity test
330 exec 3<identifiers 4>>test0.c
331 while read ident <&3; do
332 AS_ECHO([' printf("%s\n---\n", '"strtab+$ident);"]) >&4
334 AS_ECHO([' return 0;']) >&4
338 AT_CHECK([$CC -o test0$EXEEXT test0.c && ./test0$EXEEXT], [0], [---
373 AT_SETUP([gen-strtab.awk @nozero option])
374 AT_KEYWORDS([gen-strtab awk script scripts])
379 AT_CHECK([$AWK -f "$builddir/scripts/gen-strtab.awk" <test0.def >test0.h])
385 AT_CHECK([$AWK -f "$builddir/scripts/gen-strtab.awk" <test1.def >test1.h])
390 int main(void) { printf("%d %s\n", hello, strtab+hello); return 0; }
392 AT_CHECK([$CC -DHEADER='"test0.h"' -o test0$EXEEXT test.c && ./test0$EXEEXT],
395 AT_CHECK([$CC -DHEADER='"test1.h"' -o test1$EXEEXT test.c && ./test1$EXEEXT],
401 AT_SETUP([gen-strtab.awk l10n options])
402 AT_KEYWORDS([gen-strtab awk script scripts])
404 AT_DATA([l10n.sed], dnl (
406 s/.*N_(\([^)]*\)).*/\1/p
414 AT_CHECK([$AWK -f "$builddir/scripts/gen-strtab.awk" <test0.def >test0.h])
415 AT_CHECK([sed -n -f l10n.sed test0.h | LC_ALL=C sort], [0],
426 AT_CHECK([$AWK -f "$builddir/scripts/gen-strtab.awk" <test1.def >test1.h])
427 AT_CHECK([sed -n -f l10n.sed test1.h], [0],
437 printf("%s %s %s\n", strtab+a, strtab+b, strtab+c);
442 AT_CHECK([$CC -DHEADER='"test0.h"' -o test0$EXEEXT test.c && ./test0$EXEEXT],
443 [0], [[hello world world goodbye
446 AT_CHECK([$CC -DHEADER='"test1.h"' -o test1$EXEEXT test.c && ./test1$EXEEXT],
447 [0], [[hello world world goodbye
453 AT_SETUP([gen-tree.awk])
454 AT_KEYWORDS([gen-tree awk script scripts])
481 AT_CHECK([$AWK -f "$builddir/scripts/gen-tree.awk" <tree.def >tree.h])
487 struct tree { unsigned id, subtree; };
489 static const struct tree tree0[] = {
492 static const struct tree tree1[] = {
496 void print_subtree(const struct tree *root, unsigned offset, int depth)
498 const struct tree *node;
500 for (node = &root[offset]; node->id; node++) {
501 printf("%*s%s", 2*depth, "", &tree_strtab[node->id]);
503 printf(", %s_OFFSET\n", &tree_strtab[node->id]);
504 print_subtree(root, node->subtree, depth+1);
514 print_subtree(tree0, 0, 1);
516 print_subtree(tree1, 0, 1);
520 sed '/^#/d' tree.def >expout
521 AT_CHECK([$CC -o test0$EXEEXT test0.c && ./test0$EXEEXT], [0], [expout])
525 # Test the gen-tree features that avoid creating string labels for nodes.
526 AT_SETUP([gen-tree.awk @nostrtab option])
527 AT_KEYWORDS([gen-tree awk script scripts])
539 AT_CHECK([$AWK -f "$builddir/scripts/gen-tree.awk" <tree.def >tree.h])
542 [[float tree_strtab = 0;
551 static struct { int num, offset; } root[] = { ROOT_INITIALIZER };
556 for (i = 0; i < sizeof root / sizeof root[0]; i++) {
557 printf("%d, %d\n", root[i].num, root[i].offset);
563 AT_CHECK([$CC -o test0$EXEEXT test0.c && ./test0$EXEEXT], [0],
582 AT_CHECK([$AWK -f "$builddir/scripts/gen-tree.awk" <flat.def >flat.h])
584 sed -e 's/tree\.h/flat.h/' -e 's/ROOT/FLAT/' test0.c >test1.c
585 AT_CHECK([$CC -o test1$EXEEXT test1.c && ./test1$EXEEXT], [0],
595 AT_KEYWORDS([join awk script scripts])
597 JOIN="$AWK -f $builddir/scripts/join.awk --"
624 AT_CHECK([$JOIN a b], [0],
635 AT_CHECK([$JOIN -v1 a b], [0],
643 AT_CHECK([$JOIN -v2 a b], [0],
650 AT_CHECK([$JOIN -v1 -v2 a b], [0],
662 AT_CHECK([$JOIN -a1 a b], [0],
678 AT_CHECK([$JOIN -a2 a b], [0],
693 AT_CHECK([$JOIN -a1 -a2 a b], [0],
713 AT_CHECK([$JOIN b a], [0],
724 AT_CHECK([$JOIN -v1 b a], [0],
731 AT_CHECK([$JOIN -v2 b a], [0],
739 AT_CHECK([$JOIN -v1 -v2 b a], [0],
751 AT_CHECK([$JOIN -a1 b a], [0],
766 AT_CHECK([$JOIN -a2 b a], [0],
782 AT_CHECK([$JOIN -a1 -a2 b a], [0],
802 AT_CHECK([echo wat | $JOIN -v1 - /dev/null], [0],
808 m4_divert_push([PREPARE_TESTS])dnl
810 $PERL -e 'my $x = 42; exit $x;'; test $? = 42 || exit 77
811 $PERL -f "$srcdir/scripts/fix-ltdl.pl" "$@"
814 $PERL -e 'my $x = 42; exit $x;'; test $? = 42 || exit 77
815 $PERL -f "$srcdir/scripts/fix-gnulib.pl" "$@"
821 sed -n -f - "$srcdir/tests/data/gnulib.mk" <<EOF
822 /^## begin gnulib module $arg/,/^## end gnulib module $arg/p
826 m4_divert_pop([PREPARE_TESTS])
828 AT_SETUP([fix-gnulib.pl SED_HEADER variables])
830 test_gnulib_mk gen-header >test.mk.in
831 AT_CHECK([grep SED_HEADER test.mk.in >expout || exit 99])
832 AT_CHECK([test_fix_gnulib -i test.mk.in -o test.mk || exit
833 grep SED_HEADER test.mk], [0], [expout])
837 AT_SETUP([fix-gnulib.pl %reldir% substitution])
839 test_gnulib_mk sys_types >test.mk.in
840 AT_CHECK([grep '%reldir%' test.mk.in >/dev/null || exit 99])
842 sed -n -f - test.mk.in >expout <<'EOF'
844 /^## begin gnulib/,/^## end gnulib/!b
846 s|(srcdir)|(top_srcdir)|
848 s|BUILT_SOURCES|gnulib_core_headers|
850 /^MOSTLYCLEANFILES/{h;b}
854 AT_CHECK([test_fix_gnulib -i test.mk.in -o test.mk || exit
855 sed -n -e '/^## begin gnulib/,/^## end gnulib/p' \
856 -e '/CLEANFILES/p' test.mk],
861 AT_SETUP([fix-gnulib.pl warning removal])
863 AT_DATA([test.mk.in], [[
865 noinst_LTLIBRARIES += libgnu.la
866 libgnu_la_CFLAGS = $(AM_CFLAGS) $(GL_CFLAG_GNULIB_WARNINGS)
867 noinst_LIBRARIES += libgnu.a
868 libgnu_a_CFLAGS = $(AM_CFLAGS) $(GL_CFLAG_GNULIB_WARNINGS)
871 AT_CHECK([test_fix_gnulib -i test.mk.in -o test.mk || exit
872 sed -n '/^## test begin/,/^## test end/p' test.mk], [0], [## test begin
873 EXTRA_LTLIBRARIES += libgnu.la
874 EXTRA_LIBRARIES += libgnu.a
880 AT_SETUP([fix-gnulib.pl header directory creation])
882 AT_DATA([extract.sed],
898 test_gnulib_mk alloca-opt sys_types stddef >test.mk.in
899 AT_CHECK([test_fix_gnulib -i test.mk.in -o test.mk || exit
900 sed -n -f extract.sed test.mk], [0],
902 $(AM_V_GEN)$(MKDIR_P) lib
905 $(AM_V_GEN)$(MKDIR_P) lib/sys
908 $(AM_V_GEN)$(MKDIR_P) lib
914 dnl TEST_FIND_AUTOMAKE_VER([to-check], [test-action])
916 dnl For each whitespace-separated version token in to-check, check if we can
917 dnl run the programs automake-VER and aclocal-VER. The special token 'default'
918 dnl also checks the unversioned automake and aclocal (or, if set in the
919 dnl environment, $AUTOMAKE and $ACLOCAL).
921 dnl Then test-action is expanded such that shell variables $ac and $am refer to
922 dnl the aclocal and automake programs, and $amver is the actual version
923 dnl reported by --version. The action should do nothing if the version is
924 dnl acceptable, or "continue" if the version is unacceptable.
926 dnl If an acceptable version is found, the AUTOMAKE and ACLOCAL environment
927 dnl variables are set accordingly. Otherwise, the test group is skipped.
928 m4_define([TEST_FIND_AUTOMAKE],
932 [default], [ac=${ACLOCAL-aclocal} am=${AUTOMAKE-automake}],
933 [ac=aclocal-$am; am=automake-$am])
934 amver=`$am --version | sed -n '1s/.* //p'`
935 acver=`$ac --version | sed -n '1s/.* //p'`
936 set x $amver $acver; shift; test x"$[]#" = x"2" || continue
937 test x"$amver" = x"$acver" || continue
941 AT_CHECK([$have_am || exit 77])
942 AUTOMAKE=$am; export AUTOMAKE
943 ACLOCAL=$ac; export ACLOCAL
944 AT_CHECK([$ACLOCAL --version && $AUTOMAKE --version], [0], [stdout])
947 m4_define([TEST_LTDL_LIBOBJ_MANGLING],
948 [TEST_CONFIGURE_AC([[AM_INIT_AUTOMAKE([foreign subdir-objects])
951 AC_SUBST([ltdl_LTLIBOBJS], [libltdl/test.lo])
952 AC_CONFIG_FILES([Makefile])
956 AT_DATA([ltdl.mk.in], [[
957 AM_CPPFLAGS += -DSTRING=\"helloworld\"
959 noinst_LTLIBRARIES = libltdl/libltdl.la
960 libltdl_libltdl_la_SOURCES = libltdl/ltdl.c
961 libltdl_libltdl_la_LIBADD = $(ltdl_LTLIBOBJS)
962 libltdl_libltdl_la_DEPENDENCIES = $(ltdl_LTLIBOBJS)
964 EXTRA_DIST += libltdl/test.c
966 AT_DATA([Makefile.am], [[AM_CPPFLAGS =
967 include $(top_srcdir)/ltdl.mk
968 AM_LIBTOOLFLAGS = --quiet
971 test_LDADD = libltdl/libltdl.la
972 all-local: ; @printf '%s\n' $(AM_CPPFLAGS)
974 AT_DATA([libltdl/test.c], [[#include <stdio.h>
975 int foo(void) { printf("%s\n", STRING); return 0; }
977 AT_DATA([libltdl/ltdl.c], [[int foo(void); int main(void) { return foo(); }
980 AT_CHECK([test_fix_ltdl -i ltdl.mk.in -o ltdl.mk])
981 libtoolize; TEST_AUTORECONF
982 TEST_CONFIGURE([--disable-shared])
983 AT_CHECK([make -s && ./test], [0], [
987 AT_SETUP([fix-ltdl.pl LIBOBJ mangling (<automake-1.16)])
989 TEST_FIND_AUTOMAKE([default 1.10 1.11 1.12 1.13 1.14 1.15],
990 [AS_VERSION_COMPARE(["$amver"], [1.16], [], [continue], [continue])])
991 TEST_LTDL_LIBOBJ_MANGLING
995 AT_SETUP([fix-ltdl.pl LIBOBJ mangling (>=automake-1.16)])
997 TEST_FIND_AUTOMAKE([default 1.16 1.17 1.18 1.19],
998 [AS_VERSION_COMPARE(["$amver"], [1.16], [continue])])
999 TEST_LTDL_LIBOBJ_MANGLING