C++Spec 1.0.0
BDD testing for C++
Loading...
Searching...
No Matches
result.hpp
Go to the documentation of this file.
1
2#pragma once
3
4#include <ciso646>
5#include <format>
6#include <source_location>
7#include <sstream>
8#include <string>
9#include <utility>
10
11namespace CppSpec {
12
13class Result {
14 public:
15 enum class Status { Success, Failure, Error, Skipped };
16
17 Result() = default;
18
19 /*--------- Status helper functions --------------*/
20 void set_status(Status status) noexcept { status_ = status; }
21 [[nodiscard]] Status status() const noexcept { return status_; }
22 [[nodiscard]] bool is_success() const noexcept { return status_ == Status::Success; }
23 [[nodiscard]] bool is_failure() const noexcept { return status_ == Status::Failure; }
24 [[nodiscard]] bool skipped() const noexcept { return status_ == Status::Skipped; }
25 [[nodiscard]] bool is_error() const noexcept { return status_ == Status::Error; }
26
27 static Result reduce(const Result& lhs, const Result& rhs) noexcept {
28 if (lhs.is_failure()) {
29 return lhs;
30 } else if (rhs.is_failure()) {
31 return rhs;
32 } else if (lhs.is_success()) {
33 return lhs;
34 } else if (rhs.is_success()) {
35 return rhs;
36 } else {
37 return lhs;
38 }
39 }
40
41 /*--------- Location helper functions ------------*/
42 [[nodiscard]] std::source_location get_location() const noexcept { return location; }
43 [[nodiscard]] std::string get_location_string() const noexcept {
44 return std::format("{}:{}:{}", location.file_name(), location.line(), location.column());
45 }
46
47 [[nodiscard]] std::string get_type() const noexcept { return type; }
48 [[nodiscard]] std::string get_type() noexcept { return type; }
49 void set_type(std::string type) noexcept { this->type = std::move(type); }
50
51 /*--------- Message helper functions -------------*/
52 std::string get_message() noexcept { return message; }
53 [[nodiscard]] std::string get_message() const noexcept { return message; }
54 Result& set_message(std::string message) noexcept {
55 this->message = std::move(message);
56 return *this;
57 }
58
59 /*--------- Explicit constructor functions -------*/
60 static Result success(std::source_location location) noexcept { return {Status::Success, location}; }
61 static Result failure(std::source_location location) noexcept { return {Status::Failure, location}; }
62 static Result success_with(std::source_location location, std::string success_message) noexcept {
63 return {Status::Success, location, std::move(success_message)};
64 }
65 static Result failure_with(std::source_location location, std::string failure_message) noexcept {
66 return {Status::Failure, location, std::move(failure_message)};
67 }
68
69 static Result error(std::source_location location) noexcept { return {Status::Error, location}; }
70 static Result error_with(std::source_location location, std::string error_message) noexcept {
71 return {Status::Error, location, std::move(error_message)};
72 }
73
74 static Result skipped(std::source_location location) noexcept { return {Status::Skipped, location}; }
75 static Result skipped_with(std::source_location location, std::string skipped_message) noexcept {
76 return {Status::Skipped, location, std::move(skipped_message)};
77 }
78
79 /*-------------- Friend functions ----------------*/
80
81 // Stream operator
82 friend std::ostream& operator<<(std::ostream& os, const Result& res) {
83 std::stringstream ss;
84 switch (res.status()) {
85 case Status::Success:
86 ss << "Success";
87 break;
88 case Status::Failure:
89 ss << "Failure";
90 break;
91 case Status::Error:
92 ss << "Error";
93 break;
94 case Status::Skipped:
95 ss << "Skipped";
96 break;
97 }
98
99 if (not res.get_message().empty()) {
100 ss << "(\"" + res.get_message() + "\")";
101 }
102
103 return os << ss.str();
104 }
105
106 private:
107 Status status_ = Status::Success;
108 std::source_location location;
109 std::string message;
110 std::string type;
111 Result(Status status, std::source_location location, std::string message = "") noexcept
112 : status_(status), location(location), message(std::move(message)) {}
113};
114
115template <typename T>
116constexpr bool is_result_v = std::is_same_v<Result, T>;
117
118template <typename T>
119concept is_result = is_result_v<T>;
120
121} // namespace CppSpec
Definition result.hpp:119