blob: 00f336a4986d2eeca1189a887ee02bc5b28dd396 [file] [log] [blame]
Yangster-mac20877162017-12-22 17:19:39 -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
Muhammad Qureshi3f9c3302020-04-01 16:11:53 -070015#include "src/logd/LogEvent.h"
16
Yangster-mac20877162017-12-22 17:19:39 -080017#include <gtest/gtest.h>
Ruchir Rastogi13296512020-03-24 10:59:49 -070018
Yao Chen8c433862018-10-24 14:09:20 -070019#include "frameworks/base/cmds/statsd/src/atoms.pb.h"
20#include "frameworks/base/core/proto/android/stats/launcher/launcher.pb.h"
Ruchir Rastogi13296512020-03-24 10:59:49 -070021#include "log/log_event_list.h"
Ruchir Rastogi13296512020-03-24 10:59:49 -070022#include "stats_event.h"
Ruchir Rastogi1fb525e2019-11-07 14:08:24 -080023
Yangster-mac20877162017-12-22 17:19:39 -080024#ifdef __ANDROID__
25
26namespace android {
27namespace os {
28namespace statsd {
29
Yao Chen8c433862018-10-24 14:09:20 -070030using std::string;
Ruchir Rastogi1fb525e2019-11-07 14:08:24 -080031using std::vector;
Yao Chen8c433862018-10-24 14:09:20 -070032using util::ProtoOutputStream;
Joe Onorato99598ee2019-02-11 15:55:13 +000033using util::ProtoReader;
Yao Chen8c433862018-10-24 14:09:20 -070034
Muhammad Qureshi3f9c3302020-04-01 16:11:53 -070035namespace {
36
Ruchir Rastogi1fb525e2019-11-07 14:08:24 -080037Field getField(int32_t tag, const vector<int32_t>& pos, int32_t depth, const vector<bool>& last) {
38 Field f(tag, (int32_t*)pos.data(), depth);
39
40 // For loop starts at 1 because the last field at depth 0 is not decorated.
41 for (int i = 1; i < depth; i++) {
42 if (last[i]) f.decorateLastPos(i);
43 }
44
45 return f;
46}
47
Muhammad Qureshi3f9c3302020-04-01 16:11:53 -070048void createIntWithBoolAnnotationLogEvent(LogEvent* logEvent, uint8_t annotationId,
49 bool annotationValue) {
50 AStatsEvent* statsEvent = AStatsEvent_obtain();
51 AStatsEvent_setAtomId(statsEvent, /*atomId=*/100);
52 AStatsEvent_writeInt32(statsEvent, 10);
53 AStatsEvent_addBoolAnnotation(statsEvent, annotationId, annotationValue);
54 AStatsEvent_build(statsEvent);
55
56 size_t size;
57 uint8_t* buf = AStatsEvent_getBuffer(statsEvent, &size);
58 EXPECT_TRUE(logEvent->parseBuffer(buf, size));
59
60 AStatsEvent_release(statsEvent);
61}
62
63void createIntWithIntAnnotationLogEvent(LogEvent* logEvent, uint8_t annotationId,
64 int annotationValue) {
65 AStatsEvent* statsEvent = AStatsEvent_obtain();
66 AStatsEvent_setAtomId(statsEvent, /*atomId=*/100);
67 AStatsEvent_writeInt32(statsEvent, 10);
68 AStatsEvent_addInt32Annotation(statsEvent, annotationId, annotationValue);
69 AStatsEvent_build(statsEvent);
70
71 size_t size;
72 uint8_t* buf = AStatsEvent_getBuffer(statsEvent, &size);
73 EXPECT_TRUE(logEvent->parseBuffer(buf, size));
74
75 AStatsEvent_release(statsEvent);
76}
77
78} // anonymous namespace
79
Ruchir Rastogi1fb525e2019-11-07 14:08:24 -080080TEST(LogEventTest, TestPrimitiveParsing) {
Tej Singhb26d0442020-01-31 16:18:21 -080081 AStatsEvent* event = AStatsEvent_obtain();
82 AStatsEvent_setAtomId(event, 100);
83 AStatsEvent_writeInt32(event, 10);
84 AStatsEvent_writeInt64(event, 0x123456789);
85 AStatsEvent_writeFloat(event, 2.0);
86 AStatsEvent_writeBool(event, true);
87 AStatsEvent_build(event);
Ruchir Rastogi1fb525e2019-11-07 14:08:24 -080088
89 size_t size;
Tej Singhb26d0442020-01-31 16:18:21 -080090 uint8_t* buf = AStatsEvent_getBuffer(event, &size);
Ruchir Rastogi1fb525e2019-11-07 14:08:24 -080091
Ruchir Rastogidfd63d42020-02-20 17:54:13 -080092 LogEvent logEvent(/*uid=*/1000, /*pid=*/1001);
93 EXPECT_TRUE(logEvent.parseBuffer(buf, size));
94
Ruchir Rastogi1fb525e2019-11-07 14:08:24 -080095 EXPECT_EQ(100, logEvent.GetTagId());
Ruchir Rastogiab71ef02020-01-30 01:24:50 -080096 EXPECT_EQ(1000, logEvent.GetUid());
97 EXPECT_EQ(1001, logEvent.GetPid());
Muhammad Qureshi83aaa662020-04-21 12:51:36 -070098 EXPECT_FALSE(logEvent.hasAttributionChain());
Ruchir Rastogi1fb525e2019-11-07 14:08:24 -080099
100 const vector<FieldValue>& values = logEvent.getValues();
101 EXPECT_EQ(4, values.size());
102
103 const FieldValue& int32Item = values[0];
104 Field expectedField = getField(100, {1, 1, 1}, 0, {false, false, false});
105 EXPECT_EQ(expectedField, int32Item.mField);
106 EXPECT_EQ(Type::INT, int32Item.mValue.getType());
107 EXPECT_EQ(10, int32Item.mValue.int_value);
108
109 const FieldValue& int64Item = values[1];
110 expectedField = getField(100, {2, 1, 1}, 0, {false, false, false});
111 EXPECT_EQ(expectedField, int64Item.mField);
112 EXPECT_EQ(Type::LONG, int64Item.mValue.getType());
113 EXPECT_EQ(0x123456789, int64Item.mValue.long_value);
114
115 const FieldValue& floatItem = values[2];
116 expectedField = getField(100, {3, 1, 1}, 0, {false, false, false});
117 EXPECT_EQ(expectedField, floatItem.mField);
118 EXPECT_EQ(Type::FLOAT, floatItem.mValue.getType());
119 EXPECT_EQ(2.0, floatItem.mValue.float_value);
120
121 const FieldValue& boolItem = values[3];
122 expectedField = getField(100, {4, 1, 1}, 0, {true, false, false});
123 EXPECT_EQ(expectedField, boolItem.mField);
Muhammad Qureshi3f9c3302020-04-01 16:11:53 -0700124 EXPECT_EQ(Type::INT, boolItem.mValue.getType()); // FieldValue does not support boolean type
Ruchir Rastogi1fb525e2019-11-07 14:08:24 -0800125 EXPECT_EQ(1, boolItem.mValue.int_value);
126
Tej Singhb26d0442020-01-31 16:18:21 -0800127 AStatsEvent_release(event);
Ruchir Rastogi1fb525e2019-11-07 14:08:24 -0800128}
129
Ruchir Rastogi1fb525e2019-11-07 14:08:24 -0800130TEST(LogEventTest, TestStringAndByteArrayParsing) {
Tej Singhb26d0442020-01-31 16:18:21 -0800131 AStatsEvent* event = AStatsEvent_obtain();
132 AStatsEvent_setAtomId(event, 100);
Ruchir Rastogi1fb525e2019-11-07 14:08:24 -0800133 string str = "test";
Tej Singhb26d0442020-01-31 16:18:21 -0800134 AStatsEvent_writeString(event, str.c_str());
135 AStatsEvent_writeByteArray(event, (uint8_t*)str.c_str(), str.length());
136 AStatsEvent_build(event);
Ruchir Rastogi1fb525e2019-11-07 14:08:24 -0800137
138 size_t size;
Tej Singhb26d0442020-01-31 16:18:21 -0800139 uint8_t* buf = AStatsEvent_getBuffer(event, &size);
Ruchir Rastogi1fb525e2019-11-07 14:08:24 -0800140
Muhammad Qureshi3f9c3302020-04-01 16:11:53 -0700141 LogEvent logEvent(/*uid=*/1000, /*pid=*/1001);
Ruchir Rastogidfd63d42020-02-20 17:54:13 -0800142 EXPECT_TRUE(logEvent.parseBuffer(buf, size));
143
Ruchir Rastogi1fb525e2019-11-07 14:08:24 -0800144 EXPECT_EQ(100, logEvent.GetTagId());
Ruchir Rastogiab71ef02020-01-30 01:24:50 -0800145 EXPECT_EQ(1000, logEvent.GetUid());
146 EXPECT_EQ(1001, logEvent.GetPid());
Muhammad Qureshi83aaa662020-04-21 12:51:36 -0700147 EXPECT_FALSE(logEvent.hasAttributionChain());
Ruchir Rastogi1fb525e2019-11-07 14:08:24 -0800148
149 const vector<FieldValue>& values = logEvent.getValues();
150 EXPECT_EQ(2, values.size());
151
152 const FieldValue& stringItem = values[0];
153 Field expectedField = getField(100, {1, 1, 1}, 0, {false, false, false});
154 EXPECT_EQ(expectedField, stringItem.mField);
155 EXPECT_EQ(Type::STRING, stringItem.mValue.getType());
156 EXPECT_EQ(str, stringItem.mValue.str_value);
157
158 const FieldValue& storageItem = values[1];
159 expectedField = getField(100, {2, 1, 1}, 0, {true, false, false});
160 EXPECT_EQ(expectedField, storageItem.mField);
161 EXPECT_EQ(Type::STORAGE, storageItem.mValue.getType());
162 vector<uint8_t> expectedValue = {'t', 'e', 's', 't'};
163 EXPECT_EQ(expectedValue, storageItem.mValue.storage_value);
164
Tej Singhb26d0442020-01-31 16:18:21 -0800165 AStatsEvent_release(event);
Ruchir Rastogi1fb525e2019-11-07 14:08:24 -0800166}
167
168TEST(LogEventTest, TestEmptyString) {
Tej Singhb26d0442020-01-31 16:18:21 -0800169 AStatsEvent* event = AStatsEvent_obtain();
170 AStatsEvent_setAtomId(event, 100);
Ruchir Rastogi1fb525e2019-11-07 14:08:24 -0800171 string empty = "";
Tej Singhb26d0442020-01-31 16:18:21 -0800172 AStatsEvent_writeString(event, empty.c_str());
173 AStatsEvent_build(event);
Ruchir Rastogi1fb525e2019-11-07 14:08:24 -0800174
175 size_t size;
Tej Singhb26d0442020-01-31 16:18:21 -0800176 uint8_t* buf = AStatsEvent_getBuffer(event, &size);
Ruchir Rastogi1fb525e2019-11-07 14:08:24 -0800177
Muhammad Qureshi3f9c3302020-04-01 16:11:53 -0700178 LogEvent logEvent(/*uid=*/1000, /*pid=*/1001);
Ruchir Rastogidfd63d42020-02-20 17:54:13 -0800179 EXPECT_TRUE(logEvent.parseBuffer(buf, size));
180
Ruchir Rastogi1fb525e2019-11-07 14:08:24 -0800181 EXPECT_EQ(100, logEvent.GetTagId());
Ruchir Rastogiab71ef02020-01-30 01:24:50 -0800182 EXPECT_EQ(1000, logEvent.GetUid());
183 EXPECT_EQ(1001, logEvent.GetPid());
Muhammad Qureshi83aaa662020-04-21 12:51:36 -0700184 EXPECT_FALSE(logEvent.hasAttributionChain());
Ruchir Rastogi1fb525e2019-11-07 14:08:24 -0800185
186 const vector<FieldValue>& values = logEvent.getValues();
187 EXPECT_EQ(1, values.size());
188
189 const FieldValue& item = values[0];
190 Field expectedField = getField(100, {1, 1, 1}, 0, {true, false, false});
191 EXPECT_EQ(expectedField, item.mField);
192 EXPECT_EQ(Type::STRING, item.mValue.getType());
193 EXPECT_EQ(empty, item.mValue.str_value);
194
Tej Singhb26d0442020-01-31 16:18:21 -0800195 AStatsEvent_release(event);
Ruchir Rastogi1fb525e2019-11-07 14:08:24 -0800196}
197
198TEST(LogEventTest, TestByteArrayWithNullCharacter) {
Tej Singhb26d0442020-01-31 16:18:21 -0800199 AStatsEvent* event = AStatsEvent_obtain();
200 AStatsEvent_setAtomId(event, 100);
Ruchir Rastogi1fb525e2019-11-07 14:08:24 -0800201 uint8_t message[] = {'\t', 'e', '\0', 's', 't'};
Tej Singhb26d0442020-01-31 16:18:21 -0800202 AStatsEvent_writeByteArray(event, message, 5);
203 AStatsEvent_build(event);
Ruchir Rastogi1fb525e2019-11-07 14:08:24 -0800204
205 size_t size;
Tej Singhb26d0442020-01-31 16:18:21 -0800206 uint8_t* buf = AStatsEvent_getBuffer(event, &size);
Ruchir Rastogi1fb525e2019-11-07 14:08:24 -0800207
Muhammad Qureshi3f9c3302020-04-01 16:11:53 -0700208 LogEvent logEvent(/*uid=*/1000, /*pid=*/1001);
Ruchir Rastogidfd63d42020-02-20 17:54:13 -0800209 EXPECT_TRUE(logEvent.parseBuffer(buf, size));
210
Ruchir Rastogi1fb525e2019-11-07 14:08:24 -0800211 EXPECT_EQ(100, logEvent.GetTagId());
Ruchir Rastogiab71ef02020-01-30 01:24:50 -0800212 EXPECT_EQ(1000, logEvent.GetUid());
213 EXPECT_EQ(1001, logEvent.GetPid());
Ruchir Rastogi1fb525e2019-11-07 14:08:24 -0800214
215 const vector<FieldValue>& values = logEvent.getValues();
216 EXPECT_EQ(1, values.size());
217
218 const FieldValue& item = values[0];
219 Field expectedField = getField(100, {1, 1, 1}, 0, {true, false, false});
220 EXPECT_EQ(expectedField, item.mField);
221 EXPECT_EQ(Type::STORAGE, item.mValue.getType());
222 vector<uint8_t> expectedValue(message, message + 5);
223 EXPECT_EQ(expectedValue, item.mValue.storage_value);
224
Tej Singhb26d0442020-01-31 16:18:21 -0800225 AStatsEvent_release(event);
Ruchir Rastogi1fb525e2019-11-07 14:08:24 -0800226}
227
228TEST(LogEventTest, TestAttributionChain) {
Tej Singhb26d0442020-01-31 16:18:21 -0800229 AStatsEvent* event = AStatsEvent_obtain();
230 AStatsEvent_setAtomId(event, 100);
Ruchir Rastogi1fb525e2019-11-07 14:08:24 -0800231
232 string tag1 = "tag1";
233 string tag2 = "tag2";
234
235 uint32_t uids[] = {1001, 1002};
236 const char* tags[] = {tag1.c_str(), tag2.c_str()};
237
Tej Singhb26d0442020-01-31 16:18:21 -0800238 AStatsEvent_writeAttributionChain(event, uids, tags, 2);
239 AStatsEvent_build(event);
Ruchir Rastogi1fb525e2019-11-07 14:08:24 -0800240
241 size_t size;
Tej Singhb26d0442020-01-31 16:18:21 -0800242 uint8_t* buf = AStatsEvent_getBuffer(event, &size);
Ruchir Rastogi1fb525e2019-11-07 14:08:24 -0800243
Muhammad Qureshi3f9c3302020-04-01 16:11:53 -0700244 LogEvent logEvent(/*uid=*/1000, /*pid=*/1001);
Ruchir Rastogidfd63d42020-02-20 17:54:13 -0800245 EXPECT_TRUE(logEvent.parseBuffer(buf, size));
246
Ruchir Rastogi1fb525e2019-11-07 14:08:24 -0800247 EXPECT_EQ(100, logEvent.GetTagId());
Ruchir Rastogiab71ef02020-01-30 01:24:50 -0800248 EXPECT_EQ(1000, logEvent.GetUid());
249 EXPECT_EQ(1001, logEvent.GetPid());
Ruchir Rastogi1fb525e2019-11-07 14:08:24 -0800250
251 const vector<FieldValue>& values = logEvent.getValues();
Muhammad Qureshi3f9c3302020-04-01 16:11:53 -0700252 EXPECT_EQ(4, values.size()); // 2 per attribution node
Ruchir Rastogi1fb525e2019-11-07 14:08:24 -0800253
Muhammad Qureshi83aaa662020-04-21 12:51:36 -0700254 std::pair<int, int> attrIndexRange;
255 EXPECT_TRUE(logEvent.hasAttributionChain(&attrIndexRange));
256 EXPECT_EQ(0, attrIndexRange.first);
257 EXPECT_EQ(3, attrIndexRange.second);
258
Ruchir Rastogi1fb525e2019-11-07 14:08:24 -0800259 // Check first attribution node
260 const FieldValue& uid1Item = values[0];
261 Field expectedField = getField(100, {1, 1, 1}, 2, {true, false, false});
262 EXPECT_EQ(expectedField, uid1Item.mField);
263 EXPECT_EQ(Type::INT, uid1Item.mValue.getType());
264 EXPECT_EQ(1001, uid1Item.mValue.int_value);
265
266 const FieldValue& tag1Item = values[1];
267 expectedField = getField(100, {1, 1, 2}, 2, {true, false, true});
268 EXPECT_EQ(expectedField, tag1Item.mField);
269 EXPECT_EQ(Type::STRING, tag1Item.mValue.getType());
270 EXPECT_EQ(tag1, tag1Item.mValue.str_value);
271
272 // Check second attribution nodes
273 const FieldValue& uid2Item = values[2];
274 expectedField = getField(100, {1, 2, 1}, 2, {true, true, false});
275 EXPECT_EQ(expectedField, uid2Item.mField);
276 EXPECT_EQ(Type::INT, uid2Item.mValue.getType());
277 EXPECT_EQ(1002, uid2Item.mValue.int_value);
278
279 const FieldValue& tag2Item = values[3];
280 expectedField = getField(100, {1, 2, 2}, 2, {true, true, true});
281 EXPECT_EQ(expectedField, tag2Item.mField);
282 EXPECT_EQ(Type::STRING, tag2Item.mValue.getType());
283 EXPECT_EQ(tag2, tag2Item.mValue.str_value);
284
Tej Singhb26d0442020-01-31 16:18:21 -0800285 AStatsEvent_release(event);
Ruchir Rastogi1fb525e2019-11-07 14:08:24 -0800286}
287
Ruchir Rastogi13296512020-03-24 10:59:49 -0700288TEST(LogEventTest, TestAnnotationIdIsUid) {
289 LogEvent event(/*uid=*/0, /*pid=*/0);
290 createIntWithBoolAnnotationLogEvent(&event, ANNOTATION_ID_IS_UID, true);
291
292 const vector<FieldValue>& values = event.getValues();
293 EXPECT_EQ(values.size(), 1);
294 EXPECT_EQ(event.getUidFieldIndex(), 0);
295}
296
297TEST(LogEventTest, TestAnnotationIdStateNested) {
298 LogEvent event(/*uid=*/0, /*pid=*/0);
299 createIntWithBoolAnnotationLogEvent(&event, ANNOTATION_ID_STATE_NESTED, true);
300
301 const vector<FieldValue>& values = event.getValues();
302 EXPECT_EQ(values.size(), 1);
303 EXPECT_TRUE(values[0].mAnnotations.isNested());
304}
305
Ruchir Rastogi13296512020-03-24 10:59:49 -0700306TEST(LogEventTest, TestPrimaryFieldAnnotation) {
307 LogEvent event(/*uid=*/0, /*pid=*/0);
Muhammad Qureshi3f9c3302020-04-01 16:11:53 -0700308 createIntWithBoolAnnotationLogEvent(&event, ANNOTATION_ID_PRIMARY_FIELD, true);
Ruchir Rastogi13296512020-03-24 10:59:49 -0700309
310 const vector<FieldValue>& values = event.getValues();
311 EXPECT_EQ(values.size(), 1);
312 EXPECT_TRUE(values[0].mAnnotations.isPrimaryField());
313}
314
315TEST(LogEventTest, TestExclusiveStateAnnotation) {
316 LogEvent event(/*uid=*/0, /*pid=*/0);
Muhammad Qureshi3f9c3302020-04-01 16:11:53 -0700317 createIntWithBoolAnnotationLogEvent(&event, ANNOTATION_ID_EXCLUSIVE_STATE, true);
Ruchir Rastogi13296512020-03-24 10:59:49 -0700318
319 const vector<FieldValue>& values = event.getValues();
320 EXPECT_EQ(values.size(), 1);
321 EXPECT_TRUE(values[0].mAnnotations.isExclusiveState());
322}
323
324TEST(LogEventTest, TestPrimaryFieldFirstUidAnnotation) {
325 // Event has 10 ints and then an attribution chain
326 int numInts = 10;
327 int firstUidInChainIndex = numInts;
328 string tag1 = "tag1";
329 string tag2 = "tag2";
330 uint32_t uids[] = {1001, 1002};
331 const char* tags[] = {tag1.c_str(), tag2.c_str()};
332
333 // Construct AStatsEvent
334 AStatsEvent* statsEvent = AStatsEvent_obtain();
335 AStatsEvent_setAtomId(statsEvent, 100);
336 for (int i = 0; i < numInts; i++) {
337 AStatsEvent_writeInt32(statsEvent, 10);
338 }
339 AStatsEvent_writeAttributionChain(statsEvent, uids, tags, 2);
Muhammad Qureshi3f9c3302020-04-01 16:11:53 -0700340 AStatsEvent_addBoolAnnotation(statsEvent, ANNOTATION_ID_PRIMARY_FIELD_FIRST_UID, true);
Ruchir Rastogi13296512020-03-24 10:59:49 -0700341 AStatsEvent_build(statsEvent);
342
343 // Construct LogEvent
344 size_t size;
345 uint8_t* buf = AStatsEvent_getBuffer(statsEvent, &size);
346 LogEvent logEvent(/*uid=*/0, /*pid=*/0);
347 EXPECT_TRUE(logEvent.parseBuffer(buf, size));
348 AStatsEvent_release(statsEvent);
349
350 // Check annotation
351 const vector<FieldValue>& values = logEvent.getValues();
352 EXPECT_EQ(values.size(), numInts + 4);
353 EXPECT_TRUE(values[firstUidInChainIndex].mAnnotations.isPrimaryField());
354}
355
356TEST(LogEventTest, TestResetStateAnnotation) {
357 int32_t resetState = 10;
358 LogEvent event(/*uid=*/0, /*pid=*/0);
Muhammad Qureshi3f9c3302020-04-01 16:11:53 -0700359 createIntWithIntAnnotationLogEvent(&event, ANNOTATION_ID_TRIGGER_STATE_RESET, resetState);
Ruchir Rastogi13296512020-03-24 10:59:49 -0700360
361 const vector<FieldValue>& values = event.getValues();
362 EXPECT_EQ(values.size(), 1);
Ruchir Rastogi48dbf832020-04-20 16:50:46 -0700363 EXPECT_EQ(event.getResetState(), resetState);
Ruchir Rastogi13296512020-03-24 10:59:49 -0700364}
365
Yangster-mac20877162017-12-22 17:19:39 -0800366} // namespace statsd
367} // namespace os
368} // namespace android
369#else
370GTEST_LOG_(INFO) << "This test does nothing.\n";
Howard Ro4078dd42018-09-27 17:41:08 -0700371#endif