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     std::set<int32_t> usedUids;
179     producer.onDumpReport(/*dumpTimeNs=*/10,
180                           /*include_current_partial_bucket=*/true,
181                           /*erase_data=*/true, FAST, &strSet, usedUids, &output);
182 
183     ASSERT_EQ(output.size(), 0);
184     ASSERT_EQ(strSet.size(), 0);
185 }
186 
TEST_F(RestrictedEventMetricProducerTest,TestOnMetricRemove)187 TEST_F(RestrictedEventMetricProducerTest, TestOnMetricRemove) {
188     EventMetric metric;
189     metric.set_id(metricId1);
190     sp<MockConfigMetadataProvider> provider = makeMockConfigMetadataProvider(/*enabled=*/false);
191     RestrictedEventMetricProducer producer(configKey, metric,
192                                            /*conditionIndex=*/-1,
193                                            /*initialConditionCache=*/{}, new ConditionWizard(),
194                                            /*protoHash=*/0x1234567890,
195                                            /*startTimeNs=*/0, provider);
196     EXPECT_FALSE(metricTableExist(metricId1));
197 
198     std::unique_ptr<LogEvent> event1 = CreateRestrictedLogEvent(/*timestampNs=*/1);
199     producer.onMatchedLogEvent(/*matcherIndex=*/1, *event1);
200     producer.flushRestrictedData();
201     EXPECT_TRUE(metricTableExist(metricId1));
202 
203     producer.onMetricRemove();
204     EXPECT_FALSE(metricTableExist(metricId1));
205 }
206 
TEST_F(RestrictedEventMetricProducerTest,TestRestrictedEventMetricTtlDeletesFirstEvent)207 TEST_F(RestrictedEventMetricProducerTest, TestRestrictedEventMetricTtlDeletesFirstEvent) {
208     EventMetric metric;
209     metric.set_id(metricId1);
210     sp<MockConfigMetadataProvider> provider = makeMockConfigMetadataProvider(/*enabled=*/false);
211     RestrictedEventMetricProducer producer(configKey, metric,
212                                            /*conditionIndex=*/-1,
213                                            /*initialConditionCache=*/{}, new ConditionWizard(),
214                                            /*protoHash=*/0x1234567890,
215                                            /*startTimeNs=*/0, provider);
216 
217     int64_t currentTimeNs = getWallClockNs();
218     int64_t eightDaysAgo = currentTimeNs - 8 * 24 * 3600 * NS_PER_SEC;
219     std::unique_ptr<LogEvent> event1 = CreateRestrictedLogEvent(/*atomTag=*/123, /*timestampNs=*/1);
220     event1->setLogdWallClockTimestampNs(eightDaysAgo);
221     std::unique_ptr<LogEvent> event2 = CreateRestrictedLogEvent(/*atomTag=*/123, /*timestampNs=*/3);
222     event2->setLogdWallClockTimestampNs(currentTimeNs);
223 
224     producer.onMatchedLogEvent(/*matcherIndex=*/1, *event1);
225     producer.onMatchedLogEvent(/*matcherIndex=*/1, *event2);
226     producer.flushRestrictedData();
227     sqlite3* dbHandle = dbutils::getDb(configKey);
228     producer.enforceRestrictedDataTtl(dbHandle, currentTimeNs + 100);
229     dbutils::closeDb(dbHandle);
230 
231     std::stringstream query;
232     query << "SELECT * FROM metric_" << metricId1;
233     string err;
234     std::vector<int32_t> columnTypes;
235     std::vector<string> columnNames;
236     std::vector<std::vector<std::string>> rows;
237     dbutils::query(configKey, query.str(), rows, columnTypes, columnNames, err);
238     ASSERT_EQ(rows.size(), 1);
239     EXPECT_EQ(columnTypes.size(), 3 + event1->getValues().size());
240     EXPECT_THAT(columnNames,
241                 ElementsAre("atomId", "elapsedTimestampNs", "wallTimestampNs", "field_1"));
242     EXPECT_THAT(rows[0], ElementsAre(to_string(event2->GetTagId()),
243                                      to_string(event2->GetElapsedTimestampNs()),
244                                      to_string(currentTimeNs), _));
245 }
246 
TEST_F(RestrictedEventMetricProducerTest,TestLoadMetricMetadataSetsCategory)247 TEST_F(RestrictedEventMetricProducerTest, TestLoadMetricMetadataSetsCategory) {
248     metadata::MetricMetadata metricMetadata;
249     metricMetadata.set_metric_id(metricId1);
250     metricMetadata.set_restricted_category(1);  // CATEGORY_DIAGNOSTIC
251     EventMetric metric;
252     metric.set_id(metricId1);
253     sp<MockConfigMetadataProvider> provider = makeMockConfigMetadataProvider(/*enabled=*/false);
254     RestrictedEventMetricProducer producer(configKey, metric,
255                                            /*conditionIndex=*/-1,
256                                            /*initialConditionCache=*/{}, new ConditionWizard(),
257                                            /*protoHash=*/0x1234567890,
258                                            /*startTimeNs=*/0, provider);
259 
260     producer.loadMetricMetadataFromProto(metricMetadata);
261 
262     EXPECT_EQ(producer.getRestrictionCategory(), CATEGORY_DIAGNOSTIC);
263 }
264 
265 }  // namespace statsd
266 }  // namespace os
267 }  // namespace android
268 
269 #else
270 GTEST_LOG_(INFO) << "This test does nothing.\n";
271 #endif
272