blob: 327b4444f1a91341eaf06cc778e3b60e8759b1d4 [file] [log] [blame]
Tom Cherry11a3aee2017-08-03 12:54:07 -07001/*
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 "result.h"
18
19#include "errno.h"
20
21#include <string>
22
23#include <gtest/gtest.h>
24
25using namespace std::string_literals;
26
27namespace android {
28namespace init {
29
30TEST(result, result_accessors) {
31 Result<std::string> result = "success";
32 ASSERT_TRUE(result);
33 ASSERT_TRUE(result.has_value());
34
35 EXPECT_EQ("success", *result);
36 EXPECT_EQ("success", result.value());
37
38 EXPECT_EQ('s', result->data()[0]);
39}
40
41TEST(result, result_accessors_rvalue) {
42 ASSERT_TRUE(Result<std::string>("success"));
43 ASSERT_TRUE(Result<std::string>("success").has_value());
44
45 EXPECT_EQ("success", *Result<std::string>("success"));
46 EXPECT_EQ("success", Result<std::string>("success").value());
47
48 EXPECT_EQ('s', Result<std::string>("success")->data()[0]);
49}
50
51TEST(result, result_success) {
52 Result<Success> result = Success();
53 ASSERT_TRUE(result);
54 ASSERT_TRUE(result.has_value());
55
56 EXPECT_EQ(Success(), *result);
57 EXPECT_EQ(Success(), result.value());
58}
59
60TEST(result, result_success_rvalue) {
61 // Success() doesn't actually create a Result<Success> object, but rather an object that can be
62 // implicitly constructed into a Result<Success> object.
63
64 auto MakeRvalueSuccessResult = []() -> Result<Success> { return Success(); };
65 ASSERT_TRUE(MakeRvalueSuccessResult());
66 ASSERT_TRUE(MakeRvalueSuccessResult().has_value());
67
68 EXPECT_EQ(Success(), *MakeRvalueSuccessResult());
69 EXPECT_EQ(Success(), MakeRvalueSuccessResult().value());
70}
71
72TEST(result, result_error) {
73 Result<Success> result = Error() << "failure" << 1;
74 ASSERT_FALSE(result);
75 ASSERT_FALSE(result.has_value());
76
Tom Cherry130e3d72017-08-22 16:07:15 -070077 EXPECT_EQ(0, result.error_errno());
78 EXPECT_EQ("failure1", result.error_string());
Tom Cherry11a3aee2017-08-03 12:54:07 -070079}
80
81TEST(result, result_error_empty) {
82 Result<Success> result = Error();
83 ASSERT_FALSE(result);
84 ASSERT_FALSE(result.has_value());
85
Tom Cherry130e3d72017-08-22 16:07:15 -070086 EXPECT_EQ(0, result.error_errno());
87 EXPECT_EQ("", result.error_string());
Tom Cherry11a3aee2017-08-03 12:54:07 -070088}
89
90TEST(result, result_error_rvalue) {
91 // Error() and ErrnoError() aren't actually used to create a Result<T> object.
92 // Under the hood, they are an intermediate class that can be implicitly constructed into a
93 // Result<T>. This is needed both to create the ostream and because Error() itself, by
94 // definition will not know what the type, T, of the underlying Result<T> object that it would
95 // create is.
96
97 auto MakeRvalueErrorResult = []() -> Result<Success> { return Error() << "failure" << 1; };
98 ASSERT_FALSE(MakeRvalueErrorResult());
99 ASSERT_FALSE(MakeRvalueErrorResult().has_value());
100
Tom Cherry130e3d72017-08-22 16:07:15 -0700101 EXPECT_EQ(0, MakeRvalueErrorResult().error_errno());
102 EXPECT_EQ("failure1", MakeRvalueErrorResult().error_string());
Tom Cherry11a3aee2017-08-03 12:54:07 -0700103}
104
105TEST(result, result_errno_error) {
106 constexpr int test_errno = 6;
107 errno = test_errno;
108 Result<Success> result = ErrnoError() << "failure" << 1;
109
110 ASSERT_FALSE(result);
111 ASSERT_FALSE(result.has_value());
112
Tom Cherry130e3d72017-08-22 16:07:15 -0700113 EXPECT_EQ(test_errno, result.error_errno());
114 EXPECT_EQ("failure1: "s + strerror(test_errno), result.error_string());
115}
116
117TEST(result, result_errno_error_no_text) {
118 constexpr int test_errno = 6;
119 errno = test_errno;
120 Result<Success> result = ErrnoError();
121
122 ASSERT_FALSE(result);
123 ASSERT_FALSE(result.has_value());
124
125 EXPECT_EQ(test_errno, result.error_errno());
126 EXPECT_EQ(strerror(test_errno), result.error_string());
127}
128
129TEST(result, result_error_from_other_result) {
130 auto error_text = "test error"s;
131 Result<Success> result = Error() << error_text;
132
133 ASSERT_FALSE(result);
134 ASSERT_FALSE(result.has_value());
135
136 Result<std::string> result2 = result.error();
137
138 ASSERT_FALSE(result2);
139 ASSERT_FALSE(result2.has_value());
140
141 EXPECT_EQ(0, result.error_errno());
142 EXPECT_EQ(error_text, result.error_string());
143}
144
145TEST(result, result_error_through_ostream) {
146 auto error_text = "test error"s;
147 Result<Success> result = Error() << error_text;
148
149 ASSERT_FALSE(result);
150 ASSERT_FALSE(result.has_value());
151
152 Result<std::string> result2 = Error() << result.error();
153
154 ASSERT_FALSE(result2);
155 ASSERT_FALSE(result2.has_value());
156
157 EXPECT_EQ(0, result.error_errno());
158 EXPECT_EQ(error_text, result.error_string());
159}
160
161TEST(result, result_errno_error_through_ostream) {
162 auto error_text = "test error"s;
163 constexpr int test_errno = 6;
164 errno = 6;
165 Result<Success> result = ErrnoError() << error_text;
166
167 errno = 0;
168
169 ASSERT_FALSE(result);
170 ASSERT_FALSE(result.has_value());
171
172 Result<std::string> result2 = Error() << result.error();
173
174 ASSERT_FALSE(result2);
175 ASSERT_FALSE(result2.has_value());
176
177 EXPECT_EQ(test_errno, result.error_errno());
178 EXPECT_EQ(error_text + ": " + strerror(test_errno), result.error_string());
Tom Cherry11a3aee2017-08-03 12:54:07 -0700179}
180
181TEST(result, constructor_forwarding) {
182 auto result = Result<std::string>(5, 'a');
183
184 ASSERT_TRUE(result);
185 ASSERT_TRUE(result.has_value());
186
187 EXPECT_EQ("aaaaa", *result);
188}
189
190struct ConstructorTracker {
191 static size_t constructor_called;
192 static size_t copy_constructor_called;
193 static size_t move_constructor_called;
194 static size_t copy_assignment_called;
195 static size_t move_assignment_called;
196
197 template <typename T>
198 ConstructorTracker(T&& string) : string(string) {
199 ++constructor_called;
200 }
201
202 ConstructorTracker(const ConstructorTracker& ct) {
203 ++copy_constructor_called;
204 string = ct.string;
205 }
206 ConstructorTracker(ConstructorTracker&& ct) noexcept {
207 ++move_constructor_called;
208 string = std::move(ct.string);
209 }
210 ConstructorTracker& operator=(const ConstructorTracker& ct) {
211 ++copy_assignment_called;
212 string = ct.string;
213 return *this;
214 }
215 ConstructorTracker& operator=(ConstructorTracker&& ct) noexcept {
216 ++move_assignment_called;
217 string = std::move(ct.string);
218 return *this;
219 }
220
221 std::string string;
222};
223
224size_t ConstructorTracker::constructor_called = 0;
225size_t ConstructorTracker::copy_constructor_called = 0;
226size_t ConstructorTracker::move_constructor_called = 0;
227size_t ConstructorTracker::copy_assignment_called = 0;
228size_t ConstructorTracker::move_assignment_called = 0;
229
230Result<ConstructorTracker> ReturnConstructorTracker(const std::string& in) {
231 if (in.empty()) {
232 return "literal string";
233 }
234 if (in == "test2") {
235 return ConstructorTracker(in + in + "2");
236 }
237 ConstructorTracker result(in + " " + in);
238 return result;
239};
240
241TEST(result, no_copy_on_return) {
242 // If returning parameters that may be used to implicitly construct the type T of Result<T>,
243 // then those parameters are forwarded to the construction of Result<T>.
244
245 // If returning an prvalue or xvalue, it will be move constructed during the construction of
246 // Result<T>.
247
248 // This check ensures that that is the case, and particularly that no copy constructors
249 // are called.
250
251 auto result1 = ReturnConstructorTracker("");
252 ASSERT_TRUE(result1);
253 EXPECT_EQ("literal string", result1->string);
254 EXPECT_EQ(1U, ConstructorTracker::constructor_called);
255 EXPECT_EQ(0U, ConstructorTracker::copy_constructor_called);
256 EXPECT_EQ(0U, ConstructorTracker::move_constructor_called);
257 EXPECT_EQ(0U, ConstructorTracker::copy_assignment_called);
258 EXPECT_EQ(0U, ConstructorTracker::move_assignment_called);
259
260 auto result2 = ReturnConstructorTracker("test2");
261 ASSERT_TRUE(result2);
262 EXPECT_EQ("test2test22", result2->string);
263 EXPECT_EQ(2U, ConstructorTracker::constructor_called);
264 EXPECT_EQ(0U, ConstructorTracker::copy_constructor_called);
265 EXPECT_EQ(1U, ConstructorTracker::move_constructor_called);
266 EXPECT_EQ(0U, ConstructorTracker::copy_assignment_called);
267 EXPECT_EQ(0U, ConstructorTracker::move_assignment_called);
268
269 auto result3 = ReturnConstructorTracker("test3");
270 ASSERT_TRUE(result3);
271 EXPECT_EQ("test3 test3", result3->string);
272 EXPECT_EQ(3U, ConstructorTracker::constructor_called);
273 EXPECT_EQ(0U, ConstructorTracker::copy_constructor_called);
274 EXPECT_EQ(2U, ConstructorTracker::move_constructor_called);
275 EXPECT_EQ(0U, ConstructorTracker::copy_assignment_called);
276 EXPECT_EQ(0U, ConstructorTracker::move_assignment_called);
277}
278
Tom Cherryd1c9cd02017-09-12 14:44:56 -0700279// Below two tests require that we do not hide the move constructor with our forwarding reference
280// constructor. This is done with by disabling the forwarding reference constructor if its first
281// and only type is Result<T>.
282TEST(result, result_result_with_success) {
283 auto return_result_result_with_success = []() -> Result<Result<Success>> {
284 return Result<Success>();
285 };
286 auto result = return_result_result_with_success();
287 ASSERT_TRUE(result);
288 ASSERT_TRUE(*result);
289
290 auto inner_result = result.value();
291 ASSERT_TRUE(inner_result);
292}
293
294TEST(result, result_result_with_failure) {
295 auto return_result_result_with_error = []() -> Result<Result<Success>> {
296 return Result<Success>(ResultError("failure string", 6));
297 };
298 auto result = return_result_result_with_error();
299 ASSERT_TRUE(result);
300 ASSERT_FALSE(*result);
301 EXPECT_EQ("failure string", result->error_string());
302 EXPECT_EQ(6, result->error_errno());
303}
304
305// This test requires that we disable the forwarding reference constructor if Result<T> is the
306// *only* type that we are forwarding. In otherwords, if we are forwarding Result<T>, int to
307// construct a Result<T>, then we still need the constructor.
308TEST(result, result_two_parameter_constructor_same_type) {
309 struct TestStruct {
310 TestStruct(int value) : value_(value) {}
311 TestStruct(Result<TestStruct> result, int value) : value_(result->value_ * value) {}
312 int value_;
313 };
314
315 auto return_test_struct = []() -> Result<TestStruct> { return {Result<TestStruct>(6), 6}; };
316
317 auto result = return_test_struct();
318 ASSERT_TRUE(result);
319 EXPECT_EQ(36, result->value_);
320}
321
Tom Cherry11a3aee2017-08-03 12:54:07 -0700322TEST(result, die_on_access_failed_result) {
323 Result<std::string> result = Error();
324 ASSERT_DEATH(*result, "");
325}
326
327TEST(result, die_on_get_error_succesful_result) {
328 Result<std::string> result = "success";
Tom Cherry130e3d72017-08-22 16:07:15 -0700329 ASSERT_DEATH(result.error_string(), "");
Tom Cherry11a3aee2017-08-03 12:54:07 -0700330}
331
332} // namespace init
333} // namespace android