Home | History | Annotate | Download | only in quipper
      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