Implement cpputils::ProgressBar

This commit is contained in:
Sebastian Messmer 2019-01-22 22:02:34 -08:00
parent 8a5091b8a2
commit 67e9885d10
5 changed files with 134 additions and 0 deletions

View File

@ -23,6 +23,7 @@ set(SOURCES
io/IOStreamConsole.cpp io/IOStreamConsole.cpp
io/NoninteractiveConsole.cpp io/NoninteractiveConsole.cpp
io/pipestream.cpp io/pipestream.cpp
io/ProgressBar.cpp
thread/LoopThread.cpp thread/LoopThread.cpp
thread/ThreadSystem.cpp thread/ThreadSystem.cpp
thread/debugging_nonwindows.cpp thread/debugging_nonwindows.cpp

View File

@ -0,0 +1,35 @@
#include "ProgressBar.h"
#include <iostream>
#include <limits>
#include <mutex>
#include "IOStreamConsole.h"
using std::string;
namespace cpputils {
ProgressBar::ProgressBar(const char* preamble, uint64_t max_value)
: ProgressBar(std::make_shared<IOStreamConsole>(), preamble, max_value) {}
ProgressBar::ProgressBar(std::shared_ptr<Console> console, const char* preamble, uint64_t max_value)
: _console(std::move(console))
, _preamble(string("\r") + preamble + " ")
, _max_value(max_value)
, _lastPercentage(std::numeric_limits<decltype(_lastPercentage)>::max()) {
ASSERT(_max_value > 0, "Progress bar can't handle max_value of 0");
_console->print("\n");
// show progress bar. _lastPercentage is different to zero, so it shows.
update(0);
}
void ProgressBar::update(uint64_t value) {
const size_t percentage = (100 * value) / _max_value;
if (percentage != _lastPercentage) {
_console->print(_preamble + std::to_string(percentage) + "%");
_lastPercentage = percentage;
}
}
}

View File

@ -0,0 +1,31 @@
#pragma once
#ifndef MESSMER_CPPUTILS_IO_PROGRESSBAR_H
#define MESSMER_CPPUTILS_IO_PROGRESSBAR_H
#include <cpp-utils/macros.h>
#include <string>
#include <memory>
#include "Console.h"
namespace cpputils {
class ProgressBar final {
public:
explicit ProgressBar(std::shared_ptr<Console> console, const char* preamble, uint64_t max_value);
explicit ProgressBar(const char* preamble, uint64_t max_value);
void update(uint64_t value);
private:
std::shared_ptr<Console> _console;
std::string _preamble;
uint64_t _max_value;
size_t _lastPercentage;
DISALLOW_COPY_AND_ASSIGN(ProgressBar);
};
}
#endif

View File

@ -29,6 +29,7 @@ set(SOURCES
io/ConsoleTest_Print.cpp io/ConsoleTest_Print.cpp
io/ConsoleTest_Ask.cpp io/ConsoleTest_Ask.cpp
io/ConsoleTest_AskPassword.cpp io/ConsoleTest_AskPassword.cpp
io/ProgressBarTest.cpp
random/RandomIncludeTest.cpp random/RandomIncludeTest.cpp
lock/LockPoolIncludeTest.cpp lock/LockPoolIncludeTest.cpp
lock/ConditionBarrierIncludeTest.cpp lock/ConditionBarrierIncludeTest.cpp

View File

@ -0,0 +1,66 @@
#include <cpp-utils/io/ProgressBar.h>
#include <gmock/gmock.h>
using cpputils::ProgressBar;
using std::make_shared;
class MockConsole final: public cpputils::Console {
public:
void EXPECT_OUTPUT(const char* expected) {
EXPECT_EQ(expected, _output);
_output = "";
}
void print(const std::string& text) override {
_output += text;
}
unsigned int ask(const std::string&, const std::vector<std::string>&) override {
EXPECT_TRUE(false);
return 0;
}
bool askYesNo(const std::string&, bool) override {
EXPECT_TRUE(false);
return false;
}
std::string askPassword(const std::string&) override {
EXPECT_TRUE(false);
return "";
}
private:
std::string _output;
};
TEST(ProgressBarTest, testProgressBar) {
auto console = make_shared<MockConsole>();
ProgressBar bar(console, "Preamble", 2000);
console->EXPECT_OUTPUT("\n\rPreamble 0%");
// when updating to 0, doesn't reprint
bar.update(0);
console->EXPECT_OUTPUT("");
// update to half
bar.update(1000);
console->EXPECT_OUTPUT("\rPreamble 50%");
// when updating to same value, doesn't reprint
bar.update(1000);
console->EXPECT_OUTPUT("");
// when updating to value with same percentage, doesn't reprint
bar.update(1001);
console->EXPECT_OUTPUT("");
// update to 0
bar.update(0);
console->EXPECT_OUTPUT("\rPreamble 0%");
// update to full
bar.update(2000);
console->EXPECT_OUTPUT("\rPreamble 100%");
}