Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code

Side by Side Diff: test/plugin/ExceptionTest.cpp

Issue 5137721374801920: Issue #1173 - Default behavior for catch-all blocks
Patch Set: rebase + nit Created March 20, 2015, 9:36 a.m.
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/plugin/PluginStdAfx.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 /*
2 * This file is part of Adblock Plus <https://adblockplus.org/>,
3 * Copyright (C) 2006-2015 Eyeo GmbH
4 *
5 * Adblock Plus is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 3 as
7 * published by the Free Software Foundation.
8 *
9 * Adblock Plus is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with Adblock Plus. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18 #include <gtest/gtest.h>
19 #include "../../src/plugin/Exception.h"
20 #include <stdexcept>
21
22 void AssignCurrentException(std::exception_ptr& e)
23 {
24 e = std::current_exception();
25 }
26
27 /*
28 * This test verifies that std::current_exception works during exception handlin g generally,
29 * not just in the immediate context of a 'catch' clause.
30 */
31 TEST(Exception, CurrentExceptionWorksOutsideCatchHandler)
32 {
33 std::exception_ptr ep;
34 const auto e = std::runtime_error("BJTCiRhkVAmvMg");
35 try
36 {
37 throw e;
38 }
39 catch (...)
40 {
41 AssignCurrentException(ep);
42 ASSERT_TRUE(ep);
43 /*
44 * You might think that the next set would be EXPECT_EQ betwwen the thrown e xception and the original one.
45 * Such a test does not pass, nor is in necessary.
46 * The throw statement above is throwing by value, so it makes a copy.
47 */
48 }
49 try
50 {
51 rethrow_exception(ep);
52 FAIL() << "Statement after 'rethrow_exception' executed.";
53 }
54 catch (std::runtime_error& ex)
55 {
56 EXPECT_STREQ(e.what(), ex.what());
57 return;
58 }
59 catch (...)
60 {
61 FAIL() << "Rethrown exception isn't the same type as the original";
62 }
63 FAIL() << "Did not return after catching rethrown exception";
64 }
65
66 /*
67 * A plain exception, not a subclass of std::runtime_error or std::logic_error.
68 */
69 class PlainException
70 : public std::exception
71 {
72 const char* what() const override
73 {
74 return "Plain";
75 };
76 };
77
78 struct NullHandlers
79 {
80 static void Unknown(int y) {}
81 static void Exception(std::exception& ex,int y) {}
82 static void LogicError(std::logic_error& ex,int y) { Exception(ex, y); }
83 static void RuntimeError(std::runtime_error& ex,int y) { Exception(ex, y); }
84 static void SystemError(std::system_error& ex,int y) { RuntimeError(ex, y); }
85 };
86
87 /*
88 * The trivial tests assure that nothing escapes the catch-all function,
89 * that is, we ensure that nothing is thrown or rethrown.
90 */
91 template<class X>
92 void TrivialVoid(X x)
93 {
94 ASSERT_NO_THROW(
95 {
96 try
97 {
98 throw x;
99 }
100 catch (...)
101 {
102 CatchAllVoid<NullHandlers>::Handler(0);
103 }
104 });
105 }
106
107 TEST(Exception, TrivialVoidUnknown)
108 {
109 TrivialVoid(5);
110 }
111
112 TEST(Exception, TrivialVoidException)
113 {
114 TrivialVoid(PlainException());
115 }
116
117 TEST(Exception, TrivialVoidLogicError)
118 {
119 TrivialVoid(std::logic_error(""));
120 }
121
122 TEST(Exception, TrivialVoidRuntimeError)
123 {
124 TrivialVoid(std::runtime_error(""));
125 }
126
127 TEST(Exception, TrivialVoidSystemError)
128 {
129 TrivialVoid(std::system_error(std::error_code()));
130 }
131
132 enum
133 {
134 InvalidCode = -1,
135 UnknownCode = 1,
136 ExceptionCode,
137 LogicErrorCode,
138 RuntimeErrorCode,
139 SystemErrorCode
140 };
141
142 struct NullHandlersReturn
143 {
144 typedef int ReturnType;
145 static ReturnType Unknown(int) { return UnknownCode; }
146 static ReturnType Exception(std::exception& ex, int) { return ExceptionCode; }
147 static ReturnType LogicError(std::logic_error& ex, int) { return LogicErrorCod e; }
148 static ReturnType RuntimeError(std::runtime_error& ex, int) { return RuntimeEr rorCode; }
149 static ReturnType SystemError(std::system_error& ex, int) { return SystemError Code; }
150 };
151
152 template<class X>
153 void TrivialReturn(int n, X x)
154 {
155 ASSERT_NO_THROW(
156 {
157 try
158 {
159 throw x;
160 }
161 catch (...)
162 {
163 ASSERT_EQ(n, CatchAllReturn<NullHandlersReturn>::Handler(0));
164 }
165 });
166 }
167
168 TEST(Exception, TrivialReturnUnknown)
169 {
170 TrivialReturn(UnknownCode, 5);
171 }
172
173 TEST(Exception, TrivialReturnException)
174 {
175 TrivialReturn(ExceptionCode, PlainException());
176 }
177
178 TEST(Exception, TrivialReturnLogicError)
179 {
180 TrivialReturn(LogicErrorCode, std::logic_error(""));
181 }
182
183 TEST(Exception, TrivialReturnRuntimeError)
184 {
185 TrivialReturn(RuntimeErrorCode, std::runtime_error(""));
186 }
187
188 TEST(Exception, TrivialReturnSystemError)
189 {
190 TrivialReturn(SystemErrorCode, std::system_error(std::error_code()));
191 }
192
193 /*
194 * VS 2012 supports thread_local semantics for POD only, not arbitrary types.
195 * That's good enough for now.
196 * Remove the definition when VS matures.
197 */
198 #define thread_local __declspec(thread)
199
200 /*
201 * The sub-handlers are purely static functions,
202 * so getting them to return something unique for testing has possible race co nditions.
203 * We're using a thread-local variable as a return code from the simple handlers ,
204 * which ensures that even a multi-threaded test runner will work here.
205 */
206 thread_local int SimpleResult;
207 thread_local int SimpleExpected;
208
209 /*
210 * The simple tests ensure that the flow of control arrives in the correct subha ndler.
211 */
212 template<class X, class H>
213 void SimpleVoid(X x, H h)
214 {
215 SimpleResult = 0;
216 SimpleExpected = std::rand();
217 if (SimpleExpected == 0) { SimpleExpected = 1; }
218 ASSERT_NO_THROW(
219 {
220 try
221 {
222 throw x;
223 }
224 catch (...)
225 {
226 CatchAllVoid<H>::Handler(0);
227 }
228 });
229 EXPECT_EQ(SimpleExpected, SimpleResult);
230 }
231
232 /*
233 * The base handler class for the simple tests fails every execution path.
234 * Each specific test redefines a single one of the handler functions that it us es.
235 */
236 class SimpleHandlersBase
237 {
238 public:
239 static void Unknown(int) { FAIL() << "Unexpected exception of unknown type"; }
240 static void Exception(std::exception& ex, int) { FAIL() << "Unexpected std::ex ception"; }
241 static void LogicError(std::logic_error& ex, int) { FAIL() << "Unexpected std: :logic_error"; }
242 static void RuntimeError(std::runtime_error& ex, int) { FAIL() << "Unexpected std::runtime_error"; }
243 static void SystemError(std::system_error& ex, int) { FAIL() << "Unexpected st d::system_error"; };
244 protected:
245 static void Ping() { SimpleResult = SimpleExpected; }
246 };
247
248 TEST(Exception, SimpleVoidUnknown)
249 {
250 struct Handler :
251 public SimpleHandlersBase
252 {
253 static void Unknown(int) { Ping(); }
254 };
255 SimpleVoid(5, Handler());
256 }
257
258 TEST(Exception, SimpleVoidException)
259 {
260 struct Handler :
261 public SimpleHandlersBase
262 {
263 static void Exception(std::exception& ex, int) { Ping(); }
264 };
265 SimpleVoid(PlainException(), Handler());
266 }
267
268 TEST(Exception, SimpleVoidLogicError)
269 {
270 struct Handler :
271 public SimpleHandlersBase
272 {
273 static void LogicError(std::logic_error& ex, int) { Ping(); }
274 };
275 SimpleVoid(std::logic_error(""), Handler());
276 }
277
278 TEST(Exception, SimpleVoidRuntimeError)
279 {
280 struct Handler :
281 public SimpleHandlersBase
282 {
283 static void RuntimeError(std::runtime_error& ex, int) { Ping(); }
284 };
285 SimpleVoid(std::runtime_error(""), Handler());
286 }
287
288 TEST(Exception, SimpleVoidSystemError)
289 {
290 struct Handler :
291 public SimpleHandlersBase
292 {
293 static void SystemError(std::system_error& ex, int) { Ping(); }
294 };
295 SimpleVoid(std::system_error(std::error_code()), Handler());
296 }
297
298 template<class X, class H>
299 void SimpleReturn(int n, X x, H h)
300 {
301 SimpleResult = 0;
302 SimpleExpected = rand();
303 if (SimpleExpected == 0) { SimpleExpected = 1; }
304 ASSERT_NO_THROW(
305 {
306 try
307 {
308 throw x;
309 }
310 catch (...)
311 {
312 EXPECT_EQ(n, CatchAllReturn<H>::Handler(0));
313 }
314 });
315 EXPECT_EQ(SimpleExpected, SimpleResult);
316 }
317
318 /*
319 * The base handlers class fails every execution path.
320 */
321 class SimpleHandlersReturnBase
322 {
323 public:
324 typedef int ReturnType;
325 static ReturnType Unknown(int) { ADD_FAILURE() << "Unexpected exception of unk nown type"; return InvalidCode; }
326 static ReturnType Exception(std::exception& ex, int) { ADD_FAILURE() << "Unexp ected std::exception"; return InvalidCode; }
327 static ReturnType LogicError(std::logic_error& ex, int) { ADD_FAILURE() << "Un expected std::logic_error"; return InvalidCode; }
328 static ReturnType RuntimeError(std::runtime_error& ex, int) { ADD_FAILURE() << "Unexpected std::runtime_error"; return InvalidCode; }
329 static ReturnType SystemError(std::system_error& ex, int) { ADD_FAILURE() << " Unexpected std::system_error"; return InvalidCode; }
330 protected:
331 static void Ping() { SimpleResult = SimpleExpected; }
332 };
333
334 TEST(Exception, SimpleReturnUnknown)
335 {
336 struct Handler :
337 public SimpleHandlersReturnBase
338 {
339 static int Unknown(int) { Ping(); return UnknownCode; }
340 };
341 SimpleReturn(UnknownCode, 5, Handler());
342 }
343
344 TEST(Exception, SimpleReturnException)
345 {
346 struct Handler :
347 public SimpleHandlersReturnBase
348 {
349 static int Exception(std::exception& ex, int) { Ping(); return ExceptionCode ; }
350 };
351 SimpleReturn(ExceptionCode, PlainException(), Handler());
352 }
353
354 TEST(Exception, SimpleReturnLogicError)
355 {
356 struct Handler :
357 public SimpleHandlersReturnBase
358 {
359 static int LogicError(std::logic_error& ex, int) { Ping(); return LogicError Code; }
360 };
361 SimpleReturn(LogicErrorCode, std::logic_error(""), Handler());
362 }
363
364 TEST(Exception, SimpleReturnRuntimeError)
365 {
366 struct Handler :
367 public SimpleHandlersReturnBase
368 {
369 static int RuntimeError(std::runtime_error& ex, int) { Ping(); return Runtim eErrorCode; }
370 };
371 SimpleReturn(RuntimeErrorCode, std::runtime_error(""), Handler());
372 }
373
374 TEST(Exception, SimpleReturnSystemError)
375 {
376 struct Handler :
377 public SimpleHandlersReturnBase
378 {
379 static int SystemError(std::system_error& ex, int) { Ping(); return SystemEr rorCode; }
380 };
381 SimpleReturn(SystemErrorCode, std::system_error(std::error_code()), Handler()) ;
382 }
383
OLDNEW
« no previous file with comments | « src/plugin/PluginStdAfx.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld