blob: 6108a324e15e3bf4351e5ea7a3b9130207197e64 [file] [log] [blame]
Tej Singhe20bdcf2020-01-15 16:12:07 -08001/*
2 * Copyright (C) 2019 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package com.android.internal.os.statsd.libstats;
17
18import static com.google.common.truth.Truth.assertThat;
19
20import android.app.StatsManager;
21import android.content.Context;
22import android.util.Log;
23import android.util.StatsLog;
24
25import androidx.test.InstrumentationRegistry;
26import androidx.test.filters.MediumTest;
27import androidx.test.runner.AndroidJUnit4;
28
29import com.android.internal.os.StatsdConfigProto.AtomMatcher;
30import com.android.internal.os.StatsdConfigProto.FieldFilter;
31import com.android.internal.os.StatsdConfigProto.GaugeMetric;
Tej Singhdea94cd2020-03-26 22:20:19 -070032import com.android.internal.os.StatsdConfigProto.PullAtomPackages;
Tej Singhe20bdcf2020-01-15 16:12:07 -080033import com.android.internal.os.StatsdConfigProto.SimpleAtomMatcher;
34import com.android.internal.os.StatsdConfigProto.StatsdConfig;
35import com.android.internal.os.StatsdConfigProto.TimeUnit;
Tej Singhe20bdcf2020-01-15 16:12:07 -080036import com.android.internal.os.statsd.protos.TestAtoms;
37import com.android.os.AtomsProto.Atom;
38
39import org.junit.After;
40import org.junit.Before;
41import org.junit.Test;
42import org.junit.runner.RunWith;
43
44import java.util.List;
45
46/**
47 * Test puller registration.
48 */
49@MediumTest
50@RunWith(AndroidJUnit4.class)
51public class LibStatsPullTests {
52 private static final String LOG_TAG = LibStatsPullTests.class.getSimpleName();
53 private static final int SHORT_SLEEP_MILLIS = 250;
54 private static final int LONG_SLEEP_MILLIS = 1_000;
55 private Context mContext;
56 private static final int PULL_ATOM_TAG = 150030;
57 private static final int APP_BREADCRUMB_LABEL = 3;
58 private static int sPullReturnValue;
59 private static long sConfigId;
60 private static long sPullLatencyMillis;
Tej Singh16daf382020-03-13 18:42:40 -070061 private static long sPullTimeoutMillis;
62 private static long sCoolDownMillis;
Tej Singhe20bdcf2020-01-15 16:12:07 -080063 private static int sAtomsPerPull;
64
65 static {
66 System.loadLibrary("statspull_testhelper");
67 }
68
69 /**
70 * Setup the tests. Initialize shared data.
71 */
72 @Before
73 public void setup() {
Tej Singhe20bdcf2020-01-15 16:12:07 -080074 mContext = InstrumentationRegistry.getTargetContext();
75 assertThat(InstrumentationRegistry.getInstrumentation()).isNotNull();
76 sPullReturnValue = StatsManager.PULL_SUCCESS;
77 sPullLatencyMillis = 0;
Tej Singh16daf382020-03-13 18:42:40 -070078 sPullTimeoutMillis = 10_000L;
79 sCoolDownMillis = 1_000L;
Tej Singhe20bdcf2020-01-15 16:12:07 -080080 sAtomsPerPull = 1;
81 }
82
83 /**
84 * Teardown the tests.
85 */
86 @After
87 public void tearDown() throws Exception {
Tej Singh16daf382020-03-13 18:42:40 -070088 clearStatsPuller(PULL_ATOM_TAG);
Tej Singhe20bdcf2020-01-15 16:12:07 -080089 StatsManager statsManager = (StatsManager) mContext.getSystemService(
90 Context.STATS_MANAGER);
91 statsManager.removeConfig(sConfigId);
92 }
93
94 /**
95 * Tests adding a puller callback and that pulls complete successfully.
96 */
97 @Test
98 public void testPullAtomCallbackRegistration() throws Exception {
99 StatsManager statsManager = (StatsManager) mContext.getSystemService(
100 Context.STATS_MANAGER);
101 // Upload a config that captures that pulled atom.
102 createAndAddConfigToStatsd(statsManager);
103
104 // Add the puller.
Tej Singh16daf382020-03-13 18:42:40 -0700105 setStatsPuller(PULL_ATOM_TAG, sPullTimeoutMillis, sCoolDownMillis, sPullReturnValue,
Tej Singhe20bdcf2020-01-15 16:12:07 -0800106 sPullLatencyMillis, sAtomsPerPull);
107 Thread.sleep(SHORT_SLEEP_MILLIS);
108 StatsLog.logStart(APP_BREADCRUMB_LABEL);
109 // Let the current bucket finish.
110 Thread.sleep(LONG_SLEEP_MILLIS);
111 List<Atom> data = StatsConfigUtils.getGaugeMetricDataList(statsManager, sConfigId);
Tej Singh16daf382020-03-13 18:42:40 -0700112 clearStatsPuller(PULL_ATOM_TAG);
Tej Singhe20bdcf2020-01-15 16:12:07 -0800113 assertThat(data.size()).isEqualTo(1);
114 TestAtoms.PullCallbackAtomWrapper atomWrapper = null;
115 try {
116 atomWrapper = TestAtoms.PullCallbackAtomWrapper.parser()
117 .parseFrom(data.get(0).toByteArray());
118 } catch (Exception e) {
119 Log.e(LOG_TAG, "Failed to parse primitive atoms");
120 }
121 assertThat(atomWrapper).isNotNull();
122 assertThat(atomWrapper.hasPullCallbackAtom()).isTrue();
123 TestAtoms.PullCallbackAtom atom =
124 atomWrapper.getPullCallbackAtom();
125 assertThat(atom.getLongVal()).isEqualTo(1);
126 }
127
128 /**
129 * Tests that a failed pull is skipped.
130 */
131 @Test
132 public void testPullAtomCallbackFailure() throws Exception {
133 StatsManager statsManager = (StatsManager) mContext.getSystemService(
134 Context.STATS_MANAGER);
135 createAndAddConfigToStatsd(statsManager);
136 sPullReturnValue = StatsManager.PULL_SKIP;
137 // Add the puller.
Tej Singh16daf382020-03-13 18:42:40 -0700138 setStatsPuller(PULL_ATOM_TAG, sPullTimeoutMillis, sCoolDownMillis, sPullReturnValue,
Tej Singhe20bdcf2020-01-15 16:12:07 -0800139 sPullLatencyMillis, sAtomsPerPull);
140 Thread.sleep(SHORT_SLEEP_MILLIS);
141 StatsLog.logStart(APP_BREADCRUMB_LABEL);
142 // Let the current bucket finish.
143 Thread.sleep(LONG_SLEEP_MILLIS);
144 List<Atom> data = StatsConfigUtils.getGaugeMetricDataList(statsManager, sConfigId);
Tej Singh16daf382020-03-13 18:42:40 -0700145 clearStatsPuller(PULL_ATOM_TAG);
Tej Singhe20bdcf2020-01-15 16:12:07 -0800146 assertThat(data.size()).isEqualTo(0);
147 }
148
149 /**
150 * Tests that a pull that times out is skipped.
151 */
152 @Test
153 public void testPullAtomCallbackTimeout() throws Exception {
154 StatsManager statsManager = (StatsManager) mContext.getSystemService(
155 Context.STATS_MANAGER);
156 createAndAddConfigToStatsd(statsManager);
157 // The puller will sleep for 1.5 sec.
158 sPullLatencyMillis = 1_500;
159 // 1 second timeout
Tej Singh16daf382020-03-13 18:42:40 -0700160 sPullTimeoutMillis = 1_000;
Tej Singhe20bdcf2020-01-15 16:12:07 -0800161
162 // Add the puller.
Tej Singh16daf382020-03-13 18:42:40 -0700163 setStatsPuller(PULL_ATOM_TAG, sPullTimeoutMillis, sCoolDownMillis, sPullReturnValue,
Tej Singhe20bdcf2020-01-15 16:12:07 -0800164 sPullLatencyMillis, sAtomsPerPull);
165 Thread.sleep(SHORT_SLEEP_MILLIS);
166 StatsLog.logStart(APP_BREADCRUMB_LABEL);
167 // Let the current bucket finish and the pull timeout.
168 Thread.sleep(sPullLatencyMillis * 2);
169 List<Atom> data = StatsConfigUtils.getGaugeMetricDataList(statsManager, sConfigId);
Tej Singh16daf382020-03-13 18:42:40 -0700170 clearStatsPuller(PULL_ATOM_TAG);
Tej Singhe20bdcf2020-01-15 16:12:07 -0800171 assertThat(data.size()).isEqualTo(0);
172 }
173
174 /**
175 * Tests that 2 pulls in quick succession use the cache instead of pulling again.
176 */
177 @Test
178 public void testPullAtomCallbackCache() throws Exception {
179 StatsManager statsManager = (StatsManager) mContext.getSystemService(
180 Context.STATS_MANAGER);
181 createAndAddConfigToStatsd(statsManager);
182
183 // Set the cooldown to 10 seconds
Tej Singh16daf382020-03-13 18:42:40 -0700184 sCoolDownMillis = 10_000L;
Tej Singhe20bdcf2020-01-15 16:12:07 -0800185 // Add the puller.
Tej Singh16daf382020-03-13 18:42:40 -0700186 setStatsPuller(PULL_ATOM_TAG, sPullTimeoutMillis, sCoolDownMillis, sPullReturnValue,
Tej Singhe20bdcf2020-01-15 16:12:07 -0800187 sPullLatencyMillis, sAtomsPerPull);
188
189 Thread.sleep(SHORT_SLEEP_MILLIS);
190 StatsLog.logStart(APP_BREADCRUMB_LABEL);
191 // Pull from cache.
192 StatsLog.logStart(APP_BREADCRUMB_LABEL);
193 Thread.sleep(LONG_SLEEP_MILLIS);
194 List<Atom> data = StatsConfigUtils.getGaugeMetricDataList(statsManager, sConfigId);
Tej Singh16daf382020-03-13 18:42:40 -0700195 clearStatsPuller(PULL_ATOM_TAG);
Tej Singhe20bdcf2020-01-15 16:12:07 -0800196 assertThat(data.size()).isEqualTo(2);
197 for (int i = 0; i < data.size(); i++) {
198 TestAtoms.PullCallbackAtomWrapper atomWrapper = null;
199 try {
200 atomWrapper = TestAtoms.PullCallbackAtomWrapper.parser()
201 .parseFrom(data.get(i).toByteArray());
202 } catch (Exception e) {
203 Log.e(LOG_TAG, "Failed to parse primitive atoms");
204 }
205 assertThat(atomWrapper).isNotNull();
206 assertThat(atomWrapper.hasPullCallbackAtom()).isTrue();
207 TestAtoms.PullCallbackAtom atom =
208 atomWrapper.getPullCallbackAtom();
209 assertThat(atom.getLongVal()).isEqualTo(1);
210 }
211 }
212
213 /**
214 * Tests that a pull that returns 1000 stats events works properly.
215 */
216 @Test
217 public void testPullAtomCallbackStress() throws Exception {
218 StatsManager statsManager = (StatsManager) mContext.getSystemService(
219 Context.STATS_MANAGER);
220 // Upload a config that captures that pulled atom.
221 createAndAddConfigToStatsd(statsManager);
222 sAtomsPerPull = 1000;
223 // Add the puller.
Tej Singh16daf382020-03-13 18:42:40 -0700224 setStatsPuller(PULL_ATOM_TAG, sPullTimeoutMillis, sCoolDownMillis, sPullReturnValue,
Tej Singhe20bdcf2020-01-15 16:12:07 -0800225 sPullLatencyMillis, sAtomsPerPull);
226
227 Thread.sleep(SHORT_SLEEP_MILLIS);
228 StatsLog.logStart(APP_BREADCRUMB_LABEL);
229 // Let the current bucket finish.
230 Thread.sleep(LONG_SLEEP_MILLIS);
231 List<Atom> data = StatsConfigUtils.getGaugeMetricDataList(statsManager, sConfigId);
Tej Singh16daf382020-03-13 18:42:40 -0700232 clearStatsPuller(PULL_ATOM_TAG);
Tej Singhe20bdcf2020-01-15 16:12:07 -0800233 assertThat(data.size()).isEqualTo(sAtomsPerPull);
234
235 for (int i = 0; i < data.size(); i++) {
236 TestAtoms.PullCallbackAtomWrapper atomWrapper = null;
237 try {
238 atomWrapper = TestAtoms.PullCallbackAtomWrapper.parser()
239 .parseFrom(data.get(i).toByteArray());
240 } catch (Exception e) {
241 Log.e(LOG_TAG, "Failed to parse primitive atoms");
242 }
243 assertThat(atomWrapper).isNotNull();
244 assertThat(atomWrapper.hasPullCallbackAtom()).isTrue();
245 TestAtoms.PullCallbackAtom atom =
246 atomWrapper.getPullCallbackAtom();
247 assertThat(atom.getLongVal()).isEqualTo(1);
248 }
249 }
250
251 private void createAndAddConfigToStatsd(StatsManager statsManager) throws Exception {
252 sConfigId = System.currentTimeMillis();
253 long triggerMatcherId = sConfigId + 10;
254 long pullerMatcherId = sConfigId + 11;
255 long metricId = sConfigId + 100;
256 StatsdConfig config = StatsConfigUtils.getSimpleTestConfig(sConfigId)
257 .addAtomMatcher(
258 StatsConfigUtils.getAppBreadcrumbMatcher(triggerMatcherId,
259 APP_BREADCRUMB_LABEL))
260 .addAtomMatcher(AtomMatcher.newBuilder()
261 .setId(pullerMatcherId)
262 .setSimpleAtomMatcher(SimpleAtomMatcher.newBuilder()
263 .setAtomId(PULL_ATOM_TAG))
264 )
265 .addGaugeMetric(GaugeMetric.newBuilder()
266 .setId(metricId)
267 .setWhat(pullerMatcherId)
268 .setTriggerEvent(triggerMatcherId)
269 .setGaugeFieldsFilter(FieldFilter.newBuilder().setIncludeAll(true))
270 .setBucket(TimeUnit.CTS)
271 .setSamplingType(GaugeMetric.SamplingType.FIRST_N_SAMPLES)
272 .setMaxNumGaugeAtomsPerBucket(1000)
273 )
Tej Singhdea94cd2020-03-26 22:20:19 -0700274 .addPullAtomPackages(PullAtomPackages.newBuilder()
275 .setAtomId(PULL_ATOM_TAG)
276 .addPackages(LibStatsPullTests.class.getPackage().getName()))
Tej Singhe20bdcf2020-01-15 16:12:07 -0800277 .build();
278 statsManager.addConfig(sConfigId, config.toByteArray());
279 assertThat(StatsConfigUtils.verifyValidConfigExists(statsManager, sConfigId)).isTrue();
280 }
281
Tej Singh16daf382020-03-13 18:42:40 -0700282 private native void setStatsPuller(int atomTag, long timeoutMillis, long coolDownMillis,
Tej Singhe20bdcf2020-01-15 16:12:07 -0800283 int pullReturnVal, long latencyMillis, int atomPerPull);
284
Tej Singh16daf382020-03-13 18:42:40 -0700285 private native void clearStatsPuller(int atomTag);
Tej Singhe20bdcf2020-01-15 16:12:07 -0800286}
287