// Copyright 2015 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "ios/chrome/browser/metrics/mobile_session_shutdown_metrics_provider.h" #include "base/bind.h" #include "base/macros.h" #include "base/memory/scoped_ptr.h" #include "base/test/histogram_tester.h" #include "components/metrics/metrics_pref_names.h" #include "components/metrics/metrics_service.h" #include "components/metrics/metrics_state_manager.h" #include "components/metrics/test_metrics_service_client.h" #include "components/prefs/testing_pref_service.h" #include "testing/gtest/include/gtest/gtest-param-test.h" #include "testing/gtest/include/gtest/gtest.h" namespace { bool IsMetricsReportingEnabled() { return false; } } // namespace // An MobileSessionShutdownMetricsProvider that returns fake values for the last // session environment query methods. class MobileSessionShutdownMetricsProviderForTesting : public MobileSessionShutdownMetricsProvider { public: explicit MobileSessionShutdownMetricsProviderForTesting( metrics::MetricsService* metrics_service) : MobileSessionShutdownMetricsProvider(metrics_service) {} void set_is_first_launch_after_upgrade(bool value) { is_first_launch_after_upgrade_ = value; } void set_has_crash_logs(bool value) { has_crash_logs_ = value; } void set_has_uploaded_crash_reports_in_background(bool value) { has_uploaded_crash_reports_in_background_ = value; } void set_received_memory_warning_before_last_shutdown(bool value) { received_memory_warning_before_last_shutdown_ = value; } protected: // MobileSessionShutdownMetricsProvider: bool IsFirstLaunchAfterUpgrade() override { return is_first_launch_after_upgrade_; } bool HasCrashLogs() override { return has_crash_logs_; } bool HasUploadedCrashReportsInBackground() override { return has_uploaded_crash_reports_in_background_; } bool ReceivedMemoryWarningBeforeLastShutdown() override { return received_memory_warning_before_last_shutdown_; } private: bool is_first_launch_after_upgrade_; bool was_last_shutdown_clean_; bool has_crash_logs_; bool has_uploaded_crash_reports_in_background_; bool received_memory_warning_before_last_shutdown_; DISALLOW_COPY_AND_ASSIGN(MobileSessionShutdownMetricsProviderForTesting); }; class MobileSessionShutdownMetricsProviderTest : public testing::TestWithParam<int> { public: MobileSessionShutdownMetricsProviderTest() { metrics::MetricsService::RegisterPrefs(local_state_.registry()); } protected: TestingPrefServiceSimple local_state_; metrics::TestMetricsServiceClient metrics_client_; scoped_ptr<metrics::MetricsStateManager> metrics_state_; scoped_ptr<metrics::MetricsService> metrics_service_; scoped_ptr<MobileSessionShutdownMetricsProviderForTesting> metrics_provider_; private: DISALLOW_COPY_AND_ASSIGN(MobileSessionShutdownMetricsProviderTest); }; // Verifies that a sample is recorded in the correct bucket of the shutdown type // histogram when ProvideStabilityMetrics is invoked. // // This parameterized test receives a parameter in the range [0, 32), which is // used to generate values for five booleans based on the binary representation // of the parameter. The bits are assigned as follows (from least significant to // most significant): // - received memory warning; // - crash log present; // - uploaded crash reports in background; // - last shutdown was clean; // - first launch after upgrade. TEST_P(MobileSessionShutdownMetricsProviderTest, ProvideStabilityMetrics) { const bool received_memory_warning = GetParam() % 2; const bool has_crash_logs = (GetParam() >> 1) % 2; const bool has_uploaded_crash_reports_in_background = (GetParam() >> 2) % 2; const bool was_last_shutdown_clean = (GetParam() >> 3) % 2; const bool is_first_launch_after_upgrade = (GetParam() >> 4) % 2; // Expected bucket for each possible value of GetParam(). const MobileSessionShutdownType expected_buckets[] = { SHUTDOWN_IN_FOREGROUND_NO_CRASH_LOG_NO_MEMORY_WARNING, SHUTDOWN_IN_FOREGROUND_NO_CRASH_LOG_WITH_MEMORY_WARNING, SHUTDOWN_IN_FOREGROUND_WITH_CRASH_LOG_NO_MEMORY_WARNING, SHUTDOWN_IN_FOREGROUND_WITH_CRASH_LOG_WITH_MEMORY_WARNING, SHUTDOWN_IN_FOREGROUND_WITH_CRASH_LOG_NO_MEMORY_WARNING, SHUTDOWN_IN_FOREGROUND_WITH_CRASH_LOG_WITH_MEMORY_WARNING, SHUTDOWN_IN_FOREGROUND_WITH_CRASH_LOG_NO_MEMORY_WARNING, SHUTDOWN_IN_FOREGROUND_WITH_CRASH_LOG_WITH_MEMORY_WARNING, // If wasLastShutdownClean is true, the memory warning and crash log don't // matter. SHUTDOWN_IN_BACKGROUND, SHUTDOWN_IN_BACKGROUND, SHUTDOWN_IN_BACKGROUND, SHUTDOWN_IN_BACKGROUND, SHUTDOWN_IN_BACKGROUND, SHUTDOWN_IN_BACKGROUND, SHUTDOWN_IN_BACKGROUND, SHUTDOWN_IN_BACKGROUND, // If firstLaunchAfterUpgrade is true, the other flags don't matter. FIRST_LAUNCH_AFTER_UPGRADE, FIRST_LAUNCH_AFTER_UPGRADE, FIRST_LAUNCH_AFTER_UPGRADE, FIRST_LAUNCH_AFTER_UPGRADE, FIRST_LAUNCH_AFTER_UPGRADE, FIRST_LAUNCH_AFTER_UPGRADE, FIRST_LAUNCH_AFTER_UPGRADE, FIRST_LAUNCH_AFTER_UPGRADE, FIRST_LAUNCH_AFTER_UPGRADE, FIRST_LAUNCH_AFTER_UPGRADE, FIRST_LAUNCH_AFTER_UPGRADE, FIRST_LAUNCH_AFTER_UPGRADE, FIRST_LAUNCH_AFTER_UPGRADE, FIRST_LAUNCH_AFTER_UPGRADE, FIRST_LAUNCH_AFTER_UPGRADE, FIRST_LAUNCH_AFTER_UPGRADE, }; // Setup the MetricsService. local_state_.SetBoolean(metrics::prefs::kStabilityExitedCleanly, was_last_shutdown_clean); metrics_state_ = metrics::MetricsStateManager::Create( &local_state_, base::Bind(&IsMetricsReportingEnabled), metrics::MetricsStateManager::StoreClientInfoCallback(), metrics::MetricsStateManager::LoadClientInfoCallback()); metrics_service_.reset(new metrics::MetricsService( metrics_state_.get(), &metrics_client_, &local_state_)); // Create the metrics provider to test. metrics_provider_.reset(new MobileSessionShutdownMetricsProviderForTesting( metrics_service_.get())); // Setup the metrics provider for the current test. metrics_provider_->set_is_first_launch_after_upgrade( is_first_launch_after_upgrade); metrics_provider_->set_received_memory_warning_before_last_shutdown( received_memory_warning); metrics_provider_->set_has_crash_logs(has_crash_logs); metrics_provider_->set_has_uploaded_crash_reports_in_background( has_uploaded_crash_reports_in_background); // Create a histogram tester for verifying samples written to the shutdown // type histogram. base::HistogramTester histogram_tester; // Now call the method under test and verify exactly one sample is written to // the expected bucket. metrics_provider_->ProvideInitialStabilityMetrics(nullptr); histogram_tester.ExpectUniqueSample("Stability.MobileSessionShutdownType", expected_buckets[GetParam()], 1); } INSTANTIATE_TEST_CASE_P(/* No InstantiationName */, MobileSessionShutdownMetricsProviderTest, testing::Range(0, 32));