blob: d31e775e53b589ed4e26ac8a021c900a86ef6c50 [file] [log] [blame]
Jiyong Park8fd64c82019-05-31 03:43:34 +09001/*
2 * Copyright (C) 2017 The Android Open Source Project
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 "android-base/result.h"
18
19#include "errno.h"
20
21#include <istream>
22#include <string>
23
24#include <gtest/gtest.h>
25
26using namespace std::string_literals;
27
28namespace android {
29namespace base {
30
31TEST(result, result_accessors) {
32 Result<std::string> result = "success";
33 ASSERT_TRUE(result);
34 ASSERT_TRUE(result.has_value());
35
36 EXPECT_EQ("success", *result);
37 EXPECT_EQ("success", result.value());
38
39 EXPECT_EQ('s', result->data()[0]);
40}
41
42TEST(result, result_accessors_rvalue) {
43 ASSERT_TRUE(Result<std::string>("success"));
44 ASSERT_TRUE(Result<std::string>("success").has_value());
45
46 EXPECT_EQ("success", *Result<std::string>("success"));
47 EXPECT_EQ("success", Result<std::string>("success").value());
48
49 EXPECT_EQ('s', Result<std::string>("success")->data()[0]);
50}
51
52TEST(result, result_success) {
53 Result<Success> result = Success();
54 ASSERT_TRUE(result);
55 ASSERT_TRUE(result.has_value());
56
57 EXPECT_EQ(Success(), *result);
58 EXPECT_EQ(Success(), result.value());
59}
60
61TEST(result, result_success_rvalue) {
62 // Success() doesn't actually create a Result<Success> object, but rather an object that can be
63 // implicitly constructed into a Result<Success> object.
64
65 auto MakeRvalueSuccessResult = []() -> Result<Success> { return Success(); };
66 ASSERT_TRUE(MakeRvalueSuccessResult());
67 ASSERT_TRUE(MakeRvalueSuccessResult().has_value());
68
69 EXPECT_EQ(Success(), *MakeRvalueSuccessResult());
70 EXPECT_EQ(Success(), MakeRvalueSuccessResult().value());
71}
72
Jiyong Parkb2a85c42019-06-05 18:33:01 +090073TEST(result, result_void) {
74 Result<void> ok = {};
75 EXPECT_TRUE(ok);
76 ok.value(); // should not crash
77 ASSERT_DEATH(ok.error(), "");
78
79 Result<void> fail = Error() << "failure" << 1;
80 EXPECT_FALSE(fail);
81 EXPECT_EQ("failure1", fail.error().message());
82 EXPECT_EQ(0, fail.error().code());
83 EXPECT_TRUE(ok != fail);
84 ASSERT_DEATH(fail.value(), "");
85
86 auto test = [](bool ok) -> Result<void> {
87 if (ok) return {};
88 else return Error() << "failure" << 1;
89 };
90 EXPECT_TRUE(test(true));
91 EXPECT_FALSE(test(false));
92 test(true).value(); // should not crash
93 ASSERT_DEATH(test(true).error(), "");
94 ASSERT_DEATH(test(false).value(), "");
95 EXPECT_EQ("failure1", test(false).error().message());
96}
97
Jiyong Park8fd64c82019-05-31 03:43:34 +090098TEST(result, result_error) {
99 Result<Success> result = Error() << "failure" << 1;
100 ASSERT_FALSE(result);
101 ASSERT_FALSE(result.has_value());
102
103 EXPECT_EQ(0, result.error().code());
104 EXPECT_EQ("failure1", result.error().message());
105}
106
107TEST(result, result_error_empty) {
108 Result<Success> result = Error();
109 ASSERT_FALSE(result);
110 ASSERT_FALSE(result.has_value());
111
112 EXPECT_EQ(0, result.error().code());
113 EXPECT_EQ("", result.error().message());
114}
115
116TEST(result, result_error_rvalue) {
117 // Error() and ErrnoError() aren't actually used to create a Result<T> object.
118 // Under the hood, they are an intermediate class that can be implicitly constructed into a
119 // Result<T>. This is needed both to create the ostream and because Error() itself, by
120 // definition will not know what the type, T, of the underlying Result<T> object that it would
121 // create is.
122
123 auto MakeRvalueErrorResult = []() -> Result<Success> { return Error() << "failure" << 1; };
124 ASSERT_FALSE(MakeRvalueErrorResult());
125 ASSERT_FALSE(MakeRvalueErrorResult().has_value());
126
127 EXPECT_EQ(0, MakeRvalueErrorResult().error().code());
128 EXPECT_EQ("failure1", MakeRvalueErrorResult().error().message());
129}
130
131TEST(result, result_errno_error) {
132 constexpr int test_errno = 6;
133 errno = test_errno;
134 Result<Success> result = ErrnoError() << "failure" << 1;
135
136 ASSERT_FALSE(result);
137 ASSERT_FALSE(result.has_value());
138
139 EXPECT_EQ(test_errno, result.error().code());
140 EXPECT_EQ("failure1: "s + strerror(test_errno), result.error().message());
141}
142
143TEST(result, result_errno_error_no_text) {
144 constexpr int test_errno = 6;
145 errno = test_errno;
146 Result<Success> result = ErrnoError();
147
148 ASSERT_FALSE(result);
149 ASSERT_FALSE(result.has_value());
150
151 EXPECT_EQ(test_errno, result.error().code());
152 EXPECT_EQ(strerror(test_errno), result.error().message());
153}
154
155TEST(result, result_error_from_other_result) {
156 auto error_text = "test error"s;
157 Result<Success> result = Error() << error_text;
158
159 ASSERT_FALSE(result);
160 ASSERT_FALSE(result.has_value());
161
162 Result<std::string> result2 = result.error();
163
164 ASSERT_FALSE(result2);
165 ASSERT_FALSE(result2.has_value());
166
167 EXPECT_EQ(0, result.error().code());
168 EXPECT_EQ(error_text, result.error().message());
169}
170
171TEST(result, result_error_through_ostream) {
172 auto error_text = "test error"s;
173 Result<Success> result = Error() << error_text;
174
175 ASSERT_FALSE(result);
176 ASSERT_FALSE(result.has_value());
177
178 Result<std::string> result2 = Error() << result.error();
179
180 ASSERT_FALSE(result2);
181 ASSERT_FALSE(result2.has_value());
182
183 EXPECT_EQ(0, result.error().code());
184 EXPECT_EQ(error_text, result.error().message());
185}
186
187TEST(result, result_errno_error_through_ostream) {
188 auto error_text = "test error"s;
189 constexpr int test_errno = 6;
190 errno = 6;
191 Result<Success> result = ErrnoError() << error_text;
192
193 errno = 0;
194
195 ASSERT_FALSE(result);
196 ASSERT_FALSE(result.has_value());
197
198 Result<std::string> result2 = Error() << result.error();
199
200 ASSERT_FALSE(result2);
201 ASSERT_FALSE(result2.has_value());
202
203 EXPECT_EQ(test_errno, result.error().code());
204 EXPECT_EQ(error_text + ": " + strerror(test_errno), result.error().message());
205}
206
207TEST(result, constructor_forwarding) {
208 auto result = Result<std::string>(std::in_place, 5, 'a');
209
210 ASSERT_TRUE(result);
211 ASSERT_TRUE(result.has_value());
212
213 EXPECT_EQ("aaaaa", *result);
214}
215
216struct ConstructorTracker {
217 static size_t constructor_called;
218 static size_t copy_constructor_called;
219 static size_t move_constructor_called;
220 static size_t copy_assignment_called;
221 static size_t move_assignment_called;
222
223 template <typename T>
224 ConstructorTracker(T&& string) : string(string) {
225 ++constructor_called;
226 }
227
228 ConstructorTracker(const ConstructorTracker& ct) {
229 ++copy_constructor_called;
230 string = ct.string;
231 }
232 ConstructorTracker(ConstructorTracker&& ct) noexcept {
233 ++move_constructor_called;
234 string = std::move(ct.string);
235 }
236 ConstructorTracker& operator=(const ConstructorTracker& ct) {
237 ++copy_assignment_called;
238 string = ct.string;
239 return *this;
240 }
241 ConstructorTracker& operator=(ConstructorTracker&& ct) noexcept {
242 ++move_assignment_called;
243 string = std::move(ct.string);
244 return *this;
245 }
246
247 std::string string;
248};
249
250size_t ConstructorTracker::constructor_called = 0;
251size_t ConstructorTracker::copy_constructor_called = 0;
252size_t ConstructorTracker::move_constructor_called = 0;
253size_t ConstructorTracker::copy_assignment_called = 0;
254size_t ConstructorTracker::move_assignment_called = 0;
255
256Result<ConstructorTracker> ReturnConstructorTracker(const std::string& in) {
257 if (in.empty()) {
258 return "literal string";
259 }
260 if (in == "test2") {
261 return ConstructorTracker(in + in + "2");
262 }
263 ConstructorTracker result(in + " " + in);
264 return result;
265};
266
267TEST(result, no_copy_on_return) {
268 // If returning parameters that may be used to implicitly construct the type T of Result<T>,
269 // then those parameters are forwarded to the construction of Result<T>.
270
271 // If returning an prvalue or xvalue, it will be move constructed during the construction of
272 // Result<T>.
273
274 // This check ensures that that is the case, and particularly that no copy constructors
275 // are called.
276
277 auto result1 = ReturnConstructorTracker("");
278 ASSERT_TRUE(result1);
279 EXPECT_EQ("literal string", result1->string);
280 EXPECT_EQ(1U, ConstructorTracker::constructor_called);
281 EXPECT_EQ(0U, ConstructorTracker::copy_constructor_called);
282 EXPECT_EQ(0U, ConstructorTracker::move_constructor_called);
283 EXPECT_EQ(0U, ConstructorTracker::copy_assignment_called);
284 EXPECT_EQ(0U, ConstructorTracker::move_assignment_called);
285
286 auto result2 = ReturnConstructorTracker("test2");
287 ASSERT_TRUE(result2);
288 EXPECT_EQ("test2test22", result2->string);
289 EXPECT_EQ(2U, ConstructorTracker::constructor_called);
290 EXPECT_EQ(0U, ConstructorTracker::copy_constructor_called);
291 EXPECT_EQ(1U, ConstructorTracker::move_constructor_called);
292 EXPECT_EQ(0U, ConstructorTracker::copy_assignment_called);
293 EXPECT_EQ(0U, ConstructorTracker::move_assignment_called);
294
295 auto result3 = ReturnConstructorTracker("test3");
296 ASSERT_TRUE(result3);
297 EXPECT_EQ("test3 test3", result3->string);
298 EXPECT_EQ(3U, ConstructorTracker::constructor_called);
299 EXPECT_EQ(0U, ConstructorTracker::copy_constructor_called);
300 EXPECT_EQ(2U, ConstructorTracker::move_constructor_called);
301 EXPECT_EQ(0U, ConstructorTracker::copy_assignment_called);
302 EXPECT_EQ(0U, ConstructorTracker::move_assignment_called);
303}
304
305// Below two tests require that we do not hide the move constructor with our forwarding reference
306// constructor. This is done with by disabling the forwarding reference constructor if its first
307// and only type is Result<T>.
308TEST(result, result_result_with_success) {
309 auto return_result_result_with_success = []() -> Result<Result<Success>> {
310 return Result<Success>();
311 };
312 auto result = return_result_result_with_success();
313 ASSERT_TRUE(result);
314 ASSERT_TRUE(*result);
315
316 auto inner_result = result.value();
317 ASSERT_TRUE(inner_result);
318}
319
320TEST(result, result_result_with_failure) {
321 auto return_result_result_with_error = []() -> Result<Result<Success>> {
322 return Result<Success>(ResultError("failure string", 6));
323 };
324 auto result = return_result_result_with_error();
325 ASSERT_TRUE(result);
326 ASSERT_FALSE(*result);
327 EXPECT_EQ("failure string", (*result).error().message());
328 EXPECT_EQ(6, (*result).error().code());
329}
330
331// This test requires that we disable the forwarding reference constructor if Result<T> is the
332// *only* type that we are forwarding. In otherwords, if we are forwarding Result<T>, int to
333// construct a Result<T>, then we still need the constructor.
334TEST(result, result_two_parameter_constructor_same_type) {
335 struct TestStruct {
336 TestStruct(int value) : value_(value) {}
337 TestStruct(Result<TestStruct> result, int value) : value_(result->value_ * value) {}
338 int value_;
339 };
340
341 auto return_test_struct = []() -> Result<TestStruct> {
342 return Result<TestStruct>(std::in_place, Result<TestStruct>(std::in_place, 6), 6);
343 };
344
345 auto result = return_test_struct();
346 ASSERT_TRUE(result);
347 EXPECT_EQ(36, result->value_);
348}
349
350TEST(result, die_on_access_failed_result) {
351 Result<std::string> result = Error();
352 ASSERT_DEATH(*result, "");
353}
354
355TEST(result, die_on_get_error_succesful_result) {
356 Result<std::string> result = "success";
357 ASSERT_DEATH(result.error(), "");
358}
359
360template <class CharT>
361std::basic_ostream<CharT>& SetErrnoToTwo(std::basic_ostream<CharT>& ss) {
362 errno = 2;
363 return ss;
364}
365
366TEST(result, preserve_errno) {
367 errno = 1;
368 int old_errno = errno;
369 Result<int> result = Error() << "Failed" << SetErrnoToTwo<char>;
370 ASSERT_FALSE(result);
371 EXPECT_EQ(old_errno, errno);
372
373 errno = 1;
374 old_errno = errno;
375 Result<int> result2 = ErrnoError() << "Failed" << SetErrnoToTwo<char>;
376 ASSERT_FALSE(result2);
377 EXPECT_EQ(old_errno, errno);
378 EXPECT_EQ(old_errno, result2.error().code());
379}
380
381} // namespace base
382} // namespace android