1 // Copyright 2015 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "components/metrics/stability_metrics_helper.h"
6
7 #include <memory>
8
9 #include "base/process/kill.h"
10 #include "base/test/metrics/histogram_tester.h"
11 #include "build/build_config.h"
12 #include "components/prefs/pref_service.h"
13 #include "components/prefs/scoped_user_pref_update.h"
14 #include "components/prefs/testing_pref_service.h"
15 #include "extensions/buildflags/buildflags.h"
16 #include "testing/gtest/include/gtest/gtest.h"
17 #include "third_party/metrics_proto/system_profile.pb.h"
18
19 namespace metrics {
20
21 namespace {
22
23 enum RendererType {
24 RENDERER_TYPE_RENDERER = 1,
25 RENDERER_TYPE_EXTENSION,
26 // NOTE: Add new action types only immediately above this line. Also,
27 // make sure the enum list in tools/metrics/histograms/histograms.xml is
28 // updated with any change in here.
29 RENDERER_TYPE_COUNT
30 };
31
32 class StabilityMetricsHelperTest : public testing::Test {
33 public:
34 StabilityMetricsHelperTest(const StabilityMetricsHelperTest&) = delete;
35 StabilityMetricsHelperTest& operator=(const StabilityMetricsHelperTest&) =
36 delete;
37
38 protected:
StabilityMetricsHelperTest()39 StabilityMetricsHelperTest() : prefs_(new TestingPrefServiceSimple) {
40 StabilityMetricsHelper::RegisterPrefs(prefs()->registry());
41 }
42
prefs()43 TestingPrefServiceSimple* prefs() { return prefs_.get(); }
44
45 private:
46 std::unique_ptr<TestingPrefServiceSimple> prefs_;
47 };
48
49 } // namespace
50
51 #if BUILDFLAG(IS_IOS)
TEST_F(StabilityMetricsHelperTest,LogRendererCrash)52 TEST_F(StabilityMetricsHelperTest, LogRendererCrash) {
53 StabilityMetricsHelper helper(prefs());
54 base::HistogramTester histogram_tester;
55
56 helper.LogRendererCrash();
57
58 constexpr int kDummyExitCode = 105;
59 histogram_tester.ExpectUniqueSample("CrashExitCodes.Renderer", kDummyExitCode,
60 1);
61 histogram_tester.ExpectBucketCount("BrowserRenderProcessHost.ChildCrashes",
62 RENDERER_TYPE_RENDERER, 1);
63 histogram_tester.ExpectBucketCount("Stability.Counts2",
64 StabilityEventType::kRendererCrash, 1);
65 histogram_tester.ExpectBucketCount("Stability.Counts2",
66 StabilityEventType::kExtensionCrash, 0);
67 }
68 #elif !BUILDFLAG(IS_ANDROID)
TEST_F(StabilityMetricsHelperTest,LogRendererCrash)69 TEST_F(StabilityMetricsHelperTest, LogRendererCrash) {
70 StabilityMetricsHelper helper(prefs());
71 base::HistogramTester histogram_tester;
72
73 // Crash and abnormal termination should increment renderer crash count.
74 helper.LogRendererCrash(RendererHostedContentType::kForegroundMainFrame,
75 base::TERMINATION_STATUS_PROCESS_CRASHED, 1);
76
77 helper.LogRendererCrash(RendererHostedContentType::kForegroundMainFrame,
78 base::TERMINATION_STATUS_ABNORMAL_TERMINATION, 1);
79
80 // OOM should increment renderer crash count.
81 helper.LogRendererCrash(RendererHostedContentType::kForegroundMainFrame,
82 base::TERMINATION_STATUS_OOM, 1);
83
84 // Kill does not increment renderer crash count.
85 helper.LogRendererCrash(RendererHostedContentType::kForegroundMainFrame,
86 base::TERMINATION_STATUS_PROCESS_WAS_KILLED, 1);
87
88 // Failed launch increments failed launch count.
89 helper.LogRendererCrash(RendererHostedContentType::kForegroundMainFrame,
90 base::TERMINATION_STATUS_LAUNCH_FAILED, 1);
91
92 histogram_tester.ExpectUniqueSample("CrashExitCodes.Renderer", 1, 3);
93 histogram_tester.ExpectBucketCount("BrowserRenderProcessHost.ChildCrashes",
94 RENDERER_TYPE_RENDERER, 3);
95 histogram_tester.ExpectBucketCount("Stability.Counts2",
96 StabilityEventType::kRendererCrash, 3);
97 histogram_tester.ExpectBucketCount(
98 "Stability.Counts2", StabilityEventType::kRendererFailedLaunch, 1);
99 histogram_tester.ExpectBucketCount("Stability.Counts2",
100 StabilityEventType::kExtensionCrash, 0);
101
102 // One launch failure each.
103 histogram_tester.ExpectBucketCount(
104 "BrowserRenderProcessHost.ChildLaunchFailures", RENDERER_TYPE_RENDERER,
105 1);
106
107 // TERMINATION_STATUS_PROCESS_WAS_KILLED for a renderer.
108 histogram_tester.ExpectBucketCount("BrowserRenderProcessHost.ChildKills",
109 RENDERER_TYPE_RENDERER, 1);
110 histogram_tester.ExpectBucketCount("BrowserRenderProcessHost.ChildKills",
111 RENDERER_TYPE_EXTENSION, 0);
112 histogram_tester.ExpectBucketCount(
113 "BrowserRenderProcessHost.ChildLaunchFailureCodes", 1, 1);
114 }
115 #endif
116
117 // Note: ENABLE_EXTENSIONS is set to false in Android
118 #if BUILDFLAG(ENABLE_EXTENSIONS)
TEST_F(StabilityMetricsHelperTest,LogRendererCrashEnableExtensions)119 TEST_F(StabilityMetricsHelperTest, LogRendererCrashEnableExtensions) {
120 StabilityMetricsHelper helper(prefs());
121 base::HistogramTester histogram_tester;
122
123 // Crash and abnormal termination should increment extension crash count.
124 helper.LogRendererCrash(RendererHostedContentType::kExtension,
125 base::TERMINATION_STATUS_PROCESS_CRASHED, 1);
126
127 // OOM should increment extension renderer crash count.
128 helper.LogRendererCrash(RendererHostedContentType::kExtension,
129 base::TERMINATION_STATUS_OOM, 1);
130
131 // Failed launch increments extension failed launch count.
132 helper.LogRendererCrash(RendererHostedContentType::kExtension,
133 base::TERMINATION_STATUS_LAUNCH_FAILED, 1);
134
135 histogram_tester.ExpectBucketCount("Stability.Counts2",
136 StabilityEventType::kRendererCrash, 0);
137 histogram_tester.ExpectBucketCount(
138 "Stability.Counts2", StabilityEventType::kExtensionRendererFailedLaunch,
139 1);
140 histogram_tester.ExpectBucketCount("Stability.Counts2",
141 StabilityEventType::kExtensionCrash, 2);
142
143 histogram_tester.ExpectBucketCount(
144 "BrowserRenderProcessHost.ChildLaunchFailureCodes", 1, 1);
145 histogram_tester.ExpectUniqueSample("CrashExitCodes.Extension", 1, 2);
146 histogram_tester.ExpectBucketCount("BrowserRenderProcessHost.ChildCrashes",
147 RENDERER_TYPE_EXTENSION, 2);
148 histogram_tester.ExpectBucketCount(
149 "BrowserRenderProcessHost.ChildLaunchFailures", RENDERER_TYPE_EXTENSION,
150 1);
151 }
152 #endif // BUILDFLAG(ENABLE_EXTENSIONS)
153
154 #if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS)
155 // Verifies that "Stability.RendererAbnormalTermination2.*" histograms are
156 // correctly recorded by `LogRendererCrash`.
TEST_F(StabilityMetricsHelperTest,RendererAbnormalTerminationCount)157 TEST_F(StabilityMetricsHelperTest, RendererAbnormalTerminationCount) {
158 StabilityMetricsHelper helper(prefs());
159
160 {
161 // Normal termination does not record anything.
162 base::HistogramTester tester;
163 helper.LogRendererCrash(
164 RendererHostedContentType::kForegroundMainFrame,
165 base::TerminationStatus::TERMINATION_STATUS_NORMAL_TERMINATION, 0);
166 EXPECT_EQ("", tester.GetAllHistogramsRecorded());
167 }
168
169 // Test all abnormal termination status / hosted content type combinations.
170 for (auto status : {
171 base::TERMINATION_STATUS_ABNORMAL_TERMINATION,
172 base::TERMINATION_STATUS_PROCESS_WAS_KILLED,
173 base::TERMINATION_STATUS_PROCESS_CRASHED,
174 base::TERMINATION_STATUS_STILL_RUNNING,
175 #if BUILDFLAG(IS_CHROMEOS)
176 base::TERMINATION_STATUS_PROCESS_WAS_KILLED_BY_OOM,
177 #endif
178 base::TERMINATION_STATUS_LAUNCH_FAILED,
179 base::TERMINATION_STATUS_OOM,
180 #if BUILDFLAG(IS_WIN)
181 base::TERMINATION_STATUS_INTEGRITY_FAILURE,
182 #endif
183 }) {
184 #if BUILDFLAG(ENABLE_EXTENSIONS)
185 {
186 base::HistogramTester tester;
187 helper.LogRendererCrash(RendererHostedContentType::kExtension, status, 0);
188 tester.ExpectUniqueSample(
189 "Stability.RendererAbnormalTermination2.HostedContentType",
190 RendererHostedContentType::kExtension, 1);
191 tester.ExpectUniqueSample(
192 "Stability.RendererAbnormalTermination2.Extension", status, 1);
193 }
194 #endif // BUILDFLAG(ENABLE_EXTENSIONS)
195
196 {
197 base::HistogramTester tester;
198 helper.LogRendererCrash(RendererHostedContentType::kForegroundMainFrame,
199 status, 0);
200 tester.ExpectUniqueSample(
201 "Stability.RendererAbnormalTermination2.HostedContentType",
202 RendererHostedContentType::kForegroundMainFrame, 1);
203 tester.ExpectUniqueSample(
204 "Stability.RendererAbnormalTermination2.ForegroundMainFrame", status,
205 1);
206 }
207
208 {
209 base::HistogramTester tester;
210 helper.LogRendererCrash(RendererHostedContentType::kForegroundSubframe,
211 status, 0);
212 tester.ExpectUniqueSample(
213 "Stability.RendererAbnormalTermination2.HostedContentType",
214 RendererHostedContentType::kForegroundSubframe, 1);
215 tester.ExpectUniqueSample(
216 "Stability.RendererAbnormalTermination2.ForegroundSubframe", status,
217 1);
218 }
219
220 {
221 base::HistogramTester tester;
222 helper.LogRendererCrash(RendererHostedContentType::kBackgroundFrame,
223 status, 0);
224 tester.ExpectUniqueSample(
225 "Stability.RendererAbnormalTermination2.HostedContentType",
226 RendererHostedContentType::kBackgroundFrame, 1);
227 tester.ExpectUniqueSample(
228 "Stability.RendererAbnormalTermination2.BackgroundFrame", status, 1);
229 }
230
231 {
232 base::HistogramTester tester;
233 helper.LogRendererCrash(RendererHostedContentType::kInactiveFrame, status,
234 0);
235 tester.ExpectUniqueSample(
236 "Stability.RendererAbnormalTermination2.HostedContentType",
237 RendererHostedContentType::kInactiveFrame, 1);
238 tester.ExpectUniqueSample(
239 "Stability.RendererAbnormalTermination2.InactiveFrame", status, 1);
240 }
241
242 {
243 base::HistogramTester tester;
244 helper.LogRendererCrash(RendererHostedContentType::kNoFrameOrExtension,
245 status, 0);
246 tester.ExpectUniqueSample(
247 "Stability.RendererAbnormalTermination2.HostedContentType",
248 RendererHostedContentType::kNoFrameOrExtension, 1);
249 tester.ExpectUniqueSample(
250 "Stability.RendererAbnormalTermination2.NoFrameOrExtension", status,
251 1);
252 }
253 }
254 }
255 #endif // !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS)
256
257 } // namespace metrics
258