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