tut logo

tut_assert.hpp Source File


tut_assert.hpp
1 #ifndef TUT_ASSERT_H_GUARD
2 #define TUT_ASSERT_H_GUARD
3 #include <tut/tut_config.hpp>
4 
5 #include <limits>
6 #include <iomanip>
7 #include <iterator>
8 #include <cassert>
9 #include <cmath>
10 
11 #if defined(TUT_USE_POSIX)
12 #include <errno.h>
13 #include <cstring>
14 #endif
15 
16 #include "tut_exception.hpp"
17 
18 namespace tut
19 {
20 
21  namespace detail
22  {
23  template<typename M>
24  std::ostringstream &msg_prefix(std::ostringstream &str, const M &msg)
25  {
26  std::ostringstream ss;
27  ss << msg;
28 
29  if(!ss.str().empty())
30  {
31  str << msg << ": ";
32  }
33 
34  return str;
35  }
36  }
37 
38 
39 namespace
40 {
41 
46 void ensure(bool cond)
47 {
48  if (!cond)
49  {
50  // TODO: default ctor?
51  throw failure("");
52  }
53 }
54 
59 void ensure_not(bool cond)
60 {
61  ensure(!cond);
62 }
63 
68 template <typename M>
69 void ensure(const M& msg, bool cond)
70 {
71  if (!cond)
72  {
73  throw failure(msg);
74  }
75 }
76 
81 template <typename M>
82 void ensure_not(const M& msg, bool cond)
83 {
84  ensure(msg, !cond);
85 }
86 
94 template <typename M, typename LHS, typename RHS>
95 void ensure_equals(const M& msg, const LHS& actual, const RHS& expected)
96 {
97  if (expected != actual)
98  {
99  std::ostringstream ss;
100  detail::msg_prefix(ss,msg)
101  << "expected `"
102  << expected
103  << "` actual `"
104  << actual
105  << "`";
106  throw failure(ss.str());
107  }
108 }
109 
117 template <typename M, typename LHS, typename RHS>
118 void ensure_equals(const M& msg, const LHS * const actual, const RHS * const expected)
119 {
120  if (expected != actual)
121  {
122  std::ostringstream ss;
123  detail::msg_prefix(ss,msg)
124  << "expected `"
125  << (void*)expected
126  << "` actual `"
127  << (void*)actual
128  << "`";
129  throw failure(ss.str());
130  }
131 }
132 
133 template<typename M>
134 void ensure_equals(const M& msg, const double& actual, const double& expected, const double& epsilon)
135 {
136  const double diff = actual - expected;
137 
138  if ( (actual != expected) && !((diff <= epsilon) && (diff >= -epsilon )) )
139  {
140  std::ostringstream ss;
141  detail::msg_prefix(ss,msg)
142  << std::scientific
143  << std::showpoint
144  << std::setprecision(16)
145  << "expected `" << expected
146  << "` actual `" << actual
147  << "` with precision `" << epsilon << "`";
148  throw failure(ss.str());
149  }
150 }
151 
152 template<typename M>
153 void ensure_equals(const M& msg, const double& actual, const double& expected)
154 {
155  ensure_equals(msg, actual, expected, std::numeric_limits<double>::epsilon());
156 }
157 
158 template <typename LHS, typename RHS>
159 void ensure_equals(const LHS& actual, const RHS& expected)
160 {
161  ensure_equals("Values are not equal", actual, expected);
162 }
163 
164 
165 template<typename LhsIterator, typename RhsIterator>
166 void ensure_equals(const std::string &msg,
167  const LhsIterator &lhs_begin, const LhsIterator &lhs_end,
168  const RhsIterator &rhs_begin, const RhsIterator &rhs_end)
169 {
170  typename std::iterator_traits<LhsIterator>::difference_type lhs_size = std::distance(lhs_begin, lhs_end);
171  typename std::iterator_traits<RhsIterator>::difference_type rhs_size = std::distance(rhs_begin, rhs_end);
172 
173  if(lhs_size < rhs_size)
174  {
175  ensure_equals(msg + ": range is too short", lhs_size, rhs_size);
176  }
177 
178  if(lhs_size > rhs_size)
179  {
180  ensure_equals(msg + ": range is too long", lhs_size, rhs_size);
181  }
182 
183  assert(lhs_size == rhs_size);
184 
185  LhsIterator lhs_i = lhs_begin;
186  RhsIterator rhs_i = rhs_begin;
187  while( (lhs_i != lhs_end) && (rhs_i != rhs_end) )
188  {
189  if(*lhs_i != *rhs_i)
190  {
191  std::ostringstream ss;
192  detail::msg_prefix(ss,msg)
193  << "expected `" << *rhs_i
194  << "` actual `" << *lhs_i
195  << "` at offset " << std::distance(lhs_begin, lhs_i);
196  throw failure(ss.str());
197  }
198 
199  lhs_i++;
200  rhs_i++;
201  }
202 
203  assert(lhs_i == lhs_end);
204  assert(rhs_i == rhs_end);
205 }
206 
207 template<typename LhsIterator, typename RhsIterator>
208 void ensure_equals(const LhsIterator &lhs_begin, const LhsIterator &lhs_end,
209  const RhsIterator &rhs_begin, const RhsIterator &rhs_end)
210 {
211  ensure_equals("Ranges are not equal", lhs_begin, lhs_end, rhs_begin, rhs_end);
212 }
213 
214 template<typename LhsType, typename RhsType>
215 void ensure_equals(const LhsType *lhs_begin, const LhsType *lhs_end,
216  const RhsType *rhs_begin, const RhsType *rhs_end)
217 {
218  ensure_equals("Ranges are not equal", lhs_begin, lhs_end, rhs_begin, rhs_end);
219 }
220 
232 template <typename M, class T>
233 void ensure_distance(const M& msg, const T& actual, const T& expected, const T& distance)
234 {
235  if (expected-distance >= actual || expected+distance <= actual)
236  {
237  std::ostringstream ss;
238  detail::msg_prefix(ss,msg)
239  << " expected `"
240  << expected-distance
241  << "` - `"
242  << expected+distance
243  << "` actual `"
244  << actual
245  << "`";
246  throw failure(ss.str());
247  }
248 }
249 
250 template <class T>
251 void ensure_distance(const T& actual, const T& expected, const T& distance)
252 {
253  ensure_distance<>("Distance is wrong", actual, expected, distance);
254 }
255 
256 template<typename M>
257 void ensure_errno(const M& msg, bool cond)
258 {
259  if(!cond)
260  {
261 #if defined(TUT_USE_POSIX)
262  char e[512];
263  std::ostringstream ss;
264  detail::msg_prefix(ss,msg)
265  << strerror_r(errno, e, sizeof(e));
266  throw failure(ss.str());
267 #else
268  throw failure(msg);
269 #endif
270  }
271 }
272 
276 void fail(const char* msg = "")
277 {
278  throw failure(msg);
279 }
280 
281 template<typename M>
282 void fail(const M& msg)
283 {
284  throw failure(msg);
285 }
286 
290 void skip(const char* msg = "")
291 {
292  throw skipped(msg);
293 }
294 
295 template<typename M>
296 void skip(const M& msg)
297 {
298  throw skipped(msg);
299 }
300 
301 } // end of namespace
302 
303 }
304 
305 #endif
306 

All Rights Reserved. Generated on Wed Dec 18 2013 11:19:52 for TUT by doxygen 1.8.5