diff options
author | Vova Sharaienko <sharaienko@google.com> | 2023-05-10 00:40:50 +0000 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2023-05-10 00:40:50 +0000 |
commit | ca900a3139e944b561732f488c4c88bb2b24a32d (patch) | |
tree | 99d4514ac2f0518735bde7dc97ae63dce5ed8917 | |
parent | f1c1be268b83e12b6ec7478bcd1ae7178fc0e3db (diff) | |
parent | 051b24c53e89045115c51794ac3c359f7c6f7e92 (diff) | |
download | StatsD-ca900a3139e944b561732f488c4c88bb2b24a32d.tar.gz |
Merge "Added support to parse LogEvent header & body explicitly" into udc-dev
-rw-r--r-- | statsd/benchmark/log_event_benchmark.cpp | 162 | ||||
-rw-r--r-- | statsd/src/logd/LogEvent.cpp | 80 | ||||
-rw-r--r-- | statsd/src/logd/LogEvent.h | 45 | ||||
-rw-r--r-- | statsd/tests/LogEvent_test.cpp | 463 |
4 files changed, 509 insertions, 241 deletions
diff --git a/statsd/benchmark/log_event_benchmark.cpp b/statsd/benchmark/log_event_benchmark.cpp index 6eb250c4..419f323b 100644 --- a/statsd/benchmark/log_event_benchmark.cpp +++ b/statsd/benchmark/log_event_benchmark.cpp @@ -22,11 +22,19 @@ namespace android { namespace os { namespace statsd { -static size_t createAndParseStatsEvent(uint8_t* msg) { +static void writeEventTestFields(AStatsEvent& event) { + AStatsEvent_writeInt64(&event, 3L); + AStatsEvent_writeInt32(&event, 2); + AStatsEvent_writeFloat(&event, 2.0); + AStatsEvent_writeString(&event, "DemoStringValue"); +} + +static size_t createStatsEvent(uint8_t* msg, int numElements = 1) { AStatsEvent* event = AStatsEvent_obtain(); AStatsEvent_setAtomId(event, 100); - AStatsEvent_writeInt32(event, 2); - AStatsEvent_writeFloat(event, 2.0); + for (int i = 0; i < numElements; i++) { + writeEventTestFields(*event); + } AStatsEvent_build(event); size_t size; @@ -35,9 +43,21 @@ static size_t createAndParseStatsEvent(uint8_t* msg) { return size; } +static size_t createStatsEventMedium(uint8_t* msg) { + return createStatsEvent(msg, 5); +} + +static size_t createStatsEventLarge(uint8_t* msg) { + return createStatsEvent(msg, 10); +} + +static size_t createStatsEventExtraLarge(uint8_t* msg) { + return createStatsEvent(msg, 40); +} + static void BM_LogEventCreation(benchmark::State& state) { uint8_t msg[LOGGER_ENTRY_MAX_PAYLOAD]; - size_t size = createAndParseStatsEvent(msg); + size_t size = createStatsEvent(msg); while (state.KeepRunning()) { LogEvent event(/*uid=*/ 1000, /*pid=*/ 1001); benchmark::DoNotOptimize(event.parseBuffer(msg, size)); @@ -47,19 +67,145 @@ BENCHMARK(BM_LogEventCreation); static void BM_LogEventCreationWithPrefetch(benchmark::State& state) { uint8_t msg[LOGGER_ENTRY_MAX_PAYLOAD]; - size_t size = createAndParseStatsEvent(msg); + size_t size = createStatsEvent(msg); while (state.KeepRunning()) { LogEvent event(/*uid=*/1000, /*pid=*/1001); // explicitly parse header first - benchmark::DoNotOptimize(event.parseBuffer(msg, size, /*fetchHeaderOnly*/ true)); + const LogEvent::BodyBufferInfo header = event.parseHeader(msg, size); - // re-parse header & body - benchmark::DoNotOptimize(event.parseBuffer(msg, size, /*fetchHeaderOnly*/ false)); + // explicitly parse body using the header + benchmark::DoNotOptimize(event.parseBody(header)); } } BENCHMARK(BM_LogEventCreationWithPrefetch); +static void BM_LogEventCreationWithPrefetchOnly(benchmark::State& state) { + uint8_t msg[LOGGER_ENTRY_MAX_PAYLOAD]; + size_t size = createStatsEvent(msg); + while (state.KeepRunning()) { + LogEvent event(/*uid=*/1000, /*pid=*/1001); + + // explicitly parse header only and skip the body + benchmark::DoNotOptimize(event.parseHeader(msg, size)); + } +} +BENCHMARK(BM_LogEventCreationWithPrefetchOnly); + +static void BM_LogEventCreationMedium(benchmark::State& state) { + uint8_t msg[LOGGER_ENTRY_MAX_PAYLOAD]; + size_t size = createStatsEventMedium(msg); + while (state.KeepRunning()) { + LogEvent event(/*uid=*/1000, /*pid=*/1001); + + benchmark::DoNotOptimize(event.parseBuffer(msg, size)); + } +} +BENCHMARK(BM_LogEventCreationMedium); + +static void BM_LogEventCreationMediumWithPrefetch(benchmark::State& state) { + uint8_t msg[LOGGER_ENTRY_MAX_PAYLOAD]; + size_t size = createStatsEventMedium(msg); + while (state.KeepRunning()) { + LogEvent event(/*uid=*/1000, /*pid=*/1001); + + // explicitly parse header first + const LogEvent::BodyBufferInfo header = event.parseHeader(msg, size); + + // explicitly parse body using the header + benchmark::DoNotOptimize(event.parseBody(header)); + } +} +BENCHMARK(BM_LogEventCreationMediumWithPrefetch); + +static void BM_LogEventCreationMediumWithPrefetchOnly(benchmark::State& state) { + uint8_t msg[LOGGER_ENTRY_MAX_PAYLOAD]; + size_t size = createStatsEventMedium(msg); + while (state.KeepRunning()) { + LogEvent event(/*uid=*/1000, /*pid=*/1001); + + // explicitly parse header only and skip the body + benchmark::DoNotOptimize(event.parseHeader(msg, size)); + } +} +BENCHMARK(BM_LogEventCreationMediumWithPrefetchOnly); + +static void BM_LogEventCreationLarge(benchmark::State& state) { + uint8_t msg[LOGGER_ENTRY_MAX_PAYLOAD]; + size_t size = createStatsEventLarge(msg); + while (state.KeepRunning()) { + LogEvent event(/*uid=*/1000, /*pid=*/1001); + + benchmark::DoNotOptimize(event.parseBuffer(msg, size)); + } +} +BENCHMARK(BM_LogEventCreationLarge); + +static void BM_LogEventCreationLargeWithPrefetch(benchmark::State& state) { + uint8_t msg[LOGGER_ENTRY_MAX_PAYLOAD]; + size_t size = createStatsEventLarge(msg); + while (state.KeepRunning()) { + LogEvent event(/*uid=*/1000, /*pid=*/1001); + + // explicitly parse header first + const LogEvent::BodyBufferInfo header = event.parseHeader(msg, size); + + // explicitly parse body using the header + benchmark::DoNotOptimize(event.parseBody(header)); + } +} +BENCHMARK(BM_LogEventCreationLargeWithPrefetch); + +static void BM_LogEventCreationLargeWithPrefetchOnly(benchmark::State& state) { + uint8_t msg[LOGGER_ENTRY_MAX_PAYLOAD]; + size_t size = createStatsEventLarge(msg); + while (state.KeepRunning()) { + LogEvent event(/*uid=*/1000, /*pid=*/1001); + + // explicitly parse header only and skip the body + benchmark::DoNotOptimize(event.parseHeader(msg, size)); + } +} +BENCHMARK(BM_LogEventCreationLargeWithPrefetchOnly); + +static void BM_LogEventCreationExtraLarge(benchmark::State& state) { + uint8_t msg[LOGGER_ENTRY_MAX_PAYLOAD]; + size_t size = createStatsEventExtraLarge(msg); + while (state.KeepRunning()) { + LogEvent event(/*uid=*/1000, /*pid=*/1001); + + benchmark::DoNotOptimize(event.parseBuffer(msg, size)); + } +} +BENCHMARK(BM_LogEventCreationExtraLarge); + +static void BM_LogEventCreationExtraLargeWithPrefetch(benchmark::State& state) { + uint8_t msg[LOGGER_ENTRY_MAX_PAYLOAD]; + size_t size = createStatsEventExtraLarge(msg); + while (state.KeepRunning()) { + LogEvent event(/*uid=*/1000, /*pid=*/1001); + + // explicitly parse header first + const LogEvent::BodyBufferInfo header = event.parseHeader(msg, size); + + // explicitly parse body using the header + benchmark::DoNotOptimize(event.parseBody(header)); + } +} +BENCHMARK(BM_LogEventCreationExtraLargeWithPrefetch); + +static void BM_LogEventCreationExtraLargeWithPrefetchOnly(benchmark::State& state) { + uint8_t msg[LOGGER_ENTRY_MAX_PAYLOAD]; + size_t size = createStatsEventExtraLarge(msg); + while (state.KeepRunning()) { + LogEvent event(/*uid=*/1000, /*pid=*/1001); + + // explicitly parse header only and skip the body + benchmark::DoNotOptimize(event.parseHeader(msg, size)); + } +} +BENCHMARK(BM_LogEventCreationExtraLargeWithPrefetchOnly); + } // namespace statsd } // namespace os } // namespace android diff --git a/statsd/src/logd/LogEvent.cpp b/statsd/src/logd/LogEvent.cpp index 95e1e962..ff1c1923 100644 --- a/statsd/src/logd/LogEvent.cpp +++ b/statsd/src/logd/LogEvent.cpp @@ -41,6 +41,18 @@ using android::util::ProtoOutputStream; using std::string; using std::vector; +namespace { + +uint8_t getTypeId(uint8_t typeInfo) { + return typeInfo & 0x0F; // type id in lower 4 bytes +} + +uint8_t getNumAnnotations(uint8_t typeInfo) { + return (typeInfo >> 4) & 0x0F; // num annotations in upper 4 bytes +} + +} // namespace + LogEvent::LogEvent(int32_t uid, int32_t pid) : mLogdTimestampNs(getWallClockNs()), mLogUid(uid), mLogPid(pid) { } @@ -473,24 +485,34 @@ void LogEvent::parseAnnotations(uint8_t numAnnotations, std::optional<uint8_t> n } } -uint8_t LogEvent::parseHeader() { +LogEvent::BodyBufferInfo LogEvent::parseHeader(const uint8_t* buf, size_t len) { + BodyBufferInfo bodyInfo; + + mParsedHeaderOnly = true; + + mBuf = buf; + mRemainingLen = (uint32_t)len; + // Beginning of buffer is OBJECT_TYPE | NUM_FIELDS | TIMESTAMP | ATOM_ID uint8_t typeInfo = readNextValue<uint8_t>(); if (getTypeId(typeInfo) != OBJECT_TYPE) { mValid = false; - return 0; + mBuf = nullptr; + return bodyInfo; } uint8_t numElements = readNextValue<uint8_t>(); if (numElements < 2 || numElements > INT8_MAX) { mValid = false; - return 0; + mBuf = nullptr; + return bodyInfo; } typeInfo = readNextValue<uint8_t>(); if (getTypeId(typeInfo) != INT64_TYPE) { mValid = false; - return 0; + mBuf = nullptr; + return bodyInfo; } mElapsedTimestampNs = readNextValue<int64_t>(); numElements--; @@ -498,34 +520,33 @@ uint8_t LogEvent::parseHeader() { typeInfo = readNextValue<uint8_t>(); if (getTypeId(typeInfo) != INT32_TYPE) { mValid = false; - return 0; + mBuf = nullptr; + return bodyInfo; } mTagId = readNextValue<int32_t>(); numElements--; parseAnnotations(getNumAnnotations(typeInfo)); // atom-level annotations - return numElements; -} + bodyInfo.numElements = numElements; + bodyInfo.buffer = mBuf; + bodyInfo.bufferSize = mRemainingLen; -// This parsing logic is tied to the encoding scheme used in StatsEvent.java and -// stats_event.c -bool LogEvent::parseBuffer(const uint8_t* buf, size_t len, bool fetchHeaderOnly) { - mBuf = buf; - mRemainingLen = (uint32_t)len; + mBuf = nullptr; + return bodyInfo; +} - const uint8_t numElements = parseHeader(); +bool LogEvent::parseBody(const BodyBufferInfo& bodyInfo) { + mParsedHeaderOnly = false; - if (!mValid || fetchHeaderOnly) { - mBuf = nullptr; - return mValid; - } + mBuf = bodyInfo.buffer; + mRemainingLen = (uint32_t)bodyInfo.bufferSize; int32_t pos[] = {1, 1, 1}; bool last[] = {false, false, false}; - for (pos[0] = 1; pos[0] <= numElements && mValid; pos[0]++) { - last[0] = (pos[0] == numElements); + for (pos[0] = 1; pos[0] <= bodyInfo.numElements && mValid; pos[0]++) { + last[0] = (pos[0] == bodyInfo.numElements); uint8_t typeInfo = readNextValue<uint8_t>(); uint8_t typeId = getTypeId(typeInfo); @@ -573,12 +594,18 @@ bool LogEvent::parseBuffer(const uint8_t* buf, size_t len, bool fetchHeaderOnly) return mValid; } -uint8_t LogEvent::getTypeId(uint8_t typeInfo) { - return typeInfo & 0x0F; // type id in lower 4 bytes -} +// This parsing logic is tied to the encoding scheme used in StatsEvent.java and +// stats_event.c +bool LogEvent::parseBuffer(const uint8_t* buf, size_t len) { + BodyBufferInfo bodyInfo = parseHeader(buf, len); -uint8_t LogEvent::getNumAnnotations(uint8_t typeInfo) { - return (typeInfo >> 4) & 0x0F; // num annotations in upper 4 bytes + // early termination if header is invalid + if (!mValid) { + mBuf = nullptr; + return false; + } + + return parseBody(bodyInfo); } int64_t LogEvent::GetLong(size_t key, status_t* err) const { @@ -721,6 +748,11 @@ string LogEvent::ToString() const { result += " [" + annotations + "] "; } + if (isParsedHeaderOnly()) { + result += " ParsedHeaderOnly }"; + return result; + } + for (const auto& value : mValues) { result += StringPrintf("%#x", value.mField.getField()) + "->" + value.mValue.toString(); result += value.mAnnotations.toString() + " "; diff --git a/statsd/src/logd/LogEvent.h b/statsd/src/logd/LogEvent.h index a2730a28..d75b4462 100644 --- a/statsd/src/logd/LogEvent.h +++ b/statsd/src/logd/LogEvent.h @@ -89,12 +89,31 @@ public: * \param buf a buffer that begins at the start of the serialized atom (it * should not include the android_log_header_t or the StatsEventTag) * \param len size of the buffer - * \param fetchHeaderOnly force to parse only event header with atomId,timestamp - * and atom level annotations * - * \return success of the initialization + * \return success of the parsing + */ + bool parseBuffer(const uint8_t* buf, size_t len); + + struct BodyBufferInfo { + const uint8_t* buffer = nullptr; + size_t bufferSize = 0; + uint8_t numElements = 0; + }; + + /** + * @brief Parses atom header which consists of atom id, timestamp + * and atom level annotations + * Updates the value of isValid() + * @return BodyBufferInfo to be used for parseBody() + */ + BodyBufferInfo parseHeader(const uint8_t* buf, size_t len); + + /** + * @brief Parses atom body which consists of header.numElements elements + * Should be called only with BodyBufferInfo if when logEvent.isValid() == true + * \return success of the parsing */ - bool parseBuffer(const uint8_t* buf, size_t len, bool fetchHeaderOnly = false); + bool parseBody(const BodyBufferInfo& bodyInfo); // Constructs a BinaryPushStateChanged LogEvent from API call. explicit LogEvent(const std::string& trainName, int64_t trainVersionCode, bool requiresStaging, @@ -233,6 +252,13 @@ public: } /** + * @brief Returns true if only header was parsed + */ + bool isParsedHeaderOnly() const { + return mParsedHeaderOnly; + } + + /** * Only use this if copy is absolutely needed. */ LogEvent(const LogEvent&) = default; @@ -246,12 +272,6 @@ public: } private: - /** - * @brief Parses atom header which consists of atom id, timestamp - * and atom level annotations - * @return amount of fields on the atom level - */ - uint8_t parseHeader(); void parseInt32(int32_t* pos, int32_t depth, bool* last, uint8_t numAnnotations); void parseInt64(int32_t* pos, int32_t depth, bool* last, uint8_t numAnnotations); void parseString(int32_t* pos, int32_t depth, bool* last, uint8_t numAnnotations); @@ -289,6 +309,8 @@ private: bool mValid = true; // stores whether the event we received from the socket is valid + bool mParsedHeaderOnly = false; // stores whether the only header was parsed skipping the body + /** * Side-effects: * If there is enough space in buffer to read value of type T @@ -329,9 +351,6 @@ private: mValues.push_back(FieldValue(f, v)); } - uint8_t getTypeId(uint8_t typeInfo); - uint8_t getNumAnnotations(uint8_t typeInfo); - // The items are naturally sorted in DFS order as we read them. this allows us to do fast // matching. std::vector<FieldValue> mValues; diff --git a/statsd/tests/LogEvent_test.cpp b/statsd/tests/LogEvent_test.cpp index d44a8a3e..ae229081 100644 --- a/statsd/tests/LogEvent_test.cpp +++ b/statsd/tests/LogEvent_test.cpp @@ -85,36 +85,50 @@ void createStatsEvent(AStatsEvent* statsEvent, uint8_t typeId) { fillStatsEventWithSampleValue(statsEvent, typeId); } -void createFieldWithBoolAnnotationLogEvent(LogEvent* logEvent, uint8_t typeId, uint8_t annotationId, - bool annotationValue, bool parseBufferResult) { +bool createFieldWithBoolAnnotationLogEvent(LogEvent* logEvent, uint8_t typeId, uint8_t annotationId, + bool annotationValue, bool doHeaderPrefetch) { AStatsEvent* statsEvent = AStatsEvent_obtain(); createStatsEvent(statsEvent, typeId); AStatsEvent_addBoolAnnotation(statsEvent, annotationId, annotationValue); AStatsEvent_build(statsEvent); size_t size; - uint8_t* buf = AStatsEvent_getBuffer(statsEvent, &size); - EXPECT_EQ(parseBufferResult, logEvent->parseBuffer(buf, size)); - + const uint8_t* buf = AStatsEvent_getBuffer(statsEvent, &size); + if (doHeaderPrefetch) { + // Testing LogEvent header prefetch logic + const LogEvent::BodyBufferInfo bodyInfo = logEvent->parseHeader(buf, size); + logEvent->parseBody(bodyInfo); + } else { + logEvent->parseBuffer(buf, size); + } AStatsEvent_release(statsEvent); + + return logEvent->isValid(); } -void createFieldWithIntAnnotationLogEvent(LogEvent* logEvent, uint8_t typeId, uint8_t annotationId, - int annotationValue, bool parseBufferResult) { +bool createFieldWithIntAnnotationLogEvent(LogEvent* logEvent, uint8_t typeId, uint8_t annotationId, + int annotationValue, bool doHeaderPrefetch) { AStatsEvent* statsEvent = AStatsEvent_obtain(); createStatsEvent(statsEvent, typeId); AStatsEvent_addInt32Annotation(statsEvent, annotationId, annotationValue); AStatsEvent_build(statsEvent); size_t size; - uint8_t* buf = AStatsEvent_getBuffer(statsEvent, &size); - EXPECT_EQ(parseBufferResult, logEvent->parseBuffer(buf, size)); - + const uint8_t* buf = AStatsEvent_getBuffer(statsEvent, &size); + if (doHeaderPrefetch) { + // Testing LogEvent header prefetch logic + const LogEvent::BodyBufferInfo bodyInfo = logEvent->parseHeader(buf, size); + logEvent->parseBody(bodyInfo); + } else { + logEvent->parseBuffer(buf, size); + } AStatsEvent_release(statsEvent); + + return logEvent->isValid(); } -void createAtomLevelIntAnnotationLogEvent(LogEvent* logEvent, uint8_t typeId, uint8_t annotationId, - int annotationValue, bool parseBufferResult) { +bool createAtomLevelIntAnnotationLogEvent(LogEvent* logEvent, uint8_t typeId, uint8_t annotationId, + int annotationValue, bool doHeaderPrefetch) { AStatsEvent* statsEvent = AStatsEvent_obtain(); AStatsEvent_setAtomId(statsEvent, /*atomId=*/100); AStatsEvent_addInt32Annotation(statsEvent, annotationId, annotationValue); @@ -122,14 +136,21 @@ void createAtomLevelIntAnnotationLogEvent(LogEvent* logEvent, uint8_t typeId, ui AStatsEvent_build(statsEvent); size_t size; - uint8_t* buf = AStatsEvent_getBuffer(statsEvent, &size); - EXPECT_EQ(parseBufferResult, logEvent->parseBuffer(buf, size)); - + const uint8_t* buf = AStatsEvent_getBuffer(statsEvent, &size); + if (doHeaderPrefetch) { + // Testing LogEvent header prefetch logic + const LogEvent::BodyBufferInfo bodyInfo = logEvent->parseHeader(buf, size); + logEvent->parseBody(bodyInfo); + } else { + logEvent->parseBuffer(buf, size); + } AStatsEvent_release(statsEvent); + + return logEvent->isValid(); } -void createAtomLevelBoolAnnotationLogEvent(LogEvent* logEvent, uint8_t typeId, uint8_t annotationId, - bool annotationValue, bool parseBufferResult) { +bool createAtomLevelBoolAnnotationLogEvent(LogEvent* logEvent, uint8_t typeId, uint8_t annotationId, + bool annotationValue, bool doHeaderPrefetch) { AStatsEvent* statsEvent = AStatsEvent_obtain(); AStatsEvent_setAtomId(statsEvent, /*atomId=*/100); AStatsEvent_addBoolAnnotation(statsEvent, annotationId, annotationValue); @@ -137,34 +158,44 @@ void createAtomLevelBoolAnnotationLogEvent(LogEvent* logEvent, uint8_t typeId, u AStatsEvent_build(statsEvent); size_t size; - uint8_t* buf = AStatsEvent_getBuffer(statsEvent, &size); - EXPECT_EQ(parseBufferResult, logEvent->parseBuffer(buf, size)); + const uint8_t* buf = AStatsEvent_getBuffer(statsEvent, &size); + if (doHeaderPrefetch) { + // Testing LogEvent header prefetch logic + const LogEvent::BodyBufferInfo bodyInfo = logEvent->parseHeader(buf, size); + logEvent->parseBody(bodyInfo); + } else { + logEvent->parseBuffer(buf, size); + } AStatsEvent_release(statsEvent); + + return logEvent->isValid(); } } // anonymous namespace // Setup for parameterized tests. -class LogEventTestBadAnnotationFieldTypes : public testing::TestWithParam<int> { +class LogEventTestBadAnnotationFieldTypes : public testing::TestWithParam<std::tuple<int, bool>> { public: - static std::string ToString(testing::TestParamInfo<int> info) { - switch (info.param) { + static std::string ToString(testing::TestParamInfo<std::tuple<int, bool>> info) { + const std::string boolName = std::get<1>(info.param) ? "_prefetchTrue" : "_prefetchFalse"; + + switch (std::get<0>(info.param)) { case INT32_TYPE: - return "Int32"; + return "Int32" + boolName; case INT64_TYPE: - return "Int64"; + return "Int64" + boolName; case STRING_TYPE: - return "String"; + return "String" + boolName; case LIST_TYPE: - return "List"; + return "List" + boolName; case FLOAT_TYPE: - return "Float"; + return "Float" + boolName; case BYTE_ARRAY_TYPE: - return "ByteArray"; + return "ByteArray" + boolName; case ATTRIBUTION_CHAIN_TYPE: - return "AttributionChain"; + return "AttributionChain" + boolName; default: - return "Unknown"; + return "Unknown" + boolName; } } }; @@ -172,11 +203,37 @@ public: // TODO(b/222539899): Add BOOL_TYPE value once parseAnnotations is updated to check specific // typeIds. BOOL_TYPE should be a bad field type for is_uid, nested, and reset state annotations. INSTANTIATE_TEST_SUITE_P(BadAnnotationFieldTypes, LogEventTestBadAnnotationFieldTypes, - testing::Values(INT32_TYPE, INT64_TYPE, STRING_TYPE, LIST_TYPE, FLOAT_TYPE, - BYTE_ARRAY_TYPE, ATTRIBUTION_CHAIN_TYPE), + testing::Combine(testing::Values(INT32_TYPE, INT64_TYPE, STRING_TYPE, + LIST_TYPE, FLOAT_TYPE, BYTE_ARRAY_TYPE, + ATTRIBUTION_CHAIN_TYPE), + testing::Bool()), LogEventTestBadAnnotationFieldTypes::ToString); -TEST(LogEventTest, TestPrimitiveParsing) { +class LogEventTest : public testing::TestWithParam<bool> { +protected: + bool ParseBuffer(LogEvent& logEvent, const uint8_t* buf, size_t size) { + size_t bufferOffset = 0; + if (GetParam()) { + // Testing LogEvent header prefetch logic + const LogEvent::BodyBufferInfo bodyInfo = logEvent.parseHeader(buf, size); + EXPECT_TRUE(logEvent.isValid()); + EXPECT_TRUE(logEvent.isParsedHeaderOnly()); + const bool parseResult = logEvent.parseBody(bodyInfo); + EXPECT_EQ(parseResult, logEvent.isValid()); + EXPECT_FALSE(logEvent.isParsedHeaderOnly()); + } else { + const bool parseResult = logEvent.parseBuffer(buf, size); + EXPECT_EQ(parseResult, logEvent.isValid()); + EXPECT_FALSE(logEvent.isParsedHeaderOnly()); + } + return logEvent.isValid(); + } +}; + +INSTANTIATE_TEST_SUITE_P(LogEventTestBufferParsing, LogEventTest, testing::Bool(), + testing::PrintToStringParamName()); + +TEST_P(LogEventTest, TestPrimitiveParsing) { AStatsEvent* event = AStatsEvent_obtain(); AStatsEvent_setAtomId(event, 100); AStatsEvent_writeInt32(event, 10); @@ -186,10 +243,10 @@ TEST(LogEventTest, TestPrimitiveParsing) { AStatsEvent_build(event); size_t size; - uint8_t* buf = AStatsEvent_getBuffer(event, &size); + const uint8_t* buf = AStatsEvent_getBuffer(event, &size); LogEvent logEvent(/*uid=*/1000, /*pid=*/1001); - EXPECT_TRUE(logEvent.parseBuffer(buf, size)); + EXPECT_TRUE(ParseBuffer(logEvent, buf, size)); EXPECT_EQ(100, logEvent.GetTagId()); EXPECT_EQ(1000, logEvent.GetUid()); @@ -226,7 +283,7 @@ TEST(LogEventTest, TestPrimitiveParsing) { AStatsEvent_release(event); } -TEST(LogEventTest, TestFetchHeaderOnly) { +TEST(LogEventTestParsing, TestFetchHeaderOnly) { AStatsEvent* event = AStatsEvent_obtain(); AStatsEvent_setAtomId(event, 100); AStatsEvent_writeInt32(event, 10); @@ -239,7 +296,9 @@ TEST(LogEventTest, TestFetchHeaderOnly) { const uint8_t* buf = AStatsEvent_getBuffer(event, &size); LogEvent logEvent(/*uid=*/1000, /*pid=*/1001); - EXPECT_TRUE(logEvent.parseBuffer(buf, size, /*fetchHeaderOnly=*/true)); + const LogEvent::BodyBufferInfo bodyInfo = logEvent.parseHeader(buf, size); + EXPECT_TRUE(logEvent.isValid()); + EXPECT_TRUE(logEvent.isParsedHeaderOnly()); AStatsEvent_release(event); @@ -247,11 +306,10 @@ TEST(LogEventTest, TestFetchHeaderOnly) { EXPECT_EQ(1000, logEvent.GetUid()); EXPECT_EQ(1001, logEvent.GetPid()); EXPECT_FALSE(logEvent.hasAttributionChain()); - - ASSERT_EQ(logEvent.getValues().size(), 0); + ASSERT_EQ(0, logEvent.getValues().size()); } -TEST(LogEventTest, TestStringAndByteArrayParsing) { +TEST_P(LogEventTest, TestStringAndByteArrayParsing) { AStatsEvent* event = AStatsEvent_obtain(); AStatsEvent_setAtomId(event, 100); string str = "test"; @@ -260,10 +318,10 @@ TEST(LogEventTest, TestStringAndByteArrayParsing) { AStatsEvent_build(event); size_t size; - uint8_t* buf = AStatsEvent_getBuffer(event, &size); + const uint8_t* buf = AStatsEvent_getBuffer(event, &size); LogEvent logEvent(/*uid=*/1000, /*pid=*/1001); - EXPECT_TRUE(logEvent.parseBuffer(buf, size)); + EXPECT_TRUE(ParseBuffer(logEvent, buf, size)); EXPECT_EQ(100, logEvent.GetTagId()); EXPECT_EQ(1000, logEvent.GetUid()); @@ -289,7 +347,7 @@ TEST(LogEventTest, TestStringAndByteArrayParsing) { AStatsEvent_release(event); } -TEST(LogEventTest, TestEmptyString) { +TEST_P(LogEventTest, TestEmptyString) { AStatsEvent* event = AStatsEvent_obtain(); AStatsEvent_setAtomId(event, 100); string empty = ""; @@ -297,10 +355,10 @@ TEST(LogEventTest, TestEmptyString) { AStatsEvent_build(event); size_t size; - uint8_t* buf = AStatsEvent_getBuffer(event, &size); + const uint8_t* buf = AStatsEvent_getBuffer(event, &size); LogEvent logEvent(/*uid=*/1000, /*pid=*/1001); - EXPECT_TRUE(logEvent.parseBuffer(buf, size)); + EXPECT_TRUE(ParseBuffer(logEvent, buf, size)); EXPECT_EQ(100, logEvent.GetTagId()); EXPECT_EQ(1000, logEvent.GetUid()); @@ -319,7 +377,7 @@ TEST(LogEventTest, TestEmptyString) { AStatsEvent_release(event); } -TEST(LogEventTest, TestByteArrayWithNullCharacter) { +TEST_P(LogEventTest, TestByteArrayWithNullCharacter) { AStatsEvent* event = AStatsEvent_obtain(); AStatsEvent_setAtomId(event, 100); uint8_t message[] = {'\t', 'e', '\0', 's', 't'}; @@ -327,10 +385,10 @@ TEST(LogEventTest, TestByteArrayWithNullCharacter) { AStatsEvent_build(event); size_t size; - uint8_t* buf = AStatsEvent_getBuffer(event, &size); + const uint8_t* buf = AStatsEvent_getBuffer(event, &size); LogEvent logEvent(/*uid=*/1000, /*pid=*/1001); - EXPECT_TRUE(logEvent.parseBuffer(buf, size)); + EXPECT_TRUE(ParseBuffer(logEvent, buf, size)); EXPECT_EQ(100, logEvent.GetTagId()); EXPECT_EQ(1000, logEvent.GetUid()); @@ -349,7 +407,7 @@ TEST(LogEventTest, TestByteArrayWithNullCharacter) { AStatsEvent_release(event); } -TEST(LogEventTest, TestTooManyTopLevelElements) { +TEST_P(LogEventTest, TestTooManyTopLevelElements) { int32_t numElements = 128; AStatsEvent* event = AStatsEvent_obtain(); AStatsEvent_setAtomId(event, 100); @@ -361,14 +419,14 @@ TEST(LogEventTest, TestTooManyTopLevelElements) { AStatsEvent_build(event); size_t size; - uint8_t* buf = AStatsEvent_getBuffer(event, &size); + const uint8_t* buf = AStatsEvent_getBuffer(event, &size); LogEvent logEvent(/*uid=*/1000, /*pid=*/1001); - EXPECT_FALSE(logEvent.parseBuffer(buf, size)); + EXPECT_FALSE(ParseBuffer(logEvent, buf, size)); AStatsEvent_release(event); } -TEST(LogEventTest, TestAttributionChain) { +TEST_P(LogEventTest, TestAttributionChain) { AStatsEvent* event = AStatsEvent_obtain(); AStatsEvent_setAtomId(event, 100); @@ -382,10 +440,10 @@ TEST(LogEventTest, TestAttributionChain) { AStatsEvent_build(event); size_t size; - uint8_t* buf = AStatsEvent_getBuffer(event, &size); + const uint8_t* buf = AStatsEvent_getBuffer(event, &size); LogEvent logEvent(/*uid=*/1000, /*pid=*/1001); - EXPECT_TRUE(logEvent.parseBuffer(buf, size)); + EXPECT_TRUE(ParseBuffer(logEvent, buf, size)); EXPECT_EQ(100, logEvent.GetTagId()); EXPECT_EQ(1000, logEvent.GetUid()); @@ -428,7 +486,7 @@ TEST(LogEventTest, TestAttributionChain) { AStatsEvent_release(event); } -TEST(LogEventTest, TestEmptyAttributionChain) { +TEST_P(LogEventTest, TestEmptyAttributionChain) { AStatsEvent* event = AStatsEvent_obtain(); AStatsEvent_setAtomId(event, 100); @@ -437,15 +495,15 @@ TEST(LogEventTest, TestEmptyAttributionChain) { AStatsEvent_build(event); size_t size; - uint8_t* buf = AStatsEvent_getBuffer(event, &size); + const uint8_t* buf = AStatsEvent_getBuffer(event, &size); LogEvent logEvent(/*uid=*/1000, /*pid=*/1001); - EXPECT_FALSE(logEvent.parseBuffer(buf, size)); + EXPECT_FALSE(ParseBuffer(logEvent, buf, size)); AStatsEvent_release(event); } -TEST(LogEventTest, TestAttributionChainTooManyElements) { +TEST_P(LogEventTest, TestAttributionChainTooManyElements) { int32_t numNodes = 128; uint32_t uids[numNodes]; vector<string> tags(numNodes); // storage that cTag elements point to @@ -463,14 +521,14 @@ TEST(LogEventTest, TestAttributionChainTooManyElements) { AStatsEvent_build(event); size_t size; - uint8_t* buf = AStatsEvent_getBuffer(event, &size); + const uint8_t* buf = AStatsEvent_getBuffer(event, &size); LogEvent logEvent(/*uid=*/1000, /*pid=*/1001); - EXPECT_FALSE(logEvent.parseBuffer(buf, size)); + EXPECT_FALSE(ParseBuffer(logEvent, buf, size)); AStatsEvent_release(event); } -TEST(LogEventTest, TestArrayParsing) { +TEST_P(LogEventTest, TestArrayParsing) { size_t numElements = 2; int32_t int32Array[2] = {3, 6}; int64_t int64Array[2] = {1000L, 1002L}; @@ -493,10 +551,10 @@ TEST(LogEventTest, TestArrayParsing) { AStatsEvent_build(event); size_t size; - uint8_t* buf = AStatsEvent_getBuffer(event, &size); + const uint8_t* buf = AStatsEvent_getBuffer(event, &size); LogEvent logEvent(/*uid=*/1000, /*pid=*/1001); - EXPECT_TRUE(logEvent.parseBuffer(buf, size)); + EXPECT_TRUE(ParseBuffer(logEvent, buf, size)); EXPECT_EQ(100, logEvent.GetTagId()); EXPECT_EQ(1000, logEvent.GetUid()); @@ -569,7 +627,7 @@ TEST(LogEventTest, TestArrayParsing) { EXPECT_EQ("str2", stringArrayItem2.mValue.str_value); } -TEST(LogEventTest, TestEmptyStringArray) { +TEST_P(LogEventTest, TestEmptyStringArray) { const char* cStringArray[2]; string empty = ""; cStringArray[0] = empty.c_str(); @@ -581,10 +639,10 @@ TEST(LogEventTest, TestEmptyStringArray) { AStatsEvent_build(event); size_t size; - uint8_t* buf = AStatsEvent_getBuffer(event, &size); + const uint8_t* buf = AStatsEvent_getBuffer(event, &size); LogEvent logEvent(/*uid=*/1000, /*pid=*/1001); - EXPECT_TRUE(logEvent.parseBuffer(buf, size)); + EXPECT_TRUE(ParseBuffer(logEvent, buf, size)); EXPECT_EQ(100, logEvent.GetTagId()); EXPECT_EQ(1000, logEvent.GetUid()); @@ -608,7 +666,7 @@ TEST(LogEventTest, TestEmptyStringArray) { AStatsEvent_release(event); } -TEST(LogEventTest, TestArrayTooManyElements) { +TEST_P(LogEventTest, TestArrayTooManyElements) { int32_t numElements = 128; int32_t int32Array[numElements]; @@ -622,15 +680,15 @@ TEST(LogEventTest, TestArrayTooManyElements) { AStatsEvent_build(event); size_t size; - uint8_t* buf = AStatsEvent_getBuffer(event, &size); + const uint8_t* buf = AStatsEvent_getBuffer(event, &size); LogEvent logEvent(/*uid=*/1000, /*pid=*/1001); - EXPECT_FALSE(logEvent.parseBuffer(buf, size)); + EXPECT_FALSE(ParseBuffer(logEvent, buf, size)); AStatsEvent_release(event); } -TEST(LogEventTest, TestEmptyArray) { +TEST_P(LogEventTest, TestEmptyArray) { int32_t int32Array[0] = {}; AStatsEvent* event = AStatsEvent_obtain(); @@ -639,10 +697,10 @@ TEST(LogEventTest, TestEmptyArray) { AStatsEvent_build(event); size_t size; - uint8_t* buf = AStatsEvent_getBuffer(event, &size); + const uint8_t* buf = AStatsEvent_getBuffer(event, &size); LogEvent logEvent(/*uid=*/1000, /*pid=*/1001); - EXPECT_TRUE(logEvent.parseBuffer(buf, size)); + EXPECT_TRUE(ParseBuffer(logEvent, buf, size)); EXPECT_EQ(100, logEvent.GetTagId()); EXPECT_EQ(1000, logEvent.GetUid()); @@ -653,10 +711,11 @@ TEST(LogEventTest, TestEmptyArray) { AStatsEvent_release(event); } -TEST(LogEventTest, TestAnnotationIdIsUid) { +TEST_P(LogEventTest, TestAnnotationIdIsUid) { LogEvent event(/*uid=*/0, /*pid=*/0); - createFieldWithBoolAnnotationLogEvent(&event, INT32_TYPE, ASTATSLOG_ANNOTATION_ID_IS_UID, true, - /*parseBufferResult*/ true); + EXPECT_TRUE(createFieldWithBoolAnnotationLogEvent(&event, INT32_TYPE, + ASTATSLOG_ANNOTATION_ID_IS_UID, true, + /*doHeaderPrefetch=*/GetParam())); ASSERT_EQ(event.getNumUidFields(), 1); @@ -665,7 +724,7 @@ TEST(LogEventTest, TestAnnotationIdIsUid) { EXPECT_TRUE(isUidField(values.at(0))); } -TEST(LogEventTest, TestAnnotationIdIsUid_RepeatedIntAndOtherFields) { +TEST_P(LogEventTest, TestAnnotationIdIsUid_RepeatedIntAndOtherFields) { size_t numElements = 2; int32_t int32Array[2] = {3, 6}; @@ -684,9 +743,9 @@ TEST(LogEventTest, TestAnnotationIdIsUid_RepeatedIntAndOtherFields) { AStatsEvent_build(statsEvent); size_t size; - uint8_t* buf = AStatsEvent_getBuffer(statsEvent, &size); + const uint8_t* buf = AStatsEvent_getBuffer(statsEvent, &size); LogEvent logEvent(/*uid=*/1000, /*pid=*/1001); - EXPECT_TRUE(logEvent.parseBuffer(buf, size)); + EXPECT_TRUE(ParseBuffer(logEvent, buf, size)); EXPECT_EQ(2, logEvent.getNumUidFields()); const vector<FieldValue>& values = logEvent.getValues(); @@ -698,7 +757,7 @@ TEST(LogEventTest, TestAnnotationIdIsUid_RepeatedIntAndOtherFields) { EXPECT_FALSE(isUidField(values.at(4))); } -TEST(LogEventTest, TestAnnotationIdIsUid_RepeatedIntOneEntry) { +TEST_P(LogEventTest, TestAnnotationIdIsUid_RepeatedIntOneEntry) { size_t numElements = 1; int32_t int32Array[1] = {3}; @@ -709,9 +768,9 @@ TEST(LogEventTest, TestAnnotationIdIsUid_RepeatedIntOneEntry) { AStatsEvent_build(statsEvent); size_t size; - uint8_t* buf = AStatsEvent_getBuffer(statsEvent, &size); + const uint8_t* buf = AStatsEvent_getBuffer(statsEvent, &size); LogEvent logEvent(/*uid=*/1000, /*pid=*/1001); - EXPECT_TRUE(logEvent.parseBuffer(buf, size)); + EXPECT_TRUE(ParseBuffer(logEvent, buf, size)); EXPECT_EQ(1, logEvent.getNumUidFields()); const vector<FieldValue>& values = logEvent.getValues(); @@ -719,7 +778,7 @@ TEST(LogEventTest, TestAnnotationIdIsUid_RepeatedIntOneEntry) { EXPECT_TRUE(isUidField(values.at(0))); } -TEST(LogEventTest, TestAnnotationIdIsUid_EmptyIntArray) { +TEST_P(LogEventTest, TestAnnotationIdIsUid_EmptyIntArray) { int32_t int32Array[0] = {}; AStatsEvent* statsEvent = AStatsEvent_obtain(); @@ -730,16 +789,16 @@ TEST(LogEventTest, TestAnnotationIdIsUid_EmptyIntArray) { AStatsEvent_build(statsEvent); size_t size; - uint8_t* buf = AStatsEvent_getBuffer(statsEvent, &size); + const uint8_t* buf = AStatsEvent_getBuffer(statsEvent, &size); LogEvent logEvent(/*uid=*/1000, /*pid=*/1001); - EXPECT_TRUE(logEvent.parseBuffer(buf, size)); + EXPECT_TRUE(ParseBuffer(logEvent, buf, size)); EXPECT_EQ(0, logEvent.getNumUidFields()); const vector<FieldValue>& values = logEvent.getValues(); EXPECT_EQ(values.size(), 1); } -TEST(LogEventTest, TestAnnotationIdIsUid_BadRepeatedInt64) { +TEST_P(LogEventTest, TestAnnotationIdIsUid_BadRepeatedInt64) { int64_t int64Array[2] = {1000L, 1002L}; AStatsEvent* statsEvent = AStatsEvent_obtain(); @@ -749,16 +808,16 @@ TEST(LogEventTest, TestAnnotationIdIsUid_BadRepeatedInt64) { AStatsEvent_build(statsEvent); size_t size; - uint8_t* buf = AStatsEvent_getBuffer(statsEvent, &size); + const uint8_t* buf = AStatsEvent_getBuffer(statsEvent, &size); LogEvent logEvent(/*uid=*/1000, /*pid=*/1001); - EXPECT_FALSE(logEvent.parseBuffer(buf, size)); + EXPECT_FALSE(ParseBuffer(logEvent, buf, size)); EXPECT_EQ(0, logEvent.getNumUidFields()); AStatsEvent_release(statsEvent); } -TEST(LogEventTest, TestAnnotationIdIsUid_BadRepeatedString) { +TEST_P(LogEventTest, TestAnnotationIdIsUid_BadRepeatedString) { size_t numElements = 2; vector<string> stringArray = {"str1", "str2"}; const char* cStringArray[2]; @@ -773,10 +832,10 @@ TEST(LogEventTest, TestAnnotationIdIsUid_BadRepeatedString) { AStatsEvent_build(statsEvent); size_t size; - uint8_t* buf = AStatsEvent_getBuffer(statsEvent, &size); + const uint8_t* buf = AStatsEvent_getBuffer(statsEvent, &size); LogEvent logEvent(/*uid=*/1000, /*pid=*/1001); - EXPECT_FALSE(logEvent.parseBuffer(buf, size)); + EXPECT_FALSE(ParseBuffer(logEvent, buf, size)); EXPECT_EQ(0, logEvent.getNumUidFields()); AStatsEvent_release(statsEvent); @@ -785,24 +844,25 @@ TEST(LogEventTest, TestAnnotationIdIsUid_BadRepeatedString) { TEST_P(LogEventTestBadAnnotationFieldTypes, TestAnnotationIdIsUid) { LogEvent event(/*uid=*/0, /*pid=*/0); - if (GetParam() != INT32_TYPE && GetParam() != LIST_TYPE) { - createFieldWithBoolAnnotationLogEvent(&event, GetParam(), ASTATSLOG_ANNOTATION_ID_IS_UID, - true, - /*parseBufferResult*/ false); + if (std::get<0>(GetParam()) != INT32_TYPE && std::get<0>(GetParam()) != LIST_TYPE) { + EXPECT_FALSE(createFieldWithBoolAnnotationLogEvent( + &event, std::get<0>(GetParam()), ASTATSLOG_ANNOTATION_ID_IS_UID, true, + /*doHeaderPrefetch=*/std::get<1>(GetParam()))); } } -TEST(LogEventTest, TestAnnotationIdIsUid_NotIntAnnotation) { +TEST_P(LogEventTest, TestAnnotationIdIsUid_NotIntAnnotation) { LogEvent event(/*uid=*/0, /*pid=*/0); - createFieldWithIntAnnotationLogEvent(&event, INT32_TYPE, ASTATSLOG_ANNOTATION_ID_IS_UID, 10, - /*parseBufferResult*/ false); + EXPECT_FALSE(createFieldWithIntAnnotationLogEvent(&event, INT32_TYPE, + ASTATSLOG_ANNOTATION_ID_IS_UID, 10, + /*doHeaderPrefetch=*/GetParam())); } -TEST(LogEventTest, TestAnnotationIdStateNested) { +TEST_P(LogEventTest, TestAnnotationIdStateNested) { LogEvent event(/*uid=*/0, /*pid=*/0); - createFieldWithBoolAnnotationLogEvent(&event, INT32_TYPE, ASTATSLOG_ANNOTATION_ID_STATE_NESTED, - true, - /*parseBufferResult*/ true); + EXPECT_TRUE(createFieldWithBoolAnnotationLogEvent(&event, INT32_TYPE, + ASTATSLOG_ANNOTATION_ID_STATE_NESTED, true, + /*doHeaderPrefetch=*/GetParam())); const vector<FieldValue>& values = event.getValues(); ASSERT_EQ(values.size(), 1); @@ -812,25 +872,25 @@ TEST(LogEventTest, TestAnnotationIdStateNested) { TEST_P(LogEventTestBadAnnotationFieldTypes, TestAnnotationIdStateNested) { LogEvent event(/*uid=*/0, /*pid=*/0); - if (GetParam() != INT32_TYPE) { - createFieldWithBoolAnnotationLogEvent(&event, GetParam(), - ASTATSLOG_ANNOTATION_ID_STATE_NESTED, true, - /*parseBufferResult*/ false); + if (std::get<0>(GetParam()) != INT32_TYPE) { + EXPECT_FALSE(createFieldWithBoolAnnotationLogEvent( + &event, std::get<0>(GetParam()), ASTATSLOG_ANNOTATION_ID_STATE_NESTED, true, + /*doHeaderPrefetch=*/std::get<1>(GetParam()))); } } -TEST(LogEventTest, TestAnnotationIdStateNested_NotIntAnnotation) { +TEST_P(LogEventTest, TestAnnotationIdStateNested_NotIntAnnotation) { LogEvent event(/*uid=*/0, /*pid=*/0); - createFieldWithIntAnnotationLogEvent(&event, INT32_TYPE, ASTATSLOG_ANNOTATION_ID_STATE_NESTED, - 10, - /*parseBufferResult*/ false); + EXPECT_FALSE(createFieldWithIntAnnotationLogEvent(&event, INT32_TYPE, + ASTATSLOG_ANNOTATION_ID_STATE_NESTED, 10, + /*doHeaderPrefetch=*/GetParam())); } -TEST(LogEventTest, TestPrimaryFieldAnnotation) { +TEST_P(LogEventTest, TestPrimaryFieldAnnotation) { LogEvent event(/*uid=*/0, /*pid=*/0); - createFieldWithBoolAnnotationLogEvent(&event, INT32_TYPE, ASTATSLOG_ANNOTATION_ID_PRIMARY_FIELD, - true, - /*parseBufferResult*/ true); + EXPECT_TRUE(createFieldWithBoolAnnotationLogEvent(&event, INT32_TYPE, + ASTATSLOG_ANNOTATION_ID_PRIMARY_FIELD, true, + /*doHeaderPrefetch=*/GetParam())); const vector<FieldValue>& values = event.getValues(); ASSERT_EQ(values.size(), 1); @@ -840,25 +900,25 @@ TEST(LogEventTest, TestPrimaryFieldAnnotation) { TEST_P(LogEventTestBadAnnotationFieldTypes, TestPrimaryFieldAnnotation) { LogEvent event(/*uid=*/0, /*pid=*/0); - if (GetParam() == LIST_TYPE || GetParam() == ATTRIBUTION_CHAIN_TYPE) { - createFieldWithBoolAnnotationLogEvent(&event, GetParam(), - ASTATSLOG_ANNOTATION_ID_PRIMARY_FIELD, true, - /*parseBufferResult*/ false); + if (std::get<0>(GetParam()) == LIST_TYPE || std::get<0>(GetParam()) == ATTRIBUTION_CHAIN_TYPE) { + EXPECT_FALSE(createFieldWithBoolAnnotationLogEvent( + &event, std::get<0>(GetParam()), ASTATSLOG_ANNOTATION_ID_PRIMARY_FIELD, true, + /*doHeaderPrefetch=*/std::get<1>(GetParam()))); } } -TEST(LogEventTest, TestPrimaryFieldAnnotation_NotIntAnnotation) { +TEST_P(LogEventTest, TestPrimaryFieldAnnotation_NotIntAnnotation) { LogEvent event(/*uid=*/0, /*pid=*/0); - createFieldWithIntAnnotationLogEvent(&event, INT32_TYPE, ASTATSLOG_ANNOTATION_ID_PRIMARY_FIELD, - 10, - /*parseBufferResult*/ false); + EXPECT_FALSE(createFieldWithIntAnnotationLogEvent(&event, INT32_TYPE, + ASTATSLOG_ANNOTATION_ID_PRIMARY_FIELD, 10, + /*doHeaderPrefetch=*/GetParam())); } -TEST(LogEventTest, TestExclusiveStateAnnotation) { +TEST_P(LogEventTest, TestExclusiveStateAnnotation) { LogEvent event(/*uid=*/0, /*pid=*/0); - createFieldWithBoolAnnotationLogEvent(&event, INT32_TYPE, - ASTATSLOG_ANNOTATION_ID_EXCLUSIVE_STATE, true, - /*parseBufferResult*/ true); + EXPECT_TRUE(createFieldWithBoolAnnotationLogEvent(&event, INT32_TYPE, + ASTATSLOG_ANNOTATION_ID_EXCLUSIVE_STATE, true, + /*doHeaderPrefetch=*/GetParam())); const vector<FieldValue>& values = event.getValues(); ASSERT_EQ(values.size(), 1); @@ -868,21 +928,21 @@ TEST(LogEventTest, TestExclusiveStateAnnotation) { TEST_P(LogEventTestBadAnnotationFieldTypes, TestExclusiveStateAnnotation) { LogEvent event(/*uid=*/0, /*pid=*/0); - if (GetParam() != INT32_TYPE) { - createFieldWithBoolAnnotationLogEvent(&event, GetParam(), - ASTATSLOG_ANNOTATION_ID_EXCLUSIVE_STATE, true, - /*parseBufferResult*/ false); + if (std::get<0>(GetParam()) != INT32_TYPE) { + EXPECT_FALSE(createFieldWithBoolAnnotationLogEvent( + &event, std::get<0>(GetParam()), ASTATSLOG_ANNOTATION_ID_EXCLUSIVE_STATE, true, + /*doHeaderPrefetch=*/std::get<1>(GetParam()))); } } -TEST(LogEventTest, TestExclusiveStateAnnotation_NotIntAnnotation) { +TEST_P(LogEventTest, TestExclusiveStateAnnotation_NotIntAnnotation) { LogEvent event(/*uid=*/0, /*pid=*/0); - createFieldWithIntAnnotationLogEvent(&event, INT32_TYPE, - ASTATSLOG_ANNOTATION_ID_EXCLUSIVE_STATE, 10, - /*parseBufferResult*/ false); + EXPECT_FALSE(createFieldWithIntAnnotationLogEvent(&event, INT32_TYPE, + ASTATSLOG_ANNOTATION_ID_EXCLUSIVE_STATE, 10, + /*doHeaderPrefetch=*/GetParam())); } -TEST(LogEventTest, TestPrimaryFieldFirstUidAnnotation) { +TEST_P(LogEventTest, TestPrimaryFieldFirstUidAnnotation) { // Event has 10 ints and then an attribution chain int numInts = 10; int firstUidInChainIndex = numInts; @@ -904,9 +964,9 @@ TEST(LogEventTest, TestPrimaryFieldFirstUidAnnotation) { // Construct LogEvent size_t size; - uint8_t* buf = AStatsEvent_getBuffer(statsEvent, &size); + const uint8_t* buf = AStatsEvent_getBuffer(statsEvent, &size); LogEvent logEvent(/*uid=*/0, /*pid=*/0); - EXPECT_TRUE(logEvent.parseBuffer(buf, size)); + EXPECT_TRUE(ParseBuffer(logEvent, buf, size)); AStatsEvent_release(statsEvent); // Check annotation @@ -918,64 +978,65 @@ TEST(LogEventTest, TestPrimaryFieldFirstUidAnnotation) { TEST_P(LogEventTestBadAnnotationFieldTypes, TestPrimaryFieldFirstUidAnnotation) { LogEvent event(/*uid=*/0, /*pid=*/0); - if (GetParam() != ATTRIBUTION_CHAIN_TYPE) { - createFieldWithBoolAnnotationLogEvent(&event, GetParam(), - ASTATSLOG_ANNOTATION_ID_PRIMARY_FIELD_FIRST_UID, true, - /*parseBufferResult*/ false); + if (std::get<0>(GetParam()) != ATTRIBUTION_CHAIN_TYPE) { + EXPECT_FALSE(createFieldWithBoolAnnotationLogEvent( + &event, std::get<0>(GetParam()), ASTATSLOG_ANNOTATION_ID_PRIMARY_FIELD_FIRST_UID, + true, + /*doHeaderPrefetch=*/std::get<1>(GetParam()))); } } -TEST(LogEventTest, TestPrimaryFieldFirstUidAnnotation_NotIntAnnotation) { +TEST_P(LogEventTest, TestPrimaryFieldFirstUidAnnotation_NotIntAnnotation) { LogEvent event(/*uid=*/0, /*pid=*/0); - createFieldWithIntAnnotationLogEvent(&event, ATTRIBUTION_CHAIN_TYPE, - ASTATSLOG_ANNOTATION_ID_PRIMARY_FIELD_FIRST_UID, 10, - /*parseBufferResult*/ false); + EXPECT_FALSE(createFieldWithIntAnnotationLogEvent( + &event, ATTRIBUTION_CHAIN_TYPE, ASTATSLOG_ANNOTATION_ID_PRIMARY_FIELD_FIRST_UID, 10, + /*doHeaderPrefetch=*/GetParam())); } -TEST(LogEventTest, TestResetStateAnnotation) { +TEST_P(LogEventTest, TestResetStateAnnotation) { int32_t resetState = 10; LogEvent event(/*uid=*/0, /*pid=*/0); - createFieldWithIntAnnotationLogEvent(&event, INT32_TYPE, - ASTATSLOG_ANNOTATION_ID_TRIGGER_STATE_RESET, resetState, - /*parseBufferResult*/ true); + EXPECT_TRUE(createFieldWithIntAnnotationLogEvent( + &event, INT32_TYPE, ASTATSLOG_ANNOTATION_ID_TRIGGER_STATE_RESET, resetState, + /*doHeaderPrefetch=*/GetParam())); const vector<FieldValue>& values = event.getValues(); ASSERT_EQ(values.size(), 1); EXPECT_EQ(event.getResetState(), resetState); } -TEST(LogEventTest, TestRestrictionCategoryAnnotation) { +TEST_P(LogEventTest, TestRestrictionCategoryAnnotation) { FlagProvider::getInstance().overrideFlag(RESTRICTED_METRICS_FLAG, FLAG_TRUE, /*isBootFlag=*/true); int32_t restrictionCategory = ASTATSLOG_RESTRICTION_CATEGORY_DIAGNOSTIC; LogEvent event(/*uid=*/0, /*pid=*/0); - createAtomLevelIntAnnotationLogEvent(&event, INT32_TYPE, - ASTATSLOG_ANNOTATION_ID_RESTRICTION_CATEGORY, - restrictionCategory, /*parseBufferResult=*/true); + EXPECT_TRUE(createAtomLevelIntAnnotationLogEvent( + &event, INT32_TYPE, ASTATSLOG_ANNOTATION_ID_RESTRICTION_CATEGORY, restrictionCategory, + /*doHeaderPrefetch=*/GetParam())); ASSERT_EQ(event.getRestrictionCategory(), restrictionCategory); FlagProvider::getInstance().resetOverrides(); } -TEST(LogEventTest, TestInvalidRestrictionCategoryAnnotation) { +TEST_P(LogEventTest, TestInvalidRestrictionCategoryAnnotation) { FlagProvider::getInstance().overrideFlag(RESTRICTED_METRICS_FLAG, FLAG_TRUE, /*isBootFlag=*/true); int32_t restrictionCategory = 619; // unknown category LogEvent event(/*uid=*/0, /*pid=*/0); - createAtomLevelIntAnnotationLogEvent(&event, INT32_TYPE, - ASTATSLOG_ANNOTATION_ID_RESTRICTION_CATEGORY, - restrictionCategory, /*parseBufferResult=*/false); + EXPECT_FALSE(createAtomLevelIntAnnotationLogEvent( + &event, INT32_TYPE, ASTATSLOG_ANNOTATION_ID_RESTRICTION_CATEGORY, restrictionCategory, + /*doHeaderPrefetch=*/GetParam())); FlagProvider::getInstance().resetOverrides(); } -TEST(LogEventTest, TestRestrictionCategoryAnnotationFlagDisabled) { +TEST_P(LogEventTest, TestRestrictionCategoryAnnotationFlagDisabled) { FlagProvider::getInstance().overrideFlag(RESTRICTED_METRICS_FLAG, FLAG_FALSE, /*isBootFlag=*/true); int32_t restrictionCategory = ASTATSLOG_RESTRICTION_CATEGORY_DIAGNOSTIC; LogEvent event(/*uid=*/0, /*pid=*/0); - createAtomLevelIntAnnotationLogEvent(&event, INT32_TYPE, - ASTATSLOG_ANNOTATION_ID_RESTRICTION_CATEGORY, - restrictionCategory, /*parseBufferResult=*/false); + EXPECT_FALSE(createAtomLevelIntAnnotationLogEvent( + &event, INT32_TYPE, ASTATSLOG_ANNOTATION_ID_RESTRICTION_CATEGORY, restrictionCategory, + /*doHeaderPrefetch=*/GetParam())); FlagProvider::getInstance().resetOverrides(); } @@ -983,21 +1044,22 @@ TEST_P(LogEventTestBadAnnotationFieldTypes, TestResetStateAnnotation) { LogEvent event(/*uid=*/0, /*pid=*/0); int32_t resetState = 10; - if (GetParam() != INT32_TYPE) { - createFieldWithIntAnnotationLogEvent( - &event, GetParam(), ASTATSLOG_ANNOTATION_ID_TRIGGER_STATE_RESET, resetState, - /*parseBufferResult*/ false); + if (std::get<0>(GetParam()) != INT32_TYPE) { + EXPECT_FALSE(createFieldWithIntAnnotationLogEvent( + &event, std::get<0>(GetParam()), ASTATSLOG_ANNOTATION_ID_TRIGGER_STATE_RESET, + resetState, + /*doHeaderPrefetch=*/std::get<1>(GetParam()))); } } -TEST(LogEventTest, TestResetStateAnnotation_NotBoolAnnotation) { +TEST_P(LogEventTest, TestResetStateAnnotation_NotBoolAnnotation) { LogEvent event(/*uid=*/0, /*pid=*/0); - createFieldWithBoolAnnotationLogEvent(&event, INT32_TYPE, - ASTATSLOG_ANNOTATION_ID_TRIGGER_STATE_RESET, true, - /*parseBufferResult*/ false); + EXPECT_FALSE(createFieldWithBoolAnnotationLogEvent( + &event, INT32_TYPE, ASTATSLOG_ANNOTATION_ID_TRIGGER_STATE_RESET, true, + /*doHeaderPrefetch=*/GetParam())); } -TEST(LogEventTest, TestUidAnnotationWithInt8MaxValues) { +TEST_P(LogEventTest, TestUidAnnotationWithInt8MaxValues) { int32_t numElements = INT8_MAX; int32_t int32Array[numElements]; @@ -1014,14 +1076,14 @@ TEST(LogEventTest, TestUidAnnotationWithInt8MaxValues) { AStatsEvent_build(event); size_t size; - uint8_t* buf = AStatsEvent_getBuffer(event, &size); + const uint8_t* buf = AStatsEvent_getBuffer(event, &size); LogEvent logEvent(/*uid=*/1000, /*pid=*/1001); - EXPECT_TRUE(logEvent.parseBuffer(buf, size)); + EXPECT_TRUE(ParseBuffer(logEvent, buf, size)); AStatsEvent_release(event); } -TEST(LogEventTest, TestEmptyAttributionChainWithPrimaryFieldFirstUidAnnotation) { +TEST_P(LogEventTest, TestEmptyAttributionChainWithPrimaryFieldFirstUidAnnotation) { AStatsEvent* event = AStatsEvent_obtain(); AStatsEvent_setAtomId(event, 100); @@ -1035,39 +1097,41 @@ TEST(LogEventTest, TestEmptyAttributionChainWithPrimaryFieldFirstUidAnnotation) AStatsEvent_build(event); size_t size; - uint8_t* buf = AStatsEvent_getBuffer(event, &size); + const uint8_t* buf = AStatsEvent_getBuffer(event, &size); LogEvent logEvent(/*uid=*/1000, /*pid=*/1001); - EXPECT_FALSE(logEvent.parseBuffer(buf, size)); + EXPECT_FALSE(ParseBuffer(logEvent, buf, size)); AStatsEvent_release(event); } // Setup for parameterized tests. -class LogEvent_FieldRestrictionTest : public testing::TestWithParam<int> { +class LogEvent_FieldRestrictionTest : public testing::TestWithParam<std::tuple<int, bool>> { public: - static std::string ToString(testing::TestParamInfo<int> info) { - switch (info.param) { + static std::string ToString(testing::TestParamInfo<std::tuple<int, bool>> info) { + const std::string boolName = std::get<1>(info.param) ? "_prefetchTrue" : "_prefetchFalse"; + + switch (std::get<0>(info.param)) { case ASTATSLOG_ANNOTATION_ID_FIELD_RESTRICTION_PERIPHERAL_DEVICE_INFO: - return "PeripheralDeviceInfo"; + return "PeripheralDeviceInfo" + boolName; case ASTATSLOG_ANNOTATION_ID_FIELD_RESTRICTION_APP_USAGE: - return "AppUsage"; + return "AppUsage" + boolName; case ASTATSLOG_ANNOTATION_ID_FIELD_RESTRICTION_APP_ACTIVITY: - return "AppActivity"; + return "AppActivity" + boolName; case ASTATSLOG_ANNOTATION_ID_FIELD_RESTRICTION_HEALTH_CONNECT: - return "HealthConnect"; + return "HealthConnect" + boolName; case ASTATSLOG_ANNOTATION_ID_FIELD_RESTRICTION_ACCESSIBILITY: - return "Accessibility"; + return "Accessibility" + boolName; case ASTATSLOG_ANNOTATION_ID_FIELD_RESTRICTION_SYSTEM_SEARCH: - return "SystemSearch"; + return "SystemSearch" + boolName; case ASTATSLOG_ANNOTATION_ID_FIELD_RESTRICTION_USER_ENGAGEMENT: - return "UserEngagement"; + return "UserEngagement" + boolName; case ASTATSLOG_ANNOTATION_ID_FIELD_RESTRICTION_AMBIENT_SENSING: - return "AmbientSensing"; + return "AmbientSensing" + boolName; case ASTATSLOG_ANNOTATION_ID_FIELD_RESTRICTION_DEMOGRAPHIC_CLASSIFICATION: - return "DemographicClassification"; + return "DemographicClassification" + boolName; default: - return "Unknown"; + return "Unknown" + boolName; } } void TearDown() override { @@ -1079,7 +1143,9 @@ public: // typeIds. BOOL_TYPE should be a bad field type for is_uid, nested, and reset state annotations. INSTANTIATE_TEST_SUITE_P( LogEvent_FieldRestrictionTest, LogEvent_FieldRestrictionTest, - testing::Values(ASTATSLOG_ANNOTATION_ID_FIELD_RESTRICTION_PERIPHERAL_DEVICE_INFO, + testing::Combine( + testing::Values( + ASTATSLOG_ANNOTATION_ID_FIELD_RESTRICTION_PERIPHERAL_DEVICE_INFO, ASTATSLOG_ANNOTATION_ID_FIELD_RESTRICTION_APP_USAGE, ASTATSLOG_ANNOTATION_ID_FIELD_RESTRICTION_APP_ACTIVITY, ASTATSLOG_ANNOTATION_ID_FIELD_RESTRICTION_HEALTH_CONNECT, @@ -1088,14 +1154,16 @@ INSTANTIATE_TEST_SUITE_P( ASTATSLOG_ANNOTATION_ID_FIELD_RESTRICTION_USER_ENGAGEMENT, ASTATSLOG_ANNOTATION_ID_FIELD_RESTRICTION_AMBIENT_SENSING, ASTATSLOG_ANNOTATION_ID_FIELD_RESTRICTION_DEMOGRAPHIC_CLASSIFICATION), + testing::Bool()), LogEvent_FieldRestrictionTest::ToString); TEST_P(LogEvent_FieldRestrictionTest, TestFieldRestrictionAnnotation) { FlagProvider::getInstance().overrideFlag(RESTRICTED_METRICS_FLAG, FLAG_TRUE, /*isBootFlag=*/true); LogEvent event(/*uid=*/0, /*pid=*/0); - createFieldWithBoolAnnotationLogEvent(&event, INT32_TYPE, GetParam(), true, - /*parseBufferResult=*/true); + EXPECT_TRUE( + createFieldWithBoolAnnotationLogEvent(&event, INT32_TYPE, std::get<0>(GetParam()), true, + /*doHeaderPrefetch=*/std::get<1>(GetParam()))); // Some basic checks to make sure the event is parsed correctly. EXPECT_EQ(event.GetTagId(), 100); ASSERT_EQ(event.getValues().size(), 1); @@ -1106,16 +1174,18 @@ TEST_P(LogEvent_FieldRestrictionTest, TestInvalidAnnotationIntType) { FlagProvider::getInstance().overrideFlag(RESTRICTED_METRICS_FLAG, FLAG_TRUE, /*isBootFlag=*/true); LogEvent event(/*uid=*/0, /*pid=*/0); - createFieldWithIntAnnotationLogEvent(&event, STRING_TYPE, GetParam(), - /*random int*/ 15, /*parseBufferResult=*/false); + EXPECT_FALSE(createFieldWithIntAnnotationLogEvent( + &event, STRING_TYPE, std::get<0>(GetParam()), + /*random int*/ 15, /*doHeaderPrefetch=*/std::get<1>(GetParam()))); } TEST_P(LogEvent_FieldRestrictionTest, TestInvalidAnnotationAtomLevel) { FlagProvider::getInstance().overrideFlag(RESTRICTED_METRICS_FLAG, FLAG_TRUE, /*isBootFlag=*/true); LogEvent event(/*uid=*/0, /*pid=*/0); - createAtomLevelBoolAnnotationLogEvent(&event, STRING_TYPE, GetParam(), true, - /*parseBufferResult=*/false); + EXPECT_FALSE(createAtomLevelBoolAnnotationLogEvent( + &event, STRING_TYPE, std::get<0>(GetParam()), true, + /*doHeaderPrefetch=*/std::get<1>(GetParam()))); } TEST_P(LogEvent_FieldRestrictionTest, TestRestrictionCategoryAnnotationFlagDisabled) { @@ -1123,8 +1193,9 @@ TEST_P(LogEvent_FieldRestrictionTest, TestRestrictionCategoryAnnotationFlagDisab /*isBootFlag=*/true); int32_t restrictionCategory = ASTATSLOG_RESTRICTION_CATEGORY_DIAGNOSTIC; LogEvent event(/*uid=*/0, /*pid=*/0); - createFieldWithBoolAnnotationLogEvent(&event, INT32_TYPE, GetParam(), true, - /*parseBufferResult=*/false); + EXPECT_FALSE( + createFieldWithBoolAnnotationLogEvent(&event, INT32_TYPE, std::get<0>(GetParam()), true, + /*doHeaderPrefetch=*/std::get<1>(GetParam()))); } } // namespace statsd |