xrpld
Loading...
Searching...
No Matches
reporter.h
1// Distributed under the Boost Software License, Version 1.0. (See accompanying
2// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
3//
4
5#pragma once
6
7#include <xrpl/beast/unit_test/amount.h>
8#include <xrpl/beast/unit_test/runner.h>
9#include <xrpl/beast/unit_test/suite_info.h>
10
11#include <boost/optional.hpp>
12
13#include <algorithm>
14#include <chrono>
15#include <cstddef>
16#include <iomanip>
17#include <iostream>
18#include <sstream>
19#include <string>
20#include <utility>
21#include <vector>
22
23namespace beast::unit_test {
24
25namespace detail {
26
31template <class = void>
32class Reporter : public Runner
33{
34private:
36
38 {
42
43 explicit CaseResults(std::string name = "") : name(std::move(name))
44 {
45 }
46 };
47
49 {
54 clock_type::time_point start = clock_type::now();
55
56 explicit SuiteResults(std::string name = "") : name(std::move(name))
57 {
58 }
59
60 void
61 add(CaseResults const& r);
62 };
63
64 struct Results
65 {
67
68 static constexpr auto kMaxTop = 10;
69
75 clock_type::time_point start = clock_type::now();
76
77 void
78 add(SuiteResults const& r);
79 };
80
85
86public:
87 Reporter(Reporter const&) = delete;
89 operator=(Reporter const&) = delete;
90
91 ~Reporter() override;
92
93 explicit Reporter(std::ostream& os = std::cout);
94
95private:
96 static std::string
97 fmtdur(clock_type::duration const& d);
98
99 void
100 onSuiteBegin(SuiteInfo const& info) override;
101
102 void
103 onSuiteEnd() override;
104
105 void
106 onCaseBegin(std::string const& name) override;
107
108 void
109 onCaseEnd() override;
110
111 void
112 onPass() override;
113
114 void
115 onFail(std::string const& reason) override;
116
117 void
118 onLog(std::string const& s) override;
119};
120
121//------------------------------------------------------------------------------
122
123template <class Unused>
124void
126{
127 ++cases;
128 total += r.total;
129 failed += r.failed;
130}
131
132template <class Unused>
133void
135{
136 ++suites;
137 total += r.total;
138 cases += r.cases;
139 failed += r.failed;
140 auto const elapsed = clock_type::now() - r.start;
141 if (elapsed >= std::chrono::seconds{1})
142 {
143 auto const iter = std::lower_bound(
144 top.begin(),
145 top.end(),
146 elapsed,
147 [](run_time const& t1, clock_type::duration const& t2) { return t1.second > t2; });
148 if (iter != top.end())
149 {
150 if (top.size() == kMaxTop)
151 top.resize(top.size() - 1);
152 top.emplace(iter, r.name, elapsed);
153 }
154 else if (top.size() < kMaxTop)
155 {
156 top.emplace_back(r.name, elapsed);
157 }
158 }
159}
160
161//------------------------------------------------------------------------------
162
163template <class Unused>
167
168template <class Unused>
170{
171 if (results_.top.size() > 0)
172 {
173 os_ << "Longest suite times:\n";
174 for (auto const& i : results_.top)
175 os_ << std::setw(8) << fmtdur(i.second) << " " << i.first << '\n';
176 }
177 auto const elapsed = clock_type::now() - results_.start;
178 os_ << fmtdur(elapsed) << ", " << Amount{results_.suites, "suite"} << ", "
179 << Amount{results_.cases, "case"} << ", " << Amount{results_.total, "test"} << " total, "
180 << Amount{results_.failed, "failure"} << std::endl;
181}
182
183template <class Unused>
185Reporter<Unused>::fmtdur(clock_type::duration const& d)
186{
187 using namespace std::chrono;
188 auto const ms = duration_cast<milliseconds>(d);
189 if (ms < seconds{1})
190 return std::to_string(ms.count()) + "ms";
192 ss << std::fixed << std::setprecision(1) << (ms.count() / 1000.) << "s";
193 return ss.str();
194}
195
196template <class Unused>
197void
202
203template <class Unused>
204void
209
210template <class Unused>
211void
213{
215 os_ << suiteResults_.name << (caseResults_.name.empty() ? "" : (" " + caseResults_.name))
216 << std::endl;
217}
218
219template <class Unused>
220void
225
226template <class Unused>
227void
229{
230 ++caseResults_.total;
231}
232
233template <class Unused>
234void
236{
237 ++caseResults_.failed;
238 ++caseResults_.total;
239 os_ << "#" << caseResults_.total << " failed" << (reason.empty() ? "" : ": ") << reason
240 << std::endl;
241}
242
243template <class Unused>
244void
246{
247 os_ << s;
248}
249
250} // namespace detail
251
253
254} // namespace beast::unit_test
Utility for producing nicely composed output of amounts with units.
Associates a unit test type with metadata.
Definition suite_info.h:20
std::string fullName() const
Return the canonical suite name as a string.
Definition suite_info.h:78
A simple test runner that writes everything to a stream in real time.
Definition reporter.h:33
void onSuiteBegin(SuiteInfo const &info) override
Called when a new suite starts.
Definition reporter.h:198
void onFail(std::string const &reason) override
Called for each failing condition.
Definition reporter.h:235
Reporter(Reporter const &)=delete
void onCaseEnd() override
Called when a new case ends.
Definition reporter.h:221
static std::string fmtdur(clock_type::duration const &d)
Definition reporter.h:185
void onSuiteEnd() override
Called when a suite ends.
Definition reporter.h:205
void onPass() override
Called for each passing condition.
Definition reporter.h:228
Reporter & operator=(Reporter const &)=delete
void onCaseBegin(std::string const &name) override
Called when a new case starts.
Definition reporter.h:212
std::chrono::steady_clock clock_type
Definition reporter.h:35
void onLog(std::string const &s) override
Called when a test logs output.
Definition reporter.h:245
T duration_cast(T... args)
T empty(T... args)
T endl(T... args)
T fixed(T... args)
T lower_bound(T... args)
detail::Reporter<> reporter
Definition reporter.h:252
STL namespace.
T setprecision(T... args)
T setw(T... args)
T str(T... args)
void add(SuiteResults const &r)
Definition reporter.h:134
std::pair< std::string, clock_type::duration > run_time
Definition reporter.h:66
T to_string(T... args)