// Copyright (c) 2012 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 "content/test/image_decoder_test.h"

#include "base/file_util.h"
#include "base/files/file_enumerator.h"
#include "base/files/file_path.h"
#include "base/md5.h"
#include "base/memory/scoped_ptr.h"
#include "base/path_service.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "third_party/WebKit/public/platform/WebData.h"
#include "third_party/WebKit/public/platform/WebImage.h"
#include "third_party/WebKit/public/platform/WebSize.h"
#include "third_party/WebKit/public/web/WebImageDecoder.h"

// Uncomment this to recalculate the MD5 sums; see header comments.
// #define CALCULATE_MD5_SUMS

namespace {

const int kFirstFrameIndex = 0;

// Determine if we should test with file specified by |path| based
// on |file_selection| and the |threshold| for the file size.
bool ShouldSkipFile(const base::FilePath& path,
                    ImageDecoderTestFileSelection file_selection,
                    const int64 threshold) {
  if (file_selection == TEST_ALL)
    return false;

  int64 image_size = 0;
  base::GetFileSize(path, &image_size);
  return (file_selection == TEST_SMALLER) == (image_size > threshold);
}

}  // namespace

void ReadFileToVector(const base::FilePath& path, std::vector<char>* contents) {
  std::string raw_image_data;
  base::ReadFileToString(path, &raw_image_data);
  contents->resize(raw_image_data.size());
  memcpy(&contents->front(), raw_image_data.data(), raw_image_data.size());
}

base::FilePath GetMD5SumPath(const base::FilePath& path) {
  static const base::FilePath::StringType kDecodedDataExtension(
      FILE_PATH_LITERAL(".md5sum"));
  return base::FilePath(path.value() + kDecodedDataExtension);
}

#if defined(CALCULATE_MD5_SUMS)
void SaveMD5Sum(const base::FilePath& path, const blink::WebImage& web_image) {
  // Calculate MD5 sum.
  base::MD5Digest digest;
  web_image.getSkBitmap().lockPixels();
  base::MD5Sum(web_image.getSkBitmap().getPixels(),
               web_image.getSkBitmap().width() *
                   web_image.getSkBitmap().height() * sizeof(uint32_t),
               &digest);

  // Write sum to disk.
  int bytes_written = base::WriteFile(
      path, reinterpret_cast<const char*>(&digest), sizeof digest);
  ASSERT_EQ(sizeof digest, bytes_written);
  web_image.getSkBitmap().unlockPixels();
}
#endif

#if !defined(CALCULATE_MD5_SUMS)
void VerifyImage(const blink::WebImageDecoder& decoder,
                 const base::FilePath& path,
                 const base::FilePath& md5_sum_path,
                 size_t frame_index) {
  // Make sure decoding can complete successfully.
  EXPECT_TRUE(decoder.isSizeAvailable()) << path.value();
  EXPECT_GE(decoder.frameCount(), frame_index) << path.value();
  EXPECT_TRUE(decoder.isFrameCompleteAtIndex(frame_index)) << path.value();
  EXPECT_FALSE(decoder.isFailed());

  // Calculate MD5 sum.
  base::MD5Digest actual_digest;
  blink::WebImage web_image = decoder.getFrameAtIndex(frame_index);
  web_image.getSkBitmap().lockPixels();
  base::MD5Sum(web_image.getSkBitmap().getPixels(),
               web_image.getSkBitmap().width() *
                   web_image.getSkBitmap().height() * sizeof(uint32_t),
               &actual_digest);

  // Read the MD5 sum off disk.
  std::string file_bytes;
  base::ReadFileToString(md5_sum_path, &file_bytes);
  base::MD5Digest expected_digest;
  ASSERT_EQ(sizeof expected_digest, file_bytes.size()) << path.value();
  memcpy(&expected_digest, file_bytes.data(), sizeof expected_digest);

  // Verify that the sums are the same.
  EXPECT_EQ(0, memcmp(&expected_digest, &actual_digest, sizeof actual_digest))
      << path.value();
  web_image.getSkBitmap().unlockPixels();
}
#endif

void ImageDecoderTest::SetUp() {
  base::FilePath data_dir;
  ASSERT_TRUE(PathService::Get(base::DIR_SOURCE_ROOT, &data_dir));
  data_dir_ = data_dir.AppendASCII("webkit").AppendASCII("data").AppendASCII(
      format_ + "_decoder");
  if (!base::PathExists(data_dir_)) {
    const testing::TestInfo* const test_info =
        testing::UnitTest::GetInstance()->current_test_info();
    VLOG(0) << test_info->name()
            << " not running because test data wasn't found.";
    data_dir_.clear();
    return;
  }
}

std::vector<base::FilePath> ImageDecoderTest::GetImageFiles() const {
  std::string pattern = "*." + format_;
  base::FileEnumerator enumerator(data_dir_, false,
                                  base::FileEnumerator::FILES);
  std::vector<base::FilePath> image_files;
  for (base::FilePath next_file_name = enumerator.Next();
       !next_file_name.empty(); next_file_name = enumerator.Next()) {
    base::FilePath base_name = next_file_name.BaseName();
#if defined(OS_WIN)
    std::string base_name_ascii = base::UTF16ToASCII(base_name.value());
#else
    std::string base_name_ascii = base_name.value();
#endif
    if (MatchPattern(base_name_ascii, pattern))
      image_files.push_back(next_file_name);
  }

  return image_files;
}

bool ImageDecoderTest::ShouldImageFail(const base::FilePath& path) const {
  const base::FilePath::StringType kBadSuffix(FILE_PATH_LITERAL(".bad."));
  return (path.value().length() > (kBadSuffix.length() + format_.length()) &&
          !path.value().compare(path.value().length() - format_.length() -
                                    kBadSuffix.length(),
                                kBadSuffix.length(), kBadSuffix));
}

void ImageDecoderTest::TestDecoding(
    ImageDecoderTestFileSelection file_selection,
    const int64 threshold) {
  if (data_dir_.empty())
    return;
  const std::vector<base::FilePath> image_files(GetImageFiles());
  for (std::vector<base::FilePath>::const_iterator i = image_files.begin();
       i != image_files.end(); ++i) {
    if (!ShouldSkipFile(*i, file_selection, threshold))
      TestWebKitImageDecoder(*i, GetMD5SumPath(*i), kFirstFrameIndex);
  }
}

void ImageDecoderTest::TestWebKitImageDecoder(
    const base::FilePath& image_path,
    const base::FilePath& md5_sum_path,
    int desired_frame_index) const {
#if defined(CALCULATE_MD5_SUMS)
  // If we're just calculating the MD5 sums, skip failing images quickly.
  if (ShouldImageFail(image_path))
    return;
#endif

  std::vector<char> image_contents;
  ReadFileToVector(image_path, &image_contents);
  EXPECT_TRUE(image_contents.size());
  scoped_ptr<blink::WebImageDecoder> decoder(CreateWebKitImageDecoder());
  EXPECT_FALSE(decoder->isFailed());

#if !defined(CALCULATE_MD5_SUMS)
  // Test chunking file into half.
  const int partial_size = image_contents.size()/2;

  blink::WebData partial_data(
    reinterpret_cast<const char*>(&(image_contents.at(0))), partial_size);

  // Make Sure the image decoder doesn't fail when we ask for the frame
  // buffer for this partial image.
  // NOTE: We can't check that frame 0 is non-NULL, because if this is an
  // ICO and we haven't yet supplied enough data to read the directory,
  // there is no framecount and thus no first frame.
  decoder->setData(const_cast<blink::WebData&>(partial_data), false);
  EXPECT_FALSE(decoder->isFailed()) << image_path.value();
#endif

  // Make sure passing the complete image results in successful decoding.
  blink::WebData data(reinterpret_cast<const char*>(&(image_contents.at(0))),
    image_contents.size());
  decoder->setData(const_cast<blink::WebData&>(data), true);
  if (ShouldImageFail(image_path)) {
    EXPECT_FALSE(decoder->isFrameCompleteAtIndex(kFirstFrameIndex));
    EXPECT_TRUE(decoder->isFailed());
  } else {
    EXPECT_FALSE(decoder->isFailed()) << image_path.value();
#if defined(CALCULATE_MD5_SUMS)
    SaveMD5Sum(md5_sum_path, decoder->getFrameAtIndex(desired_frame_index));
#else
    VerifyImage(*decoder, image_path, md5_sum_path, desired_frame_index);
#endif
  }
}
