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 file_util::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 = file_util::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