chromium/chrome/browser/screen_ai/screen_ai_dlc_installer_unittest.cc

// Copyright 2023 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/screen_ai/screen_ai_dlc_installer.h"

#include <string_view>

#include "base/memory/raw_ptr.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/task_environment.h"
#include "base/time/time.h"
#include "chrome/browser/screen_ai/screen_ai_install_state.h"
#include "chromeos/ash/components/dbus/dlcservice/dlcservice_client.h"
#include "chromeos/ash/components/dbus/dlcservice/fake_dlcservice_client.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/cros_system_api/dbus/dlcservice/dbus-constants.h"

namespace ash {

class ScreenAIDlcInstallerTest
    : public testing::Test,
      public testing::WithParamInterface<std::string> {
 protected:
  void SetUp() override {
    install_state_ = screen_ai::ScreenAIInstallState::Create();
    base_retry_delay_in_seconds =
        screen_ai::dlc_installer::base_retry_delay_in_seconds_for_testing();
    max_install_retries =
        screen_ai::dlc_installer::max_install_retries_for_testing();
  }

  void InstallAndWait() {
    screen_ai::dlc_installer::Install();
    task_environment_.RunUntilIdle();
  }

  void UninstallAndWait() {
    screen_ai::dlc_installer::Uninstall();
    task_environment_.RunUntilIdle();
  }

  void WaitForDelay(int delay_in_seconds) {
    task_environment_.AdvanceClock(base::Seconds(delay_in_seconds));
    task_environment_.RunUntilIdle();
  }

  void SetInstallError(std::string_view error_code) {
    fake_dlcservice_client_.set_install_error(error_code);
  }

  void ExpectSuccessHistogramCount(std::string_view histogram_name,
                                   int expected_count,
                                   int expected_total_count) {
    histogram_tester_.ExpectBucketCount(histogram_name, true, expected_count);
    histogram_tester_.ExpectTotalCount(histogram_name, expected_total_count);
  }

  void ExpectFailureHistogramCount(int expected_count,
                                   int expected_total_count) {
    histogram_tester_.ExpectBucketCount(
        "Accessibility.ScreenAI.Component.Install", false, expected_count);
    histogram_tester_.ExpectTotalCount(
        "Accessibility.ScreenAI.Component.Install", expected_total_count);
  }

  int base_retry_delay_in_seconds;
  int max_install_retries;

 private:
  FakeDlcserviceClient fake_dlcservice_client_;
  base::test::TaskEnvironment task_environment_{
      base::test::TaskEnvironment::TimeSource::MOCK_TIME};
  std::unique_ptr<screen_ai::ScreenAIInstallState> install_state_;
  base::HistogramTester histogram_tester_;
};

TEST_F(ScreenAIDlcInstallerTest, InstallSuccess) {
  InstallAndWait();
  ExpectSuccessHistogramCount("Accessibility.ScreenAI.Component.Install",
                              /*expected_count=*/1, /*expected_total_count=*/1);
}

TEST_F(ScreenAIDlcInstallerTest, InstallFailureWithDlcErrorNeedReboot) {
  SetInstallError(dlcservice::kErrorNeedReboot);
  InstallAndWait();
  ExpectFailureHistogramCount(/*expected_count=*/1, /*expected_total_count=*/1);
}

TEST_F(ScreenAIDlcInstallerTest, InstallFailureWithDlcErrorBusy) {
  SetInstallError(dlcservice::kErrorBusy);
  InstallAndWait();
  ExpectFailureHistogramCount(/*expected_count=*/0, /*expected_total_count=*/0);

  int delay_in_seconds = base_retry_delay_in_seconds;
  for (int i = 0; i < max_install_retries; ++i) {
    WaitForDelay(delay_in_seconds);
    delay_in_seconds =
        screen_ai::dlc_installer::CalculateNextDelayInSecondsForTesting(
            delay_in_seconds);
  }
  ExpectFailureHistogramCount(/*expected_count=*/1, /*expected_total_count=*/1);
}

TEST_F(ScreenAIDlcInstallerTest,
       InstallFailureWithDlcErrorBusyAndRetrySuccess) {
  SetInstallError(dlcservice::kErrorBusy);
  InstallAndWait();
  int delay_in_seconds = base_retry_delay_in_seconds;
  WaitForDelay(delay_in_seconds);
  ExpectFailureHistogramCount(/*expected_count=*/0, /*expected_total_count=*/0);

  SetInstallError(dlcservice::kErrorNone);
  delay_in_seconds =
      screen_ai::dlc_installer::CalculateNextDelayInSecondsForTesting(
          delay_in_seconds);
  WaitForDelay(delay_in_seconds);
  ExpectSuccessHistogramCount("Accessibility.ScreenAI.Component.Install",
                              /*expected_count=*/1, /*expected_total_count=*/1);
}

TEST_F(ScreenAIDlcInstallerTest, InstallFailuresRepeatedWithDlcErrorBusy) {
  SetInstallError(dlcservice::kErrorBusy);
  InstallAndWait();
  ExpectFailureHistogramCount(/*expected_count=*/0, /*expected_total_count=*/0);
  int delay_in_seconds = base_retry_delay_in_seconds;
  for (int i = 0; i < max_install_retries; ++i) {
    WaitForDelay(delay_in_seconds);
    delay_in_seconds =
        screen_ai::dlc_installer::CalculateNextDelayInSecondsForTesting(
            delay_in_seconds);
  }
  ExpectFailureHistogramCount(/*expected_count=*/1, /*expected_total_count=*/1);

  InstallAndWait();
  delay_in_seconds = base_retry_delay_in_seconds;
  for (int i = 0; i < max_install_retries; ++i) {
    WaitForDelay(delay_in_seconds);
    delay_in_seconds =
        screen_ai::dlc_installer::CalculateNextDelayInSecondsForTesting(
            delay_in_seconds);
  }
  ExpectFailureHistogramCount(/*expected_count=*/2, /*expected_total_count=*/2);
}

TEST_F(ScreenAIDlcInstallerTest, UninstallSuccess) {
  UninstallAndWait();
  ExpectSuccessHistogramCount("Accessibility.ScreenAI.Component.Uninstall",
                              /*expected_count=*/1, /*expected_total_count=*/1);
}

}  // namespace ash