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

Delta Between Two Patch Sets: test/plugin/ExceptionTest.cpp

Issue 5743529531801600: Playing with Default behavior for catch-all blocks
Left Patch Set: Original patch set 9 Created March 31, 2015, 1:46 p.m.
Right 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:
Left: Side by side diff | Download
Right: Side by side diff | Download
« no previous file with change/comment | « src/plugin/PluginStdAfx.h ('k') | no next file » | no next file with change/comment »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
LEFTRIGHT
1 /* 1 /*
2 * This file is part of Adblock Plus <https://adblockplus.org/>, 2 * This file is part of Adblock Plus <https://adblockplus.org/>,
3 * Copyright (C) 2006-2015 Eyeo GmbH 3 * Copyright (C) 2006-2015 Eyeo GmbH
4 * 4 *
5 * Adblock Plus is free software: you can redistribute it and/or modify 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 6 * it under the terms of the GNU General Public License version 3 as
7 * published by the Free Software Foundation. 7 * published by the Free Software Foundation.
8 * 8 *
9 * Adblock Plus is distributed in the hope that it will be useful, 9 * Adblock Plus is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
44 * You might think that the next set would be EXPECT_EQ betwwen the thrown e xception and the original one. 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. 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. 46 * The throw statement above is throwing by value, so it makes a copy.
47 */ 47 */
48 } 48 }
49 try 49 try
50 { 50 {
51 rethrow_exception(ep); 51 rethrow_exception(ep);
52 FAIL() << "Statement after 'rethrow_exception' executed."; 52 FAIL() << "Statement after 'rethrow_exception' executed.";
53 } 53 }
54 catch (std::runtime_error& ex) 54 catch (const std::runtime_error& ex)
55 { 55 {
56 EXPECT_STREQ(e.what(), ex.what()); 56 EXPECT_STREQ(e.what(), ex.what());
57 return; 57 return;
58 } 58 }
59 catch (...) 59 catch (...)
60 { 60 {
61 FAIL() << "Rethrown exception isn't the same type as the original"; 61 FAIL() << "Rethrown exception isn't the same type as the original";
62 } 62 }
63 FAIL() << "Did not return after catching rethrown exception"; 63 FAIL() << "Did not return after catching rethrown exception";
64 } 64 }
65 65
66 /* 66 /*
67 * A plain exception, not a subclass of std::runtime_error or std::logic_error. 67 * A plain exception, not a subclass of std::runtime_error or std::logic_error.
68 */ 68 */
69 class PlainException 69 class PlainException
70 : public std::exception 70 : public std::exception
71 { 71 {
72 const char* what() const override 72 const char* what() const override
73 { 73 {
74 return "Plain"; 74 return "Plain";
75 }; 75 };
76 }; 76 };
77 77
78 struct NullHandlers 78 struct NullHandlers
79 { 79 {
80 static void Unknown(int y) {} 80 static void Unknown(int) {}
81 static void Exception(std::exception& ex,int y) {} 81 static void Exception(const std::exception&,int) {}
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 }; 82 };
86 83
87 /* 84 /*
88 * The trivial tests assure that nothing escapes the catch-all function, 85 * The trivial tests assure that nothing escapes the catch-all function,
89 * that is, we ensure that nothing is thrown or rethrown. 86 * that is, we ensure that nothing is thrown or rethrown.
90 */ 87 */
91 template<class X> 88 template<class X>
92 void TrivialVoid(X x) 89 void TrivialVoid(X x)
93 { 90 {
94 ASSERT_NO_THROW( 91 ASSERT_NO_THROW(
(...skipping 27 matching lines...) Expand all
122 TEST(Exception, TrivialVoidRuntimeError) 119 TEST(Exception, TrivialVoidRuntimeError)
123 { 120 {
124 TrivialVoid(std::runtime_error("")); 121 TrivialVoid(std::runtime_error(""));
125 } 122 }
126 123
127 TEST(Exception, TrivialVoidSystemError) 124 TEST(Exception, TrivialVoidSystemError)
128 { 125 {
129 TrivialVoid(std::system_error(std::error_code())); 126 TrivialVoid(std::system_error(std::error_code()));
130 } 127 }
131 128
132 enum 129 enum class ReturnType
133 { 130 {
134 InvalidCode = -1, 131 InvalidCode = -1,
135 UnknownCode = 1, 132 UnknownCode = 1,
136 ExceptionCode, 133 ExceptionCode,
137 LogicErrorCode, 134 LogicErrorCode,
138 RuntimeErrorCode, 135 RuntimeErrorCode,
139 SystemErrorCode 136 SystemErrorCode
140 }; 137 };
141 138
142 struct NullHandlersReturn 139 struct NullHandlersReturn
143 { 140 {
144 typedef int ReturnType; 141 typedef ReturnType ReturnType;
145 static ReturnType Unknown(int) { return UnknownCode; } 142 static ReturnType Unknown(int) { return ReturnType::UnknownCode; }
146 static ReturnType Exception(std::exception& ex, int) { return ExceptionCode; } 143 static ReturnType Exception(const std::exception&, int) { return ReturnType::E xceptionCode; }
147 static ReturnType LogicError(std::logic_error& ex, int) { return LogicErrorCod e; } 144 static ReturnType Exception(const std::logic_error&, int) { return ReturnType: :LogicErrorCode; }
148 static ReturnType RuntimeError(std::runtime_error& ex, int) { return RuntimeEr rorCode; } 145 static ReturnType Exception(const std::runtime_error&, int) { return ReturnTyp e::RuntimeErrorCode; }
149 static ReturnType SystemError(std::system_error& ex, int) { return SystemError Code; } 146 static ReturnType Exception(const std::system_error&, int) { return ReturnType ::SystemErrorCode; }
150 }; 147 };
151 148
152 template<class X> 149 template<class X>
153 void TrivialReturn(int n, X x) 150 void TrivialReturn(ReturnType n, X x)
154 { 151 {
155 ASSERT_NO_THROW( 152 ASSERT_NO_THROW(
156 { 153 {
157 try 154 try
158 { 155 {
159 throw x; 156 throw x;
160 } 157 }
161 catch (...) 158 catch (...)
162 { 159 {
163 ASSERT_EQ(n, CatchAllReturn<NullHandlersReturn>::Handler(0)); 160 ASSERT_EQ(n, CatchAllReturn<NullHandlersReturn>::Handler(0));
164 } 161 }
165 }); 162 });
166 } 163 }
167 164
168 TEST(Exception, TrivialReturnUnknown) 165 TEST(Exception, TrivialReturnUnknown)
169 { 166 {
170 TrivialReturn(UnknownCode, 5); 167 TrivialReturn(ReturnType::UnknownCode, 5);
171 } 168 }
172 169
173 TEST(Exception, TrivialReturnException) 170 TEST(Exception, TrivialReturnException)
174 { 171 {
175 TrivialReturn(ExceptionCode, PlainException()); 172 TrivialReturn(ReturnType::ExceptionCode, PlainException());
176 } 173 }
177 174
178 TEST(Exception, TrivialReturnLogicError) 175 TEST(Exception, TrivialReturnLogicError)
179 { 176 {
180 TrivialReturn(LogicErrorCode, std::logic_error("")); 177 TrivialReturn(ReturnType::LogicErrorCode, std::logic_error(""));
181 } 178 }
182 179
183 TEST(Exception, TrivialReturnRuntimeError) 180 TEST(Exception, TrivialReturnRuntimeError)
184 { 181 {
185 TrivialReturn(RuntimeErrorCode, std::runtime_error("")); 182 TrivialReturn(ReturnType::RuntimeErrorCode, std::runtime_error(""));
186 } 183 }
187 184
188 TEST(Exception, TrivialReturnSystemError) 185 TEST(Exception, TrivialReturnSystemError)
189 { 186 {
190 TrivialReturn(SystemErrorCode, std::system_error(std::error_code())); 187 TrivialReturn(ReturnType::SystemErrorCode, std::system_error(std::error_code() ));
191 } 188 }
192 189
193 /* 190 class Touchable
194 * VS 2012 supports thread_local semantics for POD only, not arbitrary types. 191 {
195 * That's good enough for now. 192 public:
196 * Remove the definition when VS matures. 193 Touchable() : m_isTouched(false){}
197 */ 194 bool IsTouched() const
198 #define thread_local __declspec(thread) 195 {
199 196 return m_isTouched;
200 /* 197 }
201 * The sub-handlers are purely static functions, 198 void Touch()
202 * so getting them to return something unique for testing has possible race co nditions. 199 {
203 * We're using a thread-local variable as a return code from the simple handlers , 200 m_isTouched = true;
204 * which ensures that even a multi-threaded test runner will work here. 201 }
205 */ 202 private:
206 thread_local int SimpleResult; 203 // In the tests we use `Touchable&` as the type for UserData, so let's make
207 thread_local int SimpleExpected; 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 };
208 210
209 /* 211 /*
210 * The simple tests ensure that the flow of control arrives in the correct subha ndler. 212 * The simple tests ensure that the flow of control arrives in the correct subha ndler.
211 */ 213 */
212 template<class X, class H> 214 template<typename H, class X>
213 void SimpleVoid(X x, H h) 215 void SimpleVoid(X x)
214 { 216 {
215 SimpleResult = 0; 217 Touchable userData;
216 SimpleExpected = std::rand();
217 if (SimpleExpected == 0) { SimpleExpected = 1; }
218 ASSERT_NO_THROW( 218 ASSERT_NO_THROW(
219 { 219 {
220 try 220 try
221 { 221 {
222 throw x; 222 throw x;
223 } 223 }
224 catch (...) 224 catch (...)
225 { 225 {
226 CatchAllVoid<H>::Handler(0); 226 CatchAllVoid<H>::Handler<Touchable&>(userData);
227 } 227 }
228 }); 228 });
229 EXPECT_EQ(SimpleExpected, SimpleResult); 229 EXPECT_TRUE(userData.IsTouched());
230 } 230 }
231 231
232 /* 232 /*
233 * The base handler class for the simple tests fails every execution path. 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. 234 * Each specific test redefines a single one of the handler functions that it us es.
235 */ 235 */
236 class SimpleHandlersBase 236 class SimpleHandlersBase
237 { 237 {
238 public: 238 public:
239 static void Unknown(int) { FAIL() << "Unexpected exception of unknown type"; } 239 typedef Touchable& UserData;
240 static void Exception(std::exception& ex, int) { FAIL() << "Unexpected std::ex ception"; } 240 SimpleHandlersBase(){}
241 static void LogicError(std::logic_error& ex, int) { FAIL() << "Unexpected std: :logic_error"; } 241 static void Unknown(UserData) { FAIL() << "Unexpected exception of unknown typ e"; }
242 static void RuntimeError(std::runtime_error& ex, int) { FAIL() << "Unexpected std::runtime_error"; } 242 static void Exception(const std::exception&, UserData) { FAIL() << "Unexpected std::exception"; }
243 static void SystemError(std::system_error& ex, int) { FAIL() << "Unexpected st d::system_error"; }; 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 protected: 244 static void Exception(const std::runtime_error&, UserData) { FAIL() << "Unexpe cted std::runtime_error"; }
245 static void Ping() { SimpleResult = SimpleExpected; } 245 static void Exception(const std::system_error&, UserData) { FAIL() << "Unexpec ted std::system_error"; };
246 }; 246 };
247 247
248 TEST(Exception, SimpleVoidUnknown) 248 TEST(Exception, SimpleVoidUnknown)
249 { 249 {
250 struct Handler : 250 struct Handler :
251 public SimpleHandlersBase 251 public SimpleHandlersBase
252 { 252 {
253 static void Unknown(int) { Ping(); } 253 static void Unknown(UserData h) { h.Touch(); }
254 }; 254 };
255 SimpleVoid(5, Handler()); 255 SimpleVoid<Handler>(5);
256 } 256 }
257 257
258 TEST(Exception, SimpleVoidException) 258 TEST(Exception, SimpleVoidException)
259 { 259 {
260 struct Handler : 260 struct Handler :
261 public SimpleHandlersBase 261 public SimpleHandlersBase
262 { 262 {
263 static void Exception(std::exception& ex, int) { Ping(); } 263 static void Exception(const std::exception&, UserData h) { h.Touch(); }
264 }; 264 };
265 SimpleVoid(PlainException(), Handler()); 265 SimpleVoid<Handler>(PlainException());
266 } 266 }
267 267
268 TEST(Exception, SimpleVoidLogicError) 268 TEST(Exception, SimpleVoidLogicError)
269 { 269 {
270 struct Handler : 270 struct Handler :
271 public SimpleHandlersBase 271 public SimpleHandlersBase
272 { 272 {
273 static void LogicError(std::logic_error& ex, int) { Ping(); } 273 static void Exception(const std::logic_error&, UserData h) { h.Touch(); }
274 }; 274 using SimpleHandlersBase::Exception;
275 SimpleVoid(std::logic_error(""), Handler()); 275 };
276 SimpleVoid<Handler>(std::logic_error(""));
276 } 277 }
277 278
278 TEST(Exception, SimpleVoidRuntimeError) 279 TEST(Exception, SimpleVoidRuntimeError)
279 { 280 {
280 struct Handler : 281 struct Handler :
281 public SimpleHandlersBase 282 public SimpleHandlersBase
282 { 283 {
283 static void RuntimeError(std::runtime_error& ex, int) { Ping(); } 284 static void Exception(const std::runtime_error&, UserData h) { h.Touch(); }
284 }; 285 using SimpleHandlersBase::Exception;
285 SimpleVoid(std::runtime_error(""), Handler()); 286 };
287 SimpleVoid<Handler>(std::runtime_error(""));
286 } 288 }
287 289
288 TEST(Exception, SimpleVoidSystemError) 290 TEST(Exception, SimpleVoidSystemError)
289 { 291 {
290 struct Handler : 292 struct Handler :
291 public SimpleHandlersBase 293 public SimpleHandlersBase
292 { 294 {
293 static void SystemError(std::system_error& ex, int) { Ping(); } 295 static void Exception(const std::system_error&, UserData h) { h.Touch(); }
294 }; 296 using SimpleHandlersBase::Exception;
295 SimpleVoid(std::system_error(std::error_code()), Handler()); 297 };
296 } 298 SimpleVoid<Handler>(std::system_error(std::error_code()));
297 299 }
298 template<class X, class H> 300
299 void SimpleReturn(int n, X x, H h) 301 template<class H, class X>
300 { 302 void SimpleReturn(ReturnType n, X x)
301 SimpleResult = 0; 303 {
302 SimpleExpected = rand(); 304 Touchable userData;
303 if (SimpleExpected == 0) { SimpleExpected = 1; }
304 ASSERT_NO_THROW( 305 ASSERT_NO_THROW(
305 { 306 {
306 try 307 try
307 { 308 {
308 throw x; 309 throw x;
309 } 310 }
310 catch (...) 311 catch (...)
311 { 312 {
312 EXPECT_EQ(n, CatchAllReturn<H>::Handler(0)); 313 EXPECT_EQ(n, CatchAllReturn<H>::Handler<Touchable&>(userData));
313 } 314 }
314 }); 315 });
315 EXPECT_EQ(SimpleExpected, SimpleResult); 316 EXPECT_TRUE(userData.IsTouched());
316 } 317 }
317 318
318 /* 319 /*
319 * The base handlers class fails every execution path. 320 * The base handlers class fails every execution path.
320 */ 321 */
321 class SimpleHandlersReturnBase 322 class SimpleHandlersReturnBase
322 { 323 {
323 public: 324 public:
324 typedef int ReturnType; 325 typedef ReturnType ReturnType;
325 static ReturnType Unknown(int) { ADD_FAILURE() << "Unexpected exception of unk nown type"; return InvalidCode; } 326 typedef Touchable& UserData;
326 static ReturnType Exception(std::exception& ex, int) { ADD_FAILURE() << "Unexp ected std::exception"; return InvalidCode; } 327 static ReturnType Unknown(UserData) { ADD_FAILURE() << "Unexpected exception o f unknown type"; return ReturnType::InvalidCode; }
327 static ReturnType LogicError(std::logic_error& ex, int) { ADD_FAILURE() << "Un expected std::logic_error"; return InvalidCode; } 328 static ReturnType Exception(const std::exception&, UserData) { ADD_FAILURE() < < "Unexpected std::exception"; return ReturnType::InvalidCode; }
328 static ReturnType RuntimeError(std::runtime_error& ex, int) { ADD_FAILURE() << "Unexpected std::runtime_error"; return InvalidCode; } 329 static ReturnType Exception(const std::logic_error&, UserData) { ADD_FAILURE() << "Unexpected std::logic_error"; return ReturnType::InvalidCode; }
329 static ReturnType SystemError(std::system_error& ex, int) { ADD_FAILURE() << " Unexpected std::system_error"; return InvalidCode; } 330 static ReturnType Exception(const std::runtime_error&, UserData) { ADD_FAILURE () << "Unexpected std::runtime_error"; return ReturnType::InvalidCode; }
330 protected: 331 static ReturnType Exception(const std::system_error&, UserData) { ADD_FAILURE( ) << "Unexpected std::system_error"; return ReturnType::InvalidCode; }
331 static void Ping() { SimpleResult = SimpleExpected; }
332 }; 332 };
333 333
334 TEST(Exception, SimpleReturnUnknown) 334 TEST(Exception, SimpleReturnUnknown)
335 { 335 {
336 struct Handler : 336 struct Handler :
337 public SimpleHandlersReturnBase 337 public SimpleHandlersReturnBase
338 { 338 {
339 static int Unknown(int) { Ping(); return UnknownCode; } 339 static ReturnType Unknown(UserData h) { h.Touch(); return ReturnType::Unknow nCode; }
340 }; 340 using SimpleHandlersReturnBase::Exception;
341 SimpleReturn(UnknownCode, 5, Handler()); 341 };
342 SimpleReturn<Handler>(ReturnType::UnknownCode, 5);
342 } 343 }
343 344
344 TEST(Exception, SimpleReturnException) 345 TEST(Exception, SimpleReturnException)
345 { 346 {
346 struct Handler : 347 struct Handler :
347 public SimpleHandlersReturnBase 348 public SimpleHandlersReturnBase
348 { 349 {
349 static int Exception(std::exception& ex, int) { Ping(); return ExceptionCode ; } 350 static ReturnType Exception(const std::exception&, UserData h) { h.Touch(); return ReturnType::ExceptionCode; }
350 }; 351 using SimpleHandlersReturnBase::Exception;
351 SimpleReturn(ExceptionCode, PlainException(), Handler()); 352 };
353 SimpleReturn<Handler>(ReturnType::ExceptionCode, PlainException());
352 } 354 }
353 355
354 TEST(Exception, SimpleReturnLogicError) 356 TEST(Exception, SimpleReturnLogicError)
355 { 357 {
356 struct Handler : 358 struct Handler :
357 public SimpleHandlersReturnBase 359 public SimpleHandlersReturnBase
358 { 360 {
359 static int LogicError(std::logic_error& ex, int) { Ping(); return LogicError Code; } 361 static ReturnType Exception(const std::logic_error&, UserData h) { h.Touch() ; return ReturnType::LogicErrorCode; }
360 }; 362 using SimpleHandlersReturnBase::Exception;
361 SimpleReturn(LogicErrorCode, std::logic_error(""), Handler()); 363 };
364 SimpleReturn<Handler>(ReturnType::LogicErrorCode, std::logic_error(""));
362 } 365 }
363 366
364 TEST(Exception, SimpleReturnRuntimeError) 367 TEST(Exception, SimpleReturnRuntimeError)
365 { 368 {
366 struct Handler : 369 struct Handler :
367 public SimpleHandlersReturnBase 370 public SimpleHandlersReturnBase
368 { 371 {
369 static int RuntimeError(std::runtime_error& ex, int) { Ping(); return Runtim eErrorCode; } 372 static ReturnType Exception(const std::runtime_error&, UserData h) { h.Touch (); return ReturnType::RuntimeErrorCode; }
370 }; 373 using SimpleHandlersReturnBase::Exception;
371 SimpleReturn(RuntimeErrorCode, std::runtime_error(""), Handler()); 374 };
375 SimpleReturn<Handler>(ReturnType::RuntimeErrorCode, std::runtime_error(""));
372 } 376 }
373 377
374 TEST(Exception, SimpleReturnSystemError) 378 TEST(Exception, SimpleReturnSystemError)
375 { 379 {
376 struct Handler : 380 struct Handler :
377 public SimpleHandlersReturnBase 381 public SimpleHandlersReturnBase
378 { 382 {
379 static int SystemError(std::system_error& ex, int) { Ping(); return SystemEr rorCode; } 383 static ReturnType Exception(const std::system_error&, UserData h) { h.Touch( ); return ReturnType::SystemErrorCode; }
380 }; 384 using SimpleHandlersReturnBase::Exception;
381 SimpleReturn(SystemErrorCode, std::system_error(std::error_code()), Handler()) ; 385 };
382 } 386 SimpleReturn<Handler>(ReturnType::SystemErrorCode, std::system_error(std::erro r_code()));
383 387 }
LEFTRIGHT

Powered by Google App Engine
This is Rietveld