xref: /aosp_15_r20/external/emboss/compiler/back_end/cpp/testcode/auto_array_size_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 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