]> git.draconx.ca Git - dxcommon.git/blob - tests/scripts.at
fix-gnulib: Ensure header rules create output directory.
[dxcommon.git] / tests / scripts.at
1 dnl Copyright © 2021-2022 Nick Bowler
2 dnl
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.
6
7 AT_BANNER([Script tests])
8
9 AT_SETUP([gen-options.awk])
10
11 AT_DATA([options.def],
12 [[--option-only
13 --option-with-val (5)
14 --option-with-flagval (&x, 5)
15 --option-with-arg=ARG
16 some "text" goes here
17 --option-with-optional-arg[=OPTIONAL]
18
19 hello
20 -a, --option-with-sopt
21
22 -b, --option-with-sopt-and-arg=SOPTARG
23 -c, --option-with-sopt-and-optional-arg[=SOPTOPTIONAL]
24 --option-with-arg-and-val=ARGVAL (42)
25 --option-with-arg-and-flagval=ARGFLAGVAL (&a[1], 'x')
26 --option-with-optional-arg-and-val[=OPTIONALARGVAL] (54)
27 --option-with-optional-arg-and-flagval[=OPTIONALFLAGVAL] (0, 0)
28 --with-sopt
29 Here is a help string
30     that has a line randomly indented
31 # with a comment
32     @&t@
33 and a blank line
34 --with-arg=ARG
35 do stuff with ARG
36 --flagval
37 ]])
38
39 AT_CHECK([$AWK -f "$builddir/scripts/gen-options.awk" <options.def >options.h])
40
41 AT_DATA([context.h],
42 [[struct option { const char *name; int has_arg; int *flag; int val; };
43 int x, a[5];
44 ]])
45
46 # test 0: sanity test
47 AT_DATA([test0.c],
48 [[#include "context.h"
49 #include "options.h"
50
51 static const char sopts[] = SOPT_STRING;
52 static const struct option opts[] = { LOPTS_INITIALIZER, {0} };
53
54 int main(void)
55 {
56   return 0;
57 }
58 ]])
59 AT_CHECK([$CC -o test0$EXEEXT test0.c && ./test0$EXEEXT], [0], [], [ignore])
60
61 # test 1: long option names and help text
62 AT_DATA([test1.c],
63 [[#include <stdio.h>
64 #include <stdlib.h>
65
66 #include "context.h"
67 #include "options.h"
68
69 static const struct option opts[] = { LOPTS_INITIALIZER };
70
71 int main(void)
72 {
73   unsigned i;
74
75   for (i = 0; i < sizeof opts / sizeof opts[0]; i++) {
76     struct lopt_help help = { "INVALID", "INVALID" };
77
78     if (!lopt_get_help(&opts[i], &help))
79       return EXIT_FAILURE;
80
81     printf("--%s", opts[i].name);
82     if (opts[i].has_arg)
83       printf("=%s", help.arg);
84     printf("\n%s", help.desc);
85     if (help.desc[0])
86       putchar('\n');
87   }
88
89   return 0;
90 }
91 ]])
92
93 # pick out interesting bits from the definitions file
94 sed -n '/^-/s/^.*--\([[^\= @<:@]]*\).*$/\1/p' options.def >options
95 sed -n '/^-/{
96   s/[[^=]]*\(=[[^@:>@ ]]*\).*$/\1/
97   s/^[[^=]].*//
98   s/^=//
99   p
100 }' options.def >argnames
101
102 AS_ECHO(["-"]) | sed -n '1s/^-.*//p
103 1,/^-/d
104 t clear
105 :clear
106 s/^-.*//p
107 t
108 s/^#.*//
109 s/^ *//
110 t next
111 :next
112 N
113 s/\n-.*//
114 t done
115 s/\n#.*//
116 s/\n */\n/g
117 t next
118 :done
119 s/"/\\\\"/g
120 s/[[^\n]][[^\n]]*/\\"&\\"/g
121 s/^\n*//
122 s/\n*$//
123 s/\n\n*/ /g
124 p
125 ' options.def - >helptext
126
127 exec 3<options 4<argnames 5<helptext 6>expout
128 while read opt <&3 && read arg <&4 && read help <&5; do
129   if test ${arg:+y}; then
130     AS_ECHO(["--$opt=$arg"]) >&6
131   else
132     AS_ECHO(["--$opt"]) >&6
133   fi
134   eval "set x $help"; shift
135   for arg
136   do
137     AS_ECHO(["$arg"]) >&6
138   done
139 done
140 exec 3<&- 4<&- 5<&- 6>&-
141
142 AT_CHECK([$CC -o test1$EXEEXT test1.c && ./test1$EXEEXT],
143   [0], [expout], [ignore])
144
145 # test 2: short option string
146 AT_DATA([test2.c],
147 [[#include <stdio.h>
148 #include <stdlib.h>
149
150 #include "context.h"
151 #include "options.h"
152
153 int main(void)
154 {
155   struct option lopts[] = {LOPTS_INITIALIZER};
156   unsigned i, j;
157
158   for (i = 0; i < sizeof SOPT_STRING - 1; i++) {
159     if (SOPT_STRING[i] != ':') {
160       for (j = 0; j < sizeof lopts / sizeof lopts[0]; j++) {
161         if (lopts[j].val == SOPT_STRING[i]) {
162           printf("--%s ", lopts[j].name);
163           break;
164         }
165       }
166     }
167     putchar(SOPT_STRING[i]);
168     if (SOPT_STRING[i+1] != ':')
169       putchar('\n');
170   }
171 }
172 ]])
173
174 sed -n '/^-/{
175   s/=.*/:/
176   s/[[@<:@]]/:/
177   s/^-\([[^-]]\)[[^:]]*/\1/p
178   s/^-.*//p
179 }' options.def >sopts
180
181 exec 3<options 4<sopts 5>expout
182 while read lopt <&3 && read sopt <&4; do
183   if test ${sopt:+y}; then
184     AS_ECHO(["--$lopt $sopt"]) >&5
185   fi
186 done
187 exec 3<&- 4<&- 5>&-
188
189 AT_CHECK([$CC -o test2$EXEEXT test2.c && ./test2$EXEEXT],
190   [0], [expout], [ignore])
191
192 # Check that all help strings are translatable
193 sed 's/\([[^\\]]\\\)" /\1\\n\\" /g' helptext >help-po
194 exec 3<options 4<argnames 5<help-po 6>expected.po
195 while read opt <&3 && read arg <&4 && read help <&5; do
196   if test ${arg:+y}; then
197     AS_ECHO(["msgctxt \"$opt\" msgid \"$arg\""]) >&6
198   fi
199   AS_ECHO(["msgctxt \"$opt\" msgid${help:+ }$help"]) >&6
200 done
201 exec 3<&- 4<&- 5<&- 6>&-
202
203 AT_CHECK([xgettext --keyword=PN_:1c,2 options.h
204   test -f messages.po || exit 77])
205
206 LC_ALL=C sort expected.po >expout
207 AT_CHECK([sed -n '/^msgctxt/{
208 t next
209 :next
210 N
211 s/\nmsgstr.*//
212 t done
213 s/\s*""//
214 s/\n/ /
215 t next
216 :done
217 p
218 }' messages.po | LC_ALL=C sort], [0], [expout])
219
220 AT_CLEANUP
221
222 AT_SETUP([gen-strtab.awk])
223
224 AT_DATA([test.def],
225 [[
226 &a world
227 &b
228 hello world
229 &c
230 hello
231 world
232 &d world\n
233 &e
234 \\not a newline
235 &f
236 \not a newline
237 &g inline
238 continued
239 &h    no\
240 newline\
241 &i
242 \   leading whitespace
243 &j oneline
244 # with a comment
245 ]])
246
247 AT_CHECK([$AWK -f "$builddir/scripts/gen-strtab.awk" <test.def >test.h])
248
249 sed -n 's/^[[&]]\([[^ ]]*\).*/\1/p' test.def >identifiers
250
251 # test 0: sanity test
252 AT_DATA([test0.c],
253 [[#include "test.h"
254 #include <stdio.h>
255
256 int main(void)
257 {
258   printf("---\n");
259 ]])
260 exec 3<identifiers 4>>test0.c
261 while read ident <&3; do
262   AS_ECHO(['  printf("%s\n---\n", '"strtab+$ident);"]) >&4
263 done
264 AS_ECHO(['  return 0;']) >&4
265 AS_ECHO(['}']) >&4
266 exec 3<&- 4>&-
267
268 AT_CHECK([$CC -o test0$EXEEXT test0.c && ./test0$EXEEXT], [0], [---
269 world
270 ---
271 hello world
272
273 ---
274 hello
275 world
276
277 ---
278 world
279
280 ---
281 \not a newline
282
283 ---
284
285 ot a newline
286
287 ---
288 inline
289 continued
290
291 ---
292 nonewline
293 ---
294    leading whitespace
295
296 ---
297 oneline
298 ---
299 ], [ignore])
300
301 AT_CLEANUP
302
303 AT_SETUP([gen-tree.awk])
304 AT_DATA([tree.def],
305 [[ROOT0
306   r0a, r0a_OFFSET
307     r0b, r0b_OFFSET
308       r0c
309     r0d
310   r0e, r0e_OFFSET
311     r0f
312     r0g
313 ROOT1
314   r1a, r1a_OFFSET
315     r1b, r1b_OFFSET
316       r1b
317       r1e
318       r1b
319   r1c, r1c_OFFSET
320     r1d, r1d_OFFSET
321       r1e
322       r1b
323       r1e
324 ]])
325
326 AT_CHECK([$AWK -f "$builddir/scripts/gen-tree.awk" <tree.def >tree.h])
327
328 AT_DATA([test0.c],
329 [[#include "tree.h"
330 #include <stdio.h>
331
332 struct tree { unsigned id, subtree; };
333
334 static const struct tree tree0[] = {
335   ROOT0_INITIALIZER
336 };
337 static const struct tree tree1[] = {
338   ROOT1_INITIALIZER
339 };
340
341 void print_subtree(const struct tree *root, unsigned offset, int depth)
342 {
343   const struct tree *node;
344
345   for (node = &root[offset]; node->id; node++) {
346     printf("%*s%s", 2*depth, "", &tree_strtab[node->id]);
347     if (node->subtree) {
348       printf(", %s_OFFSET\n", &tree_strtab[node->id]);
349       print_subtree(root, node->subtree, depth+1);
350     } else {
351       putchar('\n');
352     }
353   }
354 }
355
356 int main(void)
357 {
358   printf("ROOT0\n");
359   print_subtree(tree0, 0, 1);
360   printf("ROOT1\n");
361   print_subtree(tree1, 0, 1);
362 }
363 ]])
364 cp tree.def expout
365 AT_CHECK([$CC -o test0$EXEEXT test0.c && ./test0$EXEEXT], [0], [expout])
366
367 AT_CLEANUP
368
369 AT_SETUP([join.awk])
370
371 JOIN="$AWK -f $builddir/scripts/join.awk --"
372
373 AT_DATA([a],
374 [[1 a
375 3 a1 x
376 3 a2 x
377 5 a
378 6 a
379 8 a1 x
380 8 a2 x
381 9 a1
382 9 a2
383 9 a3
384 ]])
385
386 AT_DATA([b],
387 [[2 b
388 2 b
389 3 b y
390 4 b
391 6 b1 y
392 6 b2 y
393 7 b
394 8 b1 y
395 8 b2 y
396 ]])
397
398 AT_CHECK([$JOIN a b], [0],
399 [[3 a1 x b y
400 3 a2 x b y
401 6 a b1 y
402 6 a b2 y
403 8 a1 x b1 y
404 8 a1 x b2 y
405 8 a2 x b1 y
406 8 a2 x b2 y
407 ]])
408
409 AT_CHECK([$JOIN -v1 a b], [0],
410 [[1 a
411 5 a
412 9 a1
413 9 a2
414 9 a3
415 ]])
416
417 AT_CHECK([$JOIN -v2 a b], [0],
418 [[2 b
419 2 b
420 4 b
421 7 b
422 ]])
423
424 AT_CHECK([$JOIN -v1 -v2 a b], [0],
425 [[1 a
426 2 b
427 2 b
428 4 b
429 5 a
430 7 b
431 9 a1
432 9 a2
433 9 a3
434 ]])
435
436 AT_CHECK([$JOIN -a1 a b], [0],
437 [[1 a
438 3 a1 x b y
439 3 a2 x b y
440 5 a
441 6 a b1 y
442 6 a b2 y
443 8 a1 x b1 y
444 8 a1 x b2 y
445 8 a2 x b1 y
446 8 a2 x b2 y
447 9 a1
448 9 a2
449 9 a3
450 ]])
451
452 AT_CHECK([$JOIN -a2 a b], [0],
453 [[2 b
454 2 b
455 3 a1 x b y
456 3 a2 x b y
457 4 b
458 6 a b1 y
459 6 a b2 y
460 7 b
461 8 a1 x b1 y
462 8 a1 x b2 y
463 8 a2 x b1 y
464 8 a2 x b2 y
465 ]])
466
467 AT_CHECK([$JOIN -a1 -a2 a b], [0],
468 [[1 a
469 2 b
470 2 b
471 3 a1 x b y
472 3 a2 x b y
473 4 b
474 5 a
475 6 a b1 y
476 6 a b2 y
477 7 b
478 8 a1 x b1 y
479 8 a1 x b2 y
480 8 a2 x b1 y
481 8 a2 x b2 y
482 9 a1
483 9 a2
484 9 a3
485 ]])
486
487 AT_CHECK([$JOIN b a], [0],
488 [[3 b y a1 x
489 3 b y a2 x
490 6 b1 y a
491 6 b2 y a
492 8 b1 y a1 x
493 8 b1 y a2 x
494 8 b2 y a1 x
495 8 b2 y a2 x
496 ]])
497
498 AT_CHECK([$JOIN -v1 b a], [0],
499 [[2 b
500 2 b
501 4 b
502 7 b
503 ]])
504
505 AT_CHECK([$JOIN -v2 b a], [0],
506 [[1 a
507 5 a
508 9 a1
509 9 a2
510 9 a3
511 ]])
512
513 AT_CHECK([$JOIN -v1 -v2 b a], [0],
514 [[1 a
515 2 b
516 2 b
517 4 b
518 5 a
519 7 b
520 9 a1
521 9 a2
522 9 a3
523 ]])
524
525 AT_CHECK([$JOIN -a1 b a], [0],
526 [[2 b
527 2 b
528 3 b y a1 x
529 3 b y a2 x
530 4 b
531 6 b1 y a
532 6 b2 y a
533 7 b
534 8 b1 y a1 x
535 8 b1 y a2 x
536 8 b2 y a1 x
537 8 b2 y a2 x
538 ]])
539
540 AT_CHECK([$JOIN -a2 b a], [0],
541 [[1 a
542 3 b y a1 x
543 3 b y a2 x
544 5 a
545 6 b1 y a
546 6 b2 y a
547 8 b1 y a1 x
548 8 b1 y a2 x
549 8 b2 y a1 x
550 8 b2 y a2 x
551 9 a1
552 9 a2
553 9 a3
554 ]])
555
556 AT_CHECK([$JOIN -a1 -a2 b a], [0],
557 [[1 a
558 2 b
559 2 b
560 3 b y a1 x
561 3 b y a2 x
562 4 b
563 5 a
564 6 b1 y a
565 6 b2 y a
566 7 b
567 8 b1 y a1 x
568 8 b1 y a2 x
569 8 b2 y a1 x
570 8 b2 y a2 x
571 9 a1
572 9 a2
573 9 a3
574 ]])
575
576 AT_CHECK([echo wat | $JOIN -v1 - /dev/null], [0],
577 [[wat
578 ]])
579
580 AT_CLEANUP
581
582 m4_divert_push([PREPARE_TESTS])dnl
583 test_fix_ltdl () {
584   $PERL -e 'my $x = 42; exit $x;'; test $? = 42 || exit 77
585   $PERL -f "$srcdir/scripts/fix-ltdl.pl" "$@"
586 }
587 test_fix_gnulib () {
588   $PERL -e 'my $x = 42; exit $x;'; test $? = 42 || exit 77
589   $PERL -f "$srcdir/scripts/fix-gnulib.pl" "$@"
590 }
591 test_gnulib_mk () {
592   echo;
593   for arg
594   do
595     sed -n -f - "$srcdir/tests/data/gnulib.mk" <<EOF
596 /^## begin gnulib module $arg/,/^## end   gnulib module $arg/p
597 EOF
598   done
599 }
600 m4_divert_pop([PREPARE_TESTS])
601
602 AT_SETUP([fix-gnulib.pl SED_HEADER variables])
603
604 test_gnulib_mk gen-header >test.mk.in
605 AT_CHECK([grep SED_HEADER test.mk.in >expout || exit 99])
606 AT_CHECK([test_fix_gnulib -i test.mk.in -o test.mk || exit
607 grep SED_HEADER test.mk], [0], [expout])
608
609 AT_CLEANUP
610
611 AT_SETUP([fix-gnulib.pl %reldir% substitution])
612
613 test_gnulib_mk sys_types >test.mk.in
614 AT_CHECK([grep '%reldir%' test.mk.in >/dev/null || exit 99])
615
616 sed -n -f - test.mk.in >expout <<'EOF'
617 ${G;p;b}
618 /^## begin gnulib/,/^## end   gnulib/!b
619 /^#/{p;b}
620 s|(srcdir)|(top_srcdir)|
621 s|%reldir%|lib|
622 s|BUILT_SOURCES|gnulib_core_headers|
623 s|sys[[/_]]|lib/&|g
624 /^MOSTLYCLEANFILES/{h;b}
625 p
626 EOF
627
628 AT_CHECK([test_fix_gnulib -i test.mk.in -o test.mk || exit
629 sed -n -e '/^## begin gnulib/,/^## end   gnulib/p' \
630        -e '/CLEANFILES/p' test.mk],
631 [0], [expout])
632
633 AT_CLEANUP
634
635 AT_SETUP([fix-gnulib.pl warning removal])
636
637 AT_DATA([test.mk.in], [[
638 ## test begin
639 noinst_LTLIBRARIES += libgnu.la
640 libgnu_la_CFLAGS = $(AM_CFLAGS) $(GL_CFLAG_GNULIB_WARNINGS)
641 noinst_LIBRARIES += libgnu.a
642 libgnu_a_CFLAGS = $(AM_CFLAGS) $(GL_CFLAG_GNULIB_WARNINGS)
643 ## test end
644 ]])
645 AT_CHECK([test_fix_gnulib -i test.mk.in -o test.mk || exit
646 sed -n '/^## test begin/,/^## test end/p' test.mk], [0], [## test begin
647 EXTRA_LTLIBRARIES += libgnu.la
648 EXTRA_LIBRARIES += libgnu.a
649 ## test end
650 ])
651
652 AT_CLEANUP
653
654 AT_SETUP([fix-gnulib.pl header directory creation])
655
656 AT_DATA([extract.sed],
657 [[/AM_V_GEN/b ok
658 /gl_V_at/b ok
659 s/:.*/:/
660 h
661 b
662 :ok
663 s/'//g
664 x
665 G
666 p
667 n
668 s/[)].*/)/
669 p
670 ]])
671
672 test_gnulib_mk alloca-opt sys_types stddef >test.mk.in
673 AT_CHECK([test_fix_gnulib -i test.mk.in -o test.mk || exit
674 sed -n -f extract.sed test.mk], [0],
675 [[lib/alloca.h:
676         $(AM_V_GEN)$(MKDIR_P) lib
677         $(AM_V_at)
678 lib/sys/types.h:
679         $(AM_V_GEN)$(MKDIR_P) lib/sys
680         $(AM_V_at)
681 lib/stddef.h:
682         $(AM_V_GEN)$(MKDIR_P) lib
683         $(AM_V_at)
684 ]])
685
686 AT_CLEANUP
687
688 dnl TEST_FIND_AUTOMAKE_VER([to-check], [test-action])
689 dnl
690 dnl For each whitespace-separated version token in to-check, check if we can
691 dnl run the programs automake-VER and aclocal-VER.  The special token 'default'
692 dnl also checks the unversioned automake and aclocal (or, if set in the
693 dnl environment, $AUTOMAKE and $ACLOCAL).
694 dnl
695 dnl Then test-action is expanded such that shell variables $ac and $am refer to
696 dnl the aclocal and automake programs, and $amver is the actual version
697 dnl reported by --version.  The action should do nothing if the version is
698 dnl acceptable, or "continue" if the version is unacceptable.
699 dnl
700 dnl If an acceptable version is found, the AUTOMAKE and ACLOCAL environment
701 dnl variables are set accordingly.  Otherwise, the test group is skipped.
702 m4_define([TEST_FIND_AUTOMAKE],
703 [have_am=false
704 for am in $1; do
705   AS_CASE([$am],
706     [default], [ac=${ACLOCAL-aclocal} am=${AUTOMAKE-automake}],
707     [ac=aclocal-$am; am=automake-$am])
708   amver=`$am --version | sed -n '1s/.* //p'`
709   acver=`$ac --version | sed -n '1s/.* //p'`
710   set x $amver $acver; shift; test x"$[]#" = x"2" || continue
711   test x"$amver" = x"$acver" || continue
712   $2
713   have_am=:; break
714 done
715 AT_CHECK([$have_am || exit 77])
716 AUTOMAKE=$am; export AUTOMAKE
717 ACLOCAL=$ac; export ACLOCAL
718 AT_CHECK([$ACLOCAL --version && $AUTOMAKE --version], [0], [stdout])
719 ])
720
721 m4_define([TEST_LTDL_LIBOBJ_MANGLING],
722 [TEST_CONFIGURE_AC([[AM_INIT_AUTOMAKE([foreign subdir-objects])
723 AC_PROG_CC
724 LT_INIT
725 AC_SUBST([ltdl_LTLIBOBJS], [libltdl/test.lo])
726 AC_CONFIG_FILES([Makefile])
727 ]])
728
729 mkdir libltdl
730 AT_DATA([ltdl.mk.in], [[
731 AM_CPPFLAGS += -DSTRING=\"helloworld\"
732
733 noinst_LTLIBRARIES = libltdl/libltdl.la
734 libltdl_libltdl_la_SOURCES = libltdl/ltdl.c
735 libltdl_libltdl_la_LIBADD = $(ltdl_LTLIBOBJS)
736 libltdl_libltdl_la_DEPENDENCIES = $(ltdl_LTLIBOBJS)
737
738 EXTRA_DIST += libltdl/test.c
739 ]])
740 AT_DATA([Makefile.am], [[AM_CPPFLAGS =
741 include $(top_srcdir)/ltdl.mk
742 AM_LIBTOOLFLAGS = --quiet
743 bin_PROGRAMS = test
744 test_SOURCES =
745 test_LDADD = libltdl/libltdl.la
746 all-local: ; @printf '%s\n' $(AM_CPPFLAGS)
747 ]])
748 AT_DATA([libltdl/test.c], [[#include <stdio.h>
749 int foo(void) { printf("%s\n", STRING); return 0; }
750 ]])
751 AT_DATA([libltdl/ltdl.c], [[int foo(void); int main(void) { return foo(); }
752 ]])
753
754 AT_CHECK([test_fix_ltdl -i ltdl.mk.in -o ltdl.mk])
755 libtoolize; TEST_AUTORECONF
756 TEST_CONFIGURE([--disable-shared])
757 AT_CHECK([make -s && ./test], [0], [
758 helloworld
759 ])])
760
761 AT_SETUP([fix-ltdl.pl LIBOBJ mangling (<automake-1.16)])
762
763 TEST_FIND_AUTOMAKE([default 1.10 1.11 1.12 1.13 1.14 1.15],
764   [AS_VERSION_COMPARE(["$amver"], [1.16], [], [continue], [continue])])
765 TEST_LTDL_LIBOBJ_MANGLING
766
767 AT_CLEANUP
768
769 AT_SETUP([fix-ltdl.pl LIBOBJ mangling (>=automake-1.16)])
770
771 TEST_FIND_AUTOMAKE([default 1.16 1.17 1.18 1.19],
772   [AS_VERSION_COMPARE(["$amver"], [1.16], [continue])])
773 TEST_LTDL_LIBOBJ_MANGLING
774
775 AT_CLEANUP