#include "components/variations/service/variations_field_trial_creator.h"
#include <stddef.h>
#include <cstring>
#include <memory>
#include <string>
#include <utility>
#include <vector>
#include "base/base_switches.h"
#include "base/build_time.h"
#include "base/command_line.h"
#include "base/feature_list.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/functional/callback.h"
#include "base/functional/callback_helpers.h"
#include "base/memory/raw_ptr.h"
#include "base/metrics/field_trial_params.h"
#include "base/strings/strcat.h"
#include "base/strings/stringprintf.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/mock_entropy_provider.h"
#include "base/test/scoped_command_line.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/scoped_mock_clock_override.h"
#include "base/test/task_environment.h"
#include "base/time/time.h"
#include "base/version.h"
#include "build/branding_buildflags.h"
#include "build/build_config.h"
#include "components/metrics/clean_exit_beacon.h"
#include "components/metrics/client_info.h"
#include "components/metrics/metrics_service.h"
#include "components/metrics/metrics_state_manager.h"
#include "components/metrics/test/test_enabled_state_provider.h"
#include "components/prefs/testing_pref_service.h"
#include "components/variations/field_trial_config/field_trial_util.h"
#include "components/variations/limited_entropy_mode_gate.h"
#include "components/variations/platform_field_trials.h"
#include "components/variations/pref_names.h"
#include "components/variations/proto/variations_seed.pb.h"
#include "components/variations/scoped_variations_ids_provider.h"
#include "components/variations/service/buildflags.h"
#include "components/variations/service/limited_entropy_synthetic_trial.h"
#include "components/variations/service/safe_seed_manager.h"
#include "components/variations/service/variations_field_trial_creator_base.h"
#include "components/variations/service/variations_service.h"
#include "components/variations/service/variations_service_client.h"
#include "components/variations/synthetic_trial_registry.h"
#include "components/variations/synthetic_trials.h"
#include "components/variations/variations_safe_seed_store_local_state.h"
#include "components/variations/variations_seed_store.h"
#include "components/variations/variations_switches.h"
#include "components/variations/variations_test_utils.h"
#include "components/version_info/channel.h"
#include "components/version_info/version_info.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#if BUILDFLAG(IS_ANDROID)
#include "components/variations/seed_response.h"
#endif
namespace variations {
namespace {
_;
Ge;
NiceMock;
Return;
const char kTestSeedStudyName[] = …;
const char kTestLimitedLayerStudyName[] = …;
const char kTestSeedExperimentName[] = …;
const char kTestSafeSeedExperimentName[] = …;
const int kTestSeedExperimentProbability = …;
const char kTestSeedSerialNumber[] = …;
const char kTestSeedSerializedData[] = …;
const char kTestSeedSignature[] = …;
const int kTestSeedMilestone = …;
struct FetchAndLaunchTimeTestParams { … };
std::unique_ptr<VariationsSeedStore> CreateSeedStore(PrefService* local_state) { … }
VariationsSeed CreateTestSeed() { … }
VariationsSeed CreateTestSeedWithLimitedEntropyLayer() { … }
VariationsSeed CreateTestSeedWithLimitedEntropyLayerUsingExcessiveEntropy() { … }
VariationsSeed CreateTestSafeSeed() { … }
base::Time DistantPast() { … }
#if BUILDFLAG(IS_ANDROID)
const char kTestSeedCountry[] = "in";
VariationsSeed CreateTestSeedWithCountryFilter() {
VariationsSeed seed = CreateTestSeed();
Study* study = seed.mutable_study(0);
Study::Filter* filter = study->mutable_filter();
filter->add_country(kTestSeedCountry);
filter->add_platform(Study::PLATFORM_ANDROID);
return seed;
}
std::string SerializeSeed(const VariationsSeed& seed) {
std::string serialized_seed;
seed.SerializeToString(&serialized_seed);
return serialized_seed;
}
#endif
class MockSafeSeedManager : public SafeSeedManager { … };
class FakeSyntheticTrialObserver : public SyntheticTrialObserver { … };
class TestVariationsServiceClient : public VariationsServiceClient { … };
class TestLimitedEntropySyntheticTrial : public LimitedEntropySyntheticTrial { … };
class MockVariationsServiceClient : public TestVariationsServiceClient { … };
class TestVariationsSeedStore : public VariationsSeedStore { … };
class TestVariationsFieldTrialCreator : public VariationsFieldTrialCreator { … };
}
class FieldTrialCreatorTest : public ::testing::Test { … };
namespace {
class FieldTrialCreatorFetchAndLaunchTimeTest
: public FieldTrialCreatorTest,
public ::testing::WithParamInterface<FetchAndLaunchTimeTestParams> { … };
constexpr FetchAndLaunchTimeTestParams kAllFetchAndLaunchTimes[] = …;
}
INSTANTIATE_TEST_SUITE_P(…);
TEST_P(FieldTrialCreatorFetchAndLaunchTimeTest,
SetUpFieldTrials_ValidSeed_NotExpired) { … }
TEST_F(FieldTrialCreatorTest, SetUpFieldTrials_ValidSeed_NoLastFetchTime) { … }
TEST_F(FieldTrialCreatorTest, SetUpFieldTrials_ValidSeed_NoMilestone) { … }
TEST_F(FieldTrialCreatorTest, SetUpFieldTrials_ExpiredSeed) { … }
TEST_F(FieldTrialCreatorTest, SetUpFieldTrials_FutureMilestone) { … }
TEST_P(FieldTrialCreatorFetchAndLaunchTimeTest,
SetUpFieldTrials_ValidSafeSeed_NewBinaryUsesSeed) { … }
TEST_F(FieldTrialCreatorTest, SetUpFieldTrials_UnloadableSafeSeedNotUsed) { … }
TEST_F(FieldTrialCreatorTest, SetUpFieldTrials_ValidSafeSeed_NoLastFetchTime) { … }
TEST_F(FieldTrialCreatorTest, SetUpFieldTrials_ExpiredSafeSeed) { … }
TEST_F(FieldTrialCreatorTest, SetUpFieldTrials_SafeSeedForFutureMilestone) { … }
TEST_F(FieldTrialCreatorTest, SetUpFieldTrials_NullSeed) { … }
TEST_F(FieldTrialCreatorTest, LoadSeedFromTestSeedJsonPath) { … }
#if BUILDFLAG(IS_ANDROID)
TEST_F(FieldTrialCreatorTest, SetUpFieldTrials_LoadsCountryOnFirstRun) {
const base::Time one_day_ago = base::Time::Now() - base::Days(1);
auto initial_seed = std::make_unique<SeedResponse>();
initial_seed->data = SerializeSeed(CreateTestSeedWithCountryFilter());
initial_seed->signature = kTestSeedSignature;
initial_seed->country = kTestSeedCountry;
initial_seed->date = one_day_ago;
initial_seed->is_gzip_compressed = false;
TestVariationsServiceClient variations_service_client;
PlatformFieldTrials platform_field_trials;
NiceMock<MockSafeSeedManager> safe_seed_manager(local_state());
auto seed_store = std::make_unique<VariationsSeedStore>(
local_state(), std::move(initial_seed),
false,
std::make_unique<VariationsSafeSeedStoreLocalState>(local_state()));
VariationsFieldTrialCreator field_trial_creator(
&variations_service_client, std::move(seed_store), UIStringOverrider(),
nullptr);
metrics::TestEnabledStateProvider enabled_state_provider(true,
true);
auto metrics_state_manager = metrics::MetricsStateManager::Create(
local_state(), &enabled_state_provider, std::wstring(), base::FilePath());
metrics_state_manager->InstantiateFieldTrialList();
SyntheticTrialRegistry synthetic_trial_registry;
EXPECT_TRUE(field_trial_creator.SetUpFieldTrials(
std::vector<std::string>(),
base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
switches::kForceVariationIds),
std::vector<base::FeatureList::FeatureOverrideInfo>(),
std::make_unique<base::FeatureList>(), metrics_state_manager.get(),
&synthetic_trial_registry, &platform_field_trials, &safe_seed_manager,
true));
EXPECT_EQ(kTestSeedExperimentName,
base::FieldTrialList::FindFullName(kTestSeedStudyName));
}
TEST_F(FieldTrialCreatorTest, ClientFilterableState_HardwareClass) {
NiceMock<MockSafeSeedManager> safe_seed_manager(local_state());
TestVariationsServiceClient variations_service_client;
TestVariationsFieldTrialCreator field_trial_creator(
local_state(), &variations_service_client, &safe_seed_manager);
const base::Version& current_version = version_info::GetVersion();
EXPECT_TRUE(current_version.IsValid());
std::unique_ptr<ClientFilterableState> client_filterable_state =
field_trial_creator.GetClientFilterableStateForVersion(current_version);
EXPECT_NE(client_filterable_state->hardware_class, std::string());
}
#endif
#if BUILDFLAG(FIELDTRIAL_TESTING_ENABLED)
std::unique_ptr<TestVariationsFieldTrialCreator>
SetUpFieldTrialCreatorWithValidSeed(
PrefService* local_state,
TestVariationsServiceClient* variations_service_client,
NiceMock<MockSafeSeedManager>* safe_seed_manager) { … }
TEST_F(FieldTrialCreatorTest, NotSetUpFieldTrialConfig_ValidSeed) { … }
TEST_F(FieldTrialCreatorTest, SetUpFieldTrialConfig_ValidSeed) { … }
TEST_F(FieldTrialCreatorTest, SetUpFieldTrialConfig_ForceFieldTrials) { … }
TEST_F(FieldTrialCreatorTest, SetUpFieldTrialConfig_ForceFieldTrialsOverride) { … }
TEST_F(FieldTrialCreatorTest, SetUpFieldTrialConfig_ForceFieldTrialParams) { … }
class FieldTrialCreatorTestWithFeatures
: public FieldTrialCreatorTest,
public ::testing::WithParamInterface<const char*> { … };
INSTANTIATE_TEST_SUITE_P(…);
TEST_P(FieldTrialCreatorTestWithFeatures,
SetUpFieldTrialConfig_OverrideFeatures) { … }
#endif
TEST_F(FieldTrialCreatorTest, DoNotWriteBeaconFile) { … }
struct StartupVisibilityTestParams { … };
class FieldTrialCreatorTestWithStartupVisibility
: public FieldTrialCreatorTest,
public ::testing::WithParamInterface<StartupVisibilityTestParams> { … };
INSTANTIATE_TEST_SUITE_P(…);
TEST_P(FieldTrialCreatorTestWithStartupVisibility,
StartupVisibilityAffectsBrowserCrashMonitoring) { … }
TEST_F(FieldTrialCreatorTest, WriteBeaconFile) { … }
TEST_F(FieldTrialCreatorTest, GetGoogleGroupsFromPrefsWhenPrefNotPresent) { … }
TEST_F(FieldTrialCreatorTest, GetGoogleGroupsFromPrefsWhenEmptyDict) { … }
TEST_F(FieldTrialCreatorTest,
GetGoogleGroupsFromPrefsWhenProfileWithEmptyList) { … }
TEST_F(FieldTrialCreatorTest,
GetGoogleGroupsFromPrefsWhenProfileWithNonEmptyList) { … }
TEST_F(FieldTrialCreatorTest,
GetGoogleGroupsFromPrefsWhenProfileWithNonNumericString) { … }
TEST_F(FieldTrialCreatorTest, GetGoogleGroupsFromPrefsClearsDeletedProfiles) { … }
namespace {
TestLimitedEntropySyntheticTrial kEnabledTrial(
kLimitedEntropySyntheticTrialEnabled);
TestLimitedEntropySyntheticTrial kControlTrial(
kLimitedEntropySyntheticTrialControl);
TestLimitedEntropySyntheticTrial kDefaultTrial(
kLimitedEntropySyntheticTrialDefault);
const raw_ptr<LimitedEntropySyntheticTrial> kNoLimitedLayerSupport = …;
struct GenerateLERSTestCase { … };
class IsLimitedEntropyRandomizationSourceEnabledTest
: public FieldTrialCreatorTest,
public ::testing::WithParamInterface<GenerateLERSTestCase> { … };
const GenerateLERSTestCase kGenerateLERSTestCases[] = …;
INSTANTIATE_TEST_SUITE_P(…);
TEST_P(IsLimitedEntropyRandomizationSourceEnabledTest, ) { … }
enum class LimitedModeGate { … };
struct LimitedEntropyProcessingTestCase { … };
std::vector<LimitedEntropyProcessingTestCase> CreateTestCasesForTrials(
std::string_view test_name,
LimitedModeGate limited_mode_gate,
const VariationsSeed& seed,
const std::vector<raw_ptr<LimitedEntropySyntheticTrial>>& trials,
bool is_group_registration_expected,
bool is_seed_rejection_expected,
bool is_limited_study_active) { … }
std::vector<LimitedEntropyProcessingTestCase> FlattenTests(
const std::vector<std::vector<LimitedEntropyProcessingTestCase>>&
test_cases) { … }
const std::vector<LimitedEntropyProcessingTestCase> kTestCases = …;
class LimitedEntropyProcessingTest
: public FieldTrialCreatorTest,
public ::testing::WithParamInterface<LimitedEntropyProcessingTestCase> { … };
INSTANTIATE_TEST_SUITE_P(…);
TEST_P(LimitedEntropyProcessingTest,
RandomizeLimitedEntropyStudyOrRejectTheSeed) { … }
BASE_FEATURE(…);
BASE_FEATURE(…);
BASE_FEATURE(…);
BASE_FEATURE(…);
BASE_FEATURE(…);
BASE_FEATURE(…);
BASE_FEATURE(…);
class FieldTrialCreatorFormFactorTest
: public FieldTrialCreatorTest,
public ::testing::WithParamInterface<Study::FormFactor> { … };
constexpr Study::FormFactor kAllFormFactors[] = …;
constexpr char kFormFactorTestSeedData[] = …;
constexpr char kFormFactorTestSeedSignature[] = …;
}
INSTANTIATE_TEST_SUITE_P(…);
TEST_P(FieldTrialCreatorFormFactorTest, FilterByFormFactor) { … }
}