• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2019 The Chromium Authors
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 "base/containers/buffer_iterator.h"
6 
7 #include <string.h>
8 
9 #include <limits>
10 #include <vector>
11 
12 #include "testing/gtest/include/gtest/gtest.h"
13 
14 namespace base {
15 namespace {
16 
17 struct TestStruct {
18   uint32_t one;
19   uint8_t two;
20 };
21 
operator ==(const TestStruct & lhs,const TestStruct & rhs)22 bool operator==(const TestStruct& lhs, const TestStruct& rhs) {
23   return lhs.one == rhs.one && lhs.two == rhs.two;
24 }
25 
CreateTestStruct()26 TestStruct CreateTestStruct() {
27   TestStruct expected;
28   expected.one = 0xabcdef12;
29   expected.two = 0x34;
30   return expected;
31 }
32 
TEST(BufferIteratorTest,Object)33 TEST(BufferIteratorTest, Object) {
34   TestStruct expected = CreateTestStruct();
35 
36   char buffer[sizeof(TestStruct)];
37   memcpy(buffer, &expected, sizeof(buffer));
38 
39   {
40     // Read the object.
41     BufferIterator<char> iterator(buffer, sizeof(buffer));
42     const TestStruct* actual = iterator.Object<TestStruct>();
43     EXPECT_EQ(expected, *actual);
44   }
45   {
46     // Iterator's view of the data is not large enough to read the object.
47     BufferIterator<char> iterator(buffer, sizeof(buffer) - 1);
48     const TestStruct* actual = iterator.Object<TestStruct>();
49     EXPECT_FALSE(actual);
50   }
51 }
52 
TEST(BufferIteratorTest,MutableObject)53 TEST(BufferIteratorTest, MutableObject) {
54   TestStruct expected = CreateTestStruct();
55 
56   char buffer[sizeof(TestStruct)];
57 
58   BufferIterator<char> iterator(buffer, sizeof(buffer));
59 
60   {
61     // Write the object.
62     TestStruct* actual = iterator.MutableObject<TestStruct>();
63     actual->one = expected.one;
64     actual->two = expected.two;
65   }
66 
67   // Rewind the iterator.
68   iterator.Seek(0);
69 
70   {
71     // Read the object back.
72     const TestStruct* actual = iterator.Object<TestStruct>();
73     EXPECT_EQ(expected, *actual);
74   }
75 }
76 
TEST(BufferIteratorTest,ObjectSizeOverflow)77 TEST(BufferIteratorTest, ObjectSizeOverflow) {
78   char buffer[64];
79   BufferIterator<char> iterator(buffer, std::numeric_limits<size_t>::max());
80 
81   auto* pointer = iterator.Object<uint64_t>();
82   EXPECT_TRUE(pointer);
83 
84   iterator.Seek(iterator.total_size() - 1);
85 
86   auto* invalid_pointer = iterator.Object<uint64_t>();
87   EXPECT_FALSE(invalid_pointer);
88 }
89 
TEST(BufferIteratorTest,Span)90 TEST(BufferIteratorTest, Span) {
91   TestStruct expected = CreateTestStruct();
92 
93   std::vector<char> buffer(sizeof(TestStruct) * 3);
94 
95   {
96     // Load the span with data.
97     BufferIterator<char> iterator(buffer);
98     span<TestStruct> span = iterator.MutableSpan<TestStruct>(3);
99     for (auto& ts : span) {
100       memcpy(&ts, &expected, sizeof(expected));
101     }
102   }
103   {
104     // Read the data back out.
105     BufferIterator<char> iterator(buffer);
106 
107     const TestStruct* actual = iterator.Object<TestStruct>();
108     EXPECT_EQ(expected, *actual);
109 
110     actual = iterator.Object<TestStruct>();
111     EXPECT_EQ(expected, *actual);
112 
113     actual = iterator.Object<TestStruct>();
114     EXPECT_EQ(expected, *actual);
115 
116     EXPECT_EQ(iterator.total_size(), iterator.position());
117   }
118   {
119     // Cannot create spans larger than there are data for.
120     BufferIterator<char> iterator(buffer);
121     span<const TestStruct> span = iterator.Span<TestStruct>(4);
122     EXPECT_TRUE(span.empty());
123   }
124 }
125 
TEST(BufferIteratorTest,SpanOverflow)126 TEST(BufferIteratorTest, SpanOverflow) {
127   char buffer[64];
128 
129   BufferIterator<char> iterator(buffer, std::numeric_limits<size_t>::max());
130   {
131     span<const uint64_t> empty_span = iterator.Span<uint64_t>(
132         (std::numeric_limits<size_t>::max() / sizeof(uint64_t)) + 1);
133     EXPECT_TRUE(empty_span.empty());
134   }
135   {
136     span<const uint64_t> empty_span =
137         iterator.Span<uint64_t>(std::numeric_limits<size_t>::max());
138     EXPECT_TRUE(empty_span.empty());
139   }
140   {
141     iterator.Seek(iterator.total_size() - 7);
142     span<const uint64_t> empty_span = iterator.Span<uint64_t>(1);
143     EXPECT_TRUE(empty_span.empty());
144   }
145 }
146 
TEST(BufferIteratorTest,Position)147 TEST(BufferIteratorTest, Position) {
148   char buffer[64];
149   BufferIterator<char> iterator(buffer, sizeof(buffer));
150   EXPECT_EQ(sizeof(buffer), iterator.total_size());
151 
152   size_t position = iterator.position();
153   EXPECT_EQ(0u, position);
154 
155   iterator.Object<uint8_t>();
156   EXPECT_EQ(sizeof(uint8_t), iterator.position() - position);
157   position = iterator.position();
158 
159   iterator.Object<uint32_t>();
160   EXPECT_EQ(sizeof(uint32_t), iterator.position() - position);
161   position = iterator.position();
162 
163   iterator.Seek(32);
164   EXPECT_EQ(32u, iterator.position());
165 
166   EXPECT_EQ(sizeof(buffer), iterator.total_size());
167 }
168 
TEST(BufferIteratorTest,CopyObject)169 TEST(BufferIteratorTest, CopyObject) {
170   TestStruct expected = CreateTestStruct();
171 
172   constexpr int kNumCopies = 3;
173   char buffer[sizeof(TestStruct) * kNumCopies];
174   for (int i = 0; i < kNumCopies; i++)
175     memcpy(buffer + i * sizeof(TestStruct), &expected, sizeof(TestStruct));
176 
177   BufferIterator<char> iterator(buffer);
178   absl::optional<TestStruct> actual;
179   for (int i = 0; i < kNumCopies; i++) {
180     actual = iterator.CopyObject<TestStruct>();
181     ASSERT_TRUE(actual.has_value());
182     EXPECT_EQ(expected, *actual);
183   }
184   actual = iterator.CopyObject<TestStruct>();
185   EXPECT_FALSE(actual.has_value());
186 }
187 
TEST(BufferIteratorTest,SeekWithSizeConfines)188 TEST(BufferIteratorTest, SeekWithSizeConfines) {
189   const char buffer[] = "vindicate";
190   BufferIterator<const char> iterator(buffer);
191   iterator.Seek(5);
192   iterator.TruncateTo(3);
193   EXPECT_TRUE(iterator.Span<char>(4).empty());
194 
195   std::string result;
196   while (const char* c = iterator.Object<char>())
197     result += *c;
198   EXPECT_EQ(result, "cat");
199 }
200 
201 }  // namespace
202 }  // namespace base
203