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 "chrome/common/media_galleries/pmp_test_util.h"
      6 
      7 #include <algorithm>
      8 #include <iterator>
      9 
     10 #include "base/file_util.h"
     11 #include "base/logging.h"
     12 #include "base/strings/utf_string_conversions.h"
     13 #include "chrome/common/media_galleries/picasa_types.h"
     14 #include "testing/gtest/include/gtest/gtest.h"
     15 
     16 namespace picasa {
     17 
     18 namespace {
     19 
     20 // Flatten a vector of elements into an array of bytes.
     21 template<class T>
     22 std::vector<char> Flatten(const std::vector<T>& elems) {
     23   if (elems.empty())
     24     return std::vector<char>();
     25 
     26   const uint8* elems0 = reinterpret_cast<const uint8*>(&elems[0]);
     27   std::vector<char> data_body(elems0, elems0 + sizeof(T) * elems.size());
     28   return data_body;
     29 }
     30 
     31 // Custom specialization for std::string.
     32 template<>
     33 std::vector<char> Flatten(const std::vector<std::string>& strings) {
     34   std::vector<char> totalchars;
     35 
     36   for (std::vector<std::string>::const_iterator it = strings.begin();
     37       it != strings.end(); ++it) {
     38     std::copy(it->begin(), it->end(), std::back_inserter(totalchars));
     39     totalchars.push_back('\0');  // Add the null termination too.
     40   }
     41 
     42   return totalchars;
     43 }
     44 
     45 // Returns a new vector with the concatenated contents of |a| and |b|.
     46 std::vector<char> CombinedVectors(const std::vector<char>& a,
     47                                   const std::vector<char>& b) {
     48   std::vector<char> total;
     49 
     50   std::copy(a.begin(), a.end(), std::back_inserter(total));
     51   std::copy(b.begin(), b.end(), std::back_inserter(total));
     52 
     53   return total;
     54 }
     55 
     56 }  // namespace
     57 
     58 bool PmpTestUtil::WriteIndicatorFile(
     59     const base::FilePath& column_file_destination,
     60     const std::string& table_name) {
     61   base::FilePath indicator_path = column_file_destination.Append(
     62       base::FilePath::FromUTF8Unsafe(table_name + "_0"));
     63 
     64   return base::WriteFile(indicator_path, NULL, 0) == 0;
     65 }
     66 
     67 template<class T>
     68 bool PmpTestUtil::WriteColumnFileFromVector(
     69     const base::FilePath& column_file_destination,
     70     const std::string& table_name,
     71     const std::string& column_name,
     72     const PmpFieldType field_type,
     73     const std::vector<T>& elements_vector) {
     74   std::string file_name = table_name + "_" + column_name + "." + kPmpExtension;
     75 
     76   base::FilePath path = column_file_destination.AppendASCII(file_name);
     77 
     78   std::vector<char> data = PmpTestUtil::MakeHeaderAndBody(
     79       field_type, elements_vector.size(), elements_vector);
     80 
     81   size_t bytes_written = base::WriteFile(path, &data[0], data.size());
     82   return (bytes_written == data.size());
     83 }
     84 
     85 // Explicit Instantiation for all the valid types.
     86 template bool PmpTestUtil::WriteColumnFileFromVector<std::string>(
     87     const base::FilePath&, const std::string&, const std::string&,
     88     const PmpFieldType, const std::vector<std::string>&);
     89 template bool PmpTestUtil::WriteColumnFileFromVector<uint32>(
     90     const base::FilePath&, const std::string&, const std::string&,
     91     const PmpFieldType, const std::vector<uint32>&);
     92 template bool PmpTestUtil::WriteColumnFileFromVector<double>(
     93     const base::FilePath&, const std::string&, const std::string&,
     94     const PmpFieldType, const std::vector<double>&);
     95 template bool PmpTestUtil::WriteColumnFileFromVector<uint8>(
     96     const base::FilePath&, const std::string&, const std::string&,
     97     const PmpFieldType, const std::vector<uint8>&);
     98 template bool PmpTestUtil::WriteColumnFileFromVector<uint64>(
     99     const base::FilePath&, const std::string&, const std::string&,
    100     const PmpFieldType, const std::vector<uint64>&);
    101 
    102 // Return a vector so we don't have to worry about memory management.
    103 std::vector<char> PmpTestUtil::MakeHeader(const PmpFieldType field_type,
    104                                             const uint32 row_count) {
    105   std::vector<char> header(picasa::kPmpHeaderSize);
    106 
    107   // Copy in magic bytes.
    108   memcpy(&header[picasa::kPmpMagic1Offset], &picasa::kPmpMagic1,
    109          sizeof(picasa::kPmpMagic1));
    110   memcpy(&header[picasa::kPmpMagic2Offset], &picasa::kPmpMagic2,
    111          sizeof(picasa::kPmpMagic2));
    112   memcpy(&header[picasa::kPmpMagic3Offset], &picasa::kPmpMagic3,
    113          sizeof(picasa::kPmpMagic3));
    114   memcpy(&header[picasa::kPmpMagic4Offset], &picasa::kPmpMagic4,
    115          sizeof(picasa::kPmpMagic4));
    116 
    117   // Copy in field type.
    118   uint16 field_type_short = static_cast<uint16>(field_type);
    119   memcpy(&header[picasa::kPmpFieldType1Offset], &field_type_short,
    120          sizeof(uint16));
    121   memcpy(&header[picasa::kPmpFieldType2Offset], &field_type_short,
    122          sizeof(uint16));
    123 
    124   // Copy in row count.
    125   memcpy(&header[picasa::kPmpRowCountOffset], &row_count, sizeof(uint32));
    126 
    127   return header;
    128 }
    129 
    130 template<class T>
    131 std::vector<char> PmpTestUtil::MakeHeaderAndBody(
    132     const PmpFieldType field_type, const uint32 row_count,
    133     const std::vector<T>& elems) {
    134   return CombinedVectors(PmpTestUtil::MakeHeader(field_type, row_count),
    135                          Flatten(elems));
    136 }
    137 
    138 // Explicit Instantiation for all the valid types.
    139 template std::vector<char> PmpTestUtil::MakeHeaderAndBody<std::string>(
    140     const PmpFieldType, const uint32, const std::vector<std::string>&);
    141 template std::vector<char> PmpTestUtil::MakeHeaderAndBody<uint32>(
    142     const PmpFieldType, const uint32, const std::vector<uint32>&);
    143 template std::vector<char> PmpTestUtil::MakeHeaderAndBody<double>(
    144     const PmpFieldType, const uint32, const std::vector<double>&);
    145 template std::vector<char> PmpTestUtil::MakeHeaderAndBody<uint8>(
    146     const PmpFieldType, const uint32, const std::vector<uint8>&);
    147 template std::vector<char> PmpTestUtil::MakeHeaderAndBody<uint64>(
    148     const PmpFieldType, const uint32, const std::vector<uint64>&);
    149 
    150 }  // namespace picasa
    151