1 /*
2  * Copyright (C) 2005-2008 by Dr. Marc Boris Duerner
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * As a special exception, you may use this file as part of a free
10  * software library without restriction. Specifically, if other files
11  * instantiate templates or use macros or inline functions from this
12  * file, or you compile this file and link it with other files to
13  * produce an executable, this file does not by itself cause the
14  * resulting executable to be covered by the GNU General Public
15  * License. This exception does not however invalidate any other
16  * reasons why the executable file might be covered by the GNU Library
17  * General Public License.
18  *
19  * This library is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
22  * Lesser General Public License for more details.
23  *
24  * You should have received a copy of the GNU Lesser General Public
25  * License along with this library; if not, write to the Free Software
26  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
27  */
28 #ifndef CXXTOOLS_ASSERTION_H
29 #define CXXTOOLS_ASSERTION_H
30 
31 #include "cxxtools/sourceinfo.h"
32 #include <stdexcept>
33 #include <iostream>
34 #include <sstream>
35 
36 namespace cxxtools {
37 
38 namespace unit {
39 
40     /** @brief %Test %Assertion exception
41         @ingroup UnitTests
42 
43         Assertions are modeled as an exception type, which is thrown by Unit
44         tests when an assertion has failed. This class implements
45         std::exception and overrides std::exception::what() to return an
46         error message Besides the error message, Assertions can provide
47         information where the exception was raised in the source code through
48         a SourceInfo object. It is recommended to use the CXXTOOLS_UNIT_ASSERT
49         for easy creation from a source info object.
50 
51         @code
52             void myTest()
53             {
54                 int ten = 5 + 5;
55                 CXXTOOLS_UNIT_ASSERT(ten == 10)
56             }
57         @endcode
58     */
59     class Assertion
60     {
61         public:
62             /** @brief Construct from a message and source info.
63 
64                 Constructs a assertion exception from a message string
65                 and a source info object that describes where the
66                 assertion failed. Use the CXXTOOLS_UNIT_ASSERT macro instead
67                 of this constructor.
68 
69                 @param what Error message
70                 @param si Info where the assertion failed
71             */
72             Assertion(const std::string& what, const SourceInfo& si);
73 
74             const SourceInfo& sourceInfo() const;
75 
what()76             const char* what() const  { return _what.c_str(); }
77 
78         private:
79             SourceInfo _sourceInfo;
80             std::string _what;
81     };
82 
83     #define CXXTOOLS_UNIT_ASSERT(cond) \
84         do { \
85             if( !(cond) ) \
86                 throw cxxtools::unit::Assertion(#cond, CXXTOOLS_SOURCEINFO); \
87         } while (false)
88 
89     #define CXXTOOLS_UNIT_ASSERT_MSG(cond, what) \
90         do { \
91             if( !(cond) ) \
92             { \
93                 std::ostringstream _cxxtools_msg; \
94                 _cxxtools_msg << what; \
95                 throw cxxtools::unit::Assertion(_cxxtools_msg.str(), CXXTOOLS_SOURCEINFO); \
96             } \
97         } while (false)
98 
99     #define CXXTOOLS_UNIT_ASSERT_EQUALS(value1, value2) \
100         do { \
101             if( ! ((value1) == (value2)) ) \
102             { \
103                 std::ostringstream _cxxtools_msg; \
104                 _cxxtools_msg << "not equal:\n\tvalue1 (" #value1 ")=\n\t\t<" << value1 << ">\n\tvalue2 (" #value2 ")=\n\t\t<" << value2 << '>'; \
105                 throw cxxtools::unit::Assertion(_cxxtools_msg.str(), CXXTOOLS_SOURCEINFO); \
106             } \
107         } while (false)
108 
109     #define CXXTOOLS_UNIT_ASSERT_THROW(cond, EX) \
110         do { \
111             struct _cxxtools_ex { }; \
112             try \
113             { \
114                 cond; \
115                 throw _cxxtools_ex(); \
116             } \
117             catch(const _cxxtools_ex &) \
118             { \
119                 std::ostringstream _cxxtools_msg; \
120                 _cxxtools_msg << "exception of type " #EX " expected in " #cond; \
121                 throw cxxtools::unit::Assertion(_cxxtools_msg.str(), CXXTOOLS_SOURCEINFO); \
122             } \
123             catch(const EX &) \
124             {} \
125         } while (false)
126 
127     #define CXXTOOLS_UNIT_ASSERT_NOTHROW(cond) \
128         do { \
129             try { \
130             \
131                 cond; \
132             } \
133             catch(const std::exception& e) \
134             { \
135                 throw cxxtools::unit::Assertion( \
136                     std::string("unexpected exception of type ") + typeid(e).name() + ": " + e.what(), \
137                     CXXTOOLS_SOURCEINFO); \
138             } \
139             catch(const cxxtools::unit::Assertion&) \
140             { \
141                 throw; \
142             } \
143             catch(...) \
144             { \
145                 throw cxxtools::unit::Assertion("unexpected exception." , CXXTOOLS_SOURCEINFO); \
146             } \
147         } while (false)
148 
149     #define CXXTOOLS_UNIT_FAIL(what) \
150         do { \
151             std::ostringstream _cxxtools_msg; \
152             _cxxtools_msg << what; \
153             throw cxxtools::unit::Assertion(_cxxtools_msg.str(), CXXTOOLS_SOURCEINFO); \
154         } while (false)
155 
156 } // namespace unit
157 
158 } // namespace cxxtools
159 
160 #endif
161