OKlibrary  0.2.1.6
TestExceptions.hpp
Go to the documentation of this file.
00001 // Oliver Kullmann, 17.12.2006 (Swansea)
00002 /* Copyright 2006 - 2007 Oliver Kullmann
00003 This file is part of the OKlibrary. OKlibrary is free software; you can redistribute
00004 it and/or modify it under the terms of the GNU General Public License as published by
00005 the Free Software Foundation and included in this library; either version 3 of the
00006 License, or any later version. */
00007 
00013 #ifndef TESTEXCEPTIONSMESSAGES_jJbv448865RtFd
00014 #define TESTEXCEPTIONSMESSAGES_jJbv448865RtFd
00015 
00016 #include <string>
00017 #include <cassert>
00018 #include <tr1/memory>
00019 #include <stdexcept>
00020 #include <vector>
00021 
00022 #include <OKlib/Programming/SystemSpecifics/Demangling.hpp>
00023 #include <OKlib/Programming/Messages/MessagesMain.hpp>
00024 #include <OKlib/Programming/Messages/LineHandling.hpp>
00025 #include <OKlib/Programming/Messages/Utilities/FileIdentification.hpp>
00026 #include <OKlib/Programming/Messages/Utilities/LineIdentification.hpp>
00027 
00028 #include <OKlib/TestSystem/BasicDeclarations.hpp>
00029 #include <OKlib/TestSystem/messages/TestLevel.hpp>
00030 #include <OKlib/TestSystem/messages/TestBaseClass.hpp>
00031 
00032 namespace OKlib {
00033   namespace TestSystem {
00034     namespace messages {
00035 
00048       struct ErrorDescription : ::OKlib::Messages::MessagesPrePost {
00049         OKLIB_MESSAGES_PRINT
00050 
00051       private :
00052         
00053         typedef std::tr1::shared_ptr< ::OKlib::Messages::MessagesPrePost> MessagePointer;
00054 
00055         MessagePointer test_description;
00056         MessagePointer file;
00057         MessagePointer line;
00058         size_type indent;
00059 
00060         struct ClassIdentificationHeading : ::OKlib::Messages::MessagesPrePost {
00061           OKLIB_MESSAGES_PRINT
00062           void print(std::ostream& out, L<en_GB>, S<Basic>) const {}
00063           void print(std::ostream& out, L<en_GB>, S<Full>) const {
00064             l_start(out) << "Test class identification:"; l_end(out);
00065           }
00066         };
00067         struct ExceptionIdentificationHeading : ::OKlib::Messages::MessagesPrePost {
00068           OKLIB_MESSAGES_PRINT
00069           void print(std::ostream& out, L<en_GB>, S<Basic>) const {}
00070           void print(std::ostream& out, L<en_GB>, S<Full>) const {
00071             l_start(out) << "Test exception identification:"; l_end(out);
00072           }
00073         };
00074 
00075       public :
00076 
00077         ErrorDescription(
00078                          const ::OKlib::TestSystem::messages::BasicTestDescription& test,
00079                          ::OKlib::Messages::Utilities::FileIdentification* const file_,
00080                          ::OKlib::Messages::Utilities::LineIdentification* const line_,
00081                          const size_type indent_ = 1
00082                          ) :
00083           test_description(new ::OKlib::TestSystem::messages::BasicTestDescription(test)),
00084           file(file_),
00085           line(line_),
00086           indent(indent_)
00087         {
00088           assert(test_description.get());
00089           assert(file.get());
00090           assert(line.get());
00091         }
00092 
00093         void print(std::ostream& out, L<en_GB>, S<Basic>) const {
00094           assert(test_description.get());
00095           assert(line.get());
00096           ErrorDescription temp(*this);
00097           temp.prefix() += std::string(indent, ' ');
00098           out << ClassIdentificationHeading().cp_pp(temp);
00099           out << test_description -> cp_pp(temp);
00100           out << ExceptionIdentificationHeading().cp_pp(temp);
00101           out << line -> cp_pp(temp); l_end(out);
00102         }
00103         void print(std::ostream& out, L<en_GB>, S<Full>) const {
00104           assert(test_description.get());
00105           assert(file.get());
00106           assert(line.get());
00107           ErrorDescription temp(*this);
00108           temp.prefix() += std::string(indent, ' ');
00109           out << ClassIdentificationHeading().cp_pp(temp);
00110           out << test_description -> cp_pp(temp);
00111           out << ExceptionIdentificationHeading().cp_pp(temp);
00112           out << file -> cp_pp(temp); l_end(out);
00113           out << line -> cp_pp(temp); l_end(out);
00114         }
00115 
00116       };
00117 
00118       // ######################################################
00119 
00120 
00134       class TestException : public std::runtime_error, public ::OKlib::Messages::MessagesPrePost {
00136         typedef std::vector< ::OKlib::TestSystem::messages::ErrorDescription> ErrorContainer; 
00137         ErrorContainer errors;
00138         typedef std::tr1::shared_ptr< ::OKlib::Messages::MessagesPrePost> MessagePointer;
00139         MessagePointer additional_circumstances;
00140       public :
00141         OKLIB_MESSAGES_PRINT
00142         TestException(
00143                       const std::string& circumstances,
00144                       ::OKlib::Messages::MessagesPrePost* const additional_circumstances_ = 0
00145                       ) :
00146           std::runtime_error(circumstances),
00147           additional_circumstances(additional_circumstances_)
00148         {}
00149         ~TestException() throw() {}
00150         
00151         TestException& add(const ::OKlib::TestSystem::messages::ErrorDescription e) {
00152           errors.push_back(e);
00153           return *this;
00154         }
00155         
00156         void print(std::ostream& out, L<en_GB>, S<Basic>) const {
00157           typedef ErrorContainer::size_type size_type;
00158           l_start(out); l_end(out);
00159           l_start(out) << "EXCEPTION THROWN:"; l_end(out);
00160           l_start(out) << " error message = " << what(); l_end(out);
00161           l_start(out) << " stack trace (";
00162           {
00163             const size_type size(errors.size());
00164             out << size << " element";
00165             if (size != 1) out << "s";
00166           }
00167           out << "):"; l_end(out);
00168           typedef ErrorContainer::const_iterator iterator;
00169           const iterator& end(errors.end());
00170           size_type counter = 0;
00171           for (iterator i(errors.begin()); i != end; ++i, ++counter) {
00172             l_start(out) << "Error description " << counter << ":"; l_end(out);
00173             out << ::OKlib::TestSystem::messages::ErrorDescription(*i).cp_pp(*this);
00174           }
00175         }
00176 
00177         void print(std::ostream& out, L<en_GB>, S<Full>) const {
00178           typedef ErrorContainer::size_type size_type;
00179           l_start(out); l_end(out);
00180           l_start(out) << "TEST EXCEPTION THROWN:"; l_end(out);
00181           l_start(out) << " short error message = " << what(); l_end(out);
00182           if (additional_circumstances.get()) {
00183             l_start(out) << " additional error circumstances :"; l_end(out);
00184             out << additional_circumstances -> cp_pp(*this);
00185           }
00186           l_start(out) << " stack trace call-history (with ";
00187           {
00188             const size_type size(errors.size());
00189             out << size << " element";
00190             if (size != 1) out << "s";
00191           }
00192           out << "):"; l_end(out);
00193           typedef ErrorContainer::const_iterator iterator;
00194           const iterator& end(errors.end());
00195           size_type counter = 0;
00196           for (iterator i(errors.begin()); i != end; ++i, ++counter) {
00197             l_start(out) << "Error description " << counter << ":"; l_end(out);
00198             out << ::OKlib::TestSystem::messages::ErrorDescription(*i).cp_pp(*this);
00199           }
00200           l_start(out) << "END TEST EXCEPTION THROWN."; l_end(out);
00201         }
00202 
00203       };
00204 
00205       // ######################################################
00206 
00207 
00215       template <typename T1, typename T2>
00216       struct NotEqual : OKlib::Messages::MessagesPrePost {
00217         OKLIB_MESSAGES_PRINT
00218         const T1& a, b;
00219         NotEqual(const T1& a, const T2& b) : a(a), b(b) {}
00220         void print(std::ostream& out, L<en_GB>, S<Basic>) const {
00221           l_start(out) << "a != b, where"; l_end(out);
00222           l_start(out) << "a = " << a; l_end(out);
00223           l_start(out) << "b = " << b; l_end(out);
00224         }
00225         void print(std::ostream& out, L<en_GB>, S<Full>) const {
00226           l_start(out) << "Test \"a == b\" returned false, where a is the tested value, b the expected value, and where"; l_end(out);
00227           l_start(out) << "a = " << a; l_end(out);
00228           l_start(out) << "b = " << b; l_end(out);
00229         }
00230       };
00232       template <typename T1, typename T2>
00233       inline NotEqual<T1, T2>* test_not_equal(const T1& a, const T2& b) {
00234         if (not (a == b)) return new NotEqual<T1,T2>(a,b);
00235         else return 0;
00236       }
00237 
00238     }
00239   }
00240 }
00241 
00242 #endif