chromium/components/variations/cros_evaluate_seed/early_boot_feature_visitor_unittest.cc

// 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/variations/cros_evaluate_seed/early_boot_feature_visitor.h"

#include <map>
#include <memory>
#include <string>

#include "base/feature_list.h"
#include "base/metrics/field_trial.h"
#include "base/test/scoped_feature_list.h"
#include "chromeos/ash/components/dbus/featured/featured.pb.h"
#include "early_boot_feature_visitor.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace variations::cros_early_boot::evaluate_seed {

namespace {

constexpr char kEarlyBootFeatureTestName[] = "CrOSEarlyBootTestFeature";
constexpr char kEarlyBootFeatureOffByDefaultName[] =
    "CrOSEarlyBootOffByDefault";
BASE_FEATURE(kEarlyBootFeatureOffByDefault,
             kEarlyBootFeatureOffByDefaultName,
             base::FEATURE_DISABLED_BY_DEFAULT);

}  // namespace

TEST(EarlyBootFeatureVisitor, FeatureWithNoFieldTrial) {
  base::test::ScopedFeatureList outer_scope;
  outer_scope.InitWithEmptyFeatureAndFieldTrialLists();

  base::test::ScopedFeatureList feature_list;
  feature_list.InitAndEnableFeature(kEarlyBootFeatureOffByDefault);

  EarlyBootFeatureVisitor visitor;
  base::FeatureList::VisitFeaturesAndParams(visitor);
  google::protobuf::RepeatedPtrField<featured::FeatureOverride> overrides =
      visitor.release_overrides();

  ASSERT_EQ(overrides.size(), 1);
  const featured::FeatureOverride& feature = overrides[0];
  EXPECT_EQ(feature.name(), kEarlyBootFeatureOffByDefaultName);
  EXPECT_EQ(feature.override_state(), featured::OVERRIDE_ENABLE_FEATURE);
  EXPECT_EQ(feature.trial_name(), "");
  EXPECT_EQ(feature.group_name(), "");
  EXPECT_EQ(feature.params_size(), 0);
}

TEST(EarlyBootFeatureVisitor, InvalidFeatureName) {
  base::test::ScopedFeatureList outer_scope;
  outer_scope.InitWithEmptyFeatureAndFieldTrialLists();

  auto feature_list = std::make_unique<base::FeatureList>();
  base::FieldTrial* trial =
      base::FieldTrialList::CreateFieldTrial("TrialExample", "A");
  feature_list->RegisterFieldTrialOverride(
      "FeatureNameWithoutCrOSEarlyBootPrefix",
      base::FeatureList::OverrideState::OVERRIDE_ENABLE_FEATURE, trial);

  base::test::ScopedFeatureList initialized_field_feature_list;
  initialized_field_feature_list.InitWithFeatureList(std::move(feature_list));

  EarlyBootFeatureVisitor visitor;
  base::FeatureList::VisitFeaturesAndParams(visitor);
  google::protobuf::RepeatedPtrField<featured::FeatureOverride> overrides =
      visitor.release_overrides();

  ASSERT_EQ(overrides.size(), 0);
}

TEST(EarlyBootFeatureVisitor, FeatureOverrideUseDefault) {
  base::test::ScopedFeatureList outer_scope;
  outer_scope.InitWithEmptyFeatureAndFieldTrialLists();

  auto feature_list = std::make_unique<base::FeatureList>();
  base::FieldTrial* trial =
      base::FieldTrialList::CreateFieldTrial("TrialExample", "A");
  feature_list->RegisterFieldTrialOverride(
      kEarlyBootFeatureTestName, base::FeatureList::OVERRIDE_USE_DEFAULT,
      trial);

  base::test::ScopedFeatureList initialized_field_feature_list;
  initialized_field_feature_list.InitWithFeatureList(std::move(feature_list));

  EarlyBootFeatureVisitor visitor;
  base::FeatureList::VisitFeaturesAndParams(visitor);
  google::protobuf::RepeatedPtrField<featured::FeatureOverride> overrides =
      visitor.release_overrides();

  ASSERT_EQ(overrides.size(), 1);
  const featured::FeatureOverride& feature = overrides[0];
  EXPECT_EQ(feature.name(), kEarlyBootFeatureTestName);
  EXPECT_EQ(feature.override_state(), featured::OVERRIDE_USE_DEFAULT);
  EXPECT_EQ(feature.trial_name(), "TrialExample");
  EXPECT_EQ(feature.group_name(), "A");
}

TEST(EarlyBootFeatureVisitor, FeatureOverrideUseDisabled) {
  base::test::ScopedFeatureList outer_scope;
  outer_scope.InitWithEmptyFeatureAndFieldTrialLists();

  auto feature_list = std::make_unique<base::FeatureList>();
  base::FieldTrial* trial =
      base::FieldTrialList::CreateFieldTrial("TrialExample", "A");
  feature_list->RegisterFieldTrialOverride(
      kEarlyBootFeatureTestName, base::FeatureList::OVERRIDE_DISABLE_FEATURE,
      trial);

  base::test::ScopedFeatureList initialized_field_feature_list;
  initialized_field_feature_list.InitWithFeatureList(std::move(feature_list));

  EarlyBootFeatureVisitor visitor;
  base::FeatureList::VisitFeaturesAndParams(visitor);
  google::protobuf::RepeatedPtrField<featured::FeatureOverride> overrides =
      visitor.release_overrides();

  ASSERT_EQ(overrides.size(), 1);
  const featured::FeatureOverride& feature = overrides[0];
  EXPECT_EQ(feature.name(), kEarlyBootFeatureTestName);
  EXPECT_EQ(feature.override_state(), featured::OVERRIDE_DISABLE_FEATURE);
  EXPECT_EQ(feature.trial_name(), "TrialExample");
  EXPECT_EQ(feature.group_name(), "A");
}

TEST(EarlyBootFeatureVisitor, FeatureOverrideUseEnabled) {
  base::test::ScopedFeatureList outer_scope;
  outer_scope.InitWithEmptyFeatureAndFieldTrialLists();

  auto feature_list = std::make_unique<base::FeatureList>();
  base::FieldTrial* trial =
      base::FieldTrialList::CreateFieldTrial("TrialExample", "A");
  feature_list->RegisterFieldTrialOverride(
      kEarlyBootFeatureTestName, base::FeatureList::OVERRIDE_ENABLE_FEATURE,
      trial);

  base::test::ScopedFeatureList initialized_field_feature_list;
  initialized_field_feature_list.InitWithFeatureList(std::move(feature_list));

  EarlyBootFeatureVisitor visitor;
  base::FeatureList::VisitFeaturesAndParams(visitor);
  google::protobuf::RepeatedPtrField<featured::FeatureOverride> overrides =
      visitor.release_overrides();

  ASSERT_EQ(overrides.size(), 1);
  const featured::FeatureOverride& feature = overrides[0];
  EXPECT_EQ(feature.name(), kEarlyBootFeatureTestName);
  EXPECT_EQ(feature.override_state(), featured::OVERRIDE_ENABLE_FEATURE);
  EXPECT_EQ(feature.trial_name(), "TrialExample");
  EXPECT_EQ(feature.group_name(), "A");
}

TEST(EarlyBootFeatureVisitor, FeatureHasParams) {
  base::test::ScopedFeatureList outer_scope;
  outer_scope.InitWithEmptyFeatureAndFieldTrialLists();

  base::test::ScopedFeatureList initialized_field_feature_list;

  initialized_field_feature_list.InitFromCommandLine(
      /*enabled_features=*/"CrOSEarlyBootTestFeature<foo.bar:k1/v1/k2/v2",
      /*disabled_features=*/"");

  EarlyBootFeatureVisitor visitor;
  base::FeatureList::VisitFeaturesAndParams(visitor);

  google::protobuf::RepeatedPtrField<featured::FeatureOverride> overrides =
      visitor.release_overrides();
  ASSERT_EQ(overrides.size(), 1);
  const featured::FeatureOverride& feature = overrides[0];
  EXPECT_EQ(feature.name(), kEarlyBootFeatureTestName);
  EXPECT_EQ(feature.override_state(), featured::OVERRIDE_ENABLE_FEATURE);
  EXPECT_EQ(feature.trial_name(), "foo");
  EXPECT_EQ(feature.group_name(), "bar");

  const std::map<std::string, std::string> expected_params = {{"k1", "v1"},
                                                              {"k2", "v2"}};
  std::map<std::string, std::string> actual_params;
  for (const auto& entry : feature.params()) {
    actual_params.insert({entry.key(), entry.value()});
  }
  EXPECT_EQ(actual_params, expected_params);
}

}  // namespace variations::cros_early_boot::evaluate_seed