1 // 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 "src/logd/LogEvent.h"
16
17 #include <gtest/gtest.h>
18
19 #include "flags/FlagProvider.h"
20 #include "frameworks/proto_logging/stats/atoms.pb.h"
21 #include "frameworks/proto_logging/stats/enums/stats/launcher/launcher.pb.h"
22 #include "log/log_event_list.h"
23 #include "stats_annotations.h"
24 #include "stats_event.h"
25 #include "statsd_test_util.h"
26
27 #ifdef __ANDROID__
28
29 namespace android {
30 namespace os {
31 namespace statsd {
32
33 using std::string;
34 using std::vector;
35 using ::util::ProtoOutputStream;
36 using ::util::ProtoReader;
37
38 namespace {
39
getField(int32_t tag,const vector<int32_t> & pos,int32_t depth,const vector<uint8_t> & last)40 Field getField(int32_t tag, const vector<int32_t>& pos, int32_t depth,
41 const vector<uint8_t>& last) {
42 Field f(tag, (int32_t*)pos.data(), depth);
43
44 // only decorate last position for depths with repeated fields (depth 1)
45 if (depth > 0 && last[1]) f.decorateLastPos(1);
46
47 return f;
48 }
49
createFieldWithBoolAnnotationLogEvent(LogEvent * logEvent,uint8_t typeId,uint8_t annotationId,bool annotationValue,bool doHeaderPrefetch)50 bool createFieldWithBoolAnnotationLogEvent(LogEvent* logEvent, uint8_t typeId, uint8_t annotationId,
51 bool annotationValue, bool doHeaderPrefetch) {
52 AStatsEvent* statsEvent = AStatsEvent_obtain();
53 createStatsEvent(statsEvent, typeId, /*atomId=*/100);
54 AStatsEvent_addBoolAnnotation(statsEvent, annotationId, annotationValue);
55 AStatsEvent_build(statsEvent);
56
57 size_t size;
58 const uint8_t* buf = AStatsEvent_getBuffer(statsEvent, &size);
59 if (doHeaderPrefetch) {
60 // Testing LogEvent header prefetch logic
61 const LogEvent::BodyBufferInfo bodyInfo = logEvent->parseHeader(buf, size);
62 logEvent->parseBody(bodyInfo);
63 } else {
64 logEvent->parseBuffer(buf, size);
65 }
66 AStatsEvent_release(statsEvent);
67
68 return logEvent->isValid();
69 }
70
createFieldWithIntAnnotationLogEvent(LogEvent * logEvent,uint8_t typeId,uint8_t annotationId,int annotationValue,bool doHeaderPrefetch)71 bool createFieldWithIntAnnotationLogEvent(LogEvent* logEvent, uint8_t typeId, uint8_t annotationId,
72 int annotationValue, bool doHeaderPrefetch) {
73 AStatsEvent* statsEvent = AStatsEvent_obtain();
74 createStatsEvent(statsEvent, typeId, /*atomId=*/100);
75 AStatsEvent_addInt32Annotation(statsEvent, annotationId, annotationValue);
76 AStatsEvent_build(statsEvent);
77
78 size_t size;
79 const uint8_t* buf = AStatsEvent_getBuffer(statsEvent, &size);
80 if (doHeaderPrefetch) {
81 // Testing LogEvent header prefetch logic
82 const LogEvent::BodyBufferInfo bodyInfo = logEvent->parseHeader(buf, size);
83 logEvent->parseBody(bodyInfo);
84 } else {
85 logEvent->parseBuffer(buf, size);
86 }
87 AStatsEvent_release(statsEvent);
88
89 return logEvent->isValid();
90 }
91
createAtomLevelIntAnnotationLogEvent(LogEvent * logEvent,uint8_t typeId,uint8_t annotationId,int annotationValue,bool doHeaderPrefetch)92 bool createAtomLevelIntAnnotationLogEvent(LogEvent* logEvent, uint8_t typeId, uint8_t annotationId,
93 int annotationValue, bool doHeaderPrefetch) {
94 AStatsEvent* statsEvent = AStatsEvent_obtain();
95 AStatsEvent_setAtomId(statsEvent, /*atomId=*/100);
96 AStatsEvent_addInt32Annotation(statsEvent, annotationId, annotationValue);
97 fillStatsEventWithSampleValue(statsEvent, typeId);
98 AStatsEvent_build(statsEvent);
99
100 size_t size;
101 const uint8_t* buf = AStatsEvent_getBuffer(statsEvent, &size);
102 if (doHeaderPrefetch) {
103 // Testing LogEvent header prefetch logic
104 const LogEvent::BodyBufferInfo bodyInfo = logEvent->parseHeader(buf, size);
105 logEvent->parseBody(bodyInfo);
106 } else {
107 logEvent->parseBuffer(buf, size);
108 }
109 AStatsEvent_release(statsEvent);
110
111 return logEvent->isValid();
112 }
113
createAtomLevelBoolAnnotationLogEvent(LogEvent * logEvent,uint8_t typeId,uint8_t annotationId,bool annotationValue,bool doHeaderPrefetch)114 bool createAtomLevelBoolAnnotationLogEvent(LogEvent* logEvent, uint8_t typeId, uint8_t annotationId,
115 bool annotationValue, bool doHeaderPrefetch) {
116 AStatsEvent* statsEvent = AStatsEvent_obtain();
117 AStatsEvent_setAtomId(statsEvent, /*atomId=*/100);
118 AStatsEvent_addBoolAnnotation(statsEvent, annotationId, annotationValue);
119 fillStatsEventWithSampleValue(statsEvent, typeId);
120 AStatsEvent_build(statsEvent);
121
122 size_t size;
123 const uint8_t* buf = AStatsEvent_getBuffer(statsEvent, &size);
124 if (doHeaderPrefetch) {
125 // Testing LogEvent header prefetch logic
126 const LogEvent::BodyBufferInfo bodyInfo = logEvent->parseHeader(buf, size);
127 logEvent->parseBody(bodyInfo);
128 } else {
129 logEvent->parseBuffer(buf, size);
130 }
131 AStatsEvent_release(statsEvent);
132
133 return logEvent->isValid();
134 }
135
136 } // anonymous namespace
137
138 // Setup for parameterized tests.
139 class LogEventTestBadAnnotationFieldTypes : public testing::TestWithParam<std::tuple<int, bool>> {
140 public:
ToString(testing::TestParamInfo<std::tuple<int,bool>> info)141 static std::string ToString(testing::TestParamInfo<std::tuple<int, bool>> info) {
142 const std::string boolName = std::get<1>(info.param) ? "_prefetchTrue" : "_prefetchFalse";
143
144 switch (std::get<0>(info.param)) {
145 case INT32_TYPE:
146 return "Int32" + boolName;
147 case INT64_TYPE:
148 return "Int64" + boolName;
149 case STRING_TYPE:
150 return "String" + boolName;
151 case LIST_TYPE:
152 return "List" + boolName;
153 case FLOAT_TYPE:
154 return "Float" + boolName;
155 case BYTE_ARRAY_TYPE:
156 return "ByteArray" + boolName;
157 case ATTRIBUTION_CHAIN_TYPE:
158 return "AttributionChain" + boolName;
159 default:
160 return "Unknown" + boolName;
161 }
162 }
163 };
164
165 // TODO(b/222539899): Add BOOL_TYPE value once parseAnnotations is updated to check specific
166 // typeIds. BOOL_TYPE should be a bad field type for is_uid, nested, and reset state annotations.
167 INSTANTIATE_TEST_SUITE_P(BadAnnotationFieldTypes, LogEventTestBadAnnotationFieldTypes,
168 testing::Combine(testing::Values(INT32_TYPE, INT64_TYPE, STRING_TYPE,
169 LIST_TYPE, FLOAT_TYPE, BYTE_ARRAY_TYPE,
170 ATTRIBUTION_CHAIN_TYPE),
171 testing::Bool()),
172 LogEventTestBadAnnotationFieldTypes::ToString);
173
174 class LogEventTest : public testing::TestWithParam<bool> {
175 public:
ParseBuffer(LogEvent & logEvent,const uint8_t * buf,size_t size)176 bool ParseBuffer(LogEvent& logEvent, const uint8_t* buf, size_t size) {
177 size_t bufferOffset = 0;
178 if (GetParam()) {
179 // Testing LogEvent header prefetch logic
180 const LogEvent::BodyBufferInfo bodyInfo = logEvent.parseHeader(buf, size);
181 EXPECT_TRUE(logEvent.isParsedHeaderOnly());
182 const bool parseResult = logEvent.parseBody(bodyInfo);
183 EXPECT_EQ(parseResult, logEvent.isValid());
184 EXPECT_FALSE(logEvent.isParsedHeaderOnly());
185 } else {
186 const bool parseResult = logEvent.parseBuffer(buf, size);
187 EXPECT_EQ(parseResult, logEvent.isValid());
188 EXPECT_FALSE(logEvent.isParsedHeaderOnly());
189 }
190 return logEvent.isValid();
191 }
192
ToString(testing::TestParamInfo<bool> info)193 static std::string ToString(testing::TestParamInfo<bool> info) {
194 return info.param ? "PrefetchTrue" : "PrefetchFalse";
195 }
196
197 public:
198 void doTestArrayParsing() __INTRODUCED_IN(__ANDROID_API_T__);
199 void doTestEmptyStringArray() __INTRODUCED_IN(__ANDROID_API_T__);
200 void doTestArrayTooManyElements() __INTRODUCED_IN(__ANDROID_API_T__);
201 void doTestEmptyArray() __INTRODUCED_IN(__ANDROID_API_T__);
202 void doTestEmptyArrayWithAnnotations() __INTRODUCED_IN(__ANDROID_API_T__);
203 void doTestAnnotationIdIsUid_RepeatedIntAndOtherFields() __INTRODUCED_IN(__ANDROID_API_T__);
204 void doTestAnnotationIdIsUid_RepeatedIntOneEntry() __INTRODUCED_IN(__ANDROID_API_T__);
205 void doTestAnnotationIdIsUid_EmptyIntArray() __INTRODUCED_IN(__ANDROID_API_T__);
206 void doTestAnnotationIdIsUid_BadRepeatedInt64() __INTRODUCED_IN(__ANDROID_API_T__);
207 void doTestAnnotationIdIsUid_BadRepeatedString() __INTRODUCED_IN(__ANDROID_API_T__);
208 void doTestUidAnnotationWithInt8MaxValues() __INTRODUCED_IN(__ANDROID_API_T__);
209 void doTestInvalidBufferParsing() __INTRODUCED_IN(__ANDROID_API_T__);
210 };
211
212 INSTANTIATE_TEST_SUITE_P(LogEventTestBufferParsing, LogEventTest, testing::Bool(),
213 LogEventTest::ToString);
214
TEST_P(LogEventTest,TestPrimitiveParsing)215 TEST_P(LogEventTest, TestPrimitiveParsing) {
216 AStatsEvent* event = AStatsEvent_obtain();
217 AStatsEvent_setAtomId(event, 100);
218 AStatsEvent_writeInt32(event, 10);
219 AStatsEvent_writeInt64(event, 0x123456789);
220 AStatsEvent_writeFloat(event, 2.0);
221 AStatsEvent_writeBool(event, true);
222 AStatsEvent_build(event);
223
224 size_t size;
225 const uint8_t* buf = AStatsEvent_getBuffer(event, &size);
226
227 LogEvent logEvent(/*uid=*/1000, /*pid=*/1001);
228 EXPECT_TRUE(ParseBuffer(logEvent, buf, size));
229
230 EXPECT_EQ(100, logEvent.GetTagId());
231 EXPECT_EQ(1000, logEvent.GetUid());
232 EXPECT_EQ(1001, logEvent.GetPid());
233 EXPECT_FALSE(logEvent.hasAttributionChain());
234
235 const vector<FieldValue>& values = logEvent.getValues();
236 ASSERT_EQ(4, values.size());
237
238 const FieldValue& int32Item = values[0];
239 Field expectedField = getField(100, {1, 1, 1}, 0, {false, false, false});
240 EXPECT_EQ(expectedField, int32Item.mField);
241 EXPECT_EQ(Type::INT, int32Item.mValue.getType());
242 EXPECT_EQ(10, int32Item.mValue.int_value);
243
244 const FieldValue& int64Item = values[1];
245 expectedField = getField(100, {2, 1, 1}, 0, {false, false, false});
246 EXPECT_EQ(expectedField, int64Item.mField);
247 EXPECT_EQ(Type::LONG, int64Item.mValue.getType());
248 EXPECT_EQ(0x123456789, int64Item.mValue.long_value);
249
250 const FieldValue& floatItem = values[2];
251 expectedField = getField(100, {3, 1, 1}, 0, {false, false, false});
252 EXPECT_EQ(expectedField, floatItem.mField);
253 EXPECT_EQ(Type::FLOAT, floatItem.mValue.getType());
254 EXPECT_EQ(2.0, floatItem.mValue.float_value);
255
256 const FieldValue& boolItem = values[3];
257 expectedField = getField(100, {4, 1, 1}, 0, {true, false, false});
258 EXPECT_EQ(expectedField, boolItem.mField);
259 EXPECT_EQ(Type::INT, boolItem.mValue.getType()); // FieldValue does not support boolean type
260 EXPECT_EQ(1, boolItem.mValue.int_value);
261
262 AStatsEvent_release(event);
263 }
264
TEST_P(LogEventTest,TestEventWithInvalidHeaderParsing)265 TEST_P(LogEventTest, TestEventWithInvalidHeaderParsing) {
266 AStatsEvent* event = AStatsEvent_obtain();
267 AStatsEvent_setAtomId(event, 100);
268 AStatsEvent_writeInt32(event, 10);
269 AStatsEvent_writeInt64(event, 0x123456789);
270 AStatsEvent_writeFloat(event, 2.0);
271 AStatsEvent_writeBool(event, true);
272 AStatsEvent_build(event);
273
274 size_t size;
275 const uint8_t* buf = AStatsEvent_getBuffer(event, &size);
276
277 // Corrupt LogEvent header info
278 // OBJECT_TYPE | NUM_FIELDS | TIMESTAMP | ATOM_ID
279 // Corrupting first 4 bytes will be sufficient
280 uint8_t* bufMod = const_cast<uint8_t*>(buf);
281 memset(static_cast<void*>(bufMod), 4, ERROR_TYPE);
282
283 LogEvent logEvent(/*uid=*/1000, /*pid=*/1001);
284 EXPECT_FALSE(ParseBuffer(logEvent, buf, size));
285 EXPECT_FALSE(logEvent.isValid());
286 EXPECT_FALSE(logEvent.isParsedHeaderOnly());
287
288 AStatsEvent_release(event);
289 }
290
TEST(LogEventTestParsing,TestFetchHeaderOnly)291 TEST(LogEventTestParsing, TestFetchHeaderOnly) {
292 AStatsEvent* event = AStatsEvent_obtain();
293 AStatsEvent_setAtomId(event, 100);
294 AStatsEvent_writeInt32(event, 10);
295 AStatsEvent_writeInt64(event, 0x123456789);
296 AStatsEvent_writeFloat(event, 2.0);
297 AStatsEvent_writeBool(event, true);
298 AStatsEvent_build(event);
299
300 size_t size;
301 const uint8_t* buf = AStatsEvent_getBuffer(event, &size);
302
303 LogEvent logEvent(/*uid=*/1000, /*pid=*/1001);
304 const LogEvent::BodyBufferInfo bodyInfo = logEvent.parseHeader(buf, size);
305 EXPECT_TRUE(logEvent.isValid());
306 EXPECT_TRUE(logEvent.isParsedHeaderOnly());
307
308 AStatsEvent_release(event);
309
310 EXPECT_EQ(100, logEvent.GetTagId());
311 EXPECT_EQ(1000, logEvent.GetUid());
312 EXPECT_EQ(1001, logEvent.GetPid());
313 EXPECT_FALSE(logEvent.hasAttributionChain());
314 ASSERT_EQ(0, logEvent.getValues().size());
315 }
316
TEST_P(LogEventTest,TestStringAndByteArrayParsing)317 TEST_P(LogEventTest, TestStringAndByteArrayParsing) {
318 AStatsEvent* event = AStatsEvent_obtain();
319 AStatsEvent_setAtomId(event, 100);
320 string str = "test";
321 AStatsEvent_writeString(event, str.c_str());
322 AStatsEvent_writeByteArray(event, (uint8_t*)str.c_str(), str.length());
323 AStatsEvent_build(event);
324
325 size_t size;
326 const uint8_t* buf = AStatsEvent_getBuffer(event, &size);
327
328 LogEvent logEvent(/*uid=*/1000, /*pid=*/1001);
329 EXPECT_TRUE(ParseBuffer(logEvent, buf, size));
330
331 EXPECT_EQ(100, logEvent.GetTagId());
332 EXPECT_EQ(1000, logEvent.GetUid());
333 EXPECT_EQ(1001, logEvent.GetPid());
334 EXPECT_FALSE(logEvent.hasAttributionChain());
335
336 const vector<FieldValue>& values = logEvent.getValues();
337 ASSERT_EQ(2, values.size());
338
339 const FieldValue& stringItem = values[0];
340 Field expectedField = getField(100, {1, 1, 1}, 0, {false, false, false});
341 EXPECT_EQ(expectedField, stringItem.mField);
342 EXPECT_EQ(Type::STRING, stringItem.mValue.getType());
343 EXPECT_EQ(str, stringItem.mValue.str_value);
344
345 const FieldValue& storageItem = values[1];
346 expectedField = getField(100, {2, 1, 1}, 0, {true, false, false});
347 EXPECT_EQ(expectedField, storageItem.mField);
348 EXPECT_EQ(Type::STORAGE, storageItem.mValue.getType());
349 vector<uint8_t> expectedValue = {'t', 'e', 's', 't'};
350 EXPECT_EQ(expectedValue, storageItem.mValue.storage_value);
351
352 AStatsEvent_release(event);
353 }
354
TEST_P(LogEventTest,TestEmptyString)355 TEST_P(LogEventTest, TestEmptyString) {
356 AStatsEvent* event = AStatsEvent_obtain();
357 AStatsEvent_setAtomId(event, 100);
358 string empty = "";
359 AStatsEvent_writeString(event, empty.c_str());
360 AStatsEvent_build(event);
361
362 size_t size;
363 const uint8_t* buf = AStatsEvent_getBuffer(event, &size);
364
365 LogEvent logEvent(/*uid=*/1000, /*pid=*/1001);
366 EXPECT_TRUE(ParseBuffer(logEvent, buf, size));
367
368 EXPECT_EQ(100, logEvent.GetTagId());
369 EXPECT_EQ(1000, logEvent.GetUid());
370 EXPECT_EQ(1001, logEvent.GetPid());
371 EXPECT_FALSE(logEvent.hasAttributionChain());
372
373 const vector<FieldValue>& values = logEvent.getValues();
374 ASSERT_EQ(1, values.size());
375
376 const FieldValue& item = values[0];
377 Field expectedField = getField(100, {1, 1, 1}, 0, {true, false, false});
378 EXPECT_EQ(expectedField, item.mField);
379 EXPECT_EQ(Type::STRING, item.mValue.getType());
380 EXPECT_EQ(empty, item.mValue.str_value);
381
382 AStatsEvent_release(event);
383 }
384
TEST_P(LogEventTest,TestByteArrayWithNullCharacter)385 TEST_P(LogEventTest, TestByteArrayWithNullCharacter) {
386 AStatsEvent* event = AStatsEvent_obtain();
387 AStatsEvent_setAtomId(event, 100);
388 uint8_t message[] = {'\t', 'e', '\0', 's', 't'};
389 AStatsEvent_writeByteArray(event, message, 5);
390 AStatsEvent_build(event);
391
392 size_t size;
393 const uint8_t* buf = AStatsEvent_getBuffer(event, &size);
394
395 LogEvent logEvent(/*uid=*/1000, /*pid=*/1001);
396 EXPECT_TRUE(ParseBuffer(logEvent, buf, size));
397
398 EXPECT_EQ(100, logEvent.GetTagId());
399 EXPECT_EQ(1000, logEvent.GetUid());
400 EXPECT_EQ(1001, logEvent.GetPid());
401
402 const vector<FieldValue>& values = logEvent.getValues();
403 ASSERT_EQ(1, values.size());
404
405 const FieldValue& item = values[0];
406 Field expectedField = getField(100, {1, 1, 1}, 0, {true, false, false});
407 EXPECT_EQ(expectedField, item.mField);
408 EXPECT_EQ(Type::STORAGE, item.mValue.getType());
409 vector<uint8_t> expectedValue(message, message + 5);
410 EXPECT_EQ(expectedValue, item.mValue.storage_value);
411
412 AStatsEvent_release(event);
413 }
414
TEST_P(LogEventTest,TestTooManyTopLevelElements)415 TEST_P(LogEventTest, TestTooManyTopLevelElements) {
416 int32_t numElements = 128;
417 AStatsEvent* event = AStatsEvent_obtain();
418 AStatsEvent_setAtomId(event, 100);
419
420 for (int i = 0; i < numElements; i++) {
421 AStatsEvent_writeInt32(event, i);
422 }
423
424 AStatsEvent_build(event);
425
426 size_t size;
427 const uint8_t* buf = AStatsEvent_getBuffer(event, &size);
428 LogEvent logEvent(/*uid=*/1000, /*pid=*/1001);
429 EXPECT_FALSE(ParseBuffer(logEvent, buf, size));
430
431 AStatsEvent_release(event);
432 }
433
TEST_P(LogEventTest,TestAttributionChain)434 TEST_P(LogEventTest, TestAttributionChain) {
435 AStatsEvent* event = AStatsEvent_obtain();
436 AStatsEvent_setAtomId(event, 100);
437
438 string tag1 = "tag1";
439 string tag2 = "tag2";
440
441 uint32_t uids[] = {1001, 1002};
442 const char* tags[] = {tag1.c_str(), tag2.c_str()};
443
444 AStatsEvent_writeAttributionChain(event, uids, tags, 2);
445 AStatsEvent_build(event);
446
447 size_t size;
448 const uint8_t* buf = AStatsEvent_getBuffer(event, &size);
449
450 LogEvent logEvent(/*uid=*/1000, /*pid=*/1001);
451 EXPECT_TRUE(ParseBuffer(logEvent, buf, size));
452
453 EXPECT_EQ(100, logEvent.GetTagId());
454 EXPECT_EQ(1000, logEvent.GetUid());
455 EXPECT_EQ(1001, logEvent.GetPid());
456
457 const vector<FieldValue>& values = logEvent.getValues();
458 ASSERT_EQ(4, values.size()); // 2 per attribution node
459
460 std::pair<size_t, size_t> attrIndexRange;
461 EXPECT_TRUE(logEvent.hasAttributionChain(&attrIndexRange));
462 EXPECT_EQ(0, attrIndexRange.first);
463 EXPECT_EQ(3, attrIndexRange.second);
464
465 // Check first attribution node
466 const FieldValue& uid1Item = values[0];
467 Field expectedField = getField(100, {1, 1, 1}, 2, {true, false, false});
468 EXPECT_EQ(expectedField, uid1Item.mField);
469 EXPECT_EQ(Type::INT, uid1Item.mValue.getType());
470 EXPECT_EQ(1001, uid1Item.mValue.int_value);
471
472 const FieldValue& tag1Item = values[1];
473 expectedField = getField(100, {1, 1, 2}, 2, {true, false, true});
474 EXPECT_EQ(expectedField, tag1Item.mField);
475 EXPECT_EQ(Type::STRING, tag1Item.mValue.getType());
476 EXPECT_EQ(tag1, tag1Item.mValue.str_value);
477
478 // Check second attribution nodes
479 const FieldValue& uid2Item = values[2];
480 expectedField = getField(100, {1, 2, 1}, 2, {true, true, false});
481 EXPECT_EQ(expectedField, uid2Item.mField);
482 EXPECT_EQ(Type::INT, uid2Item.mValue.getType());
483 EXPECT_EQ(1002, uid2Item.mValue.int_value);
484
485 const FieldValue& tag2Item = values[3];
486 expectedField = getField(100, {1, 2, 2}, 2, {true, true, true});
487 EXPECT_EQ(expectedField, tag2Item.mField);
488 EXPECT_EQ(Type::STRING, tag2Item.mValue.getType());
489 EXPECT_EQ(tag2, tag2Item.mValue.str_value);
490
491 AStatsEvent_release(event);
492 }
493
TEST_P(LogEventTest,TestEmptyAttributionChain)494 TEST_P(LogEventTest, TestEmptyAttributionChain) {
495 AStatsEvent* event = AStatsEvent_obtain();
496 AStatsEvent_setAtomId(event, 100);
497
498 AStatsEvent_writeAttributionChain(event, {}, {}, 0);
499 AStatsEvent_writeInt32(event, 10);
500 AStatsEvent_build(event);
501
502 size_t size;
503 const uint8_t* buf = AStatsEvent_getBuffer(event, &size);
504
505 LogEvent logEvent(/*uid=*/1000, /*pid=*/1001);
506 EXPECT_FALSE(ParseBuffer(logEvent, buf, size));
507
508 AStatsEvent_release(event);
509 }
510
TEST_P(LogEventTest,TestAttributionChainTooManyElements)511 TEST_P(LogEventTest, TestAttributionChainTooManyElements) {
512 int32_t numNodes = 128;
513 uint32_t uids[numNodes];
514 vector<string> tags(numNodes); // storage that cTag elements point to
515 const char* cTags[numNodes];
516
517 for (int i = 0; i < numNodes; i++) {
518 uids[i] = i;
519 tags.push_back("test");
520 cTags[i] = tags[i].c_str();
521 }
522
523 AStatsEvent* event = AStatsEvent_obtain();
524 AStatsEvent_setAtomId(event, 100);
525 AStatsEvent_writeAttributionChain(event, uids, cTags, numNodes);
526 AStatsEvent_build(event);
527
528 size_t size;
529 const uint8_t* buf = AStatsEvent_getBuffer(event, &size);
530 LogEvent logEvent(/*uid=*/1000, /*pid=*/1001);
531 EXPECT_FALSE(ParseBuffer(logEvent, buf, size));
532
533 AStatsEvent_release(event);
534 }
535
TEST_P_GUARDED(LogEventTest,TestArrayParsing,__ANDROID_API_T__)536 TEST_P_GUARDED(LogEventTest, TestArrayParsing, __ANDROID_API_T__) {
537 size_t numElements = 2;
538 int32_t int32Array[2] = {3, 6};
539 int64_t int64Array[2] = {1000L, 1002L};
540 float floatArray[2] = {0.3f, 0.09f};
541 bool boolArray[2] = {0, 1};
542
543 vector<string> stringArray = {"str1", "str2"};
544 const char* cStringArray[2];
545 for (int i = 0; i < numElements; i++) {
546 cStringArray[i] = stringArray[i].c_str();
547 }
548
549 AStatsEvent* event = AStatsEvent_obtain();
550 AStatsEvent_setAtomId(event, 100);
551 AStatsEvent_writeInt32Array(event, int32Array, numElements);
552 AStatsEvent_writeInt64Array(event, int64Array, numElements);
553 AStatsEvent_writeFloatArray(event, floatArray, numElements);
554 AStatsEvent_writeBoolArray(event, boolArray, numElements);
555 AStatsEvent_writeStringArray(event, cStringArray, numElements);
556 AStatsEvent_build(event);
557
558 size_t size;
559 const uint8_t* buf = AStatsEvent_getBuffer(event, &size);
560
561 LogEvent logEvent(/*uid=*/1000, /*pid=*/1001);
562 EXPECT_TRUE(ParseBuffer(logEvent, buf, size));
563
564 EXPECT_EQ(100, logEvent.GetTagId());
565 EXPECT_EQ(1000, logEvent.GetUid());
566 EXPECT_EQ(1001, logEvent.GetPid());
567 EXPECT_FALSE(logEvent.hasAttributionChain());
568
569 const vector<FieldValue>& values = logEvent.getValues();
570 ASSERT_EQ(10, values.size()); // 2 for each array type
571
572 const FieldValue& int32ArrayItem1 = values[0];
573 Field expectedField = getField(100, {1, 1, 1}, 1, {false, false, false});
574 EXPECT_EQ(expectedField, int32ArrayItem1.mField);
575 EXPECT_EQ(Type::INT, int32ArrayItem1.mValue.getType());
576 EXPECT_EQ(3, int32ArrayItem1.mValue.int_value);
577
578 const FieldValue& int32ArrayItem2 = values[1];
579 expectedField = getField(100, {1, 2, 1}, 1, {false, true, false});
580 EXPECT_EQ(expectedField, int32ArrayItem2.mField);
581 EXPECT_EQ(Type::INT, int32ArrayItem2.mValue.getType());
582 EXPECT_EQ(6, int32ArrayItem2.mValue.int_value);
583
584 const FieldValue& int64ArrayItem1 = values[2];
585 expectedField = getField(100, {2, 1, 1}, 1, {false, false, false});
586 EXPECT_EQ(expectedField, int64ArrayItem1.mField);
587 EXPECT_EQ(Type::LONG, int64ArrayItem1.mValue.getType());
588 EXPECT_EQ(1000L, int64ArrayItem1.mValue.long_value);
589
590 const FieldValue& int64ArrayItem2 = values[3];
591 expectedField = getField(100, {2, 2, 1}, 1, {false, true, false});
592 EXPECT_EQ(expectedField, int64ArrayItem2.mField);
593 EXPECT_EQ(Type::LONG, int64ArrayItem2.mValue.getType());
594 EXPECT_EQ(1002L, int64ArrayItem2.mValue.long_value);
595
596 const FieldValue& floatArrayItem1 = values[4];
597 expectedField = getField(100, {3, 1, 1}, 1, {false, false, false});
598 EXPECT_EQ(expectedField, floatArrayItem1.mField);
599 EXPECT_EQ(Type::FLOAT, floatArrayItem1.mValue.getType());
600 EXPECT_EQ(0.3f, floatArrayItem1.mValue.float_value);
601
602 const FieldValue& floatArrayItem2 = values[5];
603 expectedField = getField(100, {3, 2, 1}, 1, {false, true, false});
604 EXPECT_EQ(expectedField, floatArrayItem2.mField);
605 EXPECT_EQ(Type::FLOAT, floatArrayItem2.mValue.getType());
606 EXPECT_EQ(0.09f, floatArrayItem2.mValue.float_value);
607
608 const FieldValue& boolArrayItem1 = values[6];
609 expectedField = getField(100, {4, 1, 1}, 1, {false, false, false});
610 EXPECT_EQ(expectedField, boolArrayItem1.mField);
611 EXPECT_EQ(Type::INT,
612 boolArrayItem1.mValue.getType()); // FieldValue does not support boolean type
613 EXPECT_EQ(false, boolArrayItem1.mValue.int_value);
614
615 const FieldValue& boolArrayItem2 = values[7];
616 expectedField = getField(100, {4, 2, 1}, 1, {false, true, false});
617 EXPECT_EQ(expectedField, boolArrayItem2.mField);
618 EXPECT_EQ(Type::INT,
619 boolArrayItem2.mValue.getType()); // FieldValue does not support boolean type
620 EXPECT_EQ(true, boolArrayItem2.mValue.int_value);
621
622 const FieldValue& stringArrayItem1 = values[8];
623 expectedField = getField(100, {5, 1, 1}, 1, {true, false, false});
624 EXPECT_EQ(expectedField, stringArrayItem1.mField);
625 EXPECT_EQ(Type::STRING, stringArrayItem1.mValue.getType());
626 EXPECT_EQ("str1", stringArrayItem1.mValue.str_value);
627
628 const FieldValue& stringArrayItem2 = values[9];
629 expectedField = getField(100, {5, 2, 1}, 1, {true, true, false});
630 EXPECT_EQ(expectedField, stringArrayItem2.mField);
631 EXPECT_EQ(Type::STRING, stringArrayItem2.mValue.getType());
632 EXPECT_EQ("str2", stringArrayItem2.mValue.str_value);
633 }
634
TEST_P_GUARDED(LogEventTest,TestEmptyStringArray,__ANDROID_API_T__)635 TEST_P_GUARDED(LogEventTest, TestEmptyStringArray, __ANDROID_API_T__) {
636 const char* cStringArray[2];
637 string empty = "";
638 cStringArray[0] = empty.c_str();
639 cStringArray[1] = empty.c_str();
640
641 AStatsEvent* event = AStatsEvent_obtain();
642 AStatsEvent_setAtomId(event, 100);
643 AStatsEvent_writeStringArray(event, cStringArray, 2);
644 AStatsEvent_build(event);
645
646 size_t size;
647 const uint8_t* buf = AStatsEvent_getBuffer(event, &size);
648
649 LogEvent logEvent(/*uid=*/1000, /*pid=*/1001);
650 EXPECT_TRUE(ParseBuffer(logEvent, buf, size));
651
652 EXPECT_EQ(100, logEvent.GetTagId());
653 EXPECT_EQ(1000, logEvent.GetUid());
654 EXPECT_EQ(1001, logEvent.GetPid());
655
656 const vector<FieldValue>& values = logEvent.getValues();
657 ASSERT_EQ(2, values.size());
658
659 const FieldValue& stringArrayItem1 = values[0];
660 Field expectedField = getField(100, {1, 1, 1}, 1, {true, false, false});
661 EXPECT_EQ(expectedField, stringArrayItem1.mField);
662 EXPECT_EQ(Type::STRING, stringArrayItem1.mValue.getType());
663 EXPECT_EQ(empty, stringArrayItem1.mValue.str_value);
664
665 const FieldValue& stringArrayItem2 = values[1];
666 expectedField = getField(100, {1, 2, 1}, 1, {true, true, false});
667 EXPECT_EQ(expectedField, stringArrayItem2.mField);
668 EXPECT_EQ(Type::STRING, stringArrayItem2.mValue.getType());
669 EXPECT_EQ(empty, stringArrayItem2.mValue.str_value);
670
671 AStatsEvent_release(event);
672 }
673
TEST_P_GUARDED(LogEventTest,TestArrayTooManyElements,__ANDROID_API_T__)674 TEST_P_GUARDED(LogEventTest, TestArrayTooManyElements, __ANDROID_API_T__) {
675 int32_t numElements = 128;
676 int32_t int32Array[numElements];
677
678 for (int i = 0; i < numElements; i++) {
679 int32Array[i] = 1;
680 }
681
682 AStatsEvent* event = AStatsEvent_obtain();
683 AStatsEvent_setAtomId(event, 100);
684 AStatsEvent_writeInt32Array(event, int32Array, numElements);
685 AStatsEvent_build(event);
686
687 size_t size;
688 const uint8_t* buf = AStatsEvent_getBuffer(event, &size);
689
690 LogEvent logEvent(/*uid=*/1000, /*pid=*/1001);
691 EXPECT_FALSE(ParseBuffer(logEvent, buf, size));
692
693 AStatsEvent_release(event);
694 }
695
TEST_P_GUARDED(LogEventTest,TestEmptyArray,__ANDROID_API_T__)696 TEST_P_GUARDED(LogEventTest, TestEmptyArray, __ANDROID_API_T__) {
697 int32_t int32Array[0] = {};
698
699 AStatsEvent* event = AStatsEvent_obtain();
700 AStatsEvent_setAtomId(event, 100);
701 AStatsEvent_writeInt32Array(event, int32Array, 0);
702 AStatsEvent_build(event);
703
704 size_t size;
705 const uint8_t* buf = AStatsEvent_getBuffer(event, &size);
706
707 LogEvent logEvent(/*uid=*/1000, /*pid=*/1001);
708 EXPECT_TRUE(ParseBuffer(logEvent, buf, size));
709
710 EXPECT_EQ(100, logEvent.GetTagId());
711 EXPECT_EQ(1000, logEvent.GetUid());
712 EXPECT_EQ(1001, logEvent.GetPid());
713
714 ASSERT_EQ(logEvent.getValues().size(), 0);
715
716 AStatsEvent_release(event);
717 }
718
TEST_P_GUARDED(LogEventTest,TestEmptyArrayWithAnnotations,__ANDROID_API_T__)719 TEST_P_GUARDED(LogEventTest, TestEmptyArrayWithAnnotations, __ANDROID_API_T__) {
720 int32_t int32Array[0] = {};
721
722 AStatsEvent* event = AStatsEvent_obtain();
723 AStatsEvent_setAtomId(event, 100);
724 AStatsEvent_writeInt32Array(event, int32Array, 0);
725 AStatsEvent_addBoolAnnotation(event, ASTATSLOG_ANNOTATION_ID_IS_UID, true);
726 AStatsEvent_build(event);
727
728 size_t size;
729 const uint8_t* buf = AStatsEvent_getBuffer(event, &size);
730
731 LogEvent logEvent(/*uid=*/1000, /*pid=*/1001);
732 EXPECT_TRUE(ParseBuffer(logEvent, buf, size));
733
734 EXPECT_EQ(100, logEvent.GetTagId());
735 EXPECT_EQ(1000, logEvent.GetUid());
736 EXPECT_EQ(1001, logEvent.GetPid());
737
738 ASSERT_EQ(logEvent.getValues().size(), 0);
739
740 AStatsEvent_release(event);
741 }
742
TEST_P(LogEventTest,TestAnnotationIdIsUid)743 TEST_P(LogEventTest, TestAnnotationIdIsUid) {
744 LogEvent event(/*uid=*/0, /*pid=*/0);
745 EXPECT_TRUE(createFieldWithBoolAnnotationLogEvent(&event, INT32_TYPE,
746 ASTATSLOG_ANNOTATION_ID_IS_UID, true,
747 /*doHeaderPrefetch=*/GetParam()));
748
749 ASSERT_EQ(event.getNumUidFields(), 1);
750
751 const vector<FieldValue>& values = event.getValues();
752 ASSERT_EQ(values.size(), 1);
753 EXPECT_TRUE(isUidField(values.at(0)));
754 }
755
TEST_P_GUARDED(LogEventTest,TestAnnotationIdIsUid_RepeatedIntAndOtherFields,__ANDROID_API_T__)756 TEST_P_GUARDED(LogEventTest, TestAnnotationIdIsUid_RepeatedIntAndOtherFields, __ANDROID_API_T__) {
757 size_t numElements = 2;
758 int32_t int32Array[2] = {3, 6};
759
760 vector<string> stringArray = {"str1", "str2"};
761 const char* cStringArray[2];
762 for (int i = 0; i < numElements; i++) {
763 cStringArray[i] = stringArray[i].c_str();
764 }
765
766 AStatsEvent* statsEvent = AStatsEvent_obtain();
767 AStatsEvent_setAtomId(statsEvent, 100);
768 AStatsEvent_writeInt32(statsEvent, 5);
769 AStatsEvent_writeInt32Array(statsEvent, int32Array, numElements);
770 AStatsEvent_addBoolAnnotation(statsEvent, ASTATSLOG_ANNOTATION_ID_IS_UID, true);
771 AStatsEvent_writeStringArray(statsEvent, cStringArray, numElements);
772 AStatsEvent_build(statsEvent);
773
774 size_t size;
775 const uint8_t* buf = AStatsEvent_getBuffer(statsEvent, &size);
776 LogEvent logEvent(/*uid=*/1000, /*pid=*/1001);
777 EXPECT_TRUE(ParseBuffer(logEvent, buf, size));
778 EXPECT_EQ(2, logEvent.getNumUidFields());
779
780 const vector<FieldValue>& values = logEvent.getValues();
781 ASSERT_EQ(values.size(), 5);
782 EXPECT_FALSE(isUidField(values.at(0)));
783 EXPECT_TRUE(isUidField(values.at(1)));
784 EXPECT_TRUE(isUidField(values.at(2)));
785 EXPECT_FALSE(isUidField(values.at(3)));
786 EXPECT_FALSE(isUidField(values.at(4)));
787 }
788
TEST_P_GUARDED(LogEventTest,TestAnnotationIdIsUid_RepeatedIntOneEntry,__ANDROID_API_T__)789 TEST_P_GUARDED(LogEventTest, TestAnnotationIdIsUid_RepeatedIntOneEntry, __ANDROID_API_T__) {
790 size_t numElements = 1;
791 int32_t int32Array[1] = {3};
792
793 AStatsEvent* statsEvent = AStatsEvent_obtain();
794 AStatsEvent_setAtomId(statsEvent, 100);
795 AStatsEvent_writeInt32Array(statsEvent, int32Array, numElements);
796 AStatsEvent_addBoolAnnotation(statsEvent, ASTATSLOG_ANNOTATION_ID_IS_UID, true);
797 AStatsEvent_build(statsEvent);
798
799 size_t size;
800 const uint8_t* buf = AStatsEvent_getBuffer(statsEvent, &size);
801 LogEvent logEvent(/*uid=*/1000, /*pid=*/1001);
802 EXPECT_TRUE(ParseBuffer(logEvent, buf, size));
803 EXPECT_EQ(1, logEvent.getNumUidFields());
804
805 const vector<FieldValue>& values = logEvent.getValues();
806 ASSERT_EQ(values.size(), 1);
807 EXPECT_TRUE(isUidField(values.at(0)));
808 }
809
TEST_P_GUARDED(LogEventTest,TestAnnotationIdIsUid_EmptyIntArray,__ANDROID_API_T__)810 TEST_P_GUARDED(LogEventTest, TestAnnotationIdIsUid_EmptyIntArray, __ANDROID_API_T__) {
811 int32_t int32Array[0] = {};
812
813 AStatsEvent* statsEvent = AStatsEvent_obtain();
814 AStatsEvent_setAtomId(statsEvent, 100);
815 AStatsEvent_writeInt32Array(statsEvent, int32Array, /*numElements*/ 0);
816 AStatsEvent_addBoolAnnotation(statsEvent, ASTATSLOG_ANNOTATION_ID_IS_UID, true);
817 AStatsEvent_writeInt32(statsEvent, 5);
818 AStatsEvent_build(statsEvent);
819
820 size_t size;
821 const uint8_t* buf = AStatsEvent_getBuffer(statsEvent, &size);
822 LogEvent logEvent(/*uid=*/1000, /*pid=*/1001);
823 EXPECT_TRUE(ParseBuffer(logEvent, buf, size));
824 EXPECT_EQ(0, logEvent.getNumUidFields());
825
826 const vector<FieldValue>& values = logEvent.getValues();
827 EXPECT_EQ(values.size(), 1);
828 }
829
TEST_P_GUARDED(LogEventTest,TestAnnotationIdIsUid_BadRepeatedInt64,__ANDROID_API_T__)830 TEST_P_GUARDED(LogEventTest, TestAnnotationIdIsUid_BadRepeatedInt64, __ANDROID_API_T__) {
831 int64_t int64Array[2] = {1000L, 1002L};
832
833 AStatsEvent* statsEvent = AStatsEvent_obtain();
834 AStatsEvent_setAtomId(statsEvent, /*atomId=*/100);
835 AStatsEvent_writeInt64Array(statsEvent, int64Array, /*numElements*/ 2);
836 AStatsEvent_addBoolAnnotation(statsEvent, ASTATSLOG_ANNOTATION_ID_IS_UID, true);
837 AStatsEvent_build(statsEvent);
838
839 size_t size;
840 const uint8_t* buf = AStatsEvent_getBuffer(statsEvent, &size);
841 LogEvent logEvent(/*uid=*/1000, /*pid=*/1001);
842
843 EXPECT_FALSE(ParseBuffer(logEvent, buf, size));
844 EXPECT_EQ(0, logEvent.getNumUidFields());
845
846 AStatsEvent_release(statsEvent);
847 }
848
TEST_P_GUARDED(LogEventTest,TestAnnotationIdIsUid_BadRepeatedString,__ANDROID_API_T__)849 TEST_P_GUARDED(LogEventTest, TestAnnotationIdIsUid_BadRepeatedString, __ANDROID_API_T__) {
850 size_t numElements = 2;
851 vector<string> stringArray = {"str1", "str2"};
852 const char* cStringArray[2];
853 for (int i = 0; i < numElements; i++) {
854 cStringArray[i] = stringArray[i].c_str();
855 }
856
857 AStatsEvent* statsEvent = AStatsEvent_obtain();
858 AStatsEvent_setAtomId(statsEvent, /*atomId=*/100);
859 AStatsEvent_writeStringArray(statsEvent, cStringArray, /*numElements*/ 2);
860 AStatsEvent_addBoolAnnotation(statsEvent, ASTATSLOG_ANNOTATION_ID_IS_UID, true);
861 AStatsEvent_build(statsEvent);
862
863 size_t size;
864 const uint8_t* buf = AStatsEvent_getBuffer(statsEvent, &size);
865 LogEvent logEvent(/*uid=*/1000, /*pid=*/1001);
866
867 EXPECT_FALSE(ParseBuffer(logEvent, buf, size));
868 EXPECT_EQ(0, logEvent.getNumUidFields());
869
870 AStatsEvent_release(statsEvent);
871 }
872
TEST_P(LogEventTestBadAnnotationFieldTypes,TestAnnotationIdIsUid)873 TEST_P(LogEventTestBadAnnotationFieldTypes, TestAnnotationIdIsUid) {
874 LogEvent event(/*uid=*/0, /*pid=*/0);
875
876 if (std::get<0>(GetParam()) != INT32_TYPE && std::get<0>(GetParam()) != LIST_TYPE) {
877 EXPECT_FALSE(createFieldWithBoolAnnotationLogEvent(
878 &event, std::get<0>(GetParam()), ASTATSLOG_ANNOTATION_ID_IS_UID, true,
879 /*doHeaderPrefetch=*/std::get<1>(GetParam())));
880 }
881 }
882
TEST_P(LogEventTest,TestAnnotationIdIsUid_NotIntAnnotation)883 TEST_P(LogEventTest, TestAnnotationIdIsUid_NotIntAnnotation) {
884 LogEvent event(/*uid=*/0, /*pid=*/0);
885 EXPECT_FALSE(createFieldWithIntAnnotationLogEvent(&event, INT32_TYPE,
886 ASTATSLOG_ANNOTATION_ID_IS_UID, 10,
887 /*doHeaderPrefetch=*/GetParam()));
888 }
889
TEST_P(LogEventTest,TestAnnotationIdStateNested)890 TEST_P(LogEventTest, TestAnnotationIdStateNested) {
891 LogEvent event(/*uid=*/0, /*pid=*/0);
892 EXPECT_TRUE(createFieldWithBoolAnnotationLogEvent(&event, INT32_TYPE,
893 ASTATSLOG_ANNOTATION_ID_STATE_NESTED, true,
894 /*doHeaderPrefetch=*/GetParam()));
895
896 const vector<FieldValue>& values = event.getValues();
897 ASSERT_EQ(values.size(), 1);
898 EXPECT_TRUE(values[0].mAnnotations.isNested());
899 }
900
TEST_P(LogEventTestBadAnnotationFieldTypes,TestAnnotationIdStateNested)901 TEST_P(LogEventTestBadAnnotationFieldTypes, TestAnnotationIdStateNested) {
902 LogEvent event(/*uid=*/0, /*pid=*/0);
903
904 if (std::get<0>(GetParam()) != INT32_TYPE &&
905 (std::get<0>(GetParam()) != LIST_TYPE || isAtLeastT())) {
906 EXPECT_FALSE(createFieldWithBoolAnnotationLogEvent(
907 &event, std::get<0>(GetParam()), ASTATSLOG_ANNOTATION_ID_STATE_NESTED, true,
908 /*doHeaderPrefetch=*/std::get<1>(GetParam())));
909 }
910 }
911
TEST_P(LogEventTest,TestAnnotationIdStateNested_NotIntAnnotation)912 TEST_P(LogEventTest, TestAnnotationIdStateNested_NotIntAnnotation) {
913 LogEvent event(/*uid=*/0, /*pid=*/0);
914 EXPECT_FALSE(createFieldWithIntAnnotationLogEvent(&event, INT32_TYPE,
915 ASTATSLOG_ANNOTATION_ID_STATE_NESTED, 10,
916 /*doHeaderPrefetch=*/GetParam()));
917 }
918
TEST_P(LogEventTest,TestPrimaryFieldAnnotation)919 TEST_P(LogEventTest, TestPrimaryFieldAnnotation) {
920 LogEvent event(/*uid=*/0, /*pid=*/0);
921 EXPECT_TRUE(createFieldWithBoolAnnotationLogEvent(&event, INT32_TYPE,
922 ASTATSLOG_ANNOTATION_ID_PRIMARY_FIELD, true,
923 /*doHeaderPrefetch=*/GetParam()));
924
925 const vector<FieldValue>& values = event.getValues();
926 ASSERT_EQ(values.size(), 1);
927 EXPECT_TRUE(values[0].mAnnotations.isPrimaryField());
928 }
929
TEST_P(LogEventTestBadAnnotationFieldTypes,TestPrimaryFieldAnnotation)930 TEST_P(LogEventTestBadAnnotationFieldTypes, TestPrimaryFieldAnnotation) {
931 LogEvent event(/*uid=*/0, /*pid=*/0);
932
933 if ((std::get<0>(GetParam()) == LIST_TYPE && isAtLeastT()) ||
934 std::get<0>(GetParam()) == ATTRIBUTION_CHAIN_TYPE) {
935 EXPECT_FALSE(createFieldWithBoolAnnotationLogEvent(
936 &event, std::get<0>(GetParam()), ASTATSLOG_ANNOTATION_ID_PRIMARY_FIELD, true,
937 /*doHeaderPrefetch=*/std::get<1>(GetParam())));
938 }
939 }
940
TEST_P(LogEventTest,TestPrimaryFieldAnnotation_NotIntAnnotation)941 TEST_P(LogEventTest, TestPrimaryFieldAnnotation_NotIntAnnotation) {
942 LogEvent event(/*uid=*/0, /*pid=*/0);
943 EXPECT_FALSE(createFieldWithIntAnnotationLogEvent(&event, INT32_TYPE,
944 ASTATSLOG_ANNOTATION_ID_PRIMARY_FIELD, 10,
945 /*doHeaderPrefetch=*/GetParam()));
946 }
947
TEST_P(LogEventTest,TestExclusiveStateAnnotation)948 TEST_P(LogEventTest, TestExclusiveStateAnnotation) {
949 LogEvent event(/*uid=*/0, /*pid=*/0);
950 EXPECT_TRUE(createFieldWithBoolAnnotationLogEvent(&event, INT32_TYPE,
951 ASTATSLOG_ANNOTATION_ID_EXCLUSIVE_STATE, true,
952 /*doHeaderPrefetch=*/GetParam()));
953
954 const vector<FieldValue>& values = event.getValues();
955 ASSERT_EQ(values.size(), 1);
956 EXPECT_TRUE(values[0].mAnnotations.isExclusiveState());
957 }
958
TEST_P(LogEventTestBadAnnotationFieldTypes,TestExclusiveStateAnnotation)959 TEST_P(LogEventTestBadAnnotationFieldTypes, TestExclusiveStateAnnotation) {
960 LogEvent event(/*uid=*/0, /*pid=*/0);
961
962 if (std::get<0>(GetParam()) != INT32_TYPE &&
963 (std::get<0>(GetParam()) != LIST_TYPE || isAtLeastT())) {
964 EXPECT_FALSE(createFieldWithBoolAnnotationLogEvent(
965 &event, std::get<0>(GetParam()), ASTATSLOG_ANNOTATION_ID_EXCLUSIVE_STATE, true,
966 /*doHeaderPrefetch=*/std::get<1>(GetParam())));
967 }
968 }
969
TEST_P(LogEventTest,TestExclusiveStateAnnotation_NotIntAnnotation)970 TEST_P(LogEventTest, TestExclusiveStateAnnotation_NotIntAnnotation) {
971 LogEvent event(/*uid=*/0, /*pid=*/0);
972 EXPECT_FALSE(createFieldWithIntAnnotationLogEvent(&event, INT32_TYPE,
973 ASTATSLOG_ANNOTATION_ID_EXCLUSIVE_STATE, 10,
974 /*doHeaderPrefetch=*/GetParam()));
975 }
976
TEST_P(LogEventTest,TestPrimaryFieldFirstUidAnnotation)977 TEST_P(LogEventTest, TestPrimaryFieldFirstUidAnnotation) {
978 // Event has 10 ints and then an attribution chain
979 int numInts = 10;
980 int firstUidInChainIndex = numInts;
981 string tag1 = "tag1";
982 string tag2 = "tag2";
983 uint32_t uids[] = {1001, 1002};
984 const char* tags[] = {tag1.c_str(), tag2.c_str()};
985
986 // Construct AStatsEvent
987 AStatsEvent* statsEvent = AStatsEvent_obtain();
988 AStatsEvent_setAtomId(statsEvent, 100);
989 for (int i = 0; i < numInts; i++) {
990 AStatsEvent_writeInt32(statsEvent, 10);
991 }
992 AStatsEvent_writeAttributionChain(statsEvent, uids, tags, 2);
993 AStatsEvent_addBoolAnnotation(statsEvent, ASTATSLOG_ANNOTATION_ID_PRIMARY_FIELD_FIRST_UID,
994 true);
995 AStatsEvent_build(statsEvent);
996
997 // Construct LogEvent
998 size_t size;
999 const uint8_t* buf = AStatsEvent_getBuffer(statsEvent, &size);
1000 LogEvent logEvent(/*uid=*/0, /*pid=*/0);
1001 EXPECT_TRUE(ParseBuffer(logEvent, buf, size));
1002 AStatsEvent_release(statsEvent);
1003
1004 // Check annotation
1005 const vector<FieldValue>& values = logEvent.getValues();
1006 ASSERT_EQ(values.size(), numInts + 4);
1007 EXPECT_TRUE(values[firstUidInChainIndex].mAnnotations.isPrimaryField());
1008 }
1009
TEST_P(LogEventTestBadAnnotationFieldTypes,TestPrimaryFieldFirstUidAnnotation)1010 TEST_P(LogEventTestBadAnnotationFieldTypes, TestPrimaryFieldFirstUidAnnotation) {
1011 LogEvent event(/*uid=*/0, /*pid=*/0);
1012
1013 if (std::get<0>(GetParam()) != ATTRIBUTION_CHAIN_TYPE &&
1014 (std::get<0>(GetParam()) != LIST_TYPE || isAtLeastT())) {
1015 EXPECT_FALSE(createFieldWithBoolAnnotationLogEvent(
1016 &event, std::get<0>(GetParam()), ASTATSLOG_ANNOTATION_ID_PRIMARY_FIELD_FIRST_UID,
1017 true,
1018 /*doHeaderPrefetch=*/std::get<1>(GetParam())));
1019 }
1020 }
1021
TEST_P(LogEventTest,TestPrimaryFieldFirstUidAnnotation_NotIntAnnotation)1022 TEST_P(LogEventTest, TestPrimaryFieldFirstUidAnnotation_NotIntAnnotation) {
1023 LogEvent event(/*uid=*/0, /*pid=*/0);
1024 EXPECT_FALSE(createFieldWithIntAnnotationLogEvent(
1025 &event, ATTRIBUTION_CHAIN_TYPE, ASTATSLOG_ANNOTATION_ID_PRIMARY_FIELD_FIRST_UID, 10,
1026 /*doHeaderPrefetch=*/GetParam()));
1027 }
1028
TEST_P(LogEventTest,TestResetStateAnnotation)1029 TEST_P(LogEventTest, TestResetStateAnnotation) {
1030 int32_t resetState = 10;
1031 LogEvent event(/*uid=*/0, /*pid=*/0);
1032 EXPECT_TRUE(createFieldWithIntAnnotationLogEvent(
1033 &event, INT32_TYPE, ASTATSLOG_ANNOTATION_ID_TRIGGER_STATE_RESET, resetState,
1034 /*doHeaderPrefetch=*/GetParam()));
1035
1036 const vector<FieldValue>& values = event.getValues();
1037 ASSERT_EQ(values.size(), 1);
1038 EXPECT_EQ(event.getResetState(), resetState);
1039 }
1040
TEST_P(LogEventTest,TestRestrictionCategoryAnnotation)1041 TEST_P(LogEventTest, TestRestrictionCategoryAnnotation) {
1042 if (!isAtLeastU()) {
1043 GTEST_SKIP();
1044 }
1045 int32_t restrictionCategory = ASTATSLOG_RESTRICTION_CATEGORY_DIAGNOSTIC;
1046 LogEvent event(/*uid=*/0, /*pid=*/0);
1047 EXPECT_TRUE(createAtomLevelIntAnnotationLogEvent(
1048 &event, INT32_TYPE, ASTATSLOG_ANNOTATION_ID_RESTRICTION_CATEGORY, restrictionCategory,
1049 /*doHeaderPrefetch=*/GetParam()));
1050
1051 ASSERT_EQ(event.getRestrictionCategory(), restrictionCategory);
1052 }
1053
TEST_P(LogEventTest,TestInvalidRestrictionCategoryAnnotation)1054 TEST_P(LogEventTest, TestInvalidRestrictionCategoryAnnotation) {
1055 if (!isAtLeastU()) {
1056 GTEST_SKIP();
1057 }
1058 int32_t restrictionCategory = 619; // unknown category
1059 LogEvent event(/*uid=*/0, /*pid=*/0);
1060 EXPECT_FALSE(createAtomLevelIntAnnotationLogEvent(
1061 &event, INT32_TYPE, ASTATSLOG_ANNOTATION_ID_RESTRICTION_CATEGORY, restrictionCategory,
1062 /*doHeaderPrefetch=*/GetParam()));
1063 }
1064
TEST_P(LogEventTest,TestRestrictionCategoryAnnotationBelowUDevice)1065 TEST_P(LogEventTest, TestRestrictionCategoryAnnotationBelowUDevice) {
1066 if (isAtLeastU()) {
1067 GTEST_SKIP();
1068 }
1069 int32_t restrictionCategory = ASTATSLOG_RESTRICTION_CATEGORY_DIAGNOSTIC;
1070 LogEvent event(/*uid=*/0, /*pid=*/0);
1071 EXPECT_FALSE(createAtomLevelIntAnnotationLogEvent(
1072 &event, INT32_TYPE, ASTATSLOG_ANNOTATION_ID_RESTRICTION_CATEGORY, restrictionCategory,
1073 /*doHeaderPrefetch=*/GetParam()));
1074 }
1075
TEST_P(LogEventTestBadAnnotationFieldTypes,TestResetStateAnnotation)1076 TEST_P(LogEventTestBadAnnotationFieldTypes, TestResetStateAnnotation) {
1077 LogEvent event(/*uid=*/0, /*pid=*/0);
1078 int32_t resetState = 10;
1079
1080 if (std::get<0>(GetParam()) != INT32_TYPE &&
1081 (std::get<0>(GetParam()) != LIST_TYPE || isAtLeastT())) {
1082 EXPECT_FALSE(createFieldWithIntAnnotationLogEvent(
1083 &event, std::get<0>(GetParam()), ASTATSLOG_ANNOTATION_ID_TRIGGER_STATE_RESET,
1084 resetState,
1085 /*doHeaderPrefetch=*/std::get<1>(GetParam())));
1086 }
1087 }
1088
TEST_P(LogEventTest,TestResetStateAnnotation_NotBoolAnnotation)1089 TEST_P(LogEventTest, TestResetStateAnnotation_NotBoolAnnotation) {
1090 LogEvent event(/*uid=*/0, /*pid=*/0);
1091 EXPECT_FALSE(createFieldWithBoolAnnotationLogEvent(
1092 &event, INT32_TYPE, ASTATSLOG_ANNOTATION_ID_TRIGGER_STATE_RESET, true,
1093 /*doHeaderPrefetch=*/GetParam()));
1094 }
1095
TEST_P_GUARDED(LogEventTest,TestUidAnnotationWithInt8MaxValues,__ANDROID_API_T__)1096 TEST_P_GUARDED(LogEventTest, TestUidAnnotationWithInt8MaxValues, __ANDROID_API_T__) {
1097 int32_t numElements = INT8_MAX;
1098 int32_t int32Array[numElements];
1099
1100 for (int i = 0; i < numElements; i++) {
1101 int32Array[i] = i;
1102 }
1103
1104 AStatsEvent* event = AStatsEvent_obtain();
1105 AStatsEvent_setAtomId(event, 100);
1106 AStatsEvent_writeInt32Array(event, int32Array, numElements);
1107 AStatsEvent_writeInt32(event, 10);
1108 AStatsEvent_writeInt32(event, 11);
1109 AStatsEvent_addBoolAnnotation(event, ASTATSLOG_ANNOTATION_ID_IS_UID, true);
1110 AStatsEvent_build(event);
1111
1112 size_t size;
1113 const uint8_t* buf = AStatsEvent_getBuffer(event, &size);
1114 LogEvent logEvent(/*uid=*/1000, /*pid=*/1001);
1115 EXPECT_TRUE(ParseBuffer(logEvent, buf, size));
1116
1117 AStatsEvent_release(event);
1118 }
1119
TEST_P(LogEventTest,TestEmptyAttributionChainWithPrimaryFieldFirstUidAnnotation)1120 TEST_P(LogEventTest, TestEmptyAttributionChainWithPrimaryFieldFirstUidAnnotation) {
1121 AStatsEvent* event = AStatsEvent_obtain();
1122 AStatsEvent_setAtomId(event, 100);
1123
1124 uint32_t uids[] = {};
1125 const char* tags[] = {};
1126
1127 AStatsEvent_writeInt32(event, 10);
1128 AStatsEvent_writeAttributionChain(event, uids, tags, 0);
1129 AStatsEvent_addBoolAnnotation(event, ASTATSLOG_ANNOTATION_ID_PRIMARY_FIELD_FIRST_UID, true);
1130
1131 AStatsEvent_build(event);
1132
1133 size_t size;
1134 const uint8_t* buf = AStatsEvent_getBuffer(event, &size);
1135
1136 LogEvent logEvent(/*uid=*/1000, /*pid=*/1001);
1137 EXPECT_FALSE(ParseBuffer(logEvent, buf, size));
1138
1139 AStatsEvent_release(event);
1140 }
1141
TEST_P_GUARDED(LogEventTest,TestInvalidBufferParsing,__ANDROID_API_T__)1142 TEST_P_GUARDED(LogEventTest, TestInvalidBufferParsing, __ANDROID_API_T__) {
1143 size_t emptyAtomBufferSize = 0;
1144 {
1145 // creating valid event to get valid buffer header size when no data fields
1146 AStatsEvent* event = AStatsEvent_obtain();
1147 AStatsEvent_setAtomId(event, 100);
1148 AStatsEvent_build(event);
1149 AStatsEvent_getBuffer(event, &emptyAtomBufferSize);
1150 AStatsEvent_release(event);
1151 }
1152
1153 uint8_t buffer[4096];
1154 memset(buffer, 0, 4096);
1155 {
1156 // creating valid event to get valid buffer header with 1 array field and 1 annotation
1157 AStatsEvent* event = AStatsEvent_obtain();
1158 AStatsEvent_setAtomId(event, 100);
1159 AStatsEvent_writeInt32Array(event, nullptr, 0);
1160 AStatsEvent_addBoolAnnotation(event, ASTATSLOG_ANNOTATION_ID_IS_UID, true);
1161 EXPECT_EQ(AStatsEvent_getErrors(event), 0);
1162 AStatsEvent_build(event);
1163
1164 const uint8_t* buf = AStatsEvent_getBuffer(event, nullptr);
1165 memcpy(buffer, buf, emptyAtomBufferSize);
1166 AStatsEvent_release(event);
1167 }
1168
1169 size_t bufferPosWithAlteredData = emptyAtomBufferSize;
1170
1171 // adding extra data to test the logEvent parser logic
1172
1173 buffer[bufferPosWithAlteredData++] = 0x13; // array with 1 annotation
1174 buffer[bufferPosWithAlteredData++] = 0x00; // size of array is 0
1175 buffer[bufferPosWithAlteredData++] = 0x00; // type of array is int32
1176 buffer[bufferPosWithAlteredData++] = 0x01; // annotation type is isUid
1177 buffer[bufferPosWithAlteredData++] = 0x01; // annotation value type is not bool
1178
1179 LogEvent logEvent(/*uid=*/1000, /*pid=*/1001);
1180 EXPECT_FALSE(ParseBuffer(logEvent, buffer, bufferPosWithAlteredData));
1181 }
1182
1183 // Setup for parameterized tests.
1184 class LogEvent_FieldRestrictionTest : public testing::TestWithParam<std::tuple<int, bool>> {
1185 public:
ToString(testing::TestParamInfo<std::tuple<int,bool>> info)1186 static std::string ToString(testing::TestParamInfo<std::tuple<int, bool>> info) {
1187 const std::string boolName = std::get<1>(info.param) ? "_prefetchTrue" : "_prefetchFalse";
1188
1189 switch (std::get<0>(info.param)) {
1190 case ASTATSLOG_ANNOTATION_ID_FIELD_RESTRICTION_PERIPHERAL_DEVICE_INFO:
1191 return "PeripheralDeviceInfo" + boolName;
1192 case ASTATSLOG_ANNOTATION_ID_FIELD_RESTRICTION_APP_USAGE:
1193 return "AppUsage" + boolName;
1194 case ASTATSLOG_ANNOTATION_ID_FIELD_RESTRICTION_APP_ACTIVITY:
1195 return "AppActivity" + boolName;
1196 case ASTATSLOG_ANNOTATION_ID_FIELD_RESTRICTION_HEALTH_CONNECT:
1197 return "HealthConnect" + boolName;
1198 case ASTATSLOG_ANNOTATION_ID_FIELD_RESTRICTION_ACCESSIBILITY:
1199 return "Accessibility" + boolName;
1200 case ASTATSLOG_ANNOTATION_ID_FIELD_RESTRICTION_SYSTEM_SEARCH:
1201 return "SystemSearch" + boolName;
1202 case ASTATSLOG_ANNOTATION_ID_FIELD_RESTRICTION_USER_ENGAGEMENT:
1203 return "UserEngagement" + boolName;
1204 case ASTATSLOG_ANNOTATION_ID_FIELD_RESTRICTION_AMBIENT_SENSING:
1205 return "AmbientSensing" + boolName;
1206 case ASTATSLOG_ANNOTATION_ID_FIELD_RESTRICTION_DEMOGRAPHIC_CLASSIFICATION:
1207 return "DemographicClassification" + boolName;
1208 default:
1209 return "Unknown" + boolName;
1210 }
1211 }
TearDown()1212 void TearDown() override {
1213 FlagProvider::getInstance().resetOverrides();
1214 }
1215 };
1216
1217 // TODO(b/222539899): Add BOOL_TYPE value once parseAnnotations is updated to check specific
1218 // typeIds. BOOL_TYPE should be a bad field type for is_uid, nested, and reset state annotations.
1219 INSTANTIATE_TEST_SUITE_P(
1220 LogEvent_FieldRestrictionTest, LogEvent_FieldRestrictionTest,
1221 testing::Combine(
1222 testing::Values(
1223 ASTATSLOG_ANNOTATION_ID_FIELD_RESTRICTION_PERIPHERAL_DEVICE_INFO,
1224 ASTATSLOG_ANNOTATION_ID_FIELD_RESTRICTION_APP_USAGE,
1225 ASTATSLOG_ANNOTATION_ID_FIELD_RESTRICTION_APP_ACTIVITY,
1226 ASTATSLOG_ANNOTATION_ID_FIELD_RESTRICTION_HEALTH_CONNECT,
1227 ASTATSLOG_ANNOTATION_ID_FIELD_RESTRICTION_ACCESSIBILITY,
1228 ASTATSLOG_ANNOTATION_ID_FIELD_RESTRICTION_SYSTEM_SEARCH,
1229 ASTATSLOG_ANNOTATION_ID_FIELD_RESTRICTION_USER_ENGAGEMENT,
1230 ASTATSLOG_ANNOTATION_ID_FIELD_RESTRICTION_AMBIENT_SENSING,
1231 ASTATSLOG_ANNOTATION_ID_FIELD_RESTRICTION_DEMOGRAPHIC_CLASSIFICATION),
1232 testing::Bool()),
1233 LogEvent_FieldRestrictionTest::ToString);
1234
TEST_P(LogEvent_FieldRestrictionTest,TestFieldRestrictionAnnotation)1235 TEST_P(LogEvent_FieldRestrictionTest, TestFieldRestrictionAnnotation) {
1236 if (!isAtLeastU()) {
1237 GTEST_SKIP();
1238 }
1239 LogEvent event(/*uid=*/0, /*pid=*/0);
1240 EXPECT_TRUE(
1241 createFieldWithBoolAnnotationLogEvent(&event, INT32_TYPE, std::get<0>(GetParam()), true,
1242 /*doHeaderPrefetch=*/std::get<1>(GetParam())));
1243 // Some basic checks to make sure the event is parsed correctly.
1244 EXPECT_EQ(event.GetTagId(), 100);
1245 ASSERT_EQ(event.getValues().size(), 1);
1246 EXPECT_EQ(event.getValues()[0].mValue.getType(), Type::INT);
1247 }
1248
TEST_P(LogEvent_FieldRestrictionTest,TestInvalidAnnotationIntType)1249 TEST_P(LogEvent_FieldRestrictionTest, TestInvalidAnnotationIntType) {
1250 if (!isAtLeastU()) {
1251 GTEST_SKIP();
1252 }
1253 LogEvent event(/*uid=*/0, /*pid=*/0);
1254 EXPECT_FALSE(createFieldWithIntAnnotationLogEvent(
1255 &event, STRING_TYPE, std::get<0>(GetParam()),
1256 /*random int*/ 15, /*doHeaderPrefetch=*/std::get<1>(GetParam())));
1257 }
1258
TEST_P(LogEvent_FieldRestrictionTest,TestInvalidAnnotationAtomLevel)1259 TEST_P(LogEvent_FieldRestrictionTest, TestInvalidAnnotationAtomLevel) {
1260 if (!isAtLeastU()) {
1261 GTEST_SKIP();
1262 }
1263 LogEvent event(/*uid=*/0, /*pid=*/0);
1264 EXPECT_FALSE(createAtomLevelBoolAnnotationLogEvent(
1265 &event, STRING_TYPE, std::get<0>(GetParam()), true,
1266 /*doHeaderPrefetch=*/std::get<1>(GetParam())));
1267 }
1268
TEST_P(LogEvent_FieldRestrictionTest,TestRestrictionCategoryAnnotationBelowUDevice)1269 TEST_P(LogEvent_FieldRestrictionTest, TestRestrictionCategoryAnnotationBelowUDevice) {
1270 if (isAtLeastU()) {
1271 GTEST_SKIP();
1272 }
1273 int32_t restrictionCategory = ASTATSLOG_RESTRICTION_CATEGORY_DIAGNOSTIC;
1274 LogEvent event(/*uid=*/0, /*pid=*/0);
1275 EXPECT_FALSE(
1276 createFieldWithBoolAnnotationLogEvent(&event, INT32_TYPE, std::get<0>(GetParam()), true,
1277 /*doHeaderPrefetch=*/std::get<1>(GetParam())));
1278 }
1279
1280 } // namespace statsd
1281 } // namespace os
1282 } // namespace android
1283 #else
1284 GTEST_LOG_(INFO) << "This test does nothing.\n";
1285 #endif
1286