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 "frameworks/proto_logging/stats/atoms.pb.h" 20 #include "frameworks/proto_logging/stats/enums/stats/launcher/launcher.pb.h" 21 #include "log/log_event_list.h" 22 #include "stats_event.h" 23 24 #ifdef __ANDROID__ 25 26 namespace android { 27 namespace os { 28 namespace statsd { 29 30 using std::string; 31 using std::vector; 32 using util::ProtoOutputStream; 33 using util::ProtoReader; 34 35 namespace { 36 37 Field getField(int32_t tag, const vector<int32_t>& pos, int32_t depth, const vector<bool>& last) { 38 Field f(tag, (int32_t*)pos.data(), depth); 39 40 // For loop starts at 1 because the last field at depth 0 is not decorated. 41 for (int i = 1; i < depth; i++) { 42 if (last[i]) f.decorateLastPos(i); 43 } 44 45 return f; 46 } 47 48 void createIntWithBoolAnnotationLogEvent(LogEvent* logEvent, uint8_t annotationId, 49 bool annotationValue) { 50 AStatsEvent* statsEvent = AStatsEvent_obtain(); 51 AStatsEvent_setAtomId(statsEvent, /*atomId=*/100); 52 AStatsEvent_writeInt32(statsEvent, 10); 53 AStatsEvent_addBoolAnnotation(statsEvent, annotationId, annotationValue); 54 AStatsEvent_build(statsEvent); 55 56 size_t size; 57 uint8_t* buf = AStatsEvent_getBuffer(statsEvent, &size); 58 EXPECT_TRUE(logEvent->parseBuffer(buf, size)); 59 60 AStatsEvent_release(statsEvent); 61 } 62 63 void createIntWithIntAnnotationLogEvent(LogEvent* logEvent, uint8_t annotationId, 64 int annotationValue) { 65 AStatsEvent* statsEvent = AStatsEvent_obtain(); 66 AStatsEvent_setAtomId(statsEvent, /*atomId=*/100); 67 AStatsEvent_writeInt32(statsEvent, 10); 68 AStatsEvent_addInt32Annotation(statsEvent, annotationId, annotationValue); 69 AStatsEvent_build(statsEvent); 70 71 size_t size; 72 uint8_t* buf = AStatsEvent_getBuffer(statsEvent, &size); 73 EXPECT_TRUE(logEvent->parseBuffer(buf, size)); 74 75 AStatsEvent_release(statsEvent); 76 } 77 78 } // anonymous namespace 79 80 TEST(LogEventTest, TestPrimitiveParsing) { 81 AStatsEvent* event = AStatsEvent_obtain(); 82 AStatsEvent_setAtomId(event, 100); 83 AStatsEvent_writeInt32(event, 10); 84 AStatsEvent_writeInt64(event, 0x123456789); 85 AStatsEvent_writeFloat(event, 2.0); 86 AStatsEvent_writeBool(event, true); 87 AStatsEvent_build(event); 88 89 size_t size; 90 uint8_t* buf = AStatsEvent_getBuffer(event, &size); 91 92 LogEvent logEvent(/*uid=*/1000, /*pid=*/1001); 93 EXPECT_TRUE(logEvent.parseBuffer(buf, size)); 94 95 EXPECT_EQ(100, logEvent.GetTagId()); 96 EXPECT_EQ(1000, logEvent.GetUid()); 97 EXPECT_EQ(1001, logEvent.GetPid()); 98 EXPECT_FALSE(logEvent.hasAttributionChain()); 99 100 const vector<FieldValue>& values = logEvent.getValues(); 101 ASSERT_EQ(4, values.size()); 102 103 const FieldValue& int32Item = values[0]; 104 Field expectedField = getField(100, {1, 1, 1}, 0, {false, false, false}); 105 EXPECT_EQ(expectedField, int32Item.mField); 106 EXPECT_EQ(Type::INT, int32Item.mValue.getType()); 107 EXPECT_EQ(10, int32Item.mValue.int_value); 108 109 const FieldValue& int64Item = values[1]; 110 expectedField = getField(100, {2, 1, 1}, 0, {false, false, false}); 111 EXPECT_EQ(expectedField, int64Item.mField); 112 EXPECT_EQ(Type::LONG, int64Item.mValue.getType()); 113 EXPECT_EQ(0x123456789, int64Item.mValue.long_value); 114 115 const FieldValue& floatItem = values[2]; 116 expectedField = getField(100, {3, 1, 1}, 0, {false, false, false}); 117 EXPECT_EQ(expectedField, floatItem.mField); 118 EXPECT_EQ(Type::FLOAT, floatItem.mValue.getType()); 119 EXPECT_EQ(2.0, floatItem.mValue.float_value); 120 121 const FieldValue& boolItem = values[3]; 122 expectedField = getField(100, {4, 1, 1}, 0, {true, false, false}); 123 EXPECT_EQ(expectedField, boolItem.mField); 124 EXPECT_EQ(Type::INT, boolItem.mValue.getType()); // FieldValue does not support boolean type 125 EXPECT_EQ(1, boolItem.mValue.int_value); 126 127 AStatsEvent_release(event); 128 } 129 130 TEST(LogEventTest, TestStringAndByteArrayParsing) { 131 AStatsEvent* event = AStatsEvent_obtain(); 132 AStatsEvent_setAtomId(event, 100); 133 string str = "test"; 134 AStatsEvent_writeString(event, str.c_str()); 135 AStatsEvent_writeByteArray(event, (uint8_t*)str.c_str(), str.length()); 136 AStatsEvent_build(event); 137 138 size_t size; 139 uint8_t* buf = AStatsEvent_getBuffer(event, &size); 140 141 LogEvent logEvent(/*uid=*/1000, /*pid=*/1001); 142 EXPECT_TRUE(logEvent.parseBuffer(buf, size)); 143 144 EXPECT_EQ(100, logEvent.GetTagId()); 145 EXPECT_EQ(1000, logEvent.GetUid()); 146 EXPECT_EQ(1001, logEvent.GetPid()); 147 EXPECT_FALSE(logEvent.hasAttributionChain()); 148 149 const vector<FieldValue>& values = logEvent.getValues(); 150 ASSERT_EQ(2, values.size()); 151 152 const FieldValue& stringItem = values[0]; 153 Field expectedField = getField(100, {1, 1, 1}, 0, {false, false, false}); 154 EXPECT_EQ(expectedField, stringItem.mField); 155 EXPECT_EQ(Type::STRING, stringItem.mValue.getType()); 156 EXPECT_EQ(str, stringItem.mValue.str_value); 157 158 const FieldValue& storageItem = values[1]; 159 expectedField = getField(100, {2, 1, 1}, 0, {true, false, false}); 160 EXPECT_EQ(expectedField, storageItem.mField); 161 EXPECT_EQ(Type::STORAGE, storageItem.mValue.getType()); 162 vector<uint8_t> expectedValue = {'t', 'e', 's', 't'}; 163 EXPECT_EQ(expectedValue, storageItem.mValue.storage_value); 164 165 AStatsEvent_release(event); 166 } 167 168 TEST(LogEventTest, TestEmptyString) { 169 AStatsEvent* event = AStatsEvent_obtain(); 170 AStatsEvent_setAtomId(event, 100); 171 string empty = ""; 172 AStatsEvent_writeString(event, empty.c_str()); 173 AStatsEvent_build(event); 174 175 size_t size; 176 uint8_t* buf = AStatsEvent_getBuffer(event, &size); 177 178 LogEvent logEvent(/*uid=*/1000, /*pid=*/1001); 179 EXPECT_TRUE(logEvent.parseBuffer(buf, size)); 180 181 EXPECT_EQ(100, logEvent.GetTagId()); 182 EXPECT_EQ(1000, logEvent.GetUid()); 183 EXPECT_EQ(1001, logEvent.GetPid()); 184 EXPECT_FALSE(logEvent.hasAttributionChain()); 185 186 const vector<FieldValue>& values = logEvent.getValues(); 187 ASSERT_EQ(1, values.size()); 188 189 const FieldValue& item = values[0]; 190 Field expectedField = getField(100, {1, 1, 1}, 0, {true, false, false}); 191 EXPECT_EQ(expectedField, item.mField); 192 EXPECT_EQ(Type::STRING, item.mValue.getType()); 193 EXPECT_EQ(empty, item.mValue.str_value); 194 195 AStatsEvent_release(event); 196 } 197 198 TEST(LogEventTest, TestByteArrayWithNullCharacter) { 199 AStatsEvent* event = AStatsEvent_obtain(); 200 AStatsEvent_setAtomId(event, 100); 201 uint8_t message[] = {'\t', 'e', '\0', 's', 't'}; 202 AStatsEvent_writeByteArray(event, message, 5); 203 AStatsEvent_build(event); 204 205 size_t size; 206 uint8_t* buf = AStatsEvent_getBuffer(event, &size); 207 208 LogEvent logEvent(/*uid=*/1000, /*pid=*/1001); 209 EXPECT_TRUE(logEvent.parseBuffer(buf, size)); 210 211 EXPECT_EQ(100, logEvent.GetTagId()); 212 EXPECT_EQ(1000, logEvent.GetUid()); 213 EXPECT_EQ(1001, logEvent.GetPid()); 214 215 const vector<FieldValue>& values = logEvent.getValues(); 216 ASSERT_EQ(1, values.size()); 217 218 const FieldValue& item = values[0]; 219 Field expectedField = getField(100, {1, 1, 1}, 0, {true, false, false}); 220 EXPECT_EQ(expectedField, item.mField); 221 EXPECT_EQ(Type::STORAGE, item.mValue.getType()); 222 vector<uint8_t> expectedValue(message, message + 5); 223 EXPECT_EQ(expectedValue, item.mValue.storage_value); 224 225 AStatsEvent_release(event); 226 } 227 228 TEST(LogEventTest, TestAttributionChain) { 229 AStatsEvent* event = AStatsEvent_obtain(); 230 AStatsEvent_setAtomId(event, 100); 231 232 string tag1 = "tag1"; 233 string tag2 = "tag2"; 234 235 uint32_t uids[] = {1001, 1002}; 236 const char* tags[] = {tag1.c_str(), tag2.c_str()}; 237 238 AStatsEvent_writeAttributionChain(event, uids, tags, 2); 239 AStatsEvent_build(event); 240 241 size_t size; 242 uint8_t* buf = AStatsEvent_getBuffer(event, &size); 243 244 LogEvent logEvent(/*uid=*/1000, /*pid=*/1001); 245 EXPECT_TRUE(logEvent.parseBuffer(buf, size)); 246 247 EXPECT_EQ(100, logEvent.GetTagId()); 248 EXPECT_EQ(1000, logEvent.GetUid()); 249 EXPECT_EQ(1001, logEvent.GetPid()); 250 251 const vector<FieldValue>& values = logEvent.getValues(); 252 ASSERT_EQ(4, values.size()); // 2 per attribution node 253 254 std::pair<int, int> attrIndexRange; 255 EXPECT_TRUE(logEvent.hasAttributionChain(&attrIndexRange)); 256 EXPECT_EQ(0, attrIndexRange.first); 257 EXPECT_EQ(3, attrIndexRange.second); 258 259 // Check first attribution node 260 const FieldValue& uid1Item = values[0]; 261 Field expectedField = getField(100, {1, 1, 1}, 2, {true, false, false}); 262 EXPECT_EQ(expectedField, uid1Item.mField); 263 EXPECT_EQ(Type::INT, uid1Item.mValue.getType()); 264 EXPECT_EQ(1001, uid1Item.mValue.int_value); 265 266 const FieldValue& tag1Item = values[1]; 267 expectedField = getField(100, {1, 1, 2}, 2, {true, false, true}); 268 EXPECT_EQ(expectedField, tag1Item.mField); 269 EXPECT_EQ(Type::STRING, tag1Item.mValue.getType()); 270 EXPECT_EQ(tag1, tag1Item.mValue.str_value); 271 272 // Check second attribution nodes 273 const FieldValue& uid2Item = values[2]; 274 expectedField = getField(100, {1, 2, 1}, 2, {true, true, false}); 275 EXPECT_EQ(expectedField, uid2Item.mField); 276 EXPECT_EQ(Type::INT, uid2Item.mValue.getType()); 277 EXPECT_EQ(1002, uid2Item.mValue.int_value); 278 279 const FieldValue& tag2Item = values[3]; 280 expectedField = getField(100, {1, 2, 2}, 2, {true, true, true}); 281 EXPECT_EQ(expectedField, tag2Item.mField); 282 EXPECT_EQ(Type::STRING, tag2Item.mValue.getType()); 283 EXPECT_EQ(tag2, tag2Item.mValue.str_value); 284 285 AStatsEvent_release(event); 286 } 287 288 TEST(LogEventTest, TestAnnotationIdIsUid) { 289 LogEvent event(/*uid=*/0, /*pid=*/0); 290 createIntWithBoolAnnotationLogEvent(&event, ANNOTATION_ID_IS_UID, true); 291 292 const vector<FieldValue>& values = event.getValues(); 293 ASSERT_EQ(values.size(), 1); 294 EXPECT_EQ(event.getUidFieldIndex(), 0); 295 } 296 297 TEST(LogEventTest, TestAnnotationIdStateNested) { 298 LogEvent event(/*uid=*/0, /*pid=*/0); 299 createIntWithBoolAnnotationLogEvent(&event, ANNOTATION_ID_STATE_NESTED, true); 300 301 const vector<FieldValue>& values = event.getValues(); 302 ASSERT_EQ(values.size(), 1); 303 EXPECT_TRUE(values[0].mAnnotations.isNested()); 304 } 305 306 TEST(LogEventTest, TestPrimaryFieldAnnotation) { 307 LogEvent event(/*uid=*/0, /*pid=*/0); 308 createIntWithBoolAnnotationLogEvent(&event, ANNOTATION_ID_PRIMARY_FIELD, true); 309 310 const vector<FieldValue>& values = event.getValues(); 311 ASSERT_EQ(values.size(), 1); 312 EXPECT_TRUE(values[0].mAnnotations.isPrimaryField()); 313 } 314 315 TEST(LogEventTest, TestExclusiveStateAnnotation) { 316 LogEvent event(/*uid=*/0, /*pid=*/0); 317 createIntWithBoolAnnotationLogEvent(&event, ANNOTATION_ID_EXCLUSIVE_STATE, true); 318 319 const vector<FieldValue>& values = event.getValues(); 320 ASSERT_EQ(values.size(), 1); 321 EXPECT_TRUE(values[0].mAnnotations.isExclusiveState()); 322 } 323 324 TEST(LogEventTest, TestPrimaryFieldFirstUidAnnotation) { 325 // Event has 10 ints and then an attribution chain 326 int numInts = 10; 327 int firstUidInChainIndex = numInts; 328 string tag1 = "tag1"; 329 string tag2 = "tag2"; 330 uint32_t uids[] = {1001, 1002}; 331 const char* tags[] = {tag1.c_str(), tag2.c_str()}; 332 333 // Construct AStatsEvent 334 AStatsEvent* statsEvent = AStatsEvent_obtain(); 335 AStatsEvent_setAtomId(statsEvent, 100); 336 for (int i = 0; i < numInts; i++) { 337 AStatsEvent_writeInt32(statsEvent, 10); 338 } 339 AStatsEvent_writeAttributionChain(statsEvent, uids, tags, 2); 340 AStatsEvent_addBoolAnnotation(statsEvent, ANNOTATION_ID_PRIMARY_FIELD_FIRST_UID, true); 341 AStatsEvent_build(statsEvent); 342 343 // Construct LogEvent 344 size_t size; 345 uint8_t* buf = AStatsEvent_getBuffer(statsEvent, &size); 346 LogEvent logEvent(/*uid=*/0, /*pid=*/0); 347 EXPECT_TRUE(logEvent.parseBuffer(buf, size)); 348 AStatsEvent_release(statsEvent); 349 350 // Check annotation 351 const vector<FieldValue>& values = logEvent.getValues(); 352 ASSERT_EQ(values.size(), numInts + 4); 353 EXPECT_TRUE(values[firstUidInChainIndex].mAnnotations.isPrimaryField()); 354 } 355 356 TEST(LogEventTest, TestResetStateAnnotation) { 357 int32_t resetState = 10; 358 LogEvent event(/*uid=*/0, /*pid=*/0); 359 createIntWithIntAnnotationLogEvent(&event, ANNOTATION_ID_TRIGGER_STATE_RESET, resetState); 360 361 const vector<FieldValue>& values = event.getValues(); 362 ASSERT_EQ(values.size(), 1); 363 EXPECT_EQ(event.getResetState(), resetState); 364 } 365 366 TEST(LogEventTest, TestExclusiveStateAnnotationAfterTooManyFields) { 367 AStatsEvent* event = AStatsEvent_obtain(); 368 AStatsEvent_setAtomId(event, 100); 369 370 const unsigned int numAttributionNodes = 64; 371 372 uint32_t uids[numAttributionNodes]; 373 const char* tags[numAttributionNodes]; 374 375 for (unsigned int i = 1; i <= numAttributionNodes; i++) { 376 uids[i-1] = i; 377 tags[i-1] = std::to_string(i).c_str(); 378 } 379 380 AStatsEvent_writeAttributionChain(event, uids, tags, numAttributionNodes); 381 AStatsEvent_writeInt32(event, 1); 382 AStatsEvent_addBoolAnnotation(event, ANNOTATION_ID_EXCLUSIVE_STATE, true); 383 384 AStatsEvent_build(event); 385 386 size_t size; 387 uint8_t* buf = AStatsEvent_getBuffer(event, &size); 388 389 LogEvent logEvent(/*uid=*/1000, /*pid=*/1001); 390 EXPECT_FALSE(logEvent.parseBuffer(buf, size)); 391 EXPECT_EQ(-1, logEvent.getExclusiveStateFieldIndex()); 392 393 AStatsEvent_release(event); 394 } 395 396 TEST(LogEventTest, TestUidAnnotationAfterTooManyFields) { 397 AStatsEvent* event = AStatsEvent_obtain(); 398 AStatsEvent_setAtomId(event, 100); 399 400 const unsigned int numAttributionNodes = 64; 401 402 uint32_t uids[numAttributionNodes]; 403 const char* tags[numAttributionNodes]; 404 405 for (unsigned int i = 1; i <= numAttributionNodes; i++) { 406 uids[i-1] = i; 407 tags[i-1] = std::to_string(i).c_str(); 408 } 409 410 AStatsEvent_writeAttributionChain(event, uids, tags, numAttributionNodes); 411 AStatsEvent_writeInt32(event, 1); 412 AStatsEvent_addBoolAnnotation(event, ANNOTATION_ID_IS_UID, true); 413 414 AStatsEvent_build(event); 415 416 size_t size; 417 uint8_t* buf = AStatsEvent_getBuffer(event, &size); 418 419 LogEvent logEvent(/*uid=*/1000, /*pid=*/1001); 420 EXPECT_FALSE(logEvent.parseBuffer(buf, size)); 421 EXPECT_EQ(-1, logEvent.getUidFieldIndex()); 422 423 AStatsEvent_release(event); 424 } 425 426 TEST(LogEventTest, TestAttributionChainEndIndexAfterTooManyFields) { 427 AStatsEvent* event = AStatsEvent_obtain(); 428 AStatsEvent_setAtomId(event, 100); 429 430 const unsigned int numAttributionNodes = 65; 431 432 uint32_t uids[numAttributionNodes]; 433 const char* tags[numAttributionNodes]; 434 435 for (unsigned int i = 1; i <= numAttributionNodes; i++) { 436 uids[i-1] = i; 437 tags[i-1] = std::to_string(i).c_str(); 438 } 439 440 AStatsEvent_writeAttributionChain(event, uids, tags, numAttributionNodes); 441 442 AStatsEvent_build(event); 443 444 size_t size; 445 uint8_t* buf = AStatsEvent_getBuffer(event, &size); 446 447 LogEvent logEvent(/*uid=*/1000, /*pid=*/1001); 448 EXPECT_FALSE(logEvent.parseBuffer(buf, size)); 449 EXPECT_FALSE(logEvent.hasAttributionChain()); 450 451 AStatsEvent_release(event); 452 } 453 454 TEST(LogEventTest, TestEmptyAttributionChainWithPrimaryFieldFirstUidAnnotation) { 455 AStatsEvent* event = AStatsEvent_obtain(); 456 AStatsEvent_setAtomId(event, 100); 457 458 uint32_t uids[] = {}; 459 const char* tags[] = {}; 460 461 AStatsEvent_writeInt32(event, 10); 462 AStatsEvent_writeAttributionChain(event, uids, tags, 0); 463 AStatsEvent_addBoolAnnotation(event, ANNOTATION_ID_PRIMARY_FIELD_FIRST_UID, true); 464 465 AStatsEvent_build(event); 466 467 size_t size; 468 uint8_t* buf = AStatsEvent_getBuffer(event, &size); 469 470 LogEvent logEvent(/*uid=*/1000, /*pid=*/1001); 471 EXPECT_FALSE(logEvent.parseBuffer(buf, size)); 472 473 AStatsEvent_release(event); 474 } 475 476 } // namespace statsd 477 } // namespace os 478 } // namespace android 479 #else 480 GTEST_LOG_(INFO) << "This test does nothing.\n"; 481 #endif 482