]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/beast/subtree/unit_test/include/boost/beast/unit_test/reporter.hpp
update sources to v12.2.3
[ceph.git] / ceph / src / boost / libs / beast / subtree / unit_test / include / boost / beast / unit_test / reporter.hpp
1 //
2 // Copyright (c) 2016-2017 Vinnie Falco (vinnie dot falco at gmail dot com)
3 //
4 // Distributed under the Boost Software License, Version 1.0. (See accompanying
5 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 //
7 // Official repository: https://github.com/boostorg/beast
8 //
9
10 #ifndef BOOST_BEAST_UNIT_TEST_REPORTER_HPP
11 #define BOOST_BEAST_UNIT_TEST_REPORTER_HPP
12
13 #include <boost/beast/unit_test/amount.hpp>
14 #include <boost/beast/unit_test/recorder.hpp>
15 #include <algorithm>
16 #include <chrono>
17 #include <functional>
18 #include <iomanip>
19 #include <iostream>
20 #include <sstream>
21 #include <string>
22 #include <utility>
23
24 namespace boost {
25 namespace beast {
26 namespace unit_test {
27
28 namespace detail {
29
30 /** A simple test runner that writes everything to a stream in real time.
31 The totals are output when the object is destroyed.
32 */
33 template<class = void>
34 class reporter : public runner
35 {
36 private:
37 using clock_type = std::chrono::steady_clock;
38
39 struct case_results
40 {
41 std::string name;
42 std::size_t total = 0;
43 std::size_t failed = 0;
44
45 explicit
46 case_results(std::string name_ = "")
47 : name(std::move(name_))
48 {
49 }
50 };
51
52 struct suite_results
53 {
54 std::string name;
55 std::size_t cases = 0;
56 std::size_t total = 0;
57 std::size_t failed = 0;
58 typename clock_type::time_point start = clock_type::now();
59
60 explicit
61 suite_results(std::string name_ = "")
62 : name(std::move(name_))
63 {
64 }
65
66 void
67 add(case_results const& r);
68 };
69
70 struct results
71 {
72 using run_time = std::pair<std::string,
73 typename clock_type::duration>;
74
75 enum
76 {
77 max_top = 10
78 };
79
80 std::size_t suites = 0;
81 std::size_t cases = 0;
82 std::size_t total = 0;
83 std::size_t failed = 0;
84 std::vector<run_time> top;
85 typename clock_type::time_point start = clock_type::now();
86
87 void
88 add(suite_results const& r);
89 };
90
91 std::ostream& os_;
92 results results_;
93 suite_results suite_results_;
94 case_results case_results_;
95
96 public:
97 reporter(reporter const&) = delete;
98 reporter& operator=(reporter const&) = delete;
99
100 ~reporter();
101
102 explicit
103 reporter(std::ostream& os = std::cout);
104
105 private:
106 static
107 std::string
108 fmtdur(typename clock_type::duration const& d);
109
110 virtual
111 void
112 on_suite_begin(suite_info const& info) override;
113
114 virtual
115 void
116 on_suite_end() override;
117
118 virtual
119 void
120 on_case_begin(std::string const& name) override;
121
122 virtual
123 void
124 on_case_end() override;
125
126 virtual
127 void
128 on_pass() override;
129
130 virtual
131 void
132 on_fail(std::string const& reason) override;
133
134 virtual
135 void
136 on_log(std::string const& s) override;
137 };
138
139 //------------------------------------------------------------------------------
140
141 template<class _>
142 void
143 reporter<_>::
144 suite_results::add(case_results const& r)
145 {
146 ++cases;
147 total += r.total;
148 failed += r.failed;
149 }
150
151 template<class _>
152 void
153 reporter<_>::
154 results::add(suite_results const& r)
155 {
156 ++suites;
157 total += r.total;
158 cases += r.cases;
159 failed += r.failed;
160 auto const elapsed = clock_type::now() - r.start;
161 if(elapsed >= std::chrono::seconds{1})
162 {
163 auto const iter = std::lower_bound(top.begin(),
164 top.end(), elapsed,
165 [](run_time const& t1,
166 typename clock_type::duration const& t2)
167 {
168 return t1.second > t2;
169 });
170 if(iter != top.end())
171 {
172 top.emplace(iter, r.name, elapsed);
173 if(top.size() > max_top)
174 top.resize(max_top);
175 }
176 }
177 }
178
179 //------------------------------------------------------------------------------
180
181 template<class _>
182 reporter<_>::
183 reporter(std::ostream& os)
184 : os_(os)
185 {
186 }
187
188 template<class _>
189 reporter<_>::~reporter()
190 {
191 if(results_.top.size() > 0)
192 {
193 os_ << "Longest suite times:\n";
194 for(auto const& i : results_.top)
195 os_ << std::setw(8) <<
196 fmtdur(i.second) << " " << i.first << '\n';
197 }
198 auto const elapsed = clock_type::now() - results_.start;
199 os_ <<
200 fmtdur(elapsed) << ", " <<
201 amount{results_.suites, "suite"} << ", " <<
202 amount{results_.cases, "case"} << ", " <<
203 amount{results_.total, "test"} << " total, " <<
204 amount{results_.failed, "failure"} <<
205 std::endl;
206 }
207
208 template<class _>
209 std::string
210 reporter<_>::fmtdur(typename clock_type::duration const& d)
211 {
212 using namespace std::chrono;
213 auto const ms = duration_cast<milliseconds>(d);
214 if(ms < seconds{1})
215 return std::to_string(ms.count()) + "ms";
216 std::stringstream ss;
217 ss << std::fixed << std::setprecision(1) <<
218 (ms.count()/1000.) << "s";
219 return ss.str();
220 }
221
222 template<class _>
223 void
224 reporter<_>::
225 on_suite_begin(suite_info const& info)
226 {
227 suite_results_ = suite_results{info.full_name()};
228 }
229
230 template<class _>
231 void
232 reporter<_>::on_suite_end()
233 {
234 results_.add(suite_results_);
235 }
236
237 template<class _>
238 void
239 reporter<_>::
240 on_case_begin(std::string const& name)
241 {
242 case_results_ = case_results(name);
243 os_ << suite_results_.name <<
244 (case_results_.name.empty() ? "" :
245 (" " + case_results_.name)) << std::endl;
246 }
247
248 template<class _>
249 void
250 reporter<_>::
251 on_case_end()
252 {
253 suite_results_.add(case_results_);
254 }
255
256 template<class _>
257 void
258 reporter<_>::
259 on_pass()
260 {
261 ++case_results_.total;
262 }
263
264 template<class _>
265 void
266 reporter<_>::
267 on_fail(std::string const& reason)
268 {
269 ++case_results_.failed;
270 ++case_results_.total;
271 os_ <<
272 "#" << case_results_.total << " failed" <<
273 (reason.empty() ? "" : ": ") << reason << std::endl;
274 }
275
276 template<class _>
277 void
278 reporter<_>::
279 on_log(std::string const& s)
280 {
281 os_ << s;
282 }
283
284 } // detail
285
286 using reporter = detail::reporter<>;
287
288 } // unit_test
289 } // beast
290 } // boost
291
292 #endif