1/*
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
77    EXPECT_EQ(0, result.error_errno());
78    EXPECT_EQ("failure1", result.error_string());
79}
80
81TEST(result, result_error_empty) {
82    Result<Success> result = Error();
83    ASSERT_FALSE(result);
84    ASSERT_FALSE(result.has_value());
85
86    EXPECT_EQ(0, result.error_errno());
87    EXPECT_EQ("", result.error_string());
88}
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
101    EXPECT_EQ(0, MakeRvalueErrorResult().error_errno());
102    EXPECT_EQ("failure1", MakeRvalueErrorResult().error_string());
103}
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
113    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());
179}
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
279// 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
322TEST(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";
329    ASSERT_DEATH(result.error_string(), "");
330}
331
332}  // namespace init
333}  // namespace android
334