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 automatically-sized arrays from auto_array_size.emb.
16
17 #include <stdint.h>
18
19 #include <iterator>
20 #include <random>
21 #include <vector>
22
23 #include "gmock/gmock.h"
24 #include "gtest/gtest.h"
25 #include "runtime/cpp/emboss_text_util.h"
26 #include "testdata/auto_array_size.emb.h"
27
28 namespace emboss {
29 namespace test {
30 namespace {
31
32 alignas(8) static const ::std::uint8_t kAutoSize[22] = {
33 0x03, // 0:1 array_size == 3
34 0x10, 0x20, 0x30, 0x40, // 1:5 four_byte_array
35 0x11, 0x12, 0x21, 0x22, // 5:9 four_struct_array[0, 1]
36 0x31, 0x32, 0x41, 0x42, // 9:13 four_struct_array[2, 3]
37 0x50, 0x60, 0x70, // 13:16 dynamic_byte_array
38 0x51, 0x52, 0x61, 0x62, 0x71, 0x72, // 16:22 dynamic_struct_array
39 };
40
TEST(AutoSizeView,IteratorIncrement)41 TEST(AutoSizeView, IteratorIncrement) {
42 auto src_buf = ::std::vector</**/ ::std::uint8_t>(
43 kAutoSize, kAutoSize + sizeof kAutoSize);
44 auto src = MakeAutoSizeView(&src_buf).four_struct_array();
45 auto dst_buf = ::std::vector</**/ ::std::uint8_t>(
46 kAutoSize, kAutoSize + sizeof kAutoSize);
47 auto dst = MakeAutoSizeView(&dst_buf).four_struct_array();
48 EXPECT_TRUE(src.Equals(dst));
49
50 ::std::fill(dst.BackingStorage().begin(), dst.BackingStorage().end(), 0);
51 EXPECT_FALSE(src.Equals(dst));
52 for (auto src_it = src.begin(), dst_it = dst.begin();
53 src_it != src.end() && dst_it != dst.end(); ++src_it, ++dst_it) {
54 dst_it->CopyFrom(*src_it);
55 }
56 EXPECT_TRUE(src.Equals(dst));
57
58 ::std::fill(dst.BackingStorage().begin(), dst.BackingStorage().end(), 0);
59 EXPECT_FALSE(src.Equals(dst));
60 for (auto src_it = src.begin(), dst_it = dst.begin();
61 src_it != src.end() && dst_it != dst.end(); src_it++, dst_it++) {
62 dst_it->CopyFrom(*src_it);
63 }
64 EXPECT_TRUE(src.Equals(dst));
65
66 ::std::fill(dst.BackingStorage().begin(), dst.BackingStorage().end(), 0);
67 EXPECT_FALSE(src.Equals(dst));
68 for (auto src_it = src.rbegin(), dst_it = dst.rbegin();
69 src_it != src.rend() && dst_it != dst.rend(); ++src_it, ++dst_it) {
70 dst_it->CopyFrom(*src_it);
71 }
72 EXPECT_TRUE(src.Equals(dst));
73
74 ::std::fill(dst.BackingStorage().begin(), dst.BackingStorage().end(), 0);
75 EXPECT_FALSE(src.Equals(dst));
76 for (auto src_it = src.rbegin(), dst_it = dst.rbegin();
77 src_it != src.rend() && dst_it != dst.rend(); src_it++, dst_it++) {
78 dst_it->CopyFrom(*src_it);
79 }
80 EXPECT_TRUE(src.Equals(dst));
81
82 EXPECT_EQ(src.begin(), src.begin()++);
83 EXPECT_EQ(src.rbegin(), src.rbegin()++);
84 EXPECT_EQ(src.end(), (src.end())--);
85 EXPECT_EQ(src.rend(), src.rend()--);
86 }
87
TEST(AutoSizeView,PreviousNext)88 TEST(AutoSizeView, PreviousNext) {
89 auto view = MakeAutoSizeView(kAutoSize, sizeof kAutoSize).four_struct_array();
90 EXPECT_TRUE(::std::next(view.begin(), 0)->Equals(view[0]));
91 EXPECT_TRUE(::std::next(view.begin(), 1)->Equals(view[1]));
92 EXPECT_TRUE(::std::next(view.begin(), 2)->Equals(view[2]));
93 EXPECT_TRUE(::std::next(view.begin(), 3)->Equals(view[3]));
94
95 EXPECT_TRUE(::std::next(view.rbegin(), 0)->Equals(view[3]));
96 EXPECT_TRUE(::std::next(view.rbegin(), 1)->Equals(view[2]));
97 EXPECT_TRUE(::std::next(view.rbegin(), 2)->Equals(view[1]));
98 EXPECT_TRUE(::std::next(view.rbegin(), 3)->Equals(view[0]));
99
100 EXPECT_TRUE(::std::prev(view.end(), 1)->Equals(view[3]));
101 EXPECT_TRUE(::std::prev(view.end(), 2)->Equals(view[2]));
102 EXPECT_TRUE(::std::prev(view.end(), 3)->Equals(view[1]));
103 EXPECT_TRUE(::std::prev(view.end(), 4)->Equals(view[0]));
104
105 EXPECT_TRUE(::std::prev(view.rend(), 1)->Equals(view[0]));
106 EXPECT_TRUE(::std::prev(view.rend(), 2)->Equals(view[1]));
107 EXPECT_TRUE(::std::prev(view.rend(), 3)->Equals(view[2]));
108 EXPECT_TRUE(::std::prev(view.rend(), 4)->Equals(view[3]));
109 }
110
TEST(AutoSizeView,ForEach)111 TEST(AutoSizeView, ForEach) {
112 auto view = MakeAutoSizeView(kAutoSize, sizeof kAutoSize).four_struct_array();
113
114 int i = 0;
115 ::std::for_each(view.begin(), view.end(), [&](ElementView element) {
116 ASSERT_TRUE(element.Equals(view[i++]));
117 });
118
119 i = view.ElementCount() - 1;
120 ::std::for_each(view.rbegin(), view.rend(), [&](ElementView element) {
121 ASSERT_TRUE(element.Equals(view[i--]));
122 });
123 }
124
TEST(AutoSizeView,ForEachWithTemporaries)125 TEST(AutoSizeView, ForEachWithTemporaries) {
126 auto view = MakeAutoSizeView(kAutoSize, sizeof kAutoSize);
127
128 int i = 0;
129 ::std::for_each(view.four_struct_array().begin(),
130 view.four_struct_array().end(), [&](ElementView element) {
131 ASSERT_TRUE(element.Equals(view.four_struct_array()[i++]));
132 });
133
134 i = view.four_struct_array().ElementCount() - 1;
135 ::std::for_each(view.four_struct_array().rbegin(),
136 view.four_struct_array().rend(), [&](ElementView element) {
137 ASSERT_TRUE(element.Equals(view.four_struct_array()[i--]));
138 });
139 }
140
TEST(AutoSizeView,Find)141 TEST(AutoSizeView, Find) {
142 auto view = MakeAutoSizeView(kAutoSize, sizeof kAutoSize).four_struct_array();
143
144 EXPECT_TRUE(
145 ::std::find_if(view.begin(), view.end(), [view](ElementView element) {
146 return element.Equals(view[0]);
147 })->Equals(view[0]));
148 EXPECT_TRUE(
149 ::std::find_if(view.begin(), view.end(), [view](ElementView element) {
150 return element.Equals(view[1]);
151 })->Equals(view[1]));
152 EXPECT_TRUE(
153 ::std::find_if(view.begin(), view.end(), [view](ElementView element) {
154 return element.Equals(view[2]);
155 })->Equals(view[2]));
156 EXPECT_TRUE(
157 ::std::find_if(view.begin(), view.end(), [view](ElementView element) {
158 return element.Equals(view[3]);
159 })->Equals(view[3]));
160
161 EXPECT_TRUE(
162 ::std::find_if(view.rbegin(), view.rend(), [view](ElementView element) {
163 return element.Equals(view[0]);
164 })->Equals(view[0]));
165 EXPECT_TRUE(
166 ::std::find_if(view.rbegin(), view.rend(), [view](ElementView element) {
167 return element.Equals(view[1]);
168 })->Equals(view[1]));
169 EXPECT_TRUE(
170 ::std::find_if(view.rbegin(), view.rend(), [view](ElementView element) {
171 return element.Equals(view[2]);
172 })->Equals(view[2]));
173 EXPECT_TRUE(
174 ::std::find_if(view.rbegin(), view.rend(), [view](ElementView element) {
175 return element.Equals(view[3]);
176 })->Equals(view[3]));
177 }
178
TEST(AutoSizeView,Comparison)179 TEST(AutoSizeView, Comparison) {
180 auto view = MakeAutoSizeView(kAutoSize, sizeof kAutoSize).four_struct_array();
181
182 EXPECT_EQ(view.begin() + view.ElementCount(), view.end());
183 EXPECT_EQ(view.end() - view.ElementCount(), view.begin());
184
185 EXPECT_EQ(view.rbegin() + view.ElementCount(), view.rend());
186 EXPECT_EQ(view.rend() - view.ElementCount(), view.rbegin());
187
188 EXPECT_LT(view.begin(), view.end());
189 EXPECT_LT(view.rbegin(), view.rend());
190
191 EXPECT_LE(view.begin() - 1, view.end());
192 EXPECT_LE(view.rbegin() - 1, view.rend());
193 EXPECT_LE(view.begin() - 1, view.end());
194 EXPECT_LE(view.rbegin() - 1, view.rend());
195
196 EXPECT_GT(view.end(), view.begin());
197 EXPECT_GT(view.rend(), view.rbegin());
198
199 EXPECT_GE(view.end() + 1, view.begin());
200 EXPECT_GE(view.end() + 1, view.begin());
201 EXPECT_GE(view.rend() + 1, view.rbegin());
202 EXPECT_GE(view.rend() + 1, view.rbegin());
203 }
204
TEST(AutoSizeView,RangeBasedFor)205 TEST(AutoSizeView, RangeBasedFor) {
206 auto view = MakeAutoSizeView(kAutoSize, sizeof kAutoSize).four_struct_array();
207
208 int i = 0;
209 for (auto element : view) {
210 ASSERT_TRUE(element.Equals(view[i++]));
211 }
212 }
213
TEST(AutoSizeView,CanReadAutoArrays)214 TEST(AutoSizeView, CanReadAutoArrays) {
215 auto view = MakeAlignedAutoSizeView<const ::std::uint8_t, 8>(
216 kAutoSize, sizeof kAutoSize);
217 EXPECT_EQ(22U, view.SizeInBytes());
218 EXPECT_EQ(3U, view.array_size().Read());
219 EXPECT_EQ(0x10U, view.four_byte_array()[0].Read());
220 EXPECT_EQ(0x20U, view.four_byte_array()[1].Read());
221 EXPECT_EQ(0x30U, view.four_byte_array()[2].Read());
222 EXPECT_EQ(0x40U, view.four_byte_array()[3].Read());
223 EXPECT_EQ(4U, view.four_byte_array().SizeInBytes());
224 #if EMBOSS_CHECK_ABORTS
225 EXPECT_DEATH(view.four_byte_array()[4].Read(), "");
226 #endif // EMBOSS_CHECK_ABORTS
227 EXPECT_EQ(0x11U, view.four_struct_array()[0].a().Read());
228 EXPECT_EQ(0x12U, view.four_struct_array()[0].b().Read());
229 EXPECT_EQ(0x21U, view.four_struct_array()[1].a().Read());
230 EXPECT_EQ(0x22U, view.four_struct_array()[1].b().Read());
231 EXPECT_EQ(0x31U, view.four_struct_array()[2].a().Read());
232 EXPECT_EQ(0x32U, view.four_struct_array()[2].b().Read());
233 EXPECT_EQ(0x41U, view.four_struct_array()[3].a().Read());
234 EXPECT_EQ(0x42U, view.four_struct_array()[3].b().Read());
235 EXPECT_EQ(8U, view.four_struct_array().SizeInBytes());
236 #if EMBOSS_CHECK_ABORTS
237 EXPECT_DEATH(view.four_struct_array()[4].a().Read(), "");
238 #endif // EMBOSS_CHECK_ABORTS
239 EXPECT_EQ(0x50U, view.dynamic_byte_array()[0].Read());
240 EXPECT_EQ(0x60U, view.dynamic_byte_array()[1].Read());
241 EXPECT_EQ(0x70U, view.dynamic_byte_array()[2].Read());
242 EXPECT_EQ(3U, view.dynamic_byte_array().SizeInBytes());
243 EXPECT_FALSE(view.dynamic_byte_array()[3].IsComplete());
244 EXPECT_EQ(0x51U, view.dynamic_struct_array()[0].a().Read());
245 EXPECT_EQ(0x52U, view.dynamic_struct_array()[0].b().Read());
246 EXPECT_EQ(0x61U, view.dynamic_struct_array()[1].a().Read());
247 EXPECT_EQ(0x62U, view.dynamic_struct_array()[1].b().Read());
248 EXPECT_EQ(0x71U, view.dynamic_struct_array()[2].a().Read());
249 EXPECT_EQ(0x72U, view.dynamic_struct_array()[2].b().Read());
250 EXPECT_EQ(6U, view.dynamic_struct_array().SizeInBytes());
251 EXPECT_FALSE(view.dynamic_struct_array()[3].IsComplete());
252 }
253
TEST(AutoSizeWriter,CanWriteAutoArrays)254 TEST(AutoSizeWriter, CanWriteAutoArrays) {
255 ::std::vector<char> buffer(sizeof kAutoSize, 0);
256 auto writer = MakeAutoSizeView(&buffer);
257 writer.array_size().Write(0);
258 EXPECT_EQ(13U, writer.SizeInBytes());
259 #if EMBOSS_CHECK_ABORTS
260 EXPECT_DEATH(writer.dynamic_byte_array()[0].Read(), "");
261 #endif // EMBOSS_CHECK_ABORTS
262 writer.array_size().Write(3);
263 EXPECT_EQ(22U, writer.SizeInBytes());
264 writer.four_byte_array()[0].Write(0x10);
265 writer.four_byte_array()[1].Write(0x20);
266 writer.four_byte_array()[2].Write(0x30);
267 writer.four_byte_array()[3].Write(0x40);
268 #if EMBOSS_CHECK_ABORTS
269 EXPECT_DEATH(writer.four_byte_array()[4].Write(0), "");
270 #endif // EMBOSS_CHECK_ABORTS
271 writer.four_struct_array()[0].a().Write(0x11);
272 writer.four_struct_array()[0].b().Write(0x12);
273 writer.four_struct_array()[1].a().Write(0x21);
274 writer.four_struct_array()[1].b().Write(0x22);
275 writer.four_struct_array()[2].a().Write(0x31);
276 writer.four_struct_array()[2].b().Write(0x32);
277 writer.four_struct_array()[3].a().Write(0x41);
278 writer.four_struct_array()[3].b().Write(0x42);
279 EXPECT_FALSE(writer.four_struct_array()[4].IsComplete());
280 writer.dynamic_byte_array()[0].Write(0x50);
281 writer.dynamic_byte_array()[1].Write(0x60);
282 writer.dynamic_byte_array()[2].Write(0x70);
283 EXPECT_FALSE(writer.dynamic_byte_array()[3].IsComplete());
284 writer.dynamic_struct_array()[0].a().Write(0x51);
285 writer.dynamic_struct_array()[0].b().Write(0x52);
286 writer.dynamic_struct_array()[1].a().Write(0x61);
287 writer.dynamic_struct_array()[1].b().Write(0x62);
288 writer.dynamic_struct_array()[2].a().Write(0x71);
289 writer.dynamic_struct_array()[2].b().Write(0x72);
290 EXPECT_FALSE(writer.dynamic_struct_array()[3].IsComplete());
291 EXPECT_EQ(::std::vector<char>(kAutoSize, kAutoSize + sizeof kAutoSize),
292 buffer);
293 }
294
TEST(AutoSizeView,CanUseDataMethod)295 TEST(AutoSizeView, CanUseDataMethod) {
296 auto view = MakeAlignedAutoSizeView<const ::std::uint8_t, 8>(
297 kAutoSize, sizeof kAutoSize);
298
299 for (unsigned i = 0; i < view.SizeInBytes(); ++i) {
300 EXPECT_EQ(*(view.BackingStorage().data() + i), kAutoSize[i])
301 << " at element " << i;
302 }
303 }
304
TEST(AutoSizeView,CanCopyFrom)305 TEST(AutoSizeView, CanCopyFrom) {
306 auto source = MakeAlignedAutoSizeView<const ::std::uint8_t, 8>(
307 kAutoSize, sizeof kAutoSize);
308
309 ::std::array</**/ ::std::uint8_t, sizeof kAutoSize> buf = {0};
310 auto dest =
311 MakeAlignedAutoSizeView</**/ ::std::uint8_t, 8>(buf.data(), buf.size());
312
313 // Copy one element.
314 EXPECT_NE(source.four_struct_array()[0].a().Read(),
315 dest.four_struct_array()[0].a().Read());
316 EXPECT_NE(source.four_struct_array()[0].b().Read(),
317 dest.four_struct_array()[0].b().Read());
318 dest.four_struct_array()[0].CopyFrom(source.four_struct_array()[0]);
319 EXPECT_EQ(source.four_struct_array()[0].a().Read(),
320 dest.four_struct_array()[0].a().Read());
321 EXPECT_EQ(source.four_struct_array()[0].b().Read(),
322 dest.four_struct_array()[0].b().Read());
323
324 // Copy entire view.
325 dest.CopyFrom(source);
326 for (unsigned i = 0; i < source.four_struct_array().ElementCount(); ++i) {
327 EXPECT_EQ(source.four_struct_array()[i].a().Read(),
328 dest.four_struct_array()[i].a().Read());
329 EXPECT_EQ(source.four_struct_array()[i].b().Read(),
330 dest.four_struct_array()[i].b().Read());
331 }
332 }
333
TEST(AutoSizeView,CanCopyFromDifferentSizes)334 TEST(AutoSizeView, CanCopyFromDifferentSizes) {
335 constexpr int padding = 10;
336 ::std::array</**/ ::std::uint8_t, sizeof kAutoSize + padding> source_buffer;
337 memset(source_buffer.data(), 0, source_buffer.size());
338 memcpy(source_buffer.data(), kAutoSize, sizeof kAutoSize);
339 auto source = MakeAutoSizeView(&source_buffer);
340
341 ::std::array</**/ ::std::uint8_t, sizeof kAutoSize + padding> buf;
342 memset(buf.data(), 0xff, buf.size());
343 auto dest = MakeAutoSizeView(buf.data(), sizeof kAutoSize);
344
345 dest.CopyFrom(source);
346 for (unsigned i = 0; i < sizeof kAutoSize; ++i) {
347 EXPECT_EQ(buf[i], source_buffer[i]) << i;
348 }
349 for (unsigned i = sizeof kAutoSize; i < sizeof kAutoSize + padding; ++i) {
350 EXPECT_EQ(buf[i], 0xff) << i;
351 }
352 }
353
TEST(AutoSizeView,CanCopyFromOverlapping)354 TEST(AutoSizeView, CanCopyFromOverlapping) {
355 constexpr int kElementSizeBytes = ElementView::SizeInBytes();
356 ::std::vector</**/ ::std::uint8_t> buf = {1, 2, 3};
357
358 auto source = MakeElementView(buf.data(), kElementSizeBytes);
359 auto dest = MakeElementView(buf.data() + 1, kElementSizeBytes);
360 EXPECT_EQ(source.a().Read(), buf[0]);
361 EXPECT_EQ(source.b().Read(), dest.a().Read());
362 EXPECT_EQ(dest.b().Read(), buf[2]);
363
364 dest.CopyFrom(source); // Forward overlap.
365 EXPECT_EQ(buf, ::std::vector</**/ ::std::uint8_t>({1, 1, 2}));
366 source.CopyFrom(dest); // Reverse overlap.
367 EXPECT_EQ(buf, ::std::vector</**/ ::std::uint8_t>({1, 2, 2}));
368 }
369
TEST(AutoSizeView,Equals)370 TEST(AutoSizeView, Equals) {
371 ::std::vector</**/ ::std::uint8_t> buf_x = {1, 2};
372 ::std::vector</**/ ::std::uint8_t> buf_y = {1, 2, 3};
373 auto x = MakeElementView(&buf_x);
374 auto x_const = MakeElementView(
375 static_cast<const ::std::vector</**/ ::std::uint8_t>*>(&buf_x));
376 auto y = MakeElementView(&buf_y);
377
378 EXPECT_TRUE(x.Equals(x));
379 EXPECT_TRUE(x.UncheckedEquals(x));
380 EXPECT_TRUE(y.Equals(y));
381 EXPECT_TRUE(y.UncheckedEquals(y));
382
383 EXPECT_TRUE(x.Equals(y));
384 EXPECT_TRUE(x.UncheckedEquals(y));
385 EXPECT_TRUE(y.Equals(x));
386 EXPECT_TRUE(y.UncheckedEquals(x));
387
388 EXPECT_TRUE(y.Equals(x_const));
389 EXPECT_TRUE(y.UncheckedEquals(x_const));
390 EXPECT_TRUE(x_const.Equals(y));
391 EXPECT_TRUE(x_const.UncheckedEquals(y));
392
393 ++buf_y[1];
394 EXPECT_FALSE(x.Equals(y));
395 EXPECT_FALSE(x.UncheckedEquals(y));
396 EXPECT_FALSE(y.Equals(x));
397 EXPECT_FALSE(y.UncheckedEquals(x));
398 }
399
400 } // namespace
401 } // namespace test
402 } // namespace emboss
403