xref: /aosp_15_r20/frameworks/native/libs/ftl/enum_test.cpp (revision 38e8c45f13ce32b0dcecb25141ffecaf386fa17f)
1*38e8c45fSAndroid Build Coastguard Worker /*
2*38e8c45fSAndroid Build Coastguard Worker  * Copyright 2021 The Android Open Source Project
3*38e8c45fSAndroid Build Coastguard Worker  *
4*38e8c45fSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*38e8c45fSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*38e8c45fSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*38e8c45fSAndroid Build Coastguard Worker  *
8*38e8c45fSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*38e8c45fSAndroid Build Coastguard Worker  *
10*38e8c45fSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*38e8c45fSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*38e8c45fSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*38e8c45fSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*38e8c45fSAndroid Build Coastguard Worker  * limitations under the License.
15*38e8c45fSAndroid Build Coastguard Worker  */
16*38e8c45fSAndroid Build Coastguard Worker 
17*38e8c45fSAndroid Build Coastguard Worker #include <ftl/enum.h>
18*38e8c45fSAndroid Build Coastguard Worker #include <gtest/gtest.h>
19*38e8c45fSAndroid Build Coastguard Worker 
20*38e8c45fSAndroid Build Coastguard Worker namespace android::test {
21*38e8c45fSAndroid Build Coastguard Worker 
22*38e8c45fSAndroid Build Coastguard Worker // Keep in sync with example usage in header file.
23*38e8c45fSAndroid Build Coastguard Worker namespace {
24*38e8c45fSAndroid Build Coastguard Worker 
25*38e8c45fSAndroid Build Coastguard Worker enum class E { A, B, C, F = 5, ftl_last = F };
26*38e8c45fSAndroid Build Coastguard Worker 
27*38e8c45fSAndroid Build Coastguard Worker static_assert(ftl::enum_begin_v<E> == E::A);
28*38e8c45fSAndroid Build Coastguard Worker static_assert(ftl::enum_last_v<E> == E::F);
29*38e8c45fSAndroid Build Coastguard Worker static_assert(ftl::enum_size_v<E> == 6);
30*38e8c45fSAndroid Build Coastguard Worker 
31*38e8c45fSAndroid Build Coastguard Worker static_assert(ftl::enum_name<E::B>() == "B");
32*38e8c45fSAndroid Build Coastguard Worker static_assert(ftl::enum_name<E::ftl_last>() == "F");
33*38e8c45fSAndroid Build Coastguard Worker static_assert(ftl::enum_name(E::C).value_or("?") == "C");
34*38e8c45fSAndroid Build Coastguard Worker static_assert(ftl::enum_name(E{3}).value_or("?") == "?");
35*38e8c45fSAndroid Build Coastguard Worker 
36*38e8c45fSAndroid Build Coastguard Worker static_assert(ftl::enum_name_full<E::B>() == "E::B");
37*38e8c45fSAndroid Build Coastguard Worker static_assert(ftl::enum_name_full<E::ftl_last>() == "E::F");
38*38e8c45fSAndroid Build Coastguard Worker static_assert(ftl::enum_name_full(E::C).value_or("?") == "E::C");
39*38e8c45fSAndroid Build Coastguard Worker static_assert(ftl::enum_name_full(E{3}).value_or("?") == "?");
40*38e8c45fSAndroid Build Coastguard Worker 
41*38e8c45fSAndroid Build Coastguard Worker enum class F : std::uint16_t { X = 0b1, Y = 0b10, Z = 0b100 };
42*38e8c45fSAndroid Build Coastguard Worker 
43*38e8c45fSAndroid Build Coastguard Worker static_assert(ftl::enum_begin_v<F> == F{0});
44*38e8c45fSAndroid Build Coastguard Worker static_assert(ftl::enum_last_v<F> == F{15});
45*38e8c45fSAndroid Build Coastguard Worker static_assert(ftl::enum_size_v<F> == 16);
46*38e8c45fSAndroid Build Coastguard Worker 
47*38e8c45fSAndroid Build Coastguard Worker static_assert(ftl::flag_name(F::Z).value_or("?") == "Z");
48*38e8c45fSAndroid Build Coastguard Worker static_assert(ftl::flag_name(F{0b111}).value_or("?") == "?");
49*38e8c45fSAndroid Build Coastguard Worker 
50*38e8c45fSAndroid Build Coastguard Worker // If a scoped enum is unsigned, its implicit range corresponds to its bit indices.
51*38e8c45fSAndroid Build Coastguard Worker enum class Flags : std::uint8_t {
52*38e8c45fSAndroid Build Coastguard Worker   kNone = 0,
53*38e8c45fSAndroid Build Coastguard Worker   kFlag1 = 0b0000'0010,
54*38e8c45fSAndroid Build Coastguard Worker   kFlag4 = 0b0001'0000,
55*38e8c45fSAndroid Build Coastguard Worker   kFlag7 = 0b1000'0000,
56*38e8c45fSAndroid Build Coastguard Worker   kMask = kFlag1 | kFlag4 | kFlag7,
57*38e8c45fSAndroid Build Coastguard Worker   kAll = 0b1111'1111
58*38e8c45fSAndroid Build Coastguard Worker };
59*38e8c45fSAndroid Build Coastguard Worker 
60*38e8c45fSAndroid Build Coastguard Worker static_assert(ftl::enum_begin_v<Flags> == Flags{0});
61*38e8c45fSAndroid Build Coastguard Worker static_assert(ftl::enum_last_v<Flags> == Flags{7});
62*38e8c45fSAndroid Build Coastguard Worker static_assert(ftl::enum_size_v<Flags> == 8);
63*38e8c45fSAndroid Build Coastguard Worker 
64*38e8c45fSAndroid Build Coastguard Worker static_assert(ftl::enum_name<Flags::kNone>() == "kNone");
65*38e8c45fSAndroid Build Coastguard Worker static_assert(ftl::enum_name<Flags::kFlag4>() == "kFlag4");
66*38e8c45fSAndroid Build Coastguard Worker static_assert(ftl::enum_name<Flags::kFlag7>() == "kFlag7");
67*38e8c45fSAndroid Build Coastguard Worker 
68*38e8c45fSAndroid Build Coastguard Worker static_assert(ftl::enum_name_full<Flags::kNone>() == "Flags::kNone");
69*38e8c45fSAndroid Build Coastguard Worker static_assert(ftl::enum_name_full<Flags::kFlag4>() == "Flags::kFlag4");
70*38e8c45fSAndroid Build Coastguard Worker static_assert(ftl::enum_name_full<Flags::kFlag7>() == "Flags::kFlag7");
71*38e8c45fSAndroid Build Coastguard Worker 
72*38e8c45fSAndroid Build Coastguard Worker // Though not flags, the enumerators are within the implicit range of bit indices.
73*38e8c45fSAndroid Build Coastguard Worker enum class Planet : std::uint8_t {
74*38e8c45fSAndroid Build Coastguard Worker   kMercury,
75*38e8c45fSAndroid Build Coastguard Worker   kVenus,
76*38e8c45fSAndroid Build Coastguard Worker   kEarth,
77*38e8c45fSAndroid Build Coastguard Worker   kMars,
78*38e8c45fSAndroid Build Coastguard Worker   kJupiter,
79*38e8c45fSAndroid Build Coastguard Worker   kSaturn,
80*38e8c45fSAndroid Build Coastguard Worker   kUranus,
81*38e8c45fSAndroid Build Coastguard Worker   kNeptune
82*38e8c45fSAndroid Build Coastguard Worker };
83*38e8c45fSAndroid Build Coastguard Worker 
84*38e8c45fSAndroid Build Coastguard Worker constexpr Planet kPluto{ftl::to_underlying(Planet::kNeptune) + 1};  // Honorable mention.
85*38e8c45fSAndroid Build Coastguard Worker 
86*38e8c45fSAndroid Build Coastguard Worker static_assert(ftl::enum_begin_v<Planet> == Planet::kMercury);
87*38e8c45fSAndroid Build Coastguard Worker static_assert(ftl::enum_last_v<Planet> == Planet::kNeptune);
88*38e8c45fSAndroid Build Coastguard Worker static_assert(ftl::enum_size_v<Planet> == 8);
89*38e8c45fSAndroid Build Coastguard Worker 
90*38e8c45fSAndroid Build Coastguard Worker static_assert(ftl::enum_name<Planet::kMercury>() == "kMercury");
91*38e8c45fSAndroid Build Coastguard Worker static_assert(ftl::enum_name<Planet::kSaturn>() == "kSaturn");
92*38e8c45fSAndroid Build Coastguard Worker 
93*38e8c45fSAndroid Build Coastguard Worker static_assert(ftl::enum_name_full<Planet::kMercury>() == "Planet::kMercury");
94*38e8c45fSAndroid Build Coastguard Worker static_assert(ftl::enum_name_full<Planet::kSaturn>() == "Planet::kSaturn");
95*38e8c45fSAndroid Build Coastguard Worker 
96*38e8c45fSAndroid Build Coastguard Worker // Unscoped enum must define explicit range, even if the underlying type is fixed.
97*38e8c45fSAndroid Build Coastguard Worker enum Temperature : int {
98*38e8c45fSAndroid Build Coastguard Worker   kRoom = 20,
99*38e8c45fSAndroid Build Coastguard Worker   kFridge = 4,
100*38e8c45fSAndroid Build Coastguard Worker   kFreezer = -18,
101*38e8c45fSAndroid Build Coastguard Worker 
102*38e8c45fSAndroid Build Coastguard Worker   ftl_first = kFreezer,
103*38e8c45fSAndroid Build Coastguard Worker   ftl_last = kRoom
104*38e8c45fSAndroid Build Coastguard Worker };
105*38e8c45fSAndroid Build Coastguard Worker 
106*38e8c45fSAndroid Build Coastguard Worker static_assert(ftl::enum_begin_v<Temperature> == kFreezer);
107*38e8c45fSAndroid Build Coastguard Worker static_assert(ftl::enum_last_v<Temperature> == kRoom);
108*38e8c45fSAndroid Build Coastguard Worker static_assert(ftl::enum_size_v<Temperature> == 39);
109*38e8c45fSAndroid Build Coastguard Worker 
110*38e8c45fSAndroid Build Coastguard Worker static_assert(ftl::enum_name<kFreezer>() == "kFreezer");
111*38e8c45fSAndroid Build Coastguard Worker static_assert(ftl::enum_name<kFridge>() == "kFridge");
112*38e8c45fSAndroid Build Coastguard Worker static_assert(ftl::enum_name<kRoom>() == "kRoom");
113*38e8c45fSAndroid Build Coastguard Worker 
114*38e8c45fSAndroid Build Coastguard Worker }  // namespace
115*38e8c45fSAndroid Build Coastguard Worker 
TEST(Enum,Range)116*38e8c45fSAndroid Build Coastguard Worker TEST(Enum, Range) {
117*38e8c45fSAndroid Build Coastguard Worker   std::string string;
118*38e8c45fSAndroid Build Coastguard Worker   for (E v : ftl::enum_range<E>()) {
119*38e8c45fSAndroid Build Coastguard Worker     string += ftl::enum_name(v).value_or("?");
120*38e8c45fSAndroid Build Coastguard Worker   }
121*38e8c45fSAndroid Build Coastguard Worker   EXPECT_EQ(string, "ABC??F");
122*38e8c45fSAndroid Build Coastguard Worker }
123*38e8c45fSAndroid Build Coastguard Worker 
TEST(Enum,Name)124*38e8c45fSAndroid Build Coastguard Worker TEST(Enum, Name) {
125*38e8c45fSAndroid Build Coastguard Worker   {
126*38e8c45fSAndroid Build Coastguard Worker     EXPECT_EQ(ftl::flag_name(Flags::kFlag1), "kFlag1");
127*38e8c45fSAndroid Build Coastguard Worker     EXPECT_EQ(ftl::flag_name(Flags::kFlag7), "kFlag7");
128*38e8c45fSAndroid Build Coastguard Worker 
129*38e8c45fSAndroid Build Coastguard Worker     EXPECT_EQ(ftl::flag_name(Flags::kNone), std::nullopt);
130*38e8c45fSAndroid Build Coastguard Worker     EXPECT_EQ(ftl::flag_name(Flags::kMask), std::nullopt);
131*38e8c45fSAndroid Build Coastguard Worker     EXPECT_EQ(ftl::flag_name(Flags::kAll), std::nullopt);
132*38e8c45fSAndroid Build Coastguard Worker   }
133*38e8c45fSAndroid Build Coastguard Worker   {
134*38e8c45fSAndroid Build Coastguard Worker     EXPECT_EQ(ftl::enum_name(Planet::kEarth), "kEarth");
135*38e8c45fSAndroid Build Coastguard Worker     EXPECT_EQ(ftl::enum_name(Planet::kNeptune), "kNeptune");
136*38e8c45fSAndroid Build Coastguard Worker 
137*38e8c45fSAndroid Build Coastguard Worker     EXPECT_EQ(ftl::enum_name_full(Planet::kEarth), "Planet::kEarth");
138*38e8c45fSAndroid Build Coastguard Worker     EXPECT_EQ(ftl::enum_name_full(Planet::kNeptune), "Planet::kNeptune");
139*38e8c45fSAndroid Build Coastguard Worker 
140*38e8c45fSAndroid Build Coastguard Worker     EXPECT_EQ(ftl::enum_name(kPluto), std::nullopt);
141*38e8c45fSAndroid Build Coastguard Worker     EXPECT_EQ(ftl::enum_name_full(kPluto), std::nullopt);
142*38e8c45fSAndroid Build Coastguard Worker   }
143*38e8c45fSAndroid Build Coastguard Worker   {
144*38e8c45fSAndroid Build Coastguard Worker     EXPECT_EQ(ftl::enum_name(kRoom), "kRoom");
145*38e8c45fSAndroid Build Coastguard Worker     EXPECT_EQ(ftl::enum_name(kFridge), "kFridge");
146*38e8c45fSAndroid Build Coastguard Worker     EXPECT_EQ(ftl::enum_name(kFreezer), "kFreezer");
147*38e8c45fSAndroid Build Coastguard Worker 
148*38e8c45fSAndroid Build Coastguard Worker     EXPECT_EQ(ftl::enum_name(kRoom), "kRoom");
149*38e8c45fSAndroid Build Coastguard Worker     EXPECT_EQ(ftl::enum_name(kFridge), "kFridge");
150*38e8c45fSAndroid Build Coastguard Worker     EXPECT_EQ(ftl::enum_name(kFreezer), "kFreezer");
151*38e8c45fSAndroid Build Coastguard Worker 
152*38e8c45fSAndroid Build Coastguard Worker     EXPECT_EQ(ftl::enum_name(static_cast<Temperature>(-30)), std::nullopt);
153*38e8c45fSAndroid Build Coastguard Worker     EXPECT_EQ(ftl::enum_name(static_cast<Temperature>(0)), std::nullopt);
154*38e8c45fSAndroid Build Coastguard Worker     EXPECT_EQ(ftl::enum_name(static_cast<Temperature>(100)), std::nullopt);
155*38e8c45fSAndroid Build Coastguard Worker 
156*38e8c45fSAndroid Build Coastguard Worker     EXPECT_EQ(ftl::enum_name_full(static_cast<Temperature>(-30)), std::nullopt);
157*38e8c45fSAndroid Build Coastguard Worker     EXPECT_EQ(ftl::enum_name_full(static_cast<Temperature>(0)), std::nullopt);
158*38e8c45fSAndroid Build Coastguard Worker     EXPECT_EQ(ftl::enum_name_full(static_cast<Temperature>(100)), std::nullopt);
159*38e8c45fSAndroid Build Coastguard Worker   }
160*38e8c45fSAndroid Build Coastguard Worker }
161*38e8c45fSAndroid Build Coastguard Worker 
TEST(Enum,String)162*38e8c45fSAndroid Build Coastguard Worker TEST(Enum, String) {
163*38e8c45fSAndroid Build Coastguard Worker   {
164*38e8c45fSAndroid Build Coastguard Worker     EXPECT_EQ(ftl::flag_string(Flags::kFlag1), "kFlag1");
165*38e8c45fSAndroid Build Coastguard Worker     EXPECT_EQ(ftl::flag_string(Flags::kFlag7), "kFlag7");
166*38e8c45fSAndroid Build Coastguard Worker 
167*38e8c45fSAndroid Build Coastguard Worker     EXPECT_EQ(ftl::flag_string(Flags::kNone), "0b0");
168*38e8c45fSAndroid Build Coastguard Worker     EXPECT_EQ(ftl::flag_string(Flags::kMask), "0b10010010");
169*38e8c45fSAndroid Build Coastguard Worker     EXPECT_EQ(ftl::flag_string(Flags::kAll), "0b11111111");
170*38e8c45fSAndroid Build Coastguard Worker 
171*38e8c45fSAndroid Build Coastguard Worker     enum class Flags64 : std::uint64_t {
172*38e8c45fSAndroid Build Coastguard Worker       kFlag0 = 0b1ull,
173*38e8c45fSAndroid Build Coastguard Worker       kFlag63 = 0x8000'0000'0000'0000ull,
174*38e8c45fSAndroid Build Coastguard Worker       kMask = kFlag0 | kFlag63
175*38e8c45fSAndroid Build Coastguard Worker     };
176*38e8c45fSAndroid Build Coastguard Worker 
177*38e8c45fSAndroid Build Coastguard Worker     EXPECT_EQ(ftl::flag_string(Flags64::kFlag0), "kFlag0");
178*38e8c45fSAndroid Build Coastguard Worker     EXPECT_EQ(ftl::flag_string(Flags64::kFlag63), "kFlag63");
179*38e8c45fSAndroid Build Coastguard Worker     EXPECT_EQ(ftl::flag_string(Flags64::kMask), "0x8000000000000001");
180*38e8c45fSAndroid Build Coastguard Worker   }
181*38e8c45fSAndroid Build Coastguard Worker   {
182*38e8c45fSAndroid Build Coastguard Worker     EXPECT_EQ(ftl::enum_string(Planet::kEarth), "kEarth");
183*38e8c45fSAndroid Build Coastguard Worker     EXPECT_EQ(ftl::enum_string(Planet::kNeptune), "kNeptune");
184*38e8c45fSAndroid Build Coastguard Worker 
185*38e8c45fSAndroid Build Coastguard Worker     EXPECT_EQ(ftl::enum_string_full(Planet::kEarth), "Planet::kEarth");
186*38e8c45fSAndroid Build Coastguard Worker     EXPECT_EQ(ftl::enum_string_full(Planet::kNeptune), "Planet::kNeptune");
187*38e8c45fSAndroid Build Coastguard Worker 
188*38e8c45fSAndroid Build Coastguard Worker     EXPECT_EQ(ftl::enum_string(kPluto), "8");
189*38e8c45fSAndroid Build Coastguard Worker 
190*38e8c45fSAndroid Build Coastguard Worker     EXPECT_EQ(ftl::enum_string_full(kPluto), "8");
191*38e8c45fSAndroid Build Coastguard Worker 
192*38e8c45fSAndroid Build Coastguard Worker   }
193*38e8c45fSAndroid Build Coastguard Worker   {
194*38e8c45fSAndroid Build Coastguard Worker     EXPECT_EQ(ftl::enum_string(kRoom), "kRoom");
195*38e8c45fSAndroid Build Coastguard Worker     EXPECT_EQ(ftl::enum_string(kFridge), "kFridge");
196*38e8c45fSAndroid Build Coastguard Worker     EXPECT_EQ(ftl::enum_string(kFreezer), "kFreezer");
197*38e8c45fSAndroid Build Coastguard Worker 
198*38e8c45fSAndroid Build Coastguard Worker     EXPECT_EQ(ftl::enum_string_full(kRoom), "20");
199*38e8c45fSAndroid Build Coastguard Worker     EXPECT_EQ(ftl::enum_string_full(kFridge), "4");
200*38e8c45fSAndroid Build Coastguard Worker     EXPECT_EQ(ftl::enum_string_full(kFreezer), "-18");
201*38e8c45fSAndroid Build Coastguard Worker 
202*38e8c45fSAndroid Build Coastguard Worker     EXPECT_EQ(ftl::enum_string(static_cast<Temperature>(-30)), "-30");
203*38e8c45fSAndroid Build Coastguard Worker     EXPECT_EQ(ftl::enum_string(static_cast<Temperature>(0)), "0");
204*38e8c45fSAndroid Build Coastguard Worker     EXPECT_EQ(ftl::enum_string(static_cast<Temperature>(100)), "100");
205*38e8c45fSAndroid Build Coastguard Worker 
206*38e8c45fSAndroid Build Coastguard Worker     EXPECT_EQ(ftl::enum_string_full(static_cast<Temperature>(-30)), "-30");
207*38e8c45fSAndroid Build Coastguard Worker     EXPECT_EQ(ftl::enum_string_full(static_cast<Temperature>(0)), "0");
208*38e8c45fSAndroid Build Coastguard Worker     EXPECT_EQ(ftl::enum_string_full(static_cast<Temperature>(100)), "100");
209*38e8c45fSAndroid Build Coastguard Worker   }
210*38e8c45fSAndroid Build Coastguard Worker }
211*38e8c45fSAndroid Build Coastguard Worker 
212*38e8c45fSAndroid Build Coastguard Worker }  // namespace android::test
213