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