chromium/chrome/browser/extensions/api/enterprise_reporting_private/enterprise_reporting_private_unittest.cc

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

#ifdef UNSAFE_BUFFERS_BUILD
// TODO(crbug.com/40285824): Remove this and convert code to safer constructs.
#pragma allow_unsafe_buffers
#endif

#include "chrome/common/extensions/api/enterprise_reporting_private.h"

#include <tuple>

#include "base/command_line.h"
#include "base/environment.h"
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/json/json_writer.h"
#include "base/memory/raw_ptr.h"
#include "build/build_config.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/enterprise/identifiers/profile_id_service_factory.h"
#include "chrome/browser/enterprise/signals/device_info_fetcher.h"
#include "chrome/browser/enterprise/signals/signals_common.h"
#include "chrome/browser/extensions/api/enterprise_reporting_private/chrome_desktop_report_request_helper.h"
#include "chrome/browser/extensions/api/enterprise_reporting_private/enterprise_reporting_private_api.h"
#include "chrome/browser/extensions/extension_api_unittest.h"
#include "chrome/browser/extensions/test_extension_system.h"
#include "chrome/browser/net/stub_resolver_config_reader.h"
#include "chrome/browser/policy/dm_token_utils.h"
#include "chrome/browser/prefs/browser_prefs.h"
#include "chrome/common/pref_names.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/component_updater/pref_names.h"
#include "components/enterprise/browser/controller/fake_browser_dm_token_storage.h"
#include "components/enterprise/browser/identifiers/profile_id_service.h"
#include "components/enterprise/connectors/core/connectors_prefs.h"
#include "components/policy/core/common/policy_pref_names.h"
#include "components/policy/core/common/policy_types.h"
#include "components/reporting/proto/synced/record.pb.h"
#include "components/safe_browsing/core/common/safe_browsing_prefs.h"
#include "components/version_info/version_info.h"
#include "extensions/browser/api_test_utils.h"
#include "extensions/browser/extension_function_dispatcher.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"

#if BUILDFLAG(IS_CHROMEOS)
#include "chromeos/dbus/missive/fake_missive_client.h"
#include "chromeos/dbus/missive/missive_client.h"
#include "components/reporting/proto/synced/record_constants.pb.h"
#include "components/reporting/util/status.h"
#endif

#if BUILDFLAG(IS_WIN)
#include <windows.h>

#include <netfw.h>
#include <shlobj.h>
#include <wrl/client.h>

#include "base/test/test_reg_util_win.h"
#endif  // BUILDFLAG(IS_WIN)

#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX)
#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
#include "chrome/browser/enterprise/signals/signals_aggregator_factory.h"
#include "components/device_signals/core/browser/mock_signals_aggregator.h"  // nogncheck
#include "components/device_signals/core/browser/signals_aggregator.h"  // nogncheck
#include "components/device_signals/core/browser/signals_types.h"  // nogncheck
#include "components/device_signals/core/browser/user_context.h"   // nogncheck
#include "components/device_signals/core/common/common_types.h"    // nogncheck
#include "components/device_signals/core/common/signals_constants.h"  // nogncheck
#include "components/device_signals/core/common/signals_features.h"  // nogncheck
#endif  // BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX)

#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
#include "base/nix/xdg_util.h"
#endif

enterprise_reporting_private;

SettingValue;
_;
Eq;
Invoke;
IsEmpty;
SizeIs;
StrEq;
WithArgs;

namespace extensions {

std::unique_ptr<KeyedService> CreateProfileIDService(
    content::BrowserContext* context) {}

#if BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || \
    BUILDFLAG(IS_LINUX)

constexpr char kNoError[] =;

#endif  // BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) ||
        // BUILDFLAG(IS_LINUX)

#if !BUILDFLAG(IS_CHROMEOS)

namespace {

constexpr char kFakeClientId[] =;

}  // namespace

// Test for API enterprise.reportingPrivate.getDeviceId
class EnterpriseReportingPrivateGetDeviceIdTest : public ExtensionApiUnittest {};

TEST_F(EnterpriseReportingPrivateGetDeviceIdTest, GetDeviceId) {}

TEST_F(EnterpriseReportingPrivateGetDeviceIdTest, DeviceIdNotExist) {}

// Test for API enterprise.reportingPrivate.getDeviceId
class EnterpriseReportingPrivateDeviceDataFunctionsTest
    : public ExtensionApiUnittest {};

TEST_F(EnterpriseReportingPrivateDeviceDataFunctionsTest, StoreDeviceData) {}

TEST_F(EnterpriseReportingPrivateDeviceDataFunctionsTest, DeviceDataMissing) {}

TEST_F(EnterpriseReportingPrivateDeviceDataFunctionsTest, DeviceBadId) {}

TEST_F(EnterpriseReportingPrivateDeviceDataFunctionsTest, RetrieveDeviceData) {}

// TODO(pastarmovj): Remove once implementation for the other platform exists.
#if BUILDFLAG(IS_WIN)

// Test for API enterprise.reportingPrivate.getDeviceId
class EnterpriseReportingPrivateGetPersistentSecretFunctionTest
    : public ExtensionApiUnittest {
 public:
  EnterpriseReportingPrivateGetPersistentSecretFunctionTest() = default;

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

  void SetUp() override {
    ExtensionApiUnittest::SetUp();
#if BUILDFLAG(IS_WIN)
    ASSERT_NO_FATAL_FAILURE(
        registry_override_manager_.OverrideRegistry(HKEY_CURRENT_USER));
#endif
  }

 private:
#if BUILDFLAG(IS_WIN)
  registry_util::RegistryOverrideManager registry_override_manager_;
#endif
};

TEST_F(EnterpriseReportingPrivateGetPersistentSecretFunctionTest, GetSecret) {
  auto function = base::MakeRefCounted<
      EnterpriseReportingPrivateGetPersistentSecretFunction>();
  std::optional<base::Value> result1 =
      RunFunctionAndReturnValue(function.get(), "[]");
  ASSERT_TRUE(result1);
  ASSERT_TRUE(result1->is_blob());
  auto generated_blob = result1->GetBlob();

  // Re-running should not change the secret.
  auto function2 = base::MakeRefCounted<
      EnterpriseReportingPrivateGetPersistentSecretFunction>();
  std::optional<base::Value> result2 =
      RunFunctionAndReturnValue(function2.get(), "[]");
  ASSERT_TRUE(result2);
  ASSERT_TRUE(result2->is_blob());
  ASSERT_EQ(generated_blob, result2->GetBlob());

  // Re-running should not change the secret even when force recreate is set.
  auto function3 = base::MakeRefCounted<
      EnterpriseReportingPrivateGetPersistentSecretFunction>();
  std::optional<base::Value> result3 =
      RunFunctionAndReturnValue(function3.get(), "[true]");
  ASSERT_TRUE(result3);
  ASSERT_TRUE(result3->is_blob());
  ASSERT_EQ(generated_blob, result3->GetBlob());

  const wchar_t kDefaultRegistryPath[] =
      L"SOFTWARE\\Google\\Endpoint Verification";
  const wchar_t kValueName[] = L"Safe Storage";

  base::win::RegKey key;
  ASSERT_EQ(ERROR_SUCCESS,
            key.Create(HKEY_CURRENT_USER, kDefaultRegistryPath, KEY_WRITE));
  // Mess up with the value.
  ASSERT_EQ(ERROR_SUCCESS, key.WriteValue(kValueName, 1337));

  // Re-running with no recreate enforcement should return an error.
  auto function4 = base::MakeRefCounted<
      EnterpriseReportingPrivateGetPersistentSecretFunction>();
  std::string error = RunFunctionAndReturnError(function4.get(), "[]");
  ASSERT_FALSE(error.empty());

  // Re=running should not change the secret even when force recreate is set.
  auto function5 = base::MakeRefCounted<
      EnterpriseReportingPrivateGetPersistentSecretFunction>();
  std::optional<base::Value> result5 =
      RunFunctionAndReturnValue(function5.get(), "[true]");
  ASSERT_TRUE(result5);
  ASSERT_TRUE(result5->is_blob());
  ASSERT_NE(generated_blob, result5->GetBlob());
}

#endif  // BUILDFLAG(IS_WIN)

EnterpriseReportingPrivateGetDeviceInfoTest;

TEST_F(EnterpriseReportingPrivateGetDeviceInfoTest, GetDeviceInfo) {}

TEST_F(EnterpriseReportingPrivateGetDeviceInfoTest, GetDeviceInfoConversion) {}

#endif  // !BUILDFLAG(IS_CHROMEOS)

class EnterpriseReportingPrivateGetContextInfoTest
    : public ExtensionApiUnittest {};

TEST_F(EnterpriseReportingPrivateGetContextInfoTest, NoSpecialContext) {}

#if BUILDFLAG(IS_WIN) && BUILDFLAG(GOOGLE_CHROME_BRANDING)
class EnterpriseReportingPrivateGetContextInfoThirdPartyBlockingTest
    : public EnterpriseReportingPrivateGetContextInfoTest,
      public testing::WithParamInterface<bool> {};

TEST_P(EnterpriseReportingPrivateGetContextInfoThirdPartyBlockingTest, Test) {
  bool policyValue = GetParam();

  g_browser_process->local_state()->SetBoolean(
      prefs::kThirdPartyBlockingEnabled, policyValue);

  enterprise_reporting_private::ContextInfo info = GetContextInfo();

  EXPECT_TRUE(info.browser_affiliation_ids.empty());
  EXPECT_TRUE(info.profile_affiliation_ids.empty());
  EXPECT_TRUE(info.on_file_attached_providers.empty());
  EXPECT_TRUE(info.on_file_downloaded_providers.empty());
  EXPECT_TRUE(info.on_bulk_data_entry_providers.empty());
  EXPECT_EQ(enterprise_reporting_private::RealtimeUrlCheckMode::kDisabled,
            info.realtime_url_check_mode);
  EXPECT_TRUE(info.on_security_event_providers.empty());
  EXPECT_EQ(version_info::GetVersionNumber(), info.browser_version);
  EXPECT_EQ(enterprise_reporting_private::SafeBrowsingLevel::kStandard,
            info.safe_browsing_protection_level);
  EXPECT_EQ(BuiltInDnsClientPlatformDefault(),
            info.built_in_dns_client_enabled);
  EXPECT_FALSE(info.chrome_remote_desktop_app_blocked);
  EXPECT_EQ(policyValue, *info.third_party_blocking_enabled);
}

INSTANTIATE_TEST_SUITE_P(
    ,
    EnterpriseReportingPrivateGetContextInfoThirdPartyBlockingTest,
    testing::Bool());
#endif  // BUILDFLAG(IS_WIN) && BUILDFLAG(GOOGLE_CHROME_BRANDING)

class EnterpriseReportingPrivateGetContextInfoSafeBrowsingTest
    : public EnterpriseReportingPrivateGetContextInfoTest,
      public testing::WithParamInterface<std::tuple<bool, bool>> {};

TEST_P(EnterpriseReportingPrivateGetContextInfoSafeBrowsingTest, Test) {}

INSTANTIATE_TEST_SUITE_P();

class EnterpriseReportingPrivateGetContextInfoBuiltInDnsClientTest
    : public EnterpriseReportingPrivateGetContextInfoTest,
      public testing::WithParamInterface<bool> {};

TEST_P(EnterpriseReportingPrivateGetContextInfoBuiltInDnsClientTest, Test) {}

INSTANTIATE_TEST_SUITE_P();

class EnterpriseReportingPrivateGetContextPasswordProtectionWarningTrigger
    : public EnterpriseReportingPrivateGetContextInfoTest,
      public testing::WithParamInterface<
          enterprise_reporting_private::PasswordProtectionTrigger> {};

TEST_P(EnterpriseReportingPrivateGetContextPasswordProtectionWarningTrigger,
       Test) {}

INSTANTIATE_TEST_SUITE_P();

#if BUILDFLAG(IS_LINUX)
class EnterpriseReportingPrivateGetContextOSFirewallLinuxTest
    : public EnterpriseReportingPrivateGetContextInfoTest,
      public testing::WithParamInterface<
          enterprise_reporting_private::SettingValue> {};

TEST_F(EnterpriseReportingPrivateGetContextOSFirewallLinuxTest,
       NoFirewallFile) {}

TEST_F(EnterpriseReportingPrivateGetContextOSFirewallLinuxTest, NoEnabledKey) {}

TEST_P(EnterpriseReportingPrivateGetContextOSFirewallLinuxTest, Test) {}

INSTANTIATE_TEST_SUITE_P();
#endif  // BUILDFLAG(IS_LINUX)

class EnterpriseReportingPrivateGetContextInfoChromeRemoteDesktopAppBlockedTest
    : public EnterpriseReportingPrivateGetContextInfoTest,
      public testing::WithParamInterface<const char*> {};

TEST_P(
    EnterpriseReportingPrivateGetContextInfoChromeRemoteDesktopAppBlockedTest,
    BlockedURL) {}

TEST_P(
    EnterpriseReportingPrivateGetContextInfoChromeRemoteDesktopAppBlockedTest,
    AllowedURL) {}

TEST_P(
    EnterpriseReportingPrivateGetContextInfoChromeRemoteDesktopAppBlockedTest,
    BlockedAndAllowedURL) {}

INSTANTIATE_TEST_SUITE_P();

#if BUILDFLAG(IS_WIN)
class EnterpriseReportingPrivateGetContextInfoOSFirewallTest
    : public EnterpriseReportingPrivateGetContextInfoTest,
      public testing::WithParamInterface<SettingValue> {
 public:
  EnterpriseReportingPrivateGetContextInfoOSFirewallTest()
      : enabled_(VARIANT_TRUE) {}

 protected:
  void SetUp() override {
    if (!::IsUserAnAdmin()) {
      // INetFwPolicy2::put_FirewallEnabled fails for non-admin users.
      GTEST_SKIP() << "This test must be run by an admin user";
    }
    EnterpriseReportingPrivateGetContextInfoTest::SetUp();
    HRESULT hr = CoCreateInstance(CLSID_NetFwPolicy2, nullptr, CLSCTX_ALL,
                                  IID_PPV_ARGS(&firewall_policy_));
    EXPECT_GE(hr, 0);

    long profile_types = 0;
    hr = firewall_policy_->get_CurrentProfileTypes(&profile_types);
    EXPECT_GE(hr, 0);

    // Setting the firewall for each active profile
    const NET_FW_PROFILE_TYPE2 kProfileTypes[] = {NET_FW_PROFILE2_PUBLIC,
                                                  NET_FW_PROFILE2_PRIVATE,
                                                  NET_FW_PROFILE2_DOMAIN};
    for (size_t i = 0; i < std::size(kProfileTypes); ++i) {
      if ((profile_types & kProfileTypes[i]) != 0) {
        hr = firewall_policy_->get_FirewallEnabled(kProfileTypes[i], &enabled_);
        EXPECT_GE(hr, 0);
        active_profile_ = kProfileTypes[i];
        hr = firewall_policy_->put_FirewallEnabled(
            kProfileTypes[i], firewall_value_ == SettingValue::ENABLED
                                  ? VARIANT_TRUE
                                  : VARIANT_FALSE);
        EXPECT_GE(hr, 0);
        break;
      }
    }
  }

  void TearDown() override {
    if (!::IsUserAnAdmin()) {
      // Test already skipped in `SetUp`.
      return;
    }
    // Resetting the firewall to its initial state
    HRESULT hr =
        firewall_policy_->put_FirewallEnabled(active_profile_, enabled_);
    EXPECT_GE(hr, 0);
    EnterpriseReportingPrivateGetContextInfoTest::TearDown();
  }

  extensions::api::enterprise_reporting_private::SettingValue
  ToInfoSettingValue(enterprise_signals::SettingValue value) {
    switch (value) {
      case SettingValue::DISABLED:
        return extensions::api::enterprise_reporting_private::SettingValue::
            kDisabled;
      case SettingValue::ENABLED:
        return extensions::api::enterprise_reporting_private::SettingValue::
            kEnabled;
      default:
        NOTREACHED_IN_MIGRATION();
        return extensions::api::enterprise_reporting_private::SettingValue::
            kUnknown;
    }
  }
  Microsoft::WRL::ComPtr<INetFwPolicy2> firewall_policy_;
  SettingValue firewall_value_ = GetParam();
  VARIANT_BOOL enabled_;
  NET_FW_PROFILE_TYPE2 active_profile_;
};

TEST_P(EnterpriseReportingPrivateGetContextInfoOSFirewallTest, Test) {
  enterprise_reporting_private::ContextInfo info = GetContextInfo();

  EXPECT_TRUE(info.browser_affiliation_ids.empty());
  EXPECT_TRUE(info.profile_affiliation_ids.empty());
  EXPECT_TRUE(info.on_file_attached_providers.empty());
  EXPECT_TRUE(info.on_file_downloaded_providers.empty());
  EXPECT_TRUE(info.on_bulk_data_entry_providers.empty());
  EXPECT_EQ(enterprise_reporting_private::RealtimeUrlCheckMode::kDisabled,
            info.realtime_url_check_mode);
  EXPECT_TRUE(info.on_security_event_providers.empty());
  EXPECT_EQ(version_info::GetVersionNumber(), info.browser_version);
  EXPECT_EQ(enterprise_reporting_private::SafeBrowsingLevel::kStandard,
            info.safe_browsing_protection_level);
  EXPECT_EQ(BuiltInDnsClientPlatformDefault(),
            info.built_in_dns_client_enabled);
  EXPECT_EQ(
      enterprise_reporting_private::PasswordProtectionTrigger::kPolicyUnset,
      info.password_protection_warning_trigger);
  EXPECT_FALSE(info.chrome_remote_desktop_app_blocked);
  ExpectDefaultThirdPartyBlockingEnabled(info);
  EXPECT_EQ(ToInfoSettingValue(firewall_value_), info.os_firewall);
  EXPECT_TRUE(info.enterprise_profile_id);
}

INSTANTIATE_TEST_SUITE_P(,
                         EnterpriseReportingPrivateGetContextInfoOSFirewallTest,
                         testing::Values(SettingValue::DISABLED,
                                         SettingValue::ENABLED));

#endif  // BUILDFLAG(IS_WIN)

class EnterpriseReportingPrivateGetContextInfoRealTimeURLCheckTest
    : public EnterpriseReportingPrivateGetContextInfoTest,
      public testing::WithParamInterface<bool> {};

INSTANTIATE_TEST_SUITE_P();

TEST_P(EnterpriseReportingPrivateGetContextInfoRealTimeURLCheckTest, Test) {}

#if BUILDFLAG(IS_CHROMEOS)

// Test for API enterprise.reportingPrivate.enqueueRecord
class EnterpriseReportingPrivateEnqueueRecordFunctionTest
    : public ExtensionApiUnittest {
 protected:
  static constexpr char kTestDMTokenValue[] = "test_dm_token_value";

  EnterpriseReportingPrivateEnqueueRecordFunctionTest() = default;

  void SetUp() override {
    ExtensionApiUnittest::SetUp();
    ::chromeos::MissiveClient::InitializeFake();
    function_ =
        base::MakeRefCounted<EnterpriseReportingPrivateEnqueueRecordFunction>();
    const auto record = GetTestRecord();
    serialized_record_data_.resize(record.ByteSizeLong());
    ASSERT_TRUE(record.SerializeToArray(serialized_record_data_.data(),
                                        serialized_record_data_.size()));
  }

  void TearDown() override {
    function_.reset();
    ::chromeos::MissiveClient::Shutdown();
    ExtensionApiUnittest::TearDown();
  }

  ::reporting::Record GetTestRecord() const {
    base::Value::Dict data;
    data.Set("TEST_KEY", base::Value("TEST_VALUE"));
    std::string serialized_data;
    DCHECK(base::JSONWriter::Write(data, &serialized_data));

    ::reporting::Record record;
    record.set_data(serialized_data);
    record.set_destination(::reporting::Destination::TELEMETRY_METRIC);
    record.set_timestamp_us(base::Time::Now().InMillisecondsSinceUnixEpoch() *
                            base::Time::kMicrosecondsPerMillisecond);

    return record;
  }

  void VerifyNoRecordsEnqueued(::reporting::Priority priority =
                                   ::reporting::Priority::BACKGROUND_BATCH) {
    ::chromeos::MissiveClient::TestInterface* const missive_test_interface =
        ::chromeos::MissiveClient::Get()->GetTestInterface();
    ASSERT_TRUE(missive_test_interface);

    const std::vector<::reporting::Record>& records =
        missive_test_interface->GetEnqueuedRecords(priority);

    ASSERT_THAT(records, IsEmpty());
  }

  std::vector<uint8_t> serialized_record_data_;
  scoped_refptr<extensions::EnterpriseReportingPrivateEnqueueRecordFunction>
      function_;
};

TEST_F(EnterpriseReportingPrivateEnqueueRecordFunctionTest,
       ValidRecordSuccessfullyEnqueued) {
  function_->SetProfileIsAffiliatedForTesting(/*is_affiliated=*/true);

  api::enterprise_reporting_private::EnqueueRecordRequest
      enqueue_record_request;
  enqueue_record_request.record_data = serialized_record_data_;
  enqueue_record_request.priority = ::reporting::Priority::BACKGROUND_BATCH;
  enqueue_record_request.event_type =
      api::enterprise_reporting_private::EventType::kUser;

  base::Value::List params;
  params.Append(enqueue_record_request.ToValue());

  // Set up DM token
  const auto dm_token = policy::DMToken::CreateValidToken(kTestDMTokenValue);
  policy::SetDMTokenForTesting(dm_token);

  api_test_utils::RunFunction(
      function_.get(), std::move(params),
      std::make_unique<ExtensionFunctionDispatcher>(profile()),
      extensions::api_test_utils::FunctionMode::kNone);
  EXPECT_EQ(function_->GetError(), kNoError);

  ::chromeos::MissiveClient::TestInterface* const missive_test_interface =
      ::chromeos::MissiveClient::Get()->GetTestInterface();
  ASSERT_TRUE(missive_test_interface);

  const std::vector<::reporting::Record>& background_batch_records =
      missive_test_interface->GetEnqueuedRecords(
          ::reporting::Priority::BACKGROUND_BATCH);

  ASSERT_THAT(background_batch_records, SizeIs(1));
  EXPECT_THAT(background_batch_records[0].destination(),
              Eq(::reporting::Destination::TELEMETRY_METRIC));
  EXPECT_THAT(background_batch_records[0].dm_token(), StrEq(dm_token.value()));
  EXPECT_THAT(background_batch_records[0].data(),
              StrEq(GetTestRecord().data()));
}

TEST_F(EnterpriseReportingPrivateEnqueueRecordFunctionTest,
       InvalidPriorityReturnsError) {
  function_->SetProfileIsAffiliatedForTesting(true);

  api::enterprise_reporting_private::EnqueueRecordRequest
      enqueue_record_request;
  enqueue_record_request.record_data = serialized_record_data_;

  // Set priority to invalid enum value
  enqueue_record_request.priority = -1;

  enqueue_record_request.event_type =
      api::enterprise_reporting_private::EventType::kUser;

  base::Value::List params;
  params.Append(enqueue_record_request.ToValue());

  policy::SetDMTokenForTesting(
      policy::DMToken::CreateValidToken(kTestDMTokenValue));

  api_test_utils::RunFunction(
      function_.get(), std::move(params),
      std::make_unique<ExtensionFunctionDispatcher>(profile()),
      extensions::api_test_utils::FunctionMode::kNone);

  EXPECT_EQ(function_->GetError(),
            EnterpriseReportingPrivateEnqueueRecordFunction::
                kErrorInvalidEnqueueRecordRequest);

  VerifyNoRecordsEnqueued();
}

TEST_F(EnterpriseReportingPrivateEnqueueRecordFunctionTest,
       NonAffiliatedUserReturnsError) {
  function_->SetProfileIsAffiliatedForTesting(false);

  api::enterprise_reporting_private::EnqueueRecordRequest
      enqueue_record_request;
  enqueue_record_request.record_data = serialized_record_data_;

  enqueue_record_request.priority = ::reporting::Priority::BACKGROUND_BATCH;

  enqueue_record_request.event_type =
      api::enterprise_reporting_private::EventType::kUser;

  base::Value::List params;
  params.Append(enqueue_record_request.ToValue());

  policy::SetDMTokenForTesting(
      policy::DMToken::CreateValidToken(kTestDMTokenValue));

  api_test_utils::RunFunction(
      function_.get(), std::move(params),
      std::make_unique<ExtensionFunctionDispatcher>(profile()),
      extensions::api_test_utils::FunctionMode::kNone);

  EXPECT_EQ(function_->GetError(),
            EnterpriseReportingPrivateEnqueueRecordFunction::
                kErrorProfileNotAffiliated);

  VerifyNoRecordsEnqueued();
}

TEST_F(EnterpriseReportingPrivateEnqueueRecordFunctionTest,
       InvalidDMTokenReturnsError) {
  function_->SetProfileIsAffiliatedForTesting(true);
  api::enterprise_reporting_private::EnqueueRecordRequest
      enqueue_record_request;
  enqueue_record_request.record_data = serialized_record_data_;
  enqueue_record_request.priority = ::reporting::Priority::BACKGROUND_BATCH;
  enqueue_record_request.event_type =
      api::enterprise_reporting_private::EventType::kUser;

  base::Value::List params;
  params.Append(enqueue_record_request.ToValue());

  // Set up invalid DM token
  policy::SetDMTokenForTesting(policy::DMToken::CreateInvalidToken());

  api_test_utils::RunFunction(
      function_.get(), std::move(params),
      std::make_unique<ExtensionFunctionDispatcher>(profile()),
      extensions::api_test_utils::FunctionMode::kNone);

  EXPECT_EQ(function_->GetError(),
            EnterpriseReportingPrivateEnqueueRecordFunction::
                kErrorCannotAssociateRecordWithUser);

  VerifyNoRecordsEnqueued();
}

TEST_F(EnterpriseReportingPrivateEnqueueRecordFunctionTest,
       InvalidRecordWithMissingTimestampReturnsError) {
  function_->SetProfileIsAffiliatedForTesting(true);
  api::enterprise_reporting_private::EnqueueRecordRequest
      enqueue_record_request;
  // Clear timestamp from test record and set up serialized record
  auto record = GetTestRecord();
  record.clear_timestamp_us();
  serialized_record_data_.clear();
  serialized_record_data_.resize(record.ByteSizeLong());
  ASSERT_TRUE(record.SerializeToArray(serialized_record_data_.data(),
                                      serialized_record_data_.size()));
  enqueue_record_request.record_data = serialized_record_data_;
  enqueue_record_request.priority = ::reporting::Priority::BACKGROUND_BATCH;
  enqueue_record_request.event_type =
      api::enterprise_reporting_private::EventType::kUser;

  base::Value::List params;
  params.Append(enqueue_record_request.ToValue());

  // Set up invalid DM token
  policy::SetDMTokenForTesting(
      policy::DMToken::CreateValidToken(kTestDMTokenValue));

  api_test_utils::RunFunction(
      function_.get(), std::move(params),
      std::make_unique<ExtensionFunctionDispatcher>(profile()),
      extensions::api_test_utils::FunctionMode::kNone);

  EXPECT_EQ(function_->GetError(),
            EnterpriseReportingPrivateEnqueueRecordFunction::
                kErrorInvalidEnqueueRecordRequest);

  VerifyNoRecordsEnqueued();
}
#endif  // BUILDFLAG(IS_CHROMEOS)

#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX)

namespace {

constexpr char kFakeUserId[] =;

enterprise_reporting_private::UserContext GetFakeUserContext() {}

std::unique_ptr<KeyedService> BuildMockAggregator(
    content::BrowserContext* context) {}

}  // namespace

// Base test class for APIs that require a UserContext parameter and which will
// make use of the SignalsAggregator to retrieve device signals.
class UserContextGatedTest : public ExtensionApiUnittest {};

// Tests for API enterprise.reportingPrivate.getFileSystemInfo
class EnterpriseReportingPrivateGetFileSystemInfoTest
    : public UserContextGatedTest {};

TEST_F(EnterpriseReportingPrivateGetFileSystemInfoTest, Success) {}

TEST_F(EnterpriseReportingPrivateGetFileSystemInfoTest, TopLevelError) {}

TEST_F(EnterpriseReportingPrivateGetFileSystemInfoTest, CollectionError) {}

class EnterpriseReportingPrivateGetFileSystemInfoDisabledTest
    : public EnterpriseReportingPrivateGetFileSystemInfoTest {};

TEST_F(EnterpriseReportingPrivateGetFileSystemInfoDisabledTest,
       FlagDisabled_Test) {}

#endif  // BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX)

#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC)

// Tests for API enterprise.reportingPrivate.getSettings
class EnterpriseReportingPrivateGetSettingsTest : public UserContextGatedTest {
 protected:
  void SetUp() override {
    UserContextGatedTest::SetUp();

    SetFeatureFlag();

    function_ =
        base::MakeRefCounted<EnterpriseReportingPrivateGetSettingsFunction>();
  }

  device_signals::SignalName signal_name() {
    return device_signals::SignalName::kSystemSettings;
  }

  enterprise_reporting_private::GetSettingsOptions GetFakeSettingsOptionsParam()
      const {
    enterprise_reporting_private::GetSettingsOptions api_param;
    api_param.path = "some path";
    api_param.key = "some key";
    api_param.get_value = true;

    api_param.hive =
        enterprise_reporting_private::RegistryHive::kHkeyCurrentUser;

    return api_param;
  }

  std::string GetFakeRequest() const {
    enterprise_reporting_private::GetSettingsRequest request;
    request.user_context = GetFakeUserContext();
    request.options.push_back(GetFakeSettingsOptionsParam());
    base::Value::List params;
    params.Append(request.ToValue());
    std::string json_value;
    base::JSONWriter::Write(params, &json_value);
    return json_value;
  }

  scoped_refptr<extensions::EnterpriseReportingPrivateGetSettingsFunction>
      function_;
};

TEST_F(EnterpriseReportingPrivateGetSettingsTest, Success) {
  device_signals::SettingsItem fake_settings_item;
  fake_settings_item.path = "fake path";
  fake_settings_item.key = "fake key";
  fake_settings_item.presence = device_signals::PresenceValue::kFound;
  std::string setting_json_value = "123";
  fake_settings_item.setting_json_value = setting_json_value;
  fake_settings_item.hive = device_signals::RegistryHive::kHkeyCurrentUser;

  device_signals::SettingsResponse signal_response;
  signal_response.settings_items.push_back(fake_settings_item);

  device_signals::SignalsAggregationResponse expected_response;
  expected_response.settings_response = signal_response;

  SetFakeResponse(expected_response);

  auto response = api_test_utils::RunFunctionAndReturnSingleResult(
      function_.get(), GetFakeRequest(), profile());

  EXPECT_EQ(function_->GetError(), kNoError);

  ASSERT_TRUE(response);
  ASSERT_TRUE(response->is_list());
  const base::Value::List& list_value = response->GetList();
  ASSERT_EQ(list_value.size(), signal_response.settings_items.size());

  const base::Value& settings_value = list_value.front();
  ASSERT_TRUE(settings_value.is_dict());
  auto parsed_settings_signal =
      enterprise_reporting_private::GetSettingsResponse::FromValue(
          settings_value.GetDict());
  ASSERT_TRUE(parsed_settings_signal);
  EXPECT_EQ(parsed_settings_signal->path, fake_settings_item.path);
  EXPECT_EQ(parsed_settings_signal->presence,
            enterprise_reporting_private::PresenceValue::kFound);
  ASSERT_TRUE(parsed_settings_signal->value);
  EXPECT_EQ(parsed_settings_signal->value.value(), setting_json_value);

  ASSERT_NE(parsed_settings_signal->hive,
            enterprise_reporting_private::RegistryHive::kNone);
  EXPECT_EQ(parsed_settings_signal->hive,
            enterprise_reporting_private::RegistryHive::kHkeyCurrentUser);

  histogram_tester_.ExpectUniqueSample(
      "Enterprise.DeviceSignals.Collection.Request.SystemSettings.Items", 1, 1);
  histogram_tester_.ExpectUniqueSample(
      "Enterprise.DeviceSignals.Collection.SystemSettings.Delta", 0, 1);
  histogram_tester_.ExpectUniqueSample(
      "Enterprise.DeviceSignals.Collection.Success", signal_name(), 1);
  histogram_tester_.ExpectUniqueSample(
      "Enterprise.DeviceSignals.Collection.Success.SystemSettings.Items",
      /*number_of_items=*/1,
      /*number_of_occurrences=*/1);
  histogram_tester_.ExpectTotalCount(
      "Enterprise.DeviceSignals.Collection.Success.SystemSettings.Latency", 1);

  histogram_tester_.ExpectTotalCount(
      "Enterprise.DeviceSignals.Collection.Failure", 0);
  histogram_tester_.ExpectTotalCount(
      "Enterprise.DeviceSignals.Collection.Failure.SystemSettings.Latency", 0);
}

TEST_F(EnterpriseReportingPrivateGetSettingsTest, TopLevelError) {
  device_signals::SignalCollectionError expected_error =
      device_signals::SignalCollectionError::kConsentRequired;

  device_signals::SignalsAggregationResponse expected_response;
  expected_response.top_level_error = expected_error;
  SetFakeResponse(expected_response);

  auto error = api_test_utils::RunFunctionAndReturnError(
      function_.get(), GetFakeRequest(), profile());

  EXPECT_EQ(error, function_->GetError());
  EXPECT_EQ(error, device_signals::ErrorToString(expected_error));

  histogram_tester_.ExpectUniqueSample(
      "Enterprise.DeviceSignals.Collection.Request.SystemSettings.Items", 1, 1);
  histogram_tester_.ExpectUniqueSample(
      "Enterprise.DeviceSignals.Collection.Failure", signal_name(), 1);
  histogram_tester_.ExpectUniqueSample(
      "Enterprise.DeviceSignals.Collection.Failure.SystemSettings."
      "TopLevelError",
      /*error=*/expected_error,
      /*number_of_occurrences=*/1);
  histogram_tester_.ExpectTotalCount(
      "Enterprise.DeviceSignals.Collection.Failure.SystemSettings.Latency", 1);

  histogram_tester_.ExpectTotalCount(
      "Enterprise.DeviceSignals.Collection.Success", 0);
  histogram_tester_.ExpectTotalCount(
      "Enterprise.DeviceSignals.Collection.Success.SystemSettings.Latency", 0);
  histogram_tester_.ExpectTotalCount(
      "Enterprise.DeviceSignals.Collection.SystemSettings.Delta", 0);
}

TEST_F(EnterpriseReportingPrivateGetSettingsTest, CollectionError) {
  device_signals::SignalCollectionError expected_error =
      device_signals::SignalCollectionError::kMissingSystemService;

  device_signals::SettingsResponse signal_response;
  signal_response.collection_error = expected_error;

  device_signals::SignalsAggregationResponse expected_response;
  expected_response.settings_response = signal_response;
  SetFakeResponse(expected_response);

  auto error = api_test_utils::RunFunctionAndReturnError(
      function_.get(), GetFakeRequest(), profile());

  EXPECT_EQ(error, function_->GetError());
  EXPECT_EQ(error, device_signals::ErrorToString(expected_error));

  histogram_tester_.ExpectUniqueSample(
      "Enterprise.DeviceSignals.Collection.Request.SystemSettings.Items", 1, 1);
  histogram_tester_.ExpectUniqueSample(
      "Enterprise.DeviceSignals.Collection.Failure", signal_name(), 1);
  histogram_tester_.ExpectUniqueSample(
      "Enterprise.DeviceSignals.Collection.Failure.SystemSettings."
      "CollectionLevelError",
      /*error=*/expected_error,
      /*number_of_occurrences=*/1);
  histogram_tester_.ExpectTotalCount(
      "Enterprise.DeviceSignals.Collection.Failure.SystemSettings.Latency", 1);

  histogram_tester_.ExpectTotalCount(
      "Enterprise.DeviceSignals.Collection.Success", 0);
  histogram_tester_.ExpectTotalCount(
      "Enterprise.DeviceSignals.Collection.Success.SystemSettings.Latency", 0);
  histogram_tester_.ExpectTotalCount(
      "Enterprise.DeviceSignals.Collection.SystemSettings.Delta", 0);
}

class EnterpriseReportingPrivateGetSettingsDisabledTest
    : public EnterpriseReportingPrivateGetSettingsTest {
 protected:
  // Overwrite this function to disable the feature flag for tests using this
  // specific fixture.
  void SetFeatureFlag() override {
    scoped_features_.InitAndEnableFeatureWithParameters(
        enterprise_signals::features::kNewEvSignalsEnabled,
        {{"DisableSettings", "true"}});
  }
};

TEST_F(EnterpriseReportingPrivateGetSettingsDisabledTest, FlagDisabled_Test) {
  auto error = api_test_utils::RunFunctionAndReturnError(
      function_.get(), GetFakeRequest(), profile());
  EXPECT_EQ(error, function_->GetError());
  EXPECT_EQ(error, device_signals::ErrorToString(
                       device_signals::SignalCollectionError::kUnsupported));
}

#endif  // BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC)

#if BUILDFLAG(IS_WIN)

std::string GetFakeUserContextJsonParams() {
  auto user_context = GetFakeUserContext();
  base::Value::List params;
  params.Append(user_context.ToValue());
  std::string json_value;
  base::JSONWriter::Write(params, &json_value);
  return json_value;
}

// Tests for API enterprise.reportingPrivate.getAvInfo
class EnterpriseReportingPrivateGetAvInfoTest : public UserContextGatedTest {
 protected:
  void SetUp() override {
    UserContextGatedTest::SetUp();

    SetFeatureFlag();

    function_ =
        base::MakeRefCounted<EnterpriseReportingPrivateGetAvInfoFunction>();
  }

  device_signals::SignalName signal_name() {
    return device_signals::SignalName::kAntiVirus;
  }

  scoped_refptr<extensions::EnterpriseReportingPrivateGetAvInfoFunction>
      function_;
};

TEST_F(EnterpriseReportingPrivateGetAvInfoTest, Success) {
  device_signals::AvProduct fake_av_product;
  fake_av_product.display_name = "Fake display name";
  fake_av_product.state = device_signals::AvProductState::kOff;
  fake_av_product.product_id = "fake product id";

  device_signals::AntiVirusSignalResponse av_response;
  av_response.av_products.push_back(fake_av_product);

  device_signals::SignalsAggregationResponse expected_response;
  expected_response.av_signal_response = av_response;

  SetFakeResponse(expected_response);

  auto response = api_test_utils::RunFunctionAndReturnSingleResult(
      function_.get(), GetFakeUserContextJsonParams(), profile());

  EXPECT_EQ(function_->GetError(), kNoError);

  ASSERT_TRUE(response);
  ASSERT_TRUE(response->is_list());
  const base::Value::List& list_value = response->GetList();
  ASSERT_EQ(list_value.size(), av_response.av_products.size());

  const base::Value& av_value = list_value.front();
  ASSERT_TRUE(av_value.is_dict());
  auto parsed_av_signal =
      enterprise_reporting_private::AntiVirusSignal::FromValue(
          av_value.GetDict());
  ASSERT_TRUE(parsed_av_signal);
  EXPECT_EQ(parsed_av_signal->display_name, fake_av_product.display_name);
  EXPECT_EQ(parsed_av_signal->state,
            enterprise_reporting_private::AntiVirusProductState::kOff);
  EXPECT_EQ(parsed_av_signal->product_id, fake_av_product.product_id);

  histogram_tester_.ExpectUniqueSample(
      "Enterprise.DeviceSignals.Collection.Success", signal_name(), 1);
  histogram_tester_.ExpectUniqueSample(
      "Enterprise.DeviceSignals.Collection.Success.AntiVirus.Items",
      /*number_of_items=*/1,
      /*number_of_occurrences=*/1);
  histogram_tester_.ExpectTotalCount(
      "Enterprise.DeviceSignals.Collection.Success.AntiVirus.Latency", 1);

  histogram_tester_.ExpectTotalCount(
      "Enterprise.DeviceSignals.Collection.Failure", 0);
  histogram_tester_.ExpectTotalCount(
      "Enterprise.DeviceSignals.Collection.Failure.AntiVirus.Latency", 0);
}

TEST_F(EnterpriseReportingPrivateGetAvInfoTest, TopLevelError) {
  device_signals::SignalCollectionError expected_error =
      device_signals::SignalCollectionError::kConsentRequired;

  device_signals::SignalsAggregationResponse expected_response;
  expected_response.top_level_error = expected_error;
  SetFakeResponse(expected_response);

  auto error = api_test_utils::RunFunctionAndReturnError(
      function_.get(), GetFakeUserContextJsonParams(), profile());

  EXPECT_EQ(error, function_->GetError());
  EXPECT_EQ(error, device_signals::ErrorToString(expected_error));

  histogram_tester_.ExpectUniqueSample(
      "Enterprise.DeviceSignals.Collection.Failure", signal_name(), 1);
  histogram_tester_.ExpectUniqueSample(
      "Enterprise.DeviceSignals.Collection.Failure.AntiVirus.TopLevelError",
      /*error=*/expected_error,
      /*number_of_occurrences=*/1);
  histogram_tester_.ExpectTotalCount(
      "Enterprise.DeviceSignals.Collection.Failure.AntiVirus.Latency", 1);

  histogram_tester_.ExpectTotalCount(
      "Enterprise.DeviceSignals.Collection.Success", 0);
  histogram_tester_.ExpectTotalCount(
      "Enterprise.DeviceSignals.Collection.Success.AntiVirus.Latency", 0);
}

TEST_F(EnterpriseReportingPrivateGetAvInfoTest, CollectionError) {
  device_signals::SignalCollectionError expected_error =
      device_signals::SignalCollectionError::kMissingSystemService;

  device_signals::AntiVirusSignalResponse av_response;
  av_response.collection_error = expected_error;

  device_signals::SignalsAggregationResponse expected_response;
  expected_response.av_signal_response = av_response;
  SetFakeResponse(expected_response);

  auto error = api_test_utils::RunFunctionAndReturnError(
      function_.get(), GetFakeUserContextJsonParams(), profile());

  EXPECT_EQ(error, function_->GetError());
  EXPECT_EQ(error, device_signals::ErrorToString(expected_error));

  histogram_tester_.ExpectUniqueSample(
      "Enterprise.DeviceSignals.Collection.Failure", signal_name(), 1);
  histogram_tester_.ExpectUniqueSample(
      "Enterprise.DeviceSignals.Collection.Failure.AntiVirus."
      "CollectionLevelError",
      /*error=*/expected_error,
      /*number_of_occurrences=*/1);
  histogram_tester_.ExpectTotalCount(
      "Enterprise.DeviceSignals.Collection.Failure.AntiVirus.Latency", 1);

  histogram_tester_.ExpectTotalCount(
      "Enterprise.DeviceSignals.Collection.Success", 0);
  histogram_tester_.ExpectTotalCount(
      "Enterprise.DeviceSignals.Collection.Success.AntiVirus.Latency", 0);
}

class EnterpriseReportingPrivateGetAvInfoDisabledTest
    : public EnterpriseReportingPrivateGetAvInfoTest {
 protected:
  // Overwrite this function to disable the feature flag for tests using this
  // specific fixture.
  void SetFeatureFlag() override {
    scoped_features_.InitAndEnableFeatureWithParameters(
        enterprise_signals::features::kNewEvSignalsEnabled,
        {{"DisableAntiVirus", "true"}});
  }
};

TEST_F(EnterpriseReportingPrivateGetAvInfoDisabledTest, FlagDisabled_Test) {
  auto error = api_test_utils::RunFunctionAndReturnError(
      function_.get(), GetFakeUserContextJsonParams(), profile());
  EXPECT_EQ(error, function_->GetError());
  EXPECT_EQ(error, device_signals::ErrorToString(
                       device_signals::SignalCollectionError::kUnsupported));
}

// Tests for API enterprise.reportingPrivate.getHotfixes
class EnterpriseReportingPrivateGetHotfixesTest : public UserContextGatedTest {
 protected:
  void SetUp() override {
    UserContextGatedTest::SetUp();

    SetFeatureFlag();

    function_ =
        base::MakeRefCounted<EnterpriseReportingPrivateGetHotfixesFunction>();
  }

  device_signals::SignalName signal_name() {
    return device_signals::SignalName::kHotfixes;
  }

  scoped_refptr<extensions::EnterpriseReportingPrivateGetHotfixesFunction>
      function_;
};

TEST_F(EnterpriseReportingPrivateGetHotfixesTest, Success) {
  static constexpr char kFakeHotfixId[] = "hotfix id";
  device_signals::HotfixSignalResponse hotfix_response;
  hotfix_response.hotfixes.push_back({kFakeHotfixId});

  device_signals::SignalsAggregationResponse expected_response;
  expected_response.hotfix_signal_response = hotfix_response;

  SetFakeResponse(expected_response);

  auto response = api_test_utils::RunFunctionAndReturnSingleResult(
      function_.get(), GetFakeUserContextJsonParams(), profile());

  EXPECT_EQ(function_->GetError(), kNoError);

  ASSERT_TRUE(response);
  ASSERT_TRUE(response->is_list());
  const base::Value::List& list_value = response->GetList();
  ASSERT_EQ(list_value.size(), hotfix_response.hotfixes.size());

  const base::Value& hotfix_value = list_value.front();
  ASSERT_TRUE(hotfix_value.is_dict());
  auto parsed_hotfix = enterprise_reporting_private::HotfixSignal::FromValue(
      hotfix_value.GetDict());
  ASSERT_TRUE(parsed_hotfix);
  EXPECT_EQ(parsed_hotfix->hotfix_id, kFakeHotfixId);

  histogram_tester_.ExpectUniqueSample(
      "Enterprise.DeviceSignals.Collection.Success", signal_name(), 1);
  histogram_tester_.ExpectUniqueSample(
      "Enterprise.DeviceSignals.Collection.Success.Hotfixes.Items",
      /*number_of_items=*/1,
      /*number_of_occurrences=*/1);
  histogram_tester_.ExpectTotalCount(
      "Enterprise.DeviceSignals.Collection.Success.Hotfixes.Latency", 1);

  histogram_tester_.ExpectTotalCount(
      "Enterprise.DeviceSignals.Collection.Failure", 0);
  histogram_tester_.ExpectTotalCount(
      "Enterprise.DeviceSignals.Collection.Failure.Hotfixes.Latency", 0);
}

TEST_F(EnterpriseReportingPrivateGetHotfixesTest, TopLevelError) {
  device_signals::SignalCollectionError expected_error =
      device_signals::SignalCollectionError::kConsentRequired;

  device_signals::SignalsAggregationResponse expected_response;
  expected_response.top_level_error = expected_error;
  SetFakeResponse(expected_response);

  auto error = api_test_utils::RunFunctionAndReturnError(
      function_.get(), GetFakeUserContextJsonParams(), profile());

  EXPECT_EQ(error, function_->GetError());
  EXPECT_EQ(error, device_signals::ErrorToString(expected_error));

  histogram_tester_.ExpectUniqueSample(
      "Enterprise.DeviceSignals.Collection.Failure", signal_name(), 1);
  histogram_tester_.ExpectUniqueSample(
      "Enterprise.DeviceSignals.Collection.Failure.Hotfixes.TopLevelError",
      /*error=*/expected_error,
      /*number_of_occurrences=*/1);
  histogram_tester_.ExpectTotalCount(
      "Enterprise.DeviceSignals.Collection.Failure.Hotfixes.Latency", 1);

  histogram_tester_.ExpectTotalCount(
      "Enterprise.DeviceSignals.Collection.Success", 0);
  histogram_tester_.ExpectTotalCount(
      "Enterprise.DeviceSignals.Collection.Success.Hotfixes.Latency", 0);
}

TEST_F(EnterpriseReportingPrivateGetHotfixesTest, CollectionError) {
  device_signals::SignalCollectionError expected_error =
      device_signals::SignalCollectionError::kMissingSystemService;

  device_signals::HotfixSignalResponse hotfix_response;
  hotfix_response.collection_error = expected_error;

  device_signals::SignalsAggregationResponse expected_response;
  expected_response.hotfix_signal_response = hotfix_response;
  SetFakeResponse(expected_response);

  auto error = api_test_utils::RunFunctionAndReturnError(
      function_.get(), GetFakeUserContextJsonParams(), profile());

  EXPECT_EQ(error, function_->GetError());
  EXPECT_EQ(error, device_signals::ErrorToString(expected_error));

  histogram_tester_.ExpectUniqueSample(
      "Enterprise.DeviceSignals.Collection.Failure", signal_name(), 1);
  histogram_tester_.ExpectUniqueSample(
      "Enterprise.DeviceSignals.Collection.Failure.Hotfixes."
      "CollectionLevelError",
      /*error=*/expected_error,
      /*number_of_occurrences=*/1);
  histogram_tester_.ExpectTotalCount(
      "Enterprise.DeviceSignals.Collection.Failure.Hotfixes.Latency", 1);

  histogram_tester_.ExpectTotalCount(
      "Enterprise.DeviceSignals.Collection.Success", 0);
  histogram_tester_.ExpectTotalCount(
      "Enterprise.DeviceSignals.Collection.Success.Hotfixes.Latency", 0);
}

class EnterpriseReportingPrivateGetHotfixesInfoDisabledTest
    : public EnterpriseReportingPrivateGetHotfixesTest {
 protected:
  // Overwrite this function to disable the feature flag for tests using this
  // specific fixture.
  void SetFeatureFlag() override {
    scoped_features_.InitAndEnableFeatureWithParameters(
        enterprise_signals::features::kNewEvSignalsEnabled,
        {{"DisableHotfix", "true"}});
  }
};

TEST_F(EnterpriseReportingPrivateGetHotfixesInfoDisabledTest,
       FlagDisabled_Test) {
  auto error = api_test_utils::RunFunctionAndReturnError(
      function_.get(), GetFakeUserContextJsonParams(), profile());
  EXPECT_EQ(error, function_->GetError());
  EXPECT_EQ(error, device_signals::ErrorToString(
                       device_signals::SignalCollectionError::kUnsupported));
}

#endif  // BUILDFLAG(IS_WIN)

}  // namespace extensions