1 #include "src/metrics/RestrictedEventMetricProducer.h"
2
3 #include <gtest/gtest.h>
4
5 #include "flags/FlagProvider.h"
6 #include "metrics_test_helper.h"
7 #include "stats_annotations.h"
8 #include "tests/statsd_test_util.h"
9 #include "utils/DbUtils.h"
10
11 using namespace testing;
12 using std::string;
13 using std::stringstream;
14 using std::vector;
15
16 #ifdef __ANDROID__
17
18 namespace android {
19 namespace os {
20 namespace statsd {
21
22 namespace {
23 const ConfigKey configKey(/*uid=*/0, /*id=*/12345);
24 const int64_t metricId1 = 123;
25 const int64_t metricId2 = 456;
26
metricTableExist(int64_t metricId)27 bool metricTableExist(int64_t metricId) {
28 stringstream query;
29 query << "SELECT * FROM metric_" << metricId;
30 vector<int32_t> columnTypes;
31 vector<vector<string>> rows;
32 vector<string> columnNames;
33 string err;
34 return dbutils::query(configKey, query.str(), rows, columnTypes, columnNames, err);
35 }
36 } // anonymous namespace
37
38 class RestrictedEventMetricProducerTest : public Test {
39 protected:
SetUp()40 void SetUp() override {
41 if (!isAtLeastU()) {
42 GTEST_SKIP();
43 }
44 }
TearDown()45 void TearDown() override {
46 if (!isAtLeastU()) {
47 GTEST_SKIP();
48 }
49 dbutils::deleteDb(configKey);
50 FlagProvider::getInstance().resetOverrides();
51 }
52 };
53
TEST_F(RestrictedEventMetricProducerTest,TestOnMatchedLogEventMultipleEvents)54 TEST_F(RestrictedEventMetricProducerTest, TestOnMatchedLogEventMultipleEvents) {
55 EventMetric metric;
56 metric.set_id(metricId1);
57 sp<MockConfigMetadataProvider> provider = makeMockConfigMetadataProvider(/*enabled=*/false);
58 RestrictedEventMetricProducer producer(configKey, metric,
59 /*conditionIndex=*/-1,
60 /*initialConditionCache=*/{}, new ConditionWizard(),
61 /*protoHash=*/0x1234567890,
62 /*startTimeNs=*/0, provider);
63 std::unique_ptr<LogEvent> event1 = CreateRestrictedLogEvent(/*atomTag=*/123, /*timestampNs=*/1);
64 std::unique_ptr<LogEvent> event2 = CreateRestrictedLogEvent(/*atomTag=*/123, /*timestampNs=*/3);
65
66 producer.onMatchedLogEvent(/*matcherIndex=*/1, *event1);
67 producer.onMatchedLogEvent(/*matcherIndex=*/1, *event2);
68 producer.flushRestrictedData();
69
70 stringstream query;
71 query << "SELECT * FROM metric_" << metricId1;
72 string err;
73 vector<int32_t> columnTypes;
74 std::vector<string> columnNames;
75 vector<vector<string>> rows;
76 dbutils::query(configKey, query.str(), rows, columnTypes, columnNames, err);
77 ASSERT_EQ(rows.size(), 2);
78 EXPECT_EQ(columnTypes.size(),
79 3 + event1->getValues().size()); // col 0:2 are reserved for metadata.
80 EXPECT_EQ(/*tagId=*/rows[0][0], to_string(event1->GetTagId()));
81 EXPECT_EQ(/*elapsedTimestampNs=*/rows[0][1], to_string(event1->GetElapsedTimestampNs()));
82 EXPECT_EQ(/*elapsedTimestampNs=*/rows[1][1], to_string(event2->GetElapsedTimestampNs()));
83
84 EXPECT_THAT(columnNames,
85 ElementsAre("atomId", "elapsedTimestampNs", "wallTimestampNs", "field_1"));
86 }
87
TEST_F(RestrictedEventMetricProducerTest,TestOnMatchedLogEventMultipleFields)88 TEST_F(RestrictedEventMetricProducerTest, TestOnMatchedLogEventMultipleFields) {
89 EventMetric metric;
90 metric.set_id(metricId2);
91 sp<MockConfigMetadataProvider> provider = makeMockConfigMetadataProvider(/*enabled=*/false);
92 RestrictedEventMetricProducer producer(configKey, metric,
93 /*conditionIndex=*/-1,
94 /*initialConditionCache=*/{}, new ConditionWizard(),
95 /*protoHash=*/0x1234567890,
96 /*startTimeNs=*/0, provider);
97 AStatsEvent* statsEvent = AStatsEvent_obtain();
98 AStatsEvent_setAtomId(statsEvent, 1);
99 AStatsEvent_addInt32Annotation(statsEvent, ASTATSLOG_ANNOTATION_ID_RESTRICTION_CATEGORY,
100 ASTATSLOG_RESTRICTION_CATEGORY_DIAGNOSTIC);
101 AStatsEvent_overwriteTimestamp(statsEvent, 1);
102
103 AStatsEvent_writeString(statsEvent, "111");
104 AStatsEvent_writeInt32(statsEvent, 11);
105 AStatsEvent_writeFloat(statsEvent, 11.0);
106 LogEvent logEvent(/*uid=*/0, /*pid=*/0);
107 parseStatsEventToLogEvent(statsEvent, &logEvent);
108
109 producer.onMatchedLogEvent(/*matcherIndex=1*/ 1, logEvent);
110 producer.flushRestrictedData();
111
112 stringstream query;
113 query << "SELECT * FROM metric_" << metricId2;
114 string err;
115 vector<int32_t> columnTypes;
116 std::vector<string> columnNames;
117 vector<vector<string>> rows;
118 EXPECT_TRUE(dbutils::query(configKey, query.str(), rows, columnTypes, columnNames, err));
119 ASSERT_EQ(rows.size(), 1);
120 EXPECT_EQ(columnTypes.size(),
121 3 + logEvent.getValues().size()); // col 0:2 are reserved for metadata.
122 EXPECT_EQ(/*field1=*/rows[0][3], "111");
123 EXPECT_EQ(/*field2=*/rows[0][4], "11");
124 EXPECT_FLOAT_EQ(/*field3=*/std::stof(rows[0][5]), 11.0);
125
126 EXPECT_THAT(columnNames, ElementsAre("atomId", "elapsedTimestampNs", "wallTimestampNs",
127 "field_1", "field_2", "field_3"));
128 }
129
TEST_F(RestrictedEventMetricProducerTest,TestOnMatchedLogEventWithCondition)130 TEST_F(RestrictedEventMetricProducerTest, TestOnMatchedLogEventWithCondition) {
131 EventMetric metric;
132 metric.set_id(metricId1);
133 metric.set_condition(StringToId("SCREEN_ON"));
134 sp<MockConfigMetadataProvider> provider = makeMockConfigMetadataProvider(/*enabled=*/false);
135 RestrictedEventMetricProducer producer(configKey, metric,
136 /*conditionIndex=*/0,
137 /*initialConditionCache=*/{ConditionState::kUnknown},
138 new ConditionWizard(),
139 /*protoHash=*/0x1234567890,
140 /*startTimeNs=*/0, provider);
141 std::unique_ptr<LogEvent> event1 = CreateRestrictedLogEvent(/*atomTag=*/123, /*timestampNs=*/1);
142 std::unique_ptr<LogEvent> event2 = CreateRestrictedLogEvent(/*atomTag=*/123, /*timestampNs=*/3);
143
144 producer.onConditionChanged(true, 0);
145 producer.onMatchedLogEvent(/*matcherIndex=*/1, *event1);
146 producer.onConditionChanged(false, 1);
147 producer.onMatchedLogEvent(/*matcherIndex=*/1, *event2);
148 producer.flushRestrictedData();
149
150 std::stringstream query;
151 query << "SELECT * FROM metric_" << metricId1;
152 string err;
153 std::vector<int32_t> columnTypes;
154 std::vector<string> columnNames;
155 std::vector<std::vector<std::string>> rows;
156 dbutils::query(configKey, query.str(), rows, columnTypes, columnNames, err);
157 ASSERT_EQ(rows.size(), 1);
158 EXPECT_EQ(columnTypes.size(), 3 + event1->getValues().size());
159 EXPECT_EQ(/*elapsedTimestampNs=*/rows[0][1], to_string(event1->GetElapsedTimestampNs()));
160
161 EXPECT_THAT(columnNames,
162 ElementsAre("atomId", "elapsedTimestampNs", "wallTimestampNs", "field_1"));
163 }
164
TEST_F(RestrictedEventMetricProducerTest,TestOnDumpReportNoOp)165 TEST_F(RestrictedEventMetricProducerTest, TestOnDumpReportNoOp) {
166 EventMetric metric;
167 metric.set_id(metricId1);
168 sp<MockConfigMetadataProvider> provider = makeMockConfigMetadataProvider(/*enabled=*/false);
169 RestrictedEventMetricProducer producer(configKey, metric,
170 /*conditionIndex=*/-1,
171 /*initialConditionCache=*/{}, new ConditionWizard(),
172 /*protoHash=*/0x1234567890,
173 /*startTimeNs=*/0, provider);
174 std::unique_ptr<LogEvent> event1 = CreateRestrictedLogEvent(/*timestampNs=*/1);
175 producer.onMatchedLogEvent(/*matcherIndex=*/1, *event1);
176 ProtoOutputStream output;
177 std::set<string> strSet;
178 producer.onDumpReport(/*dumpTimeNs=*/10,
179 /*include_current_partial_bucket=*/true,
180 /*erase_data=*/true, FAST, &strSet, &output);
181
182 ASSERT_EQ(output.size(), 0);
183 ASSERT_EQ(strSet.size(), 0);
184 }
185
TEST_F(RestrictedEventMetricProducerTest,TestOnMetricRemove)186 TEST_F(RestrictedEventMetricProducerTest, TestOnMetricRemove) {
187 EventMetric metric;
188 metric.set_id(metricId1);
189 sp<MockConfigMetadataProvider> provider = makeMockConfigMetadataProvider(/*enabled=*/false);
190 RestrictedEventMetricProducer producer(configKey, metric,
191 /*conditionIndex=*/-1,
192 /*initialConditionCache=*/{}, new ConditionWizard(),
193 /*protoHash=*/0x1234567890,
194 /*startTimeNs=*/0, provider);
195 EXPECT_FALSE(metricTableExist(metricId1));
196
197 std::unique_ptr<LogEvent> event1 = CreateRestrictedLogEvent(/*timestampNs=*/1);
198 producer.onMatchedLogEvent(/*matcherIndex=*/1, *event1);
199 producer.flushRestrictedData();
200 EXPECT_TRUE(metricTableExist(metricId1));
201
202 producer.onMetricRemove();
203 EXPECT_FALSE(metricTableExist(metricId1));
204 }
205
TEST_F(RestrictedEventMetricProducerTest,TestRestrictedEventMetricTtlDeletesFirstEvent)206 TEST_F(RestrictedEventMetricProducerTest, TestRestrictedEventMetricTtlDeletesFirstEvent) {
207 EventMetric metric;
208 metric.set_id(metricId1);
209 sp<MockConfigMetadataProvider> provider = makeMockConfigMetadataProvider(/*enabled=*/false);
210 RestrictedEventMetricProducer producer(configKey, metric,
211 /*conditionIndex=*/-1,
212 /*initialConditionCache=*/{}, new ConditionWizard(),
213 /*protoHash=*/0x1234567890,
214 /*startTimeNs=*/0, provider);
215
216 int64_t currentTimeNs = getWallClockNs();
217 int64_t eightDaysAgo = currentTimeNs - 8 * 24 * 3600 * NS_PER_SEC;
218 std::unique_ptr<LogEvent> event1 = CreateRestrictedLogEvent(/*atomTag=*/123, /*timestampNs=*/1);
219 event1->setLogdWallClockTimestampNs(eightDaysAgo);
220 std::unique_ptr<LogEvent> event2 = CreateRestrictedLogEvent(/*atomTag=*/123, /*timestampNs=*/3);
221 event2->setLogdWallClockTimestampNs(currentTimeNs);
222
223 producer.onMatchedLogEvent(/*matcherIndex=*/1, *event1);
224 producer.onMatchedLogEvent(/*matcherIndex=*/1, *event2);
225 producer.flushRestrictedData();
226 sqlite3* dbHandle = dbutils::getDb(configKey);
227 producer.enforceRestrictedDataTtl(dbHandle, currentTimeNs + 100);
228 dbutils::closeDb(dbHandle);
229
230 std::stringstream query;
231 query << "SELECT * FROM metric_" << metricId1;
232 string err;
233 std::vector<int32_t> columnTypes;
234 std::vector<string> columnNames;
235 std::vector<std::vector<std::string>> rows;
236 dbutils::query(configKey, query.str(), rows, columnTypes, columnNames, err);
237 ASSERT_EQ(rows.size(), 1);
238 EXPECT_EQ(columnTypes.size(), 3 + event1->getValues().size());
239 EXPECT_THAT(columnNames,
240 ElementsAre("atomId", "elapsedTimestampNs", "wallTimestampNs", "field_1"));
241 EXPECT_THAT(rows[0], ElementsAre(to_string(event2->GetTagId()),
242 to_string(event2->GetElapsedTimestampNs()),
243 to_string(currentTimeNs), _));
244 }
245
TEST_F(RestrictedEventMetricProducerTest,TestLoadMetricMetadataSetsCategory)246 TEST_F(RestrictedEventMetricProducerTest, TestLoadMetricMetadataSetsCategory) {
247 metadata::MetricMetadata metricMetadata;
248 metricMetadata.set_metric_id(metricId1);
249 metricMetadata.set_restricted_category(1); // CATEGORY_DIAGNOSTIC
250 EventMetric metric;
251 metric.set_id(metricId1);
252 sp<MockConfigMetadataProvider> provider = makeMockConfigMetadataProvider(/*enabled=*/false);
253 RestrictedEventMetricProducer producer(configKey, metric,
254 /*conditionIndex=*/-1,
255 /*initialConditionCache=*/{}, new ConditionWizard(),
256 /*protoHash=*/0x1234567890,
257 /*startTimeNs=*/0, provider);
258
259 producer.loadMetricMetadataFromProto(metricMetadata);
260
261 EXPECT_EQ(producer.getRestrictionCategory(), CATEGORY_DIAGNOSTIC);
262 }
263
264 } // namespace statsd
265 } // namespace os
266 } // namespace android
267
268 #else
269 GTEST_LOG_(INFO) << "This test does nothing.\n";
270 #endif
271