• 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 import static org.mockito.Mockito.verifyNoMoreInteractions;
9 
10 import android.os.Handler;
11 import android.os.Looper;
12 
13 import org.junit.Assert;
14 import org.junit.Before;
15 import org.junit.Rule;
16 import org.junit.Test;
17 import org.junit.runner.RunWith;
18 import org.mockito.Mock;
19 import org.mockito.Mockito;
20 import org.mockito.MockitoAnnotations;
21 import org.robolectric.shadows.ShadowLooper;
22 
23 import org.chromium.base.TimeUtils;
24 import org.chromium.base.test.BaseRobolectricTestRunner;
25 import org.chromium.base.test.util.JniMocker;
26 
27 /** Tests for JankReportingRunnable. */
28 @RunWith(BaseRobolectricTestRunner.class)
29 public class JankReportingRunnableTest {
30     ShadowLooper mShadowLooper;
31     Handler mHandler;
32     @Rule public JniMocker mocker = new JniMocker();
33 
34     @Mock JankMetricUMARecorder.Natives mNativeMock;
35 
36     @Before
setUp()37     public void setUp() {
38         MockitoAnnotations.initMocks(this);
39         mocker.mock(JankMetricUMARecorderJni.TEST_HOOKS, mNativeMock);
40         mShadowLooper = ShadowLooper.shadowMainLooper();
41         mHandler = new Handler(Looper.getMainLooper());
42     }
43 
44     @Test
testStartTracking()45     public void testStartTracking() {
46         FrameMetricsStore metricsStore = Mockito.spy(new FrameMetricsStore());
47         metricsStore.initialize();
48 
49         JankReportingRunnable reportingRunnable =
50                 new JankReportingRunnable(
51                         metricsStore,
52                         JankScenario.TAB_SWITCHER,
53                         /* isStartingTracking= */ true,
54                         mHandler,
55                         null);
56         reportingRunnable.run();
57 
58         verify(metricsStore).initialize();
59         verify(metricsStore).startTrackingScenario(JankScenario.TAB_SWITCHER);
60         verifyNoMoreInteractions(metricsStore);
61     }
62 
63     @Test
testStopTracking_withoutDelay()64     public void testStopTracking_withoutDelay() {
65         FrameMetricsStore metricsStore = Mockito.spy(new FrameMetricsStore());
66         metricsStore.initialize();
67 
68         JankReportingRunnable startReportingRunnable =
69                 new JankReportingRunnable(
70                         metricsStore,
71                         JankScenario.TAB_SWITCHER,
72                         /* isStartingTracking= */ true,
73                         mHandler,
74                         null);
75         startReportingRunnable.run();
76 
77         metricsStore.addFrameMeasurement(1_000_000L, 2, 1);
78 
79         JankReportingRunnable stopReportingRunnable =
80                 new JankReportingRunnable(
81                         metricsStore,
82                         JankScenario.TAB_SWITCHER,
83                         /* isStartingTracking= */ false,
84                         mHandler,
85                         null);
86         stopReportingRunnable.run();
87 
88         verify(metricsStore).initialize();
89         verify(metricsStore).startTrackingScenario(JankScenario.TAB_SWITCHER);
90         verify(metricsStore).stopTrackingScenario(JankScenario.TAB_SWITCHER);
91 
92         verify(mNativeMock)
93                 .recordJankMetrics(
94                         new long[] {1_000_000L}, new int[] {2}, 0L, 1L, JankScenario.TAB_SWITCHER);
95     }
96 
97     @Test
testStopTracking_withDelay()98     public void testStopTracking_withDelay() {
99         final long frameTime = 50L * TimeUtils.NANOSECONDS_PER_MILLISECOND;
100         FrameMetricsStore metricsStore = Mockito.spy(new FrameMetricsStore());
101         metricsStore.initialize();
102 
103         JankEndScenarioTime endScenarioTime = JankEndScenarioTime.endAt(frameTime);
104         Assert.assertTrue(endScenarioTime != null);
105         Assert.assertEquals(endScenarioTime.endScenarioTimeNs, frameTime);
106 
107         JankReportingRunnable startReportingRunnable =
108                 new JankReportingRunnable(
109                         metricsStore,
110                         JankScenario.TAB_SWITCHER,
111                         /* isStartingTracking= */ true,
112                         mHandler,
113                         endScenarioTime);
114         startReportingRunnable.run();
115 
116         metricsStore.addFrameMeasurement(1_000_000L, 2, 1 * TimeUtils.NANOSECONDS_PER_MILLISECOND);
117 
118         JankReportingRunnable stopReportingRunnable =
119                 new JankReportingRunnable(
120                         metricsStore,
121                         JankScenario.TAB_SWITCHER,
122                         /* isStartingTracking= */ false,
123                         mHandler,
124                         endScenarioTime);
125         stopReportingRunnable.run();
126 
127         // Add two frames, one added before the frame time of 50ms above and one after. The first
128         // should be included and the second ignored.
129         metricsStore.addFrameMeasurement(1_000_001L, 0, 5 * TimeUtils.NANOSECONDS_PER_MILLISECOND);
130         metricsStore.addFrameMeasurement(
131                 1_000_002L, 1, (frameTime + 5) * TimeUtils.NANOSECONDS_PER_MILLISECOND);
132 
133         mShadowLooper.runOneTask();
134 
135         verify(metricsStore).initialize();
136         verify(metricsStore).startTrackingScenario(JankScenario.TAB_SWITCHER);
137         verify(metricsStore).stopTrackingScenario(JankScenario.TAB_SWITCHER, frameTime);
138 
139         verify(mNativeMock)
140                 .recordJankMetrics(
141                         new long[] {1_000_000L, 1_000_001L},
142                         new int[] {2, 0},
143                         1L,
144                         5L,
145                         JankScenario.TAB_SWITCHER);
146     }
147 
148     @Test
testStopTracking_emptyStoreShouldntRecordAnything()149     public void testStopTracking_emptyStoreShouldntRecordAnything() {
150         // Create a store but don't add any measurements.
151         FrameMetricsStore metricsStore = Mockito.spy(new FrameMetricsStore());
152         metricsStore.initialize();
153 
154         JankReportingRunnable startReportingRunnable =
155                 new JankReportingRunnable(
156                         metricsStore,
157                         JankScenario.TAB_SWITCHER,
158                         /* isStartingTracking= */ true,
159                         mHandler,
160                         null);
161         startReportingRunnable.run();
162 
163         JankReportingRunnable stopReportingRunnable =
164                 new JankReportingRunnable(
165                         metricsStore,
166                         JankScenario.TAB_SWITCHER,
167                         /* isStartingTracking= */ false,
168                         mHandler,
169                         null);
170         stopReportingRunnable.run();
171 
172         verify(metricsStore).initialize();
173         verify(metricsStore).startTrackingScenario(JankScenario.TAB_SWITCHER);
174         verify(metricsStore).stopTrackingScenario(JankScenario.TAB_SWITCHER);
175 
176         // Native shouldn't be called when there are no measurements.
177         verifyNoMoreInteractions(mNativeMock);
178     }
179 }
180