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 l10n options])
405 AT_KEYWORDS([gen-strtab awk script scripts])
407 AT_DATA([l10n.sed], dnl (
409 s/.*N_(\([^)]*\)).*/\1/p
417 AT_CHECK([$AWK -f "$builddir/scripts/gen-strtab.awk" <test0.def >test0.h])
418 AT_CHECK([sed -n -f l10n.sed test0.h | LC_ALL=C sort], [0],
429 AT_CHECK([$AWK -f "$builddir/scripts/gen-strtab.awk" <test1.def >test1.h])
430 AT_CHECK([sed -n -f l10n.sed test1.h], [0],
440 printf("%s %s %s\n", strtab+a, strtab+b, strtab+c);
445 AT_CHECK([$CC -DHEADER='"test0.h"' -o test0$EXEEXT test.c && ./test0$EXEEXT],
446 [0], [[hello world world goodbye
449 AT_CHECK([$CC -DHEADER='"test1.h"' -o test1$EXEEXT test.c && ./test1$EXEEXT],
450 [0], [[hello world world goodbye
456 AT_SETUP([gen-tree.awk])
457 AT_KEYWORDS([gen-tree awk script scripts])
484 AT_CHECK([$AWK -f "$builddir/scripts/gen-tree.awk" <tree.def >tree.h])
490 struct tree { unsigned id, subtree; };
492 static const struct tree tree0[] = {
495 static const struct tree tree1[] = {
499 void print_subtree(const struct tree *root, unsigned offset, int depth)
501 const struct tree *node;
503 for (node = &root[offset]; node->id; node++) {
504 printf("%*s%s", 2*depth, "", &tree_strtab[node->id]);
506 printf(", %s_OFFSET\n", &tree_strtab[node->id]);
507 print_subtree(root, node->subtree, depth+1);
517 print_subtree(tree0, 0, 1);
519 print_subtree(tree1, 0, 1);
523 sed '/^#/d' tree.def >expout
524 AT_CHECK([$CC -o test0$EXEEXT test0.c && ./test0$EXEEXT], [0], [expout])
528 # Test the gen-tree features that avoid creating string labels for nodes.
529 AT_SETUP([gen-tree.awk @nostrtab option])
530 AT_KEYWORDS([gen-tree awk script scripts])
542 AT_CHECK([$AWK -f "$builddir/scripts/gen-tree.awk" <tree.def >tree.h])
545 [[float tree_strtab = 0;
554 static struct { int num, offset; } root[] = { ROOT_INITIALIZER };
559 for (i = 0; i < sizeof root / sizeof root[0]; i++) {
560 printf("%d, %d\n", root[i].num, root[i].offset);
566 AT_CHECK([$CC -o test0$EXEEXT test0.c && ./test0$EXEEXT], [0],
585 AT_CHECK([$AWK -f "$builddir/scripts/gen-tree.awk" <flat.def >flat.h])
587 sed -e 's/tree\.h/flat.h/' -e 's/ROOT/FLAT/' test0.c >test1.c
588 AT_CHECK([$CC -o test1$EXEEXT test1.c && ./test1$EXEEXT], [0],
598 AT_KEYWORDS([join awk script scripts])
600 JOIN="$AWK -f $builddir/scripts/join.awk --"
627 AT_CHECK([$JOIN a b], [0],
638 AT_CHECK([$JOIN -v1 a b], [0],
646 AT_CHECK([$JOIN -v2 a b], [0],
653 AT_CHECK([$JOIN -v1 -v2 a b], [0],
665 AT_CHECK([$JOIN -a1 a b], [0],
681 AT_CHECK([$JOIN -a2 a b], [0],
696 AT_CHECK([$JOIN -a1 -a2 a b], [0],
716 AT_CHECK([$JOIN b a], [0],
727 AT_CHECK([$JOIN -v1 b a], [0],
734 AT_CHECK([$JOIN -v2 b a], [0],
742 AT_CHECK([$JOIN -v1 -v2 b a], [0],
754 AT_CHECK([$JOIN -a1 b a], [0],
769 AT_CHECK([$JOIN -a2 b a], [0],
785 AT_CHECK([$JOIN -a1 -a2 b a], [0],
805 AT_CHECK([echo wat | $JOIN -v1 - /dev/null], [0],
811 m4_divert_push([PREPARE_TESTS])dnl
813 $PERL -e 'my $x = 42; exit $x;'; test $? = 42 || exit 77
814 $PERL -f "$srcdir/scripts/fix-ltdl.pl" "$@"
817 $PERL -e 'my $x = 42; exit $x;'; test $? = 42 || exit 77
818 $PERL -f "$srcdir/scripts/fix-gnulib.pl" "$@"
824 sed -n -f - "$srcdir/tests/data/gnulib.mk" <<EOF
825 /^## begin gnulib module $arg/,/^## end gnulib module $arg/p
829 m4_divert_pop([PREPARE_TESTS])
831 AT_SETUP([fix-gnulib.pl SED_HEADER variables])
833 test_gnulib_mk gen-header >test.mk.in
834 AT_CHECK([grep SED_HEADER test.mk.in >expout || exit 99])
835 AT_CHECK([test_fix_gnulib -i test.mk.in -o test.mk || exit
836 grep SED_HEADER test.mk], [0], [expout])
840 AT_SETUP([fix-gnulib.pl %reldir% substitution])
842 test_gnulib_mk sys_types >test.mk.in
843 AT_CHECK([grep '%reldir%' test.mk.in >/dev/null || exit 99])
845 sed -n -f - test.mk.in >expout <<'EOF'
847 /^## begin gnulib/,/^## end gnulib/!b
849 s|(srcdir)|(top_srcdir)|
851 s|BUILT_SOURCES|gnulib_core_headers|
853 /^MOSTLYCLEANFILES/{h;b}
857 AT_CHECK([test_fix_gnulib -i test.mk.in -o test.mk || exit
858 sed -n -e '/^## begin gnulib/,/^## end gnulib/p' \
859 -e '/CLEANFILES/p' test.mk],
864 AT_SETUP([fix-gnulib.pl warning removal])
866 AT_DATA([test.mk.in], [[
868 noinst_LTLIBRARIES += libgnu.la
869 libgnu_la_CFLAGS = $(AM_CFLAGS) $(GL_CFLAG_GNULIB_WARNINGS)
870 noinst_LIBRARIES += libgnu.a
871 libgnu_a_CFLAGS = $(AM_CFLAGS) $(GL_CFLAG_GNULIB_WARNINGS)
874 AT_CHECK([test_fix_gnulib -i test.mk.in -o test.mk || exit
875 sed -n '/^## test begin/,/^## test end/p' test.mk], [0], [## test begin
876 EXTRA_LTLIBRARIES += libgnu.la
877 EXTRA_LIBRARIES += libgnu.a
883 AT_SETUP([fix-gnulib.pl header directory creation])
885 AT_DATA([extract.sed],
901 test_gnulib_mk alloca-opt sys_types stddef >test.mk.in
902 AT_CHECK([test_fix_gnulib -i test.mk.in -o test.mk || exit
903 sed -n -f extract.sed test.mk], [0],
905 $(AM_V_GEN)$(MKDIR_P) lib
908 $(AM_V_GEN)$(MKDIR_P) lib/sys
911 $(AM_V_GEN)$(MKDIR_P) lib
917 dnl TEST_FIND_AUTOMAKE_VER([to-check], [test-action])
919 dnl For each whitespace-separated version token in to-check, check if we can
920 dnl run the programs automake-VER and aclocal-VER. The special token 'default'
921 dnl also checks the unversioned automake and aclocal (or, if set in the
922 dnl environment, $AUTOMAKE and $ACLOCAL).
924 dnl Then test-action is expanded such that shell variables $ac and $am refer to
925 dnl the aclocal and automake programs, and $amver is the actual version
926 dnl reported by --version. The action should do nothing if the version is
927 dnl acceptable, or "continue" if the version is unacceptable.
929 dnl If an acceptable version is found, the AUTOMAKE and ACLOCAL environment
930 dnl variables are set accordingly. Otherwise, the test group is skipped.
931 m4_define([TEST_FIND_AUTOMAKE],
935 [default], [ac=${ACLOCAL-aclocal} am=${AUTOMAKE-automake}],
936 [ac=aclocal-$am; am=automake-$am])
937 amver=`$am --version | sed -n '1s/.* //p'`
938 acver=`$ac --version | sed -n '1s/.* //p'`
939 set x $amver $acver; shift; test x"$[]#" = x"2" || continue
940 test x"$amver" = x"$acver" || continue
944 AT_CHECK([$have_am || exit 77])
945 AUTOMAKE=$am; export AUTOMAKE
946 ACLOCAL=$ac; export ACLOCAL
947 AT_CHECK([$ACLOCAL --version && $AUTOMAKE --version], [0], [stdout])
950 m4_define([TEST_LTDL_LIBOBJ_MANGLING],
951 [TEST_CONFIGURE_AC([[AM_INIT_AUTOMAKE([foreign subdir-objects])
954 AC_SUBST([ltdl_LTLIBOBJS], [libltdl/test.lo])
955 AC_CONFIG_FILES([Makefile])
959 AT_DATA([ltdl.mk.in], [[
960 AM_CPPFLAGS += -DSTRING=\"helloworld\"
962 noinst_LTLIBRARIES = libltdl/libltdl.la
963 libltdl_libltdl_la_SOURCES = libltdl/ltdl.c
964 libltdl_libltdl_la_LIBADD = $(ltdl_LTLIBOBJS)
965 libltdl_libltdl_la_DEPENDENCIES = $(ltdl_LTLIBOBJS)
967 EXTRA_DIST += libltdl/test.c
969 AT_DATA([Makefile.am], [[AM_CPPFLAGS =
970 include $(top_srcdir)/ltdl.mk
971 AM_LIBTOOLFLAGS = --quiet
974 test_LDADD = libltdl/libltdl.la
975 all-local: ; @printf '%s\n' $(AM_CPPFLAGS)
977 AT_DATA([libltdl/test.c], [[#include <stdio.h>
978 int foo(void) { printf("%s\n", STRING); return 0; }
980 AT_DATA([libltdl/ltdl.c], [[int foo(void); int main(void) { return foo(); }
983 AT_CHECK([test_fix_ltdl -i ltdl.mk.in -o ltdl.mk])
984 libtoolize; TEST_AUTORECONF
985 TEST_CONFIGURE([--disable-shared])
986 AT_CHECK([make -s && ./test], [0], [
990 AT_SETUP([fix-ltdl.pl LIBOBJ mangling (<automake-1.16)])
992 TEST_FIND_AUTOMAKE([default 1.10 1.11 1.12 1.13 1.14 1.15],
993 [AS_VERSION_COMPARE(["$amver"], [1.16], [], [continue], [continue])])
994 TEST_LTDL_LIBOBJ_MANGLING
998 AT_SETUP([fix-ltdl.pl LIBOBJ mangling (>=automake-1.16)])
1000 TEST_FIND_AUTOMAKE([default 1.16 1.17 1.18 1.19],
1001 [AS_VERSION_COMPARE(["$amver"], [1.16], [continue])])
1002 TEST_LTDL_LIBOBJ_MANGLING