// 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 <stddef.h>

#include <memory>

#include "base/files/file_enumerator.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/md5.h"
#include "base/path_service.h"
#include "base/strings/pattern.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "build/build_config.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_t threshold) {
  if (file_selection == TEST_ALL)
    return false;

  int64_t 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 (base::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_t 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());
  std::unique_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
  }
}
