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] != ':')
178 s/^-\([[^-]]\)[[^:]]*/\1/p
180 }' options.def >sopts
182 exec 3<options 4<sopts 5>expout
183 while read lopt <&3 && read sopt <&4; do
184 if test ${sopt:+y}; then
185 AS_ECHO(["--$lopt $sopt"]) >&5
190 AT_CHECK([$CC -o test2$EXEEXT test2.c && ./test2$EXEEXT],
191 [0], [expout], [ignore])
193 # Check that all help strings are translatable
194 sed 's/\([[^\\]]\\\)" /\1\\n\\" /g' helptext >help-po
195 exec 3<options 4<argnames 5<help-po 6>expected.po
196 while read opt <&3 && read arg <&4 && read help <&5; do
197 if test ${arg:+y}; then
198 AS_ECHO(["msgctxt \"$opt\" msgid \"$arg\""]) >&6
200 AS_ECHO(["msgctxt \"$opt\" msgid${help:+ }$help"]) >&6
202 exec 3<&- 4<&- 5<&- 6>&-
204 AT_CHECK([xgettext --keyword=PN_:1c,2 options.h
205 test -f messages.po || exit 77])
207 LC_ALL=C sort expected.po >expout
208 AT_CHECK([sed -n '/^msgctxt/{
219 }' messages.po | LC_ALL=C sort], [0], [expout])
223 AT_SETUP([gen-options.awk packed format])
224 AT_KEYWORDS([gen-options awk script scripts])
226 AT_DATA([test.c], [[#include <stdio.h>
227 struct option { const char *name; int has_arg; int *flag; int val; };
231 static unsigned opts[] = { LOPTS_PACKED_INITIALIZER };
239 #elif LOPT_PACK_BITS <= 8
241 #elif LOPT_PACK_BITS <= 16
243 #elif LOPT_PACK_BITS <= 32
250 for (i = 0; i < sizeof opts / sizeof opts[0]; i++) {
253 LOPT_UNPACK(o, opts[i]);
254 printf("--%s, %d, ", o.name, o.has_arg);
255 if (o.val > UCHAR_MAX)
256 printf("%d\n", o.val - UCHAR_MAX - 1);
258 printf("'%c'\n", o.val);
263 AT_DATA([single.dat],
266 AT_CHECK([$AWK -f "$builddir/scripts/gen-options.awk" <single.dat >options.h])
267 AT_CHECK([$CC -o single$EXEEXT test.c && ./single$EXEEXT], [0],
269 --single-option, 0, 0
273 [[-a, --the-first-option
274 -b, --the-second-option=ARG
275 -c, --the-third-option[=ARG]
276 -d, --the-fourth-option
278 AT_CHECK([$AWK -f "$builddir/scripts/gen-options.awk" <16bit.dat >options.h])
279 AT_CHECK([$CC -o 16bit$EXEEXT test.c && ./16bit$EXEEXT], [0],
281 --the-first-option, 0, 'a'
282 --the-second-option, 1, 'b'
283 --the-third-option, 2, 'c'
284 --the-fourth-option, 0, 'd'
289 AT_SETUP([gen-strtab.awk])
290 AT_KEYWORDS([gen-strtab awk script scripts])
315 AT_CHECK([$AWK -f "$builddir/scripts/gen-strtab.awk" <test.def >test.h])
317 sed -n 's/^[[&]]\([[^ ]]*\).*/\1/p' test.def >identifiers
319 # test 0: sanity test
328 exec 3<identifiers 4>>test0.c
329 while read ident <&3; do
330 AS_ECHO([' printf("%s\n---\n", '"strtab+$ident);"]) >&4
332 AS_ECHO([' return 0;']) >&4
336 AT_CHECK([$CC -o test0$EXEEXT test0.c && ./test0$EXEEXT], [0], [---
371 AT_SETUP([gen-strtab.awk @nozero option])
372 AT_KEYWORDS([gen-strtab awk script scripts])
377 AT_CHECK([$AWK -f "$builddir/scripts/gen-strtab.awk" <test0.def >test0.h])
383 AT_CHECK([$AWK -f "$builddir/scripts/gen-strtab.awk" <test1.def >test1.h])
388 int main(void) { printf("%d %s\n", hello, strtab+hello); return 0; }
390 AT_CHECK([$CC -DHEADER='"test0.h"' -o test0$EXEEXT test.c && ./test0$EXEEXT],
393 AT_CHECK([$CC -DHEADER='"test1.h"' -o test1$EXEEXT test.c && ./test1$EXEEXT],
399 AT_SETUP([gen-strtab.awk l10n options])
400 AT_KEYWORDS([gen-strtab awk script scripts])
402 AT_DATA([l10n.sed], dnl (
404 s/.*N_(\([^)]*\)).*/\1/p
412 AT_CHECK([$AWK -f "$builddir/scripts/gen-strtab.awk" <test0.def >test0.h])
413 AT_CHECK([sed -n -f l10n.sed test0.h | LC_ALL=C sort], [0],
424 AT_CHECK([$AWK -f "$builddir/scripts/gen-strtab.awk" <test1.def >test1.h])
425 AT_CHECK([sed -n -f l10n.sed test1.h], [0],
435 printf("%s %s %s\n", strtab+a, strtab+b, strtab+c);
440 AT_CHECK([$CC -DHEADER='"test0.h"' -o test0$EXEEXT test.c && ./test0$EXEEXT],
441 [0], [[hello world world goodbye
444 AT_CHECK([$CC -DHEADER='"test1.h"' -o test1$EXEEXT test.c && ./test1$EXEEXT],
445 [0], [[hello world world goodbye
451 AT_SETUP([gen-tree.awk])
452 AT_KEYWORDS([gen-tree awk script scripts])
479 AT_CHECK([$AWK -f "$builddir/scripts/gen-tree.awk" <tree.def >tree.h])
485 struct tree { unsigned id, subtree; };
487 static const struct tree tree0[] = {
490 static const struct tree tree1[] = {
494 void print_subtree(const struct tree *root, unsigned offset, int depth)
496 const struct tree *node;
498 for (node = &root[offset]; node->id; node++) {
499 printf("%*s%s", 2*depth, "", &tree_strtab[node->id]);
501 printf(", %s_OFFSET\n", &tree_strtab[node->id]);
502 print_subtree(root, node->subtree, depth+1);
512 print_subtree(tree0, 0, 1);
514 print_subtree(tree1, 0, 1);
518 sed '/^#/d' tree.def >expout
519 AT_CHECK([$CC -o test0$EXEEXT test0.c && ./test0$EXEEXT], [0], [expout])
523 # Test the gen-tree features that avoid creating string labels for nodes.
524 AT_SETUP([gen-tree.awk @nostrtab option])
525 AT_KEYWORDS([gen-tree awk script scripts])
537 AT_CHECK([$AWK -f "$builddir/scripts/gen-tree.awk" <tree.def >tree.h])
540 [[float tree_strtab = 0;
549 static struct { int num, offset; } root[] = { ROOT_INITIALIZER };
554 for (i = 0; i < sizeof root / sizeof root[0]; i++) {
555 printf("%d, %d\n", root[i].num, root[i].offset);
560 AT_CHECK([$CC -o test0$EXEEXT test0.c && ./test0$EXEEXT], [0],
579 AT_CHECK([$AWK -f "$builddir/scripts/gen-tree.awk" <flat.def >flat.h])
581 sed -e 's/tree\.h/flat.h/' -e 's/ROOT/FLAT/' test0.c >test1.c
582 AT_CHECK([$CC -o test1$EXEEXT test1.c && ./test1$EXEEXT], [0],
592 AT_KEYWORDS([join awk script scripts])
594 JOIN="$AWK -f $builddir/scripts/join.awk --"
621 AT_CHECK([$JOIN a b], [0],
632 AT_CHECK([$JOIN -v1 a b], [0],
640 AT_CHECK([$JOIN -v2 a b], [0],
647 AT_CHECK([$JOIN -v1 -v2 a b], [0],
659 AT_CHECK([$JOIN -a1 a b], [0],
675 AT_CHECK([$JOIN -a2 a b], [0],
690 AT_CHECK([$JOIN -a1 -a2 a b], [0],
710 AT_CHECK([$JOIN b a], [0],
721 AT_CHECK([$JOIN -v1 b a], [0],
728 AT_CHECK([$JOIN -v2 b a], [0],
736 AT_CHECK([$JOIN -v1 -v2 b a], [0],
748 AT_CHECK([$JOIN -a1 b a], [0],
763 AT_CHECK([$JOIN -a2 b a], [0],
779 AT_CHECK([$JOIN -a1 -a2 b a], [0],
799 AT_CHECK([echo wat | $JOIN -v1 - /dev/null], [0],
805 m4_divert_push([PREPARE_TESTS])dnl
807 $PERL -e 'my $x = 42; exit $x;'; test $? = 42 || exit 77
808 $PERL -f "$srcdir/scripts/fix-ltdl.pl" "$@"
811 $PERL -e 'my $x = 42; exit $x;'; test $? = 42 || exit 77
812 $PERL -f "$srcdir/scripts/fix-gnulib.pl" "$@"
818 sed -n -f - "$srcdir/tests/data/gnulib.mk" <<EOF
819 /^## begin gnulib module $arg/,/^## end gnulib module $arg/p
823 m4_divert_pop([PREPARE_TESTS])
825 AT_SETUP([fix-gnulib.pl SED_HEADER variables])
827 test_gnulib_mk gen-header >test.mk.in
828 AT_CHECK([grep SED_HEADER test.mk.in >expout || exit 99])
829 AT_CHECK([test_fix_gnulib -i test.mk.in -o test.mk || exit
830 grep SED_HEADER test.mk], [0], [expout])
834 AT_SETUP([fix-gnulib.pl %reldir% substitution])
836 test_gnulib_mk sys_types >test.mk.in
837 AT_CHECK([grep '%reldir%' test.mk.in >/dev/null || exit 99])
839 sed -n -f - test.mk.in >expout <<'EOF'
841 /^## begin gnulib/,/^## end gnulib/!b
843 s|(srcdir)|(top_srcdir)|
845 s|BUILT_SOURCES|gnulib_core_headers|
847 /^MOSTLYCLEANFILES/{h;b}
851 AT_CHECK([test_fix_gnulib -i test.mk.in -o test.mk || exit
852 sed -n -e '/^## begin gnulib/,/^## end gnulib/p' \
853 -e '/CLEANFILES/p' test.mk],
858 AT_SETUP([fix-gnulib.pl warning removal])
860 AT_DATA([test.mk.in], [[
862 noinst_LTLIBRARIES += libgnu.la
863 libgnu_la_CFLAGS = $(AM_CFLAGS) $(GL_CFLAG_GNULIB_WARNINGS)
864 noinst_LIBRARIES += libgnu.a
865 libgnu_a_CFLAGS = $(AM_CFLAGS) $(GL_CFLAG_GNULIB_WARNINGS)
868 AT_CHECK([test_fix_gnulib -i test.mk.in -o test.mk || exit
869 sed -n '/^## test begin/,/^## test end/p' test.mk], [0], [## test begin
870 EXTRA_LTLIBRARIES += libgnu.la
871 EXTRA_LIBRARIES += libgnu.a
877 AT_SETUP([fix-gnulib.pl header directory creation])
879 AT_DATA([extract.sed],
895 test_gnulib_mk alloca-opt sys_types stddef >test.mk.in
896 AT_CHECK([test_fix_gnulib -i test.mk.in -o test.mk || exit
897 sed -n -f extract.sed test.mk], [0],
899 $(AM_V_GEN)$(MKDIR_P) lib
902 $(AM_V_GEN)$(MKDIR_P) lib/sys
905 $(AM_V_GEN)$(MKDIR_P) lib
911 dnl TEST_FIND_AUTOMAKE_VER([to-check], [test-action])
913 dnl For each whitespace-separated version token in to-check, check if we can
914 dnl run the programs automake-VER and aclocal-VER. The special token 'default'
915 dnl also checks the unversioned automake and aclocal (or, if set in the
916 dnl environment, $AUTOMAKE and $ACLOCAL).
918 dnl Then test-action is expanded such that shell variables $ac and $am refer to
919 dnl the aclocal and automake programs, and $amver is the actual version
920 dnl reported by --version. The action should do nothing if the version is
921 dnl acceptable, or "continue" if the version is unacceptable.
923 dnl If an acceptable version is found, the AUTOMAKE and ACLOCAL environment
924 dnl variables are set accordingly. Otherwise, the test group is skipped.
925 m4_define([TEST_FIND_AUTOMAKE],
929 [default], [ac=${ACLOCAL-aclocal} am=${AUTOMAKE-automake}],
930 [ac=aclocal-$am; am=automake-$am])
931 amver=`$am --version | sed -n '1s/.* //p'`
932 acver=`$ac --version | sed -n '1s/.* //p'`
933 set x $amver $acver; shift; test x"$[]#" = x"2" || continue
934 test x"$amver" = x"$acver" || continue
938 AT_CHECK([$have_am || exit 77])
939 AUTOMAKE=$am; export AUTOMAKE
940 ACLOCAL=$ac; export ACLOCAL
941 AT_CHECK([$ACLOCAL --version && $AUTOMAKE --version], [0], [stdout])
944 m4_define([TEST_LTDL_LIBOBJ_MANGLING],
945 [TEST_CONFIGURE_AC([[AM_INIT_AUTOMAKE([foreign subdir-objects])
948 AC_SUBST([ltdl_LTLIBOBJS], [libltdl/test.lo])
949 AC_CONFIG_FILES([Makefile])
953 AT_DATA([ltdl.mk.in], [[
954 AM_CPPFLAGS += -DSTRING=\"helloworld\"
956 noinst_LTLIBRARIES = libltdl/libltdl.la
957 libltdl_libltdl_la_SOURCES = libltdl/ltdl.c
958 libltdl_libltdl_la_LIBADD = $(ltdl_LTLIBOBJS)
959 libltdl_libltdl_la_DEPENDENCIES = $(ltdl_LTLIBOBJS)
961 EXTRA_DIST += libltdl/test.c
963 AT_DATA([Makefile.am], [[AM_CPPFLAGS =
964 include $(top_srcdir)/ltdl.mk
965 AM_LIBTOOLFLAGS = --quiet
968 test_LDADD = libltdl/libltdl.la
969 all-local: ; @printf '%s\n' $(AM_CPPFLAGS)
971 AT_DATA([libltdl/test.c], [[#include <stdio.h>
972 int foo(void) { printf("%s\n", STRING); return 0; }
974 AT_DATA([libltdl/ltdl.c], [[int foo(void); int main(void) { return foo(); }
977 AT_CHECK([test_fix_ltdl -i ltdl.mk.in -o ltdl.mk])
978 libtoolize; TEST_AUTORECONF
979 TEST_CONFIGURE([--disable-shared])
980 AT_CHECK([make -s && ./test], [0], [
984 AT_SETUP([fix-ltdl.pl LIBOBJ mangling (<automake-1.16)])
986 TEST_FIND_AUTOMAKE([default 1.10 1.11 1.12 1.13 1.14 1.15],
987 [AS_VERSION_COMPARE(["$amver"], [1.16], [], [continue], [continue])])
988 TEST_LTDL_LIBOBJ_MANGLING
992 AT_SETUP([fix-ltdl.pl LIBOBJ mangling (>=automake-1.16)])
994 TEST_FIND_AUTOMAKE([default 1.16 1.17 1.18 1.19],
995 [AS_VERSION_COMPARE(["$amver"], [1.16], [continue])])
996 TEST_LTDL_LIBOBJ_MANGLING