xref: /aosp_15_r20/external/emboss/compiler/back_end/cpp/testcode/enum_test.cc (revision 99e0aae7469b87d12f0ad23e61142c2d74c1ef70)
1 // Copyright 2019 Google LLC
2 //
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 //     https://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 // Tests for the generated View class for Container and Box from
16 // nested_structure.emb.
17 //
18 // These tests check that nested structures work.
19 #include <array>
20 #include <cstdint>
21 #include <sstream>
22 #include <string>
23 #include <type_traits>
24 #include <vector>
25 
26 #include "gtest/gtest.h"
27 #include "testdata/enum.emb.h"
28 
29 namespace emboss {
30 namespace test {
31 namespace {
32 
33 static_assert(
34     ::std::is_same</**/ ::std::uint64_t,
35                    ::std::underlying_type<OnlyShortValues>::type>::value,
36     "Emboss enums should default to 64-bit.");
37 static_assert(
38     ::std::is_same</**/ ::std::int64_t,
39                    ::std::underlying_type<OnlyShortSignedValues>::type>::value,
40     "Emboss enums should default to 64-bit.");
41 static_assert(
42     ::std::is_same</**/ ::std::int64_t,
43                    ::std::underlying_type<ExplicitlySigned>::type>::value,
44     "Emboss enum with explicit is_signed = true should be signed.");
45 static_assert(
46     ::std::is_same</**/ ::std::int64_t,
47                    ::std::underlying_type<ExplicitlySigned>::type>::value,
48     "Emboss enum with explicit is_signed = true should be signed.");
49 static_assert(
50     ::std::is_same</**/ ::std::uint64_t,
51                    ::std::underlying_type<ExplicitlySized64>::type>::value,
52     "Emboss enum with maximum_bits = 64 should be uint64_t.");
53 static_assert(
54     ::std::is_same</**/ ::std::uint32_t,
55                    ::std::underlying_type<ExplicitlySized32>::type>::value,
56     "Emboss enum with maximum_bits = 32 should be uint32_t.");
57 static_assert(
58     ::std::is_same</**/ ::std::uint16_t,
59                    ::std::underlying_type<ExplicitlySized16>::type>::value,
60     "Emboss enum with maximum_bits = 16 should be uint16_t.");
61 static_assert(
62     ::std::is_same</**/ ::std::uint8_t,
63                    ::std::underlying_type<ExplicitlySized8>::type>::value,
64     "Emboss enum with maximum_bits = 8 should be uint8_t.");
65 static_assert(
66     ::std::is_same<
67         /**/ ::std::int32_t,
68         ::std::underlying_type<ExplicitlySizedAndSigned>::type>::value,
69     "Emboss enum with maximum_bits = 32 and is_signed = true should be "
70     "int32_t.");
71 static_assert(
72     ::std::is_same</**/ ::std::uint16_t,
73                    ::std::underlying_type<ExplicitlySized12>::type>::value,
74     "Emboss enum with maximum_bits = 12 should be uint16_t.");
75 
76 alignas(8) static const ::std::uint8_t kManifestEntry[14] = {
77     0x01,                          // 0:1  Kind  kind == SPROCKET
78     0x04, 0x00, 0x00, 0x00,        // 1:5  UInt  count == 4
79     0x02, 0x00, 0x00, 0x00,        // 5:9  Kind  wide_kind == GEEGAW
80     0x20, 0x00, 0x00, 0x00, 0x00,  // 9:14 Kind  wide_kind_in_bits == GEEGAW
81 };
82 
TEST(ManifestEntryView,CanReadKind)83 TEST(ManifestEntryView, CanReadKind) {
84   auto view = MakeAlignedManifestEntryView<const ::std::uint8_t, 8>(
85       kManifestEntry, sizeof kManifestEntry);
86   EXPECT_EQ(Kind::SPROCKET, view.kind().Read());
87   EXPECT_EQ(Kind::GEEGAW, view.wide_kind().Read());
88   EXPECT_EQ(Kind::GEEGAW, view.wide_kind_in_bits().Read());
89 }
90 
TEST(ManifestEntryView,Equals)91 TEST(ManifestEntryView, Equals) {
92   ::std::array</**/ ::std::uint8_t, sizeof kManifestEntry> buf_x;
93   ::std::array</**/ ::std::uint8_t, sizeof kManifestEntry> buf_y;
94 
95   ::std::copy(kManifestEntry, kManifestEntry + sizeof kManifestEntry,
96               buf_x.begin());
97   ::std::copy(kManifestEntry, kManifestEntry + sizeof kManifestEntry,
98               buf_y.begin());
99 
100   EXPECT_EQ(buf_x, buf_y);
101   auto x = MakeManifestEntryView(&buf_x);
102   auto x_const = MakeManifestEntryView(
103       static_cast</**/ ::std::array</**/ ::std::uint8_t, sizeof kManifestEntry>
104                       *>(&buf_x));
105   auto y = MakeManifestEntryView(&buf_y);
106 
107   EXPECT_TRUE(x.Equals(x));
108   EXPECT_TRUE(x.UncheckedEquals(x));
109   EXPECT_TRUE(y.Equals(y));
110   EXPECT_TRUE(y.UncheckedEquals(y));
111 
112   EXPECT_TRUE(x.Equals(y));
113   EXPECT_TRUE(x.UncheckedEquals(y));
114   EXPECT_TRUE(y.Equals(x));
115   EXPECT_TRUE(y.UncheckedEquals(x));
116 
117   EXPECT_TRUE(x_const.Equals(y));
118   EXPECT_TRUE(x_const.UncheckedEquals(y));
119   EXPECT_TRUE(y.Equals(x_const));
120   EXPECT_TRUE(y.UncheckedEquals(x_const));
121 
122   ++buf_y[1];
123   EXPECT_FALSE(x.Equals(y));
124   EXPECT_FALSE(x.UncheckedEquals(y));
125   EXPECT_FALSE(y.Equals(x));
126   EXPECT_FALSE(y.UncheckedEquals(x));
127 
128   EXPECT_FALSE(x_const.Equals(y));
129   EXPECT_FALSE(x_const.UncheckedEquals(y));
130   EXPECT_FALSE(y.Equals(x_const));
131   EXPECT_FALSE(y.UncheckedEquals(x_const));
132 }
133 
134 static const ::std::uint8_t kManifestEntryEdgeCases[14] = {
135     0xff,                          // 0:1  Kind  kind == 0x0f
136     0x04, 0x00, 0x00, 0x00,        // 1:5  UInt  count == 4
137     0xff, 0xff, 0xff, 0xff,        // 5:9  Kind  wide_kind == MAX32BIT
138     0xf0, 0xff, 0xff, 0xff, 0x0f,  // 9:14 Kind  wide_kind_in_bits == GEEGAW
139 };
140 
TEST(ManifestEntryView,EdgeCases)141 TEST(ManifestEntryView, EdgeCases) {
142   auto view = ManifestEntryView(kManifestEntryEdgeCases,
143                                 sizeof kManifestEntryEdgeCases);
144   EXPECT_EQ(static_cast<Kind>(255), view.kind().Read());
145   EXPECT_EQ(255U, static_cast</**/ ::std::uint64_t>(view.kind().Read()));
146   EXPECT_EQ(Kind::MAX32BIT, view.wide_kind().Read());
147   EXPECT_EQ(Kind::MAX32BIT, view.wide_kind_in_bits().Read());
148 }
149 
TEST(Kind,Values)150 TEST(Kind, Values) {
151   EXPECT_EQ(static_cast<Kind>(0), Kind::WIDGET);
152   EXPECT_EQ(static_cast<Kind>(1), Kind::SPROCKET);
153   EXPECT_EQ(static_cast<Kind>(2), Kind::GEEGAW);
154   EXPECT_EQ(
155       static_cast<Kind>(static_cast</**/ ::std::uint64_t>(Kind::GEEGAW) +
156                         static_cast</**/ ::std::uint64_t>(Kind::SPROCKET)),
157       Kind::COMPUTED);
158   EXPECT_EQ(static_cast<Kind>(4294967295), Kind::MAX32BIT);
159 }
160 
TEST(ManifestEntryWriter,CanWriteKind)161 TEST(ManifestEntryWriter, CanWriteKind) {
162   ::std::uint8_t buffer[sizeof kManifestEntry] = {0};
163   auto writer = ManifestEntryWriter(buffer, sizeof buffer);
164   writer.kind().Write(Kind::SPROCKET);
165   writer.count().Write(4);
166   writer.wide_kind().Write(Kind::GEEGAW);
167   writer.wide_kind_in_bits().Write(Kind::GEEGAW);
168   EXPECT_EQ(::std::vector</**/ ::std::uint8_t>(
169                 kManifestEntry, kManifestEntry + sizeof kManifestEntry),
170             ::std::vector</**/ ::std::uint8_t>(buffer, buffer + sizeof buffer));
171 
172 #if EMBOSS_CHECK_ABORTS
173   EXPECT_DEATH(writer.kind().Write(Kind::LARGE_VALUE), "");
174 #endif  // EMBOSS_CHECK_ABORTS
175   writer.kind().Write(static_cast<Kind>(0xff));
176   EXPECT_EQ(static_cast<Kind>(0xff), writer.kind().Read());
177   EXPECT_EQ(0xff, buffer[0]);
178   // The writes to kind() should not have overwritten the next field.
179   EXPECT_EQ(0x04, buffer[1]);
180   writer.wide_kind().Write(Kind::MAX32BIT);
181   writer.wide_kind_in_bits().Write(Kind::MAX32BIT);
182   EXPECT_EQ(::std::vector</**/ ::std::uint8_t>(
183                 kManifestEntryEdgeCases,
184                 kManifestEntryEdgeCases + sizeof kManifestEntryEdgeCases),
185             ::std::vector</**/ ::std::uint8_t>(buffer, buffer + sizeof buffer));
186 }
187 
TEST(Kind,EnumToName)188 TEST(Kind, EnumToName) {
189   EXPECT_EQ("WIDGET", TryToGetNameFromEnum(Kind::WIDGET));
190   EXPECT_EQ("SPROCKET", TryToGetNameFromEnum(Kind::SPROCKET));
191   EXPECT_EQ("MAX32BIT", TryToGetNameFromEnum(Kind::MAX32BIT));
192   // In the case of duplicate values, the first one listed in the .emb is
193   // chosen.
194   // TODO(bolms): Decide if this policy is good enough, or if the choice should
195   // be explicit.
196   EXPECT_EQ("LARGE_VALUE", TryToGetNameFromEnum(Kind::LARGE_VALUE));
197   EXPECT_EQ("LARGE_VALUE", TryToGetNameFromEnum(Kind::DUPLICATE_LARGE_VALUE));
198   EXPECT_EQ(nullptr, TryToGetNameFromEnum(static_cast<Kind>(100)));
199 }
200 
TEST(Kind,EnumToOstream)201 TEST(Kind, EnumToOstream) {
202   {
203     ::std::ostringstream s;
204     s << Kind::WIDGET;
205     EXPECT_EQ("WIDGET", s.str());
206   }
207   {
208     ::std::ostringstream s;
209     s << Kind::MAX32BIT;
210     EXPECT_EQ("MAX32BIT", s.str());
211   }
212   {
213     ::std::ostringstream s;
214     s << static_cast<Kind>(10005);
215     EXPECT_EQ("10005", s.str());
216   }
217   {
218     ::std::ostringstream s;
219     s << Kind::WIDGET << ":" << Kind::SPROCKET;
220     EXPECT_EQ("WIDGET:SPROCKET", s.str());
221   }
222 }
223 
TEST(ManifestEntryView,CopyFrom)224 TEST(ManifestEntryView, CopyFrom) {
225   ::std::array</**/ ::std::uint8_t, 14> buf_x = {0x00};
226   ::std::array</**/ ::std::uint8_t, 14> buf_y = {0xff};
227 
228   auto x = MakeManifestEntryView(&buf_x);
229   auto y = MakeManifestEntryView(&buf_y);
230 
231   EXPECT_NE(x.kind().Read(), y.kind().Read());
232   x.kind().CopyFrom(y.kind());
233   EXPECT_EQ(x.kind().Read(), y.kind().Read());
234 }
235 
TEST(ManifestEntryView,TryToCopyFrom)236 TEST(ManifestEntryView, TryToCopyFrom) {
237   ::std::array</**/ ::std::uint8_t, 14> buf_x = {0x00};
238   ::std::array</**/ ::std::uint8_t, 14> buf_y = {0xff};
239 
240   auto x = MakeManifestEntryView(&buf_x);
241   auto y = MakeManifestEntryView(&buf_y);
242 
243   EXPECT_NE(x.kind().Read(), y.kind().Read());
244   EXPECT_TRUE(x.kind().TryToCopyFrom(y.kind()));
245   EXPECT_EQ(x.kind().Read(), y.kind().Read());
246 }
247 
TEST(Kind,NameToEnum)248 TEST(Kind, NameToEnum) {
249   Kind result;
250   EXPECT_TRUE(TryToGetEnumFromName("WIDGET", &result));
251   EXPECT_EQ(Kind::WIDGET, result);
252   EXPECT_TRUE(TryToGetEnumFromName("SPROCKET", &result));
253   EXPECT_EQ(Kind::SPROCKET, result);
254   EXPECT_TRUE(TryToGetEnumFromName("MAX32BIT", &result));
255   EXPECT_EQ(Kind::MAX32BIT, result);
256   EXPECT_TRUE(TryToGetEnumFromName("LARGE_VALUE", &result));
257   EXPECT_EQ(Kind::LARGE_VALUE, result);
258   EXPECT_EQ(Kind::DUPLICATE_LARGE_VALUE, result);
259   EXPECT_TRUE(TryToGetEnumFromName("DUPLICATE_LARGE_VALUE", &result));
260   EXPECT_EQ(Kind::LARGE_VALUE, result);
261   EXPECT_EQ(Kind::DUPLICATE_LARGE_VALUE, result);
262 
263   result = Kind::WIDGET;
264   EXPECT_FALSE(TryToGetEnumFromName("MAX32BIT ", &result));
265   EXPECT_EQ(Kind::WIDGET, result);
266   EXPECT_FALSE(TryToGetEnumFromName("", &result));
267   EXPECT_EQ(Kind::WIDGET, result);
268   EXPECT_FALSE(TryToGetEnumFromName(nullptr, &result));
269   EXPECT_EQ(Kind::WIDGET, result);
270   EXPECT_FALSE(TryToGetEnumFromName(" MAX32BIT", &result));
271   EXPECT_EQ(Kind::WIDGET, result);
272   EXPECT_FALSE(TryToGetEnumFromName("MAX32BI", &result));
273   EXPECT_EQ(Kind::WIDGET, result);
274   EXPECT_FALSE(TryToGetEnumFromName("max32bit", &result));
275   EXPECT_EQ(Kind::WIDGET, result);
276 }
277 
TEST(Kind,Type)278 TEST(Kind, Type) {
279   EXPECT_TRUE((::std::is_same</**/ ::std::uint64_t,
280                               ::std::underlying_type<Kind>::type>::value));
281 }
282 
TEST(Signed,Type)283 TEST(Signed, Type) {
284   EXPECT_TRUE((::std::is_same</**/ ::std::int64_t,
285                               ::std::underlying_type<Signed>::type>::value));
286 }
287 
TEST(Foo,EnumsExposedFromView)288 TEST(Foo, EnumsExposedFromView) {
289   EXPECT_EQ(StructContainingEnum::Status::OK,
290             StructContainingEnumView::Status::OK);
291   EXPECT_EQ(StructContainingEnum::Status::FAILURE,
292             StructContainingEnumView::Status::FAILURE);
293 }
294 
TEST(Kind,EnumIsKnown)295 TEST(Kind, EnumIsKnown) {
296   EXPECT_TRUE(EnumIsKnown(Kind::WIDGET));
297   EXPECT_TRUE(EnumIsKnown(Kind::SPROCKET));
298   EXPECT_TRUE(EnumIsKnown(Kind::GEEGAW));
299   EXPECT_TRUE(EnumIsKnown(Kind::COMPUTED));
300   EXPECT_TRUE(EnumIsKnown(Kind::LARGE_VALUE));
301   EXPECT_TRUE(EnumIsKnown(Kind::DUPLICATE_LARGE_VALUE));
302   EXPECT_TRUE(EnumIsKnown(Kind::MAX32BIT));
303   EXPECT_TRUE(EnumIsKnown(Kind::MAX64BIT));
304   EXPECT_FALSE(EnumIsKnown(static_cast<Kind>(12345)));
305 }
306 
307 }  // namespace
308 }  // namespace test
309 }  // namespace emboss
310