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

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

Issue 5743529531801600: Playing with Default behavior for catch-all blocks
Patch Set: proposed changes Created March 31, 2015, 1:49 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
« 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 (const 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) {}
81 static void Exception(const std::exception&,int) {}
82 };
83
84 /*
85 * The trivial tests assure that nothing escapes the catch-all function,
86 * that is, we ensure that nothing is thrown or rethrown.
87 */
88 template<class X>
89 void TrivialVoid(X x)
90 {
91 ASSERT_NO_THROW(
92 {
93 try
94 {
95 throw x;
96 }
97 catch (...)
98 {
99 CatchAllVoid<NullHandlers>::Handler(0);
100 }
101 });
102 }
103
104 TEST(Exception, TrivialVoidUnknown)
105 {
106 TrivialVoid(5);
107 }
108
109 TEST(Exception, TrivialVoidException)
110 {
111 TrivialVoid(PlainException());
112 }
113
114 TEST(Exception, TrivialVoidLogicError)
115 {
116 TrivialVoid(std::logic_error(""));
117 }
118
119 TEST(Exception, TrivialVoidRuntimeError)
120 {
121 TrivialVoid(std::runtime_error(""));
122 }
123
124 TEST(Exception, TrivialVoidSystemError)
125 {
126 TrivialVoid(std::system_error(std::error_code()));
127 }
128
129 enum class ReturnType
130 {
131 InvalidCode = -1,
132 UnknownCode = 1,
133 ExceptionCode,
134 LogicErrorCode,
135 RuntimeErrorCode,
136 SystemErrorCode
137 };
138
139 struct NullHandlersReturn
140 {
141 typedef ReturnType ReturnType;
142 static ReturnType Unknown(int) { return ReturnType::UnknownCode; }
143 static ReturnType Exception(const std::exception&, int) { return ReturnType::E xceptionCode; }
144 static ReturnType Exception(const std::logic_error&, int) { return ReturnType: :LogicErrorCode; }
145 static ReturnType Exception(const std::runtime_error&, int) { return ReturnTyp e::RuntimeErrorCode; }
146 static ReturnType Exception(const std::system_error&, int) { return ReturnType ::SystemErrorCode; }
147 };
148
149 template<class X>
150 void TrivialReturn(ReturnType n, X x)
151 {
152 ASSERT_NO_THROW(
153 {
154 try
155 {
156 throw x;
157 }
158 catch (...)
159 {
160 ASSERT_EQ(n, CatchAllReturn<NullHandlersReturn>::Handler(0));
161 }
162 });
163 }
164
165 TEST(Exception, TrivialReturnUnknown)
166 {
167 TrivialReturn(ReturnType::UnknownCode, 5);
168 }
169
170 TEST(Exception, TrivialReturnException)
171 {
172 TrivialReturn(ReturnType::ExceptionCode, PlainException());
173 }
174
175 TEST(Exception, TrivialReturnLogicError)
176 {
177 TrivialReturn(ReturnType::LogicErrorCode, std::logic_error(""));
178 }
179
180 TEST(Exception, TrivialReturnRuntimeError)
181 {
182 TrivialReturn(ReturnType::RuntimeErrorCode, std::runtime_error(""));
183 }
184
185 TEST(Exception, TrivialReturnSystemError)
186 {
187 TrivialReturn(ReturnType::SystemErrorCode, std::system_error(std::error_code() ));
188 }
189
190 class Touchable
191 {
192 public:
193 Touchable() : m_isTouched(false){}
194 bool IsTouched() const
195 {
196 return m_isTouched;
197 }
198 void Touch()
199 {
200 m_isTouched = true;
201 }
202 private:
203 // In the tests we use `Touchable&` as the type for UserData, so let's make
204 // it uncopyable to be sure that it's not copied somewhere by accident.
205 Touchable(const Touchable&);
206 void operator=(const Touchable&);
207 private:
208 bool m_isTouched;
209 };
210
211 /*
212 * The simple tests ensure that the flow of control arrives in the correct subha ndler.
213 */
214 template<typename H, class X>
215 void SimpleVoid(X x)
216 {
217 Touchable userData;
218 ASSERT_NO_THROW(
219 {
220 try
221 {
222 throw x;
223 }
224 catch (...)
225 {
226 CatchAllVoid<H>::Handler<Touchable&>(userData);
227 }
228 });
229 EXPECT_TRUE(userData.IsTouched());
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 typedef Touchable& UserData;
240 SimpleHandlersBase(){}
241 static void Unknown(UserData) { FAIL() << "Unexpected exception of unknown typ e"; }
242 static void Exception(const std::exception&, UserData) { FAIL() << "Unexpected std::exception"; }
243 static void Exception(const std::logic_error&, UserData) { FAIL() << "Unexpect ed std::logic_error"; }
sergei 2015/04/01 07:16:02 JIC, actually, these three methods as well as the
244 static void Exception(const std::runtime_error&, UserData) { FAIL() << "Unexpe cted std::runtime_error"; }
245 static void Exception(const std::system_error&, UserData) { FAIL() << "Unexpec ted std::system_error"; };
246 };
247
248 TEST(Exception, SimpleVoidUnknown)
249 {
250 struct Handler :
251 public SimpleHandlersBase
252 {
253 static void Unknown(UserData h) { h.Touch(); }
254 };
255 SimpleVoid<Handler>(5);
256 }
257
258 TEST(Exception, SimpleVoidException)
259 {
260 struct Handler :
261 public SimpleHandlersBase
262 {
263 static void Exception(const std::exception&, UserData h) { h.Touch(); }
264 };
265 SimpleVoid<Handler>(PlainException());
266 }
267
268 TEST(Exception, SimpleVoidLogicError)
269 {
270 struct Handler :
271 public SimpleHandlersBase
272 {
273 static void Exception(const std::logic_error&, UserData h) { h.Touch(); }
274 using SimpleHandlersBase::Exception;
275 };
276 SimpleVoid<Handler>(std::logic_error(""));
277 }
278
279 TEST(Exception, SimpleVoidRuntimeError)
280 {
281 struct Handler :
282 public SimpleHandlersBase
283 {
284 static void Exception(const std::runtime_error&, UserData h) { h.Touch(); }
285 using SimpleHandlersBase::Exception;
286 };
287 SimpleVoid<Handler>(std::runtime_error(""));
288 }
289
290 TEST(Exception, SimpleVoidSystemError)
291 {
292 struct Handler :
293 public SimpleHandlersBase
294 {
295 static void Exception(const std::system_error&, UserData h) { h.Touch(); }
296 using SimpleHandlersBase::Exception;
297 };
298 SimpleVoid<Handler>(std::system_error(std::error_code()));
299 }
300
301 template<class H, class X>
302 void SimpleReturn(ReturnType n, X x)
303 {
304 Touchable userData;
305 ASSERT_NO_THROW(
306 {
307 try
308 {
309 throw x;
310 }
311 catch (...)
312 {
313 EXPECT_EQ(n, CatchAllReturn<H>::Handler<Touchable&>(userData));
314 }
315 });
316 EXPECT_TRUE(userData.IsTouched());
317 }
318
319 /*
320 * The base handlers class fails every execution path.
321 */
322 class SimpleHandlersReturnBase
323 {
324 public:
325 typedef ReturnType ReturnType;
326 typedef Touchable& UserData;
327 static ReturnType Unknown(UserData) { ADD_FAILURE() << "Unexpected exception o f unknown type"; return ReturnType::InvalidCode; }
328 static ReturnType Exception(const std::exception&, UserData) { ADD_FAILURE() < < "Unexpected std::exception"; return ReturnType::InvalidCode; }
329 static ReturnType Exception(const std::logic_error&, UserData) { ADD_FAILURE() << "Unexpected std::logic_error"; return ReturnType::InvalidCode; }
330 static ReturnType Exception(const std::runtime_error&, UserData) { ADD_FAILURE () << "Unexpected std::runtime_error"; return ReturnType::InvalidCode; }
331 static ReturnType Exception(const std::system_error&, UserData) { ADD_FAILURE( ) << "Unexpected std::system_error"; return ReturnType::InvalidCode; }
332 };
333
334 TEST(Exception, SimpleReturnUnknown)
335 {
336 struct Handler :
337 public SimpleHandlersReturnBase
338 {
339 static ReturnType Unknown(UserData h) { h.Touch(); return ReturnType::Unknow nCode; }
340 using SimpleHandlersReturnBase::Exception;
341 };
342 SimpleReturn<Handler>(ReturnType::UnknownCode, 5);
343 }
344
345 TEST(Exception, SimpleReturnException)
346 {
347 struct Handler :
348 public SimpleHandlersReturnBase
349 {
350 static ReturnType Exception(const std::exception&, UserData h) { h.Touch(); return ReturnType::ExceptionCode; }
351 using SimpleHandlersReturnBase::Exception;
352 };
353 SimpleReturn<Handler>(ReturnType::ExceptionCode, PlainException());
354 }
355
356 TEST(Exception, SimpleReturnLogicError)
357 {
358 struct Handler :
359 public SimpleHandlersReturnBase
360 {
361 static ReturnType Exception(const std::logic_error&, UserData h) { h.Touch() ; return ReturnType::LogicErrorCode; }
362 using SimpleHandlersReturnBase::Exception;
363 };
364 SimpleReturn<Handler>(ReturnType::LogicErrorCode, std::logic_error(""));
365 }
366
367 TEST(Exception, SimpleReturnRuntimeError)
368 {
369 struct Handler :
370 public SimpleHandlersReturnBase
371 {
372 static ReturnType Exception(const std::runtime_error&, UserData h) { h.Touch (); return ReturnType::RuntimeErrorCode; }
373 using SimpleHandlersReturnBase::Exception;
374 };
375 SimpleReturn<Handler>(ReturnType::RuntimeErrorCode, std::runtime_error(""));
376 }
377
378 TEST(Exception, SimpleReturnSystemError)
379 {
380 struct Handler :
381 public SimpleHandlersReturnBase
382 {
383 static ReturnType Exception(const std::system_error&, UserData h) { h.Touch( ); return ReturnType::SystemErrorCode; }
384 using SimpleHandlersReturnBase::Exception;
385 };
386 SimpleReturn<Handler>(ReturnType::SystemErrorCode, std::system_error(std::erro r_code()));
387 }
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