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 16namespace picasa { 17 18namespace { 19 20// Flatten a vector of elements into an array of bytes. 21template<class T> 22std::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. 32template<> 33std::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|. 46std::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 58bool 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 67template<class T> 68bool 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. 86template bool PmpTestUtil::WriteColumnFileFromVector<std::string>( 87 const base::FilePath&, const std::string&, const std::string&, 88 const PmpFieldType, const std::vector<std::string>&); 89template bool PmpTestUtil::WriteColumnFileFromVector<uint32>( 90 const base::FilePath&, const std::string&, const std::string&, 91 const PmpFieldType, const std::vector<uint32>&); 92template bool PmpTestUtil::WriteColumnFileFromVector<double>( 93 const base::FilePath&, const std::string&, const std::string&, 94 const PmpFieldType, const std::vector<double>&); 95template bool PmpTestUtil::WriteColumnFileFromVector<uint8>( 96 const base::FilePath&, const std::string&, const std::string&, 97 const PmpFieldType, const std::vector<uint8>&); 98template 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. 103std::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 130template<class T> 131std::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. 139template std::vector<char> PmpTestUtil::MakeHeaderAndBody<std::string>( 140 const PmpFieldType, const uint32, const std::vector<std::string>&); 141template std::vector<char> PmpTestUtil::MakeHeaderAndBody<uint32>( 142 const PmpFieldType, const uint32, const std::vector<uint32>&); 143template std::vector<char> PmpTestUtil::MakeHeaderAndBody<double>( 144 const PmpFieldType, const uint32, const std::vector<double>&); 145template std::vector<char> PmpTestUtil::MakeHeaderAndBody<uint8>( 146 const PmpFieldType, const uint32, const std::vector<uint8>&); 147template std::vector<char> PmpTestUtil::MakeHeaderAndBody<uint64>( 148 const PmpFieldType, const uint32, const std::vector<uint64>&); 149 150} // namespace picasa 151