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

Unified 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 side-by-side diff with in-line comments
Download patch
Index: webkit/fileapi/media/picasa/pmp_column_reader_unittest.cc
diff --git a/webkit/fileapi/media/picasa/pmp_column_reader_unittest.cc b/webkit/fileapi/media/picasa/pmp_column_reader_unittest.cc
new file mode 100644
index 0000000000000000000000000000000000000000..7300f77c6f668dbe41a62b88b7ff203b006eb238
--- /dev/null
+++ b/webkit/fileapi/media/picasa/pmp_column_reader_unittest.cc
@@ -0,0 +1,239 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <algorithm>
+#include <vector>
+
+#include "base/file_util.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "webkit/fileapi/media/picasa/pmp_column_reader.h"
+#include "webkit/fileapi/media/picasa/pmp_constants.h"
+
+namespace {
+
+using fileapi::PmpColumnReader;
+
+// Return a vector so we don't have to worry about memory management.
+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
+ std::vector<uint8> header(fileapi::kPmpHeaderSize);
+
+ // Copy in magic bytes.
+ memcpy(&header[fileapi::kPmpMagic1Offset], &fileapi::kPmpMagic1,
+ sizeof(fileapi::kPmpMagic1));
+ memcpy(&header[fileapi::kPmpMagic2Offset], &fileapi::kPmpMagic2,
+ sizeof(fileapi::kPmpMagic2));
+ memcpy(&header[fileapi::kPmpMagic3Offset], &fileapi::kPmpMagic3,
+ sizeof(fileapi::kPmpMagic3));
+ memcpy(&header[fileapi::kPmpMagic4Offset], &fileapi::kPmpMagic4,
+ sizeof(fileapi::kPmpMagic4));
+
+ // Copy in field type.
+ memcpy(&header[fileapi::kPmpFieldType1Offset], &field_type, 2);
+ memcpy(&header[fileapi::kPmpFieldType2Offset], &field_type, 2);
+
+ // Copy in row count.
+ memcpy(&header[fileapi::kPmpRowCountOffset], &row_count, 4);
+
+ return header;
+}
+
+// Flatten a vector of elements into an array of bytes.
+template<class T>
+std::vector<uint8> Flatten(const std::vector<T>& elems) {
+ const uint8* elems0 = reinterpret_cast<const uint8*>(&elems[0]);
+ std::vector<uint8> data_body(elems0, elems0 + sizeof(T)*elems.size());
+
+ return data_body;
+}
+
+// Custom specialization for strings.
+// Given a vector of strings, returns a vector of all the characters in strings.
+template<>
+std::vector<uint8> Flatten(const std::vector<std::string>& strings) {
+ std::vector<uint8> totalchars;
+
+ for(std::vector<std::string>::const_iterator it = strings.begin();
+ it != strings.end(); it++) {
+ std::copy(it->begin(), it->end(), std::back_inserter(totalchars));
+ totalchars.push_back('\0'); // Add the null termination too.
+ }
+
+ return totalchars;
+}
+
+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.
+ const std::vector<uint8>& b) {
+ std::vector<uint8> total;
+
+ std::copy(a.begin(), a.end(), std::back_inserter(total));
+ std::copy(b.begin(), b.end(), std::back_inserter(total));
+
+ return total;
+}
+
+// Writes memory into a temporary file for use in test
+bool ReaderReadFromMemory(PmpColumnReader* const reader, uint8* const data,
+ int length, uint32* rows_read) {
+ base::FilePath temppath;
+
+ // Cast for usage in WriteFile function
+ const char* data_char = reinterpret_cast<const char*>(data);
+
+ if(!file_util::CreateTemporaryFile(&temppath) ||
+ file_util::WriteFile(temppath, data_char, length) != length) {
+ return false;
+ }
+
+ return reader->ReadFromFile(temppath, rows_read);
+}
+
+// Overridden version of Read method to make test code templatable.
+bool DoRead(const PmpColumnReader* reader, uint32 row, std::string* target) {
+ return reader->ReadString(row, target);
+}
+
+bool DoRead(const PmpColumnReader* reader, uint32 row, uint32* target) {
+ return reader->ReadUInt32(row, target);
+}
+
+bool DoRead(const PmpColumnReader* reader, uint32 row, double* target) {
+ return reader->ReadDouble64(row, target);
+}
+
+bool DoRead(const PmpColumnReader* reader, uint32 row, uint8* target) {
+ return reader->ReadUInt8(row, target);
+}
+
+bool DoRead(const PmpColumnReader* reader, uint32 row, uint64* target) {
+ return reader->ReadUInt64(row, target);
+}
+
+// TestValid
+template<class T>
+void TestValid(PmpColumnReader* reader, const uint16 field_type,
+ const std::vector<T>& elems) {
+ uint32 rows_read = 0xFF;
+
+ std::vector<uint8> data = Combined(MakeHeader(field_type, elems.size()),
+ Flatten(elems));
+ EXPECT_TRUE(ReaderReadFromMemory(reader, &data[0], data.size(), &rows_read));
+ EXPECT_EQ(rows_read, elems.size());
+
+ for(uint32 i = 0; i < elems.size(); i++) {
+ T target;
+ EXPECT_TRUE(DoRead(reader, i, &target));
+ EXPECT_EQ(target, elems[i]);
+ }
+}
+
+template<class T>
+void TestMalformed(PmpColumnReader* reader, const uint16 field_type,
+ const std::vector<T>& elems) {
+
+ std::vector<uint8> data_too_few_declared_rows =
+ Combined(MakeHeader(field_type, elems.size()-1), Flatten(elems));
+ EXPECT_FALSE(ReaderReadFromMemory(reader, &data_too_few_declared_rows[0],
+ data_too_few_declared_rows.size(), NULL));
+
+ std::vector<uint8> data_too_many_declared_rows =
+ Combined(MakeHeader(field_type, elems.size()+1), Flatten(elems));
+ EXPECT_FALSE(ReaderReadFromMemory(reader, &data_too_many_declared_rows[0],
+ data_too_many_declared_rows.size(), NULL));
+
+ std::vector<uint8> data_truncated =
+ Combined(MakeHeader(field_type, elems.size()), Flatten(elems));
+ data_truncated.resize(data_truncated.size()-10);
+
+ EXPECT_FALSE(ReaderReadFromMemory(reader, &data_truncated[0],
+ data_truncated.size(), NULL));
+
+ std::vector<uint8> data_padded =
+ Combined(MakeHeader(field_type, elems.size()), Flatten(elems));
+ data_padded.resize(data_padded.size()+10);
+ EXPECT_FALSE(ReaderReadFromMemory(reader, &data_padded[0],
+ data_padded.size(), NULL));
+}
+
+template<class T>
+void TestPrimitives(const uint16 field_type) {
+ PmpColumnReader reader("testcolumn");
+
+ // Make an ascending vector of the primitive.
+ uint32 n = 100;
+ std::vector<T> data(n, 0);
+ for(uint32 i = 0; i < n; i++) {
+ data[i] = i*3;
+ }
+
+ TestValid<T>(&reader, field_type, data);
+ TestMalformed<T>(&reader, field_type, data);
+}
+
+
+TEST(PmpColumnReaderTest, HeaderParsingAndValidation) {
+ PmpColumnReader reader("testcolumn");
+
+ // Good header.
+ uint32 rows_read = 0xFF;
+ std::vector<uint8> good_header = MakeHeader(0x00, 0);
+ EXPECT_TRUE(ReaderReadFromMemory(&reader, &good_header[0],
+ good_header.size(), &rows_read));
+ EXPECT_EQ(rows_read, 0U) << "Read non-zero rows from header-only data.";
+
+ // Botch up elements of the header.
+ std::vector<uint8> bad_magic_byte = MakeHeader(0x00, 0);
+ bad_magic_byte[0] = 0xff;
+ EXPECT_FALSE(ReaderReadFromMemory(&reader, &bad_magic_byte[0],
+ bad_magic_byte.size(), NULL));
+
+ // Corrupt means the type fields don't agree.
+ std::vector<uint8> corrupt_type = MakeHeader(0x00, 0);
+ corrupt_type[fileapi::kPmpFieldType1Offset] = 0xff;
+ EXPECT_FALSE(ReaderReadFromMemory(&reader, &corrupt_type[0],
+ corrupt_type.size(), NULL));
+
+ std::vector<uint8> invalid_type = MakeHeader(0x00, 0);
+ invalid_type[fileapi::kPmpFieldType1Offset] = 0xff;
+ invalid_type[fileapi::kPmpFieldType2Offset] = 0xff;
+ EXPECT_FALSE(ReaderReadFromMemory(&reader, &invalid_type[0],
+ invalid_type.size(), NULL));
+
+ std::vector<uint8> incomplete_header = MakeHeader(0x00, 0);
+ incomplete_header.resize(10);
+ EXPECT_FALSE(ReaderReadFromMemory(&reader, &incomplete_header[0],
+ incomplete_header.size(), NULL));
+}
+
+TEST(PmpColumnReaderTest, StringParsing) {
+ PmpColumnReader reader("testcolumn");
+
+ std::vector<std::string> empty_strings(100, "");
+
+ // Test empty strings read okay.
+ TestValid(&reader, fileapi::kPmpFieldTypeString, empty_strings);
+
+ std::vector<std::string> mixed_strings;
+ mixed_strings.push_back("");
+ mixed_strings.push_back("Hello");
+ mixed_strings.push_back("World");
+ mixed_strings.push_back("");
+ mixed_strings.push_back("123123");
+ mixed_strings.push_back("Q");
+ mixed_strings.push_back("");
+
+ // Test that a mixed set of strings read correctly.
+ TestValid(&reader, fileapi::kPmpFieldTypeString, mixed_strings);
+
+ // Test with the data messed up in a variety of ways.
+ TestMalformed(&reader, fileapi::kPmpFieldTypeString, mixed_strings);
+}
+
+TEST(PmpColumnReaderTest, PrimitiveParsing) {
+ TestPrimitives<uint32>(fileapi::kPmpFieldTypeUInt32);
+ TestPrimitives<double>(fileapi::kPmpFieldTypeDouble64);
+ TestPrimitives<uint8>(fileapi::kPmpFieldTypeUInt8);
+ TestPrimitives<uint64>(fileapi::kPmpFieldTypeUInt64);
+}
+
+} // namespace

Powered by Google App Engine
This is Rietveld 408576698