chromium/chrome/browser/chromeos/reporting/user_reporting_settings_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/chromeos/reporting/user_reporting_settings.h"

#include <memory>

#include "base/callback_list.h"
#include "base/functional/callback_helpers.h"
#include "base/test/bind.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 "components/sync_preferences/testing_pref_service_syncable.h"
#include "content/public/test/browser_task_environment.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"

using ::testing::Eq;
using ::testing::IsNull;
using ::testing::NotNull;

namespace reporting {
namespace {

constexpr char kUserId[] = "123";
constexpr char kSettingPath[] = "TestSetting";

class UserReportingSettingsTest : public ::testing::Test {
 protected:
  void SetUp() override {
    ASSERT_TRUE(profile_manager_.SetUp());
    profile_ = profile_manager_.CreateTestingProfile(kUserId);
    user_reporting_settings_ =
        std::make_unique<UserReportingSettings>(profile_->GetWeakPtr());
  }

  ::content::BrowserTaskEnvironment task_environment_;
  TestingProfileManager profile_manager_{TestingBrowserProcess::GetGlobal()};
  raw_ptr<TestingProfile, DanglingUntriaged> profile_;
  std::unique_ptr<UserReportingSettings> user_reporting_settings_;
};

TEST_F(UserReportingSettingsTest, InvalidIntegerPrefPath) {
  profile_->GetTestingPrefService()->registry()->RegisterIntegerPref(
      kSettingPath, /*default_value=*/0);

  // Attempt to retrieve the integer reporting setting with incorrect data type
  // and confirm it fails.
  bool out_bool_value;
  ASSERT_FALSE(
      user_reporting_settings_->GetBoolean(kSettingPath, &out_bool_value));
  ASSERT_FALSE(user_reporting_settings_->GetReportingEnabled(kSettingPath,
                                                             &out_bool_value));
  const base::Value::List* out_list_value = nullptr;
  ASSERT_FALSE(
      user_reporting_settings_->GetList(kSettingPath, &out_list_value));
  EXPECT_THAT(out_list_value, IsNull());
}

TEST_F(UserReportingSettingsTest, InvalidBooleanPrefPath) {
  profile_->GetTestingPrefService()->registry()->RegisterBooleanPref(
      kSettingPath, /*default_value=*/true);

  // Attempt to retrieve the boolean reporting setting with incorrect data type
  // and confirm it fails.
  int out_int_value;
  ASSERT_FALSE(
      user_reporting_settings_->GetInteger(kSettingPath, &out_int_value));
  const base::Value::List* out_list_value = nullptr;
  ASSERT_FALSE(
      user_reporting_settings_->GetList(kSettingPath, &out_list_value));
  EXPECT_THAT(out_list_value, IsNull());
}

TEST_F(UserReportingSettingsTest, InvalidListPrefPath) {
  profile_->GetTestingPrefService()->registry()->RegisterListPref(
      kSettingPath, /*default_value=*/base::Value::List());

  // Attempt to retrieve the list reporting setting with incorrect data type and
  // confirm it fails.
  bool out_bool_value;
  ASSERT_FALSE(
      user_reporting_settings_->GetBoolean(kSettingPath, &out_bool_value));
  int out_int_value;
  EXPECT_FALSE(
      user_reporting_settings_->GetInteger(kSettingPath, &out_int_value));
}

TEST_F(UserReportingSettingsTest, GetUnregisteredSetting) {
  bool out_bool_value;
  EXPECT_FALSE(
      user_reporting_settings_->GetBoolean(kSettingPath, &out_bool_value));
  int out_int_value;
  EXPECT_FALSE(
      user_reporting_settings_->GetInteger(kSettingPath, &out_int_value));
  const base::Value::List* out_list_value = nullptr;
  EXPECT_FALSE(
      user_reporting_settings_->GetList(kSettingPath, &out_list_value));
}

TEST_F(UserReportingSettingsTest, GetBoolean) {
  profile_->GetTestingPrefService()->registry()->RegisterBooleanPref(
      kSettingPath, /*default_value=*/false);
  bool out_value = true;
  ASSERT_TRUE(user_reporting_settings_->GetBoolean(kSettingPath, &out_value));
  ASSERT_FALSE(out_value);

  // Update setting value and ensure the next fetch returns the updated value.
  profile_->GetPrefs()->SetBoolean(kSettingPath, true);
  ASSERT_TRUE(user_reporting_settings_->GetBoolean(kSettingPath, &out_value));
  EXPECT_TRUE(out_value);
}

TEST_F(UserReportingSettingsTest, GetReportingEnabled_Boolean) {
  profile_->GetTestingPrefService()->registry()->RegisterBooleanPref(
      kSettingPath, /*default_value=*/false);
  bool out_value = true;
  ASSERT_TRUE(
      user_reporting_settings_->GetReportingEnabled(kSettingPath, &out_value));
  EXPECT_FALSE(out_value);

  // Update setting value and ensure the next fetch returns the updated value.
  profile_->GetPrefs()->SetBoolean(kSettingPath, true);
  ASSERT_TRUE(user_reporting_settings_->GetBoolean(kSettingPath, &out_value));
  EXPECT_TRUE(out_value);
}

TEST_F(UserReportingSettingsTest, GetInteger) {
  profile_->GetTestingPrefService()->registry()->RegisterIntegerPref(
      kSettingPath, /*default_value=*/0);
  int out_value;
  ASSERT_TRUE(user_reporting_settings_->GetInteger(kSettingPath, &out_value));
  ASSERT_THAT(out_value, Eq(0));

  // Update setting value and ensure the next fetch returns the updated value.
  static constexpr int new_value = 1;
  profile_->GetPrefs()->SetInteger(kSettingPath, new_value);
  ASSERT_TRUE(user_reporting_settings_->GetInteger(kSettingPath, &out_value));
  EXPECT_THAT(out_value, Eq(new_value));
}

TEST_F(UserReportingSettingsTest, GetList) {
  profile_->GetTestingPrefService()->registry()->RegisterListPref(
      kSettingPath, /*default_value=*/base::Value::List());
  const base::Value::List* out_value;
  ASSERT_TRUE(user_reporting_settings_->GetList(kSettingPath, &out_value));
  ASSERT_THAT(out_value, NotNull());
  EXPECT_TRUE(out_value->empty());

  // Update setting value and ensure the next fetch returns the updated value.
  static constexpr char kListSettingItem[] = "item";
  profile_->GetPrefs()->SetList(kSettingPath,
                                base::Value::List().Append(kListSettingItem));
  ASSERT_TRUE(user_reporting_settings_->GetList(kSettingPath, &out_value));
  ASSERT_THAT(out_value, NotNull());
  ASSERT_THAT(out_value->size(), Eq(1uL));
  EXPECT_THAT(out_value->front().GetString(), Eq(kListSettingItem));
}

TEST_F(UserReportingSettingsTest, GetReportingEnabled_List) {
  profile_->GetTestingPrefService()->registry()->RegisterListPref(
      kSettingPath, /*default_value=*/base::Value::List());
  bool out_value = true;
  ASSERT_TRUE(
      user_reporting_settings_->GetReportingEnabled(kSettingPath, &out_value));
  EXPECT_FALSE(out_value);

  // Update setting value and ensure the next fetch returns the updated value.
  static constexpr char kListSettingItem[] = "item";
  profile_->GetPrefs()->SetList(kSettingPath,
                                base::Value::List().Append(kListSettingItem));
  ASSERT_TRUE(
      user_reporting_settings_->GetReportingEnabled(kSettingPath, &out_value));
  EXPECT_TRUE(out_value);
}

TEST_F(UserReportingSettingsTest, ObserveBooleanSetting) {
  profile_->GetTestingPrefService()->registry()->RegisterBooleanPref(
      kSettingPath, /*default_value=*/false);
  bool callback_called = false;
  const auto callback_subscription =
      user_reporting_settings_->AddSettingsObserver(
          kSettingPath, base::BindLambdaForTesting(
                            [&callback_called]() { callback_called = true; }));

  // Update setting value and ensure callback was triggered.
  profile_->GetPrefs()->SetBoolean(kSettingPath, true);
  ASSERT_TRUE(callback_called);
}

TEST_F(UserReportingSettingsTest, ObserveIntegerSetting) {
  profile_->GetTestingPrefService()->registry()->RegisterIntegerPref(
      kSettingPath, /*default_value=*/0);
  bool callback_called = false;
  const auto callback_subscription =
      user_reporting_settings_->AddSettingsObserver(
          kSettingPath, base::BindLambdaForTesting(
                            [&callback_called]() { callback_called = true; }));

  // Update setting value and ensure callback was triggered.
  profile_->GetPrefs()->SetInteger(kSettingPath, 1);
  ASSERT_TRUE(callback_called);
}

TEST_F(UserReportingSettingsTest, ObserveListSetting) {
  profile_->GetTestingPrefService()->registry()->RegisterListPref(
      kSettingPath, /*default_value=*/base::Value::List());
  bool callback_called = false;
  const auto callback_subscription =
      user_reporting_settings_->AddSettingsObserver(
          kSettingPath, base::BindLambdaForTesting(
                            [&callback_called]() { callback_called = true; }));

  // Update setting value and ensure callback was triggered.
  profile_->GetPrefs()->SetList(kSettingPath,
                                base::Value::List().Append("item"));
  ASSERT_TRUE(callback_called);
}

TEST_F(UserReportingSettingsTest, MultipleSettingObservers) {
  profile_->GetTestingPrefService()->registry()->RegisterBooleanPref(
      kSettingPath, /*default_value=*/false);
  int callback_trigger_count = 0;
  const auto callback_subscription_1 =
      user_reporting_settings_->AddSettingsObserver(
          kSettingPath, base::BindLambdaForTesting([&callback_trigger_count]() {
            callback_trigger_count++;
          }));
  const auto callback_subscription_2 =
      user_reporting_settings_->AddSettingsObserver(
          kSettingPath, base::BindLambdaForTesting([&callback_trigger_count]() {
            callback_trigger_count++;
          }));

  // Update setting value and ensure both callbacks were triggered.
  profile_->GetPrefs()->SetBoolean(kSettingPath, true);
  ASSERT_THAT(callback_trigger_count, Eq(2));
}

TEST_F(UserReportingSettingsTest, OnProfileDestruction) {
  profile_->GetTestingPrefService()->registry()->RegisterBooleanPref(
      kSettingPath, /*default_value=*/false);
  const auto callback_subscription =
      user_reporting_settings_->AddSettingsObserver(kSettingPath,
                                                    base::DoNothing());
  ASSERT_TRUE(
      user_reporting_settings_->IsObservingSettingsForTest(kSettingPath));

  // Delete profile and ensure the setting is no longer observed.
  profile_manager_.DeleteAllTestingProfiles();
  EXPECT_FALSE(
      user_reporting_settings_->IsObservingSettingsForTest(kSettingPath));
}

}  // namespace
}  // namespace reporting