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

Powered by Google App Engine
This is Rietveld