Roll src/third_party/WebKit f298044:aa8346d (svn 202628:202629)
[chromium-blink-merge.git] / components / browser_watcher / watcher_metrics_provider_win_unittest.cc
blobb4c39228bed067b89616bc01db26dc623bcb1987
1 // Copyright (c) 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "components/browser_watcher/watcher_metrics_provider_win.h"
7 #include <cstdlib>
9 #include "base/process/process_handle.h"
10 #include "base/strings/string16.h"
11 #include "base/strings/stringprintf.h"
12 #include "base/test/histogram_tester.h"
13 #include "base/test/test_reg_util_win.h"
14 #include "base/win/registry.h"
15 #include "components/browser_watcher/exit_funnel_win.h"
16 #include "testing/gtest/include/gtest/gtest.h"
18 namespace browser_watcher {
20 namespace {
22 const wchar_t kRegistryPath[] = L"Software\\WatcherMetricsProviderWinTest";
24 class WatcherMetricsProviderWinTest : public testing::Test {
25 public:
26 typedef testing::Test Super;
28 void SetUp() override {
29 Super::SetUp();
31 override_manager_.OverrideRegistry(HKEY_CURRENT_USER);
34 void AddProcessExitCode(bool use_own_pid, int exit_code) {
35 int pid = 0;
36 if (use_own_pid) {
37 pid = base::GetCurrentProcId();
38 } else {
39 // Make sure not to accidentally collide with own pid.
40 do {
41 pid = rand();
42 } while (pid == static_cast<int>(base::GetCurrentProcId()));
45 base::win::RegKey key(HKEY_CURRENT_USER, kRegistryPath, KEY_WRITE);
47 // Make up a unique key, starting with the given pid.
48 base::string16 key_name(base::StringPrintf(L"%d-%d", pid, rand()));
50 // Write the exit code to registry.
51 ULONG result = key.WriteValue(key_name.c_str(), exit_code);
52 ASSERT_EQ(result, ERROR_SUCCESS);
55 size_t ExitCodeRegistryPathValueCount() {
56 base::win::RegKey key(HKEY_CURRENT_USER, kRegistryPath, KEY_READ);
57 return key.GetValueCount();
60 void AddExitFunnelEvent(int pid, const base::char16* name, int64 value) {
61 base::string16 key_name =
62 base::StringPrintf(L"%ls\\%d-%d", kRegistryPath, pid, pid);
64 base::win::RegKey key(HKEY_CURRENT_USER, key_name.c_str(), KEY_WRITE);
65 ASSERT_EQ(key.WriteValue(name, &value, sizeof(value), REG_QWORD),
66 ERROR_SUCCESS);
69 protected:
70 registry_util::RegistryOverrideManager override_manager_;
71 base::HistogramTester histogram_tester_;
74 } // namespace
76 TEST_F(WatcherMetricsProviderWinTest, RecordsStabilityHistogram) {
77 // Record multiple success exits.
78 for (size_t i = 0; i < 11; ++i)
79 AddProcessExitCode(false, 0);
81 // Record a single failure.
82 AddProcessExitCode(false, 100);
84 WatcherMetricsProviderWin provider(kRegistryPath, true);
86 provider.ProvideStabilityMetrics(NULL);
87 histogram_tester_.ExpectBucketCount(
88 WatcherMetricsProviderWin::kBrowserExitCodeHistogramName, 0, 11);
89 histogram_tester_.ExpectBucketCount(
90 WatcherMetricsProviderWin::kBrowserExitCodeHistogramName, 100, 1);
91 histogram_tester_.ExpectTotalCount(
92 WatcherMetricsProviderWin::kBrowserExitCodeHistogramName, 12);
94 // Verify that the reported values are gone.
95 EXPECT_EQ(ExitCodeRegistryPathValueCount(), 0);
98 TEST_F(WatcherMetricsProviderWinTest, DoesNotReportOwnProcessId) {
99 // Record multiple success exits.
100 for (size_t i = 0; i < 11; ++i)
101 AddProcessExitCode(i, 0);
103 // Record own process as STILL_ACTIVE.
104 AddProcessExitCode(true, STILL_ACTIVE);
106 WatcherMetricsProviderWin provider(kRegistryPath, true);
108 provider.ProvideStabilityMetrics(NULL);
109 histogram_tester_.ExpectUniqueSample(
110 WatcherMetricsProviderWin::kBrowserExitCodeHistogramName, 0, 11);
112 // Verify that the reported values are gone.
113 EXPECT_EQ(ExitCodeRegistryPathValueCount(), 1);
116 TEST_F(WatcherMetricsProviderWinTest, RecordsOrderedExitFunnelEvents) {
117 // Record an exit funnel with a given set of timings and check that the
118 // ordering is correct on the reported histograms.
119 // Note the recorded times are in microseconds, but the reporting is in
120 // milliseconds, hence the times 1000.
121 AddExitFunnelEvent(100, L"One", 1000 * 1000);
122 AddExitFunnelEvent(100, L"Two", 1010 * 1000);
123 AddExitFunnelEvent(100, L"Three", 990 * 1000);
125 WatcherMetricsProviderWin provider(kRegistryPath, true);
127 provider.ProvideStabilityMetrics(NULL);
128 histogram_tester_.ExpectUniqueSample("Stability.ExitFunnel.Three", 0, 1);
129 histogram_tester_.ExpectUniqueSample("Stability.ExitFunnel.One", 10, 1);
130 histogram_tester_.ExpectUniqueSample("Stability.ExitFunnel.Two", 20, 1);
132 // Make sure the subkey is deleted on reporting.
133 base::win::RegistryKeyIterator it(HKEY_CURRENT_USER, kRegistryPath);
134 ASSERT_EQ(it.SubkeyCount(), 0);
137 TEST_F(WatcherMetricsProviderWinTest, ReadsExitFunnelWrites) {
138 // Test that the metrics provider picks up the writes from the funnel.
139 ExitFunnel funnel;
141 // Events against our own process should not get reported.
142 ASSERT_TRUE(funnel.Init(kRegistryPath, base::GetCurrentProcessHandle()));
143 ASSERT_TRUE(funnel.RecordEvent(L"Forgetaboutit"));
145 // Reset the funnel to a pseudo process. The PID 4 is the system process,
146 // which tests can hopefully never open.
147 ASSERT_TRUE(funnel.InitImpl(kRegistryPath, 4, base::Time::Now()));
149 // Each named event can only exist in a single copy.
150 ASSERT_TRUE(funnel.RecordEvent(L"One"));
151 ASSERT_TRUE(funnel.RecordEvent(L"One"));
152 ASSERT_TRUE(funnel.RecordEvent(L"One"));
153 ASSERT_TRUE(funnel.RecordEvent(L"Two"));
154 ASSERT_TRUE(funnel.RecordEvent(L"Three"));
156 WatcherMetricsProviderWin provider(kRegistryPath, true);
158 provider.ProvideStabilityMetrics(NULL);
159 histogram_tester_.ExpectTotalCount("Stability.ExitFunnel.One", 1);
160 histogram_tester_.ExpectTotalCount("Stability.ExitFunnel.Two", 1);
161 histogram_tester_.ExpectTotalCount("Stability.ExitFunnel.Three", 1);
163 // Make sure the subkey for the pseudo process has been deleted on reporting.
164 base::win::RegistryKeyIterator it(HKEY_CURRENT_USER, kRegistryPath);
165 ASSERT_EQ(it.SubkeyCount(), 1);
168 TEST_F(WatcherMetricsProviderWinTest, ClearsExitFunnelWriteWhenNotReporting) {
169 // Tests that the metrics provider cleans up, but doesn't report exit funnels
170 // when funnel reporting is quenched.
171 ExitFunnel funnel;
173 // Events against our own process should not get reported.
174 ASSERT_TRUE(funnel.Init(kRegistryPath, base::GetCurrentProcessHandle()));
175 ASSERT_TRUE(funnel.RecordEvent(L"Forgetaboutit"));
177 // Reset the funnel to a pseudo process. The PID 4 is the system process,
178 // which tests can hopefully never open.
179 ASSERT_TRUE(funnel.InitImpl(kRegistryPath, 4, base::Time::Now()));
181 // Each named event can only exist in a single copy.
182 ASSERT_TRUE(funnel.RecordEvent(L"One"));
183 ASSERT_TRUE(funnel.RecordEvent(L"One"));
184 ASSERT_TRUE(funnel.RecordEvent(L"One"));
185 ASSERT_TRUE(funnel.RecordEvent(L"Two"));
186 ASSERT_TRUE(funnel.RecordEvent(L"Three"));
188 // Turn off exit funnel reporting.
189 WatcherMetricsProviderWin provider(kRegistryPath, false);
191 provider.ProvideStabilityMetrics(NULL);
192 histogram_tester_.ExpectTotalCount("Stability.ExitFunnel.One", 0);
193 histogram_tester_.ExpectTotalCount("Stability.ExitFunnel.Two", 0);
194 histogram_tester_.ExpectTotalCount("Stability.ExitFunnel.Three", 0);
196 // Make sure the subkey for the pseudo process has been deleted on reporting.
197 base::win::RegistryKeyIterator it(HKEY_CURRENT_USER, kRegistryPath);
198 ASSERT_EQ(it.SubkeyCount(), 1);
201 } // namespace browser_watcher