summaryrefslogtreecommitdiff
path: root/libstats/socket/tests/stats_event_test.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'libstats/socket/tests/stats_event_test.cpp')
-rw-r--r--libstats/socket/tests/stats_event_test.cpp516
1 files changed, 0 insertions, 516 deletions
diff --git a/libstats/socket/tests/stats_event_test.cpp b/libstats/socket/tests/stats_event_test.cpp
deleted file mode 100644
index 2f9ccdc5c..000000000
--- a/libstats/socket/tests/stats_event_test.cpp
+++ /dev/null
@@ -1,516 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "stats_event.h"
-#include <gtest/gtest.h>
-#include <utils/SystemClock.h>
-
-// Keep in sync with stats_event.c. Consider moving to separate header file to avoid duplication.
-/* ERRORS */
-#define ERROR_NO_TIMESTAMP 0x1
-#define ERROR_NO_ATOM_ID 0x2
-#define ERROR_OVERFLOW 0x4
-#define ERROR_ATTRIBUTION_CHAIN_TOO_LONG 0x8
-#define ERROR_TOO_MANY_KEY_VALUE_PAIRS 0x10
-#define ERROR_ANNOTATION_DOES_NOT_FOLLOW_FIELD 0x20
-#define ERROR_INVALID_ANNOTATION_ID 0x40
-#define ERROR_ANNOTATION_ID_TOO_LARGE 0x80
-#define ERROR_TOO_MANY_ANNOTATIONS 0x100
-#define ERROR_TOO_MANY_FIELDS 0x200
-#define ERROR_INVALID_VALUE_TYPE 0x400
-#define ERROR_STRING_NOT_NULL_TERMINATED 0x800
-#define ERROR_ATOM_ID_INVALID_POSITION 0x2000
-
-/* TYPE IDS */
-#define INT32_TYPE 0x00
-#define INT64_TYPE 0x01
-#define STRING_TYPE 0x02
-#define LIST_TYPE 0x03
-#define FLOAT_TYPE 0x04
-#define BOOL_TYPE 0x05
-#define BYTE_ARRAY_TYPE 0x06
-#define OBJECT_TYPE 0x07
-#define KEY_VALUE_PAIRS_TYPE 0x08
-#define ATTRIBUTION_CHAIN_TYPE 0x09
-#define ERROR_TYPE 0x0F
-
-using std::string;
-using std::vector;
-
-// Side-effect: this function moves the start of the buffer past the read value
-template <class T>
-T readNext(uint8_t** buffer) {
- T value;
- if ((reinterpret_cast<uintptr_t>(*buffer) % alignof(T)) == 0) {
- value = *(T*)(*buffer);
- } else {
- memcpy(&value, *buffer, sizeof(T));
- }
- *buffer += sizeof(T);
- return value;
-}
-
-void checkTypeHeader(uint8_t** buffer, uint8_t typeId, uint8_t numAnnotations = 0) {
- uint8_t typeHeader = (numAnnotations << 4) | typeId;
- EXPECT_EQ(readNext<uint8_t>(buffer), typeHeader);
-}
-
-template <class T>
-void checkScalar(uint8_t** buffer, T expectedValue) {
- EXPECT_EQ(readNext<T>(buffer), expectedValue);
-}
-
-void checkString(uint8_t** buffer, const string& expectedString) {
- uint32_t size = readNext<uint32_t>(buffer);
- string parsedString((char*)(*buffer), size);
- EXPECT_EQ(parsedString, expectedString);
- *buffer += size; // move buffer past string we just read
-}
-
-void checkByteArray(uint8_t** buffer, const vector<uint8_t>& expectedByteArray) {
- uint32_t size = readNext<uint32_t>(buffer);
- vector<uint8_t> parsedByteArray(*buffer, *buffer + size);
- EXPECT_EQ(parsedByteArray, expectedByteArray);
- *buffer += size; // move buffer past byte array we just read
-}
-
-template <class T>
-void checkAnnotation(uint8_t** buffer, uint8_t annotationId, uint8_t typeId, T annotationValue) {
- EXPECT_EQ(readNext<uint8_t>(buffer), annotationId);
- EXPECT_EQ(readNext<uint8_t>(buffer), typeId);
- checkScalar<T>(buffer, annotationValue);
-}
-
-void checkMetadata(uint8_t** buffer, uint8_t numElements, int64_t startTime, int64_t endTime,
- uint32_t atomId, uint8_t numAtomLevelAnnotations = 0) {
- // All events start with OBJECT_TYPE id.
- checkTypeHeader(buffer, OBJECT_TYPE);
-
- // We increment by 2 because the number of elements listed in the
- // serialization accounts for the timestamp and atom id as well.
- checkScalar(buffer, static_cast<uint8_t>(numElements + 2));
-
- // Check timestamp
- checkTypeHeader(buffer, INT64_TYPE);
- int64_t timestamp = readNext<int64_t>(buffer);
- EXPECT_GE(timestamp, startTime);
- EXPECT_LE(timestamp, endTime);
-
- // Check atom id
- checkTypeHeader(buffer, INT32_TYPE, numAtomLevelAnnotations);
- checkScalar(buffer, atomId);
-}
-
-TEST(StatsEventTest, TestScalars) {
- uint32_t atomId = 100;
- int32_t int32Value = -5;
- int64_t int64Value = -2 * android::elapsedRealtimeNano();
- float floatValue = 2.0;
- bool boolValue = false;
-
- int64_t startTime = android::elapsedRealtimeNano();
- AStatsEvent* event = AStatsEvent_obtain();
- AStatsEvent_setAtomId(event, atomId);
- AStatsEvent_writeInt32(event, int32Value);
- AStatsEvent_writeInt64(event, int64Value);
- AStatsEvent_writeFloat(event, floatValue);
- AStatsEvent_writeBool(event, boolValue);
- AStatsEvent_build(event);
- int64_t endTime = android::elapsedRealtimeNano();
-
- size_t bufferSize;
- uint8_t* buffer = AStatsEvent_getBuffer(event, &bufferSize);
- uint8_t* bufferEnd = buffer + bufferSize;
-
- checkMetadata(&buffer, /*numElements=*/4, startTime, endTime, atomId);
-
- // check int32 element
- checkTypeHeader(&buffer, INT32_TYPE);
- checkScalar(&buffer, int32Value);
-
- // check int64 element
- checkTypeHeader(&buffer, INT64_TYPE);
- checkScalar(&buffer, int64Value);
-
- // check float element
- checkTypeHeader(&buffer, FLOAT_TYPE);
- checkScalar(&buffer, floatValue);
-
- // check bool element
- checkTypeHeader(&buffer, BOOL_TYPE);
- checkScalar(&buffer, boolValue);
-
- EXPECT_EQ(buffer, bufferEnd); // ensure that we have read the entire buffer
- EXPECT_EQ(AStatsEvent_getErrors(event), 0);
- AStatsEvent_release(event);
-}
-
-TEST(StatsEventTest, TestStrings) {
- uint32_t atomId = 100;
- string str = "test_string";
-
- int64_t startTime = android::elapsedRealtimeNano();
- AStatsEvent* event = AStatsEvent_obtain();
- AStatsEvent_setAtomId(event, atomId);
- AStatsEvent_writeString(event, str.c_str());
- AStatsEvent_build(event);
- int64_t endTime = android::elapsedRealtimeNano();
-
- size_t bufferSize;
- uint8_t* buffer = AStatsEvent_getBuffer(event, &bufferSize);
- uint8_t* bufferEnd = buffer + bufferSize;
-
- checkMetadata(&buffer, /*numElements=*/1, startTime, endTime, atomId);
-
- checkTypeHeader(&buffer, STRING_TYPE);
- checkString(&buffer, str);
-
- EXPECT_EQ(buffer, bufferEnd); // ensure that we have read the entire buffer
- EXPECT_EQ(AStatsEvent_getErrors(event), 0);
- AStatsEvent_release(event);
-}
-
-TEST(StatsEventTest, TestNullString) {
- uint32_t atomId = 100;
- char* str = nullptr;
-
- int64_t startTime = android::elapsedRealtimeNano();
- AStatsEvent* event = AStatsEvent_obtain();
- AStatsEvent_setAtomId(event, atomId);
- AStatsEvent_writeString(event, str);
- AStatsEvent_build(event);
- int64_t endTime = android::elapsedRealtimeNano();
-
- size_t bufferSize;
- uint8_t* buffer = AStatsEvent_getBuffer(event, &bufferSize);
- uint8_t* bufferEnd = buffer + bufferSize;
-
- checkMetadata(&buffer, /*numElements=*/1, startTime, endTime, atomId);
-
- checkTypeHeader(&buffer, STRING_TYPE);
- checkString(&buffer, "");
-
- EXPECT_EQ(buffer, bufferEnd); // ensure that we have read the entire buffer
- EXPECT_EQ(AStatsEvent_getErrors(event), 0);
- AStatsEvent_release(event);
-}
-
-TEST(StatsEventTest, TestByteArrays) {
- uint32_t atomId = 100;
- vector<uint8_t> message = {'b', 'y', 't', '\0', 'e', 's'};
-
- int64_t startTime = android::elapsedRealtimeNano();
- AStatsEvent* event = AStatsEvent_obtain();
- AStatsEvent_setAtomId(event, atomId);
- AStatsEvent_writeByteArray(event, message.data(), message.size());
- AStatsEvent_build(event);
- int64_t endTime = android::elapsedRealtimeNano();
-
- size_t bufferSize;
- uint8_t* buffer = AStatsEvent_getBuffer(event, &bufferSize);
- uint8_t* bufferEnd = buffer + bufferSize;
-
- checkMetadata(&buffer, /*numElements=*/1, startTime, endTime, atomId);
-
- checkTypeHeader(&buffer, BYTE_ARRAY_TYPE);
- checkByteArray(&buffer, message);
-
- EXPECT_EQ(buffer, bufferEnd); // ensure that we have read the entire buffer
- EXPECT_EQ(AStatsEvent_getErrors(event), 0);
- AStatsEvent_release(event);
-}
-
-TEST(StatsEventTest, TestNullByteArrays) {
- uint32_t atomId = 100;
- uint8_t* buf = nullptr;
- vector<uint8_t> message;
-
- int64_t startTime = android::elapsedRealtimeNano();
- AStatsEvent* event = AStatsEvent_obtain();
- AStatsEvent_setAtomId(event, atomId);
- AStatsEvent_writeByteArray(event, buf, 2);
- AStatsEvent_build(event);
- int64_t endTime = android::elapsedRealtimeNano();
-
- size_t bufferSize;
- uint8_t* buffer = AStatsEvent_getBuffer(event, &bufferSize);
- uint8_t* bufferEnd = buffer + bufferSize;
-
- checkMetadata(&buffer, /*numElements=*/1, startTime, endTime, atomId);
-
- checkTypeHeader(&buffer, BYTE_ARRAY_TYPE);
- checkByteArray(&buffer, message);
-
- EXPECT_EQ(buffer, bufferEnd); // ensure that we have read the entire buffer
- EXPECT_EQ(AStatsEvent_getErrors(event), 0);
- AStatsEvent_release(event);
-}
-
-TEST(StatsEventTest, TestAttributionChains) {
- uint32_t atomId = 100;
-
- uint8_t numNodes = 50;
- uint32_t uids[numNodes];
- vector<string> tags(numNodes); // storage that cTag elements point to
- const char* cTags[numNodes];
- for (int i = 0; i < (int)numNodes; i++) {
- uids[i] = i;
- if (0 == i) {
- tags.push_back("");
- cTags[i] = nullptr;
- } else {
- tags.push_back("test" + std::to_string(i));
- cTags[i] = tags[i].c_str();
- }
- }
-
- int64_t startTime = android::elapsedRealtimeNano();
- AStatsEvent* event = AStatsEvent_obtain();
- AStatsEvent_setAtomId(event, atomId);
- AStatsEvent_writeAttributionChain(event, uids, cTags, numNodes);
- AStatsEvent_build(event);
- int64_t endTime = android::elapsedRealtimeNano();
-
- size_t bufferSize;
- uint8_t* buffer = AStatsEvent_getBuffer(event, &bufferSize);
- uint8_t* bufferEnd = buffer + bufferSize;
-
- checkMetadata(&buffer, /*numElements=*/1, startTime, endTime, atomId);
-
- checkTypeHeader(&buffer, ATTRIBUTION_CHAIN_TYPE);
- checkScalar(&buffer, numNodes);
- for (int i = 0; i < numNodes; i++) {
- checkScalar(&buffer, uids[i]);
- checkString(&buffer, tags[i]);
- }
-
- EXPECT_EQ(buffer, bufferEnd); // ensure that we have read the entire buffer
- EXPECT_EQ(AStatsEvent_getErrors(event), 0);
- AStatsEvent_release(event);
-}
-
-TEST(StatsEventTest, TestFieldAnnotations) {
- uint32_t atomId = 100;
-
- // first element information
- bool boolValue = false;
- uint8_t boolAnnotation1Id = 1;
- uint8_t boolAnnotation2Id = 2;
- bool boolAnnotation1Value = true;
- int32_t boolAnnotation2Value = 3;
-
- // second element information
- float floatValue = -5.0;
- uint8_t floatAnnotation1Id = 3;
- uint8_t floatAnnotation2Id = 4;
- int32_t floatAnnotation1Value = 8;
- bool floatAnnotation2Value = false;
-
- int64_t startTime = android::elapsedRealtimeNano();
- AStatsEvent* event = AStatsEvent_obtain();
- AStatsEvent_setAtomId(event, atomId);
- AStatsEvent_writeBool(event, boolValue);
- AStatsEvent_addBoolAnnotation(event, boolAnnotation1Id, boolAnnotation1Value);
- AStatsEvent_addInt32Annotation(event, boolAnnotation2Id, boolAnnotation2Value);
- AStatsEvent_writeFloat(event, floatValue);
- AStatsEvent_addInt32Annotation(event, floatAnnotation1Id, floatAnnotation1Value);
- AStatsEvent_addBoolAnnotation(event, floatAnnotation2Id, floatAnnotation2Value);
- AStatsEvent_build(event);
- int64_t endTime = android::elapsedRealtimeNano();
-
- size_t bufferSize;
- uint8_t* buffer = AStatsEvent_getBuffer(event, &bufferSize);
- uint8_t* bufferEnd = buffer + bufferSize;
-
- checkMetadata(&buffer, /*numElements=*/2, startTime, endTime, atomId);
-
- // check first element
- checkTypeHeader(&buffer, BOOL_TYPE, /*numAnnotations=*/2);
- checkScalar(&buffer, boolValue);
- checkAnnotation(&buffer, boolAnnotation1Id, BOOL_TYPE, boolAnnotation1Value);
- checkAnnotation(&buffer, boolAnnotation2Id, INT32_TYPE, boolAnnotation2Value);
-
- // check second element
- checkTypeHeader(&buffer, FLOAT_TYPE, /*numAnnotations=*/2);
- checkScalar(&buffer, floatValue);
- checkAnnotation(&buffer, floatAnnotation1Id, INT32_TYPE, floatAnnotation1Value);
- checkAnnotation(&buffer, floatAnnotation2Id, BOOL_TYPE, floatAnnotation2Value);
-
- EXPECT_EQ(buffer, bufferEnd); // ensure that we have read the entire buffer
- EXPECT_EQ(AStatsEvent_getErrors(event), 0);
- AStatsEvent_release(event);
-}
-
-TEST(StatsEventTest, TestAtomLevelAnnotations) {
- uint32_t atomId = 100;
- // atom-level annotation information
- uint8_t boolAnnotationId = 1;
- uint8_t int32AnnotationId = 2;
- bool boolAnnotationValue = false;
- int32_t int32AnnotationValue = 5;
-
- float fieldValue = -3.5;
-
- int64_t startTime = android::elapsedRealtimeNano();
- AStatsEvent* event = AStatsEvent_obtain();
- AStatsEvent_setAtomId(event, atomId);
- AStatsEvent_addBoolAnnotation(event, boolAnnotationId, boolAnnotationValue);
- AStatsEvent_addInt32Annotation(event, int32AnnotationId, int32AnnotationValue);
- AStatsEvent_writeFloat(event, fieldValue);
- AStatsEvent_build(event);
- int64_t endTime = android::elapsedRealtimeNano();
-
- size_t bufferSize;
- uint8_t* buffer = AStatsEvent_getBuffer(event, &bufferSize);
- uint8_t* bufferEnd = buffer + bufferSize;
-
- checkMetadata(&buffer, /*numElements=*/1, startTime, endTime, atomId,
- /*numAtomLevelAnnotations=*/2);
-
- // check atom-level annotations
- checkAnnotation(&buffer, boolAnnotationId, BOOL_TYPE, boolAnnotationValue);
- checkAnnotation(&buffer, int32AnnotationId, INT32_TYPE, int32AnnotationValue);
-
- // check first element
- checkTypeHeader(&buffer, FLOAT_TYPE);
- checkScalar(&buffer, fieldValue);
-
- EXPECT_EQ(buffer, bufferEnd); // ensure that we have read the entire buffer
- EXPECT_EQ(AStatsEvent_getErrors(event), 0);
- AStatsEvent_release(event);
-}
-
-TEST(StatsEventTest, TestNoAtomIdError) {
- AStatsEvent* event = AStatsEvent_obtain();
- // Don't set the atom id in order to trigger the error.
- AStatsEvent_build(event);
-
- uint32_t errors = AStatsEvent_getErrors(event);
- EXPECT_EQ(errors & ERROR_NO_ATOM_ID, ERROR_NO_ATOM_ID);
-
- AStatsEvent_release(event);
-}
-
-TEST(StatsEventTest, TestPushOverflowError) {
- const char* str = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
- const int writeCount = 120; // Number of times to write str in the event.
-
- AStatsEvent* event = AStatsEvent_obtain();
- AStatsEvent_setAtomId(event, 100);
-
- // Add str to the event 120 times. Each str takes >35 bytes so this will
- // overflow the 4068 byte buffer.
- // We want to keep writeCount less than 127 to avoid hitting
- // ERROR_TOO_MANY_FIELDS.
- for (int i = 0; i < writeCount; i++) {
- AStatsEvent_writeString(event, str);
- }
- AStatsEvent_write(event);
-
- uint32_t errors = AStatsEvent_getErrors(event);
- EXPECT_EQ(errors & ERROR_OVERFLOW, ERROR_OVERFLOW);
-
- AStatsEvent_release(event);
-}
-
-TEST(StatsEventTest, TestPullOverflowError) {
- const uint32_t atomId = 10100;
- const vector<uint8_t> bytes(430 /* number of elements */, 1 /* value of each element */);
- const int writeCount = 120; // Number of times to write bytes in the event.
-
- AStatsEvent* event = AStatsEvent_obtain();
- AStatsEvent_setAtomId(event, atomId);
-
- // Add bytes to the event 120 times. Size of bytes is 430 so this will
- // overflow the 50 KB pulled event buffer.
- // We want to keep writeCount less than 127 to avoid hitting
- // ERROR_TOO_MANY_FIELDS.
- for (int i = 0; i < writeCount; i++) {
- AStatsEvent_writeByteArray(event, bytes.data(), bytes.size());
- }
- AStatsEvent_build(event);
-
- uint32_t errors = AStatsEvent_getErrors(event);
- EXPECT_EQ(errors & ERROR_OVERFLOW, ERROR_OVERFLOW);
-
- AStatsEvent_release(event);
-}
-
-TEST(StatsEventTest, TestLargePull) {
- const uint32_t atomId = 100;
- const string str = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
- const int writeCount = 120; // Number of times to write str in the event.
- const int64_t startTime = android::elapsedRealtimeNano();
-
- AStatsEvent* event = AStatsEvent_obtain();
- AStatsEvent_setAtomId(event, atomId);
-
- // Add str to the event 120 times.
- // We want to keep writeCount less than 127 to avoid hitting
- // ERROR_TOO_MANY_FIELDS.
- for (int i = 0; i < writeCount; i++) {
- AStatsEvent_writeString(event, str.c_str());
- }
- AStatsEvent_build(event);
- int64_t endTime = android::elapsedRealtimeNano();
-
- size_t bufferSize;
- uint8_t* buffer = AStatsEvent_getBuffer(event, &bufferSize);
- uint8_t* bufferEnd = buffer + bufferSize;
-
- checkMetadata(&buffer, writeCount, startTime, endTime, atomId);
-
- // Check all instances of str have been written.
- for (int i = 0; i < writeCount; i++) {
- checkTypeHeader(&buffer, STRING_TYPE);
- checkString(&buffer, str);
- }
-
- EXPECT_EQ(buffer, bufferEnd); // Ensure that we have read the entire buffer.
- EXPECT_EQ(AStatsEvent_getErrors(event), 0);
- AStatsEvent_release(event);
-}
-
-TEST(StatsEventTest, TestAtomIdInvalidPositionError) {
- AStatsEvent* event = AStatsEvent_obtain();
- AStatsEvent_writeInt32(event, 0);
- AStatsEvent_setAtomId(event, 100);
- AStatsEvent_writeBool(event, true);
- AStatsEvent_build(event);
-
- uint32_t errors = AStatsEvent_getErrors(event);
- EXPECT_EQ(errors & ERROR_ATOM_ID_INVALID_POSITION, ERROR_ATOM_ID_INVALID_POSITION);
-
- AStatsEvent_release(event);
-}
-
-TEST(StatsEventTest, TestOverwriteTimestamp) {
- uint32_t atomId = 100;
- int64_t expectedTimestamp = 0x123456789;
- AStatsEvent* event = AStatsEvent_obtain();
- AStatsEvent_setAtomId(event, atomId);
- AStatsEvent_overwriteTimestamp(event, expectedTimestamp);
- AStatsEvent_build(event);
-
- uint8_t* buffer = AStatsEvent_getBuffer(event, NULL);
-
- // Make sure that the timestamp is being overwritten.
- checkMetadata(&buffer, /*numElements=*/0, /*startTime=*/expectedTimestamp,
- /*endTime=*/expectedTimestamp, atomId);
-
- EXPECT_EQ(AStatsEvent_getErrors(event), 0);
- AStatsEvent_release(event);
-}