// Copyright 2015 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/metrics/stability_metrics_helper.h" #include #include "base/process/kill.h" #include "base/test/metrics/histogram_tester.h" #include "build/build_config.h" #include "components/prefs/pref_service.h" #include "components/prefs/scoped_user_pref_update.h" #include "components/prefs/testing_pref_service.h" #include "extensions/buildflags/buildflags.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/metrics_proto/system_profile.pb.h" namespace metrics { namespace { enum RendererType { RENDERER_TYPE_RENDERER = 1, RENDERER_TYPE_EXTENSION, // NOTE: Add new action types only immediately above this line. Also, // make sure the enum list in tools/metrics/histograms/histograms.xml is // updated with any change in here. RENDERER_TYPE_COUNT }; class StabilityMetricsHelperTest : public testing::Test { public: StabilityMetricsHelperTest(const StabilityMetricsHelperTest&) = delete; StabilityMetricsHelperTest& operator=(const StabilityMetricsHelperTest&) = delete; protected: StabilityMetricsHelperTest() : prefs_(new TestingPrefServiceSimple) { StabilityMetricsHelper::RegisterPrefs(prefs()->registry()); } TestingPrefServiceSimple* prefs() { return prefs_.get(); } private: std::unique_ptr prefs_; }; } // namespace #if BUILDFLAG(IS_IOS) TEST_F(StabilityMetricsHelperTest, LogRendererCrash) { StabilityMetricsHelper helper(prefs()); base::HistogramTester histogram_tester; helper.LogRendererCrash(); constexpr int kDummyExitCode = 105; histogram_tester.ExpectUniqueSample("CrashExitCodes.Renderer", kDummyExitCode, 1); histogram_tester.ExpectBucketCount("BrowserRenderProcessHost.ChildCrashes", RENDERER_TYPE_RENDERER, 1); histogram_tester.ExpectBucketCount("Stability.Counts2", StabilityEventType::kRendererCrash, 1); histogram_tester.ExpectBucketCount("Stability.Counts2", StabilityEventType::kExtensionCrash, 0); } #elif !BUILDFLAG(IS_ANDROID) TEST_F(StabilityMetricsHelperTest, LogRendererCrash) { StabilityMetricsHelper helper(prefs()); base::HistogramTester histogram_tester; // Crash and abnormal termination should increment renderer crash count. helper.LogRendererCrash(RendererHostedContentType::kForegroundMainFrame, base::TERMINATION_STATUS_PROCESS_CRASHED, 1); helper.LogRendererCrash(RendererHostedContentType::kForegroundMainFrame, base::TERMINATION_STATUS_ABNORMAL_TERMINATION, 1); // OOM should increment renderer crash count. helper.LogRendererCrash(RendererHostedContentType::kForegroundMainFrame, base::TERMINATION_STATUS_OOM, 1); // Kill does not increment renderer crash count. helper.LogRendererCrash(RendererHostedContentType::kForegroundMainFrame, base::TERMINATION_STATUS_PROCESS_WAS_KILLED, 1); // Failed launch increments failed launch count. helper.LogRendererCrash(RendererHostedContentType::kForegroundMainFrame, base::TERMINATION_STATUS_LAUNCH_FAILED, 1); histogram_tester.ExpectUniqueSample("CrashExitCodes.Renderer", 1, 3); histogram_tester.ExpectBucketCount("BrowserRenderProcessHost.ChildCrashes", RENDERER_TYPE_RENDERER, 3); histogram_tester.ExpectBucketCount("Stability.Counts2", StabilityEventType::kRendererCrash, 3); histogram_tester.ExpectBucketCount( "Stability.Counts2", StabilityEventType::kRendererFailedLaunch, 1); histogram_tester.ExpectBucketCount("Stability.Counts2", StabilityEventType::kExtensionCrash, 0); // One launch failure each. histogram_tester.ExpectBucketCount( "BrowserRenderProcessHost.ChildLaunchFailures", RENDERER_TYPE_RENDERER, 1); // TERMINATION_STATUS_PROCESS_WAS_KILLED for a renderer. histogram_tester.ExpectBucketCount("BrowserRenderProcessHost.ChildKills", RENDERER_TYPE_RENDERER, 1); histogram_tester.ExpectBucketCount("BrowserRenderProcessHost.ChildKills", RENDERER_TYPE_EXTENSION, 0); histogram_tester.ExpectBucketCount( "BrowserRenderProcessHost.ChildLaunchFailureCodes", 1, 1); } #endif // Note: ENABLE_EXTENSIONS is set to false in Android #if BUILDFLAG(ENABLE_EXTENSIONS) TEST_F(StabilityMetricsHelperTest, LogRendererCrashEnableExtensions) { StabilityMetricsHelper helper(prefs()); base::HistogramTester histogram_tester; // Crash and abnormal termination should increment extension crash count. helper.LogRendererCrash(RendererHostedContentType::kExtension, base::TERMINATION_STATUS_PROCESS_CRASHED, 1); // OOM should increment extension renderer crash count. helper.LogRendererCrash(RendererHostedContentType::kExtension, base::TERMINATION_STATUS_OOM, 1); // Failed launch increments extension failed launch count. helper.LogRendererCrash(RendererHostedContentType::kExtension, base::TERMINATION_STATUS_LAUNCH_FAILED, 1); histogram_tester.ExpectBucketCount("Stability.Counts2", StabilityEventType::kRendererCrash, 0); histogram_tester.ExpectBucketCount( "Stability.Counts2", StabilityEventType::kExtensionRendererFailedLaunch, 1); histogram_tester.ExpectBucketCount("Stability.Counts2", StabilityEventType::kExtensionCrash, 2); histogram_tester.ExpectBucketCount( "BrowserRenderProcessHost.ChildLaunchFailureCodes", 1, 1); histogram_tester.ExpectUniqueSample("CrashExitCodes.Extension", 1, 2); histogram_tester.ExpectBucketCount("BrowserRenderProcessHost.ChildCrashes", RENDERER_TYPE_EXTENSION, 2); histogram_tester.ExpectBucketCount( "BrowserRenderProcessHost.ChildLaunchFailures", RENDERER_TYPE_EXTENSION, 1); } #endif // BUILDFLAG(ENABLE_EXTENSIONS) #if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS) // Verifies that "Stability.RendererAbnormalTermination2.*" histograms are // correctly recorded by `LogRendererCrash`. TEST_F(StabilityMetricsHelperTest, RendererAbnormalTerminationCount) { StabilityMetricsHelper helper(prefs()); { // Normal termination does not record anything. base::HistogramTester tester; helper.LogRendererCrash( RendererHostedContentType::kForegroundMainFrame, base::TerminationStatus::TERMINATION_STATUS_NORMAL_TERMINATION, 0); EXPECT_EQ("", tester.GetAllHistogramsRecorded()); } // Test all abnormal termination status / hosted content type combinations. for (auto status : { base::TERMINATION_STATUS_ABNORMAL_TERMINATION, base::TERMINATION_STATUS_PROCESS_WAS_KILLED, base::TERMINATION_STATUS_PROCESS_CRASHED, base::TERMINATION_STATUS_STILL_RUNNING, #if BUILDFLAG(IS_CHROMEOS) base::TERMINATION_STATUS_PROCESS_WAS_KILLED_BY_OOM, #endif base::TERMINATION_STATUS_LAUNCH_FAILED, base::TERMINATION_STATUS_OOM, #if BUILDFLAG(IS_WIN) base::TERMINATION_STATUS_INTEGRITY_FAILURE, #endif }) { #if BUILDFLAG(ENABLE_EXTENSIONS) { base::HistogramTester tester; helper.LogRendererCrash(RendererHostedContentType::kExtension, status, 0); tester.ExpectUniqueSample( "Stability.RendererAbnormalTermination2.HostedContentType", RendererHostedContentType::kExtension, 1); tester.ExpectUniqueSample( "Stability.RendererAbnormalTermination2.Extension", status, 1); } #endif // BUILDFLAG(ENABLE_EXTENSIONS) { base::HistogramTester tester; helper.LogRendererCrash(RendererHostedContentType::kForegroundMainFrame, status, 0); tester.ExpectUniqueSample( "Stability.RendererAbnormalTermination2.HostedContentType", RendererHostedContentType::kForegroundMainFrame, 1); tester.ExpectUniqueSample( "Stability.RendererAbnormalTermination2.ForegroundMainFrame", status, 1); } { base::HistogramTester tester; helper.LogRendererCrash(RendererHostedContentType::kForegroundSubframe, status, 0); tester.ExpectUniqueSample( "Stability.RendererAbnormalTermination2.HostedContentType", RendererHostedContentType::kForegroundSubframe, 1); tester.ExpectUniqueSample( "Stability.RendererAbnormalTermination2.ForegroundSubframe", status, 1); } { base::HistogramTester tester; helper.LogRendererCrash(RendererHostedContentType::kBackgroundFrame, status, 0); tester.ExpectUniqueSample( "Stability.RendererAbnormalTermination2.HostedContentType", RendererHostedContentType::kBackgroundFrame, 1); tester.ExpectUniqueSample( "Stability.RendererAbnormalTermination2.BackgroundFrame", status, 1); } { base::HistogramTester tester; helper.LogRendererCrash(RendererHostedContentType::kInactiveFrame, status, 0); tester.ExpectUniqueSample( "Stability.RendererAbnormalTermination2.HostedContentType", RendererHostedContentType::kInactiveFrame, 1); tester.ExpectUniqueSample( "Stability.RendererAbnormalTermination2.InactiveFrame", status, 1); } { base::HistogramTester tester; helper.LogRendererCrash(RendererHostedContentType::kNoFrameOrExtension, status, 0); tester.ExpectUniqueSample( "Stability.RendererAbnormalTermination2.HostedContentType", RendererHostedContentType::kNoFrameOrExtension, 1); tester.ExpectUniqueSample( "Stability.RendererAbnormalTermination2.NoFrameOrExtension", status, 1); } } } #endif // !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS) } // namespace metrics