1 // Copyright 2015 The Chromium OS 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 <stdint.h>
6 
7 #include <algorithm>
8 #include <vector>
9 
10 #include "buffer_reader.h"
11 #include "compat/string.h"
12 #include "compat/test.h"
13 
14 namespace quipper {
15 
16 // Move the cursor around and make sure the offset is properly set each time.
TEST(BufferReaderTest,MoveOffset)17 TEST(BufferReaderTest, MoveOffset) {
18   const std::vector<uint8_t> input(1000);
19   BufferReader reader(input.data(), input.size());
20 
21   // Make sure the reader was properly created.
22   EXPECT_EQ(input.size(), reader.size());
23   EXPECT_EQ(0, reader.Tell());
24 
25   // Move the read cursor around.
26   reader.SeekSet(100);
27   EXPECT_EQ(100, reader.Tell());
28   reader.SeekSet(900);
29   EXPECT_EQ(900, reader.Tell());
30   reader.SeekSet(500);
31   EXPECT_EQ(500, reader.Tell());
32 
33   // The cursor can be set to past the end of the buffer, but can't perform any
34   // read operations there.
35   reader.SeekSet(1200);
36   EXPECT_EQ(1200, reader.Tell());
37   int dummy;
38   EXPECT_FALSE(reader.ReadData(sizeof(dummy), &dummy));
39 }
40 
41 // Make sure that the reader can handle a read size of zero.
TEST(BufferReaderTest,ReadZeroBytes)42 TEST(BufferReaderTest, ReadZeroBytes) {
43   const std::vector<uint8_t> input(10);
44   BufferReader reader(input.data(), input.size());
45 
46   // Move to some location within the buffer.
47   reader.SeekSet(5);
48   EXPECT_TRUE(reader.ReadData(0, NULL));
49 
50   // Make sure the read pointer hasn't moved.
51   EXPECT_EQ(5, reader.Tell());
52 }
53 
54 // Read in all data from the input buffer at once.
TEST(BufferReaderTest,ReadSingleChunk)55 TEST(BufferReaderTest, ReadSingleChunk) {
56   const string kInputData = "abcdefghijklmnopqrstuvwxyz";
57   BufferReader reader(kInputData.data(), kInputData.size());
58 
59   std::vector<uint8_t> output(kInputData.size());
60   EXPECT_TRUE(reader.ReadData(output.size(), output.data()));
61   EXPECT_EQ(output.size(), reader.Tell());
62   // Compare input and output data, converting the latter to a string for
63   // clarity of error messages.
64   EXPECT_EQ(kInputData, string(output.begin(), output.end()));
65 }
66 
67 // Test the ReadDataValue() function, which is a wrapper around ReadData().
TEST(BufferReaderTest,ReadDataValue)68 TEST(BufferReaderTest, ReadDataValue) {
69   const string kInputData = "abcdefghijklmnopqrstuvwxyz";
70   BufferReader reader(kInputData.data(), kInputData.size());
71 
72   std::vector<uint8_t> output(kInputData.size());
73   EXPECT_TRUE(reader.ReadDataValue(output.size(), "data", output.data()));
74   EXPECT_EQ(output.size(), reader.Tell());
75 
76   EXPECT_EQ(kInputData, string(output.begin(), output.end()));
77 }
78 
79 // Read in all data from the input buffer in multiple chunks, in order.
TEST(BufferReaderTest,ReadMultipleChunks)80 TEST(BufferReaderTest, ReadMultipleChunks) {
81   // This string is 26 characters long.
82   const string kInputData = "abcdefghijklmnopqrstuvwxyz";
83   BufferReader reader(kInputData.data(), kInputData.size());
84 
85   // Make sure the cursor is updated after each read.
86   std::vector<uint8_t> output(kInputData.size());
87   EXPECT_TRUE(reader.ReadData(10, output.data() + reader.Tell()));
88   EXPECT_EQ(10, reader.Tell());
89   EXPECT_TRUE(reader.ReadData(5, output.data() + reader.Tell()));
90   EXPECT_EQ(15, reader.Tell());
91   EXPECT_TRUE(reader.ReadData(5, output.data() + reader.Tell()));
92   EXPECT_EQ(20, reader.Tell());
93   EXPECT_TRUE(reader.ReadData(6, output.data() + reader.Tell()));
94   EXPECT_EQ(26, reader.Tell());
95 
96   EXPECT_EQ(kInputData, string(output.begin(), output.end()));
97 }
98 
99 // Read in all data from the input buffer in multiple chunks, but not in order.
TEST(BufferReaderTest,ReadWithJumps)100 TEST(BufferReaderTest, ReadWithJumps) {
101   // This string contains four parts, each 10 characters long.
102   const string kInputData =
103       "0:abcdefg;"
104       "1:hijklmn;"
105       "2:opqrstu;"
106       "3:vwxyzABC";
107   BufferReader reader(kInputData.data(), kInputData.size());
108 
109   // Read the data in multiple operations, but not in order. Overwrite the
110   // previously read data in the destination buffer during each read.
111   std::vector<uint8_t> output(10);
112 
113   reader.SeekSet(20);
114   EXPECT_TRUE(reader.ReadData(10, output.data()));
115   EXPECT_EQ(30, reader.Tell());
116   EXPECT_EQ("2:opqrstu;", string(output.begin(), output.end()));
117 
118   reader.SeekSet(10);
119   EXPECT_TRUE(reader.ReadData(10, output.data()));
120   EXPECT_EQ(20, reader.Tell());
121   EXPECT_EQ("1:hijklmn;", string(output.begin(), output.end()));
122 
123   reader.SeekSet(30);
124   EXPECT_TRUE(reader.ReadData(10, output.data()));
125   EXPECT_EQ(40, reader.Tell());
126   EXPECT_EQ("3:vwxyzABC", string(output.begin(), output.end()));
127 
128   reader.SeekSet(0);
129   EXPECT_TRUE(reader.ReadData(10, output.data()));
130   EXPECT_EQ(10, reader.Tell());
131   EXPECT_EQ("0:abcdefg;", string(output.begin(), output.end()));
132 }
133 
134 // Test reading past the end of the buffer.
TEST(BufferReaderTest,ReadPastEndOfData)135 TEST(BufferReaderTest, ReadPastEndOfData) {
136   // This string is 26 characters long.
137   const string kInputData = "abcdefghijklmnopqrstuvwxyz";
138   BufferReader reader(kInputData.data(), kInputData.size());
139 
140   // Must not be able to read past the end of the buffer.
141   std::vector<uint8_t> output(kInputData.size());
142   reader.SeekSet(0);
143   EXPECT_FALSE(reader.ReadData(30, output.data()));
144   // The read pointer should not have moved.
145   EXPECT_EQ(0, reader.Tell());
146 
147   // Should still be able to read within the bounds of the buffer, despite the
148   // out-of-bounds read earlier.
149   EXPECT_TRUE(reader.ReadData(13, output.data()));
150   EXPECT_EQ(13, reader.Tell());
151 
152   // Now attempt another read past the end of the buffer, but starting from the
153   // ending position of the previous read operation.
154   EXPECT_FALSE(reader.ReadData(20, output.data() + reader.Tell()));
155   // The read pointer should be unchanged.
156   EXPECT_EQ(13, reader.Tell());
157 
158   // Read the rest of the data and make sure it matches the input.
159   EXPECT_TRUE(reader.ReadData(13, output.data() + reader.Tell()));
160   EXPECT_EQ(26, reader.Tell());
161 
162   EXPECT_EQ(kInputData, string(output.begin(), output.end()));
163 }
164 
165 // Test string reads.
TEST(BufferReaderTest,ReadString)166 TEST(BufferReaderTest, ReadString) {
167   // Construct an input string.
168   string input("The quick brown fox jumps over the lazy dog.");
169 
170   // Read the full string.
171   BufferReader full_reader(input.data(), input.size());
172   string full_reader_output;
173   EXPECT_TRUE(full_reader.ReadString(input.size(), &full_reader_output));
174   EXPECT_EQ(input.size(), full_reader.Tell());
175   EXPECT_EQ(input, full_reader_output);
176 
177   // Read the full string plus the null pointer.
178   BufferReader full_null_reader(input.data(), input.size() + 1);
179   string full_null_reader_output;
180   EXPECT_TRUE(
181       full_null_reader.ReadString(input.size() + 1, &full_null_reader_output));
182   EXPECT_EQ(input.size() + 1, full_null_reader.Tell());
183   EXPECT_EQ(input, full_null_reader_output);
184 
185   // Read the first half of the string.
186   BufferReader half_reader(input.data(), input.size() / 2);
187   string half_reader_output;
188   EXPECT_TRUE(half_reader.ReadString(input.size() / 2, &half_reader_output));
189   EXPECT_EQ(input.size() / 2, half_reader.Tell());
190   EXPECT_EQ(input.substr(0, input.size() / 2), half_reader_output);
191 
192   // Attempt to read past the end of the string.
193   BufferReader past_end_reader(input.data(), input.size());
194   string past_end_reader_output;
195   EXPECT_FALSE(
196       past_end_reader.ReadString(input.size() + 2, &past_end_reader_output));
197 
198   // Create a vector with some extra padding behind it. The padding should be
199   // all zeroes. Read from this vector, with a size that encompasses the
200   // padding.
201   std::vector<char> input_vector(input.begin(), input.end());
202   input_vector.resize(input.size() + 10, '\0');
203 
204   BufferReader vector_reader(input_vector.data(), input_vector.size());
205   string vector_reader_output;
206   EXPECT_TRUE(
207       vector_reader.ReadString(input_vector.size(), &vector_reader_output));
208   // The reader should have read past the padding too.
209   EXPECT_EQ(input_vector.size(), vector_reader.Tell());
210   EXPECT_EQ(input, vector_reader_output);
211 }
212 
MakeStringWithNullsForSpaces(string str)213 string MakeStringWithNullsForSpaces(string str) {
214   std::replace(str.begin(), str.end(), ' ', '\0');
215   return str;
216 }
217 
TEST(BufferReaderTest,ReadDataString)218 TEST(BufferReaderTest, ReadDataString) {
219   // Construct an input string.
220   string input = MakeStringWithNullsForSpaces(
221       "The quick brown fox jumps over the lazy dog.");
222 
223   BufferReader reader(input.data(), input.size());
224 
225   string expected_out;
226   string out;
227   out.resize(5);
228   EXPECT_TRUE(reader.ReadDataString(10, &out));
229   expected_out = MakeStringWithNullsForSpaces("The quick ");
230   EXPECT_EQ(10, expected_out.size()) << "Sanity";
231   EXPECT_EQ(expected_out, out);
232 
233   out.resize(15);
234   EXPECT_TRUE(reader.ReadDataString(10, &out));
235   expected_out = MakeStringWithNullsForSpaces("brown fox ");
236   EXPECT_EQ(10, expected_out.size()) << "Sanity";
237   EXPECT_EQ(expected_out, out);
238 
239   reader.SeekSet(reader.size());
240 
241   // Check destination contents don't get modified on failure.
242   out.resize(5);
243   expected_out = out;
244   EXPECT_FALSE(reader.ReadDataString(10, &out));
245   EXPECT_EQ(expected_out, out) << "Should be unchanged.";
246 
247   out.resize(15);
248   expected_out = out;
249   EXPECT_FALSE(reader.ReadDataString(10, &out));
250   EXPECT_EQ(expected_out, out) << "Should be unchanged.";
251 
252   EXPECT_FALSE(out.empty()) << "Sanity";
253   EXPECT_TRUE(reader.ReadDataString(0, &out));
254   EXPECT_TRUE(out.empty()) << "Read zero-length should clear output.";
255 }
256 
257 // Reads data to a buffer and verifies that the buffer has not been modified
258 // beyond the writable boundaries.
TEST(BufferReaderTest,NoWritingOutOfBounds)259 TEST(BufferReaderTest, NoWritingOutOfBounds) {
260   // The input data contains all zeroes.
261   std::vector<uint8_t> input(800, 0);
262   BufferReader reader(input.data(), input.size());
263 
264   // A sentinel value that fills memory to detect when that section of memory is
265   // overwritten. If the memory shows another value, it means it has been
266   // overwritten.
267   const char kUnwrittenValue = 0xaa;
268 
269   // Create a destination buffer filled with the above sentinel value.
270   std::vector<uint8_t> buffer(1000, kUnwrittenValue);
271   // Only write to the range [100, 900).
272   EXPECT_TRUE(reader.ReadData(800, buffer.data() + 100));
273 
274   // Check that the data was written to the writable part of the buffer.
275   EXPECT_EQ(input,
276             std::vector<uint8_t>(buffer.begin() + 100, buffer.begin() + 900));
277 
278   // Now make sure that the other parts of the buffer haven't been overwritten.
279   const std::vector<uint8_t> expected_unwritten_part(100, kUnwrittenValue);
280   EXPECT_EQ(expected_unwritten_part,
281             std::vector<uint8_t>(buffer.begin(), buffer.begin() + 100));
282   EXPECT_EQ(expected_unwritten_part,
283             std::vector<uint8_t>(buffer.begin() + 900, buffer.begin() + 1000));
284 }
285 
286 }  // namespace quipper
287