Merge lp:~michihenning/unity-api/add-ExceptionImplBase into lp:unity-api
- add-ExceptionImplBase
- Merge into trunk
Status: | Merged |
---|---|
Approved by: | Jussi Pakkanen |
Approved revision: | 57 |
Merged at revision: | 59 |
Proposed branch: | lp:~michihenning/unity-api/add-ExceptionImplBase |
Merge into: | lp:unity-api |
Diff against target: |
1556 lines (+578/-612) 14 files modified
include/unity/Exception.h (+13/-21) include/unity/ExceptionImplBase.h (+65/-0) include/unity/UnityExceptions.h (+7/-21) include/unity/internal/ExceptionImpl.h (+0/-60) include/unity/internal/UnityExceptionsImpl.h (+0/-95) src/unity/CMakeLists.txt (+1/-0) src/unity/Exception.cpp (+13/-13) src/unity/ExceptionImplBase.cpp (+310/-0) src/unity/UnityExceptions.cpp (+47/-15) src/unity/internal/CMakeLists.txt (+0/-2) src/unity/internal/ExceptionImpl.cpp (+0/-244) src/unity/internal/UnityExceptionsImpl.cpp (+0/-126) src/unity/util/Daemon.cpp (+7/-0) test/gtest/unity/Exceptions_test.cpp (+115/-15) |
To merge this branch: | bzr merge lp:~michihenning/unity-api/add-ExceptionImplBase |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
PS Jenkins bot (community) | continuous-integration | Approve | |
Jussi Pakkanen (community) | Approve | ||
Review via email:
|
Commit message
Removed unity::
This allows clients of unity-api to derive their own exceptions for unity::Exception without exposing any implementation details (so the ABI won't break) and still take advantage of implementation inheritance without having to reimplement all the functionality of the base class
Description of the change
Removed unity::
This allows clients of unity-api to derive their own exceptions for unity::Exception without exposing any implementation details (so the ABI won't break) and still take advantage of implementation inheritance without having to reimplement all the functionality of the base class.
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
PS Jenkins bot (ps-jenkins) wrote : | # |
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Jussi Pakkanen (jpakkane) wrote : | # |
LGTM.
Under what circumstances would clients want to derive our exceptions, though? For their internal use they would probably use their own types. The only reason I can think of if they need to inject exceptions back to us and expect us to act on them in some way. Which seems a bit weird.
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Michi Henning (michihenning) wrote : | # |
> LGTM.
>
> Under what circumstances would clients want to derive our exceptions, though?
For example, unity-scopes-api is a client of unity-api. I need a MiddlewareException so I can catch a specific group of exceptions from the middleware layer selectively. I want to derive that exception from unity::Exception, so *all* exceptions ultimately are unity::exception or std::exception (which is a base for unity::exception). But that means I have to be able to derive form unity::exception without using the unity::internal namespace. (The previous design made that impossible.)
> For their internal use they would probably use their own types.
Yes, clients are free to do whatever they want with their own exceptions. But it's really nice to be able to say "catch any scope exception" or "catch any Unity API exception" for structured error handling.
And the functionality in unity::exception is kind of neat. Especially the nesting mechanism that preserves the original exception when an exception is re-thrown as something else is nice. It has zero API footprint and does the work quietly behind the scenes.
> The only
> reason I can think of if they need to inject exceptions back to us and expect
> us to act on them in some way. Which seems a bit weird.
There might a few places where we may expect scope to tell us something specific, in which case we can tell the author "you must throw X, if Y happens." But I don't expect there to many such cases, if any.
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Autolanding.
More details in the following jenkins job:
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
- 57. By Michi Henning
-
Merged trunk.
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:57
http://
Executed test runs:
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Michi Henning (michihenning) wrote : | # |
Jenkins is happy with this now. Can someone top-approve please?
Preview Diff
1 | === modified file 'include/unity/Exception.h' |
2 | --- include/unity/Exception.h 2013-06-12 22:07:05 +0000 |
3 | +++ include/unity/Exception.h 2013-06-17 04:58:28 +0000 |
4 | @@ -20,6 +20,7 @@ |
5 | #define UNITY_EXCEPTION_H |
6 | |
7 | #include <unity/SymbolExport.h> |
8 | +#include <unity/util/NonCopyable.h> |
9 | |
10 | #include <exception> |
11 | #include <string> |
12 | @@ -28,15 +29,7 @@ |
13 | namespace unity |
14 | { |
15 | |
16 | -namespace internal |
17 | -{ |
18 | -class ExceptionImpl; |
19 | -} |
20 | - |
21 | -// TODO: It probably would be best to split this into a base and ImplBase, with the derived part in the internal |
22 | -// namespace and declaring self(), the constructor, and pimpl(). That's because the Impl for the exception |
23 | -// is in the internal namespace, so public API clients can use Exception instances, but they cannot |
24 | -// create new derived exceptions because the Impl classes are internal to Unity. |
25 | +class ExceptionImplBase; |
26 | |
27 | /** |
28 | \brief Abstract base class for all Unity exceptions. |
29 | @@ -126,14 +119,6 @@ |
30 | */ |
31 | virtual char const* what() const noexcept = 0; |
32 | |
33 | - virtual std::string reason() const; |
34 | - |
35 | - virtual std::string to_string(std::string const& indent = " ") const; |
36 | - virtual std::string to_string(int indent_level, std::string const& indent) const; |
37 | - |
38 | - std::exception_ptr remember(std::exception_ptr earlier_exception); |
39 | - std::exception_ptr get_earlier() const noexcept; |
40 | - |
41 | /** |
42 | \brief Returns a <code>std::exception_ptr</code> to <code>this</code>. |
43 | |
44 | @@ -142,15 +127,22 @@ |
45 | */ |
46 | virtual std::exception_ptr self() const = 0; |
47 | |
48 | + std::string reason() const; |
49 | + |
50 | + std::string to_string(std::string const& indent = " ") const; |
51 | + std::string to_string(int indent_level, std::string const& indent) const; |
52 | + |
53 | + std::exception_ptr remember(std::exception_ptr earlier_exception); |
54 | + std::exception_ptr get_earlier() const noexcept; |
55 | + |
56 | protected: |
57 | //! @cond |
58 | - Exception(std::shared_ptr<internal::ExceptionImpl> const& derived); |
59 | - internal::ExceptionImpl* pimpl() const noexcept; // No need to reimplement in derived |
60 | + Exception(std::shared_ptr<ExceptionImplBase> const& derived); |
61 | //! @endcond |
62 | + ExceptionImplBase* pimpl() const noexcept; |
63 | |
64 | private: |
65 | - std::shared_ptr<internal::ExceptionImpl> p_; // shared_ptr instead of unique_ptr because |
66 | - // exceptions must be copyable |
67 | + std::shared_ptr<ExceptionImplBase> p_; // shared_ptr instead of unique_ptr because exceptions must be copyable |
68 | }; |
69 | |
70 | } // namespace unity |
71 | |
72 | === added file 'include/unity/ExceptionImplBase.h' |
73 | --- include/unity/ExceptionImplBase.h 1970-01-01 00:00:00 +0000 |
74 | +++ include/unity/ExceptionImplBase.h 2013-06-17 04:58:28 +0000 |
75 | @@ -0,0 +1,65 @@ |
76 | +/* |
77 | + * Copyright (C) 2013 Canonical Ltd |
78 | + * |
79 | + * This program is free software: you can redistribute it and/or modify |
80 | + * it under the terms of the GNU General Public License version 3 as |
81 | + * published by the Free Software Foundation. |
82 | + * |
83 | + * This program is distributed in the hope that it will be useful, |
84 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
85 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
86 | + * GNU General Public License for more details. |
87 | + * |
88 | + * You should have received a copy of the GNU General Public License |
89 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
90 | + * |
91 | + * Authored by: Michi Henning <michi.henning@canonical.com> |
92 | + */ |
93 | + |
94 | +#ifndef UNITY_EXCEPTIONIMPLBASE_H |
95 | +#define UNITY_EXCEPTIONIMPLBASE_H |
96 | + |
97 | +#include <unity/SymbolExport.h> |
98 | +#include <unity/util/NonCopyable.h> |
99 | + |
100 | +#include <exception> |
101 | +#include <string> |
102 | +#include <memory> |
103 | + |
104 | +namespace unity |
105 | +{ |
106 | + |
107 | +namespace internal |
108 | +{ |
109 | +class ExceptionData; |
110 | +} |
111 | + |
112 | +class Exception; |
113 | + |
114 | +/** |
115 | +\brief Implementation base exception class for API clients to derive new pimpl'd exception types from. |
116 | +\sa unity::Exception |
117 | +*/ |
118 | + |
119 | +class UNITY_API ExceptionImplBase : public util::NonCopyable |
120 | +{ |
121 | +public: |
122 | + explicit ExceptionImplBase(Exception const* owner, std::string const& reason); |
123 | + //! @cond |
124 | + virtual ~ExceptionImplBase() noexcept; |
125 | + //! @endcond |
126 | + |
127 | + std::string reason() const; |
128 | + |
129 | + std::string to_string(std::nested_exception const* nested, int indent_level, std::string const& indent) const; |
130 | + |
131 | + std::exception_ptr set_earlier(std::exception_ptr earlier_exception); |
132 | + std::exception_ptr get_earlier() const noexcept; |
133 | + |
134 | +private: |
135 | + std::shared_ptr<internal::ExceptionData> p_; // shared_ptr (not unique_ptr) because ExceptionData is incomplete |
136 | +}; |
137 | + |
138 | +} // namespace unity |
139 | + |
140 | +#endif |
141 | |
142 | === modified file 'include/unity/UnityExceptions.h' |
143 | --- include/unity/UnityExceptions.h 2013-06-12 22:07:05 +0000 |
144 | +++ include/unity/UnityExceptions.h 2013-06-17 04:58:28 +0000 |
145 | @@ -24,11 +24,6 @@ |
146 | namespace unity |
147 | { |
148 | |
149 | -namespace internal |
150 | -{ |
151 | -class InvalidArgumentExceptionImpl; |
152 | -} |
153 | - |
154 | /** |
155 | \brief Exception to indicate that an invalid argument was passed to a function, such as passing <code>nullptr</code> |
156 | when the function expects the argument to be non-null. |
157 | @@ -59,11 +54,6 @@ |
158 | virtual std::exception_ptr self() const override; |
159 | }; |
160 | |
161 | -namespace internal |
162 | -{ |
163 | -class LogicExceptionImpl; |
164 | -} |
165 | - |
166 | /** |
167 | \brief Exception to indicate a logic error, such as driving the API incorrectly, such as calling methods |
168 | in the wrong worder. |
169 | @@ -94,11 +84,6 @@ |
170 | virtual std::exception_ptr self() const override; |
171 | }; |
172 | |
173 | -namespace internal |
174 | -{ |
175 | -class ShutdownExceptionImpl; |
176 | -} |
177 | - |
178 | /** |
179 | \brief Exception to indicate errors during shutdown. |
180 | |
181 | @@ -174,6 +159,9 @@ |
182 | \return Returns the error number that was passed to the constructor. |
183 | */ |
184 | int error() const noexcept; |
185 | + |
186 | +private: |
187 | + std::shared_ptr<internal::FileExceptionImpl> p_; |
188 | }; |
189 | |
190 | namespace internal |
191 | @@ -217,13 +205,11 @@ |
192 | \return Returns the error number that was passed to the constructor. |
193 | */ |
194 | int error() const noexcept; |
195 | + |
196 | +private: |
197 | + //std::shared_ptr<internal::SyscallExceptionImpl> p_; |
198 | }; |
199 | |
200 | -namespace internal |
201 | -{ |
202 | -class ResourceExceptionImpl; |
203 | -} |
204 | - |
205 | /** |
206 | \brief Exception for miscellaneous errors, such as failure of a third-party library or hitting resource limitations. |
207 | */ |
208 | @@ -235,7 +221,7 @@ |
209 | \brief Constructs the exception. |
210 | \param reason Further details about the cause of the exception. |
211 | */ |
212 | - ResourceException(std::string const& reason); |
213 | + explicit ResourceException(std::string const& reason); |
214 | //! @cond |
215 | ResourceException(ResourceException const&); |
216 | ResourceException& operator=(ResourceException const&); |
217 | |
218 | === removed file 'include/unity/internal/ExceptionImpl.h' |
219 | --- include/unity/internal/ExceptionImpl.h 2013-06-12 22:07:05 +0000 |
220 | +++ include/unity/internal/ExceptionImpl.h 1970-01-01 00:00:00 +0000 |
221 | @@ -1,60 +0,0 @@ |
222 | -/* |
223 | - * Copyright (C) 2013 Canonical Ltd |
224 | - * |
225 | - * This program is free software: you can redistribute it and/or modify |
226 | - * it under the terms of the Lesser GNU General Public License version 3 as |
227 | - * published by the Free Software Foundation. |
228 | - * |
229 | - * This program is distributed in the hope that it will be useful, |
230 | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
231 | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
232 | - * Lesser GNU General Public License for more details. |
233 | - * |
234 | - * You should have received a copy of the Lesser GNU General Public License |
235 | - * along with this program. If not, see <http://www.gnu.org/licenses/>. |
236 | - * |
237 | - * Authored by: Michi Henning <michi.henning@canonical.com> |
238 | - */ |
239 | - |
240 | -#ifndef UNITY_INTERNAL_EXCEPTIONIMPL_H |
241 | -#define UNITY_INTERNAL_EXCEPTIONIMPL_H |
242 | - |
243 | -#include <unity/util/NonCopyable.h> |
244 | - |
245 | -#include <string> |
246 | -#include <exception> |
247 | - |
248 | -namespace unity |
249 | -{ |
250 | - |
251 | -class Exception; |
252 | - |
253 | -namespace internal |
254 | -{ |
255 | - |
256 | -class ExceptionImpl : private util::NonCopyable |
257 | -{ |
258 | -public: |
259 | - explicit ExceptionImpl(std::string const& reason); |
260 | - |
261 | - virtual char const* what() const noexcept = 0; |
262 | - virtual std::string reason() const; |
263 | - virtual std::string to_string(std::nested_exception const& nested, int indent_level, std::string const& indent) const; |
264 | - |
265 | - std::exception_ptr remember(unity::Exception const* env, std::exception_ptr earlier_exception); |
266 | - std::exception_ptr remember(unity::Exception const* env, Exception const& earlier_exception); |
267 | - std::exception_ptr get_earlier() const noexcept; |
268 | - |
269 | -protected: |
270 | - virtual ~ExceptionImpl() noexcept; |
271 | - |
272 | -private: |
273 | - std::string const reason_; |
274 | - std::exception_ptr previous_; |
275 | -}; |
276 | - |
277 | -} // namespace internal |
278 | - |
279 | -} // namespace unity |
280 | - |
281 | -#endif |
282 | |
283 | === removed file 'include/unity/internal/UnityExceptionsImpl.h' |
284 | --- include/unity/internal/UnityExceptionsImpl.h 2013-06-12 22:07:05 +0000 |
285 | +++ include/unity/internal/UnityExceptionsImpl.h 1970-01-01 00:00:00 +0000 |
286 | @@ -1,95 +0,0 @@ |
287 | -/* |
288 | - * Copyright (C) 2012 Canonical Ltd |
289 | - * |
290 | - * This program is free software: you can redistribute it and/or modify |
291 | - * it under the terms of the Lesser GNU General Public License version 3 as |
292 | - * published by the Free Software Foundation. |
293 | - * |
294 | - * This program is distributed in the hope that it will be useful, |
295 | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
296 | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
297 | - * Lesser GNU General Public License for more details. |
298 | - * |
299 | - * You should have received a copy of the Lesser GNU General Public License |
300 | - * along with this program. If not, see <http://www.gnu.org/licenses/>. |
301 | - * |
302 | - * Authored by: Michi Henning <michi.henning@canonical.com> |
303 | - */ |
304 | - |
305 | -#ifndef UNITY_INTERNAL_UNITYEXCEPTIONSIMPL_H |
306 | -#define UNITY_INTERNAL_UNITYEXCEPTIONSIMPL_H |
307 | - |
308 | -#include <unity/internal/ExceptionImpl.h> |
309 | - |
310 | -#include <string> |
311 | -#include <exception> |
312 | - |
313 | -namespace unity |
314 | -{ |
315 | - |
316 | -class Exception; |
317 | - |
318 | -namespace internal |
319 | -{ |
320 | - |
321 | -class InvalidArgumentExceptionImpl : public ExceptionImpl |
322 | -{ |
323 | -public: |
324 | - InvalidArgumentExceptionImpl(std::string const& reason); |
325 | - |
326 | - virtual char const* what() const noexcept override; |
327 | -}; |
328 | - |
329 | -class LogicExceptionImpl : public ExceptionImpl |
330 | -{ |
331 | -public: |
332 | - LogicExceptionImpl(std::string const& reason); |
333 | - |
334 | - virtual char const* what() const noexcept override; |
335 | -}; |
336 | - |
337 | -class ShutdownExceptionImpl : public ExceptionImpl |
338 | -{ |
339 | -public: |
340 | - ShutdownExceptionImpl(std::string const& reason); |
341 | - |
342 | - virtual char const* what() const noexcept override; |
343 | -}; |
344 | - |
345 | -class FileExceptionImpl : public ExceptionImpl |
346 | -{ |
347 | -public: |
348 | - FileExceptionImpl(std::string const& reason, int err); |
349 | - |
350 | - virtual char const* what() const noexcept override; |
351 | - int error() const noexcept; |
352 | - |
353 | -private: |
354 | - int errno_; |
355 | -}; |
356 | - |
357 | -class SyscallExceptionImpl : public ExceptionImpl |
358 | -{ |
359 | -public: |
360 | - SyscallExceptionImpl(std::string const& reason, int err); |
361 | - |
362 | - virtual char const* what() const noexcept override; |
363 | - int error() const noexcept; |
364 | - |
365 | -private: |
366 | - int const errno_; |
367 | -}; |
368 | - |
369 | -class ResourceExceptionImpl : public ExceptionImpl |
370 | -{ |
371 | -public: |
372 | - ResourceExceptionImpl(std::string const& reason); |
373 | - |
374 | - virtual char const* what() const noexcept override; |
375 | -}; |
376 | - |
377 | -} // namespace internal |
378 | - |
379 | -} // namespace unity |
380 | - |
381 | -#endif |
382 | |
383 | === modified file 'src/unity/CMakeLists.txt' |
384 | --- src/unity/CMakeLists.txt 2013-05-13 11:39:49 +0000 |
385 | +++ src/unity/CMakeLists.txt 2013-06-17 04:58:28 +0000 |
386 | @@ -4,6 +4,7 @@ |
387 | |
388 | set(UNITY_SRC |
389 | ${CMAKE_CURRENT_SOURCE_DIR}/Exception.cpp |
390 | + ${CMAKE_CURRENT_SOURCE_DIR}/ExceptionImplBase.cpp |
391 | ${CMAKE_CURRENT_SOURCE_DIR}/UnityExceptions.cpp |
392 | ) |
393 | |
394 | |
395 | === modified file 'src/unity/Exception.cpp' |
396 | --- src/unity/Exception.cpp 2013-06-12 22:07:05 +0000 |
397 | +++ src/unity/Exception.cpp 2013-06-17 04:58:28 +0000 |
398 | @@ -17,7 +17,7 @@ |
399 | */ |
400 | |
401 | #include <unity/Exception.h> |
402 | -#include <unity/internal/ExceptionImpl.h> |
403 | +#include <unity/ExceptionImplBase.h> |
404 | |
405 | using namespace std; |
406 | |
407 | @@ -27,7 +27,7 @@ |
408 | //! @cond |
409 | |
410 | Exception:: |
411 | -Exception(shared_ptr<internal::ExceptionImpl> const& derived) |
412 | +Exception(shared_ptr<ExceptionImplBase> const& derived) |
413 | : p_(derived) |
414 | { |
415 | } |
416 | @@ -59,7 +59,7 @@ |
417 | } |
418 | |
419 | /** |
420 | -Returns a string describing the exception, including any exceptions that were nested or chained. |
421 | +\brief Returns a string describing the exception, including any exceptions that were nested or chained. |
422 | |
423 | Nested exceptions are indented according to their nesting level. If the exception contains chained |
424 | exceptions, these are shown in oldest-to-newest order. |
425 | @@ -74,11 +74,11 @@ |
426 | Exception:: |
427 | to_string(std::string const& indent) const |
428 | { |
429 | - return p_->to_string(*this, 0, indent); |
430 | + return p_->to_string(this, 0, indent); |
431 | } |
432 | |
433 | /** |
434 | -Returns a string describing the exception, including any exceptions that were nested or chained. |
435 | +\brief Returns a string describing the exception, including any exceptions that were nested or chained. |
436 | |
437 | Nested exceptions are indented according to their nesting level. If the exception contains chained |
438 | exceptions, these are shown in oldest-to-newest order. |
439 | @@ -97,11 +97,11 @@ |
440 | Exception:: |
441 | to_string(int indent_level, std::string const& indent) const |
442 | { |
443 | - return p_->to_string(*this, indent_level, indent); |
444 | + return p_->to_string(this, indent_level, indent); |
445 | } |
446 | |
447 | /** |
448 | -Adds an exception to the exception history chain. |
449 | +\brief Adds an exception to the exception history chain. |
450 | |
451 | \param earlier_exception The parameter must be a <code>nullptr</code> or a <code>std::exception_ptr</code> |
452 | to an exception that was remembered earlier. This allows a sequence of exceptions to be remembered without |
453 | @@ -116,11 +116,11 @@ |
454 | Exception:: |
455 | remember(exception_ptr earlier_exception) |
456 | { |
457 | - return p_->remember(this, earlier_exception); |
458 | + return p_->set_earlier(earlier_exception); |
459 | } |
460 | |
461 | /** |
462 | -Returns the previous exception. |
463 | +\brief Returns the previous exception. |
464 | \return Returns the next-older remembered exception, or <code>nullptr</code>, if none. |
465 | */ |
466 | |
467 | @@ -131,15 +131,15 @@ |
468 | return p_->get_earlier(); |
469 | } |
470 | |
471 | -//! @cond |
472 | +/** |
473 | +\brief Returns a pointer to to the implementation instance. |
474 | +*/ |
475 | |
476 | -internal::ExceptionImpl* |
477 | +ExceptionImplBase* |
478 | Exception:: |
479 | pimpl() const noexcept |
480 | { |
481 | return p_.get(); |
482 | } |
483 | |
484 | -//! @endcond |
485 | - |
486 | } // namespace unity |
487 | |
488 | === added file 'src/unity/ExceptionImplBase.cpp' |
489 | --- src/unity/ExceptionImplBase.cpp 1970-01-01 00:00:00 +0000 |
490 | +++ src/unity/ExceptionImplBase.cpp 2013-06-17 04:58:28 +0000 |
491 | @@ -0,0 +1,310 @@ |
492 | +/* |
493 | + * Copyright (C) 2012 Canonical Ltd |
494 | + * |
495 | + * This program is free software: you can redistribute it and/or modify |
496 | + * it under the terms of the GNU General Public License version 3 as |
497 | + * published by the Free Software Foundation. |
498 | + * |
499 | + * This program is distributed in the hope that it will be useful, |
500 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
501 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
502 | + * GNU General Public License for more details. |
503 | + * |
504 | + * You should have received a copy of the GNU General Public License |
505 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
506 | + * |
507 | + * Authored by: Michi Henning <michi.henning@canonical.com> |
508 | + */ |
509 | + |
510 | +#include <unity/ExceptionImplBase.h> |
511 | +#include <unity/Exception.h> |
512 | + |
513 | +using namespace std; |
514 | + |
515 | +namespace unity |
516 | +{ |
517 | + |
518 | +namespace internal |
519 | +{ |
520 | + |
521 | +class ExceptionData |
522 | +{ |
523 | +public: |
524 | + ExceptionData(Exception const* owner, string const& reason) |
525 | + : owner_(owner) |
526 | + , reason_(reason) |
527 | + , earlier_(nullptr) |
528 | + { |
529 | + } |
530 | + |
531 | + ExceptionData(ExceptionData const&) = delete; |
532 | + ExceptionData& operator=(ExceptionData const&) = delete; |
533 | + |
534 | + Exception const* owner_; |
535 | + string reason_; |
536 | + std::exception_ptr earlier_; |
537 | +}; |
538 | + |
539 | +} |
540 | + |
541 | +/** |
542 | +\brief Instantiates an implementation instance for a unity::Exception. |
543 | +\param owner This must be set to the `this` pointer of the exception that owns this implementation. |
544 | +\param reason Further details about the cause of the exception. |
545 | +*/ |
546 | + |
547 | +ExceptionImplBase:: |
548 | +ExceptionImplBase(Exception const* owner, string const& reason) |
549 | + : p_(make_shared<internal::ExceptionData>(owner, reason)) |
550 | +{ |
551 | +} |
552 | + |
553 | +//! @cond |
554 | + |
555 | +ExceptionImplBase:: |
556 | +~ExceptionImplBase() noexcept = default; |
557 | + |
558 | +namespace |
559 | +{ |
560 | + |
561 | +// |
562 | +// Return the margin string for the indent level and indent. |
563 | +// |
564 | + |
565 | +string |
566 | +get_margin(int indent_level, string const& indent) |
567 | +{ |
568 | + string margin; |
569 | + for (int i = 0; i < indent_level; ++i) |
570 | + { |
571 | + margin += indent; |
572 | + } |
573 | + return margin; |
574 | +} |
575 | + |
576 | +// |
577 | +// Follow the nested exceptions that were rethrown along the call stack, printing them into s. |
578 | +// |
579 | + |
580 | +void |
581 | +print_name_and_reason(string& s, nested_exception const* nested) |
582 | +{ |
583 | + // Add the what() string if this is a std::exception. |
584 | + |
585 | + std::exception const* std_exception = dynamic_cast<std::exception const*>(nested); |
586 | + if (std_exception) |
587 | + { |
588 | + s += std_exception->what(); |
589 | + } |
590 | + |
591 | + // Add the reason if this is a unity::Exception. |
592 | + |
593 | + unity::Exception const* unity_exception = dynamic_cast<unity::Exception const*>(nested); |
594 | + if (unity_exception) |
595 | + { |
596 | + string reason = unity_exception->reason(); |
597 | + if (!reason.empty()) |
598 | + { |
599 | + s += ": " + reason; |
600 | + } |
601 | + } |
602 | + |
603 | + // Append info about unknown std::exception and std::nested_exception. |
604 | + |
605 | + if (!unity_exception) |
606 | + { |
607 | + if (std_exception) |
608 | + { |
609 | + s += " (derived from std::exception and std::nested_exception)"; |
610 | + } |
611 | + else |
612 | + { |
613 | + s += "std::nested_exception"; |
614 | + } |
615 | + } |
616 | +} |
617 | + |
618 | +void |
619 | +follow_nested(string& s, nested_exception const* nested, int indent_level, std::string const& indent) |
620 | +{ |
621 | + if (nested->nested_ptr()) |
622 | + { |
623 | + string margin = get_margin(indent_level, indent); |
624 | + |
625 | + s += ":\n"; |
626 | + try |
627 | + { |
628 | + nested->rethrow_nested(); |
629 | + } |
630 | + catch (std::nested_exception const& e) |
631 | + { |
632 | + unity::Exception const* ge = dynamic_cast<unity::Exception const*>(&e); |
633 | + if (ge) |
634 | + { |
635 | + s += ge->to_string(indent_level + 1, indent); |
636 | + } |
637 | + else |
638 | + { |
639 | + s += margin + indent; |
640 | + print_name_and_reason(s, &e); |
641 | + follow_nested(s, &e, indent_level + 1, indent); |
642 | + } |
643 | + } |
644 | + catch (std::exception const& e) |
645 | + { |
646 | + s += margin + indent; |
647 | + s += e.what(); // Can show only what() for std::exception. |
648 | + } |
649 | + catch (...) |
650 | + { |
651 | + s += margin + indent; |
652 | + s += "unknown exception"; // Best we can do for an exception whose type we don't know. |
653 | + } |
654 | + } |
655 | +} |
656 | + |
657 | +// |
658 | +// Follow the history chain and print each exception in the chain. |
659 | +// |
660 | + |
661 | +void |
662 | +follow_history(string& s, int& count, unity::Exception const* e, int indent_level, std::string const& indent) |
663 | +{ |
664 | + if (!e->get_earlier()) |
665 | + { |
666 | + count = 1; // We have reached the oldest exception; set exception generation count and terminate recursion. |
667 | + } |
668 | + else |
669 | + { |
670 | + try |
671 | + { |
672 | + rethrow_exception(e->get_earlier()); |
673 | + } |
674 | + catch (unity::Exception const& e) |
675 | + { |
676 | + // Recurse along the chain until we hit the end, then, as we pop back up the levels, we increment the |
677 | + // count and print it as a generation number for the exception information. |
678 | + // A bit like the "kicks" in "Inception", except that the deepest level is level 1... |
679 | + |
680 | + follow_history(s, count, &e, indent_level, indent); |
681 | + } |
682 | + ++count; |
683 | + } |
684 | + |
685 | + // Show info for this exception. |
686 | + |
687 | + s += "\n" + get_margin(indent_level, indent) + "Exception #"; |
688 | + s += to_string(count) + ":\n"; |
689 | + s += get_margin(indent_level, indent) + indent; |
690 | + print_name_and_reason(s, e); |
691 | + follow_nested(s, e, indent_level + 1, indent); |
692 | +} |
693 | + |
694 | +} // namespace |
695 | + |
696 | +//! @endcond |
697 | + |
698 | +/** |
699 | +\brief Returns the reason set by the derived class's constructor (empty string if none). |
700 | + |
701 | +Derived classes should include any other state information, such as the value of data members or |
702 | +other relevant detail in the <code>reason</code> string they pass to the protected constructor. |
703 | +*/ |
704 | + |
705 | +string |
706 | +ExceptionImplBase:: |
707 | +reason() const |
708 | +{ |
709 | + return p_->reason_; |
710 | +} |
711 | + |
712 | +/** |
713 | +\brief Returns a string describing the exception, including any exceptions that were nested or chained. |
714 | + |
715 | +Nested exceptions are indented according to their nesting level. If the exception contains chained |
716 | +exceptions, these are shown in oldest-to-newest order. |
717 | + |
718 | +\param nested This must be set to the `this` pointer of the exception that owns this implementation. |
719 | + |
720 | +\param indent_level This controls the indent level. The value <code>0</code> indicates |
721 | + the outermost level (no indent). |
722 | +\param indent This controls the amount of indenting per level. The default indent is four spaces. |
723 | +\return The string describing the exception. |
724 | +*/ |
725 | + |
726 | +string |
727 | +ExceptionImplBase:: |
728 | +to_string(nested_exception const* nested, int indent_level, string const& indent) const |
729 | +{ |
730 | + string margin = get_margin(indent_level, indent); |
731 | + string s = margin; |
732 | + s += dynamic_cast<const std::exception*>(nested)->what(); |
733 | + |
734 | + string r = reason(); |
735 | + if (!r.empty()) |
736 | + { |
737 | + s += ": " + r; |
738 | + } |
739 | + |
740 | + // Check whether there is an exception history and print each exception in the history. |
741 | + |
742 | + unity::Exception const* unity_exception(dynamic_cast<unity::Exception const*>(nested)); |
743 | + if (unity_exception && unity_exception->get_earlier()) |
744 | + { |
745 | + s += "\n" + margin + indent + "Exception history:"; |
746 | + try |
747 | + { |
748 | + rethrow_exception(unity_exception->get_earlier()); |
749 | + } |
750 | + catch (unity::Exception const& e) |
751 | + { |
752 | + int count; |
753 | + follow_history(s, count, &e, indent_level + 2, indent); |
754 | + } |
755 | + } |
756 | + |
757 | + // Print this and any nested exceptions. |
758 | + |
759 | + follow_nested(s, nested, indent_level, indent); |
760 | + |
761 | + return s; |
762 | +} |
763 | + |
764 | +/** |
765 | +\brief Adds an exception to the exception history chain. |
766 | + |
767 | +\param earlier_exception The parameter must be a <code>nullptr</code> or a <code>std::exception_ptr</code> |
768 | +to an exception that was remembered earlier. This allows a sequence of exceptions to be remembered without |
769 | +having to throw them and is useful for example, in shutdown scenarios where any one of a sequence of steps |
770 | +can fail, but we want to continue and try all the following steps and only throw after all of them have been |
771 | +tried. In this case, each step that fails can add itself to the sequence of remembered exceptions, and finally |
772 | +throw something like <code>ShutdownException</code>. |
773 | +\return A <code>std::exception_ptr</code> to <code>this</code>. |
774 | +*/ |
775 | + |
776 | +exception_ptr |
777 | +ExceptionImplBase:: |
778 | +set_earlier(exception_ptr earlier_exception) |
779 | +{ |
780 | + // Doesn't prevent loops, but protects against accidental self-assignment. |
781 | + |
782 | + if (p_->earlier_ != earlier_exception) |
783 | + { |
784 | + p_->earlier_ = earlier_exception; |
785 | + } |
786 | + return p_->owner_->self(); |
787 | +} |
788 | + |
789 | +/** |
790 | +\brief Returns the previous exception. |
791 | +\return Returns the next-older remembered exception, or <code>nullptr</code>, if none. |
792 | +*/ |
793 | + |
794 | +exception_ptr |
795 | +ExceptionImplBase:: |
796 | +get_earlier() const noexcept |
797 | +{ |
798 | + return p_->earlier_; |
799 | +} |
800 | + |
801 | +} // namespace unity |
802 | |
803 | === modified file 'src/unity/UnityExceptions.cpp' |
804 | --- src/unity/UnityExceptions.cpp 2013-06-12 22:07:05 +0000 |
805 | +++ src/unity/UnityExceptions.cpp 2013-06-17 04:58:28 +0000 |
806 | @@ -17,7 +17,7 @@ |
807 | */ |
808 | |
809 | #include <unity/UnityExceptions.h> |
810 | -#include <unity/internal/UnityExceptionsImpl.h> |
811 | +#include <unity/ExceptionImplBase.h> |
812 | |
813 | using namespace std; |
814 | |
815 | @@ -26,7 +26,7 @@ |
816 | |
817 | InvalidArgumentException:: |
818 | InvalidArgumentException(string const& reason) |
819 | - : Exception(make_shared<internal::InvalidArgumentExceptionImpl>(reason)) |
820 | + : Exception(make_shared<ExceptionImplBase>(this, reason)) |
821 | { |
822 | } |
823 | |
824 | @@ -49,7 +49,7 @@ |
825 | InvalidArgumentException:: |
826 | what() const noexcept |
827 | { |
828 | - return dynamic_cast<internal::InvalidArgumentExceptionImpl*>(pimpl())->what(); |
829 | + return "unity::InvalidArgumentException"; |
830 | } |
831 | |
832 | exception_ptr |
833 | @@ -61,7 +61,7 @@ |
834 | |
835 | LogicException:: |
836 | LogicException(string const& reason) |
837 | - : Exception(make_shared<internal::LogicExceptionImpl>(reason)) |
838 | + : Exception(make_shared<ExceptionImplBase>(this, reason)) |
839 | { |
840 | } |
841 | |
842 | @@ -83,7 +83,7 @@ |
843 | LogicException:: |
844 | what() const noexcept |
845 | { |
846 | - return dynamic_cast<internal::LogicExceptionImpl*>(pimpl())->what(); |
847 | + return "unity::LogicException"; |
848 | } |
849 | |
850 | exception_ptr |
851 | @@ -95,7 +95,7 @@ |
852 | |
853 | ShutdownException:: |
854 | ShutdownException(string const& reason) |
855 | - : Exception(make_shared<internal::ShutdownExceptionImpl>(reason)) |
856 | + : Exception(make_shared<ExceptionImplBase>(this, reason)) |
857 | { |
858 | } |
859 | |
860 | @@ -117,7 +117,7 @@ |
861 | ShutdownException:: |
862 | what() const noexcept |
863 | { |
864 | - return dynamic_cast<internal::ShutdownExceptionImpl*>(pimpl())->what(); |
865 | + return "unity::ShutdownException"; |
866 | } |
867 | |
868 | exception_ptr |
869 | @@ -127,9 +127,25 @@ |
870 | return make_exception_ptr(*this); |
871 | } |
872 | |
873 | +namespace internal |
874 | +{ |
875 | + |
876 | +class FileExceptionImpl : public unity::ExceptionImplBase |
877 | +{ |
878 | +public: |
879 | + FileExceptionImpl(FileException const* owner, string const& reason, int err) |
880 | + : ExceptionImplBase(owner, reason + (err == 0 ? "" : " (errno = " + std::to_string(err) + ")")) |
881 | + , err_(err) |
882 | + { |
883 | + } |
884 | + int err_; |
885 | +}; |
886 | + |
887 | +} |
888 | + |
889 | FileException:: |
890 | FileException(string const& reason, int err) |
891 | - : Exception(make_shared<internal::FileExceptionImpl>(reason, err)) |
892 | + : Exception(make_shared<internal::FileExceptionImpl>(this, reason, err)) |
893 | { |
894 | } |
895 | |
896 | @@ -151,14 +167,14 @@ |
897 | FileException:: |
898 | what() const noexcept |
899 | { |
900 | - return dynamic_cast<internal::FileExceptionImpl*>(pimpl())->what(); |
901 | + return "unity::FileException"; |
902 | } |
903 | |
904 | int |
905 | FileException:: |
906 | error() const noexcept |
907 | { |
908 | - return dynamic_cast<internal::FileExceptionImpl*>(pimpl())->error(); |
909 | + return dynamic_cast<const internal::FileExceptionImpl*>(pimpl())->err_; |
910 | } |
911 | |
912 | exception_ptr |
913 | @@ -168,9 +184,25 @@ |
914 | return make_exception_ptr(*this); |
915 | } |
916 | |
917 | +namespace internal |
918 | +{ |
919 | + |
920 | +class SyscallExceptionImpl : public unity::ExceptionImplBase |
921 | +{ |
922 | +public: |
923 | + SyscallExceptionImpl(SyscallException const* owner, string const& reason, int err) |
924 | + : ExceptionImplBase(owner, reason + (reason.empty() ? "" : " ") + "(errno = " + std::to_string(err) + ")") |
925 | + , err_(err) |
926 | + { |
927 | + } |
928 | + int err_; |
929 | +}; |
930 | + |
931 | +} |
932 | + |
933 | SyscallException:: |
934 | SyscallException(string const& reason, int err) |
935 | - : Exception(make_shared<internal::SyscallExceptionImpl>(reason, err)) |
936 | + : Exception(make_shared<internal::SyscallExceptionImpl>(this, reason, err)) |
937 | { |
938 | } |
939 | |
940 | @@ -192,14 +224,14 @@ |
941 | SyscallException:: |
942 | what() const noexcept |
943 | { |
944 | - return dynamic_cast<internal::SyscallExceptionImpl*>(pimpl())->what(); |
945 | + return "unity::SyscallException"; |
946 | } |
947 | |
948 | int |
949 | SyscallException:: |
950 | error() const noexcept |
951 | { |
952 | - return dynamic_cast<internal::SyscallExceptionImpl*>(pimpl())->error(); |
953 | + return dynamic_cast<const internal::SyscallExceptionImpl*>(pimpl())->err_; |
954 | } |
955 | |
956 | exception_ptr |
957 | @@ -211,7 +243,7 @@ |
958 | |
959 | ResourceException:: |
960 | ResourceException(string const& reason) |
961 | - : Exception(make_shared<internal::ResourceExceptionImpl>(reason)) |
962 | + : Exception(make_shared<ExceptionImplBase>(this, reason)) |
963 | { |
964 | } |
965 | |
966 | @@ -233,7 +265,7 @@ |
967 | ResourceException:: |
968 | what() const noexcept |
969 | { |
970 | - return dynamic_cast<internal::ResourceExceptionImpl*>(pimpl())->what(); |
971 | + return "unity::ResourceException"; |
972 | } |
973 | |
974 | exception_ptr |
975 | |
976 | === modified file 'src/unity/internal/CMakeLists.txt' |
977 | --- src/unity/internal/CMakeLists.txt 2013-05-13 11:39:49 +0000 |
978 | +++ src/unity/internal/CMakeLists.txt 2013-06-17 04:58:28 +0000 |
979 | @@ -1,6 +1,4 @@ |
980 | set(UNITY_INTERNAL_SRC |
981 | - ${CMAKE_CURRENT_SOURCE_DIR}/ExceptionImpl.cpp |
982 | - ${CMAKE_CURRENT_SOURCE_DIR}/UnityExceptionsImpl.cpp |
983 | ) |
984 | |
985 | set(UNITY_API_LIB_SRC ${UNITY_API_LIB_SRC} ${UNITY_INTERNAL_SRC} PARENT_SCOPE) |
986 | |
987 | === removed file 'src/unity/internal/ExceptionImpl.cpp' |
988 | --- src/unity/internal/ExceptionImpl.cpp 2013-06-12 22:07:05 +0000 |
989 | +++ src/unity/internal/ExceptionImpl.cpp 1970-01-01 00:00:00 +0000 |
990 | @@ -1,244 +0,0 @@ |
991 | -/* |
992 | - * Copyright (C) 2013 Canonical Ltd |
993 | - * |
994 | - * This program is free software: you can redistribute it and/or modify |
995 | - * it under the terms of the Lesser GNU General Public License version 3 as |
996 | - * published by the Free Software Foundation. |
997 | - * |
998 | - * This program is distributed in the hope that it will be useful, |
999 | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1000 | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1001 | - * Lesser GNU General Public License for more details. |
1002 | - * |
1003 | - * You should have received a copy of the Lesser GNU General Public License |
1004 | - * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1005 | - * |
1006 | - * Authored by: Michi Henning <michi.henning@canonical.com> |
1007 | - */ |
1008 | - |
1009 | -#include <unity/internal/ExceptionImpl.h> |
1010 | -#include <unity/Exception.h> |
1011 | - |
1012 | -using namespace std; |
1013 | - |
1014 | -namespace unity |
1015 | -{ |
1016 | - |
1017 | -namespace internal |
1018 | -{ |
1019 | - |
1020 | -ExceptionImpl:: |
1021 | -ExceptionImpl(string const& reason) |
1022 | - : reason_(reason) |
1023 | -{ |
1024 | -} |
1025 | - |
1026 | -ExceptionImpl:: |
1027 | -~ExceptionImpl() noexcept = default; |
1028 | - |
1029 | -string |
1030 | -ExceptionImpl:: |
1031 | -reason() const |
1032 | -{ |
1033 | - return reason_; |
1034 | -} |
1035 | - |
1036 | -namespace |
1037 | -{ |
1038 | - |
1039 | -// |
1040 | -// Return the margin string for the indent level and indent. |
1041 | -// |
1042 | - |
1043 | -string |
1044 | -get_margin(int indent_level, string const& indent) |
1045 | -{ |
1046 | - string margin; |
1047 | - for (int i = 0; i < indent_level; ++i) |
1048 | - { |
1049 | - margin += indent; |
1050 | - } |
1051 | - return margin; |
1052 | -} |
1053 | - |
1054 | -// |
1055 | -// Follow the nested exceptions that were rethrown along the call stack, printing them into s. |
1056 | -// |
1057 | - |
1058 | -void |
1059 | -print_name_and_reason(string& s, nested_exception const& nested) |
1060 | -{ |
1061 | - // Add the what() string if this is a std::exception. |
1062 | - |
1063 | - std::exception const* std_exception = dynamic_cast<std::exception const*>(&nested); |
1064 | - if (std_exception) |
1065 | - { |
1066 | - s += std_exception->what(); |
1067 | - } |
1068 | - |
1069 | - // Add the reason if this is a unity::Exception. |
1070 | - |
1071 | - unity::Exception const* unity_exception = dynamic_cast<unity::Exception const*>(&nested); |
1072 | - if (unity_exception) |
1073 | - { |
1074 | - string reason = unity_exception->reason(); |
1075 | - if (!reason.empty()) |
1076 | - { |
1077 | - s += ": " + reason; |
1078 | - } |
1079 | - } |
1080 | - |
1081 | - // Append info about unknown std::exception and std::nested_exception. |
1082 | - |
1083 | - if (!unity_exception) |
1084 | - { |
1085 | - if (std_exception) |
1086 | - { |
1087 | - s += " (derived from std::exception and std::nested_exception)"; |
1088 | - } |
1089 | - else |
1090 | - { |
1091 | - s += "std::nested_exception"; |
1092 | - } |
1093 | - } |
1094 | -} |
1095 | - |
1096 | -void |
1097 | -follow_nested(string& s, nested_exception const& nested, int indent_level, std::string const& indent) |
1098 | -{ |
1099 | - if (nested.nested_ptr()) |
1100 | - { |
1101 | - string margin = get_margin(indent_level, indent); |
1102 | - |
1103 | - s += ":\n"; |
1104 | - try |
1105 | - { |
1106 | - nested.rethrow_nested(); |
1107 | - } |
1108 | - catch (std::nested_exception const& e) |
1109 | - { |
1110 | - unity::Exception const* ge = dynamic_cast<unity::Exception const*>(&e); |
1111 | - if (ge) |
1112 | - { |
1113 | - s += ge->to_string(indent_level + 1, indent); |
1114 | - } |
1115 | - else |
1116 | - { |
1117 | - s += margin + indent; |
1118 | - print_name_and_reason(s, e); |
1119 | - follow_nested(s, e, indent_level + 1, indent); |
1120 | - } |
1121 | - } |
1122 | - catch (std::exception const& e) |
1123 | - { |
1124 | - s += margin + indent; |
1125 | - s += e.what(); // Can show only what() for std::exception. |
1126 | - } |
1127 | - catch (...) |
1128 | - { |
1129 | - s += margin + indent; |
1130 | - s += "unknown exception"; // Best we can do for an exception whose type we don't know. |
1131 | - } |
1132 | - } |
1133 | -} |
1134 | - |
1135 | -// |
1136 | -// Follow the history chain and print each exception in the chain. |
1137 | -// |
1138 | - |
1139 | -void |
1140 | -follow_history(string& s, int& count, unity::Exception const& e, int indent_level, std::string const& indent) |
1141 | -{ |
1142 | - if (!e.get_earlier()) |
1143 | - { |
1144 | - count = 1; // We have reached the oldest exception; set exception generation count and terminate recursion. |
1145 | - } |
1146 | - else |
1147 | - { |
1148 | - try |
1149 | - { |
1150 | - rethrow_exception(e.get_earlier()); |
1151 | - } |
1152 | - catch (unity::Exception const& e) |
1153 | - { |
1154 | - // Recurse along the chain until we hit the end, then, as we pop back up the levels, we increment the |
1155 | - // count and print it as a generation number for the exception information. |
1156 | - // A bit like the "kicks" in "Inception", except that the deepest level is level 1... |
1157 | - |
1158 | - follow_history(s, count, e, indent_level, indent); |
1159 | - } |
1160 | - ++count; |
1161 | - } |
1162 | - |
1163 | - // Show info for this exception. |
1164 | - |
1165 | - s += "\n" + get_margin(indent_level, indent) + "Exception #"; |
1166 | - s += to_string(count) + ":\n"; |
1167 | - s += get_margin(indent_level, indent) + indent; |
1168 | - print_name_and_reason(s, e); |
1169 | - follow_nested(s, e, indent_level + 1, indent); |
1170 | -} |
1171 | - |
1172 | -} // namespace |
1173 | - |
1174 | -string |
1175 | -ExceptionImpl:: |
1176 | -to_string(nested_exception const& nested, int indent_level, string const& indent) const |
1177 | -{ |
1178 | - string margin = get_margin(indent_level, indent); |
1179 | - string s = margin; |
1180 | - s += what(); |
1181 | - |
1182 | - string r = reason(); |
1183 | - if (!r.empty()) |
1184 | - { |
1185 | - s += ": " + r; |
1186 | - } |
1187 | - |
1188 | - // Check whether there is an exception history and print each exception in the history. |
1189 | - |
1190 | - unity::Exception const* unity_exception(dynamic_cast<unity::Exception const*>(&nested)); |
1191 | - if (unity_exception && unity_exception->get_earlier()) |
1192 | - { |
1193 | - s += "\n" + margin + indent + "Exception history:"; |
1194 | - try |
1195 | - { |
1196 | - rethrow_exception(unity_exception->get_earlier()); |
1197 | - } |
1198 | - catch (unity::Exception const& e) |
1199 | - { |
1200 | - int count; |
1201 | - follow_history(s, count, e, indent_level + 2, indent); |
1202 | - } |
1203 | - } |
1204 | - |
1205 | - // Print this and any nested exceptions. |
1206 | - |
1207 | - follow_nested(s, nested, indent_level, indent); |
1208 | - |
1209 | - return s; |
1210 | -} |
1211 | - |
1212 | -exception_ptr |
1213 | -ExceptionImpl:: |
1214 | -remember(Exception const* env, exception_ptr earlier_exception) |
1215 | -{ |
1216 | - // Doesn't prevent loops, but protects against accidental self-assignment. |
1217 | - |
1218 | - if (previous_ != earlier_exception) |
1219 | - { |
1220 | - previous_ = earlier_exception; |
1221 | - } |
1222 | - return env->self(); |
1223 | -} |
1224 | - |
1225 | -exception_ptr |
1226 | -ExceptionImpl:: |
1227 | -get_earlier() const noexcept |
1228 | -{ |
1229 | - return previous_; |
1230 | -} |
1231 | - |
1232 | -} // namespace internal |
1233 | - |
1234 | -} // namespace unity |
1235 | |
1236 | === removed file 'src/unity/internal/UnityExceptionsImpl.cpp' |
1237 | --- src/unity/internal/UnityExceptionsImpl.cpp 2013-06-12 22:07:05 +0000 |
1238 | +++ src/unity/internal/UnityExceptionsImpl.cpp 1970-01-01 00:00:00 +0000 |
1239 | @@ -1,126 +0,0 @@ |
1240 | -/* |
1241 | - * Copyright (C) 2012 Canonical Ltd |
1242 | - * |
1243 | - * This program is free software: you can redistribute it and/or modify |
1244 | - * it under the terms of the Lesser GNU General Public License version 3 as |
1245 | - * published by the Free Software Foundation. |
1246 | - * |
1247 | - * This program is distributed in the hope that it will be useful, |
1248 | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1249 | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1250 | - * Lesser GNU General Public License for more details. |
1251 | - * |
1252 | - * You should have received a copy of the Lesser GNU General Public License |
1253 | - * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1254 | - * |
1255 | - * Authored by: Michi Henning <michi.henning@canonical.com> |
1256 | - */ |
1257 | - |
1258 | -#include <unity/internal/UnityExceptionsImpl.h> |
1259 | - |
1260 | -using namespace std; |
1261 | - |
1262 | -namespace unity |
1263 | -{ |
1264 | - |
1265 | -namespace internal |
1266 | -{ |
1267 | - |
1268 | -InvalidArgumentExceptionImpl:: |
1269 | -InvalidArgumentExceptionImpl(string const& reason) |
1270 | - : ExceptionImpl(reason) |
1271 | -{ |
1272 | -} |
1273 | - |
1274 | -char const* |
1275 | -InvalidArgumentExceptionImpl:: |
1276 | -what() const noexcept |
1277 | -{ |
1278 | - return "unity::InvalidArgumentException"; |
1279 | -} |
1280 | - |
1281 | -LogicExceptionImpl:: |
1282 | -LogicExceptionImpl(string const& reason) |
1283 | - : ExceptionImpl(reason) |
1284 | -{ |
1285 | -} |
1286 | - |
1287 | -char const* |
1288 | -LogicExceptionImpl:: |
1289 | -what() const noexcept |
1290 | -{ |
1291 | - return "unity::LogicException"; |
1292 | -} |
1293 | - |
1294 | -ShutdownExceptionImpl:: |
1295 | -ShutdownExceptionImpl(string const& reason) |
1296 | - : ExceptionImpl(reason) |
1297 | -{ |
1298 | -} |
1299 | - |
1300 | -char const* |
1301 | -ShutdownExceptionImpl:: |
1302 | -what() const noexcept |
1303 | -{ |
1304 | - return "unity::ShutdownException"; |
1305 | -} |
1306 | - |
1307 | -FileExceptionImpl:: |
1308 | -FileExceptionImpl(string const& reason, int err) |
1309 | - : ExceptionImpl(reason + (err == 0 ? "" : " (errno = " + std::to_string(err) + ")")) |
1310 | - , errno_(err) |
1311 | -{ |
1312 | -} |
1313 | - |
1314 | -char const* |
1315 | -FileExceptionImpl:: |
1316 | -what() const noexcept |
1317 | -{ |
1318 | - return "unity::FileException"; |
1319 | -} |
1320 | - |
1321 | -int |
1322 | -FileExceptionImpl:: |
1323 | -error() const noexcept |
1324 | -{ |
1325 | - return errno_; |
1326 | -} |
1327 | - |
1328 | -SyscallExceptionImpl:: |
1329 | -SyscallExceptionImpl(string const& reason, int err) |
1330 | - : ExceptionImpl(reason + (reason.empty() ? "" : " ") + "(errno = " + std::to_string(err) + ")") |
1331 | - , errno_(err) |
1332 | -{ |
1333 | -} |
1334 | - |
1335 | -char const* |
1336 | -SyscallExceptionImpl:: |
1337 | -what() const noexcept |
1338 | -{ |
1339 | - return "unity::SyscallException"; |
1340 | -} |
1341 | - |
1342 | -int |
1343 | -SyscallExceptionImpl:: |
1344 | -error() const noexcept |
1345 | -{ |
1346 | - return errno_; |
1347 | -} |
1348 | - |
1349 | -ResourceExceptionImpl:: |
1350 | -ResourceExceptionImpl(string const& reason) |
1351 | - : ExceptionImpl(reason) |
1352 | -{ |
1353 | -} |
1354 | - |
1355 | -char const* |
1356 | -ResourceExceptionImpl:: |
1357 | -what() const noexcept |
1358 | -{ |
1359 | - return "unity::ResourceException"; |
1360 | -} |
1361 | - |
1362 | - |
1363 | -} // namespace internal |
1364 | - |
1365 | -} // namespace unity |
1366 | |
1367 | === modified file 'src/unity/util/Daemon.cpp' |
1368 | --- src/unity/util/Daemon.cpp 2013-06-12 22:07:05 +0000 |
1369 | +++ src/unity/util/Daemon.cpp 2013-06-17 04:58:28 +0000 |
1370 | @@ -34,6 +34,11 @@ |
1371 | return UPtr(new Daemon()); |
1372 | } |
1373 | |
1374 | +// This is covered by tests, but only when we are not building for coverage. |
1375 | +// (Closing all file descriptors interferes with the coverage reporting.) |
1376 | + |
1377 | +// LCOV_EXCL_START |
1378 | + |
1379 | void |
1380 | Daemon:: |
1381 | close_fds() noexcept |
1382 | @@ -41,6 +46,8 @@ |
1383 | p_->close_fds(); |
1384 | } |
1385 | |
1386 | +// LCOV_EXCL_STOP |
1387 | + |
1388 | void |
1389 | Daemon:: |
1390 | reset_signals() noexcept |
1391 | |
1392 | === modified file 'test/gtest/unity/Exceptions_test.cpp' |
1393 | --- test/gtest/unity/Exceptions_test.cpp 2013-06-12 22:07:05 +0000 |
1394 | +++ test/gtest/unity/Exceptions_test.cpp 2013-06-17 04:58:28 +0000 |
1395 | @@ -17,7 +17,7 @@ |
1396 | */ |
1397 | |
1398 | #include <unity/UnityExceptions.h> |
1399 | -#include <unity/internal/UnityExceptionsImpl.h> |
1400 | +#include <unity/ExceptionImplBase.h> |
1401 | |
1402 | #include <gtest/gtest.h> |
1403 | |
1404 | @@ -47,6 +47,15 @@ |
1405 | EXPECT_EQ("unity::SyscallException: blah (errno = 0)", e3.to_string(0, " ")); |
1406 | EXPECT_EQ(" unity::SyscallException: blah (errno = 0)", e3.to_string(1, " ")); |
1407 | EXPECT_EQ(" unity::SyscallException: blah (errno = 0)", e3.to_string(2, " ")); |
1408 | + |
1409 | + try |
1410 | + { |
1411 | + throw e; |
1412 | + } |
1413 | + catch (Exception& e) |
1414 | + { |
1415 | + EXPECT_STREQ("unity::SyscallException", e.what()); |
1416 | + } |
1417 | } |
1418 | |
1419 | TEST(Exception, empty_reason) |
1420 | @@ -250,19 +259,9 @@ |
1421 | exception_ptr ep = make_exception_ptr(e); |
1422 | |
1423 | InvalidArgumentException e2(""); |
1424 | - exception_ptr ep2 = e2.remember(ep); |
1425 | - EXPECT_EQ(e2.get_earlier(), ep); |
1426 | - } |
1427 | - |
1428 | - { |
1429 | - InvalidArgumentException e(""); |
1430 | - exception_ptr ep = make_exception_ptr(e); |
1431 | - |
1432 | - InvalidArgumentException e2(""); |
1433 | - exception_ptr ep2 = e2.remember(ep); |
1434 | - EXPECT_EQ(e2.get_earlier(), ep); |
1435 | - } |
1436 | - |
1437 | + e2.remember(ep); |
1438 | + EXPECT_EQ(e2.get_earlier(), ep); |
1439 | + } |
1440 | |
1441 | // Check that we are following the history chain. |
1442 | |
1443 | @@ -297,7 +296,6 @@ |
1444 | } |
1445 | } |
1446 | |
1447 | - |
1448 | // Same test, but this time with nested exceptions in the history. |
1449 | |
1450 | { |
1451 | @@ -534,3 +532,105 @@ |
1452 | delete ep; |
1453 | } |
1454 | } |
1455 | + |
1456 | +class StatelessException : public unity::Exception |
1457 | +{ |
1458 | +public: |
1459 | + explicit StatelessException(std::string const& reason) |
1460 | + : Exception(make_shared<ExceptionImplBase>(this, reason)) |
1461 | + { |
1462 | + } |
1463 | + explicit StatelessException(std::shared_ptr<ExceptionImplBase> const& derived) |
1464 | + : Exception(derived) |
1465 | + { |
1466 | + } |
1467 | + StatelessException(StatelessException const&) = default; |
1468 | + StatelessException& operator=(StatelessException const&) = default; |
1469 | + virtual ~StatelessException() noexcept {} |
1470 | + |
1471 | + virtual char const* what() const noexcept override |
1472 | + { |
1473 | + return "StatelessException"; |
1474 | + } |
1475 | + |
1476 | + virtual std::exception_ptr self() const override |
1477 | + { |
1478 | + return make_exception_ptr(*this); |
1479 | + } |
1480 | + |
1481 | +}; |
1482 | + |
1483 | +TEST(Derivation, stateless_derivation) |
1484 | +{ |
1485 | + StatelessException e("test"); |
1486 | + EXPECT_EQ("test", e.reason()); |
1487 | + EXPECT_STREQ("StatelessException", e.what()); |
1488 | +} |
1489 | + |
1490 | +namespace Impl |
1491 | +{ |
1492 | +class StatefulExceptionImpl; |
1493 | +} |
1494 | + |
1495 | +class StatefulException : public unity::Exception |
1496 | +{ |
1497 | +public: |
1498 | + StatefulException(std::string const& reason, int state); |
1499 | + StatefulException(std::shared_ptr<ExceptionImplBase> const& derived) |
1500 | + : Exception(derived) |
1501 | + { |
1502 | + } |
1503 | + StatefulException(StatefulException const&) = default; |
1504 | + StatefulException& operator=(StatefulException const&) = default; |
1505 | + virtual ~StatefulException() noexcept {} |
1506 | + |
1507 | + virtual char const* what() const noexcept override |
1508 | + { |
1509 | + return "StatefulException"; |
1510 | + } |
1511 | + |
1512 | + virtual std::exception_ptr self() const override |
1513 | + { |
1514 | + return make_exception_ptr(*this); |
1515 | + } |
1516 | + |
1517 | +}; |
1518 | + |
1519 | +namespace Impl |
1520 | +{ |
1521 | + |
1522 | +class StatefulExceptionImpl : public unity::ExceptionImplBase |
1523 | +{ |
1524 | +public: |
1525 | + StatefulExceptionImpl(StatefulException const* owner, string const& reason, int state) |
1526 | + : ExceptionImplBase(owner, reason + " state = " + std::to_string(state)) |
1527 | + , state_(state) |
1528 | + { |
1529 | + } |
1530 | + int state_; |
1531 | +}; |
1532 | + |
1533 | +} |
1534 | + |
1535 | +StatefulException:: |
1536 | +StatefulException(std::string const& reason, int state) |
1537 | + : Exception(make_shared<Impl::StatefulExceptionImpl>(this, reason, state)) |
1538 | +{ |
1539 | +} |
1540 | + |
1541 | +TEST(Derivation, stateful_derivation) |
1542 | +{ |
1543 | + StatefulException e("test", 99); |
1544 | + EXPECT_EQ("test state = 99", e.reason()); |
1545 | + EXPECT_STREQ("StatefulException", e.what()); |
1546 | +} |
1547 | + |
1548 | +#if 0 |
1549 | + |
1550 | +TEST(Derivation, two_level_derivation) |
1551 | +{ |
1552 | + StatefulException e("test", 99); |
1553 | + EXPECT_EQ("test state = 99", e.reason()); |
1554 | + EXPECT_STREQ("StatefulException", e.what()); |
1555 | +} |
1556 | +#endif |
PASSED: Continuous integration, rev:56 jenkins. qa.ubuntu. com/job/ unity-api- ci/74/ jenkins. qa.ubuntu. com/job/ unity-api- saucy-armhf- ci/31 jenkins. qa.ubuntu. com/job/ unity-api- saucy-armhf- ci/31/artifact/ work/output/ *zip*/output. zip jenkins. qa.ubuntu. com/job/ unity-api- saucy-i386- ci/32
http://
Executed test runs:
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild: s-jenkins: 8080/job/ unity-api- ci/74/rebuild
http://