// Copyright 2014 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 "chrome/browser/extensions/api/image_writer_private/write_from_url_operation.h"

#include "base/task_scheduler/post_task.h"
#include "chrome/browser/extensions/api/image_writer_private/error_messages.h"
#include "chrome/browser/extensions/api/image_writer_private/test_utils.h"
#include "chrome/test/base/testing_profile.h"
#include "content/public/browser/browser_thread.h"
#include "net/url_request/test_url_request_interceptor.h"

namespace extensions {
namespace image_writer {

namespace {

using content::BrowserThread;
using testing::_;
using testing::AnyNumber;
using testing::AtLeast;
using testing::Gt;
using testing::Lt;

const char kTestImageUrl[] = "http://localhost/test/image.zip";

typedef net::LocalHostTestURLRequestInterceptor GetInterceptor;

}  // namespace

// This class gives us a generic Operation with the ability to set or inspect
// the current path to the image file.
class WriteFromUrlOperationForTest : public WriteFromUrlOperation {
 public:
  WriteFromUrlOperationForTest(base::WeakPtr<OperationManager> manager,
                               const ExtensionId& extension_id,
                               net::URLRequestContextGetter* request_context,
                               GURL url,
                               const std::string& hash,
                               const std::string& storage_unit_id)
      : WriteFromUrlOperation(manager,
                              extension_id,
                              request_context,
                              url,
                              hash,
                              storage_unit_id,
                              base::FilePath(FILE_PATH_LITERAL("/var/tmp"))) {}

  void StartImpl() override {}

  // Following methods let us:
  // 1. Expose stages for testing.
  // 2. Make sure Operation methods are invoked on its task runner.
  void Start() {
    PostTask(base::BindOnce(&WriteFromUrlOperation::Start, this));
  }
  void GetDownloadTarget(const base::Closure& continuation) {
    PostTask(base::BindOnce(&WriteFromUrlOperation::GetDownloadTarget, this,
                            continuation));
  }

  void Download(const base::Closure& continuation) {
    PostTask(
        base::BindOnce(&WriteFromUrlOperation::Download, this, continuation));
  }

  void VerifyDownload(const base::Closure& continuation) {
    PostTask(base::BindOnce(&WriteFromUrlOperation::VerifyDownload, this,
                            continuation));
  }

  void Cancel() {
    PostTask(base::BindOnce(&WriteFromUrlOperation::Cancel, this));
  }

  // Helpers to set-up state for intermediate stages.
  void SetImagePath(const base::FilePath image_path) {
    image_path_ = image_path;
  }

  base::FilePath GetImagePath() { return image_path_; }

 private:
  ~WriteFromUrlOperationForTest() override {}
};

class ImageWriterWriteFromUrlOperationTest : public ImageWriterUnitTestBase {
 protected:
  ImageWriterWriteFromUrlOperationTest() : manager_(&test_profile_) {}

  void SetUp() override {
    ImageWriterUnitTestBase::SetUp();

    // Turn on interception and set up our dummy file.
    get_interceptor_.reset(new GetInterceptor(
        BrowserThread::GetTaskRunnerForThread(BrowserThread::IO),
        base::CreateTaskRunnerWithTraits(
            {base::MayBlock(), base::TaskPriority::BACKGROUND,
             base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN})));
    get_interceptor_->SetResponse(GURL(kTestImageUrl),
                                  test_utils_.GetImagePath());
  }

  void TearDown() override {
    ImageWriterUnitTestBase::TearDown();
  }

  scoped_refptr<WriteFromUrlOperationForTest> CreateOperation(
      const GURL& url,
      const std::string& hash) {
    scoped_refptr<WriteFromUrlOperationForTest> operation(
        new WriteFromUrlOperationForTest(
            manager_.AsWeakPtr(), kDummyExtensionId,
            test_profile_.GetRequestContext(), url, hash,
            test_utils_.GetDevicePath().AsUTF8Unsafe()));
    operation->Start();
    return operation;
  }

  TestingProfile test_profile_;
  std::unique_ptr<GetInterceptor> get_interceptor_;

  MockOperationManager manager_;
};

TEST_F(ImageWriterWriteFromUrlOperationTest, SelectTargetWithoutExtension) {
  scoped_refptr<WriteFromUrlOperationForTest> operation =
      CreateOperation(GURL("http://localhost/foo/bar"), "");

  base::RunLoop run_loop;
  operation->GetDownloadTarget(run_loop.QuitClosure());
  run_loop.Run();

  EXPECT_EQ(FILE_PATH_LITERAL("bar"),
            operation->GetImagePath().BaseName().value());

  operation->Cancel();
  content::RunAllBlockingPoolTasksUntilIdle();
}

TEST_F(ImageWriterWriteFromUrlOperationTest, SelectTargetWithExtension) {
  scoped_refptr<WriteFromUrlOperationForTest> operation =
      CreateOperation(GURL("http://localhost/foo/bar.zip"), "");

  base::RunLoop run_loop;
  operation->GetDownloadTarget(run_loop.QuitClosure());
  run_loop.Run();

  EXPECT_EQ(FILE_PATH_LITERAL("bar.zip"),
            operation->GetImagePath().BaseName().value());

  operation->Cancel();
}

TEST_F(ImageWriterWriteFromUrlOperationTest, DownloadFile) {
  // This test actually triggers the URL fetch code, which will drain the
  // message queues while waiting for IO, thus we have to run until the
  // operation completes.
  base::RunLoop runloop;
  base::FilePath download_target_path;
  scoped_refptr<WriteFromUrlOperationForTest> operation =
      CreateOperation(GURL(kTestImageUrl), "");

  EXPECT_TRUE(base::CreateTemporaryFileInDir(test_utils_.GetTempDir(),
                                             &download_target_path));
  operation->SetImagePath(download_target_path);

  EXPECT_CALL(
      manager_,
      OnProgress(kDummyExtensionId, image_writer_api::STAGE_DOWNLOAD, _))
      .Times(AtLeast(1));
  EXPECT_CALL(
      manager_,
      OnProgress(kDummyExtensionId, image_writer_api::STAGE_DOWNLOAD, 0))
      .Times(AnyNumber());
  EXPECT_CALL(
      manager_,
      OnProgress(kDummyExtensionId, image_writer_api::STAGE_DOWNLOAD, 100))
      .Times(AnyNumber());

  operation->Download(runloop.QuitClosure());
  runloop.Run();
  content::RunAllBlockingPoolTasksUntilIdle();

  EXPECT_TRUE(base::ContentsEqual(test_utils_.GetImagePath(),
                                  operation->GetImagePath()));

  EXPECT_EQ(1, get_interceptor_->GetHitCount());

  operation->Cancel();
}

TEST_F(ImageWriterWriteFromUrlOperationTest, VerifyFile) {
  std::unique_ptr<char[]> data_buffer(new char[kTestFileSize]);
  base::ReadFile(test_utils_.GetImagePath(), data_buffer.get(), kTestFileSize);
  base::MD5Digest expected_digest;
  base::MD5Sum(data_buffer.get(), kTestFileSize, &expected_digest);
  std::string expected_hash = base::MD5DigestToBase16(expected_digest);

  scoped_refptr<WriteFromUrlOperationForTest> operation =
      CreateOperation(GURL(""), expected_hash);

  EXPECT_CALL(
      manager_,
      OnProgress(kDummyExtensionId, image_writer_api::STAGE_VERIFYDOWNLOAD, _))
      .Times(AtLeast(1));
  EXPECT_CALL(
      manager_,
      OnProgress(kDummyExtensionId, image_writer_api::STAGE_VERIFYDOWNLOAD, 0))
      .Times(AtLeast(1));
  EXPECT_CALL(manager_,
              OnProgress(kDummyExtensionId,
                         image_writer_api::STAGE_VERIFYDOWNLOAD,
                         100)).Times(AtLeast(1));

  operation->SetImagePath(test_utils_.GetImagePath());
  {
    base::RunLoop run_loop;
    operation->VerifyDownload(run_loop.QuitClosure());
    run_loop.Run();
  }

  operation->Cancel();
}

}  // namespace image_writer
}  // namespace extensions
