GCC Code Coverage Report


Directory: include/tts/
File: include/tts/sinks/colorized.hpp
Date: 2026-10-14 16:28:14
Exec Total Coverage
Lines: 45 49 91.8%
Functions: 9 10 90.0%
Branches: 16 20 80.0%

Line Branch Exec Source
1 //======================================================================================================================
2 //! @file
3 /*
4 TTS - Tiny Test System
5 Copyright : TTS Contributors & Maintainers
6 SPDX-License-Identifier: BSL-1.0
7 */
8 //======================================================================================================================
9 #pragma once
10
11 #include <tts/tools/output.hpp>
12
13 namespace tts
14 {
15 //====================================================================================================================
16 /**
17 @ingroup tools-sinks
18 @public
19 @brief output_sink wrapping another sink, colorizing pass/fail/fatal lines with ANSI escapes.
20
21 Wraps a target sink (tts::output_handler::default_sink() by default). Opt-in: not every
22 terminal or CI log renders ANSI escapes usefully. See @ref output-sinks for a colored example
23 of a full run.
24
25 @groupheader{Example}
26 @code
27 tts::colorized_sink colorized;
28 tts::output().sink(colorized);
29 @endcode
30 **/
31 //====================================================================================================================
32 struct colorized_sink : output_sink
33 {
34 100 explicit colorized_sink(output_sink& target = output_handler::default_sink())
35 100 : target_(&target)
36 {
37 100 }
38
39 19 void write(text const& t) override
40 {
41 19 char const* s = t.data();
42
43 // "\n" ends the current line's color only, not active_color_, so a hook's color can span
44 // several write() calls until the next hook changes it.
45
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 11 times.
19 if(strcmp(s, "\n") == 0) // NOSONAR - avoids std::string
46 {
47
3/3
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 3 times.
✓ Branch 4 taken 5 times.
8 if(color_applied_) target_->write(text {"\033[0m"}); // NOSONAR - \o{} is C++23-only
48 8 color_applied_ = false;
49 8 target_->write(t);
50 8 return;
51 }
52
53
3/4
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
11 if(active_color_ && !color_applied_)
54 {
55
1/1
✓ Branch 2 taken 8 times.
8 target_->write(text {active_color_});
56 8 color_applied_ = true;
57 }
58
59 11 target_->write(t);
60
61 // suite_metric() colors only its own segment - fall back once it's written.
62
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 9 times.
11 if(revert_to_)
63 {
64 2 active_color_ = revert_to_;
65 2 color_applied_ = false;
66 2 revert_to_ = nullptr;
67 }
68 }
69
70 // Each hook below sets or clears active_color_ decisively, even under -q.
71
72 2 void test_started([[maybe_unused]] text const& name) override
73 {
74 2 set_color(nullptr);
75 2 }
76
77 1 void assertion_failed([[maybe_unused]] text const& location,
78 [[maybe_unused]] text const& message,
79 [[maybe_unused]] bool fatal) override
80 {
81 1 set_color("\033[31m"); // red - NOSONAR, \o{} is C++23-only
82 1 }
83
84 2 void test_finished([[maybe_unused]] text const& name,
85 bool passed,
86 bool invalid,
87 [[maybe_unused]] nanoseconds duration_ns) override
88 {
89
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if(invalid) set_color("\033[33m"); // yellow - NOSONAR, \o{} is C++23-only
90
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 else if(passed) set_color("\033[32m"); // green - NOSONAR, \o{} is C++23-only
91 1 else set_color(nullptr); // plain failure - assertion_failed() already colored its line
92 2 }
93
94 1 void suite_finished([[maybe_unused]] counter fail_count,
95 [[maybe_unused]] counter invalid_count) override
96 {
97 1 set_color("\033[1m"); // bold, neutral - NOSONAR, \o{} is C++23-only
98 1 }
99
100 2 void suite_metric(outcome kind,
101 [[maybe_unused]] counter count,
102 [[maybe_unused]] counter total) override
103 {
104 using enum outcome;
105 2 revert_to_ = active_color_; // fall back to this once the segment below is written
106
2/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
2 switch(kind)
107 {
108 1 case success: set_color("\033[1;32m"); break; // bold green - NOSONAR
109 1 case failure: set_color("\033[1;31m"); break; // bold red - NOSONAR
110 ✗ case invalid: set_color("\033[1;33m"); break; // bold yellow - NOSONAR
111 }
112 2 }
113
114 ✗ void suite_aborted() override
115 {
116 ✗ set_color("\033[31m"); // red - NOSONAR, \o{} is C++23-only
117 ✗ }
118
119 3 void flush() override
120 {
121 3 target_->flush();
122 3 }
123
124 private:
125 8 void set_color(char const* color)
126 {
127 8 active_color_ = color;
128 8 color_applied_ = false;
129 8 }
130
131 output_sink* target_;
132 char const* active_color_ = nullptr;
133 bool color_applied_ = false;
134 char const* revert_to_ = nullptr;
135 };
136 }
137