Modernise Lumiera Error baseclass
This commit is contained in:
parent
d6167c1845
commit
21e47e014a
4 changed files with 177 additions and 164 deletions
|
|
@ -45,11 +45,6 @@ using std::exception;
|
|||
|
||||
|
||||
namespace lumiera {
|
||||
|
||||
typedef const char* CStr;
|
||||
typedef const char* const CCStr;
|
||||
|
||||
|
||||
namespace error {
|
||||
|
||||
/** the message shown to the user per default
|
||||
|
|
@ -58,22 +53,16 @@ namespace lumiera {
|
|||
* @todo to be localised
|
||||
*/
|
||||
inline const string
|
||||
default_usermsg (Error* exception_obj) throw()
|
||||
default_usermsg (Error* exception_obj) noexcept
|
||||
{
|
||||
return string("Sorry, Lumiera encountered an internal error. (")
|
||||
+ util::typeStr(*exception_obj) + ")";
|
||||
}
|
||||
|
||||
inline CStr
|
||||
default_or_given (CCStr id)
|
||||
{
|
||||
return id? id : LUMIERA_ERROR_STATE;
|
||||
}
|
||||
|
||||
CStr
|
||||
detailInfo ()
|
||||
{
|
||||
CCStr detailinfo = lumiera_error_extra();
|
||||
CStr detailinfo = lumiera_error_extra();
|
||||
return isnil (detailinfo)? "Lumiera errorstate detected"
|
||||
: detailinfo;
|
||||
}
|
||||
|
|
@ -90,16 +79,14 @@ namespace lumiera {
|
|||
LUMIERA_ERROR_DEFINE (ASSERTION, "assertion failure");
|
||||
|
||||
/* some further generic error situations */
|
||||
LUMIERA_ERROR_DEFINE (LIFECYCLE, "Lifecycle assumptions violated");
|
||||
LUMIERA_ERROR_DEFINE (WRONG_TYPE, "runtime type mismatch");
|
||||
LUMIERA_ERROR_DEFINE (LIFECYCLE, "Lifecycle assumptions violated");
|
||||
LUMIERA_ERROR_DEFINE (WRONG_TYPE, "runtime type mismatch");
|
||||
LUMIERA_ERROR_DEFINE (ITER_EXHAUST, "end of sequence reached");
|
||||
LUMIERA_ERROR_DEFINE (CAPACITY, "predefined fixed storage capacity");
|
||||
LUMIERA_ERROR_DEFINE (INDEX_BOUNDS, "index out of bounds");
|
||||
LUMIERA_ERROR_DEFINE (BOTTOM_VALUE, "invalid or NIL value");
|
||||
LUMIERA_ERROR_DEFINE (UNCONNECTED, "missing connection");
|
||||
LUMIERA_ERROR_DEFINE (UNIMPLEMENTED, "using a feature not yet implemented....");
|
||||
|
||||
|
||||
LUMIERA_ERROR_DEFINE (UNCONNECTED, "missing connection");
|
||||
LUMIERA_ERROR_DEFINE (UNIMPLEMENTED,"using a feature not yet implemented....");
|
||||
|
||||
} // namespace error
|
||||
|
||||
|
|
@ -109,38 +96,29 @@ namespace lumiera {
|
|||
|
||||
|
||||
/** @note we set the C-style errorstate as a side effect */
|
||||
Error::Error (string description, CCStr id) throw()
|
||||
: std::exception (),
|
||||
id_ (error::default_or_given (id)),
|
||||
msg_ (error::default_usermsg (this)),
|
||||
desc_ (description),
|
||||
cause_ ("")
|
||||
{
|
||||
lumiera_error_set (this->id_, description.c_str ());
|
||||
}
|
||||
Error::Error (string description, lumiera_err const id) noexcept
|
||||
: std::exception{}
|
||||
, id_{id}
|
||||
, msg_{error::default_usermsg (this)}
|
||||
, desc_{description}
|
||||
, cause_{}
|
||||
{
|
||||
lumiera_error_set (this->id_, description.c_str());
|
||||
}
|
||||
|
||||
|
||||
Error::Error (std::exception const& cause,
|
||||
string description, CCStr id) throw()
|
||||
: std::exception (),
|
||||
id_ (error::default_or_given (id)),
|
||||
msg_ (error::default_usermsg (this)),
|
||||
desc_ (description),
|
||||
cause_ (extractCauseMsg(cause))
|
||||
{
|
||||
lumiera_error_set (this->id_, description.c_str ());
|
||||
}
|
||||
string description, lumiera_err const id) noexcept
|
||||
: std::exception{}
|
||||
, id_{id}
|
||||
, msg_{error::default_usermsg (this)}
|
||||
, desc_{description}
|
||||
, cause_{extractCauseMsg(cause)}
|
||||
{
|
||||
lumiera_error_set (this->id_, description.c_str());
|
||||
}
|
||||
|
||||
|
||||
/** @note copy ctor behaves like chaining, i.e setting the cause_. */
|
||||
Error::Error (const Error& ref) throw()
|
||||
: std::exception (),
|
||||
id_ (ref.id_),
|
||||
msg_ (ref.msg_),
|
||||
desc_ (ref.desc_),
|
||||
cause_ (extractCauseMsg(ref))
|
||||
{ }
|
||||
|
||||
|
||||
|
||||
/** Description of the problem, including the internal char constant
|
||||
|
|
@ -149,7 +127,7 @@ namespace lumiera {
|
|||
* generated output as well.
|
||||
*/
|
||||
CStr
|
||||
Error::what() const throw()
|
||||
Error::what() const noexcept
|
||||
{
|
||||
if (isnil (this->what_))
|
||||
{
|
||||
|
|
@ -165,9 +143,9 @@ namespace lumiera {
|
|||
* first exception encountered in a chain of exceptions
|
||||
*/
|
||||
const string
|
||||
Error::extractCauseMsg (const exception& cause) throw()
|
||||
Error::extractCauseMsg (const exception& cause) noexcept
|
||||
{
|
||||
const Error* err=dynamic_cast<const Error*> (&cause);
|
||||
const Error* err = dynamic_cast<const Error*> (&cause);
|
||||
if (err)
|
||||
{
|
||||
if (isnil (err->cause_))
|
||||
|
|
@ -175,7 +153,6 @@ namespace lumiera {
|
|||
else
|
||||
return err->cause_; // cause was caused by another exception
|
||||
}
|
||||
|
||||
// unknown other exception type
|
||||
return cause.what ();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -69,16 +69,16 @@ typedef const char* lumiera_err;
|
|||
* @param err name of the error without the 'LUMIERA_ERROR_' prefix (example: NO_MEMORY)
|
||||
*/
|
||||
#define LUMIERA_ERROR_DECLARE(err) \
|
||||
extern lumiera_err LUMIERA_ERROR_##err
|
||||
extern lumiera_err const LUMIERA_ERROR_##err
|
||||
|
||||
/**
|
||||
* Definition and initialization of an error constant.
|
||||
* Definition and initialisation of an error constant.
|
||||
* This macro eases the error definition in implementation files
|
||||
* @param err name of the error without the 'LUMIERA_ERROR_' prefix (example: NO_MEMORY)
|
||||
* @param msg message describing the error in plain english (example: "memory allocation failed")
|
||||
* @param msg message describing the error in plain English (example: "memory allocation failed")
|
||||
*/
|
||||
#define LUMIERA_ERROR_DEFINE(err, msg) \
|
||||
lumiera_err LUMIERA_ERROR_##err = "LUMIERA_ERROR_" #err ":" msg
|
||||
lumiera_err const LUMIERA_ERROR_##err = "LUMIERA_ERROR_" #err ":" msg
|
||||
|
||||
/**
|
||||
* Helper macro to raise an error for the current thread.
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@
|
|||
** Within Lumiera, C-style error states and C++-style exceptions
|
||||
** are tightly integrated. Creating an exception sets the error flag,
|
||||
** and there are helpers available to throw an exception automatically
|
||||
** when a non-cleare error state is detected.
|
||||
** when a unclear error state is detected.
|
||||
**
|
||||
** @see error-state.c
|
||||
** @see error.hpp
|
||||
|
|
@ -42,67 +42,106 @@
|
|||
#include "include/logging.h"
|
||||
#include "include/lifecycle.h"
|
||||
#include "lib/error.h"
|
||||
|
||||
#include <exception>
|
||||
#include <string>
|
||||
|
||||
|
||||
namespace lumiera {
|
||||
|
||||
using std::string;
|
||||
using CStr = const char*;
|
||||
|
||||
|
||||
#define LERR_(_NAME_) LUMIERA_ERROR_##_NAME_
|
||||
|
||||
/** error-ID for unspecified exceptions */
|
||||
LUMIERA_ERROR_DECLARE(EXCEPTION);
|
||||
LUMIERA_ERROR_DECLARE(EXCEPTION);
|
||||
|
||||
/**
|
||||
* Interface and Base class of all Exceptions thrown
|
||||
* from within Lumiera (C++) code. Common operations
|
||||
* for getting an diagnostic message and for obtaining
|
||||
* the root cause, i.e. the first exception encountered
|
||||
* in a chain of exceptions.
|
||||
* Interface and Base definition for all Lumiera Exceptions.
|
||||
* Provides common operations for getting an diagnostic message
|
||||
* and to obtaining the _root cause_ message, i.e. the message
|
||||
* from the first exception encountered in a chain of exceptions.
|
||||
*/
|
||||
class Error : public std::exception
|
||||
class Error
|
||||
: public std::exception
|
||||
{
|
||||
lumiera_err const id_; ///< an LUMIERA_ERROR id, which is set as errorstate on construction
|
||||
string msg_; ///< friendly message intended for users (to be localised)
|
||||
string desc_; ///< detailed description of the error situation for the developers
|
||||
mutable string what_; ///< buffer for generating the detailed description on demand
|
||||
const string cause_; ///< description of first exception encountered in the chain
|
||||
|
||||
|
||||
public:
|
||||
Error (string description="", const char* const id=LUMIERA_ERROR_EXCEPTION) throw();
|
||||
Error (std::exception const& cause,
|
||||
string description="", const char* const id=LUMIERA_ERROR_EXCEPTION) throw();
|
||||
virtual ~Error () noexcept { }; ///< this is an interface
|
||||
|
||||
Error (const Error&) throw();
|
||||
virtual ~Error () throw() {};
|
||||
|
||||
/** yield a diagnostic message characterising the problem */
|
||||
virtual const char* what () const throw();
|
||||
Error (string description=""
|
||||
,lumiera_err const id =LERR_(EXCEPTION)) noexcept;
|
||||
Error (std::exception const& cause
|
||||
,string description=""
|
||||
,lumiera_err const id =LERR_(EXCEPTION)) noexcept;
|
||||
|
||||
/** the internal Lumiera-error-ID (was set as C-errorstate in ctor) */
|
||||
const char* getID () const throw() { return this->id_; }
|
||||
Error (Error &&) = default;
|
||||
Error (Error const&) = default;
|
||||
Error& operator= (Error &&) = delete;
|
||||
Error& operator= (Error const&) = delete;
|
||||
|
||||
/** std::exception interface : yield a diagnostic message */
|
||||
virtual CStr
|
||||
what () const noexcept override;
|
||||
|
||||
/** the internal Lumiera-error-ID
|
||||
* (was set as C-errorstate in ctor) */
|
||||
lumiera_err
|
||||
getID () const noexcept
|
||||
{
|
||||
return id_;
|
||||
}
|
||||
|
||||
/** extract the message to be displayed for the user */
|
||||
const string& getUsermsg () const throw();
|
||||
string const&
|
||||
getUsermsg () const noexcept
|
||||
{
|
||||
return msg_;
|
||||
}
|
||||
|
||||
/** If this exception was caused by a chain of further exceptions,
|
||||
* return the description of the first one registered in this throw sequence.
|
||||
* This works only if every exceptions thrown as a consequence of another exception
|
||||
* This works only if every exceptions thrown as a consequence of another exception
|
||||
* is properly constructed by passing the original exception to the constructor
|
||||
* @return the description string, maybe empty (if there is no known root cause)
|
||||
*/
|
||||
const string& rootCause () const throw() { return this->cause_; }
|
||||
string const&
|
||||
rootCause () const noexcept
|
||||
{
|
||||
return cause_;
|
||||
}
|
||||
|
||||
/** replace the previous or default friendly message for the user. To be localised. */
|
||||
Error& setUsermsg (const string& newMsg) throw() { this->msg_ = newMsg; return *this; }
|
||||
/** replace the previous or default friendly message for the user.
|
||||
* @note to be localised / translated.
|
||||
*/
|
||||
Error&
|
||||
setUsermsg (string const& newMsg) noexcept
|
||||
{
|
||||
msg_ = newMsg;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** give additional developer info. Typically used at intermediate handlers to add context. */
|
||||
Error& prependInfo (const string& text) throw() { this->desc_.insert (0,text); return *this; }
|
||||
Error&
|
||||
prependInfo (string const& text) noexcept
|
||||
{
|
||||
desc_.insert (0, text);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
const char* id_; ///< an LUMIERA_ERROR id, which is set as errorstate on construction
|
||||
string msg_; ///< friendly message intended for users (to be localised)
|
||||
string desc_; ///< detailed description of the error situation for the developers
|
||||
mutable string what_; ///< buffer for generating the detailed description on demand
|
||||
const string cause_; ///< description of first exception encountered in the chain
|
||||
|
||||
static const string extractCauseMsg (std::exception const&) throw();
|
||||
static const string
|
||||
extractCauseMsg (std::exception const&) noexcept;
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -115,7 +154,7 @@ namespace lumiera {
|
|||
namespace error {
|
||||
|
||||
/** global function for handling unknown exceptions
|
||||
* encountered at functions declaring not to throw
|
||||
* encountered at functions declaring not to throw
|
||||
* this kind of exception. Basically, any such event
|
||||
* can be considered a severe design flaw; we can just
|
||||
* add some diagnostics prior to halting.
|
||||
|
|
@ -148,43 +187,41 @@ namespace lumiera {
|
|||
|
||||
|
||||
|
||||
/** Macro for creating derived exception classes properly
|
||||
* integrated into Lumiera's exception hierarchy. Using
|
||||
* this macro assures that the new class will get the full
|
||||
* set of constructors and behaviour common to all exception
|
||||
* classes, so it should be used when creating an derived
|
||||
* exception type for more then strictly local purposes
|
||||
*/
|
||||
#define LUMIERA_EXCEPTION_DECLARE(CLASS, PARENT, _ID_) \
|
||||
class CLASS : public PARENT \
|
||||
{ \
|
||||
public: \
|
||||
CLASS (std::string description="", \
|
||||
const char* id=_ID_) throw() \
|
||||
: PARENT (description, id) {} \
|
||||
\
|
||||
CLASS (std::exception const& cause, \
|
||||
std::string description="", \
|
||||
const char* id=_ID_) throw() \
|
||||
: PARENT (cause, description, id) {} \
|
||||
/**
|
||||
* Derived specific exceptions within Lumiera's exception hierarchy.
|
||||
*/
|
||||
template<lumiera_err const& eID, class PAR =Error>
|
||||
class LumieraError
|
||||
: public PAR
|
||||
{
|
||||
public:
|
||||
LumieraError (std::string description=""
|
||||
,lumiera_err const id=eID) noexcept
|
||||
: PAR{description, id}
|
||||
{ }
|
||||
LumieraError (std::exception const& cause
|
||||
,std::string description=""
|
||||
,lumiera_err const id=eID) noexcept
|
||||
: PAR{cause, description, id}
|
||||
{ }
|
||||
};
|
||||
|
||||
//-------------------------CLASS-----PARENT--ID----------------------
|
||||
LUMIERA_EXCEPTION_DECLARE (Logic, Error, LUMIERA_ERROR_LOGIC);
|
||||
LUMIERA_EXCEPTION_DECLARE (Fatal, Logic, LUMIERA_ERROR_FATAL);
|
||||
LUMIERA_EXCEPTION_DECLARE (Config, Error, LUMIERA_ERROR_CONFIG);
|
||||
LUMIERA_EXCEPTION_DECLARE (State, Error, LUMIERA_ERROR_STATE);
|
||||
LUMIERA_EXCEPTION_DECLARE (Flag, State, LUMIERA_ERROR_FLAG);
|
||||
LUMIERA_EXCEPTION_DECLARE (Invalid, Error, LUMIERA_ERROR_INVALID);
|
||||
LUMIERA_EXCEPTION_DECLARE (External, Error, LUMIERA_ERROR_EXTERNAL);
|
||||
//----CLASS-------------------ID--------------PARENT------
|
||||
using Logic = LumieraError<LERR_(LOGIC)>;
|
||||
using Fatal = LumieraError<LERR_(FATAL), Logic>;
|
||||
using State = LumieraError<LERR_(STATE)>;
|
||||
using Flag = LumieraError<LERR_(FLAG), State>;
|
||||
using Invalid = LumieraError<LERR_(INVALID)>;
|
||||
using Config = LumieraError<LERR_(CONFIG), Invalid>;
|
||||
using External = LumieraError<LERR_(EXTERNAL)>;
|
||||
|
||||
|
||||
/** install our own handler for undeclared exceptions. Will be
|
||||
* called automatically ON_BASIC_INIT when linking exception.cpp */
|
||||
void install_unexpectedException_handler ();
|
||||
void install_unexpectedException_handler();
|
||||
|
||||
/** @return error detail-info if currently set, a default message else */
|
||||
const char* detailInfo ();
|
||||
CStr detailInfo();
|
||||
|
||||
} // namespace error
|
||||
|
||||
|
|
@ -213,22 +250,14 @@ namespace lumiera {
|
|||
*/
|
||||
template<class EX>
|
||||
inline void
|
||||
maybeThrow(string description)
|
||||
maybeThrow (string description ="")
|
||||
{
|
||||
if (lumiera_err errorFlag =lumiera_error())
|
||||
{
|
||||
throw EX (error::Flag( error::detailInfo()
|
||||
, errorFlag)
|
||||
throw EX (error::Flag{error::detailInfo(), errorFlag}
|
||||
,description);
|
||||
} }
|
||||
|
||||
template<class EX>
|
||||
inline void
|
||||
maybeThrow()
|
||||
{
|
||||
maybeThrow<EX>("");
|
||||
}
|
||||
|
||||
|
||||
} // namespace lumiera
|
||||
|
||||
|
|
@ -256,7 +285,7 @@ namespace lumiera {
|
|||
|
||||
|
||||
/**************************************************//**
|
||||
* if NoBug is used, redefine some macros
|
||||
* if NoBug is used, redefine some macros
|
||||
* to rather throw Lumiera Errors instead of aborting
|
||||
*/
|
||||
#if 0 ///////////////////////////////////TODO disabled for now. NoBug aborts are hard and may hold some locks. There are hooks to allow throwing from NoBug TODO use them....
|
||||
|
|
|
|||
|
|
@ -28,41 +28,39 @@
|
|||
|
||||
#include "lib/error.h"
|
||||
#include "lib/error.hpp"
|
||||
|
||||
#include "lib/test/run.hpp"
|
||||
#include "lib/format-cout.hpp"
|
||||
#include "lib/util.hpp"
|
||||
|
||||
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include <exception>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
|
||||
using std::runtime_error;
|
||||
using std::exception;
|
||||
using std::string;
|
||||
using std::cout;
|
||||
|
||||
|
||||
|
||||
namespace lumiera {
|
||||
namespace test {
|
||||
|
||||
/** local specific error-constant for use in the
|
||||
LUMIERA_ERROR_DEFINE (LIFE_AND_UNIVERSE, "and everything?");
|
||||
/** local specific error-constant for use in the
|
||||
* constructor of the nested SpecificError class.
|
||||
*/
|
||||
LUMIERA_ERROR_DEFINE(LIFE_AND_UNIVERSE, "and everything?");
|
||||
LUMIERA_ERROR_DEFINE(DERIVED, "convoluted exception");
|
||||
LUMIERA_ERROR_DECLARE(DERIVED);
|
||||
LUMIERA_ERROR_DEFINE (DERIVED, "convoluted exception");
|
||||
|
||||
/** declare a specific Error class with parent class error::external */
|
||||
LUMIERA_EXCEPTION_DECLARE (DerivedError, error::External, LUMIERA_ERROR_DERIVED);
|
||||
/** define a specific Error subclass derived from error::external */
|
||||
using DerivedError = error::LumieraError<LERR_(DERIVED), error::External>;
|
||||
|
||||
|
||||
/******************************************************//**
|
||||
* Some aspects of C++ exception handling.
|
||||
* Not to be confused with the basic C-style error value
|
||||
* Not to be confused with the basic C-style error value
|
||||
* mechanism used by the low-level parts of the backend.
|
||||
* Both approaches are laregely orthogonal, but the
|
||||
* Both approaches are largely orthogonal, but the
|
||||
* C++ exception handling uses the C-style error constants.
|
||||
*
|
||||
*/
|
||||
|
|
@ -71,8 +69,8 @@ namespace lumiera {
|
|||
typedef ExceptionError_test test;
|
||||
virtual void run (Arg arg)
|
||||
{
|
||||
if (0 < arg.size() && arg[1]=="terminate")
|
||||
terminateUnknown ();
|
||||
if (0 < arg.size() and arg[1]=="terminate")
|
||||
terminateUnknown();
|
||||
|
||||
|
||||
catcher (&test::throwSpecial, "");
|
||||
|
|
@ -109,22 +107,22 @@ namespace lumiera {
|
|||
* which we are able to catch because it is derived from std::exception.
|
||||
* We don't need to know the exact type, but we can classify the error situation
|
||||
* as a "state error" and throw an error::State, passing on the root cause.
|
||||
* Some levels up, this error get caught and the root cause can be
|
||||
* Some levels up, this error get caught and the root cause can be
|
||||
* extracted successfully.
|
||||
*/
|
||||
void nestedThrower (string msg) throw(Error)
|
||||
void nestedThrower (string msg)
|
||||
{
|
||||
try { throwExternal(msg); }
|
||||
catch (std::exception& e)
|
||||
{
|
||||
cout << "intermediate handler caught: " << e.what()
|
||||
cout << "intermediate handler caught: " << e.what()
|
||||
<< "....will rethrow as error::State\n";
|
||||
throw error::State (e);
|
||||
}
|
||||
}
|
||||
|
||||
/** @test repeated repackaging and rethrowing */
|
||||
void doubleNestedTh (string msg) throw(error::Config)
|
||||
void doubleNestedTh (string msg)
|
||||
{
|
||||
try { nestedThrower (msg); }
|
||||
catch (Error& e)
|
||||
|
|
@ -142,25 +140,25 @@ namespace lumiera {
|
|||
void checkErrorIntegration()
|
||||
{
|
||||
lumiera_error ();
|
||||
CHECK (!lumiera_error ());
|
||||
CHECK (not lumiera_error());
|
||||
|
||||
Error err1;
|
||||
Error err2("boo",LUMIERA_ERROR_DERIVED);
|
||||
Error err2("boo",LERR_(DERIVED));
|
||||
CHECK (err1.getID () == lumiera_error ()); // (we didn't clear the first one!)
|
||||
|
||||
Error err3("boooo",LUMIERA_ERROR_DERIVED);
|
||||
Error err3("boooo",LERR_(DERIVED));
|
||||
CHECK (err3.getID () == lumiera_error ());
|
||||
|
||||
SpecificError err4;
|
||||
CHECK (err4.getID () == LUMIERA_ERROR_LIFE_AND_UNIVERSE);
|
||||
CHECK (err4.getID () == LERR_(LIFE_AND_UNIVERSE));
|
||||
CHECK (err4.getID () == lumiera_error ());
|
||||
|
||||
CHECK (!lumiera_error ());
|
||||
CHECK (not lumiera_error());
|
||||
}
|
||||
|
||||
|
||||
void detectErrorflag (string) { throwOnError(); }
|
||||
void detectErrorflagChained (string msg) { maybeThrow<error::Logic>(msg); }
|
||||
void detectErrorflagChained (string msg) { maybeThrow<error::Logic> (msg); }
|
||||
|
||||
|
||||
/** @test verify throwing of Exceptions
|
||||
|
|
@ -168,14 +166,14 @@ namespace lumiera {
|
|||
*/
|
||||
void checkErrorFlagPropagation()
|
||||
{
|
||||
lumiera_error_set(LUMIERA_ERROR_LIFE_AND_UNIVERSE, "what is the answer?");
|
||||
lumiera_error_set(LERR_(LIFE_AND_UNIVERSE), "what is the answer?");
|
||||
CHECK (lumiera_error_peek());
|
||||
|
||||
catcher (&test::detectErrorflag, "");
|
||||
CHECK (LUMIERA_ERROR_LIFE_AND_UNIVERSE == lumiera_error_peek());
|
||||
CHECK (LERR_(LIFE_AND_UNIVERSE) == lumiera_error_peek());
|
||||
|
||||
catcher (&test::detectErrorflagChained, "the big bang");
|
||||
CHECK (LUMIERA_ERROR_LIFE_AND_UNIVERSE == lumiera_error());
|
||||
CHECK (LERR_(LIFE_AND_UNIVERSE) == lumiera_error());
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -186,8 +184,8 @@ namespace lumiera {
|
|||
{
|
||||
error::Logic err1;
|
||||
error::Config err2(err1);
|
||||
error::Config err3(err2); //note: using copy ctor behaves like chaining
|
||||
Error err4(err1); // note: copy ctor
|
||||
error::Config err3(err2);
|
||||
Error err4(err1); // note: copy ctor
|
||||
|
||||
std::runtime_error rerr("what a shame");
|
||||
error::External err5(rerr);
|
||||
|
|
@ -195,7 +193,7 @@ namespace lumiera {
|
|||
|
||||
CHECK (err2.rootCause() == err1.what());
|
||||
CHECK (err3.rootCause() == err1.what());
|
||||
CHECK (err4.rootCause() == err1.what());
|
||||
CHECK (err4.rootCause() == err1.rootCause()); // mere copy is not a root cause
|
||||
|
||||
CHECK (err5.rootCause() == rerr.what());
|
||||
CHECK (err6.rootCause() == rerr.what());
|
||||
|
|
@ -204,31 +202,40 @@ namespace lumiera {
|
|||
|
||||
/** @test terminate the Application by throwing an undeclared exception.
|
||||
* this should result in the global unknown() handler to be called,
|
||||
* so usually it will terminate the test run.
|
||||
* so usually it will terminate the test run.
|
||||
* @note inside error.hpp, an initialisation hook has been installed into
|
||||
* AppState, causing our own unknown() handler to be installed and
|
||||
* invoked, which gives additional diagnostics.*/
|
||||
void terminateUnknown () throw()
|
||||
void terminateUnknown () noexcept
|
||||
{
|
||||
throw Error("You'll never get me, won't you?");
|
||||
}
|
||||
|
||||
|
||||
/** a very specific Exception class
|
||||
* local to this scope and with
|
||||
* local to this scope and with
|
||||
* additional behaviour.
|
||||
*/
|
||||
class SpecificError : public error::Invalid
|
||||
*/
|
||||
class SpecificError
|
||||
: public error::Invalid
|
||||
{
|
||||
int value;
|
||||
int value_;
|
||||
public:
|
||||
SpecificError () : Invalid("don't panic",LUMIERA_ERROR_LIFE_AND_UNIVERSE), value(42) {}
|
||||
int revealIt () { return value; }
|
||||
SpecificError()
|
||||
: error::Invalid{"don't panic", LUMIERA_ERROR_LIFE_AND_UNIVERSE}
|
||||
, value_(42)
|
||||
{ }
|
||||
|
||||
int
|
||||
revealIt()
|
||||
{
|
||||
return value_;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
/** helper: provides a bunch of catch-clauses and
|
||||
/** helper: provides a bunch of catch-clauses and
|
||||
* runs the given member functions within
|
||||
*/
|
||||
void catcher (void (ExceptionError_test::*funky)(string), string context)
|
||||
|
|
|
|||
Loading…
Reference in a new issue