1#include <stdio.h>
2
3#include <string>
4
5#include "exceptions.h"
6
7using std::string;
8
9static const char *kCaughtNothing		= "nothing";
10static const char *kCaughtGeneric		= "generic";
11static const char *kCaughtBase			= "ExceptionBase";
12static const char *kCaughtA				= "ExceptionA";
13static const char *kCaughtB				= "ExceptionB";
14static const char *kCaughtVirtualBase	= "VirtualExceptionBase";
15static const char *kCaughtVirtualA		= "VirtualExceptionA";
16static const char *kCaughtVirtualB		= "VirtualExceptionB";
17static const char *kCaughtInt			= "VirtualInt";
18
19
20static string
21catchBase(void (*function)())
22{
23	try {
24		(*function)();
25	} catch (ExceptionBase exception) {
26		return kCaughtBase;
27	} catch (...) {
28		return kCaughtGeneric;
29	}
30	return kCaughtNothing;
31}
32
33
34static string
35catchA(void (*function)())
36{
37	try {
38		(*function)();
39	} catch (ExceptionA exception) {
40		return kCaughtA;
41	} catch (...) {
42		return kCaughtGeneric;
43	}
44	return kCaughtNothing;
45}
46
47
48static string
49catchB(void (*function)())
50{
51	try {
52		(*function)();
53	} catch (ExceptionB exception) {
54		return kCaughtB;
55	} catch (...) {
56		return kCaughtGeneric;
57	}
58	return kCaughtNothing;
59}
60
61
62static string
63catchVirtualBase(void (*function)())
64{
65	try {
66		(*function)();
67	} catch (VirtualExceptionBase exception) {
68		return kCaughtVirtualBase;
69	} catch (...) {
70		return kCaughtGeneric;
71	}
72	return kCaughtNothing;
73}
74
75
76static string
77catchVirtualA(void (*function)())
78{
79	try {
80		(*function)();
81	} catch (VirtualExceptionA exception) {
82		return kCaughtVirtualA;
83	} catch (...) {
84		return kCaughtGeneric;
85	}
86	return kCaughtNothing;
87}
88
89
90static string
91catchVirtualB(void (*function)())
92{
93	try {
94		(*function)();
95	} catch (VirtualExceptionB exception) {
96		return kCaughtVirtualB;
97	} catch (...) {
98		return kCaughtGeneric;
99	}
100	return kCaughtNothing;
101}
102
103
104static string
105catchInt(void (*function)())
106{
107	try {
108		(*function)();
109	} catch (int exception) {
110		return kCaughtInt;
111	} catch (...) {
112		return kCaughtGeneric;
113	}
114	return kCaughtNothing;
115}
116
117static string
118catchAny(void (*function)())
119{
120	try {
121		(*function)();
122	} catch (int exception) {
123		return kCaughtInt;
124	} catch (VirtualExceptionA exception) {
125		return kCaughtVirtualA;
126	} catch (VirtualExceptionB exception) {
127		return kCaughtVirtualB;
128	} catch (VirtualExceptionBase exception) {
129		return kCaughtVirtualBase;
130	} catch (ExceptionA exception) {
131		return kCaughtA;
132	} catch (ExceptionB exception) {
133		return kCaughtB;
134	} catch (ExceptionBase exception) {
135		return kCaughtBase;
136	} catch (...) {
137		return kCaughtGeneric;
138	}
139	return kCaughtNothing;
140}
141
142static void
143test(string (*catcher)(void (*)()), void (*thrower)(), const char *expected)
144{
145	string caught((*catcher)(thrower));
146	if (caught != expected) {
147		printf("ERROR: expected exception: %s, but caught: %s\n", expected,
148			caught.c_str());
149	}
150}
151
152int
153main()
154{
155	test(catchBase, throwBase, kCaughtBase);
156	test(catchBase, throwA, kCaughtBase);
157	test(catchBase, throwB, kCaughtBase);
158	test(catchBase, throwVirtualBase, kCaughtBase);
159	test(catchBase, throwVirtualA, kCaughtBase);
160	test(catchBase, throwVirtualB, kCaughtBase);
161	test(catchBase, throwInt, kCaughtGeneric);
162
163	test(catchA, throwBase, kCaughtGeneric);
164	test(catchA, throwA, kCaughtA);
165	test(catchA, throwB, kCaughtGeneric);
166	test(catchA, throwVirtualBase, kCaughtGeneric);
167	test(catchA, throwVirtualA, kCaughtGeneric);
168	test(catchA, throwVirtualB, kCaughtGeneric);
169	test(catchA, throwInt, kCaughtGeneric);
170
171	test(catchVirtualBase, throwBase, kCaughtGeneric);
172	test(catchVirtualBase, throwA, kCaughtGeneric);
173	test(catchVirtualBase, throwB, kCaughtGeneric);
174	test(catchVirtualBase, throwVirtualBase, kCaughtVirtualBase);
175	test(catchVirtualBase, throwVirtualA, kCaughtVirtualBase);
176	test(catchVirtualBase, throwVirtualB, kCaughtVirtualBase);
177	test(catchVirtualBase, throwInt, kCaughtGeneric);
178
179	test(catchVirtualA, throwBase, kCaughtGeneric);
180	test(catchVirtualA, throwA, kCaughtGeneric);
181	test(catchVirtualA, throwB, kCaughtGeneric);
182	test(catchVirtualA, throwVirtualBase, kCaughtGeneric);
183	test(catchVirtualA, throwVirtualA, kCaughtVirtualA);
184	test(catchVirtualA, throwVirtualB, kCaughtGeneric);
185	test(catchVirtualA, throwInt, kCaughtGeneric);
186
187	test(catchInt, throwBase, kCaughtGeneric);
188	test(catchInt, throwA, kCaughtGeneric);
189	test(catchInt, throwB, kCaughtGeneric);
190	test(catchInt, throwVirtualBase, kCaughtGeneric);
191	test(catchInt, throwVirtualA, kCaughtGeneric);
192	test(catchInt, throwVirtualB, kCaughtGeneric);
193	test(catchInt, throwInt, kCaughtInt);
194
195	test(catchAny, throwBase, kCaughtBase);
196	test(catchAny, throwA, kCaughtA);
197	test(catchAny, throwB, kCaughtB);
198	test(catchAny, throwVirtualBase, kCaughtVirtualBase);
199	test(catchAny, throwVirtualA, kCaughtVirtualA);
200	test(catchAny, throwVirtualB, kCaughtVirtualB);
201	test(catchAny, throwInt, kCaughtInt);
202
203	return 0;
204}
205