dnl Copyright © 2019-2023 Nick Bowler dnl License GPLv2+: GNU General Public License version 2 or any later version. dnl This is free software: you are free to change and redistribute it. dnl There is NO WARRANTY, to the extent permitted by law. AT_SETUP([test.gob compilation]) AT_CHECK([gob2 "$abs_top_srcdir/t/test.gob"]) AT_CHECK([$HAVE_GTK2 || exit 77]) TEST_COMPILE_GOBJECT([$GTK_CFLAGS test-object.c], [0], [], [ignore]) AT_CLEANUP AT_SETUP([test.gob C++ compilation]) AT_CHECK([gob2 --for-cpp "$abs_top_srcdir/t/test.gob"]) AT_CHECK([$HAVE_GTK2 || exit 77]) TEST_COMPILEXX_GOBJECT([$GTK_CFLAGS test-object.cc], [0], [], [ignore]) AT_CLEANUP AT_SETUP([str.gob]) # check if compiler supports format warnings AT_DATA([fmt.c], [[#include #include void foo(const char *, ...) G_GNUC_PRINTF(1, 2); void bar(void) { #line 99 "VERIFY" foo("%s", 0); } ]]) AT_DATA([fmt.awk], [[BEGIN { pass=0; FS=":"; } /%s/ && $1 == "VERIFY" && $2 == 99 { pass=1; } END { exit(!pass); } ]]) fmt_warnings=false set x $CPPFLAGS $CFLAGS $LIBGOBJECT_CFLAGS; shift AS_IF([$CC "$@" -c fmt.c 1>/dev/null 2>out && $AWK -f fmt.awk out], [fmt_warnings=:], [AS_IF([$CC "$@" -Wformat -c fmt.c 1>/dev/null 2>out && $AWK -f fmt.awk out], [CFLAGS="$CFLAGS -Wformat" fmt_warnings=:])]) AT_DATA([main.c], [[#include #include "str.h" int main(void) { Str *test_good, *test_bad; char *stupid_pointer = "ug"; int the_answer = 42; g_type_init (); /* This works fine. */ test_good = (Str *) (str_new ("%d", the_answer)); test_good = test_good; /* This gets a warning thanks to our function attribute. */ test_bad = (Str *) (str_new ("%d", stupid_pointer)); test_bad = test_bad; return 0; } ]]) str_gob=$abs_top_srcdir/t/str.gob AT_CHECK([gob2 "$str_gob"]) AT_CHECK([$HAVE_GOBJECT_PRIVATES || exit 77]) TEST_COMPILE_GOBJECT([str.c], [0], [], [stderr]) mv stderr str_stderr TEST_COMPILE_GOBJECT([main.c], [0], [], [stderr]) mv stderr main_stderr TEST_LINK_GOBJECT([main], [str.o main.o]) AT_DATA([str.awk], [[/want a string/ { lines[NR] = 1; } END { FS=":"; while ((rc = getline < "str_stderr") > 0) { sub(/.*[\/]/, "", $1); if (/%s/ && $1 == "str.gob" && $2 in lines) lines[$2]--; } if (rc < 0) exit(1); count=0; for (l in lines) { if (lines[l]) exit(1); count++; } exit(count != 2); } ]]) # Check for correct diagnostic messages on the target lines... AT_CHECK([$fmt_warnings || exit 77 $AWK -f str.awk "$str_gob" || exit 1 $AWK -f - main_stderr <<'EOF' BEGIN { pass=0; FS=":"; } /%d/ && $1 == "main.c" && $2 == 17 { pass=1; } END { exit(!pass); } EOF]) AT_CLEANUP dnl Check that dynamic types are accepted and compile OK... AT_SETUP([dynamic types]) AT_KEYWORDS([dynamic]) AT_DATA([test.gob], [[%ctop{ #include %} class :Test from G:Object (dynamic) { public void test(void) { } } ]]) AT_CHECK([gob2 test.gob]) TEST_COMPILE_GOBJECT([test.c], [0], [], [ignore]) AT_DATA([main.c], [[#include #include "test.h" int main(void) { g_type_init(); test_register_type(NULL); } ]]) TEST_COMPILE_GOBJECT([main.c], [0], [], [ignore]) TEST_LINK_GOBJECT([main], [test.o main.o]) AT_CLEANUP dnl Dynamic types: simple test case which checks that we can instantiate a dnl dynamic type after registration. AT_SETUP([dynamic type registration]) AT_KEYWORDS([dynamic runtime]) AT_DATA([test.gob], [[%ctop{ #include %} %{ #include %} class :Test from G:Object (dynamic) { public gchar *s = { g_strdup("(nil)") }; property STRING s (link); public void test(self) { printf("%s\n", self->s); } } ]]) AT_CHECK([gob2 test.gob]) TEST_COMPILE_GOBJECT([test.c], [0], [], [ignore]) TEST_TYPE_MODULE([:Test]) AT_DATA([main.c], [[#include #include "test.h" #include "test-mod.h" void devnull(const char *a, GLogLevelFlags b, const char *c, gpointer d) { } int main(void) { guint handler; Test *t; g_type_init(); /* should fail, suppress internal glib logging... */ handler = g_log_set_handler("GLib-GObject", G_LOG_LEVEL_MASK, devnull, 0); t = g_object_new(test_get_type(), NULL); if (t != NULL) return EXIT_FAILURE; g_log_remove_handler("GLib-GObject", handler); /* Register dynamic type */ g_type_module_use(g_object_new(test_mod_get_type(), NULL)); /* should work now */ t = g_object_new(test_get_type(), "s", "Hello, World", (char *)NULL); if (!t) return EXIT_FAILURE; test_test(t); return EXIT_SUCCESS; } ]]) TEST_COMPILE_GOBJECT([main.c], [0], [], [ignore]) TEST_LINK_GOBJECT([main], [test.o test-mod.o main.o]) AT_CHECK([./main], [0], [Hello, World ]) AT_CLEANUP AT_SETUP([GOB2_CHECK min-version test]) AT_DATA([configure.ac], [[AC_PREREQ([2.62]) AC_INIT([test], [0]) AC_OUTPUT ]]) AT_CHECK([$AUTOCONF && test -f configure || exit 77], [0], [ignore], [ignore]) m4_define([MYVER], m4_bpatsubst(m4_dquote(m4_defn([AT_PACKAGE_VERSION])), [[^][0-9.]])) m4_define([MYVER_P1], m4_dquote(m4_reverse(m4_unquote( m4_split(m4_defn([MYVER]), [[.]]))))) m4_define([MYVER_P1], m4_join([.], m4_reverse( m4_eval(m4_car(MYVER_P1)+1), m4_shift(MYVER_P1)))) AT_DATA([test.in], [[@GOB2@ ]]) cat >configure.ac <expout AT_CHECK([cat test], [0], [expout], [ignore]) sed '/GOB2_CHECK/c\ [GOB2_CHECK(]m4_dquote(m4_defn([MYVER_P1]))[)]' configure.ac >configure.new mv -f configure.new configure.ac AT_CHECK([$AUTOCONF --force]) AT_CHECK([./configure], [1], [ignore], [ignore]) AT_CLEANUP AT_SETUP([private data members]) AT_DATA([test.gob], [[%ctop{ #include %} class :Test from G:Object { private int x = 42; public int get_x(G:Object *go) { return TEST(go)->_priv->x; } public void set_x(G:Object *go, int val) { TEST(go)->_priv->x = val; } } ]]) AT_CHECK([gob2 test.gob]) AT_CHECK([$HAVE_GOBJECT_PRIVATES || exit 77]) TEST_COMPILE_GOBJECT([test.c], [0], [], [ignore]) AT_DATA([main.c], [[#include #include #include "test.h" int main(void) { GObject *go; g_type_init(); go = g_object_new(test_get_type(), NULL); printf("%d\n", test_get_x(go)); printf("%d\n", (test_set_x(go, 123), test_get_x(go))); return 0; } ]]) TEST_COMPILE_GOBJECT([main.c], [0], [], [ignore]) TEST_LINK_GOBJECT([main], [test.o main.o]) AT_CHECK([./main], [0], [42 123 ]) AT_CLEANUP AT_SETUP([private data members (dynamic)]) AT_DATA([test.gob], [[%ctop{ #include %} class :Test from G:Object (dynamic) { private int x = 54; public int get_x(G:Object *go) { return TEST(go)->_priv->x; } public void set_x(G:Object *go, int val) { TEST(go)->_priv->x = val; } } ]]) AT_CHECK([gob2 test.gob]) AT_CHECK([$HAVE_GOBJECT_PRIVATES || exit 77]) TEST_COMPILE_GOBJECT([test.c], [0], [], [ignore]) TEST_TYPE_MODULE([:Test]) AT_DATA([main.c], [[#include #include #include "test.h" #include "test-mod.h" int main(void) { GObject *go; g_type_init(); g_type_module_use(g_object_new(test_mod_get_type(), NULL)); go = g_object_new(test_get_type(), NULL); printf("%d\n", test_get_x(go)); printf("%d\n", (test_set_x(go, 123), test_get_x(go))); return 0; } ]]) TEST_COMPILE_GOBJECT([main.c], [0], [], [ignore]) TEST_LINK_GOBJECT([main], [test.o test-mod.o main.o]) AT_CHECK([./main], [0], [54 123 ]) AT_CLEANUP