• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2017 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "components/zucchini/buffer_view.h"
6 
7 #include <stddef.h>
8 #include <stdint.h>
9 
10 #include <iterator>
11 #include <type_traits>
12 #include <vector>
13 
14 #include "base/test/gtest_util.h"
15 #include "components/zucchini/test_utils.h"
16 #include "testing/gtest/include/gtest/gtest.h"
17 
18 namespace zucchini {
19 
20 class BufferViewTest : public testing::Test {
21  protected:
22   // Some tests might modify this.
23   std::vector<uint8_t> bytes_ = ParseHexString("10 32 54 76 98 BA DC FE 10 00");
24 };
25 
TEST_F(BufferViewTest,Size)26 TEST_F(BufferViewTest, Size) {
27   for (size_t len = 0; len <= bytes_.size(); ++len) {
28     EXPECT_EQ(len, ConstBufferView(bytes_.data(), len).size());
29     EXPECT_EQ(len, MutableBufferView(bytes_.data(), len).size());
30   }
31 }
32 
TEST_F(BufferViewTest,Empty)33 TEST_F(BufferViewTest, Empty) {
34   // Empty view.
35   EXPECT_TRUE(ConstBufferView(bytes_.data(), 0).empty());
36   EXPECT_TRUE(MutableBufferView(bytes_.data(), 0).empty());
37 
38   for (size_t len = 1; len <= bytes_.size(); ++len) {
39     EXPECT_FALSE(ConstBufferView(bytes_.data(), len).empty());
40     EXPECT_FALSE(MutableBufferView(bytes_.data(), len).empty());
41   }
42 }
43 
TEST_F(BufferViewTest,FromRange)44 TEST_F(BufferViewTest, FromRange) {
45   constexpr size_t kSize = 10;
46   uint8_t raw_data[kSize] = {0x10, 0x32, 0x54, 0x76, 0x98,
47                              0xBA, 0xDC, 0xFE, 0x10, 0x00};
48   ConstBufferView buffer =
49       ConstBufferView::FromRange(std::begin(raw_data), std::end(raw_data));
50   EXPECT_EQ(bytes_.size(), buffer.size());
51   EXPECT_EQ(std::begin(raw_data), buffer.begin());
52 
53   MutableBufferView mutable_buffer =
54       MutableBufferView::FromRange(std::begin(raw_data), std::end(raw_data));
55   EXPECT_EQ(bytes_.size(), mutable_buffer.size());
56   EXPECT_EQ(std::begin(raw_data), mutable_buffer.begin());
57 
58   EXPECT_DCHECK_DEATH(
59       ConstBufferView::FromRange(std::end(raw_data), std::begin(raw_data)));
60 
61   EXPECT_DCHECK_DEATH(MutableBufferView::FromRange(std::begin(raw_data) + 1,
62                                                    std::begin(raw_data)));
63 }
64 
TEST_F(BufferViewTest,Subscript)65 TEST_F(BufferViewTest, Subscript) {
66   ConstBufferView view(bytes_.data(), bytes_.size());
67 
68   EXPECT_EQ(0x10, view[0]);
69   static_assert(!std::is_assignable<decltype(view[0]), uint8_t>::value,
70                 "BufferView values should not be mutable.");
71 
72   MutableBufferView mutable_view(bytes_.data(), bytes_.size());
73 
74   EXPECT_EQ(bytes_.data(), &mutable_view[0]);
75   mutable_view[0] = 42;
76   EXPECT_EQ(42, mutable_view[0]);
77 }
78 
TEST_F(BufferViewTest,SubRegion)79 TEST_F(BufferViewTest, SubRegion) {
80   ConstBufferView view(bytes_.data(), bytes_.size());
81 
82   ConstBufferView sub_view = view[{2, 4}];
83   EXPECT_EQ(view.begin() + 2, sub_view.begin());
84   EXPECT_EQ(size_t(4), sub_view.size());
85 }
86 
TEST_F(BufferViewTest,Shrink)87 TEST_F(BufferViewTest, Shrink) {
88   ConstBufferView buffer(bytes_.data(), bytes_.size());
89 
90   buffer.shrink(bytes_.size());
91   EXPECT_EQ(bytes_.size(), buffer.size());
92   buffer.shrink(2);
93   EXPECT_EQ(size_t(2), buffer.size());
94   EXPECT_DCHECK_DEATH(buffer.shrink(bytes_.size()));
95 }
96 
TEST_F(BufferViewTest,Read)97 TEST_F(BufferViewTest, Read) {
98   ConstBufferView buffer(bytes_.data(), bytes_.size());
99 
100   EXPECT_EQ(0x10U, buffer.read<uint8_t>(0));
101   EXPECT_EQ(0x54U, buffer.read<uint8_t>(2));
102 
103   EXPECT_EQ(0x3210U, buffer.read<uint16_t>(0));
104   EXPECT_EQ(0x7654U, buffer.read<uint16_t>(2));
105 
106   EXPECT_EQ(0x76543210U, buffer.read<uint32_t>(0));
107   EXPECT_EQ(0xBA987654U, buffer.read<uint32_t>(2));
108 
109   EXPECT_EQ(0xFEDCBA9876543210ULL, buffer.read<uint64_t>(0));
110 
111   EXPECT_EQ(0x00, buffer.read<uint8_t>(9));
112   EXPECT_DEATH(buffer.read<uint8_t>(10), "");
113 
114   EXPECT_EQ(0x0010FEDCU, buffer.read<uint32_t>(6));
115   EXPECT_DEATH(buffer.read<uint32_t>(7), "");
116 }
117 
TEST_F(BufferViewTest,Write)118 TEST_F(BufferViewTest, Write) {
119   MutableBufferView buffer(bytes_.data(), bytes_.size());
120 
121   buffer.write<uint32_t>(0, 0x01234567);
122   buffer.write<uint32_t>(4, 0x89ABCDEF);
123   EXPECT_EQ(ParseHexString("67 45 23 01 EF CD AB 89 10 00"),
124             std::vector<uint8_t>(buffer.begin(), buffer.end()));
125 
126   buffer.write<uint8_t>(9, 0xFF);
127   EXPECT_DEATH(buffer.write<uint8_t>(10, 0xFF), "");
128 
129   buffer.write<uint32_t>(6, 0xFFFFFFFF);
130   EXPECT_DEATH(buffer.write<uint32_t>(7, 0xFFFFFFFF), "");
131 }
132 
TEST_F(BufferViewTest,Modify)133 TEST_F(BufferViewTest, Modify) {
134   struct TestStruct {
135     uint32_t a;
136     uint32_t b;
137   };
138 
139   MutableBufferView buffer(bytes_.data(), bytes_.size());
140 
141   buffer.modify<TestStruct>(0).a = 0x01234567;
142   buffer.modify<TestStruct>(0).b = 0x89ABCDEF;
143   EXPECT_EQ(ParseHexString("67 45 23 01 EF CD AB 89 10 00"),
144             std::vector<uint8_t>(buffer.begin(), buffer.end()));
145 
146   buffer.modify<uint8_t>(9);
147   EXPECT_DEATH(buffer.modify<uint8_t>(10), "");
148 
149   buffer.modify<uint32_t>(6);
150   EXPECT_DEATH(buffer.modify<uint32_t>(7), "");
151 }
152 
TEST_F(BufferViewTest,CanAccess)153 TEST_F(BufferViewTest, CanAccess) {
154   MutableBufferView buffer(bytes_.data(), bytes_.size());
155   EXPECT_TRUE(buffer.can_access<uint32_t>(0));
156   EXPECT_TRUE(buffer.can_access<uint32_t>(6));
157   EXPECT_FALSE(buffer.can_access<uint32_t>(7));
158   EXPECT_FALSE(buffer.can_access<uint32_t>(10));
159   EXPECT_FALSE(buffer.can_access<uint32_t>(0xFFFFFFFFU));
160 
161   EXPECT_TRUE(buffer.can_access<uint8_t>(0));
162   EXPECT_TRUE(buffer.can_access<uint8_t>(7));
163   EXPECT_TRUE(buffer.can_access<uint8_t>(9));
164   EXPECT_FALSE(buffer.can_access<uint8_t>(10));
165   EXPECT_FALSE(buffer.can_access<uint8_t>(0xFFFFFFFF));
166 }
167 
TEST_F(BufferViewTest,LocalRegion)168 TEST_F(BufferViewTest, LocalRegion) {
169   ConstBufferView view(bytes_.data(), bytes_.size());
170 
171   BufferRegion region = view.local_region();
172   EXPECT_EQ(0U, region.offset);
173   EXPECT_EQ(bytes_.size(), region.size);
174 }
175 
TEST_F(BufferViewTest,Covers)176 TEST_F(BufferViewTest, Covers) {
177   EXPECT_TRUE(ConstBufferView().covers({0, 0}));
178   EXPECT_FALSE(ConstBufferView().covers({0, 1}));
179 
180   ConstBufferView view(bytes_.data(), bytes_.size());
181 
182   EXPECT_TRUE(view.covers({0, 0}));
183   EXPECT_TRUE(view.covers({0, 1}));
184   EXPECT_TRUE(view.covers({0, bytes_.size()}));
185   EXPECT_FALSE(view.covers({0, bytes_.size() + 1}));
186   EXPECT_FALSE(view.covers({1, bytes_.size()}));
187 
188   EXPECT_TRUE(view.covers({bytes_.size() - 1, 0}));
189   EXPECT_TRUE(view.covers({bytes_.size() - 1, 1}));
190   EXPECT_FALSE(view.covers({bytes_.size() - 1, 2}));
191   EXPECT_TRUE(view.covers({bytes_.size(), 0}));
192   EXPECT_FALSE(view.covers({bytes_.size(), 1}));
193   EXPECT_FALSE(view.covers({bytes_.size() + 1, 0}));
194   EXPECT_FALSE(view.covers({bytes_.size() + 1, 1}));
195 
196   EXPECT_FALSE(view.covers({1, size_t(-1)}));
197   EXPECT_FALSE(view.covers({size_t(-1), 1}));
198   EXPECT_FALSE(view.covers({size_t(-1), size_t(-1)}));
199 }
200 
TEST_F(BufferViewTest,CoversArray)201 TEST_F(BufferViewTest, CoversArray) {
202   ConstBufferView view(bytes_.data(), bytes_.size());
203 
204   for (uint32_t i = 1; i <= bytes_.size(); ++i) {
205     EXPECT_TRUE(view.covers_array(0, 1, i));
206     EXPECT_TRUE(view.covers_array(0, i, 1));
207     EXPECT_TRUE(view.covers_array(0, i, bytes_.size() / i));
208     EXPECT_TRUE(view.covers_array(0, bytes_.size() / i, i));
209     if (i < bytes_.size()) {
210       EXPECT_TRUE(view.covers_array(i, 1, bytes_.size() - i));
211       EXPECT_TRUE(view.covers_array(i, bytes_.size() - i, 1));
212     }
213     EXPECT_TRUE(view.covers_array(bytes_.size() - (bytes_.size() / i) * i, 1,
214                                   bytes_.size() / i));
215   }
216 
217   EXPECT_TRUE(view.covers_array(0, 0, bytes_.size()));
218   EXPECT_TRUE(view.covers_array(bytes_.size() - 1, 0, bytes_.size()));
219   EXPECT_TRUE(view.covers_array(bytes_.size(), 0, bytes_.size()));
220   EXPECT_TRUE(view.covers_array(0, 0, 0x10000));
221   EXPECT_TRUE(view.covers_array(bytes_.size() - 1, 0, 0x10000));
222   EXPECT_TRUE(view.covers_array(bytes_.size(), 0, 0x10000));
223 
224   EXPECT_FALSE(view.covers_array(0, 1, bytes_.size() + 1));
225   EXPECT_FALSE(view.covers_array(0, 2, bytes_.size()));
226   EXPECT_FALSE(view.covers_array(0, bytes_.size() + 11, 1));
227   EXPECT_FALSE(view.covers_array(0, bytes_.size(), 2));
228   EXPECT_FALSE(view.covers_array(1, bytes_.size(), 1));
229 
230   EXPECT_FALSE(view.covers_array(bytes_.size(), 1, 1));
231   EXPECT_TRUE(view.covers_array(bytes_.size(), 0, 1));
232   EXPECT_FALSE(view.covers_array(0, 0x10000, 0x10000));
233 }
234 
TEST_F(BufferViewTest,Equals)235 TEST_F(BufferViewTest, Equals) {
236   // Almost identical to |bytes_|, except at 2 places:         v  v
237   std::vector<uint8_t> bytes2 = ParseHexString("10 32 54 76 98 AB CD FE 10 00");
238   ConstBufferView view1(bytes_.data(), bytes_.size());
239   ConstBufferView view2(&bytes2[0], bytes2.size());
240 
241   EXPECT_TRUE(view1.equals(view1));
242   EXPECT_TRUE(view2.equals(view2));
243   EXPECT_FALSE(view1.equals(view2));
244   EXPECT_FALSE(view2.equals(view1));
245 
246   EXPECT_TRUE((view1[{0, 0}]).equals(view2[{0, 0}]));
247   EXPECT_TRUE((view1[{0, 0}]).equals(view2[{5, 0}]));
248   EXPECT_TRUE((view1[{0, 5}]).equals(view2[{0, 5}]));
249   EXPECT_FALSE((view1[{0, 6}]).equals(view2[{0, 6}]));
250   EXPECT_FALSE((view1[{0, 7}]).equals(view1[{0, 6}]));
251   EXPECT_TRUE((view1[{5, 3}]).equals(view1[{5, 3}]));
252   EXPECT_FALSE((view1[{5, 1}]).equals(view1[{5, 3}]));
253   EXPECT_TRUE((view2[{0, 1}]).equals(view2[{8, 1}]));
254   EXPECT_FALSE((view2[{1, 1}]).equals(view2[{8, 1}]));
255 }
256 
TEST_F(BufferViewTest,AlignOn)257 TEST_F(BufferViewTest, AlignOn) {
258   using size_type = ConstBufferView::size_type;
259   ConstBufferView image(bytes_.data(), bytes_.size());
260   ConstBufferView view = image;
261   ASSERT_EQ(10U, view.size());
262 
263   auto get_pos = [&image, &view]() -> size_type {
264     EXPECT_TRUE(view.begin() >= image.begin());  // Iterator compare.
265     return static_cast<size_type>(view.begin() - image.begin());
266   };
267 
268   EXPECT_EQ(0U, get_pos());
269   view.remove_prefix(1U);
270   EXPECT_EQ(1U, get_pos());
271   view.remove_prefix(4U);
272   EXPECT_EQ(5U, get_pos());
273 
274   // Align.
275   EXPECT_TRUE(view.AlignOn(image, 1U));  // Trival case.
276   EXPECT_EQ(5U, get_pos());
277 
278   EXPECT_TRUE(view.AlignOn(image, 2U));
279   EXPECT_EQ(6U, get_pos());
280   EXPECT_TRUE(view.AlignOn(image, 2U));
281   EXPECT_EQ(6U, get_pos());
282 
283   EXPECT_TRUE(view.AlignOn(image, 4U));
284   EXPECT_EQ(8U, get_pos());
285   EXPECT_TRUE(view.AlignOn(image, 2U));
286   EXPECT_EQ(8U, get_pos());
287 
288   view.remove_prefix(1U);
289   EXPECT_EQ(9U, get_pos());
290 
291   // Pos is at 9, align to 4 would yield 12, but size is 10, so this fails.
292   EXPECT_FALSE(view.AlignOn(image, 4U));
293   EXPECT_EQ(9U, get_pos());
294   EXPECT_TRUE(view.AlignOn(image, 2U));
295   EXPECT_EQ(10U, get_pos());
296 }
297 
298 }  // namespace zucchini
299