]> git.stg.codes - stg.git/blob - tests/tut/tut_console_reporter.hpp
Merge branch 'master' into full-month-stats
[stg.git] / tests / tut / tut_console_reporter.hpp
1 #ifndef TUT_CONSOLE_REPORTER
2 #define TUT_CONSOLE_REPORTER
3
4 #include <tut/tut.hpp>
5 #include <cassert>
6
7 /**
8  * Template Unit Tests Framework for C++.
9  * http://tut.dozen.ru
10  *
11  * @author Vladimir Dyuzhev, Vladimir.Dyuzhev@gmail.com
12  */
13 namespace
14 {
15
16 std::ostream& operator<<(std::ostream& os, const tut::test_result& tr)
17 {
18     switch(tr.result)
19     {
20     case tut::test_result::ok:
21         os << '.';
22         break;
23     case tut::test_result::fail:
24         os << '[' << tr.test << "=F]";
25         break;
26     case tut::test_result::ex_ctor:
27         os << '[' << tr.test << "=C]";
28         break;
29     case tut::test_result::ex:
30         os << '[' << tr.test << "=X]";
31         break;
32     case tut::test_result::warn:
33         os << '[' << tr.test << "=W]";
34         break;
35     case tut::test_result::term:
36         os << '[' << tr.test << "=T]";
37         break;
38     case tut::test_result::rethrown:
39         os << '[' << tr.test << "=P]";
40         break;
41     case tut::test_result::dummy:
42         assert(!"Should never be called");
43     }
44
45     return os;
46 }
47
48 } // end of namespace
49
50 namespace tut
51 {
52
53 /**
54  * Default TUT callback handler.
55  */
56 class console_reporter : public tut::callback
57 {
58     std::string current_group;
59     typedef std::vector<tut::test_result> not_passed_list;
60     not_passed_list not_passed;
61     std::ostream& os;
62
63 public:
64
65     int ok_count;
66     int exceptions_count;
67     int failures_count;
68     int terminations_count;
69     int warnings_count;
70
71     console_reporter()
72         : os(std::cout)
73     {
74         init();
75     }
76
77     console_reporter(std::ostream& out)
78         : os(out)
79     {
80         init();
81     }
82
83     void run_started()
84     {
85         init();
86     }
87
88     void test_completed(const tut::test_result& tr)
89     {
90         if (tr.group != current_group)
91         {
92             os << std::endl << tr.group << ": " << std::flush;
93             current_group = tr.group;
94         }
95
96         os << tr << std::flush;
97
98         // update global statistics
99         switch (tr.result) {
100             case test_result::ok:
101                 ok_count++;
102                 break;
103             case test_result::fail:
104             case test_result::rethrown:
105                 failures_count++;
106                 break;
107             case test_result::ex:
108             case test_result::ex_ctor:
109                 exceptions_count++;
110                 break;
111             case test_result::warn:
112                 warnings_count++;
113                 break;
114             case test_result::term:
115                 terminations_count++;
116                 break;
117             case tut::test_result::dummy:
118                 assert(!"Should never be called");
119         } // switch
120
121         if (tr.result != tut::test_result::ok)
122         {
123             not_passed.push_back(tr);
124         }
125     }
126
127     void run_completed()
128     {
129         os << std::endl;
130
131         if (not_passed.size() > 0)
132         {
133             not_passed_list::const_iterator i = not_passed.begin();
134             while (i != not_passed.end())
135             {
136                 tut::test_result tr = *i;
137
138                 os << std::endl;
139
140                 os << "---> " << "group: " << tr.group
141                 << ", test: test<" << tr.test << ">"
142                 << (!tr.name.empty() ? (std::string(" : ") + tr.name) : std::string())
143                 << std::endl;
144
145 #if defined(TUT_USE_POSIX)
146                 if(tr.pid != getpid())
147                 {
148                     os << "     child pid: " << tr.pid << std::endl;
149                 }
150 #endif
151                 os << "     problem: ";
152                 switch(tr.result)
153                 {
154                 case test_result::rethrown:
155                     os << "assertion failed in child" << std::endl;
156                     break;
157                 case test_result::fail:
158                     os << "assertion failed" << std::endl;
159                     break;
160                 case test_result::ex:
161                 case test_result::ex_ctor:
162                     os << "unexpected exception" << std::endl;
163                     if( tr.exception_typeid != "" )
164                     {
165                         os << "     exception typeid: "
166                         << tr.exception_typeid << std::endl;
167                     }
168                     break;
169                 case test_result::term:
170                     os << "would be terminated" << std::endl;
171                     break;
172                 case test_result::warn:
173                     os << "test passed, but cleanup code (destructor) raised"
174                         " an exception" << std::endl;
175                     break;
176                 default:
177                     break;
178                 }
179
180                 if (!tr.message.empty())
181                 {
182                     if (tr.result == test_result::fail)
183                     {
184                         os << "     failed assertion: \"" << tr.message << "\""
185                             << std::endl;
186                     }
187                     else
188                     {
189                         os << "     message: \"" << tr.message << "\""
190                             << std::endl;
191                     }
192                 }
193
194                 ++i;
195             }
196         }
197
198         os << std::endl;
199
200         os << "tests summary:";
201         if (terminations_count > 0)
202         {
203             os << " terminations:" << terminations_count;
204         }
205         if (exceptions_count > 0)
206         {
207             os << " exceptions:" << exceptions_count;
208         }
209         if (failures_count > 0)
210         {
211             os << " failures:" << failures_count;
212         }
213         if (warnings_count > 0)
214         {
215             os << " warnings:" << warnings_count;
216         }
217         os << " ok:" << ok_count;
218         os << std::endl;
219     }
220
221     bool all_ok() const
222     {
223         return not_passed.empty();
224     }
225
226 private:
227
228     void init()
229     {
230         ok_count = 0;
231         exceptions_count = 0;
232         failures_count = 0;
233         terminations_count = 0;
234         warnings_count = 0;
235         not_passed.clear();
236     }
237 };
238
239 }
240
241 #endif