blob: de6e6e542c604e8c6903bcd4ad7f426930e45f64 [file] [log] [blame]
David Chend9269e22017-12-05 13:43:51 -08001// Copyright (C) 2017 The Android Open Source Project
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#include "StatsLogProcessor.h"
16#include "config/ConfigKey.h"
David Chen35045cb2018-03-23 22:21:47 -070017#include "frameworks/base/cmds/statsd/src/stats_log.pb.h"
David Chend9269e22017-12-05 13:43:51 -080018#include "frameworks/base/cmds/statsd/src/statsd_config.pb.h"
19#include "guardrail/StatsdStats.h"
20#include "logd/LogEvent.h"
21#include "packages/UidMap.h"
22#include "statslog.h"
23
24#include <gmock/gmock.h>
25#include <gtest/gtest.h>
26
27#include <stdio.h>
28
29using namespace android;
30using namespace testing;
31
32namespace android {
33namespace os {
34namespace statsd {
35
Yao Chen288c6002017-12-12 13:43:18 -080036using android::util::ProtoOutputStream;
37
David Chend9269e22017-12-05 13:43:51 -080038#ifdef __ANDROID__
39
40/**
41 * Mock MetricsManager (ByteSize() is called).
42 */
43class MockMetricsManager : public MetricsManager {
44public:
Yangster-mac932ecec2018-02-01 10:23:52 -080045 MockMetricsManager() : MetricsManager(
Yangster-macc04feba2018-04-02 14:37:33 -070046 ConfigKey(1, 12345), StatsdConfig(), 1000, 1000,
Yangster-mac932ecec2018-02-01 10:23:52 -080047 new UidMap(),
48 new AlarmMonitor(10, [](const sp<IStatsCompanionService>&, int64_t){},
49 [](const sp<IStatsCompanionService>&){}),
50 new AlarmMonitor(10, [](const sp<IStatsCompanionService>&, int64_t){},
51 [](const sp<IStatsCompanionService>&){})) {
David Chend9269e22017-12-05 13:43:51 -080052 }
53
54 MOCK_METHOD0(byteSize, size_t());
Yao Chen06dba5d2018-01-26 13:38:16 -080055
Yangster-macb142cc82018-03-30 15:22:08 -070056 MOCK_METHOD1(dropData, void(const int64_t dropTimeNs));
David Chend9269e22017-12-05 13:43:51 -080057};
58
59TEST(StatsLogProcessorTest, TestRateLimitByteSize) {
60 sp<UidMap> m = new UidMap();
Yangster-mac932ecec2018-02-01 10:23:52 -080061 sp<AlarmMonitor> anomalyAlarmMonitor;
62 sp<AlarmMonitor> periodicAlarmMonitor;
David Chend9269e22017-12-05 13:43:51 -080063 // Construct the processor with a dummy sendBroadcast function that does nothing.
Yangster-mac932ecec2018-02-01 10:23:52 -080064 StatsLogProcessor p(m, anomalyAlarmMonitor, periodicAlarmMonitor, 0,
David Chen48944902018-05-03 10:29:11 -070065 [](const ConfigKey& key) {return true;});
David Chend9269e22017-12-05 13:43:51 -080066
67 MockMetricsManager mockMetricsManager;
68
Yangster-mac94e197c2018-01-02 16:03:03 -080069 ConfigKey key(100, 12345);
David Chend9269e22017-12-05 13:43:51 -080070 // Expect only the first flush to trigger a check for byte size since the last two are
71 // rate-limited.
72 EXPECT_CALL(mockMetricsManager, byteSize()).Times(1);
Yangster-macb0d06282018-01-05 15:44:07 -080073 p.flushIfNecessaryLocked(99, key, mockMetricsManager);
74 p.flushIfNecessaryLocked(100, key, mockMetricsManager);
75 p.flushIfNecessaryLocked(101, key, mockMetricsManager);
David Chend9269e22017-12-05 13:43:51 -080076}
77
78TEST(StatsLogProcessorTest, TestRateLimitBroadcast) {
79 sp<UidMap> m = new UidMap();
Yangster-mac932ecec2018-02-01 10:23:52 -080080 sp<AlarmMonitor> anomalyAlarmMonitor;
81 sp<AlarmMonitor> subscriberAlarmMonitor;
David Chend9269e22017-12-05 13:43:51 -080082 int broadcastCount = 0;
Yangster-mac932ecec2018-02-01 10:23:52 -080083 StatsLogProcessor p(m, anomalyAlarmMonitor, subscriberAlarmMonitor, 0,
David Chen48944902018-05-03 10:29:11 -070084 [&broadcastCount](const ConfigKey& key) { broadcastCount++; return true;});
David Chend9269e22017-12-05 13:43:51 -080085
86 MockMetricsManager mockMetricsManager;
87
Yangster-mac94e197c2018-01-02 16:03:03 -080088 ConfigKey key(100, 12345);
David Chend9269e22017-12-05 13:43:51 -080089 EXPECT_CALL(mockMetricsManager, byteSize())
Yao Chen8a8d16c2018-02-08 14:50:40 -080090 .Times(1)
David Chend9269e22017-12-05 13:43:51 -080091 .WillRepeatedly(Return(int(StatsdStats::kMaxMetricsBytesPerConfig * .95)));
92
93 // Expect only one broadcast despite always returning a size that should trigger broadcast.
Yangster-macb0d06282018-01-05 15:44:07 -080094 p.flushIfNecessaryLocked(1, key, mockMetricsManager);
David Chend9269e22017-12-05 13:43:51 -080095 EXPECT_EQ(1, broadcastCount);
96
Yao Chen8a8d16c2018-02-08 14:50:40 -080097 // b/73089712
David Chend9269e22017-12-05 13:43:51 -080098 // This next call to flush should not trigger a broadcast.
Yao Chen8a8d16c2018-02-08 14:50:40 -080099 // p.mLastByteSizeTimes.clear(); // Force another check for byte size.
100 // p.flushIfNecessaryLocked(2, key, mockMetricsManager);
101 // EXPECT_EQ(1, broadcastCount);
David Chend9269e22017-12-05 13:43:51 -0800102}
103
104TEST(StatsLogProcessorTest, TestDropWhenByteSizeTooLarge) {
105 sp<UidMap> m = new UidMap();
Yangster-mac932ecec2018-02-01 10:23:52 -0800106 sp<AlarmMonitor> anomalyAlarmMonitor;
107 sp<AlarmMonitor> subscriberAlarmMonitor;
David Chend9269e22017-12-05 13:43:51 -0800108 int broadcastCount = 0;
Yangster-mac932ecec2018-02-01 10:23:52 -0800109 StatsLogProcessor p(m, anomalyAlarmMonitor, subscriberAlarmMonitor, 0,
David Chen48944902018-05-03 10:29:11 -0700110 [&broadcastCount](const ConfigKey& key) { broadcastCount++; return true;});
David Chend9269e22017-12-05 13:43:51 -0800111
112 MockMetricsManager mockMetricsManager;
113
Yangster-mac94e197c2018-01-02 16:03:03 -0800114 ConfigKey key(100, 12345);
David Chend9269e22017-12-05 13:43:51 -0800115 EXPECT_CALL(mockMetricsManager, byteSize())
116 .Times(1)
117 .WillRepeatedly(Return(int(StatsdStats::kMaxMetricsBytesPerConfig * 1.2)));
118
Yao Chen06dba5d2018-01-26 13:38:16 -0800119 EXPECT_CALL(mockMetricsManager, dropData(_)).Times(1);
David Chend9269e22017-12-05 13:43:51 -0800120
121 // Expect to call the onDumpReport and skip the broadcast.
Yangster-macb0d06282018-01-05 15:44:07 -0800122 p.flushIfNecessaryLocked(1, key, mockMetricsManager);
David Chend9269e22017-12-05 13:43:51 -0800123 EXPECT_EQ(0, broadcastCount);
124}
125
David Chen35045cb2018-03-23 22:21:47 -0700126TEST(StatsLogProcessorTest, TestUidMapHasSnapshot) {
127 // Setup simple config key corresponding to empty config.
128 sp<UidMap> m = new UidMap();
David Chenbd125272018-04-04 19:02:50 -0700129 m->updateMap(1, {1, 2}, {1, 2}, {String16("p1"), String16("p2")});
David Chen35045cb2018-03-23 22:21:47 -0700130 sp<AlarmMonitor> anomalyAlarmMonitor;
131 sp<AlarmMonitor> subscriberAlarmMonitor;
132 int broadcastCount = 0;
133 StatsLogProcessor p(m, anomalyAlarmMonitor, subscriberAlarmMonitor, 0,
David Chen48944902018-05-03 10:29:11 -0700134 [&broadcastCount](const ConfigKey& key) { broadcastCount++; return true;});
David Chen35045cb2018-03-23 22:21:47 -0700135 ConfigKey key(3, 4);
136 StatsdConfig config;
137 config.add_allowed_log_source("AID_ROOT");
Yangster-macc04feba2018-04-02 14:37:33 -0700138 p.OnConfigUpdated(0, key, config);
David Chen35045cb2018-03-23 22:21:47 -0700139
140 // Expect to get no metrics, but snapshot specified above in uidmap.
141 vector<uint8_t> bytes;
Yangster-mac9def8e32018-04-17 13:55:51 -0700142 p.onDumpReport(key, 1, false, true, ADB_DUMP, &bytes);
David Chen35045cb2018-03-23 22:21:47 -0700143
144 ConfigMetricsReportList output;
145 output.ParseFromArray(bytes.data(), bytes.size());
146 EXPECT_TRUE(output.reports_size() > 0);
147 auto uidmap = output.reports(0).uid_map();
148 EXPECT_TRUE(uidmap.snapshots_size() > 0);
149 EXPECT_EQ(2, uidmap.snapshots(0).package_info_size());
150}
151
David Chenfaa1af52018-03-30 15:14:04 -0700152TEST(StatsLogProcessorTest, TestReportIncludesSubConfig) {
153 // Setup simple config key corresponding to empty config.
154 sp<UidMap> m = new UidMap();
155 sp<AlarmMonitor> anomalyAlarmMonitor;
156 sp<AlarmMonitor> subscriberAlarmMonitor;
157 int broadcastCount = 0;
158 StatsLogProcessor p(m, anomalyAlarmMonitor, subscriberAlarmMonitor, 0,
David Chen48944902018-05-03 10:29:11 -0700159 [&broadcastCount](const ConfigKey& key) { broadcastCount++; return true;});
David Chenfaa1af52018-03-30 15:14:04 -0700160 ConfigKey key(3, 4);
161 StatsdConfig config;
162 auto annotation = config.add_annotation();
163 annotation->set_field_int64(1);
164 annotation->set_field_int32(2);
165 config.add_allowed_log_source("AID_ROOT");
166 p.OnConfigUpdated(1, key, config);
167
168 // Expect to get no metrics, but snapshot specified above in uidmap.
169 vector<uint8_t> bytes;
Yangster-mac9def8e32018-04-17 13:55:51 -0700170 p.onDumpReport(key, 1, false, true, ADB_DUMP, &bytes);
David Chenfaa1af52018-03-30 15:14:04 -0700171
172 ConfigMetricsReportList output;
173 output.ParseFromArray(bytes.data(), bytes.size());
174 EXPECT_TRUE(output.reports_size() > 0);
175 auto report = output.reports(0);
176 EXPECT_EQ(1, report.annotation_size());
177 EXPECT_EQ(1, report.annotation(0).field_int64());
178 EXPECT_EQ(2, report.annotation(0).field_int32());
179}
180
Yao Chen163d2602018-04-10 10:39:53 -0700181TEST(StatsLogProcessorTest, TestOutOfOrderLogs) {
182 // Setup simple config key corresponding to empty config.
183 sp<UidMap> m = new UidMap();
184 sp<AlarmMonitor> anomalyAlarmMonitor;
185 sp<AlarmMonitor> subscriberAlarmMonitor;
186 int broadcastCount = 0;
187 StatsLogProcessor p(m, anomalyAlarmMonitor, subscriberAlarmMonitor, 0,
David Chen48944902018-05-03 10:29:11 -0700188 [&broadcastCount](const ConfigKey& key) { broadcastCount++; return true;});
Yao Chen163d2602018-04-10 10:39:53 -0700189
190 LogEvent event1(0, 1 /*logd timestamp*/, 1001 /*elapsedRealtime*/);
191 event1.init();
192
193 LogEvent event2(0, 2, 1002);
194 event2.init();
195
196 LogEvent event3(0, 3, 1005);
197 event3.init();
198
199 LogEvent event4(0, 4, 1004);
200 event4.init();
201
202 // <----- Reconnection happens
203
204 LogEvent event5(0, 5, 999);
205 event5.init();
206
207 LogEvent event6(0, 6, 2000);
208 event6.init();
209
210 // <----- Reconnection happens
211
212 LogEvent event7(0, 7, 3000);
213 event7.init();
214
215 // first event ever
216 p.OnLogEvent(&event1, true);
217 EXPECT_EQ(1UL, p.mLogCount);
218 EXPECT_EQ(1001LL, p.mLargestTimestampSeen);
219 EXPECT_EQ(1001LL, p.mLastTimestampSeen);
220
221 p.OnLogEvent(&event2, false);
222 EXPECT_EQ(2UL, p.mLogCount);
223 EXPECT_EQ(1002LL, p.mLargestTimestampSeen);
224 EXPECT_EQ(1002LL, p.mLastTimestampSeen);
225
226 p.OnLogEvent(&event3, false);
227 EXPECT_EQ(3UL, p.mLogCount);
228 EXPECT_EQ(1005LL, p.mLargestTimestampSeen);
229 EXPECT_EQ(1005LL, p.mLastTimestampSeen);
230
231 p.OnLogEvent(&event4, false);
232 EXPECT_EQ(4UL, p.mLogCount);
233 EXPECT_EQ(1005LL, p.mLargestTimestampSeen);
234 EXPECT_EQ(1004LL, p.mLastTimestampSeen);
235 EXPECT_FALSE(p.mInReconnection);
236
237 // Reconnect happens, event1 out of buffer. Read event2
238 p.OnLogEvent(&event2, true);
239 EXPECT_EQ(4UL, p.mLogCount);
240 EXPECT_EQ(1005LL, p.mLargestTimestampSeen);
241 EXPECT_EQ(1004LL, p.mLastTimestampSeen);
242 EXPECT_TRUE(p.mInReconnection);
243
244 p.OnLogEvent(&event3, false);
245 EXPECT_EQ(4UL, p.mLogCount);
246 EXPECT_EQ(1005LL, p.mLargestTimestampSeen);
247 EXPECT_EQ(1004LL, p.mLastTimestampSeen);
248 EXPECT_TRUE(p.mInReconnection);
249
250 p.OnLogEvent(&event4, false);
251 EXPECT_EQ(4UL, p.mLogCount);
252 EXPECT_EQ(1005LL, p.mLargestTimestampSeen);
253 EXPECT_EQ(1004LL, p.mLastTimestampSeen);
254 EXPECT_FALSE(p.mInReconnection);
255
256 // Fresh event comes.
257 p.OnLogEvent(&event5, false);
258 EXPECT_EQ(5UL, p.mLogCount);
259 EXPECT_EQ(1005LL, p.mLargestTimestampSeen);
260 EXPECT_EQ(999LL, p.mLastTimestampSeen);
261
262 p.OnLogEvent(&event6, false);
263 EXPECT_EQ(6UL, p.mLogCount);
264 EXPECT_EQ(2000LL, p.mLargestTimestampSeen);
265 EXPECT_EQ(2000LL, p.mLastTimestampSeen);
266
267 // Reconnect happens, read from event4
268 p.OnLogEvent(&event4, true);
269 EXPECT_EQ(6UL, p.mLogCount);
270 EXPECT_EQ(2000LL, p.mLargestTimestampSeen);
271 EXPECT_EQ(2000LL, p.mLastTimestampSeen);
272 EXPECT_TRUE(p.mInReconnection);
273
274 p.OnLogEvent(&event5, false);
275 EXPECT_EQ(6UL, p.mLogCount);
276 EXPECT_EQ(2000LL, p.mLargestTimestampSeen);
277 EXPECT_EQ(2000LL, p.mLastTimestampSeen);
278 EXPECT_TRUE(p.mInReconnection);
279
280 // Before we get out of reconnection state, it reconnects again.
281 p.OnLogEvent(&event5, true);
282 EXPECT_EQ(6UL, p.mLogCount);
283 EXPECT_EQ(2000LL, p.mLargestTimestampSeen);
284 EXPECT_EQ(2000LL, p.mLastTimestampSeen);
285 EXPECT_TRUE(p.mInReconnection);
286
287 p.OnLogEvent(&event6, false);
288 EXPECT_EQ(6UL, p.mLogCount);
289 EXPECT_EQ(2000LL, p.mLargestTimestampSeen);
290 EXPECT_EQ(2000LL, p.mLastTimestampSeen);
291 EXPECT_FALSE(p.mInReconnection);
292 EXPECT_EQ(0, p.mLogLossCount);
293
294 // it reconnects again. All old events are gone. We lose CP.
295 p.OnLogEvent(&event7, true);
296 EXPECT_EQ(7UL, p.mLogCount);
297 EXPECT_EQ(3000LL, p.mLargestTimestampSeen);
298 EXPECT_EQ(3000LL, p.mLastTimestampSeen);
299 EXPECT_EQ(1, p.mLogLossCount);
300 EXPECT_FALSE(p.mInReconnection);
301}
302
David Chend9269e22017-12-05 13:43:51 -0800303#else
304GTEST_LOG_(INFO) << "This test does nothing.\n";
305#endif
306
307} // namespace statsd
308} // namespace os
Yao Chen288c6002017-12-12 13:43:18 -0800309} // namespace android