xref: /aosp_15_r20/external/pytorch/c10/test/util/optional_test.cpp (revision da0073e96a02ea20f0ac840b70461e3646d07c45)
1 #include <optional>
2 
3 #include <gmock/gmock.h>
4 #include <gtest/gtest.h>
5 
6 #include <array>
7 #include <cstdint>
8 #include <string>
9 
10 #include <c10/util/ArrayRef.h>
11 
12 namespace {
13 
14 using testing::Eq;
15 using testing::Ge;
16 using testing::Gt;
17 using testing::Le;
18 using testing::Lt;
19 using testing::Ne;
20 using testing::Not;
21 
22 template <typename T>
23 class OptionalTest : public ::testing::Test {
24  public:
25   using optional = std::optional<T>;
26 };
27 
28 template <typename T>
29 T getSampleValue();
30 
31 template <>
getSampleValue()32 bool getSampleValue() {
33   return true;
34 }
35 
36 template <>
getSampleValue()37 uint64_t getSampleValue() {
38   return 42;
39 }
40 
41 template <>
getSampleValue()42 c10::IntArrayRef getSampleValue() {
43   return {};
44 }
45 
46 template <>
getSampleValue()47 std::string getSampleValue() {
48   return "hello";
49 }
50 
51 using OptionalTypes = ::testing::Types<
52     // 32-bit scalar optimization.
53     bool,
54     // Trivially destructible but not 32-bit scalar.
55     uint64_t,
56     // ArrayRef optimization.
57     c10::IntArrayRef,
58     // Non-trivial destructor.
59     std::string>;
60 
61 TYPED_TEST_SUITE(OptionalTest, OptionalTypes);
62 
TYPED_TEST(OptionalTest,Empty)63 TYPED_TEST(OptionalTest, Empty) {
64   typename TestFixture::optional empty;
65 
66   EXPECT_FALSE((bool)empty);
67   EXPECT_FALSE(empty.has_value());
68 
69   // NOLINTNEXTLINE(bugprone-unchecked-optional-access,hicpp-avoid-goto,cppcoreguidelines-avoid-goto)
70   EXPECT_THROW(empty.value(), std::bad_optional_access);
71 }
72 
TYPED_TEST(OptionalTest,Initialized)73 TYPED_TEST(OptionalTest, Initialized) {
74   using optional = typename TestFixture::optional;
75 
76   const auto val = getSampleValue<TypeParam>();
77   optional opt((val));
78   auto copy(opt), moveFrom1(opt), moveFrom2(opt);
79   optional move(std::move(moveFrom1));
80   optional copyAssign;
81   copyAssign = opt;
82   optional moveAssign;
83   moveAssign = std::move(moveFrom2);
84 
85   std::array<typename TestFixture::optional*, 5> opts = {
86       &opt, &copy, &copyAssign, &move, &moveAssign};
87   for (auto* popt : opts) {
88     auto& opt = *popt;
89     EXPECT_TRUE((bool)opt);
90     EXPECT_TRUE(opt.has_value());
91 
92     // NOLINTNEXTLINE(bugprone-unchecked-optional-access)
93     EXPECT_EQ(opt.value(), val);
94     // NOLINTNEXTLINE(bugprone-unchecked-optional-access)
95     EXPECT_EQ(*opt, val);
96   }
97 }
98 
99 class SelfCompareTest : public testing::TestWithParam<std::optional<int>> {};
100 
TEST_P(SelfCompareTest,SelfCompare)101 TEST_P(SelfCompareTest, SelfCompare) {
102   std::optional<int> x = GetParam();
103   EXPECT_THAT(x, Eq(x));
104   EXPECT_THAT(x, Le(x));
105   EXPECT_THAT(x, Ge(x));
106   EXPECT_THAT(x, Not(Ne(x)));
107   EXPECT_THAT(x, Not(Lt(x)));
108   EXPECT_THAT(x, Not(Gt(x)));
109 }
110 
111 INSTANTIATE_TEST_SUITE_P(
112     nullopt,
113     SelfCompareTest,
114     testing::Values(std::nullopt));
115 INSTANTIATE_TEST_SUITE_P(
116     int,
117     SelfCompareTest,
118     testing::Values(std::make_optional(2)));
119 
TEST(OptionalTest,Nullopt)120 TEST(OptionalTest, Nullopt) {
121   std::optional<int> x = 2;
122 
123   EXPECT_THAT(std::nullopt, Not(Eq(x)));
124   EXPECT_THAT(x, Not(Eq(std::nullopt)));
125 
126   EXPECT_THAT(x, Ne(std::nullopt));
127   EXPECT_THAT(std::nullopt, Ne(x));
128 
129   EXPECT_THAT(x, Not(Lt(std::nullopt)));
130   EXPECT_THAT(std::nullopt, Lt(x));
131 
132   EXPECT_THAT(x, Not(Le(std::nullopt)));
133   EXPECT_THAT(std::nullopt, Le(x));
134 
135   EXPECT_THAT(x, Gt(std::nullopt));
136   EXPECT_THAT(std::nullopt, Not(Gt(x)));
137 
138   EXPECT_THAT(x, Ge(std::nullopt));
139   EXPECT_THAT(std::nullopt, Not(Ge(x)));
140 }
141 
142 // Ensure comparisons work...
143 using CmpTestTypes = testing::Types<
144     // between two optionals
145     std::pair<std::optional<int>, std::optional<int>>,
146 
147     // between an optional and a value
148     std::pair<std::optional<int>, int>,
149     // between a value and an optional
150     std::pair<int, std::optional<int>>,
151 
152     // between an optional and a differently typed value
153     std::pair<std::optional<int>, long>,
154     // between a differently typed value and an optional
155     std::pair<long, std::optional<int>>>;
156 template <typename T>
157 class CmpTest : public testing::Test {};
158 TYPED_TEST_SUITE(CmpTest, CmpTestTypes);
159 
TYPED_TEST(CmpTest,Cmp)160 TYPED_TEST(CmpTest, Cmp) {
161   TypeParam pair = {2, 3};
162   auto x = pair.first;
163   auto y = pair.second;
164 
165   EXPECT_THAT(x, Not(Eq(y)));
166 
167   EXPECT_THAT(x, Ne(y));
168 
169   EXPECT_THAT(x, Lt(y));
170   EXPECT_THAT(y, Not(Lt(x)));
171 
172   EXPECT_THAT(x, Le(y));
173   EXPECT_THAT(y, Not(Le(x)));
174 
175   EXPECT_THAT(x, Not(Gt(y)));
176   EXPECT_THAT(y, Gt(x));
177 
178   EXPECT_THAT(x, Not(Ge(y)));
179   EXPECT_THAT(y, Ge(x));
180 }
181 
182 } // namespace
183