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