Merge "Comment out Statsd tests"

This commit is contained in:
TreeHugger Robot
2020-02-19 04:57:51 +00:00
committed by Android (Google) Code Review
35 changed files with 15396 additions and 16037 deletions

View File

@@ -105,10 +105,6 @@ cc_defaults {
"src/uid_data.proto",
],
cflags: [
"-DNEW_ENCODING_SCHEME",
],
local_include_dirs: [
"src",
],
@@ -321,55 +317,55 @@ cc_test {
// statsd micro benchmark
//#############################
cc_benchmark {
name: "statsd_benchmark",
defaults: ["statsd_defaults"],
srcs: [
// atom_field_options.proto needs field_options.proto, but that is
// not included in libprotobuf-cpp-lite, so compile it here.
":libprotobuf-internal-protos",
"benchmark/duration_metric_benchmark.cpp",
"benchmark/filter_value_benchmark.cpp",
"benchmark/get_dimensions_for_condition_benchmark.cpp",
"benchmark/hello_world_benchmark.cpp",
"benchmark/log_event_benchmark.cpp",
"benchmark/main.cpp",
"benchmark/metric_util.cpp",
"benchmark/stats_write_benchmark.cpp",
"src/atom_field_options.proto",
"src/atoms.proto",
"src/stats_log.proto",
],
proto: {
type: "lite",
include_dirs: ["external/protobuf/src"],
},
cflags: [
"-Wall",
"-Werror",
"-Wno-unused-parameter",
"-Wno-unused-variable",
"-Wno-unused-function",
// Bug: http://b/29823425 Disable -Wvarargs for Clang update to r271374
"-Wno-varargs",
],
static_libs: [
"libplatformprotos",
],
shared_libs: [
"libgtest_prod",
"libprotobuf-cpp-lite",
"libstatslog",
"libstatssocket",
],
}
//cc_benchmark {
// name: "statsd_benchmark",
// defaults: ["statsd_defaults"],
//
// srcs: [
// // atom_field_options.proto needs field_options.proto, but that is
// // not included in libprotobuf-cpp-lite, so compile it here.
// ":libprotobuf-internal-protos",
//
// "benchmark/duration_metric_benchmark.cpp",
// "benchmark/filter_value_benchmark.cpp",
// "benchmark/get_dimensions_for_condition_benchmark.cpp",
// "benchmark/hello_world_benchmark.cpp",
// "benchmark/log_event_benchmark.cpp",
// "benchmark/main.cpp",
// "benchmark/metric_util.cpp",
// "benchmark/stats_write_benchmark.cpp",
// "src/atom_field_options.proto",
// "src/atoms.proto",
// "src/stats_log.proto",
// ],
//
// proto: {
// type: "lite",
// include_dirs: ["external/protobuf/src"],
// },
//
// cflags: [
// "-Wall",
// "-Werror",
// "-Wno-unused-parameter",
// "-Wno-unused-variable",
// "-Wno-unused-function",
//
// // Bug: http://b/29823425 Disable -Wvarargs for Clang update to r271374
// "-Wno-varargs",
// ],
//
// static_libs: [
// "libplatformprotos",
// ],
//
// shared_libs: [
// "libgtest_prod",
// "libprotobuf-cpp-lite",
// "libstatslog",
// "libstatssocket",
// ],
//}
// ==== java proto device library (for test only) ==============================
java_library {

View File

@@ -208,12 +208,8 @@ void StatsLogProcessor::onBinaryPushStateChangedEventLocked(LogEvent* event) {
trainInfo.requiresLowLatencyMonitor =
event->GetBool(5 /*requires low latency monitor field id*/, &err);
trainInfo.status = int32_t(event->GetLong(6 /*state field id*/, &err));
#ifdef NEW_ENCODING_SCHEME
std::vector<uint8_t> trainExperimentIdBytes =
event->GetStorage(7 /*experiment ids field id*/, &err);
#else
string trainExperimentIdString = event->GetString(7 /*experiment ids field id*/, &err);
#endif
bool is_rollback = event->GetBool(10 /*is rollback field id*/, &err);
if (err != NO_ERROR) {
@@ -221,12 +217,8 @@ void StatsLogProcessor::onBinaryPushStateChangedEventLocked(LogEvent* event) {
return;
}
ExperimentIds trainExperimentIds;
#ifdef NEW_ENCODING_SCHEME
if (!trainExperimentIds.ParseFromArray(trainExperimentIdBytes.data(),
trainExperimentIdBytes.size())) {
#else
if (!trainExperimentIds.ParseFromString(trainExperimentIdString)) {
#endif
ALOGE("Failed to parse experimentids in binary push state changed.");
return;
}
@@ -241,11 +233,7 @@ void StatsLogProcessor::onBinaryPushStateChangedEventLocked(LogEvent* event) {
int32_t userId = multiuser_get_user_id(uid);
event->updateValue(2 /*train version field id*/, trainInfo.trainVersionCode, LONG);
#ifdef NEW_ENCODING_SCHEME
event->updateValue(7 /*experiment ids field id*/, trainExperimentIdProto, STORAGE);
#else
event->updateValue(7 /*experiment ids field id*/, trainExperimentIdProto, STRING);
#endif
event->updateValue(8 /*user id field id*/, userId, INT);
// If this event is a rollback event, then the following bits in the event
@@ -352,11 +340,7 @@ void StatsLogProcessor::onWatchdogRollbackOccurredLocked(LogEvent* event) {
vector<uint8_t> experimentIdProto;
writeExperimentIdsToProto(experimentIds, &experimentIdProto);
#ifdef NEW_ENCODING_SCHEME
event->updateValue(6 /*experiment ids field id*/, experimentIdProto, STORAGE);
#else
event->updateValue(6 /*experiment ids field id*/, experimentIdProto, STRING);
#endif
}
vector<int64_t> StatsLogProcessor::processWatchdogRollbackOccurred(const int32_t rollbackTypeIn,

View File

@@ -69,8 +69,7 @@ bool StatsCallbackPuller::PullInternal(vector<shared_ptr<LogEvent>>* data) {
uint8_t* buf = reinterpret_cast<uint8_t*>(
const_cast<int8_t*>(parcel.buffer.data()));
shared_ptr<LogEvent> event = make_shared<LogEvent>(
buf, parcel.buffer.size(), /*uid=*/-1, /*pid=*/-1,
/*useNewSchema=*/true);
buf, parcel.buffer.size(), /*uid=*/-1, /*pid=*/-1);
sharedData->push_back(event);
}
*pullSuccess = success;

View File

@@ -74,29 +74,7 @@ LogEvent::LogEvent(uint8_t* msg, uint32_t len, int32_t uid, int32_t pid)
mLogUid(uid),
mLogPid(pid)
{
#ifdef NEW_ENCODING_SCHEME
initNew();
# else
mContext = create_android_log_parser((char*)msg, len);
init(mContext);
if (mContext) android_log_destroy(&mContext); // set mContext to NULL
#endif
}
LogEvent::LogEvent(uint8_t* msg, uint32_t len, int32_t uid, int32_t pid, bool useNewSchema)
: mBuf(msg),
mRemainingLen(len),
mLogdTimestampNs(time(nullptr)),
mLogUid(uid),
mLogPid(pid)
{
if (useNewSchema) {
initNew();
} else {
mContext = create_android_log_parser((char*)msg, len);
init(mContext);
if (mContext) android_log_destroy(&mContext); // set mContext to NULL
}
}
LogEvent::LogEvent(const LogEvent& event) {
@@ -225,22 +203,6 @@ LogEvent::LogEvent(int32_t tagId, int64_t timestampNs, int32_t uid) {
}
}
void LogEvent::init() {
if (mContext) {
const char* buffer;
size_t len = android_log_write_list_buffer(mContext, &buffer);
// turns to reader mode
android_log_context contextForRead = create_android_log_parser(buffer, len);
if (contextForRead) {
init(contextForRead);
// destroy the context to save memory.
// android_log_destroy will set mContext to NULL
android_log_destroy(&contextForRead);
}
android_log_destroy(&mContext);
}
}
LogEvent::~LogEvent() {
if (mContext) {
// This is for the case when LogEvent is created using the test interface
@@ -577,132 +539,6 @@ uint8_t LogEvent::getNumAnnotations(uint8_t typeInfo) {
return (typeInfo >> 4) & 0x0F;
}
/**
* The elements of each log event are stored as a vector of android_log_list_elements.
* The goal is to do as little preprocessing as possible, because we read a tiny fraction
* of the elements that are written to the log.
*
* The idea here is to read through the log items once, we get as much information we need for
* matching as possible. Because this log will be matched against lots of matchers.
*/
void LogEvent::init(android_log_context context) {
android_log_list_element elem;
int i = 0;
int depth = -1;
int pos[] = {1, 1, 1};
bool isKeyValuePairAtom = false;
do {
elem = android_log_read_next(context);
switch ((int)elem.type) {
case EVENT_TYPE_INT:
// elem at [0] is EVENT_TYPE_LIST, [1] is the timestamp, [2] is tag id.
if (i == 2) {
mTagId = elem.data.int32;
isKeyValuePairAtom = (mTagId == android::util::KEY_VALUE_PAIRS_ATOM);
} else {
if (depth < 0 || depth > 2) {
return;
}
mValues.push_back(
FieldValue(Field(mTagId, pos, depth), Value((int32_t)elem.data.int32)));
pos[depth]++;
}
break;
case EVENT_TYPE_FLOAT: {
if (depth < 0 || depth > 2) {
ALOGE("Depth > 2. Not supported!");
return;
}
// Handles the oneof field in KeyValuePair atom.
if (isKeyValuePairAtom && depth == 2) {
pos[depth] = 5;
}
mValues.push_back(FieldValue(Field(mTagId, pos, depth), Value(elem.data.float32)));
pos[depth]++;
} break;
case EVENT_TYPE_STRING: {
if (depth < 0 || depth > 2) {
ALOGE("Depth > 2. Not supported!");
return;
}
// Handles the oneof field in KeyValuePair atom.
if (isKeyValuePairAtom && depth == 2) {
pos[depth] = 4;
}
mValues.push_back(FieldValue(Field(mTagId, pos, depth),
Value(string(elem.data.string, elem.len))));
pos[depth]++;
} break;
case EVENT_TYPE_LONG: {
if (i == 1) {
mElapsedTimestampNs = elem.data.int64;
} else {
if (depth < 0 || depth > 2) {
ALOGE("Depth > 2. Not supported!");
return;
}
// Handles the oneof field in KeyValuePair atom.
if (isKeyValuePairAtom && depth == 2) {
pos[depth] = 3;
}
mValues.push_back(
FieldValue(Field(mTagId, pos, depth), Value((int64_t)elem.data.int64)));
pos[depth]++;
}
} break;
case EVENT_TYPE_LIST:
depth++;
if (depth > 2) {
ALOGE("Depth > 2. Not supported!");
return;
}
pos[depth] = 1;
break;
case EVENT_TYPE_LIST_STOP: {
int prevDepth = depth;
depth--;
if (depth >= 0 && depth < 2) {
// Now go back to decorate the previous items that are last at prevDepth.
// So that we can later easily match them with Position=Last matchers.
pos[prevDepth]--;
int path = getEncodedField(pos, prevDepth, false);
for (auto it = mValues.rbegin(); it != mValues.rend(); ++it) {
if (it->mField.getDepth() >= prevDepth &&
it->mField.getPath(prevDepth) == path) {
it->mField.decorateLastPos(prevDepth);
} else {
// Safe to break, because the items are in DFS order.
break;
}
}
pos[depth]++;
}
break;
}
case EVENT_TYPE_UNKNOWN:
break;
default:
break;
}
i++;
} while ((elem.type != EVENT_TYPE_UNKNOWN) && !elem.complete);
if (isKeyValuePairAtom && mValues.size() > 0) {
mValues[0] = FieldValue(Field(android::util::KEY_VALUE_PAIRS_ATOM, getSimpleField(1)),
Value((int32_t)mLogUid));
}
}
int64_t LogEvent::GetLong(size_t key, status_t* err) const {
// TODO(b/110561208): encapsulate the magical operations in Field struct as static functions
int field = getSimpleField(key);

View File

@@ -70,11 +70,6 @@ public:
*/
explicit LogEvent(uint8_t* msg, uint32_t len, int32_t uid, int32_t pid);
/**
* Temp constructor to use for pulled atoms until we flip the socket schema.
*/
explicit LogEvent(uint8_t* msg, uint32_t len, int32_t uid, int32_t pid, bool useNewSchema);
/**
* Constructs a LogEvent with synthetic data for testing. Must call init() before reading.
*/
@@ -171,12 +166,6 @@ public:
*/
void ToProto(android::util::ProtoOutputStream& out) const;
/**
* Used with the constructor where tag is passed in. Converts the log_event_list to read mode
* and prepares the list for reading.
*/
void init();
/**
* Set elapsed timestamp if the original timestamp is missing.
*/
@@ -304,11 +293,6 @@ private:
uint8_t getTypeId(uint8_t typeInfo);
uint8_t getNumAnnotations(uint8_t typeInfo);
/**
* Parses a log_msg into a LogEvent object.
*/
void init(android_log_context context);
// The items are naturally sorted in DFS order as we read them. this allows us to do fast
// matching.
std::vector<FieldValue> mValues;

View File

@@ -72,65 +72,66 @@ TEST(AtomMatcherTest, TestFieldTranslation_ALL) {
EXPECT_EQ((int32_t)0xff7f7f7f, matcher12.mMask);
}
TEST(AtomMatcherTest, TestFilter_ALL) {
FieldMatcher matcher1;
matcher1.set_field(10);
FieldMatcher* child = matcher1.add_child();
child->set_field(1);
child->set_position(Position::ALL);
child->add_child()->set_field(1);
child->add_child()->set_field(2);
child = matcher1.add_child();
child->set_field(2);
vector<Matcher> matchers;
translateFieldMatcher(matcher1, &matchers);
AttributionNodeInternal attribution_node1;
attribution_node1.set_uid(1111);
attribution_node1.set_tag("location1");
AttributionNodeInternal attribution_node2;
attribution_node2.set_uid(2222);
attribution_node2.set_tag("location2");
AttributionNodeInternal attribution_node3;
attribution_node3.set_uid(3333);
attribution_node3.set_tag("location3");
std::vector<AttributionNodeInternal> attribution_nodes = {attribution_node1, attribution_node2,
attribution_node3};
// Set up the event
LogEvent event(10, 12345);
event.write(attribution_nodes);
event.write("some value");
// Convert to a LogEvent
event.init();
HashableDimensionKey output;
filterValues(matchers, event.getValues(), &output);
EXPECT_EQ((size_t)7, output.getValues().size());
EXPECT_EQ((int32_t)0x02010101, output.getValues()[0].mField.getField());
EXPECT_EQ((int32_t)1111, output.getValues()[0].mValue.int_value);
EXPECT_EQ((int32_t)0x02010102, output.getValues()[1].mField.getField());
EXPECT_EQ("location1", output.getValues()[1].mValue.str_value);
EXPECT_EQ((int32_t)0x02010201, output.getValues()[2].mField.getField());
EXPECT_EQ((int32_t)2222, output.getValues()[2].mValue.int_value);
EXPECT_EQ((int32_t)0x02010202, output.getValues()[3].mField.getField());
EXPECT_EQ("location2", output.getValues()[3].mValue.str_value);
EXPECT_EQ((int32_t)0x02010301, output.getValues()[4].mField.getField());
EXPECT_EQ((int32_t)3333, output.getValues()[4].mValue.int_value);
EXPECT_EQ((int32_t)0x02010302, output.getValues()[5].mField.getField());
EXPECT_EQ("location3", output.getValues()[5].mValue.str_value);
EXPECT_EQ((int32_t)0x00020000, output.getValues()[6].mField.getField());
EXPECT_EQ("some value", output.getValues()[6].mValue.str_value);
}
// TODO(b/149590301): Update this test to use new socket schema.
//TEST(AtomMatcherTest, TestFilter_ALL) {
// FieldMatcher matcher1;
// matcher1.set_field(10);
// FieldMatcher* child = matcher1.add_child();
// child->set_field(1);
// child->set_position(Position::ALL);
//
// child->add_child()->set_field(1);
// child->add_child()->set_field(2);
//
// child = matcher1.add_child();
// child->set_field(2);
//
// vector<Matcher> matchers;
// translateFieldMatcher(matcher1, &matchers);
//
// AttributionNodeInternal attribution_node1;
// attribution_node1.set_uid(1111);
// attribution_node1.set_tag("location1");
//
// AttributionNodeInternal attribution_node2;
// attribution_node2.set_uid(2222);
// attribution_node2.set_tag("location2");
//
// AttributionNodeInternal attribution_node3;
// attribution_node3.set_uid(3333);
// attribution_node3.set_tag("location3");
// std::vector<AttributionNodeInternal> attribution_nodes = {attribution_node1, attribution_node2,
// attribution_node3};
//
// // Set up the event
// LogEvent event(10, 12345);
// event.write(attribution_nodes);
// event.write("some value");
// // Convert to a LogEvent
// event.init();
// HashableDimensionKey output;
//
// filterValues(matchers, event.getValues(), &output);
//
// EXPECT_EQ((size_t)7, output.getValues().size());
// EXPECT_EQ((int32_t)0x02010101, output.getValues()[0].mField.getField());
// EXPECT_EQ((int32_t)1111, output.getValues()[0].mValue.int_value);
// EXPECT_EQ((int32_t)0x02010102, output.getValues()[1].mField.getField());
// EXPECT_EQ("location1", output.getValues()[1].mValue.str_value);
//
// EXPECT_EQ((int32_t)0x02010201, output.getValues()[2].mField.getField());
// EXPECT_EQ((int32_t)2222, output.getValues()[2].mValue.int_value);
// EXPECT_EQ((int32_t)0x02010202, output.getValues()[3].mField.getField());
// EXPECT_EQ("location2", output.getValues()[3].mValue.str_value);
//
// EXPECT_EQ((int32_t)0x02010301, output.getValues()[4].mField.getField());
// EXPECT_EQ((int32_t)3333, output.getValues()[4].mValue.int_value);
// EXPECT_EQ((int32_t)0x02010302, output.getValues()[5].mField.getField());
// EXPECT_EQ("location3", output.getValues()[5].mValue.str_value);
//
// EXPECT_EQ((int32_t)0x00020000, output.getValues()[6].mField.getField());
// EXPECT_EQ("some value", output.getValues()[6].mValue.str_value);
//}
TEST(AtomMatcherTest, TestSubDimension) {
HashableDimensionKey dim;
@@ -173,60 +174,61 @@ TEST(AtomMatcherTest, TestSubDimension) {
EXPECT_TRUE(dim.contains(subDim4));
}
TEST(AtomMatcherTest, TestMetric2ConditionLink) {
AttributionNodeInternal attribution_node1;
attribution_node1.set_uid(1111);
attribution_node1.set_tag("location1");
AttributionNodeInternal attribution_node2;
attribution_node2.set_uid(2222);
attribution_node2.set_tag("location2");
AttributionNodeInternal attribution_node3;
attribution_node3.set_uid(3333);
attribution_node3.set_tag("location3");
std::vector<AttributionNodeInternal> attribution_nodes = {attribution_node1, attribution_node2,
attribution_node3};
// Set up the event
LogEvent event(10, 12345);
event.write(attribution_nodes);
event.write("some value");
// Convert to a LogEvent
event.init();
FieldMatcher whatMatcher;
whatMatcher.set_field(10);
FieldMatcher* child11 = whatMatcher.add_child();
child11->set_field(1);
child11->set_position(Position::ANY);
child11 = child11->add_child();
child11->set_field(1);
FieldMatcher conditionMatcher;
conditionMatcher.set_field(27);
FieldMatcher* child2 = conditionMatcher.add_child();
child2->set_field(2);
child2->set_position(Position::LAST);
child2 = child2->add_child();
child2->set_field(2);
Metric2Condition link;
translateFieldMatcher(whatMatcher, &link.metricFields);
translateFieldMatcher(conditionMatcher, &link.conditionFields);
EXPECT_EQ((size_t)1, link.metricFields.size());
EXPECT_EQ((int32_t)0x02010001, link.metricFields[0].mMatcher.getField());
EXPECT_EQ((int32_t)0xff7f007f, link.metricFields[0].mMask);
EXPECT_EQ((int32_t)10, link.metricFields[0].mMatcher.getTag());
EXPECT_EQ((size_t)1, link.conditionFields.size());
EXPECT_EQ((int32_t)0x02028002, link.conditionFields[0].mMatcher.getField());
EXPECT_EQ((int32_t)0xff7f807f, link.conditionFields[0].mMask);
EXPECT_EQ((int32_t)27, link.conditionFields[0].mMatcher.getTag());
}
// TODO(b/149590301): Update this test to use new socket schema.
//TEST(AtomMatcherTest, TestMetric2ConditionLink) {
// AttributionNodeInternal attribution_node1;
// attribution_node1.set_uid(1111);
// attribution_node1.set_tag("location1");
//
// AttributionNodeInternal attribution_node2;
// attribution_node2.set_uid(2222);
// attribution_node2.set_tag("location2");
//
// AttributionNodeInternal attribution_node3;
// attribution_node3.set_uid(3333);
// attribution_node3.set_tag("location3");
// std::vector<AttributionNodeInternal> attribution_nodes = {attribution_node1, attribution_node2,
// attribution_node3};
//
// // Set up the event
// LogEvent event(10, 12345);
// event.write(attribution_nodes);
// event.write("some value");
// // Convert to a LogEvent
// event.init();
//
// FieldMatcher whatMatcher;
// whatMatcher.set_field(10);
// FieldMatcher* child11 = whatMatcher.add_child();
// child11->set_field(1);
// child11->set_position(Position::ANY);
// child11 = child11->add_child();
// child11->set_field(1);
//
// FieldMatcher conditionMatcher;
// conditionMatcher.set_field(27);
// FieldMatcher* child2 = conditionMatcher.add_child();
// child2->set_field(2);
// child2->set_position(Position::LAST);
//
// child2 = child2->add_child();
// child2->set_field(2);
//
// Metric2Condition link;
//
// translateFieldMatcher(whatMatcher, &link.metricFields);
// translateFieldMatcher(conditionMatcher, &link.conditionFields);
//
// EXPECT_EQ((size_t)1, link.metricFields.size());
// EXPECT_EQ((int32_t)0x02010001, link.metricFields[0].mMatcher.getField());
// EXPECT_EQ((int32_t)0xff7f007f, link.metricFields[0].mMask);
// EXPECT_EQ((int32_t)10, link.metricFields[0].mMatcher.getTag());
//
// EXPECT_EQ((size_t)1, link.conditionFields.size());
// EXPECT_EQ((int32_t)0x02028002, link.conditionFields[0].mMatcher.getField());
// EXPECT_EQ((int32_t)0xff7f807f, link.conditionFields[0].mMask);
// EXPECT_EQ((int32_t)27, link.conditionFields[0].mMatcher.getTag());
//}
TEST(AtomMatcherTest, TestWriteDimensionPath) {
for (auto position : {Position::ANY, Position::ALL, Position::FIRST, Position::LAST}) {
@@ -437,49 +439,50 @@ TEST(AtomMatcherTest, TestWriteDimensionLeafNodesToProto) {
EXPECT_EQ(99999, dim4.value_long());
}
TEST(AtomMatcherTest, TestWriteAtomToProto) {
AttributionNodeInternal attribution_node1;
attribution_node1.set_uid(1111);
attribution_node1.set_tag("location1");
AttributionNodeInternal attribution_node2;
attribution_node2.set_uid(2222);
attribution_node2.set_tag("location2");
std::vector<AttributionNodeInternal> attribution_nodes = {attribution_node1, attribution_node2};
// Set up the event
LogEvent event(4, 12345);
event.write(attribution_nodes);
event.write((int32_t)999);
// Convert to a LogEvent
event.init();
android::util::ProtoOutputStream protoOutput;
writeFieldValueTreeToStream(event.GetTagId(), event.getValues(), &protoOutput);
vector<uint8_t> outData;
outData.resize(protoOutput.size());
size_t pos = 0;
sp<ProtoReader> reader = protoOutput.data();
while (reader->readBuffer() != NULL) {
size_t toRead = reader->currentToRead();
std::memcpy(&(outData[pos]), reader->readBuffer(), toRead);
pos += toRead;
reader->move(toRead);
}
Atom result;
EXPECT_EQ(true, result.ParseFromArray(&outData[0], outData.size()));
EXPECT_EQ(Atom::PushedCase::kBleScanResultReceived, result.pushed_case());
const auto& atom = result.ble_scan_result_received();
EXPECT_EQ(2, atom.attribution_node_size());
EXPECT_EQ(1111, atom.attribution_node(0).uid());
EXPECT_EQ("location1", atom.attribution_node(0).tag());
EXPECT_EQ(2222, atom.attribution_node(1).uid());
EXPECT_EQ("location2", atom.attribution_node(1).tag());
EXPECT_EQ(999, atom.num_results());
}
// TODO(b/149590301): Update this test to use new socket schema.
//TEST(AtomMatcherTest, TestWriteAtomToProto) {
// AttributionNodeInternal attribution_node1;
// attribution_node1.set_uid(1111);
// attribution_node1.set_tag("location1");
//
// AttributionNodeInternal attribution_node2;
// attribution_node2.set_uid(2222);
// attribution_node2.set_tag("location2");
//
// std::vector<AttributionNodeInternal> attribution_nodes = {attribution_node1, attribution_node2};
//
// // Set up the event
// LogEvent event(4, 12345);
// event.write(attribution_nodes);
// event.write((int32_t)999);
// // Convert to a LogEvent
// event.init();
//
// android::util::ProtoOutputStream protoOutput;
// writeFieldValueTreeToStream(event.GetTagId(), event.getValues(), &protoOutput);
//
// vector<uint8_t> outData;
// outData.resize(protoOutput.size());
// size_t pos = 0;
// sp<ProtoReader> reader = protoOutput.data();
// while (reader->readBuffer() != NULL) {
// size_t toRead = reader->currentToRead();
// std::memcpy(&(outData[pos]), reader->readBuffer(), toRead);
// pos += toRead;
// reader->move(toRead);
// }
//
// Atom result;
// EXPECT_EQ(true, result.ParseFromArray(&outData[0], outData.size()));
// EXPECT_EQ(Atom::PushedCase::kBleScanResultReceived, result.pushed_case());
// const auto& atom = result.ble_scan_result_received();
// EXPECT_EQ(2, atom.attribution_node_size());
// EXPECT_EQ(1111, atom.attribution_node(0).uid());
// EXPECT_EQ("location1", atom.attribution_node(0).tag());
// EXPECT_EQ(2222, atom.attribution_node(1).uid());
// EXPECT_EQ("location2", atom.attribution_node(1).tag());
// EXPECT_EQ(999, atom.num_results());
//}
/*
* Test two Matchers is not a subset of one Matcher.

File diff suppressed because it is too large Load Diff

View File

@@ -31,9 +31,6 @@ using std::vector;
using util::ProtoOutputStream;
using util::ProtoReader;
#ifdef NEW_ENCODING_SCHEME
Field getField(int32_t tag, const vector<int32_t>& pos, int32_t depth, const vector<bool>& last) {
Field f(tag, (int32_t*)pos.data(), depth);
@@ -241,480 +238,6 @@ TEST(LogEventTest, TestAttributionChain) {
AStatsEvent_release(event);
}
#else // NEW_ENCODING_SCHEME
TEST(LogEventTest, TestLogParsing) {
LogEvent event1(1, 2000);
std::vector<AttributionNodeInternal> nodes;
AttributionNodeInternal node1;
node1.set_uid(1000);
node1.set_tag("tag1");
nodes.push_back(node1);
AttributionNodeInternal node2;
node2.set_uid(2000);
node2.set_tag("tag2");
nodes.push_back(node2);
event1.write(nodes);
event1.write("hello");
event1.write((int32_t)10);
event1.write((int64_t)20);
event1.write((float)1.1);
event1.init();
const auto& items = event1.getValues();
EXPECT_EQ((size_t)8, items.size());
EXPECT_EQ(1, event1.GetTagId());
const FieldValue& item0 = event1.getValues()[0];
EXPECT_EQ(0x2010101, item0.mField.getField());
EXPECT_EQ(Type::INT, item0.mValue.getType());
EXPECT_EQ(1000, item0.mValue.int_value);
const FieldValue& item1 = event1.getValues()[1];
EXPECT_EQ(0x2010182, item1.mField.getField());
EXPECT_EQ(Type::STRING, item1.mValue.getType());
EXPECT_EQ("tag1", item1.mValue.str_value);
const FieldValue& item2 = event1.getValues()[2];
EXPECT_EQ(0x2018201, item2.mField.getField());
EXPECT_EQ(Type::INT, item2.mValue.getType());
EXPECT_EQ(2000, item2.mValue.int_value);
const FieldValue& item3 = event1.getValues()[3];
EXPECT_EQ(0x2018282, item3.mField.getField());
EXPECT_EQ(Type::STRING, item3.mValue.getType());
EXPECT_EQ("tag2", item3.mValue.str_value);
const FieldValue& item4 = event1.getValues()[4];
EXPECT_EQ(0x20000, item4.mField.getField());
EXPECT_EQ(Type::STRING, item4.mValue.getType());
EXPECT_EQ("hello", item4.mValue.str_value);
const FieldValue& item5 = event1.getValues()[5];
EXPECT_EQ(0x30000, item5.mField.getField());
EXPECT_EQ(Type::INT, item5.mValue.getType());
EXPECT_EQ(10, item5.mValue.int_value);
const FieldValue& item6 = event1.getValues()[6];
EXPECT_EQ(0x40000, item6.mField.getField());
EXPECT_EQ(Type::LONG, item6.mValue.getType());
EXPECT_EQ((int64_t)20, item6.mValue.long_value);
const FieldValue& item7 = event1.getValues()[7];
EXPECT_EQ(0x50000, item7.mField.getField());
EXPECT_EQ(Type::FLOAT, item7.mValue.getType());
EXPECT_EQ((float)1.1, item7.mValue.float_value);
}
TEST(LogEventTest, TestKeyValuePairsAtomParsing) {
LogEvent event1(83, 2000, 1000);
std::map<int32_t, int32_t> int_map;
std::map<int32_t, int64_t> long_map;
std::map<int32_t, std::string> string_map;
std::map<int32_t, float> float_map;
int_map[11] = 123;
int_map[22] = 345;
long_map[33] = 678L;
long_map[44] = 890L;
string_map[1] = "test2";
string_map[2] = "test1";
float_map[111] = 2.2f;
float_map[222] = 1.1f;
EXPECT_TRUE(event1.writeKeyValuePairs(0, // Logging side logs 0 uid.
int_map,
long_map,
string_map,
float_map));
event1.init();
EXPECT_EQ(83, event1.GetTagId());
const auto& items = event1.getValues();
EXPECT_EQ((size_t)17, items.size());
const FieldValue& item0 = event1.getValues()[0];
EXPECT_EQ(0x10000, item0.mField.getField());
EXPECT_EQ(Type::INT, item0.mValue.getType());
EXPECT_EQ(1000, item0.mValue.int_value);
const FieldValue& item1 = event1.getValues()[1];
EXPECT_EQ(0x2010201, item1.mField.getField());
EXPECT_EQ(Type::INT, item1.mValue.getType());
EXPECT_EQ(11, item1.mValue.int_value);
const FieldValue& item2 = event1.getValues()[2];
EXPECT_EQ(0x2010282, item2.mField.getField());
EXPECT_EQ(Type::INT, item2.mValue.getType());
EXPECT_EQ(123, item2.mValue.int_value);
const FieldValue& item3 = event1.getValues()[3];
EXPECT_EQ(0x2010301, item3.mField.getField());
EXPECT_EQ(Type::INT, item3.mValue.getType());
EXPECT_EQ(22, item3.mValue.int_value);
const FieldValue& item4 = event1.getValues()[4];
EXPECT_EQ(0x2010382, item4.mField.getField());
EXPECT_EQ(Type::INT, item4.mValue.getType());
EXPECT_EQ(345, item4.mValue.int_value);
const FieldValue& item5 = event1.getValues()[5];
EXPECT_EQ(0x2010401, item5.mField.getField());
EXPECT_EQ(Type::INT, item5.mValue.getType());
EXPECT_EQ(33, item5.mValue.int_value);
const FieldValue& item6 = event1.getValues()[6];
EXPECT_EQ(0x2010483, item6.mField.getField());
EXPECT_EQ(Type::LONG, item6.mValue.getType());
EXPECT_EQ(678L, item6.mValue.int_value);
const FieldValue& item7 = event1.getValues()[7];
EXPECT_EQ(0x2010501, item7.mField.getField());
EXPECT_EQ(Type::INT, item7.mValue.getType());
EXPECT_EQ(44, item7.mValue.int_value);
const FieldValue& item8 = event1.getValues()[8];
EXPECT_EQ(0x2010583, item8.mField.getField());
EXPECT_EQ(Type::LONG, item8.mValue.getType());
EXPECT_EQ(890L, item8.mValue.int_value);
const FieldValue& item9 = event1.getValues()[9];
EXPECT_EQ(0x2010601, item9.mField.getField());
EXPECT_EQ(Type::INT, item9.mValue.getType());
EXPECT_EQ(1, item9.mValue.int_value);
const FieldValue& item10 = event1.getValues()[10];
EXPECT_EQ(0x2010684, item10.mField.getField());
EXPECT_EQ(Type::STRING, item10.mValue.getType());
EXPECT_EQ("test2", item10.mValue.str_value);
const FieldValue& item11 = event1.getValues()[11];
EXPECT_EQ(0x2010701, item11.mField.getField());
EXPECT_EQ(Type::INT, item11.mValue.getType());
EXPECT_EQ(2, item11.mValue.int_value);
const FieldValue& item12 = event1.getValues()[12];
EXPECT_EQ(0x2010784, item12.mField.getField());
EXPECT_EQ(Type::STRING, item12.mValue.getType());
EXPECT_EQ("test1", item12.mValue.str_value);
const FieldValue& item13 = event1.getValues()[13];
EXPECT_EQ(0x2010801, item13.mField.getField());
EXPECT_EQ(Type::INT, item13.mValue.getType());
EXPECT_EQ(111, item13.mValue.int_value);
const FieldValue& item14 = event1.getValues()[14];
EXPECT_EQ(0x2010885, item14.mField.getField());
EXPECT_EQ(Type::FLOAT, item14.mValue.getType());
EXPECT_EQ(2.2f, item14.mValue.float_value);
const FieldValue& item15 = event1.getValues()[15];
EXPECT_EQ(0x2018901, item15.mField.getField());
EXPECT_EQ(Type::INT, item15.mValue.getType());
EXPECT_EQ(222, item15.mValue.int_value);
const FieldValue& item16 = event1.getValues()[16];
EXPECT_EQ(0x2018985, item16.mField.getField());
EXPECT_EQ(Type::FLOAT, item16.mValue.getType());
EXPECT_EQ(1.1f, item16.mValue.float_value);
}
TEST(LogEventTest, TestLogParsing2) {
LogEvent event1(1, 2000);
std::vector<AttributionNodeInternal> nodes;
event1.write("hello");
// repeated msg can be in the middle
AttributionNodeInternal node1;
node1.set_uid(1000);
node1.set_tag("tag1");
nodes.push_back(node1);
AttributionNodeInternal node2;
node2.set_uid(2000);
node2.set_tag("tag2");
nodes.push_back(node2);
event1.write(nodes);
event1.write((int32_t)10);
event1.write((int64_t)20);
event1.write((float)1.1);
event1.init();
const auto& items = event1.getValues();
EXPECT_EQ((size_t)8, items.size());
EXPECT_EQ(1, event1.GetTagId());
const FieldValue& item = event1.getValues()[0];
EXPECT_EQ(0x00010000, item.mField.getField());
EXPECT_EQ(Type::STRING, item.mValue.getType());
EXPECT_EQ("hello", item.mValue.str_value);
const FieldValue& item0 = event1.getValues()[1];
EXPECT_EQ(0x2020101, item0.mField.getField());
EXPECT_EQ(Type::INT, item0.mValue.getType());
EXPECT_EQ(1000, item0.mValue.int_value);
const FieldValue& item1 = event1.getValues()[2];
EXPECT_EQ(0x2020182, item1.mField.getField());
EXPECT_EQ(Type::STRING, item1.mValue.getType());
EXPECT_EQ("tag1", item1.mValue.str_value);
const FieldValue& item2 = event1.getValues()[3];
EXPECT_EQ(0x2028201, item2.mField.getField());
EXPECT_EQ(Type::INT, item2.mValue.getType());
EXPECT_EQ(2000, item2.mValue.int_value);
const FieldValue& item3 = event1.getValues()[4];
EXPECT_EQ(0x2028282, item3.mField.getField());
EXPECT_EQ(Type::STRING, item3.mValue.getType());
EXPECT_EQ("tag2", item3.mValue.str_value);
const FieldValue& item5 = event1.getValues()[5];
EXPECT_EQ(0x30000, item5.mField.getField());
EXPECT_EQ(Type::INT, item5.mValue.getType());
EXPECT_EQ(10, item5.mValue.int_value);
const FieldValue& item6 = event1.getValues()[6];
EXPECT_EQ(0x40000, item6.mField.getField());
EXPECT_EQ(Type::LONG, item6.mValue.getType());
EXPECT_EQ((int64_t)20, item6.mValue.long_value);
const FieldValue& item7 = event1.getValues()[7];
EXPECT_EQ(0x50000, item7.mField.getField());
EXPECT_EQ(Type::FLOAT, item7.mValue.getType());
EXPECT_EQ((float)1.1, item7.mValue.float_value);
}
TEST(LogEventTest, TestKeyValuePairsEvent) {
std::map<int32_t, int32_t> int_map;
std::map<int32_t, int64_t> long_map;
std::map<int32_t, std::string> string_map;
std::map<int32_t, float> float_map;
int_map[11] = 123;
int_map[22] = 345;
long_map[33] = 678L;
long_map[44] = 890L;
string_map[1] = "test2";
string_map[2] = "test1";
float_map[111] = 2.2f;
float_map[222] = 1.1f;
LogEvent event1(83, 2000, 2001, 10001, int_map, long_map, string_map, float_map);
event1.init();
EXPECT_EQ(83, event1.GetTagId());
EXPECT_EQ((int64_t)2000, event1.GetLogdTimestampNs());
EXPECT_EQ((int64_t)2001, event1.GetElapsedTimestampNs());
EXPECT_EQ((int64_t)10001, event1.GetUid());
const auto& items = event1.getValues();
EXPECT_EQ((size_t)17, items.size());
const FieldValue& item0 = event1.getValues()[0];
EXPECT_EQ(0x00010000, item0.mField.getField());
EXPECT_EQ(Type::INT, item0.mValue.getType());
EXPECT_EQ(10001, item0.mValue.int_value);
const FieldValue& item1 = event1.getValues()[1];
EXPECT_EQ(0x2020101, item1.mField.getField());
EXPECT_EQ(Type::INT, item1.mValue.getType());
EXPECT_EQ(11, item1.mValue.int_value);
const FieldValue& item2 = event1.getValues()[2];
EXPECT_EQ(0x2020182, item2.mField.getField());
EXPECT_EQ(Type::INT, item2.mValue.getType());
EXPECT_EQ(123, item2.mValue.int_value);
const FieldValue& item3 = event1.getValues()[3];
EXPECT_EQ(0x2020201, item3.mField.getField());
EXPECT_EQ(Type::INT, item3.mValue.getType());
EXPECT_EQ(22, item3.mValue.int_value);
const FieldValue& item4 = event1.getValues()[4];
EXPECT_EQ(0x2020282, item4.mField.getField());
EXPECT_EQ(Type::INT, item4.mValue.getType());
EXPECT_EQ(345, item4.mValue.int_value);
const FieldValue& item5 = event1.getValues()[5];
EXPECT_EQ(0x2020301, item5.mField.getField());
EXPECT_EQ(Type::INT, item5.mValue.getType());
EXPECT_EQ(33, item5.mValue.int_value);
const FieldValue& item6 = event1.getValues()[6];
EXPECT_EQ(0x2020383, item6.mField.getField());
EXPECT_EQ(Type::LONG, item6.mValue.getType());
EXPECT_EQ(678L, item6.mValue.long_value);
const FieldValue& item7 = event1.getValues()[7];
EXPECT_EQ(0x2020401, item7.mField.getField());
EXPECT_EQ(Type::INT, item7.mValue.getType());
EXPECT_EQ(44, item7.mValue.int_value);
const FieldValue& item8 = event1.getValues()[8];
EXPECT_EQ(0x2020483, item8.mField.getField());
EXPECT_EQ(Type::LONG, item8.mValue.getType());
EXPECT_EQ(890L, item8.mValue.long_value);
const FieldValue& item9 = event1.getValues()[9];
EXPECT_EQ(0x2020501, item9.mField.getField());
EXPECT_EQ(Type::INT, item9.mValue.getType());
EXPECT_EQ(1, item9.mValue.int_value);
const FieldValue& item10 = event1.getValues()[10];
EXPECT_EQ(0x2020584, item10.mField.getField());
EXPECT_EQ(Type::STRING, item10.mValue.getType());
EXPECT_EQ("test2", item10.mValue.str_value);
const FieldValue& item11 = event1.getValues()[11];
EXPECT_EQ(0x2020601, item11.mField.getField());
EXPECT_EQ(Type::INT, item11.mValue.getType());
EXPECT_EQ(2, item11.mValue.int_value);
const FieldValue& item12 = event1.getValues()[12];
EXPECT_EQ(0x2020684, item12.mField.getField());
EXPECT_EQ(Type::STRING, item12.mValue.getType());
EXPECT_EQ("test1", item12.mValue.str_value);
const FieldValue& item13 = event1.getValues()[13];
EXPECT_EQ(0x2020701, item13.mField.getField());
EXPECT_EQ(Type::INT, item13.mValue.getType());
EXPECT_EQ(111, item13.mValue.int_value);
const FieldValue& item14 = event1.getValues()[14];
EXPECT_EQ(0x2020785, item14.mField.getField());
EXPECT_EQ(Type::FLOAT, item14.mValue.getType());
EXPECT_EQ(2.2f, item14.mValue.float_value);
const FieldValue& item15 = event1.getValues()[15];
EXPECT_EQ(0x2028801, item15.mField.getField());
EXPECT_EQ(Type::INT, item15.mValue.getType());
EXPECT_EQ(222, item15.mValue.int_value);
const FieldValue& item16 = event1.getValues()[16];
EXPECT_EQ(0x2028885, item16.mField.getField());
EXPECT_EQ(Type::FLOAT, item16.mValue.getType());
EXPECT_EQ(1.1f, item16.mValue.float_value);
}
TEST(LogEventTest, TestBinaryFieldAtom) {
Atom launcherAtom;
auto launcher_event = launcherAtom.mutable_launcher_event();
launcher_event->set_action(stats::launcher::LauncherAction::LONGPRESS);
launcher_event->set_src_state(stats::launcher::LauncherState::OVERVIEW);
launcher_event->set_dst_state(stats::launcher::LauncherState::ALLAPPS);
auto extension = launcher_event->mutable_extension();
auto src_target = extension->add_src_target();
src_target->set_type(stats::launcher::LauncherTarget_Type_ITEM_TYPE);
src_target->set_item(stats::launcher::LauncherTarget_Item_FOLDER_ICON);
auto dst_target = extension->add_dst_target();
dst_target->set_type(stats::launcher::LauncherTarget_Type_ITEM_TYPE);
dst_target->set_item(stats::launcher::LauncherTarget_Item_WIDGET);
string extension_str;
extension->SerializeToString(&extension_str);
LogEvent event1(Atom::kLauncherEventFieldNumber, 1000);
event1.write((int32_t)stats::launcher::LauncherAction::LONGPRESS);
event1.write((int32_t)stats::launcher::LauncherState::OVERVIEW);
event1.write((int64_t)stats::launcher::LauncherState::ALLAPPS);
event1.writeBytes(extension_str);
event1.init();
ProtoOutputStream proto;
event1.ToProto(proto);
std::vector<uint8_t> outData;
outData.resize(proto.size());
size_t pos = 0;
sp<ProtoReader> reader = proto.data();
while (reader->readBuffer() != NULL) {
size_t toRead = reader->currentToRead();
std::memcpy(&(outData[pos]), reader->readBuffer(), toRead);
pos += toRead;
reader->move(toRead);
}
std::string result_str(outData.begin(), outData.end());
std::string orig_str;
launcherAtom.SerializeToString(&orig_str);
EXPECT_EQ(orig_str, result_str);
}
TEST(LogEventTest, TestBinaryFieldAtom_empty) {
Atom launcherAtom;
auto launcher_event = launcherAtom.mutable_launcher_event();
launcher_event->set_action(stats::launcher::LauncherAction::LONGPRESS);
launcher_event->set_src_state(stats::launcher::LauncherState::OVERVIEW);
launcher_event->set_dst_state(stats::launcher::LauncherState::ALLAPPS);
// empty string.
string extension_str;
LogEvent event1(Atom::kLauncherEventFieldNumber, 1000);
event1.write((int32_t)stats::launcher::LauncherAction::LONGPRESS);
event1.write((int32_t)stats::launcher::LauncherState::OVERVIEW);
event1.write((int64_t)stats::launcher::LauncherState::ALLAPPS);
event1.writeBytes(extension_str);
event1.init();
ProtoOutputStream proto;
event1.ToProto(proto);
std::vector<uint8_t> outData;
outData.resize(proto.size());
size_t pos = 0;
sp<ProtoReader> reader = proto.data();
while (reader->readBuffer() != NULL) {
size_t toRead = reader->currentToRead();
std::memcpy(&(outData[pos]), reader->readBuffer(), toRead);
pos += toRead;
reader->move(toRead);
}
std::string result_str(outData.begin(), outData.end());
std::string orig_str;
launcherAtom.SerializeToString(&orig_str);
EXPECT_EQ(orig_str, result_str);
}
TEST(LogEventTest, TestWriteExperimentIdsToProto) {
std::vector<int64_t> expIds;
expIds.push_back(5038);
std::vector<uint8_t> proto;
writeExperimentIdsToProto(expIds, &proto);
EXPECT_EQ(proto.size(), 3);
// Proto wire format for field ID 1, varint
EXPECT_EQ(proto[0], 0x08);
// varint of 5038, 2 bytes long
EXPECT_EQ(proto[1], 0xae);
EXPECT_EQ(proto[2], 0x27);
}
#endif // NEW_ENCODING_SCHEME
} // namespace statsd
} // namespace os
} // namespace android

File diff suppressed because it is too large Load Diff

View File

@@ -39,34 +39,35 @@ using android::util::ProtoReader;
const string kApp1 = "app1.sharing.1";
const string kApp2 = "app2.sharing.1";
TEST(UidMapTest, TestIsolatedUID) {
sp<UidMap> m = new UidMap();
sp<StatsPullerManager> pullerManager = new StatsPullerManager();
sp<AlarmMonitor> anomalyAlarmMonitor;
sp<AlarmMonitor> subscriberAlarmMonitor;
// Construct the processor with a dummy sendBroadcast function that does nothing.
StatsLogProcessor p(m, pullerManager, anomalyAlarmMonitor, subscriberAlarmMonitor, 0,
[](const ConfigKey& key) { return true; },
[](const int&, const vector<int64_t>&) {return true;});
LogEvent addEvent(android::util::ISOLATED_UID_CHANGED, 1);
addEvent.write(100); // parent UID
addEvent.write(101); // isolated UID
addEvent.write(1); // Indicates creation.
addEvent.init();
EXPECT_EQ(101, m->getHostUidOrSelf(101));
p.OnLogEvent(&addEvent);
EXPECT_EQ(100, m->getHostUidOrSelf(101));
LogEvent removeEvent(android::util::ISOLATED_UID_CHANGED, 1);
removeEvent.write(100); // parent UID
removeEvent.write(101); // isolated UID
removeEvent.write(0); // Indicates removal.
removeEvent.init();
p.OnLogEvent(&removeEvent);
EXPECT_EQ(101, m->getHostUidOrSelf(101));
}
// TODO(b/149590301): Update this test to use new socket schema.
//TEST(UidMapTest, TestIsolatedUID) {
// sp<UidMap> m = new UidMap();
// sp<StatsPullerManager> pullerManager = new StatsPullerManager();
// sp<AlarmMonitor> anomalyAlarmMonitor;
// sp<AlarmMonitor> subscriberAlarmMonitor;
// // Construct the processor with a dummy sendBroadcast function that does nothing.
// StatsLogProcessor p(m, pullerManager, anomalyAlarmMonitor, subscriberAlarmMonitor, 0,
// [](const ConfigKey& key) { return true; },
// [](const int&, const vector<int64_t>&) {return true;});
// LogEvent addEvent(android::util::ISOLATED_UID_CHANGED, 1);
// addEvent.write(100); // parent UID
// addEvent.write(101); // isolated UID
// addEvent.write(1); // Indicates creation.
// addEvent.init();
//
// EXPECT_EQ(101, m->getHostUidOrSelf(101));
//
// p.OnLogEvent(&addEvent);
// EXPECT_EQ(100, m->getHostUidOrSelf(101));
//
// LogEvent removeEvent(android::util::ISOLATED_UID_CHANGED, 1);
// removeEvent.write(100); // parent UID
// removeEvent.write(101); // isolated UID
// removeEvent.write(0); // Indicates removal.
// removeEvent.init();
// p.OnLogEvent(&removeEvent);
// EXPECT_EQ(101, m->getHostUidOrSelf(101));
//}
TEST(UidMapTest, TestMatching) {
UidMap m;

View File

@@ -67,13 +67,14 @@ void writeAttributionNodesToEvent(LogEvent* event, const std::vector<int> &uids)
event->write(nodes); // attribution chain.
}
void makeWakeLockEvent(
LogEvent* event, const std::vector<int> &uids, const string& wl, int acquire) {
writeAttributionNodesToEvent(event, uids);
event->write(wl);
event->write(acquire);
event->init();
}
// TODO(b/149590301): Update this helper to use new socket schema.
//void makeWakeLockEvent(
// LogEvent* event, const std::vector<int> &uids, const string& wl, int acquire) {
// writeAttributionNodesToEvent(event, uids);
// event->write(wl);
// event->write(acquire);
// event->init();
//}
std::map<int64_t, HashableDimensionKey> getWakeLockQueryKey(
const Position position,
@@ -264,377 +265,378 @@ TEST(SimpleConditionTrackerTest, TestNonSlicedConditionNestCounting) {
EXPECT_TRUE(changedCache[0]);
}
TEST(SimpleConditionTrackerTest, TestSlicedCondition) {
std::vector<sp<ConditionTracker>> allConditions;
for (Position position :
{ Position::FIRST, Position::LAST}) {
SimplePredicate simplePredicate = getWakeLockHeldCondition(
true /*nesting*/, true /*default to false*/, true /*output slice by uid*/,
position);
string conditionName = "WL_HELD_BY_UID2";
unordered_map<int64_t, int> trackerNameIndexMap;
trackerNameIndexMap[StringToId("WAKE_LOCK_ACQUIRE")] = 0;
trackerNameIndexMap[StringToId("WAKE_LOCK_RELEASE")] = 1;
trackerNameIndexMap[StringToId("RELEASE_ALL")] = 2;
SimpleConditionTracker conditionTracker(kConfigKey, StringToId(conditionName),
0 /*condition tracker index*/, simplePredicate,
trackerNameIndexMap);
std::vector<int> uids = {111, 222, 333};
LogEvent event(1 /*tagId*/, 0 /*timestamp*/);
makeWakeLockEvent(&event, uids, "wl1", 1);
// one matched start
vector<MatchingState> matcherState;
matcherState.push_back(MatchingState::kMatched);
matcherState.push_back(MatchingState::kNotMatched);
matcherState.push_back(MatchingState::kNotMatched);
vector<sp<ConditionTracker>> allPredicates;
vector<ConditionState> conditionCache(1, ConditionState::kNotEvaluated);
vector<bool> changedCache(1, false);
conditionTracker.evaluateCondition(event, matcherState, allPredicates, conditionCache,
changedCache);
if (position == Position::FIRST ||
position == Position::LAST) {
EXPECT_EQ(1UL, conditionTracker.mSlicedConditionState.size());
} else {
EXPECT_EQ(uids.size(), conditionTracker.mSlicedConditionState.size());
}
EXPECT_TRUE(changedCache[0]);
if (position == Position::FIRST ||
position == Position::LAST) {
EXPECT_EQ(conditionTracker.getChangedToTrueDimensions(allConditions)->size(), 1u);
EXPECT_TRUE(conditionTracker.getChangedToFalseDimensions(allConditions)->empty());
} else {
EXPECT_EQ(conditionTracker.getChangedToTrueDimensions(allConditions)->size(), uids.size());
}
// Now test query
const auto queryKey = getWakeLockQueryKey(position, uids, conditionName);
conditionCache[0] = ConditionState::kNotEvaluated;
conditionTracker.isConditionMet(queryKey, allPredicates,
false,
conditionCache);
EXPECT_EQ(ConditionState::kTrue, conditionCache[0]);
// another wake lock acquired by this uid
LogEvent event2(1 /*tagId*/, 0 /*timestamp*/);
makeWakeLockEvent(&event2, uids, "wl2", 1);
matcherState.clear();
matcherState.push_back(MatchingState::kMatched);
matcherState.push_back(MatchingState::kNotMatched);
conditionCache[0] = ConditionState::kNotEvaluated;
changedCache[0] = false;
conditionTracker.evaluateCondition(event2, matcherState, allPredicates, conditionCache,
changedCache);
EXPECT_FALSE(changedCache[0]);
if (position == Position::FIRST ||
position == Position::LAST) {
EXPECT_EQ(1UL, conditionTracker.mSlicedConditionState.size());
} else {
EXPECT_EQ(uids.size(), conditionTracker.mSlicedConditionState.size());
}
EXPECT_TRUE(conditionTracker.getChangedToTrueDimensions(allConditions)->empty());
EXPECT_TRUE(conditionTracker.getChangedToFalseDimensions(allConditions)->empty());
// wake lock 1 release
LogEvent event3(1 /*tagId*/, 0 /*timestamp*/);
makeWakeLockEvent(&event3, uids, "wl1", 0); // now release it.
matcherState.clear();
matcherState.push_back(MatchingState::kNotMatched);
matcherState.push_back(MatchingState::kMatched);
conditionCache[0] = ConditionState::kNotEvaluated;
changedCache[0] = false;
conditionTracker.evaluateCondition(event3, matcherState, allPredicates, conditionCache,
changedCache);
// nothing changes, because wake lock 2 is still held for this uid
EXPECT_FALSE(changedCache[0]);
if (position == Position::FIRST ||
position == Position::LAST) {
EXPECT_EQ(1UL, conditionTracker.mSlicedConditionState.size());
} else {
EXPECT_EQ(uids.size(), conditionTracker.mSlicedConditionState.size());
}
EXPECT_TRUE(conditionTracker.getChangedToTrueDimensions(allConditions)->empty());
EXPECT_TRUE(conditionTracker.getChangedToFalseDimensions(allConditions)->empty());
LogEvent event4(1 /*tagId*/, 0 /*timestamp*/);
makeWakeLockEvent(&event4, uids, "wl2", 0); // now release it.
matcherState.clear();
matcherState.push_back(MatchingState::kNotMatched);
matcherState.push_back(MatchingState::kMatched);
conditionCache[0] = ConditionState::kNotEvaluated;
changedCache[0] = false;
conditionTracker.evaluateCondition(event4, matcherState, allPredicates, conditionCache,
changedCache);
EXPECT_EQ(0UL, conditionTracker.mSlicedConditionState.size());
EXPECT_TRUE(changedCache[0]);
if (position == Position::FIRST ||
position == Position::LAST) {
EXPECT_EQ(conditionTracker.getChangedToFalseDimensions(allConditions)->size(), 1u);
EXPECT_TRUE(conditionTracker.getChangedToTrueDimensions(allConditions)->empty());
} else {
EXPECT_EQ(conditionTracker.getChangedToFalseDimensions(allConditions)->size(), uids.size());
}
// query again
conditionCache[0] = ConditionState::kNotEvaluated;
conditionTracker.isConditionMet(queryKey, allPredicates,
false,
conditionCache);
EXPECT_EQ(ConditionState::kFalse, conditionCache[0]);
}
}
TEST(SimpleConditionTrackerTest, TestSlicedWithNoOutputDim) {
std::vector<sp<ConditionTracker>> allConditions;
SimplePredicate simplePredicate = getWakeLockHeldCondition(
true /*nesting*/, true /*default to false*/, false /*slice output by uid*/,
Position::ANY /* position */);
string conditionName = "WL_HELD";
unordered_map<int64_t, int> trackerNameIndexMap;
trackerNameIndexMap[StringToId("WAKE_LOCK_ACQUIRE")] = 0;
trackerNameIndexMap[StringToId("WAKE_LOCK_RELEASE")] = 1;
trackerNameIndexMap[StringToId("RELEASE_ALL")] = 2;
SimpleConditionTracker conditionTracker(kConfigKey, StringToId(conditionName),
0 /*condition tracker index*/, simplePredicate,
trackerNameIndexMap);
EXPECT_FALSE(conditionTracker.isSliced());
std::vector<int> uid_list1 = {111, 1111, 11111};
string uid1_wl1 = "wl1_1";
std::vector<int> uid_list2 = {222, 2222, 22222};
string uid2_wl1 = "wl2_1";
LogEvent event(1 /*tagId*/, 0 /*timestamp*/);
makeWakeLockEvent(&event, uid_list1, uid1_wl1, 1);
// one matched start for uid1
vector<MatchingState> matcherState;
matcherState.push_back(MatchingState::kMatched);
matcherState.push_back(MatchingState::kNotMatched);
matcherState.push_back(MatchingState::kNotMatched);
vector<sp<ConditionTracker>> allPredicates;
vector<ConditionState> conditionCache(1, ConditionState::kNotEvaluated);
vector<bool> changedCache(1, false);
conditionTracker.evaluateCondition(event, matcherState, allPredicates, conditionCache,
changedCache);
EXPECT_EQ(1UL, conditionTracker.mSlicedConditionState.size());
EXPECT_TRUE(changedCache[0]);
// Now test query
ConditionKey queryKey;
conditionCache[0] = ConditionState::kNotEvaluated;
conditionTracker.isConditionMet(queryKey, allPredicates,
true,
conditionCache);
EXPECT_EQ(ConditionState::kTrue, conditionCache[0]);
// another wake lock acquired by this uid
LogEvent event2(1 /*tagId*/, 0 /*timestamp*/);
makeWakeLockEvent(&event2, uid_list2, uid2_wl1, 1);
matcherState.clear();
matcherState.push_back(MatchingState::kMatched);
matcherState.push_back(MatchingState::kNotMatched);
conditionCache[0] = ConditionState::kNotEvaluated;
changedCache[0] = false;
conditionTracker.evaluateCondition(event2, matcherState, allPredicates, conditionCache,
changedCache);
EXPECT_FALSE(changedCache[0]);
// uid1 wake lock 1 release
LogEvent event3(1 /*tagId*/, 0 /*timestamp*/);
makeWakeLockEvent(&event3, uid_list1, uid1_wl1, 0); // now release it.
matcherState.clear();
matcherState.push_back(MatchingState::kNotMatched);
matcherState.push_back(MatchingState::kMatched);
conditionCache[0] = ConditionState::kNotEvaluated;
changedCache[0] = false;
conditionTracker.evaluateCondition(event3, matcherState, allPredicates, conditionCache,
changedCache);
// nothing changes, because uid2 is still holding wl.
EXPECT_FALSE(changedCache[0]);
LogEvent event4(1 /*tagId*/, 0 /*timestamp*/);
makeWakeLockEvent(&event4, uid_list2, uid2_wl1, 0); // now release it.
matcherState.clear();
matcherState.push_back(MatchingState::kNotMatched);
matcherState.push_back(MatchingState::kMatched);
conditionCache[0] = ConditionState::kNotEvaluated;
changedCache[0] = false;
conditionTracker.evaluateCondition(event4, matcherState, allPredicates, conditionCache,
changedCache);
EXPECT_EQ(0UL, conditionTracker.mSlicedConditionState.size());
EXPECT_TRUE(changedCache[0]);
// query again
conditionCache[0] = ConditionState::kNotEvaluated;
conditionTracker.isConditionMet(queryKey, allPredicates,
true,
conditionCache);
EXPECT_EQ(ConditionState::kFalse, conditionCache[0]);
}
TEST(SimpleConditionTrackerTest, TestStopAll) {
std::vector<sp<ConditionTracker>> allConditions;
for (Position position :
{ Position::FIRST, Position::LAST }) {
SimplePredicate simplePredicate = getWakeLockHeldCondition(
true /*nesting*/, true /*default to false*/, true /*output slice by uid*/,
position);
string conditionName = "WL_HELD_BY_UID3";
unordered_map<int64_t, int> trackerNameIndexMap;
trackerNameIndexMap[StringToId("WAKE_LOCK_ACQUIRE")] = 0;
trackerNameIndexMap[StringToId("WAKE_LOCK_RELEASE")] = 1;
trackerNameIndexMap[StringToId("RELEASE_ALL")] = 2;
SimpleConditionTracker conditionTracker(kConfigKey, StringToId(conditionName),
0 /*condition tracker index*/, simplePredicate,
trackerNameIndexMap);
std::vector<int> uid_list1 = {111, 1111, 11111};
std::vector<int> uid_list2 = {222, 2222, 22222};
LogEvent event(1 /*tagId*/, 0 /*timestamp*/);
makeWakeLockEvent(&event, uid_list1, "wl1", 1);
// one matched start
vector<MatchingState> matcherState;
matcherState.push_back(MatchingState::kMatched);
matcherState.push_back(MatchingState::kNotMatched);
matcherState.push_back(MatchingState::kNotMatched);
vector<sp<ConditionTracker>> allPredicates;
vector<ConditionState> conditionCache(1, ConditionState::kNotEvaluated);
vector<bool> changedCache(1, false);
conditionTracker.evaluateCondition(event, matcherState, allPredicates, conditionCache,
changedCache);
if (position == Position::FIRST ||
position == Position::LAST) {
EXPECT_EQ(1UL, conditionTracker.mSlicedConditionState.size());
} else {
EXPECT_EQ(uid_list1.size(), conditionTracker.mSlicedConditionState.size());
}
EXPECT_TRUE(changedCache[0]);
{
if (position == Position::FIRST ||
position == Position::LAST) {
EXPECT_EQ(1UL, conditionTracker.getChangedToTrueDimensions(allConditions)->size());
EXPECT_TRUE(conditionTracker.getChangedToFalseDimensions(allConditions)->empty());
} else {
EXPECT_EQ(uid_list1.size(), conditionTracker.getChangedToTrueDimensions(allConditions)->size());
EXPECT_TRUE(conditionTracker.getChangedToFalseDimensions(allConditions)->empty());
}
}
// Now test query
const auto queryKey = getWakeLockQueryKey(position, uid_list1, conditionName);
conditionCache[0] = ConditionState::kNotEvaluated;
conditionTracker.isConditionMet(queryKey, allPredicates,
false,
conditionCache);
EXPECT_EQ(ConditionState::kTrue, conditionCache[0]);
// another wake lock acquired by uid2
LogEvent event2(1 /*tagId*/, 0 /*timestamp*/);
makeWakeLockEvent(&event2, uid_list2, "wl2", 1);
matcherState.clear();
matcherState.push_back(MatchingState::kMatched);
matcherState.push_back(MatchingState::kNotMatched);
matcherState.push_back(MatchingState::kNotMatched);
conditionCache[0] = ConditionState::kNotEvaluated;
changedCache[0] = false;
conditionTracker.evaluateCondition(event2, matcherState, allPredicates, conditionCache,
changedCache);
if (position == Position::FIRST ||
position == Position::LAST) {
EXPECT_EQ(2UL, conditionTracker.mSlicedConditionState.size());
} else {
EXPECT_EQ(uid_list1.size() + uid_list2.size(),
conditionTracker.mSlicedConditionState.size());
}
EXPECT_TRUE(changedCache[0]);
{
if (position == Position::FIRST ||
position == Position::LAST) {
EXPECT_EQ(1UL, conditionTracker.getChangedToTrueDimensions(allConditions)->size());
EXPECT_TRUE(conditionTracker.getChangedToFalseDimensions(allConditions)->empty());
} else {
EXPECT_EQ(uid_list2.size(), conditionTracker.getChangedToTrueDimensions(allConditions)->size());
EXPECT_TRUE(conditionTracker.getChangedToFalseDimensions(allConditions)->empty());
}
}
// TEST QUERY
const auto queryKey2 = getWakeLockQueryKey(position, uid_list2, conditionName);
conditionCache[0] = ConditionState::kNotEvaluated;
conditionTracker.isConditionMet(queryKey, allPredicates,
false,
conditionCache);
EXPECT_EQ(ConditionState::kTrue, conditionCache[0]);
// stop all event
LogEvent event3(2 /*tagId*/, 0 /*timestamp*/);
matcherState.clear();
matcherState.push_back(MatchingState::kNotMatched);
matcherState.push_back(MatchingState::kNotMatched);
matcherState.push_back(MatchingState::kMatched);
conditionCache[0] = ConditionState::kNotEvaluated;
changedCache[0] = false;
conditionTracker.evaluateCondition(event3, matcherState, allPredicates, conditionCache,
changedCache);
EXPECT_TRUE(changedCache[0]);
EXPECT_EQ(0UL, conditionTracker.mSlicedConditionState.size());
{
if (position == Position::FIRST || position == Position::LAST) {
EXPECT_EQ(2UL, conditionTracker.getChangedToFalseDimensions(allConditions)->size());
EXPECT_TRUE(conditionTracker.getChangedToTrueDimensions(allConditions)->empty());
} else {
EXPECT_EQ(uid_list1.size() + uid_list2.size(),
conditionTracker.getChangedToFalseDimensions(allConditions)->size());
EXPECT_TRUE(conditionTracker.getChangedToTrueDimensions(allConditions)->empty());
}
}
// TEST QUERY
const auto queryKey3 = getWakeLockQueryKey(position, uid_list1, conditionName);
conditionCache[0] = ConditionState::kNotEvaluated;
conditionTracker.isConditionMet(queryKey, allPredicates,
false,
conditionCache);
EXPECT_EQ(ConditionState::kFalse, conditionCache[0]);
// TEST QUERY
const auto queryKey4 = getWakeLockQueryKey(position, uid_list2, conditionName);
conditionCache[0] = ConditionState::kNotEvaluated;
conditionTracker.isConditionMet(queryKey, allPredicates,
false,
conditionCache);
EXPECT_EQ(ConditionState::kFalse, conditionCache[0]);
}
}
// TODO(b/149590301): Update these tests to use new socket schema.
//TEST(SimpleConditionTrackerTest, TestSlicedCondition) {
// std::vector<sp<ConditionTracker>> allConditions;
// for (Position position :
// { Position::FIRST, Position::LAST}) {
//
// SimplePredicate simplePredicate = getWakeLockHeldCondition(
// true /*nesting*/, true /*default to false*/, true /*output slice by uid*/,
// position);
// string conditionName = "WL_HELD_BY_UID2";
//
// unordered_map<int64_t, int> trackerNameIndexMap;
// trackerNameIndexMap[StringToId("WAKE_LOCK_ACQUIRE")] = 0;
// trackerNameIndexMap[StringToId("WAKE_LOCK_RELEASE")] = 1;
// trackerNameIndexMap[StringToId("RELEASE_ALL")] = 2;
//
// SimpleConditionTracker conditionTracker(kConfigKey, StringToId(conditionName),
// 0 /*condition tracker index*/, simplePredicate,
// trackerNameIndexMap);
//
// std::vector<int> uids = {111, 222, 333};
//
// LogEvent event(1 /*tagId*/, 0 /*timestamp*/);
// makeWakeLockEvent(&event, uids, "wl1", 1);
//
// // one matched start
// vector<MatchingState> matcherState;
// matcherState.push_back(MatchingState::kMatched);
// matcherState.push_back(MatchingState::kNotMatched);
// matcherState.push_back(MatchingState::kNotMatched);
// vector<sp<ConditionTracker>> allPredicates;
// vector<ConditionState> conditionCache(1, ConditionState::kNotEvaluated);
// vector<bool> changedCache(1, false);
//
// conditionTracker.evaluateCondition(event, matcherState, allPredicates, conditionCache,
// changedCache);
//
// if (position == Position::FIRST ||
// position == Position::LAST) {
// EXPECT_EQ(1UL, conditionTracker.mSlicedConditionState.size());
// } else {
// EXPECT_EQ(uids.size(), conditionTracker.mSlicedConditionState.size());
// }
// EXPECT_TRUE(changedCache[0]);
// if (position == Position::FIRST ||
// position == Position::LAST) {
// EXPECT_EQ(conditionTracker.getChangedToTrueDimensions(allConditions)->size(), 1u);
// EXPECT_TRUE(conditionTracker.getChangedToFalseDimensions(allConditions)->empty());
// } else {
// EXPECT_EQ(conditionTracker.getChangedToTrueDimensions(allConditions)->size(), uids.size());
// }
//
// // Now test query
// const auto queryKey = getWakeLockQueryKey(position, uids, conditionName);
// conditionCache[0] = ConditionState::kNotEvaluated;
//
// conditionTracker.isConditionMet(queryKey, allPredicates,
// false,
// conditionCache);
// EXPECT_EQ(ConditionState::kTrue, conditionCache[0]);
//
// // another wake lock acquired by this uid
// LogEvent event2(1 /*tagId*/, 0 /*timestamp*/);
// makeWakeLockEvent(&event2, uids, "wl2", 1);
// matcherState.clear();
// matcherState.push_back(MatchingState::kMatched);
// matcherState.push_back(MatchingState::kNotMatched);
// conditionCache[0] = ConditionState::kNotEvaluated;
// changedCache[0] = false;
// conditionTracker.evaluateCondition(event2, matcherState, allPredicates, conditionCache,
// changedCache);
// EXPECT_FALSE(changedCache[0]);
// if (position == Position::FIRST ||
// position == Position::LAST) {
// EXPECT_EQ(1UL, conditionTracker.mSlicedConditionState.size());
// } else {
// EXPECT_EQ(uids.size(), conditionTracker.mSlicedConditionState.size());
// }
// EXPECT_TRUE(conditionTracker.getChangedToTrueDimensions(allConditions)->empty());
// EXPECT_TRUE(conditionTracker.getChangedToFalseDimensions(allConditions)->empty());
//
//
// // wake lock 1 release
// LogEvent event3(1 /*tagId*/, 0 /*timestamp*/);
// makeWakeLockEvent(&event3, uids, "wl1", 0); // now release it.
// matcherState.clear();
// matcherState.push_back(MatchingState::kNotMatched);
// matcherState.push_back(MatchingState::kMatched);
// conditionCache[0] = ConditionState::kNotEvaluated;
// changedCache[0] = false;
// conditionTracker.evaluateCondition(event3, matcherState, allPredicates, conditionCache,
// changedCache);
// // nothing changes, because wake lock 2 is still held for this uid
// EXPECT_FALSE(changedCache[0]);
// if (position == Position::FIRST ||
// position == Position::LAST) {
// EXPECT_EQ(1UL, conditionTracker.mSlicedConditionState.size());
// } else {
// EXPECT_EQ(uids.size(), conditionTracker.mSlicedConditionState.size());
// }
// EXPECT_TRUE(conditionTracker.getChangedToTrueDimensions(allConditions)->empty());
// EXPECT_TRUE(conditionTracker.getChangedToFalseDimensions(allConditions)->empty());
//
// LogEvent event4(1 /*tagId*/, 0 /*timestamp*/);
// makeWakeLockEvent(&event4, uids, "wl2", 0); // now release it.
// matcherState.clear();
// matcherState.push_back(MatchingState::kNotMatched);
// matcherState.push_back(MatchingState::kMatched);
// conditionCache[0] = ConditionState::kNotEvaluated;
// changedCache[0] = false;
// conditionTracker.evaluateCondition(event4, matcherState, allPredicates, conditionCache,
// changedCache);
// EXPECT_EQ(0UL, conditionTracker.mSlicedConditionState.size());
// EXPECT_TRUE(changedCache[0]);
// if (position == Position::FIRST ||
// position == Position::LAST) {
// EXPECT_EQ(conditionTracker.getChangedToFalseDimensions(allConditions)->size(), 1u);
// EXPECT_TRUE(conditionTracker.getChangedToTrueDimensions(allConditions)->empty());
// } else {
// EXPECT_EQ(conditionTracker.getChangedToFalseDimensions(allConditions)->size(), uids.size());
// }
//
// // query again
// conditionCache[0] = ConditionState::kNotEvaluated;
// conditionTracker.isConditionMet(queryKey, allPredicates,
// false,
// conditionCache);
// EXPECT_EQ(ConditionState::kFalse, conditionCache[0]);
// }
//
//}
//
//TEST(SimpleConditionTrackerTest, TestSlicedWithNoOutputDim) {
// std::vector<sp<ConditionTracker>> allConditions;
//
// SimplePredicate simplePredicate = getWakeLockHeldCondition(
// true /*nesting*/, true /*default to false*/, false /*slice output by uid*/,
// Position::ANY /* position */);
// string conditionName = "WL_HELD";
//
// unordered_map<int64_t, int> trackerNameIndexMap;
// trackerNameIndexMap[StringToId("WAKE_LOCK_ACQUIRE")] = 0;
// trackerNameIndexMap[StringToId("WAKE_LOCK_RELEASE")] = 1;
// trackerNameIndexMap[StringToId("RELEASE_ALL")] = 2;
//
// SimpleConditionTracker conditionTracker(kConfigKey, StringToId(conditionName),
// 0 /*condition tracker index*/, simplePredicate,
// trackerNameIndexMap);
//
// EXPECT_FALSE(conditionTracker.isSliced());
//
// std::vector<int> uid_list1 = {111, 1111, 11111};
// string uid1_wl1 = "wl1_1";
// std::vector<int> uid_list2 = {222, 2222, 22222};
// string uid2_wl1 = "wl2_1";
//
// LogEvent event(1 /*tagId*/, 0 /*timestamp*/);
// makeWakeLockEvent(&event, uid_list1, uid1_wl1, 1);
//
// // one matched start for uid1
// vector<MatchingState> matcherState;
// matcherState.push_back(MatchingState::kMatched);
// matcherState.push_back(MatchingState::kNotMatched);
// matcherState.push_back(MatchingState::kNotMatched);
// vector<sp<ConditionTracker>> allPredicates;
// vector<ConditionState> conditionCache(1, ConditionState::kNotEvaluated);
// vector<bool> changedCache(1, false);
//
// conditionTracker.evaluateCondition(event, matcherState, allPredicates, conditionCache,
// changedCache);
//
// EXPECT_EQ(1UL, conditionTracker.mSlicedConditionState.size());
// EXPECT_TRUE(changedCache[0]);
//
// // Now test query
// ConditionKey queryKey;
// conditionCache[0] = ConditionState::kNotEvaluated;
//
// conditionTracker.isConditionMet(queryKey, allPredicates,
// true,
// conditionCache);
// EXPECT_EQ(ConditionState::kTrue, conditionCache[0]);
//
// // another wake lock acquired by this uid
// LogEvent event2(1 /*tagId*/, 0 /*timestamp*/);
// makeWakeLockEvent(&event2, uid_list2, uid2_wl1, 1);
// matcherState.clear();
// matcherState.push_back(MatchingState::kMatched);
// matcherState.push_back(MatchingState::kNotMatched);
// conditionCache[0] = ConditionState::kNotEvaluated;
// changedCache[0] = false;
// conditionTracker.evaluateCondition(event2, matcherState, allPredicates, conditionCache,
// changedCache);
// EXPECT_FALSE(changedCache[0]);
//
// // uid1 wake lock 1 release
// LogEvent event3(1 /*tagId*/, 0 /*timestamp*/);
// makeWakeLockEvent(&event3, uid_list1, uid1_wl1, 0); // now release it.
// matcherState.clear();
// matcherState.push_back(MatchingState::kNotMatched);
// matcherState.push_back(MatchingState::kMatched);
// conditionCache[0] = ConditionState::kNotEvaluated;
// changedCache[0] = false;
// conditionTracker.evaluateCondition(event3, matcherState, allPredicates, conditionCache,
// changedCache);
// // nothing changes, because uid2 is still holding wl.
// EXPECT_FALSE(changedCache[0]);
//
// LogEvent event4(1 /*tagId*/, 0 /*timestamp*/);
// makeWakeLockEvent(&event4, uid_list2, uid2_wl1, 0); // now release it.
// matcherState.clear();
// matcherState.push_back(MatchingState::kNotMatched);
// matcherState.push_back(MatchingState::kMatched);
// conditionCache[0] = ConditionState::kNotEvaluated;
// changedCache[0] = false;
// conditionTracker.evaluateCondition(event4, matcherState, allPredicates, conditionCache,
// changedCache);
// EXPECT_EQ(0UL, conditionTracker.mSlicedConditionState.size());
// EXPECT_TRUE(changedCache[0]);
//
// // query again
// conditionCache[0] = ConditionState::kNotEvaluated;
// conditionTracker.isConditionMet(queryKey, allPredicates,
// true,
// conditionCache);
// EXPECT_EQ(ConditionState::kFalse, conditionCache[0]);
//}
//
//TEST(SimpleConditionTrackerTest, TestStopAll) {
// std::vector<sp<ConditionTracker>> allConditions;
// for (Position position :
// { Position::FIRST, Position::LAST }) {
// SimplePredicate simplePredicate = getWakeLockHeldCondition(
// true /*nesting*/, true /*default to false*/, true /*output slice by uid*/,
// position);
// string conditionName = "WL_HELD_BY_UID3";
//
// unordered_map<int64_t, int> trackerNameIndexMap;
// trackerNameIndexMap[StringToId("WAKE_LOCK_ACQUIRE")] = 0;
// trackerNameIndexMap[StringToId("WAKE_LOCK_RELEASE")] = 1;
// trackerNameIndexMap[StringToId("RELEASE_ALL")] = 2;
//
// SimpleConditionTracker conditionTracker(kConfigKey, StringToId(conditionName),
// 0 /*condition tracker index*/, simplePredicate,
// trackerNameIndexMap);
//
// std::vector<int> uid_list1 = {111, 1111, 11111};
// std::vector<int> uid_list2 = {222, 2222, 22222};
//
// LogEvent event(1 /*tagId*/, 0 /*timestamp*/);
// makeWakeLockEvent(&event, uid_list1, "wl1", 1);
//
// // one matched start
// vector<MatchingState> matcherState;
// matcherState.push_back(MatchingState::kMatched);
// matcherState.push_back(MatchingState::kNotMatched);
// matcherState.push_back(MatchingState::kNotMatched);
// vector<sp<ConditionTracker>> allPredicates;
// vector<ConditionState> conditionCache(1, ConditionState::kNotEvaluated);
// vector<bool> changedCache(1, false);
//
// conditionTracker.evaluateCondition(event, matcherState, allPredicates, conditionCache,
// changedCache);
// if (position == Position::FIRST ||
// position == Position::LAST) {
// EXPECT_EQ(1UL, conditionTracker.mSlicedConditionState.size());
// } else {
// EXPECT_EQ(uid_list1.size(), conditionTracker.mSlicedConditionState.size());
// }
// EXPECT_TRUE(changedCache[0]);
// {
// if (position == Position::FIRST ||
// position == Position::LAST) {
// EXPECT_EQ(1UL, conditionTracker.getChangedToTrueDimensions(allConditions)->size());
// EXPECT_TRUE(conditionTracker.getChangedToFalseDimensions(allConditions)->empty());
// } else {
// EXPECT_EQ(uid_list1.size(), conditionTracker.getChangedToTrueDimensions(allConditions)->size());
// EXPECT_TRUE(conditionTracker.getChangedToFalseDimensions(allConditions)->empty());
// }
// }
//
// // Now test query
// const auto queryKey = getWakeLockQueryKey(position, uid_list1, conditionName);
// conditionCache[0] = ConditionState::kNotEvaluated;
//
// conditionTracker.isConditionMet(queryKey, allPredicates,
// false,
// conditionCache);
// EXPECT_EQ(ConditionState::kTrue, conditionCache[0]);
//
// // another wake lock acquired by uid2
// LogEvent event2(1 /*tagId*/, 0 /*timestamp*/);
// makeWakeLockEvent(&event2, uid_list2, "wl2", 1);
// matcherState.clear();
// matcherState.push_back(MatchingState::kMatched);
// matcherState.push_back(MatchingState::kNotMatched);
// matcherState.push_back(MatchingState::kNotMatched);
// conditionCache[0] = ConditionState::kNotEvaluated;
// changedCache[0] = false;
// conditionTracker.evaluateCondition(event2, matcherState, allPredicates, conditionCache,
// changedCache);
// if (position == Position::FIRST ||
// position == Position::LAST) {
// EXPECT_EQ(2UL, conditionTracker.mSlicedConditionState.size());
// } else {
// EXPECT_EQ(uid_list1.size() + uid_list2.size(),
// conditionTracker.mSlicedConditionState.size());
// }
// EXPECT_TRUE(changedCache[0]);
// {
// if (position == Position::FIRST ||
// position == Position::LAST) {
// EXPECT_EQ(1UL, conditionTracker.getChangedToTrueDimensions(allConditions)->size());
// EXPECT_TRUE(conditionTracker.getChangedToFalseDimensions(allConditions)->empty());
// } else {
// EXPECT_EQ(uid_list2.size(), conditionTracker.getChangedToTrueDimensions(allConditions)->size());
// EXPECT_TRUE(conditionTracker.getChangedToFalseDimensions(allConditions)->empty());
// }
// }
//
//
// // TEST QUERY
// const auto queryKey2 = getWakeLockQueryKey(position, uid_list2, conditionName);
// conditionCache[0] = ConditionState::kNotEvaluated;
// conditionTracker.isConditionMet(queryKey, allPredicates,
// false,
// conditionCache);
//
// EXPECT_EQ(ConditionState::kTrue, conditionCache[0]);
//
//
// // stop all event
// LogEvent event3(2 /*tagId*/, 0 /*timestamp*/);
// matcherState.clear();
// matcherState.push_back(MatchingState::kNotMatched);
// matcherState.push_back(MatchingState::kNotMatched);
// matcherState.push_back(MatchingState::kMatched);
//
// conditionCache[0] = ConditionState::kNotEvaluated;
// changedCache[0] = false;
// conditionTracker.evaluateCondition(event3, matcherState, allPredicates, conditionCache,
// changedCache);
// EXPECT_TRUE(changedCache[0]);
// EXPECT_EQ(0UL, conditionTracker.mSlicedConditionState.size());
// {
// if (position == Position::FIRST || position == Position::LAST) {
// EXPECT_EQ(2UL, conditionTracker.getChangedToFalseDimensions(allConditions)->size());
// EXPECT_TRUE(conditionTracker.getChangedToTrueDimensions(allConditions)->empty());
// } else {
// EXPECT_EQ(uid_list1.size() + uid_list2.size(),
// conditionTracker.getChangedToFalseDimensions(allConditions)->size());
// EXPECT_TRUE(conditionTracker.getChangedToTrueDimensions(allConditions)->empty());
// }
// }
//
// // TEST QUERY
// const auto queryKey3 = getWakeLockQueryKey(position, uid_list1, conditionName);
// conditionCache[0] = ConditionState::kNotEvaluated;
// conditionTracker.isConditionMet(queryKey, allPredicates,
// false,
// conditionCache);
// EXPECT_EQ(ConditionState::kFalse, conditionCache[0]);
//
// // TEST QUERY
// const auto queryKey4 = getWakeLockQueryKey(position, uid_list2, conditionName);
// conditionCache[0] = ConditionState::kNotEvaluated;
// conditionTracker.isConditionMet(queryKey, allPredicates,
// false,
// conditionCache);
// EXPECT_EQ(ConditionState::kFalse, conditionCache[0]);
// }
//}
} // namespace statsd
} // namespace os

View File

@@ -44,65 +44,66 @@ SimplePredicate getUidProcStatePredicate() {
return simplePredicate;
}
void makeUidProcStateEvent(int32_t uid, int32_t state, LogEvent* event) {
event->write(uid);
event->write(state);
event->init();
}
TEST(StateConditionTrackerTest, TestStateChange) {
int uid1 = 111;
int uid2 = 222;
int state1 = 1001;
int state2 = 1002;
unordered_map<int64_t, int> trackerNameIndexMap;
trackerNameIndexMap[StringToId("UidProcState")] = 0;
vector<Matcher> primaryFields;
primaryFields.push_back(getSimpleMatcher(kUidProcTag, 1));
StateConditionTracker tracker(ConfigKey(12, 123), 123, 0, getUidProcStatePredicate(),
trackerNameIndexMap, primaryFields);
LogEvent event(kUidProcTag, 0 /*timestamp*/);
makeUidProcStateEvent(uid1, state1, &event);
vector<MatchingState> matcherState;
matcherState.push_back(MatchingState::kMatched);
vector<sp<ConditionTracker>> allPredicates;
vector<ConditionState> conditionCache(1, ConditionState::kNotEvaluated);
vector<bool> changedCache(1, false);
tracker.evaluateCondition(event, matcherState, allPredicates, conditionCache, changedCache);
EXPECT_EQ(1ULL, tracker.mLastChangedToTrueDimensions.size());
EXPECT_EQ(0ULL, tracker.mLastChangedToFalseDimensions.size());
EXPECT_TRUE(changedCache[0]);
changedCache[0] = false;
conditionCache[0] = ConditionState::kNotEvaluated;
tracker.evaluateCondition(event, matcherState, allPredicates, conditionCache, changedCache);
EXPECT_EQ(0ULL, tracker.mLastChangedToTrueDimensions.size());
EXPECT_EQ(0ULL, tracker.mLastChangedToFalseDimensions.size());
EXPECT_FALSE(changedCache[0]);
LogEvent event2(kUidProcTag, 0 /*timestamp*/);
makeUidProcStateEvent(uid1, state2, &event2);
changedCache[0] = false;
conditionCache[0] = ConditionState::kNotEvaluated;
tracker.evaluateCondition(event2, matcherState, allPredicates, conditionCache, changedCache);
EXPECT_EQ(1ULL, tracker.mLastChangedToTrueDimensions.size());
EXPECT_EQ(1ULL, tracker.mLastChangedToFalseDimensions.size());
EXPECT_TRUE(changedCache[0]);
LogEvent event3(kUidProcTag, 0 /*timestamp*/);
makeUidProcStateEvent(uid2, state1, &event3);
changedCache[0] = false;
conditionCache[0] = ConditionState::kNotEvaluated;
tracker.evaluateCondition(event3, matcherState, allPredicates, conditionCache, changedCache);
EXPECT_EQ(1ULL, tracker.mLastChangedToTrueDimensions.size());
EXPECT_EQ(0ULL, tracker.mLastChangedToFalseDimensions.size());
EXPECT_TRUE(changedCache[0]);
}
// TODO(b/149590301): Update these tests to use new socket schema.
//void makeUidProcStateEvent(int32_t uid, int32_t state, LogEvent* event) {
// event->write(uid);
// event->write(state);
// event->init();
//}
//
//TEST(StateConditionTrackerTest, TestStateChange) {
// int uid1 = 111;
// int uid2 = 222;
//
// int state1 = 1001;
// int state2 = 1002;
// unordered_map<int64_t, int> trackerNameIndexMap;
// trackerNameIndexMap[StringToId("UidProcState")] = 0;
// vector<Matcher> primaryFields;
// primaryFields.push_back(getSimpleMatcher(kUidProcTag, 1));
// StateConditionTracker tracker(ConfigKey(12, 123), 123, 0, getUidProcStatePredicate(),
// trackerNameIndexMap, primaryFields);
//
// LogEvent event(kUidProcTag, 0 /*timestamp*/);
// makeUidProcStateEvent(uid1, state1, &event);
//
// vector<MatchingState> matcherState;
// matcherState.push_back(MatchingState::kMatched);
// vector<sp<ConditionTracker>> allPredicates;
// vector<ConditionState> conditionCache(1, ConditionState::kNotEvaluated);
// vector<bool> changedCache(1, false);
//
// tracker.evaluateCondition(event, matcherState, allPredicates, conditionCache, changedCache);
// EXPECT_EQ(1ULL, tracker.mLastChangedToTrueDimensions.size());
// EXPECT_EQ(0ULL, tracker.mLastChangedToFalseDimensions.size());
// EXPECT_TRUE(changedCache[0]);
//
// changedCache[0] = false;
// conditionCache[0] = ConditionState::kNotEvaluated;
// tracker.evaluateCondition(event, matcherState, allPredicates, conditionCache, changedCache);
// EXPECT_EQ(0ULL, tracker.mLastChangedToTrueDimensions.size());
// EXPECT_EQ(0ULL, tracker.mLastChangedToFalseDimensions.size());
// EXPECT_FALSE(changedCache[0]);
//
// LogEvent event2(kUidProcTag, 0 /*timestamp*/);
// makeUidProcStateEvent(uid1, state2, &event2);
//
// changedCache[0] = false;
// conditionCache[0] = ConditionState::kNotEvaluated;
// tracker.evaluateCondition(event2, matcherState, allPredicates, conditionCache, changedCache);
// EXPECT_EQ(1ULL, tracker.mLastChangedToTrueDimensions.size());
// EXPECT_EQ(1ULL, tracker.mLastChangedToFalseDimensions.size());
// EXPECT_TRUE(changedCache[0]);
//
// LogEvent event3(kUidProcTag, 0 /*timestamp*/);
// makeUidProcStateEvent(uid2, state1, &event3);
// changedCache[0] = false;
// conditionCache[0] = ConditionState::kNotEvaluated;
// tracker.evaluateCondition(event3, matcherState, allPredicates, conditionCache, changedCache);
// EXPECT_EQ(1ULL, tracker.mLastChangedToTrueDimensions.size());
// EXPECT_EQ(0ULL, tracker.mLastChangedToFalseDimensions.size());
// EXPECT_TRUE(changedCache[0]);
//}
} // namespace statsd
} // namespace os

View File

@@ -53,184 +53,185 @@ StatsdConfig CreateStatsdConfig(int num_buckets, int threshold) {
} // namespace
TEST(AnomalyDetectionE2eTest, TestSlicedCountMetric_single_bucket) {
const int num_buckets = 1;
const int threshold = 3;
auto config = CreateStatsdConfig(num_buckets, threshold);
const uint64_t alert_id = config.alert(0).id();
const uint32_t refractory_period_sec = config.alert(0).refractory_period_secs();
int64_t bucketStartTimeNs = 10000000000;
int64_t bucketSizeNs =
TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000000;
ConfigKey cfgKey;
auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
EXPECT_EQ(1u, processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers.size());
sp<AnomalyTracker> anomalyTracker =
processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers[0];
std::vector<AttributionNodeInternal> attributions1 = {CreateAttribution(111, "App1")};
std::vector<AttributionNodeInternal> attributions2 = {
CreateAttribution(111, "App1"), CreateAttribution(222, "GMSCoreModule1")};
std::vector<AttributionNodeInternal> attributions3 = {
CreateAttribution(111, "App1"), CreateAttribution(333, "App3")};
std::vector<AttributionNodeInternal> attributions4 = {
CreateAttribution(222, "GMSCoreModule1"), CreateAttribution(333, "App3")};
std::vector<AttributionNodeInternal> attributions5 = {
CreateAttribution(222, "GMSCoreModule1") };
FieldValue fieldValue1(Field(android::util::WAKELOCK_STATE_CHANGED, (int32_t)0x02010101),
Value((int32_t)111));
HashableDimensionKey whatKey1({fieldValue1});
MetricDimensionKey dimensionKey1(whatKey1, DEFAULT_DIMENSION_KEY);
FieldValue fieldValue2(Field(android::util::WAKELOCK_STATE_CHANGED, (int32_t)0x02010101),
Value((int32_t)222));
HashableDimensionKey whatKey2({fieldValue2});
MetricDimensionKey dimensionKey2(whatKey2, DEFAULT_DIMENSION_KEY);
auto event = CreateAcquireWakelockEvent(attributions1, "wl1", bucketStartTimeNs + 2);
processor->OnLogEvent(event.get());
EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
event = CreateAcquireWakelockEvent(attributions4, "wl2", bucketStartTimeNs + 2);
processor->OnLogEvent(event.get());
EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey2));
event = CreateAcquireWakelockEvent(attributions2, "wl1", bucketStartTimeNs + 3);
processor->OnLogEvent(event.get());
EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
event = CreateAcquireWakelockEvent(attributions5, "wl2", bucketStartTimeNs + 3);
processor->OnLogEvent(event.get());
EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey2));
event = CreateAcquireWakelockEvent(attributions3, "wl1", bucketStartTimeNs + 4);
processor->OnLogEvent(event.get());
EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
event = CreateAcquireWakelockEvent(attributions5, "wl2", bucketStartTimeNs + 4);
processor->OnLogEvent(event.get());
EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey2));
// Fired alarm and refractory period end timestamp updated.
event = CreateAcquireWakelockEvent(attributions1, "wl1", bucketStartTimeNs + 5);
processor->OnLogEvent(event.get());
EXPECT_EQ(refractory_period_sec + bucketStartTimeNs / NS_PER_SEC + 1,
anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
event = CreateAcquireWakelockEvent(attributions1, "wl1", bucketStartTimeNs + 100);
processor->OnLogEvent(event.get());
EXPECT_EQ(refractory_period_sec + bucketStartTimeNs / NS_PER_SEC + 1,
anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
event = CreateAcquireWakelockEvent(attributions1, "wl1", bucketStartTimeNs + bucketSizeNs - 1);
processor->OnLogEvent(event.get());
EXPECT_EQ(refractory_period_sec + (bucketStartTimeNs + bucketSizeNs - 1) / NS_PER_SEC + 1,
anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
event = CreateAcquireWakelockEvent(attributions1, "wl1", bucketStartTimeNs + bucketSizeNs + 1);
processor->OnLogEvent(event.get());
EXPECT_EQ(refractory_period_sec + (bucketStartTimeNs + bucketSizeNs - 1) / NS_PER_SEC + 1,
anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
event = CreateAcquireWakelockEvent(attributions4, "wl2", bucketStartTimeNs + bucketSizeNs + 1);
processor->OnLogEvent(event.get());
EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey2));
event = CreateAcquireWakelockEvent(attributions5, "wl2", bucketStartTimeNs + bucketSizeNs + 2);
processor->OnLogEvent(event.get());
EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey2));
event = CreateAcquireWakelockEvent(attributions5, "wl2", bucketStartTimeNs + bucketSizeNs + 3);
processor->OnLogEvent(event.get());
EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey2));
event = CreateAcquireWakelockEvent(attributions5, "wl2", bucketStartTimeNs + bucketSizeNs + 4);
processor->OnLogEvent(event.get());
EXPECT_EQ(refractory_period_sec + (bucketStartTimeNs + bucketSizeNs + 4) / NS_PER_SEC + 1,
anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey2));
}
TEST(AnomalyDetectionE2eTest, TestSlicedCountMetric_multiple_buckets) {
const int num_buckets = 3;
const int threshold = 3;
auto config = CreateStatsdConfig(num_buckets, threshold);
const uint64_t alert_id = config.alert(0).id();
const uint32_t refractory_period_sec = config.alert(0).refractory_period_secs();
int64_t bucketStartTimeNs = 10000000000;
int64_t bucketSizeNs =
TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000000;
ConfigKey cfgKey;
auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
EXPECT_EQ(1u, processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers.size());
sp<AnomalyTracker> anomalyTracker =
processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers[0];
std::vector<AttributionNodeInternal> attributions1 = {CreateAttribution(111, "App1")};
std::vector<AttributionNodeInternal> attributions2 = {
CreateAttribution(111, "App1"), CreateAttribution(222, "GMSCoreModule1")};
std::vector<AttributionNodeInternal> attributions3 = {
CreateAttribution(111, "App1"), CreateAttribution(333, "App3")};
std::vector<AttributionNodeInternal> attributions4 = {
CreateAttribution(222, "GMSCoreModule1"), CreateAttribution(333, "App3")};
std::vector<AttributionNodeInternal> attributions5 = {
CreateAttribution(222, "GMSCoreModule1") };
FieldValue fieldValue1(Field(android::util::WAKELOCK_STATE_CHANGED, (int32_t)0x02010101),
Value((int32_t)111));
HashableDimensionKey whatKey1({fieldValue1});
MetricDimensionKey dimensionKey1(whatKey1, DEFAULT_DIMENSION_KEY);
FieldValue fieldValue2(Field(android::util::WAKELOCK_STATE_CHANGED, (int32_t)0x02010101),
Value((int32_t)222));
HashableDimensionKey whatKey2({fieldValue2});
MetricDimensionKey dimensionKey2(whatKey2, DEFAULT_DIMENSION_KEY);
auto event = CreateAcquireWakelockEvent(attributions1, "wl1", bucketStartTimeNs + 2);
processor->OnLogEvent(event.get());
EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
event = CreateAcquireWakelockEvent(attributions2, "wl1", bucketStartTimeNs + 3);
processor->OnLogEvent(event.get());
EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
// Fired alarm and refractory period end timestamp updated.
event = CreateAcquireWakelockEvent(attributions1, "wl1", bucketStartTimeNs + 4);
processor->OnLogEvent(event.get());
EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
event = CreateAcquireWakelockEvent(attributions1, "wl1", bucketStartTimeNs + bucketSizeNs + 1);
processor->OnLogEvent(event.get());
EXPECT_EQ(refractory_period_sec + (bucketStartTimeNs + bucketSizeNs + 1) / NS_PER_SEC + 1,
anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
event = CreateAcquireWakelockEvent(attributions2, "wl1", bucketStartTimeNs + bucketSizeNs + 2);
processor->OnLogEvent(event.get());
EXPECT_EQ(refractory_period_sec + (bucketStartTimeNs + bucketSizeNs + 1) / NS_PER_SEC + 1,
anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
event = CreateAcquireWakelockEvent(
attributions2, "wl1", bucketStartTimeNs + 3 * bucketSizeNs + 1);
processor->OnLogEvent(event.get());
EXPECT_EQ(refractory_period_sec + (bucketStartTimeNs + bucketSizeNs + 1) / NS_PER_SEC + 1,
anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
event = CreateAcquireWakelockEvent(
attributions2, "wl1", bucketStartTimeNs + 3 * bucketSizeNs + 2);
processor->OnLogEvent(event.get());
EXPECT_EQ(refractory_period_sec + (bucketStartTimeNs + 3 * bucketSizeNs + 2) / NS_PER_SEC + 1,
anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
}
// TODO(b/149590301): Update these tests to use new socket schema.
//TEST(AnomalyDetectionE2eTest, TestSlicedCountMetric_single_bucket) {
// const int num_buckets = 1;
// const int threshold = 3;
// auto config = CreateStatsdConfig(num_buckets, threshold);
// const uint64_t alert_id = config.alert(0).id();
// const uint32_t refractory_period_sec = config.alert(0).refractory_period_secs();
//
// int64_t bucketStartTimeNs = 10000000000;
// int64_t bucketSizeNs =
// TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000000;
//
// ConfigKey cfgKey;
// auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
// EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
// EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
// EXPECT_EQ(1u, processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers.size());
//
// sp<AnomalyTracker> anomalyTracker =
// processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers[0];
//
// std::vector<AttributionNodeInternal> attributions1 = {CreateAttribution(111, "App1")};
// std::vector<AttributionNodeInternal> attributions2 = {
// CreateAttribution(111, "App1"), CreateAttribution(222, "GMSCoreModule1")};
// std::vector<AttributionNodeInternal> attributions3 = {
// CreateAttribution(111, "App1"), CreateAttribution(333, "App3")};
// std::vector<AttributionNodeInternal> attributions4 = {
// CreateAttribution(222, "GMSCoreModule1"), CreateAttribution(333, "App3")};
// std::vector<AttributionNodeInternal> attributions5 = {
// CreateAttribution(222, "GMSCoreModule1") };
//
// FieldValue fieldValue1(Field(android::util::WAKELOCK_STATE_CHANGED, (int32_t)0x02010101),
// Value((int32_t)111));
// HashableDimensionKey whatKey1({fieldValue1});
// MetricDimensionKey dimensionKey1(whatKey1, DEFAULT_DIMENSION_KEY);
//
// FieldValue fieldValue2(Field(android::util::WAKELOCK_STATE_CHANGED, (int32_t)0x02010101),
// Value((int32_t)222));
// HashableDimensionKey whatKey2({fieldValue2});
// MetricDimensionKey dimensionKey2(whatKey2, DEFAULT_DIMENSION_KEY);
//
// auto event = CreateAcquireWakelockEvent(attributions1, "wl1", bucketStartTimeNs + 2);
// processor->OnLogEvent(event.get());
// EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
//
// event = CreateAcquireWakelockEvent(attributions4, "wl2", bucketStartTimeNs + 2);
// processor->OnLogEvent(event.get());
// EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey2));
//
// event = CreateAcquireWakelockEvent(attributions2, "wl1", bucketStartTimeNs + 3);
// processor->OnLogEvent(event.get());
// EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
//
// event = CreateAcquireWakelockEvent(attributions5, "wl2", bucketStartTimeNs + 3);
// processor->OnLogEvent(event.get());
// EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey2));
//
// event = CreateAcquireWakelockEvent(attributions3, "wl1", bucketStartTimeNs + 4);
// processor->OnLogEvent(event.get());
// EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
//
// event = CreateAcquireWakelockEvent(attributions5, "wl2", bucketStartTimeNs + 4);
// processor->OnLogEvent(event.get());
// EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey2));
//
// // Fired alarm and refractory period end timestamp updated.
// event = CreateAcquireWakelockEvent(attributions1, "wl1", bucketStartTimeNs + 5);
// processor->OnLogEvent(event.get());
// EXPECT_EQ(refractory_period_sec + bucketStartTimeNs / NS_PER_SEC + 1,
// anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
//
// event = CreateAcquireWakelockEvent(attributions1, "wl1", bucketStartTimeNs + 100);
// processor->OnLogEvent(event.get());
// EXPECT_EQ(refractory_period_sec + bucketStartTimeNs / NS_PER_SEC + 1,
// anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
//
// event = CreateAcquireWakelockEvent(attributions1, "wl1", bucketStartTimeNs + bucketSizeNs - 1);
// processor->OnLogEvent(event.get());
// EXPECT_EQ(refractory_period_sec + (bucketStartTimeNs + bucketSizeNs - 1) / NS_PER_SEC + 1,
// anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
//
// event = CreateAcquireWakelockEvent(attributions1, "wl1", bucketStartTimeNs + bucketSizeNs + 1);
// processor->OnLogEvent(event.get());
// EXPECT_EQ(refractory_period_sec + (bucketStartTimeNs + bucketSizeNs - 1) / NS_PER_SEC + 1,
// anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
//
// event = CreateAcquireWakelockEvent(attributions4, "wl2", bucketStartTimeNs + bucketSizeNs + 1);
// processor->OnLogEvent(event.get());
// EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey2));
//
// event = CreateAcquireWakelockEvent(attributions5, "wl2", bucketStartTimeNs + bucketSizeNs + 2);
// processor->OnLogEvent(event.get());
// EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey2));
//
// event = CreateAcquireWakelockEvent(attributions5, "wl2", bucketStartTimeNs + bucketSizeNs + 3);
// processor->OnLogEvent(event.get());
// EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey2));
//
// event = CreateAcquireWakelockEvent(attributions5, "wl2", bucketStartTimeNs + bucketSizeNs + 4);
// processor->OnLogEvent(event.get());
// EXPECT_EQ(refractory_period_sec + (bucketStartTimeNs + bucketSizeNs + 4) / NS_PER_SEC + 1,
// anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey2));
//}
//
//TEST(AnomalyDetectionE2eTest, TestSlicedCountMetric_multiple_buckets) {
// const int num_buckets = 3;
// const int threshold = 3;
// auto config = CreateStatsdConfig(num_buckets, threshold);
// const uint64_t alert_id = config.alert(0).id();
// const uint32_t refractory_period_sec = config.alert(0).refractory_period_secs();
//
// int64_t bucketStartTimeNs = 10000000000;
// int64_t bucketSizeNs =
// TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000000;
//
// ConfigKey cfgKey;
// auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
// EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
// EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
// EXPECT_EQ(1u, processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers.size());
//
// sp<AnomalyTracker> anomalyTracker =
// processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers[0];
//
// std::vector<AttributionNodeInternal> attributions1 = {CreateAttribution(111, "App1")};
// std::vector<AttributionNodeInternal> attributions2 = {
// CreateAttribution(111, "App1"), CreateAttribution(222, "GMSCoreModule1")};
// std::vector<AttributionNodeInternal> attributions3 = {
// CreateAttribution(111, "App1"), CreateAttribution(333, "App3")};
// std::vector<AttributionNodeInternal> attributions4 = {
// CreateAttribution(222, "GMSCoreModule1"), CreateAttribution(333, "App3")};
// std::vector<AttributionNodeInternal> attributions5 = {
// CreateAttribution(222, "GMSCoreModule1") };
//
// FieldValue fieldValue1(Field(android::util::WAKELOCK_STATE_CHANGED, (int32_t)0x02010101),
// Value((int32_t)111));
// HashableDimensionKey whatKey1({fieldValue1});
// MetricDimensionKey dimensionKey1(whatKey1, DEFAULT_DIMENSION_KEY);
//
// FieldValue fieldValue2(Field(android::util::WAKELOCK_STATE_CHANGED, (int32_t)0x02010101),
// Value((int32_t)222));
// HashableDimensionKey whatKey2({fieldValue2});
// MetricDimensionKey dimensionKey2(whatKey2, DEFAULT_DIMENSION_KEY);
//
// auto event = CreateAcquireWakelockEvent(attributions1, "wl1", bucketStartTimeNs + 2);
// processor->OnLogEvent(event.get());
// EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
//
// event = CreateAcquireWakelockEvent(attributions2, "wl1", bucketStartTimeNs + 3);
// processor->OnLogEvent(event.get());
// EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
//
// // Fired alarm and refractory period end timestamp updated.
// event = CreateAcquireWakelockEvent(attributions1, "wl1", bucketStartTimeNs + 4);
// processor->OnLogEvent(event.get());
// EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
//
// event = CreateAcquireWakelockEvent(attributions1, "wl1", bucketStartTimeNs + bucketSizeNs + 1);
// processor->OnLogEvent(event.get());
// EXPECT_EQ(refractory_period_sec + (bucketStartTimeNs + bucketSizeNs + 1) / NS_PER_SEC + 1,
// anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
//
// event = CreateAcquireWakelockEvent(attributions2, "wl1", bucketStartTimeNs + bucketSizeNs + 2);
// processor->OnLogEvent(event.get());
// EXPECT_EQ(refractory_period_sec + (bucketStartTimeNs + bucketSizeNs + 1) / NS_PER_SEC + 1,
// anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
//
// event = CreateAcquireWakelockEvent(
// attributions2, "wl1", bucketStartTimeNs + 3 * bucketSizeNs + 1);
// processor->OnLogEvent(event.get());
// EXPECT_EQ(refractory_period_sec + (bucketStartTimeNs + bucketSizeNs + 1) / NS_PER_SEC + 1,
// anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
//
// event = CreateAcquireWakelockEvent(
// attributions2, "wl1", bucketStartTimeNs + 3 * bucketSizeNs + 2);
// processor->OnLogEvent(event.get());
// EXPECT_EQ(refractory_period_sec + (bucketStartTimeNs + 3 * bucketSizeNs + 2) / NS_PER_SEC + 1,
// anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
//}
#else
GTEST_LOG_(INFO) << "This test does nothing.\n";

View File

@@ -89,393 +89,394 @@ MetricDimensionKey dimensionKey2(
(int32_t)0x02010101), Value((int32_t)222))}),
DEFAULT_DIMENSION_KEY);
TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_single_bucket) {
const int num_buckets = 1;
const uint64_t threshold_ns = NS_PER_SEC;
auto config = CreateStatsdConfig(num_buckets, threshold_ns, DurationMetric::SUM, true);
const uint64_t alert_id = config.alert(0).id();
const uint32_t refractory_period_sec = config.alert(0).refractory_period_secs();
int64_t bucketStartTimeNs = 10 * NS_PER_SEC;
int64_t bucketSizeNs =
TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000;
ConfigKey cfgKey;
auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
EXPECT_EQ(1u, processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers.size());
sp<AnomalyTracker> anomalyTracker =
processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers[0];
auto screen_on_event = CreateScreenStateChangedEvent(
android::view::DisplayStateEnum::DISPLAY_STATE_ON, bucketStartTimeNs + 1);
auto screen_off_event = CreateScreenStateChangedEvent(
android::view::DisplayStateEnum::DISPLAY_STATE_OFF, bucketStartTimeNs + 10);
processor->OnLogEvent(screen_on_event.get());
processor->OnLogEvent(screen_off_event.get());
// Acquire wakelock wl1.
auto acquire_event = CreateAcquireWakelockEvent(attributions1, "wl1", bucketStartTimeNs + 11);
processor->OnLogEvent(acquire_event.get());
EXPECT_EQ((bucketStartTimeNs + 11 + threshold_ns) / NS_PER_SEC + 1,
anomalyTracker->getAlarmTimestampSec(dimensionKey));
EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
// Release wakelock wl1. No anomaly detected. Alarm cancelled at the "release" event.
auto release_event = CreateReleaseWakelockEvent(attributions1, "wl1", bucketStartTimeNs + 101);
processor->OnLogEvent(release_event.get());
EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey));
EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
// Acquire wakelock wl1 within bucket #0.
acquire_event = CreateAcquireWakelockEvent(attributions2, "wl1", bucketStartTimeNs + 110);
processor->OnLogEvent(acquire_event.get());
EXPECT_EQ((bucketStartTimeNs + 110 + threshold_ns - 90) / NS_PER_SEC + 1,
anomalyTracker->getAlarmTimestampSec(dimensionKey));
EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
// Release wakelock wl1. One anomaly detected.
release_event = CreateReleaseWakelockEvent(
attributions2, "wl1", bucketStartTimeNs + NS_PER_SEC + 109);
processor->OnLogEvent(release_event.get());
EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey));
EXPECT_EQ(refractory_period_sec + (bucketStartTimeNs + NS_PER_SEC + 109) / NS_PER_SEC + 1,
anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
// Acquire wakelock wl1.
acquire_event = CreateAcquireWakelockEvent(
attributions1, "wl1", bucketStartTimeNs + NS_PER_SEC + 112);
processor->OnLogEvent(acquire_event.get());
// Wakelock has been hold longer than the threshold in bucket #0. The alarm is set at the
// end of the refractory period.
const int64_t alarmFiredTimestampSec0 = anomalyTracker->getAlarmTimestampSec(dimensionKey);
EXPECT_EQ(refractory_period_sec + (bucketStartTimeNs + NS_PER_SEC + 109) / NS_PER_SEC + 1,
(uint32_t)alarmFiredTimestampSec0);
// Anomaly alarm fired.
auto alarmSet = processor->getAnomalyAlarmMonitor()->popSoonerThan(
static_cast<uint32_t>(alarmFiredTimestampSec0));
EXPECT_EQ(1u, alarmSet.size());
processor->onAnomalyAlarmFired(alarmFiredTimestampSec0 * NS_PER_SEC, alarmSet);
EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey));
EXPECT_EQ(refractory_period_sec + alarmFiredTimestampSec0,
anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
// Release wakelock wl1.
release_event = CreateReleaseWakelockEvent(
attributions1, "wl1", alarmFiredTimestampSec0 * NS_PER_SEC + NS_PER_SEC + 1);
processor->OnLogEvent(release_event.get());
EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey));
// Within refractory period. No more anomaly detected.
EXPECT_EQ(refractory_period_sec + alarmFiredTimestampSec0,
anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
// Acquire wakelock wl1.
acquire_event = CreateAcquireWakelockEvent(
attributions2, "wl1", bucketStartTimeNs + bucketSizeNs - 5 * NS_PER_SEC - 11);
processor->OnLogEvent(acquire_event.get());
const int64_t alarmFiredTimestampSec1 = anomalyTracker->getAlarmTimestampSec(dimensionKey);
EXPECT_EQ((bucketStartTimeNs + bucketSizeNs - 5 * NS_PER_SEC) / NS_PER_SEC,
(uint64_t)alarmFiredTimestampSec1);
// Release wakelock wl1.
release_event = CreateReleaseWakelockEvent(
attributions2, "wl1", bucketStartTimeNs + bucketSizeNs - 4 * NS_PER_SEC - 10);
processor->OnLogEvent(release_event.get());
EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey));
EXPECT_EQ(refractory_period_sec +
(bucketStartTimeNs + bucketSizeNs - 4 * NS_PER_SEC - 10) / NS_PER_SEC + 1,
anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
alarmSet = processor->getAnomalyAlarmMonitor()->popSoonerThan(
static_cast<uint32_t>(alarmFiredTimestampSec1));
EXPECT_EQ(0u, alarmSet.size());
// Acquire wakelock wl1 near the end of bucket #0.
acquire_event = CreateAcquireWakelockEvent(
attributions1, "wl1", bucketStartTimeNs + bucketSizeNs - 2);
processor->OnLogEvent(acquire_event.get());
EXPECT_EQ((bucketStartTimeNs + bucketSizeNs) / NS_PER_SEC,
anomalyTracker->getAlarmTimestampSec(dimensionKey));
// Release the event at early bucket #1.
release_event = CreateReleaseWakelockEvent(
attributions1, "wl1", bucketStartTimeNs + bucketSizeNs + NS_PER_SEC - 1);
processor->OnLogEvent(release_event.get());
EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey));
// Anomaly detected when stopping the alarm. The refractory period does not change.
EXPECT_EQ(refractory_period_sec +
(bucketStartTimeNs + bucketSizeNs + NS_PER_SEC) / NS_PER_SEC,
anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
// Condition changes to false.
screen_on_event = CreateScreenStateChangedEvent(
android::view::DisplayStateEnum::DISPLAY_STATE_ON,
bucketStartTimeNs + 2 * bucketSizeNs + 20);
processor->OnLogEvent(screen_on_event.get());
EXPECT_EQ(refractory_period_sec +
(bucketStartTimeNs + bucketSizeNs + NS_PER_SEC) / NS_PER_SEC,
anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey));
acquire_event = CreateAcquireWakelockEvent(
attributions2, "wl1", bucketStartTimeNs + 2 * bucketSizeNs + 30);
processor->OnLogEvent(acquire_event.get());
// The condition is false. Do not start the alarm.
EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey));
EXPECT_EQ(refractory_period_sec +
(bucketStartTimeNs + bucketSizeNs + NS_PER_SEC) / NS_PER_SEC,
anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
// Condition turns true.
screen_off_event = CreateScreenStateChangedEvent(
android::view::DisplayStateEnum::DISPLAY_STATE_OFF,
bucketStartTimeNs + 2 * bucketSizeNs + NS_PER_SEC);
processor->OnLogEvent(screen_off_event.get());
EXPECT_EQ((bucketStartTimeNs + 2 * bucketSizeNs + NS_PER_SEC + threshold_ns) / NS_PER_SEC,
anomalyTracker->getAlarmTimestampSec(dimensionKey));
// Condition turns to false.
screen_on_event = CreateScreenStateChangedEvent(
android::view::DisplayStateEnum::DISPLAY_STATE_ON,
bucketStartTimeNs + 2 * bucketSizeNs + 2 * NS_PER_SEC + 1);
processor->OnLogEvent(screen_on_event.get());
// Condition turns to false. Cancelled the alarm.
EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey));
// Detected one anomaly.
EXPECT_EQ(refractory_period_sec +
(bucketStartTimeNs + 2 * bucketSizeNs + 2 * NS_PER_SEC + 1) / NS_PER_SEC + 1,
anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
// Condition turns to true again.
screen_off_event = CreateScreenStateChangedEvent(
android::view::DisplayStateEnum::DISPLAY_STATE_OFF,
bucketStartTimeNs + 2 * bucketSizeNs + 2 * NS_PER_SEC + 2);
processor->OnLogEvent(screen_off_event.get());
EXPECT_EQ((bucketStartTimeNs + 2 * bucketSizeNs) / NS_PER_SEC + 2 + 2 + 1,
anomalyTracker->getAlarmTimestampSec(dimensionKey));
release_event = CreateReleaseWakelockEvent(
attributions2, "wl1", bucketStartTimeNs + 2 * bucketSizeNs + 5 * NS_PER_SEC);
processor->OnLogEvent(release_event.get());
EXPECT_EQ(refractory_period_sec +
(bucketStartTimeNs + 2 * bucketSizeNs + 5 * NS_PER_SEC) / NS_PER_SEC,
anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey));
}
TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_multiple_buckets) {
const int num_buckets = 3;
const uint64_t threshold_ns = NS_PER_SEC;
auto config = CreateStatsdConfig(num_buckets, threshold_ns, DurationMetric::SUM, true);
const uint64_t alert_id = config.alert(0).id();
const uint32_t refractory_period_sec = config.alert(0).refractory_period_secs();
int64_t bucketStartTimeNs = 10 * NS_PER_SEC;
int64_t bucketSizeNs =
TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000;
ConfigKey cfgKey;
auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
EXPECT_EQ(1u, processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers.size());
sp<AnomalyTracker> anomalyTracker =
processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers[0];
auto screen_off_event = CreateScreenStateChangedEvent(
android::view::DisplayStateEnum::DISPLAY_STATE_OFF, bucketStartTimeNs + 1);
processor->OnLogEvent(screen_off_event.get());
// Acquire wakelock "wc1" in bucket #0.
auto acquire_event = CreateAcquireWakelockEvent(
attributions1, "wl1", bucketStartTimeNs + bucketSizeNs - NS_PER_SEC / 2 - 1);
processor->OnLogEvent(acquire_event.get());
EXPECT_EQ((bucketStartTimeNs + bucketSizeNs) / NS_PER_SEC + 1,
anomalyTracker->getAlarmTimestampSec(dimensionKey));
EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
// Release wakelock "wc1" in bucket #0.
auto release_event = CreateReleaseWakelockEvent(
attributions1, "wl1", bucketStartTimeNs + bucketSizeNs - 1);
processor->OnLogEvent(release_event.get());
EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey));
EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
// Acquire wakelock "wc1" in bucket #1.
acquire_event = CreateAcquireWakelockEvent(
attributions2, "wl1", bucketStartTimeNs + bucketSizeNs + 1);
processor->OnLogEvent(acquire_event.get());
EXPECT_EQ((bucketStartTimeNs + bucketSizeNs) / NS_PER_SEC + 1,
anomalyTracker->getAlarmTimestampSec(dimensionKey));
EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
release_event = CreateReleaseWakelockEvent(
attributions2, "wl1", bucketStartTimeNs + bucketSizeNs + 100);
processor->OnLogEvent(release_event.get());
EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey));
EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
// Acquire wakelock "wc2" in bucket #2.
acquire_event = CreateAcquireWakelockEvent(
attributions3, "wl2", bucketStartTimeNs + 2 * bucketSizeNs + 1);
processor->OnLogEvent(acquire_event.get());
EXPECT_EQ((bucketStartTimeNs + 2 * bucketSizeNs) / NS_PER_SEC + 2,
anomalyTracker->getAlarmTimestampSec(dimensionKey2));
EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey2));
// Release wakelock "wc2" in bucket #2.
release_event = CreateReleaseWakelockEvent(
attributions3, "wl2", bucketStartTimeNs + 2 * bucketSizeNs + 2 * NS_PER_SEC);
processor->OnLogEvent(release_event.get());
EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey2));
EXPECT_EQ(refractory_period_sec +
(bucketStartTimeNs + 2 * bucketSizeNs + 2 * NS_PER_SEC) / NS_PER_SEC,
anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey2));
// Acquire wakelock "wc1" in bucket #2.
acquire_event = CreateAcquireWakelockEvent(
attributions2, "wl1", bucketStartTimeNs + 2 * bucketSizeNs + 2 * NS_PER_SEC);
processor->OnLogEvent(acquire_event.get());
EXPECT_EQ((bucketStartTimeNs + 2 * bucketSizeNs) / NS_PER_SEC + 2 + 1,
anomalyTracker->getAlarmTimestampSec(dimensionKey));
EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
// Release wakelock "wc1" in bucket #2.
release_event = CreateReleaseWakelockEvent(
attributions2, "wl1", bucketStartTimeNs + 2 * bucketSizeNs + 2.5 * NS_PER_SEC);
processor->OnLogEvent(release_event.get());
EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey));
EXPECT_EQ(refractory_period_sec +
(int64_t)(bucketStartTimeNs + 2 * bucketSizeNs + 2.5 * NS_PER_SEC) / NS_PER_SEC + 1,
anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
acquire_event = CreateAcquireWakelockEvent(
attributions3, "wl2", bucketStartTimeNs + 6 * bucketSizeNs - NS_PER_SEC + 4);
processor->OnLogEvent(acquire_event.get());
acquire_event = CreateAcquireWakelockEvent(
attributions1, "wl1", bucketStartTimeNs + 6 * bucketSizeNs - NS_PER_SEC + 5);
processor->OnLogEvent(acquire_event.get());
EXPECT_EQ((bucketStartTimeNs + 6 * bucketSizeNs) / NS_PER_SEC + 1,
anomalyTracker->getAlarmTimestampSec(dimensionKey));
EXPECT_EQ((bucketStartTimeNs + 6 * bucketSizeNs) / NS_PER_SEC + 1,
anomalyTracker->getAlarmTimestampSec(dimensionKey2));
release_event = CreateReleaseWakelockEvent(
attributions3, "wl2", bucketStartTimeNs + 6 * bucketSizeNs + 2);
processor->OnLogEvent(release_event.get());
release_event = CreateReleaseWakelockEvent(
attributions1, "wl1", bucketStartTimeNs + 6 * bucketSizeNs + 6);
processor->OnLogEvent(release_event.get());
EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey));
EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey2));
// The buckets are not messed up across dimensions. Only one dimension has anomaly triggered.
EXPECT_EQ(refractory_period_sec +
(int64_t)(bucketStartTimeNs + 6 * bucketSizeNs) / NS_PER_SEC + 1,
anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
}
TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_long_refractory_period) {
const int num_buckets = 2;
const uint64_t threshold_ns = 3 * NS_PER_SEC;
auto config = CreateStatsdConfig(num_buckets, threshold_ns, DurationMetric::SUM, false);
int64_t bucketStartTimeNs = 10 * NS_PER_SEC;
int64_t bucketSizeNs =
TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000;
const uint64_t alert_id = config.alert(0).id();
const uint32_t refractory_period_sec = 3 * bucketSizeNs / NS_PER_SEC;
config.mutable_alert(0)->set_refractory_period_secs(refractory_period_sec);
ConfigKey cfgKey;
auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
EXPECT_EQ(1u, processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers.size());
sp<AnomalyTracker> anomalyTracker =
processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers[0];
auto screen_off_event = CreateScreenStateChangedEvent(
android::view::DisplayStateEnum::DISPLAY_STATE_OFF, bucketStartTimeNs + 1);
processor->OnLogEvent(screen_off_event.get());
// Acquire wakelock "wc1" in bucket #0.
auto acquire_event = CreateAcquireWakelockEvent(
attributions1, "wl1", bucketStartTimeNs + bucketSizeNs - 100);
processor->OnLogEvent(acquire_event.get());
EXPECT_EQ((bucketStartTimeNs + bucketSizeNs) / NS_PER_SEC + 3,
anomalyTracker->getAlarmTimestampSec(dimensionKey));
EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
// Acquire the wakelock "wc1" again.
acquire_event = CreateAcquireWakelockEvent(
attributions1, "wl1", bucketStartTimeNs + bucketSizeNs + 2 * NS_PER_SEC + 1);
processor->OnLogEvent(acquire_event.get());
// The alarm does not change.
EXPECT_EQ((bucketStartTimeNs + bucketSizeNs) / NS_PER_SEC + 3,
anomalyTracker->getAlarmTimestampSec(dimensionKey));
EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
// Anomaly alarm fired late.
const int64_t firedAlarmTimestampNs = bucketStartTimeNs + 2 * bucketSizeNs - NS_PER_SEC;
auto alarmSet = processor->getAnomalyAlarmMonitor()->popSoonerThan(
static_cast<uint32_t>(firedAlarmTimestampNs / NS_PER_SEC));
EXPECT_EQ(1u, alarmSet.size());
processor->onAnomalyAlarmFired(firedAlarmTimestampNs, alarmSet);
EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey));
EXPECT_EQ(refractory_period_sec + firedAlarmTimestampNs / NS_PER_SEC,
anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
acquire_event = CreateAcquireWakelockEvent(
attributions1, "wl1", bucketStartTimeNs + 2 * bucketSizeNs - 100);
processor->OnLogEvent(acquire_event.get());
EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey));
EXPECT_EQ(refractory_period_sec + firedAlarmTimestampNs / NS_PER_SEC,
anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
auto release_event = CreateReleaseWakelockEvent(
attributions1, "wl1", bucketStartTimeNs + 2 * bucketSizeNs + 1);
processor->OnLogEvent(release_event.get());
EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey));
// Within the refractory period. No anomaly.
EXPECT_EQ(refractory_period_sec + firedAlarmTimestampNs / NS_PER_SEC,
anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
// A new wakelock, but still within refractory period.
acquire_event = CreateAcquireWakelockEvent(
attributions1, "wl1", bucketStartTimeNs + 2 * bucketSizeNs + 10 * NS_PER_SEC);
processor->OnLogEvent(acquire_event.get());
EXPECT_EQ(refractory_period_sec + firedAlarmTimestampNs / NS_PER_SEC,
anomalyTracker->getAlarmTimestampSec(dimensionKey));
release_event = CreateReleaseWakelockEvent(
attributions1, "wl1", bucketStartTimeNs + 3 * bucketSizeNs - NS_PER_SEC);
// Still in the refractory period. No anomaly.
processor->OnLogEvent(release_event.get());
EXPECT_EQ(refractory_period_sec + firedAlarmTimestampNs / NS_PER_SEC,
anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
acquire_event = CreateAcquireWakelockEvent(
attributions1, "wl1", bucketStartTimeNs + 5 * bucketSizeNs - 3 * NS_PER_SEC - 5);
processor->OnLogEvent(acquire_event.get());
EXPECT_EQ((bucketStartTimeNs + 5 * bucketSizeNs) / NS_PER_SEC,
anomalyTracker->getAlarmTimestampSec(dimensionKey));
release_event = CreateReleaseWakelockEvent(
attributions1, "wl1", bucketStartTimeNs + 5 * bucketSizeNs - 3 * NS_PER_SEC - 4);
processor->OnLogEvent(release_event.get());
EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey));
acquire_event = CreateAcquireWakelockEvent(
attributions1, "wl1", bucketStartTimeNs + 5 * bucketSizeNs - 3 * NS_PER_SEC - 3);
processor->OnLogEvent(acquire_event.get());
EXPECT_EQ((bucketStartTimeNs + 5 * bucketSizeNs) / NS_PER_SEC,
anomalyTracker->getAlarmTimestampSec(dimensionKey));
}
// TODO(b/149590301): Update these tests to use new socket schema.
//TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_single_bucket) {
// const int num_buckets = 1;
// const uint64_t threshold_ns = NS_PER_SEC;
// auto config = CreateStatsdConfig(num_buckets, threshold_ns, DurationMetric::SUM, true);
// const uint64_t alert_id = config.alert(0).id();
// const uint32_t refractory_period_sec = config.alert(0).refractory_period_secs();
//
// int64_t bucketStartTimeNs = 10 * NS_PER_SEC;
// int64_t bucketSizeNs =
// TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000;
//
// ConfigKey cfgKey;
// auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
// EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
// EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
// EXPECT_EQ(1u, processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers.size());
//
// sp<AnomalyTracker> anomalyTracker =
// processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers[0];
//
// auto screen_on_event = CreateScreenStateChangedEvent(
// android::view::DisplayStateEnum::DISPLAY_STATE_ON, bucketStartTimeNs + 1);
// auto screen_off_event = CreateScreenStateChangedEvent(
// android::view::DisplayStateEnum::DISPLAY_STATE_OFF, bucketStartTimeNs + 10);
// processor->OnLogEvent(screen_on_event.get());
// processor->OnLogEvent(screen_off_event.get());
//
// // Acquire wakelock wl1.
// auto acquire_event = CreateAcquireWakelockEvent(attributions1, "wl1", bucketStartTimeNs + 11);
// processor->OnLogEvent(acquire_event.get());
// EXPECT_EQ((bucketStartTimeNs + 11 + threshold_ns) / NS_PER_SEC + 1,
// anomalyTracker->getAlarmTimestampSec(dimensionKey));
// EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
//
// // Release wakelock wl1. No anomaly detected. Alarm cancelled at the "release" event.
// auto release_event = CreateReleaseWakelockEvent(attributions1, "wl1", bucketStartTimeNs + 101);
// processor->OnLogEvent(release_event.get());
// EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey));
// EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
//
// // Acquire wakelock wl1 within bucket #0.
// acquire_event = CreateAcquireWakelockEvent(attributions2, "wl1", bucketStartTimeNs + 110);
// processor->OnLogEvent(acquire_event.get());
// EXPECT_EQ((bucketStartTimeNs + 110 + threshold_ns - 90) / NS_PER_SEC + 1,
// anomalyTracker->getAlarmTimestampSec(dimensionKey));
// EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
//
// // Release wakelock wl1. One anomaly detected.
// release_event = CreateReleaseWakelockEvent(
// attributions2, "wl1", bucketStartTimeNs + NS_PER_SEC + 109);
// processor->OnLogEvent(release_event.get());
// EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey));
// EXPECT_EQ(refractory_period_sec + (bucketStartTimeNs + NS_PER_SEC + 109) / NS_PER_SEC + 1,
// anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
//
// // Acquire wakelock wl1.
// acquire_event = CreateAcquireWakelockEvent(
// attributions1, "wl1", bucketStartTimeNs + NS_PER_SEC + 112);
// processor->OnLogEvent(acquire_event.get());
// // Wakelock has been hold longer than the threshold in bucket #0. The alarm is set at the
// // end of the refractory period.
// const int64_t alarmFiredTimestampSec0 = anomalyTracker->getAlarmTimestampSec(dimensionKey);
// EXPECT_EQ(refractory_period_sec + (bucketStartTimeNs + NS_PER_SEC + 109) / NS_PER_SEC + 1,
// (uint32_t)alarmFiredTimestampSec0);
//
// // Anomaly alarm fired.
// auto alarmSet = processor->getAnomalyAlarmMonitor()->popSoonerThan(
// static_cast<uint32_t>(alarmFiredTimestampSec0));
// EXPECT_EQ(1u, alarmSet.size());
// processor->onAnomalyAlarmFired(alarmFiredTimestampSec0 * NS_PER_SEC, alarmSet);
// EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey));
// EXPECT_EQ(refractory_period_sec + alarmFiredTimestampSec0,
// anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
//
// // Release wakelock wl1.
// release_event = CreateReleaseWakelockEvent(
// attributions1, "wl1", alarmFiredTimestampSec0 * NS_PER_SEC + NS_PER_SEC + 1);
// processor->OnLogEvent(release_event.get());
// EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey));
// // Within refractory period. No more anomaly detected.
// EXPECT_EQ(refractory_period_sec + alarmFiredTimestampSec0,
// anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
//
// // Acquire wakelock wl1.
// acquire_event = CreateAcquireWakelockEvent(
// attributions2, "wl1", bucketStartTimeNs + bucketSizeNs - 5 * NS_PER_SEC - 11);
// processor->OnLogEvent(acquire_event.get());
// const int64_t alarmFiredTimestampSec1 = anomalyTracker->getAlarmTimestampSec(dimensionKey);
// EXPECT_EQ((bucketStartTimeNs + bucketSizeNs - 5 * NS_PER_SEC) / NS_PER_SEC,
// (uint64_t)alarmFiredTimestampSec1);
//
// // Release wakelock wl1.
// release_event = CreateReleaseWakelockEvent(
// attributions2, "wl1", bucketStartTimeNs + bucketSizeNs - 4 * NS_PER_SEC - 10);
// processor->OnLogEvent(release_event.get());
// EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey));
// EXPECT_EQ(refractory_period_sec +
// (bucketStartTimeNs + bucketSizeNs - 4 * NS_PER_SEC - 10) / NS_PER_SEC + 1,
// anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
//
// alarmSet = processor->getAnomalyAlarmMonitor()->popSoonerThan(
// static_cast<uint32_t>(alarmFiredTimestampSec1));
// EXPECT_EQ(0u, alarmSet.size());
//
// // Acquire wakelock wl1 near the end of bucket #0.
// acquire_event = CreateAcquireWakelockEvent(
// attributions1, "wl1", bucketStartTimeNs + bucketSizeNs - 2);
// processor->OnLogEvent(acquire_event.get());
// EXPECT_EQ((bucketStartTimeNs + bucketSizeNs) / NS_PER_SEC,
// anomalyTracker->getAlarmTimestampSec(dimensionKey));
//
// // Release the event at early bucket #1.
// release_event = CreateReleaseWakelockEvent(
// attributions1, "wl1", bucketStartTimeNs + bucketSizeNs + NS_PER_SEC - 1);
// processor->OnLogEvent(release_event.get());
// EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey));
// // Anomaly detected when stopping the alarm. The refractory period does not change.
// EXPECT_EQ(refractory_period_sec +
// (bucketStartTimeNs + bucketSizeNs + NS_PER_SEC) / NS_PER_SEC,
// anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
//
// // Condition changes to false.
// screen_on_event = CreateScreenStateChangedEvent(
// android::view::DisplayStateEnum::DISPLAY_STATE_ON,
// bucketStartTimeNs + 2 * bucketSizeNs + 20);
// processor->OnLogEvent(screen_on_event.get());
// EXPECT_EQ(refractory_period_sec +
// (bucketStartTimeNs + bucketSizeNs + NS_PER_SEC) / NS_PER_SEC,
// anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
// EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey));
//
// acquire_event = CreateAcquireWakelockEvent(
// attributions2, "wl1", bucketStartTimeNs + 2 * bucketSizeNs + 30);
// processor->OnLogEvent(acquire_event.get());
// // The condition is false. Do not start the alarm.
// EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey));
// EXPECT_EQ(refractory_period_sec +
// (bucketStartTimeNs + bucketSizeNs + NS_PER_SEC) / NS_PER_SEC,
// anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
//
// // Condition turns true.
// screen_off_event = CreateScreenStateChangedEvent(
// android::view::DisplayStateEnum::DISPLAY_STATE_OFF,
// bucketStartTimeNs + 2 * bucketSizeNs + NS_PER_SEC);
// processor->OnLogEvent(screen_off_event.get());
// EXPECT_EQ((bucketStartTimeNs + 2 * bucketSizeNs + NS_PER_SEC + threshold_ns) / NS_PER_SEC,
// anomalyTracker->getAlarmTimestampSec(dimensionKey));
//
// // Condition turns to false.
// screen_on_event = CreateScreenStateChangedEvent(
// android::view::DisplayStateEnum::DISPLAY_STATE_ON,
// bucketStartTimeNs + 2 * bucketSizeNs + 2 * NS_PER_SEC + 1);
// processor->OnLogEvent(screen_on_event.get());
// // Condition turns to false. Cancelled the alarm.
// EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey));
// // Detected one anomaly.
// EXPECT_EQ(refractory_period_sec +
// (bucketStartTimeNs + 2 * bucketSizeNs + 2 * NS_PER_SEC + 1) / NS_PER_SEC + 1,
// anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
//
// // Condition turns to true again.
// screen_off_event = CreateScreenStateChangedEvent(
// android::view::DisplayStateEnum::DISPLAY_STATE_OFF,
// bucketStartTimeNs + 2 * bucketSizeNs + 2 * NS_PER_SEC + 2);
// processor->OnLogEvent(screen_off_event.get());
// EXPECT_EQ((bucketStartTimeNs + 2 * bucketSizeNs) / NS_PER_SEC + 2 + 2 + 1,
// anomalyTracker->getAlarmTimestampSec(dimensionKey));
//
// release_event = CreateReleaseWakelockEvent(
// attributions2, "wl1", bucketStartTimeNs + 2 * bucketSizeNs + 5 * NS_PER_SEC);
// processor->OnLogEvent(release_event.get());
// EXPECT_EQ(refractory_period_sec +
// (bucketStartTimeNs + 2 * bucketSizeNs + 5 * NS_PER_SEC) / NS_PER_SEC,
// anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
// EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey));
//}
//
//TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_multiple_buckets) {
// const int num_buckets = 3;
// const uint64_t threshold_ns = NS_PER_SEC;
// auto config = CreateStatsdConfig(num_buckets, threshold_ns, DurationMetric::SUM, true);
// const uint64_t alert_id = config.alert(0).id();
// const uint32_t refractory_period_sec = config.alert(0).refractory_period_secs();
//
// int64_t bucketStartTimeNs = 10 * NS_PER_SEC;
// int64_t bucketSizeNs =
// TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000;
//
// ConfigKey cfgKey;
// auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
// EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
// EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
// EXPECT_EQ(1u, processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers.size());
//
// sp<AnomalyTracker> anomalyTracker =
// processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers[0];
//
// auto screen_off_event = CreateScreenStateChangedEvent(
// android::view::DisplayStateEnum::DISPLAY_STATE_OFF, bucketStartTimeNs + 1);
// processor->OnLogEvent(screen_off_event.get());
//
// // Acquire wakelock "wc1" in bucket #0.
// auto acquire_event = CreateAcquireWakelockEvent(
// attributions1, "wl1", bucketStartTimeNs + bucketSizeNs - NS_PER_SEC / 2 - 1);
// processor->OnLogEvent(acquire_event.get());
// EXPECT_EQ((bucketStartTimeNs + bucketSizeNs) / NS_PER_SEC + 1,
// anomalyTracker->getAlarmTimestampSec(dimensionKey));
// EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
//
// // Release wakelock "wc1" in bucket #0.
// auto release_event = CreateReleaseWakelockEvent(
// attributions1, "wl1", bucketStartTimeNs + bucketSizeNs - 1);
// processor->OnLogEvent(release_event.get());
// EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey));
// EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
//
// // Acquire wakelock "wc1" in bucket #1.
// acquire_event = CreateAcquireWakelockEvent(
// attributions2, "wl1", bucketStartTimeNs + bucketSizeNs + 1);
// processor->OnLogEvent(acquire_event.get());
// EXPECT_EQ((bucketStartTimeNs + bucketSizeNs) / NS_PER_SEC + 1,
// anomalyTracker->getAlarmTimestampSec(dimensionKey));
// EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
//
// release_event = CreateReleaseWakelockEvent(
// attributions2, "wl1", bucketStartTimeNs + bucketSizeNs + 100);
// processor->OnLogEvent(release_event.get());
// EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey));
// EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
//
// // Acquire wakelock "wc2" in bucket #2.
// acquire_event = CreateAcquireWakelockEvent(
// attributions3, "wl2", bucketStartTimeNs + 2 * bucketSizeNs + 1);
// processor->OnLogEvent(acquire_event.get());
// EXPECT_EQ((bucketStartTimeNs + 2 * bucketSizeNs) / NS_PER_SEC + 2,
// anomalyTracker->getAlarmTimestampSec(dimensionKey2));
// EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey2));
//
// // Release wakelock "wc2" in bucket #2.
// release_event = CreateReleaseWakelockEvent(
// attributions3, "wl2", bucketStartTimeNs + 2 * bucketSizeNs + 2 * NS_PER_SEC);
// processor->OnLogEvent(release_event.get());
// EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey2));
// EXPECT_EQ(refractory_period_sec +
// (bucketStartTimeNs + 2 * bucketSizeNs + 2 * NS_PER_SEC) / NS_PER_SEC,
// anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey2));
//
// // Acquire wakelock "wc1" in bucket #2.
// acquire_event = CreateAcquireWakelockEvent(
// attributions2, "wl1", bucketStartTimeNs + 2 * bucketSizeNs + 2 * NS_PER_SEC);
// processor->OnLogEvent(acquire_event.get());
// EXPECT_EQ((bucketStartTimeNs + 2 * bucketSizeNs) / NS_PER_SEC + 2 + 1,
// anomalyTracker->getAlarmTimestampSec(dimensionKey));
// EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
//
// // Release wakelock "wc1" in bucket #2.
// release_event = CreateReleaseWakelockEvent(
// attributions2, "wl1", bucketStartTimeNs + 2 * bucketSizeNs + 2.5 * NS_PER_SEC);
// processor->OnLogEvent(release_event.get());
// EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey));
// EXPECT_EQ(refractory_period_sec +
// (int64_t)(bucketStartTimeNs + 2 * bucketSizeNs + 2.5 * NS_PER_SEC) / NS_PER_SEC + 1,
// anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
//
// acquire_event = CreateAcquireWakelockEvent(
// attributions3, "wl2", bucketStartTimeNs + 6 * bucketSizeNs - NS_PER_SEC + 4);
// processor->OnLogEvent(acquire_event.get());
// acquire_event = CreateAcquireWakelockEvent(
// attributions1, "wl1", bucketStartTimeNs + 6 * bucketSizeNs - NS_PER_SEC + 5);
// processor->OnLogEvent(acquire_event.get());
// EXPECT_EQ((bucketStartTimeNs + 6 * bucketSizeNs) / NS_PER_SEC + 1,
// anomalyTracker->getAlarmTimestampSec(dimensionKey));
// EXPECT_EQ((bucketStartTimeNs + 6 * bucketSizeNs) / NS_PER_SEC + 1,
// anomalyTracker->getAlarmTimestampSec(dimensionKey2));
//
// release_event = CreateReleaseWakelockEvent(
// attributions3, "wl2", bucketStartTimeNs + 6 * bucketSizeNs + 2);
// processor->OnLogEvent(release_event.get());
// release_event = CreateReleaseWakelockEvent(
// attributions1, "wl1", bucketStartTimeNs + 6 * bucketSizeNs + 6);
// processor->OnLogEvent(release_event.get());
// EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey));
// EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey2));
// // The buckets are not messed up across dimensions. Only one dimension has anomaly triggered.
// EXPECT_EQ(refractory_period_sec +
// (int64_t)(bucketStartTimeNs + 6 * bucketSizeNs) / NS_PER_SEC + 1,
// anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
//}
//
//TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_long_refractory_period) {
// const int num_buckets = 2;
// const uint64_t threshold_ns = 3 * NS_PER_SEC;
// auto config = CreateStatsdConfig(num_buckets, threshold_ns, DurationMetric::SUM, false);
// int64_t bucketStartTimeNs = 10 * NS_PER_SEC;
// int64_t bucketSizeNs =
// TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000;
//
// const uint64_t alert_id = config.alert(0).id();
// const uint32_t refractory_period_sec = 3 * bucketSizeNs / NS_PER_SEC;
// config.mutable_alert(0)->set_refractory_period_secs(refractory_period_sec);
//
// ConfigKey cfgKey;
// auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
// EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
// EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
// EXPECT_EQ(1u, processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers.size());
//
// sp<AnomalyTracker> anomalyTracker =
// processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers[0];
//
// auto screen_off_event = CreateScreenStateChangedEvent(
// android::view::DisplayStateEnum::DISPLAY_STATE_OFF, bucketStartTimeNs + 1);
// processor->OnLogEvent(screen_off_event.get());
//
// // Acquire wakelock "wc1" in bucket #0.
// auto acquire_event = CreateAcquireWakelockEvent(
// attributions1, "wl1", bucketStartTimeNs + bucketSizeNs - 100);
// processor->OnLogEvent(acquire_event.get());
// EXPECT_EQ((bucketStartTimeNs + bucketSizeNs) / NS_PER_SEC + 3,
// anomalyTracker->getAlarmTimestampSec(dimensionKey));
// EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
//
// // Acquire the wakelock "wc1" again.
// acquire_event = CreateAcquireWakelockEvent(
// attributions1, "wl1", bucketStartTimeNs + bucketSizeNs + 2 * NS_PER_SEC + 1);
// processor->OnLogEvent(acquire_event.get());
// // The alarm does not change.
// EXPECT_EQ((bucketStartTimeNs + bucketSizeNs) / NS_PER_SEC + 3,
// anomalyTracker->getAlarmTimestampSec(dimensionKey));
// EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
//
// // Anomaly alarm fired late.
// const int64_t firedAlarmTimestampNs = bucketStartTimeNs + 2 * bucketSizeNs - NS_PER_SEC;
// auto alarmSet = processor->getAnomalyAlarmMonitor()->popSoonerThan(
// static_cast<uint32_t>(firedAlarmTimestampNs / NS_PER_SEC));
// EXPECT_EQ(1u, alarmSet.size());
// processor->onAnomalyAlarmFired(firedAlarmTimestampNs, alarmSet);
// EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey));
// EXPECT_EQ(refractory_period_sec + firedAlarmTimestampNs / NS_PER_SEC,
// anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
//
// acquire_event = CreateAcquireWakelockEvent(
// attributions1, "wl1", bucketStartTimeNs + 2 * bucketSizeNs - 100);
// processor->OnLogEvent(acquire_event.get());
// EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey));
// EXPECT_EQ(refractory_period_sec + firedAlarmTimestampNs / NS_PER_SEC,
// anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
//
// auto release_event = CreateReleaseWakelockEvent(
// attributions1, "wl1", bucketStartTimeNs + 2 * bucketSizeNs + 1);
// processor->OnLogEvent(release_event.get());
// EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey));
// // Within the refractory period. No anomaly.
// EXPECT_EQ(refractory_period_sec + firedAlarmTimestampNs / NS_PER_SEC,
// anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
//
// // A new wakelock, but still within refractory period.
// acquire_event = CreateAcquireWakelockEvent(
// attributions1, "wl1", bucketStartTimeNs + 2 * bucketSizeNs + 10 * NS_PER_SEC);
// processor->OnLogEvent(acquire_event.get());
// EXPECT_EQ(refractory_period_sec + firedAlarmTimestampNs / NS_PER_SEC,
// anomalyTracker->getAlarmTimestampSec(dimensionKey));
//
// release_event = CreateReleaseWakelockEvent(
// attributions1, "wl1", bucketStartTimeNs + 3 * bucketSizeNs - NS_PER_SEC);
// // Still in the refractory period. No anomaly.
// processor->OnLogEvent(release_event.get());
// EXPECT_EQ(refractory_period_sec + firedAlarmTimestampNs / NS_PER_SEC,
// anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
//
// acquire_event = CreateAcquireWakelockEvent(
// attributions1, "wl1", bucketStartTimeNs + 5 * bucketSizeNs - 3 * NS_PER_SEC - 5);
// processor->OnLogEvent(acquire_event.get());
// EXPECT_EQ((bucketStartTimeNs + 5 * bucketSizeNs) / NS_PER_SEC,
// anomalyTracker->getAlarmTimestampSec(dimensionKey));
//
// release_event = CreateReleaseWakelockEvent(
// attributions1, "wl1", bucketStartTimeNs + 5 * bucketSizeNs - 3 * NS_PER_SEC - 4);
// processor->OnLogEvent(release_event.get());
// EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey));
//
// acquire_event = CreateAcquireWakelockEvent(
// attributions1, "wl1", bucketStartTimeNs + 5 * bucketSizeNs - 3 * NS_PER_SEC - 3);
// processor->OnLogEvent(acquire_event.get());
// EXPECT_EQ((bucketStartTimeNs + 5 * bucketSizeNs) / NS_PER_SEC,
// anomalyTracker->getAlarmTimestampSec(dimensionKey));
//}
#else
GTEST_LOG_(INFO) << "This test does nothing.\n";

View File

@@ -55,364 +55,365 @@ StatsdConfig CreateStatsdConfig(const Position position) {
} // namespace
TEST(AttributionE2eTest, TestAttributionMatchAndSliceByFirstUid) {
auto config = CreateStatsdConfig(Position::FIRST);
int64_t bucketStartTimeNs = 10000000000;
int64_t bucketSizeNs =
TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000000;
ConfigKey cfgKey;
auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
// Here it assumes that GMS core has two uids.
processor->getUidMap()->updateMap(
1, {222, 444, 111, 333}, {1, 1, 2, 2},
{String16("v1"), String16("v1"), String16("v2"), String16("v2")},
{String16("com.android.gmscore"), String16("com.android.gmscore"), String16("app1"),
String16("APP3")},
{String16(""), String16(""), String16(""), String16("")});
// GMS core node is in the middle.
std::vector<AttributionNodeInternal> attributions1 = {CreateAttribution(111, "App1"),
CreateAttribution(222, "GMSCoreModule1"),
CreateAttribution(333, "App3")};
// GMS core node is the last one.
std::vector<AttributionNodeInternal> attributions2 = {CreateAttribution(111, "App1"),
CreateAttribution(333, "App3"),
CreateAttribution(222, "GMSCoreModule1")};
// GMS core node is the first one.
std::vector<AttributionNodeInternal> attributions3 = {CreateAttribution(222, "GMSCoreModule1"),
CreateAttribution(333, "App3")};
// Single GMS core node.
std::vector<AttributionNodeInternal> attributions4 = {CreateAttribution(222, "GMSCoreModule1")};
// GMS core has another uid.
std::vector<AttributionNodeInternal> attributions5 = {CreateAttribution(111, "App1"),
CreateAttribution(444, "GMSCoreModule2"),
CreateAttribution(333, "App3")};
// Multiple GMS core nodes.
std::vector<AttributionNodeInternal> attributions6 = {CreateAttribution(444, "GMSCoreModule2"),
CreateAttribution(222, "GMSCoreModule1")};
// No GMS core nodes.
std::vector<AttributionNodeInternal> attributions7 = {CreateAttribution(111, "App1"),
CreateAttribution(333, "App3")};
std::vector<AttributionNodeInternal> attributions8 = {CreateAttribution(111, "App1")};
// GMS core node with isolated uid.
const int isolatedUid = 666;
std::vector<AttributionNodeInternal> attributions9 = {
CreateAttribution(isolatedUid, "GMSCoreModule3")};
std::vector<std::unique_ptr<LogEvent>> events;
// Events 1~4 are in the 1st bucket.
events.push_back(CreateAcquireWakelockEvent(
attributions1, "wl1", bucketStartTimeNs + 2));
events.push_back(CreateAcquireWakelockEvent(
attributions2, "wl1", bucketStartTimeNs + 200));
events.push_back(CreateAcquireWakelockEvent(
attributions3, "wl1", bucketStartTimeNs + bucketSizeNs - 1));
events.push_back(CreateAcquireWakelockEvent(
attributions4, "wl1", bucketStartTimeNs + bucketSizeNs));
// Events 5~8 are in the 3rd bucket.
events.push_back(CreateAcquireWakelockEvent(
attributions5, "wl2", bucketStartTimeNs + 2 * bucketSizeNs + 1));
events.push_back(CreateAcquireWakelockEvent(
attributions6, "wl2", bucketStartTimeNs + 2 * bucketSizeNs + 100));
events.push_back(CreateAcquireWakelockEvent(
attributions7, "wl2", bucketStartTimeNs + 3 * bucketSizeNs - 2));
events.push_back(CreateAcquireWakelockEvent(
attributions8, "wl2", bucketStartTimeNs + 3 * bucketSizeNs));
events.push_back(CreateAcquireWakelockEvent(
attributions9, "wl2", bucketStartTimeNs + 3 * bucketSizeNs + 1));
events.push_back(CreateAcquireWakelockEvent(
attributions9, "wl2", bucketStartTimeNs + 3 * bucketSizeNs + 100));
events.push_back(CreateIsolatedUidChangedEvent(
isolatedUid, 222, true/* is_create*/, bucketStartTimeNs + 3 * bucketSizeNs - 1));
events.push_back(CreateIsolatedUidChangedEvent(
isolatedUid, 222, false/* is_create*/, bucketStartTimeNs + 3 * bucketSizeNs + 10));
sortLogEventsByTimestamp(&events);
for (const auto& event : events) {
processor->OnLogEvent(event.get());
}
ConfigMetricsReportList reports;
vector<uint8_t> buffer;
processor->onDumpReport(cfgKey, bucketStartTimeNs + 4 * bucketSizeNs + 1, false, true,
ADB_DUMP, FAST, &buffer);
EXPECT_TRUE(buffer.size() > 0);
EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
backfillDimensionPath(&reports);
backfillStringInReport(&reports);
backfillStartEndTimestamp(&reports);
EXPECT_EQ(reports.reports_size(), 1);
EXPECT_EQ(reports.reports(0).metrics_size(), 1);
StatsLogReport::CountMetricDataWrapper countMetrics;
sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).count_metrics(), &countMetrics);
EXPECT_EQ(countMetrics.data_size(), 4);
auto data = countMetrics.data(0);
ValidateAttributionUidAndTagDimension(
data.dimensions_in_what(), android::util::WAKELOCK_STATE_CHANGED, 111,
"App1");
EXPECT_EQ(data.bucket_info_size(), 2);
EXPECT_EQ(data.bucket_info(0).count(), 2);
EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs);
EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), bucketStartTimeNs + bucketSizeNs);
EXPECT_EQ(data.bucket_info(1).count(), 1);
EXPECT_EQ(data.bucket_info(1).start_bucket_elapsed_nanos(), bucketStartTimeNs + 2 * bucketSizeNs);
EXPECT_EQ(data.bucket_info(1).end_bucket_elapsed_nanos(), bucketStartTimeNs + 3 * bucketSizeNs);
data = countMetrics.data(1);
ValidateAttributionUidAndTagDimension(
data.dimensions_in_what(), android::util::WAKELOCK_STATE_CHANGED, 222,
"GMSCoreModule1");
EXPECT_EQ(data.bucket_info_size(), 2);
EXPECT_EQ(data.bucket_info(0).count(), 1);
EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs);
EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), bucketStartTimeNs + bucketSizeNs);
EXPECT_EQ(data.bucket_info(1).count(), 1);
EXPECT_EQ(data.bucket_info(1).start_bucket_elapsed_nanos(), bucketStartTimeNs + bucketSizeNs);
EXPECT_EQ(data.bucket_info(1).end_bucket_elapsed_nanos(), bucketStartTimeNs + 2 * bucketSizeNs);
data = countMetrics.data(2);
ValidateAttributionUidAndTagDimension(
data.dimensions_in_what(), android::util::WAKELOCK_STATE_CHANGED, 222,
"GMSCoreModule3");
EXPECT_EQ(data.bucket_info_size(), 1);
EXPECT_EQ(data.bucket_info(0).count(), 1);
EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs + 3 * bucketSizeNs);
EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), bucketStartTimeNs + 4 * bucketSizeNs);
data = countMetrics.data(3);
ValidateAttributionUidAndTagDimension(
data.dimensions_in_what(), android::util::WAKELOCK_STATE_CHANGED, 444,
"GMSCoreModule2");
EXPECT_EQ(data.bucket_info_size(), 1);
EXPECT_EQ(data.bucket_info(0).count(), 1);
EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs + 2 * bucketSizeNs);
EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), bucketStartTimeNs + 3 * bucketSizeNs);
}
TEST(AttributionE2eTest, TestAttributionMatchAndSliceByChain) {
auto config = CreateStatsdConfig(Position::ALL);
int64_t bucketStartTimeNs = 10000000000;
int64_t bucketSizeNs =
TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000000;
ConfigKey cfgKey;
auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
// Here it assumes that GMS core has two uids.
processor->getUidMap()->updateMap(
1, {222, 444, 111, 333}, {1, 1, 2, 2},
{String16("v1"), String16("v1"), String16("v2"), String16("v2")},
{String16("com.android.gmscore"), String16("com.android.gmscore"), String16("app1"),
String16("APP3")},
{String16(""), String16(""), String16(""), String16("")});
// GMS core node is in the middle.
std::vector<AttributionNodeInternal> attributions1 = {CreateAttribution(111, "App1"),
CreateAttribution(222, "GMSCoreModule1"),
CreateAttribution(333, "App3")};
// GMS core node is the last one.
std::vector<AttributionNodeInternal> attributions2 = {CreateAttribution(111, "App1"),
CreateAttribution(333, "App3"),
CreateAttribution(222, "GMSCoreModule1")};
// GMS core node is the first one.
std::vector<AttributionNodeInternal> attributions3 = {CreateAttribution(222, "GMSCoreModule1"),
CreateAttribution(333, "App3")};
// Single GMS core node.
std::vector<AttributionNodeInternal> attributions4 = {CreateAttribution(222, "GMSCoreModule1")};
// GMS core has another uid.
std::vector<AttributionNodeInternal> attributions5 = {CreateAttribution(111, "App1"),
CreateAttribution(444, "GMSCoreModule2"),
CreateAttribution(333, "App3")};
// Multiple GMS core nodes.
std::vector<AttributionNodeInternal> attributions6 = {CreateAttribution(444, "GMSCoreModule2"),
CreateAttribution(222, "GMSCoreModule1")};
// No GMS core nodes.
std::vector<AttributionNodeInternal> attributions7 = {CreateAttribution(111, "App1"),
CreateAttribution(333, "App3")};
std::vector<AttributionNodeInternal> attributions8 = {CreateAttribution(111, "App1")};
// GMS core node with isolated uid.
const int isolatedUid = 666;
std::vector<AttributionNodeInternal> attributions9 = {
CreateAttribution(isolatedUid, "GMSCoreModule1")};
std::vector<std::unique_ptr<LogEvent>> events;
// Events 1~4 are in the 1st bucket.
events.push_back(CreateAcquireWakelockEvent(
attributions1, "wl1", bucketStartTimeNs + 2));
events.push_back(CreateAcquireWakelockEvent(
attributions2, "wl1", bucketStartTimeNs + 200));
events.push_back(CreateAcquireWakelockEvent(
attributions3, "wl1", bucketStartTimeNs + bucketSizeNs - 1));
events.push_back(CreateAcquireWakelockEvent(
attributions4, "wl1", bucketStartTimeNs + bucketSizeNs));
// Events 5~8 are in the 3rd bucket.
events.push_back(CreateAcquireWakelockEvent(
attributions5, "wl2", bucketStartTimeNs + 2 * bucketSizeNs + 1));
events.push_back(CreateAcquireWakelockEvent(
attributions6, "wl2", bucketStartTimeNs + 2 * bucketSizeNs + 100));
events.push_back(CreateAcquireWakelockEvent(
attributions7, "wl2", bucketStartTimeNs + 3 * bucketSizeNs - 2));
events.push_back(CreateAcquireWakelockEvent(
attributions8, "wl2", bucketStartTimeNs + 3 * bucketSizeNs));
events.push_back(CreateAcquireWakelockEvent(
attributions9, "wl2", bucketStartTimeNs + 3 * bucketSizeNs + 1));
events.push_back(CreateAcquireWakelockEvent(
attributions9, "wl2", bucketStartTimeNs + 3 * bucketSizeNs + 100));
events.push_back(CreateIsolatedUidChangedEvent(
isolatedUid, 222, true/* is_create*/, bucketStartTimeNs + 3 * bucketSizeNs - 1));
events.push_back(CreateIsolatedUidChangedEvent(
isolatedUid, 222, false/* is_create*/, bucketStartTimeNs + 3 * bucketSizeNs + 10));
sortLogEventsByTimestamp(&events);
for (const auto& event : events) {
processor->OnLogEvent(event.get());
}
ConfigMetricsReportList reports;
vector<uint8_t> buffer;
processor->onDumpReport(cfgKey, bucketStartTimeNs + 4 * bucketSizeNs + 1, false, true,
ADB_DUMP, FAST, &buffer);
EXPECT_TRUE(buffer.size() > 0);
EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
backfillDimensionPath(&reports);
backfillStringInReport(&reports);
backfillStartEndTimestamp(&reports);
EXPECT_EQ(reports.reports_size(), 1);
EXPECT_EQ(reports.reports(0).metrics_size(), 1);
StatsLogReport::CountMetricDataWrapper countMetrics;
sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).count_metrics(), &countMetrics);
EXPECT_EQ(countMetrics.data_size(), 6);
auto data = countMetrics.data(0);
ValidateAttributionUidAndTagDimension(
data.dimensions_in_what(), android::util::WAKELOCK_STATE_CHANGED, 222, "GMSCoreModule1");
EXPECT_EQ(2, data.bucket_info_size());
EXPECT_EQ(1, data.bucket_info(0).count());
EXPECT_EQ(bucketStartTimeNs + bucketSizeNs,
data.bucket_info(0).start_bucket_elapsed_nanos());
EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
data.bucket_info(0).end_bucket_elapsed_nanos());
EXPECT_EQ(1, data.bucket_info(1).count());
EXPECT_EQ(bucketStartTimeNs + 3 * bucketSizeNs,
data.bucket_info(1).start_bucket_elapsed_nanos());
EXPECT_EQ(bucketStartTimeNs + 4 * bucketSizeNs,
data.bucket_info(1).end_bucket_elapsed_nanos());
data = countMetrics.data(1);
ValidateUidDimension(
data.dimensions_in_what(), 0, android::util::WAKELOCK_STATE_CHANGED, 222);
ValidateAttributionUidAndTagDimension(
data.dimensions_in_what(), 0, android::util::WAKELOCK_STATE_CHANGED, 222, "GMSCoreModule1");
ValidateUidDimension(
data.dimensions_in_what(), 1, android::util::WAKELOCK_STATE_CHANGED, 333);
ValidateAttributionUidAndTagDimension(
data.dimensions_in_what(), 1, android::util::WAKELOCK_STATE_CHANGED, 333, "App3");
EXPECT_EQ(data.bucket_info_size(), 1);
EXPECT_EQ(data.bucket_info(0).count(), 1);
EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs);
EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), bucketStartTimeNs + bucketSizeNs);
data = countMetrics.data(2);
ValidateUidDimension(
data.dimensions_in_what(), 0, android::util::WAKELOCK_STATE_CHANGED, 444);
ValidateAttributionUidAndTagDimension(
data.dimensions_in_what(), 0, android::util::WAKELOCK_STATE_CHANGED, 444, "GMSCoreModule2");
ValidateUidDimension(
data.dimensions_in_what(), 1, android::util::WAKELOCK_STATE_CHANGED, 222);
ValidateAttributionUidAndTagDimension(
data.dimensions_in_what(), 1, android::util::WAKELOCK_STATE_CHANGED, 222, "GMSCoreModule1");
EXPECT_EQ(data.bucket_info_size(), 1);
EXPECT_EQ(data.bucket_info(0).count(), 1);
EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
data.bucket_info(0).start_bucket_elapsed_nanos());
EXPECT_EQ(bucketStartTimeNs + 3 * bucketSizeNs,
data.bucket_info(0).end_bucket_elapsed_nanos());
data = countMetrics.data(3);
ValidateUidDimension(
data.dimensions_in_what(), 0, android::util::WAKELOCK_STATE_CHANGED, 111);
ValidateAttributionUidAndTagDimension(
data.dimensions_in_what(), 0, android::util::WAKELOCK_STATE_CHANGED, 111, "App1");
ValidateUidDimension(
data.dimensions_in_what(), 1, android::util::WAKELOCK_STATE_CHANGED, 222);
ValidateAttributionUidAndTagDimension(
data.dimensions_in_what(), 1, android::util::WAKELOCK_STATE_CHANGED, 222, "GMSCoreModule1");
ValidateUidDimension(
data.dimensions_in_what(), 2, android::util::WAKELOCK_STATE_CHANGED, 333);
ValidateAttributionUidAndTagDimension(
data.dimensions_in_what(), 2, android::util::WAKELOCK_STATE_CHANGED, 333, "App3");
EXPECT_EQ(data.bucket_info_size(), 1);
EXPECT_EQ(data.bucket_info(0).count(), 1);
EXPECT_EQ(bucketStartTimeNs,
data.bucket_info(0).start_bucket_elapsed_nanos());
EXPECT_EQ(bucketStartTimeNs + bucketSizeNs,
data.bucket_info(0).end_bucket_elapsed_nanos());
data = countMetrics.data(4);
ValidateUidDimension(
data.dimensions_in_what(), 0, android::util::WAKELOCK_STATE_CHANGED, 111);
ValidateAttributionUidAndTagDimension(
data.dimensions_in_what(), 0, android::util::WAKELOCK_STATE_CHANGED, 111, "App1");
ValidateUidDimension(
data.dimensions_in_what(), 1, android::util::WAKELOCK_STATE_CHANGED, 333);
ValidateAttributionUidAndTagDimension(
data.dimensions_in_what(), 1, android::util::WAKELOCK_STATE_CHANGED, 333, "App3");
ValidateUidDimension(
data.dimensions_in_what(), 2, android::util::WAKELOCK_STATE_CHANGED, 222);
ValidateAttributionUidAndTagDimension(
data.dimensions_in_what(), 2, android::util::WAKELOCK_STATE_CHANGED, 222, "GMSCoreModule1");
EXPECT_EQ(data.bucket_info_size(), 1);
EXPECT_EQ(data.bucket_info(0).count(), 1);
EXPECT_EQ(bucketStartTimeNs,
data.bucket_info(0).start_bucket_elapsed_nanos());
EXPECT_EQ(bucketStartTimeNs + bucketSizeNs,
data.bucket_info(0).end_bucket_elapsed_nanos());
data = countMetrics.data(5);
ValidateUidDimension(
data.dimensions_in_what(), 0, android::util::WAKELOCK_STATE_CHANGED, 111);
ValidateAttributionUidAndTagDimension(
data.dimensions_in_what(), 0, android::util::WAKELOCK_STATE_CHANGED, 111, "App1");
ValidateUidDimension(
data.dimensions_in_what(), 1, android::util::WAKELOCK_STATE_CHANGED, 444);
ValidateAttributionUidAndTagDimension(
data.dimensions_in_what(), 1, android::util::WAKELOCK_STATE_CHANGED, 444, "GMSCoreModule2");
ValidateUidDimension(
data.dimensions_in_what(), 2, android::util::WAKELOCK_STATE_CHANGED, 333);
ValidateAttributionUidAndTagDimension(
data.dimensions_in_what(), 2, android::util::WAKELOCK_STATE_CHANGED, 333, "App3");
EXPECT_EQ(data.bucket_info_size(), 1);
EXPECT_EQ(data.bucket_info(0).count(), 1);
EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
data.bucket_info(0).start_bucket_elapsed_nanos());
EXPECT_EQ(bucketStartTimeNs + 3 * bucketSizeNs,
data.bucket_info(0).end_bucket_elapsed_nanos());
}
// TODO(b/149590301): Update these tests to use new socket schema.
//TEST(AttributionE2eTest, TestAttributionMatchAndSliceByFirstUid) {
// auto config = CreateStatsdConfig(Position::FIRST);
// int64_t bucketStartTimeNs = 10000000000;
// int64_t bucketSizeNs =
// TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000000;
//
// ConfigKey cfgKey;
// auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
// EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
// EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
//
// // Here it assumes that GMS core has two uids.
// processor->getUidMap()->updateMap(
// 1, {222, 444, 111, 333}, {1, 1, 2, 2},
// {String16("v1"), String16("v1"), String16("v2"), String16("v2")},
// {String16("com.android.gmscore"), String16("com.android.gmscore"), String16("app1"),
// String16("APP3")},
// {String16(""), String16(""), String16(""), String16("")});
//
// // GMS core node is in the middle.
// std::vector<AttributionNodeInternal> attributions1 = {CreateAttribution(111, "App1"),
// CreateAttribution(222, "GMSCoreModule1"),
// CreateAttribution(333, "App3")};
//
// // GMS core node is the last one.
// std::vector<AttributionNodeInternal> attributions2 = {CreateAttribution(111, "App1"),
// CreateAttribution(333, "App3"),
// CreateAttribution(222, "GMSCoreModule1")};
//
// // GMS core node is the first one.
// std::vector<AttributionNodeInternal> attributions3 = {CreateAttribution(222, "GMSCoreModule1"),
// CreateAttribution(333, "App3")};
//
// // Single GMS core node.
// std::vector<AttributionNodeInternal> attributions4 = {CreateAttribution(222, "GMSCoreModule1")};
//
// // GMS core has another uid.
// std::vector<AttributionNodeInternal> attributions5 = {CreateAttribution(111, "App1"),
// CreateAttribution(444, "GMSCoreModule2"),
// CreateAttribution(333, "App3")};
//
// // Multiple GMS core nodes.
// std::vector<AttributionNodeInternal> attributions6 = {CreateAttribution(444, "GMSCoreModule2"),
// CreateAttribution(222, "GMSCoreModule1")};
//
// // No GMS core nodes.
// std::vector<AttributionNodeInternal> attributions7 = {CreateAttribution(111, "App1"),
// CreateAttribution(333, "App3")};
// std::vector<AttributionNodeInternal> attributions8 = {CreateAttribution(111, "App1")};
//
// // GMS core node with isolated uid.
// const int isolatedUid = 666;
// std::vector<AttributionNodeInternal> attributions9 = {
// CreateAttribution(isolatedUid, "GMSCoreModule3")};
//
// std::vector<std::unique_ptr<LogEvent>> events;
// // Events 1~4 are in the 1st bucket.
// events.push_back(CreateAcquireWakelockEvent(
// attributions1, "wl1", bucketStartTimeNs + 2));
// events.push_back(CreateAcquireWakelockEvent(
// attributions2, "wl1", bucketStartTimeNs + 200));
// events.push_back(CreateAcquireWakelockEvent(
// attributions3, "wl1", bucketStartTimeNs + bucketSizeNs - 1));
// events.push_back(CreateAcquireWakelockEvent(
// attributions4, "wl1", bucketStartTimeNs + bucketSizeNs));
//
// // Events 5~8 are in the 3rd bucket.
// events.push_back(CreateAcquireWakelockEvent(
// attributions5, "wl2", bucketStartTimeNs + 2 * bucketSizeNs + 1));
// events.push_back(CreateAcquireWakelockEvent(
// attributions6, "wl2", bucketStartTimeNs + 2 * bucketSizeNs + 100));
// events.push_back(CreateAcquireWakelockEvent(
// attributions7, "wl2", bucketStartTimeNs + 3 * bucketSizeNs - 2));
// events.push_back(CreateAcquireWakelockEvent(
// attributions8, "wl2", bucketStartTimeNs + 3 * bucketSizeNs));
// events.push_back(CreateAcquireWakelockEvent(
// attributions9, "wl2", bucketStartTimeNs + 3 * bucketSizeNs + 1));
// events.push_back(CreateAcquireWakelockEvent(
// attributions9, "wl2", bucketStartTimeNs + 3 * bucketSizeNs + 100));
// events.push_back(CreateIsolatedUidChangedEvent(
// isolatedUid, 222, true/* is_create*/, bucketStartTimeNs + 3 * bucketSizeNs - 1));
// events.push_back(CreateIsolatedUidChangedEvent(
// isolatedUid, 222, false/* is_create*/, bucketStartTimeNs + 3 * bucketSizeNs + 10));
//
// sortLogEventsByTimestamp(&events);
//
// for (const auto& event : events) {
// processor->OnLogEvent(event.get());
// }
// ConfigMetricsReportList reports;
// vector<uint8_t> buffer;
// processor->onDumpReport(cfgKey, bucketStartTimeNs + 4 * bucketSizeNs + 1, false, true,
// ADB_DUMP, FAST, &buffer);
// EXPECT_TRUE(buffer.size() > 0);
// EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
// backfillDimensionPath(&reports);
// backfillStringInReport(&reports);
// backfillStartEndTimestamp(&reports);
// EXPECT_EQ(reports.reports_size(), 1);
// EXPECT_EQ(reports.reports(0).metrics_size(), 1);
//
// StatsLogReport::CountMetricDataWrapper countMetrics;
// sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).count_metrics(), &countMetrics);
// EXPECT_EQ(countMetrics.data_size(), 4);
//
// auto data = countMetrics.data(0);
// ValidateAttributionUidAndTagDimension(
// data.dimensions_in_what(), android::util::WAKELOCK_STATE_CHANGED, 111,
// "App1");
// EXPECT_EQ(data.bucket_info_size(), 2);
// EXPECT_EQ(data.bucket_info(0).count(), 2);
// EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs);
// EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), bucketStartTimeNs + bucketSizeNs);
// EXPECT_EQ(data.bucket_info(1).count(), 1);
// EXPECT_EQ(data.bucket_info(1).start_bucket_elapsed_nanos(), bucketStartTimeNs + 2 * bucketSizeNs);
// EXPECT_EQ(data.bucket_info(1).end_bucket_elapsed_nanos(), bucketStartTimeNs + 3 * bucketSizeNs);
//
// data = countMetrics.data(1);
// ValidateAttributionUidAndTagDimension(
// data.dimensions_in_what(), android::util::WAKELOCK_STATE_CHANGED, 222,
// "GMSCoreModule1");
// EXPECT_EQ(data.bucket_info_size(), 2);
// EXPECT_EQ(data.bucket_info(0).count(), 1);
// EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs);
// EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), bucketStartTimeNs + bucketSizeNs);
// EXPECT_EQ(data.bucket_info(1).count(), 1);
// EXPECT_EQ(data.bucket_info(1).start_bucket_elapsed_nanos(), bucketStartTimeNs + bucketSizeNs);
// EXPECT_EQ(data.bucket_info(1).end_bucket_elapsed_nanos(), bucketStartTimeNs + 2 * bucketSizeNs);
//
// data = countMetrics.data(2);
// ValidateAttributionUidAndTagDimension(
// data.dimensions_in_what(), android::util::WAKELOCK_STATE_CHANGED, 222,
// "GMSCoreModule3");
// EXPECT_EQ(data.bucket_info_size(), 1);
// EXPECT_EQ(data.bucket_info(0).count(), 1);
// EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs + 3 * bucketSizeNs);
// EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), bucketStartTimeNs + 4 * bucketSizeNs);
//
// data = countMetrics.data(3);
// ValidateAttributionUidAndTagDimension(
// data.dimensions_in_what(), android::util::WAKELOCK_STATE_CHANGED, 444,
// "GMSCoreModule2");
// EXPECT_EQ(data.bucket_info_size(), 1);
// EXPECT_EQ(data.bucket_info(0).count(), 1);
// EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs + 2 * bucketSizeNs);
// EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), bucketStartTimeNs + 3 * bucketSizeNs);
//}
//
//TEST(AttributionE2eTest, TestAttributionMatchAndSliceByChain) {
// auto config = CreateStatsdConfig(Position::ALL);
// int64_t bucketStartTimeNs = 10000000000;
// int64_t bucketSizeNs =
// TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000000;
//
// ConfigKey cfgKey;
// auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
// EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
// EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
//
// // Here it assumes that GMS core has two uids.
// processor->getUidMap()->updateMap(
// 1, {222, 444, 111, 333}, {1, 1, 2, 2},
// {String16("v1"), String16("v1"), String16("v2"), String16("v2")},
// {String16("com.android.gmscore"), String16("com.android.gmscore"), String16("app1"),
// String16("APP3")},
// {String16(""), String16(""), String16(""), String16("")});
//
// // GMS core node is in the middle.
// std::vector<AttributionNodeInternal> attributions1 = {CreateAttribution(111, "App1"),
// CreateAttribution(222, "GMSCoreModule1"),
// CreateAttribution(333, "App3")};
//
// // GMS core node is the last one.
// std::vector<AttributionNodeInternal> attributions2 = {CreateAttribution(111, "App1"),
// CreateAttribution(333, "App3"),
// CreateAttribution(222, "GMSCoreModule1")};
//
// // GMS core node is the first one.
// std::vector<AttributionNodeInternal> attributions3 = {CreateAttribution(222, "GMSCoreModule1"),
// CreateAttribution(333, "App3")};
//
// // Single GMS core node.
// std::vector<AttributionNodeInternal> attributions4 = {CreateAttribution(222, "GMSCoreModule1")};
//
// // GMS core has another uid.
// std::vector<AttributionNodeInternal> attributions5 = {CreateAttribution(111, "App1"),
// CreateAttribution(444, "GMSCoreModule2"),
// CreateAttribution(333, "App3")};
//
// // Multiple GMS core nodes.
// std::vector<AttributionNodeInternal> attributions6 = {CreateAttribution(444, "GMSCoreModule2"),
// CreateAttribution(222, "GMSCoreModule1")};
//
// // No GMS core nodes.
// std::vector<AttributionNodeInternal> attributions7 = {CreateAttribution(111, "App1"),
// CreateAttribution(333, "App3")};
// std::vector<AttributionNodeInternal> attributions8 = {CreateAttribution(111, "App1")};
//
// // GMS core node with isolated uid.
// const int isolatedUid = 666;
// std::vector<AttributionNodeInternal> attributions9 = {
// CreateAttribution(isolatedUid, "GMSCoreModule1")};
//
// std::vector<std::unique_ptr<LogEvent>> events;
// // Events 1~4 are in the 1st bucket.
// events.push_back(CreateAcquireWakelockEvent(
// attributions1, "wl1", bucketStartTimeNs + 2));
// events.push_back(CreateAcquireWakelockEvent(
// attributions2, "wl1", bucketStartTimeNs + 200));
// events.push_back(CreateAcquireWakelockEvent(
// attributions3, "wl1", bucketStartTimeNs + bucketSizeNs - 1));
// events.push_back(CreateAcquireWakelockEvent(
// attributions4, "wl1", bucketStartTimeNs + bucketSizeNs));
//
// // Events 5~8 are in the 3rd bucket.
// events.push_back(CreateAcquireWakelockEvent(
// attributions5, "wl2", bucketStartTimeNs + 2 * bucketSizeNs + 1));
// events.push_back(CreateAcquireWakelockEvent(
// attributions6, "wl2", bucketStartTimeNs + 2 * bucketSizeNs + 100));
// events.push_back(CreateAcquireWakelockEvent(
// attributions7, "wl2", bucketStartTimeNs + 3 * bucketSizeNs - 2));
// events.push_back(CreateAcquireWakelockEvent(
// attributions8, "wl2", bucketStartTimeNs + 3 * bucketSizeNs));
// events.push_back(CreateAcquireWakelockEvent(
// attributions9, "wl2", bucketStartTimeNs + 3 * bucketSizeNs + 1));
// events.push_back(CreateAcquireWakelockEvent(
// attributions9, "wl2", bucketStartTimeNs + 3 * bucketSizeNs + 100));
// events.push_back(CreateIsolatedUidChangedEvent(
// isolatedUid, 222, true/* is_create*/, bucketStartTimeNs + 3 * bucketSizeNs - 1));
// events.push_back(CreateIsolatedUidChangedEvent(
// isolatedUid, 222, false/* is_create*/, bucketStartTimeNs + 3 * bucketSizeNs + 10));
//
// sortLogEventsByTimestamp(&events);
//
// for (const auto& event : events) {
// processor->OnLogEvent(event.get());
// }
// ConfigMetricsReportList reports;
// vector<uint8_t> buffer;
// processor->onDumpReport(cfgKey, bucketStartTimeNs + 4 * bucketSizeNs + 1, false, true,
// ADB_DUMP, FAST, &buffer);
// EXPECT_TRUE(buffer.size() > 0);
// EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
// backfillDimensionPath(&reports);
// backfillStringInReport(&reports);
// backfillStartEndTimestamp(&reports);
// EXPECT_EQ(reports.reports_size(), 1);
// EXPECT_EQ(reports.reports(0).metrics_size(), 1);
//
// StatsLogReport::CountMetricDataWrapper countMetrics;
// sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).count_metrics(), &countMetrics);
// EXPECT_EQ(countMetrics.data_size(), 6);
//
// auto data = countMetrics.data(0);
// ValidateAttributionUidAndTagDimension(
// data.dimensions_in_what(), android::util::WAKELOCK_STATE_CHANGED, 222, "GMSCoreModule1");
// EXPECT_EQ(2, data.bucket_info_size());
// EXPECT_EQ(1, data.bucket_info(0).count());
// EXPECT_EQ(bucketStartTimeNs + bucketSizeNs,
// data.bucket_info(0).start_bucket_elapsed_nanos());
// EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
// data.bucket_info(0).end_bucket_elapsed_nanos());
// EXPECT_EQ(1, data.bucket_info(1).count());
// EXPECT_EQ(bucketStartTimeNs + 3 * bucketSizeNs,
// data.bucket_info(1).start_bucket_elapsed_nanos());
// EXPECT_EQ(bucketStartTimeNs + 4 * bucketSizeNs,
// data.bucket_info(1).end_bucket_elapsed_nanos());
//
// data = countMetrics.data(1);
// ValidateUidDimension(
// data.dimensions_in_what(), 0, android::util::WAKELOCK_STATE_CHANGED, 222);
// ValidateAttributionUidAndTagDimension(
// data.dimensions_in_what(), 0, android::util::WAKELOCK_STATE_CHANGED, 222, "GMSCoreModule1");
// ValidateUidDimension(
// data.dimensions_in_what(), 1, android::util::WAKELOCK_STATE_CHANGED, 333);
// ValidateAttributionUidAndTagDimension(
// data.dimensions_in_what(), 1, android::util::WAKELOCK_STATE_CHANGED, 333, "App3");
// EXPECT_EQ(data.bucket_info_size(), 1);
// EXPECT_EQ(data.bucket_info(0).count(), 1);
// EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs);
// EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), bucketStartTimeNs + bucketSizeNs);
//
// data = countMetrics.data(2);
// ValidateUidDimension(
// data.dimensions_in_what(), 0, android::util::WAKELOCK_STATE_CHANGED, 444);
// ValidateAttributionUidAndTagDimension(
// data.dimensions_in_what(), 0, android::util::WAKELOCK_STATE_CHANGED, 444, "GMSCoreModule2");
// ValidateUidDimension(
// data.dimensions_in_what(), 1, android::util::WAKELOCK_STATE_CHANGED, 222);
// ValidateAttributionUidAndTagDimension(
// data.dimensions_in_what(), 1, android::util::WAKELOCK_STATE_CHANGED, 222, "GMSCoreModule1");
// EXPECT_EQ(data.bucket_info_size(), 1);
// EXPECT_EQ(data.bucket_info(0).count(), 1);
// EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
// data.bucket_info(0).start_bucket_elapsed_nanos());
// EXPECT_EQ(bucketStartTimeNs + 3 * bucketSizeNs,
// data.bucket_info(0).end_bucket_elapsed_nanos());
//
// data = countMetrics.data(3);
// ValidateUidDimension(
// data.dimensions_in_what(), 0, android::util::WAKELOCK_STATE_CHANGED, 111);
// ValidateAttributionUidAndTagDimension(
// data.dimensions_in_what(), 0, android::util::WAKELOCK_STATE_CHANGED, 111, "App1");
// ValidateUidDimension(
// data.dimensions_in_what(), 1, android::util::WAKELOCK_STATE_CHANGED, 222);
// ValidateAttributionUidAndTagDimension(
// data.dimensions_in_what(), 1, android::util::WAKELOCK_STATE_CHANGED, 222, "GMSCoreModule1");
// ValidateUidDimension(
// data.dimensions_in_what(), 2, android::util::WAKELOCK_STATE_CHANGED, 333);
// ValidateAttributionUidAndTagDimension(
// data.dimensions_in_what(), 2, android::util::WAKELOCK_STATE_CHANGED, 333, "App3");
// EXPECT_EQ(data.bucket_info_size(), 1);
// EXPECT_EQ(data.bucket_info(0).count(), 1);
// EXPECT_EQ(bucketStartTimeNs,
// data.bucket_info(0).start_bucket_elapsed_nanos());
// EXPECT_EQ(bucketStartTimeNs + bucketSizeNs,
// data.bucket_info(0).end_bucket_elapsed_nanos());
//
// data = countMetrics.data(4);
// ValidateUidDimension(
// data.dimensions_in_what(), 0, android::util::WAKELOCK_STATE_CHANGED, 111);
// ValidateAttributionUidAndTagDimension(
// data.dimensions_in_what(), 0, android::util::WAKELOCK_STATE_CHANGED, 111, "App1");
// ValidateUidDimension(
// data.dimensions_in_what(), 1, android::util::WAKELOCK_STATE_CHANGED, 333);
// ValidateAttributionUidAndTagDimension(
// data.dimensions_in_what(), 1, android::util::WAKELOCK_STATE_CHANGED, 333, "App3");
// ValidateUidDimension(
// data.dimensions_in_what(), 2, android::util::WAKELOCK_STATE_CHANGED, 222);
// ValidateAttributionUidAndTagDimension(
// data.dimensions_in_what(), 2, android::util::WAKELOCK_STATE_CHANGED, 222, "GMSCoreModule1");
// EXPECT_EQ(data.bucket_info_size(), 1);
// EXPECT_EQ(data.bucket_info(0).count(), 1);
// EXPECT_EQ(bucketStartTimeNs,
// data.bucket_info(0).start_bucket_elapsed_nanos());
// EXPECT_EQ(bucketStartTimeNs + bucketSizeNs,
// data.bucket_info(0).end_bucket_elapsed_nanos());
//
// data = countMetrics.data(5);
// ValidateUidDimension(
// data.dimensions_in_what(), 0, android::util::WAKELOCK_STATE_CHANGED, 111);
// ValidateAttributionUidAndTagDimension(
// data.dimensions_in_what(), 0, android::util::WAKELOCK_STATE_CHANGED, 111, "App1");
// ValidateUidDimension(
// data.dimensions_in_what(), 1, android::util::WAKELOCK_STATE_CHANGED, 444);
// ValidateAttributionUidAndTagDimension(
// data.dimensions_in_what(), 1, android::util::WAKELOCK_STATE_CHANGED, 444, "GMSCoreModule2");
// ValidateUidDimension(
// data.dimensions_in_what(), 2, android::util::WAKELOCK_STATE_CHANGED, 333);
// ValidateAttributionUidAndTagDimension(
// data.dimensions_in_what(), 2, android::util::WAKELOCK_STATE_CHANGED, 333, "App3");
// EXPECT_EQ(data.bucket_info_size(), 1);
// EXPECT_EQ(data.bucket_info(0).count(), 1);
// EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
// data.bucket_info(0).start_bucket_elapsed_nanos());
// EXPECT_EQ(bucketStartTimeNs + 3 * bucketSizeNs,
// data.bucket_info(0).end_bucket_elapsed_nanos());
//}
#else
GTEST_LOG_(INFO) << "This test does nothing.\n";

View File

@@ -56,52 +56,53 @@ StatsdConfig CreateStatsdConfig(int num_buckets, int threshold) {
} // namespace
TEST(ConfigTtlE2eTest, TestCountMetric) {
const int num_buckets = 1;
const int threshold = 3;
auto config = CreateStatsdConfig(num_buckets, threshold);
const uint64_t alert_id = config.alert(0).id();
const uint32_t refractory_period_sec = config.alert(0).refractory_period_secs();
int64_t bucketStartTimeNs = 10000000000;
int64_t bucketSizeNs =
TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000000;
ConfigKey cfgKey;
auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
std::vector<AttributionNodeInternal> attributions1 = {CreateAttribution(111, "App1")};
FieldValue fieldValue1(Field(android::util::WAKELOCK_STATE_CHANGED, (int32_t)0x02010101),
Value((int32_t)111));
HashableDimensionKey whatKey1({fieldValue1});
MetricDimensionKey dimensionKey1(whatKey1, DEFAULT_DIMENSION_KEY);
FieldValue fieldValue2(Field(android::util::WAKELOCK_STATE_CHANGED, (int32_t)0x02010101),
Value((int32_t)222));
HashableDimensionKey whatKey2({fieldValue2});
MetricDimensionKey dimensionKey2(whatKey2, DEFAULT_DIMENSION_KEY);
auto event = CreateAcquireWakelockEvent(attributions1, "wl1", bucketStartTimeNs + 2);
processor->OnLogEvent(event.get());
event = CreateAcquireWakelockEvent(attributions1, "wl2", bucketStartTimeNs + bucketSizeNs + 2);
processor->OnLogEvent(event.get());
event = CreateAcquireWakelockEvent(
attributions1, "wl1", bucketStartTimeNs + 25 * bucketSizeNs + 2);
processor->OnLogEvent(event.get());
EXPECT_EQ((int64_t)(bucketStartTimeNs + 25 * bucketSizeNs + 2 + 2 * 3600 * NS_PER_SEC),
processor->mMetricsManagers.begin()->second->getTtlEndNs());
// Clear the data stored on disk as a result of the ttl.
vector<uint8_t> buffer;
processor->onDumpReport(cfgKey, bucketStartTimeNs + 25 * bucketSizeNs + 3, false, true,
ADB_DUMP, FAST, &buffer);
}
// TODO(b/149590301): Update this test to use new socket schema.
//TEST(ConfigTtlE2eTest, TestCountMetric) {
// const int num_buckets = 1;
// const int threshold = 3;
// auto config = CreateStatsdConfig(num_buckets, threshold);
// const uint64_t alert_id = config.alert(0).id();
// const uint32_t refractory_period_sec = config.alert(0).refractory_period_secs();
//
// int64_t bucketStartTimeNs = 10000000000;
// int64_t bucketSizeNs =
// TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000000;
//
// ConfigKey cfgKey;
// auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
// EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
// EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
//
// std::vector<AttributionNodeInternal> attributions1 = {CreateAttribution(111, "App1")};
//
// FieldValue fieldValue1(Field(android::util::WAKELOCK_STATE_CHANGED, (int32_t)0x02010101),
// Value((int32_t)111));
// HashableDimensionKey whatKey1({fieldValue1});
// MetricDimensionKey dimensionKey1(whatKey1, DEFAULT_DIMENSION_KEY);
//
// FieldValue fieldValue2(Field(android::util::WAKELOCK_STATE_CHANGED, (int32_t)0x02010101),
// Value((int32_t)222));
// HashableDimensionKey whatKey2({fieldValue2});
// MetricDimensionKey dimensionKey2(whatKey2, DEFAULT_DIMENSION_KEY);
//
// auto event = CreateAcquireWakelockEvent(attributions1, "wl1", bucketStartTimeNs + 2);
// processor->OnLogEvent(event.get());
//
// event = CreateAcquireWakelockEvent(attributions1, "wl2", bucketStartTimeNs + bucketSizeNs + 2);
// processor->OnLogEvent(event.get());
//
// event = CreateAcquireWakelockEvent(
// attributions1, "wl1", bucketStartTimeNs + 25 * bucketSizeNs + 2);
// processor->OnLogEvent(event.get());
//
// EXPECT_EQ((int64_t)(bucketStartTimeNs + 25 * bucketSizeNs + 2 + 2 * 3600 * NS_PER_SEC),
// processor->mMetricsManagers.begin()->second->getTtlEndNs());
//
// // Clear the data stored on disk as a result of the ttl.
// vector<uint8_t> buffer;
// processor->onDumpReport(cfgKey, bucketStartTimeNs + 25 * bucketSizeNs + 3, false, true,
// ADB_DUMP, FAST, &buffer);
//}
#else

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -63,483 +63,484 @@ StatsdConfig CreateStatsdConfig(const GaugeMetric::SamplingType sampling_type,
return config;
}
} // namespace
TEST(GaugeMetricE2eTest, TestRandomSamplePulledEvents) {
auto config = CreateStatsdConfig(GaugeMetric::RANDOM_ONE_SAMPLE);
int64_t baseTimeNs = getElapsedRealtimeNs();
int64_t configAddedTimeNs = 10 * 60 * NS_PER_SEC + baseTimeNs;
int64_t bucketSizeNs =
TimeUnitToBucketSizeInMillis(config.gauge_metric(0).bucket()) * 1000000;
ConfigKey cfgKey;
auto processor = CreateStatsLogProcessor(baseTimeNs, configAddedTimeNs, config, cfgKey,
SharedRefBase::make<FakeSubsystemSleepCallback>(),
ATOM_TAG);
EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
processor->mPullerManager->ForceClearPullerCache();
int startBucketNum = processor->mMetricsManagers.begin()->second->
mAllMetricProducers[0]->getCurrentBucketNum();
EXPECT_GT(startBucketNum, (int64_t)0);
// When creating the config, the gauge metric producer should register the alarm at the
// end of the current bucket.
EXPECT_EQ((size_t)1, processor->mPullerManager->mReceivers.size());
EXPECT_EQ(bucketSizeNs,
processor->mPullerManager->mReceivers.begin()->second.front().intervalNs);
int64_t& nextPullTimeNs =
processor->mPullerManager->mReceivers.begin()->second.front().nextPullTimeNs;
EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + bucketSizeNs, nextPullTimeNs);
auto screenOffEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
configAddedTimeNs + 55);
processor->OnLogEvent(screenOffEvent.get());
// Pulling alarm arrives on time and reset the sequential pulling alarm.
processor->informPullAlarmFired(nextPullTimeNs + 1);
EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 2 * bucketSizeNs, nextPullTimeNs);
auto screenOnEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
configAddedTimeNs + bucketSizeNs + 10);
processor->OnLogEvent(screenOnEvent.get());
screenOffEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
configAddedTimeNs + bucketSizeNs + 100);
processor->OnLogEvent(screenOffEvent.get());
processor->informPullAlarmFired(nextPullTimeNs + 1);
EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 3 * bucketSizeNs,
nextPullTimeNs);
processor->informPullAlarmFired(nextPullTimeNs + 1);
EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 4 * bucketSizeNs, nextPullTimeNs);
screenOnEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
configAddedTimeNs + 3 * bucketSizeNs + 2);
processor->OnLogEvent(screenOnEvent.get());
processor->informPullAlarmFired(nextPullTimeNs + 3);
EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 5 * bucketSizeNs, nextPullTimeNs);
screenOffEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
configAddedTimeNs + 5 * bucketSizeNs + 1);
processor->OnLogEvent(screenOffEvent.get());
processor->informPullAlarmFired(nextPullTimeNs + 2);
EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 6 * bucketSizeNs, nextPullTimeNs);
processor->informPullAlarmFired(nextPullTimeNs + 2);
ConfigMetricsReportList reports;
vector<uint8_t> buffer;
processor->onDumpReport(cfgKey, configAddedTimeNs + 7 * bucketSizeNs + 10, false, true,
ADB_DUMP, FAST, &buffer);
EXPECT_TRUE(buffer.size() > 0);
EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
backfillDimensionPath(&reports);
backfillStringInReport(&reports);
backfillStartEndTimestamp(&reports);
EXPECT_EQ(1, reports.reports_size());
EXPECT_EQ(1, reports.reports(0).metrics_size());
StatsLogReport::GaugeMetricDataWrapper gaugeMetrics;
sortMetricDataByDimensionsValue(
reports.reports(0).metrics(0).gauge_metrics(), &gaugeMetrics);
EXPECT_GT((int)gaugeMetrics.data_size(), 1);
auto data = gaugeMetrics.data(0);
EXPECT_EQ(ATOM_TAG, data.dimensions_in_what().field());
EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
EXPECT_EQ(1 /* subsystem name field */,
data.dimensions_in_what().value_tuple().dimensions_value(0).field());
EXPECT_FALSE(data.dimensions_in_what().value_tuple().dimensions_value(0).value_str().empty());
EXPECT_EQ(6, data.bucket_info_size());
EXPECT_EQ(1, data.bucket_info(0).atom_size());
EXPECT_EQ(1, data.bucket_info(0).elapsed_timestamp_nanos_size());
EXPECT_EQ(configAddedTimeNs + 55, data.bucket_info(0).elapsed_timestamp_nanos(0));
EXPECT_EQ(0, data.bucket_info(0).wall_clock_timestamp_nanos_size());
EXPECT_EQ(baseTimeNs + 2 * bucketSizeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
EXPECT_TRUE(data.bucket_info(0).atom(0).subsystem_sleep_state().subsystem_name().empty());
EXPECT_GT(data.bucket_info(0).atom(0).subsystem_sleep_state().time_millis(), 0);
EXPECT_EQ(1, data.bucket_info(1).atom_size());
EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs + 1,
data.bucket_info(1).elapsed_timestamp_nanos(0));
EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs + 1, data.bucket_info(1).elapsed_timestamp_nanos(0));
EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs, data.bucket_info(1).start_bucket_elapsed_nanos());
EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs, data.bucket_info(1).end_bucket_elapsed_nanos());
EXPECT_TRUE(data.bucket_info(1).atom(0).subsystem_sleep_state().subsystem_name().empty());
EXPECT_GT(data.bucket_info(1).atom(0).subsystem_sleep_state().time_millis(), 0);
EXPECT_EQ(1, data.bucket_info(2).atom_size());
EXPECT_EQ(1, data.bucket_info(2).elapsed_timestamp_nanos_size());
EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs + 1,
data.bucket_info(2).elapsed_timestamp_nanos(0));
EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs, data.bucket_info(2).start_bucket_elapsed_nanos());
EXPECT_EQ(baseTimeNs + 5 * bucketSizeNs, data.bucket_info(2).end_bucket_elapsed_nanos());
EXPECT_TRUE(data.bucket_info(2).atom(0).subsystem_sleep_state().subsystem_name().empty());
EXPECT_GT(data.bucket_info(2).atom(0).subsystem_sleep_state().time_millis(), 0);
EXPECT_EQ(1, data.bucket_info(3).atom_size());
EXPECT_EQ(1, data.bucket_info(3).elapsed_timestamp_nanos_size());
EXPECT_EQ(baseTimeNs + 5 * bucketSizeNs + 1,
data.bucket_info(3).elapsed_timestamp_nanos(0));
EXPECT_EQ(baseTimeNs + 5 * bucketSizeNs, data.bucket_info(3).start_bucket_elapsed_nanos());
EXPECT_EQ(baseTimeNs + 6 * bucketSizeNs, data.bucket_info(3).end_bucket_elapsed_nanos());
EXPECT_TRUE(data.bucket_info(3).atom(0).subsystem_sleep_state().subsystem_name().empty());
EXPECT_GT(data.bucket_info(3).atom(0).subsystem_sleep_state().time_millis(), 0);
EXPECT_EQ(1, data.bucket_info(4).atom_size());
EXPECT_EQ(1, data.bucket_info(4).elapsed_timestamp_nanos_size());
EXPECT_EQ(baseTimeNs + 7 * bucketSizeNs + 1,
data.bucket_info(4).elapsed_timestamp_nanos(0));
EXPECT_EQ(baseTimeNs + 7 * bucketSizeNs, data.bucket_info(4).start_bucket_elapsed_nanos());
EXPECT_EQ(baseTimeNs + 8 * bucketSizeNs, data.bucket_info(4).end_bucket_elapsed_nanos());
EXPECT_TRUE(data.bucket_info(4).atom(0).subsystem_sleep_state().subsystem_name().empty());
EXPECT_GT(data.bucket_info(4).atom(0).subsystem_sleep_state().time_millis(), 0);
EXPECT_EQ(1, data.bucket_info(5).atom_size());
EXPECT_EQ(1, data.bucket_info(5).elapsed_timestamp_nanos_size());
EXPECT_EQ(baseTimeNs + 8 * bucketSizeNs + 2,
data.bucket_info(5).elapsed_timestamp_nanos(0));
EXPECT_EQ(baseTimeNs + 8 * bucketSizeNs, data.bucket_info(5).start_bucket_elapsed_nanos());
EXPECT_EQ(baseTimeNs + 9 * bucketSizeNs, data.bucket_info(5).end_bucket_elapsed_nanos());
EXPECT_TRUE(data.bucket_info(5).atom(0).subsystem_sleep_state().subsystem_name().empty());
EXPECT_GT(data.bucket_info(5).atom(0).subsystem_sleep_state().time_millis(), 0);
}
TEST(GaugeMetricE2eTest, TestConditionChangeToTrueSamplePulledEvents) {
auto config = CreateStatsdConfig(GaugeMetric::CONDITION_CHANGE_TO_TRUE);
int64_t baseTimeNs = getElapsedRealtimeNs();
int64_t configAddedTimeNs = 10 * 60 * NS_PER_SEC + baseTimeNs;
int64_t bucketSizeNs =
TimeUnitToBucketSizeInMillis(config.gauge_metric(0).bucket()) * 1000000;
ConfigKey cfgKey;
auto processor = CreateStatsLogProcessor(baseTimeNs, configAddedTimeNs, config, cfgKey,
SharedRefBase::make<FakeSubsystemSleepCallback>(),
ATOM_TAG);
EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
processor->mPullerManager->ForceClearPullerCache();
int startBucketNum = processor->mMetricsManagers.begin()->second->
mAllMetricProducers[0]->getCurrentBucketNum();
EXPECT_GT(startBucketNum, (int64_t)0);
auto screenOffEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
configAddedTimeNs + 55);
processor->OnLogEvent(screenOffEvent.get());
auto screenOnEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
configAddedTimeNs + bucketSizeNs + 10);
processor->OnLogEvent(screenOnEvent.get());
screenOffEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
configAddedTimeNs + bucketSizeNs + 100);
processor->OnLogEvent(screenOffEvent.get());
screenOnEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
configAddedTimeNs + 3 * bucketSizeNs + 2);
processor->OnLogEvent(screenOnEvent.get());
screenOffEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
configAddedTimeNs + 5 * bucketSizeNs + 1);
processor->OnLogEvent(screenOffEvent.get());
screenOnEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
configAddedTimeNs + 5 * bucketSizeNs + 3);
processor->OnLogEvent(screenOnEvent.get());
screenOffEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
configAddedTimeNs + 5 * bucketSizeNs + 10);
processor->OnLogEvent(screenOffEvent.get());
ConfigMetricsReportList reports;
vector<uint8_t> buffer;
processor->onDumpReport(cfgKey, configAddedTimeNs + 8 * bucketSizeNs + 10, false, true,
ADB_DUMP, FAST, &buffer);
EXPECT_TRUE(buffer.size() > 0);
EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
backfillDimensionPath(&reports);
backfillStringInReport(&reports);
backfillStartEndTimestamp(&reports);
EXPECT_EQ(1, reports.reports_size());
EXPECT_EQ(1, reports.reports(0).metrics_size());
StatsLogReport::GaugeMetricDataWrapper gaugeMetrics;
sortMetricDataByDimensionsValue(
reports.reports(0).metrics(0).gauge_metrics(), &gaugeMetrics);
EXPECT_GT((int)gaugeMetrics.data_size(), 1);
auto data = gaugeMetrics.data(0);
EXPECT_EQ(ATOM_TAG, data.dimensions_in_what().field());
EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
EXPECT_EQ(1 /* subsystem name field */,
data.dimensions_in_what().value_tuple().dimensions_value(0).field());
EXPECT_FALSE(data.dimensions_in_what().value_tuple().dimensions_value(0).value_str().empty());
EXPECT_EQ(3, data.bucket_info_size());
EXPECT_EQ(1, data.bucket_info(0).atom_size());
EXPECT_EQ(1, data.bucket_info(0).elapsed_timestamp_nanos_size());
EXPECT_EQ(configAddedTimeNs + 55, data.bucket_info(0).elapsed_timestamp_nanos(0));
EXPECT_EQ(0, data.bucket_info(0).wall_clock_timestamp_nanos_size());
EXPECT_EQ(baseTimeNs + 2 * bucketSizeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
EXPECT_TRUE(data.bucket_info(0).atom(0).subsystem_sleep_state().subsystem_name().empty());
EXPECT_GT(data.bucket_info(0).atom(0).subsystem_sleep_state().time_millis(), 0);
EXPECT_EQ(1, data.bucket_info(1).atom_size());
EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs + 100,
data.bucket_info(1).elapsed_timestamp_nanos(0));
EXPECT_EQ(configAddedTimeNs + 55, data.bucket_info(0).elapsed_timestamp_nanos(0));
EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs, data.bucket_info(1).start_bucket_elapsed_nanos());
EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs, data.bucket_info(1).end_bucket_elapsed_nanos());
EXPECT_TRUE(data.bucket_info(1).atom(0).subsystem_sleep_state().subsystem_name().empty());
EXPECT_GT(data.bucket_info(1).atom(0).subsystem_sleep_state().time_millis(), 0);
EXPECT_EQ(2, data.bucket_info(2).atom_size());
EXPECT_EQ(2, data.bucket_info(2).elapsed_timestamp_nanos_size());
EXPECT_EQ(baseTimeNs + 7 * bucketSizeNs + 1,
data.bucket_info(2).elapsed_timestamp_nanos(0));
EXPECT_EQ(baseTimeNs + 7 * bucketSizeNs + 10,
data.bucket_info(2).elapsed_timestamp_nanos(1));
EXPECT_EQ(baseTimeNs + 7 * bucketSizeNs, data.bucket_info(2).start_bucket_elapsed_nanos());
EXPECT_EQ(baseTimeNs + 8 * bucketSizeNs, data.bucket_info(2).end_bucket_elapsed_nanos());
EXPECT_TRUE(data.bucket_info(2).atom(0).subsystem_sleep_state().subsystem_name().empty());
EXPECT_GT(data.bucket_info(2).atom(0).subsystem_sleep_state().time_millis(), 0);
EXPECT_TRUE(data.bucket_info(2).atom(1).subsystem_sleep_state().subsystem_name().empty());
EXPECT_GT(data.bucket_info(2).atom(1).subsystem_sleep_state().time_millis(), 0);
}
TEST(GaugeMetricE2eTest, TestRandomSamplePulledEvent_LateAlarm) {
auto config = CreateStatsdConfig(GaugeMetric::RANDOM_ONE_SAMPLE);
int64_t baseTimeNs = getElapsedRealtimeNs();
int64_t configAddedTimeNs = 10 * 60 * NS_PER_SEC + baseTimeNs;
int64_t bucketSizeNs =
TimeUnitToBucketSizeInMillis(config.gauge_metric(0).bucket()) * 1000000;
ConfigKey cfgKey;
auto processor = CreateStatsLogProcessor(baseTimeNs, configAddedTimeNs, config, cfgKey,
SharedRefBase::make<FakeSubsystemSleepCallback>(),
ATOM_TAG);
EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
processor->mPullerManager->ForceClearPullerCache();
int startBucketNum = processor->mMetricsManagers.begin()->second->
mAllMetricProducers[0]->getCurrentBucketNum();
EXPECT_GT(startBucketNum, (int64_t)0);
// When creating the config, the gauge metric producer should register the alarm at the
// end of the current bucket.
EXPECT_EQ((size_t)1, processor->mPullerManager->mReceivers.size());
EXPECT_EQ(bucketSizeNs,
processor->mPullerManager->mReceivers.begin()->second.front().intervalNs);
int64_t& nextPullTimeNs =
processor->mPullerManager->mReceivers.begin()->second.front().nextPullTimeNs;
EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + bucketSizeNs, nextPullTimeNs);
auto screenOffEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
configAddedTimeNs + 55);
processor->OnLogEvent(screenOffEvent.get());
auto screenOnEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
configAddedTimeNs + bucketSizeNs + 10);
processor->OnLogEvent(screenOnEvent.get());
// Pulling alarm arrives one bucket size late.
processor->informPullAlarmFired(nextPullTimeNs + bucketSizeNs);
EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 3 * bucketSizeNs, nextPullTimeNs);
screenOffEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
configAddedTimeNs + 3 * bucketSizeNs + 11);
processor->OnLogEvent(screenOffEvent.get());
// Pulling alarm arrives more than one bucket size late.
processor->informPullAlarmFired(nextPullTimeNs + bucketSizeNs + 12);
EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 5 * bucketSizeNs, nextPullTimeNs);
ConfigMetricsReportList reports;
vector<uint8_t> buffer;
processor->onDumpReport(cfgKey, configAddedTimeNs + 7 * bucketSizeNs + 10, false, true,
ADB_DUMP, FAST, &buffer);
EXPECT_TRUE(buffer.size() > 0);
EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
backfillDimensionPath(&reports);
backfillStringInReport(&reports);
backfillStartEndTimestamp(&reports);
EXPECT_EQ(1, reports.reports_size());
EXPECT_EQ(1, reports.reports(0).metrics_size());
StatsLogReport::GaugeMetricDataWrapper gaugeMetrics;
sortMetricDataByDimensionsValue(
reports.reports(0).metrics(0).gauge_metrics(), &gaugeMetrics);
EXPECT_GT((int)gaugeMetrics.data_size(), 1);
auto data = gaugeMetrics.data(0);
EXPECT_EQ(ATOM_TAG, data.dimensions_in_what().field());
EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
EXPECT_EQ(1 /* subsystem name field */,
data.dimensions_in_what().value_tuple().dimensions_value(0).field());
EXPECT_FALSE(data.dimensions_in_what().value_tuple().dimensions_value(0).value_str().empty());
EXPECT_EQ(3, data.bucket_info_size());
EXPECT_EQ(1, data.bucket_info(0).atom_size());
EXPECT_EQ(1, data.bucket_info(0).elapsed_timestamp_nanos_size());
EXPECT_EQ(configAddedTimeNs + 55, data.bucket_info(0).elapsed_timestamp_nanos(0));
EXPECT_EQ(baseTimeNs + 2 * bucketSizeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
EXPECT_TRUE(data.bucket_info(0).atom(0).subsystem_sleep_state().subsystem_name().empty());
EXPECT_GT(data.bucket_info(0).atom(0).subsystem_sleep_state().time_millis(), 0);
EXPECT_EQ(1, data.bucket_info(1).atom_size());
EXPECT_EQ(configAddedTimeNs + 3 * bucketSizeNs + 11,
data.bucket_info(1).elapsed_timestamp_nanos(0));
EXPECT_EQ(configAddedTimeNs + 55, data.bucket_info(0).elapsed_timestamp_nanos(0));
EXPECT_EQ(baseTimeNs + 5 * bucketSizeNs, data.bucket_info(1).start_bucket_elapsed_nanos());
EXPECT_EQ(baseTimeNs + 6 * bucketSizeNs, data.bucket_info(1).end_bucket_elapsed_nanos());
EXPECT_TRUE(data.bucket_info(1).atom(0).subsystem_sleep_state().subsystem_name().empty());
EXPECT_GT(data.bucket_info(1).atom(0).subsystem_sleep_state().time_millis(), 0);
EXPECT_EQ(1, data.bucket_info(2).atom_size());
EXPECT_EQ(1, data.bucket_info(2).elapsed_timestamp_nanos_size());
EXPECT_EQ(baseTimeNs + 6 * bucketSizeNs + 12,
data.bucket_info(2).elapsed_timestamp_nanos(0));
EXPECT_EQ(baseTimeNs + 6 * bucketSizeNs, data.bucket_info(2).start_bucket_elapsed_nanos());
EXPECT_EQ(baseTimeNs + 7 * bucketSizeNs, data.bucket_info(2).end_bucket_elapsed_nanos());
EXPECT_TRUE(data.bucket_info(2).atom(0).subsystem_sleep_state().subsystem_name().empty());
EXPECT_GT(data.bucket_info(2).atom(0).subsystem_sleep_state().time_millis(), 0);
}
TEST(GaugeMetricE2eTest, TestRandomSamplePulledEventsWithActivation) {
auto config = CreateStatsdConfig(GaugeMetric::RANDOM_ONE_SAMPLE, /*useCondition=*/false);
int64_t baseTimeNs = getElapsedRealtimeNs();
int64_t configAddedTimeNs = 10 * 60 * NS_PER_SEC + baseTimeNs;
int64_t bucketSizeNs =
TimeUnitToBucketSizeInMillis(config.gauge_metric(0).bucket()) * 1000000;
auto batterySaverStartMatcher = CreateBatterySaverModeStartAtomMatcher();
*config.add_atom_matcher() = batterySaverStartMatcher;
const int64_t ttlNs = 2 * bucketSizeNs; // Two buckets.
auto metric_activation = config.add_metric_activation();
metric_activation->set_metric_id(metricId);
metric_activation->set_activation_type(ACTIVATE_IMMEDIATELY);
auto event_activation = metric_activation->add_event_activation();
event_activation->set_atom_matcher_id(batterySaverStartMatcher.id());
event_activation->set_ttl_seconds(ttlNs / 1000000000);
ConfigKey cfgKey;
auto processor = CreateStatsLogProcessor(baseTimeNs, configAddedTimeNs, config, cfgKey,
SharedRefBase::make<FakeSubsystemSleepCallback>(),
ATOM_TAG);
EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
processor->mPullerManager->ForceClearPullerCache();
int startBucketNum = processor->mMetricsManagers.begin()->second->
mAllMetricProducers[0]->getCurrentBucketNum();
EXPECT_GT(startBucketNum, (int64_t)0);
EXPECT_FALSE(processor->mMetricsManagers.begin()->second->mAllMetricProducers[0]->isActive());
// When creating the config, the gauge metric producer should register the alarm at the
// end of the current bucket.
EXPECT_EQ((size_t)1, processor->mPullerManager->mReceivers.size());
EXPECT_EQ(bucketSizeNs,
processor->mPullerManager->mReceivers.begin()->second.front().intervalNs);
int64_t& nextPullTimeNs =
processor->mPullerManager->mReceivers.begin()->second.front().nextPullTimeNs;
EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + bucketSizeNs, nextPullTimeNs);
// Pulling alarm arrives on time and reset the sequential pulling alarm.
// Event should not be kept.
processor->informPullAlarmFired(nextPullTimeNs + 1); // 15 mins + 1 ns.
EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 2 * bucketSizeNs, nextPullTimeNs);
EXPECT_FALSE(processor->mMetricsManagers.begin()->second->mAllMetricProducers[0]->isActive());
// Activate the metric. A pull occurs upon activation.
const int64_t activationNs = configAddedTimeNs + bucketSizeNs + (2 * 1000 * 1000); // 2 millis.
auto batterySaverOnEvent = CreateBatterySaverOnEvent(activationNs);
processor->OnLogEvent(batterySaverOnEvent.get()); // 15 mins + 2 ms.
EXPECT_TRUE(processor->mMetricsManagers.begin()->second->mAllMetricProducers[0]->isActive());
// This event should be kept. 2 total.
processor->informPullAlarmFired(nextPullTimeNs + 1); // 20 mins + 1 ns.
EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 3 * bucketSizeNs,
nextPullTimeNs);
// This event should be kept. 3 total.
processor->informPullAlarmFired(nextPullTimeNs + 2); // 25 mins + 2 ns.
EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 4 * bucketSizeNs, nextPullTimeNs);
// Create random event to deactivate metric.
auto deactivationEvent = CreateScreenBrightnessChangedEvent(50, activationNs + ttlNs + 1);
processor->OnLogEvent(deactivationEvent.get());
EXPECT_FALSE(processor->mMetricsManagers.begin()->second->mAllMetricProducers[0]->isActive());
// Event should not be kept. 3 total.
processor->informPullAlarmFired(nextPullTimeNs + 3);
EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 5 * bucketSizeNs, nextPullTimeNs);
processor->informPullAlarmFired(nextPullTimeNs + 2);
ConfigMetricsReportList reports;
vector<uint8_t> buffer;
processor->onDumpReport(cfgKey, configAddedTimeNs + 7 * bucketSizeNs + 10, false, true,
ADB_DUMP, FAST, &buffer);
EXPECT_TRUE(buffer.size() > 0);
EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
backfillDimensionPath(&reports);
backfillStringInReport(&reports);
backfillStartEndTimestamp(&reports);
EXPECT_EQ(1, reports.reports_size());
EXPECT_EQ(1, reports.reports(0).metrics_size());
StatsLogReport::GaugeMetricDataWrapper gaugeMetrics;
sortMetricDataByDimensionsValue(
reports.reports(0).metrics(0).gauge_metrics(), &gaugeMetrics);
EXPECT_GT((int)gaugeMetrics.data_size(), 0);
auto data = gaugeMetrics.data(0);
EXPECT_EQ(ATOM_TAG, data.dimensions_in_what().field());
EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
EXPECT_EQ(1 /* subsystem name field */,
data.dimensions_in_what().value_tuple().dimensions_value(0).field());
EXPECT_FALSE(data.dimensions_in_what().value_tuple().dimensions_value(0).value_str().empty());
EXPECT_EQ(3, data.bucket_info_size());
auto bucketInfo = data.bucket_info(0);
EXPECT_EQ(1, bucketInfo.atom_size());
EXPECT_EQ(1, bucketInfo.elapsed_timestamp_nanos_size());
EXPECT_EQ(activationNs, bucketInfo.elapsed_timestamp_nanos(0));
EXPECT_EQ(0, bucketInfo.wall_clock_timestamp_nanos_size());
EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs, bucketInfo.start_bucket_elapsed_nanos());
EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs, bucketInfo.end_bucket_elapsed_nanos());
EXPECT_TRUE(bucketInfo.atom(0).subsystem_sleep_state().subsystem_name().empty());
EXPECT_GT(bucketInfo.atom(0).subsystem_sleep_state().time_millis(), 0);
bucketInfo = data.bucket_info(1);
EXPECT_EQ(1, bucketInfo.atom_size());
EXPECT_EQ(1, bucketInfo.elapsed_timestamp_nanos_size());
EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs + 1, bucketInfo.elapsed_timestamp_nanos(0));
EXPECT_EQ(0, bucketInfo.wall_clock_timestamp_nanos_size());
EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs, bucketInfo.start_bucket_elapsed_nanos());
EXPECT_EQ(baseTimeNs + 5 * bucketSizeNs, bucketInfo.end_bucket_elapsed_nanos());
EXPECT_TRUE(bucketInfo.atom(0).subsystem_sleep_state().subsystem_name().empty());
EXPECT_GT(bucketInfo.atom(0).subsystem_sleep_state().time_millis(), 0);
bucketInfo = data.bucket_info(2);
EXPECT_EQ(1, bucketInfo.atom_size());
EXPECT_EQ(1, bucketInfo.elapsed_timestamp_nanos_size());
EXPECT_EQ(baseTimeNs + 5 * bucketSizeNs + 2, bucketInfo.elapsed_timestamp_nanos(0));
EXPECT_EQ(0, bucketInfo.wall_clock_timestamp_nanos_size());
EXPECT_EQ(MillisToNano(NanoToMillis(baseTimeNs + 5 * bucketSizeNs)),
bucketInfo.start_bucket_elapsed_nanos());
EXPECT_EQ(MillisToNano(NanoToMillis(activationNs + ttlNs + 1)),
bucketInfo.end_bucket_elapsed_nanos());
EXPECT_TRUE(bucketInfo.atom(0).subsystem_sleep_state().subsystem_name().empty());
EXPECT_GT(bucketInfo.atom(0).subsystem_sleep_state().time_millis(), 0);
}
} // namespaces
// TODO(b/149590301): Update this test to use new socket schema.
//TEST(GaugeMetricE2eTest, TestRandomSamplePulledEvents) {
// auto config = CreateStatsdConfig(GaugeMetric::RANDOM_ONE_SAMPLE);
// int64_t baseTimeNs = getElapsedRealtimeNs();
// int64_t configAddedTimeNs = 10 * 60 * NS_PER_SEC + baseTimeNs;
// int64_t bucketSizeNs =
// TimeUnitToBucketSizeInMillis(config.gauge_metric(0).bucket()) * 1000000;
//
// ConfigKey cfgKey;
// auto processor = CreateStatsLogProcessor(baseTimeNs, configAddedTimeNs, config, cfgKey,
// SharedRefBase::make<FakeSubsystemSleepCallback>(),
// ATOM_TAG);
// EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
// EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
// processor->mPullerManager->ForceClearPullerCache();
//
// int startBucketNum = processor->mMetricsManagers.begin()->second->
// mAllMetricProducers[0]->getCurrentBucketNum();
// EXPECT_GT(startBucketNum, (int64_t)0);
//
// // When creating the config, the gauge metric producer should register the alarm at the
// // end of the current bucket.
// EXPECT_EQ((size_t)1, processor->mPullerManager->mReceivers.size());
// EXPECT_EQ(bucketSizeNs,
// processor->mPullerManager->mReceivers.begin()->second.front().intervalNs);
// int64_t& nextPullTimeNs =
// processor->mPullerManager->mReceivers.begin()->second.front().nextPullTimeNs;
// EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + bucketSizeNs, nextPullTimeNs);
//
// auto screenOffEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
// configAddedTimeNs + 55);
// processor->OnLogEvent(screenOffEvent.get());
//
// // Pulling alarm arrives on time and reset the sequential pulling alarm.
// processor->informPullAlarmFired(nextPullTimeNs + 1);
// EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 2 * bucketSizeNs, nextPullTimeNs);
//
// auto screenOnEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
// configAddedTimeNs + bucketSizeNs + 10);
// processor->OnLogEvent(screenOnEvent.get());
//
// screenOffEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
// configAddedTimeNs + bucketSizeNs + 100);
// processor->OnLogEvent(screenOffEvent.get());
//
// processor->informPullAlarmFired(nextPullTimeNs + 1);
// EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 3 * bucketSizeNs,
// nextPullTimeNs);
//
// processor->informPullAlarmFired(nextPullTimeNs + 1);
// EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 4 * bucketSizeNs, nextPullTimeNs);
//
// screenOnEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
// configAddedTimeNs + 3 * bucketSizeNs + 2);
// processor->OnLogEvent(screenOnEvent.get());
//
// processor->informPullAlarmFired(nextPullTimeNs + 3);
// EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 5 * bucketSizeNs, nextPullTimeNs);
//
// screenOffEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
// configAddedTimeNs + 5 * bucketSizeNs + 1);
// processor->OnLogEvent(screenOffEvent.get());
//
// processor->informPullAlarmFired(nextPullTimeNs + 2);
// EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 6 * bucketSizeNs, nextPullTimeNs);
//
// processor->informPullAlarmFired(nextPullTimeNs + 2);
//
// ConfigMetricsReportList reports;
// vector<uint8_t> buffer;
// processor->onDumpReport(cfgKey, configAddedTimeNs + 7 * bucketSizeNs + 10, false, true,
// ADB_DUMP, FAST, &buffer);
// EXPECT_TRUE(buffer.size() > 0);
// EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
// backfillDimensionPath(&reports);
// backfillStringInReport(&reports);
// backfillStartEndTimestamp(&reports);
// EXPECT_EQ(1, reports.reports_size());
// EXPECT_EQ(1, reports.reports(0).metrics_size());
// StatsLogReport::GaugeMetricDataWrapper gaugeMetrics;
// sortMetricDataByDimensionsValue(
// reports.reports(0).metrics(0).gauge_metrics(), &gaugeMetrics);
// EXPECT_GT((int)gaugeMetrics.data_size(), 1);
//
// auto data = gaugeMetrics.data(0);
// EXPECT_EQ(ATOM_TAG, data.dimensions_in_what().field());
// EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
// EXPECT_EQ(1 /* subsystem name field */,
// data.dimensions_in_what().value_tuple().dimensions_value(0).field());
// EXPECT_FALSE(data.dimensions_in_what().value_tuple().dimensions_value(0).value_str().empty());
// EXPECT_EQ(6, data.bucket_info_size());
//
// EXPECT_EQ(1, data.bucket_info(0).atom_size());
// EXPECT_EQ(1, data.bucket_info(0).elapsed_timestamp_nanos_size());
// EXPECT_EQ(configAddedTimeNs + 55, data.bucket_info(0).elapsed_timestamp_nanos(0));
// EXPECT_EQ(0, data.bucket_info(0).wall_clock_timestamp_nanos_size());
// EXPECT_EQ(baseTimeNs + 2 * bucketSizeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
// EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
// EXPECT_TRUE(data.bucket_info(0).atom(0).subsystem_sleep_state().subsystem_name().empty());
// EXPECT_GT(data.bucket_info(0).atom(0).subsystem_sleep_state().time_millis(), 0);
//
// EXPECT_EQ(1, data.bucket_info(1).atom_size());
// EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs + 1,
// data.bucket_info(1).elapsed_timestamp_nanos(0));
// EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs + 1, data.bucket_info(1).elapsed_timestamp_nanos(0));
// EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs, data.bucket_info(1).start_bucket_elapsed_nanos());
// EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs, data.bucket_info(1).end_bucket_elapsed_nanos());
// EXPECT_TRUE(data.bucket_info(1).atom(0).subsystem_sleep_state().subsystem_name().empty());
// EXPECT_GT(data.bucket_info(1).atom(0).subsystem_sleep_state().time_millis(), 0);
//
// EXPECT_EQ(1, data.bucket_info(2).atom_size());
// EXPECT_EQ(1, data.bucket_info(2).elapsed_timestamp_nanos_size());
// EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs + 1,
// data.bucket_info(2).elapsed_timestamp_nanos(0));
// EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs, data.bucket_info(2).start_bucket_elapsed_nanos());
// EXPECT_EQ(baseTimeNs + 5 * bucketSizeNs, data.bucket_info(2).end_bucket_elapsed_nanos());
// EXPECT_TRUE(data.bucket_info(2).atom(0).subsystem_sleep_state().subsystem_name().empty());
// EXPECT_GT(data.bucket_info(2).atom(0).subsystem_sleep_state().time_millis(), 0);
//
// EXPECT_EQ(1, data.bucket_info(3).atom_size());
// EXPECT_EQ(1, data.bucket_info(3).elapsed_timestamp_nanos_size());
// EXPECT_EQ(baseTimeNs + 5 * bucketSizeNs + 1,
// data.bucket_info(3).elapsed_timestamp_nanos(0));
// EXPECT_EQ(baseTimeNs + 5 * bucketSizeNs, data.bucket_info(3).start_bucket_elapsed_nanos());
// EXPECT_EQ(baseTimeNs + 6 * bucketSizeNs, data.bucket_info(3).end_bucket_elapsed_nanos());
// EXPECT_TRUE(data.bucket_info(3).atom(0).subsystem_sleep_state().subsystem_name().empty());
// EXPECT_GT(data.bucket_info(3).atom(0).subsystem_sleep_state().time_millis(), 0);
//
// EXPECT_EQ(1, data.bucket_info(4).atom_size());
// EXPECT_EQ(1, data.bucket_info(4).elapsed_timestamp_nanos_size());
// EXPECT_EQ(baseTimeNs + 7 * bucketSizeNs + 1,
// data.bucket_info(4).elapsed_timestamp_nanos(0));
// EXPECT_EQ(baseTimeNs + 7 * bucketSizeNs, data.bucket_info(4).start_bucket_elapsed_nanos());
// EXPECT_EQ(baseTimeNs + 8 * bucketSizeNs, data.bucket_info(4).end_bucket_elapsed_nanos());
// EXPECT_TRUE(data.bucket_info(4).atom(0).subsystem_sleep_state().subsystem_name().empty());
// EXPECT_GT(data.bucket_info(4).atom(0).subsystem_sleep_state().time_millis(), 0);
//
// EXPECT_EQ(1, data.bucket_info(5).atom_size());
// EXPECT_EQ(1, data.bucket_info(5).elapsed_timestamp_nanos_size());
// EXPECT_EQ(baseTimeNs + 8 * bucketSizeNs + 2,
// data.bucket_info(5).elapsed_timestamp_nanos(0));
// EXPECT_EQ(baseTimeNs + 8 * bucketSizeNs, data.bucket_info(5).start_bucket_elapsed_nanos());
// EXPECT_EQ(baseTimeNs + 9 * bucketSizeNs, data.bucket_info(5).end_bucket_elapsed_nanos());
// EXPECT_TRUE(data.bucket_info(5).atom(0).subsystem_sleep_state().subsystem_name().empty());
// EXPECT_GT(data.bucket_info(5).atom(0).subsystem_sleep_state().time_millis(), 0);
//}
//
//TEST(GaugeMetricE2eTest, TestConditionChangeToTrueSamplePulledEvents) {
// auto config = CreateStatsdConfig(GaugeMetric::CONDITION_CHANGE_TO_TRUE);
// int64_t baseTimeNs = getElapsedRealtimeNs();
// int64_t configAddedTimeNs = 10 * 60 * NS_PER_SEC + baseTimeNs;
// int64_t bucketSizeNs =
// TimeUnitToBucketSizeInMillis(config.gauge_metric(0).bucket()) * 1000000;
//
// ConfigKey cfgKey;
// auto processor = CreateStatsLogProcessor(baseTimeNs, configAddedTimeNs, config, cfgKey,
// SharedRefBase::make<FakeSubsystemSleepCallback>(),
// ATOM_TAG);
// EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
// EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
// processor->mPullerManager->ForceClearPullerCache();
//
// int startBucketNum = processor->mMetricsManagers.begin()->second->
// mAllMetricProducers[0]->getCurrentBucketNum();
// EXPECT_GT(startBucketNum, (int64_t)0);
//
// auto screenOffEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
// configAddedTimeNs + 55);
// processor->OnLogEvent(screenOffEvent.get());
//
// auto screenOnEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
// configAddedTimeNs + bucketSizeNs + 10);
// processor->OnLogEvent(screenOnEvent.get());
//
// screenOffEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
// configAddedTimeNs + bucketSizeNs + 100);
// processor->OnLogEvent(screenOffEvent.get());
//
// screenOnEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
// configAddedTimeNs + 3 * bucketSizeNs + 2);
// processor->OnLogEvent(screenOnEvent.get());
//
// screenOffEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
// configAddedTimeNs + 5 * bucketSizeNs + 1);
// processor->OnLogEvent(screenOffEvent.get());
// screenOnEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
// configAddedTimeNs + 5 * bucketSizeNs + 3);
// processor->OnLogEvent(screenOnEvent.get());
// screenOffEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
// configAddedTimeNs + 5 * bucketSizeNs + 10);
// processor->OnLogEvent(screenOffEvent.get());
//
// ConfigMetricsReportList reports;
// vector<uint8_t> buffer;
// processor->onDumpReport(cfgKey, configAddedTimeNs + 8 * bucketSizeNs + 10, false, true,
// ADB_DUMP, FAST, &buffer);
// EXPECT_TRUE(buffer.size() > 0);
// EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
// backfillDimensionPath(&reports);
// backfillStringInReport(&reports);
// backfillStartEndTimestamp(&reports);
// EXPECT_EQ(1, reports.reports_size());
// EXPECT_EQ(1, reports.reports(0).metrics_size());
// StatsLogReport::GaugeMetricDataWrapper gaugeMetrics;
// sortMetricDataByDimensionsValue(
// reports.reports(0).metrics(0).gauge_metrics(), &gaugeMetrics);
// EXPECT_GT((int)gaugeMetrics.data_size(), 1);
//
// auto data = gaugeMetrics.data(0);
// EXPECT_EQ(ATOM_TAG, data.dimensions_in_what().field());
// EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
// EXPECT_EQ(1 /* subsystem name field */,
// data.dimensions_in_what().value_tuple().dimensions_value(0).field());
// EXPECT_FALSE(data.dimensions_in_what().value_tuple().dimensions_value(0).value_str().empty());
// EXPECT_EQ(3, data.bucket_info_size());
//
// EXPECT_EQ(1, data.bucket_info(0).atom_size());
// EXPECT_EQ(1, data.bucket_info(0).elapsed_timestamp_nanos_size());
// EXPECT_EQ(configAddedTimeNs + 55, data.bucket_info(0).elapsed_timestamp_nanos(0));
// EXPECT_EQ(0, data.bucket_info(0).wall_clock_timestamp_nanos_size());
// EXPECT_EQ(baseTimeNs + 2 * bucketSizeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
// EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
// EXPECT_TRUE(data.bucket_info(0).atom(0).subsystem_sleep_state().subsystem_name().empty());
// EXPECT_GT(data.bucket_info(0).atom(0).subsystem_sleep_state().time_millis(), 0);
//
// EXPECT_EQ(1, data.bucket_info(1).atom_size());
// EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs + 100,
// data.bucket_info(1).elapsed_timestamp_nanos(0));
// EXPECT_EQ(configAddedTimeNs + 55, data.bucket_info(0).elapsed_timestamp_nanos(0));
// EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs, data.bucket_info(1).start_bucket_elapsed_nanos());
// EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs, data.bucket_info(1).end_bucket_elapsed_nanos());
// EXPECT_TRUE(data.bucket_info(1).atom(0).subsystem_sleep_state().subsystem_name().empty());
// EXPECT_GT(data.bucket_info(1).atom(0).subsystem_sleep_state().time_millis(), 0);
//
// EXPECT_EQ(2, data.bucket_info(2).atom_size());
// EXPECT_EQ(2, data.bucket_info(2).elapsed_timestamp_nanos_size());
// EXPECT_EQ(baseTimeNs + 7 * bucketSizeNs + 1,
// data.bucket_info(2).elapsed_timestamp_nanos(0));
// EXPECT_EQ(baseTimeNs + 7 * bucketSizeNs + 10,
// data.bucket_info(2).elapsed_timestamp_nanos(1));
// EXPECT_EQ(baseTimeNs + 7 * bucketSizeNs, data.bucket_info(2).start_bucket_elapsed_nanos());
// EXPECT_EQ(baseTimeNs + 8 * bucketSizeNs, data.bucket_info(2).end_bucket_elapsed_nanos());
// EXPECT_TRUE(data.bucket_info(2).atom(0).subsystem_sleep_state().subsystem_name().empty());
// EXPECT_GT(data.bucket_info(2).atom(0).subsystem_sleep_state().time_millis(), 0);
// EXPECT_TRUE(data.bucket_info(2).atom(1).subsystem_sleep_state().subsystem_name().empty());
// EXPECT_GT(data.bucket_info(2).atom(1).subsystem_sleep_state().time_millis(), 0);
//}
//
//
//TEST(GaugeMetricE2eTest, TestRandomSamplePulledEvent_LateAlarm) {
// auto config = CreateStatsdConfig(GaugeMetric::RANDOM_ONE_SAMPLE);
// int64_t baseTimeNs = getElapsedRealtimeNs();
// int64_t configAddedTimeNs = 10 * 60 * NS_PER_SEC + baseTimeNs;
// int64_t bucketSizeNs =
// TimeUnitToBucketSizeInMillis(config.gauge_metric(0).bucket()) * 1000000;
//
// ConfigKey cfgKey;
// auto processor = CreateStatsLogProcessor(baseTimeNs, configAddedTimeNs, config, cfgKey,
// SharedRefBase::make<FakeSubsystemSleepCallback>(),
// ATOM_TAG);
// EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
// EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
// processor->mPullerManager->ForceClearPullerCache();
//
// int startBucketNum = processor->mMetricsManagers.begin()->second->
// mAllMetricProducers[0]->getCurrentBucketNum();
// EXPECT_GT(startBucketNum, (int64_t)0);
//
// // When creating the config, the gauge metric producer should register the alarm at the
// // end of the current bucket.
// EXPECT_EQ((size_t)1, processor->mPullerManager->mReceivers.size());
// EXPECT_EQ(bucketSizeNs,
// processor->mPullerManager->mReceivers.begin()->second.front().intervalNs);
// int64_t& nextPullTimeNs =
// processor->mPullerManager->mReceivers.begin()->second.front().nextPullTimeNs;
// EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + bucketSizeNs, nextPullTimeNs);
//
// auto screenOffEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
// configAddedTimeNs + 55);
// processor->OnLogEvent(screenOffEvent.get());
//
// auto screenOnEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
// configAddedTimeNs + bucketSizeNs + 10);
// processor->OnLogEvent(screenOnEvent.get());
//
// // Pulling alarm arrives one bucket size late.
// processor->informPullAlarmFired(nextPullTimeNs + bucketSizeNs);
// EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 3 * bucketSizeNs, nextPullTimeNs);
//
// screenOffEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
// configAddedTimeNs + 3 * bucketSizeNs + 11);
// processor->OnLogEvent(screenOffEvent.get());
//
// // Pulling alarm arrives more than one bucket size late.
// processor->informPullAlarmFired(nextPullTimeNs + bucketSizeNs + 12);
// EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 5 * bucketSizeNs, nextPullTimeNs);
//
// ConfigMetricsReportList reports;
// vector<uint8_t> buffer;
// processor->onDumpReport(cfgKey, configAddedTimeNs + 7 * bucketSizeNs + 10, false, true,
// ADB_DUMP, FAST, &buffer);
// EXPECT_TRUE(buffer.size() > 0);
// EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
// backfillDimensionPath(&reports);
// backfillStringInReport(&reports);
// backfillStartEndTimestamp(&reports);
// EXPECT_EQ(1, reports.reports_size());
// EXPECT_EQ(1, reports.reports(0).metrics_size());
// StatsLogReport::GaugeMetricDataWrapper gaugeMetrics;
// sortMetricDataByDimensionsValue(
// reports.reports(0).metrics(0).gauge_metrics(), &gaugeMetrics);
// EXPECT_GT((int)gaugeMetrics.data_size(), 1);
//
// auto data = gaugeMetrics.data(0);
// EXPECT_EQ(ATOM_TAG, data.dimensions_in_what().field());
// EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
// EXPECT_EQ(1 /* subsystem name field */,
// data.dimensions_in_what().value_tuple().dimensions_value(0).field());
// EXPECT_FALSE(data.dimensions_in_what().value_tuple().dimensions_value(0).value_str().empty());
// EXPECT_EQ(3, data.bucket_info_size());
//
// EXPECT_EQ(1, data.bucket_info(0).atom_size());
// EXPECT_EQ(1, data.bucket_info(0).elapsed_timestamp_nanos_size());
// EXPECT_EQ(configAddedTimeNs + 55, data.bucket_info(0).elapsed_timestamp_nanos(0));
// EXPECT_EQ(baseTimeNs + 2 * bucketSizeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
// EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
// EXPECT_TRUE(data.bucket_info(0).atom(0).subsystem_sleep_state().subsystem_name().empty());
// EXPECT_GT(data.bucket_info(0).atom(0).subsystem_sleep_state().time_millis(), 0);
//
// EXPECT_EQ(1, data.bucket_info(1).atom_size());
// EXPECT_EQ(configAddedTimeNs + 3 * bucketSizeNs + 11,
// data.bucket_info(1).elapsed_timestamp_nanos(0));
// EXPECT_EQ(configAddedTimeNs + 55, data.bucket_info(0).elapsed_timestamp_nanos(0));
// EXPECT_EQ(baseTimeNs + 5 * bucketSizeNs, data.bucket_info(1).start_bucket_elapsed_nanos());
// EXPECT_EQ(baseTimeNs + 6 * bucketSizeNs, data.bucket_info(1).end_bucket_elapsed_nanos());
// EXPECT_TRUE(data.bucket_info(1).atom(0).subsystem_sleep_state().subsystem_name().empty());
// EXPECT_GT(data.bucket_info(1).atom(0).subsystem_sleep_state().time_millis(), 0);
//
// EXPECT_EQ(1, data.bucket_info(2).atom_size());
// EXPECT_EQ(1, data.bucket_info(2).elapsed_timestamp_nanos_size());
// EXPECT_EQ(baseTimeNs + 6 * bucketSizeNs + 12,
// data.bucket_info(2).elapsed_timestamp_nanos(0));
// EXPECT_EQ(baseTimeNs + 6 * bucketSizeNs, data.bucket_info(2).start_bucket_elapsed_nanos());
// EXPECT_EQ(baseTimeNs + 7 * bucketSizeNs, data.bucket_info(2).end_bucket_elapsed_nanos());
// EXPECT_TRUE(data.bucket_info(2).atom(0).subsystem_sleep_state().subsystem_name().empty());
// EXPECT_GT(data.bucket_info(2).atom(0).subsystem_sleep_state().time_millis(), 0);
//}
//
//TEST(GaugeMetricE2eTest, TestRandomSamplePulledEventsWithActivation) {
// auto config = CreateStatsdConfig(GaugeMetric::RANDOM_ONE_SAMPLE, /*useCondition=*/false);
//
// int64_t baseTimeNs = getElapsedRealtimeNs();
// int64_t configAddedTimeNs = 10 * 60 * NS_PER_SEC + baseTimeNs;
// int64_t bucketSizeNs =
// TimeUnitToBucketSizeInMillis(config.gauge_metric(0).bucket()) * 1000000;
//
// auto batterySaverStartMatcher = CreateBatterySaverModeStartAtomMatcher();
// *config.add_atom_matcher() = batterySaverStartMatcher;
// const int64_t ttlNs = 2 * bucketSizeNs; // Two buckets.
// auto metric_activation = config.add_metric_activation();
// metric_activation->set_metric_id(metricId);
// metric_activation->set_activation_type(ACTIVATE_IMMEDIATELY);
// auto event_activation = metric_activation->add_event_activation();
// event_activation->set_atom_matcher_id(batterySaverStartMatcher.id());
// event_activation->set_ttl_seconds(ttlNs / 1000000000);
//
// ConfigKey cfgKey;
// auto processor = CreateStatsLogProcessor(baseTimeNs, configAddedTimeNs, config, cfgKey,
// SharedRefBase::make<FakeSubsystemSleepCallback>(),
// ATOM_TAG);
// EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
// EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
// processor->mPullerManager->ForceClearPullerCache();
//
// int startBucketNum = processor->mMetricsManagers.begin()->second->
// mAllMetricProducers[0]->getCurrentBucketNum();
// EXPECT_GT(startBucketNum, (int64_t)0);
// EXPECT_FALSE(processor->mMetricsManagers.begin()->second->mAllMetricProducers[0]->isActive());
//
// // When creating the config, the gauge metric producer should register the alarm at the
// // end of the current bucket.
// EXPECT_EQ((size_t)1, processor->mPullerManager->mReceivers.size());
// EXPECT_EQ(bucketSizeNs,
// processor->mPullerManager->mReceivers.begin()->second.front().intervalNs);
// int64_t& nextPullTimeNs =
// processor->mPullerManager->mReceivers.begin()->second.front().nextPullTimeNs;
// EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + bucketSizeNs, nextPullTimeNs);
//
// // Pulling alarm arrives on time and reset the sequential pulling alarm.
// // Event should not be kept.
// processor->informPullAlarmFired(nextPullTimeNs + 1); // 15 mins + 1 ns.
// EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 2 * bucketSizeNs, nextPullTimeNs);
// EXPECT_FALSE(processor->mMetricsManagers.begin()->second->mAllMetricProducers[0]->isActive());
//
// // Activate the metric. A pull occurs upon activation.
// const int64_t activationNs = configAddedTimeNs + bucketSizeNs + (2 * 1000 * 1000); // 2 millis.
// auto batterySaverOnEvent = CreateBatterySaverOnEvent(activationNs);
// processor->OnLogEvent(batterySaverOnEvent.get()); // 15 mins + 2 ms.
// EXPECT_TRUE(processor->mMetricsManagers.begin()->second->mAllMetricProducers[0]->isActive());
//
// // This event should be kept. 2 total.
// processor->informPullAlarmFired(nextPullTimeNs + 1); // 20 mins + 1 ns.
// EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 3 * bucketSizeNs,
// nextPullTimeNs);
//
// // This event should be kept. 3 total.
// processor->informPullAlarmFired(nextPullTimeNs + 2); // 25 mins + 2 ns.
// EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 4 * bucketSizeNs, nextPullTimeNs);
//
// // Create random event to deactivate metric.
// auto deactivationEvent = CreateScreenBrightnessChangedEvent(50, activationNs + ttlNs + 1);
// processor->OnLogEvent(deactivationEvent.get());
// EXPECT_FALSE(processor->mMetricsManagers.begin()->second->mAllMetricProducers[0]->isActive());
//
// // Event should not be kept. 3 total.
// processor->informPullAlarmFired(nextPullTimeNs + 3);
// EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 5 * bucketSizeNs, nextPullTimeNs);
//
// processor->informPullAlarmFired(nextPullTimeNs + 2);
//
// ConfigMetricsReportList reports;
// vector<uint8_t> buffer;
// processor->onDumpReport(cfgKey, configAddedTimeNs + 7 * bucketSizeNs + 10, false, true,
// ADB_DUMP, FAST, &buffer);
// EXPECT_TRUE(buffer.size() > 0);
// EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
// backfillDimensionPath(&reports);
// backfillStringInReport(&reports);
// backfillStartEndTimestamp(&reports);
// EXPECT_EQ(1, reports.reports_size());
// EXPECT_EQ(1, reports.reports(0).metrics_size());
// StatsLogReport::GaugeMetricDataWrapper gaugeMetrics;
// sortMetricDataByDimensionsValue(
// reports.reports(0).metrics(0).gauge_metrics(), &gaugeMetrics);
// EXPECT_GT((int)gaugeMetrics.data_size(), 0);
//
// auto data = gaugeMetrics.data(0);
// EXPECT_EQ(ATOM_TAG, data.dimensions_in_what().field());
// EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
// EXPECT_EQ(1 /* subsystem name field */,
// data.dimensions_in_what().value_tuple().dimensions_value(0).field());
// EXPECT_FALSE(data.dimensions_in_what().value_tuple().dimensions_value(0).value_str().empty());
// EXPECT_EQ(3, data.bucket_info_size());
//
// auto bucketInfo = data.bucket_info(0);
// EXPECT_EQ(1, bucketInfo.atom_size());
// EXPECT_EQ(1, bucketInfo.elapsed_timestamp_nanos_size());
// EXPECT_EQ(activationNs, bucketInfo.elapsed_timestamp_nanos(0));
// EXPECT_EQ(0, bucketInfo.wall_clock_timestamp_nanos_size());
// EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs, bucketInfo.start_bucket_elapsed_nanos());
// EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs, bucketInfo.end_bucket_elapsed_nanos());
// EXPECT_TRUE(bucketInfo.atom(0).subsystem_sleep_state().subsystem_name().empty());
// EXPECT_GT(bucketInfo.atom(0).subsystem_sleep_state().time_millis(), 0);
//
// bucketInfo = data.bucket_info(1);
// EXPECT_EQ(1, bucketInfo.atom_size());
// EXPECT_EQ(1, bucketInfo.elapsed_timestamp_nanos_size());
// EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs + 1, bucketInfo.elapsed_timestamp_nanos(0));
// EXPECT_EQ(0, bucketInfo.wall_clock_timestamp_nanos_size());
// EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs, bucketInfo.start_bucket_elapsed_nanos());
// EXPECT_EQ(baseTimeNs + 5 * bucketSizeNs, bucketInfo.end_bucket_elapsed_nanos());
// EXPECT_TRUE(bucketInfo.atom(0).subsystem_sleep_state().subsystem_name().empty());
// EXPECT_GT(bucketInfo.atom(0).subsystem_sleep_state().time_millis(), 0);
//
// bucketInfo = data.bucket_info(2);
// EXPECT_EQ(1, bucketInfo.atom_size());
// EXPECT_EQ(1, bucketInfo.elapsed_timestamp_nanos_size());
// EXPECT_EQ(baseTimeNs + 5 * bucketSizeNs + 2, bucketInfo.elapsed_timestamp_nanos(0));
// EXPECT_EQ(0, bucketInfo.wall_clock_timestamp_nanos_size());
// EXPECT_EQ(MillisToNano(NanoToMillis(baseTimeNs + 5 * bucketSizeNs)),
// bucketInfo.start_bucket_elapsed_nanos());
// EXPECT_EQ(MillisToNano(NanoToMillis(activationNs + ttlNs + 1)),
// bucketInfo.end_bucket_elapsed_nanos());
// EXPECT_TRUE(bucketInfo.atom(0).subsystem_sleep_state().subsystem_name().empty());
// EXPECT_GT(bucketInfo.atom(0).subsystem_sleep_state().time_millis(), 0);
//}
TEST(GaugeMetricE2eTest, TestRandomSamplePulledEventsNoCondition) {
auto config = CreateStatsdConfig(GaugeMetric::RANDOM_ONE_SAMPLE, /*useCondition=*/false);

View File

@@ -68,219 +68,221 @@ StatsdConfig CreateStatsdConfigForPushedEvent(const GaugeMetric::SamplingType sa
return config;
}
std::unique_ptr<LogEvent> CreateAppStartOccurredEvent(
const int uid, const string& pkg_name, AppStartOccurred::TransitionType type,
const string& activity_name, const string& calling_pkg_name, const bool is_instant_app,
int64_t activity_start_msec, uint64_t timestampNs) {
auto logEvent = std::make_unique<LogEvent>(
android::util::APP_START_OCCURRED, timestampNs);
logEvent->write(uid);
logEvent->write(pkg_name);
logEvent->write(type);
logEvent->write(activity_name);
logEvent->write(calling_pkg_name);
logEvent->write(is_instant_app);
logEvent->write(activity_start_msec);
logEvent->init();
return logEvent;
}
// TODO(b/149590301): Update this helper to use new socket schema.
//std::unique_ptr<LogEvent> CreateAppStartOccurredEvent(
// const int uid, const string& pkg_name, AppStartOccurred::TransitionType type,
// const string& activity_name, const string& calling_pkg_name, const bool is_instant_app,
// int64_t activity_start_msec, uint64_t timestampNs) {
// auto logEvent = std::make_unique<LogEvent>(
// android::util::APP_START_OCCURRED, timestampNs);
// logEvent->write(uid);
// logEvent->write(pkg_name);
// logEvent->write(type);
// logEvent->write(activity_name);
// logEvent->write(calling_pkg_name);
// logEvent->write(is_instant_app);
// logEvent->write(activity_start_msec);
// logEvent->init();
// return logEvent;
//}
} // namespace
TEST(GaugeMetricE2eTest, TestMultipleFieldsForPushedEvent) {
for (const auto& sampling_type :
{ GaugeMetric::FIRST_N_SAMPLES, GaugeMetric:: RANDOM_ONE_SAMPLE }) {
auto config = CreateStatsdConfigForPushedEvent(sampling_type);
int64_t bucketStartTimeNs = 10000000000;
int64_t bucketSizeNs =
TimeUnitToBucketSizeInMillis(config.gauge_metric(0).bucket()) * 1000000;
ConfigKey cfgKey;
auto processor = CreateStatsLogProcessor(
bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
int appUid1 = 123;
int appUid2 = 456;
std::vector<std::unique_ptr<LogEvent>> events;
events.push_back(CreateMoveToBackgroundEvent(appUid1, bucketStartTimeNs + 15));
events.push_back(CreateMoveToForegroundEvent(
appUid1, bucketStartTimeNs + bucketSizeNs + 250));
events.push_back(CreateMoveToBackgroundEvent(
appUid1, bucketStartTimeNs + bucketSizeNs + 350));
events.push_back(CreateMoveToForegroundEvent(
appUid1, bucketStartTimeNs + 2 * bucketSizeNs + 100));
events.push_back(CreateAppStartOccurredEvent(
appUid1, "app1", AppStartOccurred::WARM, "activity_name1", "calling_pkg_name1",
true /*is_instant_app*/, 101 /*activity_start_msec*/, bucketStartTimeNs + 10));
events.push_back(CreateAppStartOccurredEvent(
appUid1, "app1", AppStartOccurred::HOT, "activity_name2", "calling_pkg_name2",
true /*is_instant_app*/, 102 /*activity_start_msec*/, bucketStartTimeNs + 20));
events.push_back(CreateAppStartOccurredEvent(
appUid1, "app1", AppStartOccurred::COLD, "activity_name3", "calling_pkg_name3",
true /*is_instant_app*/, 103 /*activity_start_msec*/, bucketStartTimeNs + 30));
events.push_back(CreateAppStartOccurredEvent(
appUid1, "app1", AppStartOccurred::WARM, "activity_name4", "calling_pkg_name4",
true /*is_instant_app*/, 104 /*activity_start_msec*/,
bucketStartTimeNs + bucketSizeNs + 30));
events.push_back(CreateAppStartOccurredEvent(
appUid1, "app1", AppStartOccurred::COLD, "activity_name5", "calling_pkg_name5",
true /*is_instant_app*/, 105 /*activity_start_msec*/,
bucketStartTimeNs + 2 * bucketSizeNs));
events.push_back(CreateAppStartOccurredEvent(
appUid1, "app1", AppStartOccurred::HOT, "activity_name6", "calling_pkg_name6",
false /*is_instant_app*/, 106 /*activity_start_msec*/,
bucketStartTimeNs + 2 * bucketSizeNs + 10));
events.push_back(CreateMoveToBackgroundEvent(
appUid2, bucketStartTimeNs + bucketSizeNs + 10));
events.push_back(CreateAppStartOccurredEvent(
appUid2, "app2", AppStartOccurred::COLD, "activity_name7", "calling_pkg_name7",
true /*is_instant_app*/, 201 /*activity_start_msec*/,
bucketStartTimeNs + 2 * bucketSizeNs + 10));
sortLogEventsByTimestamp(&events);
for (const auto& event : events) {
processor->OnLogEvent(event.get());
}
ConfigMetricsReportList reports;
vector<uint8_t> buffer;
processor->onDumpReport(cfgKey, bucketStartTimeNs + 3 * bucketSizeNs, false, true,
ADB_DUMP, FAST, &buffer);
EXPECT_TRUE(buffer.size() > 0);
EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
backfillDimensionPath(&reports);
backfillStringInReport(&reports);
backfillStartEndTimestamp(&reports);
EXPECT_EQ(1, reports.reports_size());
EXPECT_EQ(1, reports.reports(0).metrics_size());
StatsLogReport::GaugeMetricDataWrapper gaugeMetrics;
sortMetricDataByDimensionsValue(
reports.reports(0).metrics(0).gauge_metrics(), &gaugeMetrics);
EXPECT_EQ(2, gaugeMetrics.data_size());
auto data = gaugeMetrics.data(0);
EXPECT_EQ(android::util::APP_START_OCCURRED, data.dimensions_in_what().field());
EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
EXPECT_EQ(1 /* uid field */,
data.dimensions_in_what().value_tuple().dimensions_value(0).field());
EXPECT_EQ(appUid1, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
EXPECT_EQ(3, data.bucket_info_size());
if (sampling_type == GaugeMetric::FIRST_N_SAMPLES) {
EXPECT_EQ(2, data.bucket_info(0).atom_size());
EXPECT_EQ(2, data.bucket_info(0).elapsed_timestamp_nanos_size());
EXPECT_EQ(0, data.bucket_info(0).wall_clock_timestamp_nanos_size());
EXPECT_EQ(bucketStartTimeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
EXPECT_EQ(bucketStartTimeNs + bucketSizeNs,
data.bucket_info(0).end_bucket_elapsed_nanos());
EXPECT_EQ(AppStartOccurred::HOT,
data.bucket_info(0).atom(0).app_start_occurred().type());
EXPECT_EQ("activity_name2",
data.bucket_info(0).atom(0).app_start_occurred().activity_name());
EXPECT_EQ(102L,
data.bucket_info(0).atom(0).app_start_occurred().activity_start_millis());
EXPECT_EQ(AppStartOccurred::COLD,
data.bucket_info(0).atom(1).app_start_occurred().type());
EXPECT_EQ("activity_name3",
data.bucket_info(0).atom(1).app_start_occurred().activity_name());
EXPECT_EQ(103L,
data.bucket_info(0).atom(1).app_start_occurred().activity_start_millis());
EXPECT_EQ(1, data.bucket_info(1).atom_size());
EXPECT_EQ(1, data.bucket_info(1).elapsed_timestamp_nanos_size());
EXPECT_EQ(bucketStartTimeNs + bucketSizeNs,
data.bucket_info(1).start_bucket_elapsed_nanos());
EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
data.bucket_info(1).end_bucket_elapsed_nanos());
EXPECT_EQ(AppStartOccurred::WARM,
data.bucket_info(1).atom(0).app_start_occurred().type());
EXPECT_EQ("activity_name4",
data.bucket_info(1).atom(0).app_start_occurred().activity_name());
EXPECT_EQ(104L,
data.bucket_info(1).atom(0).app_start_occurred().activity_start_millis());
EXPECT_EQ(2, data.bucket_info(2).atom_size());
EXPECT_EQ(2, data.bucket_info(2).elapsed_timestamp_nanos_size());
EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
data.bucket_info(2).start_bucket_elapsed_nanos());
EXPECT_EQ(bucketStartTimeNs + 3 * bucketSizeNs,
data.bucket_info(2).end_bucket_elapsed_nanos());
EXPECT_EQ(AppStartOccurred::COLD,
data.bucket_info(2).atom(0).app_start_occurred().type());
EXPECT_EQ("activity_name5",
data.bucket_info(2).atom(0).app_start_occurred().activity_name());
EXPECT_EQ(105L,
data.bucket_info(2).atom(0).app_start_occurred().activity_start_millis());
EXPECT_EQ(AppStartOccurred::HOT,
data.bucket_info(2).atom(1).app_start_occurred().type());
EXPECT_EQ("activity_name6",
data.bucket_info(2).atom(1).app_start_occurred().activity_name());
EXPECT_EQ(106L,
data.bucket_info(2).atom(1).app_start_occurred().activity_start_millis());
} else {
EXPECT_EQ(1, data.bucket_info(0).atom_size());
EXPECT_EQ(1, data.bucket_info(0).elapsed_timestamp_nanos_size());
EXPECT_EQ(bucketStartTimeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
EXPECT_EQ(bucketStartTimeNs + bucketSizeNs,
data.bucket_info(0).end_bucket_elapsed_nanos());
EXPECT_EQ(AppStartOccurred::HOT,
data.bucket_info(0).atom(0).app_start_occurred().type());
EXPECT_EQ("activity_name2",
data.bucket_info(0).atom(0).app_start_occurred().activity_name());
EXPECT_EQ(102L,
data.bucket_info(0).atom(0).app_start_occurred().activity_start_millis());
EXPECT_EQ(1, data.bucket_info(1).atom_size());
EXPECT_EQ(1, data.bucket_info(1).elapsed_timestamp_nanos_size());
EXPECT_EQ(bucketStartTimeNs + bucketSizeNs,
data.bucket_info(1).start_bucket_elapsed_nanos());
EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
data.bucket_info(1).end_bucket_elapsed_nanos());
EXPECT_EQ(AppStartOccurred::WARM,
data.bucket_info(1).atom(0).app_start_occurred().type());
EXPECT_EQ("activity_name4",
data.bucket_info(1).atom(0).app_start_occurred().activity_name());
EXPECT_EQ(104L,
data.bucket_info(1).atom(0).app_start_occurred().activity_start_millis());
EXPECT_EQ(1, data.bucket_info(2).atom_size());
EXPECT_EQ(1, data.bucket_info(2).elapsed_timestamp_nanos_size());
EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
data.bucket_info(2).start_bucket_elapsed_nanos());
EXPECT_EQ(bucketStartTimeNs + 3 * bucketSizeNs,
data.bucket_info(2).end_bucket_elapsed_nanos());
EXPECT_EQ(AppStartOccurred::COLD,
data.bucket_info(2).atom(0).app_start_occurred().type());
EXPECT_EQ("activity_name5",
data.bucket_info(2).atom(0).app_start_occurred().activity_name());
EXPECT_EQ(105L,
data.bucket_info(2).atom(0).app_start_occurred().activity_start_millis());
}
data = gaugeMetrics.data(1);
EXPECT_EQ(data.dimensions_in_what().field(), android::util::APP_START_OCCURRED);
EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value_size(), 1);
EXPECT_EQ(1 /* uid field */,
data.dimensions_in_what().value_tuple().dimensions_value(0).field());
EXPECT_EQ(appUid2, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
EXPECT_EQ(1, data.bucket_info_size());
EXPECT_EQ(1, data.bucket_info(0).atom_size());
EXPECT_EQ(1, data.bucket_info(0).elapsed_timestamp_nanos_size());
EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
data.bucket_info(0).start_bucket_elapsed_nanos());
EXPECT_EQ(bucketStartTimeNs + 3 * bucketSizeNs,
data.bucket_info(0).end_bucket_elapsed_nanos());
EXPECT_EQ(AppStartOccurred::COLD, data.bucket_info(0).atom(0).app_start_occurred().type());
EXPECT_EQ("activity_name7",
data.bucket_info(0).atom(0).app_start_occurred().activity_name());
EXPECT_EQ(201L, data.bucket_info(0).atom(0).app_start_occurred().activity_start_millis());
}
}
// TODO(b/149590301): Update this test to use new socket schema.
//TEST(GaugeMetricE2eTest, TestMultipleFieldsForPushedEvent) {
// for (const auto& sampling_type :
// { GaugeMetric::FIRST_N_SAMPLES, GaugeMetric:: RANDOM_ONE_SAMPLE }) {
// auto config = CreateStatsdConfigForPushedEvent(sampling_type);
// int64_t bucketStartTimeNs = 10000000000;
// int64_t bucketSizeNs =
// TimeUnitToBucketSizeInMillis(config.gauge_metric(0).bucket()) * 1000000;
//
// ConfigKey cfgKey;
// auto processor = CreateStatsLogProcessor(
// bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
// EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
// EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
//
// int appUid1 = 123;
// int appUid2 = 456;
// std::vector<std::unique_ptr<LogEvent>> events;
// events.push_back(CreateMoveToBackgroundEvent(appUid1, bucketStartTimeNs + 15));
// events.push_back(CreateMoveToForegroundEvent(
// appUid1, bucketStartTimeNs + bucketSizeNs + 250));
// events.push_back(CreateMoveToBackgroundEvent(
// appUid1, bucketStartTimeNs + bucketSizeNs + 350));
// events.push_back(CreateMoveToForegroundEvent(
// appUid1, bucketStartTimeNs + 2 * bucketSizeNs + 100));
//
//
// events.push_back(CreateAppStartOccurredEvent(
// appUid1, "app1", AppStartOccurred::WARM, "activity_name1", "calling_pkg_name1",
// true /*is_instant_app*/, 101 /*activity_start_msec*/, bucketStartTimeNs + 10));
// events.push_back(CreateAppStartOccurredEvent(
// appUid1, "app1", AppStartOccurred::HOT, "activity_name2", "calling_pkg_name2",
// true /*is_instant_app*/, 102 /*activity_start_msec*/, bucketStartTimeNs + 20));
// events.push_back(CreateAppStartOccurredEvent(
// appUid1, "app1", AppStartOccurred::COLD, "activity_name3", "calling_pkg_name3",
// true /*is_instant_app*/, 103 /*activity_start_msec*/, bucketStartTimeNs + 30));
// events.push_back(CreateAppStartOccurredEvent(
// appUid1, "app1", AppStartOccurred::WARM, "activity_name4", "calling_pkg_name4",
// true /*is_instant_app*/, 104 /*activity_start_msec*/,
// bucketStartTimeNs + bucketSizeNs + 30));
// events.push_back(CreateAppStartOccurredEvent(
// appUid1, "app1", AppStartOccurred::COLD, "activity_name5", "calling_pkg_name5",
// true /*is_instant_app*/, 105 /*activity_start_msec*/,
// bucketStartTimeNs + 2 * bucketSizeNs));
// events.push_back(CreateAppStartOccurredEvent(
// appUid1, "app1", AppStartOccurred::HOT, "activity_name6", "calling_pkg_name6",
// false /*is_instant_app*/, 106 /*activity_start_msec*/,
// bucketStartTimeNs + 2 * bucketSizeNs + 10));
//
// events.push_back(CreateMoveToBackgroundEvent(
// appUid2, bucketStartTimeNs + bucketSizeNs + 10));
// events.push_back(CreateAppStartOccurredEvent(
// appUid2, "app2", AppStartOccurred::COLD, "activity_name7", "calling_pkg_name7",
// true /*is_instant_app*/, 201 /*activity_start_msec*/,
// bucketStartTimeNs + 2 * bucketSizeNs + 10));
//
// sortLogEventsByTimestamp(&events);
//
// for (const auto& event : events) {
// processor->OnLogEvent(event.get());
// }
// ConfigMetricsReportList reports;
// vector<uint8_t> buffer;
// processor->onDumpReport(cfgKey, bucketStartTimeNs + 3 * bucketSizeNs, false, true,
// ADB_DUMP, FAST, &buffer);
// EXPECT_TRUE(buffer.size() > 0);
// EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
// backfillDimensionPath(&reports);
// backfillStringInReport(&reports);
// backfillStartEndTimestamp(&reports);
// EXPECT_EQ(1, reports.reports_size());
// EXPECT_EQ(1, reports.reports(0).metrics_size());
// StatsLogReport::GaugeMetricDataWrapper gaugeMetrics;
// sortMetricDataByDimensionsValue(
// reports.reports(0).metrics(0).gauge_metrics(), &gaugeMetrics);
// EXPECT_EQ(2, gaugeMetrics.data_size());
//
// auto data = gaugeMetrics.data(0);
// EXPECT_EQ(android::util::APP_START_OCCURRED, data.dimensions_in_what().field());
// EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
// EXPECT_EQ(1 /* uid field */,
// data.dimensions_in_what().value_tuple().dimensions_value(0).field());
// EXPECT_EQ(appUid1, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
// EXPECT_EQ(3, data.bucket_info_size());
// if (sampling_type == GaugeMetric::FIRST_N_SAMPLES) {
// EXPECT_EQ(2, data.bucket_info(0).atom_size());
// EXPECT_EQ(2, data.bucket_info(0).elapsed_timestamp_nanos_size());
// EXPECT_EQ(0, data.bucket_info(0).wall_clock_timestamp_nanos_size());
// EXPECT_EQ(bucketStartTimeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
// EXPECT_EQ(bucketStartTimeNs + bucketSizeNs,
// data.bucket_info(0).end_bucket_elapsed_nanos());
// EXPECT_EQ(AppStartOccurred::HOT,
// data.bucket_info(0).atom(0).app_start_occurred().type());
// EXPECT_EQ("activity_name2",
// data.bucket_info(0).atom(0).app_start_occurred().activity_name());
// EXPECT_EQ(102L,
// data.bucket_info(0).atom(0).app_start_occurred().activity_start_millis());
// EXPECT_EQ(AppStartOccurred::COLD,
// data.bucket_info(0).atom(1).app_start_occurred().type());
// EXPECT_EQ("activity_name3",
// data.bucket_info(0).atom(1).app_start_occurred().activity_name());
// EXPECT_EQ(103L,
// data.bucket_info(0).atom(1).app_start_occurred().activity_start_millis());
//
// EXPECT_EQ(1, data.bucket_info(1).atom_size());
// EXPECT_EQ(1, data.bucket_info(1).elapsed_timestamp_nanos_size());
// EXPECT_EQ(bucketStartTimeNs + bucketSizeNs,
// data.bucket_info(1).start_bucket_elapsed_nanos());
// EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
// data.bucket_info(1).end_bucket_elapsed_nanos());
// EXPECT_EQ(AppStartOccurred::WARM,
// data.bucket_info(1).atom(0).app_start_occurred().type());
// EXPECT_EQ("activity_name4",
// data.bucket_info(1).atom(0).app_start_occurred().activity_name());
// EXPECT_EQ(104L,
// data.bucket_info(1).atom(0).app_start_occurred().activity_start_millis());
//
// EXPECT_EQ(2, data.bucket_info(2).atom_size());
// EXPECT_EQ(2, data.bucket_info(2).elapsed_timestamp_nanos_size());
// EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
// data.bucket_info(2).start_bucket_elapsed_nanos());
// EXPECT_EQ(bucketStartTimeNs + 3 * bucketSizeNs,
// data.bucket_info(2).end_bucket_elapsed_nanos());
// EXPECT_EQ(AppStartOccurred::COLD,
// data.bucket_info(2).atom(0).app_start_occurred().type());
// EXPECT_EQ("activity_name5",
// data.bucket_info(2).atom(0).app_start_occurred().activity_name());
// EXPECT_EQ(105L,
// data.bucket_info(2).atom(0).app_start_occurred().activity_start_millis());
// EXPECT_EQ(AppStartOccurred::HOT,
// data.bucket_info(2).atom(1).app_start_occurred().type());
// EXPECT_EQ("activity_name6",
// data.bucket_info(2).atom(1).app_start_occurred().activity_name());
// EXPECT_EQ(106L,
// data.bucket_info(2).atom(1).app_start_occurred().activity_start_millis());
// } else {
// EXPECT_EQ(1, data.bucket_info(0).atom_size());
// EXPECT_EQ(1, data.bucket_info(0).elapsed_timestamp_nanos_size());
// EXPECT_EQ(bucketStartTimeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
// EXPECT_EQ(bucketStartTimeNs + bucketSizeNs,
// data.bucket_info(0).end_bucket_elapsed_nanos());
// EXPECT_EQ(AppStartOccurred::HOT,
// data.bucket_info(0).atom(0).app_start_occurred().type());
// EXPECT_EQ("activity_name2",
// data.bucket_info(0).atom(0).app_start_occurred().activity_name());
// EXPECT_EQ(102L,
// data.bucket_info(0).atom(0).app_start_occurred().activity_start_millis());
//
// EXPECT_EQ(1, data.bucket_info(1).atom_size());
// EXPECT_EQ(1, data.bucket_info(1).elapsed_timestamp_nanos_size());
// EXPECT_EQ(bucketStartTimeNs + bucketSizeNs,
// data.bucket_info(1).start_bucket_elapsed_nanos());
// EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
// data.bucket_info(1).end_bucket_elapsed_nanos());
// EXPECT_EQ(AppStartOccurred::WARM,
// data.bucket_info(1).atom(0).app_start_occurred().type());
// EXPECT_EQ("activity_name4",
// data.bucket_info(1).atom(0).app_start_occurred().activity_name());
// EXPECT_EQ(104L,
// data.bucket_info(1).atom(0).app_start_occurred().activity_start_millis());
//
// EXPECT_EQ(1, data.bucket_info(2).atom_size());
// EXPECT_EQ(1, data.bucket_info(2).elapsed_timestamp_nanos_size());
// EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
// data.bucket_info(2).start_bucket_elapsed_nanos());
// EXPECT_EQ(bucketStartTimeNs + 3 * bucketSizeNs,
// data.bucket_info(2).end_bucket_elapsed_nanos());
// EXPECT_EQ(AppStartOccurred::COLD,
// data.bucket_info(2).atom(0).app_start_occurred().type());
// EXPECT_EQ("activity_name5",
// data.bucket_info(2).atom(0).app_start_occurred().activity_name());
// EXPECT_EQ(105L,
// data.bucket_info(2).atom(0).app_start_occurred().activity_start_millis());
// }
//
// data = gaugeMetrics.data(1);
//
// EXPECT_EQ(data.dimensions_in_what().field(), android::util::APP_START_OCCURRED);
// EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value_size(), 1);
// EXPECT_EQ(1 /* uid field */,
// data.dimensions_in_what().value_tuple().dimensions_value(0).field());
// EXPECT_EQ(appUid2, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
// EXPECT_EQ(1, data.bucket_info_size());
// EXPECT_EQ(1, data.bucket_info(0).atom_size());
// EXPECT_EQ(1, data.bucket_info(0).elapsed_timestamp_nanos_size());
// EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
// data.bucket_info(0).start_bucket_elapsed_nanos());
// EXPECT_EQ(bucketStartTimeNs + 3 * bucketSizeNs,
// data.bucket_info(0).end_bucket_elapsed_nanos());
// EXPECT_EQ(AppStartOccurred::COLD, data.bucket_info(0).atom(0).app_start_occurred().type());
// EXPECT_EQ("activity_name7",
// data.bucket_info(0).atom(0).app_start_occurred().activity_name());
// EXPECT_EQ(201L, data.bucket_info(0).atom(0).app_start_occurred().activity_start_millis());
// }
//}
#else
GTEST_LOG_(INFO) << "This test does nothing.\n";

File diff suppressed because it is too large Load Diff

View File

@@ -97,249 +97,250 @@ StatsdConfig CreateStatsdConfig() {
}
} // namespace
// If we want to test multiple dump data, we must do it in separate tests, because in the e2e tests,
// we should use the real API which will clear the data after dump data is called.
TEST(MetricConditionLinkE2eTest, TestMultiplePredicatesAndLinks1) {
auto config = CreateStatsdConfig();
uint64_t bucketStartTimeNs = 10000000000;
uint64_t bucketSizeNs =
TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000000LL;
ConfigKey cfgKey;
auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
int appUid = 123;
auto crashEvent1 = CreateAppCrashEvent(appUid, bucketStartTimeNs + 1);
auto crashEvent2 = CreateAppCrashEvent(appUid, bucketStartTimeNs + 201);
auto crashEvent3= CreateAppCrashEvent(appUid, bucketStartTimeNs + 2 * bucketSizeNs - 101);
auto crashEvent4 = CreateAppCrashEvent(appUid, bucketStartTimeNs + 51);
auto crashEvent5 = CreateAppCrashEvent(appUid, bucketStartTimeNs + bucketSizeNs + 299);
auto crashEvent6 = CreateAppCrashEvent(appUid, bucketStartTimeNs + bucketSizeNs + 2001);
auto crashEvent7 = CreateAppCrashEvent(appUid, bucketStartTimeNs + 16);
auto crashEvent8 = CreateAppCrashEvent(appUid, bucketStartTimeNs + bucketSizeNs + 249);
auto crashEvent9 = CreateAppCrashEvent(appUid, bucketStartTimeNs + bucketSizeNs + 351);
auto crashEvent10 = CreateAppCrashEvent(appUid, bucketStartTimeNs + 2 * bucketSizeNs - 2);
auto screenTurnedOnEvent =
CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_ON,
bucketStartTimeNs + 2);
auto screenTurnedOffEvent =
CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_OFF,
bucketStartTimeNs + 200);
auto screenTurnedOnEvent2 =
CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_ON,
bucketStartTimeNs + 2 * bucketSizeNs - 100);
std::vector<AttributionNodeInternal> attributions = {
CreateAttribution(appUid, "App1"), CreateAttribution(appUid + 1, "GMSCoreModule1")};
auto syncOnEvent1 =
CreateSyncStartEvent(attributions, "ReadEmail", bucketStartTimeNs + 50);
auto syncOffEvent1 =
CreateSyncEndEvent(attributions, "ReadEmail", bucketStartTimeNs + bucketSizeNs + 300);
auto syncOnEvent2 =
CreateSyncStartEvent(attributions, "ReadDoc", bucketStartTimeNs + bucketSizeNs + 2000);
auto moveToBackgroundEvent1 =
CreateMoveToBackgroundEvent(appUid, bucketStartTimeNs + 15);
auto moveToForegroundEvent1 =
CreateMoveToForegroundEvent(appUid, bucketStartTimeNs + bucketSizeNs + 250);
auto moveToBackgroundEvent2 =
CreateMoveToBackgroundEvent(appUid, bucketStartTimeNs + bucketSizeNs + 350);
auto moveToForegroundEvent2 =
CreateMoveToForegroundEvent(appUid, bucketStartTimeNs + 2 * bucketSizeNs - 1);
/*
bucket #1 bucket #2
| | | | | | | | | | (crashEvents)
|-------------------------------------|-----------------------------------|---------
| | (MoveToBkground)
| | (MoveToForeground)
| | (SyncIsOn)
| (SyncIsOff)
| | (ScreenIsOn)
| (ScreenIsOff)
*/
std::vector<std::unique_ptr<LogEvent>> events;
events.push_back(std::move(crashEvent1));
events.push_back(std::move(crashEvent2));
events.push_back(std::move(crashEvent3));
events.push_back(std::move(crashEvent4));
events.push_back(std::move(crashEvent5));
events.push_back(std::move(crashEvent6));
events.push_back(std::move(crashEvent7));
events.push_back(std::move(crashEvent8));
events.push_back(std::move(crashEvent9));
events.push_back(std::move(crashEvent10));
events.push_back(std::move(screenTurnedOnEvent));
events.push_back(std::move(screenTurnedOffEvent));
events.push_back(std::move(screenTurnedOnEvent2));
events.push_back(std::move(syncOnEvent1));
events.push_back(std::move(syncOffEvent1));
events.push_back(std::move(syncOnEvent2));
events.push_back(std::move(moveToBackgroundEvent1));
events.push_back(std::move(moveToForegroundEvent1));
events.push_back(std::move(moveToBackgroundEvent2));
events.push_back(std::move(moveToForegroundEvent2));
sortLogEventsByTimestamp(&events);
for (const auto& event : events) {
processor->OnLogEvent(event.get());
}
ConfigMetricsReportList reports;
vector<uint8_t> buffer;
processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs - 1, false, true,
ADB_DUMP, FAST, &buffer);
EXPECT_TRUE(buffer.size() > 0);
EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
backfillDimensionPath(&reports);
backfillStringInReport(&reports);
backfillStartEndTimestamp(&reports);
EXPECT_EQ(reports.reports_size(), 1);
EXPECT_EQ(reports.reports(0).metrics_size(), 1);
EXPECT_EQ(reports.reports(0).metrics(0).count_metrics().data_size(), 1);
EXPECT_EQ(reports.reports(0).metrics(0).count_metrics().data(0).bucket_info_size(), 1);
EXPECT_EQ(reports.reports(0).metrics(0).count_metrics().data(0).bucket_info(0).count(), 1);
auto data = reports.reports(0).metrics(0).count_metrics().data(0);
// Validate dimension value.
EXPECT_EQ(data.dimensions_in_what().field(), android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED);
EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value_size(), 1);
// Uid field.
EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), 1);
EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_int(), appUid);
}
TEST(MetricConditionLinkE2eTest, TestMultiplePredicatesAndLinks2) {
auto config = CreateStatsdConfig();
uint64_t bucketStartTimeNs = 10000000000;
uint64_t bucketSizeNs =
TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000000LL;
ConfigKey cfgKey;
auto processor = CreateStatsLogProcessor(
bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
int appUid = 123;
auto crashEvent1 = CreateAppCrashEvent(appUid, bucketStartTimeNs + 1);
auto crashEvent2 = CreateAppCrashEvent(appUid, bucketStartTimeNs + 201);
auto crashEvent3 = CreateAppCrashEvent(appUid, bucketStartTimeNs + 2 * bucketSizeNs - 101);
auto crashEvent4 = CreateAppCrashEvent(appUid, bucketStartTimeNs + 51);
auto crashEvent5 = CreateAppCrashEvent(appUid, bucketStartTimeNs + bucketSizeNs + 299);
auto crashEvent6 = CreateAppCrashEvent(appUid, bucketStartTimeNs + bucketSizeNs + 2001);
auto crashEvent7 = CreateAppCrashEvent(appUid, bucketStartTimeNs + 16);
auto crashEvent8 = CreateAppCrashEvent(appUid, bucketStartTimeNs + bucketSizeNs + 249);
auto crashEvent9 = CreateAppCrashEvent(appUid, bucketStartTimeNs + bucketSizeNs + 351);
auto crashEvent10 = CreateAppCrashEvent(appUid, bucketStartTimeNs + 2 * bucketSizeNs - 2);
auto screenTurnedOnEvent = CreateScreenStateChangedEvent(
android::view::DisplayStateEnum::DISPLAY_STATE_ON, bucketStartTimeNs + 2);
auto screenTurnedOffEvent = CreateScreenStateChangedEvent(
android::view::DisplayStateEnum::DISPLAY_STATE_OFF, bucketStartTimeNs + 200);
auto screenTurnedOnEvent2 =
CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_ON,
bucketStartTimeNs + 2 * bucketSizeNs - 100);
std::vector<AttributionNodeInternal> attributions = {
CreateAttribution(appUid, "App1"), CreateAttribution(appUid + 1, "GMSCoreModule1")};
auto syncOnEvent1 = CreateSyncStartEvent(attributions, "ReadEmail", bucketStartTimeNs + 50);
auto syncOffEvent1 =
CreateSyncEndEvent(attributions, "ReadEmail", bucketStartTimeNs + bucketSizeNs + 300);
auto syncOnEvent2 =
CreateSyncStartEvent(attributions, "ReadDoc", bucketStartTimeNs + bucketSizeNs + 2000);
auto moveToBackgroundEvent1 = CreateMoveToBackgroundEvent(appUid, bucketStartTimeNs + 15);
auto moveToForegroundEvent1 =
CreateMoveToForegroundEvent(appUid, bucketStartTimeNs + bucketSizeNs + 250);
auto moveToBackgroundEvent2 =
CreateMoveToBackgroundEvent(appUid, bucketStartTimeNs + bucketSizeNs + 350);
auto moveToForegroundEvent2 =
CreateMoveToForegroundEvent(appUid, bucketStartTimeNs + 2 * bucketSizeNs - 1);
/*
bucket #1 bucket #2
| | | | | | | | | | (crashEvents)
|-------------------------------------|-----------------------------------|---------
| | (MoveToBkground)
| | (MoveToForeground)
| | (SyncIsOn)
| (SyncIsOff)
| | (ScreenIsOn)
| (ScreenIsOff)
*/
std::vector<std::unique_ptr<LogEvent>> events;
events.push_back(std::move(crashEvent1));
events.push_back(std::move(crashEvent2));
events.push_back(std::move(crashEvent3));
events.push_back(std::move(crashEvent4));
events.push_back(std::move(crashEvent5));
events.push_back(std::move(crashEvent6));
events.push_back(std::move(crashEvent7));
events.push_back(std::move(crashEvent8));
events.push_back(std::move(crashEvent9));
events.push_back(std::move(crashEvent10));
events.push_back(std::move(screenTurnedOnEvent));
events.push_back(std::move(screenTurnedOffEvent));
events.push_back(std::move(screenTurnedOnEvent2));
events.push_back(std::move(syncOnEvent1));
events.push_back(std::move(syncOffEvent1));
events.push_back(std::move(syncOnEvent2));
events.push_back(std::move(moveToBackgroundEvent1));
events.push_back(std::move(moveToForegroundEvent1));
events.push_back(std::move(moveToBackgroundEvent2));
events.push_back(std::move(moveToForegroundEvent2));
sortLogEventsByTimestamp(&events);
for (const auto& event : events) {
processor->OnLogEvent(event.get());
}
ConfigMetricsReportList reports;
vector<uint8_t> buffer;
processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, false, true,
ADB_DUMP, FAST, &buffer);
EXPECT_TRUE(buffer.size() > 0);
EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
backfillDimensionPath(&reports);
backfillStringInReport(&reports);
backfillStartEndTimestamp(&reports);
EXPECT_EQ(reports.reports_size(), 1);
EXPECT_EQ(reports.reports(0).metrics_size(), 1);
EXPECT_EQ(reports.reports(0).metrics(0).count_metrics().data_size(), 1);
EXPECT_EQ(reports.reports(0).metrics(0).count_metrics().data(0).bucket_info_size(), 2);
EXPECT_EQ(reports.reports(0).metrics(0).count_metrics().data(0).bucket_info(0).count(), 1);
EXPECT_EQ(reports.reports(0).metrics(0).count_metrics().data(0).bucket_info(1).count(), 3);
auto data = reports.reports(0).metrics(0).count_metrics().data(0);
// Validate dimension value.
EXPECT_EQ(data.dimensions_in_what().field(),
android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED);
EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value_size(), 1);
// Uid field.
EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), 1);
EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_int(), appUid);
}
// TODO(b/149590301): Update these tests to use new socket schema.
//// If we want to test multiple dump data, we must do it in separate tests, because in the e2e tests,
//// we should use the real API which will clear the data after dump data is called.
//TEST(MetricConditionLinkE2eTest, TestMultiplePredicatesAndLinks1) {
// auto config = CreateStatsdConfig();
// uint64_t bucketStartTimeNs = 10000000000;
// uint64_t bucketSizeNs =
// TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000000LL;
//
// ConfigKey cfgKey;
// auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
// EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
// EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
//
// int appUid = 123;
// auto crashEvent1 = CreateAppCrashEvent(appUid, bucketStartTimeNs + 1);
// auto crashEvent2 = CreateAppCrashEvent(appUid, bucketStartTimeNs + 201);
// auto crashEvent3= CreateAppCrashEvent(appUid, bucketStartTimeNs + 2 * bucketSizeNs - 101);
//
// auto crashEvent4 = CreateAppCrashEvent(appUid, bucketStartTimeNs + 51);
// auto crashEvent5 = CreateAppCrashEvent(appUid, bucketStartTimeNs + bucketSizeNs + 299);
// auto crashEvent6 = CreateAppCrashEvent(appUid, bucketStartTimeNs + bucketSizeNs + 2001);
//
// auto crashEvent7 = CreateAppCrashEvent(appUid, bucketStartTimeNs + 16);
// auto crashEvent8 = CreateAppCrashEvent(appUid, bucketStartTimeNs + bucketSizeNs + 249);
//
// auto crashEvent9 = CreateAppCrashEvent(appUid, bucketStartTimeNs + bucketSizeNs + 351);
// auto crashEvent10 = CreateAppCrashEvent(appUid, bucketStartTimeNs + 2 * bucketSizeNs - 2);
//
// auto screenTurnedOnEvent =
// CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_ON,
// bucketStartTimeNs + 2);
// auto screenTurnedOffEvent =
// CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_OFF,
// bucketStartTimeNs + 200);
// auto screenTurnedOnEvent2 =
// CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_ON,
// bucketStartTimeNs + 2 * bucketSizeNs - 100);
//
// std::vector<AttributionNodeInternal> attributions = {
// CreateAttribution(appUid, "App1"), CreateAttribution(appUid + 1, "GMSCoreModule1")};
// auto syncOnEvent1 =
// CreateSyncStartEvent(attributions, "ReadEmail", bucketStartTimeNs + 50);
// auto syncOffEvent1 =
// CreateSyncEndEvent(attributions, "ReadEmail", bucketStartTimeNs + bucketSizeNs + 300);
// auto syncOnEvent2 =
// CreateSyncStartEvent(attributions, "ReadDoc", bucketStartTimeNs + bucketSizeNs + 2000);
//
// auto moveToBackgroundEvent1 =
// CreateMoveToBackgroundEvent(appUid, bucketStartTimeNs + 15);
// auto moveToForegroundEvent1 =
// CreateMoveToForegroundEvent(appUid, bucketStartTimeNs + bucketSizeNs + 250);
//
// auto moveToBackgroundEvent2 =
// CreateMoveToBackgroundEvent(appUid, bucketStartTimeNs + bucketSizeNs + 350);
// auto moveToForegroundEvent2 =
// CreateMoveToForegroundEvent(appUid, bucketStartTimeNs + 2 * bucketSizeNs - 1);
//
// /*
// bucket #1 bucket #2
//
//
// | | | | | | | | | | (crashEvents)
// |-------------------------------------|-----------------------------------|---------
//
// | | (MoveToBkground)
//
// | | (MoveToForeground)
//
// | | (SyncIsOn)
// | (SyncIsOff)
// | | (ScreenIsOn)
// | (ScreenIsOff)
// */
// std::vector<std::unique_ptr<LogEvent>> events;
// events.push_back(std::move(crashEvent1));
// events.push_back(std::move(crashEvent2));
// events.push_back(std::move(crashEvent3));
// events.push_back(std::move(crashEvent4));
// events.push_back(std::move(crashEvent5));
// events.push_back(std::move(crashEvent6));
// events.push_back(std::move(crashEvent7));
// events.push_back(std::move(crashEvent8));
// events.push_back(std::move(crashEvent9));
// events.push_back(std::move(crashEvent10));
// events.push_back(std::move(screenTurnedOnEvent));
// events.push_back(std::move(screenTurnedOffEvent));
// events.push_back(std::move(screenTurnedOnEvent2));
// events.push_back(std::move(syncOnEvent1));
// events.push_back(std::move(syncOffEvent1));
// events.push_back(std::move(syncOnEvent2));
// events.push_back(std::move(moveToBackgroundEvent1));
// events.push_back(std::move(moveToForegroundEvent1));
// events.push_back(std::move(moveToBackgroundEvent2));
// events.push_back(std::move(moveToForegroundEvent2));
//
// sortLogEventsByTimestamp(&events);
//
// for (const auto& event : events) {
// processor->OnLogEvent(event.get());
// }
// ConfigMetricsReportList reports;
// vector<uint8_t> buffer;
// processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs - 1, false, true,
// ADB_DUMP, FAST, &buffer);
// EXPECT_TRUE(buffer.size() > 0);
// EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
// backfillDimensionPath(&reports);
// backfillStringInReport(&reports);
// backfillStartEndTimestamp(&reports);
// EXPECT_EQ(reports.reports_size(), 1);
// EXPECT_EQ(reports.reports(0).metrics_size(), 1);
// EXPECT_EQ(reports.reports(0).metrics(0).count_metrics().data_size(), 1);
// EXPECT_EQ(reports.reports(0).metrics(0).count_metrics().data(0).bucket_info_size(), 1);
// EXPECT_EQ(reports.reports(0).metrics(0).count_metrics().data(0).bucket_info(0).count(), 1);
// auto data = reports.reports(0).metrics(0).count_metrics().data(0);
// // Validate dimension value.
// EXPECT_EQ(data.dimensions_in_what().field(), android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED);
// EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value_size(), 1);
// // Uid field.
// EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), 1);
// EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_int(), appUid);
//}
//
//TEST(MetricConditionLinkE2eTest, TestMultiplePredicatesAndLinks2) {
// auto config = CreateStatsdConfig();
// uint64_t bucketStartTimeNs = 10000000000;
// uint64_t bucketSizeNs =
// TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000000LL;
//
// ConfigKey cfgKey;
// auto processor = CreateStatsLogProcessor(
// bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
// EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
// EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
//
// int appUid = 123;
// auto crashEvent1 = CreateAppCrashEvent(appUid, bucketStartTimeNs + 1);
// auto crashEvent2 = CreateAppCrashEvent(appUid, bucketStartTimeNs + 201);
// auto crashEvent3 = CreateAppCrashEvent(appUid, bucketStartTimeNs + 2 * bucketSizeNs - 101);
//
// auto crashEvent4 = CreateAppCrashEvent(appUid, bucketStartTimeNs + 51);
// auto crashEvent5 = CreateAppCrashEvent(appUid, bucketStartTimeNs + bucketSizeNs + 299);
// auto crashEvent6 = CreateAppCrashEvent(appUid, bucketStartTimeNs + bucketSizeNs + 2001);
//
// auto crashEvent7 = CreateAppCrashEvent(appUid, bucketStartTimeNs + 16);
// auto crashEvent8 = CreateAppCrashEvent(appUid, bucketStartTimeNs + bucketSizeNs + 249);
//
// auto crashEvent9 = CreateAppCrashEvent(appUid, bucketStartTimeNs + bucketSizeNs + 351);
// auto crashEvent10 = CreateAppCrashEvent(appUid, bucketStartTimeNs + 2 * bucketSizeNs - 2);
//
// auto screenTurnedOnEvent = CreateScreenStateChangedEvent(
// android::view::DisplayStateEnum::DISPLAY_STATE_ON, bucketStartTimeNs + 2);
// auto screenTurnedOffEvent = CreateScreenStateChangedEvent(
// android::view::DisplayStateEnum::DISPLAY_STATE_OFF, bucketStartTimeNs + 200);
// auto screenTurnedOnEvent2 =
// CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_ON,
// bucketStartTimeNs + 2 * bucketSizeNs - 100);
//
// std::vector<AttributionNodeInternal> attributions = {
// CreateAttribution(appUid, "App1"), CreateAttribution(appUid + 1, "GMSCoreModule1")};
// auto syncOnEvent1 = CreateSyncStartEvent(attributions, "ReadEmail", bucketStartTimeNs + 50);
// auto syncOffEvent1 =
// CreateSyncEndEvent(attributions, "ReadEmail", bucketStartTimeNs + bucketSizeNs + 300);
// auto syncOnEvent2 =
// CreateSyncStartEvent(attributions, "ReadDoc", bucketStartTimeNs + bucketSizeNs + 2000);
//
// auto moveToBackgroundEvent1 = CreateMoveToBackgroundEvent(appUid, bucketStartTimeNs + 15);
// auto moveToForegroundEvent1 =
// CreateMoveToForegroundEvent(appUid, bucketStartTimeNs + bucketSizeNs + 250);
//
// auto moveToBackgroundEvent2 =
// CreateMoveToBackgroundEvent(appUid, bucketStartTimeNs + bucketSizeNs + 350);
// auto moveToForegroundEvent2 =
// CreateMoveToForegroundEvent(appUid, bucketStartTimeNs + 2 * bucketSizeNs - 1);
//
// /*
// bucket #1 bucket #2
//
//
// | | | | | | | | | | (crashEvents)
// |-------------------------------------|-----------------------------------|---------
//
// | | (MoveToBkground)
//
// | | (MoveToForeground)
//
// | | (SyncIsOn)
// | (SyncIsOff)
// | | (ScreenIsOn)
// | (ScreenIsOff)
// */
// std::vector<std::unique_ptr<LogEvent>> events;
// events.push_back(std::move(crashEvent1));
// events.push_back(std::move(crashEvent2));
// events.push_back(std::move(crashEvent3));
// events.push_back(std::move(crashEvent4));
// events.push_back(std::move(crashEvent5));
// events.push_back(std::move(crashEvent6));
// events.push_back(std::move(crashEvent7));
// events.push_back(std::move(crashEvent8));
// events.push_back(std::move(crashEvent9));
// events.push_back(std::move(crashEvent10));
// events.push_back(std::move(screenTurnedOnEvent));
// events.push_back(std::move(screenTurnedOffEvent));
// events.push_back(std::move(screenTurnedOnEvent2));
// events.push_back(std::move(syncOnEvent1));
// events.push_back(std::move(syncOffEvent1));
// events.push_back(std::move(syncOnEvent2));
// events.push_back(std::move(moveToBackgroundEvent1));
// events.push_back(std::move(moveToForegroundEvent1));
// events.push_back(std::move(moveToBackgroundEvent2));
// events.push_back(std::move(moveToForegroundEvent2));
//
// sortLogEventsByTimestamp(&events);
//
// for (const auto& event : events) {
// processor->OnLogEvent(event.get());
// }
// ConfigMetricsReportList reports;
// vector<uint8_t> buffer;
//
// processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, false, true,
// ADB_DUMP, FAST, &buffer);
// EXPECT_TRUE(buffer.size() > 0);
// EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
// backfillDimensionPath(&reports);
// backfillStringInReport(&reports);
// backfillStartEndTimestamp(&reports);
// EXPECT_EQ(reports.reports_size(), 1);
// EXPECT_EQ(reports.reports(0).metrics_size(), 1);
// EXPECT_EQ(reports.reports(0).metrics(0).count_metrics().data_size(), 1);
// EXPECT_EQ(reports.reports(0).metrics(0).count_metrics().data(0).bucket_info_size(), 2);
// EXPECT_EQ(reports.reports(0).metrics(0).count_metrics().data(0).bucket_info(0).count(), 1);
// EXPECT_EQ(reports.reports(0).metrics(0).count_metrics().data(0).bucket_info(1).count(), 3);
// auto data = reports.reports(0).metrics(0).count_metrics().data(0);
// // Validate dimension value.
// EXPECT_EQ(data.dimensions_in_what().field(),
// android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED);
// EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value_size(), 1);
// // Uid field.
// EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), 1);
// EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_int(), appUid);
//}
#else
GTEST_LOG_(INFO) << "This test does nothing.\n";

View File

@@ -113,95 +113,96 @@ StatsdConfig MakeGaugeMetricConfig(int64_t minTime) {
}
} // anonymous namespace
TEST(PartialBucketE2eTest, TestCountMetricWithoutSplit) {
shared_ptr<StatsService> service = SharedRefBase::make<StatsService>(nullptr, nullptr);
SendConfig(service, MakeConfig());
int64_t start = getElapsedRealtimeNs(); // This is the start-time the metrics producers are
// initialized with.
service->mProcessor->OnLogEvent(CreateAppCrashEvent(100, start + 1).get());
service->mProcessor->OnLogEvent(CreateAppCrashEvent(100, start + 2).get());
ConfigMetricsReport report = GetReports(service->mProcessor, start + 3);
// Expect no metrics since the bucket has not finished yet.
EXPECT_EQ(1, report.metrics_size());
EXPECT_EQ(0, report.metrics(0).count_metrics().data_size());
}
TEST(PartialBucketE2eTest, TestCountMetricNoSplitOnNewApp) {
shared_ptr<StatsService> service = SharedRefBase::make<StatsService>(nullptr, nullptr);
SendConfig(service, MakeConfig());
int64_t start = getElapsedRealtimeNs(); // This is the start-time the metrics producers are
// initialized with.
// Force the uidmap to update at timestamp 2.
service->mProcessor->OnLogEvent(CreateAppCrashEvent(100, start + 1).get());
// This is a new installation, so there shouldn't be a split (should be same as the without
// split case).
service->mUidMap->updateApp(start + 2, String16(kApp1.c_str()), 1, 2, String16("v2"),
String16(""));
// Goes into the second bucket.
service->mProcessor->OnLogEvent(CreateAppCrashEvent(100, start + 3).get());
ConfigMetricsReport report = GetReports(service->mProcessor, start + 4);
EXPECT_EQ(1, report.metrics_size());
EXPECT_EQ(0, report.metrics(0).count_metrics().data_size());
}
TEST(PartialBucketE2eTest, TestCountMetricSplitOnUpgrade) {
shared_ptr<StatsService> service = SharedRefBase::make<StatsService>(nullptr, nullptr);
SendConfig(service, MakeConfig());
int64_t start = getElapsedRealtimeNs(); // This is the start-time the metrics producers are
// initialized with.
service->mUidMap->updateMap(start, {1}, {1}, {String16("v1")}, {String16(kApp1.c_str())},
{String16("")});
// Force the uidmap to update at timestamp 2.
service->mProcessor->OnLogEvent(CreateAppCrashEvent(100, start + 1).get());
service->mUidMap->updateApp(start + 2, String16(kApp1.c_str()), 1, 2, String16("v2"),
String16(""));
// Goes into the second bucket.
service->mProcessor->OnLogEvent(CreateAppCrashEvent(100, start + 3).get());
ConfigMetricsReport report = GetReports(service->mProcessor, start + 4);
backfillStartEndTimestamp(&report);
ASSERT_EQ(1, report.metrics_size());
ASSERT_EQ(1, report.metrics(0).count_metrics().data_size());
ASSERT_EQ(1, report.metrics(0).count_metrics().data(0).bucket_info_size());
EXPECT_TRUE(report.metrics(0).count_metrics().data(0).bucket_info(0).
has_start_bucket_elapsed_nanos());
EXPECT_TRUE(report.metrics(0).count_metrics().data(0).bucket_info(0).
has_end_bucket_elapsed_nanos());
EXPECT_EQ(1, report.metrics(0).count_metrics().data(0).bucket_info(0).count());
}
TEST(PartialBucketE2eTest, TestCountMetricSplitOnRemoval) {
shared_ptr<StatsService> service = SharedRefBase::make<StatsService>(nullptr, nullptr);
SendConfig(service, MakeConfig());
int64_t start = getElapsedRealtimeNs(); // This is the start-time the metrics producers are
// initialized with.
service->mUidMap->updateMap(start, {1}, {1}, {String16("v1")}, {String16(kApp1.c_str())},
{String16("")});
// Force the uidmap to update at timestamp 2.
service->mProcessor->OnLogEvent(CreateAppCrashEvent(100, start + 1).get());
service->mUidMap->removeApp(start + 2, String16(kApp1.c_str()), 1);
// Goes into the second bucket.
service->mProcessor->OnLogEvent(CreateAppCrashEvent(100, start + 3).get());
ConfigMetricsReport report = GetReports(service->mProcessor, start + 4);
backfillStartEndTimestamp(&report);
ASSERT_EQ(1, report.metrics_size());
ASSERT_EQ(1, report.metrics(0).count_metrics().data_size());
ASSERT_EQ(1, report.metrics(0).count_metrics().data(0).bucket_info_size());
EXPECT_TRUE(report.metrics(0).count_metrics().data(0).bucket_info(0).
has_start_bucket_elapsed_nanos());
EXPECT_TRUE(report.metrics(0).count_metrics().data(0).bucket_info(0).
has_end_bucket_elapsed_nanos());
EXPECT_EQ(1, report.metrics(0).count_metrics().data(0).bucket_info(0).count());
}
// TODO(b/149590301): Update this test to use new socket schema.
//TEST(PartialBucketE2eTest, TestCountMetricWithoutSplit) {
// shared_ptr<StatsService> service = SharedRefBase::make<StatsService>(nullptr, nullptr);
// SendConfig(service, MakeConfig());
// int64_t start = getElapsedRealtimeNs(); // This is the start-time the metrics producers are
// // initialized with.
//
// service->mProcessor->OnLogEvent(CreateAppCrashEvent(100, start + 1).get());
// service->mProcessor->OnLogEvent(CreateAppCrashEvent(100, start + 2).get());
//
// ConfigMetricsReport report = GetReports(service->mProcessor, start + 3);
// // Expect no metrics since the bucket has not finished yet.
// EXPECT_EQ(1, report.metrics_size());
// EXPECT_EQ(0, report.metrics(0).count_metrics().data_size());
//}
//
//TEST(PartialBucketE2eTest, TestCountMetricNoSplitOnNewApp) {
// shared_ptr<StatsService> service = SharedRefBase::make<StatsService>(nullptr, nullptr);
// SendConfig(service, MakeConfig());
// int64_t start = getElapsedRealtimeNs(); // This is the start-time the metrics producers are
// // initialized with.
//
// // Force the uidmap to update at timestamp 2.
// service->mProcessor->OnLogEvent(CreateAppCrashEvent(100, start + 1).get());
// // This is a new installation, so there shouldn't be a split (should be same as the without
// // split case).
// service->mUidMap->updateApp(start + 2, String16(kApp1.c_str()), 1, 2, String16("v2"),
// String16(""));
// // Goes into the second bucket.
// service->mProcessor->OnLogEvent(CreateAppCrashEvent(100, start + 3).get());
//
// ConfigMetricsReport report = GetReports(service->mProcessor, start + 4);
// EXPECT_EQ(1, report.metrics_size());
// EXPECT_EQ(0, report.metrics(0).count_metrics().data_size());
//}
//
//TEST(PartialBucketE2eTest, TestCountMetricSplitOnUpgrade) {
// shared_ptr<StatsService> service = SharedRefBase::make<StatsService>(nullptr, nullptr);
// SendConfig(service, MakeConfig());
// int64_t start = getElapsedRealtimeNs(); // This is the start-time the metrics producers are
// // initialized with.
// service->mUidMap->updateMap(start, {1}, {1}, {String16("v1")}, {String16(kApp1.c_str())},
// {String16("")});
//
// // Force the uidmap to update at timestamp 2.
// service->mProcessor->OnLogEvent(CreateAppCrashEvent(100, start + 1).get());
// service->mUidMap->updateApp(start + 2, String16(kApp1.c_str()), 1, 2, String16("v2"),
// String16(""));
// // Goes into the second bucket.
// service->mProcessor->OnLogEvent(CreateAppCrashEvent(100, start + 3).get());
//
// ConfigMetricsReport report = GetReports(service->mProcessor, start + 4);
// backfillStartEndTimestamp(&report);
//
// ASSERT_EQ(1, report.metrics_size());
// ASSERT_EQ(1, report.metrics(0).count_metrics().data_size());
// ASSERT_EQ(1, report.metrics(0).count_metrics().data(0).bucket_info_size());
// EXPECT_TRUE(report.metrics(0).count_metrics().data(0).bucket_info(0).
// has_start_bucket_elapsed_nanos());
// EXPECT_TRUE(report.metrics(0).count_metrics().data(0).bucket_info(0).
// has_end_bucket_elapsed_nanos());
// EXPECT_EQ(1, report.metrics(0).count_metrics().data(0).bucket_info(0).count());
//}
//
//TEST(PartialBucketE2eTest, TestCountMetricSplitOnRemoval) {
// shared_ptr<StatsService> service = SharedRefBase::make<StatsService>(nullptr, nullptr);
// SendConfig(service, MakeConfig());
// int64_t start = getElapsedRealtimeNs(); // This is the start-time the metrics producers are
// // initialized with.
// service->mUidMap->updateMap(start, {1}, {1}, {String16("v1")}, {String16(kApp1.c_str())},
// {String16("")});
//
// // Force the uidmap to update at timestamp 2.
// service->mProcessor->OnLogEvent(CreateAppCrashEvent(100, start + 1).get());
// service->mUidMap->removeApp(start + 2, String16(kApp1.c_str()), 1);
// // Goes into the second bucket.
// service->mProcessor->OnLogEvent(CreateAppCrashEvent(100, start + 3).get());
//
// ConfigMetricsReport report = GetReports(service->mProcessor, start + 4);
// backfillStartEndTimestamp(&report);
//
// ASSERT_EQ(1, report.metrics_size());
// ASSERT_EQ(1, report.metrics(0).count_metrics().data_size());
// ASSERT_EQ(1, report.metrics(0).count_metrics().data(0).bucket_info_size());
// EXPECT_TRUE(report.metrics(0).count_metrics().data(0).bucket_info(0).
// has_start_bucket_elapsed_nanos());
// EXPECT_TRUE(report.metrics(0).count_metrics().data(0).bucket_info(0).
// has_end_bucket_elapsed_nanos());
// EXPECT_EQ(1, report.metrics(0).count_metrics().data(0).bucket_info(0).count());
//}
TEST(PartialBucketE2eTest, TestValueMetricWithoutMinPartialBucket) {
shared_ptr<StatsService> service = SharedRefBase::make<StatsService>(nullptr, nullptr);

View File

@@ -64,316 +64,317 @@ StatsdConfig CreateStatsdConfig(bool useCondition = true) {
} // namespace
TEST(ValueMetricE2eTest, TestPulledEvents) {
auto config = CreateStatsdConfig();
int64_t baseTimeNs = getElapsedRealtimeNs();
int64_t configAddedTimeNs = 10 * 60 * NS_PER_SEC + baseTimeNs;
int64_t bucketSizeNs =
TimeUnitToBucketSizeInMillis(config.value_metric(0).bucket()) * 1000000;
ConfigKey cfgKey;
auto processor = CreateStatsLogProcessor(baseTimeNs, configAddedTimeNs, config, cfgKey,
SharedRefBase::make<FakeSubsystemSleepCallback>(),
android::util::SUBSYSTEM_SLEEP_STATE);
EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
processor->mPullerManager->ForceClearPullerCache();
int startBucketNum = processor->mMetricsManagers.begin()->second->
mAllMetricProducers[0]->getCurrentBucketNum();
EXPECT_GT(startBucketNum, (int64_t)0);
// When creating the config, the value metric producer should register the alarm at the
// end of the current bucket.
EXPECT_EQ((size_t)1, processor->mPullerManager->mReceivers.size());
EXPECT_EQ(bucketSizeNs,
processor->mPullerManager->mReceivers.begin()->second.front().intervalNs);
int64_t& expectedPullTimeNs =
processor->mPullerManager->mReceivers.begin()->second.front().nextPullTimeNs;
EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + bucketSizeNs, expectedPullTimeNs);
auto screenOffEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
configAddedTimeNs + 55);
processor->OnLogEvent(screenOffEvent.get());
auto screenOnEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
configAddedTimeNs + 65);
processor->OnLogEvent(screenOnEvent.get());
screenOffEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
configAddedTimeNs + 75);
processor->OnLogEvent(screenOffEvent.get());
// Pulling alarm arrives on time and reset the sequential pulling alarm.
processor->informPullAlarmFired(expectedPullTimeNs + 1);
EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 2 * bucketSizeNs, expectedPullTimeNs);
processor->informPullAlarmFired(expectedPullTimeNs + 1);
screenOnEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
configAddedTimeNs + 2 * bucketSizeNs + 15);
processor->OnLogEvent(screenOnEvent.get());
processor->informPullAlarmFired(expectedPullTimeNs + 1);
processor->informPullAlarmFired(expectedPullTimeNs + 1);
screenOffEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
configAddedTimeNs + 4 * bucketSizeNs + 11);
processor->OnLogEvent(screenOffEvent.get());
processor->informPullAlarmFired(expectedPullTimeNs + 1);
processor->informPullAlarmFired(expectedPullTimeNs + 1);
ConfigMetricsReportList reports;
vector<uint8_t> buffer;
processor->onDumpReport(cfgKey, configAddedTimeNs + 7 * bucketSizeNs + 10, false, true,
ADB_DUMP, FAST, &buffer);
EXPECT_TRUE(buffer.size() > 0);
EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
backfillDimensionPath(&reports);
backfillStringInReport(&reports);
backfillStartEndTimestamp(&reports);
EXPECT_EQ(1, reports.reports_size());
EXPECT_EQ(1, reports.reports(0).metrics_size());
StatsLogReport::ValueMetricDataWrapper valueMetrics;
sortMetricDataByDimensionsValue(
reports.reports(0).metrics(0).value_metrics(), &valueMetrics);
EXPECT_GT((int)valueMetrics.data_size(), 1);
auto data = valueMetrics.data(0);
EXPECT_EQ(android::util::SUBSYSTEM_SLEEP_STATE, data.dimensions_in_what().field());
EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
EXPECT_EQ(1 /* subsystem name field */,
data.dimensions_in_what().value_tuple().dimensions_value(0).field());
EXPECT_FALSE(data.dimensions_in_what().value_tuple().dimensions_value(0).value_str().empty());
// We have 4 buckets, the first one was incomplete since the condition was unknown.
EXPECT_EQ(4, data.bucket_info_size());
EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
EXPECT_EQ(1, data.bucket_info(0).values_size());
EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs, data.bucket_info(1).start_bucket_elapsed_nanos());
EXPECT_EQ(baseTimeNs + 5 * bucketSizeNs, data.bucket_info(1).end_bucket_elapsed_nanos());
EXPECT_EQ(1, data.bucket_info(1).values_size());
EXPECT_EQ(baseTimeNs + 6 * bucketSizeNs, data.bucket_info(2).start_bucket_elapsed_nanos());
EXPECT_EQ(baseTimeNs + 7 * bucketSizeNs, data.bucket_info(2).end_bucket_elapsed_nanos());
EXPECT_EQ(1, data.bucket_info(2).values_size());
EXPECT_EQ(baseTimeNs + 7 * bucketSizeNs, data.bucket_info(3).start_bucket_elapsed_nanos());
EXPECT_EQ(baseTimeNs + 8 * bucketSizeNs, data.bucket_info(3).end_bucket_elapsed_nanos());
EXPECT_EQ(1, data.bucket_info(3).values_size());
}
TEST(ValueMetricE2eTest, TestPulledEvents_LateAlarm) {
auto config = CreateStatsdConfig();
int64_t baseTimeNs = getElapsedRealtimeNs();
// 10 mins == 2 bucket durations.
int64_t configAddedTimeNs = 10 * 60 * NS_PER_SEC + baseTimeNs;
int64_t bucketSizeNs =
TimeUnitToBucketSizeInMillis(config.value_metric(0).bucket()) * 1000000;
ConfigKey cfgKey;
auto processor = CreateStatsLogProcessor(baseTimeNs, configAddedTimeNs, config, cfgKey,
SharedRefBase::make<FakeSubsystemSleepCallback>(),
android::util::SUBSYSTEM_SLEEP_STATE);
EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
processor->mPullerManager->ForceClearPullerCache();
int startBucketNum = processor->mMetricsManagers.begin()->second->
mAllMetricProducers[0]->getCurrentBucketNum();
EXPECT_GT(startBucketNum, (int64_t)0);
// When creating the config, the value metric producer should register the alarm at the
// end of the current bucket.
EXPECT_EQ((size_t)1, processor->mPullerManager->mReceivers.size());
EXPECT_EQ(bucketSizeNs,
processor->mPullerManager->mReceivers.begin()->second.front().intervalNs);
int64_t& expectedPullTimeNs =
processor->mPullerManager->mReceivers.begin()->second.front().nextPullTimeNs;
EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + bucketSizeNs, expectedPullTimeNs);
// Screen off/on/off events.
auto screenOffEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
configAddedTimeNs + 55);
processor->OnLogEvent(screenOffEvent.get());
auto screenOnEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
configAddedTimeNs + 65);
processor->OnLogEvent(screenOnEvent.get());
screenOffEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
configAddedTimeNs + 75);
processor->OnLogEvent(screenOffEvent.get());
// Pulling alarm arrives late by 2 buckets and 1 ns. 2 buckets late is too far away in the
// future, data will be skipped.
processor->informPullAlarmFired(expectedPullTimeNs + 2 * bucketSizeNs + 1);
EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 4 * bucketSizeNs, expectedPullTimeNs);
// This screen state change will start a new bucket.
screenOnEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
configAddedTimeNs + 4 * bucketSizeNs + 65);
processor->OnLogEvent(screenOnEvent.get());
// The alarm is delayed but we already created a bucket thanks to the screen state condition.
// This bucket does not have to be skipped since the alarm arrives in time for the next bucket.
processor->informPullAlarmFired(expectedPullTimeNs + bucketSizeNs + 21);
EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 6 * bucketSizeNs, expectedPullTimeNs);
screenOffEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
configAddedTimeNs + 6 * bucketSizeNs + 31);
processor->OnLogEvent(screenOffEvent.get());
processor->informPullAlarmFired(expectedPullTimeNs + bucketSizeNs + 21);
EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 8 * bucketSizeNs, expectedPullTimeNs);
processor->informPullAlarmFired(expectedPullTimeNs + 1);
EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 9 * bucketSizeNs, expectedPullTimeNs);
ConfigMetricsReportList reports;
vector<uint8_t> buffer;
processor->onDumpReport(cfgKey, configAddedTimeNs + 9 * bucketSizeNs + 10, false, true,
ADB_DUMP, FAST, &buffer);
EXPECT_TRUE(buffer.size() > 0);
EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
backfillDimensionPath(&reports);
backfillStringInReport(&reports);
backfillStartEndTimestamp(&reports);
EXPECT_EQ(1, reports.reports_size());
EXPECT_EQ(1, reports.reports(0).metrics_size());
StatsLogReport::ValueMetricDataWrapper valueMetrics;
sortMetricDataByDimensionsValue(
reports.reports(0).metrics(0).value_metrics(), &valueMetrics);
EXPECT_GT((int)valueMetrics.data_size(), 1);
auto data = valueMetrics.data(0);
EXPECT_EQ(android::util::SUBSYSTEM_SLEEP_STATE, data.dimensions_in_what().field());
EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
EXPECT_EQ(1 /* subsystem name field */,
data.dimensions_in_what().value_tuple().dimensions_value(0).field());
EXPECT_FALSE(data.dimensions_in_what().value_tuple().dimensions_value(0).value_str().empty());
EXPECT_EQ(3, data.bucket_info_size());
EXPECT_EQ(baseTimeNs + 5 * bucketSizeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
EXPECT_EQ(baseTimeNs + 6 * bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
EXPECT_EQ(1, data.bucket_info(0).values_size());
EXPECT_EQ(baseTimeNs + 8 * bucketSizeNs, data.bucket_info(1).start_bucket_elapsed_nanos());
EXPECT_EQ(baseTimeNs + 9 * bucketSizeNs, data.bucket_info(1).end_bucket_elapsed_nanos());
EXPECT_EQ(1, data.bucket_info(1).values_size());
EXPECT_EQ(baseTimeNs + 9 * bucketSizeNs, data.bucket_info(2).start_bucket_elapsed_nanos());
EXPECT_EQ(baseTimeNs + 10 * bucketSizeNs, data.bucket_info(2).end_bucket_elapsed_nanos());
EXPECT_EQ(1, data.bucket_info(2).values_size());
}
TEST(ValueMetricE2eTest, TestPulledEvents_WithActivation) {
auto config = CreateStatsdConfig(false);
int64_t baseTimeNs = getElapsedRealtimeNs();
int64_t configAddedTimeNs = 10 * 60 * NS_PER_SEC + baseTimeNs;
int64_t bucketSizeNs =
TimeUnitToBucketSizeInMillis(config.value_metric(0).bucket()) * 1000000;
auto batterySaverStartMatcher = CreateBatterySaverModeStartAtomMatcher();
*config.add_atom_matcher() = batterySaverStartMatcher;
const int64_t ttlNs = 2 * bucketSizeNs; // Two buckets.
auto metric_activation = config.add_metric_activation();
metric_activation->set_metric_id(metricId);
metric_activation->set_activation_type(ACTIVATE_IMMEDIATELY);
auto event_activation = metric_activation->add_event_activation();
event_activation->set_atom_matcher_id(batterySaverStartMatcher.id());
event_activation->set_ttl_seconds(ttlNs / 1000000000);
ConfigKey cfgKey;
auto processor = CreateStatsLogProcessor(baseTimeNs, configAddedTimeNs, config, cfgKey,
SharedRefBase::make<FakeSubsystemSleepCallback>(),
android::util::SUBSYSTEM_SLEEP_STATE);
EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
processor->mPullerManager->ForceClearPullerCache();
int startBucketNum = processor->mMetricsManagers.begin()->second->
mAllMetricProducers[0]->getCurrentBucketNum();
EXPECT_GT(startBucketNum, (int64_t)0);
EXPECT_FALSE(processor->mMetricsManagers.begin()->second->mAllMetricProducers[0]->isActive());
// When creating the config, the value metric producer should register the alarm at the
// end of the current bucket.
EXPECT_EQ((size_t)1, processor->mPullerManager->mReceivers.size());
EXPECT_EQ(bucketSizeNs,
processor->mPullerManager->mReceivers.begin()->second.front().intervalNs);
int64_t& expectedPullTimeNs =
processor->mPullerManager->mReceivers.begin()->second.front().nextPullTimeNs;
EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + bucketSizeNs, expectedPullTimeNs);
// Pulling alarm arrives on time and reset the sequential pulling alarm.
processor->informPullAlarmFired(expectedPullTimeNs + 1); // 15 mins + 1 ns.
EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 2 * bucketSizeNs, expectedPullTimeNs);
EXPECT_FALSE(processor->mMetricsManagers.begin()->second->mAllMetricProducers[0]->isActive());
// Activate the metric. A pull occurs here
const int64_t activationNs = configAddedTimeNs + bucketSizeNs + (2 * 1000 * 1000); // 2 millis.
auto batterySaverOnEvent = CreateBatterySaverOnEvent(activationNs);
processor->OnLogEvent(batterySaverOnEvent.get()); // 15 mins + 2 ms.
EXPECT_TRUE(processor->mMetricsManagers.begin()->second->mAllMetricProducers[0]->isActive());
processor->informPullAlarmFired(expectedPullTimeNs + 1); // 20 mins + 1 ns.
EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 3 * bucketSizeNs, expectedPullTimeNs);
processor->informPullAlarmFired(expectedPullTimeNs + 2); // 25 mins + 2 ns.
EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 4 * bucketSizeNs, expectedPullTimeNs);
// Create random event to deactivate metric.
auto deactivationEvent = CreateScreenBrightnessChangedEvent(50, activationNs + ttlNs + 1);
processor->OnLogEvent(deactivationEvent.get());
EXPECT_FALSE(processor->mMetricsManagers.begin()->second->mAllMetricProducers[0]->isActive());
processor->informPullAlarmFired(expectedPullTimeNs + 3);
EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 5 * bucketSizeNs, expectedPullTimeNs);
processor->informPullAlarmFired(expectedPullTimeNs + 4);
EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 6 * bucketSizeNs, expectedPullTimeNs);
ConfigMetricsReportList reports;
vector<uint8_t> buffer;
processor->onDumpReport(cfgKey, configAddedTimeNs + 7 * bucketSizeNs + 10, false, true,
ADB_DUMP, FAST, &buffer);
EXPECT_TRUE(buffer.size() > 0);
EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
backfillDimensionPath(&reports);
backfillStringInReport(&reports);
backfillStartEndTimestamp(&reports);
EXPECT_EQ(1, reports.reports_size());
EXPECT_EQ(1, reports.reports(0).metrics_size());
StatsLogReport::ValueMetricDataWrapper valueMetrics;
sortMetricDataByDimensionsValue(
reports.reports(0).metrics(0).value_metrics(), &valueMetrics);
EXPECT_GT((int)valueMetrics.data_size(), 0);
auto data = valueMetrics.data(0);
EXPECT_EQ(android::util::SUBSYSTEM_SLEEP_STATE, data.dimensions_in_what().field());
EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
EXPECT_EQ(1 /* subsystem name field */,
data.dimensions_in_what().value_tuple().dimensions_value(0).field());
EXPECT_FALSE(data.dimensions_in_what().value_tuple().dimensions_value(0).value_str().empty());
// We have 2 full buckets, the two surrounding the activation are dropped.
EXPECT_EQ(2, data.bucket_info_size());
auto bucketInfo = data.bucket_info(0);
EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs, bucketInfo.start_bucket_elapsed_nanos());
EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs, bucketInfo.end_bucket_elapsed_nanos());
EXPECT_EQ(1, bucketInfo.values_size());
bucketInfo = data.bucket_info(1);
EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs, bucketInfo.start_bucket_elapsed_nanos());
EXPECT_EQ(baseTimeNs + 5 * bucketSizeNs, bucketInfo.end_bucket_elapsed_nanos());
EXPECT_EQ(1, bucketInfo.values_size());
}
// TODO(b/149590301): Update this test to use new socket schema.
//TEST(ValueMetricE2eTest, TestPulledEvents) {
// auto config = CreateStatsdConfig();
// int64_t baseTimeNs = getElapsedRealtimeNs();
// int64_t configAddedTimeNs = 10 * 60 * NS_PER_SEC + baseTimeNs;
// int64_t bucketSizeNs =
// TimeUnitToBucketSizeInMillis(config.value_metric(0).bucket()) * 1000000;
//
// ConfigKey cfgKey;
// auto processor = CreateStatsLogProcessor(baseTimeNs, configAddedTimeNs, config, cfgKey,
// SharedRefBase::make<FakeSubsystemSleepCallback>(),
// android::util::SUBSYSTEM_SLEEP_STATE);
// EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
// EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
// processor->mPullerManager->ForceClearPullerCache();
//
// int startBucketNum = processor->mMetricsManagers.begin()->second->
// mAllMetricProducers[0]->getCurrentBucketNum();
// EXPECT_GT(startBucketNum, (int64_t)0);
//
// // When creating the config, the value metric producer should register the alarm at the
// // end of the current bucket.
// EXPECT_EQ((size_t)1, processor->mPullerManager->mReceivers.size());
// EXPECT_EQ(bucketSizeNs,
// processor->mPullerManager->mReceivers.begin()->second.front().intervalNs);
// int64_t& expectedPullTimeNs =
// processor->mPullerManager->mReceivers.begin()->second.front().nextPullTimeNs;
// EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + bucketSizeNs, expectedPullTimeNs);
//
// auto screenOffEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
// configAddedTimeNs + 55);
// processor->OnLogEvent(screenOffEvent.get());
//
// auto screenOnEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
// configAddedTimeNs + 65);
// processor->OnLogEvent(screenOnEvent.get());
//
// screenOffEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
// configAddedTimeNs + 75);
// processor->OnLogEvent(screenOffEvent.get());
//
// // Pulling alarm arrives on time and reset the sequential pulling alarm.
// processor->informPullAlarmFired(expectedPullTimeNs + 1);
// EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 2 * bucketSizeNs, expectedPullTimeNs);
//
// processor->informPullAlarmFired(expectedPullTimeNs + 1);
//
// screenOnEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
// configAddedTimeNs + 2 * bucketSizeNs + 15);
// processor->OnLogEvent(screenOnEvent.get());
//
// processor->informPullAlarmFired(expectedPullTimeNs + 1);
//
// processor->informPullAlarmFired(expectedPullTimeNs + 1);
//
// screenOffEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
// configAddedTimeNs + 4 * bucketSizeNs + 11);
// processor->OnLogEvent(screenOffEvent.get());
//
// processor->informPullAlarmFired(expectedPullTimeNs + 1);
//
// processor->informPullAlarmFired(expectedPullTimeNs + 1);
//
// ConfigMetricsReportList reports;
// vector<uint8_t> buffer;
// processor->onDumpReport(cfgKey, configAddedTimeNs + 7 * bucketSizeNs + 10, false, true,
// ADB_DUMP, FAST, &buffer);
// EXPECT_TRUE(buffer.size() > 0);
// EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
// backfillDimensionPath(&reports);
// backfillStringInReport(&reports);
// backfillStartEndTimestamp(&reports);
// EXPECT_EQ(1, reports.reports_size());
// EXPECT_EQ(1, reports.reports(0).metrics_size());
// StatsLogReport::ValueMetricDataWrapper valueMetrics;
// sortMetricDataByDimensionsValue(
// reports.reports(0).metrics(0).value_metrics(), &valueMetrics);
// EXPECT_GT((int)valueMetrics.data_size(), 1);
//
// auto data = valueMetrics.data(0);
// EXPECT_EQ(android::util::SUBSYSTEM_SLEEP_STATE, data.dimensions_in_what().field());
// EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
// EXPECT_EQ(1 /* subsystem name field */,
// data.dimensions_in_what().value_tuple().dimensions_value(0).field());
// EXPECT_FALSE(data.dimensions_in_what().value_tuple().dimensions_value(0).value_str().empty());
// // We have 4 buckets, the first one was incomplete since the condition was unknown.
// EXPECT_EQ(4, data.bucket_info_size());
//
// EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
// EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
// EXPECT_EQ(1, data.bucket_info(0).values_size());
//
// EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs, data.bucket_info(1).start_bucket_elapsed_nanos());
// EXPECT_EQ(baseTimeNs + 5 * bucketSizeNs, data.bucket_info(1).end_bucket_elapsed_nanos());
// EXPECT_EQ(1, data.bucket_info(1).values_size());
//
// EXPECT_EQ(baseTimeNs + 6 * bucketSizeNs, data.bucket_info(2).start_bucket_elapsed_nanos());
// EXPECT_EQ(baseTimeNs + 7 * bucketSizeNs, data.bucket_info(2).end_bucket_elapsed_nanos());
// EXPECT_EQ(1, data.bucket_info(2).values_size());
//
// EXPECT_EQ(baseTimeNs + 7 * bucketSizeNs, data.bucket_info(3).start_bucket_elapsed_nanos());
// EXPECT_EQ(baseTimeNs + 8 * bucketSizeNs, data.bucket_info(3).end_bucket_elapsed_nanos());
// EXPECT_EQ(1, data.bucket_info(3).values_size());
//}
//
//TEST(ValueMetricE2eTest, TestPulledEvents_LateAlarm) {
// auto config = CreateStatsdConfig();
// int64_t baseTimeNs = getElapsedRealtimeNs();
// // 10 mins == 2 bucket durations.
// int64_t configAddedTimeNs = 10 * 60 * NS_PER_SEC + baseTimeNs;
// int64_t bucketSizeNs =
// TimeUnitToBucketSizeInMillis(config.value_metric(0).bucket()) * 1000000;
//
// ConfigKey cfgKey;
// auto processor = CreateStatsLogProcessor(baseTimeNs, configAddedTimeNs, config, cfgKey,
// SharedRefBase::make<FakeSubsystemSleepCallback>(),
// android::util::SUBSYSTEM_SLEEP_STATE);
// EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
// EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
// processor->mPullerManager->ForceClearPullerCache();
//
// int startBucketNum = processor->mMetricsManagers.begin()->second->
// mAllMetricProducers[0]->getCurrentBucketNum();
// EXPECT_GT(startBucketNum, (int64_t)0);
//
// // When creating the config, the value metric producer should register the alarm at the
// // end of the current bucket.
// EXPECT_EQ((size_t)1, processor->mPullerManager->mReceivers.size());
// EXPECT_EQ(bucketSizeNs,
// processor->mPullerManager->mReceivers.begin()->second.front().intervalNs);
// int64_t& expectedPullTimeNs =
// processor->mPullerManager->mReceivers.begin()->second.front().nextPullTimeNs;
// EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + bucketSizeNs, expectedPullTimeNs);
//
// // Screen off/on/off events.
// auto screenOffEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
// configAddedTimeNs + 55);
// processor->OnLogEvent(screenOffEvent.get());
//
// auto screenOnEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
// configAddedTimeNs + 65);
// processor->OnLogEvent(screenOnEvent.get());
//
// screenOffEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
// configAddedTimeNs + 75);
// processor->OnLogEvent(screenOffEvent.get());
//
// // Pulling alarm arrives late by 2 buckets and 1 ns. 2 buckets late is too far away in the
// // future, data will be skipped.
// processor->informPullAlarmFired(expectedPullTimeNs + 2 * bucketSizeNs + 1);
// EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 4 * bucketSizeNs, expectedPullTimeNs);
//
// // This screen state change will start a new bucket.
// screenOnEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
// configAddedTimeNs + 4 * bucketSizeNs + 65);
// processor->OnLogEvent(screenOnEvent.get());
//
// // The alarm is delayed but we already created a bucket thanks to the screen state condition.
// // This bucket does not have to be skipped since the alarm arrives in time for the next bucket.
// processor->informPullAlarmFired(expectedPullTimeNs + bucketSizeNs + 21);
// EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 6 * bucketSizeNs, expectedPullTimeNs);
//
// screenOffEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
// configAddedTimeNs + 6 * bucketSizeNs + 31);
// processor->OnLogEvent(screenOffEvent.get());
//
// processor->informPullAlarmFired(expectedPullTimeNs + bucketSizeNs + 21);
// EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 8 * bucketSizeNs, expectedPullTimeNs);
//
// processor->informPullAlarmFired(expectedPullTimeNs + 1);
// EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 9 * bucketSizeNs, expectedPullTimeNs);
//
// ConfigMetricsReportList reports;
// vector<uint8_t> buffer;
// processor->onDumpReport(cfgKey, configAddedTimeNs + 9 * bucketSizeNs + 10, false, true,
// ADB_DUMP, FAST, &buffer);
// EXPECT_TRUE(buffer.size() > 0);
// EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
// backfillDimensionPath(&reports);
// backfillStringInReport(&reports);
// backfillStartEndTimestamp(&reports);
// EXPECT_EQ(1, reports.reports_size());
// EXPECT_EQ(1, reports.reports(0).metrics_size());
// StatsLogReport::ValueMetricDataWrapper valueMetrics;
// sortMetricDataByDimensionsValue(
// reports.reports(0).metrics(0).value_metrics(), &valueMetrics);
// EXPECT_GT((int)valueMetrics.data_size(), 1);
//
// auto data = valueMetrics.data(0);
// EXPECT_EQ(android::util::SUBSYSTEM_SLEEP_STATE, data.dimensions_in_what().field());
// EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
// EXPECT_EQ(1 /* subsystem name field */,
// data.dimensions_in_what().value_tuple().dimensions_value(0).field());
// EXPECT_FALSE(data.dimensions_in_what().value_tuple().dimensions_value(0).value_str().empty());
// EXPECT_EQ(3, data.bucket_info_size());
//
// EXPECT_EQ(baseTimeNs + 5 * bucketSizeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
// EXPECT_EQ(baseTimeNs + 6 * bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
// EXPECT_EQ(1, data.bucket_info(0).values_size());
//
// EXPECT_EQ(baseTimeNs + 8 * bucketSizeNs, data.bucket_info(1).start_bucket_elapsed_nanos());
// EXPECT_EQ(baseTimeNs + 9 * bucketSizeNs, data.bucket_info(1).end_bucket_elapsed_nanos());
// EXPECT_EQ(1, data.bucket_info(1).values_size());
//
// EXPECT_EQ(baseTimeNs + 9 * bucketSizeNs, data.bucket_info(2).start_bucket_elapsed_nanos());
// EXPECT_EQ(baseTimeNs + 10 * bucketSizeNs, data.bucket_info(2).end_bucket_elapsed_nanos());
// EXPECT_EQ(1, data.bucket_info(2).values_size());
//}
//
//TEST(ValueMetricE2eTest, TestPulledEvents_WithActivation) {
// auto config = CreateStatsdConfig(false);
// int64_t baseTimeNs = getElapsedRealtimeNs();
// int64_t configAddedTimeNs = 10 * 60 * NS_PER_SEC + baseTimeNs;
// int64_t bucketSizeNs =
// TimeUnitToBucketSizeInMillis(config.value_metric(0).bucket()) * 1000000;
//
// auto batterySaverStartMatcher = CreateBatterySaverModeStartAtomMatcher();
// *config.add_atom_matcher() = batterySaverStartMatcher;
// const int64_t ttlNs = 2 * bucketSizeNs; // Two buckets.
// auto metric_activation = config.add_metric_activation();
// metric_activation->set_metric_id(metricId);
// metric_activation->set_activation_type(ACTIVATE_IMMEDIATELY);
// auto event_activation = metric_activation->add_event_activation();
// event_activation->set_atom_matcher_id(batterySaverStartMatcher.id());
// event_activation->set_ttl_seconds(ttlNs / 1000000000);
//
// ConfigKey cfgKey;
// auto processor = CreateStatsLogProcessor(baseTimeNs, configAddedTimeNs, config, cfgKey,
// SharedRefBase::make<FakeSubsystemSleepCallback>(),
// android::util::SUBSYSTEM_SLEEP_STATE);
// EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
// EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
// processor->mPullerManager->ForceClearPullerCache();
//
// int startBucketNum = processor->mMetricsManagers.begin()->second->
// mAllMetricProducers[0]->getCurrentBucketNum();
// EXPECT_GT(startBucketNum, (int64_t)0);
// EXPECT_FALSE(processor->mMetricsManagers.begin()->second->mAllMetricProducers[0]->isActive());
//
// // When creating the config, the value metric producer should register the alarm at the
// // end of the current bucket.
// EXPECT_EQ((size_t)1, processor->mPullerManager->mReceivers.size());
// EXPECT_EQ(bucketSizeNs,
// processor->mPullerManager->mReceivers.begin()->second.front().intervalNs);
// int64_t& expectedPullTimeNs =
// processor->mPullerManager->mReceivers.begin()->second.front().nextPullTimeNs;
// EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + bucketSizeNs, expectedPullTimeNs);
//
// // Pulling alarm arrives on time and reset the sequential pulling alarm.
// processor->informPullAlarmFired(expectedPullTimeNs + 1); // 15 mins + 1 ns.
// EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 2 * bucketSizeNs, expectedPullTimeNs);
// EXPECT_FALSE(processor->mMetricsManagers.begin()->second->mAllMetricProducers[0]->isActive());
//
// // Activate the metric. A pull occurs here
// const int64_t activationNs = configAddedTimeNs + bucketSizeNs + (2 * 1000 * 1000); // 2 millis.
// auto batterySaverOnEvent = CreateBatterySaverOnEvent(activationNs);
// processor->OnLogEvent(batterySaverOnEvent.get()); // 15 mins + 2 ms.
// EXPECT_TRUE(processor->mMetricsManagers.begin()->second->mAllMetricProducers[0]->isActive());
//
// processor->informPullAlarmFired(expectedPullTimeNs + 1); // 20 mins + 1 ns.
// EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 3 * bucketSizeNs, expectedPullTimeNs);
//
// processor->informPullAlarmFired(expectedPullTimeNs + 2); // 25 mins + 2 ns.
// EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 4 * bucketSizeNs, expectedPullTimeNs);
//
// // Create random event to deactivate metric.
// auto deactivationEvent = CreateScreenBrightnessChangedEvent(50, activationNs + ttlNs + 1);
// processor->OnLogEvent(deactivationEvent.get());
// EXPECT_FALSE(processor->mMetricsManagers.begin()->second->mAllMetricProducers[0]->isActive());
//
// processor->informPullAlarmFired(expectedPullTimeNs + 3);
// EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 5 * bucketSizeNs, expectedPullTimeNs);
//
// processor->informPullAlarmFired(expectedPullTimeNs + 4);
// EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 6 * bucketSizeNs, expectedPullTimeNs);
//
// ConfigMetricsReportList reports;
// vector<uint8_t> buffer;
// processor->onDumpReport(cfgKey, configAddedTimeNs + 7 * bucketSizeNs + 10, false, true,
// ADB_DUMP, FAST, &buffer);
// EXPECT_TRUE(buffer.size() > 0);
// EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
// backfillDimensionPath(&reports);
// backfillStringInReport(&reports);
// backfillStartEndTimestamp(&reports);
// EXPECT_EQ(1, reports.reports_size());
// EXPECT_EQ(1, reports.reports(0).metrics_size());
// StatsLogReport::ValueMetricDataWrapper valueMetrics;
// sortMetricDataByDimensionsValue(
// reports.reports(0).metrics(0).value_metrics(), &valueMetrics);
// EXPECT_GT((int)valueMetrics.data_size(), 0);
//
// auto data = valueMetrics.data(0);
// EXPECT_EQ(android::util::SUBSYSTEM_SLEEP_STATE, data.dimensions_in_what().field());
// EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
// EXPECT_EQ(1 /* subsystem name field */,
// data.dimensions_in_what().value_tuple().dimensions_value(0).field());
// EXPECT_FALSE(data.dimensions_in_what().value_tuple().dimensions_value(0).value_str().empty());
// // We have 2 full buckets, the two surrounding the activation are dropped.
// EXPECT_EQ(2, data.bucket_info_size());
//
// auto bucketInfo = data.bucket_info(0);
// EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs, bucketInfo.start_bucket_elapsed_nanos());
// EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs, bucketInfo.end_bucket_elapsed_nanos());
// EXPECT_EQ(1, bucketInfo.values_size());
//
// bucketInfo = data.bucket_info(1);
// EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs, bucketInfo.start_bucket_elapsed_nanos());
// EXPECT_EQ(baseTimeNs + 5 * bucketSizeNs, bucketInfo.end_bucket_elapsed_nanos());
// EXPECT_EQ(1, bucketInfo.values_size());
//}
/**
* Test initialization of a simple value metric that is sliced by a state.

View File

@@ -69,282 +69,284 @@ std::vector<AttributionNodeInternal> attributions2 = {CreateAttribution(111, "Ap
CreateAttribution(222, "GMSCoreModule1"),
CreateAttribution(222, "GMSCoreModule2")};
/*
Events:
Screen off is met from (200ns,1 min+500ns].
Acquire event for wl1 from 2ns to 1min+2ns
Acquire event for wl2 from 1min-10ns to 2min-15ns
*/
void FeedEvents(StatsdConfig config, sp<StatsLogProcessor> processor) {
uint64_t bucketStartTimeNs = 10000000000;
uint64_t bucketSizeNs =
TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
auto screenTurnedOnEvent = CreateScreenStateChangedEvent(
android::view::DisplayStateEnum::DISPLAY_STATE_ON, bucketStartTimeNs + 1);
auto screenTurnedOffEvent = CreateScreenStateChangedEvent(
android::view::DisplayStateEnum::DISPLAY_STATE_OFF, bucketStartTimeNs + 200);
auto screenTurnedOnEvent2 =
CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_ON,
bucketStartTimeNs + bucketSizeNs + 500);
auto acquireEvent1 = CreateAcquireWakelockEvent(attributions1, "wl1", bucketStartTimeNs + 2);
auto releaseEvent1 =
CreateReleaseWakelockEvent(attributions1, "wl1", bucketStartTimeNs + bucketSizeNs + 2);
auto acquireEvent2 =
CreateAcquireWakelockEvent(attributions2, "wl2", bucketStartTimeNs + bucketSizeNs - 10);
auto releaseEvent2 = CreateReleaseWakelockEvent(attributions2, "wl2",
bucketStartTimeNs + 2 * bucketSizeNs - 15);
std::vector<std::unique_ptr<LogEvent>> events;
events.push_back(std::move(screenTurnedOnEvent));
events.push_back(std::move(screenTurnedOffEvent));
events.push_back(std::move(screenTurnedOnEvent2));
events.push_back(std::move(acquireEvent1));
events.push_back(std::move(acquireEvent2));
events.push_back(std::move(releaseEvent1));
events.push_back(std::move(releaseEvent2));
sortLogEventsByTimestamp(&events);
for (const auto& event : events) {
processor->OnLogEvent(event.get());
}
}
// TODO(b/149590301): Update this helper to use new socket schema.
///*
//Events:
//Screen off is met from (200ns,1 min+500ns].
//Acquire event for wl1 from 2ns to 1min+2ns
//Acquire event for wl2 from 1min-10ns to 2min-15ns
//*/
//void FeedEvents(StatsdConfig config, sp<StatsLogProcessor> processor) {
// uint64_t bucketStartTimeNs = 10000000000;
// uint64_t bucketSizeNs =
// TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
//
// auto screenTurnedOnEvent = CreateScreenStateChangedEvent(
// android::view::DisplayStateEnum::DISPLAY_STATE_ON, bucketStartTimeNs + 1);
// auto screenTurnedOffEvent = CreateScreenStateChangedEvent(
// android::view::DisplayStateEnum::DISPLAY_STATE_OFF, bucketStartTimeNs + 200);
// auto screenTurnedOnEvent2 =
// CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_ON,
// bucketStartTimeNs + bucketSizeNs + 500);
//
// auto acquireEvent1 = CreateAcquireWakelockEvent(attributions1, "wl1", bucketStartTimeNs + 2);
// auto releaseEvent1 =
// CreateReleaseWakelockEvent(attributions1, "wl1", bucketStartTimeNs + bucketSizeNs + 2);
// auto acquireEvent2 =
// CreateAcquireWakelockEvent(attributions2, "wl2", bucketStartTimeNs + bucketSizeNs - 10);
// auto releaseEvent2 = CreateReleaseWakelockEvent(attributions2, "wl2",
// bucketStartTimeNs + 2 * bucketSizeNs - 15);
//
// std::vector<std::unique_ptr<LogEvent>> events;
//
// events.push_back(std::move(screenTurnedOnEvent));
// events.push_back(std::move(screenTurnedOffEvent));
// events.push_back(std::move(screenTurnedOnEvent2));
// events.push_back(std::move(acquireEvent1));
// events.push_back(std::move(acquireEvent2));
// events.push_back(std::move(releaseEvent1));
// events.push_back(std::move(releaseEvent2));
//
// sortLogEventsByTimestamp(&events);
//
// for (const auto& event : events) {
// processor->OnLogEvent(event.get());
// }
//}
} // namespace
TEST(WakelockDurationE2eTest, TestAggregatedPredicateDimensionsForSumDuration1) {
ConfigKey cfgKey;
auto config = CreateStatsdConfig(DurationMetric::SUM);
uint64_t bucketStartTimeNs = 10000000000;
uint64_t bucketSizeNs =
TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
FeedEvents(config, processor);
vector<uint8_t> buffer;
ConfigMetricsReportList reports;
processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs - 1, false, true,
ADB_DUMP, FAST, &buffer);
EXPECT_TRUE(buffer.size() > 0);
EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
backfillDimensionPath(&reports);
backfillStringInReport(&reports);
backfillStartEndTimestamp(&reports);
EXPECT_EQ(reports.reports_size(), 1);
EXPECT_EQ(reports.reports(0).metrics_size(), 1);
// Only 1 dimension output. The tag dimension in the predicate has been aggregated.
EXPECT_EQ(reports.reports(0).metrics(0).duration_metrics().data_size(), 1);
auto data = reports.reports(0).metrics(0).duration_metrics().data(0);
// Validate dimension value.
ValidateAttributionUidDimension(data.dimensions_in_what(),
android::util::WAKELOCK_STATE_CHANGED, 111);
// Validate bucket info.
EXPECT_EQ(reports.reports(0).metrics(0).duration_metrics().data(0).bucket_info_size(), 1);
data = reports.reports(0).metrics(0).duration_metrics().data(0);
// The wakelock holding interval starts from the screen off event and to the end of the 1st
// bucket.
EXPECT_EQ((unsigned long long)data.bucket_info(0).duration_nanos(), bucketSizeNs - 200);
}
TEST(WakelockDurationE2eTest, TestAggregatedPredicateDimensionsForSumDuration2) {
ConfigKey cfgKey;
auto config = CreateStatsdConfig(DurationMetric::SUM);
uint64_t bucketStartTimeNs = 10000000000;
uint64_t bucketSizeNs =
TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
FeedEvents(config, processor);
vector<uint8_t> buffer;
ConfigMetricsReportList reports;
processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, false, true,
ADB_DUMP, FAST, &buffer);
EXPECT_TRUE(buffer.size() > 0);
EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
backfillDimensionPath(&reports);
backfillStringInReport(&reports);
backfillStartEndTimestamp(&reports);
EXPECT_EQ(reports.reports_size(), 1);
EXPECT_EQ(reports.reports(0).metrics_size(), 1);
EXPECT_EQ(reports.reports(0).metrics(0).duration_metrics().data_size(), 1);
// Dump the report after the end of 2nd bucket.
EXPECT_EQ(reports.reports(0).metrics(0).duration_metrics().data(0).bucket_info_size(), 2);
auto data = reports.reports(0).metrics(0).duration_metrics().data(0);
// Validate dimension value.
ValidateAttributionUidDimension(data.dimensions_in_what(),
android::util::WAKELOCK_STATE_CHANGED, 111);
// Two output buckets.
// The wakelock holding interval in the 1st bucket starts from the screen off event and to
// the end of the 1st bucket.
EXPECT_EQ((unsigned long long)data.bucket_info(0).duration_nanos(),
bucketStartTimeNs + bucketSizeNs - (bucketStartTimeNs + 200));
// The wakelock holding interval in the 2nd bucket starts at the beginning of the bucket and
// ends at the second screen on event.
EXPECT_EQ((unsigned long long)data.bucket_info(1).duration_nanos(), 500UL);
}
TEST(WakelockDurationE2eTest, TestAggregatedPredicateDimensionsForSumDuration3) {
ConfigKey cfgKey;
auto config = CreateStatsdConfig(DurationMetric::SUM);
uint64_t bucketStartTimeNs = 10000000000;
uint64_t bucketSizeNs =
TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
FeedEvents(config, processor);
vector<uint8_t> buffer;
ConfigMetricsReportList reports;
std::vector<std::unique_ptr<LogEvent>> events;
events.push_back(
CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_OFF,
bucketStartTimeNs + 2 * bucketSizeNs + 90));
events.push_back(CreateAcquireWakelockEvent(attributions1, "wl3",
bucketStartTimeNs + 2 * bucketSizeNs + 100));
events.push_back(CreateReleaseWakelockEvent(attributions1, "wl3",
bucketStartTimeNs + 5 * bucketSizeNs + 100));
sortLogEventsByTimestamp(&events);
for (const auto& event : events) {
processor->OnLogEvent(event.get());
}
processor->onDumpReport(cfgKey, bucketStartTimeNs + 6 * bucketSizeNs + 1, false, true,
ADB_DUMP, FAST, &buffer);
EXPECT_TRUE(buffer.size() > 0);
EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
backfillDimensionPath(&reports);
backfillStringInReport(&reports);
backfillStartEndTimestamp(&reports);
EXPECT_EQ(reports.reports_size(), 1);
EXPECT_EQ(reports.reports(0).metrics_size(), 1);
EXPECT_EQ(reports.reports(0).metrics(0).duration_metrics().data_size(), 1);
EXPECT_EQ(reports.reports(0).metrics(0).duration_metrics().data(0).bucket_info_size(), 6);
auto data = reports.reports(0).metrics(0).duration_metrics().data(0);
ValidateAttributionUidDimension(data.dimensions_in_what(),
android::util::WAKELOCK_STATE_CHANGED, 111);
// The last wakelock holding spans 4 buckets.
EXPECT_EQ((unsigned long long)data.bucket_info(2).duration_nanos(), bucketSizeNs - 100);
EXPECT_EQ((unsigned long long)data.bucket_info(3).duration_nanos(), bucketSizeNs);
EXPECT_EQ((unsigned long long)data.bucket_info(4).duration_nanos(), bucketSizeNs);
EXPECT_EQ((unsigned long long)data.bucket_info(5).duration_nanos(), 100UL);
}
TEST(WakelockDurationE2eTest, TestAggregatedPredicateDimensionsForMaxDuration1) {
ConfigKey cfgKey;
auto config = CreateStatsdConfig(DurationMetric::MAX_SPARSE);
uint64_t bucketStartTimeNs = 10000000000;
uint64_t bucketSizeNs =
TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
FeedEvents(config, processor);
ConfigMetricsReportList reports;
vector<uint8_t> buffer;
processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs - 1, false, true,
ADB_DUMP, FAST, &buffer);
EXPECT_TRUE(buffer.size() > 0);
EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
backfillDimensionPath(&reports);
backfillStringInReport(&reports);
backfillStartEndTimestamp(&reports);
EXPECT_EQ(reports.reports_size(), 1);
// When using ProtoOutputStream, if nothing written to a sub msg, it won't be treated as
// one. It was previsouly 1 because we had a fake onDumpReport which calls add_metric() by
// itself.
EXPECT_EQ(1, reports.reports(0).metrics_size());
EXPECT_EQ(0, reports.reports(0).metrics(0).duration_metrics().data_size());
}
TEST(WakelockDurationE2eTest, TestAggregatedPredicateDimensionsForMaxDuration2) {
ConfigKey cfgKey;
auto config = CreateStatsdConfig(DurationMetric::MAX_SPARSE);
uint64_t bucketStartTimeNs = 10000000000;
uint64_t bucketSizeNs =
TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
FeedEvents(config, processor);
ConfigMetricsReportList reports;
vector<uint8_t> buffer;
processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, false, true,
ADB_DUMP, FAST, &buffer);
EXPECT_TRUE(buffer.size() > 0);
EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
backfillDimensionPath(&reports);
backfillStringInReport(&reports);
backfillStartEndTimestamp(&reports);
EXPECT_EQ(reports.reports_size(), 1);
EXPECT_EQ(reports.reports(0).metrics_size(), 1);
EXPECT_EQ(reports.reports(0).metrics(0).duration_metrics().data_size(), 1);
// Dump the report after the end of 2nd bucket. One dimension with one bucket.
EXPECT_EQ(reports.reports(0).metrics(0).duration_metrics().data(0).bucket_info_size(), 1);
auto data = reports.reports(0).metrics(0).duration_metrics().data(0);
// Validate dimension value.
ValidateAttributionUidDimension(data.dimensions_in_what(),
android::util::WAKELOCK_STATE_CHANGED, 111);
// The max is acquire event for wl1 to screen off start.
EXPECT_EQ((unsigned long long)data.bucket_info(0).duration_nanos(), bucketSizeNs + 2 - 200);
}
TEST(WakelockDurationE2eTest, TestAggregatedPredicateDimensionsForMaxDuration3) {
ConfigKey cfgKey;
auto config = CreateStatsdConfig(DurationMetric::MAX_SPARSE);
uint64_t bucketStartTimeNs = 10000000000;
uint64_t bucketSizeNs =
TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
FeedEvents(config, processor);
ConfigMetricsReportList reports;
vector<uint8_t> buffer;
std::vector<std::unique_ptr<LogEvent>> events;
events.push_back(
CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_OFF,
bucketStartTimeNs + 2 * bucketSizeNs + 90));
events.push_back(CreateAcquireWakelockEvent(attributions1, "wl3",
bucketStartTimeNs + 2 * bucketSizeNs + 100));
events.push_back(CreateReleaseWakelockEvent(attributions1, "wl3",
bucketStartTimeNs + 5 * bucketSizeNs + 100));
sortLogEventsByTimestamp(&events);
for (const auto& event : events) {
processor->OnLogEvent(event.get());
}
processor->onDumpReport(cfgKey, bucketStartTimeNs + 6 * bucketSizeNs + 1, false, true,
ADB_DUMP, FAST, &buffer);
EXPECT_TRUE(buffer.size() > 0);
EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
backfillDimensionPath(&reports);
backfillStringInReport(&reports);
backfillStartEndTimestamp(&reports);
EXPECT_EQ(reports.reports_size(), 1);
EXPECT_EQ(reports.reports(0).metrics_size(), 1);
EXPECT_EQ(reports.reports(0).metrics(0).duration_metrics().data_size(), 1);
EXPECT_EQ(reports.reports(0).metrics(0).duration_metrics().data(0).bucket_info_size(), 2);
auto data = reports.reports(0).metrics(0).duration_metrics().data(0);
ValidateAttributionUidDimension(data.dimensions_in_what(),
android::util::WAKELOCK_STATE_CHANGED, 111);
// The last wakelock holding spans 4 buckets.
EXPECT_EQ((unsigned long long)data.bucket_info(1).duration_nanos(), 3 * bucketSizeNs);
EXPECT_EQ((unsigned long long)data.bucket_info(1).start_bucket_elapsed_nanos(),
bucketStartTimeNs + 5 * bucketSizeNs);
EXPECT_EQ((unsigned long long)data.bucket_info(1).end_bucket_elapsed_nanos(),
bucketStartTimeNs + 6 * bucketSizeNs);
}
// TODO(b/149590301): Update these tests to use new socket schema.
//TEST(WakelockDurationE2eTest, TestAggregatedPredicateDimensionsForSumDuration1) {
// ConfigKey cfgKey;
// auto config = CreateStatsdConfig(DurationMetric::SUM);
// uint64_t bucketStartTimeNs = 10000000000;
// uint64_t bucketSizeNs =
// TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
// auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
// EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
// EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
// FeedEvents(config, processor);
// vector<uint8_t> buffer;
// ConfigMetricsReportList reports;
// processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs - 1, false, true,
// ADB_DUMP, FAST, &buffer);
// EXPECT_TRUE(buffer.size() > 0);
// EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
// backfillDimensionPath(&reports);
// backfillStringInReport(&reports);
// backfillStartEndTimestamp(&reports);
//
// EXPECT_EQ(reports.reports_size(), 1);
// EXPECT_EQ(reports.reports(0).metrics_size(), 1);
// // Only 1 dimension output. The tag dimension in the predicate has been aggregated.
// EXPECT_EQ(reports.reports(0).metrics(0).duration_metrics().data_size(), 1);
//
// auto data = reports.reports(0).metrics(0).duration_metrics().data(0);
// // Validate dimension value.
// ValidateAttributionUidDimension(data.dimensions_in_what(),
// android::util::WAKELOCK_STATE_CHANGED, 111);
// // Validate bucket info.
// EXPECT_EQ(reports.reports(0).metrics(0).duration_metrics().data(0).bucket_info_size(), 1);
// data = reports.reports(0).metrics(0).duration_metrics().data(0);
// // The wakelock holding interval starts from the screen off event and to the end of the 1st
// // bucket.
// EXPECT_EQ((unsigned long long)data.bucket_info(0).duration_nanos(), bucketSizeNs - 200);
//}
//
//TEST(WakelockDurationE2eTest, TestAggregatedPredicateDimensionsForSumDuration2) {
// ConfigKey cfgKey;
// auto config = CreateStatsdConfig(DurationMetric::SUM);
// uint64_t bucketStartTimeNs = 10000000000;
// uint64_t bucketSizeNs =
// TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
// auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
// EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
// EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
// FeedEvents(config, processor);
// vector<uint8_t> buffer;
// ConfigMetricsReportList reports;
// processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, false, true,
// ADB_DUMP, FAST, &buffer);
// EXPECT_TRUE(buffer.size() > 0);
// EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
// backfillDimensionPath(&reports);
// backfillStringInReport(&reports);
// backfillStartEndTimestamp(&reports);
// EXPECT_EQ(reports.reports_size(), 1);
// EXPECT_EQ(reports.reports(0).metrics_size(), 1);
// EXPECT_EQ(reports.reports(0).metrics(0).duration_metrics().data_size(), 1);
// // Dump the report after the end of 2nd bucket.
// EXPECT_EQ(reports.reports(0).metrics(0).duration_metrics().data(0).bucket_info_size(), 2);
// auto data = reports.reports(0).metrics(0).duration_metrics().data(0);
// // Validate dimension value.
// ValidateAttributionUidDimension(data.dimensions_in_what(),
// android::util::WAKELOCK_STATE_CHANGED, 111);
// // Two output buckets.
// // The wakelock holding interval in the 1st bucket starts from the screen off event and to
// // the end of the 1st bucket.
// EXPECT_EQ((unsigned long long)data.bucket_info(0).duration_nanos(),
// bucketStartTimeNs + bucketSizeNs - (bucketStartTimeNs + 200));
// // The wakelock holding interval in the 2nd bucket starts at the beginning of the bucket and
// // ends at the second screen on event.
// EXPECT_EQ((unsigned long long)data.bucket_info(1).duration_nanos(), 500UL);
//}
//TEST(WakelockDurationE2eTest, TestAggregatedPredicateDimensionsForSumDuration3) {
// ConfigKey cfgKey;
// auto config = CreateStatsdConfig(DurationMetric::SUM);
// uint64_t bucketStartTimeNs = 10000000000;
// uint64_t bucketSizeNs =
// TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
// auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
// EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
// EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
// FeedEvents(config, processor);
// vector<uint8_t> buffer;
// ConfigMetricsReportList reports;
//
// std::vector<std::unique_ptr<LogEvent>> events;
// events.push_back(
// CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_OFF,
// bucketStartTimeNs + 2 * bucketSizeNs + 90));
// events.push_back(CreateAcquireWakelockEvent(attributions1, "wl3",
// bucketStartTimeNs + 2 * bucketSizeNs + 100));
// events.push_back(CreateReleaseWakelockEvent(attributions1, "wl3",
// bucketStartTimeNs + 5 * bucketSizeNs + 100));
// sortLogEventsByTimestamp(&events);
// for (const auto& event : events) {
// processor->OnLogEvent(event.get());
// }
//
// processor->onDumpReport(cfgKey, bucketStartTimeNs + 6 * bucketSizeNs + 1, false, true,
// ADB_DUMP, FAST, &buffer);
// EXPECT_TRUE(buffer.size() > 0);
// EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
// backfillDimensionPath(&reports);
// backfillStringInReport(&reports);
// backfillStartEndTimestamp(&reports);
// EXPECT_EQ(reports.reports_size(), 1);
// EXPECT_EQ(reports.reports(0).metrics_size(), 1);
// EXPECT_EQ(reports.reports(0).metrics(0).duration_metrics().data_size(), 1);
// EXPECT_EQ(reports.reports(0).metrics(0).duration_metrics().data(0).bucket_info_size(), 6);
// auto data = reports.reports(0).metrics(0).duration_metrics().data(0);
// ValidateAttributionUidDimension(data.dimensions_in_what(),
// android::util::WAKELOCK_STATE_CHANGED, 111);
// // The last wakelock holding spans 4 buckets.
// EXPECT_EQ((unsigned long long)data.bucket_info(2).duration_nanos(), bucketSizeNs - 100);
// EXPECT_EQ((unsigned long long)data.bucket_info(3).duration_nanos(), bucketSizeNs);
// EXPECT_EQ((unsigned long long)data.bucket_info(4).duration_nanos(), bucketSizeNs);
// EXPECT_EQ((unsigned long long)data.bucket_info(5).duration_nanos(), 100UL);
//}
//
//TEST(WakelockDurationE2eTest, TestAggregatedPredicateDimensionsForMaxDuration1) {
// ConfigKey cfgKey;
// auto config = CreateStatsdConfig(DurationMetric::MAX_SPARSE);
// uint64_t bucketStartTimeNs = 10000000000;
// uint64_t bucketSizeNs =
// TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
// auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
// EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
// EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
// FeedEvents(config, processor);
// ConfigMetricsReportList reports;
// vector<uint8_t> buffer;
// processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs - 1, false, true,
// ADB_DUMP, FAST, &buffer);
// EXPECT_TRUE(buffer.size() > 0);
//
// EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
// backfillDimensionPath(&reports);
// backfillStringInReport(&reports);
// backfillStartEndTimestamp(&reports);
//
// EXPECT_EQ(reports.reports_size(), 1);
//
// // When using ProtoOutputStream, if nothing written to a sub msg, it won't be treated as
// // one. It was previsouly 1 because we had a fake onDumpReport which calls add_metric() by
// // itself.
// EXPECT_EQ(1, reports.reports(0).metrics_size());
// EXPECT_EQ(0, reports.reports(0).metrics(0).duration_metrics().data_size());
//}
//
//TEST(WakelockDurationE2eTest, TestAggregatedPredicateDimensionsForMaxDuration2) {
// ConfigKey cfgKey;
// auto config = CreateStatsdConfig(DurationMetric::MAX_SPARSE);
// uint64_t bucketStartTimeNs = 10000000000;
// uint64_t bucketSizeNs =
// TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
// auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
// EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
// EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
// FeedEvents(config, processor);
// ConfigMetricsReportList reports;
// vector<uint8_t> buffer;
// processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, false, true,
// ADB_DUMP, FAST, &buffer);
// EXPECT_TRUE(buffer.size() > 0);
// EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
// backfillDimensionPath(&reports);
// backfillStringInReport(&reports);
// backfillStartEndTimestamp(&reports);
// EXPECT_EQ(reports.reports_size(), 1);
// EXPECT_EQ(reports.reports(0).metrics_size(), 1);
// EXPECT_EQ(reports.reports(0).metrics(0).duration_metrics().data_size(), 1);
// // Dump the report after the end of 2nd bucket. One dimension with one bucket.
// EXPECT_EQ(reports.reports(0).metrics(0).duration_metrics().data(0).bucket_info_size(), 1);
// auto data = reports.reports(0).metrics(0).duration_metrics().data(0);
// // Validate dimension value.
// ValidateAttributionUidDimension(data.dimensions_in_what(),
// android::util::WAKELOCK_STATE_CHANGED, 111);
// // The max is acquire event for wl1 to screen off start.
// EXPECT_EQ((unsigned long long)data.bucket_info(0).duration_nanos(), bucketSizeNs + 2 - 200);
//}
//
//TEST(WakelockDurationE2eTest, TestAggregatedPredicateDimensionsForMaxDuration3) {
// ConfigKey cfgKey;
// auto config = CreateStatsdConfig(DurationMetric::MAX_SPARSE);
// uint64_t bucketStartTimeNs = 10000000000;
// uint64_t bucketSizeNs =
// TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
// auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
// EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
// EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
// FeedEvents(config, processor);
// ConfigMetricsReportList reports;
// vector<uint8_t> buffer;
//
// std::vector<std::unique_ptr<LogEvent>> events;
// events.push_back(
// CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_OFF,
// bucketStartTimeNs + 2 * bucketSizeNs + 90));
// events.push_back(CreateAcquireWakelockEvent(attributions1, "wl3",
// bucketStartTimeNs + 2 * bucketSizeNs + 100));
// events.push_back(CreateReleaseWakelockEvent(attributions1, "wl3",
// bucketStartTimeNs + 5 * bucketSizeNs + 100));
// sortLogEventsByTimestamp(&events);
// for (const auto& event : events) {
// processor->OnLogEvent(event.get());
// }
//
// processor->onDumpReport(cfgKey, bucketStartTimeNs + 6 * bucketSizeNs + 1, false, true,
// ADB_DUMP, FAST, &buffer);
// EXPECT_TRUE(buffer.size() > 0);
// EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
// backfillDimensionPath(&reports);
// backfillStringInReport(&reports);
// backfillStartEndTimestamp(&reports);
// EXPECT_EQ(reports.reports_size(), 1);
// EXPECT_EQ(reports.reports(0).metrics_size(), 1);
// EXPECT_EQ(reports.reports(0).metrics(0).duration_metrics().data_size(), 1);
// EXPECT_EQ(reports.reports(0).metrics(0).duration_metrics().data(0).bucket_info_size(), 2);
// auto data = reports.reports(0).metrics(0).duration_metrics().data(0);
// ValidateAttributionUidDimension(data.dimensions_in_what(),
// android::util::WAKELOCK_STATE_CHANGED, 111);
// // The last wakelock holding spans 4 buckets.
// EXPECT_EQ((unsigned long long)data.bucket_info(1).duration_nanos(), 3 * bucketSizeNs);
// EXPECT_EQ((unsigned long long)data.bucket_info(1).start_bucket_elapsed_nanos(),
// bucketStartTimeNs + 5 * bucketSizeNs);
// EXPECT_EQ((unsigned long long)data.bucket_info(1).end_bucket_elapsed_nanos(),
// bucketStartTimeNs + 6 * bucketSizeNs);
//}
#else
GTEST_LOG_(INFO) << "This test does nothing.\n";

View File

@@ -57,12 +57,13 @@ private:
FakePuller puller;
shared_ptr<LogEvent> createSimpleEvent(int64_t eventTimeNs, int64_t value) {
shared_ptr<LogEvent> event = make_shared<LogEvent>(pullTagId, eventTimeNs);
event->write(value);
event->init();
return event;
}
// TODO(b/149590301): Update this helper to use new socket schema.
//shared_ptr<LogEvent> createSimpleEvent(int64_t eventTimeNs, int64_t value) {
// shared_ptr<LogEvent> event = make_shared<LogEvent>(pullTagId, eventTimeNs);
// event->write(value);
// event->init();
// return event;
//}
class StatsPullerTest : public ::testing::Test {
public:
@@ -79,148 +80,149 @@ public:
} // Anonymous namespace.
TEST_F(StatsPullerTest, PullSuccess) {
pullData.push_back(createSimpleEvent(1111L, 33));
pullSuccess = true;
vector<std::shared_ptr<LogEvent>> dataHolder;
EXPECT_TRUE(puller.Pull(&dataHolder));
EXPECT_EQ(1, dataHolder.size());
EXPECT_EQ(pullTagId, dataHolder[0]->GetTagId());
EXPECT_EQ(1111L, dataHolder[0]->GetElapsedTimestampNs());
EXPECT_EQ(1, dataHolder[0]->size());
EXPECT_EQ(33, dataHolder[0]->getValues()[0].mValue.int_value);
sleep_for(std::chrono::seconds(1));
pullData.clear();
pullData.push_back(createSimpleEvent(2222L, 44));
pullSuccess = true;
EXPECT_TRUE(puller.Pull(&dataHolder));
EXPECT_EQ(1, dataHolder.size());
EXPECT_EQ(pullTagId, dataHolder[0]->GetTagId());
EXPECT_EQ(2222L, dataHolder[0]->GetElapsedTimestampNs());
EXPECT_EQ(1, dataHolder[0]->size());
EXPECT_EQ(44, dataHolder[0]->getValues()[0].mValue.int_value);
}
TEST_F(StatsPullerTest, PullFailAfterSuccess) {
pullData.push_back(createSimpleEvent(1111L, 33));
pullSuccess = true;
vector<std::shared_ptr<LogEvent>> dataHolder;
EXPECT_TRUE(puller.Pull(&dataHolder));
EXPECT_EQ(1, dataHolder.size());
EXPECT_EQ(pullTagId, dataHolder[0]->GetTagId());
EXPECT_EQ(1111L, dataHolder[0]->GetElapsedTimestampNs());
EXPECT_EQ(1, dataHolder[0]->size());
EXPECT_EQ(33, dataHolder[0]->getValues()[0].mValue.int_value);
sleep_for(std::chrono::seconds(1));
pullData.clear();
pullData.push_back(createSimpleEvent(2222L, 44));
pullSuccess = false;
dataHolder.clear();
EXPECT_FALSE(puller.Pull(&dataHolder));
EXPECT_EQ(0, dataHolder.size());
pullSuccess = true;
dataHolder.clear();
EXPECT_FALSE(puller.Pull(&dataHolder));
EXPECT_EQ(0, dataHolder.size());
}
// Test pull takes longer than timeout, 2nd pull happens shorter than cooldown
TEST_F(StatsPullerTest, PullTakeTooLongAndPullFast) {
pullData.push_back(createSimpleEvent(1111L, 33));
pullSuccess = true;
// timeout is 0.5
pullDelayNs = (long)(0.8 * NS_PER_SEC);
vector<std::shared_ptr<LogEvent>> dataHolder;
EXPECT_FALSE(puller.Pull(&dataHolder));
EXPECT_EQ(0, dataHolder.size());
pullData.clear();
pullData.push_back(createSimpleEvent(2222L, 44));
pullSuccess = true;
dataHolder.clear();
EXPECT_FALSE(puller.Pull(&dataHolder));
EXPECT_EQ(0, dataHolder.size());
}
TEST_F(StatsPullerTest, PullFail) {
pullData.push_back(createSimpleEvent(1111L, 33));
pullSuccess = false;
vector<std::shared_ptr<LogEvent>> dataHolder;
EXPECT_FALSE(puller.Pull(&dataHolder));
EXPECT_EQ(0, dataHolder.size());
}
TEST_F(StatsPullerTest, PullTakeTooLong) {
pullData.push_back(createSimpleEvent(1111L, 33));
pullSuccess = true;
pullDelayNs = NS_PER_SEC;
vector<std::shared_ptr<LogEvent>> dataHolder;
EXPECT_FALSE(puller.Pull(&dataHolder));
EXPECT_EQ(0, dataHolder.size());
}
TEST_F(StatsPullerTest, PullTooFast) {
pullData.push_back(createSimpleEvent(1111L, 33));
pullSuccess = true;
vector<std::shared_ptr<LogEvent>> dataHolder;
EXPECT_TRUE(puller.Pull(&dataHolder));
EXPECT_EQ(1, dataHolder.size());
EXPECT_EQ(pullTagId, dataHolder[0]->GetTagId());
EXPECT_EQ(1111L, dataHolder[0]->GetElapsedTimestampNs());
EXPECT_EQ(1, dataHolder[0]->size());
EXPECT_EQ(33, dataHolder[0]->getValues()[0].mValue.int_value);
pullData.clear();
pullData.push_back(createSimpleEvent(2222L, 44));
pullSuccess = true;
dataHolder.clear();
EXPECT_TRUE(puller.Pull(&dataHolder));
EXPECT_EQ(1, dataHolder.size());
EXPECT_EQ(pullTagId, dataHolder[0]->GetTagId());
EXPECT_EQ(1111L, dataHolder[0]->GetElapsedTimestampNs());
EXPECT_EQ(1, dataHolder[0]->size());
EXPECT_EQ(33, dataHolder[0]->getValues()[0].mValue.int_value);
}
TEST_F(StatsPullerTest, PullFailsAndTooFast) {
pullData.push_back(createSimpleEvent(1111L, 33));
pullSuccess = false;
vector<std::shared_ptr<LogEvent>> dataHolder;
EXPECT_FALSE(puller.Pull(&dataHolder));
EXPECT_EQ(0, dataHolder.size());
pullData.clear();
pullData.push_back(createSimpleEvent(2222L, 44));
pullSuccess = true;
EXPECT_FALSE(puller.Pull(&dataHolder));
EXPECT_EQ(0, dataHolder.size());
}
// TODO(b/149590301): Update these tests to use new socket schema.
//TEST_F(StatsPullerTest, PullSuccess) {
// pullData.push_back(createSimpleEvent(1111L, 33));
//
// pullSuccess = true;
//
// vector<std::shared_ptr<LogEvent>> dataHolder;
// EXPECT_TRUE(puller.Pull(&dataHolder));
// EXPECT_EQ(1, dataHolder.size());
// EXPECT_EQ(pullTagId, dataHolder[0]->GetTagId());
// EXPECT_EQ(1111L, dataHolder[0]->GetElapsedTimestampNs());
// EXPECT_EQ(1, dataHolder[0]->size());
// EXPECT_EQ(33, dataHolder[0]->getValues()[0].mValue.int_value);
//
// sleep_for(std::chrono::seconds(1));
//
// pullData.clear();
// pullData.push_back(createSimpleEvent(2222L, 44));
//
// pullSuccess = true;
//
// EXPECT_TRUE(puller.Pull(&dataHolder));
// EXPECT_EQ(1, dataHolder.size());
// EXPECT_EQ(pullTagId, dataHolder[0]->GetTagId());
// EXPECT_EQ(2222L, dataHolder[0]->GetElapsedTimestampNs());
// EXPECT_EQ(1, dataHolder[0]->size());
// EXPECT_EQ(44, dataHolder[0]->getValues()[0].mValue.int_value);
//}
//
//TEST_F(StatsPullerTest, PullFailAfterSuccess) {
// pullData.push_back(createSimpleEvent(1111L, 33));
//
// pullSuccess = true;
//
// vector<std::shared_ptr<LogEvent>> dataHolder;
// EXPECT_TRUE(puller.Pull(&dataHolder));
// EXPECT_EQ(1, dataHolder.size());
// EXPECT_EQ(pullTagId, dataHolder[0]->GetTagId());
// EXPECT_EQ(1111L, dataHolder[0]->GetElapsedTimestampNs());
// EXPECT_EQ(1, dataHolder[0]->size());
// EXPECT_EQ(33, dataHolder[0]->getValues()[0].mValue.int_value);
//
// sleep_for(std::chrono::seconds(1));
//
// pullData.clear();
// pullData.push_back(createSimpleEvent(2222L, 44));
//
// pullSuccess = false;
// dataHolder.clear();
// EXPECT_FALSE(puller.Pull(&dataHolder));
// EXPECT_EQ(0, dataHolder.size());
//
// pullSuccess = true;
// dataHolder.clear();
// EXPECT_FALSE(puller.Pull(&dataHolder));
// EXPECT_EQ(0, dataHolder.size());
//}
//
//// Test pull takes longer than timeout, 2nd pull happens shorter than cooldown
//TEST_F(StatsPullerTest, PullTakeTooLongAndPullFast) {
// pullData.push_back(createSimpleEvent(1111L, 33));
// pullSuccess = true;
// // timeout is 0.5
// pullDelayNs = (long)(0.8 * NS_PER_SEC);
//
// vector<std::shared_ptr<LogEvent>> dataHolder;
// EXPECT_FALSE(puller.Pull(&dataHolder));
// EXPECT_EQ(0, dataHolder.size());
//
// pullData.clear();
// pullData.push_back(createSimpleEvent(2222L, 44));
//
// pullSuccess = true;
// dataHolder.clear();
// EXPECT_FALSE(puller.Pull(&dataHolder));
// EXPECT_EQ(0, dataHolder.size());
//}
//
//TEST_F(StatsPullerTest, PullFail) {
// pullData.push_back(createSimpleEvent(1111L, 33));
//
// pullSuccess = false;
//
// vector<std::shared_ptr<LogEvent>> dataHolder;
// EXPECT_FALSE(puller.Pull(&dataHolder));
// EXPECT_EQ(0, dataHolder.size());
//}
//
//TEST_F(StatsPullerTest, PullTakeTooLong) {
// pullData.push_back(createSimpleEvent(1111L, 33));
//
// pullSuccess = true;
// pullDelayNs = NS_PER_SEC;
//
// vector<std::shared_ptr<LogEvent>> dataHolder;
// EXPECT_FALSE(puller.Pull(&dataHolder));
// EXPECT_EQ(0, dataHolder.size());
//}
//
//TEST_F(StatsPullerTest, PullTooFast) {
// pullData.push_back(createSimpleEvent(1111L, 33));
//
// pullSuccess = true;
//
// vector<std::shared_ptr<LogEvent>> dataHolder;
// EXPECT_TRUE(puller.Pull(&dataHolder));
// EXPECT_EQ(1, dataHolder.size());
// EXPECT_EQ(pullTagId, dataHolder[0]->GetTagId());
// EXPECT_EQ(1111L, dataHolder[0]->GetElapsedTimestampNs());
// EXPECT_EQ(1, dataHolder[0]->size());
// EXPECT_EQ(33, dataHolder[0]->getValues()[0].mValue.int_value);
//
// pullData.clear();
// pullData.push_back(createSimpleEvent(2222L, 44));
//
// pullSuccess = true;
//
// dataHolder.clear();
// EXPECT_TRUE(puller.Pull(&dataHolder));
// EXPECT_EQ(1, dataHolder.size());
// EXPECT_EQ(pullTagId, dataHolder[0]->GetTagId());
// EXPECT_EQ(1111L, dataHolder[0]->GetElapsedTimestampNs());
// EXPECT_EQ(1, dataHolder[0]->size());
// EXPECT_EQ(33, dataHolder[0]->getValues()[0].mValue.int_value);
//}
//
//TEST_F(StatsPullerTest, PullFailsAndTooFast) {
// pullData.push_back(createSimpleEvent(1111L, 33));
//
// pullSuccess = false;
//
// vector<std::shared_ptr<LogEvent>> dataHolder;
// EXPECT_FALSE(puller.Pull(&dataHolder));
// EXPECT_EQ(0, dataHolder.size());
//
// pullData.clear();
// pullData.push_back(createSimpleEvent(2222L, 44));
//
// pullSuccess = true;
//
// EXPECT_FALSE(puller.Pull(&dataHolder));
// EXPECT_EQ(0, dataHolder.size());
//}
} // namespace statsd
} // namespace os

View File

@@ -60,209 +60,210 @@ void extractIntoVector(vector<shared_ptr<LogEvent>> events,
}
} // anonymous namespace
TEST(puller_util, MergeNoDimension) {
vector<shared_ptr<LogEvent>> inputData;
shared_ptr<LogEvent> event = make_shared<LogEvent>(uidAtomTagId, timestamp);
// 30->22->31
event->write(isolatedUid);
event->write(hostNonAdditiveData);
event->write(isolatedAdditiveData);
event->init();
inputData.push_back(event);
// 20->22->21
event = make_shared<LogEvent>(uidAtomTagId, timestamp);
event->write(hostUid);
event->write(hostNonAdditiveData);
event->write(hostAdditiveData);
event->init();
inputData.push_back(event);
sp<MockUidMap> uidMap = new NaggyMock<MockUidMap>();
EXPECT_CALL(*uidMap, getHostUidOrSelf(isolatedUid))
.WillRepeatedly(Return(hostUid));
EXPECT_CALL(*uidMap, getHostUidOrSelf(Ne(isolatedUid)))
.WillRepeatedly(ReturnArg<0>());
mapAndMergeIsolatedUidsToHostUid(inputData, uidMap, uidAtomTagId, uidAdditiveFields);
vector<vector<int>> actual;
extractIntoVector(inputData, actual);
vector<int> expectedV1 = {20, 22, 52};
EXPECT_EQ(1, (int)actual.size());
EXPECT_THAT(actual, Contains(expectedV1));
}
TEST(puller_util, MergeWithDimension) {
vector<shared_ptr<LogEvent>> inputData;
shared_ptr<LogEvent> event = make_shared<LogEvent>(uidAtomTagId, timestamp);
// 30->32->31
event->write(isolatedUid);
event->write(isolatedNonAdditiveData);
event->write(isolatedAdditiveData);
event->init();
inputData.push_back(event);
// 20->32->21
event = make_shared<LogEvent>(uidAtomTagId, timestamp);
event->write(hostUid);
event->write(isolatedNonAdditiveData);
event->write(hostAdditiveData);
event->init();
inputData.push_back(event);
// 20->22->21
event = make_shared<LogEvent>(uidAtomTagId, timestamp);
event->write(hostUid);
event->write(hostNonAdditiveData);
event->write(hostAdditiveData);
event->init();
inputData.push_back(event);
sp<MockUidMap> uidMap = new NaggyMock<MockUidMap>();
EXPECT_CALL(*uidMap, getHostUidOrSelf(isolatedUid))
.WillRepeatedly(Return(hostUid));
EXPECT_CALL(*uidMap, getHostUidOrSelf(Ne(isolatedUid)))
.WillRepeatedly(ReturnArg<0>());
mapAndMergeIsolatedUidsToHostUid(inputData, uidMap, uidAtomTagId, uidAdditiveFields);
vector<vector<int>> actual;
extractIntoVector(inputData, actual);
vector<int> expectedV1 = {20, 22, 21};
vector<int> expectedV2 = {20, 32, 52};
EXPECT_EQ(2, (int)actual.size());
EXPECT_THAT(actual, Contains(expectedV1));
EXPECT_THAT(actual, Contains(expectedV2));
}
TEST(puller_util, NoMergeHostUidOnly) {
vector<shared_ptr<LogEvent>> inputData;
shared_ptr<LogEvent> event = make_shared<LogEvent>(uidAtomTagId, timestamp);
// 20->32->31
event->write(hostUid);
event->write(isolatedNonAdditiveData);
event->write(isolatedAdditiveData);
event->init();
inputData.push_back(event);
// 20->22->21
event = make_shared<LogEvent>(uidAtomTagId, timestamp);
event->write(hostUid);
event->write(hostNonAdditiveData);
event->write(hostAdditiveData);
event->init();
inputData.push_back(event);
sp<MockUidMap> uidMap = new NaggyMock<MockUidMap>();
EXPECT_CALL(*uidMap, getHostUidOrSelf(isolatedUid))
.WillRepeatedly(Return(hostUid));
EXPECT_CALL(*uidMap, getHostUidOrSelf(Ne(isolatedUid)))
.WillRepeatedly(ReturnArg<0>());
mapAndMergeIsolatedUidsToHostUid(inputData, uidMap, uidAtomTagId, uidAdditiveFields);
// 20->32->31
// 20->22->21
vector<vector<int>> actual;
extractIntoVector(inputData, actual);
vector<int> expectedV1 = {20, 32, 31};
vector<int> expectedV2 = {20, 22, 21};
EXPECT_EQ(2, (int)actual.size());
EXPECT_THAT(actual, Contains(expectedV1));
EXPECT_THAT(actual, Contains(expectedV2));
}
TEST(puller_util, IsolatedUidOnly) {
vector<shared_ptr<LogEvent>> inputData;
shared_ptr<LogEvent> event = make_shared<LogEvent>(uidAtomTagId, timestamp);
// 30->32->31
event->write(hostUid);
event->write(isolatedNonAdditiveData);
event->write(isolatedAdditiveData);
event->init();
inputData.push_back(event);
// 30->22->21
event = make_shared<LogEvent>(uidAtomTagId, timestamp);
event->write(hostUid);
event->write(hostNonAdditiveData);
event->write(hostAdditiveData);
event->init();
inputData.push_back(event);
sp<MockUidMap> uidMap = new NaggyMock<MockUidMap>();
EXPECT_CALL(*uidMap, getHostUidOrSelf(isolatedUid))
.WillRepeatedly(Return(hostUid));
EXPECT_CALL(*uidMap, getHostUidOrSelf(Ne(isolatedUid)))
.WillRepeatedly(ReturnArg<0>());
mapAndMergeIsolatedUidsToHostUid(inputData, uidMap, uidAtomTagId, uidAdditiveFields);
// 20->32->31
// 20->22->21
vector<vector<int>> actual;
extractIntoVector(inputData, actual);
vector<int> expectedV1 = {20, 32, 31};
vector<int> expectedV2 = {20, 22, 21};
EXPECT_EQ(2, (int)actual.size());
EXPECT_THAT(actual, Contains(expectedV1));
EXPECT_THAT(actual, Contains(expectedV2));
}
TEST(puller_util, MultipleIsolatedUidToOneHostUid) {
vector<shared_ptr<LogEvent>> inputData;
shared_ptr<LogEvent> event = make_shared<LogEvent>(uidAtomTagId, timestamp);
// 30->32->31
event->write(isolatedUid);
event->write(isolatedNonAdditiveData);
event->write(isolatedAdditiveData);
event->init();
inputData.push_back(event);
// 31->32->21
event = make_shared<LogEvent>(uidAtomTagId, timestamp);
event->write(isolatedUid + 1);
event->write(isolatedNonAdditiveData);
event->write(hostAdditiveData);
event->init();
inputData.push_back(event);
// 20->32->21
event = make_shared<LogEvent>(uidAtomTagId, timestamp);
event->write(hostUid);
event->write(isolatedNonAdditiveData);
event->write(hostAdditiveData);
event->init();
inputData.push_back(event);
sp<MockUidMap> uidMap = new NaggyMock<MockUidMap>();
EXPECT_CALL(*uidMap, getHostUidOrSelf(_)).WillRepeatedly(Return(hostUid));
mapAndMergeIsolatedUidsToHostUid(inputData, uidMap, uidAtomTagId, uidAdditiveFields);
vector<vector<int>> actual;
extractIntoVector(inputData, actual);
vector<int> expectedV1 = {20, 32, 73};
EXPECT_EQ(1, (int)actual.size());
EXPECT_THAT(actual, Contains(expectedV1));
}
TEST(puller_util, NoNeedToMerge) {
vector<shared_ptr<LogEvent>> inputData;
shared_ptr<LogEvent> event =
make_shared<LogEvent>(nonUidAtomTagId, timestamp);
// 32
event->write(isolatedNonAdditiveData);
event->init();
inputData.push_back(event);
event = make_shared<LogEvent>(nonUidAtomTagId, timestamp);
// 22
event->write(hostNonAdditiveData);
event->init();
inputData.push_back(event);
sp<MockUidMap> uidMap = new NaggyMock<MockUidMap>();
mapAndMergeIsolatedUidsToHostUid(inputData, uidMap, nonUidAtomTagId, {} /*no additive fields*/);
EXPECT_EQ(2, (int)inputData.size());
}
// TODO(b/149590301): Update these tests to use new socket schema.
//TEST(puller_util, MergeNoDimension) {
// vector<shared_ptr<LogEvent>> inputData;
// shared_ptr<LogEvent> event = make_shared<LogEvent>(uidAtomTagId, timestamp);
// // 30->22->31
// event->write(isolatedUid);
// event->write(hostNonAdditiveData);
// event->write(isolatedAdditiveData);
// event->init();
// inputData.push_back(event);
//
// // 20->22->21
// event = make_shared<LogEvent>(uidAtomTagId, timestamp);
// event->write(hostUid);
// event->write(hostNonAdditiveData);
// event->write(hostAdditiveData);
// event->init();
// inputData.push_back(event);
//
// sp<MockUidMap> uidMap = new NaggyMock<MockUidMap>();
// EXPECT_CALL(*uidMap, getHostUidOrSelf(isolatedUid))
// .WillRepeatedly(Return(hostUid));
// EXPECT_CALL(*uidMap, getHostUidOrSelf(Ne(isolatedUid)))
// .WillRepeatedly(ReturnArg<0>());
// mapAndMergeIsolatedUidsToHostUid(inputData, uidMap, uidAtomTagId, uidAdditiveFields);
//
// vector<vector<int>> actual;
// extractIntoVector(inputData, actual);
// vector<int> expectedV1 = {20, 22, 52};
// EXPECT_EQ(1, (int)actual.size());
// EXPECT_THAT(actual, Contains(expectedV1));
//}
//
//TEST(puller_util, MergeWithDimension) {
// vector<shared_ptr<LogEvent>> inputData;
// shared_ptr<LogEvent> event = make_shared<LogEvent>(uidAtomTagId, timestamp);
// // 30->32->31
// event->write(isolatedUid);
// event->write(isolatedNonAdditiveData);
// event->write(isolatedAdditiveData);
// event->init();
// inputData.push_back(event);
//
// // 20->32->21
// event = make_shared<LogEvent>(uidAtomTagId, timestamp);
// event->write(hostUid);
// event->write(isolatedNonAdditiveData);
// event->write(hostAdditiveData);
// event->init();
// inputData.push_back(event);
//
// // 20->22->21
// event = make_shared<LogEvent>(uidAtomTagId, timestamp);
// event->write(hostUid);
// event->write(hostNonAdditiveData);
// event->write(hostAdditiveData);
// event->init();
// inputData.push_back(event);
//
// sp<MockUidMap> uidMap = new NaggyMock<MockUidMap>();
// EXPECT_CALL(*uidMap, getHostUidOrSelf(isolatedUid))
// .WillRepeatedly(Return(hostUid));
// EXPECT_CALL(*uidMap, getHostUidOrSelf(Ne(isolatedUid)))
// .WillRepeatedly(ReturnArg<0>());
// mapAndMergeIsolatedUidsToHostUid(inputData, uidMap, uidAtomTagId, uidAdditiveFields);
//
// vector<vector<int>> actual;
// extractIntoVector(inputData, actual);
// vector<int> expectedV1 = {20, 22, 21};
// vector<int> expectedV2 = {20, 32, 52};
// EXPECT_EQ(2, (int)actual.size());
// EXPECT_THAT(actual, Contains(expectedV1));
// EXPECT_THAT(actual, Contains(expectedV2));
//}
//
//TEST(puller_util, NoMergeHostUidOnly) {
// vector<shared_ptr<LogEvent>> inputData;
// shared_ptr<LogEvent> event = make_shared<LogEvent>(uidAtomTagId, timestamp);
// // 20->32->31
// event->write(hostUid);
// event->write(isolatedNonAdditiveData);
// event->write(isolatedAdditiveData);
// event->init();
// inputData.push_back(event);
//
// // 20->22->21
// event = make_shared<LogEvent>(uidAtomTagId, timestamp);
// event->write(hostUid);
// event->write(hostNonAdditiveData);
// event->write(hostAdditiveData);
// event->init();
// inputData.push_back(event);
//
// sp<MockUidMap> uidMap = new NaggyMock<MockUidMap>();
// EXPECT_CALL(*uidMap, getHostUidOrSelf(isolatedUid))
// .WillRepeatedly(Return(hostUid));
// EXPECT_CALL(*uidMap, getHostUidOrSelf(Ne(isolatedUid)))
// .WillRepeatedly(ReturnArg<0>());
// mapAndMergeIsolatedUidsToHostUid(inputData, uidMap, uidAtomTagId, uidAdditiveFields);
//
// // 20->32->31
// // 20->22->21
// vector<vector<int>> actual;
// extractIntoVector(inputData, actual);
// vector<int> expectedV1 = {20, 32, 31};
// vector<int> expectedV2 = {20, 22, 21};
// EXPECT_EQ(2, (int)actual.size());
// EXPECT_THAT(actual, Contains(expectedV1));
// EXPECT_THAT(actual, Contains(expectedV2));
//}
//
//TEST(puller_util, IsolatedUidOnly) {
// vector<shared_ptr<LogEvent>> inputData;
// shared_ptr<LogEvent> event = make_shared<LogEvent>(uidAtomTagId, timestamp);
// // 30->32->31
// event->write(hostUid);
// event->write(isolatedNonAdditiveData);
// event->write(isolatedAdditiveData);
// event->init();
// inputData.push_back(event);
//
// // 30->22->21
// event = make_shared<LogEvent>(uidAtomTagId, timestamp);
// event->write(hostUid);
// event->write(hostNonAdditiveData);
// event->write(hostAdditiveData);
// event->init();
// inputData.push_back(event);
//
// sp<MockUidMap> uidMap = new NaggyMock<MockUidMap>();
// EXPECT_CALL(*uidMap, getHostUidOrSelf(isolatedUid))
// .WillRepeatedly(Return(hostUid));
// EXPECT_CALL(*uidMap, getHostUidOrSelf(Ne(isolatedUid)))
// .WillRepeatedly(ReturnArg<0>());
// mapAndMergeIsolatedUidsToHostUid(inputData, uidMap, uidAtomTagId, uidAdditiveFields);
//
// // 20->32->31
// // 20->22->21
// vector<vector<int>> actual;
// extractIntoVector(inputData, actual);
// vector<int> expectedV1 = {20, 32, 31};
// vector<int> expectedV2 = {20, 22, 21};
// EXPECT_EQ(2, (int)actual.size());
// EXPECT_THAT(actual, Contains(expectedV1));
// EXPECT_THAT(actual, Contains(expectedV2));
//}
//
//TEST(puller_util, MultipleIsolatedUidToOneHostUid) {
// vector<shared_ptr<LogEvent>> inputData;
// shared_ptr<LogEvent> event = make_shared<LogEvent>(uidAtomTagId, timestamp);
// // 30->32->31
// event->write(isolatedUid);
// event->write(isolatedNonAdditiveData);
// event->write(isolatedAdditiveData);
// event->init();
// inputData.push_back(event);
//
// // 31->32->21
// event = make_shared<LogEvent>(uidAtomTagId, timestamp);
// event->write(isolatedUid + 1);
// event->write(isolatedNonAdditiveData);
// event->write(hostAdditiveData);
// event->init();
// inputData.push_back(event);
//
// // 20->32->21
// event = make_shared<LogEvent>(uidAtomTagId, timestamp);
// event->write(hostUid);
// event->write(isolatedNonAdditiveData);
// event->write(hostAdditiveData);
// event->init();
// inputData.push_back(event);
//
// sp<MockUidMap> uidMap = new NaggyMock<MockUidMap>();
// EXPECT_CALL(*uidMap, getHostUidOrSelf(_)).WillRepeatedly(Return(hostUid));
// mapAndMergeIsolatedUidsToHostUid(inputData, uidMap, uidAtomTagId, uidAdditiveFields);
//
// vector<vector<int>> actual;
// extractIntoVector(inputData, actual);
// vector<int> expectedV1 = {20, 32, 73};
// EXPECT_EQ(1, (int)actual.size());
// EXPECT_THAT(actual, Contains(expectedV1));
//}
//
//TEST(puller_util, NoNeedToMerge) {
// vector<shared_ptr<LogEvent>> inputData;
// shared_ptr<LogEvent> event =
// make_shared<LogEvent>(nonUidAtomTagId, timestamp);
// // 32
// event->write(isolatedNonAdditiveData);
// event->init();
// inputData.push_back(event);
//
// event = make_shared<LogEvent>(nonUidAtomTagId, timestamp);
// // 22
// event->write(hostNonAdditiveData);
// event->init();
// inputData.push_back(event);
//
// sp<MockUidMap> uidMap = new NaggyMock<MockUidMap>();
// mapAndMergeIsolatedUidsToHostUid(inputData, uidMap, nonUidAtomTagId, {} /*no additive fields*/);
//
// EXPECT_EQ(2, (int)inputData.size());
//}
} // namespace statsd
} // namespace os

View File

@@ -37,365 +37,366 @@ namespace statsd {
const ConfigKey kConfigKey(0, 12345);
TEST(CountMetricProducerTest, TestFirstBucket) {
CountMetric metric;
metric.set_id(1);
metric.set_bucket(ONE_MINUTE);
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
CountMetricProducer countProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard, 5,
600 * NS_PER_SEC + NS_PER_SEC / 2);
EXPECT_EQ(600500000000, countProducer.mCurrentBucketStartTimeNs);
EXPECT_EQ(10, countProducer.mCurrentBucketNum);
EXPECT_EQ(660000000005, countProducer.getCurrentBucketEndTimeNs());
}
TEST(CountMetricProducerTest, TestNonDimensionalEvents) {
int64_t bucketStartTimeNs = 10000000000;
int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
int64_t bucket2StartTimeNs = bucketStartTimeNs + bucketSizeNs;
int64_t bucket3StartTimeNs = bucketStartTimeNs + 2 * bucketSizeNs;
int tagId = 1;
CountMetric metric;
metric.set_id(1);
metric.set_bucket(ONE_MINUTE);
LogEvent event1(tagId, bucketStartTimeNs + 1);
event1.init();
LogEvent event2(tagId, bucketStartTimeNs + 2);
event2.init();
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
CountMetricProducer countProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
bucketStartTimeNs, bucketStartTimeNs);
// 2 events in bucket 1.
countProducer.onMatchedLogEvent(1 /*log matcher index*/, event1);
countProducer.onMatchedLogEvent(1 /*log matcher index*/, event2);
// Flushes at event #2.
countProducer.flushIfNeededLocked(bucketStartTimeNs + 2);
EXPECT_EQ(0UL, countProducer.mPastBuckets.size());
// Flushes.
countProducer.flushIfNeededLocked(bucketStartTimeNs + bucketSizeNs + 1);
EXPECT_EQ(1UL, countProducer.mPastBuckets.size());
EXPECT_TRUE(countProducer.mPastBuckets.find(DEFAULT_METRIC_DIMENSION_KEY) !=
countProducer.mPastBuckets.end());
const auto& buckets = countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY];
EXPECT_EQ(1UL, buckets.size());
EXPECT_EQ(bucketStartTimeNs, buckets[0].mBucketStartNs);
EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, buckets[0].mBucketEndNs);
EXPECT_EQ(2LL, buckets[0].mCount);
// 1 matched event happens in bucket 2.
LogEvent event3(tagId, bucketStartTimeNs + bucketSizeNs + 2);
event3.init();
countProducer.onMatchedLogEvent(1 /*log matcher index*/, event3);
countProducer.flushIfNeededLocked(bucketStartTimeNs + 2 * bucketSizeNs + 1);
EXPECT_EQ(1UL, countProducer.mPastBuckets.size());
EXPECT_TRUE(countProducer.mPastBuckets.find(DEFAULT_METRIC_DIMENSION_KEY) !=
countProducer.mPastBuckets.end());
EXPECT_EQ(2UL, countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
const auto& bucketInfo2 = countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][1];
EXPECT_EQ(bucket2StartTimeNs, bucketInfo2.mBucketStartNs);
EXPECT_EQ(bucket2StartTimeNs + bucketSizeNs, bucketInfo2.mBucketEndNs);
EXPECT_EQ(1LL, bucketInfo2.mCount);
// nothing happens in bucket 3. we should not record anything for bucket 3.
countProducer.flushIfNeededLocked(bucketStartTimeNs + 3 * bucketSizeNs + 1);
EXPECT_EQ(1UL, countProducer.mPastBuckets.size());
EXPECT_TRUE(countProducer.mPastBuckets.find(DEFAULT_METRIC_DIMENSION_KEY) !=
countProducer.mPastBuckets.end());
const auto& buckets3 = countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY];
EXPECT_EQ(2UL, buckets3.size());
}
TEST(CountMetricProducerTest, TestEventsWithNonSlicedCondition) {
int64_t bucketStartTimeNs = 10000000000;
int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
CountMetric metric;
metric.set_id(1);
metric.set_bucket(ONE_MINUTE);
metric.set_condition(StringToId("SCREEN_ON"));
LogEvent event1(1, bucketStartTimeNs + 1);
event1.init();
LogEvent event2(1, bucketStartTimeNs + 10);
event2.init();
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
CountMetricProducer countProducer(kConfigKey, metric, 1, wizard, bucketStartTimeNs,
bucketStartTimeNs);
countProducer.onConditionChanged(true, bucketStartTimeNs);
countProducer.onMatchedLogEvent(1 /*matcher index*/, event1);
EXPECT_EQ(0UL, countProducer.mPastBuckets.size());
countProducer.onConditionChanged(false /*new condition*/, bucketStartTimeNs + 2);
// Upon this match event, the matched event1 is flushed.
countProducer.onMatchedLogEvent(1 /*matcher index*/, event2);
EXPECT_EQ(0UL, countProducer.mPastBuckets.size());
countProducer.flushIfNeededLocked(bucketStartTimeNs + bucketSizeNs + 1);
EXPECT_EQ(1UL, countProducer.mPastBuckets.size());
EXPECT_TRUE(countProducer.mPastBuckets.find(DEFAULT_METRIC_DIMENSION_KEY) !=
countProducer.mPastBuckets.end());
{
const auto& buckets = countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY];
EXPECT_EQ(1UL, buckets.size());
const auto& bucketInfo = buckets[0];
EXPECT_EQ(bucketStartTimeNs, bucketInfo.mBucketStartNs);
EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, bucketInfo.mBucketEndNs);
EXPECT_EQ(1LL, bucketInfo.mCount);
}
}
TEST(CountMetricProducerTest, TestEventsWithSlicedCondition) {
int64_t bucketStartTimeNs = 10000000000;
int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
int tagId = 1;
int conditionTagId = 2;
CountMetric metric;
metric.set_id(1);
metric.set_bucket(ONE_MINUTE);
metric.set_condition(StringToId("APP_IN_BACKGROUND_PER_UID_AND_SCREEN_ON"));
MetricConditionLink* link = metric.add_links();
link->set_condition(StringToId("APP_IN_BACKGROUND_PER_UID"));
buildSimpleAtomFieldMatcher(tagId, 1, link->mutable_fields_in_what());
buildSimpleAtomFieldMatcher(conditionTagId, 2, link->mutable_fields_in_condition());
LogEvent event1(tagId, bucketStartTimeNs + 1);
event1.write("111"); // uid
event1.init();
ConditionKey key1;
key1[StringToId("APP_IN_BACKGROUND_PER_UID")] =
{getMockedDimensionKey(conditionTagId, 2, "111")};
LogEvent event2(tagId, bucketStartTimeNs + 10);
event2.write("222"); // uid
event2.init();
ConditionKey key2;
key2[StringToId("APP_IN_BACKGROUND_PER_UID")] =
{getMockedDimensionKey(conditionTagId, 2, "222")};
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
EXPECT_CALL(*wizard, query(_, key1, _)).WillOnce(Return(ConditionState::kFalse));
EXPECT_CALL(*wizard, query(_, key2, _)).WillOnce(Return(ConditionState::kTrue));
CountMetricProducer countProducer(kConfigKey, metric, 1 /*condition tracker index*/, wizard,
bucketStartTimeNs, bucketStartTimeNs);
countProducer.onMatchedLogEvent(1 /*log matcher index*/, event1);
countProducer.flushIfNeededLocked(bucketStartTimeNs + 1);
EXPECT_EQ(0UL, countProducer.mPastBuckets.size());
countProducer.onMatchedLogEvent(1 /*log matcher index*/, event2);
countProducer.flushIfNeededLocked(bucketStartTimeNs + bucketSizeNs + 1);
EXPECT_EQ(1UL, countProducer.mPastBuckets.size());
EXPECT_TRUE(countProducer.mPastBuckets.find(DEFAULT_METRIC_DIMENSION_KEY) !=
countProducer.mPastBuckets.end());
const auto& buckets = countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY];
EXPECT_EQ(1UL, buckets.size());
const auto& bucketInfo = buckets[0];
EXPECT_EQ(bucketStartTimeNs, bucketInfo.mBucketStartNs);
EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, bucketInfo.mBucketEndNs);
EXPECT_EQ(1LL, bucketInfo.mCount);
}
TEST(CountMetricProducerTest, TestEventWithAppUpgrade) {
sp<AlarmMonitor> alarmMonitor;
int64_t bucketStartTimeNs = 10000000000;
int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
int64_t eventUpgradeTimeNs = bucketStartTimeNs + 15 * NS_PER_SEC;
int tagId = 1;
int conditionTagId = 2;
CountMetric metric;
metric.set_id(1);
metric.set_bucket(ONE_MINUTE);
Alert alert;
alert.set_num_buckets(3);
alert.set_trigger_if_sum_gt(2);
LogEvent event1(tagId, bucketStartTimeNs + 1);
event1.write("111"); // uid
event1.init();
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
CountMetricProducer countProducer(kConfigKey, metric, -1 /* no condition */, wizard,
bucketStartTimeNs, bucketStartTimeNs);
sp<AnomalyTracker> anomalyTracker = countProducer.addAnomalyTracker(alert, alarmMonitor);
EXPECT_TRUE(anomalyTracker != nullptr);
// Bucket is flushed yet.
countProducer.onMatchedLogEvent(1 /*log matcher index*/, event1);
EXPECT_EQ(0UL, countProducer.mPastBuckets.size());
EXPECT_EQ(0, anomalyTracker->getSumOverPastBuckets(DEFAULT_METRIC_DIMENSION_KEY));
// App upgrade forces bucket flush.
// Check that there's a past bucket and the bucket end is not adjusted.
countProducer.notifyAppUpgrade(eventUpgradeTimeNs, "ANY.APP", 1, 1);
EXPECT_EQ(1UL, countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
EXPECT_EQ((long long)bucketStartTimeNs,
countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][0].mBucketStartNs);
EXPECT_EQ((long long)eventUpgradeTimeNs,
countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][0].mBucketEndNs);
EXPECT_EQ(eventUpgradeTimeNs, countProducer.mCurrentBucketStartTimeNs);
// Anomaly tracker only contains full buckets.
EXPECT_EQ(0, anomalyTracker->getSumOverPastBuckets(DEFAULT_METRIC_DIMENSION_KEY));
int64_t lastEndTimeNs = countProducer.getCurrentBucketEndTimeNs();
// Next event occurs in same bucket as partial bucket created.
LogEvent event2(tagId, bucketStartTimeNs + 59 * NS_PER_SEC + 10);
event2.write("222"); // uid
event2.init();
countProducer.onMatchedLogEvent(1 /*log matcher index*/, event2);
EXPECT_EQ(1UL, countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
EXPECT_EQ(eventUpgradeTimeNs, countProducer.mCurrentBucketStartTimeNs);
EXPECT_EQ(0, anomalyTracker->getSumOverPastBuckets(DEFAULT_METRIC_DIMENSION_KEY));
// Third event in following bucket.
LogEvent event3(tagId, bucketStartTimeNs + 62 * NS_PER_SEC + 10);
event3.write("333"); // uid
event3.init();
countProducer.onMatchedLogEvent(1 /*log matcher index*/, event3);
EXPECT_EQ(2UL, countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
EXPECT_EQ(lastEndTimeNs, countProducer.mCurrentBucketStartTimeNs);
EXPECT_EQ(2, anomalyTracker->getSumOverPastBuckets(DEFAULT_METRIC_DIMENSION_KEY));
}
TEST(CountMetricProducerTest, TestEventWithAppUpgradeInNextBucket) {
int64_t bucketStartTimeNs = 10000000000;
int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
int64_t eventUpgradeTimeNs = bucketStartTimeNs + 65 * NS_PER_SEC;
int tagId = 1;
int conditionTagId = 2;
CountMetric metric;
metric.set_id(1);
metric.set_bucket(ONE_MINUTE);
LogEvent event1(tagId, bucketStartTimeNs + 1);
event1.write("111"); // uid
event1.init();
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
CountMetricProducer countProducer(kConfigKey, metric, -1 /* no condition */, wizard,
bucketStartTimeNs, bucketStartTimeNs);
// Bucket is flushed yet.
countProducer.onMatchedLogEvent(1 /*log matcher index*/, event1);
EXPECT_EQ(0UL, countProducer.mPastBuckets.size());
// App upgrade forces bucket flush.
// Check that there's a past bucket and the bucket end is not adjusted.
countProducer.notifyAppUpgrade(eventUpgradeTimeNs, "ANY.APP", 1, 1);
EXPECT_EQ(1UL, countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
EXPECT_EQ((int64_t)bucketStartTimeNs,
countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][0].mBucketStartNs);
EXPECT_EQ(bucketStartTimeNs + bucketSizeNs,
countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][0].mBucketEndNs);
EXPECT_EQ(eventUpgradeTimeNs, countProducer.mCurrentBucketStartTimeNs);
// Next event occurs in same bucket as partial bucket created.
LogEvent event2(tagId, bucketStartTimeNs + 70 * NS_PER_SEC + 10);
event2.write("222"); // uid
event2.init();
countProducer.onMatchedLogEvent(1 /*log matcher index*/, event2);
EXPECT_EQ(1UL, countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
// Third event in following bucket.
LogEvent event3(tagId, bucketStartTimeNs + 121 * NS_PER_SEC + 10);
event3.write("333"); // uid
event3.init();
countProducer.onMatchedLogEvent(1 /*log matcher index*/, event3);
EXPECT_EQ(2UL, countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
EXPECT_EQ((int64_t)eventUpgradeTimeNs,
countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][1].mBucketStartNs);
EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][1].mBucketEndNs);
}
TEST(CountMetricProducerTest, TestAnomalyDetectionUnSliced) {
sp<AlarmMonitor> alarmMonitor;
Alert alert;
alert.set_id(11);
alert.set_metric_id(1);
alert.set_trigger_if_sum_gt(2);
alert.set_num_buckets(2);
const int32_t refPeriodSec = 1;
alert.set_refractory_period_secs(refPeriodSec);
int64_t bucketStartTimeNs = 10000000000;
int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
int64_t bucket2StartTimeNs = bucketStartTimeNs + bucketSizeNs;
int64_t bucket3StartTimeNs = bucketStartTimeNs + 2 * bucketSizeNs;
CountMetric metric;
metric.set_id(1);
metric.set_bucket(ONE_MINUTE);
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
CountMetricProducer countProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
bucketStartTimeNs, bucketStartTimeNs);
sp<AnomalyTracker> anomalyTracker = countProducer.addAnomalyTracker(alert, alarmMonitor);
int tagId = 1;
LogEvent event1(tagId, bucketStartTimeNs + 1);
event1.init();
LogEvent event2(tagId, bucketStartTimeNs + 2);
event2.init();
LogEvent event3(tagId, bucketStartTimeNs + 2 * bucketSizeNs + 1);
event3.init();
LogEvent event4(tagId, bucketStartTimeNs + 3 * bucketSizeNs + 1);
event4.init();
LogEvent event5(tagId, bucketStartTimeNs + 3 * bucketSizeNs + 2);
event5.init();
LogEvent event6(tagId, bucketStartTimeNs + 3 * bucketSizeNs + 3);
event6.init();
LogEvent event7(tagId, bucketStartTimeNs + 3 * bucketSizeNs + 2 * NS_PER_SEC);
event7.init();
// Two events in bucket #0.
countProducer.onMatchedLogEvent(1 /*log matcher index*/, event1);
countProducer.onMatchedLogEvent(1 /*log matcher index*/, event2);
EXPECT_EQ(1UL, countProducer.mCurrentSlicedCounter->size());
EXPECT_EQ(2L, countProducer.mCurrentSlicedCounter->begin()->second);
EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY), 0U);
// One event in bucket #2. No alarm as bucket #0 is trashed out.
countProducer.onMatchedLogEvent(1 /*log matcher index*/, event3);
EXPECT_EQ(1UL, countProducer.mCurrentSlicedCounter->size());
EXPECT_EQ(1L, countProducer.mCurrentSlicedCounter->begin()->second);
EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY), 0U);
// Two events in bucket #3.
countProducer.onMatchedLogEvent(1 /*log matcher index*/, event4);
countProducer.onMatchedLogEvent(1 /*log matcher index*/, event5);
countProducer.onMatchedLogEvent(1 /*log matcher index*/, event6);
EXPECT_EQ(1UL, countProducer.mCurrentSlicedCounter->size());
EXPECT_EQ(3L, countProducer.mCurrentSlicedCounter->begin()->second);
// Anomaly at event 6 is within refractory period. The alarm is at event 5 timestamp not event 6
EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY),
std::ceil(1.0 * event5.GetElapsedTimestampNs() / NS_PER_SEC + refPeriodSec));
countProducer.onMatchedLogEvent(1 /*log matcher index*/, event7);
EXPECT_EQ(1UL, countProducer.mCurrentSlicedCounter->size());
EXPECT_EQ(4L, countProducer.mCurrentSlicedCounter->begin()->second);
EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY),
std::ceil(1.0 * event7.GetElapsedTimestampNs() / NS_PER_SEC + refPeriodSec));
}
// TODO(b/149590301): Update these tests to use new socket schema.
//TEST(CountMetricProducerTest, TestFirstBucket) {
// CountMetric metric;
// metric.set_id(1);
// metric.set_bucket(ONE_MINUTE);
// sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
//
// CountMetricProducer countProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard, 5,
// 600 * NS_PER_SEC + NS_PER_SEC / 2);
// EXPECT_EQ(600500000000, countProducer.mCurrentBucketStartTimeNs);
// EXPECT_EQ(10, countProducer.mCurrentBucketNum);
// EXPECT_EQ(660000000005, countProducer.getCurrentBucketEndTimeNs());
//}
//
//TEST(CountMetricProducerTest, TestNonDimensionalEvents) {
// int64_t bucketStartTimeNs = 10000000000;
// int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
// int64_t bucket2StartTimeNs = bucketStartTimeNs + bucketSizeNs;
// int64_t bucket3StartTimeNs = bucketStartTimeNs + 2 * bucketSizeNs;
// int tagId = 1;
//
// CountMetric metric;
// metric.set_id(1);
// metric.set_bucket(ONE_MINUTE);
//
// LogEvent event1(tagId, bucketStartTimeNs + 1);
// event1.init();
// LogEvent event2(tagId, bucketStartTimeNs + 2);
// event2.init();
//
// sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
//
// CountMetricProducer countProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
// bucketStartTimeNs, bucketStartTimeNs);
//
// // 2 events in bucket 1.
// countProducer.onMatchedLogEvent(1 /*log matcher index*/, event1);
// countProducer.onMatchedLogEvent(1 /*log matcher index*/, event2);
//
// // Flushes at event #2.
// countProducer.flushIfNeededLocked(bucketStartTimeNs + 2);
// EXPECT_EQ(0UL, countProducer.mPastBuckets.size());
//
// // Flushes.
// countProducer.flushIfNeededLocked(bucketStartTimeNs + bucketSizeNs + 1);
// EXPECT_EQ(1UL, countProducer.mPastBuckets.size());
// EXPECT_TRUE(countProducer.mPastBuckets.find(DEFAULT_METRIC_DIMENSION_KEY) !=
// countProducer.mPastBuckets.end());
// const auto& buckets = countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY];
// EXPECT_EQ(1UL, buckets.size());
// EXPECT_EQ(bucketStartTimeNs, buckets[0].mBucketStartNs);
// EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, buckets[0].mBucketEndNs);
// EXPECT_EQ(2LL, buckets[0].mCount);
//
// // 1 matched event happens in bucket 2.
// LogEvent event3(tagId, bucketStartTimeNs + bucketSizeNs + 2);
// event3.init();
//
// countProducer.onMatchedLogEvent(1 /*log matcher index*/, event3);
// countProducer.flushIfNeededLocked(bucketStartTimeNs + 2 * bucketSizeNs + 1);
// EXPECT_EQ(1UL, countProducer.mPastBuckets.size());
// EXPECT_TRUE(countProducer.mPastBuckets.find(DEFAULT_METRIC_DIMENSION_KEY) !=
// countProducer.mPastBuckets.end());
// EXPECT_EQ(2UL, countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
// const auto& bucketInfo2 = countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][1];
// EXPECT_EQ(bucket2StartTimeNs, bucketInfo2.mBucketStartNs);
// EXPECT_EQ(bucket2StartTimeNs + bucketSizeNs, bucketInfo2.mBucketEndNs);
// EXPECT_EQ(1LL, bucketInfo2.mCount);
//
// // nothing happens in bucket 3. we should not record anything for bucket 3.
// countProducer.flushIfNeededLocked(bucketStartTimeNs + 3 * bucketSizeNs + 1);
// EXPECT_EQ(1UL, countProducer.mPastBuckets.size());
// EXPECT_TRUE(countProducer.mPastBuckets.find(DEFAULT_METRIC_DIMENSION_KEY) !=
// countProducer.mPastBuckets.end());
// const auto& buckets3 = countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY];
// EXPECT_EQ(2UL, buckets3.size());
//}
//
//TEST(CountMetricProducerTest, TestEventsWithNonSlicedCondition) {
// int64_t bucketStartTimeNs = 10000000000;
// int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
//
// CountMetric metric;
// metric.set_id(1);
// metric.set_bucket(ONE_MINUTE);
// metric.set_condition(StringToId("SCREEN_ON"));
//
// LogEvent event1(1, bucketStartTimeNs + 1);
// event1.init();
//
// LogEvent event2(1, bucketStartTimeNs + 10);
// event2.init();
//
// sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
//
// CountMetricProducer countProducer(kConfigKey, metric, 1, wizard, bucketStartTimeNs,
// bucketStartTimeNs);
//
// countProducer.onConditionChanged(true, bucketStartTimeNs);
// countProducer.onMatchedLogEvent(1 /*matcher index*/, event1);
// EXPECT_EQ(0UL, countProducer.mPastBuckets.size());
//
// countProducer.onConditionChanged(false /*new condition*/, bucketStartTimeNs + 2);
// // Upon this match event, the matched event1 is flushed.
// countProducer.onMatchedLogEvent(1 /*matcher index*/, event2);
// EXPECT_EQ(0UL, countProducer.mPastBuckets.size());
//
// countProducer.flushIfNeededLocked(bucketStartTimeNs + bucketSizeNs + 1);
// EXPECT_EQ(1UL, countProducer.mPastBuckets.size());
// EXPECT_TRUE(countProducer.mPastBuckets.find(DEFAULT_METRIC_DIMENSION_KEY) !=
// countProducer.mPastBuckets.end());
// {
// const auto& buckets = countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY];
// EXPECT_EQ(1UL, buckets.size());
// const auto& bucketInfo = buckets[0];
// EXPECT_EQ(bucketStartTimeNs, bucketInfo.mBucketStartNs);
// EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, bucketInfo.mBucketEndNs);
// EXPECT_EQ(1LL, bucketInfo.mCount);
// }
//}
//
//TEST(CountMetricProducerTest, TestEventsWithSlicedCondition) {
// int64_t bucketStartTimeNs = 10000000000;
// int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
//
// int tagId = 1;
// int conditionTagId = 2;
//
// CountMetric metric;
// metric.set_id(1);
// metric.set_bucket(ONE_MINUTE);
// metric.set_condition(StringToId("APP_IN_BACKGROUND_PER_UID_AND_SCREEN_ON"));
// MetricConditionLink* link = metric.add_links();
// link->set_condition(StringToId("APP_IN_BACKGROUND_PER_UID"));
// buildSimpleAtomFieldMatcher(tagId, 1, link->mutable_fields_in_what());
// buildSimpleAtomFieldMatcher(conditionTagId, 2, link->mutable_fields_in_condition());
//
// LogEvent event1(tagId, bucketStartTimeNs + 1);
// event1.write("111"); // uid
// event1.init();
// ConditionKey key1;
// key1[StringToId("APP_IN_BACKGROUND_PER_UID")] =
// {getMockedDimensionKey(conditionTagId, 2, "111")};
//
// LogEvent event2(tagId, bucketStartTimeNs + 10);
// event2.write("222"); // uid
// event2.init();
// ConditionKey key2;
// key2[StringToId("APP_IN_BACKGROUND_PER_UID")] =
// {getMockedDimensionKey(conditionTagId, 2, "222")};
//
// sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
// EXPECT_CALL(*wizard, query(_, key1, _)).WillOnce(Return(ConditionState::kFalse));
//
// EXPECT_CALL(*wizard, query(_, key2, _)).WillOnce(Return(ConditionState::kTrue));
//
// CountMetricProducer countProducer(kConfigKey, metric, 1 /*condition tracker index*/, wizard,
// bucketStartTimeNs, bucketStartTimeNs);
//
// countProducer.onMatchedLogEvent(1 /*log matcher index*/, event1);
// countProducer.flushIfNeededLocked(bucketStartTimeNs + 1);
// EXPECT_EQ(0UL, countProducer.mPastBuckets.size());
//
// countProducer.onMatchedLogEvent(1 /*log matcher index*/, event2);
// countProducer.flushIfNeededLocked(bucketStartTimeNs + bucketSizeNs + 1);
// EXPECT_EQ(1UL, countProducer.mPastBuckets.size());
// EXPECT_TRUE(countProducer.mPastBuckets.find(DEFAULT_METRIC_DIMENSION_KEY) !=
// countProducer.mPastBuckets.end());
// const auto& buckets = countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY];
// EXPECT_EQ(1UL, buckets.size());
// const auto& bucketInfo = buckets[0];
// EXPECT_EQ(bucketStartTimeNs, bucketInfo.mBucketStartNs);
// EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, bucketInfo.mBucketEndNs);
// EXPECT_EQ(1LL, bucketInfo.mCount);
//}
//
//TEST(CountMetricProducerTest, TestEventWithAppUpgrade) {
// sp<AlarmMonitor> alarmMonitor;
// int64_t bucketStartTimeNs = 10000000000;
// int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
// int64_t eventUpgradeTimeNs = bucketStartTimeNs + 15 * NS_PER_SEC;
//
// int tagId = 1;
// int conditionTagId = 2;
//
// CountMetric metric;
// metric.set_id(1);
// metric.set_bucket(ONE_MINUTE);
// Alert alert;
// alert.set_num_buckets(3);
// alert.set_trigger_if_sum_gt(2);
// LogEvent event1(tagId, bucketStartTimeNs + 1);
// event1.write("111"); // uid
// event1.init();
// sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
// CountMetricProducer countProducer(kConfigKey, metric, -1 /* no condition */, wizard,
// bucketStartTimeNs, bucketStartTimeNs);
//
// sp<AnomalyTracker> anomalyTracker = countProducer.addAnomalyTracker(alert, alarmMonitor);
// EXPECT_TRUE(anomalyTracker != nullptr);
//
// // Bucket is flushed yet.
// countProducer.onMatchedLogEvent(1 /*log matcher index*/, event1);
// EXPECT_EQ(0UL, countProducer.mPastBuckets.size());
// EXPECT_EQ(0, anomalyTracker->getSumOverPastBuckets(DEFAULT_METRIC_DIMENSION_KEY));
//
// // App upgrade forces bucket flush.
// // Check that there's a past bucket and the bucket end is not adjusted.
// countProducer.notifyAppUpgrade(eventUpgradeTimeNs, "ANY.APP", 1, 1);
// EXPECT_EQ(1UL, countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
// EXPECT_EQ((long long)bucketStartTimeNs,
// countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][0].mBucketStartNs);
// EXPECT_EQ((long long)eventUpgradeTimeNs,
// countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][0].mBucketEndNs);
// EXPECT_EQ(eventUpgradeTimeNs, countProducer.mCurrentBucketStartTimeNs);
// // Anomaly tracker only contains full buckets.
// EXPECT_EQ(0, anomalyTracker->getSumOverPastBuckets(DEFAULT_METRIC_DIMENSION_KEY));
//
// int64_t lastEndTimeNs = countProducer.getCurrentBucketEndTimeNs();
// // Next event occurs in same bucket as partial bucket created.
// LogEvent event2(tagId, bucketStartTimeNs + 59 * NS_PER_SEC + 10);
// event2.write("222"); // uid
// event2.init();
// countProducer.onMatchedLogEvent(1 /*log matcher index*/, event2);
// EXPECT_EQ(1UL, countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
// EXPECT_EQ(eventUpgradeTimeNs, countProducer.mCurrentBucketStartTimeNs);
// EXPECT_EQ(0, anomalyTracker->getSumOverPastBuckets(DEFAULT_METRIC_DIMENSION_KEY));
//
// // Third event in following bucket.
// LogEvent event3(tagId, bucketStartTimeNs + 62 * NS_PER_SEC + 10);
// event3.write("333"); // uid
// event3.init();
// countProducer.onMatchedLogEvent(1 /*log matcher index*/, event3);
// EXPECT_EQ(2UL, countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
// EXPECT_EQ(lastEndTimeNs, countProducer.mCurrentBucketStartTimeNs);
// EXPECT_EQ(2, anomalyTracker->getSumOverPastBuckets(DEFAULT_METRIC_DIMENSION_KEY));
//}
//
//TEST(CountMetricProducerTest, TestEventWithAppUpgradeInNextBucket) {
// int64_t bucketStartTimeNs = 10000000000;
// int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
// int64_t eventUpgradeTimeNs = bucketStartTimeNs + 65 * NS_PER_SEC;
//
// int tagId = 1;
// int conditionTagId = 2;
//
// CountMetric metric;
// metric.set_id(1);
// metric.set_bucket(ONE_MINUTE);
// LogEvent event1(tagId, bucketStartTimeNs + 1);
// event1.write("111"); // uid
// event1.init();
// sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
// CountMetricProducer countProducer(kConfigKey, metric, -1 /* no condition */, wizard,
// bucketStartTimeNs, bucketStartTimeNs);
//
// // Bucket is flushed yet.
// countProducer.onMatchedLogEvent(1 /*log matcher index*/, event1);
// EXPECT_EQ(0UL, countProducer.mPastBuckets.size());
//
// // App upgrade forces bucket flush.
// // Check that there's a past bucket and the bucket end is not adjusted.
// countProducer.notifyAppUpgrade(eventUpgradeTimeNs, "ANY.APP", 1, 1);
// EXPECT_EQ(1UL, countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
// EXPECT_EQ((int64_t)bucketStartTimeNs,
// countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][0].mBucketStartNs);
// EXPECT_EQ(bucketStartTimeNs + bucketSizeNs,
// countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][0].mBucketEndNs);
// EXPECT_EQ(eventUpgradeTimeNs, countProducer.mCurrentBucketStartTimeNs);
//
// // Next event occurs in same bucket as partial bucket created.
// LogEvent event2(tagId, bucketStartTimeNs + 70 * NS_PER_SEC + 10);
// event2.write("222"); // uid
// event2.init();
// countProducer.onMatchedLogEvent(1 /*log matcher index*/, event2);
// EXPECT_EQ(1UL, countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
//
// // Third event in following bucket.
// LogEvent event3(tagId, bucketStartTimeNs + 121 * NS_PER_SEC + 10);
// event3.write("333"); // uid
// event3.init();
// countProducer.onMatchedLogEvent(1 /*log matcher index*/, event3);
// EXPECT_EQ(2UL, countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
// EXPECT_EQ((int64_t)eventUpgradeTimeNs,
// countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][1].mBucketStartNs);
// EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
// countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][1].mBucketEndNs);
//}
//
//TEST(CountMetricProducerTest, TestAnomalyDetectionUnSliced) {
// sp<AlarmMonitor> alarmMonitor;
// Alert alert;
// alert.set_id(11);
// alert.set_metric_id(1);
// alert.set_trigger_if_sum_gt(2);
// alert.set_num_buckets(2);
// const int32_t refPeriodSec = 1;
// alert.set_refractory_period_secs(refPeriodSec);
//
// int64_t bucketStartTimeNs = 10000000000;
// int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
// int64_t bucket2StartTimeNs = bucketStartTimeNs + bucketSizeNs;
// int64_t bucket3StartTimeNs = bucketStartTimeNs + 2 * bucketSizeNs;
//
// CountMetric metric;
// metric.set_id(1);
// metric.set_bucket(ONE_MINUTE);
//
// sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
// CountMetricProducer countProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
// bucketStartTimeNs, bucketStartTimeNs);
//
// sp<AnomalyTracker> anomalyTracker = countProducer.addAnomalyTracker(alert, alarmMonitor);
//
// int tagId = 1;
// LogEvent event1(tagId, bucketStartTimeNs + 1);
// event1.init();
// LogEvent event2(tagId, bucketStartTimeNs + 2);
// event2.init();
// LogEvent event3(tagId, bucketStartTimeNs + 2 * bucketSizeNs + 1);
// event3.init();
// LogEvent event4(tagId, bucketStartTimeNs + 3 * bucketSizeNs + 1);
// event4.init();
// LogEvent event5(tagId, bucketStartTimeNs + 3 * bucketSizeNs + 2);
// event5.init();
// LogEvent event6(tagId, bucketStartTimeNs + 3 * bucketSizeNs + 3);
// event6.init();
// LogEvent event7(tagId, bucketStartTimeNs + 3 * bucketSizeNs + 2 * NS_PER_SEC);
// event7.init();
//
// // Two events in bucket #0.
// countProducer.onMatchedLogEvent(1 /*log matcher index*/, event1);
// countProducer.onMatchedLogEvent(1 /*log matcher index*/, event2);
//
// EXPECT_EQ(1UL, countProducer.mCurrentSlicedCounter->size());
// EXPECT_EQ(2L, countProducer.mCurrentSlicedCounter->begin()->second);
// EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY), 0U);
//
// // One event in bucket #2. No alarm as bucket #0 is trashed out.
// countProducer.onMatchedLogEvent(1 /*log matcher index*/, event3);
// EXPECT_EQ(1UL, countProducer.mCurrentSlicedCounter->size());
// EXPECT_EQ(1L, countProducer.mCurrentSlicedCounter->begin()->second);
// EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY), 0U);
//
// // Two events in bucket #3.
// countProducer.onMatchedLogEvent(1 /*log matcher index*/, event4);
// countProducer.onMatchedLogEvent(1 /*log matcher index*/, event5);
// countProducer.onMatchedLogEvent(1 /*log matcher index*/, event6);
// EXPECT_EQ(1UL, countProducer.mCurrentSlicedCounter->size());
// EXPECT_EQ(3L, countProducer.mCurrentSlicedCounter->begin()->second);
// // Anomaly at event 6 is within refractory period. The alarm is at event 5 timestamp not event 6
// EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY),
// std::ceil(1.0 * event5.GetElapsedTimestampNs() / NS_PER_SEC + refPeriodSec));
//
// countProducer.onMatchedLogEvent(1 /*log matcher index*/, event7);
// EXPECT_EQ(1UL, countProducer.mCurrentSlicedCounter->size());
// EXPECT_EQ(4L, countProducer.mCurrentSlicedCounter->begin()->second);
// EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY),
// std::ceil(1.0 * event7.GetElapsedTimestampNs() / NS_PER_SEC + refPeriodSec));
//}
TEST(CountMetricProducerTest, TestOneWeekTimeUnit) {
CountMetric metric;

View File

@@ -56,382 +56,383 @@ TEST(DurationMetricTrackerTest, TestFirstBucket) {
EXPECT_EQ(660000000005, durationProducer.getCurrentBucketEndTimeNs());
}
TEST(DurationMetricTrackerTest, TestNoCondition) {
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
int64_t bucketStartTimeNs = 10000000000;
int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
DurationMetric metric;
metric.set_id(1);
metric.set_bucket(ONE_MINUTE);
metric.set_aggregation_type(DurationMetric_AggregationType_SUM);
int tagId = 1;
LogEvent event1(tagId, bucketStartTimeNs + 1);
event1.init();
LogEvent event2(tagId, bucketStartTimeNs + bucketSizeNs + 2);
event2.init();
FieldMatcher dimensions;
DurationMetricProducer durationProducer(
kConfigKey, metric, -1 /*no condition*/, 1 /* start index */, 2 /* stop index */,
3 /* stop_all index */, false /*nesting*/, wizard, dimensions, bucketStartTimeNs, bucketStartTimeNs);
durationProducer.onMatchedLogEvent(1 /* start index*/, event1);
durationProducer.onMatchedLogEvent(2 /* stop index*/, event2);
durationProducer.flushIfNeededLocked(bucketStartTimeNs + 2 * bucketSizeNs + 1);
EXPECT_EQ(1UL, durationProducer.mPastBuckets.size());
EXPECT_TRUE(durationProducer.mPastBuckets.find(DEFAULT_METRIC_DIMENSION_KEY) !=
durationProducer.mPastBuckets.end());
const auto& buckets = durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY];
EXPECT_EQ(2UL, buckets.size());
EXPECT_EQ(bucketStartTimeNs, buckets[0].mBucketStartNs);
EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, buckets[0].mBucketEndNs);
EXPECT_EQ(bucketSizeNs - 1LL, buckets[0].mDuration);
EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, buckets[1].mBucketStartNs);
EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs, buckets[1].mBucketEndNs);
EXPECT_EQ(2LL, buckets[1].mDuration);
}
TEST(DurationMetricTrackerTest, TestNonSlicedCondition) {
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
int64_t bucketStartTimeNs = 10000000000;
int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
DurationMetric metric;
metric.set_id(1);
metric.set_bucket(ONE_MINUTE);
metric.set_aggregation_type(DurationMetric_AggregationType_SUM);
int tagId = 1;
LogEvent event1(tagId, bucketStartTimeNs + 1);
event1.init();
LogEvent event2(tagId, bucketStartTimeNs + 2);
event2.init();
LogEvent event3(tagId, bucketStartTimeNs + bucketSizeNs + 1);
event3.init();
LogEvent event4(tagId, bucketStartTimeNs + bucketSizeNs + 3);
event4.init();
FieldMatcher dimensions;
DurationMetricProducer durationProducer(
kConfigKey, metric, 0 /* condition index */, 1 /* start index */, 2 /* stop index */,
3 /* stop_all index */, false /*nesting*/, wizard, dimensions, bucketStartTimeNs, bucketStartTimeNs);
durationProducer.mCondition = ConditionState::kFalse;
EXPECT_FALSE(durationProducer.mCondition);
EXPECT_FALSE(durationProducer.isConditionSliced());
durationProducer.onMatchedLogEvent(1 /* start index*/, event1);
durationProducer.onMatchedLogEvent(2 /* stop index*/, event2);
durationProducer.flushIfNeededLocked(bucketStartTimeNs + bucketSizeNs + 1);
EXPECT_EQ(0UL, durationProducer.mPastBuckets.size());
durationProducer.onMatchedLogEvent(1 /* start index*/, event3);
durationProducer.onConditionChanged(true /* condition */, bucketStartTimeNs + bucketSizeNs + 2);
durationProducer.onMatchedLogEvent(2 /* stop index*/, event4);
durationProducer.flushIfNeededLocked(bucketStartTimeNs + 2 * bucketSizeNs + 1);
EXPECT_EQ(1UL, durationProducer.mPastBuckets.size());
EXPECT_TRUE(durationProducer.mPastBuckets.find(DEFAULT_METRIC_DIMENSION_KEY) !=
durationProducer.mPastBuckets.end());
const auto& buckets2 = durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY];
EXPECT_EQ(1UL, buckets2.size());
EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, buckets2[0].mBucketStartNs);
EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs, buckets2[0].mBucketEndNs);
EXPECT_EQ(1LL, buckets2[0].mDuration);
}
TEST(DurationMetricTrackerTest, TestNonSlicedConditionUnknownState) {
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
int64_t bucketStartTimeNs = 10000000000;
int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
DurationMetric metric;
metric.set_id(1);
metric.set_bucket(ONE_MINUTE);
metric.set_aggregation_type(DurationMetric_AggregationType_SUM);
int tagId = 1;
LogEvent event1(tagId, bucketStartTimeNs + 1);
event1.init();
LogEvent event2(tagId, bucketStartTimeNs + 2);
event2.init();
LogEvent event3(tagId, bucketStartTimeNs + bucketSizeNs + 1);
event3.init();
LogEvent event4(tagId, bucketStartTimeNs + bucketSizeNs + 3);
event4.init();
FieldMatcher dimensions;
DurationMetricProducer durationProducer(
kConfigKey, metric, 0 /* condition index */, 1 /* start index */, 2 /* stop index */,
3 /* stop_all index */, false /*nesting*/, wizard, dimensions, bucketStartTimeNs, bucketStartTimeNs);
EXPECT_EQ(ConditionState::kUnknown, durationProducer.mCondition);
EXPECT_FALSE(durationProducer.isConditionSliced());
durationProducer.onMatchedLogEvent(1 /* start index*/, event1);
durationProducer.onMatchedLogEvent(2 /* stop index*/, event2);
durationProducer.flushIfNeededLocked(bucketStartTimeNs + bucketSizeNs + 1);
EXPECT_EQ(0UL, durationProducer.mPastBuckets.size());
durationProducer.onMatchedLogEvent(1 /* start index*/, event3);
durationProducer.onConditionChanged(true /* condition */, bucketStartTimeNs + bucketSizeNs + 2);
durationProducer.onMatchedLogEvent(2 /* stop index*/, event4);
durationProducer.flushIfNeededLocked(bucketStartTimeNs + 2 * bucketSizeNs + 1);
EXPECT_EQ(1UL, durationProducer.mPastBuckets.size());
const auto& buckets2 = durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY];
EXPECT_EQ(1UL, buckets2.size());
EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, buckets2[0].mBucketStartNs);
EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs, buckets2[0].mBucketEndNs);
EXPECT_EQ(1LL, buckets2[0].mDuration);
}
TEST(DurationMetricTrackerTest, TestSumDurationWithUpgrade) {
/**
* The duration starts from the first bucket, through the two partial buckets (10-70sec),
* another bucket, and ends at the beginning of the next full bucket.
* Expected buckets:
* - [10,25]: 14 secs
* - [25,70]: All 45 secs
* - [70,130]: All 60 secs
* - [130, 210]: Only 5 secs (event ended at 135sec)
*/
int64_t bucketStartTimeNs = 10000000000;
int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
int64_t eventUpgradeTimeNs = bucketStartTimeNs + 15 * NS_PER_SEC;
int64_t startTimeNs = bucketStartTimeNs + 1 * NS_PER_SEC;
int64_t endTimeNs = startTimeNs + 125 * NS_PER_SEC;
int tagId = 1;
DurationMetric metric;
metric.set_id(1);
metric.set_bucket(ONE_MINUTE);
metric.set_aggregation_type(DurationMetric_AggregationType_SUM);
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
FieldMatcher dimensions;
DurationMetricProducer durationProducer(
kConfigKey, metric, -1 /* no condition */, 1 /* start index */, 2 /* stop index */,
3 /* stop_all index */, false /*nesting*/, wizard, dimensions, bucketStartTimeNs, bucketStartTimeNs);
LogEvent start_event(tagId, startTimeNs);
start_event.init();
durationProducer.onMatchedLogEvent(1 /* start index*/, start_event);
EXPECT_EQ(0UL, durationProducer.mPastBuckets.size());
EXPECT_EQ(bucketStartTimeNs, durationProducer.mCurrentBucketStartTimeNs);
durationProducer.notifyAppUpgrade(eventUpgradeTimeNs, "ANY.APP", 1, 1);
EXPECT_EQ(1UL, durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
std::vector<DurationBucket> buckets =
durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY];
EXPECT_EQ(bucketStartTimeNs, buckets[0].mBucketStartNs);
EXPECT_EQ(eventUpgradeTimeNs, buckets[0].mBucketEndNs);
EXPECT_EQ(eventUpgradeTimeNs - startTimeNs, buckets[0].mDuration);
EXPECT_EQ(eventUpgradeTimeNs, durationProducer.mCurrentBucketStartTimeNs);
// We skip ahead one bucket, so we fill in the first two partial buckets and one full bucket.
LogEvent end_event(tagId, endTimeNs);
end_event.init();
durationProducer.onMatchedLogEvent(2 /* stop index*/, end_event);
buckets = durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY];
EXPECT_EQ(3UL, buckets.size());
EXPECT_EQ(eventUpgradeTimeNs, buckets[1].mBucketStartNs);
EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, buckets[1].mBucketEndNs);
EXPECT_EQ(bucketStartTimeNs + bucketSizeNs - eventUpgradeTimeNs, buckets[1].mDuration);
EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, buckets[2].mBucketStartNs);
EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs, buckets[2].mBucketEndNs);
EXPECT_EQ(bucketSizeNs, buckets[2].mDuration);
}
TEST(DurationMetricTrackerTest, TestSumDurationWithUpgradeInFollowingBucket) {
/**
* Expected buckets (start at 11s, upgrade at 75s, end at 135s):
* - [10,70]: 59 secs
* - [70,75]: 5 sec
* - [75,130]: 55 secs
*/
int64_t bucketStartTimeNs = 10000000000;
int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
int64_t eventUpgradeTimeNs = bucketStartTimeNs + 65 * NS_PER_SEC;
int64_t startTimeNs = bucketStartTimeNs + 1 * NS_PER_SEC;
int64_t endTimeNs = startTimeNs + 125 * NS_PER_SEC;
int tagId = 1;
DurationMetric metric;
metric.set_id(1);
metric.set_bucket(ONE_MINUTE);
metric.set_aggregation_type(DurationMetric_AggregationType_SUM);
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
FieldMatcher dimensions;
DurationMetricProducer durationProducer(
kConfigKey, metric, -1 /* no condition */, 1 /* start index */, 2 /* stop index */,
3 /* stop_all index */, false /*nesting*/, wizard, dimensions, bucketStartTimeNs, bucketStartTimeNs);
LogEvent start_event(tagId, startTimeNs);
start_event.init();
durationProducer.onMatchedLogEvent(1 /* start index*/, start_event);
EXPECT_EQ(0UL, durationProducer.mPastBuckets.size());
EXPECT_EQ(bucketStartTimeNs, durationProducer.mCurrentBucketStartTimeNs);
durationProducer.notifyAppUpgrade(eventUpgradeTimeNs, "ANY.APP", 1, 1);
EXPECT_EQ(2UL, durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
std::vector<DurationBucket> buckets =
durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY];
EXPECT_EQ(bucketStartTimeNs, buckets[0].mBucketStartNs);
EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, buckets[0].mBucketEndNs);
EXPECT_EQ(bucketStartTimeNs + bucketSizeNs - startTimeNs, buckets[0].mDuration);
EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, buckets[1].mBucketStartNs);
EXPECT_EQ(eventUpgradeTimeNs, buckets[1].mBucketEndNs);
EXPECT_EQ(eventUpgradeTimeNs - (bucketStartTimeNs + bucketSizeNs), buckets[1].mDuration);
EXPECT_EQ(eventUpgradeTimeNs, durationProducer.mCurrentBucketStartTimeNs);
// We skip ahead one bucket, so we fill in the first two partial buckets and one full bucket.
LogEvent end_event(tagId, endTimeNs);
end_event.init();
durationProducer.onMatchedLogEvent(2 /* stop index*/, end_event);
buckets = durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY];
EXPECT_EQ(3UL, buckets.size());
EXPECT_EQ(eventUpgradeTimeNs, buckets[2].mBucketStartNs);
EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs, buckets[2].mBucketEndNs);
EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs - eventUpgradeTimeNs, buckets[2].mDuration);
}
TEST(DurationMetricTrackerTest, TestSumDurationAnomalyWithUpgrade) {
sp<AlarmMonitor> alarmMonitor;
int64_t bucketStartTimeNs = 10000000000;
int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
int64_t eventUpgradeTimeNs = bucketStartTimeNs + 15 * NS_PER_SEC;
int64_t startTimeNs = bucketStartTimeNs + 1;
int64_t endTimeNs = startTimeNs + 65 * NS_PER_SEC;
int tagId = 1;
// Setup metric with alert.
DurationMetric metric;
metric.set_id(1);
metric.set_bucket(ONE_MINUTE);
metric.set_aggregation_type(DurationMetric_AggregationType_SUM);
Alert alert;
alert.set_num_buckets(3);
alert.set_trigger_if_sum_gt(2);
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
FieldMatcher dimensions;
DurationMetricProducer durationProducer(
kConfigKey, metric, -1 /* no condition */, 1 /* start index */, 2 /* stop index */,
3 /* stop_all index */, false /*nesting*/, wizard, dimensions, bucketStartTimeNs, bucketStartTimeNs);
sp<AnomalyTracker> anomalyTracker = durationProducer.addAnomalyTracker(alert, alarmMonitor);
EXPECT_TRUE(anomalyTracker != nullptr);
LogEvent start_event(tagId, startTimeNs);
start_event.init();
durationProducer.onMatchedLogEvent(1 /* start index*/, start_event);
durationProducer.notifyAppUpgrade(eventUpgradeTimeNs, "ANY.APP", 1, 1);
// We skip ahead one bucket, so we fill in the first two partial buckets and one full bucket.
LogEvent end_event(tagId, endTimeNs);
end_event.init();
durationProducer.onMatchedLogEvent(2 /* stop index*/, end_event);
EXPECT_EQ(bucketStartTimeNs + bucketSizeNs - startTimeNs,
anomalyTracker->getSumOverPastBuckets(DEFAULT_METRIC_DIMENSION_KEY));
}
TEST(DurationMetricTrackerTest, TestMaxDurationWithUpgrade) {
int64_t bucketStartTimeNs = 10000000000;
int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
int64_t eventUpgradeTimeNs = bucketStartTimeNs + 15 * NS_PER_SEC;
int64_t startTimeNs = bucketStartTimeNs + 1;
int64_t endTimeNs = startTimeNs + 125 * NS_PER_SEC;
int tagId = 1;
DurationMetric metric;
metric.set_id(1);
metric.set_bucket(ONE_MINUTE);
metric.set_aggregation_type(DurationMetric_AggregationType_MAX_SPARSE);
LogEvent event1(tagId, startTimeNs);
event1.write("111"); // uid
event1.init();
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
FieldMatcher dimensions;
DurationMetricProducer durationProducer(
kConfigKey, metric, -1 /* no condition */, 1 /* start index */, 2 /* stop index */,
3 /* stop_all index */, false /*nesting*/, wizard, dimensions, bucketStartTimeNs, bucketStartTimeNs);
LogEvent start_event(tagId, startTimeNs);
start_event.init();
durationProducer.onMatchedLogEvent(1 /* start index*/, start_event);
EXPECT_EQ(0UL, durationProducer.mPastBuckets.size());
EXPECT_EQ(bucketStartTimeNs, durationProducer.mCurrentBucketStartTimeNs);
durationProducer.notifyAppUpgrade(eventUpgradeTimeNs, "ANY.APP", 1, 1);
EXPECT_EQ(0UL, durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
EXPECT_EQ(eventUpgradeTimeNs, durationProducer.mCurrentBucketStartTimeNs);
// We skip ahead one bucket, so we fill in the first two partial buckets and one full bucket.
LogEvent end_event(tagId, endTimeNs);
end_event.init();
durationProducer.onMatchedLogEvent(2 /* stop index*/, end_event);
EXPECT_EQ(0UL, durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
durationProducer.flushIfNeededLocked(bucketStartTimeNs + 3 * bucketSizeNs + 1);
std::vector<DurationBucket> buckets =
durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY];
EXPECT_EQ(1UL, buckets.size());
EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs, buckets[0].mBucketStartNs);
EXPECT_EQ(bucketStartTimeNs + 3 * bucketSizeNs, buckets[0].mBucketEndNs);
EXPECT_EQ(endTimeNs - startTimeNs, buckets[0].mDuration);
}
TEST(DurationMetricTrackerTest, TestMaxDurationWithUpgradeInNextBucket) {
int64_t bucketStartTimeNs = 10000000000;
int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
int64_t eventUpgradeTimeNs = bucketStartTimeNs + 65 * NS_PER_SEC;
int64_t startTimeNs = bucketStartTimeNs + 1;
int64_t endTimeNs = startTimeNs + 115 * NS_PER_SEC;
int tagId = 1;
DurationMetric metric;
metric.set_id(1);
metric.set_bucket(ONE_MINUTE);
metric.set_aggregation_type(DurationMetric_AggregationType_MAX_SPARSE);
LogEvent event1(tagId, startTimeNs);
event1.write("111"); // uid
event1.init();
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
FieldMatcher dimensions;
DurationMetricProducer durationProducer(
kConfigKey, metric, -1 /* no condition */, 1 /* start index */, 2 /* stop index */,
3 /* stop_all index */, false /*nesting*/, wizard, dimensions, bucketStartTimeNs, bucketStartTimeNs);
LogEvent start_event(tagId, startTimeNs);
start_event.init();
durationProducer.onMatchedLogEvent(1 /* start index*/, start_event);
EXPECT_EQ(0UL, durationProducer.mPastBuckets.size());
EXPECT_EQ(bucketStartTimeNs, durationProducer.mCurrentBucketStartTimeNs);
durationProducer.notifyAppUpgrade(eventUpgradeTimeNs, "ANY.APP", 1, 1);
EXPECT_EQ(0UL, durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
EXPECT_EQ(eventUpgradeTimeNs, durationProducer.mCurrentBucketStartTimeNs);
// Stop occurs in the same partial bucket as created for the app upgrade.
LogEvent end_event(tagId, endTimeNs);
end_event.init();
durationProducer.onMatchedLogEvent(2 /* stop index*/, end_event);
EXPECT_EQ(0UL, durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
EXPECT_EQ(eventUpgradeTimeNs, durationProducer.mCurrentBucketStartTimeNs);
durationProducer.flushIfNeededLocked(bucketStartTimeNs + 2 * bucketSizeNs + 1);
std::vector<DurationBucket> buckets =
durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY];
EXPECT_EQ(1UL, buckets.size());
EXPECT_EQ(eventUpgradeTimeNs, buckets[0].mBucketStartNs);
EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs, buckets[0].mBucketEndNs);
EXPECT_EQ(endTimeNs - startTimeNs, buckets[0].mDuration);
}
// TODO(b/149590301): Update these to use new socket schema.
//TEST(DurationMetricTrackerTest, TestNoCondition) {
// sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
// int64_t bucketStartTimeNs = 10000000000;
// int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
//
// DurationMetric metric;
// metric.set_id(1);
// metric.set_bucket(ONE_MINUTE);
// metric.set_aggregation_type(DurationMetric_AggregationType_SUM);
//
// int tagId = 1;
// LogEvent event1(tagId, bucketStartTimeNs + 1);
// event1.init();
// LogEvent event2(tagId, bucketStartTimeNs + bucketSizeNs + 2);
// event2.init();
//
// FieldMatcher dimensions;
// DurationMetricProducer durationProducer(
// kConfigKey, metric, -1 /*no condition*/, 1 /* start index */, 2 /* stop index */,
// 3 /* stop_all index */, false /*nesting*/, wizard, dimensions, bucketStartTimeNs, bucketStartTimeNs);
//
// durationProducer.onMatchedLogEvent(1 /* start index*/, event1);
// durationProducer.onMatchedLogEvent(2 /* stop index*/, event2);
// durationProducer.flushIfNeededLocked(bucketStartTimeNs + 2 * bucketSizeNs + 1);
// EXPECT_EQ(1UL, durationProducer.mPastBuckets.size());
// EXPECT_TRUE(durationProducer.mPastBuckets.find(DEFAULT_METRIC_DIMENSION_KEY) !=
// durationProducer.mPastBuckets.end());
// const auto& buckets = durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY];
// EXPECT_EQ(2UL, buckets.size());
// EXPECT_EQ(bucketStartTimeNs, buckets[0].mBucketStartNs);
// EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, buckets[0].mBucketEndNs);
// EXPECT_EQ(bucketSizeNs - 1LL, buckets[0].mDuration);
// EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, buckets[1].mBucketStartNs);
// EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs, buckets[1].mBucketEndNs);
// EXPECT_EQ(2LL, buckets[1].mDuration);
//}
//
//TEST(DurationMetricTrackerTest, TestNonSlicedCondition) {
// sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
// int64_t bucketStartTimeNs = 10000000000;
// int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
//
// DurationMetric metric;
// metric.set_id(1);
// metric.set_bucket(ONE_MINUTE);
// metric.set_aggregation_type(DurationMetric_AggregationType_SUM);
//
// int tagId = 1;
// LogEvent event1(tagId, bucketStartTimeNs + 1);
// event1.init();
// LogEvent event2(tagId, bucketStartTimeNs + 2);
// event2.init();
// LogEvent event3(tagId, bucketStartTimeNs + bucketSizeNs + 1);
// event3.init();
// LogEvent event4(tagId, bucketStartTimeNs + bucketSizeNs + 3);
// event4.init();
//
// FieldMatcher dimensions;
// DurationMetricProducer durationProducer(
// kConfigKey, metric, 0 /* condition index */, 1 /* start index */, 2 /* stop index */,
// 3 /* stop_all index */, false /*nesting*/, wizard, dimensions, bucketStartTimeNs, bucketStartTimeNs);
// durationProducer.mCondition = ConditionState::kFalse;
//
// EXPECT_FALSE(durationProducer.mCondition);
// EXPECT_FALSE(durationProducer.isConditionSliced());
//
// durationProducer.onMatchedLogEvent(1 /* start index*/, event1);
// durationProducer.onMatchedLogEvent(2 /* stop index*/, event2);
// durationProducer.flushIfNeededLocked(bucketStartTimeNs + bucketSizeNs + 1);
// EXPECT_EQ(0UL, durationProducer.mPastBuckets.size());
//
// durationProducer.onMatchedLogEvent(1 /* start index*/, event3);
// durationProducer.onConditionChanged(true /* condition */, bucketStartTimeNs + bucketSizeNs + 2);
// durationProducer.onMatchedLogEvent(2 /* stop index*/, event4);
// durationProducer.flushIfNeededLocked(bucketStartTimeNs + 2 * bucketSizeNs + 1);
// EXPECT_EQ(1UL, durationProducer.mPastBuckets.size());
// EXPECT_TRUE(durationProducer.mPastBuckets.find(DEFAULT_METRIC_DIMENSION_KEY) !=
// durationProducer.mPastBuckets.end());
// const auto& buckets2 = durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY];
// EXPECT_EQ(1UL, buckets2.size());
// EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, buckets2[0].mBucketStartNs);
// EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs, buckets2[0].mBucketEndNs);
// EXPECT_EQ(1LL, buckets2[0].mDuration);
//}
//
//TEST(DurationMetricTrackerTest, TestNonSlicedConditionUnknownState) {
// sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
// int64_t bucketStartTimeNs = 10000000000;
// int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
//
// DurationMetric metric;
// metric.set_id(1);
// metric.set_bucket(ONE_MINUTE);
// metric.set_aggregation_type(DurationMetric_AggregationType_SUM);
//
// int tagId = 1;
// LogEvent event1(tagId, bucketStartTimeNs + 1);
// event1.init();
// LogEvent event2(tagId, bucketStartTimeNs + 2);
// event2.init();
// LogEvent event3(tagId, bucketStartTimeNs + bucketSizeNs + 1);
// event3.init();
// LogEvent event4(tagId, bucketStartTimeNs + bucketSizeNs + 3);
// event4.init();
//
// FieldMatcher dimensions;
// DurationMetricProducer durationProducer(
// kConfigKey, metric, 0 /* condition index */, 1 /* start index */, 2 /* stop index */,
// 3 /* stop_all index */, false /*nesting*/, wizard, dimensions, bucketStartTimeNs, bucketStartTimeNs);
//
// EXPECT_EQ(ConditionState::kUnknown, durationProducer.mCondition);
// EXPECT_FALSE(durationProducer.isConditionSliced());
//
// durationProducer.onMatchedLogEvent(1 /* start index*/, event1);
// durationProducer.onMatchedLogEvent(2 /* stop index*/, event2);
// durationProducer.flushIfNeededLocked(bucketStartTimeNs + bucketSizeNs + 1);
// EXPECT_EQ(0UL, durationProducer.mPastBuckets.size());
//
// durationProducer.onMatchedLogEvent(1 /* start index*/, event3);
// durationProducer.onConditionChanged(true /* condition */, bucketStartTimeNs + bucketSizeNs + 2);
// durationProducer.onMatchedLogEvent(2 /* stop index*/, event4);
// durationProducer.flushIfNeededLocked(bucketStartTimeNs + 2 * bucketSizeNs + 1);
// EXPECT_EQ(1UL, durationProducer.mPastBuckets.size());
// const auto& buckets2 = durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY];
// EXPECT_EQ(1UL, buckets2.size());
// EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, buckets2[0].mBucketStartNs);
// EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs, buckets2[0].mBucketEndNs);
// EXPECT_EQ(1LL, buckets2[0].mDuration);
//}
//
//TEST(DurationMetricTrackerTest, TestSumDurationWithUpgrade) {
// /**
// * The duration starts from the first bucket, through the two partial buckets (10-70sec),
// * another bucket, and ends at the beginning of the next full bucket.
// * Expected buckets:
// * - [10,25]: 14 secs
// * - [25,70]: All 45 secs
// * - [70,130]: All 60 secs
// * - [130, 210]: Only 5 secs (event ended at 135sec)
// */
// int64_t bucketStartTimeNs = 10000000000;
// int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
// int64_t eventUpgradeTimeNs = bucketStartTimeNs + 15 * NS_PER_SEC;
// int64_t startTimeNs = bucketStartTimeNs + 1 * NS_PER_SEC;
// int64_t endTimeNs = startTimeNs + 125 * NS_PER_SEC;
//
// int tagId = 1;
//
// DurationMetric metric;
// metric.set_id(1);
// metric.set_bucket(ONE_MINUTE);
// metric.set_aggregation_type(DurationMetric_AggregationType_SUM);
// sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
// FieldMatcher dimensions;
// DurationMetricProducer durationProducer(
// kConfigKey, metric, -1 /* no condition */, 1 /* start index */, 2 /* stop index */,
// 3 /* stop_all index */, false /*nesting*/, wizard, dimensions, bucketStartTimeNs, bucketStartTimeNs);
//
// LogEvent start_event(tagId, startTimeNs);
// start_event.init();
// durationProducer.onMatchedLogEvent(1 /* start index*/, start_event);
// EXPECT_EQ(0UL, durationProducer.mPastBuckets.size());
// EXPECT_EQ(bucketStartTimeNs, durationProducer.mCurrentBucketStartTimeNs);
//
// durationProducer.notifyAppUpgrade(eventUpgradeTimeNs, "ANY.APP", 1, 1);
// EXPECT_EQ(1UL, durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
// std::vector<DurationBucket> buckets =
// durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY];
// EXPECT_EQ(bucketStartTimeNs, buckets[0].mBucketStartNs);
// EXPECT_EQ(eventUpgradeTimeNs, buckets[0].mBucketEndNs);
// EXPECT_EQ(eventUpgradeTimeNs - startTimeNs, buckets[0].mDuration);
// EXPECT_EQ(eventUpgradeTimeNs, durationProducer.mCurrentBucketStartTimeNs);
//
// // We skip ahead one bucket, so we fill in the first two partial buckets and one full bucket.
// LogEvent end_event(tagId, endTimeNs);
// end_event.init();
// durationProducer.onMatchedLogEvent(2 /* stop index*/, end_event);
// buckets = durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY];
// EXPECT_EQ(3UL, buckets.size());
// EXPECT_EQ(eventUpgradeTimeNs, buckets[1].mBucketStartNs);
// EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, buckets[1].mBucketEndNs);
// EXPECT_EQ(bucketStartTimeNs + bucketSizeNs - eventUpgradeTimeNs, buckets[1].mDuration);
// EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, buckets[2].mBucketStartNs);
// EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs, buckets[2].mBucketEndNs);
// EXPECT_EQ(bucketSizeNs, buckets[2].mDuration);
//}
//
//TEST(DurationMetricTrackerTest, TestSumDurationWithUpgradeInFollowingBucket) {
// /**
// * Expected buckets (start at 11s, upgrade at 75s, end at 135s):
// * - [10,70]: 59 secs
// * - [70,75]: 5 sec
// * - [75,130]: 55 secs
// */
// int64_t bucketStartTimeNs = 10000000000;
// int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
// int64_t eventUpgradeTimeNs = bucketStartTimeNs + 65 * NS_PER_SEC;
// int64_t startTimeNs = bucketStartTimeNs + 1 * NS_PER_SEC;
// int64_t endTimeNs = startTimeNs + 125 * NS_PER_SEC;
//
// int tagId = 1;
//
// DurationMetric metric;
// metric.set_id(1);
// metric.set_bucket(ONE_MINUTE);
// metric.set_aggregation_type(DurationMetric_AggregationType_SUM);
// sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
// FieldMatcher dimensions;
// DurationMetricProducer durationProducer(
// kConfigKey, metric, -1 /* no condition */, 1 /* start index */, 2 /* stop index */,
// 3 /* stop_all index */, false /*nesting*/, wizard, dimensions, bucketStartTimeNs, bucketStartTimeNs);
//
// LogEvent start_event(tagId, startTimeNs);
// start_event.init();
// durationProducer.onMatchedLogEvent(1 /* start index*/, start_event);
// EXPECT_EQ(0UL, durationProducer.mPastBuckets.size());
// EXPECT_EQ(bucketStartTimeNs, durationProducer.mCurrentBucketStartTimeNs);
//
// durationProducer.notifyAppUpgrade(eventUpgradeTimeNs, "ANY.APP", 1, 1);
// EXPECT_EQ(2UL, durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
// std::vector<DurationBucket> buckets =
// durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY];
// EXPECT_EQ(bucketStartTimeNs, buckets[0].mBucketStartNs);
// EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, buckets[0].mBucketEndNs);
// EXPECT_EQ(bucketStartTimeNs + bucketSizeNs - startTimeNs, buckets[0].mDuration);
// EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, buckets[1].mBucketStartNs);
// EXPECT_EQ(eventUpgradeTimeNs, buckets[1].mBucketEndNs);
// EXPECT_EQ(eventUpgradeTimeNs - (bucketStartTimeNs + bucketSizeNs), buckets[1].mDuration);
// EXPECT_EQ(eventUpgradeTimeNs, durationProducer.mCurrentBucketStartTimeNs);
//
// // We skip ahead one bucket, so we fill in the first two partial buckets and one full bucket.
// LogEvent end_event(tagId, endTimeNs);
// end_event.init();
// durationProducer.onMatchedLogEvent(2 /* stop index*/, end_event);
// buckets = durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY];
// EXPECT_EQ(3UL, buckets.size());
// EXPECT_EQ(eventUpgradeTimeNs, buckets[2].mBucketStartNs);
// EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs, buckets[2].mBucketEndNs);
// EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs - eventUpgradeTimeNs, buckets[2].mDuration);
//}
//
//TEST(DurationMetricTrackerTest, TestSumDurationAnomalyWithUpgrade) {
// sp<AlarmMonitor> alarmMonitor;
// int64_t bucketStartTimeNs = 10000000000;
// int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
// int64_t eventUpgradeTimeNs = bucketStartTimeNs + 15 * NS_PER_SEC;
// int64_t startTimeNs = bucketStartTimeNs + 1;
// int64_t endTimeNs = startTimeNs + 65 * NS_PER_SEC;
//
// int tagId = 1;
//
// // Setup metric with alert.
// DurationMetric metric;
// metric.set_id(1);
// metric.set_bucket(ONE_MINUTE);
// metric.set_aggregation_type(DurationMetric_AggregationType_SUM);
// Alert alert;
// alert.set_num_buckets(3);
// alert.set_trigger_if_sum_gt(2);
//
// sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
// FieldMatcher dimensions;
// DurationMetricProducer durationProducer(
// kConfigKey, metric, -1 /* no condition */, 1 /* start index */, 2 /* stop index */,
// 3 /* stop_all index */, false /*nesting*/, wizard, dimensions, bucketStartTimeNs, bucketStartTimeNs);
//
// sp<AnomalyTracker> anomalyTracker = durationProducer.addAnomalyTracker(alert, alarmMonitor);
// EXPECT_TRUE(anomalyTracker != nullptr);
//
// LogEvent start_event(tagId, startTimeNs);
// start_event.init();
// durationProducer.onMatchedLogEvent(1 /* start index*/, start_event);
// durationProducer.notifyAppUpgrade(eventUpgradeTimeNs, "ANY.APP", 1, 1);
// // We skip ahead one bucket, so we fill in the first two partial buckets and one full bucket.
// LogEvent end_event(tagId, endTimeNs);
// end_event.init();
// durationProducer.onMatchedLogEvent(2 /* stop index*/, end_event);
//
// EXPECT_EQ(bucketStartTimeNs + bucketSizeNs - startTimeNs,
// anomalyTracker->getSumOverPastBuckets(DEFAULT_METRIC_DIMENSION_KEY));
//}
//
//TEST(DurationMetricTrackerTest, TestMaxDurationWithUpgrade) {
// int64_t bucketStartTimeNs = 10000000000;
// int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
// int64_t eventUpgradeTimeNs = bucketStartTimeNs + 15 * NS_PER_SEC;
// int64_t startTimeNs = bucketStartTimeNs + 1;
// int64_t endTimeNs = startTimeNs + 125 * NS_PER_SEC;
//
// int tagId = 1;
//
// DurationMetric metric;
// metric.set_id(1);
// metric.set_bucket(ONE_MINUTE);
// metric.set_aggregation_type(DurationMetric_AggregationType_MAX_SPARSE);
// LogEvent event1(tagId, startTimeNs);
// event1.write("111"); // uid
// event1.init();
// sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
// FieldMatcher dimensions;
// DurationMetricProducer durationProducer(
// kConfigKey, metric, -1 /* no condition */, 1 /* start index */, 2 /* stop index */,
// 3 /* stop_all index */, false /*nesting*/, wizard, dimensions, bucketStartTimeNs, bucketStartTimeNs);
//
// LogEvent start_event(tagId, startTimeNs);
// start_event.init();
// durationProducer.onMatchedLogEvent(1 /* start index*/, start_event);
// EXPECT_EQ(0UL, durationProducer.mPastBuckets.size());
// EXPECT_EQ(bucketStartTimeNs, durationProducer.mCurrentBucketStartTimeNs);
//
// durationProducer.notifyAppUpgrade(eventUpgradeTimeNs, "ANY.APP", 1, 1);
// EXPECT_EQ(0UL, durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
// EXPECT_EQ(eventUpgradeTimeNs, durationProducer.mCurrentBucketStartTimeNs);
//
// // We skip ahead one bucket, so we fill in the first two partial buckets and one full bucket.
// LogEvent end_event(tagId, endTimeNs);
// end_event.init();
// durationProducer.onMatchedLogEvent(2 /* stop index*/, end_event);
// EXPECT_EQ(0UL, durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
//
// durationProducer.flushIfNeededLocked(bucketStartTimeNs + 3 * bucketSizeNs + 1);
// std::vector<DurationBucket> buckets =
// durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY];
// EXPECT_EQ(1UL, buckets.size());
// EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs, buckets[0].mBucketStartNs);
// EXPECT_EQ(bucketStartTimeNs + 3 * bucketSizeNs, buckets[0].mBucketEndNs);
// EXPECT_EQ(endTimeNs - startTimeNs, buckets[0].mDuration);
//}
//
//TEST(DurationMetricTrackerTest, TestMaxDurationWithUpgradeInNextBucket) {
// int64_t bucketStartTimeNs = 10000000000;
// int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
// int64_t eventUpgradeTimeNs = bucketStartTimeNs + 65 * NS_PER_SEC;
// int64_t startTimeNs = bucketStartTimeNs + 1;
// int64_t endTimeNs = startTimeNs + 115 * NS_PER_SEC;
//
// int tagId = 1;
//
// DurationMetric metric;
// metric.set_id(1);
// metric.set_bucket(ONE_MINUTE);
// metric.set_aggregation_type(DurationMetric_AggregationType_MAX_SPARSE);
// LogEvent event1(tagId, startTimeNs);
// event1.write("111"); // uid
// event1.init();
// sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
// FieldMatcher dimensions;
// DurationMetricProducer durationProducer(
// kConfigKey, metric, -1 /* no condition */, 1 /* start index */, 2 /* stop index */,
// 3 /* stop_all index */, false /*nesting*/, wizard, dimensions, bucketStartTimeNs, bucketStartTimeNs);
//
// LogEvent start_event(tagId, startTimeNs);
// start_event.init();
// durationProducer.onMatchedLogEvent(1 /* start index*/, start_event);
// EXPECT_EQ(0UL, durationProducer.mPastBuckets.size());
// EXPECT_EQ(bucketStartTimeNs, durationProducer.mCurrentBucketStartTimeNs);
//
// durationProducer.notifyAppUpgrade(eventUpgradeTimeNs, "ANY.APP", 1, 1);
// EXPECT_EQ(0UL, durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
// EXPECT_EQ(eventUpgradeTimeNs, durationProducer.mCurrentBucketStartTimeNs);
//
// // Stop occurs in the same partial bucket as created for the app upgrade.
// LogEvent end_event(tagId, endTimeNs);
// end_event.init();
// durationProducer.onMatchedLogEvent(2 /* stop index*/, end_event);
// EXPECT_EQ(0UL, durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
// EXPECT_EQ(eventUpgradeTimeNs, durationProducer.mCurrentBucketStartTimeNs);
//
// durationProducer.flushIfNeededLocked(bucketStartTimeNs + 2 * bucketSizeNs + 1);
// std::vector<DurationBucket> buckets =
// durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY];
// EXPECT_EQ(1UL, buckets.size());
// EXPECT_EQ(eventUpgradeTimeNs, buckets[0].mBucketStartNs);
// EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs, buckets[0].mBucketEndNs);
// EXPECT_EQ(endTimeNs - startTimeNs, buckets[0].mDuration);
//}
} // namespace statsd
} // namespace os

View File

@@ -85,46 +85,47 @@ TEST(EventMetricProducerTest, TestEventsWithNonSlicedCondition) {
// eventProducer.onDumpReport();
}
TEST(EventMetricProducerTest, TestEventsWithSlicedCondition) {
int64_t bucketStartTimeNs = 10000000000;
int64_t bucketSizeNs = 30 * 1000 * 1000 * 1000LL;
int tagId = 1;
int conditionTagId = 2;
EventMetric metric;
metric.set_id(1);
metric.set_condition(StringToId("APP_IN_BACKGROUND_PER_UID_AND_SCREEN_ON"));
MetricConditionLink* link = metric.add_links();
link->set_condition(StringToId("APP_IN_BACKGROUND_PER_UID"));
buildSimpleAtomFieldMatcher(tagId, 1, link->mutable_fields_in_what());
buildSimpleAtomFieldMatcher(conditionTagId, 2, link->mutable_fields_in_condition());
LogEvent event1(tagId, bucketStartTimeNs + 1);
EXPECT_TRUE(event1.write("111"));
event1.init();
ConditionKey key1;
key1[StringToId("APP_IN_BACKGROUND_PER_UID")] = {getMockedDimensionKey(conditionTagId, 2, "111")};
LogEvent event2(tagId, bucketStartTimeNs + 10);
EXPECT_TRUE(event2.write("222"));
event2.init();
ConditionKey key2;
key2[StringToId("APP_IN_BACKGROUND_PER_UID")] = {getMockedDimensionKey(conditionTagId, 2, "222")};
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
EXPECT_CALL(*wizard, query(_, key1, _)).WillOnce(Return(ConditionState::kFalse));
EXPECT_CALL(*wizard, query(_, key2, _)).WillOnce(Return(ConditionState::kTrue));
EventMetricProducer eventProducer(kConfigKey, metric, 1, wizard, bucketStartTimeNs);
eventProducer.onMatchedLogEvent(1 /*matcher index*/, event1);
eventProducer.onMatchedLogEvent(1 /*matcher index*/, event2);
// TODO: get the report and check the content after the ProtoOutputStream change is done.
// eventProducer.onDumpReport();
}
// TODO(b/149590301): Update this test to use new socket schema.
//TEST(EventMetricProducerTest, TestEventsWithSlicedCondition) {
// int64_t bucketStartTimeNs = 10000000000;
// int64_t bucketSizeNs = 30 * 1000 * 1000 * 1000LL;
//
// int tagId = 1;
// int conditionTagId = 2;
//
// EventMetric metric;
// metric.set_id(1);
// metric.set_condition(StringToId("APP_IN_BACKGROUND_PER_UID_AND_SCREEN_ON"));
// MetricConditionLink* link = metric.add_links();
// link->set_condition(StringToId("APP_IN_BACKGROUND_PER_UID"));
// buildSimpleAtomFieldMatcher(tagId, 1, link->mutable_fields_in_what());
// buildSimpleAtomFieldMatcher(conditionTagId, 2, link->mutable_fields_in_condition());
//
// LogEvent event1(tagId, bucketStartTimeNs + 1);
// EXPECT_TRUE(event1.write("111"));
// event1.init();
// ConditionKey key1;
// key1[StringToId("APP_IN_BACKGROUND_PER_UID")] = {getMockedDimensionKey(conditionTagId, 2, "111")};
//
// LogEvent event2(tagId, bucketStartTimeNs + 10);
// EXPECT_TRUE(event2.write("222"));
// event2.init();
// ConditionKey key2;
// key2[StringToId("APP_IN_BACKGROUND_PER_UID")] = {getMockedDimensionKey(conditionTagId, 2, "222")};
//
// sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
// EXPECT_CALL(*wizard, query(_, key1, _)).WillOnce(Return(ConditionState::kFalse));
//
// EXPECT_CALL(*wizard, query(_, key2, _)).WillOnce(Return(ConditionState::kTrue));
//
// EventMetricProducer eventProducer(kConfigKey, metric, 1, wizard, bucketStartTimeNs);
//
// eventProducer.onMatchedLogEvent(1 /*matcher index*/, event1);
// eventProducer.onMatchedLogEvent(1 /*matcher index*/, event2);
//
// // TODO: get the report and check the content after the ProtoOutputStream change is done.
// // eventProducer.onDumpReport();
//}
} // namespace statsd
} // namespace os

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -105,29 +105,30 @@ void runShellTest(ShellSubscription config, sp<MockUidMap> uidMap,
close(fds_data[0]);
}
TEST(ShellSubscriberTest, testPushedSubscription) {
sp<MockUidMap> uidMap = new NaggyMock<MockUidMap>();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
vector<std::shared_ptr<LogEvent>> pushedList;
std::shared_ptr<LogEvent> event1 =
std::make_shared<LogEvent>(29 /*screen_state_atom_id*/, 1000 /*timestamp*/);
event1->write(::android::view::DisplayStateEnum::DISPLAY_STATE_ON);
event1->init();
pushedList.push_back(event1);
// create a simple config to get screen events
ShellSubscription config;
config.add_pushed()->set_atom_id(29);
// this is the expected screen event atom.
ShellData shellData;
shellData.add_atom()->mutable_screen_state_changed()->set_state(
::android::view::DisplayStateEnum::DISPLAY_STATE_ON);
runShellTest(config, uidMap, pullerManager, pushedList, shellData);
}
// TODO(b/149590301): Update this test to use new socket schema.
//TEST(ShellSubscriberTest, testPushedSubscription) {
// sp<MockUidMap> uidMap = new NaggyMock<MockUidMap>();
//
// sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
// vector<std::shared_ptr<LogEvent>> pushedList;
//
// std::shared_ptr<LogEvent> event1 =
// std::make_shared<LogEvent>(29 /*screen_state_atom_id*/, 1000 /*timestamp*/);
// event1->write(::android::view::DisplayStateEnum::DISPLAY_STATE_ON);
// event1->init();
// pushedList.push_back(event1);
//
// // create a simple config to get screen events
// ShellSubscription config;
// config.add_pushed()->set_atom_id(29);
//
// // this is the expected screen event atom.
// ShellData shellData;
// shellData.add_atom()->mutable_screen_state_changed()->set_state(
// ::android::view::DisplayStateEnum::DISPLAY_STATE_ON);
//
// runShellTest(config, uidMap, pullerManager, pushedList, shellData);
//}
namespace {
@@ -160,30 +161,31 @@ ShellSubscription getPulledConfig() {
} // namespace
TEST(ShellSubscriberTest, testPulledSubscription) {
sp<MockUidMap> uidMap = new NaggyMock<MockUidMap>();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
EXPECT_CALL(*pullerManager, Pull(10016, _))
.WillRepeatedly(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
data->clear();
shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, 1111L);
event->write(kUid1);
event->write(kCpuTime1);
event->init();
data->push_back(event);
// another event
event = make_shared<LogEvent>(tagId, 1111L);
event->write(kUid2);
event->write(kCpuTime2);
event->init();
data->push_back(event);
return true;
}));
runShellTest(getPulledConfig(), uidMap, pullerManager, vector<std::shared_ptr<LogEvent>>(),
getExpectedShellData());
}
// TODO(b/149590301): Update this test to use new socket schema.
//TEST(ShellSubscriberTest, testPulledSubscription) {
// sp<MockUidMap> uidMap = new NaggyMock<MockUidMap>();
//
// sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
// EXPECT_CALL(*pullerManager, Pull(10016, _))
// .WillRepeatedly(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
// data->clear();
// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, 1111L);
// event->write(kUid1);
// event->write(kCpuTime1);
// event->init();
// data->push_back(event);
// // another event
// event = make_shared<LogEvent>(tagId, 1111L);
// event->write(kUid2);
// event->write(kCpuTime2);
// event->init();
// data->push_back(event);
// return true;
// }));
//
// runShellTest(getPulledConfig(), uidMap, pullerManager, vector<std::shared_ptr<LogEvent>>(),
// getExpectedShellData());
//}
#else
GTEST_LOG_(INFO) << "This test does nothing.\n";

View File

@@ -56,94 +56,95 @@ int getStateInt(StateManager& mgr, int atomId, const HashableDimensionKey& query
return output.mValue.int_value;
}
// START: build event functions.
// State with no primary fields - ScreenStateChanged
std::shared_ptr<LogEvent> buildScreenEvent(int state) {
std::shared_ptr<LogEvent> event =
std::make_shared<LogEvent>(android::util::SCREEN_STATE_CHANGED, 1000 /*timestamp*/);
event->write((int32_t)state);
event->init();
return event;
}
// State with one primary field - UidProcessStateChanged
std::shared_ptr<LogEvent> buildUidProcessEvent(int uid, int state) {
std::shared_ptr<LogEvent> event =
std::make_shared<LogEvent>(android::util::UID_PROCESS_STATE_CHANGED, 1000 /*timestamp*/);
event->write((int32_t)uid);
event->write((int32_t)state);
event->init();
return event;
}
// State with first uid in attribution chain as primary field - WakelockStateChanged
std::shared_ptr<LogEvent> buildPartialWakelockEvent(int uid, const std::string& tag, bool acquire) {
std::vector<AttributionNodeInternal> chain;
chain.push_back(AttributionNodeInternal());
AttributionNodeInternal& attr = chain.back();
attr.set_uid(uid);
std::shared_ptr<LogEvent> event =
std::make_shared<LogEvent>(android::util::WAKELOCK_STATE_CHANGED, 1000 /* timestamp */);
event->write(chain);
event->write((int32_t)1); // PARTIAL_WAKE_LOCK
event->write(tag);
event->write(acquire ? 1 : 0);
event->init();
return event;
}
// State with multiple primary fields - OverlayStateChanged
std::shared_ptr<LogEvent> buildOverlayEvent(int uid, const std::string& packageName, int state) {
std::shared_ptr<LogEvent> event =
std::make_shared<LogEvent>(android::util::OVERLAY_STATE_CHANGED, 1000 /*timestamp*/);
event->write((int32_t)uid);
event->write(packageName);
event->write(true); // using_alert_window
event->write((int32_t)state);
event->init();
return event;
}
// Incorrect event - missing fields
std::shared_ptr<LogEvent> buildIncorrectOverlayEvent(int uid, const std::string& packageName, int state) {
std::shared_ptr<LogEvent> event =
std::make_shared<LogEvent>(android::util::OVERLAY_STATE_CHANGED, 1000 /*timestamp*/);
event->write((int32_t)uid);
event->write(packageName);
event->write((int32_t)state);
event->init();
return event;
}
// Incorrect event - exclusive state has wrong type
std::shared_ptr<LogEvent> buildOverlayEventBadStateType(int uid, const std::string& packageName) {
std::shared_ptr<LogEvent> event =
std::make_shared<LogEvent>(android::util::OVERLAY_STATE_CHANGED, 1000 /*timestamp*/);
event->write((int32_t)uid);
event->write(packageName);
event->write(true);
event->write("string"); // exclusive state: string instead of int
event->init();
return event;
}
std::shared_ptr<LogEvent> buildBleScanEvent(int uid, bool acquire, bool reset) {
std::vector<AttributionNodeInternal> chain;
chain.push_back(AttributionNodeInternal());
AttributionNodeInternal& attr = chain.back();
attr.set_uid(uid);
std::shared_ptr<LogEvent> event =
std::make_shared<LogEvent>(android::util::BLE_SCAN_STATE_CHANGED, 1000);
event->write(chain);
event->write(reset ? 2 : acquire ? 1 : 0); // PARTIAL_WAKE_LOCK
event->write(0); // filtered
event->write(0); // first match
event->write(0); // opportunistic
event->init();
return event;
}
// TODO(b/149590301): Update these helpers to use new socket schema.
//// START: build event functions.
//// State with no primary fields - ScreenStateChanged
//std::shared_ptr<LogEvent> buildScreenEvent(int state) {
// std::shared_ptr<LogEvent> event =
// std::make_shared<LogEvent>(android::util::SCREEN_STATE_CHANGED, 1000 /*timestamp*/);
// event->write((int32_t)state);
// event->init();
// return event;
//}
//
//// State with one primary field - UidProcessStateChanged
//std::shared_ptr<LogEvent> buildUidProcessEvent(int uid, int state) {
// std::shared_ptr<LogEvent> event =
// std::make_shared<LogEvent>(android::util::UID_PROCESS_STATE_CHANGED, 1000 /*timestamp*/);
// event->write((int32_t)uid);
// event->write((int32_t)state);
// event->init();
// return event;
//}
//
//// State with first uid in attribution chain as primary field - WakelockStateChanged
//std::shared_ptr<LogEvent> buildPartialWakelockEvent(int uid, const std::string& tag, bool acquire) {
// std::vector<AttributionNodeInternal> chain;
// chain.push_back(AttributionNodeInternal());
// AttributionNodeInternal& attr = chain.back();
// attr.set_uid(uid);
//
// std::shared_ptr<LogEvent> event =
// std::make_shared<LogEvent>(android::util::WAKELOCK_STATE_CHANGED, 1000 /* timestamp */);
// event->write(chain);
// event->write((int32_t)1); // PARTIAL_WAKE_LOCK
// event->write(tag);
// event->write(acquire ? 1 : 0);
// event->init();
// return event;
//}
//
//// State with multiple primary fields - OverlayStateChanged
//std::shared_ptr<LogEvent> buildOverlayEvent(int uid, const std::string& packageName, int state) {
// std::shared_ptr<LogEvent> event =
// std::make_shared<LogEvent>(android::util::OVERLAY_STATE_CHANGED, 1000 /*timestamp*/);
// event->write((int32_t)uid);
// event->write(packageName);
// event->write(true); // using_alert_window
// event->write((int32_t)state);
// event->init();
// return event;
//}
//
//// Incorrect event - missing fields
//std::shared_ptr<LogEvent> buildIncorrectOverlayEvent(int uid, const std::string& packageName, int state) {
// std::shared_ptr<LogEvent> event =
// std::make_shared<LogEvent>(android::util::OVERLAY_STATE_CHANGED, 1000 /*timestamp*/);
// event->write((int32_t)uid);
// event->write(packageName);
// event->write((int32_t)state);
// event->init();
// return event;
//}
//
//// Incorrect event - exclusive state has wrong type
//std::shared_ptr<LogEvent> buildOverlayEventBadStateType(int uid, const std::string& packageName) {
// std::shared_ptr<LogEvent> event =
// std::make_shared<LogEvent>(android::util::OVERLAY_STATE_CHANGED, 1000 /*timestamp*/);
// event->write((int32_t)uid);
// event->write(packageName);
// event->write(true);
// event->write("string"); // exclusive state: string instead of int
// event->init();
// return event;
//}
//
//std::shared_ptr<LogEvent> buildBleScanEvent(int uid, bool acquire, bool reset) {
// std::vector<AttributionNodeInternal> chain;
// chain.push_back(AttributionNodeInternal());
// AttributionNodeInternal& attr = chain.back();
// attr.set_uid(uid);
//
// std::shared_ptr<LogEvent> event =
// std::make_shared<LogEvent>(android::util::BLE_SCAN_STATE_CHANGED, 1000);
// event->write(chain);
// event->write(reset ? 2 : acquire ? 1 : 0); // PARTIAL_WAKE_LOCK
// event->write(0); // filtered
// event->write(0); // first match
// event->write(0); // opportunistic
// event->init();
// return event;
//}
// END: build event functions.
// START: get primary key functions
@@ -292,302 +293,302 @@ TEST(StateTrackerTest, TestUnregisterListener) {
EXPECT_EQ(0, mgr.getStateTrackersCount());
EXPECT_EQ(-1, mgr.getListenersCount(android::util::SCREEN_STATE_CHANGED));
}
/**
* Test a binary state atom with nested counting.
*
* To go from an "ON" state to an "OFF" state with nested counting, we must see
* an equal number of "OFF" events as "ON" events.
* For example, ACQUIRE, ACQUIRE, RELEASE will still be in the ACQUIRE state.
* ACQUIRE, ACQUIRE, RELEASE, RELEASE will be in the RELEASE state.
*/
TEST(StateTrackerTest, TestStateChangeNested) {
sp<TestStateListener> listener = new TestStateListener();
StateManager mgr;
mgr.registerListener(android::util::WAKELOCK_STATE_CHANGED, listener);
std::shared_ptr<LogEvent> event1 =
buildPartialWakelockEvent(1000 /* uid */, "tag", true /*acquire*/);
mgr.onLogEvent(*event1);
EXPECT_EQ(1, listener->updates.size());
EXPECT_EQ(1000, listener->updates[0].mKey.getValues()[0].mValue.int_value);
EXPECT_EQ(1, listener->updates[0].mState);
listener->updates.clear();
std::shared_ptr<LogEvent> event2 =
buildPartialWakelockEvent(1000 /* uid */, "tag", true /*acquire*/);
mgr.onLogEvent(*event2);
EXPECT_EQ(0, listener->updates.size());
std::shared_ptr<LogEvent> event3 =
buildPartialWakelockEvent(1000 /* uid */, "tag", false /*release*/);
mgr.onLogEvent(*event3);
EXPECT_EQ(0, listener->updates.size());
std::shared_ptr<LogEvent> event4 =
buildPartialWakelockEvent(1000 /* uid */, "tag", false /*release*/);
mgr.onLogEvent(*event4);
EXPECT_EQ(1, listener->updates.size());
EXPECT_EQ(1000, listener->updates[0].mKey.getValues()[0].mValue.int_value);
EXPECT_EQ(0, listener->updates[0].mState);
}
/**
* Test a state atom with a reset state.
*
* If the reset state value is seen, every state in the map is set to the default
* state and every listener is notified.
*/
TEST(StateTrackerTest, TestStateChangeReset) {
sp<TestStateListener> listener = new TestStateListener();
StateManager mgr;
mgr.registerListener(android::util::BLE_SCAN_STATE_CHANGED, listener);
std::shared_ptr<LogEvent> event1 =
buildBleScanEvent(1000 /* uid */, true /*acquire*/, false /*reset*/);
mgr.onLogEvent(*event1);
EXPECT_EQ(1, listener->updates.size());
EXPECT_EQ(1000, listener->updates[0].mKey.getValues()[0].mValue.int_value);
EXPECT_EQ(BleScanStateChanged::ON, listener->updates[0].mState);
listener->updates.clear();
std::shared_ptr<LogEvent> event2 =
buildBleScanEvent(2000 /* uid */, true /*acquire*/, false /*reset*/);
mgr.onLogEvent(*event2);
EXPECT_EQ(1, listener->updates.size());
EXPECT_EQ(2000, listener->updates[0].mKey.getValues()[0].mValue.int_value);
EXPECT_EQ(BleScanStateChanged::ON, listener->updates[0].mState);
listener->updates.clear();
std::shared_ptr<LogEvent> event3 =
buildBleScanEvent(2000 /* uid */, false /*acquire*/, true /*reset*/);
mgr.onLogEvent(*event3);
EXPECT_EQ(2, listener->updates.size());
EXPECT_EQ(BleScanStateChanged::OFF, listener->updates[0].mState);
EXPECT_EQ(BleScanStateChanged::OFF, listener->updates[1].mState);
}
/**
* Test StateManager's onLogEvent and StateListener's onStateChanged correctly
* updates listener for states without primary keys.
*/
TEST(StateTrackerTest, TestStateChangeNoPrimaryFields) {
sp<TestStateListener> listener1 = new TestStateListener();
StateManager mgr;
mgr.registerListener(android::util::SCREEN_STATE_CHANGED, listener1);
// log event
std::shared_ptr<LogEvent> event =
buildScreenEvent(android::view::DisplayStateEnum::DISPLAY_STATE_ON);
mgr.onLogEvent(*event);
// check listener was updated
EXPECT_EQ(1, listener1->updates.size());
EXPECT_EQ(DEFAULT_DIMENSION_KEY, listener1->updates[0].mKey);
EXPECT_EQ(2, listener1->updates[0].mState);
// check StateTracker was updated by querying for state
HashableDimensionKey queryKey = DEFAULT_DIMENSION_KEY;
EXPECT_EQ(android::view::DisplayStateEnum::DISPLAY_STATE_ON,
getStateInt(mgr, android::util::SCREEN_STATE_CHANGED, queryKey));
}
/**
* Test StateManager's onLogEvent and StateListener's onStateChanged correctly
* updates listener for states with one primary key.
*/
TEST(StateTrackerTest, TestStateChangeOnePrimaryField) {
sp<TestStateListener> listener1 = new TestStateListener();
StateManager mgr;
mgr.registerListener(android::util::UID_PROCESS_STATE_CHANGED, listener1);
// log event
std::shared_ptr<LogEvent> event =
buildUidProcessEvent(1000 /* uid */, android::app::ProcessStateEnum::PROCESS_STATE_TOP);
mgr.onLogEvent(*event);
// check listener was updated
EXPECT_EQ(1, listener1->updates.size());
EXPECT_EQ(1000, listener1->updates[0].mKey.getValues()[0].mValue.int_value);
EXPECT_EQ(1002, listener1->updates[0].mState);
// check StateTracker was updated by querying for state
HashableDimensionKey queryKey;
getUidProcessKey(1000 /* uid */, &queryKey);
EXPECT_EQ(android::app::ProcessStateEnum::PROCESS_STATE_TOP,
getStateInt(mgr, android::util::UID_PROCESS_STATE_CHANGED, queryKey));
}
TEST(StateTrackerTest, TestStateChangePrimaryFieldAttrChain) {
sp<TestStateListener> listener1 = new TestStateListener();
StateManager mgr;
mgr.registerListener(android::util::WAKELOCK_STATE_CHANGED, listener1);
// Log event.
std::shared_ptr<LogEvent> event =
buildPartialWakelockEvent(1001 /* uid */, "tag1", true /* acquire */);
mgr.onLogEvent(*event);
EXPECT_EQ(1, mgr.getStateTrackersCount());
EXPECT_EQ(1, mgr.getListenersCount(android::util::WAKELOCK_STATE_CHANGED));
// Check listener was updated.
EXPECT_EQ(1, listener1->updates.size());
EXPECT_EQ(3, listener1->updates[0].mKey.getValues().size());
EXPECT_EQ(1001, listener1->updates[0].mKey.getValues()[0].mValue.int_value);
EXPECT_EQ(1, listener1->updates[0].mKey.getValues()[1].mValue.int_value);
EXPECT_EQ("tag1", listener1->updates[0].mKey.getValues()[2].mValue.str_value);
EXPECT_EQ(WakelockStateChanged::ACQUIRE, listener1->updates[0].mState);
// Check StateTracker was updated by querying for state.
HashableDimensionKey queryKey;
getPartialWakelockKey(1001 /* uid */, "tag1", &queryKey);
EXPECT_EQ(WakelockStateChanged::ACQUIRE,
getStateInt(mgr, android::util::WAKELOCK_STATE_CHANGED, queryKey));
// No state stored for this query key.
HashableDimensionKey queryKey2;
getPartialWakelockKey(1002 /* uid */, "tag1", &queryKey2);
EXPECT_EQ(WakelockStateChanged::RELEASE,
getStateInt(mgr, android::util::WAKELOCK_STATE_CHANGED, queryKey2));
// Partial query fails.
HashableDimensionKey queryKey3;
getPartialWakelockKey(1001 /* uid */, &queryKey3);
EXPECT_EQ(WakelockStateChanged::RELEASE,
getStateInt(mgr, android::util::WAKELOCK_STATE_CHANGED, queryKey3));
}
/**
* Test StateManager's onLogEvent and StateListener's onStateChanged correctly
* updates listener for states with multiple primary keys.
*/
TEST(StateTrackerTest, TestStateChangeMultiplePrimaryFields) {
sp<TestStateListener> listener1 = new TestStateListener();
StateManager mgr;
mgr.registerListener(android::util::OVERLAY_STATE_CHANGED, listener1);
// log event
std::shared_ptr<LogEvent> event =
buildOverlayEvent(1000 /* uid */, "package1", 1); // state: ENTERED
mgr.onLogEvent(*event);
// check listener was updated
EXPECT_EQ(1, listener1->updates.size());
EXPECT_EQ(1000, listener1->updates[0].mKey.getValues()[0].mValue.int_value);
EXPECT_EQ(1, listener1->updates[0].mState);
// check StateTracker was updated by querying for state
HashableDimensionKey queryKey;
getOverlayKey(1000 /* uid */, "package1", &queryKey);
EXPECT_EQ(OverlayStateChanged::ENTERED,
getStateInt(mgr, android::util::OVERLAY_STATE_CHANGED, queryKey));
}
/**
* Test StateManager's onLogEvent and StateListener's onStateChanged
* when there is an error extracting state from log event. Listener is not
* updated of state change.
*/
TEST(StateTrackerTest, TestStateChangeEventError) {
sp<TestStateListener> listener1 = new TestStateListener();
StateManager mgr;
mgr.registerListener(android::util::OVERLAY_STATE_CHANGED, listener1);
// log event
std::shared_ptr<LogEvent> event1 =
buildIncorrectOverlayEvent(1000 /* uid */, "package1", 1 /* state */);
std::shared_ptr<LogEvent> event2 = buildOverlayEventBadStateType(1001 /* uid */, "package2");
// check listener was updated
mgr.onLogEvent(*event1);
EXPECT_EQ(0, listener1->updates.size());
mgr.onLogEvent(*event2);
EXPECT_EQ(0, listener1->updates.size());
}
TEST(StateTrackerTest, TestStateQuery) {
sp<TestStateListener> listener1 = new TestStateListener();
sp<TestStateListener> listener2 = new TestStateListener();
sp<TestStateListener> listener3 = new TestStateListener();
sp<TestStateListener> listener4 = new TestStateListener();
StateManager mgr;
mgr.registerListener(android::util::SCREEN_STATE_CHANGED, listener1);
mgr.registerListener(android::util::UID_PROCESS_STATE_CHANGED, listener2);
mgr.registerListener(android::util::OVERLAY_STATE_CHANGED, listener3);
mgr.registerListener(android::util::WAKELOCK_STATE_CHANGED, listener4);
std::shared_ptr<LogEvent> event1 = buildUidProcessEvent(
1000,
android::app::ProcessStateEnum::PROCESS_STATE_TOP); // state value: 1002
std::shared_ptr<LogEvent> event2 = buildUidProcessEvent(
1001,
android::app::ProcessStateEnum::PROCESS_STATE_FOREGROUND_SERVICE); // state value:
// 1003
std::shared_ptr<LogEvent> event3 = buildUidProcessEvent(
1002,
android::app::ProcessStateEnum::PROCESS_STATE_PERSISTENT); // state value: 1000
std::shared_ptr<LogEvent> event4 = buildUidProcessEvent(
1001,
android::app::ProcessStateEnum::PROCESS_STATE_TOP); // state value: 1002
std::shared_ptr<LogEvent> event5 =
buildScreenEvent(android::view::DisplayStateEnum::DISPLAY_STATE_ON);
std::shared_ptr<LogEvent> event6 =
buildOverlayEvent(1000, "package1", OverlayStateChanged::ENTERED);
std::shared_ptr<LogEvent> event7 =
buildOverlayEvent(1000, "package2", OverlayStateChanged::EXITED);
std::shared_ptr<LogEvent> event8 = buildPartialWakelockEvent(1005, "tag1", true);
std::shared_ptr<LogEvent> event9 = buildPartialWakelockEvent(1005, "tag2", false);
mgr.onLogEvent(*event1);
mgr.onLogEvent(*event2);
mgr.onLogEvent(*event3);
mgr.onLogEvent(*event5);
mgr.onLogEvent(*event5);
mgr.onLogEvent(*event6);
mgr.onLogEvent(*event7);
mgr.onLogEvent(*event8);
mgr.onLogEvent(*event9);
// Query for UidProcessState of uid 1001
HashableDimensionKey queryKey1;
getUidProcessKey(1001, &queryKey1);
EXPECT_EQ(android::app::ProcessStateEnum::PROCESS_STATE_FOREGROUND_SERVICE,
getStateInt(mgr, android::util::UID_PROCESS_STATE_CHANGED, queryKey1));
// Query for UidProcessState of uid 1004 - not in state map
HashableDimensionKey queryKey2;
getUidProcessKey(1004, &queryKey2);
EXPECT_EQ(-1, getStateInt(mgr, android::util::UID_PROCESS_STATE_CHANGED,
queryKey2)); // default state
// Query for UidProcessState of uid 1001 - after change in state
mgr.onLogEvent(*event4);
EXPECT_EQ(android::app::ProcessStateEnum::PROCESS_STATE_TOP,
getStateInt(mgr, android::util::UID_PROCESS_STATE_CHANGED, queryKey1));
// Query for ScreenState
EXPECT_EQ(android::view::DisplayStateEnum::DISPLAY_STATE_ON,
getStateInt(mgr, android::util::SCREEN_STATE_CHANGED, DEFAULT_DIMENSION_KEY));
// Query for OverlayState of uid 1000, package name "package2"
HashableDimensionKey queryKey3;
getOverlayKey(1000, "package2", &queryKey3);
EXPECT_EQ(OverlayStateChanged::EXITED,
getStateInt(mgr, android::util::OVERLAY_STATE_CHANGED, queryKey3));
// Query for WakelockState of uid 1005, tag 2
HashableDimensionKey queryKey4;
getPartialWakelockKey(1005, "tag2", &queryKey4);
EXPECT_EQ(WakelockStateChanged::RELEASE,
getStateInt(mgr, android::util::WAKELOCK_STATE_CHANGED, queryKey4));
// Query for WakelockState of uid 1005, tag 1
HashableDimensionKey queryKey5;
getPartialWakelockKey(1005, "tag1", &queryKey5);
EXPECT_EQ(WakelockStateChanged::ACQUIRE,
getStateInt(mgr, android::util::WAKELOCK_STATE_CHANGED, queryKey5));
}
// TODO(b/149590301): Update these tests to use new socket schema.
///**
// * Test a binary state atom with nested counting.
// *
// * To go from an "ON" state to an "OFF" state with nested counting, we must see
// * an equal number of "OFF" events as "ON" events.
// * For example, ACQUIRE, ACQUIRE, RELEASE will still be in the ACQUIRE state.
// * ACQUIRE, ACQUIRE, RELEASE, RELEASE will be in the RELEASE state.
// */
//TEST(StateTrackerTest, TestStateChangeNested) {
// sp<TestStateListener> listener = new TestStateListener();
// StateManager mgr;
// mgr.registerListener(android::util::WAKELOCK_STATE_CHANGED, listener);
//
// std::shared_ptr<LogEvent> event1 =
// buildPartialWakelockEvent(1000 /* uid */, "tag", true /*acquire*/);
// mgr.onLogEvent(*event1);
// EXPECT_EQ(1, listener->updates.size());
// EXPECT_EQ(1000, listener->updates[0].mKey.getValues()[0].mValue.int_value);
// EXPECT_EQ(1, listener->updates[0].mState);
// listener->updates.clear();
//
// std::shared_ptr<LogEvent> event2 =
// buildPartialWakelockEvent(1000 /* uid */, "tag", true /*acquire*/);
// mgr.onLogEvent(*event2);
// EXPECT_EQ(0, listener->updates.size());
//
// std::shared_ptr<LogEvent> event3 =
// buildPartialWakelockEvent(1000 /* uid */, "tag", false /*release*/);
// mgr.onLogEvent(*event3);
// EXPECT_EQ(0, listener->updates.size());
//
// std::shared_ptr<LogEvent> event4 =
// buildPartialWakelockEvent(1000 /* uid */, "tag", false /*release*/);
// mgr.onLogEvent(*event4);
// EXPECT_EQ(1, listener->updates.size());
// EXPECT_EQ(1000, listener->updates[0].mKey.getValues()[0].mValue.int_value);
// EXPECT_EQ(0, listener->updates[0].mState);
//}
//
///**
// * Test a state atom with a reset state.
// *
// * If the reset state value is seen, every state in the map is set to the default
// * state and every listener is notified.
// */
//TEST(StateTrackerTest, TestStateChangeReset) {
// sp<TestStateListener> listener = new TestStateListener();
// StateManager mgr;
// mgr.registerListener(android::util::BLE_SCAN_STATE_CHANGED, listener);
//
// std::shared_ptr<LogEvent> event1 =
// buildBleScanEvent(1000 /* uid */, true /*acquire*/, false /*reset*/);
// mgr.onLogEvent(*event1);
// EXPECT_EQ(1, listener->updates.size());
// EXPECT_EQ(1000, listener->updates[0].mKey.getValues()[0].mValue.int_value);
// EXPECT_EQ(BleScanStateChanged::ON, listener->updates[0].mState);
// listener->updates.clear();
//
// std::shared_ptr<LogEvent> event2 =
// buildBleScanEvent(2000 /* uid */, true /*acquire*/, false /*reset*/);
// mgr.onLogEvent(*event2);
// EXPECT_EQ(1, listener->updates.size());
// EXPECT_EQ(2000, listener->updates[0].mKey.getValues()[0].mValue.int_value);
// EXPECT_EQ(BleScanStateChanged::ON, listener->updates[0].mState);
// listener->updates.clear();
//
// std::shared_ptr<LogEvent> event3 =
// buildBleScanEvent(2000 /* uid */, false /*acquire*/, true /*reset*/);
// mgr.onLogEvent(*event3);
// EXPECT_EQ(2, listener->updates.size());
// EXPECT_EQ(BleScanStateChanged::OFF, listener->updates[0].mState);
// EXPECT_EQ(BleScanStateChanged::OFF, listener->updates[1].mState);
//}
//
///**
// * Test StateManager's onLogEvent and StateListener's onStateChanged correctly
// * updates listener for states without primary keys.
// */
//TEST(StateTrackerTest, TestStateChangeNoPrimaryFields) {
// sp<TestStateListener> listener1 = new TestStateListener();
// StateManager mgr;
// mgr.registerListener(android::util::SCREEN_STATE_CHANGED, listener1);
//
// // log event
// std::shared_ptr<LogEvent> event =
// buildScreenEvent(android::view::DisplayStateEnum::DISPLAY_STATE_ON);
// mgr.onLogEvent(*event);
//
// // check listener was updated
// EXPECT_EQ(1, listener1->updates.size());
// EXPECT_EQ(DEFAULT_DIMENSION_KEY, listener1->updates[0].mKey);
// EXPECT_EQ(2, listener1->updates[0].mState);
//
// // check StateTracker was updated by querying for state
// HashableDimensionKey queryKey = DEFAULT_DIMENSION_KEY;
// EXPECT_EQ(android::view::DisplayStateEnum::DISPLAY_STATE_ON,
// getStateInt(mgr, android::util::SCREEN_STATE_CHANGED, queryKey));
//}
//
///**
// * Test StateManager's onLogEvent and StateListener's onStateChanged correctly
// * updates listener for states with one primary key.
// */
//TEST(StateTrackerTest, TestStateChangeOnePrimaryField) {
// sp<TestStateListener> listener1 = new TestStateListener();
// StateManager mgr;
// mgr.registerListener(android::util::UID_PROCESS_STATE_CHANGED, listener1);
//
// // log event
// std::shared_ptr<LogEvent> event =
// buildUidProcessEvent(1000 /* uid */, android::app::ProcessStateEnum::PROCESS_STATE_TOP);
// mgr.onLogEvent(*event);
//
// // check listener was updated
// EXPECT_EQ(1, listener1->updates.size());
// EXPECT_EQ(1000, listener1->updates[0].mKey.getValues()[0].mValue.int_value);
// EXPECT_EQ(1002, listener1->updates[0].mState);
//
// // check StateTracker was updated by querying for state
// HashableDimensionKey queryKey;
// getUidProcessKey(1000 /* uid */, &queryKey);
// EXPECT_EQ(android::app::ProcessStateEnum::PROCESS_STATE_TOP,
// getStateInt(mgr, android::util::UID_PROCESS_STATE_CHANGED, queryKey));
//}
//
//TEST(StateTrackerTest, TestStateChangePrimaryFieldAttrChain) {
// sp<TestStateListener> listener1 = new TestStateListener();
// StateManager mgr;
// mgr.registerListener(android::util::WAKELOCK_STATE_CHANGED, listener1);
//
// // Log event.
// std::shared_ptr<LogEvent> event =
// buildPartialWakelockEvent(1001 /* uid */, "tag1", true /* acquire */);
// mgr.onLogEvent(*event);
//
// EXPECT_EQ(1, mgr.getStateTrackersCount());
// EXPECT_EQ(1, mgr.getListenersCount(android::util::WAKELOCK_STATE_CHANGED));
//
// // Check listener was updated.
// EXPECT_EQ(1, listener1->updates.size());
// EXPECT_EQ(3, listener1->updates[0].mKey.getValues().size());
// EXPECT_EQ(1001, listener1->updates[0].mKey.getValues()[0].mValue.int_value);
// EXPECT_EQ(1, listener1->updates[0].mKey.getValues()[1].mValue.int_value);
// EXPECT_EQ("tag1", listener1->updates[0].mKey.getValues()[2].mValue.str_value);
// EXPECT_EQ(WakelockStateChanged::ACQUIRE, listener1->updates[0].mState);
//
// // Check StateTracker was updated by querying for state.
// HashableDimensionKey queryKey;
// getPartialWakelockKey(1001 /* uid */, "tag1", &queryKey);
// EXPECT_EQ(WakelockStateChanged::ACQUIRE,
// getStateInt(mgr, android::util::WAKELOCK_STATE_CHANGED, queryKey));
//
// // No state stored for this query key.
// HashableDimensionKey queryKey2;
// getPartialWakelockKey(1002 /* uid */, "tag1", &queryKey2);
// EXPECT_EQ(WakelockStateChanged::RELEASE,
// getStateInt(mgr, android::util::WAKELOCK_STATE_CHANGED, queryKey2));
//
// // Partial query fails.
// HashableDimensionKey queryKey3;
// getPartialWakelockKey(1001 /* uid */, &queryKey3);
// EXPECT_EQ(WakelockStateChanged::RELEASE,
// getStateInt(mgr, android::util::WAKELOCK_STATE_CHANGED, queryKey3));
//}
//
///**
// * Test StateManager's onLogEvent and StateListener's onStateChanged correctly
// * updates listener for states with multiple primary keys.
// */
//TEST(StateTrackerTest, TestStateChangeMultiplePrimaryFields) {
// sp<TestStateListener> listener1 = new TestStateListener();
// StateManager mgr;
// mgr.registerListener(android::util::OVERLAY_STATE_CHANGED, listener1);
//
// // log event
// std::shared_ptr<LogEvent> event =
// buildOverlayEvent(1000 /* uid */, "package1", 1); // state: ENTERED
// mgr.onLogEvent(*event);
//
// // check listener was updated
// EXPECT_EQ(1, listener1->updates.size());
// EXPECT_EQ(1000, listener1->updates[0].mKey.getValues()[0].mValue.int_value);
// EXPECT_EQ(1, listener1->updates[0].mState);
//
// // check StateTracker was updated by querying for state
// HashableDimensionKey queryKey;
// getOverlayKey(1000 /* uid */, "package1", &queryKey);
// EXPECT_EQ(OverlayStateChanged::ENTERED,
// getStateInt(mgr, android::util::OVERLAY_STATE_CHANGED, queryKey));
//}
//
///**
// * Test StateManager's onLogEvent and StateListener's onStateChanged
// * when there is an error extracting state from log event. Listener is not
// * updated of state change.
// */
//TEST(StateTrackerTest, TestStateChangeEventError) {
// sp<TestStateListener> listener1 = new TestStateListener();
// StateManager mgr;
// mgr.registerListener(android::util::OVERLAY_STATE_CHANGED, listener1);
//
// // log event
// std::shared_ptr<LogEvent> event1 =
// buildIncorrectOverlayEvent(1000 /* uid */, "package1", 1 /* state */);
// std::shared_ptr<LogEvent> event2 = buildOverlayEventBadStateType(1001 /* uid */, "package2");
//
// // check listener was updated
// mgr.onLogEvent(*event1);
// EXPECT_EQ(0, listener1->updates.size());
// mgr.onLogEvent(*event2);
// EXPECT_EQ(0, listener1->updates.size());
//}
//
//TEST(StateTrackerTest, TestStateQuery) {
// sp<TestStateListener> listener1 = new TestStateListener();
// sp<TestStateListener> listener2 = new TestStateListener();
// sp<TestStateListener> listener3 = new TestStateListener();
// sp<TestStateListener> listener4 = new TestStateListener();
// StateManager mgr;
// mgr.registerListener(android::util::SCREEN_STATE_CHANGED, listener1);
// mgr.registerListener(android::util::UID_PROCESS_STATE_CHANGED, listener2);
// mgr.registerListener(android::util::OVERLAY_STATE_CHANGED, listener3);
// mgr.registerListener(android::util::WAKELOCK_STATE_CHANGED, listener4);
//
// std::shared_ptr<LogEvent> event1 = buildUidProcessEvent(
// 1000,
// android::app::ProcessStateEnum::PROCESS_STATE_TOP); // state value: 1002
// std::shared_ptr<LogEvent> event2 = buildUidProcessEvent(
// 1001,
// android::app::ProcessStateEnum::PROCESS_STATE_FOREGROUND_SERVICE); // state value:
// // 1003
// std::shared_ptr<LogEvent> event3 = buildUidProcessEvent(
// 1002,
// android::app::ProcessStateEnum::PROCESS_STATE_PERSISTENT); // state value: 1000
// std::shared_ptr<LogEvent> event4 = buildUidProcessEvent(
// 1001,
// android::app::ProcessStateEnum::PROCESS_STATE_TOP); // state value: 1002
// std::shared_ptr<LogEvent> event5 =
// buildScreenEvent(android::view::DisplayStateEnum::DISPLAY_STATE_ON);
// std::shared_ptr<LogEvent> event6 =
// buildOverlayEvent(1000, "package1", OverlayStateChanged::ENTERED);
// std::shared_ptr<LogEvent> event7 =
// buildOverlayEvent(1000, "package2", OverlayStateChanged::EXITED);
// std::shared_ptr<LogEvent> event8 = buildPartialWakelockEvent(1005, "tag1", true);
// std::shared_ptr<LogEvent> event9 = buildPartialWakelockEvent(1005, "tag2", false);
//
// mgr.onLogEvent(*event1);
// mgr.onLogEvent(*event2);
// mgr.onLogEvent(*event3);
// mgr.onLogEvent(*event5);
// mgr.onLogEvent(*event5);
// mgr.onLogEvent(*event6);
// mgr.onLogEvent(*event7);
// mgr.onLogEvent(*event8);
// mgr.onLogEvent(*event9);
//
// // Query for UidProcessState of uid 1001
// HashableDimensionKey queryKey1;
// getUidProcessKey(1001, &queryKey1);
// EXPECT_EQ(android::app::ProcessStateEnum::PROCESS_STATE_FOREGROUND_SERVICE,
// getStateInt(mgr, android::util::UID_PROCESS_STATE_CHANGED, queryKey1));
//
// // Query for UidProcessState of uid 1004 - not in state map
// HashableDimensionKey queryKey2;
// getUidProcessKey(1004, &queryKey2);
// EXPECT_EQ(-1, getStateInt(mgr, android::util::UID_PROCESS_STATE_CHANGED,
// queryKey2)); // default state
//
// // Query for UidProcessState of uid 1001 - after change in state
// mgr.onLogEvent(*event4);
// EXPECT_EQ(android::app::ProcessStateEnum::PROCESS_STATE_TOP,
// getStateInt(mgr, android::util::UID_PROCESS_STATE_CHANGED, queryKey1));
//
// // Query for ScreenState
// EXPECT_EQ(android::view::DisplayStateEnum::DISPLAY_STATE_ON,
// getStateInt(mgr, android::util::SCREEN_STATE_CHANGED, DEFAULT_DIMENSION_KEY));
//
// // Query for OverlayState of uid 1000, package name "package2"
// HashableDimensionKey queryKey3;
// getOverlayKey(1000, "package2", &queryKey3);
// EXPECT_EQ(OverlayStateChanged::EXITED,
// getStateInt(mgr, android::util::OVERLAY_STATE_CHANGED, queryKey3));
//
// // Query for WakelockState of uid 1005, tag 2
// HashableDimensionKey queryKey4;
// getPartialWakelockKey(1005, "tag2", &queryKey4);
// EXPECT_EQ(WakelockStateChanged::RELEASE,
// getStateInt(mgr, android::util::WAKELOCK_STATE_CHANGED, queryKey4));
//
// // Query for WakelockState of uid 1005, tag 1
// HashableDimensionKey queryKey5;
// getPartialWakelockKey(1005, "tag1", &queryKey5);
// EXPECT_EQ(WakelockStateChanged::ACQUIRE,
// getStateInt(mgr, android::util::WAKELOCK_STATE_CHANGED, queryKey5));
//}
} // namespace statsd
} // namespace os

View File

@@ -409,180 +409,181 @@ FieldMatcher CreateDimensions(const int atomId, const std::vector<int>& fields)
return dimensions;
}
std::unique_ptr<LogEvent> CreateScreenStateChangedEvent(
const android::view::DisplayStateEnum state, uint64_t timestampNs) {
auto event = std::make_unique<LogEvent>(android::util::SCREEN_STATE_CHANGED, timestampNs);
EXPECT_TRUE(event->write(state));
event->init();
return event;
}
std::unique_ptr<LogEvent> CreateBatterySaverOnEvent(uint64_t timestampNs) {
auto event = std::make_unique<LogEvent>(
android::util::BATTERY_SAVER_MODE_STATE_CHANGED, timestampNs);
EXPECT_TRUE(event->write(BatterySaverModeStateChanged::ON));
event->init();
return event;
}
std::unique_ptr<LogEvent> CreateBatterySaverOffEvent(uint64_t timestampNs) {
auto event = std::make_unique<LogEvent>(
android::util::BATTERY_SAVER_MODE_STATE_CHANGED, timestampNs);
EXPECT_TRUE(event->write(BatterySaverModeStateChanged::OFF));
event->init();
return event;
}
std::unique_ptr<LogEvent> CreateScreenBrightnessChangedEvent(
int level, uint64_t timestampNs) {
auto event = std::make_unique<LogEvent>(android::util::SCREEN_BRIGHTNESS_CHANGED, timestampNs);
EXPECT_TRUE(event->write(level));
event->init();
return event;
}
std::unique_ptr<LogEvent> CreateScheduledJobStateChangedEvent(
const std::vector<AttributionNodeInternal>& attributions, const string& jobName,
const ScheduledJobStateChanged::State state, uint64_t timestampNs) {
auto event = std::make_unique<LogEvent>(android::util::SCHEDULED_JOB_STATE_CHANGED, timestampNs);
event->write(attributions);
event->write(jobName);
event->write(state);
event->init();
return event;
}
std::unique_ptr<LogEvent> CreateStartScheduledJobEvent(
const std::vector<AttributionNodeInternal>& attributions,
const string& name, uint64_t timestampNs) {
return CreateScheduledJobStateChangedEvent(
attributions, name, ScheduledJobStateChanged::STARTED, timestampNs);
}
// Create log event when scheduled job finishes.
std::unique_ptr<LogEvent> CreateFinishScheduledJobEvent(
const std::vector<AttributionNodeInternal>& attributions,
const string& name, uint64_t timestampNs) {
return CreateScheduledJobStateChangedEvent(
attributions, name, ScheduledJobStateChanged::FINISHED, timestampNs);
}
std::unique_ptr<LogEvent> CreateWakelockStateChangedEvent(
const std::vector<AttributionNodeInternal>& attributions, const string& wakelockName,
const WakelockStateChanged::State state, uint64_t timestampNs) {
auto event = std::make_unique<LogEvent>(android::util::WAKELOCK_STATE_CHANGED, timestampNs);
event->write(attributions);
event->write(android::os::WakeLockLevelEnum::PARTIAL_WAKE_LOCK);
event->write(wakelockName);
event->write(state);
event->init();
return event;
}
std::unique_ptr<LogEvent> CreateAcquireWakelockEvent(
const std::vector<AttributionNodeInternal>& attributions, const string& wakelockName,
uint64_t timestampNs) {
return CreateWakelockStateChangedEvent(
attributions, wakelockName, WakelockStateChanged::ACQUIRE, timestampNs);
}
std::unique_ptr<LogEvent> CreateReleaseWakelockEvent(
const std::vector<AttributionNodeInternal>& attributions, const string& wakelockName,
uint64_t timestampNs) {
return CreateWakelockStateChangedEvent(
attributions, wakelockName, WakelockStateChanged::RELEASE, timestampNs);
}
std::unique_ptr<LogEvent> CreateActivityForegroundStateChangedEvent(
const int uid, const ActivityForegroundStateChanged::State state, uint64_t timestampNs) {
auto event = std::make_unique<LogEvent>(
android::util::ACTIVITY_FOREGROUND_STATE_CHANGED, timestampNs);
event->write(uid);
event->write("pkg_name");
event->write("class_name");
event->write(state);
event->init();
return event;
}
std::unique_ptr<LogEvent> CreateMoveToBackgroundEvent(const int uid, uint64_t timestampNs) {
return CreateActivityForegroundStateChangedEvent(
uid, ActivityForegroundStateChanged::BACKGROUND, timestampNs);
}
std::unique_ptr<LogEvent> CreateMoveToForegroundEvent(const int uid, uint64_t timestampNs) {
return CreateActivityForegroundStateChangedEvent(
uid, ActivityForegroundStateChanged::FOREGROUND, timestampNs);
}
std::unique_ptr<LogEvent> CreateSyncStateChangedEvent(
const std::vector<AttributionNodeInternal>& attributions, const string& name,
const SyncStateChanged::State state, uint64_t timestampNs) {
auto event = std::make_unique<LogEvent>(android::util::SYNC_STATE_CHANGED, timestampNs);
event->write(attributions);
event->write(name);
event->write(state);
event->init();
return event;
}
std::unique_ptr<LogEvent> CreateSyncStartEvent(
const std::vector<AttributionNodeInternal>& attributions, const string& name,
uint64_t timestampNs) {
return CreateSyncStateChangedEvent(attributions, name, SyncStateChanged::ON, timestampNs);
}
std::unique_ptr<LogEvent> CreateSyncEndEvent(
const std::vector<AttributionNodeInternal>& attributions, const string& name,
uint64_t timestampNs) {
return CreateSyncStateChangedEvent(attributions, name, SyncStateChanged::OFF, timestampNs);
}
std::unique_ptr<LogEvent> CreateProcessLifeCycleStateChangedEvent(
const int uid, const ProcessLifeCycleStateChanged::State state, uint64_t timestampNs) {
auto logEvent = std::make_unique<LogEvent>(
android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED, timestampNs);
logEvent->write(uid);
logEvent->write("");
logEvent->write(state);
logEvent->init();
return logEvent;
}
std::unique_ptr<LogEvent> CreateAppCrashEvent(const int uid, uint64_t timestampNs) {
return CreateProcessLifeCycleStateChangedEvent(
uid, ProcessLifeCycleStateChanged::CRASHED, timestampNs);
}
std::unique_ptr<LogEvent> CreateAppCrashOccurredEvent(const int uid, uint64_t timestampNs) {
auto event = std::make_unique<LogEvent>(android::util::APP_CRASH_OCCURRED, timestampNs);
event->write(uid);
event->write("eventType");
event->write("processName");
event->init();
return event;
}
std::unique_ptr<LogEvent> CreateIsolatedUidChangedEvent(
int isolatedUid, int hostUid, bool is_create, uint64_t timestampNs) {
auto logEvent = std::make_unique<LogEvent>(
android::util::ISOLATED_UID_CHANGED, timestampNs);
logEvent->write(hostUid);
logEvent->write(isolatedUid);
logEvent->write(is_create);
logEvent->init();
return logEvent;
}
std::unique_ptr<LogEvent> CreateUidProcessStateChangedEvent(
int uid, const android::app::ProcessStateEnum state, uint64_t timestampNs) {
auto event = std::make_unique<LogEvent>(android::util::UID_PROCESS_STATE_CHANGED, timestampNs);
event->write(uid);
event->write(state);
event->init();
return event;
}
// TODO(b/149590301): Update these helpers to use new socket schema.
//std::unique_ptr<LogEvent> CreateScreenStateChangedEvent(
// const android::view::DisplayStateEnum state, uint64_t timestampNs) {
// auto event = std::make_unique<LogEvent>(android::util::SCREEN_STATE_CHANGED, timestampNs);
// EXPECT_TRUE(event->write(state));
// event->init();
// return event;
//}
//
//std::unique_ptr<LogEvent> CreateBatterySaverOnEvent(uint64_t timestampNs) {
// auto event = std::make_unique<LogEvent>(
// android::util::BATTERY_SAVER_MODE_STATE_CHANGED, timestampNs);
// EXPECT_TRUE(event->write(BatterySaverModeStateChanged::ON));
// event->init();
// return event;
//}
//
//std::unique_ptr<LogEvent> CreateBatterySaverOffEvent(uint64_t timestampNs) {
// auto event = std::make_unique<LogEvent>(
// android::util::BATTERY_SAVER_MODE_STATE_CHANGED, timestampNs);
// EXPECT_TRUE(event->write(BatterySaverModeStateChanged::OFF));
// event->init();
// return event;
//}
//
//std::unique_ptr<LogEvent> CreateScreenBrightnessChangedEvent(
// int level, uint64_t timestampNs) {
// auto event = std::make_unique<LogEvent>(android::util::SCREEN_BRIGHTNESS_CHANGED, timestampNs);
// EXPECT_TRUE(event->write(level));
// event->init();
// return event;
//
//}
//
//std::unique_ptr<LogEvent> CreateScheduledJobStateChangedEvent(
// const std::vector<AttributionNodeInternal>& attributions, const string& jobName,
// const ScheduledJobStateChanged::State state, uint64_t timestampNs) {
// auto event = std::make_unique<LogEvent>(android::util::SCHEDULED_JOB_STATE_CHANGED, timestampNs);
// event->write(attributions);
// event->write(jobName);
// event->write(state);
// event->init();
// return event;
//}
//
//std::unique_ptr<LogEvent> CreateStartScheduledJobEvent(
// const std::vector<AttributionNodeInternal>& attributions,
// const string& name, uint64_t timestampNs) {
// return CreateScheduledJobStateChangedEvent(
// attributions, name, ScheduledJobStateChanged::STARTED, timestampNs);
//}
//
//// Create log event when scheduled job finishes.
//std::unique_ptr<LogEvent> CreateFinishScheduledJobEvent(
// const std::vector<AttributionNodeInternal>& attributions,
// const string& name, uint64_t timestampNs) {
// return CreateScheduledJobStateChangedEvent(
// attributions, name, ScheduledJobStateChanged::FINISHED, timestampNs);
//}
//
//std::unique_ptr<LogEvent> CreateWakelockStateChangedEvent(
// const std::vector<AttributionNodeInternal>& attributions, const string& wakelockName,
// const WakelockStateChanged::State state, uint64_t timestampNs) {
// auto event = std::make_unique<LogEvent>(android::util::WAKELOCK_STATE_CHANGED, timestampNs);
// event->write(attributions);
// event->write(android::os::WakeLockLevelEnum::PARTIAL_WAKE_LOCK);
// event->write(wakelockName);
// event->write(state);
// event->init();
// return event;
//}
//
//std::unique_ptr<LogEvent> CreateAcquireWakelockEvent(
// const std::vector<AttributionNodeInternal>& attributions, const string& wakelockName,
// uint64_t timestampNs) {
// return CreateWakelockStateChangedEvent(
// attributions, wakelockName, WakelockStateChanged::ACQUIRE, timestampNs);
//}
//
//std::unique_ptr<LogEvent> CreateReleaseWakelockEvent(
// const std::vector<AttributionNodeInternal>& attributions, const string& wakelockName,
// uint64_t timestampNs) {
// return CreateWakelockStateChangedEvent(
// attributions, wakelockName, WakelockStateChanged::RELEASE, timestampNs);
//}
//
//std::unique_ptr<LogEvent> CreateActivityForegroundStateChangedEvent(
// const int uid, const ActivityForegroundStateChanged::State state, uint64_t timestampNs) {
// auto event = std::make_unique<LogEvent>(
// android::util::ACTIVITY_FOREGROUND_STATE_CHANGED, timestampNs);
// event->write(uid);
// event->write("pkg_name");
// event->write("class_name");
// event->write(state);
// event->init();
// return event;
//}
//
//std::unique_ptr<LogEvent> CreateMoveToBackgroundEvent(const int uid, uint64_t timestampNs) {
// return CreateActivityForegroundStateChangedEvent(
// uid, ActivityForegroundStateChanged::BACKGROUND, timestampNs);
//}
//
//std::unique_ptr<LogEvent> CreateMoveToForegroundEvent(const int uid, uint64_t timestampNs) {
// return CreateActivityForegroundStateChangedEvent(
// uid, ActivityForegroundStateChanged::FOREGROUND, timestampNs);
//}
//
//std::unique_ptr<LogEvent> CreateSyncStateChangedEvent(
// const std::vector<AttributionNodeInternal>& attributions, const string& name,
// const SyncStateChanged::State state, uint64_t timestampNs) {
// auto event = std::make_unique<LogEvent>(android::util::SYNC_STATE_CHANGED, timestampNs);
// event->write(attributions);
// event->write(name);
// event->write(state);
// event->init();
// return event;
//}
//
//std::unique_ptr<LogEvent> CreateSyncStartEvent(
// const std::vector<AttributionNodeInternal>& attributions, const string& name,
// uint64_t timestampNs) {
// return CreateSyncStateChangedEvent(attributions, name, SyncStateChanged::ON, timestampNs);
//}
//
//std::unique_ptr<LogEvent> CreateSyncEndEvent(
// const std::vector<AttributionNodeInternal>& attributions, const string& name,
// uint64_t timestampNs) {
// return CreateSyncStateChangedEvent(attributions, name, SyncStateChanged::OFF, timestampNs);
//}
//
//std::unique_ptr<LogEvent> CreateProcessLifeCycleStateChangedEvent(
// const int uid, const ProcessLifeCycleStateChanged::State state, uint64_t timestampNs) {
// auto logEvent = std::make_unique<LogEvent>(
// android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED, timestampNs);
// logEvent->write(uid);
// logEvent->write("");
// logEvent->write(state);
// logEvent->init();
// return logEvent;
//}
//
//std::unique_ptr<LogEvent> CreateAppCrashEvent(const int uid, uint64_t timestampNs) {
// return CreateProcessLifeCycleStateChangedEvent(
// uid, ProcessLifeCycleStateChanged::CRASHED, timestampNs);
//}
//
//std::unique_ptr<LogEvent> CreateAppCrashOccurredEvent(const int uid, uint64_t timestampNs) {
// auto event = std::make_unique<LogEvent>(android::util::APP_CRASH_OCCURRED, timestampNs);
// event->write(uid);
// event->write("eventType");
// event->write("processName");
// event->init();
// return event;
//}
//
//std::unique_ptr<LogEvent> CreateIsolatedUidChangedEvent(
// int isolatedUid, int hostUid, bool is_create, uint64_t timestampNs) {
// auto logEvent = std::make_unique<LogEvent>(
// android::util::ISOLATED_UID_CHANGED, timestampNs);
// logEvent->write(hostUid);
// logEvent->write(isolatedUid);
// logEvent->write(is_create);
// logEvent->init();
// return logEvent;
//}
//
//std::unique_ptr<LogEvent> CreateUidProcessStateChangedEvent(
// int uid, const android::app::ProcessStateEnum state, uint64_t timestampNs) {
// auto event = std::make_unique<LogEvent>(android::util::UID_PROCESS_STATE_CHANGED, timestampNs);
// event->write(uid);
// event->write(state);
// event->init();
// return event;
//}
sp<StatsLogProcessor> CreateStatsLogProcessor(const int64_t timeBaseNs, const int64_t currentTimeNs,
const StatsdConfig& config, const ConfigKey& key,