1 #include "xxl.h"
2 
3 #include <stdlib.h>
4 
5 #define FAIL(why)                                                           \
6     do {                                                                    \
7         fprintf(stderr, "%s\n", (why));                                     \
8         exit(1);                                                            \
9     } while (0)
10 
11 typedef struct {
12     int cleaned;
13 } test_asset_t;
14 
15 static void
cleanup_test_asset(void * asset,void * arg)16 cleanup_test_asset(void *asset, void *arg)
17 {
18     ((test_asset_t *)asset)->cleaned = 1;
19 }
20 
21 static void
test_catch(void)22 test_catch(void)
23 {
24     int caught, pass;
25 
26     for (pass = 0;  pass < 3;  pass++)
27     {
28         XXL_TRY_BEGIN {
29             caught = 0;
30             switch (pass)
31             {
32                 case 0: XXL_THROW_ERROR(0x42174217, NULL);
33                 case 1: XXL_THROW_ERROR(0x17421742, NULL);
34                 case 2: break;
35             }
36         }
37         XXL_CATCH(0x42174217) { caught = 1; }
38         XXL_EXCEPT            { caught = 2; }
39         XXL_TRY_END;
40 
41         switch (pass)
42         {
43             case 0:
44                 if (caught == 0) FAIL("Did not catch exception 0x42174217\n");
45                 if (caught == 2) FAIL("Caught 0x42174217 as 0x17421742\n");
46                 if (caught != 1) FAIL("(catch pass 0) 'caught' is totally wrong!\n");
47                 break;
48             case 1:
49                 if (caught == 0) FAIL("Did not catch exception 0x17421742\n");
50                 if (caught == 1) FAIL("Caught 0x17421742 as 0x42174217\n");
51                 if (caught != 2) FAIL("(catch pass 1) 'caught' is totally wrong!\n");
52 
53                 break;
54             default:
55                 if (caught != 0) FAIL("Exception caught when none thrown\n");
56                 break;
57         }
58     }
59 }
60 
61 static void
test_finally(void)62 test_finally(void)
63 {
64     int caught, finally, pass;
65 
66     for (pass = 0;  pass < 3;  pass++)
67     {
68         XXL_TRY_BEGIN
69         {
70             caught = finally = 0;
71             switch (pass)
72             {
73                 case 0: break;
74                 case 1: XXL_THROW_ERROR(0x42174217, NULL);
75                 case 2: XXL_THROW_ERROR(0x17421742, NULL);
76             }
77         }
78         XXL_CATCH(0x42174217)   { caught  = 1; }
79         XXL_EXCEPT              { caught  = 2; }
80         XXL_FINALLY             { finally = 1; }
81         XXL_TRY_END;
82 
83         switch (pass)
84         {
85             case 0:
86                 if (caught == 1) FAIL("Caught 0x42174217 when none thrown with finally\n");
87                 if (caught == 2) FAIL("Caught 0x17421742 when none thrown with finally\n");
88                 if (caught != 0) FAIL("(finally pass 0) 'caught' is totally wrong!\n");
89                 if (!finally)    FAIL("Finally failed to run when no exception thrown\n");
90                 break;
91             case 1:
92                 if (caught == 0) FAIL("Did not catch exception 0x42174217 with finally\n");
93                 if (caught == 2) FAIL("Caught 0x42174217 as 0x17421742 with finally\n");
94                 if (caught != 1) FAIL("(finally pass 1) 'caught' is totally wrong!\n");
95                 if (!finally)    FAIL("Finally failed to run when specific exception caught\n");
96                 break;
97             case 2:
98                 if (caught == 0) FAIL("Did not catch exception 0x17421742 with finally\n");
99                 if (caught == 1) FAIL("Caught 0x17421742 as 0x42174217 with finally\n");
100                 if (caught != 2) FAIL("(finally pass 2) 'caught' is totally wrong!\n");
101                 if (!finally)    FAIL("Finally failed to run when non-specific exception caught\n");
102                 break;
103         }
104     }
105 }
106 
107 static void
test_assets(void)108 test_assets(void)
109 {
110     int             pass;
111     test_asset_t    asset;
112     xxl_assettype_t type;
113 
114     for (pass = 0;  pass < 8;  pass++)
115     {
116         XXL_TRY_BEGIN
117         {
118             asset.cleaned = 0;
119             switch (pass)
120             {
121                 case 0: case 4: type = XXL_ASSET_PERMANENT;  break;
122                 case 1: case 5: type = XXL_ASSET_TEMPORARY;  break;
123                 case 2: case 6: type = XXL_ASSET_PROMOTE;    break;
124                 case 3: case 7: type = XXL_ASSET_DEMOTE;     break;
125             }
126             XXL_ASSET_SAVE(&asset, cleanup_test_asset, NULL, type);
127             if (pass > 3) XXL_THROW_ERROR(0x42174217, NULL);
128         }
129         XXL_EXCEPT {}
130         XXL_TRY_END;
131 
132         switch (pass)
133         {
134             case 0:
135                 if (asset.cleaned)
136                     FAIL("PERMANENT asset cleaned; no exception thrown\n");
137                 break;
138             case 1:
139                 if (!asset.cleaned)
140                     FAIL("TEMPORARY asset NOT cleaned; no exception thrown\n");
141                 break;
142             case 2:
143                 if (asset.cleaned)
144                     FAIL("PROMOTE asset cleaned; no exception thrown\n");
145                 break;
146             case 3:
147                 if (!asset.cleaned)
148                     FAIL("DEMOTE asset NOT cleaned; no exception thrown\n");
149                 break;
150             case 4:
151                 if (asset.cleaned)
152                     FAIL("PERMANENT asset cleaned; exception thrown\n");
153                 break;
154             case 5:
155                 if (!asset.cleaned)
156                     FAIL("TEMPORARY asset NOT cleaned; exception thrown\n");
157                 break;
158             case 6:
159                 if (!asset.cleaned)
160                     FAIL("PROMOTE asset NOT cleaned; exception thrown\n");
161                 break;
162             case 7:
163                 if (asset.cleaned)
164                     FAIL("DEMOTE asset cleaned; exception thrown\n");
165                 break;
166         }
167     }
168 }
169 
170 static void
test_nested(void)171 test_nested(void)
172 {
173     int caught, inner_finally, outer_finally, pass;
174 
175     for (pass = 0;  pass < 2;  pass++)
176     {
177         XXL_TRY_BEGIN
178         {
179             caught = inner_finally = outer_finally = 0;
180             XXL_TRY_BEGIN
181             {
182                 switch (pass)
183                 {
184                     case 0: XXL_THROW_ERROR(0x42174217, NULL);
185                     case 1: XXL_THROW_ERROR(0x17421742, NULL);
186                 }
187             }
188             XXL_CATCH(0x42174217)   { XXL_RETHROW_ERROR(); }
189             XXL_FINALLY             { inner_finally = 1;   }
190             XXL_TRY_END;
191         }
192         XXL_CATCH(0x42174217)       { caught = 1;          }
193         XXL_CATCH(0x17421742)       { caught = 2;          }
194         XXL_FINALLY                 { outer_finally = 1;   }
195         XXL_TRY_END;
196 
197         switch (pass)
198         {
199             case 0:
200                 if (caught == 0)    FAIL("Outer try did not catch 0x42174217\n");
201                 if (caught == 2)    FAIL("Outer try caught 0x42174217 as 0x17421742\n");
202                 if (caught != 1)    FAIL("(nested pass 0) 'caught' is totally wrong!\n");
203                 if (!inner_finally) FAIL("(nested pass 0) Inner finally block did not run\n");
204                 if (!outer_finally) FAIL("(nested pass 0) Outer finally block did not run\n");
205                 break;
206             case 1:
207                 if (caught == 0)    FAIL("Outer try did not catch 0x17421742\n");
208                 if (caught == 1)    FAIL("Outer try caught 0x17421742 as 0x42174217\n");
209                 if (caught != 2)    FAIL("(nested pass 1) 'caught' is totally wrong!\n");
210                 if (!inner_finally) FAIL("(nested pass 1) Inner finally block did not run\n");
211                 if (!outer_finally) FAIL("(nested pass 1) Outer finally block did not run\n");
212                 break;
213         }
214     }
215 }
216 
main(int argc,char * agrv[])217 int main(int argc, char *agrv[])
218 {
219     printf("Testing simple exception catching ...\n");
220     test_catch();
221 
222     printf("Testing simple finally block execution ...\n");
223     test_finally();
224 
225     printf("Testing simple asset management ...\n");
226     test_assets();
227 
228     printf("Testing nested exception handling ...\n");
229     test_nested();
230 
231     exit(0);
232     return 0;
233 }
234