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