910e62b5创建于 1月15日历史提交
// Copyright 2024 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "components/attribution_reporting/attribution_scopes_data.h"

#include <optional>

#include "base/test/gmock_expected_support.h"
#include "base/test/values_test_util.h"
#include "base/types/expected.h"
#include "base/values.h"
#include "components/attribution_reporting/attribution_scopes_set.h"
#include "components/attribution_reporting/constants.h"
#include "components/attribution_reporting/source_registration_error.mojom.h"
#include "components/attribution_reporting/test_utils.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace attribution_reporting {
namespace {

using ::attribution_reporting::mojom::SourceRegistrationError;
using ::base::test::ErrorIs;
using ::base::test::ValueIs;
using ::testing::AllOf;
using ::testing::Property;

TEST(AttributionScopesDataTest, Parse) {
  const struct {
    const char* desc;
    const char* json;
    ::testing::Matcher<
        base::expected<AttributionScopesData, SourceRegistrationError>>
        matches;
  } kTestCases[] = {
      {
          "wrong_type",
          R"json([])json",
          ErrorIs(SourceRegistrationError::kAttributionScopesInvalid),
      },
      {
          "empty",
          R"json({})json",
          ErrorIs(SourceRegistrationError::kAttributionScopeLimitRequired),
      },
      {
          "scope_limit_only",
          R"json({"limit": 1})json",
          ErrorIs(SourceRegistrationError::kAttributionScopesListInvalid),
      },
      {
          "scope_limit_wrong_type",
          R"json({
            "limit": "1"
          })json",
          ErrorIs(SourceRegistrationError::kAttributionScopeLimitInvalid),
      },
      {
          "scope_limit_zero",
          R"json({
            "limit": 0
          })json",
          ErrorIs(SourceRegistrationError::kAttributionScopeLimitInvalid),
      },
      {
          "scope_limit_double",
          R"json({
            "limit": 1.5
          })json",
          ErrorIs(SourceRegistrationError::kAttributionScopeLimitInvalid),
      },
      {
          "scope_limit_negative",
          R"json({
            "limit": -1
          })json",
          ErrorIs(SourceRegistrationError::kAttributionScopeLimitInvalid),
      },
      {
          "scope_limit_uint32_max",
          R"json({
            "limit": 4294967295,
            "values": ["1"]
          })json",
          ValueIs(*AttributionScopesData::Create(
              AttributionScopesSet({"1"}),
              /*attribution_scope_limit=*/std::numeric_limits<uint32_t>::max(),
              /*max_event_states=*/kDefaultMaxEventStates)),
      },
      {
          "scope_limit_greater_than_uint32",
          R"json({
            "limit": 4294967296
          })json",
          ErrorIs(SourceRegistrationError::kAttributionScopeLimitInvalid),
      },
      {
          "scopes_wrong_type",
          R"json({
            "limit": 1,
            "values": "1"
          })json",
          ErrorIs(SourceRegistrationError::kAttributionScopesListInvalid),
      },
      {
          "scope_limit_and_scopes",
          R"json({
            "limit": 1,
            "values": ["1"]
          })json",
          ValueIs(*AttributionScopesData::Create(AttributionScopesSet({"1"}),
                                                 /*attribution_scope_limit=*/1u,
                                                 kDefaultMaxEventStates)),
      },
      {
          "empty_scopes",
          R"json({
            "limit": 1,
            "values": []
          })json",
          ErrorIs(SourceRegistrationError::kAttributionScopesListInvalid),
      },
      {
          "scopes_exceed_limit",
          R"json({
            "limit": 1,
            "values": ["1", "2"]
          })json",
          ErrorIs(SourceRegistrationError::kAttributionScopesListInvalid),
      },
      {
          "event_states_wrong_type",
          R"json({
            "limit": 1,
            "max_event_states": "1"
          })json",
          ErrorIs(SourceRegistrationError::kMaxEventStatesInvalid),
      },
      {
          "event_states_zero",
          R"json({
            "limit": 1,
            "max_event_states": 0
          })json",
          ErrorIs(SourceRegistrationError::kMaxEventStatesInvalid),
      },
      {
          "event_states_double",
          R"json({
            "limit": 1,
            "max_event_states": 1.5
          })json",
          ErrorIs(SourceRegistrationError::kMaxEventStatesInvalid),
      },
      {
          "event_states_negative",
          R"json({
            "limit": 1,
            "max_event_states": -1
          })json",
          ErrorIs(SourceRegistrationError::kMaxEventStatesInvalid),
      },
      {
          "event_states_uint32_max",
          R"json({
            "limit": 1,
            "max_event_states": 4294967295,
            "values": ["1"]
          })json",
          ValueIs(*AttributionScopesData::Create(
              AttributionScopesSet({"1"}), /*attribution_scope_limit=*/1u,
              /*max_event_states=*/std::numeric_limits<uint32_t>::max())),
      },
      {
          "event_states_greater_than_uint32",
          R"json({
            "limit": 1,
            "max_event_states": 4294967296
          })json",
          ErrorIs(SourceRegistrationError::kMaxEventStatesInvalid),
      },
      {
          "all_fields",
          R"json({
            "limit": 1,
            "max_event_states": 1,
            "values": ["1"]
          })json",
          ValueIs(*AttributionScopesData::Create(AttributionScopesSet({"1"}),
                                                 /*attribution_scope_limit=*/1u,
                                                 /*max_event_states=*/1u)),
      },
  };

  for (const auto& test_case : kTestCases) {
    SCOPED_TRACE(test_case.desc);
    base::Value value = base::test::ParseJson(test_case.json);
    EXPECT_THAT(AttributionScopesData::FromJSON(value), test_case.matches);
  }
}

TEST(AttributionScopesDataTest, Serialize) {
  const struct {
    AttributionScopesData input;
    const char* expected_json;
  } kTestCases[] = {
      {
          *AttributionScopesData::Create(AttributionScopesSet({"foo"}),
                                         /*attribution_scope_limit=*/1u,
                                         /*max_event_states=*/1u),
          R"json({
            "limit": 1,
            "max_event_states": 1,
            "values": ["foo"]
          })json",
      },
  };

  for (const auto& test_case : kTestCases) {
    EXPECT_THAT(test_case.input.ToJson(),
                base::test::IsJson(test_case.expected_json));
  }
}

}  // namespace
}  // namespace attribution_reporting