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.
8 #include "base/files/file.h"
9 #include "base/files/file_util.h"
10 #include "base/files/scoped_temp_dir.h"
11 #include "chrome/common/media_galleries/pmp_constants.h"
12 #include "chrome/common/media_galleries/pmp_test_util.h"
13 #include "chrome/utility/media_galleries/pmp_column_reader.h"
14 #include "testing/gtest/include/gtest/gtest.h"
20 bool InitColumnReaderFromBytes(
21 PmpColumnReader
* const reader
,
22 const std::vector
<char>& data
,
23 const PmpFieldType expected_type
) {
24 base::ScopedTempDir temp_dir
;
25 if (!temp_dir
.CreateUniqueTempDir())
28 base::FilePath temp_path
;
29 if (!base::CreateTemporaryFileInDir(temp_dir
.path(), &temp_path
))
32 // Explicit conversion from signed to unsigned.
33 size_t bytes_written
= base::WriteFile(temp_path
, &data
[0], data
.size());
34 if (bytes_written
!= data
.size())
37 base::File
file(temp_path
, base::File::FLAG_OPEN
| base::File::FLAG_READ
);
41 return reader
->ReadFile(&file
, expected_type
);
44 // Overridden version of Read method to make test code templatable.
45 bool DoRead(const PmpColumnReader
* reader
, uint32 row
, std::string
* target
) {
46 return reader
->ReadString(row
, target
);
49 bool DoRead(const PmpColumnReader
* reader
, uint32 row
, uint32
* target
) {
50 return reader
->ReadUInt32(row
, target
);
53 bool DoRead(const PmpColumnReader
* reader
, uint32 row
, double* target
) {
54 return reader
->ReadDouble64(row
, target
);
57 bool DoRead(const PmpColumnReader
* reader
, uint32 row
, uint8
* target
) {
58 return reader
->ReadUInt8(row
, target
);
61 bool DoRead(const PmpColumnReader
* reader
, uint32 row
, uint64
* target
) {
62 return reader
->ReadUInt64(row
, target
);
67 void TestValid(const PmpFieldType field_type
,
68 const std::vector
<T
>& elems
) {
69 PmpColumnReader reader
;
70 std::vector
<char> data
=
71 PmpTestUtil::MakeHeaderAndBody(field_type
, elems
.size(), elems
);
72 ASSERT_TRUE(InitColumnReaderFromBytes(&reader
, data
, field_type
));
73 EXPECT_EQ(elems
.size(), reader
.rows_read());
75 for (uint32 i
= 0; i
< elems
.size() && i
< reader
.rows_read(); i
++) {
77 EXPECT_TRUE(DoRead(&reader
, i
, &target
));
78 EXPECT_EQ(elems
[i
], target
);
83 void TestMalformed(const PmpFieldType field_type
,
84 const std::vector
<T
>& elems
) {
85 PmpColumnReader reader_too_few_declared_rows
;
86 std::vector
<char> data_too_few_declared_rows
=
87 PmpTestUtil::MakeHeaderAndBody(field_type
, elems
.size()-1, elems
);
88 EXPECT_FALSE(InitColumnReaderFromBytes(&reader_too_few_declared_rows
,
89 data_too_few_declared_rows
,
92 PmpColumnReader reader_too_many_declared_rows
;
93 std::vector
<char> data_too_many_declared_rows
=
94 PmpTestUtil::MakeHeaderAndBody(field_type
, elems
.size()+1, elems
);
95 EXPECT_FALSE(InitColumnReaderFromBytes(&reader_too_many_declared_rows
,
96 data_too_many_declared_rows
,
99 PmpColumnReader reader_truncated
;
100 std::vector
<char> data_truncated
=
101 PmpTestUtil::MakeHeaderAndBody(field_type
, elems
.size(), elems
);
102 data_truncated
.resize(data_truncated
.size()-10);
103 EXPECT_FALSE(InitColumnReaderFromBytes(&reader_truncated
,
107 PmpColumnReader reader_padded
;
108 std::vector
<char> data_padded
=
109 PmpTestUtil::MakeHeaderAndBody(field_type
, elems
.size(), elems
);
110 data_padded
.resize(data_padded
.size()+10);
111 EXPECT_FALSE(InitColumnReaderFromBytes(&reader_padded
,
117 void TestPrimitive(const PmpFieldType field_type
) {
118 // Make an ascending vector of the primitive.
120 std::vector
<T
> data(n
, 0);
121 for (uint32 i
= 0; i
< n
; i
++) {
125 TestValid
<T
>(field_type
, data
);
126 TestMalformed
<T
>(field_type
, data
);
130 TEST(PmpColumnReaderTest
, HeaderParsingAndValidation
) {
131 PmpColumnReader reader_good_header
;
132 std::vector
<char> good_header
=
133 PmpTestUtil::MakeHeader(PMP_TYPE_STRING
, 0);
134 EXPECT_TRUE(InitColumnReaderFromBytes(&reader_good_header
,
137 EXPECT_EQ(0U, reader_good_header
.rows_read()) <<
138 "Read non-zero rows from header-only data.";
140 PmpColumnReader reader_bad_magic_bytes
;
141 std::vector
<char> bad_magic_bytes
=
142 PmpTestUtil::MakeHeader(PMP_TYPE_STRING
, 0);
143 bad_magic_bytes
[0] = static_cast<char>(-128);
144 EXPECT_FALSE(InitColumnReaderFromBytes(&reader_bad_magic_bytes
,
148 PmpColumnReader reader_inconsistent_types
;
149 std::vector
<char> inconsistent_type
=
150 PmpTestUtil::MakeHeader(PMP_TYPE_STRING
, 0);
151 inconsistent_type
[kPmpFieldType1Offset
] = static_cast<char>(-128);
152 EXPECT_FALSE(InitColumnReaderFromBytes(&reader_inconsistent_types
,
156 PmpColumnReader reader_invalid_type
;
157 std::vector
<char> invalid_type
=
158 PmpTestUtil::MakeHeader(PMP_TYPE_STRING
, 0);
159 invalid_type
[kPmpFieldType1Offset
] = static_cast<char>(-128);
160 invalid_type
[kPmpFieldType2Offset
] = static_cast<char>(-128);
161 EXPECT_FALSE(InitColumnReaderFromBytes(&reader_invalid_type
,
165 PmpColumnReader reader_incomplete_header
;
166 std::vector
<char> incomplete_header
=
167 PmpTestUtil::MakeHeader(PMP_TYPE_STRING
, 0);
168 incomplete_header
.resize(10);
169 EXPECT_FALSE(InitColumnReaderFromBytes(&reader_incomplete_header
,
174 TEST(PmpColumnReaderTest
, StringParsing
) {
175 std::vector
<std::string
> empty_strings(100, "");
177 // Test empty strings read okay.
178 TestValid(PMP_TYPE_STRING
, empty_strings
);
180 std::vector
<std::string
> mixed_strings
;
181 mixed_strings
.push_back("");
182 mixed_strings
.push_back("Hello");
183 mixed_strings
.push_back("World");
184 mixed_strings
.push_back("");
185 mixed_strings
.push_back("123123");
186 mixed_strings
.push_back("Q");
187 mixed_strings
.push_back("");
189 // Test that a mixed set of strings read correctly.
190 TestValid(PMP_TYPE_STRING
, mixed_strings
);
192 // Test with the data messed up in a variety of ways.
193 TestMalformed(PMP_TYPE_STRING
, mixed_strings
);
196 TEST(PmpColumnReaderTest
, PrimitiveParsing
) {
197 TestPrimitive
<uint32
>(PMP_TYPE_UINT32
);
198 TestPrimitive
<double>(PMP_TYPE_DOUBLE64
);
199 TestPrimitive
<uint8
>(PMP_TYPE_UINT8
);
200 TestPrimitive
<uint64
>(PMP_TYPE_UINT64
);
205 } // namespace picasa