1 | /** |
2 | * Copyright (c) Glow Contributors. See CONTRIBUTORS file. |
3 | * |
4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
5 | * you may not use this file except in compliance with the License. |
6 | * You may obtain a copy of the License at |
7 | * |
8 | * http://www.apache.org/licenses/LICENSE-2.0 |
9 | * |
10 | * Unless required by applicable law or agreed to in writing, software |
11 | * distributed under the License is distributed on an "AS IS" BASIS, |
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
13 | * See the License for the specific language governing permissions and |
14 | * limitations under the License. |
15 | */ |
16 | |
17 | #include "glow/Support/Error.h" |
18 | |
19 | #include "gtest/gtest.h" |
20 | |
21 | using namespace glow; |
22 | |
23 | TEST(Error, BasicError) { |
24 | auto err = MAKE_ERR("some error" ); |
25 | EXPECT_TRUE(ERR_TO_BOOL(std::move(err))); |
26 | } |
27 | |
28 | TEST(Error, ErrorSuccess) { |
29 | auto err = Error::success(); |
30 | EXPECT_FALSE(ERR_TO_BOOL(std::move(err))); |
31 | } |
32 | |
33 | TEST(Error, ErrorSuccessReturn) { |
34 | auto f = []() -> Error { return Error::success(); }; |
35 | auto err = f(); |
36 | EXPECT_FALSE(ERR_TO_BOOL(std::move(err))); |
37 | } |
38 | |
39 | TEST(Error, ErrorString) { |
40 | const char *msg = "some error" ; |
41 | auto err = MAKE_ERR(msg); |
42 | auto str = ERR_TO_STRING(std::move(err)); |
43 | EXPECT_NE(str.find(msg), std::string::npos) |
44 | << "Error should preserve the given message" ; |
45 | } |
46 | |
47 | TEST(Error, BasicOpaque) { |
48 | using glow::detail::Opaque; |
49 | |
50 | Opaque<int64_t> opaqueInt; |
51 | opaqueInt.set(42); |
52 | EXPECT_EQ(opaqueInt.get(), 42); |
53 | } |
54 | |
55 | TEST(Error, OpaqueDestructorCall) { |
56 | using glow::detail::Opaque; |
57 | |
58 | /// Struct that takes a pointer to a boolean in it's constructor and set's the |
59 | /// boolean to true when it is destructed. |
60 | struct SetFlagOnDestruct { |
61 | bool *b_ = nullptr; |
62 | |
63 | SetFlagOnDestruct(bool *b) : b_(b) {} |
64 | |
65 | ~SetFlagOnDestruct() { |
66 | if (b_ != nullptr) { |
67 | *b_ = true; |
68 | } |
69 | } |
70 | |
71 | SetFlagOnDestruct(SetFlagOnDestruct &&other) { std::swap(b_, other.b_); } |
72 | |
73 | SetFlagOnDestruct &operator=(SetFlagOnDestruct &&other) { |
74 | std::swap(b_, other.b_); |
75 | return *this; |
76 | } |
77 | }; |
78 | |
79 | bool b1 = false; |
80 | SetFlagOnDestruct flagSetter1(&b1); |
81 | |
82 | bool b2 = false; |
83 | SetFlagOnDestruct flagSetter2(&b2); |
84 | |
85 | { |
86 | Opaque<SetFlagOnDestruct> opaque1; |
87 | opaque1.set(std::move(flagSetter1)); |
88 | } |
89 | |
90 | { |
91 | Opaque<SetFlagOnDestruct> opaque2; |
92 | opaque2.set(std::move(flagSetter2)); |
93 | opaque2.destroy(); |
94 | } |
95 | |
96 | ASSERT_FALSE(b1) << "The destructor of the contents of Opaque shouldn't be " |
97 | "called when Opaque is destroyed" ; |
98 | |
99 | EXPECT_TRUE(b2) << "The destructor of the contents of Opaque should be " |
100 | "called when Opaque.destroy() is called" ; |
101 | |
102 | // Check size and alignment of Opaque<SetFlagOnDestruct> |
103 | EXPECT_EQ(sizeof(Opaque<SetFlagOnDestruct>), sizeof(SetFlagOnDestruct)); |
104 | EXPECT_EQ(alignof(Opaque<SetFlagOnDestruct>), alignof(SetFlagOnDestruct)); |
105 | } |
106 | |
107 | TEST(Error, ExpectedValue) { |
108 | Expected<std::string> stringOrErr("hello world" ); |
109 | if (stringOrErr) { |
110 | EXPECT_EQ(stringOrErr.get(), "hello world" ); |
111 | } else { |
112 | FAIL() << "This expected should have a value" ; |
113 | } |
114 | } |
115 | |
116 | TEST(Error, ExpectedError) { |
117 | const char *msg = "some error" ; |
118 | auto err = MAKE_ERR(msg); |
119 | Expected<int> intOrErr = std::move(err); |
120 | if (intOrErr) { |
121 | FAIL() << "This expected should not have a value" ; |
122 | } else { |
123 | auto err2 = intOrErr.takeError(); |
124 | auto str = ERR_TO_STRING(std::move(err2)); |
125 | EXPECT_NE(str.find(msg), std::string::npos) |
126 | << "Expected should preserve the given message" ; |
127 | } |
128 | } |
129 | |
130 | TEST(Error, ExpectedTakeErrorWithoutError) { |
131 | Expected<int> intOrErr(42); |
132 | auto err = intOrErr.takeError(); |
133 | EXPECT_FALSE(err); |
134 | } |
135 | |
136 | TEST(Error, EmptyErrors) { |
137 | Error err = Error::empty(); |
138 | |
139 | auto f = [&]() { err = MAKE_ERR("something" ); }; |
140 | |
141 | f(); |
142 | |
143 | EXPECT_TRUE(ERR_TO_BOOL(std::move(err))); |
144 | } |
145 | |
146 | // Creating an unused OneErrOnly should be safe. |
147 | TEST(Error, UntouchedOneErrOnly) { OneErrOnly foo; } |
148 | |
149 | TEST(Error, ExpectedConversion) { |
150 | auto foo = []() -> Expected<int32_t> { return 42; }; |
151 | |
152 | auto bar = [&]() -> Expected<int64_t> { return foo(); }; |
153 | |
154 | int64_t barRes; |
155 | ASSIGN_VALUE_OR_FAIL_TEST(barRes, bar()); |
156 | |
157 | EXPECT_EQ(barRes, 42); |
158 | } |
159 | |
160 | TEST(Error, ReturnIfExpectedIsErr) { |
161 | auto retErr = [&]() -> Expected<int> { return MAKE_ERR("Error!" ); }; |
162 | auto test = [&]() -> Error { |
163 | RETURN_IF_EXPECTED_IS_ERR(retErr()); |
164 | return Error::success(); |
165 | }; |
166 | |
167 | EXPECT_TRUE(ERR_TO_BOOL(test())); |
168 | } |
169 | |
170 | TEST(Error, PeekError) { |
171 | const char *msg = "some error" ; |
172 | auto err = MAKE_ERR(msg); |
173 | auto str = err.peekErrorValue()->logToString(); |
174 | EXPECT_NE(str.find(msg), std::string::npos) |
175 | << "Error should preserve the given message" ; |
176 | #ifndef NDEBUG |
177 | EXPECT_FALSE(err.isChecked_()); |
178 | #endif |
179 | ERR_TO_VOID(std::move(err)); |
180 | } |
181 | |
182 | TEST(Error, PeekExpected) { |
183 | const char *msg = "some error" ; |
184 | Expected<int> intOrErr = MAKE_ERR(msg); |
185 | auto str = intOrErr.peekErrorValue()->logToString(); |
186 | EXPECT_NE(str.find(msg), std::string::npos) |
187 | << "Error should preserve the given message" ; |
188 | #ifndef NDEBUG |
189 | EXPECT_FALSE(intOrErr.isChecked_()); |
190 | #endif |
191 | ERR_TO_VOID(intOrErr.takeError()); |
192 | } |
193 | |
194 | TEST(Error, WarningString) { |
195 | const char *msg = "some message" ; |
196 | auto err = MAKE_ERR(msg); |
197 | auto str = ERR_TO_STRING(std::move(err), /*warning*/ true); |
198 | EXPECT_NE(str.find("Warning" ), std::string::npos) |
199 | << "Expect warning to be present in message" ; |
200 | } |
201 | |
202 | TEST(Error, StackMessages) { |
203 | const char *msg = "some message" ; |
204 | auto err = MAKE_ERR(msg); |
205 | ADD_MESSAGE_TO_ERR_STACK(err, "banana" ); |
206 | auto str = ERR_TO_STRING(std::move(err)); |
207 | EXPECT_NE(str.find("banana" ), std::string::npos) |
208 | << "Expect stack message to be present in message" ; |
209 | } |
210 | |