Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1318)

Side by Side Diff: webkit/fileapi/media/picasa/pmp_column_reader_unittest.cc

Issue 12704024: Simple PMP reader to parse Picasa's metadata (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fix rvalue usage in move operation. Created 7 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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/file_util.h"
9 #include "testing/gtest/include/gtest/gtest.h"
10 #include "webkit/fileapi/media/picasa/pmp_column_reader.h"
11 #include "webkit/fileapi/media/picasa/pmp_constants.h"
12
13 namespace {
14
15 using fileapi::PmpColumnReader;
16
17 // Return a vector so we don't have to worry about memory management.
18 std::vector<uint8> MakeHeader(const uint16 field_type, const uint32 row_count) {
vandebo (ex-Chrome) 2013/03/28 00:56:04 All these functions might be better organized in a
tommycli 2013/03/29 00:16:01 Moving these to PmpTestUtil so I can use in multip
19 std::vector<uint8> header(fileapi::kPmpHeaderSize);
20
21 // Copy in magic bytes.
22 memcpy(&header[fileapi::kPmpMagic1Offset], &fileapi::kPmpMagic1,
23 sizeof(fileapi::kPmpMagic1));
24 memcpy(&header[fileapi::kPmpMagic2Offset], &fileapi::kPmpMagic2,
25 sizeof(fileapi::kPmpMagic2));
26 memcpy(&header[fileapi::kPmpMagic3Offset], &fileapi::kPmpMagic3,
27 sizeof(fileapi::kPmpMagic3));
28 memcpy(&header[fileapi::kPmpMagic4Offset], &fileapi::kPmpMagic4,
29 sizeof(fileapi::kPmpMagic4));
30
31 // Copy in field type.
32 memcpy(&header[fileapi::kPmpFieldType1Offset], &field_type, 2);
33 memcpy(&header[fileapi::kPmpFieldType2Offset], &field_type, 2);
34
35 // Copy in row count.
36 memcpy(&header[fileapi::kPmpRowCountOffset], &row_count, 4);
37
38 return header;
39 }
40
41 // Flatten a vector of elements into an array of bytes.
42 template<class T>
43 std::vector<uint8> Flatten(const std::vector<T>& elems) {
44 const uint8* elems0 = reinterpret_cast<const uint8*>(&elems[0]);
45 std::vector<uint8> data_body(elems0, elems0 + sizeof(T)*elems.size());
46
47 return data_body;
48 }
49
50 // Custom specialization for strings.
51 // Given a vector of strings, returns a vector of all the characters in strings.
52 template<>
53 std::vector<uint8> Flatten(const std::vector<std::string>& strings) {
54 std::vector<uint8> totalchars;
55
56 for(std::vector<std::string>::const_iterator it = strings.begin();
57 it != strings.end(); it++) {
58 std::copy(it->begin(), it->end(), std::back_inserter(totalchars));
59 totalchars.push_back('\0'); // Add the null termination too.
60 }
61
62 return totalchars;
63 }
64
65 std::vector<uint8> Combined(const std::vector<uint8>& a,
vandebo (ex-Chrome) 2013/03/28 00:56:04 CombineVectors ?
tommycli 2013/03/29 00:16:01 Done.
66 const std::vector<uint8>& b) {
67 std::vector<uint8> total;
68
69 std::copy(a.begin(), a.end(), std::back_inserter(total));
70 std::copy(b.begin(), b.end(), std::back_inserter(total));
71
72 return total;
73 }
74
75 // Writes memory into a temporary file for use in test
76 bool ReaderReadFromMemory(PmpColumnReader* const reader, uint8* const data,
77 int length, uint32* rows_read) {
78 base::FilePath temppath;
79
80 // Cast for usage in WriteFile function
81 const char* data_char = reinterpret_cast<const char*>(data);
82
83 if(!file_util::CreateTemporaryFile(&temppath) ||
84 file_util::WriteFile(temppath, data_char, length) != length) {
85 return false;
86 }
87
88 return reader->ReadFromFile(temppath, rows_read);
89 }
90
91 // Overridden version of Read method to make test code templatable.
92 bool DoRead(const PmpColumnReader* reader, uint32 row, std::string* target) {
93 return reader->ReadString(row, target);
94 }
95
96 bool DoRead(const PmpColumnReader* reader, uint32 row, uint32* target) {
97 return reader->ReadUInt32(row, target);
98 }
99
100 bool DoRead(const PmpColumnReader* reader, uint32 row, double* target) {
101 return reader->ReadDouble64(row, target);
102 }
103
104 bool DoRead(const PmpColumnReader* reader, uint32 row, uint8* target) {
105 return reader->ReadUInt8(row, target);
106 }
107
108 bool DoRead(const PmpColumnReader* reader, uint32 row, uint64* target) {
109 return reader->ReadUInt64(row, target);
110 }
111
112 // TestValid
113 template<class T>
114 void TestValid(PmpColumnReader* reader, const uint16 field_type,
115 const std::vector<T>& elems) {
116 uint32 rows_read = 0xFF;
117
118 std::vector<uint8> data = Combined(MakeHeader(field_type, elems.size()),
119 Flatten(elems));
120 EXPECT_TRUE(ReaderReadFromMemory(reader, &data[0], data.size(), &rows_read));
121 EXPECT_EQ(rows_read, elems.size());
122
123 for(uint32 i = 0; i < elems.size(); i++) {
124 T target;
125 EXPECT_TRUE(DoRead(reader, i, &target));
126 EXPECT_EQ(target, elems[i]);
127 }
128 }
129
130 template<class T>
131 void TestMalformed(PmpColumnReader* reader, const uint16 field_type,
132 const std::vector<T>& elems) {
133
134 std::vector<uint8> data_too_few_declared_rows =
135 Combined(MakeHeader(field_type, elems.size()-1), Flatten(elems));
136 EXPECT_FALSE(ReaderReadFromMemory(reader, &data_too_few_declared_rows[0],
137 data_too_few_declared_rows.size(), NULL));
138
139 std::vector<uint8> data_too_many_declared_rows =
140 Combined(MakeHeader(field_type, elems.size()+1), Flatten(elems));
141 EXPECT_FALSE(ReaderReadFromMemory(reader, &data_too_many_declared_rows[0],
142 data_too_many_declared_rows.size(), NULL));
143
144 std::vector<uint8> data_truncated =
145 Combined(MakeHeader(field_type, elems.size()), Flatten(elems));
146 data_truncated.resize(data_truncated.size()-10);
147
148 EXPECT_FALSE(ReaderReadFromMemory(reader, &data_truncated[0],
149 data_truncated.size(), NULL));
150
151 std::vector<uint8> data_padded =
152 Combined(MakeHeader(field_type, elems.size()), Flatten(elems));
153 data_padded.resize(data_padded.size()+10);
154 EXPECT_FALSE(ReaderReadFromMemory(reader, &data_padded[0],
155 data_padded.size(), NULL));
156 }
157
158 template<class T>
159 void TestPrimitives(const uint16 field_type) {
160 PmpColumnReader reader("testcolumn");
161
162 // Make an ascending vector of the primitive.
163 uint32 n = 100;
164 std::vector<T> data(n, 0);
165 for(uint32 i = 0; i < n; i++) {
166 data[i] = i*3;
167 }
168
169 TestValid<T>(&reader, field_type, data);
170 TestMalformed<T>(&reader, field_type, data);
171 }
172
173
174 TEST(PmpColumnReaderTest, HeaderParsingAndValidation) {
175 PmpColumnReader reader("testcolumn");
176
177 // Good header.
178 uint32 rows_read = 0xFF;
179 std::vector<uint8> good_header = MakeHeader(0x00, 0);
180 EXPECT_TRUE(ReaderReadFromMemory(&reader, &good_header[0],
181 good_header.size(), &rows_read));
182 EXPECT_EQ(rows_read, 0U) << "Read non-zero rows from header-only data.";
183
184 // Botch up elements of the header.
185 std::vector<uint8> bad_magic_byte = MakeHeader(0x00, 0);
186 bad_magic_byte[0] = 0xff;
187 EXPECT_FALSE(ReaderReadFromMemory(&reader, &bad_magic_byte[0],
188 bad_magic_byte.size(), NULL));
189
190 // Corrupt means the type fields don't agree.
191 std::vector<uint8> corrupt_type = MakeHeader(0x00, 0);
192 corrupt_type[fileapi::kPmpFieldType1Offset] = 0xff;
193 EXPECT_FALSE(ReaderReadFromMemory(&reader, &corrupt_type[0],
194 corrupt_type.size(), NULL));
195
196 std::vector<uint8> invalid_type = MakeHeader(0x00, 0);
197 invalid_type[fileapi::kPmpFieldType1Offset] = 0xff;
198 invalid_type[fileapi::kPmpFieldType2Offset] = 0xff;
199 EXPECT_FALSE(ReaderReadFromMemory(&reader, &invalid_type[0],
200 invalid_type.size(), NULL));
201
202 std::vector<uint8> incomplete_header = MakeHeader(0x00, 0);
203 incomplete_header.resize(10);
204 EXPECT_FALSE(ReaderReadFromMemory(&reader, &incomplete_header[0],
205 incomplete_header.size(), NULL));
206 }
207
208 TEST(PmpColumnReaderTest, StringParsing) {
209 PmpColumnReader reader("testcolumn");
210
211 std::vector<std::string> empty_strings(100, "");
212
213 // Test empty strings read okay.
214 TestValid(&reader, fileapi::kPmpFieldTypeString, empty_strings);
215
216 std::vector<std::string> mixed_strings;
217 mixed_strings.push_back("");
218 mixed_strings.push_back("Hello");
219 mixed_strings.push_back("World");
220 mixed_strings.push_back("");
221 mixed_strings.push_back("123123");
222 mixed_strings.push_back("Q");
223 mixed_strings.push_back("");
224
225 // Test that a mixed set of strings read correctly.
226 TestValid(&reader, fileapi::kPmpFieldTypeString, mixed_strings);
227
228 // Test with the data messed up in a variety of ways.
229 TestMalformed(&reader, fileapi::kPmpFieldTypeString, mixed_strings);
230 }
231
232 TEST(PmpColumnReaderTest, PrimitiveParsing) {
233 TestPrimitives<uint32>(fileapi::kPmpFieldTypeUInt32);
234 TestPrimitives<double>(fileapi::kPmpFieldTypeDouble64);
235 TestPrimitives<uint8>(fileapi::kPmpFieldTypeUInt8);
236 TestPrimitives<uint64>(fileapi::kPmpFieldTypeUInt64);
237 }
238
239 } // namespace
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698