• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

kimci86 / bkcrack / 31338874084

09 Aug 2026 10:13PM UTC coverage: 93.049% (-0.07%) from 93.121%
31338874084

Pull #166

github

kimci86
wip
Pull Request #166: Show console progress without Virtual Terminal sequences

31 of 33 new or added lines in 2 files covered. (93.94%)

1874 of 2014 relevant lines covered (93.05%)

2825713.02 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

96.08
/src/cli/ConsoleProgress.cpp
1
#include "ConsoleProgress.hpp"
2

3
#include <bkcrack/log.hpp>
4

5
#include <array>
6
#include <cstdio>
7

8
ConsoleProgress::ConsoleProgress(std::ostream& os, const std::chrono::milliseconds& interval)
26✔
9
: Progress{os}
10
, m_interval{interval}
26✔
11
, m_in_destructor{false}
26✔
12
, m_printer{&ConsoleProgress::printerFunction, this}
26✔
13
{
14
}
26✔
15

16
ConsoleProgress::~ConsoleProgress()
52✔
17
{
18
    {
19
        const auto lock = std::scoped_lock{m_in_destructor_mutex};
52✔
20
        m_in_destructor = true;
52✔
21
    }
52✔
22

23
    m_in_destructor_cv.notify_all();
52✔
24
    m_printer.join();
52✔
25
}
52✔
26

27
void ConsoleProgress::printerFunction()
26✔
28
{
29
    auto repeat = true;
26✔
30

31
    // Give a small delay before the first time progress is printed so that
32
    // the running operation is likely to have initialized the total number of steps.
33
    {
34
        auto lock = std::unique_lock{m_in_destructor_mutex};
26✔
35
        repeat = !m_in_destructor_cv.wait_for(lock, std::chrono::milliseconds{1}, [this] { return m_in_destructor; });
78✔
36
    }
26✔
37

38
    while (repeat)
397✔
39
    {
40
        if (const auto line = getProgressLine(); !line.empty())
371✔
41
        {
42
            const auto lock = std::scoped_lock{m_os_mutex};
366✔
43
            m_os << '\r' << line;
366✔
44
            if (line.size() < m_lengthToClear)
366✔
NEW
45
                m_os << std::string(m_lengthToClear - line.size(), ' ');
×
46
            m_os << std::flush;
366✔
47
            m_lengthToClear = line.size();
366✔
48
        }
737✔
49

50
        auto lock = std::unique_lock{m_in_destructor_mutex};
371✔
51
        repeat    = !m_in_destructor_cv.wait_for(lock, m_interval, [this] { return m_in_destructor; });
1,113✔
52
    }
371✔
53

54
    if (const auto line = getProgressLine(); !line.empty())
26✔
55
    {
56
        const auto lock = std::scoped_lock{m_os_mutex};
9✔
57
        m_os << '\r' << line;
9✔
58
        if (line.size() < m_lengthToClear)
9✔
NEW
59
            m_os << std::string(m_lengthToClear - line.size(), ' ');
×
60
        m_os << std::endl;
9✔
61
        m_lengthToClear = 0;
9✔
62
    }
35✔
63
}
26✔
64

65
void ConsoleProgress::beforeLog(std::ostream& os)
43✔
66
{
67
    if (!m_lengthToClear)
43✔
68
        return;
38✔
69

70
    os << '\r' << std::string(m_lengthToClear, ' ') << '\r';
10✔
71
    m_lengthToClear = 0;
5✔
72
}
73

74
auto ConsoleProgress::getProgressLine() -> std::string
397✔
75
{
76
    if (const auto total = this->total.load())
794✔
77
    {
78
        const auto done   = this->done.load();
375✔
79
        auto       buffer = std::array<char, 80 + 1>{};
375✔
80
        const auto length =
81
            std::snprintf(buffer.data(), buffer.size(), "%.1f %% (%d / %d)", 100.0 * done / total, done, total);
750✔
82
        if (0 <= length && length < int{sizeof(buffer)})
375✔
83
            return std::string{buffer.data(), static_cast<std::size_t>(length)};
1,125✔
84
    }
85
    return "";
44✔
86
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc