/*
 * Copyright (C) 2012 Google Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1.  Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 * 2.  Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "third_party/blink/renderer/platform/graphics/image_frame_generator.h"

#include <memory>
#include "base/location.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/renderer/platform/cross_thread_functional.h"
#include "third_party/blink/renderer/platform/graphics/image_decoding_store.h"
#include "third_party/blink/renderer/platform/graphics/test/mock_image_decoder.h"
#include "third_party/blink/renderer/platform/image-decoders/segment_reader.h"
#include "third_party/blink/renderer/platform/scheduler/public/thread.h"
#include "third_party/blink/renderer/platform/shared_buffer.h"
#include "third_party/blink/renderer/platform/testing/testing_platform_support.h"
#include "third_party/blink/renderer/platform/web_task_runner.h"

namespace blink {

namespace {

// Helper methods to generate standard sizes.
SkISize FullSize() {
  return SkISize::Make(100, 100);
}

SkImageInfo ImageInfo() {
  return SkImageInfo::Make(100, 100, kBGRA_8888_SkColorType,
                           kOpaque_SkAlphaType);
}

}  // namespace

class ImageFrameGeneratorTest : public testing::Test,
                                public MockImageDecoderClient {
 public:
  void SetUp() override {
    ImageDecodingStore::Instance().SetCacheLimitInBytes(1024 * 1024);
    generator_ = ImageFrameGenerator::Create(FullSize(), false,
                                             ColorBehavior::Ignore(), {});
    data_ = SharedBuffer::Create();
    segment_reader_ = SegmentReader::CreateFromSharedBuffer(data_);
    UseMockImageDecoderFactory();
    decoders_destroyed_ = 0;
    decode_request_count_ = 0;
    memory_allocator_set_count_ = 0;
    status_ = ImageFrame::kFrameEmpty;
    frame_count_ = 1;
    requested_clear_except_frame_ = kNotFound;
  }

  void TearDown() override { ImageDecodingStore::Instance().Clear(); }

  void DecoderBeingDestroyed() override { ++decoders_destroyed_; }

  void DecodeRequested() override { ++decode_request_count_; }

  void MemoryAllocatorSet() override { ++memory_allocator_set_count_; }

  ImageFrame::Status GetStatus(size_t index) override {
    ImageFrame::Status current_status = status_;
    status_ = next_frame_status_;
    return current_status;
  }

  void ClearCacheExceptFrameRequested(size_t clear_except_frame) override {
    requested_clear_except_frame_ = clear_except_frame;
  };

  size_t FrameCount() override { return frame_count_; }
  int RepetitionCount() const override {
    return frame_count_ == 1 ? kAnimationNone : kAnimationLoopOnce;
  }
  TimeDelta FrameDuration() const override { return TimeDelta(); }

 protected:
  void UseMockImageDecoderFactory() {
    generator_->SetImageDecoderFactory(
        MockImageDecoderFactory::Create(this, FullSize()));
  }

  void AddNewData() { data_->Append("g", 1u); }

  void SetFrameStatus(ImageFrame::Status status) {
    status_ = next_frame_status_ = status;
  }
  void SetNextFrameStatus(ImageFrame::Status status) {
    next_frame_status_ = status;
  }
  void SetFrameCount(size_t count) {
    frame_count_ = count;
    if (count > 1) {
      generator_ = nullptr;
      generator_ = ImageFrameGenerator::Create(FullSize(), true,
                                               ColorBehavior::Ignore(), {});
      UseMockImageDecoderFactory();
    }
  }
  void SetSupportedSizes(std::vector<SkISize> sizes) {
    generator_ = nullptr;
    generator_ = ImageFrameGenerator::Create(
        FullSize(), true, ColorBehavior::Ignore(), std::move(sizes));
    UseMockImageDecoderFactory();
  }

  scoped_refptr<SharedBuffer> data_;
  scoped_refptr<SegmentReader> segment_reader_;
  scoped_refptr<ImageFrameGenerator> generator_;
  int decoders_destroyed_;
  int decode_request_count_;
  int memory_allocator_set_count_;
  ImageFrame::Status status_;
  ImageFrame::Status next_frame_status_;
  size_t frame_count_;
  size_t requested_clear_except_frame_;
};

TEST_F(ImageFrameGeneratorTest, GetSupportedSizes) {
  ASSERT_TRUE(FullSize() == SkISize::Make(100, 100));

  std::vector<SkISize> supported_sizes = {SkISize::Make(2, 2),
                                          SkISize::Make(50, 50),
                                          SkISize::Make(75, 75), FullSize()};
  SetSupportedSizes(supported_sizes);

  struct Test {
    SkISize query_size;
    size_t supported_size_index;
  } tests[] = {{SkISize::Make(1, 1), 0},     {SkISize::Make(2, 2), 0},
               {SkISize::Make(25, 10), 1},   {SkISize::Make(1, 25), 1},
               {SkISize::Make(50, 51), 2},   {SkISize::Make(80, 80), 3},
               {SkISize::Make(100, 100), 3}, {SkISize::Make(1000, 1000), 3}};
  for (auto& test : tests) {
    EXPECT_TRUE(generator_->GetSupportedDecodeSize(test.query_size) ==
                supported_sizes[test.supported_size_index]);
  }
}

TEST_F(ImageFrameGeneratorTest, incompleteDecode) {
  SetFrameStatus(ImageFrame::kFramePartial);

  char buffer[100 * 100 * 4];
  generator_->DecodeAndScale(segment_reader_.get(), false, 0, ImageInfo(),
                             buffer, 100 * 4, ImageDecoder::kAlphaPremultiplied,
                             cc::PaintImage::kDefaultGeneratorClientId);
  EXPECT_EQ(1, decode_request_count_);
  EXPECT_EQ(0, memory_allocator_set_count_);

  AddNewData();
  generator_->DecodeAndScale(segment_reader_.get(), false, 0, ImageInfo(),
                             buffer, 100 * 4, ImageDecoder::kAlphaPremultiplied,
                             cc::PaintImage::kDefaultGeneratorClientId);
  EXPECT_EQ(2, decode_request_count_);
  EXPECT_EQ(0, decoders_destroyed_);
  EXPECT_EQ(0, memory_allocator_set_count_);
}

class ImageFrameGeneratorTestPlatform : public TestingPlatformSupport {
 public:
  bool IsLowEndDevice() override { return true; }
};

// This is the same as incompleteData, but with a low-end device set.
TEST_F(ImageFrameGeneratorTest, LowEndDeviceDestroysDecoderOnPartialDecode) {
  ScopedTestingPlatformSupport<ImageFrameGeneratorTestPlatform> platform;

  SetFrameStatus(ImageFrame::kFramePartial);

  char buffer[100 * 100 * 4];
  generator_->DecodeAndScale(segment_reader_.get(), false, 0, ImageInfo(),
                             buffer, 100 * 4, ImageDecoder::kAlphaPremultiplied,
                             cc::PaintImage::kDefaultGeneratorClientId);
  EXPECT_EQ(1, decode_request_count_);
  EXPECT_EQ(1, decoders_destroyed_);
  // The memory allocator is set to the external one, then cleared after decode.
  EXPECT_EQ(2, memory_allocator_set_count_);

  AddNewData();
  generator_->DecodeAndScale(segment_reader_.get(), false, 0, ImageInfo(),
                             buffer, 100 * 4, ImageDecoder::kAlphaPremultiplied,
                             cc::PaintImage::kDefaultGeneratorClientId);
  EXPECT_EQ(2, decode_request_count_);
  EXPECT_EQ(2, decoders_destroyed_);
  // The memory allocator is set to the external one, then cleared after decode.
  EXPECT_EQ(4, memory_allocator_set_count_);
}

TEST_F(ImageFrameGeneratorTest, incompleteDecodeBecomesComplete) {
  SetFrameStatus(ImageFrame::kFramePartial);

  char buffer[100 * 100 * 4];
  generator_->DecodeAndScale(segment_reader_.get(), false, 0, ImageInfo(),
                             buffer, 100 * 4, ImageDecoder::kAlphaPremultiplied,
                             cc::PaintImage::kDefaultGeneratorClientId);
  EXPECT_EQ(1, decode_request_count_);
  EXPECT_EQ(0, decoders_destroyed_);
  EXPECT_EQ(0, memory_allocator_set_count_);

  SetFrameStatus(ImageFrame::kFrameComplete);
  AddNewData();

  generator_->DecodeAndScale(segment_reader_.get(), false, 0, ImageInfo(),
                             buffer, 100 * 4, ImageDecoder::kAlphaPremultiplied,
                             cc::PaintImage::kDefaultGeneratorClientId);
  EXPECT_EQ(2, decode_request_count_);
  EXPECT_EQ(1, decoders_destroyed_);

  // Decoder created again.
  generator_->DecodeAndScale(segment_reader_.get(), false, 0, ImageInfo(),
                             buffer, 100 * 4, ImageDecoder::kAlphaPremultiplied,
                             cc::PaintImage::kDefaultGeneratorClientId);
  EXPECT_EQ(3, decode_request_count_);
}

static void DecodeThreadMain(ImageFrameGenerator* generator,
                             SegmentReader* segment_reader) {
  char buffer[100 * 100 * 4];
  generator->DecodeAndScale(segment_reader, false, 0, ImageInfo(), buffer,
                            100 * 4, ImageDecoder::kAlphaPremultiplied,
                            cc::PaintImage::kDefaultGeneratorClientId);
}

TEST_F(ImageFrameGeneratorTest, incompleteDecodeBecomesCompleteMultiThreaded) {
  SetFrameStatus(ImageFrame::kFramePartial);

  char buffer[100 * 100 * 4];
  generator_->DecodeAndScale(segment_reader_.get(), false, 0, ImageInfo(),
                             buffer, 100 * 4, ImageDecoder::kAlphaPremultiplied,
                             cc::PaintImage::kDefaultGeneratorClientId);
  EXPECT_EQ(1, decode_request_count_);
  EXPECT_EQ(0, decoders_destroyed_);

  // LocalFrame can now be decoded completely.
  SetFrameStatus(ImageFrame::kFrameComplete);
  AddNewData();
  std::unique_ptr<WebThread> thread = Platform::Current()->CreateThread(
      WebThreadCreationParams(WebThreadType::kTestThread)
          .SetThreadNameForTest("DecodeThread"));
  PostCrossThreadTask(
      *thread->GetTaskRunner(), FROM_HERE,
      CrossThreadBind(&DecodeThreadMain, WTF::RetainedRef(generator_),
                      WTF::RetainedRef(segment_reader_)));
  thread.reset();
  EXPECT_EQ(2, decode_request_count_);
  EXPECT_EQ(1, decoders_destroyed_);

  // Decoder created again.
  generator_->DecodeAndScale(segment_reader_.get(), false, 0, ImageInfo(),
                             buffer, 100 * 4, ImageDecoder::kAlphaPremultiplied,
                             cc::PaintImage::kDefaultGeneratorClientId);
  EXPECT_EQ(3, decode_request_count_);

  AddNewData();

  // Delete generator.
  generator_ = nullptr;
}

TEST_F(ImageFrameGeneratorTest, frameHasAlpha) {
  SetFrameStatus(ImageFrame::kFramePartial);

  char buffer[100 * 100 * 4];
  generator_->DecodeAndScale(segment_reader_.get(), false, 0, ImageInfo(),
                             buffer, 100 * 4, ImageDecoder::kAlphaPremultiplied,
                             cc::PaintImage::kDefaultGeneratorClientId);
  EXPECT_TRUE(generator_->HasAlpha(0));
  EXPECT_EQ(1, decode_request_count_);

  ImageDecoder* temp_decoder = nullptr;
  EXPECT_TRUE(ImageDecodingStore::Instance().LockDecoder(
      generator_.get(), FullSize(), ImageDecoder::kAlphaPremultiplied,
      cc::PaintImage::kDefaultGeneratorClientId, &temp_decoder));
  ASSERT_TRUE(temp_decoder);
  temp_decoder->DecodeFrameBufferAtIndex(0)->SetHasAlpha(false);
  ImageDecodingStore::Instance().UnlockDecoder(
      generator_.get(), cc::PaintImage::kDefaultGeneratorClientId,
      temp_decoder);
  EXPECT_EQ(2, decode_request_count_);

  SetFrameStatus(ImageFrame::kFrameComplete);
  generator_->DecodeAndScale(segment_reader_.get(), false, 0, ImageInfo(),
                             buffer, 100 * 4, ImageDecoder::kAlphaPremultiplied,
                             cc::PaintImage::kDefaultGeneratorClientId);
  EXPECT_EQ(3, decode_request_count_);
  EXPECT_FALSE(generator_->HasAlpha(0));
}

TEST_F(ImageFrameGeneratorTest, clearMultiFrameDecoder) {
  SetFrameCount(3);
  SetFrameStatus(ImageFrame::kFrameComplete);

  char buffer[100 * 100 * 4];
  generator_->DecodeAndScale(segment_reader_.get(), true, 0, ImageInfo(),
                             buffer, 100 * 4, ImageDecoder::kAlphaPremultiplied,
                             cc::PaintImage::kDefaultGeneratorClientId);
  EXPECT_EQ(1, decode_request_count_);
  EXPECT_EQ(0, decoders_destroyed_);
  EXPECT_EQ(0U, requested_clear_except_frame_);

  SetFrameStatus(ImageFrame::kFrameComplete);

  generator_->DecodeAndScale(segment_reader_.get(), true, 1, ImageInfo(),
                             buffer, 100 * 4, ImageDecoder::kAlphaPremultiplied,
                             cc::PaintImage::kDefaultGeneratorClientId);
  EXPECT_EQ(2, decode_request_count_);
  EXPECT_EQ(0, decoders_destroyed_);
  EXPECT_EQ(1U, requested_clear_except_frame_);

  SetFrameStatus(ImageFrame::kFrameComplete);

  // Decoding the last frame of a multi-frame images should trigger clearing
  // all the frame data, but not destroying the decoder.  See comments in
  // ImageFrameGenerator::tryToResumeDecode().
  generator_->DecodeAndScale(segment_reader_.get(), true, 2, ImageInfo(),
                             buffer, 100 * 4, ImageDecoder::kAlphaPremultiplied,
                             cc::PaintImage::kDefaultGeneratorClientId);
  EXPECT_EQ(3, decode_request_count_);
  EXPECT_EQ(0, decoders_destroyed_);
  EXPECT_EQ(kNotFound, requested_clear_except_frame_);
}

}  // namespace blink
