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
22namespace panda::test::expected {
23
24enum class ErrorCode { First, Second };
25
26static 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
38struct Default {
39    int v;
40};
41
42struct NonDefaultConstructible {
43    NonDefaultConstructible() = delete;
44};
45
46TEST(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
55TEST(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
80TEST(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
92TEST(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
104TEST(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
117TEST(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