1 /*
2  * Copyright (C) 2017 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 #include <gtest/gtest.h>
17 #include "frameworks/base/cmds/statsd/src/stats_log.pb.h"
18 #include "frameworks/base/cmds/statsd/src/statsd_config.pb.h"
19 #include "matchers/matcher_util.h"
20 #include "src/logd/LogEvent.h"
21 #include "stats_log_util.h"
22 #include "stats_util.h"
23 #include "subscriber/SubscriberReporter.h"
24 
25 #ifdef __ANDROID__
26 
27 using android::util::ProtoReader;
28 
29 namespace android {
30 namespace os {
31 namespace statsd {
32 
TEST(AtomMatcherTest,TestFieldTranslation)33 TEST(AtomMatcherTest, TestFieldTranslation) {
34     FieldMatcher matcher1;
35     matcher1.set_field(10);
36     FieldMatcher* child = matcher1.add_child();
37     child->set_field(1);
38     child->set_position(Position::ANY);
39 
40     child = child->add_child();
41     child->set_field(1);
42 
43     vector<Matcher> output;
44     translateFieldMatcher(matcher1, &output);
45 
46     EXPECT_EQ((size_t)1, output.size());
47 
48     const auto& matcher12 = output[0];
49     EXPECT_EQ((int32_t)10, matcher12.mMatcher.getTag());
50     EXPECT_EQ((int32_t)0x02010001, matcher12.mMatcher.getField());
51     EXPECT_EQ((int32_t)0xff7f007f, matcher12.mMask);
52 }
53 
TEST(AtomMatcherTest,TestFieldTranslation_ALL)54 TEST(AtomMatcherTest, TestFieldTranslation_ALL) {
55     FieldMatcher matcher1;
56     matcher1.set_field(10);
57     FieldMatcher* child = matcher1.add_child();
58     child->set_field(1);
59     child->set_position(Position::ALL);
60 
61     child = child->add_child();
62     child->set_field(1);
63 
64     vector<Matcher> output;
65     translateFieldMatcher(matcher1, &output);
66 
67     EXPECT_EQ((size_t)1, output.size());
68 
69     const auto& matcher12 = output[0];
70     EXPECT_EQ((int32_t)10, matcher12.mMatcher.getTag());
71     EXPECT_EQ((int32_t)0x02010001, matcher12.mMatcher.getField());
72     EXPECT_EQ((int32_t)0xff7f7f7f, matcher12.mMask);
73 }
74 
TEST(AtomMatcherTest,TestFilter_ALL)75 TEST(AtomMatcherTest, TestFilter_ALL) {
76     FieldMatcher matcher1;
77     matcher1.set_field(10);
78     FieldMatcher* child = matcher1.add_child();
79     child->set_field(1);
80     child->set_position(Position::ALL);
81 
82     child->add_child()->set_field(1);
83     child->add_child()->set_field(2);
84 
85     child = matcher1.add_child();
86     child->set_field(2);
87 
88     vector<Matcher> matchers;
89     translateFieldMatcher(matcher1, &matchers);
90 
91     AttributionNodeInternal attribution_node1;
92     attribution_node1.set_uid(1111);
93     attribution_node1.set_tag("location1");
94 
95     AttributionNodeInternal attribution_node2;
96     attribution_node2.set_uid(2222);
97     attribution_node2.set_tag("location2");
98 
99     AttributionNodeInternal attribution_node3;
100     attribution_node3.set_uid(3333);
101     attribution_node3.set_tag("location3");
102     std::vector<AttributionNodeInternal> attribution_nodes = {attribution_node1, attribution_node2,
103                                                               attribution_node3};
104 
105     // Set up the event
106     LogEvent event(10, 12345);
107     event.write(attribution_nodes);
108     event.write("some value");
109     // Convert to a LogEvent
110     event.init();
111     HashableDimensionKey output;
112 
113     filterValues(matchers, event.getValues(), &output);
114 
115     EXPECT_EQ((size_t)7, output.getValues().size());
116     EXPECT_EQ((int32_t)0x02010101, output.getValues()[0].mField.getField());
117     EXPECT_EQ((int32_t)1111, output.getValues()[0].mValue.int_value);
118     EXPECT_EQ((int32_t)0x02010102, output.getValues()[1].mField.getField());
119     EXPECT_EQ("location1", output.getValues()[1].mValue.str_value);
120 
121     EXPECT_EQ((int32_t)0x02010201, output.getValues()[2].mField.getField());
122     EXPECT_EQ((int32_t)2222, output.getValues()[2].mValue.int_value);
123     EXPECT_EQ((int32_t)0x02010202, output.getValues()[3].mField.getField());
124     EXPECT_EQ("location2", output.getValues()[3].mValue.str_value);
125 
126     EXPECT_EQ((int32_t)0x02010301, output.getValues()[4].mField.getField());
127     EXPECT_EQ((int32_t)3333, output.getValues()[4].mValue.int_value);
128     EXPECT_EQ((int32_t)0x02010302, output.getValues()[5].mField.getField());
129     EXPECT_EQ("location3", output.getValues()[5].mValue.str_value);
130 
131     EXPECT_EQ((int32_t)0x00020000, output.getValues()[6].mField.getField());
132     EXPECT_EQ("some value", output.getValues()[6].mValue.str_value);
133 }
134 
TEST(AtomMatcherTest,TestSubDimension)135 TEST(AtomMatcherTest, TestSubDimension) {
136     HashableDimensionKey dim;
137 
138     int pos1[] = {1, 1, 1};
139     int pos2[] = {1, 1, 2};
140     int pos3[] = {1, 1, 3};
141     int pos4[] = {2, 0, 0};
142     Field field1(10, pos1, 2);
143     Field field2(10, pos2, 2);
144 
145     Field field3(10, pos3, 2);
146     Field field4(10, pos4, 0);
147 
148     Value value1((int32_t)10025);
149     Value value2("tag");
150 
151     Value value11((int32_t)10026);
152     Value value22("tag2");
153 
154     dim.addValue(FieldValue(field1, value1));
155     dim.addValue(FieldValue(field2, value2));
156 
157     HashableDimensionKey subDim1;
158     subDim1.addValue(FieldValue(field1, value1));
159 
160     HashableDimensionKey subDim2;
161     subDim1.addValue(FieldValue(field2, value2));
162 
163     EXPECT_TRUE(dim.contains(dim));
164     EXPECT_TRUE(dim.contains(subDim1));
165     EXPECT_TRUE(dim.contains(subDim2));
166 
167     HashableDimensionKey subDim3;
168     subDim3.addValue(FieldValue(field1, value11));
169     EXPECT_FALSE(dim.contains(subDim3));
170 
171     HashableDimensionKey subDim4;
172     // Empty dimension is always a sub dimension of other dimensions
173     EXPECT_TRUE(dim.contains(subDim4));
174 }
175 
TEST(AtomMatcherTest,TestMetric2ConditionLink)176 TEST(AtomMatcherTest, TestMetric2ConditionLink) {
177     AttributionNodeInternal attribution_node1;
178     attribution_node1.set_uid(1111);
179     attribution_node1.set_tag("location1");
180 
181     AttributionNodeInternal attribution_node2;
182     attribution_node2.set_uid(2222);
183     attribution_node2.set_tag("location2");
184 
185     AttributionNodeInternal attribution_node3;
186     attribution_node3.set_uid(3333);
187     attribution_node3.set_tag("location3");
188     std::vector<AttributionNodeInternal> attribution_nodes = {attribution_node1, attribution_node2,
189                                                               attribution_node3};
190 
191     // Set up the event
192     LogEvent event(10, 12345);
193     event.write(attribution_nodes);
194     event.write("some value");
195     // Convert to a LogEvent
196     event.init();
197 
198     FieldMatcher whatMatcher;
199     whatMatcher.set_field(10);
200     FieldMatcher* child11 = whatMatcher.add_child();
201     child11->set_field(1);
202     child11->set_position(Position::ANY);
203     child11 = child11->add_child();
204     child11->set_field(1);
205 
206     FieldMatcher conditionMatcher;
207     conditionMatcher.set_field(27);
208     FieldMatcher* child2 = conditionMatcher.add_child();
209     child2->set_field(2);
210     child2->set_position(Position::LAST);
211 
212     child2 = child2->add_child();
213     child2->set_field(2);
214 
215     Metric2Condition link;
216 
217     translateFieldMatcher(whatMatcher, &link.metricFields);
218     translateFieldMatcher(conditionMatcher, &link.conditionFields);
219 
220     EXPECT_EQ((size_t)1, link.metricFields.size());
221     EXPECT_EQ((int32_t)0x02010001, link.metricFields[0].mMatcher.getField());
222     EXPECT_EQ((int32_t)0xff7f007f, link.metricFields[0].mMask);
223     EXPECT_EQ((int32_t)10, link.metricFields[0].mMatcher.getTag());
224 
225     EXPECT_EQ((size_t)1, link.conditionFields.size());
226     EXPECT_EQ((int32_t)0x02028002, link.conditionFields[0].mMatcher.getField());
227     EXPECT_EQ((int32_t)0xff7f807f, link.conditionFields[0].mMask);
228     EXPECT_EQ((int32_t)27, link.conditionFields[0].mMatcher.getTag());
229 }
230 
TEST(AtomMatcherTest,TestWriteDimensionPath)231 TEST(AtomMatcherTest, TestWriteDimensionPath) {
232     for (auto position : {Position::ANY, Position::ALL, Position::FIRST, Position::LAST}) {
233         FieldMatcher matcher1;
234         matcher1.set_field(10);
235         FieldMatcher* child = matcher1.add_child();
236         child->set_field(2);
237         child->set_position(position);
238         child->add_child()->set_field(1);
239         child->add_child()->set_field(3);
240 
241         child = matcher1.add_child();
242         child->set_field(4);
243 
244         child = matcher1.add_child();
245         child->set_field(6);
246         child->add_child()->set_field(2);
247 
248         vector<Matcher> matchers;
249         translateFieldMatcher(matcher1, &matchers);
250 
251         android::util::ProtoOutputStream protoOut;
252         writeDimensionPathToProto(matchers, &protoOut);
253 
254         vector<uint8_t> outData;
255         outData.resize(protoOut.size());
256         size_t pos = 0;
257         sp<ProtoReader> reader = protoOut.data();
258         while (reader->readBuffer() != NULL) {
259             size_t toRead = reader->currentToRead();
260             std::memcpy(&(outData[pos]), reader->readBuffer(), toRead);
261             pos += toRead;
262             reader->move(toRead);
263         }
264 
265         DimensionsValue result;
266         EXPECT_EQ(true, result.ParseFromArray(&outData[0], outData.size()));
267 
268         EXPECT_EQ(10, result.field());
269         EXPECT_EQ(DimensionsValue::ValueCase::kValueTuple, result.value_case());
270         EXPECT_EQ(3, result.value_tuple().dimensions_value_size());
271 
272         const auto& dim1 = result.value_tuple().dimensions_value(0);
273         EXPECT_EQ(2, dim1.field());
274         EXPECT_EQ(2, dim1.value_tuple().dimensions_value_size());
275 
276         const auto& dim11 = dim1.value_tuple().dimensions_value(0);
277         EXPECT_EQ(1, dim11.field());
278 
279         const auto& dim12 = dim1.value_tuple().dimensions_value(1);
280         EXPECT_EQ(3, dim12.field());
281 
282         const auto& dim2 = result.value_tuple().dimensions_value(1);
283         EXPECT_EQ(4, dim2.field());
284 
285         const auto& dim3 = result.value_tuple().dimensions_value(2);
286         EXPECT_EQ(6, dim3.field());
287         EXPECT_EQ(1, dim3.value_tuple().dimensions_value_size());
288         const auto& dim31 = dim3.value_tuple().dimensions_value(0);
289         EXPECT_EQ(2, dim31.field());
290     }
291 }
292 
TEST(AtomMatcherTest,TestSubscriberDimensionWrite)293 TEST(AtomMatcherTest, TestSubscriberDimensionWrite) {
294     HashableDimensionKey dim;
295 
296     int pos1[] = {1, 1, 1};
297     int pos2[] = {1, 1, 2};
298     int pos3[] = {1, 1, 3};
299     int pos4[] = {2, 0, 0};
300 
301     Field field1(10, pos1, 2);
302     Field field2(10, pos2, 2);
303     Field field3(10, pos3, 2);
304     Field field4(10, pos4, 0);
305 
306     Value value1((int32_t)10025);
307     Value value2("tag");
308     Value value3((int32_t)987654);
309     Value value4((int32_t)99999);
310 
311     dim.addValue(FieldValue(field1, value1));
312     dim.addValue(FieldValue(field2, value2));
313     dim.addValue(FieldValue(field3, value3));
314     dim.addValue(FieldValue(field4, value4));
315 
316     SubscriberReporter::getStatsDimensionsValue(dim);
317     // TODO(b/110562792): can't test anything here because StatsDimensionsValue class doesn't
318     // have any read api.
319 }
320 
TEST(AtomMatcherTest,TestWriteDimensionToProto)321 TEST(AtomMatcherTest, TestWriteDimensionToProto) {
322     HashableDimensionKey dim;
323     int pos1[] = {1, 1, 1};
324     int pos2[] = {1, 1, 2};
325     int pos3[] = {1, 1, 3};
326     int pos4[] = {2, 0, 0};
327     Field field1(10, pos1, 2);
328     Field field2(10, pos2, 2);
329     Field field3(10, pos3, 2);
330     Field field4(10, pos4, 0);
331 
332     Value value1((int32_t)10025);
333     Value value2("tag");
334     Value value3((int32_t)987654);
335     Value value4((int32_t)99999);
336 
337     dim.addValue(FieldValue(field1, value1));
338     dim.addValue(FieldValue(field2, value2));
339     dim.addValue(FieldValue(field3, value3));
340     dim.addValue(FieldValue(field4, value4));
341 
342     android::util::ProtoOutputStream protoOut;
343     writeDimensionToProto(dim, nullptr /* include strings */, &protoOut);
344 
345     vector<uint8_t> outData;
346     outData.resize(protoOut.size());
347     size_t pos = 0;
348     sp<ProtoReader> reader = protoOut.data();
349     while (reader->readBuffer() != NULL) {
350         size_t toRead = reader->currentToRead();
351         std::memcpy(&(outData[pos]), reader->readBuffer(), toRead);
352         pos += toRead;
353         reader->move(toRead);
354     }
355 
356     DimensionsValue result;
357     EXPECT_EQ(true, result.ParseFromArray(&outData[0], outData.size()));
358     EXPECT_EQ(10, result.field());
359     EXPECT_EQ(DimensionsValue::ValueCase::kValueTuple, result.value_case());
360     EXPECT_EQ(2, result.value_tuple().dimensions_value_size());
361 
362     const auto& dim1 = result.value_tuple().dimensions_value(0);
363     EXPECT_EQ(DimensionsValue::ValueCase::kValueTuple, dim1.value_case());
364     EXPECT_EQ(3, dim1.value_tuple().dimensions_value_size());
365 
366     const auto& dim11 = dim1.value_tuple().dimensions_value(0);
367     EXPECT_EQ(DimensionsValue::ValueCase::kValueInt, dim11.value_case());
368     EXPECT_EQ(10025, dim11.value_int());
369 
370     const auto& dim12 = dim1.value_tuple().dimensions_value(1);
371     EXPECT_EQ(DimensionsValue::ValueCase::kValueStr, dim12.value_case());
372     EXPECT_EQ("tag", dim12.value_str());
373 
374     const auto& dim13 = dim1.value_tuple().dimensions_value(2);
375     EXPECT_EQ(DimensionsValue::ValueCase::kValueInt, dim13.value_case());
376     EXPECT_EQ(987654, dim13.value_int());
377 
378     const auto& dim2 = result.value_tuple().dimensions_value(1);
379     EXPECT_EQ(DimensionsValue::ValueCase::kValueInt, dim2.value_case());
380     EXPECT_EQ(99999, dim2.value_int());
381 }
382 
TEST(AtomMatcherTest,TestWriteDimensionLeafNodesToProto)383 TEST(AtomMatcherTest, TestWriteDimensionLeafNodesToProto) {
384     HashableDimensionKey dim;
385     int pos1[] = {1, 1, 1};
386     int pos2[] = {1, 1, 2};
387     int pos3[] = {1, 1, 3};
388     int pos4[] = {2, 0, 0};
389     Field field1(10, pos1, 2);
390     Field field2(10, pos2, 2);
391     Field field3(10, pos3, 2);
392     Field field4(10, pos4, 0);
393 
394     Value value1((int32_t)10025);
395     Value value2("tag");
396     Value value3((int32_t)987654);
397     Value value4((int64_t)99999);
398 
399     dim.addValue(FieldValue(field1, value1));
400     dim.addValue(FieldValue(field2, value2));
401     dim.addValue(FieldValue(field3, value3));
402     dim.addValue(FieldValue(field4, value4));
403 
404     android::util::ProtoOutputStream protoOut;
405     writeDimensionLeafNodesToProto(dim, 1, nullptr /* include strings */, &protoOut);
406 
407     vector<uint8_t> outData;
408     outData.resize(protoOut.size());
409     size_t pos = 0;
410     sp<ProtoReader> reader = protoOut.data();
411     while (reader->readBuffer() != NULL) {
412         size_t toRead = reader->currentToRead();
413         std::memcpy(&(outData[pos]), reader->readBuffer(), toRead);
414         pos += toRead;
415         reader->move(toRead);
416     }
417 
418     DimensionsValueTuple result;
419     EXPECT_EQ(true, result.ParseFromArray(&outData[0], outData.size()));
420     EXPECT_EQ(4, result.dimensions_value_size());
421 
422     const auto& dim1 = result.dimensions_value(0);
423     EXPECT_EQ(DimensionsValue::ValueCase::kValueInt, dim1.value_case());
424     EXPECT_EQ(10025, dim1.value_int());
425 
426     const auto& dim2 = result.dimensions_value(1);
427     EXPECT_EQ(DimensionsValue::ValueCase::kValueStr, dim2.value_case());
428     EXPECT_EQ("tag", dim2.value_str());
429 
430     const auto& dim3 = result.dimensions_value(2);
431     EXPECT_EQ(DimensionsValue::ValueCase::kValueInt, dim3.value_case());
432     EXPECT_EQ(987654, dim3.value_int());
433 
434     const auto& dim4 = result.dimensions_value(3);
435     EXPECT_EQ(DimensionsValue::ValueCase::kValueLong, dim4.value_case());
436     EXPECT_EQ(99999, dim4.value_long());
437 }
438 
TEST(AtomMatcherTest,TestWriteAtomToProto)439 TEST(AtomMatcherTest, TestWriteAtomToProto) {
440     AttributionNodeInternal attribution_node1;
441     attribution_node1.set_uid(1111);
442     attribution_node1.set_tag("location1");
443 
444     AttributionNodeInternal attribution_node2;
445     attribution_node2.set_uid(2222);
446     attribution_node2.set_tag("location2");
447 
448     std::vector<AttributionNodeInternal> attribution_nodes = {attribution_node1, attribution_node2};
449 
450     // Set up the event
451     LogEvent event(4, 12345);
452     event.write(attribution_nodes);
453     event.write((int32_t)999);
454     // Convert to a LogEvent
455     event.init();
456 
457     android::util::ProtoOutputStream protoOutput;
458     writeFieldValueTreeToStream(event.GetTagId(), event.getValues(), &protoOutput);
459 
460     vector<uint8_t> outData;
461     outData.resize(protoOutput.size());
462     size_t pos = 0;
463     sp<ProtoReader> reader = protoOutput.data();
464     while (reader->readBuffer() != NULL) {
465         size_t toRead = reader->currentToRead();
466         std::memcpy(&(outData[pos]), reader->readBuffer(), toRead);
467         pos += toRead;
468         reader->move(toRead);
469     }
470 
471     Atom result;
472     EXPECT_EQ(true, result.ParseFromArray(&outData[0], outData.size()));
473     EXPECT_EQ(Atom::PushedCase::kBleScanResultReceived, result.pushed_case());
474     const auto& atom = result.ble_scan_result_received();
475     EXPECT_EQ(2, atom.attribution_node_size());
476     EXPECT_EQ(1111, atom.attribution_node(0).uid());
477     EXPECT_EQ("location1", atom.attribution_node(0).tag());
478     EXPECT_EQ(2222, atom.attribution_node(1).uid());
479     EXPECT_EQ("location2", atom.attribution_node(1).tag());
480     EXPECT_EQ(999, atom.num_results());
481 }
482 
483 
484 }  // namespace statsd
485 }  // namespace os
486 }  // namespace android
487 #else
488 GTEST_LOG_(INFO) << "This test does nothing.\n";
489 #endif
490