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 #include "runtime/cpp/emboss_array_view.h"
16
17 #include <string>
18 #include <type_traits>
19
20 #include "absl/strings/str_format.h"
21 #include "gtest/gtest.h"
22 #include "runtime/cpp/emboss_prelude.h"
23 #include "runtime/cpp/emboss_text_util.h"
24
25 namespace emboss {
26 namespace support {
27 namespace test {
28
29 using ::emboss::prelude::IntView;
30 using ::emboss::prelude::UIntView;
31
32 template <class ElementView, class BufferType, ::std::size_t kElementSize>
33 using ArrayView = GenericArrayView<ElementView, BufferType, kElementSize, 8>;
34
35 template <class ElementView, class BufferType, ::std::size_t kElementSize>
36 using BitArrayView = GenericArrayView<ElementView, BufferType, kElementSize, 1>;
37
38 template </**/ ::std::size_t kBits>
39 using LittleEndianBitBlockN =
40 BitBlock<LittleEndianByteOrderer<ReadWriteContiguousBuffer>, kBits>;
41
42 template </**/ ::std::size_t kBits>
43 using FixedUIntView = UIntView<FixedSizeViewParameters<kBits, AllValuesAreOk>,
44 LittleEndianBitBlockN<kBits>>;
45
46 template </**/ ::std::size_t kBits>
47 using FixedIntView = IntView<FixedSizeViewParameters<kBits, AllValuesAreOk>,
48 LittleEndianBitBlockN<kBits>>;
49
TEST(ArrayView,Methods)50 TEST(ArrayView, Methods) {
51 ::std::uint8_t bytes[] = {0x10, 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09,
52 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01};
53 auto byte_array = ArrayView<FixedUIntView<8>, ReadWriteContiguousBuffer, 1>{
54 ReadWriteContiguousBuffer{bytes, sizeof bytes - 4}};
55 EXPECT_EQ(sizeof bytes - 4, byte_array.SizeInBytes());
56 EXPECT_EQ(bytes[0], byte_array[0].Read());
57 EXPECT_EQ(bytes[1], byte_array[1].Read());
58 EXPECT_EQ(bytes[2], byte_array[2].Read());
59 #if EMBOSS_CHECK_ABORTS
60 EXPECT_DEATH(byte_array[sizeof bytes - 4].Read(), "");
61 #endif // EMBOSS_CHECK_ABORTS
62 EXPECT_EQ(bytes[sizeof bytes - 4],
63 byte_array[sizeof bytes - 4].UncheckedRead());
64 EXPECT_TRUE(byte_array[sizeof bytes - 5].IsComplete());
65 EXPECT_FALSE(byte_array[sizeof bytes - 4].IsComplete());
66 EXPECT_TRUE(byte_array.Ok());
67 EXPECT_TRUE(byte_array.IsComplete());
68 EXPECT_FALSE((ArrayView<FixedUIntView<8>, ReadWriteContiguousBuffer, 1>{
69 ReadWriteContiguousBuffer{
70 nullptr}}.Ok()));
71 EXPECT_TRUE(byte_array.IsComplete());
72
73 auto uint32_array =
74 ArrayView<FixedUIntView<32>, ReadWriteContiguousBuffer, 4>{
75 ReadWriteContiguousBuffer{bytes, sizeof bytes - 4}};
76 EXPECT_EQ(sizeof bytes - 4, uint32_array.SizeInBytes());
77 EXPECT_TRUE(uint32_array[0].Ok());
78 EXPECT_EQ(0x0d0e0f10U, uint32_array[0].Read());
79 EXPECT_EQ(0x090a0b0cU, uint32_array[1].Read());
80 EXPECT_EQ(0x05060708U, uint32_array[2].Read());
81 #if EMBOSS_CHECK_ABORTS
82 EXPECT_DEATH(uint32_array[3].Read(), "");
83 #endif // EMBOSS_CHECK_ABORTS
84 EXPECT_EQ(0x01020304U, uint32_array[3].UncheckedRead());
85 EXPECT_TRUE(uint32_array[2].IsComplete());
86 EXPECT_FALSE(uint32_array[3].IsComplete());
87 EXPECT_TRUE(uint32_array.Ok());
88 EXPECT_TRUE(uint32_array.IsComplete());
89 EXPECT_FALSE((ArrayView<FixedUIntView<32>, ReadWriteContiguousBuffer, 1>{
90 ReadWriteContiguousBuffer{
91 nullptr}}.Ok()));
92 }
93
TEST(ArrayView,Ok)94 TEST(ArrayView, Ok) {
95 ::std::uint8_t bytes[] = {0x10, 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09,
96 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01};
97 // All elements are complete and, themselves, Ok(), so the array should be
98 // Ok().
99 auto byte_array = ArrayView<FixedUIntView<16>, ReadWriteContiguousBuffer, 2>(
100 ReadWriteContiguousBuffer(bytes, sizeof bytes - 4));
101 EXPECT_TRUE(byte_array.Ok());
102
103 // An array with a partial element at the end should not be Ok().
104 byte_array = ArrayView<FixedUIntView<16>, ReadWriteContiguousBuffer, 2>(
105 ReadWriteContiguousBuffer(bytes, sizeof bytes - 3));
106 EXPECT_FALSE(byte_array.Ok());
107
108 // An empty array should be Ok().
109 byte_array = ArrayView<FixedUIntView<16>, ReadWriteContiguousBuffer, 2>(
110 ReadWriteContiguousBuffer(bytes, 0));
111 EXPECT_TRUE(byte_array.Ok());
112 }
113
TEST(ArrayView,TextFormatInput)114 TEST(ArrayView, TextFormatInput) {
115 ::std::uint8_t bytes[16] = {0};
116 auto byte_array = ArrayView<FixedUIntView<8>, ReadWriteContiguousBuffer, 1>{
117 ReadWriteContiguousBuffer{bytes, sizeof bytes}};
118 EXPECT_FALSE(UpdateFromText(byte_array, ""));
119 EXPECT_FALSE(UpdateFromText(byte_array, "[]"));
120 EXPECT_FALSE(UpdateFromText(byte_array, "{"));
121 EXPECT_FALSE(UpdateFromText(byte_array, "{[0"));
122 EXPECT_FALSE(UpdateFromText(byte_array, "{[0:0}"));
123 EXPECT_FALSE(UpdateFromText(byte_array, "{[]:0}"));
124 EXPECT_FALSE(UpdateFromText(byte_array, "{[0] 0}"));
125 EXPECT_FALSE(UpdateFromText(byte_array, "{[0] 0}"));
126 EXPECT_TRUE(UpdateFromText(byte_array, "{}"));
127 EXPECT_FALSE(UpdateFromText(byte_array, "{,1}"));
128 EXPECT_FALSE(UpdateFromText(byte_array, "{1,,}"));
129 EXPECT_FALSE(UpdateFromText(byte_array, "{ a }"));
130 EXPECT_TRUE(UpdateFromText(byte_array, "{1}"));
131 EXPECT_EQ(1, bytes[0]);
132 EXPECT_TRUE(UpdateFromText(byte_array, " {2}"));
133 EXPECT_EQ(2, bytes[0]);
134 EXPECT_TRUE(UpdateFromText(byte_array, " {\t\r\n4 } junk"));
135 EXPECT_EQ(4, bytes[0]);
136 EXPECT_TRUE(UpdateFromText(byte_array, "{3,}"));
137 EXPECT_EQ(3, bytes[0]);
138 EXPECT_FALSE(UpdateFromText(byte_array, "{4 5}"));
139 EXPECT_TRUE(UpdateFromText(byte_array, "{4, 5}"));
140 EXPECT_EQ(4, bytes[0]);
141 EXPECT_EQ(5, bytes[1]);
142 EXPECT_TRUE(UpdateFromText(byte_array, "{5, [6]: 5}"));
143 EXPECT_EQ(5, bytes[0]);
144 EXPECT_EQ(5, bytes[1]);
145 EXPECT_EQ(5, bytes[6]);
146 EXPECT_TRUE(UpdateFromText(byte_array, "{6, [7]:6, 6}"));
147 EXPECT_EQ(6, bytes[0]);
148 EXPECT_EQ(5, bytes[1]);
149 EXPECT_EQ(5, bytes[6]);
150 EXPECT_EQ(6, bytes[7]);
151 EXPECT_EQ(6, bytes[8]);
152 EXPECT_TRUE(UpdateFromText(byte_array, "{[7]: 7, 7, [0]: 7, 7}"));
153 EXPECT_EQ(7, bytes[0]);
154 EXPECT_EQ(7, bytes[1]);
155 EXPECT_EQ(7, bytes[7]);
156 EXPECT_EQ(7, bytes[8]);
157 EXPECT_FALSE(UpdateFromText(byte_array, "{[16]: 0}"));
158 EXPECT_FALSE(UpdateFromText(byte_array, "{[15]: 0, 0}"));
159 }
160
TEST(ArrayView,TextFormatOutput_WithAndWithoutComments)161 TEST(ArrayView, TextFormatOutput_WithAndWithoutComments) {
162 signed char bytes[16] = {-3, 2, -1, 1, 0, 1, 1, 2,
163 3, 5, 8, 13, 21, 34, 55, 89};
164 auto buffer = ReadWriteContiguousBuffer{
165 reinterpret_cast</**/ ::std::uint8_t *>(bytes), sizeof bytes};
166 auto byte_array =
167 ArrayView<FixedIntView<8>, ReadWriteContiguousBuffer, 1>{buffer};
168 EXPECT_EQ(
169 "{ [0]: -3, 2, -1, 1, 0, 1, 1, 2, [8]: 3, 5, 8, 13, 21, 34, 55, 89 }",
170 WriteToString(byte_array));
171 EXPECT_EQ(WriteToString(byte_array, MultilineText()),
172 R"({
173 # ............."7Y
174 [0]: -3 # -0x3
175 [1]: 2 # 0x2
176 [2]: -1 # -0x1
177 [3]: 1 # 0x1
178 [4]: 0 # 0x0
179 [5]: 1 # 0x1
180 [6]: 1 # 0x1
181 [7]: 2 # 0x2
182 [8]: 3 # 0x3
183 [9]: 5 # 0x5
184 [10]: 8 # 0x8
185 [11]: 13 # 0xd
186 [12]: 21 # 0x15
187 [13]: 34 # 0x22
188 [14]: 55 # 0x37
189 [15]: 89 # 0x59
190 })");
191 EXPECT_EQ(
192 WriteToString(byte_array,
193 MultilineText().WithIndent(" ").WithComments(false)),
194 R"({
195 [0]: -3
196 [1]: 2
197 [2]: -1
198 [3]: 1
199 [4]: 0
200 [5]: 1
201 [6]: 1
202 [7]: 2
203 [8]: 3
204 [9]: 5
205 [10]: 8
206 [11]: 13
207 [12]: 21
208 [13]: 34
209 [14]: 55
210 [15]: 89
211 })");
212 EXPECT_EQ(
213 WriteToString(byte_array, TextOutputOptions().WithNumericBase(16)),
214 "{ [0x0]: -0x3, 0x2, -0x1, 0x1, 0x0, 0x1, 0x1, 0x2, [0x8]: 0x3, 0x5, "
215 "0x8, 0xd, 0x15, 0x22, 0x37, 0x59 }");
216 }
217
TEST(ArrayView,TextFormatOutput_8BitIntElementTypes)218 TEST(ArrayView, TextFormatOutput_8BitIntElementTypes) {
219 ::std::uint8_t bytes[1] = {65};
220 auto buffer = ReadWriteContiguousBuffer{bytes, sizeof bytes};
221 const ::std::string expected_text = R"({
222 # A
223 [0]: 65 # 0x41
224 })";
225 EXPECT_EQ(
226 WriteToString(
227 ArrayView<FixedIntView<8>, ReadWriteContiguousBuffer, 1>{buffer},
228 MultilineText()),
229 expected_text);
230 EXPECT_EQ(
231 WriteToString(
232 ArrayView<FixedUIntView<8>, ReadWriteContiguousBuffer, 1>{buffer},
233 MultilineText()),
234 expected_text);
235 }
236
TEST(ArrayView,TextFormatOutput_16BitIntElementTypes)237 TEST(ArrayView, TextFormatOutput_16BitIntElementTypes) {
238 ::std::uint16_t bytes[1] = {65};
239 auto buffer = ReadWriteContiguousBuffer{
240 reinterpret_cast</**/ ::std::uint8_t *>(bytes), sizeof bytes};
241 const ::std::string expected_text = R"({
242 [0]: 65 # 0x41
243 })";
244 EXPECT_EQ(
245 WriteToString(
246 ArrayView<FixedIntView<16>, ReadWriteContiguousBuffer, 2>{buffer},
247 MultilineText()),
248 expected_text);
249 EXPECT_EQ(
250 WriteToString(
251 ArrayView<FixedUIntView<16>, ReadWriteContiguousBuffer, 2>{buffer},
252 MultilineText()),
253 expected_text);
254 }
255
TEST(ArrayView,TextFormatOutput_MultilineComment)256 TEST(ArrayView, TextFormatOutput_MultilineComment) {
257 ::std::uint8_t bytes[65];
258 for (::std::size_t i = 0; i < sizeof bytes; ++i) {
259 bytes[i] = '0' + (i % 10);
260 }
261 for (const ::std::size_t length : {63, 64, 65}) {
262 auto buffer = ReadWriteContiguousBuffer{bytes, length};
263 ::std::string expected_text =
264 "{\n # "
265 "012345678901234567890123456789012345678901234567890123456789012";
266 if (length > 63) expected_text += "3";
267 if (length > 64) expected_text += "\n # 4";
268 expected_text += "\n";
269 for (::std::size_t i = 0; i < length; ++i) {
270 expected_text +=
271 absl::StrFormat(" [%d]: %d # 0x%02x\n", i, bytes[i], bytes[i]);
272 }
273 expected_text += "}";
274 EXPECT_EQ(
275 WriteToString(
276 ArrayView<FixedIntView<8>, ReadWriteContiguousBuffer, 1>{buffer},
277 MultilineText()),
278 expected_text);
279 }
280 }
281
282 } // namespace test
283 } // namespace support
284 } // namespace emboss
285