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