1 /**
2  * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "utils/expected.h"
17 
18 #include <gtest/gtest.h>
19 
20 #include <type_traits>
21 
22 namespace panda::test::expected {
23 
24 enum class ErrorCode { First, Second };
25 
helper(int v)26 static Expected<int, ErrorCode> helper(int v)
27 {
28     switch (v) {
29         case 0:
30             return Unexpected {ErrorCode::First};
31         case 1:
32             return {42};
33         default:
34             return Unexpected {ErrorCode::Second};
35     }
36 }
37 
38 struct Default {
39     int v;
40 };
41 
42 struct NonDefaultConstructible {
43     NonDefaultConstructible() = delete;
44 };
45 
TEST(Expected, Unexpected)46 TEST(Expected, Unexpected)
47 {
48     int e = 1;
49     auto u = Unexpected(e);
50     EXPECT_EQ(Unexpected<int>(1).Value(), 1);
51     EXPECT_EQ(u.Value(), 1);
52     EXPECT_EQ(static_cast<const Unexpected<int> &>(u).Value(), 1);
53 }
54 
TEST(Expected, Ctor)55 TEST(Expected, Ctor)
56 {
57     int v = 1;
58     auto e = Expected<int, ErrorCode>(v);
59     EXPECT_TRUE(e);
60     EXPECT_EQ(e.Value(), 1);
61     EXPECT_EQ(*e, 1);
62 
63     auto e0 = Expected<int, ErrorCode>();
64     EXPECT_EQ(*e0, 0);
65 
66     auto e1 = Expected<int, ErrorCode>(2);
67     EXPECT_EQ(e1.Value(), 2);
68 
69     auto e2 = Expected<int, ErrorCode>(Unexpected(ErrorCode::First));
70     auto u = Unexpected(ErrorCode::Second);
71     auto e3 = Expected<int, ErrorCode>(u);
72     EXPECT_FALSE(e2);
73     EXPECT_EQ(e2.Error(), ErrorCode::First);
74     EXPECT_EQ(e3.Error(), ErrorCode::Second);
75 
76     // Default constructor is only enabled if T is default constructible.
77     EXPECT_FALSE((std::is_default_constructible_v<Expected<NonDefaultConstructible, ErrorCode>>));
78 }
79 
TEST(Expected, Access)80 TEST(Expected, Access)
81 {
82     const auto e1 = Expected<int, ErrorCode>(Unexpected(ErrorCode::First));
83     EXPECT_EQ(e1.Error(), ErrorCode::First);
84     EXPECT_EQ((Expected<int, ErrorCode>(Unexpected(ErrorCode::Second)).Error()), ErrorCode::Second);
85     const auto e2 = Expected<int, ErrorCode>(1);
86     EXPECT_EQ(e2.Value(), 1);
87     EXPECT_EQ(*e2, 1);
88     EXPECT_EQ((*Expected<int, ErrorCode>(2)), 2);
89     EXPECT_EQ((Expected<int, ErrorCode>(3).Value()), 3);
90 }
91 
TEST(Expected, Assignment)92 TEST(Expected, Assignment)
93 {
94     auto d = Default {1};
95     Expected<Default, ErrorCode> t = d;
96     t.Value() = Default {2};
97     EXPECT_TRUE(t);
98     EXPECT_EQ((*t).v, 2);
99     t = Unexpected(ErrorCode::First);
100     EXPECT_FALSE(t);
101     EXPECT_EQ(t.Error(), ErrorCode::First);
102 }
103 
TEST(Expected, Basic)104 TEST(Expected, Basic)
105 {
106     auto res1 = helper(0);
107     auto res2 = helper(1);
108     auto res3 = helper(2);
109     EXPECT_FALSE(res1);
110     EXPECT_TRUE(res2);
111     EXPECT_FALSE(res3);
112     EXPECT_EQ(res1.Error(), ErrorCode::First);
113     EXPECT_EQ(*res2, 42);
114     EXPECT_EQ(res3.Error(), ErrorCode::Second);
115 }
116 
TEST(Expected, ValueOr)117 TEST(Expected, ValueOr)
118 {
119     auto res1 = helper(0).ValueOr(1);
120     auto res2 = helper(res1).ValueOr(res1);
121     auto e = Expected<int, ErrorCode>(1);
122     EXPECT_EQ(res1, 1);
123     EXPECT_EQ(res2, 42);
124     EXPECT_EQ(e.ValueOr(0), 1);
125 }
126 }  // namespace panda::test::expected
127