libsex
3.1.0
simple exception library (C++)
|
The unit tests serve as compilable and runnable documentation (not included in this API documentation).
At first, let's declare a very primitive exception in tests/framework/ExampleException1.hxx
/** * @file * * Shows how to _declare_ basic exception class. */ #ifndef EXAMPLEEXCEPTION1_HXX #define EXAMPLEEXCEPTION1_HXX #include <libsex/declare.hxx> #include <libsex/Exception.hxx> namespace example { // Forward declare to ensure the namespace exists. class ExampleException1; } // ExampleException1 inherits from libsex::Exception. LIBSEX_DECLARE(libsex::Exception, example, ExampleException1) #endif
We then define it and assign an error message in tests/framework/ExampleException1.cxx
/** * @file * Shows how to _define_ a basic exception class. */ #include <libsex/define.hxx> #include <libsex/Exception.hxx> #include <tests/framework/ExampleException1.hxx> // Define ExampleException1 and provide a message template. // If you want to localize your exceptions, you just have // to localize that line. LIBSEX_DEFINE(libsex::Exception, example, ExampleException1, "Error!")
We repeat that procedure to create a more sophisticated class:
tests/framework/ExampleException2.hxx
/** * @file * * Shows how to _declare_ an exception class that uses * placedholders in its message template. * * Note that it is _declared_ in exactly the same way as a * basic exception class. */ #ifndef EXAMPLEEXCEPTION2_HXX #define EXAMPLEEXCEPTION2_HXX #include <libsex/declare.hxx> #include <libsex/Exception.hxx> namespace example { class ExampleException2; } // ExampleException2 inherits from libsex::Exception. LIBSEX_DECLARE(libsex::Exception, example, ExampleException2) #endif
tests/framework/ExampleException2.cxx
/** * @file * * Shows how to _define_ an exception class that contains * placeholders in its message template. */ #include <libsex/define.hxx> #include <libsex/Exception.hxx> #include <tests/framework/ExampleException2.hxx> // Define ExampleException2 and provide a message template // (see printf for a list and explanation of placeholders). LIBSEX_DEFINE(libsex::Exception, example, ExampleException2, "%s is %d")
Finally, here's how to use those classes and the framework:
tests/UsageExamples.cxx
/** * @file * * Shows how this framework is supposed to be used. */ // Needed for the tests in this file, not part of the examples. #include <tests/UsageExamples.hxx> #include <sstream> // Usage examples begin now. #include <libsex/throw.hxx> #include <tests/framework/ExampleException1.hxx> #include <tests/framework/ExampleException2.hxx> /** * How to simply create an exception. */ void tests::UsageExamples::testSimpleConstruction() { // The error message. std::string msg("Someone has set us up the bomb!"); // Create an exception, do not throw it. Note we // can pass an arbitrary string as message -- // the Exception subsystem itself does not depend // on message templates. example::ExampleException2 e(msg.c_str()); // Turn description into an instance of std::string // (needed for comparing). std::string what(e.what()); CPPUNIT_ASSERT_EQUAL(msg, what); } /** * How to throw a single exception without placeholders in * its message template. */ void tests::UsageExamples::testSimpleThrowing() { bool success = false; try { // Create an instance and throw it. Note // that THROW uses the message template, so // we can not pass an arbitrary string. // Since ExampleException1's message // template does not expect any arguments, // we can use THROW_ARGLESS. THROW_ARGLESS(example::ExampleException1); } catch (example::ExampleException1& e) { // Check whether result is as expected. std::string exp(__FILE__); exp += ":55: Error!"; std::string act(e.what()); CPPUNIT_ASSERT_EQUAL(exp, act); success = true; } CPPUNIT_ASSERT(success); } /** * How to throw a single exception. */ void tests::UsageExamples::testThrowing() { bool success = false; try { // Fill the parameters into the message // template and throw an exception // containing the resulting string. THROW(example::ExampleException2, "foobar", 42); } catch (example::ExampleException2& e) { // Check whether result is as expected. std::string exp(__FILE__); exp += ":81: foobar is 42"; std::string act(e.what()); CPPUNIT_ASSERT_EQUAL(exp, act); success = true; } CPPUNIT_ASSERT(success); } /** * How to chain exceptions. */ void tests::UsageExamples::testChaining() { bool success = false; try { try { THROW(example::ExampleException2, "foo", 21); } catch (example::ExampleException2& e) { // Note that CHAIN expects the // variable name of the previous // exception to be "e"! CHAIN(example::ExampleException2, "bar", 42); } } catch (example::ExampleException2& e) { // Check whether result is as expected. std::string exp(__FILE__); exp += ":110: bar is 42\n"; exp += __FILE__; exp += ":105: foo is 21"; std::stringstream act; e.backtrace(act); CPPUNIT_ASSERT_EQUAL( exp, act.str()); success = true; } CPPUNIT_ASSERT(success); }