1 /*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <stdlib.h>
18 #include <string.h>
19
20 #include <gtest/gtest.h>
21
22 #include <nvram/messages/io.h>
23
24 namespace nvram {
25
26 namespace {
27
28 // A simple |InputStreamBuffer| implementation that sets up a sequence of
29 // windows of |sizes| specified by the template parameters. Each byte read from
30 // the buffer has a value corresponding to its position in the stream.
31 template<size_t... sizes>
32 class TestInputStreamBuffer : public InputStreamBuffer {
33 public:
TestInputStreamBuffer()34 TestInputStreamBuffer() {
35 Advance();
36 }
37
38 private:
Advance()39 bool Advance() override {
40 if (index_ >= (sizeof(kSizes) / sizeof(kSizes[0]))) {
41 return false;
42 }
43
44 memset(buffer, 0xff, kMaxSize);
45 const size_t size = kSizes[index_] < kMaxSize ? kSizes[index_] : kMaxSize;
46 pos_ = buffer;
47 end_ = buffer + size;
48 for (uint8_t* p = buffer; p < end_; ++p) {
49 *p = static_cast<uint8_t>(count_++ % 256);
50 }
51 ++index_;
52 return true;
53 }
54
55 static constexpr size_t kMaxSize = 256;
56 static constexpr size_t kSizes[] = { sizes... };
57
58 uint8_t buffer[kMaxSize];
59 size_t index_ = 0;
60 size_t count_ = 0;
61 };
62
63 template<size_t... sizes>
64 constexpr size_t TestInputStreamBuffer<sizes...>::kSizes[];
65
66 // Tests whether a read of the given size returns the correct data, i.e. bytes
67 // with consecutive values starting at |pos|.
CheckRead(InputStreamBuffer * buffer,size_t size,size_t pos)68 void CheckRead(InputStreamBuffer* buffer, size_t size, size_t pos) {
69 uint8_t data[256];
70 ASSERT_LE(size, sizeof(data));
71 EXPECT_TRUE(buffer->Read(data, size));
72 for (uint8_t* p = data; p < data + size; ++p) {
73 EXPECT_EQ(pos++ % 256, *p);
74 }
75 }
76
77 } // namespace
78
TEST(InputStreamBufferTest,Basic)79 TEST(InputStreamBufferTest, Basic) {
80 TestInputStreamBuffer<10> buf;
81 EXPECT_FALSE(buf.Done());
82
83 uint8_t byte = 0;
84 EXPECT_TRUE(buf.ReadByte(&byte));
85 EXPECT_EQ(0, byte);
86 EXPECT_FALSE(buf.Done());
87
88 CheckRead(&buf, 6, 1);
89 EXPECT_FALSE(buf.Done());
90
91 EXPECT_TRUE(buf.Skip(3));
92 EXPECT_TRUE(buf.Done());
93 }
94
TEST(InputStreamBufferTest,Empty)95 TEST(InputStreamBufferTest, Empty) {
96 InputStreamBuffer buf(nullptr, nullptr);
97 EXPECT_TRUE(buf.Done());
98 uint8_t byte = 0;
99 EXPECT_FALSE(buf.ReadByte(&byte));
100 }
101
TEST(InputStreamBufferTest,LargeRead)102 TEST(InputStreamBufferTest, LargeRead) {
103 TestInputStreamBuffer<10> buf;
104 uint8_t read_buf[10];
105 EXPECT_FALSE(buf.Read(read_buf, SIZE_MAX));
106 }
107
TEST(InputStreamBufferTest,LargeSkip)108 TEST(InputStreamBufferTest, LargeSkip) {
109 TestInputStreamBuffer<10> buf;
110 EXPECT_FALSE(buf.Skip(SIZE_MAX));
111 }
112
TEST(InputStreamBufferTest,OverlappingReadByte)113 TEST(InputStreamBufferTest, OverlappingReadByte) {
114 TestInputStreamBuffer<1, 1> buf;
115
116 uint8_t byte = 0;
117 EXPECT_TRUE(buf.ReadByte(&byte));
118 EXPECT_EQ(0, byte);
119 EXPECT_FALSE(buf.Done());
120
121 EXPECT_TRUE(buf.ReadByte(&byte));
122 EXPECT_EQ(1, byte);
123 EXPECT_TRUE(buf.Done());
124 }
125
TEST(InputStreamBufferTest,OverlappingRead)126 TEST(InputStreamBufferTest, OverlappingRead) {
127 TestInputStreamBuffer<10, 10, 10> buf;
128 CheckRead(&buf, 15, 0);
129 CheckRead(&buf, 10, 15);
130 CheckRead(&buf, 5, 25);
131 EXPECT_TRUE(buf.Done());
132 }
133
TEST(InputStreamBufferTest,OverlappingSkip)134 TEST(InputStreamBufferTest, OverlappingSkip) {
135 TestInputStreamBuffer<10, 10, 10> buf;
136 EXPECT_TRUE(buf.Skip(15));
137 EXPECT_TRUE(buf.Skip(10));
138 EXPECT_TRUE(buf.Skip(5));
139 EXPECT_TRUE(buf.Done());
140 }
141
TEST(NestedInputStreamBufferTest,Large)142 TEST(NestedInputStreamBufferTest, Large) {
143 TestInputStreamBuffer<10> buf;
144 NestedInputStreamBuffer nested(&buf, SIZE_MAX);
145 EXPECT_FALSE(nested.Skip(SIZE_MAX));
146 }
147
TEST(NestedInputStreamBufferTest,Short)148 TEST(NestedInputStreamBufferTest, Short) {
149 TestInputStreamBuffer<10> buf;
150 NestedInputStreamBuffer nested(&buf, 5);
151 CheckRead(&nested, 5, 0);
152 EXPECT_TRUE(nested.Done());
153 EXPECT_FALSE(nested.Skip(1));
154 }
155
TEST(NestedInputStreamBufferTest,Matching)156 TEST(NestedInputStreamBufferTest, Matching) {
157 TestInputStreamBuffer<10, 5> buf;
158 NestedInputStreamBuffer nested(&buf, 10);
159 CheckRead(&nested, 10, 0);
160 EXPECT_TRUE(nested.Done());
161 EXPECT_FALSE(nested.Skip(1));
162 }
163
TEST(NestedInputStreamBufferTest,Overlapping)164 TEST(NestedInputStreamBufferTest, Overlapping) {
165 TestInputStreamBuffer<2, 3, 5, 8> buf;
166 NestedInputStreamBuffer nested(&buf, 16);
167 CheckRead(&nested, 8, 0);
168 EXPECT_FALSE(nested.Done());
169 CheckRead(&nested, 8, 8);
170 EXPECT_TRUE(nested.Done());
171 EXPECT_FALSE(nested.Skip(1));
172 }
173
174 namespace {
175
176 // An |OutputStreamBuffer| implementation backed by a sequence of buffer windows
177 // of |sizes| specified as template parameters. The output is expected to be
178 // sequential byte values starting at 0.
179 template<size_t... sizes>
180 class TestOutputStreamBuffer : public OutputStreamBuffer {
181 public:
TestOutputStreamBuffer()182 TestOutputStreamBuffer() {
183 Advance();
184 }
185
~TestOutputStreamBuffer()186 ~TestOutputStreamBuffer() {
187 EXPECT_TRUE(Verify());
188 }
189
Verify()190 bool Verify() {
191 for (; check_pos_ < pos_; check_pos_++, count_++) {
192 data_matches_ &= *check_pos_ == (count_ % 256);
193 }
194
195 return data_matches_;
196 }
197
198 private:
Advance()199 bool Advance() override {
200 if (index_ >= (sizeof(kSizes) / sizeof(kSizes[0]))) {
201 return false;
202 }
203
204 pos_ = end_;
205 Verify();
206
207 memset(buffer, 0xff, kMaxSize);
208 const size_t size = kSizes[index_] < kMaxSize ? kSizes[index_] : kMaxSize;
209 pos_ = buffer;
210 check_pos_ = buffer;
211 end_ = buffer + size;
212 ++index_;
213 return true;
214 }
215
216 static constexpr size_t kMaxSize = 256;
217 static constexpr size_t kSizes[] = { sizes... };
218
219 uint8_t buffer[kMaxSize];
220 size_t index_ = 0;
221
222 // The pointer in buffer until which the data has been checked to match the
223 // expectations.
224 uint8_t* check_pos_ = nullptr;
225
226 // The counter that determines the expected value for the buffer bytes.
227 size_t count_ = 0;
228
229 // Whether all bytes that have been checked so far had the expected value.
230 bool data_matches_ = true;
231 };
232
233 template<size_t... sizes>
234 constexpr size_t TestOutputStreamBuffer<sizes...>::kSizes[];
235
236 // Writes a buffer of |size| to |buf|. The buffer contains consecutive byte
237 // value starting at pos.
WriteBuf(OutputStreamBuffer * buffer,size_t size,size_t pos)238 void WriteBuf(OutputStreamBuffer* buffer, size_t size, size_t pos) {
239 uint8_t data[1024];
240 ASSERT_LE(size, sizeof(data));
241 for (uint8_t* p = data; p < data + size; ++p) {
242 *p = pos++ % 256;
243 }
244 EXPECT_TRUE(buffer->Write(data, size));
245 }
246
247 } // namespace
248
TEST(OutputStreamBufferTest,Basic)249 TEST(OutputStreamBufferTest, Basic) {
250 TestOutputStreamBuffer<10> buf;
251 EXPECT_FALSE(buf.Done());
252
253 EXPECT_TRUE(buf.WriteByte(0));
254 EXPECT_TRUE(buf.WriteByte(1));
255 EXPECT_FALSE(buf.Done());
256 EXPECT_TRUE(buf.Verify());
257
258 WriteBuf(&buf, 6, 2);
259 EXPECT_FALSE(buf.Done());
260 EXPECT_TRUE(buf.Verify());
261
262 WriteBuf(&buf, 2, 8);
263 EXPECT_TRUE(buf.Done());
264 }
265
TEST(OutputStreamBufferTest,Empty)266 TEST(OutputStreamBufferTest, Empty) {
267 OutputStreamBuffer buf(nullptr, nullptr);
268 EXPECT_TRUE(buf.Done());
269 EXPECT_FALSE(buf.WriteByte(0));
270 }
271
TEST(OutputStreamBufferTest,ShortWrite)272 TEST(OutputStreamBufferTest, ShortWrite) {
273 TestOutputStreamBuffer<10> buf;
274 WriteBuf(&buf, 5, 0);
275 }
276
TEST(OutputStreamBufferTest,LargeWrite)277 TEST(OutputStreamBufferTest, LargeWrite) {
278 TestOutputStreamBuffer<5> buf;
279 uint8_t data[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
280 EXPECT_FALSE(buf.Write(data, sizeof(data)));
281 }
282
TEST(OutputStreamBufferTest,OverlappingWriteByte)283 TEST(OutputStreamBufferTest, OverlappingWriteByte) {
284 TestOutputStreamBuffer<1, 1> buf;
285 EXPECT_TRUE(buf.WriteByte(0));
286 EXPECT_FALSE(buf.Done());
287 EXPECT_TRUE(buf.WriteByte(1));
288 EXPECT_TRUE(buf.Done());
289 }
290
TEST(OutputStreamBufferTest,OverlappingWrite)291 TEST(OutputStreamBufferTest, OverlappingWrite) {
292 TestOutputStreamBuffer<10, 10, 10> buf;
293 WriteBuf(&buf, 15, 0);
294 EXPECT_FALSE(buf.Done());
295 WriteBuf(&buf, 10, 15);
296 EXPECT_FALSE(buf.Done());
297 WriteBuf(&buf, 5, 25);
298 EXPECT_TRUE(buf.Done());
299 }
300
TEST(CountingOutputStreamBuffer,Basic)301 TEST(CountingOutputStreamBuffer, Basic) {
302 CountingOutputStreamBuffer buf;
303 EXPECT_EQ(0U, buf.bytes_written());
304 EXPECT_FALSE(buf.Done());
305
306 WriteBuf(&buf, 15, 0);
307 EXPECT_EQ(15U, buf.bytes_written());
308 EXPECT_FALSE(buf.Done());
309
310 EXPECT_TRUE(buf.WriteByte(0));
311 EXPECT_EQ(16U, buf.bytes_written());
312 EXPECT_FALSE(buf.Done());
313
314 WriteBuf(&buf, 1024, 0);
315 EXPECT_EQ(1040U, buf.bytes_written());
316 EXPECT_FALSE(buf.Done());
317 }
318
TEST(BlobOutputStreamBuffer,Basic)319 TEST(BlobOutputStreamBuffer, Basic) {
320 Blob blob;
321 ASSERT_TRUE(blob.Resize(1024 * 1024));
322 BlobOutputStreamBuffer buf(&blob);
323
324 WriteBuf(&buf, 15, 0);
325 EXPECT_FALSE(buf.Done());
326
327 EXPECT_TRUE(buf.WriteByte(15));
328 EXPECT_FALSE(buf.Done());
329
330 EXPECT_TRUE(buf.Truncate());
331 EXPECT_EQ(16U, blob.size());
332 for (size_t i = 0; i < blob.size(); ++i) {
333 EXPECT_EQ(i % 256, blob.data()[i]);
334 }
335
336 WriteBuf(&buf, 1024, 16);
337 EXPECT_FALSE(buf.Done());
338
339 EXPECT_TRUE(buf.Truncate());
340 EXPECT_EQ(1040U, blob.size());
341 for (size_t i = 0; i < blob.size(); ++i) {
342 EXPECT_EQ(i % 256, blob.data()[i]);
343 }
344 }
345
346 } // namespace nvram
347