Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(317)

Side by Side Diff: ios/chrome/browser/metrics/tab_usage_recorder_unittest.mm

Issue 2585233003: Upstream Chrome on iOS source code [2/11]. (Closed)
Patch Set: Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2013 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.
4
5 #include <memory>
6
7 #include "base/mac/scoped_nsobject.h"
8 #include "base/message_loop/message_loop.h"
9 #include "base/metrics/histogram_samples.h"
10 #include "base/stl_util.h"
11 #include "base/test/histogram_tester.h"
12 #import "ios/chrome/browser/metrics/previous_session_info.h"
13 #include "ios/chrome/browser/metrics/tab_usage_recorder.h"
14 #import "ios/chrome/browser/metrics/tab_usage_recorder_delegate.h"
15 #import "ios/chrome/browser/tabs/tab.h"
16 #include "ios/testing/ocmock_complex_type_helper.h"
17 #include "ios/web/public/test/test_web_thread.h"
18 #import "ios/web/web_state/ui/crw_web_controller.h"
19 #include "testing/gtest/include/gtest/gtest.h"
20 #include "testing/platform_test.h"
21 #include "third_party/ocmock/ocmock_extensions.h"
22
23 @interface TURTestTabMock : OCMockComplexTypeHelper {
24 GURL _url;
25 }
26
27 @property(nonatomic, assign) const GURL& url;
28 @end
29
30 @implementation TURTestTabMock
31 - (const GURL&)url {
32 return _url;
33 }
34 - (void)setUrl:(const GURL&)url {
35 _url = url;
36 }
37 @end
38
39 // A mock TabUsageRecorderDelegate which allows the unit tests to control
40 // the count of live tabs returned from the |liveTabsCount| delegate method.
41 @interface MockTabUsageRecorderDelegate : NSObject<TabUsageRecorderDelegate> {
42 NSUInteger _tabCount;
43 }
44
45 // Sets the live tab count returned from the |liveTabsCount| delegate method.
46 - (void)setLiveTabsCount:(NSUInteger)count;
47
48 @end
49
50 @implementation MockTabUsageRecorderDelegate
51
52 - (void)setLiveTabsCount:(NSUInteger)count {
53 _tabCount = count;
54 }
55
56 - (NSUInteger)liveTabsCount {
57 return _tabCount;
58 }
59
60 @end
61
62 namespace {
63
64 // The number of alive tabs at a renderer termination used by unit test.
65 const NSUInteger kAliveTabsCountAtRendererTermination = 2U;
66
67 // The number of timestamps added to the renderer termination timestamp list
68 // that are not counted in the RecentlyAliveTabs metric.
69 const int kExpiredTimesAddedCount = 2;
70
71 class TabUsageRecorderForTesting : public TabUsageRecorder {
72 public:
73 TabUsageRecorderForTesting(MockTabUsageRecorderDelegate* delegate)
74 : TabUsageRecorder(delegate) {}
75 // For testing only.
76 base::TimeTicks RestoreStartTime() const { return restore_start_time_; }
77
78 // Adds |time| to the deque keeping track of renderer termination
79 // timestamps.
80 void AddTimeToDeque(base::TimeTicks time) {
81 termination_timestamps_.push_back(time);
82 }
83 };
84
85 class TabUsageRecorderTest : public PlatformTest {
86 protected:
87 void SetUp() override {
88 loop_.reset(new base::MessageLoop(base::MessageLoop::TYPE_DEFAULT));
89 ui_thread_.reset(new web::TestWebThread(web::WebThread::UI, loop_.get()));
90 histogram_tester_.reset(new base::HistogramTester());
91 // Set the delegate to nil to allow the relevant unit tests direct access to
92 // the mock delegate.
93 tab_usage_recorder_.reset(new TabUsageRecorderForTesting(nil));
94 webUrl_ = GURL("http://www.chromium.org");
95 nativeUrl_ = GURL("chrome://version");
96 }
97
98 id MockTab(bool inMemory) {
99 id tab_mock = [[TURTestTabMock alloc]
100 initWithRepresentedObject:[OCMockObject mockForClass:[Tab class]]];
101 id web_controller_mock =
102 [OCMockObject mockForClass:[CRWWebController class]];
103 [[[tab_mock stub] andReturn:web_controller_mock] webController];
104 [[[tab_mock stub] andReturnBool:false] isPrerenderTab];
105 [tab_mock setUrl:webUrl_];
106 [[[web_controller_mock stub] andReturnBool:inMemory] isViewAlive];
107 [[web_controller_mock stub] removeObserver:OCMOCK_ANY];
108 return [tab_mock autorelease];
109 }
110
111 GURL webUrl_;
112 GURL nativeUrl_;
113 std::unique_ptr<base::MessageLoop> loop_;
114 std::unique_ptr<web::TestWebThread> ui_thread_;
115 std::unique_ptr<base::HistogramTester> histogram_tester_;
116 std::unique_ptr<TabUsageRecorderForTesting> tab_usage_recorder_;
117 };
118
119 TEST_F(TabUsageRecorderTest, SwitchBetweenInMemoryTabs) {
120 id tab_mock_a = MockTab(true);
121 id tab_mock_b = MockTab(true);
122
123 tab_usage_recorder_->RecordTabSwitched(tab_mock_a, tab_mock_b);
124 histogram_tester_->ExpectUniqueSample(kSelectedTabHistogramName,
125 TabUsageRecorder::IN_MEMORY, 1);
126 }
127
128 TEST_F(TabUsageRecorderTest, SwitchToEvictedTab) {
129 id tab_mock_a = MockTab(true);
130 id tab_mock_b = MockTab(false);
131
132 tab_usage_recorder_->RecordTabSwitched(tab_mock_a, tab_mock_b);
133 histogram_tester_->ExpectUniqueSample(kSelectedTabHistogramName,
134 TabUsageRecorder::EVICTED, 1);
135 }
136
137 TEST_F(TabUsageRecorderTest, SwitchFromEvictedTab) {
138 id tab_mock_a = MockTab(false);
139 id tab_mock_b = MockTab(true);
140
141 tab_usage_recorder_->RecordTabSwitched(tab_mock_a, tab_mock_b);
142 histogram_tester_->ExpectUniqueSample(kSelectedTabHistogramName,
143 TabUsageRecorder::IN_MEMORY, 1);
144 }
145
146 TEST_F(TabUsageRecorderTest, SwitchBetweenEvictedTabs) {
147 id tab_mock_a = MockTab(false);
148 id tab_mock_b = MockTab(false);
149
150 tab_usage_recorder_->RecordTabSwitched(tab_mock_a, tab_mock_b);
151 histogram_tester_->ExpectUniqueSample(kSelectedTabHistogramName,
152 TabUsageRecorder::EVICTED, 1);
153 }
154
155 TEST_F(TabUsageRecorderTest, CountPageLoadsBeforeEvictedTab) {
156 id tab_mock_a = MockTab(true);
157 id tab_mock_b = MockTab(false);
158
159 // Call reload an arbitrary number of times.
160 const int kNumReloads = 4;
161 for (int i = 0; i < kNumReloads; i++) {
162 tab_usage_recorder_->RecordPageLoadStart(tab_mock_a);
163 }
164 tab_usage_recorder_->RecordTabSwitched(tab_mock_a, tab_mock_b);
165 histogram_tester_->ExpectUniqueSample(kPageLoadsBeforeEvictedTabSelected,
166 kNumReloads, 1);
167 }
168
169 TEST_F(TabUsageRecorderTest, CountNativePageLoadsBeforeEvictedTab) {
170 id tab_mock_a = MockTab(true);
171 id tab_mock_b = MockTab(false);
172 [tab_mock_a setUrl:nativeUrl_];
173 [tab_mock_b setUrl:nativeUrl_];
174
175 // Call reload an arbitrary number of times.
176 const int kNumReloads = 4;
177 for (int i = 0; i < kNumReloads; i++) {
178 tab_usage_recorder_->RecordPageLoadStart(tab_mock_a);
179 }
180 tab_usage_recorder_->RecordTabSwitched(tab_mock_a, tab_mock_b);
181 histogram_tester_->ExpectTotalCount(kPageLoadsBeforeEvictedTabSelected, 0);
182 }
183
184 TEST_F(TabUsageRecorderTest, TestColdStartTabs) {
185 id tab_mock_a = MockTab(false);
186 id tab_mock_b = MockTab(false);
187 id tab_mock_c = MockTab(false);
188 // Set A and B as cold-start evicted tabs. Leave C just evicted.
189 NSMutableArray* cold_start_tabs = [NSMutableArray array];
190 [cold_start_tabs addObject:tab_mock_a];
191 [cold_start_tabs addObject:tab_mock_b];
192 tab_usage_recorder_->InitialRestoredTabs(tab_mock_a, cold_start_tabs);
193
194 // Switch from A (cold start evicted) to B (cold start evicted).
195 tab_usage_recorder_->RecordTabSwitched(tab_mock_a, tab_mock_b);
196 // Switch from B (cold start evicted) to C (evicted).
197 tab_usage_recorder_->RecordTabSwitched(tab_mock_b, tab_mock_c);
198 histogram_tester_->ExpectTotalCount(kSelectedTabHistogramName, 2);
199 histogram_tester_->ExpectBucketCount(
200 kSelectedTabHistogramName, TabUsageRecorder::EVICTED_DUE_TO_COLD_START,
201 1);
202 histogram_tester_->ExpectBucketCount(kSelectedTabHistogramName,
203 TabUsageRecorder::EVICTED, 1);
204 }
205
206 TEST_F(TabUsageRecorderTest, TestSwitchedModeTabs) {
207 id tab_mock_a = MockTab(false);
208 id tab_mock_b = MockTab(false);
209 id tab_mock_c = MockTab(false);
210 NSMutableArray* switch_to_incognito_tabs = [NSMutableArray array];
211 [switch_to_incognito_tabs addObject:tab_mock_a];
212 [switch_to_incognito_tabs addObject:tab_mock_b];
213 tab_usage_recorder_->RecordPrimaryTabModelChange(false, nil);
214
215 // Switch from A (incognito evicted) to B (incognito evicted).
216 tab_usage_recorder_->RecordTabSwitched(tab_mock_a, tab_mock_b);
217 // Switch from B (incognito evicted) to C (evicted).
218 tab_usage_recorder_->RecordTabSwitched(tab_mock_b, tab_mock_c);
219 histogram_tester_->ExpectTotalCount(kSelectedTabHistogramName, 2);
220 histogram_tester_->ExpectBucketCount(
221 kSelectedTabHistogramName, TabUsageRecorder::EVICTED_DUE_TO_INCOGNITO, 0);
222 histogram_tester_->ExpectBucketCount(kSelectedTabHistogramName,
223 TabUsageRecorder::EVICTED, 2);
224 }
225
226 TEST_F(TabUsageRecorderTest, TestEvictedTabReloadTime) {
227 id tab_mock_a = MockTab(true);
228 id tab_mock_b = MockTab(false);
229 tab_usage_recorder_->RecordTabSwitched(tab_mock_a, tab_mock_b);
230 tab_usage_recorder_->RecordPageLoadStart(tab_mock_b);
231 tab_usage_recorder_->RecordPageLoadDone(tab_mock_b, true);
232 histogram_tester_->ExpectTotalCount(kEvictedTabReloadTime, 1);
233 }
234
235 TEST_F(TabUsageRecorderTest, TestEvictedTabReloadSuccess) {
236 id tab_mock_a = MockTab(true);
237 id tab_mock_b = MockTab(false);
238 tab_usage_recorder_->RecordTabSwitched(tab_mock_a, tab_mock_b);
239 tab_usage_recorder_->RecordPageLoadStart(tab_mock_b);
240 tab_usage_recorder_->RecordPageLoadDone(tab_mock_b, true);
241 histogram_tester_->ExpectUniqueSample(kEvictedTabReloadSuccessRate,
242 TabUsageRecorder::LOAD_SUCCESS, 1);
243 }
244
245 TEST_F(TabUsageRecorderTest, TestEvictedTabReloadFailure) {
246 id tab_mock_a = MockTab(true);
247 id tab_mock_b = MockTab(false);
248 tab_usage_recorder_->RecordTabSwitched(tab_mock_a, tab_mock_b);
249 tab_usage_recorder_->RecordPageLoadStart(tab_mock_b);
250 tab_usage_recorder_->RecordPageLoadDone(tab_mock_b, false);
251 histogram_tester_->ExpectUniqueSample(kEvictedTabReloadSuccessRate,
252 TabUsageRecorder::LOAD_FAILURE, 1);
253 }
254
255 TEST_F(TabUsageRecorderTest, TestUserWaitedForEvictedTabLoad) {
256 id tab_mock_a = MockTab(true);
257 id tab_mock_b = MockTab(false);
258 tab_usage_recorder_->RecordTabSwitched(tab_mock_a, tab_mock_b);
259 tab_usage_recorder_->RecordPageLoadStart(tab_mock_b);
260 tab_usage_recorder_->RecordPageLoadDone(tab_mock_b, true);
261 tab_usage_recorder_->RecordTabSwitched(tab_mock_b, tab_mock_a);
262 histogram_tester_->ExpectUniqueSample(kDidUserWaitForEvictedTabReload,
263 TabUsageRecorder::USER_WAITED, 1);
264 }
265
266 TEST_F(TabUsageRecorderTest, TestUserDidNotWaitForEvictedTabLoad) {
267 id tab_mock_a = MockTab(true);
268 id tab_mock_b = MockTab(false);
269 tab_usage_recorder_->RecordTabSwitched(tab_mock_a, tab_mock_b);
270 tab_usage_recorder_->RecordPageLoadStart(tab_mock_b);
271 tab_usage_recorder_->RecordTabSwitched(tab_mock_b, tab_mock_a);
272 histogram_tester_->ExpectUniqueSample(kDidUserWaitForEvictedTabReload,
273 TabUsageRecorder::USER_DID_NOT_WAIT, 1);
274 }
275
276 TEST_F(TabUsageRecorderTest, TestUserBackgroundedDuringEvictedTabLoad) {
277 id tab_mock_a = MockTab(true);
278 id tab_mock_b = MockTab(false);
279 tab_usage_recorder_->RecordTabSwitched(tab_mock_a, tab_mock_b);
280 tab_usage_recorder_->RecordPageLoadStart(tab_mock_b);
281 tab_usage_recorder_->AppDidEnterBackground();
282 histogram_tester_->ExpectUniqueSample(kDidUserWaitForEvictedTabReload,
283 TabUsageRecorder::USER_LEFT_CHROME, 1);
284 }
285
286 TEST_F(TabUsageRecorderTest, TestTimeBetweenRestores) {
287 id tab_mock_a = MockTab(false);
288 id tab_mock_b = MockTab(false);
289 tab_usage_recorder_->RecordTabSwitched(tab_mock_a, tab_mock_b);
290 // Should record the time since launch until this page load begins.
291 tab_usage_recorder_->RecordPageLoadStart(tab_mock_b);
292 tab_usage_recorder_->RecordTabSwitched(tab_mock_b, tab_mock_a);
293 // Should record the time since previous restore until this restore.
294 tab_usage_recorder_->RecordPageLoadStart(tab_mock_a);
295 histogram_tester_->ExpectTotalCount(kTimeBetweenRestores, 2);
296 }
297
298 TEST_F(TabUsageRecorderTest, TestTimeAfterLastRestore) {
299 id tab_mock_a = MockTab(false);
300 id tab_mock_b = MockTab(false);
301 // Should record time since launch until background.
302 tab_usage_recorder_->AppDidEnterBackground();
303 tab_usage_recorder_->AppWillEnterForeground();
304 tab_usage_recorder_->RecordTabSwitched(tab_mock_a, tab_mock_b);
305 // Should record nothing.
306 tab_usage_recorder_->RecordPageLoadStart(tab_mock_b);
307 histogram_tester_->ExpectTotalCount(kTimeAfterLastRestore, 1);
308 }
309
310 // Verifies that metrics are recorded correctly when a renderer terminates.
311 TEST_F(TabUsageRecorderTest, RendererTerminated) {
312 Tab* terminated_tab = MockTab(false);
313
314 // Set up the delegate to return |kAliveTabsCountAtRenderTermination|.
315 base::scoped_nsobject<MockTabUsageRecorderDelegate> delegate(
316 [[MockTabUsageRecorderDelegate alloc] init]);
317 [delegate setLiveTabsCount:kAliveTabsCountAtRendererTermination];
318 tab_usage_recorder_->SetDelegate(delegate);
319
320 base::TimeTicks now = base::TimeTicks::Now();
321
322 // Add |kExpiredTimesAddedCount| expired timestamps and one recent timestamp
323 // to the termination timestamp list.
324 for (int seconds = kExpiredTimesAddedCount; seconds > 0; seconds--) {
325 int expired_time_delta = kSecondsBeforeRendererTermination + seconds;
326 tab_usage_recorder_->AddTimeToDeque(
327 now - base::TimeDelta::FromSeconds(expired_time_delta));
328 }
329 base::TimeTicks recent_time =
330 now - base::TimeDelta::FromSeconds(kSecondsBeforeRendererTermination / 2);
331 tab_usage_recorder_->AddTimeToDeque(recent_time);
332
333 tab_usage_recorder_->RendererTerminated(terminated_tab, false);
334
335 NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
336 BOOL saw_memory_warning =
337 [defaults boolForKey:previous_session_info_constants::
338 kDidSeeMemoryWarningShortlyBeforeTerminating];
339 histogram_tester_->ExpectUniqueSample(kRendererTerminationSawMemoryWarning,
340 saw_memory_warning, 1);
341 histogram_tester_->ExpectUniqueSample(kRendererTerminationAliveRenderers,
342 kAliveTabsCountAtRendererTermination,
343 1);
344 // Tests that the logged count of recently alive renderers is equal to the
345 // live count at termination plus the recent termination and the
346 // renderer terminated just now.
347 histogram_tester_->ExpectUniqueSample(
348 kRendererTerminationRecentlyAliveRenderers,
349 kAliveTabsCountAtRendererTermination + 2, 1);
350 }
351
352 // Verifies that metrics are recorded correctly when a renderer terminated tab
353 // is switched to and reloaded.
354 TEST_F(TabUsageRecorderTest, SwitchToRendererTerminatedTab) {
355 id tab_mock_a = MockTab(true);
356 id tab_mock_b = MockTab(false);
357
358 tab_usage_recorder_->RendererTerminated(tab_mock_b, false);
359 tab_usage_recorder_->RecordTabSwitched(tab_mock_a, tab_mock_b);
360
361 histogram_tester_->ExpectUniqueSample(
362 kSelectedTabHistogramName,
363 TabUsageRecorder::EVICTED_DUE_TO_RENDERER_TERMINATION, 1);
364 }
365
366 } // namespace
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698