chromium/components/feature_engagement/internal/chrome_variations_configuration_unittest.cc

// Copyright 2017 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/feature_engagement/internal/chrome_variations_configuration.h"

#include <map>
#include <string>
#include <vector>

#include "base/feature_list.h"
#include "base/metrics/field_trial.h"
#include "base/metrics/field_trial_param_associator.h"
#include "base/metrics/field_trial_params.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
#include "build/build_config.h"
#include "build/chromeos_buildflags.h"
#include "components/feature_engagement/public/configuration.h"
#include "components/feature_engagement/public/configuration_provider.h"
#include "components/feature_engagement/public/group_constants.h"
#include "components/feature_engagement/public/stats.h"
#include "components/feature_engagement/public/tracker.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace feature_engagement {

namespace {

BASE_FEATURE();
BASE_FEATURE();
BASE_FEATURE();

BASE_FEATURE();
BASE_FEATURE();
BASE_FEATURE();

const char kFooTrialName[] =;
const char kBarTrialName[] =;
const char kQuxTrialName[] =;
const char kGroupOneTrialName[] =;
const char kGroupTwoTrialName[] =;
const char kGroupThreeTrialName[] =;
const char kTrialGroupName[] =;
const char kConfigParseEventName[] =;

SessionRateImpact CreateSessionRateImpactExplicit(
    std::vector<std::string> affected_features) {}

BlockedBy CreateBlockedByExplicit(std::vector<std::string> affected_features) {}

#if BUILDFLAG(IS_CHROMEOS_ASH)
class TestConfigurationProvider : public ConfigurationProvider {
 public:
  TestConfigurationProvider() = default;
  ~TestConfigurationProvider() override = default;

  // ConfigurationProvider:
  bool MaybeProvideFeatureConfiguration(
      const base::Feature& feature,
      feature_engagement::FeatureConfig& config,
      const feature_engagement::FeatureVector& known_features,
      const feature_engagement::GroupVector& known_groups) const override {
    config = config_;
    return true;
  }

  const char* GetConfigurationSourceDescription() const override {
    return "Test Configuration Provider";
  }

  std::set<std::string> MaybeProvideAllowedEventPrefixes(
      const base::Feature& feature) const override {
    return {"TestEventPrefix"};
  }

  void SetConfig(const FeatureConfig& config) { config_ = config; }

 private:
  FeatureConfig config_;
};
#endif

class ChromeVariationsConfigurationTest : public ::testing::Test {};

}  // namespace

TEST_F(ChromeVariationsConfigurationTest,
       DisabledFeatureShouldHaveInvalidConfig) {}

TEST_F(ChromeVariationsConfigurationTest, ParseSingleFeature) {}

TEST_F(ChromeVariationsConfigurationTest, ParsePrefixedParamNames) {}

TEST_F(ChromeVariationsConfigurationTest,
       MultipleFeaturesWithPrefixedAndUnprefixedParams) {}

TEST_F(ChromeVariationsConfigurationTest, MissingUsedIsInvalid) {}

TEST_F(ChromeVariationsConfigurationTest, MissingTriggerIsInvalid) {}

TEST_F(ChromeVariationsConfigurationTest, OnlyTriggerAndUsedIsValid) {}

void RunBlockedByTest(ChromeVariationsConfigurationTest* test,
                      ChromeVariationsConfiguration* configuration,
                      std::vector<const base::Feature*> features,
                      std::string blocked_by_param_value,
                      BlockedBy expected_blocked_by,
                      bool is_valid) {}

TEST_F(ChromeVariationsConfigurationTest, ParseBlockingNone) {}

TEST_F(ChromeVariationsConfigurationTest, ParseBlockingAll) {}

TEST_F(ChromeVariationsConfigurationTest, ParseInvalidBlockingParams) {}

TEST_F(ChromeVariationsConfigurationTest, ParseBlockedByAll) {}

TEST_F(ChromeVariationsConfigurationTest, ParseBlockedByNone) {}

TEST_F(ChromeVariationsConfigurationTest, ParseBlockedByExplicitSelf) {}

TEST_F(ChromeVariationsConfigurationTest, ParseBlockedByExplicitOther) {}

TEST_F(ChromeVariationsConfigurationTest, ParseBlockedByExplicitMultiple) {}

TEST_F(ChromeVariationsConfigurationTest, ParseBlockedByExplicitEmpty) {}

TEST_F(ChromeVariationsConfigurationTest, ParseBlockedByExplicitOnlySeparator) {}

TEST_F(ChromeVariationsConfigurationTest,
       ParseBlockedByExplicitUnknownFeature) {}

TEST_F(ChromeVariationsConfigurationTest, ParseBlockedByExplicitAll) {}

void RunSessionRateImpactTest(ChromeVariationsConfigurationTest* test,
                              ChromeVariationsConfiguration* configuration,
                              std::vector<const base::Feature*> features,
                              std::string session_rate_impact_param_value,
                              SessionRateImpact expected_impact,
                              bool is_valid) {}

TEST_F(ChromeVariationsConfigurationTest, SessionRateImpactAll) {}

TEST_F(ChromeVariationsConfigurationTest, SessionRateImpactNone) {}

TEST_F(ChromeVariationsConfigurationTest, SessionRateImpactExplicitSelf) {}

TEST_F(ChromeVariationsConfigurationTest, SessionRateImpactExplicitOther) {}

TEST_F(ChromeVariationsConfigurationTest, SessionRateImpactExplicitMultiple) {}

TEST_F(ChromeVariationsConfigurationTest,
       SessionRateImpactExplicitAtLeastOneValidFeature) {}

TEST_F(ChromeVariationsConfigurationTest,
       SessionRateImpactExplicitAtLeastOneValidFeaturePlusEmpty) {}

void TestInvalidSessionRateImpactParamValue(
    ChromeVariationsConfigurationTest* test,
    ChromeVariationsConfiguration* configuration,
    std::string session_rate_impact_param_value,
    uint32_t parse_errors,
    uint32_t unknown_features) {}

TEST_F(ChromeVariationsConfigurationTest, SessionRateImpactExplicitEmpty) {}

TEST_F(ChromeVariationsConfigurationTest,
       SessionRateImpactExplicitEmptyWhitespace) {}

TEST_F(ChromeVariationsConfigurationTest,
       SessionRateImpactExplicitOnlySeparator) {}

TEST_F(ChromeVariationsConfigurationTest,
       SessionRateImpactExplicitOnlySeparatorWhitespace) {}

TEST_F(ChromeVariationsConfigurationTest,
       SessionRateImpactExplicitOnlyUnknownFeature) {}

TEST_F(ChromeVariationsConfigurationTest,
       SessionRateImpactExplicitOnlyMultipleUnknownFeatures) {}

TEST_F(ChromeVariationsConfigurationTest,
       SessionRateImpactExplicitOnlyUnknownFeaturePlusEmpty) {}

TEST_F(ChromeVariationsConfigurationTest,
       SessionRateImpactExplicitInvalidFeatureNameAllFirst) {}

TEST_F(ChromeVariationsConfigurationTest,
       SessionRateImpactExplicitInvalidFeatureNameAllLast) {}

TEST_F(ChromeVariationsConfigurationTest,
       SessionRateImpactExplicitInvalidFeatureNameAllLastInvalidFirst) {}

TEST_F(ChromeVariationsConfigurationTest,
       SessionRateImpactExplicitInvalidFeatureNameNoneFirst) {}

TEST_F(ChromeVariationsConfigurationTest,
       SessionRateImpactExplicitInvalidFeatureNameNoneLast) {}

TEST_F(ChromeVariationsConfigurationTest,
       SessionRateImpactExplicitInvalidFeatureNameNoneLastInvalidFirst) {}

TEST_F(ChromeVariationsConfigurationTest,
       SessionRateImpactExplicitInvalidFeatureNameFromCodeReview) {}

void RunGroupsTest(ChromeVariationsConfigurationTest* test,
                   ChromeVariationsConfiguration* configuration,
                   FeatureVector features,
                   GroupVector groups,
                   std::string groups_param_value,
                   std::vector<std::string> expected_groups,
                   bool is_valid) {}

TEST_F(ChromeVariationsConfigurationTest, ParseGroupsItem) {}

TEST_F(ChromeVariationsConfigurationTest, ParseGroupsMultiple) {}

TEST_F(ChromeVariationsConfigurationTest, ParseGroupsEmpty) {}

TEST_F(ChromeVariationsConfigurationTest, ParseGroupsOnlySeparator) {}

TEST_F(ChromeVariationsConfigurationTest, ParseGroupsUnknownGroup) {}

TEST_F(ChromeVariationsConfigurationTest,
       ParseGroupsCombinationKnownAndUnknownGroups) {}

TEST_F(ChromeVariationsConfigurationTest, WhitespaceIsValid) {}

TEST_F(ChromeVariationsConfigurationTest, IgnoresInvalidConfigKeys) {}

TEST_F(ChromeVariationsConfigurationTest, IgnoresInvalidEventConfigTokens) {}

TEST_F(ChromeVariationsConfigurationTest,
       MissingAllEventConfigParamsIsInvalid) {}

TEST_F(ChromeVariationsConfigurationTest,
       MissingEventEventConfigParamIsInvalid) {}

TEST_F(ChromeVariationsConfigurationTest,
       MissingComparatorEventConfigParamIsInvalid) {}

TEST_F(ChromeVariationsConfigurationTest,
       MissingWindowEventConfigParamIsInvalid) {}

TEST_F(ChromeVariationsConfigurationTest,
       MissingStorageEventConfigParamIsInvalid) {}

TEST_F(ChromeVariationsConfigurationTest,
       EventSpecifiedMultipleTimesIsInvalid) {}

TEST_F(ChromeVariationsConfigurationTest,
       ComparatorSpecifiedMultipleTimesIsInvalid) {}

TEST_F(ChromeVariationsConfigurationTest,
       WindowSpecifiedMultipleTimesIsInvalid) {}

TEST_F(ChromeVariationsConfigurationTest,
       StorageSpecifiedMultipleTimesIsInvalid) {}

TEST_F(ChromeVariationsConfigurationTest,
       InvalidSessionRateCausesInvalidConfig) {}

TEST_F(ChromeVariationsConfigurationTest,
       InvalidAvailabilityCausesInvalidConfig) {}

TEST_F(ChromeVariationsConfigurationTest, InvalidUsedCausesInvalidConfig) {}

TEST_F(ChromeVariationsConfigurationTest, InvalidTriggerCausesInvalidConfig) {}

TEST_F(ChromeVariationsConfigurationTest,
       InvalidEventConfigCausesInvalidConfig) {}

TEST_F(ChromeVariationsConfigurationTest,
       InvalidTrackingOnlyCausesInvalidConfig) {}

void RunTrackingOnlyTest(ChromeVariationsConfigurationTest* test,
                         ChromeVariationsConfiguration* configuration,
                         std::vector<const base::Feature*> features,
                         std::string tracking_only_definition,
                         bool expected_value,
                         bool is_valid) {}

TEST_F(ChromeVariationsConfigurationTest, TrackingOnlyReturnsTrue) {}

TEST_F(ChromeVariationsConfigurationTest,
       TrackingOnlyReturnsTrueCaseInsensitive) {}

TEST_F(ChromeVariationsConfigurationTest, TrackingOnlyReturnsFalse) {}

TEST_F(ChromeVariationsConfigurationTest,
       TrackingOnlyReturnsFalseCaseInsensitive) {}

TEST_F(ChromeVariationsConfigurationTest, AllComparatorTypesWork) {}

TEST_F(ChromeVariationsConfigurationTest, MultipleEventsWithSameName) {}

TEST_F(ChromeVariationsConfigurationTest, ParseMultipleFeatures) {}

TEST_F(ChromeVariationsConfigurationTest, CheckedInConfigIsReadable) {}

TEST_F(ChromeVariationsConfigurationTest,
       CheckedInConfigButDisabledFeatureIsInvalid) {}

TEST_F(ChromeVariationsConfigurationTest, NonExistingConfigIsInvalid) {}

TEST_F(ChromeVariationsConfigurationTest, ParseValidSnoozeParams) {}

TEST_F(ChromeVariationsConfigurationTest, UnorderedSnoozeParams) {}

TEST_F(ChromeVariationsConfigurationTest, InvalidMaxLimitSnoozeParams) {}

TEST_F(ChromeVariationsConfigurationTest, InvalidIntervalSnoozeParams) {}

TEST_F(ChromeVariationsConfigurationTest, IncompleteSnoozeParams) {}

TEST_F(ChromeVariationsConfigurationTest,
       DisabledGroupShouldHaveInvalidConfig) {}

TEST_F(ChromeVariationsConfigurationTest, ParseSingleGroup) {}

TEST_F(ChromeVariationsConfigurationTest, EmptyGroupIsInvalid) {}

TEST_F(ChromeVariationsConfigurationTest, GroupOnlyTriggerIsValid) {}

TEST_F(ChromeVariationsConfigurationTest, GroupIgnoresInvalidConfigKeys) {}

TEST_F(ChromeVariationsConfigurationTest,
       GroupInvalidSessionRateCausesInvalidConfig) {}

TEST_F(ChromeVariationsConfigurationTest,
       GroupInvalidTriggerCausesInvalidConfig) {}

TEST_F(ChromeVariationsConfigurationTest,
       GroupInvalidEventConfigCausesInvalidConfig) {}

TEST_F(ChromeVariationsConfigurationTest, GroupMultipleEventsWithSameName) {}

TEST_F(ChromeVariationsConfigurationTest, ParseMultipleGroups) {}

TEST_F(ChromeVariationsConfigurationTest, CheckedInGroupConfigIsReadable) {}

TEST_F(ChromeVariationsConfigurationTest,
       CheckedInGroupConfigButDisabledGroupIsInvalid) {}

TEST_F(ChromeVariationsConfigurationTest, NonExistingGroupConfigIsInvalid) {}

TEST_F(ChromeVariationsConfigurationTest,
       ParseExpandsBlockedByGroupNameIntoFeatures) {}

TEST_F(ChromeVariationsConfigurationTest,
       ParseExpandsBlockedByEmptyGroupIntoEmptyList) {}

TEST_F(ChromeVariationsConfigurationTest,
       ParseExpandsBlockedByGroupAndFeature) {}

TEST_F(ChromeVariationsConfigurationTest, ParseExpandsBlockedByMultipleGroups) {}

TEST_F(ChromeVariationsConfigurationTest,
       ParseExpandsBlockedByFeatureAppearsMultipleTimes) {}

TEST_F(ChromeVariationsConfigurationTest,
       ParseExpandsSessionRateImpactGroupNameIntoFeatures) {}

TEST_F(ChromeVariationsConfigurationTest,
       ParseExpandsSessionRateEmptyGroupIntoEmptyList) {}

#if BUILDFLAG(IS_CHROMEOS_ASH)
TEST_F(ChromeVariationsConfigurationTest, UpdateConfigs) {
  FeatureConfig expected_foo;
  expected_foo.valid = true;
  expected_foo.used =
      EventConfig("page_download_started", Comparator(ANY, 0), 0, 360);
  expected_foo.trigger =
      EventConfig("opened_chrome_home", Comparator(ANY, 0), 0, 360);
  expected_foo.event_configs.insert(EventConfig(
      "user_has_seen_dino", Comparator(GREATER_THAN_OR_EQUAL, 1), 120, 180));
  expected_foo.event_configs.insert(EventConfig(
      "user_opened_app_menu", Comparator(LESS_THAN_OR_EQUAL, 0), 120, 180));
  expected_foo.event_configs.insert(
      EventConfig("user_opened_downloads_home", Comparator(ANY, 0), 0, 360));

  auto provider = std::make_unique<TestConfigurationProvider>();
  provider->SetConfig(expected_foo);
  configuration_.UpdateConfig(kChromeTestFeatureFoo, provider.get());

  FeatureConfig foo = configuration_.GetFeatureConfig(kChromeTestFeatureFoo);
  EXPECT_EQ(expected_foo, foo);

  // Update config, removing `event_1` and `event_3`.
  expected_foo = FeatureConfig();
  expected_foo.valid = true;
  expected_foo.used =
      EventConfig("page_download_started", Comparator(ANY, 0), 0, 360);
  expected_foo.trigger =
      EventConfig("opened_chrome_home", Comparator(ANY, 0), 0, 360);
  expected_foo.event_configs.insert(EventConfig(
      "user_opened_app_menu", Comparator(LESS_THAN_OR_EQUAL, 0), 120, 180));
  EXPECT_NE(expected_foo, foo);

  provider->SetConfig(expected_foo);
  configuration_.UpdateConfig(kChromeTestFeatureFoo, provider.get());

  foo = configuration_.GetFeatureConfig(kChromeTestFeatureFoo);
  EXPECT_EQ(expected_foo, foo);
}

TEST_F(ChromeVariationsConfigurationTest, GetEventPrefixes) {
  ConfigurationProviderList providers;
  providers.emplace_back(std::make_unique<TestConfigurationProvider>());
  configuration_.LoadConfigs(providers, /*features=*/{&kChromeTestFeatureFoo},
                             /*groups=*/{});

  const auto& prefixes = configuration_.GetRegisteredAllowedEventPrefixes();
  EXPECT_EQ(1u, prefixes.size());
  EXPECT_TRUE(prefixes.contains("TestEventPrefix"));
}
#endif

}  // namespace feature_engagement