Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-19 09:25:01

0001 //
0002 // Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
0003 //
0004 // Distributed under the Boost Software License, Version 1.0. (See accompanying
0005 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0006 //
0007 // Official repository: https://github.com/boostorg/beast
0008 //
0009 
0010 #ifndef BOOST_BEAST_UNIT_TEST_REPORTER_HPP
0011 #define BOOST_BEAST_UNIT_TEST_REPORTER_HPP
0012 
0013 #include <boost/beast/_experimental/unit_test/amount.hpp>
0014 #include <boost/beast/_experimental/unit_test/recorder.hpp>
0015 #include <algorithm>
0016 #include <chrono>
0017 #include <functional>
0018 #include <iomanip>
0019 #include <iostream>
0020 #include <sstream>
0021 #include <string>
0022 #include <utility>
0023 
0024 namespace boost {
0025 namespace beast {
0026 namespace unit_test {
0027 
0028 namespace detail {
0029 
0030 /** A simple test runner that writes everything to a stream in real time.
0031     The totals are output when the object is destroyed.
0032 */
0033 template<class = void>
0034 class reporter : public runner
0035 {
0036 private:
0037     using clock_type = std::chrono::steady_clock;
0038 
0039     struct case_results
0040     {
0041         std::string name;
0042         std::size_t total = 0;
0043         std::size_t failed = 0;
0044 
0045         explicit
0046         case_results(std::string name_ = "")
0047             : name(std::move(name_))
0048         {
0049         }
0050     };
0051 
0052     struct suite_results
0053     {
0054         std::string name;
0055         std::size_t cases = 0;
0056         std::size_t total = 0;
0057         std::size_t failed = 0;
0058         typename clock_type::time_point start = clock_type::now();
0059 
0060         explicit
0061         suite_results(std::string name_ = "")
0062             : name(std::move(name_))
0063         {
0064         }
0065 
0066         void
0067         add(case_results const& r);
0068     };
0069 
0070     struct results
0071     {
0072         using run_time = std::pair<std::string,
0073             typename clock_type::duration>;
0074 
0075         enum
0076         {
0077             max_top = 10
0078         };
0079 
0080         std::size_t suites = 0;
0081         std::size_t cases = 0;
0082         std::size_t total = 0;
0083         std::size_t failed = 0;
0084         std::vector<run_time> top;
0085         typename clock_type::time_point start = clock_type::now();
0086 
0087         void
0088         add(suite_results const& r);
0089     };
0090 
0091     std::ostream& os_;
0092     results results_;
0093     suite_results suite_results_;
0094     case_results case_results_;
0095 
0096 public:
0097     reporter(reporter const&) = delete;
0098     reporter& operator=(reporter const&) = delete;
0099 
0100     ~reporter();
0101 
0102     explicit
0103     reporter(std::ostream& os = std::cout);
0104 
0105 private:
0106     static
0107     std::string
0108     fmtdur(typename clock_type::duration const& d);
0109 
0110     virtual
0111     void
0112     on_suite_begin(suite_info const& info) override;
0113 
0114     virtual
0115     void
0116     on_suite_end() override;
0117 
0118     virtual
0119     void
0120     on_case_begin(std::string const& name) override;
0121 
0122     virtual
0123     void
0124     on_case_end() override;
0125 
0126     virtual
0127     void
0128     on_pass() override;
0129 
0130     virtual
0131     void
0132     on_fail(std::string const& reason) override;
0133 
0134     virtual
0135     void
0136     on_log(std::string const& s) override;
0137 };
0138 
0139 //------------------------------------------------------------------------------
0140 
0141 template<class _>
0142 void
0143 reporter<_>::
0144 suite_results::add(case_results const& r)
0145 {
0146     ++cases;
0147     total += r.total;
0148     failed += r.failed;
0149 }
0150 
0151 template<class _>
0152 void
0153 reporter<_>::
0154 results::add(suite_results const& r)
0155 {
0156     ++suites;
0157     total += r.total;
0158     cases += r.cases;
0159     failed += r.failed;
0160     auto const elapsed = clock_type::now() - r.start;
0161     if(elapsed >= std::chrono::seconds{1})
0162     {
0163         auto const iter = std::lower_bound(top.begin(),
0164             top.end(), elapsed,
0165             [](run_time const& t1,
0166                 typename clock_type::duration const& t2)
0167             {
0168                 return t1.second > t2;
0169             });
0170         if(iter != top.end())
0171         {
0172             top.emplace(iter, r.name, elapsed);
0173             if(top.size() > max_top)
0174                 top.resize(max_top);
0175         }
0176     }
0177 }
0178 
0179 //------------------------------------------------------------------------------
0180 
0181 template<class _>
0182 reporter<_>::
0183 reporter(std::ostream& os)
0184     : os_(os)
0185 {
0186 }
0187 
0188 template<class _>
0189 reporter<_>::~reporter()
0190 {
0191     if(results_.top.size() > 0)
0192     {
0193         os_ << "Longest suite times:\n";
0194         for(auto const& i : results_.top)
0195             os_ << std::setw(8) <<
0196                 fmtdur(i.second) << " " << i.first << '\n';
0197     }
0198     auto const elapsed = clock_type::now() - results_.start;
0199     os_ <<
0200         fmtdur(elapsed) << ", " <<
0201         amount{results_.suites, "suite"} << ", " <<
0202         amount{results_.cases, "case"} << ", " <<
0203         amount{results_.total, "test"} << " total, " <<
0204         amount{results_.failed, "failure"} <<
0205         std::endl;
0206 }
0207 
0208 template<class _>
0209 std::string
0210 reporter<_>::fmtdur(typename clock_type::duration const& d)
0211 {
0212     using namespace std::chrono;
0213     auto const ms = duration_cast<milliseconds>(d);
0214     if(ms < seconds{1})
0215         return std::to_string(ms.count()) + "ms";
0216     std::stringstream ss;
0217     ss << std::fixed << std::setprecision(1) <<
0218        (ms.count()/1000.) << "s";
0219     return ss.str();
0220 }
0221 
0222 template<class _>
0223 void
0224 reporter<_>::
0225 on_suite_begin(suite_info const& info)
0226 {
0227     suite_results_ = suite_results{info.full_name()};
0228 }
0229 
0230 template<class _>
0231 void
0232 reporter<_>::on_suite_end()
0233 {
0234     results_.add(suite_results_);
0235 }
0236 
0237 template<class _>
0238 void
0239 reporter<_>::
0240 on_case_begin(std::string const& name)
0241 {
0242     case_results_ = case_results(name);
0243     os_ << suite_results_.name <<
0244         (case_results_.name.empty() ? "" :
0245             (" " + case_results_.name)) << std::endl;
0246 }
0247 
0248 template<class _>
0249 void
0250 reporter<_>::
0251 on_case_end()
0252 {
0253     suite_results_.add(case_results_);
0254 }
0255 
0256 template<class _>
0257 void
0258 reporter<_>::
0259 on_pass()
0260 {
0261     ++case_results_.total;
0262 }
0263 
0264 template<class _>
0265 void
0266 reporter<_>::
0267 on_fail(std::string const& reason)
0268 {
0269     ++case_results_.failed;
0270     ++case_results_.total;
0271     os_ <<
0272         "#" << case_results_.total << " failed" <<
0273        (reason.empty() ? "" : ": ") << reason << std::endl;
0274 }
0275 
0276 template<class _>
0277 void
0278 reporter<_>::
0279 on_log(std::string const& s)
0280 {
0281     os_ << s;
0282 }
0283 
0284 } // detail
0285 
0286 using reporter = detail::reporter<>;
0287 
0288 } // unit_test
0289 } // beast
0290 } // boost
0291 
0292 #endif