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