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