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