• 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 
18 #include "src/stats_log.pb.h"
19 #include "src/statsd_config.pb.h"
20 #include "matchers/matcher_util.h"
21 #include "src/logd/LogEvent.h"
22 #include "stats_event.h"
23 #include "stats_log_util.h"
24 #include "stats_util.h"
25 #include "subscriber/SubscriberReporter.h"
26 #include "tests/statsd_test_util.h"
27 
28 #ifdef __ANDROID__
29 
30 using android::util::ProtoReader;
31 
32 namespace android {
33 namespace os {
34 namespace statsd {
35 
36 namespace {
37 
makeLogEvent(LogEvent * logEvent,const int32_t atomId,const int64_t timestamp,const vector<int> & attributionUids,const vector<string> & attributionTags,const string & name)38 void makeLogEvent(LogEvent* logEvent, const int32_t atomId, const int64_t timestamp,
39                   const vector<int>& attributionUids, const vector<string>& attributionTags,
40                   const string& name) {
41     AStatsEvent* statsEvent = AStatsEvent_obtain();
42     AStatsEvent_setAtomId(statsEvent, atomId);
43     AStatsEvent_overwriteTimestamp(statsEvent, timestamp);
44 
45     writeAttribution(statsEvent, attributionUids, attributionTags);
46     AStatsEvent_writeString(statsEvent, name.c_str());
47 
48     parseStatsEventToLogEvent(statsEvent, logEvent);
49 }
50 
makeLogEvent(LogEvent * logEvent,const int32_t atomId,const int64_t timestamp,const vector<int> & attributionUids,const vector<string> & attributionTags,const int32_t value)51 void makeLogEvent(LogEvent* logEvent, const int32_t atomId, const int64_t timestamp,
52                   const vector<int>& attributionUids, const vector<string>& attributionTags,
53                   const int32_t value) {
54     AStatsEvent* statsEvent = AStatsEvent_obtain();
55     AStatsEvent_setAtomId(statsEvent, atomId);
56     AStatsEvent_overwriteTimestamp(statsEvent, timestamp);
57 
58     writeAttribution(statsEvent, attributionUids, attributionTags);
59     AStatsEvent_writeInt32(statsEvent, value);
60 
61     parseStatsEventToLogEvent(statsEvent, logEvent);
62 }
63 
makeRepeatedIntLogEvent(LogEvent * logEvent,const int32_t atomId,const vector<int> & intArray)64 void makeRepeatedIntLogEvent(LogEvent* logEvent, const int32_t atomId,
65                              const vector<int>& intArray) {
66     AStatsEvent* statsEvent = AStatsEvent_obtain();
67     AStatsEvent_setAtomId(statsEvent, atomId);
68     AStatsEvent_writeInt32Array(statsEvent, intArray.data(), intArray.size());
69     parseStatsEventToLogEvent(statsEvent, logEvent);
70 }
71 }  // anonymous namespace
72 
TEST(AtomMatcherTest,TestFieldTranslation)73 TEST(AtomMatcherTest, TestFieldTranslation) {
74     FieldMatcher matcher1;
75     matcher1.set_field(10);
76     FieldMatcher* child = matcher1.add_child();
77     child->set_field(1);
78     child->set_position(Position::ANY);
79 
80     child = child->add_child();
81     child->set_field(1);
82 
83     vector<Matcher> output;
84     translateFieldMatcher(matcher1, &output);
85 
86     ASSERT_EQ((size_t)1, output.size());
87 
88     const auto& matcher12 = output[0];
89     EXPECT_EQ((int32_t)10, matcher12.mMatcher.getTag());
90     EXPECT_EQ((int32_t)0x02010001, matcher12.mMatcher.getField());
91     EXPECT_EQ((int32_t)0xff7f007f, matcher12.mMask);
92 }
93 
TEST(AtomMatcherTest,TestFieldTranslation_ALL)94 TEST(AtomMatcherTest, TestFieldTranslation_ALL) {
95     FieldMatcher matcher1;
96     matcher1.set_field(10);
97     FieldMatcher* child = matcher1.add_child();
98     child->set_field(1);
99     child->set_position(Position::ALL);
100 
101     child = child->add_child();
102     child->set_field(1);
103 
104     vector<Matcher> output;
105     translateFieldMatcher(matcher1, &output);
106 
107     ASSERT_EQ((size_t)1, output.size());
108 
109     const auto& matcher12 = output[0];
110     EXPECT_EQ((int32_t)10, matcher12.mMatcher.getTag());
111     EXPECT_EQ((int32_t)0x02010001, matcher12.mMatcher.getField());
112     EXPECT_EQ((int32_t)0xff7f7f7f, matcher12.mMask);
113 }
114 
TEST(AtomMatcherTest,TestFilter_ALL)115 TEST(AtomMatcherTest, TestFilter_ALL) {
116     FieldMatcher matcher1;
117     matcher1.set_field(10);
118     FieldMatcher* child = matcher1.add_child();
119     child->set_field(1);
120     child->set_position(Position::ALL);
121 
122     child->add_child()->set_field(1);
123     child->add_child()->set_field(2);
124 
125     child = matcher1.add_child();
126     child->set_field(2);
127 
128     vector<Matcher> matchers;
129     translateFieldMatcher(matcher1, &matchers);
130 
131     std::vector<int> attributionUids = {1111, 2222, 3333};
132     std::vector<string> attributionTags = {"location1", "location2", "location3"};
133 
134     LogEvent event(/*uid=*/0, /*pid=*/0);
135     makeLogEvent(&event, 10 /*atomId*/, /*timestamp=*/1012345, attributionUids, attributionTags,
136                  "some value");
137     HashableDimensionKey output;
138 
139     filterValues(matchers, event.getValues(), &output);
140 
141     ASSERT_EQ((size_t)7, output.getValues().size());
142     EXPECT_EQ((int32_t)0x02010101, output.getValues()[0].mField.getField());
143     EXPECT_EQ((int32_t)1111, output.getValues()[0].mValue.int_value);
144     EXPECT_EQ((int32_t)0x02010102, output.getValues()[1].mField.getField());
145     EXPECT_EQ("location1", output.getValues()[1].mValue.str_value);
146 
147     EXPECT_EQ((int32_t)0x02010201, output.getValues()[2].mField.getField());
148     EXPECT_EQ((int32_t)2222, output.getValues()[2].mValue.int_value);
149     EXPECT_EQ((int32_t)0x02010202, output.getValues()[3].mField.getField());
150     EXPECT_EQ("location2", output.getValues()[3].mValue.str_value);
151 
152     EXPECT_EQ((int32_t)0x02010301, output.getValues()[4].mField.getField());
153     EXPECT_EQ((int32_t)3333, output.getValues()[4].mValue.int_value);
154     EXPECT_EQ((int32_t)0x02010302, output.getValues()[5].mField.getField());
155     EXPECT_EQ("location3", output.getValues()[5].mValue.str_value);
156 
157     EXPECT_EQ((int32_t)0x00020000, output.getValues()[6].mField.getField());
158     EXPECT_EQ("some value", output.getValues()[6].mValue.str_value);
159 }
160 
TEST(AtomMatcherTest,TestFilterRepeated_FIRST)161 TEST(AtomMatcherTest, TestFilterRepeated_FIRST) {
162     FieldMatcher matcher;
163     matcher.set_field(123);
164     FieldMatcher* child = matcher.add_child();
165     child->set_field(1);
166     child->set_position(Position::FIRST);
167 
168     vector<Matcher> matchers;
169     translateFieldMatcher(matcher, &matchers);
170 
171     LogEvent event(/*uid=*/0, /*pid=*/0);
172     vector<int> intArray = {21, 9, 13};
173     makeRepeatedIntLogEvent(&event, 123, intArray);
174 
175     HashableDimensionKey output;
176     EXPECT_TRUE(filterValues(matchers, event.getValues(), &output));
177 
178     ASSERT_EQ((size_t)1, output.getValues().size());
179     EXPECT_EQ((int32_t)0x01010100, output.getValues()[0].mField.getField());
180     EXPECT_EQ((int32_t)21, output.getValues()[0].mValue.int_value);
181 }
182 
TEST(AtomMatcherTest,TestFilterRepeated_LAST)183 TEST(AtomMatcherTest, TestFilterRepeated_LAST) {
184     FieldMatcher matcher;
185     matcher.set_field(123);
186     FieldMatcher* child = matcher.add_child();
187     child->set_field(1);
188     child->set_position(Position::LAST);
189 
190     vector<Matcher> matchers;
191     translateFieldMatcher(matcher, &matchers);
192 
193     LogEvent event(/*uid=*/0, /*pid=*/0);
194     vector<int> intArray = {21, 9, 13};
195     makeRepeatedIntLogEvent(&event, 123, intArray);
196 
197     HashableDimensionKey output;
198     EXPECT_TRUE(filterValues(matchers, event.getValues(), &output));
199 
200     ASSERT_EQ((size_t)1, output.getValues().size());
201     EXPECT_EQ((int32_t)0x01018000, output.getValues()[0].mField.getField());
202     EXPECT_EQ((int32_t)13, output.getValues()[0].mValue.int_value);
203 }
204 
TEST(AtomMatcherTest,TestFilterRepeated_ALL)205 TEST(AtomMatcherTest, TestFilterRepeated_ALL) {
206     FieldMatcher matcher;
207     matcher.set_field(123);
208     FieldMatcher* child = matcher.add_child();
209     child->set_field(1);
210     child->set_position(Position::ALL);
211 
212     vector<Matcher> matchers;
213     translateFieldMatcher(matcher, &matchers);
214 
215     LogEvent event(/*uid=*/0, /*pid=*/0);
216     vector<int> intArray = {21, 9, 13};
217     makeRepeatedIntLogEvent(&event, 123, intArray);
218 
219     HashableDimensionKey output;
220     EXPECT_TRUE(filterValues(matchers, event.getValues(), &output));
221 
222     ASSERT_EQ((size_t)3, output.getValues().size());
223     EXPECT_EQ((int32_t)0x01010100, output.getValues()[0].mField.getField());
224     EXPECT_EQ((int32_t)21, output.getValues()[0].mValue.int_value);
225     EXPECT_EQ((int32_t)0x01010200, output.getValues()[1].mField.getField());
226     EXPECT_EQ((int32_t)9, output.getValues()[1].mValue.int_value);
227     EXPECT_EQ((int32_t)0x01010300, output.getValues()[2].mField.getField());
228     EXPECT_EQ((int32_t)13, output.getValues()[2].mValue.int_value);
229 }
230 
TEST(AtomMatcherTest,TestFilterWithOneMatcher)231 TEST(AtomMatcherTest, TestFilterWithOneMatcher) {
232     FieldMatcher matcher;
233     matcher.set_field(10);
234     FieldMatcher* child = matcher.add_child();
235     child->set_field(2);
236 
237     vector<Matcher> matchers;
238     translateFieldMatcher(matcher, &matchers);
239 
240     std::vector<int> attributionUids = {1111, 2222, 3333};
241     std::vector<string> attributionTags = {"location1", "location2", "location3"};
242 
243     LogEvent event(/*uid=*/0, /*pid=*/0);
244     makeLogEvent(&event, 10 /*atomId*/, /*timestamp=*/1012345, attributionUids, attributionTags,
245                  "some value");
246     FieldValue value;
247 
248     EXPECT_TRUE(filterValues(matchers[0], event.getValues(), &value));
249     EXPECT_EQ((int32_t)0x20000, value.mField.getField());
250     EXPECT_EQ("some value", value.mValue.str_value);
251 }
252 
TEST(AtomMatcherTest,TestFilterWithOneMatcher_PositionFIRST)253 TEST(AtomMatcherTest, TestFilterWithOneMatcher_PositionFIRST) {
254     FieldMatcher matcher;
255     matcher.set_field(10);
256     FieldMatcher* child = matcher.add_child();
257     child->set_field(1);
258     child->set_position(Position::FIRST);
259     child->add_child()->set_field(1);
260 
261     vector<Matcher> matchers;
262     translateFieldMatcher(matcher, &matchers);
263 
264     std::vector<int> attributionUids = {1111, 2222, 3333};
265     std::vector<string> attributionTags = {"location1", "location2", "location3"};
266 
267     LogEvent event(/*uid=*/0, /*pid=*/0);
268     makeLogEvent(&event, 10 /*atomId*/, /*timestamp=*/1012345, attributionUids, attributionTags,
269                  "some value");
270     FieldValue value;
271 
272     // Should only match the first field.
273     EXPECT_TRUE(filterValues(matchers[0], event.getValues(), &value));
274     EXPECT_EQ((int32_t)0x02010101, value.mField.getField());
275     EXPECT_EQ((int32_t)1111, value.mValue.int_value);
276 }
277 
TEST(AtomMatcherTest,TestFilterWithOneMatcher_PositionLAST)278 TEST(AtomMatcherTest, TestFilterWithOneMatcher_PositionLAST) {
279     FieldMatcher matcher;
280     matcher.set_field(10);
281     FieldMatcher* child = matcher.add_child();
282     child->set_field(1);
283     child->set_position(Position::LAST);
284     child->add_child()->set_field(1);
285 
286     vector<Matcher> matchers;
287     translateFieldMatcher(matcher, &matchers);
288 
289     std::vector<int> attributionUids = {1111, 2222, 3333};
290     std::vector<string> attributionTags = {"location1", "location2", "location3"};
291 
292     LogEvent event(/*uid=*/0, /*pid=*/0);
293     makeLogEvent(&event, 10 /*atomId*/, /*timestamp=*/1012345, attributionUids, attributionTags,
294                  "some value");
295     FieldValue value;
296 
297     // Should only match the last field.
298     EXPECT_TRUE(filterValues(matchers[0], event.getValues(), &value));
299     EXPECT_EQ((int32_t)0x02018301, value.mField.getField());
300     EXPECT_EQ((int32_t)3333, value.mValue.int_value);
301 }
302 
TEST(AtomMatcherTest,TestFilterWithOneMatcher_PositionALL)303 TEST(AtomMatcherTest, TestFilterWithOneMatcher_PositionALL) {
304     FieldMatcher matcher;
305     matcher.set_field(10);
306     FieldMatcher* child = matcher.add_child();
307     child->set_field(1);
308     child->set_position(Position::ALL);
309     child->add_child()->set_field(1);
310 
311     vector<Matcher> matchers;
312     translateFieldMatcher(matcher, &matchers);
313 
314     std::vector<int> attributionUids = {1111, 2222, 3333};
315     std::vector<string> attributionTags = {"location1", "location2", "location3"};
316 
317     LogEvent event(/*uid=*/0, /*pid=*/0);
318     makeLogEvent(&event, 10 /*atomId*/, 1012345, attributionUids, attributionTags, "some value");
319     FieldValue value;
320 
321     // Can't filter with position ALL matcher.
322     EXPECT_FALSE(filterValues(matchers[0], event.getValues(), &value));
323 }
324 
TEST(AtomMatcherTest,TestFilterWithOneMatcher_DifferentField)325 TEST(AtomMatcherTest, TestFilterWithOneMatcher_DifferentField) {
326     FieldMatcher matcher;
327     matcher.set_field(10);
328     FieldMatcher* child = matcher.add_child();
329     child->set_field(3);
330 
331     vector<Matcher> matchers;
332     translateFieldMatcher(matcher, &matchers);
333 
334     std::vector<int> attributionUids = {1111, 2222, 3333};
335     std::vector<string> attributionTags = {"location1", "location2", "location3"};
336 
337     LogEvent event(/*uid=*/0, /*pid=*/0);
338     makeLogEvent(&event, 10 /*atomId*/, /*timestamp=*/1012345, attributionUids, attributionTags,
339                  "some value");
340     FieldValue value;
341 
342     // Shouldn't match any fields because matcher is looking for field 3.
343     EXPECT_FALSE(filterValues(matchers[0], event.getValues(), &value));
344 }
345 
TEST(AtomMatcherTest,TestFilterWithOneMatcher_EmptyAttributionUids)346 TEST(AtomMatcherTest, TestFilterWithOneMatcher_EmptyAttributionUids) {
347     FieldMatcher matcher;
348     matcher.set_field(10);
349     FieldMatcher* child = matcher.add_child();
350     child->set_field(1);
351     child->set_position(Position::ALL);
352     child->add_child()->set_field(1);
353 
354     vector<Matcher> matchers;
355     translateFieldMatcher(matcher, &matchers);
356 
357     std::vector<string> attributionTags = {"location1", "location2", "location3"};
358 
359     LogEvent event(/*uid=*/0, /*pid=*/0);
360     makeLogEvent(&event, 10 /*atomId*/, /*timestamp=*/1012345, {}, attributionTags, "some value");
361     FieldValue value;
362 
363     // Shouldn't match any fields because field 1 is empty.
364     EXPECT_FALSE(filterValues(matchers[0], event.getValues(), &value));
365 }
366 
TEST(AtomMatcherTest,TestSubDimension)367 TEST(AtomMatcherTest, TestSubDimension) {
368     HashableDimensionKey dim;
369 
370     int pos1[] = {1, 1, 1};
371     int pos2[] = {1, 1, 2};
372     int pos3[] = {1, 1, 3};
373     int pos4[] = {2, 0, 0};
374     Field field1(10, pos1, 2);
375     Field field2(10, pos2, 2);
376 
377     Field field3(10, pos3, 2);
378     Field field4(10, pos4, 0);
379 
380     Value value1((int32_t)10025);
381     Value value2("tag");
382 
383     Value value11((int32_t)10026);
384     Value value22("tag2");
385 
386     dim.addValue(FieldValue(field1, value1));
387     dim.addValue(FieldValue(field2, value2));
388 
389     HashableDimensionKey subDim1;
390     subDim1.addValue(FieldValue(field1, value1));
391 
392     HashableDimensionKey subDim2;
393     subDim1.addValue(FieldValue(field2, value2));
394 
395     EXPECT_TRUE(dim.contains(dim));
396     EXPECT_TRUE(dim.contains(subDim1));
397     EXPECT_TRUE(dim.contains(subDim2));
398 
399     HashableDimensionKey subDim3;
400     subDim3.addValue(FieldValue(field1, value11));
401     EXPECT_FALSE(dim.contains(subDim3));
402 
403     HashableDimensionKey subDim4;
404     // Empty dimension is always a sub dimension of other dimensions
405     EXPECT_TRUE(dim.contains(subDim4));
406 }
407 
TEST(AtomMatcherTest,TestMetric2ConditionLink)408 TEST(AtomMatcherTest, TestMetric2ConditionLink) {
409     std::vector<int> attributionUids = {1111, 2222, 3333};
410     std::vector<string> attributionTags = {"location1", "location2", "location3"};
411 
412     LogEvent event(/*uid=*/0, /*pid=*/0);
413     makeLogEvent(&event, 10 /*atomId*/, 12345, attributionUids, attributionTags, "some value");
414 
415     FieldMatcher whatMatcher;
416     whatMatcher.set_field(10);
417     FieldMatcher* child11 = whatMatcher.add_child();
418     child11->set_field(1);
419     child11->set_position(Position::ANY);
420     child11 = child11->add_child();
421     child11->set_field(1);
422 
423     FieldMatcher conditionMatcher;
424     conditionMatcher.set_field(27);
425     FieldMatcher* child2 = conditionMatcher.add_child();
426     child2->set_field(2);
427     child2->set_position(Position::LAST);
428 
429     child2 = child2->add_child();
430     child2->set_field(2);
431 
432     Metric2Condition link;
433 
434     translateFieldMatcher(whatMatcher, &link.metricFields);
435     translateFieldMatcher(conditionMatcher, &link.conditionFields);
436 
437     ASSERT_EQ((size_t)1, link.metricFields.size());
438     EXPECT_EQ((int32_t)0x02010001, link.metricFields[0].mMatcher.getField());
439     EXPECT_EQ((int32_t)0xff7f007f, link.metricFields[0].mMask);
440     EXPECT_EQ((int32_t)10, link.metricFields[0].mMatcher.getTag());
441 
442     ASSERT_EQ((size_t)1, link.conditionFields.size());
443     EXPECT_EQ((int32_t)0x02028002, link.conditionFields[0].mMatcher.getField());
444     EXPECT_EQ((int32_t)0xff7f807f, link.conditionFields[0].mMask);
445     EXPECT_EQ((int32_t)27, link.conditionFields[0].mMatcher.getTag());
446 }
447 
TEST(AtomMatcherTest,TestWriteDimensionPath)448 TEST(AtomMatcherTest, TestWriteDimensionPath) {
449     for (auto position : {Position::ALL, Position::FIRST, Position::LAST}) {
450         FieldMatcher matcher1;
451         matcher1.set_field(10);
452 
453         // Repeated nested fields (attribution chain).
454         FieldMatcher* child = matcher1.add_child();
455         child->set_field(2);
456         child->set_position(position);
457         child->add_child()->set_field(1);
458         child->add_child()->set_field(3);
459 
460         // Primitive field.
461         child = matcher1.add_child();
462         child->set_field(4);
463 
464         // Repeated primitive field.
465         child = matcher1.add_child();
466         child->set_field(6);
467         child->set_position(position);
468 
469         vector<Matcher> matchers;
470         translateFieldMatcher(matcher1, &matchers);
471 
472         android::util::ProtoOutputStream protoOut;
473         writeDimensionPathToProto(matchers, &protoOut);
474 
475         vector<uint8_t> outData;
476         outData.resize(protoOut.size());
477         size_t pos = 0;
478         sp<ProtoReader> reader = protoOut.data();
479         while (reader->readBuffer() != NULL) {
480             size_t toRead = reader->currentToRead();
481             std::memcpy(&(outData[pos]), reader->readBuffer(), toRead);
482             pos += toRead;
483             reader->move(toRead);
484         }
485 
486         DimensionsValue result;
487         ASSERT_EQ(true, result.ParseFromArray(&outData[0], outData.size()));
488 
489         EXPECT_EQ(10, result.field());
490         EXPECT_EQ(DimensionsValue::ValueCase::kValueTuple, result.value_case());
491         ASSERT_EQ(3, result.value_tuple().dimensions_value_size());
492 
493         const auto& dim1 = result.value_tuple().dimensions_value(0);
494         EXPECT_EQ(2, dim1.field());
495         ASSERT_EQ(2, dim1.value_tuple().dimensions_value_size());
496 
497         const auto& dim11 = dim1.value_tuple().dimensions_value(0);
498         EXPECT_EQ(1, dim11.field());
499 
500         const auto& dim12 = dim1.value_tuple().dimensions_value(1);
501         EXPECT_EQ(3, dim12.field());
502 
503         const auto& dim2 = result.value_tuple().dimensions_value(1);
504         EXPECT_EQ(4, dim2.field());
505 
506         const auto& dim3 = result.value_tuple().dimensions_value(2);
507         EXPECT_EQ(6, dim3.field());
508     }
509 }
510 
checkAttributionNodeInDimensionsValueParcel(StatsDimensionsValueParcel & attributionNodeParcel,int32_t nodeDepthInAttributionChain,int32_t uid,string tag)511 void checkAttributionNodeInDimensionsValueParcel(StatsDimensionsValueParcel& attributionNodeParcel,
512                                                  int32_t nodeDepthInAttributionChain,
513                                                  int32_t uid, string tag) {
514     EXPECT_EQ(attributionNodeParcel.field, nodeDepthInAttributionChain /*position at depth 1*/);
515     ASSERT_EQ(attributionNodeParcel.valueType, STATS_DIMENSIONS_VALUE_TUPLE_TYPE);
516     ASSERT_EQ(attributionNodeParcel.tupleValue.size(), 2);
517 
518     StatsDimensionsValueParcel uidParcel = attributionNodeParcel.tupleValue[0];
519     EXPECT_EQ(uidParcel.field, 1 /*position at depth 2*/);
520     EXPECT_EQ(uidParcel.valueType, STATS_DIMENSIONS_VALUE_INT_TYPE);
521     EXPECT_EQ(uidParcel.intValue, uid);
522 
523     StatsDimensionsValueParcel tagParcel = attributionNodeParcel.tupleValue[1];
524     EXPECT_EQ(tagParcel.field, 2 /*position at depth 2*/);
525     EXPECT_EQ(tagParcel.valueType, STATS_DIMENSIONS_VALUE_STRING_TYPE);
526     EXPECT_EQ(tagParcel.stringValue, tag);
527 }
528 
529 // Test conversion of a HashableDimensionKey into a StatsDimensionValueParcel
TEST(AtomMatcherTest,TestSubscriberDimensionWrite)530 TEST(AtomMatcherTest, TestSubscriberDimensionWrite) {
531     int atomId = 10;
532     // First four fields form an attribution chain
533     int pos1[] = {1, 1, 1};
534     int pos2[] = {1, 1, 2};
535     int pos3[] = {1, 2, 1};
536     int pos4[] = {1, 2, 2};
537     int pos5[] = {2, 1, 1};
538 
539     Field field1(atomId, pos1, /*depth=*/2);
540     Field field2(atomId, pos2, /*depth=*/2);
541     Field field3(atomId, pos3, /*depth=*/2);
542     Field field4(atomId, pos4, /*depth=*/2);
543     Field field5(atomId, pos5, /*depth=*/0);
544 
545     Value value1((int32_t)1);
546     Value value2("string2");
547     Value value3((int32_t)3);
548     Value value4("string4");
549     Value value5((float)5.0);
550 
551     HashableDimensionKey dimensionKey;
552     dimensionKey.addValue(FieldValue(field1, value1));
553     dimensionKey.addValue(FieldValue(field2, value2));
554     dimensionKey.addValue(FieldValue(field3, value3));
555     dimensionKey.addValue(FieldValue(field4, value4));
556     dimensionKey.addValue(FieldValue(field5, value5));
557 
558     StatsDimensionsValueParcel rootParcel = dimensionKey.toStatsDimensionsValueParcel();
559     EXPECT_EQ(rootParcel.field, atomId);
560     ASSERT_EQ(rootParcel.valueType, STATS_DIMENSIONS_VALUE_TUPLE_TYPE);
561     ASSERT_EQ(rootParcel.tupleValue.size(), 2);
562 
563     // Check that attribution chain is populated correctly
564     StatsDimensionsValueParcel attributionChainParcel = rootParcel.tupleValue[0];
565     EXPECT_EQ(attributionChainParcel.field, 1 /*position at depth 0*/);
566     ASSERT_EQ(attributionChainParcel.valueType, STATS_DIMENSIONS_VALUE_TUPLE_TYPE);
567     ASSERT_EQ(attributionChainParcel.tupleValue.size(), 2);
568     checkAttributionNodeInDimensionsValueParcel(attributionChainParcel.tupleValue[0],
569                                                 /*nodeDepthInAttributionChain=*/1,
570                                                 value1.int_value, value2.str_value);
571     checkAttributionNodeInDimensionsValueParcel(attributionChainParcel.tupleValue[1],
572                                                 /*nodeDepthInAttributionChain=*/2,
573                                                 value3.int_value, value4.str_value);
574 
575     // Check that the float is populated correctly
576     StatsDimensionsValueParcel floatParcel = rootParcel.tupleValue[1];
577     EXPECT_EQ(floatParcel.field, 2 /*position at depth 0*/);
578     EXPECT_EQ(floatParcel.valueType, STATS_DIMENSIONS_VALUE_FLOAT_TYPE);
579     EXPECT_EQ(floatParcel.floatValue, value5.float_value);
580 }
581 
TEST(AtomMatcherTest,TestWriteDimensionToProto)582 TEST(AtomMatcherTest, TestWriteDimensionToProto) {
583     HashableDimensionKey dim;
584     int pos1[] = {1, 1, 1};
585     int pos2[] = {1, 1, 2};
586     int pos3[] = {1, 1, 3};
587     int pos4[] = {2, 0, 0};
588     Field field1(10, pos1, 2);
589     Field field2(10, pos2, 2);
590     Field field3(10, pos3, 2);
591     Field field4(10, pos4, 0);
592 
593     Value value1((int32_t)10025);
594     Value value2("tag");
595     Value value3((int32_t)987654);
596     Value value4((int32_t)99999);
597 
598     dim.addValue(FieldValue(field1, value1));
599     dim.addValue(FieldValue(field2, value2));
600     dim.addValue(FieldValue(field3, value3));
601     dim.addValue(FieldValue(field4, value4));
602 
603     android::util::ProtoOutputStream protoOut;
604     writeDimensionToProto(dim, nullptr /* include strings */, &protoOut);
605 
606     vector<uint8_t> outData;
607     outData.resize(protoOut.size());
608     size_t pos = 0;
609     sp<ProtoReader> reader = protoOut.data();
610     while (reader->readBuffer() != NULL) {
611         size_t toRead = reader->currentToRead();
612         std::memcpy(&(outData[pos]), reader->readBuffer(), toRead);
613         pos += toRead;
614         reader->move(toRead);
615     }
616 
617     DimensionsValue result;
618     ASSERT_EQ(true, result.ParseFromArray(&outData[0], outData.size()));
619     EXPECT_EQ(10, result.field());
620     EXPECT_EQ(DimensionsValue::ValueCase::kValueTuple, result.value_case());
621     ASSERT_EQ(2, result.value_tuple().dimensions_value_size());
622 
623     const auto& dim1 = result.value_tuple().dimensions_value(0);
624     EXPECT_EQ(DimensionsValue::ValueCase::kValueTuple, dim1.value_case());
625     ASSERT_EQ(3, dim1.value_tuple().dimensions_value_size());
626 
627     const auto& dim11 = dim1.value_tuple().dimensions_value(0);
628     EXPECT_EQ(DimensionsValue::ValueCase::kValueInt, dim11.value_case());
629     EXPECT_EQ(10025, dim11.value_int());
630 
631     const auto& dim12 = dim1.value_tuple().dimensions_value(1);
632     EXPECT_EQ(DimensionsValue::ValueCase::kValueStr, dim12.value_case());
633     EXPECT_EQ("tag", dim12.value_str());
634 
635     const auto& dim13 = dim1.value_tuple().dimensions_value(2);
636     EXPECT_EQ(DimensionsValue::ValueCase::kValueInt, dim13.value_case());
637     EXPECT_EQ(987654, dim13.value_int());
638 
639     const auto& dim2 = result.value_tuple().dimensions_value(1);
640     EXPECT_EQ(DimensionsValue::ValueCase::kValueInt, dim2.value_case());
641     EXPECT_EQ(99999, dim2.value_int());
642 }
643 
TEST(AtomMatcherTest,TestWriteDimensionLeafNodesToProto)644 TEST(AtomMatcherTest, TestWriteDimensionLeafNodesToProto) {
645     HashableDimensionKey dim;
646     int pos1[] = {1, 1, 1};
647     int pos2[] = {1, 1, 2};
648     int pos3[] = {1, 1, 3};
649     int pos4[] = {2, 0, 0};
650     Field field1(10, pos1, 2);
651     Field field2(10, pos2, 2);
652     Field field3(10, pos3, 2);
653     Field field4(10, pos4, 0);
654 
655     Value value1((int32_t)10025);
656     Value value2("tag");
657     Value value3((int32_t)987654);
658     Value value4((int64_t)99999);
659 
660     dim.addValue(FieldValue(field1, value1));
661     dim.addValue(FieldValue(field2, value2));
662     dim.addValue(FieldValue(field3, value3));
663     dim.addValue(FieldValue(field4, value4));
664 
665     android::util::ProtoOutputStream protoOut;
666     writeDimensionLeafNodesToProto(dim, 1, nullptr /* include strings */, &protoOut);
667 
668     vector<uint8_t> outData;
669     outData.resize(protoOut.size());
670     size_t pos = 0;
671     sp<ProtoReader> reader = protoOut.data();
672     while (reader->readBuffer() != NULL) {
673         size_t toRead = reader->currentToRead();
674         std::memcpy(&(outData[pos]), reader->readBuffer(), toRead);
675         pos += toRead;
676         reader->move(toRead);
677     }
678 
679     DimensionsValueTuple result;
680     ASSERT_EQ(true, result.ParseFromArray(&outData[0], outData.size()));
681     ASSERT_EQ(4, result.dimensions_value_size());
682 
683     const auto& dim1 = result.dimensions_value(0);
684     EXPECT_EQ(DimensionsValue::ValueCase::kValueInt, dim1.value_case());
685     EXPECT_EQ(10025, dim1.value_int());
686 
687     const auto& dim2 = result.dimensions_value(1);
688     EXPECT_EQ(DimensionsValue::ValueCase::kValueStr, dim2.value_case());
689     EXPECT_EQ("tag", dim2.value_str());
690 
691     const auto& dim3 = result.dimensions_value(2);
692     EXPECT_EQ(DimensionsValue::ValueCase::kValueInt, dim3.value_case());
693     EXPECT_EQ(987654, dim3.value_int());
694 
695     const auto& dim4 = result.dimensions_value(3);
696     EXPECT_EQ(DimensionsValue::ValueCase::kValueLong, dim4.value_case());
697     EXPECT_EQ(99999, dim4.value_long());
698 }
699 
TEST(AtomMatcherTest,TestWriteAtomToProto)700 TEST(AtomMatcherTest, TestWriteAtomToProto) {
701     std::vector<int> attributionUids = {1111, 2222};
702     std::vector<string> attributionTags = {"location1", "location2"};
703 
704     LogEvent event(/*uid=*/0, /*pid=*/0);
705     makeLogEvent(&event, 4 /*atomId*/, 12345, attributionUids, attributionTags, 999);
706 
707     android::util::ProtoOutputStream protoOutput;
708     writeFieldValueTreeToStream(event.GetTagId(), event.getValues(), &protoOutput);
709 
710     vector<uint8_t> outData;
711     outData.resize(protoOutput.size());
712     size_t pos = 0;
713     sp<ProtoReader> reader = protoOutput.data();
714     while (reader->readBuffer() != NULL) {
715         size_t toRead = reader->currentToRead();
716         std::memcpy(&(outData[pos]), reader->readBuffer(), toRead);
717         pos += toRead;
718         reader->move(toRead);
719     }
720 
721     Atom result;
722     ASSERT_EQ(true, result.ParseFromArray(&outData[0], outData.size()));
723     EXPECT_EQ(Atom::PushedCase::kBleScanResultReceived, result.pushed_case());
724     const auto& atom = result.ble_scan_result_received();
725     ASSERT_EQ(2, atom.attribution_node_size());
726     EXPECT_EQ(1111, atom.attribution_node(0).uid());
727     EXPECT_EQ("location1", atom.attribution_node(0).tag());
728     EXPECT_EQ(2222, atom.attribution_node(1).uid());
729     EXPECT_EQ("location2", atom.attribution_node(1).tag());
730     EXPECT_EQ(999, atom.num_results());
731 }
732 
TEST(AtomMatcherTest,TestWriteAtomWithRepeatedFieldsToProto)733 TEST(AtomMatcherTest, TestWriteAtomWithRepeatedFieldsToProto) {
734     vector<int> intArray = {3, 6};
735     vector<int64_t> longArray = {1000L, 10002L};
736     vector<float> floatArray = {0.3f, 0.09f};
737     vector<string> stringArray = {"str1", "str2"};
738     int boolArrayLength = 2;
739     bool boolArray[boolArrayLength];
740     boolArray[0] = 1;
741     boolArray[1] = 0;
742     vector<bool> boolArrayVector = {1, 0};
743     vector<int> enumArray = {TestAtomReported::ON, TestAtomReported::OFF};
744 
745     unique_ptr<LogEvent> event = CreateTestAtomReportedEventVariableRepeatedFields(
746             12345, intArray, longArray, floatArray, stringArray, boolArray, boolArrayLength,
747             enumArray);
748 
749     android::util::ProtoOutputStream protoOutput;
750     writeFieldValueTreeToStream(event->GetTagId(), event->getValues(), &protoOutput);
751 
752     vector<uint8_t> outData;
753     outData.resize(protoOutput.size());
754     size_t pos = 0;
755     sp<ProtoReader> reader = protoOutput.data();
756     while (reader->readBuffer() != NULL) {
757         size_t toRead = reader->currentToRead();
758         std::memcpy(&(outData[pos]), reader->readBuffer(), toRead);
759         pos += toRead;
760         reader->move(toRead);
761     }
762 
763     Atom result;
764     ASSERT_EQ(true, result.ParseFromArray(&outData[0], outData.size()));
765     EXPECT_EQ(Atom::PushedCase::kTestAtomReported, result.pushed_case());
766     TestAtomReported atom = result.test_atom_reported();
767     EXPECT_THAT(atom.repeated_int_field(), ElementsAreArray(intArray));
768     EXPECT_THAT(atom.repeated_long_field(), ElementsAreArray(longArray));
769     EXPECT_THAT(atom.repeated_float_field(), ElementsAreArray(floatArray));
770     EXPECT_THAT(atom.repeated_string_field(), ElementsAreArray(stringArray));
771     EXPECT_THAT(atom.repeated_boolean_field(), ElementsAreArray(boolArrayVector));
772     EXPECT_THAT(atom.repeated_enum_field(), ElementsAreArray(enumArray));
773 }
774 
775 /*
776  * Test two Matchers is not a subset of one Matcher.
777  * Test one Matcher is subset of two Matchers.
778  */
TEST(AtomMatcherTest,TestSubsetDimensions1)779 TEST(AtomMatcherTest, TestSubsetDimensions1) {
780     // Initialize first set of matchers
781     FieldMatcher matcher1;
782     matcher1.set_field(10);
783 
784     FieldMatcher* child = matcher1.add_child();
785     child->set_field(1);
786     child->set_position(Position::ALL);
787     child->add_child()->set_field(1);
788     child->add_child()->set_field(2);
789 
790     vector<Matcher> matchers1;
791     translateFieldMatcher(matcher1, &matchers1);
792     ASSERT_EQ(2, matchers1.size());
793 
794     // Initialize second set of matchers
795     FieldMatcher matcher2;
796     matcher2.set_field(10);
797 
798     child = matcher2.add_child();
799     child->set_field(1);
800     child->set_position(Position::ALL);
801     child->add_child()->set_field(1);
802 
803     vector<Matcher> matchers2;
804     translateFieldMatcher(matcher2, &matchers2);
805     ASSERT_EQ(1, matchers2.size());
806 
807     EXPECT_FALSE(subsetDimensions(matchers1, matchers2));
808     EXPECT_TRUE(subsetDimensions(matchers2, matchers1));
809 }
810 /*
811  * Test not a subset with one matching Matcher, one non-matching Matcher.
812  */
TEST(AtomMatcherTest,TestSubsetDimensions2)813 TEST(AtomMatcherTest, TestSubsetDimensions2) {
814     // Initialize first set of matchers
815     FieldMatcher matcher1;
816     matcher1.set_field(10);
817 
818     FieldMatcher* child = matcher1.add_child();
819     child->set_field(1);
820 
821     child = matcher1.add_child();
822     child->set_field(2);
823 
824     vector<Matcher> matchers1;
825     translateFieldMatcher(matcher1, &matchers1);
826 
827     // Initialize second set of matchers
828     FieldMatcher matcher2;
829     matcher2.set_field(10);
830 
831     child = matcher2.add_child();
832     child->set_field(1);
833 
834     child = matcher2.add_child();
835     child->set_field(3);
836 
837     vector<Matcher> matchers2;
838     translateFieldMatcher(matcher2, &matchers2);
839 
840     EXPECT_FALSE(subsetDimensions(matchers1, matchers2));
841 }
842 
843 /*
844  * Test not a subset if parent field is not equal.
845  */
TEST(AtomMatcherTest,TestSubsetDimensions3)846 TEST(AtomMatcherTest, TestSubsetDimensions3) {
847     // Initialize first set of matchers
848     FieldMatcher matcher1;
849     matcher1.set_field(10);
850 
851     FieldMatcher* child = matcher1.add_child();
852     child->set_field(1);
853 
854     vector<Matcher> matchers1;
855     translateFieldMatcher(matcher1, &matchers1);
856 
857     // Initialize second set of matchers
858     FieldMatcher matcher2;
859     matcher2.set_field(5);
860 
861     child = matcher2.add_child();
862     child->set_field(1);
863 
864     vector<Matcher> matchers2;
865     translateFieldMatcher(matcher2, &matchers2);
866 
867     EXPECT_FALSE(subsetDimensions(matchers1, matchers2));
868 }
869 
870 /*
871  * Test is subset with two matching Matchers.
872  */
TEST(AtomMatcherTest,TestSubsetDimensions4)873 TEST(AtomMatcherTest, TestSubsetDimensions4) {
874     // Initialize first set of matchers
875     FieldMatcher matcher1;
876     matcher1.set_field(10);
877 
878     FieldMatcher* child = matcher1.add_child();
879     child->set_field(1);
880 
881     child = matcher1.add_child();
882     child->set_field(2);
883 
884     vector<Matcher> matchers1;
885     translateFieldMatcher(matcher1, &matchers1);
886 
887     // Initialize second set of matchers
888     FieldMatcher matcher2;
889     matcher2.set_field(10);
890 
891     child = matcher2.add_child();
892     child->set_field(1);
893 
894     child = matcher2.add_child();
895     child->set_field(2);
896 
897     child = matcher2.add_child();
898     child->set_field(3);
899 
900     vector<Matcher> matchers2;
901     translateFieldMatcher(matcher2, &matchers2);
902 
903     EXPECT_TRUE(subsetDimensions(matchers1, matchers2));
904     EXPECT_FALSE(subsetDimensions(matchers2, matchers1));
905 }
906 
TEST(AtomMatcherTest,TestIsPrimitiveRepeatedField)907 TEST(AtomMatcherTest, TestIsPrimitiveRepeatedField) {
908     int pos1[] = {1, 1, 1};  // attribution uid
909     int pos2[] = {1, 1, 2};  // attribution tag
910     int pos3[] = {1, 2, 1};  // attribution uid - second node
911     int pos4[] = {1, 2, 2};  // attribution tag - second node
912     int pos5[] = {2, 1, 1};  // repeated field first element
913     int pos6[] = {2, 2, 1};  // repeated field second element
914     int pos7[] = {3, 1, 1};  // top-level field
915     Field field1(10, pos1, 2);
916     Field field2(10, pos2, 2);
917     Field field3(10, pos3, 2);
918     Field field4(10, pos4, 2);
919     Field field5(10, pos5, 1);
920     Field field6(10, pos6, 1);
921     Field field7(10, pos7, 0);
922 
923     EXPECT_FALSE(isPrimitiveRepeatedField(field1));
924     EXPECT_FALSE(isPrimitiveRepeatedField(field2));
925     EXPECT_FALSE(isPrimitiveRepeatedField(field3));
926     EXPECT_FALSE(isPrimitiveRepeatedField(field4));
927     EXPECT_TRUE(isPrimitiveRepeatedField(field5));
928     EXPECT_TRUE(isPrimitiveRepeatedField(field6));
929     EXPECT_FALSE(isPrimitiveRepeatedField(field7));
930 }
931 
TEST(FieldValueTest,TestShouldKeepSampleInt)932 TEST(FieldValueTest, TestShouldKeepSampleInt) {
933     int shardOffset = 5;
934     int shardCount = 2;
935     int pos1[] = {1, 1, 1};
936 
937     Field field(1, pos1, 2);
938 
939     Value value1((int32_t)1001);
940     Value value2((int32_t)1002);
941 
942     FieldValue fieldValue1(field, value1);
943     FieldValue fieldValue2(field, value2);
944 
945     EXPECT_TRUE(shouldKeepSample(fieldValue1, shardOffset, shardCount));
946     EXPECT_FALSE(shouldKeepSample(fieldValue2, shardOffset, shardCount));
947 }
948 
TEST(FieldValueTest,TestShouldKeepSampleLong)949 TEST(FieldValueTest, TestShouldKeepSampleLong) {
950     int shardOffset = 5;
951     int shardCount = 2;
952     int pos1[] = {1, 1, 1};
953 
954     Field field(1, pos1, 2);
955 
956     Value value1((int64_t)1001L);
957     Value value2((int64_t)1005L);
958 
959     FieldValue fieldValue1(field, value1);
960     FieldValue fieldValue2(field, value2);
961 
962     EXPECT_FALSE(shouldKeepSample(fieldValue1, shardOffset, shardCount));
963     EXPECT_TRUE(shouldKeepSample(fieldValue2, shardOffset, shardCount));
964 }
965 
TEST(FieldValueTest,TestShouldKeepSampleFloat)966 TEST(FieldValueTest, TestShouldKeepSampleFloat) {
967     int shardOffset = 5;
968     int shardCount = 2;
969     int pos1[] = {1, 1, 1};
970 
971     Field field(1, pos1, 2);
972 
973     Value value1((float)10.5);
974     Value value2((float)3.9);
975 
976     FieldValue fieldValue1(field, value1);
977     FieldValue fieldValue2(field, value2);
978 
979     EXPECT_TRUE(shouldKeepSample(fieldValue1, shardOffset, shardCount));
980     EXPECT_FALSE(shouldKeepSample(fieldValue2, shardOffset, shardCount));
981 }
982 
TEST(FieldValueTest,TestShouldKeepSampleDouble)983 TEST(FieldValueTest, TestShouldKeepSampleDouble) {
984     int shardOffset = 5;
985     int shardCount = 2;
986     int pos1[] = {1, 1, 1};
987 
988     Field field(1, pos1, 2);
989 
990     Value value1((double)1.5);
991     Value value2((double)3.9);
992 
993     FieldValue fieldValue1(field, value1);
994     FieldValue fieldValue2(field, value2);
995 
996     EXPECT_TRUE(shouldKeepSample(fieldValue1, shardOffset, shardCount));
997     EXPECT_FALSE(shouldKeepSample(fieldValue2, shardOffset, shardCount));
998 }
999 
TEST(FieldValueTest,TestShouldKeepSampleString)1000 TEST(FieldValueTest, TestShouldKeepSampleString) {
1001     int shardOffset = 5;
1002     int shardCount = 2;
1003     int pos1[] = {1, 1, 1};
1004 
1005     Field field(1, pos1, 2);
1006 
1007     Value value1("str1");
1008     Value value2("str2");
1009 
1010     FieldValue fieldValue1(field, value1);
1011     FieldValue fieldValue2(field, value2);
1012 
1013     EXPECT_FALSE(shouldKeepSample(fieldValue1, shardOffset, shardCount));
1014     EXPECT_TRUE(shouldKeepSample(fieldValue2, shardOffset, shardCount));
1015 }
1016 
TEST(FieldValueTest,TestShouldKeepSampleByteArray)1017 TEST(FieldValueTest, TestShouldKeepSampleByteArray) {
1018     int shardOffset = 5;
1019     int shardCount = 2;
1020     int pos1[] = {1, 1, 1};
1021 
1022     Field field(1, pos1, 2);
1023 
1024     vector<uint8_t> message1 = {'\t', 'e', '\0', 's', 't'};
1025     vector<uint8_t> message2 = {'\t', 'e', '\0', 's', 't', 't'};
1026 
1027     Value value1(message1);
1028     Value value2(message2);
1029 
1030     FieldValue fieldValue1(field, value1);
1031     FieldValue fieldValue2(field, value2);
1032 
1033     EXPECT_FALSE(shouldKeepSample(fieldValue1, shardOffset, shardCount));
1034     EXPECT_TRUE(shouldKeepSample(fieldValue2, shardOffset, shardCount));
1035 }
1036 
1037 }  // namespace statsd
1038 }  // namespace os
1039 }  // namespace android
1040 #else
1041 GTEST_LOG_(INFO) << "This test does nothing.\n";
1042 #endif
1043