1818
1919*/
2020
21+ // TODO: time extimations
22+ // TODO: personalized messages
23+ // TODO: statistics in runner closure
24+
2125#ifndef _LITTLETEST_HPP_
2226#define _LITTLETEST_HPP_
2327
2428#include < string>
2529#include < iostream>
2630#include < sstream>
31+ #include < algorithm>
32+
33+ #define WARN 0
34+ #define CHECK 1
35+ #define ASSERT 2
2736
28- #define BEGIN_TEST_ENV () int main () {
29- #define END_TEST_ENV () return 0 ; }
30- #define TEST (name ) name ## _obj
31- #define CREATE_RUNNER (suite_name, runner_name ) \
37+ #define LT_BEGIN_TEST_ENV () int main () {
38+ #define LT_END_TEST_ENV () return 0 ; }
39+ #define LT_TEST (name ) name ## _obj
40+ #define LT_CREATE_RUNNER (suite_name, runner_name ) \
3241 std::cout << " ** Initializing Runner \" " << #runner_name << " \" for suite \" " << #suite_name << " \" **" << std::endl; \
3342 test_runner<suite_name> runner_name
34- #define RUNNER (runner_name ) runner_name
35- #define SUITE (name ) struct name : public suite <name>
36- #define BEGIN_TEST (suite_name, test_name ) \
43+ #define LT_RUNNER (runner_name ) runner_name
44+ #define LT_SUITE (name ) struct name : public suite <name>
45+ #define LT_CHECKPOINT () tr->set_checkpoint (__FILE__, __LINE__)
46+ #define LT_BEGIN_TEST (suite_name, test_name ) \
3747 struct test_name : public suite_name , test<suite_name, test_name> \
3848 { \
3949 public: \
4050 static const char * name; \
4151 void operator ()(test_runner<suite_name>* tr) \
4252 {
4353
44- #define END_TEST (test_name ) \
54+ #define LT_END_TEST (test_name ) \
4555 } \
4656 }; \
4757 const char * test_name::name = #test_name; \
4858 test_name test_name ## _obj;
4959
50- #define CHECK_EQ (a, b ) \
60+ #define LT_SWITCH_MODE (mode ) \
61+ switch (mode) \
62+ { \
63+ case (WARN): \
64+ throw warn_unattended (ss.str ()); \
65+ case (CHECK): \
66+ throw check_unattended (ss.str ()); \
67+ case (ASSERT): \
68+ throw assert_unattended (ss.str ()); \
69+ }
70+
71+ #define LT_SIMPLE_OP (name, val, file, line, mode ) \
72+ if (!(val)) \
73+ { \
74+ std::stringstream ss; \
75+ ss << " (" << file << " :" << line << " ) - error in " << " \" " << name << " \" " ; \
76+ LT_SWITCH_MODE (mode) \
77+ }
78+
79+ #define LT_THROW_OP (name, operation, file, line, mode ) \
80+ bool thrown = false ; \
81+ std::stringstream ss; \
82+ try \
83+ { \
84+ operation ;\
85+ ss << " (" << file << " :" << line << " ) - error in " << " \" " << name << " \" : no exceptions thown by " << #operation; \
86+ thrown = true ; \
87+ } \
88+ catch (...) { } \
89+ if (thrown) \
90+ LT_SWITCH_MODE (mode)
91+
92+ #define LT_NOTHROW_OP (name, operation, file, line, mode ) \
5193 try \
5294 { \
53- check_eq (name, a, b, __FILE__, __LINE__); \
54- tr->add_success (); \
95+ operation ;\
5596 } \
97+ catch (...) \
98+ { \
99+ std::stringstream ss; \
100+ ss << " (" << file << " :" << line << " ) - error in " << " \" " << name << " \" : exceptions thown by " << #operation; \
101+ LT_SWITCH_MODE (mode) \
102+ }
103+
104+ #define LT_COLLEQ_OP (name, first_begin, first_end, second_begin, file, line, mode ) \
105+ if (! std::equal (first_begin, first_end, second_begin)) \
106+ { \
107+ std::stringstream ss; \
108+ ss << " (" << file << " :" << line << " ) - error in " << " \" " << name << " \" : collections are different" ; \
109+ LT_SWITCH_MODE (mode) \
110+ }
111+
112+ #define LT_COLLNEQ_OP (name, first_begin, first_end, second_begin, file, line, mode ) \
113+ if (std::equal (first_begin, first_end, second_begin)) \
114+ { \
115+ std::stringstream ss; \
116+ ss << " (" << file << " :" << line << " ) - error in " << " \" " << name << " \" : collections are equal" ; \
117+ LT_SWITCH_MODE (mode) \
118+ }
119+
120+ #define LT_OP (name, a, b, file, line, op, mode ) \
121+ if (a op b) \
122+ { \
123+ std::stringstream ss; \
124+ ss << " (" << file << " :" << line << " ) - error in " << " \" " << name << " \" : " << a << #op << b; \
125+ LT_SWITCH_MODE (mode) \
126+ }
127+
128+ #define LT_CATCH_ERRORS \
56129 catch (check_unattended& cu) \
57130 { \
58- std::cout << cu.what () << std::endl; \
131+ std::cout << " [CHECK FAILURE] " << cu.what () << std::endl; \
132+ tr->add_failure (); \
133+ } \
134+ catch (assert_unattended& au) \
135+ { \
136+ std::cout << " [ASSERT FAILURE] " << au.what () << std::endl; \
59137 tr->add_failure (); \
138+ throw au; \
139+ } \
140+ catch (warn_unattended& wu) \
141+ { \
142+ std::cout << " [WARN] " << wu.what () << std::endl; \
60143 }
61144
62- // #define CHECK_NEQ((a), (b)) check_eq(a, b);
63- // #define CHECK_GT((a), (b)) check_eq(a, b);
64- // #define CHECK_GTE((a), (b)) check_eq(a, b);
65- // #define CHECK_LT((a), (b)) check_eq(a, b);
66- // #define CHECK_LTE((a), (b)) check_eq(a, b);
145+ #define LT_ADD_SUCCESS (mode ) \
146+ if (mode) \
147+ tr->add_success ();
148+
149+ #define LT_EV (a, b, op, mode ) \
150+ try \
151+ { \
152+ LT_OP (name, a, b, __FILE__, __LINE__, op, mode); \
153+ LT_ADD_SUCCESS (mode) \
154+ } \
155+ LT_CATCH_ERRORS
156+
157+ #define LT_SIMPLE_EV (val, mode ) \
158+ try \
159+ { \
160+ LT_SIMPLE_OP (name, val, __FILE__, __LINE__, mode); \
161+ LT_ADD_SUCCESS (mode) \
162+ } \
163+ LT_CATCH_ERRORS
164+
165+ #define LT_THROW_EV (operation, mode ) \
166+ try \
167+ { \
168+ LT_THROW_OP (name, operation, __FILE__, __LINE__, mode); \
169+ LT_ADD_SUCCESS (mode) \
170+ } \
171+ LT_CATCH_ERRORS
172+
173+ #define LT_NOTHROW_EV (operation, mode ) \
174+ try \
175+ { \
176+ LT_NOTHROW_OP (name, operation, __FILE__, __LINE__, mode); \
177+ LT_ADD_SUCCESS (mode) \
178+ } \
179+ LT_CATCH_ERRORS
180+
181+ #define LT_COLLEQ_EV (first_begin, first_end, second_begin, mode ) \
182+ try \
183+ { \
184+ LT_COLLEQ_OP (name, first_begin, first_end, second_begin, __FILE__, __LINE__, mode); \
185+ LT_ADD_SUCCESS (mode) \
186+ } \
187+ LT_CATCH_ERRORS
188+
189+ #define LT_COLLNEQ_EV (first_begin, first_end, second_begin, mode ) \
190+ try \
191+ { \
192+ LT_COLLNEQ_OP (name, first_begin, first_end, second_begin, __FILE__, __LINE__, mode); \
193+ LT_ADD_SUCCESS (mode) \
194+ } \
195+ LT_CATCH_ERRORS
196+
197+ #define LT_WARN (val ) LT_SIMPLE_EV(val, WARN)
198+ #define LT_WARN_EQ (a, b ) LT_EV(a, b, !=, WARN)
199+ #define LT_WARN_NEQ (a, b ) LT_EV(a, b, ==, WARN)
200+ #define LT_WARN_GT (a, b ) LT_EV(a, b, <=, WARN)
201+ #define LT_WARN_GTE (a, b ) LT_EV(a, b, <, WARN)
202+ #define LT_WARN_LT (a, b ) LT_EV(a, b, >=, WARN)
203+ #define LT_WARN_LTE (a, b ) LT_EV(a, b, >, WARN)
204+ #define LT_WARN_THROW (operation ) LT_THROW_EV(operation, WARN)
205+ #define LT_WARN_NOTHROW (operation ) LT_NOTHROW_EV(operation, WARN)
206+ #define LT_WARN_COLLECTIONS_EQ (first_begin, first_end, second_begin ) LT_COLLEQ_EV(first_begin, first_end, second_begin, WARN)
207+ #define LT_WARN_COLLECTIONS_NEQ (first_begin, first_end, second_begin ) LT_COLLNEQ_EV(first_begin, first_end, second_begin, WARN)
208+
209+ #define LT_CHECK (val ) LT_SIMPLE_EV(val, CHECK)
210+ #define LT_CHECK_EQ (a, b ) LT_EV(a, b, !=, CHECK)
211+ #define LT_CHECK_NEQ (a, b ) LT_EV(a, b, ==, CHECK)
212+ #define LT_CHECK_GT (a, b ) LT_EV(a, b, <=, CHECK)
213+ #define LT_CHECK_GTE (a, b ) LT_EV(a, b, <, CHECK)
214+ #define LT_CHECK_LT (a, b ) LT_EV(a, b, >=, CHECK)
215+ #define LT_CHECK_LTE (a, b ) LT_EV(a, b, >, CHECK)
216+ #define LT_CHECK_THROW (operation ) LT_THROW_EV(operation, CHECK)
217+ #define LT_CHECK_NOTHROW (operation ) LT_NOTHROW_EV(operation, CHECK)
218+ #define LT_CHECK_COLLECTIONS_EQ (first_begin, first_end, second_begin ) LT_COLLEQ_EV(first_begin, first_end, second_begin, CHECK)
219+ #define LT_CHECK_COLLECTIONS_NEQ (first_begin, first_end, second_begin ) LT_COLLNEQ_EV(first_begin, first_end, second_begin, CHECK)
220+
221+ #define LT_ASSERT (val ) LT_SIMPLE_EV(val, ASSERT)
222+ #define LT_ASSERT_EQ (a, b ) LT_EV(a, b, !=, ASSERT)
223+ #define LT_ASSERT_NEQ (a, b ) LT_EV(a, b, ==, ASSERT)
224+ #define LT_ASSERT_GT (a, b ) LT_EV(a, b, <=, ASSERT)
225+ #define LT_ASSERT_GTE (a, b ) LT_EV(a, b, <, ASSERT)
226+ #define LT_ASSERT_LT (a, b ) LT_EV(a, b, >=, ASSERT)
227+ #define LT_ASSERT_LTE (a, b ) LT_EV(a, b, >, ASSERT)
228+ #define LT_ASSERT_THROW (operation ) LT_THROW_EV(operation, ASSERT)
229+ #define LT_ASSERT_NOTHROW (operation ) LT_NOTHROW_EV(operation, ASSERT)
230+ #define LT_ASSERT_COLLECTIONS_EQ (first_begin, first_end, second_begin ) LT_COLLEQ_EV(first_begin, first_end, second_begin, ASSERT)
231+ #define LT_ASSERT_COLLECTIONS_NEQ (first_begin, first_end, second_begin ) LT_COLLNEQ_EV(first_begin, first_end, second_begin, ASSERT)
232+
233+ #define LT_FAIL (message ) \
234+ std::cout << " [ASSERT FAILURE] (" << __FILE__ << " :" << __LINE__ << " ) - error in " << " \" " << name << " \" : " << message << std::endl; \
235+ tr->add_failure (); \
236+ throw assert_unattended (" " );
67237
68238struct check_unattended : public std ::exception
69239{
@@ -98,79 +268,21 @@ struct assert_unattended : public std::exception
98268 std::string message;
99269};
100270
101- template <typename T1, typename T2>
102- void check_eq (std::string name, T1 a, T2 b, const char * file, short line)
103- throw (check_unattended)
104- {
105- if (a != b)
106- {
107- std::stringstream ss;
108- ss << " (" << file << " :" << line << " ) - error in " << " \" " << name << " \" : " << a << " != " << b;
109- throw check_unattended (ss.str ());
110- }
111- }
112-
113- /*
114- template <typename T1, typename T2>
115- void check_neq(T1 a, T2 b)
116- throw(check_unattended)
117- {
118- if(a == b)
119- {
120- std::stringstream ss;
121- ss << a << "==" << b;
122- throw check_unattended(ss.str());
123- }
124- }
125-
126- template <typename T1, typename T2>
127- void check_gt(T1 a, T2 b)
128- throw(check_unattended)
129- {
130- if(a <= b)
131- {
132- std::stringstream ss;
133- ss << a << "<=" << b;
134- throw check_unattended(ss.str());
135- }
136- }
137-
138- template <typename T1, typename T2>
139- void check_gte(T1 a, T2 b)
140- throw(check_unattended)
141- {
142- if(a < b)
143- {
144- std::stringstream ss;
145- ss << a << "<" << b;
146- throw check_unattended(ss.str());
147- }
148- }
149-
150- template <typename T1, typename T2>
151- void check_lt(T1 a, T2 b)
152- throw(check_unattended)
271+ struct warn_unattended : public std ::exception
153272{
154- if(a >= b)
273+ warn_unattended (const std::string& message):
274+ message (message)
155275 {
156- std::stringstream ss;
157- ss << a << ">=" << b;
158- throw check_unattended(ss.str());
159276 }
160- }
161-
162- template <typename T1, typename T2>
163- void check_lte(T1 a, T2 b)
164- throw(check_unattended)
165- {
166- if(a > b)
277+ ~warn_unattended () throw () { }
278+ virtual const char * what () const throw()
167279 {
168- std::stringstream ss ;
169- ss << a << ">" << b;
170- throw check_unattended(ss.str());
171- }
172- }
173- */
280+ return message. c_str () ;
281+ }
282+
283+ private:
284+ std::string message;
285+ };
174286
175287template <class suite_impl >
176288class suite
@@ -213,10 +325,14 @@ class test
213325 {
214326 std::cout << " Exception during " << test_impl::name << " run" << std::endl;
215327 std::cout << e.what () << std::endl;
328+ if (tr->last_checkpoint_line != -1 )
329+ std::cout << " Last checkpoint in " << tr->last_checkpoint_file << " :" << tr->last_checkpoint_line << std::endl;
216330 }
217331 catch (...)
218332 {
219333 std::cout << " Exception during " << test_impl::name << " run" << std::endl;
334+ if (tr->last_checkpoint_line != -1 )
335+ std::cout << " Last checkpoint in " << tr->last_checkpoint_file << " :" << tr->last_checkpoint_line << std::endl;
220336 }
221337 static_cast <test_impl* >(this )->suite_tier_down ();
222338 return result;
@@ -235,7 +351,9 @@ struct test_runner
235351 test_runner () :
236352 test_counter (1 ),
237353 success_counter (0 ),
238- failures_counter (0 )
354+ failures_counter (0 ),
355+ last_checkpoint_file (" " ),
356+ last_checkpoint_line (-1 )
239357 {
240358 }
241359
@@ -273,6 +391,14 @@ struct test_runner
273391 success_counter++;
274392 }
275393
394+ void set_checkpoint (const char * file, int line)
395+ {
396+ last_checkpoint_file = file;
397+ last_checkpoint_line = line;
398+ }
399+
400+ std::string last_checkpoint_file;
401+ int last_checkpoint_line;
276402
277403 private:
278404 int test_counter;
0 commit comments