1 # Copyright © 2019-2020, 2022-2024 Nick Bowler
3 # This program is free software: you can redistribute it and/or modify
4 # it under the terms of the GNU General Public License as published by
5 # the Free Software Foundation, either version 3 of the License, or
6 # (at your option) any later version.
8 # This program is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # GNU General Public License for more details.
13 # You should have received a copy of the GNU General Public License
14 # along with this program. If not, see <https://www.gnu.org/licenses/>.
16 AT_BANNER([Library tests])
18 # TEST_DUMMY_PKGCONFIG([cflags], [libs])
20 # Create a hack pkg-config script in the current working directory which
21 # responds to --cflags and --libs with the provided values. The macro
22 # arguments should each be a single shell word, suitable for the right
23 # hand side of a shell assignment.
24 m4_define([TEST_DUMMY_PKGCONFIG],
25 [[cat >pkg-config <<EOF
31 --cflags) cflags=]$1[;;
33 --atleast-pkgconfig-version) exit;;
36 printf '%s %s\n' "\$cflags" "\$libs"
41 AT_SETUP([libdiscid probes])
42 AT_KEYWORDS([lib libdiscid])
45 AT_DATA([discid/discid.h],
46 [[typedef void DiscId;
47 DiscId *discid_new(void);
48 void discid_free(DiscId *);
49 #ifndef DISCID_VERSION_MAJOR
50 # define DISCID_VERSION_MAJOR 2
60 TEST_CONFIGURE_AC([[DX_LIB_LIBDISCID([1.2.3], [HAVE_LIBDISCID=yes],
62 AC_SUBST([HAVE_LIBDISCID])
63 AC_CONFIG_FILES([test])
67 # Check the search via explicit flags
68 TEST_CONFIGURE([LIBDISCID_CFLAGS=-I. LIBDISCID_LIBS="$builddir/t/libdummy.a"])
69 AT_CHECK_UNQUOTED([cat test], [0], [yes
71 $builddir/t/libdummy.a
74 # Check the search via pkg-config
75 TEST_DUMMY_PKGCONFIG([-I.], [$builddir/t/libdummy.a])
76 TEST_CONFIGURE([PKG_CONFIG=$PWD/pkg-config])
77 AT_CHECK_UNQUOTED([cat test], [0], [yes
79 $builddir/t/libdummy.a
82 # Check the default -ldiscid search
83 cp "$builddir/t/libdummy.a" libdiscid.a
84 TEST_CONFIGURE([PKG_CONFIG=false CFLAGS=-I. LDFLAGS=-L.])
85 AT_CHECK_UNQUOTED([cat test], [0], [yes
90 # Check the failure case
91 TEST_CONFIGURE([PKG_CONFIG=false CFLAGS='-I. -DDISCID_VERSION_MAJOR=0'])
92 AT_CHECK_UNQUOTED([cat test], [0], [no
99 AT_SETUP([curses probes])
100 AT_KEYWORDS([lib curses ncurses])
103 [[void initscr(void) { }
104 void endwin(void) { }
114 TEST_CONFIGURE_AC([[DX_LIB_CURSES([HAVE_CURSES=yes], [HAVE_CURSES=no])
115 AC_SUBST([HAVE_CURSES])
116 AC_CONFIG_FILES([test])
120 # Check the search via explicit flags
121 TEST_CONFIGURE([CURSES_CFLAGS=-I. CURSES_LIBS="$builddir/t/libdummy.a"])
122 AT_CHECK_UNQUOTED([cat test], [0], [yes
124 $builddir/t/libdummy.a
127 # Check the search via pkg-config
128 TEST_DUMMY_PKGCONFIG([-I.], [$builddir/t/libdummy.a])
129 TEST_CONFIGURE([PKG_CONFIG=$PWD/pkg-config])
130 AT_CHECK_UNQUOTED([cat test], [0], [yes
132 $builddir/t/libdummy.a
135 # Check the default -lcurses search
136 cp "$builddir/t/libdummy.a" libcurses.a
137 TEST_CONFIGURE([PKG_CONFIG=false CFLAGS=-I. LDFLAGS=-L.])
138 AT_CHECK_UNQUOTED([cat test], [0], [yes
143 # Check the failure case
144 cp "$builddir/t/libempty.a" libcurses.a
145 TEST_CONFIGURE([PKG_CONFIG=false CFLAGS=-I. LDFLAGS=-L.])
146 AT_CHECK_UNQUOTED([cat test], [0], [no
153 AT_SETUP([DX_CHECK_CURSES_GETMOUSE_NCURSES])
154 AT_KEYWORDS([lib curses ncurses])
156 mkdir ncurses sysv bogus
157 AT_DATA([ncurses/curses.h],
158 [[typedef struct MEVENT { int x; } MEVENT;
159 int getmouse_nc_(MEVENT *);
160 #define getmouse getmouse_nc_
163 AT_DATA([sysv/curses.h],
164 [[unsigned getmouse(void);
167 AT_DATA([bogus/curses.h],
168 [[typedef int MEVENT;
169 int getmouse_bogus_(void *);
170 #define getmouse getmouse_bogus_
174 [[@dx_cv_curses_have_getmouse_ncurses@
177 TEST_CONFIGURE_AC([[AC_CONFIG_HEADERS([config.h])
178 DX_CHECK_CURSES_GETMOUSE_NCURSES
179 AC_SUBST([dx_cv_curses_have_getmouse_ncurses])
180 AC_CONFIG_FILES([test])
184 TEST_CONFIGURE([CURSES_CFLAGS=-Incurses CURSES_LIBS="$builddir/t/libdummy.a"])
185 AT_CHECK([cat test && grep HAVE_CURSES config.h], [0], [yes
186 #define HAVE_CURSES_GETMOUSE_NCURSES 1
189 TEST_CONFIGURE([CURSES_CFLAGS=-Isysv CURSES_LIBS="$builddir/t/libdummy.a"])
190 AT_CHECK([cat test && grep HAVE_CURSES config.h], [0], [no
191 /* #undef HAVE_CURSES_GETMOUSE_NCURSES */
194 TEST_CONFIGURE([CURSES_CFLAGS=-Ibogus CURSES_LIBS="$builddir/t/libdummy.a"])
195 AT_CHECK([cat test && grep HAVE_CURSES config.h], [0], [no
196 /* #undef HAVE_CURSES_GETMOUSE_NCURSES */
201 AT_SETUP([DX_CHECK_CURSES_MOUSE_SUPPORT])
202 AT_KEYWORDS([lib curses ncurses])
204 mkdir hp ncurses sysv
206 # HP-UX 11 curses contains definitions of mouse functions in the library but
207 # is missing declarations and associated macros in <curses.h>, although they
208 # are present in the alternate "cur_colr" implementation.
210 # Regardless, neither implementation seems to have working mouse support with
211 # any X terminal emulator so for now no workarounds are provided and the checks
212 # are expected to return "no".
213 AT_DATA([hp/curses.h],
214 [[int mouse_set(unsigned long);
215 int request_mouse_pos(void);
218 # Ncurses-like mouse functions.
219 AT_DATA([ncurses/curses.h],
220 [[unsigned long mousemask(unsigned long, unsigned long *);
222 int getmouse_nc_(MEVENT *);
223 #define getmouse getmouse_nc_
224 #define BUTTON1_RELEASED 1L
225 #define BUTTON1_PRESSED 2L
227 /* rename this to avoid false positives in the test */
228 #define mouse_set mouse_set_bogus_
231 # SysV-like mouse funcitons.
232 AT_DATA([sysv/curses.h],
233 [[int mouse_set(unsigned long);
234 int request_mouse_pos(void);
236 #define BUTTON_STATUS(x) 0
237 #define BUTTON_RELEASED 0
238 #define BUTTON_PRESSED 1
240 #define BUTTON1_RELEASED 1L
241 #define BUTTON1_PRESSED 2L
245 [[@dx_cv_curses_have_mouse_set@
246 @dx_cv_curses_have_mousemask@
247 @dx_cv_curses_have_getmouse_ncurses@
248 @dx_cv_curses_have_request_mouse_pos@
251 TEST_CONFIGURE_AC([[AC_CONFIG_HEADERS([config.h])
252 DX_CHECK_CURSES_MOUSE_SUPPORT
253 AC_SUBST([dx_cv_curses_have_mouse_set])
254 AC_SUBST([dx_cv_curses_have_mousemask])
255 AC_SUBST([dx_cv_curses_have_request_mouse_pos])
256 AC_SUBST([dx_cv_curses_have_getmouse_ncurses])
257 AC_CONFIG_FILES([test])
261 TEST_CONFIGURE([CURSES_CFLAGS=-Ihp CURSES_LIBS="$builddir/t/libdummy.a"])
262 AT_CHECK([cat test && grep CURSES_MOUSE_SUPPORT config.h], [0], [no
266 /* #undef HAVE_CURSES_MOUSE_SUPPORT */
269 TEST_CONFIGURE([CURSES_CFLAGS=-Incurses CURSES_LIBS="$builddir/t/libdummy.a"])
270 AT_CHECK([cat test && grep CURSES_MOUSE_SUPPORT config.h], [0], [no
274 #define HAVE_CURSES_MOUSE_SUPPORT 1
277 TEST_CONFIGURE([CURSES_CFLAGS=-Isysv CURSES_LIBS="$builddir/t/libdummy.a"])
278 AT_CHECK([cat test && grep CURSES_MOUSE_SUPPORT config.h], [0], [yes
282 #define HAVE_CURSES_MOUSE_SUPPORT 1
287 AT_SETUP([GLib GNU inline workaround])
289 TEST_DUMMY_PKGCONFIG([-I.], [$builddir/t/libdummy.a])
291 # This test will only work if we have a version of GCC that implements
292 # C99 inline semantics by default.
295 extern inline void my_dup_fn(void) { }
297 int main(void) { return 0; }
301 extern inline void my_dup_fn(void) { }
305 AT_DATA([test.sh.in],
307 @CC@ @CPPFLAGS@ @CFLAGS@ -c a.c || exit 77
308 @CC@ @CPPFLAGS@ @CFLAGS@ -c b.c || exit 77
309 @CC@ @CFLAGS@ @LDFLAGS@ a.o b.o || exit 0
314 [[#define GLIB_CHECK_VERSION(x, y, z) 1
315 const char *g_get_prgname(void);
318 TEST_CONFIGURE_AC([[AC_CONFIG_HEADERS([config.h])
320 AC_CONFIG_FILES([test.sh], [chmod +x test.sh])
323 TEST_CONFIGURE([PKG_CONFIG=$PWD/pkg-config])
324 AT_CHECK([./test.sh], [0], [ignore], [ignore])
326 AT_CHECK([grep '#.*G_INLINE_FUNC' config.h], [0],
327 [/* #undef G_INLINE_FUNC */
329 AT_CHECK([grep '#.*G_IMPLEMENT_INLINES' config.h], [0],
330 [/* #undef G_IMPLEMENT_INLINES */
333 cp glib.h glib-orig.h
334 cat glib-orig.h - >glib.h <<'EOF'
335 #ifndef G_INLINE_FUNC
336 # define G_INLINE_FUNC extern inline
338 G_INLINE_FUNC void break_things(void) { }
341 TEST_CONFIGURE([PKG_CONFIG=$PWD/pkg-config])
342 AT_CHECK([grep '#.*G_INLINE_FUNC' config.h], [0],
343 [#define G_INLINE_FUNC static inline
345 AT_CHECK([grep '#.*G_IMPLEMENT_INLINES' config.h], [0],
346 [/* #undef G_IMPLEMENT_INLINES */
349 cat glib-orig.h - >glib.h <<'EOF'
350 #define G_INLINE_FUNC extern inline
351 #ifdef G_IMPLEMENT_INLINES
352 extern void break_things(void);
354 G_INLINE_FUNC void break_things(void) { }
358 TEST_CONFIGURE([PKG_CONFIG=$PWD/pkg-config])
359 AT_CHECK([grep '#.*G_INLINE_FUNC' config.h], [0],
360 [/* #undef G_INLINE_FUNC */
362 AT_CHECK([grep '#.*G_IMPLEMENT_INLINES' config.h], [0],
363 [#define G_IMPLEMENT_INLINES 1
368 AT_SETUP([DX_CHECK_SYSLOG])
371 [[/* since syslog is normally in the standard C library, to make negative
372 link tests possible we use a dummy external name */
373 extern void dx_link_stub(void);
375 static void openlog(const char *, int, int) { dx_link_stub(); }
376 static void syslog(int, const char *, ...) { dx_link_stub(); }
377 static void closelog(void) { dx_link_stub(); }
385 [[@ac_cv_header_syslog_h@
389 TEST_CONFIGURE_AC([[DX_CHECK_SYSLOG
390 AC_SUBST([ac_cv_header_syslog_h])
391 AC_SUBST([dx_cv_have_syslog])
392 AC_CONFIG_FILES([test])
396 TEST_CONFIGURE([CFLAGS=-I.])
397 AT_CHECK([cat test], [0], [yes
401 TEST_CONFIGURE([CFLAGS=-I. LIBS="$builddir/t/libdummy.a"])
402 AT_CHECK([cat test], [0], [yes
408 AT_SETUP([DX_CHECK_GETLINE])
411 [[/* since getline is normally in the standard C library, to make negative link
412 tests possible we use a dummy external name */
413 extern void dx_link_stub(void);
414 typedef unsigned long size_t;
415 typedef long ssize_t;
418 static FILE stdin[1];
421 static size_t getline(char **line, size_t *n, FILE *f) { dx_link_stub(); }
426 [[@dx_cv_have_getline@
430 TEST_CONFIGURE_AC([[AC_PROG_CC
431 CPPFLAGS="-I$srcdir $CPPFLAGS"
433 AC_SUBST([dx_cv_have_getline])
434 AC_CONFIG_FILES([test])
439 AT_CHECK([sed '[s/-DPACKAGE\([^\\ ]*\\.\)*[^ ]* *//g]' test], [0], [no
443 TEST_CONFIGURE([LIBS="$builddir/t/libdummy.a"])
444 AT_CHECK([sed '[s/-DPACKAGE\([^\\ ]*\\.\)*[^ ]* *//g]' test], [0], [yes
448 TEST_CONFIGURE([CPPFLAGS="-DNO_GETLINE_DECL" LIBS="$builddir/t/libdummy.a"])
449 AT_CHECK([sed '[s/-DPACKAGE\([^\\ ]*\\.\)*[^ ]* *//g]' test], [0], [no
455 AT_SETUP([DX_CHECK_GETOPT_LONG(_ONLY)])
456 AT_KEYWORDS([DX_CHECK_GETOPT_LONG DX_CHECK_GETOPT_LONG_ONLY])
459 [[/* since getopt_long(_only) is normally in the standard C library, to make
460 negative link tests possible we use a dummy external name */
461 extern void dx_link_stub(void);
464 struct option { char *name; int has_arg, *flag, val; };
468 extern int optind, optopt, opterr;
472 #if !NO_GETOPT_LONG_DECL
473 static int getopt_long(int argc, char * const *argv, const char *sopts,
474 const struct option *lopts, int *idx)
481 #if !NO_GETOPT_LONG_ONLY_DECL
482 static int getopt_long_only(int argc, char * const *argv, const char *sopts,
483 const struct option *lopts, int *idx)
485 #if NO_GETOPT_LONG_ONLY
486 extern void dx_link_error(void);
497 [[@dx_cv_have_getopt_long@ @dx_cv_have_getopt_long_only@
501 TEST_CONFIGURE_AC([[AC_PROG_CC
502 CPPFLAGS="-I$srcdir $CPPFLAGS"
504 DX_CHECK_GETOPT_LONG_ONLY
505 AC_SUBST([dx_cv_have_getopt_long])
506 AC_SUBST([dx_cv_have_getopt_long_only])
507 AC_CONFIG_FILES([test])
512 AT_CHECK([sed '[s/-DPACKAGE\([^\\ ]*\\.\)*[^ ]* *//g]' test], [0], [no no
516 LIBS="$builddir/t/libdummy.a"; export LIBS
518 AT_CHECK([sed '[s/-DPACKAGE\([^\\ ]*\\.\)*[^ ]* *//g]' test], [0], [yes yes
519 -DHAVE_GETOPT_LONG=1 -DHAVE_GETOPT_LONG_ONLY=1
522 TEST_CONFIGURE([CPPFLAGS="-DNO_GETOPT_LONG_ONLY"])
523 AT_CHECK([sed '[s/-DPACKAGE\([^\\ ]*\\.\)*[^ ]* *//g]' test], [0], [yes no
527 TEST_CONFIGURE([CPPFLAGS="-DNO_STRUCT_DECL"])
528 AT_CHECK([sed '[s/-DPACKAGE\([^\\ ]*\\.\)*[^ ]* *//g]' test], [0], [no no
532 TEST_CONFIGURE([CPPFLAGS="-DNO_VAR_DECL"])
533 AT_CHECK([sed '[s/-DPACKAGE\([^\\ ]*\\.\)*[^ ]* *//g]' test], [0], [no no
539 AT_SETUP([DX_CHECK_MBRTOWC_WCWIDTH])
542 [[/* Since mbrtowc and wcwidth are normally in the standard C library, to make
543 negative link tests possible we use a dummy external name */
544 extern void dx_link_stub(void);
546 #if !NO_MBSTATE_DECL && (!HPUX_MBSTATE_DECL || _XOPEN_SOURCE == 500)
547 typedef int mbstate_t;
550 typedef unsigned short wchar_t;
551 wchar_t dummy_extern;
554 # define mbrtowc nonexistent_function
556 static unsigned mbrtowc(wchar_t *out, const char *s, unsigned n, int *ps)
565 # define wcwidth nonexistent_function
567 static int wcwidth(wchar_t c)
576 [[@dx_cv_have_mbrtowc_wcwidth@
580 TEST_CONFIGURE_AC([[AC_PROG_CC
581 CPPFLAGS="-I$srcdir $CPPFLAGS"
583 AC_DEFUN([AC_USE_SYSTEM_EXTENSIONS],
584 [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([#include <wchar.h>
586 [save_CPPFLAGS=$CPPFLAGS; CPPFLAGS="-D_XOPEN_SOURCE=500 $CPPFLAGS"
587 AC_COMPILE_IFELSE([AC_LANG_PROGRAM([#include <wchar.h>
588 mbstate_t x;])], [AC_DEFINE([_XOPEN_SOURCE], [500])])
589 CPPFLAGS=$save_CPPFLAGS])])
591 DX_CHECK_MBRTOWC_WCWIDTH
592 AC_SUBST([dx_cv_have_mbrtowc_wcwidth])
593 AC_CONFIG_FILES([test])
598 AT_CHECK([sed '[s/-DPACKAGE\([^\\ ]*\\.\)*[^ ]* *//g]' test], [0], [no
602 LIBS="$builddir/t/libdummy.a"; export LIBS
604 AT_CHECK([sed '[s/-DPACKAGE\([^\\ ]*\\.\)*[^ ]* *//g]' test], [0], [yes
605 -DHAVE_MBRTOWC=1 -DHAVE_WCWIDTH=1
608 TEST_CONFIGURE([CPPFLAGS=-DHPUX_MBSTATE_DECL])
609 AT_CHECK([sed '[s/-DPACKAGE\([^\\ ]*\\.\)*[^ ]* *//g]' test], [0], [yes
610 -D_XOPEN_SOURCE=500 -DHAVE_MBRTOWC=1 -DHAVE_WCWIDTH=1
613 TEST_CONFIGURE([CPPFLAGS=-DNO_MBRTOWC])
614 AT_CHECK([sed '[s/-DPACKAGE\([^\\ ]*\\.\)*[^ ]* *//g]' test], [0], [no
618 TEST_CONFIGURE([CPPFLAGS=-DNO_WCWIDTH])
619 AT_CHECK([sed '[s/-DPACKAGE\([^\\ ]*\\.\)*[^ ]* *//g]' test], [0], [no