From a0b10b4c505f4cab75cb8e1ecd4cd7c23d8beef5 Mon Sep 17 00:00:00 2001 From: Henry Fredrick Schreiner Date: Wed, 22 Mar 2017 10:40:00 -0400 Subject: [PATCH] Adding timer --- CHANGELOG.md | 1 + include/CLI/Timer.hpp | 74 +++++++++++++++++++++++++++++++++++++++++++ tests/CMakeLists.txt | 12 +++++++ tests/TimerTest.cpp | 53 +++++++++++++++++++++++++++++++ 4 files changed, 140 insertions(+) create mode 100644 include/CLI/Timer.hpp create mode 100644 tests/TimerTest.cpp diff --git a/CHANGELOG.md b/CHANGELOG.md index df3f902a..beb1c553 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ * Lots of small bugfixes related to adding tests to increase coverage * Error handling now uses scoped enum in errors * Reparsing rules changed a little to accommodate Ini files. Callbacks are now called when parsing INI, and reset any time results are added. +* Adding extra utilities in seperate files version only, `Timer` (not needed for parsing, but useful for general CLI applications). ## Version 0.6 diff --git a/include/CLI/Timer.hpp b/include/CLI/Timer.hpp new file mode 100644 index 00000000..c34768d3 --- /dev/null +++ b/include/CLI/Timer.hpp @@ -0,0 +1,74 @@ +#pragma once + +// Distributed under the LGPL v2.1 license. See accompanying +// file LICENSE or https://github.com/henryiii/CLI11 for details. + +#include +#include +#include +#include + +namespace CLI { + +class Timer { +protected: + typedef std::chrono::high_resolution_clock clock; + typedef std::chrono::time_point time_point; + typedef std::function time_print_t; + + std::string title_; + time_point start_; + time_print_t time_print_; +public: + static std::string Simple(std::string title, std::string time) { + return title + ": " + time; + } + + static std::string Big(std::string title, std::string time) { + return "-----------------------------------------\n" + + title + " | Time = " + time + "\n" + + "-----------------------------------------"; + } + +public: + Timer(std::string title="Timer", time_print_t time_print = Simple) + : title_(title), time_print_(time_print), start_(clock::now()) {} + + + std::string make_time_str() const { + time_point stop = clock::now(); + std::chrono::duration elapsed = stop - start_; + double time = elapsed.count(); + + // LCOV_EXCL_START + if(time < 1) + return std::to_string(int(time*1000000)) + " ns"; + else if(time < 10) + return std::to_string(int(time*100) / 100.) + " ms"; + else if(time < 1000) + return std::to_string(int(time)) + " ms"; + else if(time < 10000) + return std::to_string(int(time*10000) / 10. ) + " s"; + else + return std::to_string(int(time*1000)) + " s"; + // LCOV_EXCL_END + } + std::string to_string() const { + return time_print_(title_, make_time_str()); + } +}; + +class AutoTimer : public Timer { +public: + using Timer::Timer; + + ~AutoTimer () { + std::cout << to_string() << std::endl; + } +}; + +} + +std::ostream & operator<< (std::ostream& in, const CLI::Timer& timer) { + return in << timer.to_string(); +} diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 67440a2e..78579a22 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -9,6 +9,10 @@ set(CLI_TESTS SubcommandTest HelpTest) +set(CLI_SINGLE_TESTS + TimerTest + ) + # Only affects current directory, so safe include_directories(${CMAKE_CURRENT_SOURCE_DIR}) @@ -26,3 +30,11 @@ foreach(T ${CLI_TESTS}) endforeach() +foreach(T ${CLI_SINGLE_TESTS}) + + add_executable(${T} ${T}.cpp ${CLI_headers}) + target_link_libraries(${T} PUBLIC CLI) + add_gtest(${T}) + +endforeach() + diff --git a/tests/TimerTest.cpp b/tests/TimerTest.cpp new file mode 100644 index 00000000..c9366ce5 --- /dev/null +++ b/tests/TimerTest.cpp @@ -0,0 +1,53 @@ +#include "gtest/gtest.h" +#include "gmock/gmock.h" +#include "CLI/Timer.hpp" +#include +#include +#include +#include + +using ::testing::HasSubstr; + +TEST(Timer, MSTimes) { + CLI::Timer timer{"My Timer"}; + std::this_thread::sleep_for(std::chrono::milliseconds(123)); + std::string output = timer.to_string(); + EXPECT_THAT(output, HasSubstr("My Timer")); + EXPECT_THAT(output, HasSubstr(" ms")); +} + +/* Takes too long +TEST(Timer, STimes) { + CLI::Timer timer; + std::this_thread::sleep_for(std::chrono::seconds(1)); + std::string output = timer.to_string(); + EXPECT_THAT(output, HasSubstr(" s")); +} +*/ + +TEST(Timer, NStimes) { + CLI::Timer timer; + std::string output = timer.to_string(); + EXPECT_THAT(output, HasSubstr(" ns")); +} + +TEST(Timer, BigTimer) { + CLI::Timer timer{"My Timer", CLI::Timer::Big}; + std::string output = timer.to_string(); + EXPECT_THAT(output, HasSubstr("Time =")); + EXPECT_THAT(output, HasSubstr("-----------")); +} + +TEST(Timer, AutoTimer) { + CLI::AutoTimer timer; + std::string output = timer.to_string(); + EXPECT_THAT(output, HasSubstr("Timer")); +} + +TEST(Timer, PrintTimer) { + std::stringstream out; + CLI::AutoTimer timer; + out << timer; + std::string output = out.str(); + EXPECT_THAT(output, HasSubstr("Timer")); +}