]> git.draconx.ca Git - gob-dx.git/blob - tests/interface.at
61c42bb4f35ce8cab82437d8c0829e7f8c279597
[gob-dx.git] / tests / interface.at
1 dnl Copyright © 2020 Nick Bowler
2 dnl License GPLv2+: GNU General Public License version 2 or any later version.
3 dnl This is free software: you are free to change and redistribute it.
4 dnl There is NO WARRANTY, to the extent permitted by law.
5
6 dnl TEST_TYPE_MODULE(Class:Name)
7 dnl Create a GTypeModule (Class:Name:Mod) which registers the dynamic
8 dnl type indiciated by Class:Name.
9 m4_define([TEST_TYPE_MODULE],
10 [TEST_TYPE_MODULE_([$1], m4_translit([[$1]], [:A-Z], [_a-z]),
11   m4_translit([[$1]], [:A-Z], [-a-z]))])
12
13 m4_define([TEST_TYPE_MODULE_],
14 [AT_KEYWORDS([dynamic])dnl
15
16 AT_DATA([$3-mod.gob], [[%{
17 #include "$3.h"
18 %}
19 class $1:Mod from G:Type:Module
20 {
21   override (G:Type:Module) gboolean load(G:Type:Module *m)
22   {
23     $2_register_type(m);
24     return TRUE;
25   }
26 }
27 ]])
28 AT_CHECK([gob2 $3-mod.gob])
29 TEST_COMPILE_GOBJECT([$3-mod.c], [0], [], [ignore])])
30
31 dnl Create the Test:Fooable interface with the following interface method:
32 dnl
33 dnl   int foo(G:Object *obj);
34 dnl
35 dnl Link in test-fooable.o
36 m4_define([TEST_FOOABLE_IFACE],
37 [AT_KEYWORDS([interface])dnl
38 AT_CHECK([cp $srcdir/t/test-fooable.c $srcdir/t/test-fooable.h .])
39 TEST_COMPILE_GOBJECT([test-fooable.c], [0], [], [ignore])])
40
41 dnl TEST_FOOABLE_IMPL(Class:Name, Parent:Class, foo_body)
42 dnl TEST_FOOABLE_IMPL_DYN(Class:Name, Parent:Class, foo_body)
43 m4_define([TEST_FOOABLE_IMPL],
44   [TEST_FOOABLE_IMPL_([$1], m4_translit([[$1]], [:A-Z], [-a-z]),
45                       [$2], m4_translit([[$2]], [:A-Z], [-a-z]),
46                       [$3], [$4])])
47
48 m4_define([TEST_FOOABLE_IMPL_DYN],
49 [TEST_FOOABLE_IMPL([$1], [$2], [$3], [(dynamic)])
50 TEST_TYPE_MODULE([$1])])
51
52 m4_define([TEST_FOOABLE_IMPL_],
53 [AT_DATA([$2.gob], [[%{
54 #include <stdio.h>
55 #include <stdlib.h>
56 #include "test-fooable.h"
57 %}
58 ]m4_if([$4], [g-object], [], [[
59 %h{
60 #include "$4.h"
61 %}
62 ]])[
63 class $1 from $3]m4_default_nblank([
64   $6])[
65   (interface Test:Fooable)
66 {
67   interface Test:Fooable private int foo(G:Object *go)
68     onerror 88
69   {
70     $5
71     abort();
72   }
73 }
74 ]])
75 AT_CHECK([gob2 $2.gob])
76 TEST_COMPILE_GOBJECT([$2.c], [0], [], [ignore])])
77
78 dnl Test that a static type can implement an interface.
79 AT_SETUP([interface implementation])
80 AT_KEYWORDS([runtime])dnl
81
82 TEST_FOOABLE_IFACE()
83 TEST_FOOABLE_IMPL([Test:A], [G:Object], [return 42;])
84
85 AT_DATA([main.c],
86 [[#include <stdio.h>
87 #include <stdlib.h>
88 #include "test-fooable.h"
89 #include "test-a.h"
90
91 int main(void)
92 {
93   int rc;
94
95   rc = test_foo(g_object_new(TEST_TYPE_A, NULL));
96   printf("%d\n", rc);
97   if (rc < 0)
98     return EXIT_FAILURE;
99   return 0;
100 }
101 ]])
102 TEST_COMPILE_GOBJECT([main.c], [0], [], [ignore])
103
104 AT_CHECK([$CC $CFLAGS $LDFLAGS $LIBGOBJECT_LIBS -o main \
105   test-a.o test-fooable.o main.o])
106 AT_CHECK([./main], [0], [42
107 ])
108
109 AT_CLEANUP
110
111 dnl Test that a dynamic type can implement an interface.
112 AT_SETUP([interface implementation (dynamic)])
113 AT_KEYWORDS([runtime])dnl
114
115 TEST_FOOABLE_IFACE()
116 TEST_FOOABLE_IMPL_DYN([Test:A], [G:Object], [return 54;])
117
118 AT_DATA([main.c],
119 [[#include <stdio.h>
120 #include <stdlib.h>
121 #include "test-fooable.h"
122 #include "test-a.h"
123 #include "test-a-mod.h"
124
125 int main(void)
126 {
127   int rc;
128
129   g_type_module_use(g_object_new(TEST_TYPE_A_MOD, NULL));
130
131   rc = test_foo(g_object_new(TEST_TYPE_A, NULL));
132   printf("%d\n", rc);
133   if (rc < 0)
134     return EXIT_FAILURE;
135   return 0;
136 }
137 ]])
138 TEST_COMPILE_GOBJECT([main.c], [0], [], [ignore])
139
140 AT_CHECK([$CC $CFLAGS $LDFLAGS $LIBGOBJECT_LIBS -o main \
141   test-a.o test-a-mod.o test-fooable.o main.o])
142 AT_CHECK([./main], [0], [54
143 ])
144
145 AT_CLEANUP
146
147 dnl Test that a static type can override the interface implementation
148 dnl in the parent type.
149 AT_SETUP([interface method override])
150 AT_KEYWORDS([runtime])dnl
151
152 TEST_FOOABLE_IFACE()
153 TEST_FOOABLE_IMPL([Test:A], [G:Object],
154   [puts("Test:A foo called"); return 42;])
155 TEST_FOOABLE_IMPL([Test:B], [Test:A],
156   [puts("Test:B foo called"); return 54;])
157
158 AT_DATA([main.c],
159 [[#include <stdio.h>
160 #include <stdlib.h>
161 #include "test-fooable.h"
162 #include "test-a.h"
163 #include "test-b.h"
164
165 int main(void)
166 {
167   int rc;
168
169   rc = test_foo(g_object_new(TEST_TYPE_A, NULL));
170   printf("%d\n", rc);
171   if (rc < 0)
172     return EXIT_FAILURE;
173
174   rc = test_foo(g_object_new(TEST_TYPE_B, NULL));
175   printf("%d\n", rc);
176   if (rc < 0)
177     return EXIT_FAILURE;
178
179   return 0;
180 }
181 ]])
182 TEST_COMPILE_GOBJECT([main.c], [0], [], [ignore])
183
184 AT_CHECK([$CC $CFLAGS $LDFLAGS $LIBGOBJECT_LIBS -o main \
185   test-a.o test-b.o test-fooable.o main.o])
186 AT_CHECK([./main], [0], [Test:A foo called
187 42
188 Test:B foo called
189 54
190 ])
191
192 AT_CLEANUP
193
194 dnl Test that a dynamic type can override the interface implementation of
195 dnl a static parent type.
196 AT_SETUP([interface method override (dynamic)])
197 AT_KEYWORDS([runtime])dnl
198
199 TEST_FOOABLE_IFACE()
200 TEST_FOOABLE_IMPL([Test:A], [G:Object],
201   [puts("Test:A foo called"); return 42;])
202 TEST_FOOABLE_IMPL_DYN([Test:B], [Test:A],
203   [puts("Test:B foo called"); return 54;])
204
205 AT_DATA([main.c],
206 [[#include <stdio.h>
207 #include "test-fooable.h"
208 #include "test-a.h"
209 #include "test-b.h"
210 #include "test-b-mod.h"
211
212 int main(void)
213 {
214   int rc;
215
216   g_type_module_use(g_object_new(TEST_TYPE_B_MOD, NULL));
217
218   rc = test_foo(g_object_new(TEST_TYPE_A, NULL));
219   printf("%d\n", rc);
220   if (rc < 0)
221     return EXIT_FAILURE;
222
223   rc = test_foo(g_object_new(TEST_TYPE_B, NULL));
224   printf("%d\n", rc);
225   if (rc < 0)
226     return EXIT_FAILURE;
227
228   return 0;
229 }
230 ]])
231 TEST_COMPILE_GOBJECT([main.c], [0], [], [ignore])
232
233 AT_CHECK([$CC $CFLAGS $LDFLAGS $LIBGOBJECT_LIBS -o main \
234   test-a.o test-b.o test-b-mod.o test-fooable.o main.o])
235
236 AT_CHECK([./main], [0], [Test:A foo called
237 42
238 Test:B foo called
239 54
240 ])
241
242 AT_CLEANUP
243
244 dnl Test that a dynamic type can override the interface implementation of a
245 dnl dynamic parent type.
246 AT_SETUP([interface method override (dynamic) #2])
247 AT_KEYWORDS([runtime])dnl
248
249 TEST_FOOABLE_IFACE()
250 TEST_FOOABLE_IMPL_DYN([Test:A], [G:Object],
251   [puts("Test:A foo called"); return 42;])
252 TEST_FOOABLE_IMPL_DYN([Test:B], [Test:A],
253   [puts("Test:B foo called"); return 54;])
254
255 AT_DATA([main.c],
256 [[#include <stdio.h>
257 #include "test-fooable.h"
258 #include "test-a.h"
259 #include "test-a-mod.h"
260 #include "test-b.h"
261 #include "test-b-mod.h"
262
263 int main(void)
264 {
265   int rc;
266
267   g_type_module_use(g_object_new(TEST_TYPE_A_MOD, NULL));
268   g_type_module_use(g_object_new(TEST_TYPE_B_MOD, NULL));
269
270   rc = test_foo(g_object_new(TEST_TYPE_A, NULL));
271   printf("%d\n", rc);
272   if (rc < 0)
273     return EXIT_FAILURE;
274
275   rc = test_foo(g_object_new(TEST_TYPE_B, NULL));
276   printf("%d\n", rc);
277   if (rc < 0)
278     return EXIT_FAILURE;
279
280   return 0;
281 }
282 ]])
283 TEST_COMPILE_GOBJECT([main.c], [0], [], [ignore])
284
285 AT_CHECK([$CC $CFLAGS $LDFLAGS $LIBGOBJECT_LIBS -o main \
286   test-a.o test-a-mod.o test-b.o test-b-mod.o test-fooable.o main.o])
287
288 AT_CHECK([./main], [0], [Test:A foo called
289 42
290 Test:B foo called
291 54
292 ])
293
294 AT_CLEANUP
295
296 AT_SETUP([interface method chaining])
297 AT_KEYWORDS([runtime])dnl
298
299 TEST_FOOABLE_IFACE()
300 TEST_FOOABLE_IMPL([Test:A], [G:Object],
301   [puts("Test:A foo called"); return PARENT_HANDLER(go);])
302 TEST_FOOABLE_IMPL([Test:B], [Test:A],
303   [puts("Test:B foo called"); return PARENT_HANDLER(go);])
304 TEST_FOOABLE_IMPL([Test:C], [Test:B],
305   [puts("Test:C foo called"); return PARENT_HANDLER(go);])
306
307 AT_DATA([main.c],
308 [[#include <stdio.h>
309 #include "test-fooable.h"
310 #include "test-a.h"
311 #include "test-b.h"
312 #include "test-c.h"
313
314 int main(void)
315 {
316   int rc;
317
318   rc = test_foo(g_object_new(TEST_TYPE_C, NULL));
319   printf("%d\n", rc);
320   if (rc < 0)
321     return EXIT_FAILURE;
322
323   return 0;
324 }
325 ]])
326
327 TEST_COMPILE_GOBJECT([main.c], [0], [], [ignore])
328
329 AT_CHECK([$CC $CFLAGS $LDFLAGS $LIBGOBJECT_LIBS -o main \
330   test-a.o test-b.o test-c.o test-fooable.o main.o])
331 AT_CHECK([./main], [0], [Test:C foo called
332 Test:B foo called
333 Test:A foo called
334 88
335 ])
336
337 AT_CLEANUP
338
339 AT_SETUP([interface method chaining (dynamic)])
340 AT_KEYWORDS([runtime])dnl
341
342 TEST_FOOABLE_IFACE()
343 TEST_FOOABLE_IMPL_DYN([Test:A], [G:Object],
344   [puts("Test:A foo called"); return PARENT_HANDLER(go);])
345 TEST_FOOABLE_IMPL_DYN([Test:B], [Test:A],
346   [puts("Test:B foo called"); return PARENT_HANDLER(go);])
347 TEST_FOOABLE_IMPL_DYN([Test:C], [Test:B],
348   [puts("Test:C foo called"); return PARENT_HANDLER(go);])
349
350 AT_DATA([main.c],
351 [[#include <stdio.h>
352 #include "test-fooable.h"
353 #include "test-a.h"
354 #include "test-a-mod.h"
355 #include "test-b.h"
356 #include "test-b-mod.h"
357 #include "test-c.h"
358 #include "test-c-mod.h"
359
360 int main(void)
361 {
362   int rc;
363
364   g_type_module_use(g_object_new(TEST_TYPE_A_MOD, NULL));
365   g_type_module_use(g_object_new(TEST_TYPE_B_MOD, NULL));
366   g_type_module_use(g_object_new(TEST_TYPE_C_MOD, NULL));
367
368   rc = test_foo(g_object_new(TEST_TYPE_C, NULL));
369   printf("%d\n", rc);
370   if (rc < 0)
371     return EXIT_FAILURE;
372
373   return 0;
374 }
375 ]])
376
377 TEST_COMPILE_GOBJECT([main.c], [0], [], [ignore])
378
379 AT_CHECK([$CC $CFLAGS $LDFLAGS $LIBGOBJECT_LIBS -o main \
380   test-a.o test-a-mod.o test-b.o test-b-mod.o test-c.o test-c-mod.o \
381   test-fooable.o main.o])
382 AT_CHECK([./main], [0], [Test:C foo called
383 Test:B foo called
384 Test:A foo called
385 88
386 ])
387
388 AT_CLEANUP