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