X-Git-Url: https://git.draconx.ca/gitweb/gob-dx.git/blobdiff_plain/4f931a71edce4d7456c233487703a894410fd599..4e6eb5db5593f2d73c2c9af9c925e1a2866c8303:/tests/general.at diff --git a/tests/general.at b/tests/general.at index 9e5fbcc..52c3fca 100644 --- a/tests/general.at +++ b/tests/general.at @@ -1,4 +1,4 @@ -dnl Copyright © 2019 Nick Bowler +dnl Copyright © 2019-2022 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. @@ -21,22 +21,48 @@ 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 "str.h" +[[#include +#include "str.h" int main(void) { - g_type_init (); - - int the_answer = 42; + Str *test_good, *test_bad; char *stupid_pointer = "ug"; + int the_answer = 42; + + g_type_init (); /* This works fine. */ - Str *test_good = (Str *) (str_new ("%d", the_answer)); + test_good = (Str *) (str_new ("%d", the_answer)); test_good = test_good; /* This gets a warning thanks to our function attribute. */ - Str *test_bad = (Str *) (str_new ("%d", stupid_pointer)); + test_bad = (Str *) (str_new ("%d", stupid_pointer)); test_bad = test_bad; return 0; @@ -45,25 +71,46 @@ int main(void) 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 +AT_CHECK([$CC $CFLAGS $LDFLAGS $LIBGOBJECT_LIBS -o main str.o main.o]) -# Check for correct diagnostic messages on the target lines... -AT_CHECK([awk '/want a string/ { print NR }' "$str_gob" >str_lines]) -total=0 -exec 3 0) { + sub(/.*[\/]/, "", $1); + if (/%s/ && $1 == "str.gob" && $2 in lines) + lines[$2]--; + } -TEST_COMPILE_GOBJECT([main.c], [0], [], [stderr]) -AT_CHECK([awk -NF : '$1 == "main.c" && $2 == "15" { exit 42 }' stderr], [42]) + if (rc < 0) + exit(1); -AT_CHECK([$CC $CFLAGS $LDFLAGS $LIBGOBJECT_LIBS -o main str.o main.o]) + 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 @@ -71,8 +118,10 @@ dnl Check that dynamic types are accepted and compile OK... AT_SETUP([dynamic types]) AT_KEYWORDS([dynamic]) -AT_DATA([test.gob], -[[class :Test from G:Object (dynamic) +AT_DATA([test.gob], [[%ctop{ +#include +%} +class :Test from G:Object (dynamic) { public void test(void) { @@ -80,17 +129,19 @@ AT_DATA([test.gob], } ]]) AT_CHECK([gob2 test.gob]) +TEST_COMPILE_GOBJECT([test.c], [0], [], [ignore]) AT_DATA([main.c], -[[#include "test.h" +[[#include +#include "test.h" int main(void) { + g_type_init(); test_register_type(NULL); } ]]) - -TEST_COMPILE_GOBJECT([test.c], [0], [], [ignore]) TEST_COMPILE_GOBJECT([main.c], [0], [], [ignore]) + AT_CHECK([$CC $CFLAGS $LDFLAGS $LIBGOBJECT_LIBS -o main test.o main.o]) AT_CLEANUP @@ -100,8 +151,10 @@ dnl dynamic type after registration. AT_SETUP([dynamic type registration]) AT_KEYWORDS([dynamic runtime]) -AT_DATA([test.gob], -[[%{ +AT_DATA([test.gob], [[%ctop{ +#include +%} +%{ #include %} class :Test from G:Object (dynamic) @@ -115,34 +168,25 @@ class :Test from G:Object (dynamic) } } ]]) +AT_CHECK([gob2 test.gob]) +TEST_COMPILE_GOBJECT([test.c], [0], [], [ignore]) -AT_DATA([mod.gob], -[[%{ -#include "test.h" -%} -class :Mod from G:Type:Module -{ - override (G:Type:Module) gboolean load(G:Type:Module *m) - { - test_register_type(m); - return TRUE; - } -} -]]) +TEST_TYPE_MODULE([:Test]) AT_DATA([main.c], -[[#include -#include "mod.h" +[[#include #include "test.h" +#include "test-mod.h" void devnull(const char *a, GLogLevelFlags b, const char *c, gpointer d) { } int main(void) { - GTypeModule *m = g_object_new(mod_get_type(), NULL); 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); @@ -150,7 +194,9 @@ int main(void) return EXIT_FAILURE; g_log_remove_handler("GLib-GObject", handler); - g_type_module_use(m); + /* 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) @@ -160,109 +206,147 @@ int main(void) return EXIT_SUCCESS; } ]]) - -AT_CHECK([gob2 mod.gob]) -AT_CHECK([gob2 test.gob]) -TEST_COMPILE_GOBJECT([mod.c], [0], [], [ignore]) -TEST_COMPILE_GOBJECT([test.c], [0], [], [ignore]) TEST_COMPILE_GOBJECT([main.c], [0], [], [ignore]) -AT_CHECK([$CC $CFLAGS $LDFLAGS $LIBGOBJECT_LIBS -o main mod.o test.o main.o]) + +AT_CHECK([$CC $CFLAGS $LDFLAGS $LIBGOBJECT_LIBS -o main \ + test.o test-mod.o main.o]) AT_CHECK([./main], [0], [Hello, World ]) AT_CLEANUP -dnl Dynamic types: check that we can call interface methods of dynamic types. -AT_SETUP([dynamic interface implementation]) -AT_KEYWORDS([dynamic runtime interface]) +AT_SETUP([GOB2_CHECK min-version test]) -AT_DATA([iface.h], -[[#define IF_TYPE_TEST if_test_get_type() +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]) -typedef struct IFTestIface { - GTypeInterface parent; +m4_define([MYVER], + m4_bpatsubst(m4_dquote(m4_defn([AT_PACKAGE_VERSION])), [[^][0-9.]])) - void (*test)(GObject *obj); -} IFTestIface; +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)))) -GType if_test_get_type(void); +AT_DATA([test.in], [[@GOB2@ ]]) -AT_DATA([test.gob], -[[%{ -#include -#include "iface.h" -%} +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]) -class :Test from G:Object (dynamic) - (interface IF:Test) +AT_CLEANUP + +AT_SETUP([private data members]) + +AT_DATA([test.gob], [[%ctop{ +#include +%} +class :Test from G:Object { - private const char *s = { "Hello, World!" }; - interface IF:Test private void test(G:Object *o) - { - Self *self = SELF(o); - printf("%s\n", self->_priv->s); - } + 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([mod.gob], -[[%{ +AT_DATA([main.c], [[#include +#include #include "test.h" -%} -class :Mod from G:Type:Module + +int main(void) { - override (G:Type:Module) gboolean load(G:Type:Module *m) - { - test_register_type(m); - return TRUE; - } + 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]) -AT_DATA([main.c], -[[#include "test.h" -#include "mod.h" -#include "iface.h" +AT_CHECK([$CC $CFLAGS $LDFLAGS $LIBGOBJECT_LIBS -o main \ + test.o main.o]) +AT_CHECK([./main], [0], [42 +123 +]) + +AT_CLEANUP + +AT_SETUP([private data members (dynamic)]) -GType if_test_get_type(void) +AT_DATA([test.gob], [[%ctop{ +#include +%} +class :Test from G:Object (dynamic) { - static GType type = 0; - if (type == 0) { - static const GTypeInfo info = { - sizeof (IFTestIface), - NULL, - NULL, - }; - - type = g_type_register_static(G_TYPE_INTERFACE, "IFTest", &info, 0); - } - return type; + 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) { - GTypeModule *m = g_object_new(TYPE_MOD, NULL); - GObject *t; + GObject *go; - g_type_module_use(m); - t = g_object_new(TYPE_TEST, NULL); + g_type_init(); + g_type_module_use(g_object_new(test_mod_get_type(), NULL)); + go = g_object_new(test_get_type(), NULL); - g_return_val_if_fail(G_TYPE_CHECK_INSTANCE_TYPE(t, IF_TYPE_TEST), - EXIT_FAILURE); - G_TYPE_INSTANCE_GET_INTERFACE(t, IF_TYPE_TEST, IFTestIface)->test(t); + printf("%d\n", test_get_x(go)); + printf("%d\n", (test_set_x(go, 123), test_get_x(go))); - return EXIT_SUCCESS; + return 0; } ]]) - -AT_CHECK([gob2 mod.gob]) -AT_CHECK([gob2 test.gob]) -TEST_COMPILE_GOBJECT([mod.c], [0], [], [ignore]) -TEST_COMPILE_GOBJECT([test.c], [0], [], [ignore]) TEST_COMPILE_GOBJECT([main.c], [0], [], [ignore]) -AT_CHECK([$CC $CFLAGS $LDFLAGS $LIBGOBJECT_LIBS -o main mod.o test.o main.o]) -AT_CHECK([./main], [0], [Hello, World! + +AT_CHECK([$CC $CFLAGS $LDFLAGS $LIBGOBJECT_LIBS -o main \ + test.o test-mod.o main.o]) +AT_CHECK([./main], [0], [54 +123 ]) AT_CLEANUP