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