root/chrome/utility/media_galleries/pmp_column_reader_unittest.cc

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. InitColumnReaderFromBytes
  2. DoRead
  3. DoRead
  4. DoRead
  5. DoRead
  6. DoRead
  7. TestValid
  8. TestMalformed
  9. TestPrimitive
  10. TEST
  11. TEST
  12. TEST

// 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 "base/files/file.h"
#include "base/files/scoped_temp_dir.h"
#include "chrome/common/media_galleries/pmp_constants.h"
#include "chrome/common/media_galleries/pmp_test_util.h"
#include "chrome/utility/media_galleries/pmp_column_reader.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace picasa {

namespace {

bool InitColumnReaderFromBytes(
    PmpColumnReader* const reader,
    const std::vector<char>& data,
    const PmpFieldType expected_type) {
  base::ScopedTempDir temp_dir;
  if (!temp_dir.CreateUniqueTempDir())
    return false;

  base::FilePath temp_path;
  if (!base::CreateTemporaryFileInDir(temp_dir.path(), &temp_path))
    return false;

  // Explicit conversion from signed to unsigned.
  size_t bytes_written = base::WriteFile(temp_path, &data[0], data.size());
  if (bytes_written != data.size())
    return false;

  base::File file(temp_path, base::File::FLAG_OPEN | base::File::FLAG_READ);
  if (!file.IsValid())
    return false;

  return reader->ReadFile(&file, expected_type);
}

// 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(const PmpFieldType field_type,
               const std::vector<T>& elems) {
  PmpColumnReader reader;
  std::vector<char> data =
      PmpTestUtil::MakeHeaderAndBody(field_type, elems.size(), elems);
  ASSERT_TRUE(InitColumnReaderFromBytes(&reader, data, field_type));
  EXPECT_EQ(elems.size(), reader.rows_read());

  for (uint32 i = 0; i < elems.size() && i < reader.rows_read(); i++) {
    T target;
    EXPECT_TRUE(DoRead(&reader, i, &target));
    EXPECT_EQ(elems[i], target);
  }
}

template<class T>
void TestMalformed(const PmpFieldType field_type,
                   const std::vector<T>& elems) {
  PmpColumnReader reader_too_few_declared_rows;
  std::vector<char> data_too_few_declared_rows =
      PmpTestUtil::MakeHeaderAndBody(field_type, elems.size()-1, elems);
  EXPECT_FALSE(InitColumnReaderFromBytes(&reader_too_few_declared_rows,
                                         data_too_few_declared_rows,
                                         field_type));

  PmpColumnReader reader_too_many_declared_rows;
  std::vector<char> data_too_many_declared_rows =
      PmpTestUtil::MakeHeaderAndBody(field_type, elems.size()+1, elems);
  EXPECT_FALSE(InitColumnReaderFromBytes(&reader_too_many_declared_rows,
                                         data_too_many_declared_rows,
                                         field_type));

  PmpColumnReader reader_truncated;
  std::vector<char> data_truncated =
      PmpTestUtil::MakeHeaderAndBody(field_type, elems.size(), elems);
  data_truncated.resize(data_truncated.size()-10);
  EXPECT_FALSE(InitColumnReaderFromBytes(&reader_truncated,
                                         data_truncated,
                                         field_type));

  PmpColumnReader reader_padded;
  std::vector<char> data_padded =
      PmpTestUtil::MakeHeaderAndBody(field_type, elems.size(), elems);
  data_padded.resize(data_padded.size()+10);
  EXPECT_FALSE(InitColumnReaderFromBytes(&reader_padded,
                                         data_padded,
                                         field_type));
}

template<class T>
void TestPrimitive(const PmpFieldType field_type) {
  // 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>(field_type, data);
  TestMalformed<T>(field_type, data);
}


TEST(PmpColumnReaderTest, HeaderParsingAndValidation) {
  PmpColumnReader reader_good_header;
  std::vector<char> good_header =
      PmpTestUtil::MakeHeader(PMP_TYPE_STRING, 0);
  EXPECT_TRUE(InitColumnReaderFromBytes(&reader_good_header,
                                        good_header,
                                        PMP_TYPE_STRING));
  EXPECT_EQ(0U, reader_good_header.rows_read()) <<
      "Read non-zero rows from header-only data.";

  PmpColumnReader reader_bad_magic_bytes;
  std::vector<char> bad_magic_bytes =
      PmpTestUtil::MakeHeader(PMP_TYPE_STRING, 0);
  bad_magic_bytes[0] = (char)0xff;
  EXPECT_FALSE(InitColumnReaderFromBytes(&reader_bad_magic_bytes,
                                         bad_magic_bytes,
                                         PMP_TYPE_STRING));

  PmpColumnReader reader_inconsistent_types;
  std::vector<char> inconsistent_type =
      PmpTestUtil::MakeHeader(PMP_TYPE_STRING, 0);
  inconsistent_type[kPmpFieldType1Offset] = (char)0xff;
  EXPECT_FALSE(InitColumnReaderFromBytes(&reader_inconsistent_types,
                                         inconsistent_type,
                                         PMP_TYPE_STRING));

  PmpColumnReader reader_invalid_type;
  std::vector<char> invalid_type =
      PmpTestUtil::MakeHeader(PMP_TYPE_STRING, 0);
  invalid_type[kPmpFieldType1Offset] = (char)0xff;
  invalid_type[kPmpFieldType2Offset] = (char)0xff;
  EXPECT_FALSE(InitColumnReaderFromBytes(&reader_invalid_type,
                                         invalid_type,
                                         PMP_TYPE_STRING));

  PmpColumnReader reader_incomplete_header;
  std::vector<char> incomplete_header =
      PmpTestUtil::MakeHeader(PMP_TYPE_STRING, 0);
  incomplete_header.resize(10);
  EXPECT_FALSE(InitColumnReaderFromBytes(&reader_incomplete_header,
                                         incomplete_header,
                                         PMP_TYPE_STRING));
}

TEST(PmpColumnReaderTest, StringParsing) {
  std::vector<std::string> empty_strings(100, "");

  // Test empty strings read okay.
  TestValid(PMP_TYPE_STRING, 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(PMP_TYPE_STRING, mixed_strings);

  // Test with the data messed up in a variety of ways.
  TestMalformed(PMP_TYPE_STRING, mixed_strings);
}

TEST(PmpColumnReaderTest, PrimitiveParsing) {
  TestPrimitive<uint32>(PMP_TYPE_UINT32);
  TestPrimitive<double>(PMP_TYPE_DOUBLE64);
  TestPrimitive<uint8>(PMP_TYPE_UINT8);
  TestPrimitive<uint64>(PMP_TYPE_UINT64);
}

}  // namespace

}  // namespace picasa

/* [<][>][^][v][top][bottom][index][help] */