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-strtab.awk])
224 AT_KEYWORDS([gen-strtab awk script scripts])
249 AT_CHECK([$AWK -f "$builddir/scripts/gen-strtab.awk" <test.def >test.h])
251 sed -n 's/^[[&]]\([[^ ]]*\).*/\1/p' test.def >identifiers
253 # test 0: sanity test
262 exec 3<identifiers 4>>test0.c
263 while read ident <&3; do
264 AS_ECHO([' printf("%s\n---\n", '"strtab+$ident);"]) >&4
266 AS_ECHO([' return 0;']) >&4
270 AT_CHECK([$CC -o test0$EXEEXT test0.c && ./test0$EXEEXT], [0], [---
305 AT_SETUP([gen-strtab.awk @nozero option])
306 AT_KEYWORDS([gen-strtab awk script scripts])
311 AT_CHECK([$AWK -f "$builddir/scripts/gen-strtab.awk" <test0.def >test0.h])
317 AT_CHECK([$AWK -f "$builddir/scripts/gen-strtab.awk" <test1.def >test1.h])
322 int main(void) { printf("%d %s\n", hello, strtab+hello); return 0; }
324 AT_CHECK([$CC -DHEADER='"test0.h"' -o test0$EXEEXT test.c && ./test0$EXEEXT],
327 AT_CHECK([$CC -DHEADER='"test1.h"' -o test1$EXEEXT test.c && ./test1$EXEEXT],
333 AT_SETUP([gen-strtab.awk l10n options])
334 AT_KEYWORDS([gen-strtab awk script scripts])
336 AT_DATA([l10n.sed], dnl (
338 s/.*N_(\([^)]*\)).*/\1/p
346 AT_CHECK([$AWK -f "$builddir/scripts/gen-strtab.awk" <test0.def >test0.h])
347 AT_CHECK([sed -n -f l10n.sed test0.h | LC_ALL=C sort], [0],
358 AT_CHECK([$AWK -f "$builddir/scripts/gen-strtab.awk" <test1.def >test1.h])
359 AT_CHECK([sed -n -f l10n.sed test1.h], [0],
369 printf("%s %s %s\n", strtab+a, strtab+b, strtab+c);
374 AT_CHECK([$CC -DHEADER='"test0.h"' -o test0$EXEEXT test.c && ./test0$EXEEXT],
375 [0], [[hello world world goodbye
378 AT_CHECK([$CC -DHEADER='"test1.h"' -o test1$EXEEXT test.c && ./test1$EXEEXT],
379 [0], [[hello world world goodbye
385 AT_SETUP([gen-tree.awk])
386 AT_KEYWORDS([gen-tree awk script scripts])
413 AT_CHECK([$AWK -f "$builddir/scripts/gen-tree.awk" <tree.def >tree.h])
419 struct tree { unsigned id, subtree; };
421 static const struct tree tree0[] = {
424 static const struct tree tree1[] = {
428 void print_subtree(const struct tree *root, unsigned offset, int depth)
430 const struct tree *node;
432 for (node = &root[offset]; node->id; node++) {
433 printf("%*s%s", 2*depth, "", &tree_strtab[node->id]);
435 printf(", %s_OFFSET\n", &tree_strtab[node->id]);
436 print_subtree(root, node->subtree, depth+1);
446 print_subtree(tree0, 0, 1);
448 print_subtree(tree1, 0, 1);
452 sed '/^#/d' tree.def >expout
453 AT_CHECK([$CC -o test0$EXEEXT test0.c && ./test0$EXEEXT], [0], [expout])
457 # Test the gen-tree features that avoid creating string labels for nodes.
458 AT_SETUP([gen-tree.awk @nostrtab option])
459 AT_KEYWORDS([gen-tree awk script scripts])
471 AT_CHECK([$AWK -f "$builddir/scripts/gen-tree.awk" <tree.def >tree.h])
474 [[float tree_strtab = 0;
483 static struct { int num, offset; } root[] = { ROOT_INITIALIZER };
488 for (i = 0; i < sizeof root / sizeof root[0]; i++) {
489 printf("%d, %d\n", root[i].num, root[i].offset);
494 AT_CHECK([$CC -o test0$EXEEXT test0.c && ./test0$EXEEXT], [0],
513 AT_CHECK([$AWK -f "$builddir/scripts/gen-tree.awk" <flat.def >flat.h])
515 sed -e 's/tree\.h/flat.h/' -e 's/ROOT/FLAT/' test0.c >test1.c
516 AT_CHECK([$CC -o test1$EXEEXT test1.c && ./test1$EXEEXT], [0],
526 AT_KEYWORDS([join awk script scripts])
528 JOIN="$AWK -f $builddir/scripts/join.awk --"
555 AT_CHECK([$JOIN a b], [0],
566 AT_CHECK([$JOIN -v1 a b], [0],
574 AT_CHECK([$JOIN -v2 a b], [0],
581 AT_CHECK([$JOIN -v1 -v2 a b], [0],
593 AT_CHECK([$JOIN -a1 a b], [0],
609 AT_CHECK([$JOIN -a2 a b], [0],
624 AT_CHECK([$JOIN -a1 -a2 a b], [0],
644 AT_CHECK([$JOIN b a], [0],
655 AT_CHECK([$JOIN -v1 b a], [0],
662 AT_CHECK([$JOIN -v2 b a], [0],
670 AT_CHECK([$JOIN -v1 -v2 b a], [0],
682 AT_CHECK([$JOIN -a1 b a], [0],
697 AT_CHECK([$JOIN -a2 b a], [0],
713 AT_CHECK([$JOIN -a1 -a2 b a], [0],
733 AT_CHECK([echo wat | $JOIN -v1 - /dev/null], [0],
739 m4_divert_push([PREPARE_TESTS])dnl
741 $PERL -e 'my $x = 42; exit $x;'; test $? = 42 || exit 77
742 $PERL -f "$srcdir/scripts/fix-ltdl.pl" "$@"
745 $PERL -e 'my $x = 42; exit $x;'; test $? = 42 || exit 77
746 $PERL -f "$srcdir/scripts/fix-gnulib.pl" "$@"
752 sed -n -f - "$srcdir/tests/data/gnulib.mk" <<EOF
753 /^## begin gnulib module $arg/,/^## end gnulib module $arg/p
757 m4_divert_pop([PREPARE_TESTS])
759 AT_SETUP([fix-gnulib.pl SED_HEADER variables])
761 test_gnulib_mk gen-header >test.mk.in
762 AT_CHECK([grep SED_HEADER test.mk.in >expout || exit 99])
763 AT_CHECK([test_fix_gnulib -i test.mk.in -o test.mk || exit
764 grep SED_HEADER test.mk], [0], [expout])
768 AT_SETUP([fix-gnulib.pl %reldir% substitution])
770 test_gnulib_mk sys_types >test.mk.in
771 AT_CHECK([grep '%reldir%' test.mk.in >/dev/null || exit 99])
773 sed -n -f - test.mk.in >expout <<'EOF'
775 /^## begin gnulib/,/^## end gnulib/!b
777 s|(srcdir)|(top_srcdir)|
779 s|BUILT_SOURCES|gnulib_core_headers|
781 /^MOSTLYCLEANFILES/{h;b}
785 AT_CHECK([test_fix_gnulib -i test.mk.in -o test.mk || exit
786 sed -n -e '/^## begin gnulib/,/^## end gnulib/p' \
787 -e '/CLEANFILES/p' test.mk],
792 AT_SETUP([fix-gnulib.pl warning removal])
794 AT_DATA([test.mk.in], [[
796 noinst_LTLIBRARIES += libgnu.la
797 libgnu_la_CFLAGS = $(AM_CFLAGS) $(GL_CFLAG_GNULIB_WARNINGS)
798 noinst_LIBRARIES += libgnu.a
799 libgnu_a_CFLAGS = $(AM_CFLAGS) $(GL_CFLAG_GNULIB_WARNINGS)
802 AT_CHECK([test_fix_gnulib -i test.mk.in -o test.mk || exit
803 sed -n '/^## test begin/,/^## test end/p' test.mk], [0], [## test begin
804 EXTRA_LTLIBRARIES += libgnu.la
805 EXTRA_LIBRARIES += libgnu.a
811 AT_SETUP([fix-gnulib.pl header directory creation])
813 AT_DATA([extract.sed],
829 test_gnulib_mk alloca-opt sys_types stddef >test.mk.in
830 AT_CHECK([test_fix_gnulib -i test.mk.in -o test.mk || exit
831 sed -n -f extract.sed test.mk], [0],
833 $(AM_V_GEN)$(MKDIR_P) lib
836 $(AM_V_GEN)$(MKDIR_P) lib/sys
839 $(AM_V_GEN)$(MKDIR_P) lib
845 dnl TEST_FIND_AUTOMAKE_VER([to-check], [test-action])
847 dnl For each whitespace-separated version token in to-check, check if we can
848 dnl run the programs automake-VER and aclocal-VER. The special token 'default'
849 dnl also checks the unversioned automake and aclocal (or, if set in the
850 dnl environment, $AUTOMAKE and $ACLOCAL).
852 dnl Then test-action is expanded such that shell variables $ac and $am refer to
853 dnl the aclocal and automake programs, and $amver is the actual version
854 dnl reported by --version. The action should do nothing if the version is
855 dnl acceptable, or "continue" if the version is unacceptable.
857 dnl If an acceptable version is found, the AUTOMAKE and ACLOCAL environment
858 dnl variables are set accordingly. Otherwise, the test group is skipped.
859 m4_define([TEST_FIND_AUTOMAKE],
863 [default], [ac=${ACLOCAL-aclocal} am=${AUTOMAKE-automake}],
864 [ac=aclocal-$am; am=automake-$am])
865 amver=`$am --version | sed -n '1s/.* //p'`
866 acver=`$ac --version | sed -n '1s/.* //p'`
867 set x $amver $acver; shift; test x"$[]#" = x"2" || continue
868 test x"$amver" = x"$acver" || continue
872 AT_CHECK([$have_am || exit 77])
873 AUTOMAKE=$am; export AUTOMAKE
874 ACLOCAL=$ac; export ACLOCAL
875 AT_CHECK([$ACLOCAL --version && $AUTOMAKE --version], [0], [stdout])
878 m4_define([TEST_LTDL_LIBOBJ_MANGLING],
879 [TEST_CONFIGURE_AC([[AM_INIT_AUTOMAKE([foreign subdir-objects])
882 AC_SUBST([ltdl_LTLIBOBJS], [libltdl/test.lo])
883 AC_CONFIG_FILES([Makefile])
887 AT_DATA([ltdl.mk.in], [[
888 AM_CPPFLAGS += -DSTRING=\"helloworld\"
890 noinst_LTLIBRARIES = libltdl/libltdl.la
891 libltdl_libltdl_la_SOURCES = libltdl/ltdl.c
892 libltdl_libltdl_la_LIBADD = $(ltdl_LTLIBOBJS)
893 libltdl_libltdl_la_DEPENDENCIES = $(ltdl_LTLIBOBJS)
895 EXTRA_DIST += libltdl/test.c
897 AT_DATA([Makefile.am], [[AM_CPPFLAGS =
898 include $(top_srcdir)/ltdl.mk
899 AM_LIBTOOLFLAGS = --quiet
902 test_LDADD = libltdl/libltdl.la
903 all-local: ; @printf '%s\n' $(AM_CPPFLAGS)
905 AT_DATA([libltdl/test.c], [[#include <stdio.h>
906 int foo(void) { printf("%s\n", STRING); return 0; }
908 AT_DATA([libltdl/ltdl.c], [[int foo(void); int main(void) { return foo(); }
911 AT_CHECK([test_fix_ltdl -i ltdl.mk.in -o ltdl.mk])
912 libtoolize; TEST_AUTORECONF
913 TEST_CONFIGURE([--disable-shared])
914 AT_CHECK([make -s && ./test], [0], [
918 AT_SETUP([fix-ltdl.pl LIBOBJ mangling (<automake-1.16)])
920 TEST_FIND_AUTOMAKE([default 1.10 1.11 1.12 1.13 1.14 1.15],
921 [AS_VERSION_COMPARE(["$amver"], [1.16], [], [continue], [continue])])
922 TEST_LTDL_LIBOBJ_MANGLING
926 AT_SETUP([fix-ltdl.pl LIBOBJ mangling (>=automake-1.16)])
928 TEST_FIND_AUTOMAKE([default 1.16 1.17 1.18 1.19],
929 [AS_VERSION_COMPARE(["$amver"], [1.16], [continue])])
930 TEST_LTDL_LIBOBJ_MANGLING