#include "components/metrics/metrics_service.h"
#include <stdint.h>
#include <algorithm>
#include <memory>
#include <string>
#include <string_view>
#include "base/containers/contains.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/functional/bind.h"
#include "base/memory/raw_ptr.h"
#include "base/metrics/field_trial.h"
#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_snapshot_manager.h"
#include "base/metrics/metrics_hashes.h"
#include "base/metrics/statistics_recorder.h"
#include "base/metrics/user_metrics.h"
#include "base/task/single_thread_task_runner.h"
#include "base/test/bind.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/task_environment.h"
#include "base/threading/platform_thread.h"
#include "build/build_config.h"
#include "components/metrics/clean_exit_beacon.h"
#include "components/metrics/client_info.h"
#include "components/metrics/cloned_install_detector.h"
#include "components/metrics/environment_recorder.h"
#include "components/metrics/log_decoder.h"
#include "components/metrics/metrics_features.h"
#include "components/metrics/metrics_log.h"
#include "components/metrics/metrics_pref_names.h"
#include "components/metrics/metrics_scheduler.h"
#include "components/metrics/metrics_state_manager.h"
#include "components/metrics/metrics_upload_scheduler.h"
#include "components/metrics/stability_metrics_helper.h"
#include "components/metrics/test/test_enabled_state_provider.h"
#include "components/metrics/test/test_metrics_provider.h"
#include "components/metrics/test/test_metrics_service_client.h"
#include "components/metrics/unsent_log_store_metrics_impl.h"
#include "components/prefs/testing_pref_service.h"
#include "components/variations/active_field_trials.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/metrics_proto/chrome_user_metrics_extension.pb.h"
#include "third_party/metrics_proto/system_profile.pb.h"
#include "third_party/zlib/google/compression_utils.h"
namespace metrics {
namespace {
const char kTestPrefName[] = …;
class TestUnsentLogStore : public UnsentLogStore { … };
bool IsFieldTrialPresent(const SystemProfileProto& proto,
const std::string& trial_name,
const std::string& group_name) { … }
class TestMetricsService : public MetricsService { … };
class TestMetricsLog : public MetricsLog { … };
const char kOnDidCreateMetricsLogHistogramName[] = …;
class TestMetricsProviderForOnDidCreateMetricsLog : public TestMetricsProvider { … };
const char kProvideHistogramsHistogramName[] = …;
class TestMetricsProviderForProvideHistograms : public TestMetricsProvider { … };
class TestMetricsProviderForProvideHistogramsEarlyReturn
: public TestMetricsProviderForProvideHistograms { … };
class TestIndependentMetricsProvider : public MetricsProvider { … };
class MetricsServiceTest : public testing::Test { … };
class MetricsServiceTestWithFeatures
: public MetricsServiceTest,
public ::testing::WithParamInterface<std::tuple<bool>> { … };
struct StartupVisibilityTestParams { … };
class MetricsServiceTestWithStartupVisibility
: public MetricsServiceTest,
public ::testing::WithParamInterface<
std::tuple<StartupVisibilityTestParams, bool>> { … };
class ExperimentTestMetricsProvider : public TestMetricsProvider { … };
bool HistogramExists(std::string_view name) { … }
base::HistogramBase::Count GetHistogramDeltaTotalCount(std::string_view name) { … }
}
INSTANTIATE_TEST_SUITE_P(…);
TEST_P(MetricsServiceTestWithFeatures, RecordId) { … }
TEST_P(MetricsServiceTestWithFeatures, InitialStabilityLogAfterCleanShutDown) { … }
TEST_P(MetricsServiceTestWithFeatures, InitialStabilityLogAtProviderRequest) { … }
TEST_P(MetricsServiceTestWithFeatures, IndependentLogAtProviderRequest) { … }
TEST_P(MetricsServiceTestWithFeatures, OnDidCreateMetricsLogAtShutdown) { … }
TEST_P(MetricsServiceTestWithFeatures, ProvideHistograms) { … }
TEST_P(MetricsServiceTestWithFeatures, ProvideHistogramsEarlyReturn) { … }
INSTANTIATE_TEST_SUITE_P(…);
TEST_P(MetricsServiceTestWithStartupVisibility, InitialStabilityLogAfterCrash) { … }
TEST_P(MetricsServiceTestWithFeatures,
InitialLogsHaveOnDidCreateMetricsLogHistograms) { … }
TEST_P(MetricsServiceTestWithFeatures, MarkCurrentHistogramsAsReported) { … }
TEST_P(MetricsServiceTestWithFeatures, LogHasUserActions) { … }
TEST_P(MetricsServiceTestWithFeatures, FirstLogCreatedBeforeUnsentLogsSent) { … }
TEST_P(MetricsServiceTestWithFeatures,
MetricsProviderOnRecordingDisabledCalledOnInitialStop) { … }
TEST_P(MetricsServiceTestWithFeatures, MetricsProvidersInitialized) { … }
TEST_P(MetricsServiceTestWithFeatures, ActiveFieldTrialsReported) { … }
TEST_P(MetricsServiceTestWithFeatures,
SystemProfileDataProvidedOnEnableRecording) { … }
TEST_P(MetricsServiceTestWithFeatures, SplitRotation) { … }
TEST_P(MetricsServiceTestWithFeatures, LastLiveTimestamp) { … }
TEST_P(MetricsServiceTestWithFeatures, EnablementObserverNotification) { … }
TEST_P(MetricsServiceTestWithFeatures, PurgeLogsOnClonedInstallDetected) { … }
#if BUILDFLAG(IS_CHROMEOS_LACROS)
TEST_P(MetricsServiceTestWithFeatures, SetClientIdToExternalId) {
EnableMetricsReporting();
TestMetricsServiceClient client;
TestMetricsService service(GetMetricsStateManager(), &client,
GetLocalState());
const std::string client_id = "d92ad666-a420-4c73-8718-94311ae2ff5f";
EXPECT_NE(service.GetClientId(), client_id);
service.SetExternalClientId(client_id);
service.ResetClientId();
EXPECT_EQ(service.GetClientId(), client_id);
}
#endif
#if BUILDFLAG(IS_CHROMEOS_ASH)
TEST_P(MetricsServiceTestWithFeatures,
OngoingLogNotFlushedBeforeInitialLogWhenUserLogStoreSet) {
EnableMetricsReporting();
TestMetricsServiceClient client;
TestMetricsService service(GetMetricsStateManager(), &client,
GetLocalState());
service.InitializeMetricsRecordingState();
service.Start();
ASSERT_EQ(TestMetricsService::INIT_TASK_SCHEDULED, service.state());
MetricsLogStore* test_log_store = service.LogStoreForTest();
std::unique_ptr<TestUnsentLogStore> alternate_ongoing_log_store =
InitializeTestLogStoreAndGet();
TestUnsentLogStore* alternate_ongoing_log_store_ptr =
alternate_ongoing_log_store.get();
ASSERT_EQ(0u, test_log_store->initial_log_count());
ASSERT_EQ(0u, test_log_store->ongoing_log_count());
service.SetUserLogStore(std::move(alternate_ongoing_log_store));
ASSERT_EQ(0u, test_log_store->initial_log_count());
ASSERT_EQ(0u, test_log_store->ongoing_log_count());
base::TimeDelta initialization_delay = service.GetInitializationDelay();
task_environment_.FastForwardBy(initialization_delay);
EXPECT_EQ(TestMetricsService::INIT_TASK_DONE, service.state());
task_environment_.FastForwardBy(
base::Seconds(MetricsScheduler::GetInitialIntervalSeconds()) -
initialization_delay);
ASSERT_EQ(TestMetricsService::SENDING_LOGS, service.state());
EXPECT_EQ(0u, test_log_store->initial_log_count());
EXPECT_EQ(0u, test_log_store->ongoing_log_count());
EXPECT_EQ(1u, alternate_ongoing_log_store_ptr->size());
}
TEST_P(MetricsServiceTestWithFeatures,
OngoingLogFlushedAfterInitialLogWhenUserLogStoreSet) {
EnableMetricsReporting();
TestMetricsServiceClient client;
TestMetricsService service(GetMetricsStateManager(), &client,
GetLocalState());
service.InitializeMetricsRecordingState();
service.Start();
ASSERT_EQ(TestMetricsService::INIT_TASK_SCHEDULED, service.state());
MetricsLogStore* test_log_store = service.LogStoreForTest();
std::unique_ptr<TestUnsentLogStore> alternate_ongoing_log_store =
InitializeTestLogStoreAndGet();
ASSERT_EQ(0u, test_log_store->initial_log_count());
ASSERT_EQ(0u, test_log_store->ongoing_log_count());
base::TimeDelta initialization_delay = service.GetInitializationDelay();
task_environment_.FastForwardBy(initialization_delay);
EXPECT_EQ(TestMetricsService::INIT_TASK_DONE, service.state());
task_environment_.FastForwardBy(
base::Seconds(MetricsScheduler::GetInitialIntervalSeconds()) -
initialization_delay);
ASSERT_EQ(TestMetricsService::SENDING_LOGS, service.state());
ASSERT_EQ(0u, test_log_store->initial_log_count());
ASSERT_EQ(1u, test_log_store->ongoing_log_count());
service.SetUserLogStore(std::move(alternate_ongoing_log_store));
ASSERT_EQ(0u, test_log_store->initial_log_count());
ASSERT_EQ(2u, test_log_store->ongoing_log_count());
}
TEST_P(MetricsServiceTestWithFeatures,
OngoingLogDiscardedAfterEarlyUnsetUserLogStore) {
EnableMetricsReporting();
TestMetricsServiceClient client;
TestMetricsService service(GetMetricsStateManager(), &client,
GetLocalState());
service.InitializeMetricsRecordingState();
service.Start();
ASSERT_EQ(TestMetricsService::INIT_TASK_SCHEDULED, service.state());
MetricsLogStore* test_log_store = service.LogStoreForTest();
std::unique_ptr<TestUnsentLogStore> alternate_ongoing_log_store =
InitializeTestLogStoreAndGet();
ASSERT_EQ(0u, test_log_store->initial_log_count());
ASSERT_EQ(0u, test_log_store->ongoing_log_count());
service.SetUserLogStore(std::move(alternate_ongoing_log_store));
base::UmaHistogramBoolean("Test.Before.Histogram", true);
service.UnsetUserLogStore();
base::UmaHistogramBoolean("Test.After.Histogram", true);
EXPECT_FALSE(service.GetCurrentLogForTest());
EXPECT_EQ(0, GetHistogramDeltaTotalCount("Test.Before.Histogram"));
EXPECT_EQ(1, GetHistogramDeltaTotalCount("Test.After.Histogram"));
base::StatisticsRecorder::ForgetHistogramForTesting("Test.Before.Histogram");
base::StatisticsRecorder::ForgetHistogramForTesting("Test.After.Histogram");
}
TEST_P(MetricsServiceTestWithFeatures,
UnsettingLogStoreShouldDisableRecording) {
EnableMetricsReporting();
TestMetricsServiceClient client;
TestMetricsService service(GetMetricsStateManager(), &client,
GetLocalState());
service.InitializeMetricsRecordingState();
service.Start();
ASSERT_TRUE(service.recording_active());
std::unique_ptr<TestUnsentLogStore> alternate_ongoing_log_store =
InitializeTestLogStoreAndGet();
service.SetUserLogStore(std::move(alternate_ongoing_log_store));
service.UnsetUserLogStore();
ASSERT_FALSE(service.recording_active());
base::RecordAction(base::UserMetricsAction("TestAction"));
}
#endif
}