TerrainGen coverage


terraingen/
Coverage:
low: ≥ 0%
medium: ≥ 75.0%
high: ≥ 90.0%
Lines:
71 / 71
100.0%
Branches:
43 / 46
93.5%
Functions:
14 / 14
100.0%

util/log.cpp
Line Branch Exec Source
1 #include "terraingen/util/log.h"
2
3 #include <algorithm>
4 #include <array>
5 #include <atomic>
6 #include <cctype>
7 #include <cstdio>
8 #include <iostream>
9 #include <mutex>
10 #include <utility>
11
12 namespace terraingen {
13
14 namespace {
15
16 struct LogState {
17 std::mutex mutex;
18 LogSink sink = StandardErrorLogSink();
19 std::atomic<LogLevel> level{LogLevel::Warning};
20 };
21
22 1551878 LogState& State() {
23
4/7
✓ Branch 0 taken 380 times.
✓ Branch 1 taken 1551498 times.
✓ Branch 3 taken 380 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 380 times.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
1551878 static LogState state;
24 1551878 return state;
25 }
26
27 thread_local bool inSink = false;
28
29 /// Marks the current thread as inside the sink, so records the sink logs are dropped.
30 class SinkGuard {
31 public:
32 8093 SinkGuard() {
33 8093 inSink = true;
34 8093 }
35 8093 ~SinkGuard() {
36 8093 inSink = false;
37 8093 }
38 SinkGuard(const SinkGuard&) = delete;
39 SinkGuard& operator=(const SinkGuard&) = delete;
40 };
41
42 } // namespace
43
44 420 std::string_view LogLevelName(LogLevel level) {
45
7/7
✓ Branch 0 taken 98 times.
✓ Branch 1 taken 98 times.
✓ Branch 2 taken 112 times.
✓ Branch 3 taken 94 times.
✓ Branch 4 taken 9 times.
✓ Branch 5 taken 8 times.
✓ Branch 6 taken 1 time.
420 switch (level) {
46 98 case LogLevel::Trace:
47 98 return "trace";
48 98 case LogLevel::Debug:
49 98 return "debug";
50 112 case LogLevel::Info:
51 112 return "info";
52 94 case LogLevel::Warning:
53 94 return "warning";
54 9 case LogLevel::Error:
55 9 return "error";
56 8 case LogLevel::Off:
57 8 return "off";
58 }
59 1 return "unknown";
60 }
61
62 98 std::optional<LogLevel> ParseLogLevel(std::string_view name) {
63
1/1
✓ Branch 1 taken 98 times.
98 std::string lower(name);
64 98 std::transform(lower.begin(), lower.end(), lower.begin(),
65 642 [](unsigned char c) { return static_cast<char>(std::tolower(c)); });
66
3/3
✓ Branch 1 taken 98 times.
✓ Branch 3 taken 1 time.
✓ Branch 4 taken 97 times.
98 if (lower == "warn") {
67 1 return LogLevel::Warning;
68 }
69 97 constexpr std::array kLevels{LogLevel::Trace, LogLevel::Debug, LogLevel::Info,
70 LogLevel::Warning, LogLevel::Error, LogLevel::Off};
71
2/2
✓ Branch 2 taken 391 times.
✓ Branch 3 taken 3 times.
394 for (const LogLevel level : kLevels) {
72
2/2
✓ Branch 3 taken 94 times.
✓ Branch 4 taken 297 times.
391 if (lower == LogLevelName(level)) {
73 94 return level;
74 }
75 }
76 3 return std::nullopt;
77 98 }
78
79 441 LogSink StandardErrorLogSink() {
80 441 return [](const LogRecord& record) {
81 36 std::cerr << "[terraingen] " << LogLevelName(record.level) << ' ' << record.category << ": "
82 18 << record.message << '\n';
83 441 };
84 }
85
86 128 void SetLogSink(LogSink sink) {
87
1/1
✓ Branch 1 taken 128 times.
128 LogState& state = State();
88
1/1
✓ Branch 1 taken 128 times.
128 const std::lock_guard lock(state.mutex);
89
2/2
✓ Branch 1 taken 67 times.
✓ Branch 2 taken 61 times.
128 state.sink = sink ? std::move(sink) : StandardErrorLogSink();
90 128 }
91
92 205 void SetLogLevel(LogLevel level) {
93 205 State().level.store(level, std::memory_order_relaxed);
94 205 }
95
96 1543452 LogLevel GetLogLevel() {
97 1543452 return State().level.load(std::memory_order_relaxed);
98 }
99
100 1543367 bool LogEnabled(LogLevel level) {
101
4/4
✓ Branch 0 taken 1543366 times.
✓ Branch 1 taken 1 time.
✓ Branch 3 taken 16184 times.
✓ Branch 4 taken 1527182 times.
1543367 return level != LogLevel::Off && level >= GetLogLevel();
102 }
103
104 8405 void Log(LogLevel level, std::string_view category, std::string message) {
105
7/7
✓ Branch 1 taken 8405 times.
✓ Branch 3 taken 8095 times.
✓ Branch 4 taken 310 times.
✓ Branch 5 taken 2 times.
✓ Branch 6 taken 8093 times.
✓ Branch 7 taken 312 times.
✓ Branch 8 taken 8093 times.
8405 if (!LogEnabled(level) || inSink) {
106 312 return;
107 }
108 8093 const LogRecord record{level, std::string(category), std::move(message),
109
1/1
✓ Branch 1 taken 8093 times.
16186 std::chrono::system_clock::now()};
110
1/1
✓ Branch 1 taken 8093 times.
8093 LogState& state = State();
111
1/1
✓ Branch 1 taken 8093 times.
8093 const std::lock_guard lock(state.mutex);
112 8093 const SinkGuard guard;
113
1/1
✓ Branch 1 taken 8093 times.
8093 state.sink(record);
114 8093 }
115
116 366526 std::string FormatDuration(double milliseconds) {
117 366526 std::array<char, 32> buffer{};
118
2/2
✓ Branch 0 taken 284 times.
✓ Branch 1 taken 366242 times.
366526 if (milliseconds >= 1000.0) {
119 852 std::snprintf(buffer.data(), buffer.size(), "%.2f s", milliseconds / 1000.0);
120
2/2
✓ Branch 0 taken 2429 times.
✓ Branch 1 taken 363813 times.
366242 } else if (milliseconds >= 10.0) {
121 4858 std::snprintf(buffer.data(), buffer.size(), "%.1f ms", milliseconds);
122 } else {
123 727626 std::snprintf(buffer.data(), buffer.size(), "%.2f ms", milliseconds);
124 }
125
1/1
✓ Branch 1 taken 366526 times.
733052 return buffer.data();
126 }
127
128 } // namespace terraingen
129