]> git.draconx.ca Git - dxcommon.git/blob - tests/scripts.at
fix-ltdl: Fix LIBOBJ mangling to work with automake-1.16.
[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; sed -n -f - "$srcdir/tests/data/gnulib.mk" <<EOF
593 /^## begin gnulib module $1/,/^## end   gnulib module $1/p
594 EOF
595 }
596 m4_divert_pop([PREPARE_TESTS])
597
598 AT_SETUP([fix-gnulib.pl SED_HEADER variables])
599
600 test_gnulib_mk gen-header >test.mk.in
601 AT_CHECK([grep SED_HEADER test.mk.in >expout || exit 99])
602 AT_CHECK([test_fix_gnulib -i test.mk.in -o test.mk || exit
603 grep SED_HEADER test.mk], [0], [expout])
604
605 AT_CLEANUP
606
607 AT_SETUP([fix-gnulib.pl %reldir% substitution])
608
609 test_gnulib_mk sys_types >test.mk.in
610 AT_CHECK([grep '%reldir%' test.mk.in >/dev/null || exit 99])
611
612 sed -n -f - test.mk.in >expout <<'EOF'
613 ${G;p;b}
614 /^## begin gnulib/,/^## end   gnulib/!b
615 /^#/{p;b}
616 s|(srcdir)|(top_srcdir)|
617 s|%reldir%|lib|
618 s|BUILT_SOURCES|gnulib_core_headers|
619 s|sys[[/_]]|lib/&|g
620 /^MOSTLYCLEANFILES/{h;b}
621 p
622 EOF
623
624 AT_CHECK([test_fix_gnulib -i test.mk.in -o test.mk || exit
625 sed -n -e '/^## begin gnulib/,/^## end   gnulib/p' \
626        -e '/CLEANFILES/p' test.mk],
627 [0], [expout])
628
629 AT_CLEANUP
630
631 dnl TEST_FIND_AUTOMAKE_VER([to-check], [test-action])
632 dnl
633 dnl For each whitespace-separated version token in to-check, check if we can
634 dnl run the programs automake-VER and aclocal-VER.  The special token 'default'
635 dnl also checks the unversioned automake and aclocal (or, if set in the
636 dnl environment, $AUTOMAKE and $ACLOCAL).
637 dnl
638 dnl Then test-action is expanded such that shell variables $ac and $am refer to
639 dnl the aclocal and automake programs, and $amver is the actual version
640 dnl reported by --version.  The action should do nothing if the version is
641 dnl acceptable, or "continue" if the version is unacceptable.
642 dnl
643 dnl If an acceptable version is found, the AUTOMAKE and ACLOCAL environment
644 dnl variables are set accordingly.  Otherwise, the test group is skipped.
645 m4_define([TEST_FIND_AUTOMAKE],
646 [have_am=false
647 for am in $1; do
648   AS_CASE([$am],
649     [default], [ac=${ACLOCAL-aclocal} am=${AUTOMAKE-automake}],
650     [ac=aclocal-$am; am=automake-$am])
651   amver=`$am --version | sed -n '1s/.* //p'`
652   acver=`$ac --version | sed -n '1s/.* //p'`
653   set x $amver $acver; shift; test x"$[]#" = x"2" || continue
654   test x"$amver" = x"$acver" || continue
655   $2
656   have_am=:; break
657 done
658 AT_CHECK([$have_am || exit 77])
659 AUTOMAKE=$am; export AUTOMAKE
660 ACLOCAL=$ac; export ACLOCAL
661 AT_CHECK([$ACLOCAL --version && $AUTOMAKE --version], [0], [stdout])
662 ])
663
664 m4_define([TEST_LTDL_LIBOBJ_MANGLING],
665 [TEST_CONFIGURE_AC([[AM_INIT_AUTOMAKE([foreign subdir-objects])
666 AC_PROG_CC
667 LT_INIT
668 AC_SUBST([ltdl_LTLIBOBJS], [libltdl/test.lo])
669 AC_CONFIG_FILES([Makefile])
670 ]])
671
672 mkdir libltdl
673 AT_DATA([ltdl.mk.in], [[
674 AM_CPPFLAGS += -DSTRING=\"helloworld\"
675
676 noinst_LTLIBRARIES = libltdl/libltdl.la
677 libltdl_libltdl_la_SOURCES = libltdl/ltdl.c
678 libltdl_libltdl_la_LIBADD = $(ltdl_LTLIBOBJS)
679 libltdl_libltdl_la_DEPENDENCIES = $(ltdl_LTLIBOBJS)
680
681 EXTRA_DIST += libltdl/test.c
682 ]])
683 AT_DATA([Makefile.am], [[AM_CPPFLAGS =
684 include $(top_srcdir)/ltdl.mk
685 AM_LIBTOOLFLAGS = --quiet
686 bin_PROGRAMS = test
687 test_SOURCES =
688 test_LDADD = libltdl/libltdl.la
689 all-local: ; @printf '%s\n' $(AM_CPPFLAGS)
690 ]])
691 AT_DATA([libltdl/test.c], [[#include <stdio.h>
692 int foo(void) { printf("%s\n", STRING); return 0; }
693 ]])
694 AT_DATA([libltdl/ltdl.c], [[int foo(void); int main(void) { return foo(); }
695 ]])
696
697 AT_CHECK([test_fix_ltdl -i ltdl.mk.in -o ltdl.mk])
698 libtoolize; TEST_AUTORECONF
699 TEST_CONFIGURE([--disable-shared])
700 AT_CHECK([make -s && ./test], [0], [
701 helloworld
702 ])])
703
704 AT_SETUP([fix-ltdl.pl LIBOBJ mangling (<automake-1.16)])
705
706 TEST_FIND_AUTOMAKE([default 1.10 1.11 1.12 1.13 1.14 1.15],
707   [AS_VERSION_COMPARE(["$amver"], [1.16], [], [continue], [continue])])
708 TEST_LTDL_LIBOBJ_MANGLING
709
710 AT_CLEANUP
711
712 AT_SETUP([fix-ltdl.pl LIBOBJ mangling (>=automake-1.16)])
713
714 TEST_FIND_AUTOMAKE([default 1.16 1.17 1.18 1.19],
715   [AS_VERSION_COMPARE(["$amver"], [1.16], [continue])])
716 TEST_LTDL_LIBOBJ_MANGLING
717
718 AT_CLEANUP