source: doc/working/exception/impl/test-main.c @ 78372fd

ADTaaron-thesisarm-ehast-experimentalcleanup-dtorsdeferred_resndemanglerenumforall-pointer-decayjacob/cs343-translationjenkins-sandboxnew-astnew-ast-unique-exprnew-envno_listpersistent-indexerpthread-emulationqualifiedEnumresolv-newwith_gc
Last change on this file since 78372fd was 6a48cc9, checked in by Andrew Beach <ajbeach@…>, 7 years ago

More tests for the exception library.

  • Property mode set to 100644
File size: 8.5 KB
Line 
1#include "exception.h"
2
3// Use: gcc -fexceptions -Wall -Werror -g exception.c test-main.c
4
5#include <stdio.h>
6#include <stdbool.h>
7
8// Translation Helpers:
9#define CLEANUP(function) \
10        struct __cleanup_hook __hidden_hook __attribute__((cleanup(function)))
11
12#define SET_UP_RESUME_NODE(handler_function) \
13        struct __try_resume_node node \
14                __attribute__((cleanup(__try_resume_node_delete))); \
15        __try_resume_node_new(&node, handler_function)
16
17void __try_resume_node_new(struct __try_resume_node * node,
18        _Bool (*handler)(exception except)) {
19    node->next = shared_stack.top_resume;
20    shared_stack.top_resume = node;
21    node->try_to_handle = handler;
22}
23
24void __try_resume_node_delete(struct __try_resume_node * node) {
25    shared_stack.top_resume = node->next;
26}
27
28// Local Print On Exit:
29struct raii_base_type {
30        const char * area;
31};
32
33void raii_dtor(struct raii_base_type * this) {
34        printf("Exiting: %s\n", this->area);
35}
36
37#define raii_t __attribute__((cleanup(raii_dtor))) struct raii_base_type
38
39// ===========================================================================
40// Runtime code (post-translation).
41void terminate(int except_value) {
42        raii_t a = {"terminate function"};
43        __throw_terminate(except_value);
44        printf("terminate returned\n");
45}
46
47void resume(int except_value) {
48        raii_t a = {"resume function"};
49        __throw_resume(except_value);
50        printf("resume returned\n");
51}
52
53// Termination Test: Two handlers: no catch, catch
54void bar() {
55        raii_t a = {"bar function"};
56        {
57                void bar_try1() {
58                        terminate(4);
59                }
60                void bar_catch1(int index, exception except) {
61                        switch(except) {
62                        case 1:
63                                printf("bar caught exception 3.\n");
64                                break;
65                        default:
66                                printf("INVALID INDEX in bar: %d (%d)\n", index, except);
67                        }
68                }
69                int bar_match1(exception except) {
70                        if (3 == except) {
71                                return 1;
72                        } else {
73                                return 0;
74                        }
75                }
76                __try_terminate(bar_try1, bar_catch1, bar_match1);
77        }
78}
79
80void foo() {
81        raii_t a = {"foo function"};
82        {
83                void foo_try1() {
84                        bar();
85                }
86                void foo_catch1(int index, exception except) {
87                        switch(index) {
88                        case 1:
89                                printf("foo caught exception 4.\n");
90                                break;
91                        case 2:
92                                printf("foo caught exception 2.\n");
93                                break;
94                        default:
95                                printf("INVALID INDEX in foo: %d (%d)\n", index, except);
96                        }
97                }
98                int foo_match1(exception except) {
99                        if (4 == except) {
100                                return 1;
101                        } else if (2 == except) {
102                                return 2;
103                        } else {
104                                return 0;
105                        }
106                }
107                __try_terminate(foo_try1, foo_catch1, foo_match1);
108        }
109}
110
111// Resumption Two Handler Test: no catch, catch.
112void beta() {
113        raii_t a = {"beta function"};
114        {
115                bool beta_handle1(exception except) {
116                        if (3 == except) {
117                                printf("beta caught exception 3\n");
118                                return true;
119                        } else {
120                                return false;
121                        }
122                }
123                struct __try_resume_node node
124                        __attribute__((cleanup(__try_resume_node_delete)));
125                __try_resume_node_new(&node, beta_handle1);
126                {
127                        resume(4);
128                }
129        }
130}
131void alpha() {
132        raii_t a = {"alpha function"};
133        {
134                bool alpha_handle1(exception except) {
135                        if (2 == except) {
136                                printf("alpha caught exception 2\n");
137                                return true;
138                        } else if (4 == except) {
139                                printf("alpha caught exception 4\n");
140                                return true;
141                        } else {
142                                return false;
143                        }
144                }
145                struct __try_resume_node node
146                        __attribute__((cleanup(__try_resume_node_delete)));
147                __try_resume_node_new(&node, alpha_handle1);
148                {
149                        beta();
150                }
151        }
152}
153
154// Finally Test:
155void farewell() {
156        {
157                void farewell_finally1() {
158                        printf("See you next time\n");
159                }
160                struct __cleanup_hook __hidden_hook
161                        __attribute__((cleanup(farewell_finally1)));
162                {
163                        printf("walk out of farewell\n");
164                }
165        }
166}
167
168// Resume-to-Terminate Test:
169void fallback() {
170        {
171                void fallback_try1() {
172                        resume(1);
173                }
174                void fallback_catch1(int index, exception except) {
175                        switch (index) {
176                        case 1:
177                                printf("fallback caught termination 1\n");
178                                break;
179                        default:
180                                printf("INVALID INDEX in fallback: %d (%d)\n", index, except);
181                        }
182                }
183                int fallback_match1(exception except) {
184                        if (1 == except) {
185                                return 1;
186                        } else {
187                                return 0;
188                        }
189                }
190                __try_terminate(fallback_try1, fallback_catch1, fallback_match1);
191        }
192}
193
194// Terminate Throw New Exception:
195void terminate_swap() {
196        raii_t a = {"terminate_swap"};
197        {
198                void fn_try1() {
199                        terminate(2);
200                }
201                void fn_catch1(int index, exception except) {
202                        switch (index) {
203                        case 1:
204                                terminate(1);
205                                break;
206                        default:
207                                printf("INVALID INDEX in terminate_swap: %d (%d)\n",
208                                        index, except);
209                        }
210                }
211                int fn_match1(exception except) {
212                        if (2 == except) {
213                                return 1;
214                        } else {
215                                return 0;
216                        }
217                }
218                __try_terminate(fn_try1, fn_catch1, fn_match1);
219        }
220}
221
222void terminate_swapped() {
223        raii_t a = {"terminate_swapped"};
224        {
225                void fn_try1() {
226                        terminate_swap();
227                }
228                void fn_catch1(int index, exception except) {
229                        switch (index) {
230                        case 1:
231                                printf("terminate_swapped caught exception 1\n");
232                                break;
233                        default:
234                                printf("INVALID INDEX in terminate_swapped: %d (%d)\n",
235                                        index, except);
236                        }
237                }
238                int fn_match1(exception except) {
239                        if (1 == except) {
240                                return 1;
241                        } else {
242                                return 0;
243                        }
244                }
245                __try_terminate(fn_try1, fn_catch1, fn_match1);
246        }
247}
248
249// Resume Throw New Exception:
250void resume_swap() {
251        raii_t a = {"terminate_swap"};
252        {
253                bool fn_handle1(exception except) {
254                        if (2 == except) {
255                                resume(1);
256                                return true;
257                        } else {
258                                return false;
259                        }
260                }
261                struct __try_resume_node node
262                        __attribute__((cleanup(__try_resume_node_delete)));
263                __try_resume_node_new(&node, fn_handle1);
264                {
265                        resume(2);
266                }
267        }
268}
269
270void resume_swapped() {
271        {
272                bool fn_handle1(exception except) {
273                        if (1 == except) {
274                                printf("resume_swapped caught exception 1\n");
275                                return true;
276                        } else {
277                                return false;
278                        }
279                }
280                struct __try_resume_node node
281                        __attribute__((cleanup(__try_resume_node_delete)));
282                __try_resume_node_new(&node, fn_handle1);
283                {
284                        resume_swap();
285                }
286        }
287}
288
289// Terminate Rethrow:
290// I don't have an implementation for this.
291
292// Resume Rethrow:
293void reresume() {
294        {
295                bool reresume_handle1(exception except) {
296                        if (1 == except) {
297                                printf("reresume 1 caught exception 1\n");
298                                return true;
299                        } else {
300                                return false;
301                        }
302                }
303                struct __try_resume_node node
304                        __attribute__((cleanup(__try_resume_node_delete)));
305                __try_resume_node_new(&node, reresume_handle1);
306                {
307                        bool reresume_handle2(exception except) {
308                                if (1 == except) {
309                                        printf("reresume 2 caught and rethrows exception 1\n");
310                                        return false;
311                                } else {
312                                        return false;
313                                }
314                        }
315                        struct __try_resume_node node
316                                __attribute__((cleanup(__try_resume_node_delete)));
317                        __try_resume_node_new(&node, reresume_handle2);
318                        {
319                                resume(1);
320                        }
321                }
322        }
323}
324
325// Terminate-Resume interaction:
326void fum() {
327        // terminate block, call resume
328        {
329                void fum_try1() {
330                        resume(3);
331                }
332                void fum_catch1(int index, exception except) {
333                        switch (index) {
334                        case 1:
335                                printf("fum caught exception 3\n");
336                                break;
337                        default:
338                                printf("INVALID INDEX in fum: %d (%d)\n", index, except);
339                        }
340                }
341                int fum_match1(exception except) {
342                        if (3 == except) {
343                                return 1;
344                        } else {
345                                return 0;
346                        }
347                }
348                __try_terminate(fum_try1, fum_catch1, fum_match1);
349        }
350}
351
352void foe() {
353        // resume block, call terminate
354        {
355                bool foe_handle1(exception except) {
356                        if (3 == except) {
357                                printf("foe caught exception 3\n");
358                                return true;
359                        } else {
360                                return false;
361                        }
362                }
363                struct __try_resume_node node
364                        __attribute__((cleanup(__try_resume_node_delete)));
365                __try_resume_node_new(&node, foe_handle1);
366                {
367                        terminate(3);
368                }
369        }
370}
371
372void fy() {
373        // terminate block calls fum, call foe
374        {
375                void fy_try1() {
376                        foe();
377                }
378                void fy_catch1(int index, exception except) {
379                        switch (index) {
380                        case 1:
381                                printf("fy caught exception 3\n");
382                                fum();
383                                break;
384                        default:
385                                printf("INVALID INDEX in fy: %d (%d)\n", index, except);
386                        }
387                }
388                int fy_match1(exception except) {
389                        if (3 == except) {
390                                return 1;
391                        } else {
392                                return 0;
393                        }
394                }
395                __try_terminate(fy_try1, fy_catch1, fy_match1);
396        }
397}
398
399void fee() {
400        // resume block, call fy
401        {
402                bool fee_handle1(exception except) {
403                        if (3 == except) {
404                                printf("fee caught exception 3\n");
405                                return true;
406                        } else {
407                                return false;
408                        }
409                }
410                struct __try_resume_node node
411                        __attribute__((cleanup(__try_resume_node_delete)));
412                __try_resume_node_new(&node, fee_handle1);
413                {
414                        fy();
415                }
416        }
417}
418
419
420// main: choose which tests to run
421int main(int argc, char * argv[]) {
422        raii_t a = {"main function"};
423
424        foo(); printf("\n");
425        alpha(); printf("\n");
426        farewell(); printf("\n");
427        fallback(); printf("\n");
428        terminate_swapped(); printf("\n");
429        resume_swapped(); printf("\n");
430        reresume(); printf("\n");
431        fee(); printf("\n");
432        // Uncaught termination test.
433        terminate(7);
434}
Note: See TracBrowser for help on using the repository browser.