C++Spec 1.0.0
BDD testing for C++
Loading...
Searching...
No Matches
progress.hpp
Go to the documentation of this file.
1
2#pragma once
3
4#include <forward_list>
5#include <list>
6#include <string>
7
8#include "term_colors.hpp"
9#include "verbose.hpp"
10
11namespace CppSpec::Formatters {
12
13// The TAP format makes things a little tricky
14class Progress : public BaseFormatter {
15 std::list<std::string> baked_failure_messages;
16
17 std::string prep_failure_helper(const ItBase& it);
18
19 public:
20 ~Progress() override {
21 format_failure_messages(); // Print any failures that we have
22 }
23 void format(const ItBase& it) override;
24
25 void format_failure_messages();
26 void prep_failure(const ItBase& it);
27
28 static char status_char(Result::Status status) {
29 switch (status) {
30 case Result::Status::Success:
31 return '.';
32 case Result::Status::Failure:
33 return 'F';
34 case Result::Status::Error:
35 return 'E';
36 case Result::Status::Skipped:
37 return 'S';
38 }
39 return '.'; // Default to success if status is unknown
40 }
41};
42
44inline std::string Progress::prep_failure_helper(const ItBase& it) {
45 // a singly-linked list to act as a LIFO queue
46 std::forward_list<std::string> list;
47
48 // a temporary stream for our helper formatter to write to
49 std::ostringstream temp_stream;
50
51 // A lambda to clean up some code reuse
52 auto push_and_clear = [&]() {
53 list.push_front(temp_stream.str()); // push the stream's contents onto the
54 temp_stream.clear(); // clear the stream's flags
55 temp_stream.str(""); // reset it to empty
56 };
57
58 // Format the 'it' example first
59 temp_stream << it.padding() << it.get_description() << std::endl;
60 push_and_clear();
61
62 // Verbose already has the majority of what we need
63 // defined, so we'll use it.
64 Verbose helper_formatter = Verbose(*this, temp_stream);
65
66 // Ascend the tree to the root, formatting the nodes and
67 // enqueing each formatted string as we go.
68 const auto* parent = it.get_parent_as<Description>();
69
70 do {
71 helper_formatter.format(*parent); // Format the node
72 push_and_clear();
73 } while ((parent = dynamic_cast<const Description*>(parent->get_parent())) != nullptr);
74
75 return Util::join(list); // squash the list of strings and return it.
76}
77
78inline void Progress::prep_failure(const ItBase& it) {
79 std::list<std::string> raw_failure_messages; // raw failure messages
80 std::ranges::transform(it.get_results(), std::back_inserter(raw_failure_messages),
81 [](const Result& result) { return result.get_message(); });
82
83 std::ostringstream string_builder; // oss is used as the local string builder
84 string_builder << set_color(RED); // if we're doing color, make it red
85 string_builder << "Test number " << test_counter << " failed:"; // Tell us what test # failed
86 string_builder << reset_color(); // reset the color
87 string_builder << prep_failure_helper(it);
88 string_builder << set_color(RED);
89 string_builder << Util::join_endl(raw_failure_messages);
90 string_builder << reset_color(); // reset the color
91 string_builder << std::endl;
92
93 raw_failure_messages.clear();
94 baked_failure_messages.push_back(string_builder.str());
95}
96
97inline void Progress::format(const ItBase& it) {
98 out_stream << status_color(it.get_result().status());
99 out_stream << status_char(it.get_result().status());
100 out_stream << reset_color();
101 out_stream << std::flush;
102
103 if (it.get_result().status() == Result::Status::Failure) {
104 prep_failure(it);
105 }
106 get_and_increment_test_counter();
107}
108
109inline void Progress::format_failure_messages() {
110 if (baked_failure_messages.empty()) {
111 out_stream << std::endl; // If we don't have any failures, just print a blank line.
112 return;
113 }
114
115 // If we have any failures to format
116 for (const std::string& message : baked_failure_messages) {
117 out_stream << std::endl;
118 out_stream << message; // separated by a blank line
119 }
120 baked_failure_messages.clear(); // Finally, clear the failures list.
121}
122
123static Progress progress;
124
125} // namespace CppSpec::Formatters
Definition description.hpp:20
Definition progress.hpp:14
Base class for it expressions.
Definition it_base.hpp:32