Home | History | Annotate | Download | only in media_galleries
      1 // Copyright 2013 The Chromium 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 <algorithm>
      6 #include <vector>
      7 
      8 #include "base/files/file.h"
      9 #include "base/files/file_util.h"
     10 #include "base/files/scoped_temp_dir.h"
     11 #include "chrome/common/media_galleries/pmp_constants.h"
     12 #include "chrome/common/media_galleries/pmp_test_util.h"
     13 #include "chrome/utility/media_galleries/pmp_column_reader.h"
     14 #include "testing/gtest/include/gtest/gtest.h"
     15 
     16 namespace picasa {
     17 
     18 namespace {
     19 
     20 bool InitColumnReaderFromBytes(
     21     PmpColumnReader* const reader,
     22     const std::vector<char>& data,
     23     const PmpFieldType expected_type) {
     24   base::ScopedTempDir temp_dir;
     25   if (!temp_dir.CreateUniqueTempDir())
     26     return false;
     27 
     28   base::FilePath temp_path;
     29   if (!base::CreateTemporaryFileInDir(temp_dir.path(), &temp_path))
     30     return false;
     31 
     32   // Explicit conversion from signed to unsigned.
     33   size_t bytes_written = base::WriteFile(temp_path, &data[0], data.size());
     34   if (bytes_written != data.size())
     35     return false;
     36 
     37   base::File file(temp_path, base::File::FLAG_OPEN | base::File::FLAG_READ);
     38   if (!file.IsValid())
     39     return false;
     40 
     41   return reader->ReadFile(&file, expected_type);
     42 }
     43 
     44 // Overridden version of Read method to make test code templatable.
     45 bool DoRead(const PmpColumnReader* reader, uint32 row, std::string* target) {
     46   return reader->ReadString(row, target);
     47 }
     48 
     49 bool DoRead(const PmpColumnReader* reader, uint32 row, uint32* target) {
     50   return reader->ReadUInt32(row, target);
     51 }
     52 
     53 bool DoRead(const PmpColumnReader* reader, uint32 row, double* target) {
     54   return reader->ReadDouble64(row, target);
     55 }
     56 
     57 bool DoRead(const PmpColumnReader* reader, uint32 row, uint8* target) {
     58   return reader->ReadUInt8(row, target);
     59 }
     60 
     61 bool DoRead(const PmpColumnReader* reader, uint32 row, uint64* target) {
     62   return reader->ReadUInt64(row, target);
     63 }
     64 
     65 // TestValid
     66 template<class T>
     67 void TestValid(const PmpFieldType field_type,
     68                const std::vector<T>& elems) {
     69   PmpColumnReader reader;
     70   std::vector<char> data =
     71       PmpTestUtil::MakeHeaderAndBody(field_type, elems.size(), elems);
     72   ASSERT_TRUE(InitColumnReaderFromBytes(&reader, data, field_type));
     73   EXPECT_EQ(elems.size(), reader.rows_read());
     74 
     75   for (uint32 i = 0; i < elems.size() && i < reader.rows_read(); i++) {
     76     T target;
     77     EXPECT_TRUE(DoRead(&reader, i, &target));
     78     EXPECT_EQ(elems[i], target);
     79   }
     80 }
     81 
     82 template<class T>
     83 void TestMalformed(const PmpFieldType field_type,
     84                    const std::vector<T>& elems) {
     85   PmpColumnReader reader_too_few_declared_rows;
     86   std::vector<char> data_too_few_declared_rows =
     87       PmpTestUtil::MakeHeaderAndBody(field_type, elems.size()-1, elems);
     88   EXPECT_FALSE(InitColumnReaderFromBytes(&reader_too_few_declared_rows,
     89                                          data_too_few_declared_rows,
     90                                          field_type));
     91 
     92   PmpColumnReader reader_too_many_declared_rows;
     93   std::vector<char> data_too_many_declared_rows =
     94       PmpTestUtil::MakeHeaderAndBody(field_type, elems.size()+1, elems);
     95   EXPECT_FALSE(InitColumnReaderFromBytes(&reader_too_many_declared_rows,
     96                                          data_too_many_declared_rows,
     97                                          field_type));
     98 
     99   PmpColumnReader reader_truncated;
    100   std::vector<char> data_truncated =
    101       PmpTestUtil::MakeHeaderAndBody(field_type, elems.size(), elems);
    102   data_truncated.resize(data_truncated.size()-10);
    103   EXPECT_FALSE(InitColumnReaderFromBytes(&reader_truncated,
    104                                          data_truncated,
    105                                          field_type));
    106 
    107   PmpColumnReader reader_padded;
    108   std::vector<char> data_padded =
    109       PmpTestUtil::MakeHeaderAndBody(field_type, elems.size(), elems);
    110   data_padded.resize(data_padded.size()+10);
    111   EXPECT_FALSE(InitColumnReaderFromBytes(&reader_padded,
    112                                          data_padded,
    113                                          field_type));
    114 }
    115 
    116 template<class T>
    117 void TestPrimitive(const PmpFieldType field_type) {
    118   // Make an ascending vector of the primitive.
    119   uint32 n = 100;
    120   std::vector<T> data(n, 0);
    121   for (uint32 i = 0; i < n; i++) {
    122     data[i] = i*3;
    123   }
    124 
    125   TestValid<T>(field_type, data);
    126   TestMalformed<T>(field_type, data);
    127 }
    128 
    129 
    130 TEST(PmpColumnReaderTest, HeaderParsingAndValidation) {
    131   PmpColumnReader reader_good_header;
    132   std::vector<char> good_header =
    133       PmpTestUtil::MakeHeader(PMP_TYPE_STRING, 0);
    134   EXPECT_TRUE(InitColumnReaderFromBytes(&reader_good_header,
    135                                         good_header,
    136                                         PMP_TYPE_STRING));
    137   EXPECT_EQ(0U, reader_good_header.rows_read()) <<
    138       "Read non-zero rows from header-only data.";
    139 
    140   PmpColumnReader reader_bad_magic_bytes;
    141   std::vector<char> bad_magic_bytes =
    142       PmpTestUtil::MakeHeader(PMP_TYPE_STRING, 0);
    143   bad_magic_bytes[0] = static_cast<char>(-128);
    144   EXPECT_FALSE(InitColumnReaderFromBytes(&reader_bad_magic_bytes,
    145                                          bad_magic_bytes,
    146                                          PMP_TYPE_STRING));
    147 
    148   PmpColumnReader reader_inconsistent_types;
    149   std::vector<char> inconsistent_type =
    150       PmpTestUtil::MakeHeader(PMP_TYPE_STRING, 0);
    151   inconsistent_type[kPmpFieldType1Offset] = static_cast<char>(-128);
    152   EXPECT_FALSE(InitColumnReaderFromBytes(&reader_inconsistent_types,
    153                                          inconsistent_type,
    154                                          PMP_TYPE_STRING));
    155 
    156   PmpColumnReader reader_invalid_type;
    157   std::vector<char> invalid_type =
    158       PmpTestUtil::MakeHeader(PMP_TYPE_STRING, 0);
    159   invalid_type[kPmpFieldType1Offset] = static_cast<char>(-128);
    160   invalid_type[kPmpFieldType2Offset] = static_cast<char>(-128);
    161   EXPECT_FALSE(InitColumnReaderFromBytes(&reader_invalid_type,
    162                                          invalid_type,
    163                                          PMP_TYPE_STRING));
    164 
    165   PmpColumnReader reader_incomplete_header;
    166   std::vector<char> incomplete_header =
    167       PmpTestUtil::MakeHeader(PMP_TYPE_STRING, 0);
    168   incomplete_header.resize(10);
    169   EXPECT_FALSE(InitColumnReaderFromBytes(&reader_incomplete_header,
    170                                          incomplete_header,
    171                                          PMP_TYPE_STRING));
    172 }
    173 
    174 TEST(PmpColumnReaderTest, StringParsing) {
    175   std::vector<std::string> empty_strings(100, "");
    176 
    177   // Test empty strings read okay.
    178   TestValid(PMP_TYPE_STRING, empty_strings);
    179 
    180   std::vector<std::string> mixed_strings;
    181   mixed_strings.push_back("");
    182   mixed_strings.push_back("Hello");
    183   mixed_strings.push_back("World");
    184   mixed_strings.push_back("");
    185   mixed_strings.push_back("123123");
    186   mixed_strings.push_back("Q");
    187   mixed_strings.push_back("");
    188 
    189   // Test that a mixed set of strings read correctly.
    190   TestValid(PMP_TYPE_STRING, mixed_strings);
    191 
    192   // Test with the data messed up in a variety of ways.
    193   TestMalformed(PMP_TYPE_STRING, mixed_strings);
    194 }
    195 
    196 TEST(PmpColumnReaderTest, PrimitiveParsing) {
    197   TestPrimitive<uint32>(PMP_TYPE_UINT32);
    198   TestPrimitive<double>(PMP_TYPE_DOUBLE64);
    199   TestPrimitive<uint8>(PMP_TYPE_UINT8);
    200   TestPrimitive<uint64>(PMP_TYPE_UINT64);
    201 }
    202 
    203 }  // namespace
    204 
    205 }  // namespace picasa
    206