| #ifndef __HAYAI_CONSOLEOUTPUTTER |
| #define __HAYAI_CONSOLEOUTPUTTER |
| #include "hayai_outputter.hpp" |
| #include "hayai_console.hpp" |
| |
| |
| namespace hayai |
| { |
| /// Console outputter. |
| |
| /// Prints the result to standard output. |
| class ConsoleOutputter |
| : public Outputter |
| { |
| public: |
| /// Initialize console outputter. |
| |
| /// @param stream Output stream. Must exist for the entire duration of |
| /// the outputter's use. |
| ConsoleOutputter(std::ostream& stream = std::cout) |
| : _stream(stream) |
| { |
| |
| } |
| |
| |
| virtual void Begin(const std::size_t& enabledCount, |
| const std::size_t& disabledCount) |
| { |
| _stream << std::fixed; |
| _stream << Console::TextGreen << "[==========]" |
| << Console::TextDefault << " Running " |
| << enabledCount |
| << (enabledCount == 1 ? " benchmark." : " benchmarks"); |
| |
| if (disabledCount) |
| _stream << ", skipping " |
| << disabledCount |
| << (disabledCount == 1 ? |
| " benchmark." : |
| " benchmarks"); |
| else |
| _stream << "."; |
| |
| _stream << std::endl; |
| } |
| |
| |
| virtual void End(const std::size_t& executedCount, |
| const std::size_t& disabledCount) |
| { |
| _stream << Console::TextGreen << "[==========]" |
| << Console::TextDefault << " Ran " << executedCount |
| << (executedCount == 1 ? |
| " benchmark." : |
| " benchmarks"); |
| |
| if (disabledCount) |
| _stream << ", skipped " |
| << disabledCount |
| << (disabledCount == 1 ? |
| " benchmark." : |
| " benchmarks"); |
| else |
| _stream << "."; |
| |
| _stream << std::endl; |
| } |
| |
| |
| inline void BeginOrSkipTest(const std::string& fixtureName, |
| const std::string& testName, |
| const TestParametersDescriptor& parameters, |
| const std::size_t& runsCount, |
| const std::size_t& iterationsCount, |
| const bool skip) |
| { |
| if (skip) |
| _stream << Console::TextCyan << "[ DISABLED ]"; |
| else |
| _stream << Console::TextGreen << "[ RUN ]"; |
| |
| _stream << Console::TextYellow << " "; |
| WriteTestNameToStream(_stream, fixtureName, testName, parameters); |
| _stream << Console::TextDefault |
| << " (" << runsCount |
| << (runsCount == 1 ? " run, " : " runs, ") |
| << iterationsCount |
| << (iterationsCount == 1 ? |
| " iteration per run)" : |
| " iterations per run)") |
| << std::endl; |
| } |
| |
| |
| virtual void BeginTest(const std::string& fixtureName, |
| const std::string& testName, |
| const TestParametersDescriptor& parameters, |
| const std::size_t& runsCount, |
| const std::size_t& iterationsCount) |
| { |
| BeginOrSkipTest(fixtureName, |
| testName, |
| parameters, |
| runsCount, |
| iterationsCount, |
| false); |
| } |
| |
| |
| virtual void SkipDisabledTest( |
| const std::string& fixtureName, |
| const std::string& testName, |
| const TestParametersDescriptor& parameters, |
| const std::size_t& runsCount, |
| const std::size_t& iterationsCount |
| ) |
| { |
| BeginOrSkipTest(fixtureName, |
| testName, |
| parameters, |
| runsCount, |
| iterationsCount, |
| true); |
| } |
| |
| |
| virtual void EndTest(const std::string& fixtureName, |
| const std::string& testName, |
| const TestParametersDescriptor& parameters, |
| const TestResult& result) |
| { |
| #define PAD(x) _stream << std::setw(34) << x << std::endl; |
| #define PAD_DEVIATION(description, \ |
| deviated, \ |
| average, \ |
| unit) \ |
| { \ |
| double _d_ = \ |
| double(deviated) - double(average); \ |
| \ |
| PAD(description << \ |
| deviated << " " << unit << " (" << \ |
| (deviated < average ? \ |
| Console::TextRed : \ |
| Console::TextGreen) << \ |
| (deviated > average ? "+" : "") << \ |
| _d_ << " " << unit << " / " << \ |
| (deviated > average ? "+" : "") << \ |
| (_d_ * 100.0 / average) << " %" << \ |
| Console::TextDefault << ")"); \ |
| } |
| #define PAD_DEVIATION_INVERSE(description, \ |
| deviated, \ |
| average, \ |
| unit) \ |
| { \ |
| double _d_ = \ |
| double(deviated) - double(average); \ |
| \ |
| PAD(description << \ |
| deviated << " " << unit << " (" << \ |
| (deviated > average ? \ |
| Console::TextRed : \ |
| Console::TextGreen) << \ |
| (deviated > average ? "+" : "") << \ |
| _d_ << " " << unit << " / " << \ |
| (deviated > average ? "+" : "") << \ |
| (_d_ * 100.0 / average) << " %" << \ |
| Console::TextDefault << ")"); \ |
| } |
| |
| _stream << Console::TextGreen << "[ DONE ]" |
| << Console::TextYellow << " "; |
| WriteTestNameToStream(_stream, fixtureName, testName, parameters); |
| _stream << Console::TextDefault << " (" |
| << std::setprecision(6) |
| << (result.TimeTotal() / 1000000.0) << " ms)" |
| << std::endl; |
| |
| _stream << Console::TextBlue << "[ RUNS ] " |
| << Console::TextDefault |
| << " Average time: " |
| << std::setprecision(3) |
| << result.RunTimeAverage() / 1000.0 << " us " |
| << "(" << Console::TextBlue << "~" |
| << result.RunTimeStdDev() / 1000.0 << " us" |
| << Console::TextDefault << ")" |
| << std::endl; |
| |
| PAD_DEVIATION_INVERSE("Fastest time: ", |
| (result.RunTimeMinimum() / 1000.0), |
| (result.RunTimeAverage() / 1000.0), |
| "us"); |
| PAD_DEVIATION_INVERSE("Slowest time: ", |
| (result.RunTimeMaximum() / 1000.0), |
| (result.RunTimeAverage() / 1000.0), |
| "us"); |
| PAD("Median time: " << |
| result.RunTimeMedian() / 1000.0 << " us (" << |
| Console::TextCyan << "1st quartile: " << |
| result.RunTimeQuartile1() / 1000.0 << " us | 3rd quartile: " << |
| result.RunTimeQuartile3() / 1000.0 << " us" << |
| Console::TextDefault << ")"); |
| |
| _stream << std::setprecision(5); |
| |
| PAD(""); |
| PAD("Average performance: " << |
| result.RunsPerSecondAverage() << " runs/s"); |
| PAD_DEVIATION("Best performance: ", |
| result.RunsPerSecondMaximum(), |
| result.RunsPerSecondAverage(), |
| "runs/s"); |
| PAD_DEVIATION("Worst performance: ", |
| result.RunsPerSecondMinimum(), |
| result.RunsPerSecondAverage(), |
| "runs/s"); |
| PAD("Median performance: " << |
| result.RunsPerSecondMedian() << " runs/s (" << |
| Console::TextCyan << "1st quartile: " << |
| result.RunsPerSecondQuartile1() << " | 3rd quartile: " << |
| result.RunsPerSecondQuartile3() << |
| Console::TextDefault << ")"); |
| |
| PAD(""); |
| _stream << Console::TextBlue << "[ITERATIONS] " |
| << Console::TextDefault |
| << std::setprecision(3) |
| << " Average time: " |
| << result.IterationTimeAverage() / 1000.0 << " us " |
| << "(" << Console::TextBlue << "~" |
| << result.IterationTimeStdDev() / 1000.0 << " us" |
| << Console::TextDefault << ")" |
| << std::endl; |
| |
| PAD_DEVIATION_INVERSE("Fastest time: ", |
| (result.IterationTimeMinimum() / 1000.0), |
| (result.IterationTimeAverage() / 1000.0), |
| "us"); |
| PAD_DEVIATION_INVERSE("Slowest time: ", |
| (result.IterationTimeMaximum() / 1000.0), |
| (result.IterationTimeAverage() / 1000.0), |
| "us"); |
| PAD("Median time: " << |
| result.IterationTimeMedian() / 1000.0 << " us (" << |
| Console::TextCyan << "1st quartile: " << |
| result.IterationTimeQuartile1() / 1000.0 << |
| " us | 3rd quartile: " << |
| result.IterationTimeQuartile3() / 1000.0 << " us" << |
| Console::TextDefault << ")"); |
| |
| _stream << std::setprecision(5); |
| |
| PAD(""); |
| PAD("Average performance: " << |
| result.IterationsPerSecondAverage() << |
| " iterations/s"); |
| PAD_DEVIATION("Best performance: ", |
| (result.IterationsPerSecondMaximum()), |
| (result.IterationsPerSecondAverage()), |
| "iterations/s"); |
| PAD_DEVIATION("Worst performance: ", |
| (result.IterationsPerSecondMinimum()), |
| (result.IterationsPerSecondAverage()), |
| "iterations/s"); |
| PAD("Median performance: " << |
| result.IterationsPerSecondMedian() << " iterations/s (" << |
| Console::TextCyan << "1st quartile: " << |
| result.IterationsPerSecondQuartile1() << |
| " | 3rd quartile: " << |
| result.IterationsPerSecondQuartile3() << |
| Console::TextDefault << ")"); |
| |
| #undef PAD_DEVIATION_INVERSE |
| #undef PAD_DEVIATION |
| #undef PAD |
| } |
| |
| |
| std::ostream& _stream; |
| }; |
| } |
| #endif |