]> git.draconx.ca Git - gob-dx.git/blob - tests/interface.at
9c368b689d777300a620b849a46d97526fc561a6
[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 <stdlib.h>
208 #include "test-fooable.h"
209 #include "test-a.h"
210 #include "test-b.h"
211 #include "test-b-mod.h"
212
213 int main(void)
214 {
215   int rc;
216
217   g_type_module_use(g_object_new(TEST_TYPE_B_MOD, NULL));
218
219   rc = test_foo(g_object_new(TEST_TYPE_A, NULL));
220   printf("%d\n", rc);
221   if (rc < 0)
222     return EXIT_FAILURE;
223
224   rc = test_foo(g_object_new(TEST_TYPE_B, NULL));
225   printf("%d\n", rc);
226   if (rc < 0)
227     return EXIT_FAILURE;
228
229   return 0;
230 }
231 ]])
232 TEST_COMPILE_GOBJECT([main.c], [0], [], [ignore])
233
234 AT_CHECK([$CC $CFLAGS $LDFLAGS $LIBGOBJECT_LIBS -o main \
235   test-a.o test-b.o test-b-mod.o test-fooable.o main.o])
236
237 AT_CHECK([./main], [0], [Test:A foo called
238 42
239 Test:B foo called
240 54
241 ])
242
243 AT_CLEANUP
244
245 dnl Test that a dynamic type can override the interface implementation of a
246 dnl dynamic parent type.
247 AT_SETUP([interface method override (dynamic) #2])
248 AT_KEYWORDS([runtime])dnl
249
250 TEST_FOOABLE_IFACE()
251 TEST_FOOABLE_IMPL_DYN([Test:A], [G:Object],
252   [puts("Test:A foo called"); return 42;])
253 TEST_FOOABLE_IMPL_DYN([Test:B], [Test:A],
254   [puts("Test:B foo called"); return 54;])
255
256 AT_DATA([main.c],
257 [[#include <stdio.h>
258 #include <stdlib.h>
259 #include "test-fooable.h"
260 #include "test-a.h"
261 #include "test-a-mod.h"
262 #include "test-b.h"
263 #include "test-b-mod.h"
264
265 int main(void)
266 {
267   int rc;
268
269   g_type_module_use(g_object_new(TEST_TYPE_A_MOD, NULL));
270   g_type_module_use(g_object_new(TEST_TYPE_B_MOD, NULL));
271
272   rc = test_foo(g_object_new(TEST_TYPE_A, NULL));
273   printf("%d\n", rc);
274   if (rc < 0)
275     return EXIT_FAILURE;
276
277   rc = test_foo(g_object_new(TEST_TYPE_B, NULL));
278   printf("%d\n", rc);
279   if (rc < 0)
280     return EXIT_FAILURE;
281
282   return 0;
283 }
284 ]])
285 TEST_COMPILE_GOBJECT([main.c], [0], [], [ignore])
286
287 AT_CHECK([$CC $CFLAGS $LDFLAGS $LIBGOBJECT_LIBS -o main \
288   test-a.o test-a-mod.o test-b.o test-b-mod.o test-fooable.o main.o])
289
290 AT_CHECK([./main], [0], [Test:A foo called
291 42
292 Test:B foo called
293 54
294 ])
295
296 AT_CLEANUP
297
298 AT_SETUP([interface method chaining])
299 AT_KEYWORDS([runtime])dnl
300
301 TEST_FOOABLE_IFACE()
302 TEST_FOOABLE_IMPL([Test:A], [G:Object],
303   [puts("Test:A foo called"); return PARENT_HANDLER(go);])
304 TEST_FOOABLE_IMPL([Test:B], [Test:A],
305   [puts("Test:B foo called"); return PARENT_HANDLER(go);])
306 TEST_FOOABLE_IMPL([Test:C], [Test:B],
307   [puts("Test:C foo called"); return PARENT_HANDLER(go);])
308
309 AT_DATA([main.c],
310 [[#include <stdio.h>
311 #include <stdlib.h>
312 #include "test-fooable.h"
313 #include "test-a.h"
314 #include "test-b.h"
315 #include "test-c.h"
316
317 int main(void)
318 {
319   int rc;
320
321   rc = test_foo(g_object_new(TEST_TYPE_C, NULL));
322   printf("%d\n", rc);
323   if (rc < 0)
324     return EXIT_FAILURE;
325
326   return 0;
327 }
328 ]])
329
330 TEST_COMPILE_GOBJECT([main.c], [0], [], [ignore])
331
332 AT_CHECK([$CC $CFLAGS $LDFLAGS $LIBGOBJECT_LIBS -o main \
333   test-a.o test-b.o test-c.o test-fooable.o main.o])
334 AT_CHECK([./main], [0], [Test:C foo called
335 Test:B foo called
336 Test:A foo called
337 88
338 ])
339
340 AT_CLEANUP
341
342 AT_SETUP([interface method chaining (dynamic)])
343 AT_KEYWORDS([runtime])dnl
344
345 TEST_FOOABLE_IFACE()
346 TEST_FOOABLE_IMPL_DYN([Test:A], [G:Object],
347   [puts("Test:A foo called"); return PARENT_HANDLER(go);])
348 TEST_FOOABLE_IMPL_DYN([Test:B], [Test:A],
349   [puts("Test:B foo called"); return PARENT_HANDLER(go);])
350 TEST_FOOABLE_IMPL_DYN([Test:C], [Test:B],
351   [puts("Test:C foo called"); return PARENT_HANDLER(go);])
352
353 AT_DATA([main.c],
354 [[#include <stdio.h>
355 #include <stdlib.h>
356 #include "test-fooable.h"
357 #include "test-a.h"
358 #include "test-a-mod.h"
359 #include "test-b.h"
360 #include "test-b-mod.h"
361 #include "test-c.h"
362 #include "test-c-mod.h"
363
364 int main(void)
365 {
366   int rc;
367
368   g_type_module_use(g_object_new(TEST_TYPE_A_MOD, NULL));
369   g_type_module_use(g_object_new(TEST_TYPE_B_MOD, NULL));
370   g_type_module_use(g_object_new(TEST_TYPE_C_MOD, NULL));
371
372   rc = test_foo(g_object_new(TEST_TYPE_C, NULL));
373   printf("%d\n", rc);
374   if (rc < 0)
375     return EXIT_FAILURE;
376
377   return 0;
378 }
379 ]])
380
381 TEST_COMPILE_GOBJECT([main.c], [0], [], [ignore])
382
383 AT_CHECK([$CC $CFLAGS $LDFLAGS $LIBGOBJECT_LIBS -o main \
384   test-a.o test-a-mod.o test-b.o test-b-mod.o test-c.o test-c-mod.o \
385   test-fooable.o main.o])
386 AT_CHECK([./main], [0], [Test:C foo called
387 Test:B foo called
388 Test:A foo called
389 88
390 ])
391
392 AT_CLEANUP