dnl Copyright © 2020 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. dnl TEST_TYPE_MODULE(Class:Name) dnl Create a GTypeModule (Class:Name:Mod) which registers the dynamic dnl type indiciated by Class:Name. m4_define([TEST_TYPE_MODULE], [TEST_TYPE_MODULE_([$1], m4_translit([[$1]], [:A-Z], [_a-z]), m4_translit([[$1]], [:A-Z], [-a-z]))]) m4_define([TEST_TYPE_MODULE_], [AT_KEYWORDS([dynamic])dnl AT_DATA([$3-mod.gob], [[%{ #include "$3.h" %} class $1:Mod from G:Type:Module { override (G:Type:Module) gboolean load(G:Type:Module *m) { $2_register_type(m); return TRUE; } } ]]) AT_CHECK([gob2 $3-mod.gob]) TEST_COMPILE_GOBJECT([$3-mod.c], [0], [], [ignore])]) dnl Create the Test:Fooable interface with the following interface method: dnl dnl int foo(G:Object *obj); dnl dnl Link in test-fooable.o m4_define([TEST_FOOABLE_IFACE], [AT_KEYWORDS([interface])dnl AT_CHECK([cp $srcdir/t/test-fooable.c $srcdir/t/test-fooable.h .]) TEST_COMPILE_GOBJECT([test-fooable.c], [0], [], [ignore])]) dnl TEST_FOOABLE_IMPL(Class:Name, Parent:Class, foo_body) dnl TEST_FOOABLE_IMPL_DYN(Class:Name, Parent:Class, foo_body) m4_define([TEST_FOOABLE_IMPL], [TEST_FOOABLE_IMPL_([$1], m4_translit([[$1]], [:A-Z], [-a-z]), [$2], m4_translit([[$2]], [:A-Z], [-a-z]), [$3], [$4])]) m4_define([TEST_FOOABLE_IMPL_DYN], [TEST_FOOABLE_IMPL([$1], [$2], [$3], [(dynamic)]) TEST_TYPE_MODULE([$1])]) m4_define([TEST_FOOABLE_IMPL_], [AT_DATA([$2.gob], [[%{ #include #include #include "test-fooable.h" %} ]m4_if([$4], [g-object], [], [[ %h{ #include "$4.h" %} ]])[ class $1 from $3]m4_default_nblank([ $6])[ (interface Test:Fooable) { interface Test:Fooable private int foo(G:Object *go) { $5 abort(); } } ]]) AT_CHECK([gob2 $2.gob]) TEST_COMPILE_GOBJECT([$2.c], [0], [], [ignore])]) dnl Test that a static type can implement an interface. AT_SETUP([interface implementation]) AT_KEYWORDS([runtime])dnl TEST_FOOABLE_IFACE() TEST_FOOABLE_IMPL([Test:A], [G:Object], [return 42;]) AT_DATA([main.c], [[#include #include #include "test-fooable.h" #include "test-a.h" int main(void) { int rc; rc = test_foo(g_object_new(TEST_TYPE_A, NULL)); printf("%d\n", rc); if (rc < 0) return EXIT_FAILURE; return 0; } ]]) TEST_COMPILE_GOBJECT([main.c], [0], [], [ignore]) AT_CHECK([$CC $CFLAGS $LDFLAGS $LIBGOBJECT_LIBS -o main \ test-a.o test-fooable.o main.o]) AT_CHECK([./main], [0], [42 ]) AT_CLEANUP dnl Test that a dynamic type can implement an interface. AT_SETUP([interface implementation (dynamic)]) AT_KEYWORDS([runtime])dnl TEST_FOOABLE_IFACE() TEST_FOOABLE_IMPL_DYN([Test:A], [G:Object], [return 54;]) AT_DATA([main.c], [[#include #include #include "test-fooable.h" #include "test-a.h" #include "test-a-mod.h" int main(void) { int rc; g_type_module_use(g_object_new(TEST_TYPE_A_MOD, NULL)); rc = test_foo(g_object_new(TEST_TYPE_A, NULL)); printf("%d\n", rc); if (rc < 0) return EXIT_FAILURE; return 0; } ]]) TEST_COMPILE_GOBJECT([main.c], [0], [], [ignore]) AT_CHECK([$CC $CFLAGS $LDFLAGS $LIBGOBJECT_LIBS -o main \ test-a.o test-a-mod.o test-fooable.o main.o]) AT_CHECK([./main], [0], [54 ]) AT_CLEANUP dnl Test that a static type can override the interface implementation dnl in the parent type. AT_SETUP([interface method override]) AT_KEYWORDS([runtime])dnl TEST_FOOABLE_IFACE() TEST_FOOABLE_IMPL([Test:A], [G:Object], [puts("Test:A foo called"); return 42;]) TEST_FOOABLE_IMPL([Test:B], [Test:A], [puts("Test:B foo called"); return 54;]) AT_DATA([main.c], [[#include #include #include "test-fooable.h" #include "test-a.h" #include "test-b.h" int main(void) { int rc; rc = test_foo(g_object_new(TEST_TYPE_A, NULL)); printf("%d\n", rc); if (rc < 0) return EXIT_FAILURE; rc = test_foo(g_object_new(TEST_TYPE_B, NULL)); printf("%d\n", rc); if (rc < 0) return EXIT_FAILURE; return 0; } ]]) TEST_COMPILE_GOBJECT([main.c], [0], [], [ignore]) AT_CHECK([$CC $CFLAGS $LDFLAGS $LIBGOBJECT_LIBS -o main \ test-a.o test-b.o test-fooable.o main.o]) AT_CHECK([./main], [0], [Test:A foo called 42 Test:B foo called 54 ]) AT_CLEANUP dnl Test that a dynamic type can override the interface implementation of dnl a static parent type. AT_SETUP([interface method override (dynamic)]) AT_KEYWORDS([runtime])dnl TEST_FOOABLE_IFACE() TEST_FOOABLE_IMPL([Test:A], [G:Object], [puts("Test:A foo called"); return 42;]) TEST_FOOABLE_IMPL_DYN([Test:B], [Test:A], [puts("Test:B foo called"); return 54;]) AT_DATA([main.c], [[#include #include "test-fooable.h" #include "test-a.h" #include "test-b.h" #include "test-b-mod.h" int main(void) { int rc; g_type_module_use(g_object_new(TEST_TYPE_B_MOD, NULL)); rc = test_foo(g_object_new(TEST_TYPE_A, NULL)); printf("%d\n", rc); if (rc < 0) return EXIT_FAILURE; rc = test_foo(g_object_new(TEST_TYPE_B, NULL)); printf("%d\n", rc); if (rc < 0) return EXIT_FAILURE; return 0; } ]]) TEST_COMPILE_GOBJECT([main.c], [0], [], [ignore]) AT_CHECK([$CC $CFLAGS $LDFLAGS $LIBGOBJECT_LIBS -o main \ test-a.o test-b.o test-b-mod.o test-fooable.o main.o]) # Currently borked AT_XFAIL_IF([:]) AT_CHECK([./main], [0], [Test:A foo called 42 Test:B foo called 54 ]) AT_CLEANUP dnl Test that a dynamic type can override the interface implementation of a dnl dynamic parent type. AT_SETUP([interface method override (dynamic) #2]) AT_KEYWORDS([runtime])dnl TEST_FOOABLE_IFACE() TEST_FOOABLE_IMPL_DYN([Test:A], [G:Object], [puts("Test:A foo called"); return 42;]) TEST_FOOABLE_IMPL_DYN([Test:B], [Test:A], [puts("Test:B foo called"); return 54;]) AT_DATA([main.c], [[#include #include "test-fooable.h" #include "test-a.h" #include "test-a-mod.h" #include "test-b.h" #include "test-b-mod.h" int main(void) { int rc; g_type_module_use(g_object_new(TEST_TYPE_A_MOD, NULL)); g_type_module_use(g_object_new(TEST_TYPE_B_MOD, NULL)); rc = test_foo(g_object_new(TEST_TYPE_A, NULL)); printf("%d\n", rc); if (rc < 0) return EXIT_FAILURE; rc = test_foo(g_object_new(TEST_TYPE_B, NULL)); printf("%d\n", rc); if (rc < 0) return EXIT_FAILURE; return 0; } ]]) TEST_COMPILE_GOBJECT([main.c], [0], [], [ignore]) AT_CHECK([$CC $CFLAGS $LDFLAGS $LIBGOBJECT_LIBS -o main \ test-a.o test-a-mod.o test-b.o test-b-mod.o test-fooable.o main.o]) # Currently borked AT_XFAIL_IF([:]) AT_CHECK([./main], [0], [Test:A foo called 42 Test:B foo called 54 ]) AT_CLEANUP