• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2023 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 package org.chromium.base.jank_tracker;
6 
7 import static org.mockito.Mockito.verify;
8 
9 import org.junit.Assert;
10 import org.junit.Before;
11 import org.junit.Test;
12 import org.junit.runner.RunWith;
13 import org.mockito.InOrder;
14 import org.mockito.Mock;
15 import org.mockito.Mockito;
16 import org.mockito.MockitoAnnotations;
17 import org.robolectric.annotation.LooperMode;
18 import org.robolectric.shadow.api.Shadow;
19 import org.robolectric.shadows.ShadowLooper;
20 
21 import org.chromium.base.test.BaseRobolectricTestRunner;
22 
23 /** Tests for JankReportingScheduler. */
24 @RunWith(BaseRobolectricTestRunner.class)
25 @LooperMode(LooperMode.Mode.LEGACY)
26 public class JankReportingSchedulerTest {
27     ShadowLooper mShadowLooper;
28 
29     @Mock private FrameMetricsStore mFrameMetricsStore;
30 
createJankReportingScheduler()31     JankReportingScheduler createJankReportingScheduler() {
32         JankReportingScheduler scheduler = new JankReportingScheduler(mFrameMetricsStore);
33         mShadowLooper = Shadow.extract(scheduler.getOrCreateHandler().getLooper());
34 
35         return scheduler;
36     }
37 
38     @Before
setUp()39     public void setUp() {
40         MockitoAnnotations.initMocks(this);
41     }
42 
43     @Test
jankScenarioTracking_startTracking()44     public void jankScenarioTracking_startTracking() {
45         JankReportingScheduler jankReportingScheduler = createJankReportingScheduler();
46 
47         jankReportingScheduler.startTrackingScenario(JankScenario.NEW_TAB_PAGE);
48 
49         // When first getting the handler we need to run the initialize on the handler.
50         mShadowLooper.runOneTask();
51         // Starting tracking posts a task to begin recording metrics in FrameMetricsStore.
52         mShadowLooper.runOneTask();
53 
54         verify(mFrameMetricsStore).initialize();
55         verify(mFrameMetricsStore).startTrackingScenario(JankScenario.NEW_TAB_PAGE);
56     }
57 
58     @Test
jankScenarioTracking_startAndStopTracking()59     public void jankScenarioTracking_startAndStopTracking() {
60         JankReportingScheduler jankReportingScheduler = createJankReportingScheduler();
61 
62         jankReportingScheduler.startTrackingScenario(JankScenario.NEW_TAB_PAGE);
63         jankReportingScheduler.finishTrackingScenario(JankScenario.NEW_TAB_PAGE);
64 
65         // When first getting the handler we need to run the initialize on the handler.
66         mShadowLooper.runOneTask();
67         // Starting tracking posts a task to begin recording metrics in FrameMetricsStore.
68         mShadowLooper.runOneTask();
69         // Stopping tracking posts a task to finish tracking and upload the calculated metrics.
70         mShadowLooper.runOneTask();
71 
72         InOrder orderVerifier = Mockito.inOrder(mFrameMetricsStore);
73 
74         // After both tasks we should have started and stopped tracking the periodic reporting
75         // scenario.
76         orderVerifier.verify(mFrameMetricsStore).initialize();
77         orderVerifier.verify(mFrameMetricsStore).startTrackingScenario(JankScenario.NEW_TAB_PAGE);
78         orderVerifier.verify(mFrameMetricsStore).stopTrackingScenario(JankScenario.NEW_TAB_PAGE);
79 
80         Assert.assertFalse(mShadowLooper.getScheduler().areAnyRunnable());
81     }
82 
83     @Test
jankReportingSchedulerTest_StartPeriodicReporting()84     public void jankReportingSchedulerTest_StartPeriodicReporting() {
85         JankReportingScheduler jankReportingScheduler = createJankReportingScheduler();
86 
87         jankReportingScheduler.startReportingPeriodicMetrics();
88 
89         // When first getting the handler we need to run the initialize on the handler.
90         mShadowLooper.runOneTask();
91         // When periodic reporting is enabled a task is immediately posted to begin tracking.
92         mShadowLooper.runOneTask();
93         // Then a delayed task is posted for the reporting loop.
94         mShadowLooper.runOneTask();
95         // The reporting loop task posts an immediate task to stop tracking and record the data.
96         mShadowLooper.runOneTask();
97 
98         InOrder orderVerifier = Mockito.inOrder(mFrameMetricsStore);
99 
100         // After both tasks we should have started and stopped tracking the periodic reporting
101         // scenario.
102         orderVerifier.verify(mFrameMetricsStore).initialize();
103         orderVerifier
104                 .verify(mFrameMetricsStore)
105                 .startTrackingScenario(JankScenario.PERIODIC_REPORTING);
106         orderVerifier
107                 .verify(mFrameMetricsStore)
108                 .stopTrackingScenario(JankScenario.PERIODIC_REPORTING);
109 
110         // There should be another task posted to continue the loop.
111         Assert.assertTrue(mShadowLooper.getScheduler().areAnyRunnable());
112     }
113 
114     @Test
jankReportingSchedulerTest_StopPeriodicReporting()115     public void jankReportingSchedulerTest_StopPeriodicReporting() {
116         JankReportingScheduler jankReportingScheduler = createJankReportingScheduler();
117 
118         jankReportingScheduler.startReportingPeriodicMetrics();
119 
120         // When first getting the handler we need to run the initialize on the handler.
121         mShadowLooper.runOneTask();
122         // Run tracking initialization task.
123         mShadowLooper.runOneTask();
124         // Run the first reporting loop (delayed 30s).
125         mShadowLooper.runOneTask();
126         // Run task to stop tracking 1st loop and record data.
127         mShadowLooper.runOneTask();
128         // Run task to start tracking the 2nd reporting loop.
129         mShadowLooper.runOneTask();
130 
131         jankReportingScheduler.stopReportingPeriodicMetrics();
132 
133         // Stopping periodic metric recording posts a reporting loop task immediately to stop
134         // tracking and record results.
135         mShadowLooper.runOneTask();
136         // The reporting loop task posts another immediate task to stop tracking and report data.
137         mShadowLooper.runOneTask();
138 
139         InOrder orderVerifier = Mockito.inOrder(mFrameMetricsStore);
140 
141         // This start/stop pair corresponds to the first reporting period.
142         orderVerifier.verify(mFrameMetricsStore).initialize();
143         orderVerifier
144                 .verify(mFrameMetricsStore)
145                 .startTrackingScenario(JankScenario.PERIODIC_REPORTING);
146         orderVerifier
147                 .verify(mFrameMetricsStore)
148                 .stopTrackingScenario(JankScenario.PERIODIC_REPORTING);
149 
150         // Stopping reporting forces an immediate report of recorded frames, if any.
151         orderVerifier
152                 .verify(mFrameMetricsStore)
153                 .startTrackingScenario(JankScenario.PERIODIC_REPORTING);
154         orderVerifier
155                 .verify(mFrameMetricsStore)
156                 .stopTrackingScenario(JankScenario.PERIODIC_REPORTING);
157 
158         // There should not be another task posted to continue the loop.
159         Assert.assertFalse(mShadowLooper.getScheduler().areAnyRunnable());
160     }
161 }
162