1 /* Copyright 2017-2018 Fizyr B.V. - https://fizyr.com
2  *
3  * Redistribution and use in source and binary forms, with or without modification,
4  * are permitted provided that the following conditions are met:
5  *
6  * 1. Redistributions of source code must retain the above copyright notice,
7  *    this list of conditions and the following disclaimer.
8  *
9  * 2. Redistributions in binary form must reproduce the above copyright notice,
10  *    this list of conditions and the following disclaimer in the documentation
11  *    and/or other materials provided with the distribution.
12  *
13  * 3. Neither the name of the copyright holder nor the names of its contributors
14  *    may be used to endorse or promote products derived from this software without
15  *    specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
21  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
24  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 #include "result/error.hpp"
30 #include "traits/is_comparible.hpp"
31 #include "result/catch_string_conversions.hpp"
32 
33 #include <catch2/catch.hpp>
34 
35 namespace estd {
36 
37 class test_category_ : public std::error_category {
name() const38 	char const * name() const noexcept override {
39 		return "test";
40 	}
41 
message(int code) const42 	std::string message(int code) const override {
43 		switch (code) {
44 			case 1: return "one";
45 			case 2: return "two";
46 			case 3: return "three";
47 		}
48 		return "unknown error";
49 	}
50 } test_category_;
51 
test_category()52 std::error_category const & test_category() {
53 	return test_category_;
54 }
55 
56 
57 TEST_CASE("error compares to std::error_code", "[result]") {
58 	static_assert(is_comparible<error, std::error_code>);
59 	REQUIRE(error{std::errc::invalid_argument} == make_error_code(std::errc::invalid_argument));
60 	REQUIRE(error{std::errc::invalid_argument} != make_error_code(std::errc::address_in_use));
61 }
62 
63 TEST_CASE("error compares to std::error_condition", "[result]") {
64 	static_assert(is_comparible<error, std::errc>);
65 	REQUIRE(error{std::errc::invalid_argument} == make_error_condition(std::errc::invalid_argument));
66 	REQUIRE(error{std::errc::invalid_argument} != make_error_condition(std::errc::address_in_use));
67 }
68 
69 TEST_CASE("error compares to std::errc", "[result]") {
70 	static_assert(is_comparible<error, std::error_condition>);
71 	REQUIRE(error{std::errc::invalid_argument} == std::errc::invalid_argument);
72 	REQUIRE(error{std::errc::invalid_argument} != std::errc::address_in_use);
73 }
74 
75 TEST_CASE("error is not comparible with itself", "[result]") {
76 	static_assert(is_comparible<error, error> == false);
77 	CHECK((is_comparible<error, error>) == false);
78 }
79 
80 TEST_CASE("unspecified errors have the right category and value", "[result]") {
81 	CHECK(error("aap").code == unspecified_errc::unspecified);
82 	CHECK(error({"aap", "noot"}).code == unspecified_errc::unspecified);
83 }
84 
85 TEST_CASE("error.format_code() formats correctly", "[result]") {
86 	std::error_code test_code = {1, test_category()};
87 
88 	CHECK(error(test_code).format_code() == "test error 1: one");
89 	SECTION("error description does not influence format_code()") {
90 		CHECK(error(test_code, "aap").format_code() == "test error 1: one");
91 	}
92 
93 	SECTION("errors of unspecified category only print the category name and value") {
94 		CHECK(error(unspecified_errc::unspecified).format_code() == "unspecified error -1");
95 		CHECK(error({1, unspecified_error_category()}).format_code() == "unspecified error 1");
96 	}
97 }
98 
99 TEST_CASE("error.format_description() formats correctly", "[result]") {
100 	CHECK(error(std::errc::invalid_argument).format_description() == "");
101 	CHECK(error(std::errc::invalid_argument, "aap").format_description() == "aap");
102 	CHECK(error(std::errc::invalid_argument, {"aap", "noot"}).format_description() == "noot: aap");
103 }
104 
105 TEST_CASE("error.format() formats correctly", "[result]") {
106 	std::error_code test_code = {1, test_category()};
107 
108 	CHECK(error(test_code).format() == "test error 1: one");
109 	CHECK(error(test_code, "aap").format() == "aap: test error 1: one");
110 	CHECK(error(test_code, {"aap", "noot"}).format() == "noot: aap: test error 1: one");
111 
112 	SECTION("unspecified errors don't include the code") {
113 		CHECK(error("aap").format() == "aap");
114 		CHECK(error({"aap", "noot"}).format() == "noot: aap");
115 		SECTION("unless they have no description") {
116 			CHECK(error(unspecified_errc::unspecified).format() == "unspecified error -1");
117 		}
118 	}
119 }
120 
121 }
122