// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/ash/scanning/scan_service.h"

#include <cstdint>
#include <map>
#include <memory>
#include <optional>
#include <string>
#include <vector>

#include "ash/webui/scanning/mojom/scanning.mojom.h"
#include "ash/webui/scanning/scanning_uma.h"
#include "base/containers/flat_set.h"
#include "base/containers/span.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/i18n/time_formatting.h"
#include "base/memory/raw_ptr.h"
#include "base/strings/string_view_util.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/task_environment.h"
#include "base/test/test_future.h"
#include "base/time/time.h"
#include "base/unguessable_token.h"
#include "chrome/browser/ash/login/users/fake_chrome_user_manager.h"
#include "chrome/browser/ash/profiles/profile_helper.h"
#include "chrome/browser/ash/scanning/fake_lorgnette_scanner_manager.h"
#include "chrome/browser/ui/ash/holding_space/holding_space_keyed_service.h"
#include "chrome/browser/ui/ash/holding_space/holding_space_keyed_service_factory.h"
#include "chrome/browser/ui/ash/holding_space/scoped_test_mount_point.h"
#include "chrome/browser/ui/ash/session/test_session_controller.h"
#include "chrome/test/base/testing_browser_process.h"
#include "chrome/test/base/testing_profile.h"
#include "chrome/test/base/testing_profile_manager.h"
#include "chromeos/ash/components/browser_context_helper/annotated_account_id.h"
#include "chromeos/ash/components/dbus/lorgnette/lorgnette_service.pb.h"
#include "components/account_id/account_id.h"
#include "components/user_manager/scoped_user_manager.h"
#include "content/public/test/browser_task_environment.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/receiver.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/gfx/codec/jpeg_codec.h"

namespace ash {

using holding_space::ScopedTestMountPoint;

namespace {

namespace mojo_ipc = scanning::mojom;

using ProtoScanFailureMode = lorgnette::ScanFailureMode;

// Path to the user's "My files" folder.
constexpr char kMyFilesPath[] = "/home/chronos/user/MyFiles";

// Scanner names used for tests.
constexpr char kFirstTestScannerName[] = "Test Scanner 1";
constexpr char16_t kFirstTestScannerName16[] = u"Test Scanner 1";
constexpr char kSecondTestScannerName[] = "Test Scanner 2";
constexpr char16_t kSecondTestScannerName16[] = u"Test Scanner 2";
constexpr char kEpsonTestName[] =
    "airscan:escl:EPSON XP-7100 Series:http://100.107.108.190:443/eSCL/";

// Document source name used for tests.
constexpr char kDocumentSourceName[] = "Flatbed";
constexpr char kAdfSourceName[] = "ADF Duplex";

// Resolutions used for tests.
constexpr uint32_t kFirstResolution = 75;
constexpr uint32_t kSecondResolution = 300;

// Email used for test profile.
constexpr char kUserEmail[] = "user@email.com";

// Translation from file type to saved file extension.
const std::map<mojo_ipc::FileType, std::string> kFileTypes = {
    {mojo_ipc::FileType::kJpg, "jpg"},
    {mojo_ipc::FileType::kPdf, "pdf"},
    {mojo_ipc::FileType::kPng, "png"}};

// Returns a DocumentSource object.
lorgnette::DocumentSource CreateLorgnetteDocumentSource() {
  lorgnette::DocumentSource source;
  source.set_type(lorgnette::SOURCE_PLATEN);
  source.set_name(kDocumentSourceName);
  source.add_color_modes(lorgnette::MODE_COLOR);
  source.add_resolutions(kFirstResolution);
  source.add_resolutions(kSecondResolution);
  return source;
}

// Returns an ADF Duplex DocumentSource object.
lorgnette::DocumentSource CreateAdfDuplexDocumentSource() {
  lorgnette::DocumentSource source;
  source.set_type(lorgnette::SOURCE_ADF_DUPLEX);
  source.set_name(kAdfSourceName);
  return source;
}

// Returns a ScannerCapabilities object.
lorgnette::ScannerCapabilities CreateLorgnetteScannerCapabilities() {
  lorgnette::ScannerCapabilities caps;
  *caps.add_sources() = CreateLorgnetteDocumentSource();
  return caps;
}

// Returns a ScannerCapabilities object used for testing a scanner
// that flips alternate pages..
lorgnette::ScannerCapabilities CreateEpsonScannerCapabilities() {
  lorgnette::ScannerCapabilities caps;
  *caps.add_sources() = CreateAdfDuplexDocumentSource();
  caps.add_color_modes(lorgnette::MODE_COLOR);
  caps.add_resolutions(kFirstResolution);
  caps.add_resolutions(kSecondResolution);
  return caps;
}

std::string GetTimestamp(const base::Time& scan_time) {
  return base::UnlocalizedTimeFormatWithPattern(scan_time, "yyMMdd-HHmmss");
}

// Returns single FilePath to mimic saved PDF format scan.
base::FilePath CreateSavedPdfScanPath(const base::FilePath& dir,
                                      const base::Time& scan_time) {
  return dir.Append(
      base::StringPrintf("scan_%s.pdf", GetTimestamp(scan_time).c_str()));
}

// Returns a vector of FilePaths to mimic saved scans.
std::vector<base::FilePath> CreateSavedScanPaths(
    const base::FilePath& dir,
    const base::Time& scan_time,
    const mojo_ipc::FileType& file_type,
    int num_pages_to_scan) {
  const auto typeAndExtension = kFileTypes.find(file_type);
  EXPECT_NE(typeAndExtension, kFileTypes.cend());
  std::vector<base::FilePath> file_paths;
  if (file_type == mojo_ipc::FileType::kPdf) {
    file_paths.reserve(1);
    file_paths.push_back(CreateSavedPdfScanPath(dir, scan_time));
  } else {
    file_paths.reserve(num_pages_to_scan);
    for (int i = 1; i <= num_pages_to_scan; i++) {
      file_paths.push_back(dir.Append(
          base::StringPrintf("scan_%s_%d.%s", GetTimestamp(scan_time).c_str(),
                             i, typeAndExtension->second.c_str())));
    }
  }
  return file_paths;
}

// Returns a manually generated JPEG image. |alpha| is used to make them unique.
std::string CreateJpeg(const int alpha = 255) {
  SkBitmap bitmap;
  bitmap.allocN32Pixels(100, 100);
  bitmap.eraseARGB(alpha, 0, 0, 255);
  std::optional<std::vector<uint8_t>> bytes =
      gfx::JPEGCodec::Encode(bitmap, 90);
  CHECK(bytes);
  return std::string(base::as_string_view(bytes.value()));
}

// Returns scan settings with the given path and file type.
mojo_ipc::ScanSettings CreateScanSettings(
    const base::FilePath& scan_to_path,
    const mojo_ipc::FileType& file_type,
    const std::string& source = "",
    mojo_ipc::ColorMode color_mode = mojo_ipc::ColorMode::kColor,
    mojo_ipc::PageSize page_size = mojo_ipc::PageSize::kIsoA3,
    uint32_t resolution = kFirstResolution) {
  mojo_ipc::ScanSettings settings;
  settings.scan_to_path = scan_to_path;
  settings.file_type = file_type;
  settings.source_name = source;
  settings.page_size = page_size;
  settings.color_mode = color_mode;
  settings.resolution_dpi = resolution;
  return settings;
}

// Returns a profile manager set up to generate testing profiles.
std::unique_ptr<TestingProfileManager> CreateTestingProfileManager() {
  auto profile_manager = std::make_unique<TestingProfileManager>(
      TestingBrowserProcess::GetGlobal());
  EXPECT_TRUE(profile_manager->SetUp());
  return profile_manager;
}

}  // namespace

class FakeScanJobObserver : public mojo_ipc::ScanJobObserver {
 public:
  FakeScanJobObserver() = default;
  ~FakeScanJobObserver() override = default;

  FakeScanJobObserver(const FakeScanJobObserver&) = delete;
  FakeScanJobObserver& operator=(const FakeScanJobObserver&) = delete;

  // mojo_ipc::ScanJobObserver:
  void OnPageProgress(uint32_t page_number,
                      uint32_t progress_percent) override {
    progress_ = progress_percent;
  }

  void OnPageComplete(const std::vector<uint8_t>& page_data,
                      const uint32_t new_page_index) override {
    page_complete_ = true;
    new_page_index_ = new_page_index;
  }

  void OnScanComplete(
      ProtoScanFailureMode result,
      const std::vector<base::FilePath>& scanned_file_paths) override {
    scan_result_ = result;
    scanned_file_paths_ = scanned_file_paths;
  }

  void OnCancelComplete(bool success) override {
    cancel_scan_success_ = success;
  }

  void OnMultiPageScanFail(ProtoScanFailureMode result) override {
    multi_page_scan_result_ = result;
  }

  // Creates a pending remote that can be passed in calls to
  // ScanService::StartScan().
  mojo::PendingRemote<mojo_ipc::ScanJobObserver> GenerateRemote() {
    if (receiver_.is_bound())
      receiver_.reset();

    mojo::PendingRemote<mojo_ipc::ScanJobObserver> remote;
    receiver_.Bind(remote.InitWithNewPipeAndPassReceiver());
    return remote;
  }

  // Returns true if the scan completed successfully.
  bool scan_success() const {
    return progress_ == 100 && page_complete_ &&
           scan_result_ == ProtoScanFailureMode::SCAN_FAILURE_MODE_NO_FAILURE;
  }

  // Returns true if the cancel scan request completed successfully.
  bool cancel_scan_success() const { return cancel_scan_success_; }

  uint32_t new_page_index() const { return new_page_index_; }

  // Returns the result of the scan job.
  ProtoScanFailureMode scan_result() const { return scan_result_; }

  // Returns the result of the multi-page scan job.
  ProtoScanFailureMode multi_page_scan_result() const {
    return multi_page_scan_result_;
  }

  // Returns file paths of the saved scan files.
  std::vector<base::FilePath> scanned_file_paths() const {
    return scanned_file_paths_;
  }

 private:
  uint32_t progress_ = 0;
  bool page_complete_ = false;
  uint32_t new_page_index_ = UINT32_MAX;
  ProtoScanFailureMode scan_result_ =
      ProtoScanFailureMode::SCAN_FAILURE_MODE_UNKNOWN;
  ProtoScanFailureMode multi_page_scan_result_ =
      ProtoScanFailureMode::SCAN_FAILURE_MODE_UNKNOWN;
  bool cancel_scan_success_ = false;
  std::vector<base::FilePath> scanned_file_paths_;
  mojo::Receiver<mojo_ipc::ScanJobObserver> receiver_{this};
};

class ScanServiceTest : public testing::Test {
 public:
  ScanServiceTest()
      : profile_manager_(CreateTestingProfileManager()),
        session_controller_(std::make_unique<TestSessionController>()),
        user_manager_(new ash::FakeChromeUserManager),
        user_manager_owner_(base::WrapUnique(user_manager_.get())) {
    const AccountId account_id(AccountId::FromUserEmail(kUserEmail));
    user_manager_->AddUser(account_id);
    user_manager_->LoginUser(account_id, /*set_profile_created_flag=*/false);

    profile_ = profile_manager_->CreateTestingProfile(kUserEmail);
    AnnotatedAccountId::Set(profile_, account_id);
    user_manager_->OnUserProfileCreated(account_id, profile_->GetPrefs());

    scanned_files_mount_ =
        ScopedTestMountPoint::CreateAndMountDownloads(profile_);
    DCHECK(scanned_files_mount_->IsValid());

    SetupScanService(scanned_files_mount_->GetRootPath(),
                     base::FilePath("/google/drive"));
  }

  void SetupScanService(base::FilePath my_files_path,
                        base::FilePath google_drive_path) {
    scan_service_ = std::make_unique<ScanService>(
        &fake_lorgnette_scanner_manager_, my_files_path, google_drive_path,
        profile_);
    if (scan_service_remote_.is_bound()) {
      scan_service_remote_.reset();
    }
    scan_service_->BindInterface(
        scan_service_remote_.BindNewPipeAndPassReceiver());
  }

  // Gets scanners by calling ScanService::GetScanners() via the mojo::Remote.
  std::vector<mojo_ipc::ScannerPtr> GetScanners() {
    base::test::TestFuture<std::vector<mojo_ipc::ScannerPtr>> future;
    scan_service_remote_->GetScanners(future.GetCallback());
    return future.Take();
  }

  // Gets scanner capabilities for the scanner identified by |scanner_id| by
  // calling ScanService::GetScannerCapabilities() via the mojo::Remote.
  mojo_ipc::ScannerCapabilitiesPtr GetScannerCapabilities(
      const base::UnguessableToken& scanner_id) {
    base::test::TestFuture<mojo_ipc::ScannerCapabilitiesPtr> future;
    scan_service_remote_->GetScannerCapabilities(scanner_id,
                                                 future.GetCallback());
    return future.Take();
  }

  // Starts a scan with the scanner identified by |scanner_id| with the given
  // |settings| by calling ScanService::StartScan() via the mojo::Remote.
  bool StartScan(const base::UnguessableToken& scanner_id,
                 mojo_ipc::ScanSettingsPtr settings) {
    base::test::TestFuture<bool> future;
    scan_service_remote_->StartScan(scanner_id, std::move(settings),
                                    fake_scan_job_observer_.GenerateRemote(),
                                    future.GetCallback());
    bool success = future.Take();
    task_environment_.RunUntilIdle();
    return success;
  }

  // Starts a multi-page scan with the scanner identified by |scanner_id| with
  // the given |settings| by calling ScanService::StartMultiPageScan() via the
  // mojo::Remote. Binds the returned MultiPageScanController
  // mojo::PendingRemote.
  bool StartMultiPageScan(const base::UnguessableToken& scanner_id,
                          mojo_ipc::ScanSettingsPtr settings) {
    base::test::TestFuture<
        mojo::PendingRemote<mojo_ipc::MultiPageScanController>>
        future;
    scan_service_remote_->StartMultiPageScan(
        scanner_id, std::move(settings),
        fake_scan_job_observer_.GenerateRemote(), future.GetCallback());
    auto pending_remote = future.Take();
    if (!pending_remote.is_valid())
      return false;

    multi_page_scan_controller_remote_.Bind(std::move(pending_remote));
    task_environment_.RunUntilIdle();
    return true;
  }

  void ResetMultiPageScanControllerRemote() {
    multi_page_scan_controller_remote_.reset();
  }

  bool ScanNextPage(const base::UnguessableToken& scanner_id,
                    mojo_ipc::ScanSettingsPtr settings) {
    base::test::TestFuture<bool> future;
    multi_page_scan_controller_remote_->ScanNextPage(
        scanner_id, std::move(settings), future.GetCallback());
    bool success = future.Take();
    task_environment_.RunUntilIdle();
    return success;
  }

  // Performs a cancel scan request.
  void CancelScan() {
    scan_service_remote_->CancelScan();
    task_environment_.RunUntilIdle();
  }

  void CompleteMultiPageScan() {
    multi_page_scan_controller_remote_->CompleteMultiPageScan();
    task_environment_.RunUntilIdle();
  }

  void RemovePage(const uint32_t page_index) {
    multi_page_scan_controller_remote_->RemovePage(page_index);
    task_environment_.RunUntilIdle();
  }

  bool RescanPage(const base::UnguessableToken& scanner_id,
                  mojo_ipc::ScanSettingsPtr settings,
                  const uint32_t page_index) {
    base::test::TestFuture<bool> future;
    multi_page_scan_controller_remote_->RescanPage(
        scanner_id, std::move(settings), page_index, future.GetCallback());
    bool success = future.Take();
    task_environment_.RunUntilIdle();
    return success;
  }

 protected:
  // A `BrowserTaskEnvironment` allows the test to create a `TestingProfile`.
  content::BrowserTaskEnvironment task_environment_{
      base::test::TaskEnvironment::TimeSource::MOCK_TIME};
  FakeLorgnetteScannerManager fake_lorgnette_scanner_manager_;
  FakeScanJobObserver fake_scan_job_observer_;
  std::unique_ptr<TestingProfileManager> profile_manager_;
  raw_ptr<TestingProfile> profile_ = nullptr;
  std::unique_ptr<ScopedTestMountPoint> scanned_files_mount_;
  std::unique_ptr<TestSessionController> session_controller_;
  const raw_ptr<ash::FakeChromeUserManager, DanglingUntriaged> user_manager_;
  user_manager::ScopedUserManager user_manager_owner_;
  std::unique_ptr<ScanService> scan_service_;

 private:
  mojo::Remote<mojo_ipc::ScanService> scan_service_remote_;
  mojo::Remote<mojo_ipc::MultiPageScanController>
      multi_page_scan_controller_remote_;
};

// Test that no scanners are returned when there are no scanner names.
TEST_F(ScanServiceTest, NoScannerNames) {
  fake_lorgnette_scanner_manager_.SetGetScannerNamesResponse({});
  auto scanners = GetScanners();
  EXPECT_TRUE(scanners.empty());
}

// Test that a scanner is returned with the correct display name.
TEST_F(ScanServiceTest, GetScanners) {
  fake_lorgnette_scanner_manager_.SetGetScannerNamesResponse(
      {kFirstTestScannerName});
  auto scanners = GetScanners();
  ASSERT_EQ(scanners.size(), 1u);
  EXPECT_EQ(scanners[0]->display_name, kFirstTestScannerName16);
}

// Test that two returned scanners have unique IDs.
TEST_F(ScanServiceTest, UniqueScannerIds) {
  fake_lorgnette_scanner_manager_.SetGetScannerNamesResponse(
      {kFirstTestScannerName, kSecondTestScannerName});
  auto scanners = GetScanners();
  ASSERT_EQ(scanners.size(), 2u);
  EXPECT_EQ(scanners[0]->display_name, kFirstTestScannerName16);
  EXPECT_EQ(scanners[1]->display_name, kSecondTestScannerName16);
  EXPECT_NE(scanners[0]->id, scanners[1]->id);
}

// Test that the number of detected scanners is recorded.
TEST_F(ScanServiceTest, RecordNumDetectedScanners) {
  base::HistogramTester histogram_tester;
  histogram_tester.ExpectTotalCount("Scanning.NumDetectedScanners", 0);
  fake_lorgnette_scanner_manager_.SetGetScannerNamesResponse(
      {kFirstTestScannerName, kSecondTestScannerName});
  auto scanners = GetScanners();
  ASSERT_EQ(scanners.size(), 2u);
  histogram_tester.ExpectUniqueSample("Scanning.NumDetectedScanners", 2, 1);
}

// Test that attempting to get capabilities with a scanner ID that doesn't
// correspond to a scanner results in obtaining no capabilities.
TEST_F(ScanServiceTest, BadScannerId) {
  auto caps = GetScannerCapabilities(base::UnguessableToken::Create());
  EXPECT_TRUE(caps->sources.empty());
}

// Test that failing to obtain capabilities from the LorgnetteScannerManager
// results in obtaining no capabilities.
TEST_F(ScanServiceTest, NoCapabilities) {
  fake_lorgnette_scanner_manager_.SetGetScannerNamesResponse(
      {kFirstTestScannerName});
  fake_lorgnette_scanner_manager_.SetGetScannerCapabilitiesResponse(
      std::nullopt);
  auto scanners = GetScanners();
  ASSERT_EQ(scanners.size(), 1u);
  auto caps = GetScannerCapabilities(scanners[0]->id);
  EXPECT_TRUE(caps->sources.empty());
}

// Test that scanner capabilities can be obtained successfully.
TEST_F(ScanServiceTest, GetScannerCapabilities) {
  fake_lorgnette_scanner_manager_.SetGetScannerNamesResponse(
      {kFirstTestScannerName});
  fake_lorgnette_scanner_manager_.SetGetScannerCapabilitiesResponse(
      CreateLorgnetteScannerCapabilities());
  auto scanners = GetScanners();
  ASSERT_EQ(scanners.size(), 1u);
  auto caps = GetScannerCapabilities(scanners[0]->id);
  ASSERT_EQ(caps->sources.size(), 1u);
  EXPECT_EQ(caps->sources[0]->type, mojo_ipc::SourceType::kFlatbed);
  EXPECT_EQ(caps->sources[0]->name, kDocumentSourceName);
  ASSERT_EQ(caps->sources[0]->color_modes.size(), 1u);
  EXPECT_EQ(caps->sources[0]->color_modes[0], mojo_ipc::ColorMode::kColor);
  ASSERT_EQ(caps->sources[0]->resolutions.size(), 2u);
  EXPECT_EQ(caps->sources[0]->resolutions[0], kFirstResolution);
  EXPECT_EQ(caps->sources[0]->resolutions[1], kSecondResolution);
}

// Test that attempting to scan with a scanner ID that doesn't correspond to a
// scanner results in a failed scan.
TEST_F(ScanServiceTest, ScanWithBadScannerId) {
  EXPECT_FALSE(StartScan(base::UnguessableToken::Create(),
                         mojo_ipc::ScanSettings::New()));
}

// Test that attempting to scan with an unsupported file path fails.
// Specifically, use a file path with directory navigation (e.g. "..") to verify
// it can't be used to save scanned images to an unsupported path.
TEST_F(ScanServiceTest, ScanWithUnsupportedFilePath) {
  const base::FilePath my_files_path(kMyFilesPath);
  SetupScanService(my_files_path, base::FilePath("/google/drive"));

  fake_lorgnette_scanner_manager_.SetGetScannerNamesResponse(
      {kFirstTestScannerName});
  const std::vector<std::string> scan_data = {"TestData"};
  fake_lorgnette_scanner_manager_.SetScanResponse(scan_data);
  auto scanners = GetScanners();
  ASSERT_EQ(scanners.size(), 1u);

  const mojo_ipc::ScanSettings settings = CreateScanSettings(
      my_files_path.Append("../../../var/log"), mojo_ipc::FileType::kPng);
  EXPECT_FALSE(StartScan(scanners[0]->id, settings.Clone()));
}

// Test that a scan can be performed successfully.
TEST_F(ScanServiceTest, Scan) {
  fake_lorgnette_scanner_manager_.SetGetScannerNamesResponse(
      {kFirstTestScannerName});
  const std::vector<std::string> scan_data = {CreateJpeg(), CreateJpeg(),
                                              CreateJpeg()};
  fake_lorgnette_scanner_manager_.SetScanResponse(scan_data);
  auto scanners = GetScanners();
  ASSERT_EQ(scanners.size(), 1u);

  const auto now = base::Time::Now();
  base::HistogramTester histogram_tester;
  int num_single_file_scans = 0u;
  int num_multi_file_scans = 0u;
  for (int type_num = static_cast<int>(mojo_ipc::FileType::kMinValue);
       type_num <= static_cast<int>(mojo_ipc::FileType::kMaxValue);
       ++type_num) {
    auto type = static_cast<mojo_ipc::FileType>(type_num);

    const std::vector<base::FilePath> saved_scan_paths = CreateSavedScanPaths(
        scanned_files_mount_->GetRootPath(), now, type, scan_data.size());
    for (const auto& saved_scan_path : saved_scan_paths)
      EXPECT_FALSE(base::PathExists(saved_scan_path));

    mojo_ipc::ScanSettings settings =
        CreateScanSettings(scanned_files_mount_->GetRootPath(), type);
    EXPECT_TRUE(StartScan(scanners[0]->id, settings.Clone()));
    for (const auto& saved_scan_path : saved_scan_paths)
      EXPECT_TRUE(base::PathExists(saved_scan_path));

    EXPECT_TRUE(fake_scan_job_observer_.scan_success());
    EXPECT_EQ(ProtoScanFailureMode::SCAN_FAILURE_MODE_NO_FAILURE,
              fake_scan_job_observer_.scan_result());
    EXPECT_EQ(scan_data.size() - 1, fake_scan_job_observer_.new_page_index());
    EXPECT_EQ(saved_scan_paths, fake_scan_job_observer_.scanned_file_paths());

    // Verify that the histograms have been updated correctly.
    histogram_tester.ExpectBucketCount(
        "Scanning.NumFilesCreated", saved_scan_paths.size(),
        type == mojo_ipc::FileType::kPdf ? ++num_single_file_scans
                                         : ++num_multi_file_scans);
    histogram_tester.ExpectUniqueSample(
        "Scanning.NumPagesScanned", scan_data.size(),
        num_single_file_scans + num_multi_file_scans);
  }
}

// Test that an Epson ADF Duplex scan, which produces flipped pages, completes
// successfully.
TEST_F(ScanServiceTest, RotateEpsonADF) {
  fake_lorgnette_scanner_manager_.SetGetScannerNamesResponse({kEpsonTestName});
  fake_lorgnette_scanner_manager_.SetGetScannerCapabilitiesResponse(
      CreateEpsonScannerCapabilities());
  const std::vector<std::string> scan_data = {CreateJpeg(), CreateJpeg(),
                                              CreateJpeg()};
  fake_lorgnette_scanner_manager_.SetScanResponse(scan_data);
  auto scanners = GetScanners();
  ASSERT_EQ(scanners.size(), 1u);

  mojo_ipc::ScanSettings settings =
      CreateScanSettings(scanned_files_mount_->GetRootPath(),
                         mojo_ipc::FileType::kPdf, "ADF Duplex");
  const base::FilePath saved_scan_path = CreateSavedPdfScanPath(
      scanned_files_mount_->GetRootPath(), base::Time::Now());
  EXPECT_FALSE(base::PathExists(saved_scan_path));
  EXPECT_TRUE(StartScan(scanners[0]->id, settings.Clone()));
  EXPECT_TRUE(base::PathExists(saved_scan_path));
  EXPECT_TRUE(fake_scan_job_observer_.scan_success());
  const std::vector<base::FilePath> scanned_file_paths =
      fake_scan_job_observer_.scanned_file_paths();
  EXPECT_EQ(1u, scanned_file_paths.size());
  EXPECT_EQ(scan_data.size() - 1, fake_scan_job_observer_.new_page_index());
  EXPECT_EQ(saved_scan_path, scanned_file_paths.front());
}

// Test that when a scan fails, the scan job is marked as failed.
TEST_F(ScanServiceTest, ScanFails) {
  // Skip setting the scan data in FakeLorgnetteScannerManager so the scan will
  // fail.
  fake_lorgnette_scanner_manager_.SetGetScannerNamesResponse(
      {kFirstTestScannerName});
  auto scanners = GetScanners();
  ASSERT_EQ(scanners.size(), 1u);

  const mojo_ipc::ScanSettings settings = CreateScanSettings(
      scanned_files_mount_->GetRootPath(), mojo_ipc::FileType::kPng);

  EXPECT_TRUE(StartScan(scanners[0]->id, settings.Clone()));
  EXPECT_FALSE(fake_scan_job_observer_.scan_success());
  EXPECT_EQ(ProtoScanFailureMode::SCAN_FAILURE_MODE_DEVICE_BUSY,
            fake_scan_job_observer_.scan_result());
  EXPECT_TRUE(fake_scan_job_observer_.scanned_file_paths().empty());
}

// Tests that a new scan job can succeed after the previous scan failed.
TEST_F(ScanServiceTest, ScanAfterFailedScan) {
  // Skip setting the scan data in FakeLorgnetteScannerManager so the scan will
  // fail.
  fake_lorgnette_scanner_manager_.SetGetScannerNamesResponse(
      {kFirstTestScannerName});
  auto scanners = GetScanners();
  ASSERT_EQ(scanners.size(), 1u);

  const mojo_ipc::ScanSettings settings = CreateScanSettings(
      scanned_files_mount_->GetRootPath(), mojo_ipc::FileType::kPng);

  EXPECT_TRUE(StartScan(scanners[0]->id, settings.Clone()));
  EXPECT_FALSE(fake_scan_job_observer_.scan_success());
  EXPECT_EQ(ProtoScanFailureMode::SCAN_FAILURE_MODE_DEVICE_BUSY,
            fake_scan_job_observer_.scan_result());
  EXPECT_TRUE(fake_scan_job_observer_.scanned_file_paths().empty());

  // Set scan data so next scan is successful.
  const std::vector<std::string> scan_data = {"TestData1", "TestData2",
                                              "TestData3"};
  fake_lorgnette_scanner_manager_.SetScanResponse(scan_data);

  const std::vector<base::FilePath> saved_scan_paths = CreateSavedScanPaths(
      scanned_files_mount_->GetRootPath(), base::Time::Now(),
      mojo_ipc::FileType::kPng, scan_data.size());
  for (const auto& saved_scan_path : saved_scan_paths)
    EXPECT_FALSE(base::PathExists(saved_scan_path));

  EXPECT_TRUE(StartScan(scanners[0]->id, settings.Clone()));
  for (const auto& saved_scan_path : saved_scan_paths)
    EXPECT_TRUE(base::PathExists(saved_scan_path));

  EXPECT_TRUE(fake_scan_job_observer_.scan_success());
  EXPECT_EQ(ProtoScanFailureMode::SCAN_FAILURE_MODE_NO_FAILURE,
            fake_scan_job_observer_.scan_result());
  EXPECT_EQ(saved_scan_paths, fake_scan_job_observer_.scanned_file_paths());
  EXPECT_EQ(scan_data.size() - 1, fake_scan_job_observer_.new_page_index());
}

// Tests that a failed scan does not retain values from the previous successful
// scan.
TEST_F(ScanServiceTest, FailedScanAfterSuccessfulScan) {
  fake_lorgnette_scanner_manager_.SetGetScannerNamesResponse(
      {kFirstTestScannerName});
  const std::vector<std::string> scan_data = {"TestData1", "TestData2",
                                              "TestData3"};
  fake_lorgnette_scanner_manager_.SetScanResponse(scan_data);
  auto scanners = GetScanners();
  ASSERT_EQ(scanners.size(), 1u);

  const mojo_ipc::ScanSettings settings = CreateScanSettings(
      scanned_files_mount_->GetRootPath(), mojo_ipc::FileType::kPng);
  const std::vector<base::FilePath> saved_scan_paths = CreateSavedScanPaths(
      scanned_files_mount_->GetRootPath(), base::Time::Now(),
      mojo_ipc::FileType::kPng, scan_data.size());
  for (const auto& saved_scan_path : saved_scan_paths)
    EXPECT_FALSE(base::PathExists(saved_scan_path));

  EXPECT_TRUE(StartScan(scanners[0]->id, settings.Clone()));
  for (const auto& saved_scan_path : saved_scan_paths)
    EXPECT_TRUE(base::PathExists(saved_scan_path));

  EXPECT_TRUE(fake_scan_job_observer_.scan_success());
  EXPECT_EQ(ProtoScanFailureMode::SCAN_FAILURE_MODE_NO_FAILURE,
            fake_scan_job_observer_.scan_result());
  EXPECT_EQ(saved_scan_paths, fake_scan_job_observer_.scanned_file_paths());
  EXPECT_EQ(scan_data.size() - 1, fake_scan_job_observer_.new_page_index());

  // Remove the scan data from FakeLorgnetteScannerManager so the scan will
  // fail.
  fake_lorgnette_scanner_manager_.SetScanResponse({});

  EXPECT_TRUE(StartScan(scanners[0]->id, settings.Clone()));
  EXPECT_FALSE(fake_scan_job_observer_.scan_success());
  EXPECT_EQ(ProtoScanFailureMode::SCAN_FAILURE_MODE_DEVICE_BUSY,
            fake_scan_job_observer_.scan_result());
  EXPECT_TRUE(fake_scan_job_observer_.scanned_file_paths().empty());
}

// Test that canceling sends an update to the observer OnCancelComplete().
TEST_F(ScanServiceTest, CancelScanBeforeScanCompletes) {
  fake_lorgnette_scanner_manager_.SetGetScannerNamesResponse(
      {kFirstTestScannerName});
  const std::vector<std::string> scan_data = {"TestData"};
  fake_lorgnette_scanner_manager_.SetScanResponse(scan_data);
  auto scanners = GetScanners();
  ASSERT_EQ(scanners.size(), 1u);

  const mojo_ipc::ScanSettings settings = CreateScanSettings(
      scanned_files_mount_->GetRootPath(), mojo_ipc::FileType::kPng);

  StartScan(scanners[0]->id, settings.Clone());
  CancelScan();
  EXPECT_TRUE(fake_scan_job_observer_.cancel_scan_success());
}

// Test that a multi-page image scan creates a holding space item.
TEST_F(ScanServiceTest, HoldingSpaceScan) {
  fake_lorgnette_scanner_manager_.SetGetScannerNamesResponse(
      {kFirstTestScannerName});
  const std::vector<std::string> scan_data = {CreateJpeg(), CreateJpeg(),
                                              CreateJpeg()};
  auto scanners = GetScanners();
  ASSERT_EQ(scanners.size(), 1u);

  // Verify that the holding space starts out empty.
  HoldingSpaceKeyedService* holding_space_keyed_service =
      HoldingSpaceKeyedServiceFactory::GetInstance()->GetService(profile_);
  ASSERT_TRUE(holding_space_keyed_service);
  const HoldingSpaceModel* holding_space_model =
      holding_space_keyed_service->model_for_testing();
  ASSERT_TRUE(holding_space_model);
  size_t num_items_in_holding_space = 0u;
  ASSERT_EQ(num_items_in_holding_space, holding_space_model->items().size());

  const auto now = base::Time::Now();
  for (int type_num = static_cast<int>(mojo_ipc::FileType::kMinValue);
       type_num <= static_cast<int>(mojo_ipc::FileType::kMaxValue);
       ++type_num) {
    auto type = static_cast<mojo_ipc::FileType>(type_num);

    fake_lorgnette_scanner_manager_.SetScanResponse(scan_data);
    const std::vector<base::FilePath> saved_scan_paths = CreateSavedScanPaths(
        scanned_files_mount_->GetRootPath(), now, type, scan_data.size());
    for (const auto& saved_scan_path : saved_scan_paths)
      EXPECT_FALSE(base::PathExists(saved_scan_path));

    mojo_ipc::ScanSettings settings =
        CreateScanSettings(scanned_files_mount_->GetRootPath(), type);
    EXPECT_TRUE(StartScan(scanners[0]->id, settings.Clone()));
    EXPECT_TRUE(fake_scan_job_observer_.scan_success());
    EXPECT_EQ(ProtoScanFailureMode::SCAN_FAILURE_MODE_NO_FAILURE,
              fake_scan_job_observer_.scan_result());
    EXPECT_EQ(saved_scan_paths, fake_scan_job_observer_.scanned_file_paths());

    // Verify that the all pages of each scan are added to the holding space.
    EXPECT_EQ(num_items_in_holding_space + saved_scan_paths.size(),
              holding_space_model->items().size());
    for (const auto& saved_scan_path : saved_scan_paths) {
      EXPECT_TRUE(base::PathExists(saved_scan_path));
      HoldingSpaceItem* scanned_item =
          holding_space_model->items()[num_items_in_holding_space++].get();
      EXPECT_EQ(scanned_item->type(), HoldingSpaceItem::Type::kScan);
      EXPECT_EQ(scanned_item->file().file_path, saved_scan_path);
    }

    // Remove the scan data from FakeLorgnetteScannerManager so the scan will
    // fail.
    fake_lorgnette_scanner_manager_.SetScanResponse({});

    EXPECT_TRUE(StartScan(scanners[0]->id, settings.Clone()));
    EXPECT_FALSE(fake_scan_job_observer_.scan_success());
    EXPECT_EQ(ProtoScanFailureMode::SCAN_FAILURE_MODE_DEVICE_BUSY,
              fake_scan_job_observer_.scan_result());
    EXPECT_TRUE(fake_scan_job_observer_.scanned_file_paths().empty());

    // Verify that no item is added to the holding space when a scan fails.
    EXPECT_EQ(num_items_in_holding_space, holding_space_model->items().size());
  }
}

// Test that a multi-page scan can be performed successfully.
TEST_F(ScanServiceTest, MultiPageScan) {
  base::HistogramTester histogram_tester;

  fake_lorgnette_scanner_manager_.SetGetScannerNamesResponse(
      {kFirstTestScannerName});
  const std::vector<std::string> scan_data = {CreateJpeg()};
  fake_lorgnette_scanner_manager_.SetScanResponse(scan_data);
  auto scanners = GetScanners();
  ASSERT_EQ(scanners.size(), 1u);

  const std::vector<base::FilePath> saved_scan_paths = CreateSavedScanPaths(
      scanned_files_mount_->GetRootPath(), base::Time::Now(),
      mojo_ipc::FileType::kPdf, scan_data.size());
  for (const auto& saved_scan_path : saved_scan_paths)
    EXPECT_FALSE(base::PathExists(saved_scan_path));

  mojo_ipc::ScanSettings settings = CreateScanSettings(
      scanned_files_mount_->GetRootPath(), mojo_ipc::FileType::kPdf);
  uint32_t new_page_index = 0;

  // Scan the first page without completing the scan.
  EXPECT_TRUE(StartMultiPageScan(scanners[0]->id, settings.Clone()));
  for (const auto& saved_scan_path : saved_scan_paths)
    EXPECT_FALSE(base::PathExists(saved_scan_path));
  EXPECT_FALSE(fake_scan_job_observer_.scan_success());
  EXPECT_TRUE(fake_scan_job_observer_.scanned_file_paths().empty());
  EXPECT_EQ(new_page_index++, fake_scan_job_observer_.new_page_index());

  // Scan the second page without completing the scan.
  EXPECT_TRUE(ScanNextPage(scanners[0]->id, settings.Clone()));
  for (const auto& saved_scan_path : saved_scan_paths)
    EXPECT_FALSE(base::PathExists(saved_scan_path));
  EXPECT_FALSE(fake_scan_job_observer_.scan_success());
  EXPECT_TRUE(fake_scan_job_observer_.scanned_file_paths().empty());
  EXPECT_EQ(new_page_index++, fake_scan_job_observer_.new_page_index());

  // Complete the multi-page scan expecting 2 pages to be scanned and a single
  // PDF to be created.
  CompleteMultiPageScan();
  for (const auto& saved_scan_path : saved_scan_paths)
    EXPECT_TRUE(base::PathExists(saved_scan_path));
  EXPECT_TRUE(fake_scan_job_observer_.scan_success());
  EXPECT_EQ(saved_scan_paths, fake_scan_job_observer_.scanned_file_paths());
  histogram_tester.ExpectUniqueSample("Scanning.NumPagesScanned", 2, 1);
  histogram_tester.ExpectUniqueSample("Scanning.MultiPageScan.NumPagesScanned",
                                      2, 1);
  histogram_tester.ExpectUniqueSample("Scanning.MultiPageScan.PageScanResult",
                                      scanning::ScanJobFailureReason::kSuccess,
                                      2);
}

// Test that when a multi-page scan fails, the scan job is marked as failed.
TEST_F(ScanServiceTest, MultiPageScanFails) {
  base::HistogramTester histogram_tester;

  fake_lorgnette_scanner_manager_.SetGetScannerNamesResponse(
      {kFirstTestScannerName});
  const std::vector<std::string> scan_data = {CreateJpeg()};
  fake_lorgnette_scanner_manager_.SetScanResponse(scan_data);
  auto scanners = GetScanners();
  ASSERT_EQ(scanners.size(), 1u);

  mojo_ipc::ScanSettings settings = CreateScanSettings(
      scanned_files_mount_->GetRootPath(), mojo_ipc::FileType::kPdf);

  // The first scan should pass with no failure.
  EXPECT_TRUE(StartMultiPageScan(scanners[0]->id, settings.Clone()));
  EXPECT_FALSE(fake_scan_job_observer_.scan_success());
  EXPECT_EQ(ProtoScanFailureMode::SCAN_FAILURE_MODE_UNKNOWN,
            fake_scan_job_observer_.multi_page_scan_result());
  EXPECT_TRUE(fake_scan_job_observer_.scanned_file_paths().empty());
  EXPECT_EQ(0u, fake_scan_job_observer_.new_page_index());

  // Set scan data to empty vector in FakeLorgnetteScannerManager so the next
  // scan will fail.
  fake_lorgnette_scanner_manager_.SetScanResponse({});
  EXPECT_TRUE(ScanNextPage(scanners[0]->id, settings.Clone()));
  EXPECT_FALSE(fake_scan_job_observer_.scan_success());
  EXPECT_EQ(ProtoScanFailureMode::SCAN_FAILURE_MODE_DEVICE_BUSY,
            fake_scan_job_observer_.multi_page_scan_result());
  EXPECT_TRUE(fake_scan_job_observer_.scanned_file_paths().empty());

  histogram_tester.ExpectBucketCount("Scanning.MultiPageScan.PageScanResult",
                                     scanning::ScanJobFailureReason::kSuccess,
                                     1);
  histogram_tester.ExpectBucketCount(
      "Scanning.MultiPageScan.PageScanResult",
      scanning::ScanJobFailureReason::kDeviceBusy, 1);
}

// Test that attempting to start a second multi-page scan while another
// multi-page scan session is going will fail.
TEST_F(ScanServiceTest, StartingAnotherMultiPageScan) {
  fake_lorgnette_scanner_manager_.SetGetScannerNamesResponse(
      {kFirstTestScannerName});
  const std::vector<std::string> scan_data = {CreateJpeg()};
  fake_lorgnette_scanner_manager_.SetScanResponse(scan_data);
  auto scanners = GetScanners();
  ASSERT_EQ(scanners.size(), 1u);

  mojo_ipc::ScanSettings settings = CreateScanSettings(
      scanned_files_mount_->GetRootPath(), mojo_ipc::FileType::kPdf);

  // The first scan should pass with no failure.
  EXPECT_TRUE(StartMultiPageScan(scanners[0]->id, settings.Clone()));
  EXPECT_FALSE(fake_scan_job_observer_.scan_success());
  EXPECT_EQ(ProtoScanFailureMode::SCAN_FAILURE_MODE_UNKNOWN,
            fake_scan_job_observer_.multi_page_scan_result());
  EXPECT_TRUE(fake_scan_job_observer_.scanned_file_paths().empty());
  EXPECT_EQ(0u, fake_scan_job_observer_.new_page_index());

  // The second attempt should fail.
  EXPECT_FALSE(StartMultiPageScan(scanners[0]->id, settings.Clone()));
}

// Test that a page can be removed from a multi-page scan with two scanned
// images.
TEST_F(ScanServiceTest, MultiPageScanRemoveWithTwoPages) {
  base::HistogramTester histogram_tester;

  fake_lorgnette_scanner_manager_.SetGetScannerNamesResponse(
      {kFirstTestScannerName});
  auto scanners = GetScanners();
  ASSERT_EQ(scanners.size(), 1u);

  mojo_ipc::ScanSettings settings = CreateScanSettings(
      scanned_files_mount_->GetRootPath(), mojo_ipc::FileType::kPdf);
  uint32_t new_page_index = 0;

  const std::string first_scanned_image = CreateJpeg(/*alpha=*/1);
  const std::vector<std::string> first_scan_data = {first_scanned_image};
  fake_lorgnette_scanner_manager_.SetScanResponse(first_scan_data);
  EXPECT_TRUE(StartMultiPageScan(scanners[0]->id, settings.Clone()));
  EXPECT_EQ(new_page_index++, fake_scan_job_observer_.new_page_index());

  const std::string second_scanned_image = CreateJpeg(/*alpha=*/2);
  const std::vector<std::string> second_scan_data = {second_scanned_image};
  fake_lorgnette_scanner_manager_.SetScanResponse(second_scan_data);
  EXPECT_TRUE(ScanNextPage(scanners[0]->id, settings.Clone()));
  EXPECT_EQ(new_page_index++, fake_scan_job_observer_.new_page_index());

  // Delete the first page.
  RemovePage(0);
  CompleteMultiPageScan();

  const std::vector<std::string> scanned_images =
      scan_service_->GetScannedImagesForTesting();
  EXPECT_EQ(1u, scanned_images.size());
  EXPECT_EQ(second_scanned_image, scanned_images[0]);

  // Expect 1 record of the Scanning.NumPagesScanned metric in the 1 pages
  // scanned bucket.
  histogram_tester.ExpectUniqueSample("Scanning.NumPagesScanned", 1, 1);
  histogram_tester.ExpectUniqueSample("Scanning.MultiPageScan.NumPagesScanned",
                                      1, 1);
  histogram_tester.ExpectUniqueSample(
      "Scanning.MultiPageScan.ToolbarAction",
      scanning::ScanMultiPageToolbarAction::kRemovePage, 1);
}

// Test that a page can be removed from a multi-page scan with three scanned
// images.
TEST_F(ScanServiceTest, MultiPageScanRemoveWithThreePages) {
  base::HistogramTester histogram_tester;

  fake_lorgnette_scanner_manager_.SetGetScannerNamesResponse(
      {kFirstTestScannerName});
  auto scanners = GetScanners();
  ASSERT_EQ(scanners.size(), 1u);

  mojo_ipc::ScanSettings settings = CreateScanSettings(
      scanned_files_mount_->GetRootPath(), mojo_ipc::FileType::kPdf);
  uint32_t new_page_index = 0;

  const std::string first_scanned_image = CreateJpeg(/*alpha=*/1);
  const std::vector<std::string> first_scan_data = {first_scanned_image};
  fake_lorgnette_scanner_manager_.SetScanResponse(first_scan_data);
  EXPECT_TRUE(StartMultiPageScan(scanners[0]->id, settings.Clone()));
  EXPECT_EQ(new_page_index++, fake_scan_job_observer_.new_page_index());

  const std::string second_scanned_image = CreateJpeg(/*alpha=*/2);
  const std::vector<std::string> second_scan_data = {second_scanned_image};
  fake_lorgnette_scanner_manager_.SetScanResponse(second_scan_data);
  EXPECT_TRUE(ScanNextPage(scanners[0]->id, settings.Clone()));
  EXPECT_EQ(new_page_index++, fake_scan_job_observer_.new_page_index());

  const std::string third_scanned_image = CreateJpeg(/*alpha=*/3);
  const std::vector<std::string> third_scan_data = {third_scanned_image};
  fake_lorgnette_scanner_manager_.SetScanResponse(third_scan_data);
  EXPECT_TRUE(ScanNextPage(scanners[0]->id, settings.Clone()));
  EXPECT_EQ(new_page_index++, fake_scan_job_observer_.new_page_index());

  // Delete the second page.
  RemovePage(1);
  CompleteMultiPageScan();

  const std::vector<std::string> scanned_images =
      scan_service_->GetScannedImagesForTesting();
  EXPECT_EQ(2u, scanned_images.size());
  EXPECT_EQ(first_scanned_image, scanned_images[0]);
  EXPECT_EQ(third_scanned_image, scanned_images[1]);

  // Expect 1 record of the Scanning.NumPagesScanned metric in the 2 pages
  // scanned bucket.
  histogram_tester.ExpectUniqueSample("Scanning.NumPagesScanned", 2, 1);
  histogram_tester.ExpectUniqueSample("Scanning.MultiPageScan.NumPagesScanned",
                                      2, 1);
  histogram_tester.ExpectUniqueSample(
      "Scanning.MultiPageScan.ToolbarAction",
      scanning::ScanMultiPageToolbarAction::kRemovePage, 1);
}

// Test that if there's only one page available, the page is removed and the
// multi-page scan session is reset and a new session can be started.
TEST_F(ScanServiceTest, MultiPageScanRemoveLastPage) {
  base::HistogramTester histogram_tester;

  fake_lorgnette_scanner_manager_.SetGetScannerNamesResponse(
      {kFirstTestScannerName});
  const std::vector<std::string> scan_data = {CreateJpeg()};
  fake_lorgnette_scanner_manager_.SetScanResponse(scan_data);
  auto scanners = GetScanners();
  ASSERT_EQ(scanners.size(), 1u);

  mojo_ipc::ScanSettings settings = CreateScanSettings(
      scanned_files_mount_->GetRootPath(), mojo_ipc::FileType::kPdf);
  uint32_t new_page_index = 0;

  EXPECT_TRUE(StartMultiPageScan(scanners[0]->id, settings.Clone()));
  EXPECT_EQ(new_page_index++, fake_scan_job_observer_.new_page_index());

  // Removing the page should reset the multi-page scan session.
  RemovePage(0);
  --new_page_index;

  // Start a new scan and complete it with 1 page.
  ResetMultiPageScanControllerRemote();
  EXPECT_TRUE(StartMultiPageScan(scanners[0]->id, settings.Clone()));
  EXPECT_EQ(new_page_index++, fake_scan_job_observer_.new_page_index());
  CompleteMultiPageScan();

  const std::vector<std::string> scanned_images =
      scan_service_->GetScannedImagesForTesting();
  EXPECT_EQ(1u, scanned_images.size());

  // Expect 1 record of the Scanning.NumPagesScanned metric in the 1 page
  // scanned bucket.
  histogram_tester.ExpectUniqueSample("Scanning.NumPagesScanned", 1, 1);
  histogram_tester.ExpectUniqueSample("Scanning.MultiPageScan.NumPagesScanned",
                                      1, 1);
  histogram_tester.ExpectUniqueSample(
      "Scanning.MultiPageScan.ToolbarAction",
      scanning::ScanMultiPageToolbarAction::kRemovePage, 1);
}

// Test that a page can be rescanned and replaced from a multi-page scan with
// one scanned image.
TEST_F(ScanServiceTest, MultiPageScanRescanWithOnePage) {
  base::HistogramTester histogram_tester;

  fake_lorgnette_scanner_manager_.SetGetScannerNamesResponse(
      {kFirstTestScannerName});
  auto scanners = GetScanners();
  ASSERT_EQ(scanners.size(), 1u);

  mojo_ipc::ScanSettings settings = CreateScanSettings(
      scanned_files_mount_->GetRootPath(), mojo_ipc::FileType::kPdf);
  uint32_t new_page_index = 0;

  const std::string first_scanned_image = CreateJpeg(/*alpha=*/1);
  const std::vector<std::string> first_scan_data = {first_scanned_image};
  fake_lorgnette_scanner_manager_.SetScanResponse(first_scan_data);
  EXPECT_TRUE(StartMultiPageScan(scanners[0]->id, settings.Clone()));
  EXPECT_EQ(new_page_index++, fake_scan_job_observer_.new_page_index());

  // Rescan the page.
  const std::string rescanned_scanned_image = CreateJpeg(/*alpha=*/2);
  const std::vector<std::string> rescanned_scan_data = {
      rescanned_scanned_image};
  fake_lorgnette_scanner_manager_.SetScanResponse(rescanned_scan_data);
  EXPECT_TRUE(RescanPage(scanners[0]->id, settings.Clone(), /*page_index=*/0));
  EXPECT_EQ(0u, fake_scan_job_observer_.new_page_index());
  CompleteMultiPageScan();

  const std::vector<std::string> scanned_images =
      scan_service_->GetScannedImagesForTesting();
  EXPECT_EQ(1u, scanned_images.size());
  EXPECT_EQ(rescanned_scanned_image, scanned_images[0]);

  // Expect 1 record of the Scanning.NumPagesScanned metric in the 1 pages
  // scanned bucket.
  histogram_tester.ExpectUniqueSample("Scanning.NumPagesScanned", 1, 1);
  histogram_tester.ExpectUniqueSample("Scanning.MultiPageScan.NumPagesScanned",
                                      1, 1);
  histogram_tester.ExpectUniqueSample(
      "Scanning.MultiPageScan.ToolbarAction",
      scanning::ScanMultiPageToolbarAction::kRescanPage, 1);
}

// Test that a page can be rescanned and replaced from a multi-page scan with
// three scanned images.
TEST_F(ScanServiceTest, MultiPageScanRescanWithThreePages) {
  base::HistogramTester histogram_tester;

  fake_lorgnette_scanner_manager_.SetGetScannerNamesResponse(
      {kFirstTestScannerName});
  auto scanners = GetScanners();
  ASSERT_EQ(scanners.size(), 1u);

  mojo_ipc::ScanSettings settings = CreateScanSettings(
      scanned_files_mount_->GetRootPath(), mojo_ipc::FileType::kPdf);
  uint32_t new_page_index = 0;

  const std::string first_scanned_image = CreateJpeg(/*alpha=*/1);
  const std::vector<std::string> first_scan_data = {first_scanned_image};
  fake_lorgnette_scanner_manager_.SetScanResponse(first_scan_data);
  EXPECT_TRUE(StartMultiPageScan(scanners[0]->id, settings.Clone()));
  EXPECT_EQ(new_page_index++, fake_scan_job_observer_.new_page_index());

  const std::string second_scanned_image = CreateJpeg(/*alpha=*/2);
  const std::vector<std::string> second_scan_data = {second_scanned_image};
  fake_lorgnette_scanner_manager_.SetScanResponse(second_scan_data);
  EXPECT_TRUE(ScanNextPage(scanners[0]->id, settings.Clone()));
  EXPECT_EQ(new_page_index++, fake_scan_job_observer_.new_page_index());

  const std::string third_scanned_image = CreateJpeg(/*alpha=*/3);
  const std::vector<std::string> third_scan_data = {third_scanned_image};
  fake_lorgnette_scanner_manager_.SetScanResponse(third_scan_data);
  EXPECT_TRUE(ScanNextPage(scanners[0]->id, settings.Clone()));
  EXPECT_EQ(new_page_index++, fake_scan_job_observer_.new_page_index());

  // Rescan the second page.
  const std::string rescanned_scanned_image = CreateJpeg(/*alpha=*/4);
  const std::vector<std::string> rescanned_scan_data = {
      rescanned_scanned_image};
  fake_lorgnette_scanner_manager_.SetScanResponse(rescanned_scan_data);
  EXPECT_TRUE(RescanPage(scanners[0]->id, settings.Clone(), /*page_index=*/1));
  EXPECT_EQ(1u, fake_scan_job_observer_.new_page_index());
  CompleteMultiPageScan();

  const std::vector<std::string> scanned_images =
      scan_service_->GetScannedImagesForTesting();
  EXPECT_EQ(3u, scanned_images.size());
  EXPECT_EQ(first_scanned_image, scanned_images[0]);
  EXPECT_EQ(rescanned_scanned_image, scanned_images[1]);
  EXPECT_EQ(third_scanned_image, scanned_images[2]);

  // Expect 1 record of the Scanning.NumPagesScanned metric in the 3 pages
  // scanned bucket.
  histogram_tester.ExpectUniqueSample("Scanning.NumPagesScanned", 3, 1);
  histogram_tester.ExpectUniqueSample("Scanning.MultiPageScan.NumPagesScanned",
                                      3, 1);
  histogram_tester.ExpectUniqueSample(
      "Scanning.MultiPageScan.ToolbarAction",
      scanning::ScanMultiPageToolbarAction::kRescanPage, 1);
}

TEST_F(ScanServiceTest, ResetReceiverOnBindInterface) {
  // This test simulates a user refreshing the WebUI page. The receiver should
  // be reset before binding the new receiver. Otherwise we would get a DCHECK
  // error from mojo::Receiver
  mojo::Remote<scanning::mojom::ScanService> remote;
  scan_service_->BindInterface(remote.BindNewPipeAndPassReceiver());
  base::RunLoop().RunUntilIdle();

  remote.reset();

  scan_service_->BindInterface(remote.BindNewPipeAndPassReceiver());
  base::RunLoop().RunUntilIdle();
}

// TODO(b:307385730): Parameterize this test once more settings combinations
// are added.
TEST_F(ScanServiceTest, ScanDataSettings) {
  fake_lorgnette_scanner_manager_.SetGetScannerNamesResponse(
      {kFirstTestScannerName});
  auto scanners = GetScanners();
  ASSERT_EQ(scanners.size(), 1u);

  // Settings correspond to "flatbed_jpeg_color_letter_300_dpi"
  // which sets the `alpha` used in the generated JPEG images to
  // 1.
  mojo_ipc::ScanSettings settings = CreateScanSettings(
      scanned_files_mount_->GetRootPath(), mojo_ipc::FileType::kPdf, "flatbed",
      mojo_ipc::ColorMode::kColor, mojo_ipc::PageSize::kNaLetter,
      kSecondResolution);

  EXPECT_TRUE(StartScan(scanners[0]->id, settings.Clone()));
  EXPECT_EQ(1u, scan_service_->GetScannedImagesForTesting().size());
  EXPECT_EQ(CreateJpeg(/*alpha=*/1),
            scan_service_->GetScannedImagesForTesting()[0]);
}

}  // namespace ash
