blob: 4d4b1cd732edff966002d978abf7cb3490a953c3 [file] [log] [blame]
Tristan Matthews0a329cc2013-07-17 13:20:14 -04001/* $Id: exception.c 3553 2011-05-05 06:14:19Z nanang $ */
2/*
3 * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
4 * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20#include "test.h"
21
22
23/**
24 * \page page_pjlib_exception_test Test: Exception Handling
25 *
26 * This file provides implementation of \b exception_test(). It tests the
27 * functionality of the exception handling API.
28 *
29 * @note This test use static ID not acquired through proper registration.
30 * This is not recommended, since it may create ID collissions.
31 *
32 * \section exception_test_sec Scope of the Test
33 *
34 * Some scenarios tested:
35 * - no exception situation
36 * - basic TRY/CATCH
37 * - multiple exception handlers
38 * - default handlers
39 *
40 *
41 * This file is <b>pjlib-test/exception.c</b>
42 *
43 * \include pjlib-test/exception.c
44 */
45
46
47#if INCLUDE_EXCEPTION_TEST
48
49#include <pjlib.h>
50
51#define ID_1 1
52#define ID_2 2
53
54static int throw_id_1(void)
55{
56 PJ_THROW( ID_1 );
57 PJ_UNREACHED(return -1;)
58}
59
60static int throw_id_2(void)
61{
62 PJ_THROW( ID_2 );
63 PJ_UNREACHED(return -1;)
64}
65
66static int try_catch_test(void)
67{
68 PJ_USE_EXCEPTION;
69 int rc = -200;
70
71 PJ_TRY {
72 PJ_THROW(ID_1);
73 }
74 PJ_CATCH_ANY {
75 rc = 0;
76 }
77 PJ_END;
78 return rc;
79}
80
81static int throw_in_handler(void)
82{
83 PJ_USE_EXCEPTION;
84 int rc = 0;
85
86 PJ_TRY {
87 PJ_THROW(ID_1);
88 }
89 PJ_CATCH_ANY {
90 if (PJ_GET_EXCEPTION() != ID_1)
91 rc = -300;
92 else
93 PJ_THROW(ID_2);
94 }
95 PJ_END;
96 return rc;
97}
98
99static int return_in_handler(void)
100{
101 PJ_USE_EXCEPTION;
102
103 PJ_TRY {
104 PJ_THROW(ID_1);
105 }
106 PJ_CATCH_ANY {
107 return 0;
108 }
109 PJ_END;
110 return -400;
111}
112
113
114static int test(void)
115{
116 int rc = 0;
117 PJ_USE_EXCEPTION;
118
119 /*
120 * No exception situation.
121 */
122 PJ_TRY {
123 rc = rc;
124 }
125 PJ_CATCH_ANY {
126 rc = -3;
127 }
128 PJ_END;
129
130 if (rc != 0)
131 return rc;
132
133
134 /*
135 * Basic TRY/CATCH
136 */
137 PJ_TRY {
138 rc = throw_id_1();
139
140 // should not reach here.
141 rc = -10;
142 }
143 PJ_CATCH_ANY {
144 int id = PJ_GET_EXCEPTION();
145 if (id != ID_1) {
146 PJ_LOG(3,("", "...error: got unexpected exception %d (%s)",
147 id, pj_exception_id_name(id)));
148 if (!rc) rc = -20;
149 }
150 }
151 PJ_END;
152
153 if (rc != 0)
154 return rc;
155
156 /*
157 * Multiple exceptions handlers
158 */
159 PJ_TRY {
160 rc = throw_id_2();
161 // should not reach here.
162 rc = -25;
163 }
164 PJ_CATCH_ANY {
165 switch (PJ_GET_EXCEPTION()) {
166 case ID_1:
167 if (!rc) rc = -30; break;
168 case ID_2:
169 if (!rc) rc = 0; break;
170 default:
171 if (!rc) rc = -40;
172 break;
173 }
174 }
175 PJ_END;
176
177 if (rc != 0)
178 return rc;
179
180 /*
181 * Test default handler.
182 */
183 PJ_TRY {
184 rc = throw_id_1();
185 // should not reach here
186 rc = -50;
187 }
188 PJ_CATCH_ANY {
189 switch (PJ_GET_EXCEPTION()) {
190 case ID_1:
191 if (!rc) rc = 0;
192 break;
193 default:
194 if (!rc) rc = -60;
195 break;
196 }
197 }
198 PJ_END;
199
200 if (rc != 0)
201 return rc;
202
203 /*
204 * Nested handlers
205 */
206 PJ_TRY {
207 rc = try_catch_test();
208 }
209 PJ_CATCH_ANY {
210 rc = -70;
211 }
212 PJ_END;
213
214 if (rc != 0)
215 return rc;
216
217 /*
218 * Throwing exception inside handler
219 */
220 rc = -80;
221 PJ_TRY {
222 int rc2;
223 rc2 = throw_in_handler();
224 if (rc2)
225 rc = rc2;
226 }
227 PJ_CATCH_ANY {
228 if (PJ_GET_EXCEPTION() == ID_2) {
229 rc = 0;
230 } else {
231 rc = -90;
232 }
233 }
234 PJ_END;
235
236 if (rc != 0)
237 return rc;
238
239
240 /*
241 * Return from handler. Returning from the function inside a handler
242 * should be okay (though returning from the function inside the
243 * PJ_TRY block IS NOT OKAY!!). We want to test to see if handler
244 * is cleaned up properly, but not sure how to do this.
245 */
246 PJ_TRY {
247 int rc2;
248 rc2 = return_in_handler();
249 if (rc2)
250 rc = rc2;
251 }
252 PJ_CATCH_ANY {
253 rc = -100;
254 }
255 PJ_END;
256
257
258 return 0;
259}
260
261int exception_test(void)
262{
263 int i, rc;
264 enum { LOOP = 10 };
265
266 for (i=0; i<LOOP; ++i) {
267 if ((rc=test()) != 0) {
268 PJ_LOG(3,("", "...failed at i=%d (rc=%d)", i, rc));
269 return rc;
270 }
271 }
272 return 0;
273}
274
275#else
276/* To prevent warning about "translation unit is empty"
277 * when this test is disabled.
278 */
279int dummy_exception_test;
280#endif /* INCLUDE_EXCEPTION_TEST */
281
282