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 {
makeLogEvent(LogEvent * logEvent,const int32_t atomId,const int64_t timestamp,const vector<int> & attributionUids,const vector<string> & attributionTags,const string & name)37 void makeLogEvent(LogEvent* logEvent, const int32_t atomId, const int64_t timestamp,
38 const vector<int>& attributionUids, const vector<string>& attributionTags,
39 const string& name) {
40 AStatsEvent* statsEvent = AStatsEvent_obtain();
41 AStatsEvent_setAtomId(statsEvent, atomId);
42 AStatsEvent_overwriteTimestamp(statsEvent, timestamp);
43
44 writeAttribution(statsEvent, attributionUids, attributionTags);
45 AStatsEvent_writeString(statsEvent, name.c_str());
46
47 parseStatsEventToLogEvent(statsEvent, logEvent);
48 }
49
makeLogEvent(LogEvent * logEvent,const int32_t atomId,const int64_t timestamp,const vector<int> & attributionUids,const vector<string> & attributionTags,const int32_t value)50 void makeLogEvent(LogEvent* logEvent, const int32_t atomId, const int64_t timestamp,
51 const vector<int>& attributionUids, const vector<string>& attributionTags,
52 const int32_t value) {
53 AStatsEvent* statsEvent = AStatsEvent_obtain();
54 AStatsEvent_setAtomId(statsEvent, atomId);
55 AStatsEvent_overwriteTimestamp(statsEvent, timestamp);
56
57 writeAttribution(statsEvent, attributionUids, attributionTags);
58 AStatsEvent_writeInt32(statsEvent, value);
59
60 parseStatsEventToLogEvent(statsEvent, logEvent);
61 }
62 } // anonymous namespace
63
TEST(AtomMatcherTest,TestFieldTranslation)64 TEST(AtomMatcherTest, TestFieldTranslation) {
65 FieldMatcher matcher1;
66 matcher1.set_field(10);
67 FieldMatcher* child = matcher1.add_child();
68 child->set_field(1);
69 child->set_position(Position::ANY);
70
71 child = child->add_child();
72 child->set_field(1);
73
74 vector<Matcher> output;
75 translateFieldMatcher(matcher1, &output);
76
77 ASSERT_EQ((size_t)1, output.size());
78
79 const auto& matcher12 = output[0];
80 EXPECT_EQ((int32_t)10, matcher12.mMatcher.getTag());
81 EXPECT_EQ((int32_t)0x02010001, matcher12.mMatcher.getField());
82 EXPECT_EQ((int32_t)0xff7f007f, matcher12.mMask);
83 }
84
TEST(AtomMatcherTest,TestFieldTranslation_ALL)85 TEST(AtomMatcherTest, TestFieldTranslation_ALL) {
86 FieldMatcher matcher1;
87 matcher1.set_field(10);
88 FieldMatcher* child = matcher1.add_child();
89 child->set_field(1);
90 child->set_position(Position::ALL);
91
92 child = child->add_child();
93 child->set_field(1);
94
95 vector<Matcher> output;
96 translateFieldMatcher(matcher1, &output);
97
98 ASSERT_EQ((size_t)1, output.size());
99
100 const auto& matcher12 = output[0];
101 EXPECT_EQ((int32_t)10, matcher12.mMatcher.getTag());
102 EXPECT_EQ((int32_t)0x02010001, matcher12.mMatcher.getField());
103 EXPECT_EQ((int32_t)0xff7f7f7f, matcher12.mMask);
104 }
105
TEST(AtomMatcherTest,TestFilter_ALL)106 TEST(AtomMatcherTest, TestFilter_ALL) {
107 FieldMatcher matcher1;
108 matcher1.set_field(10);
109 FieldMatcher* child = matcher1.add_child();
110 child->set_field(1);
111 child->set_position(Position::ALL);
112
113 child->add_child()->set_field(1);
114 child->add_child()->set_field(2);
115
116 child = matcher1.add_child();
117 child->set_field(2);
118
119 vector<Matcher> matchers;
120 translateFieldMatcher(matcher1, &matchers);
121
122 std::vector<int> attributionUids = {1111, 2222, 3333};
123 std::vector<string> attributionTags = {"location1", "location2", "location3"};
124
125 LogEvent event(/*uid=*/0, /*pid=*/0);
126 makeLogEvent(&event, 10 /*atomId*/, 1012345, attributionUids, attributionTags, "some value");
127 HashableDimensionKey output;
128
129 filterValues(matchers, event.getValues(), &output);
130
131 ASSERT_EQ((size_t)7, output.getValues().size());
132 EXPECT_EQ((int32_t)0x02010101, output.getValues()[0].mField.getField());
133 EXPECT_EQ((int32_t)1111, output.getValues()[0].mValue.int_value);
134 EXPECT_EQ((int32_t)0x02010102, output.getValues()[1].mField.getField());
135 EXPECT_EQ("location1", output.getValues()[1].mValue.str_value);
136
137 EXPECT_EQ((int32_t)0x02010201, output.getValues()[2].mField.getField());
138 EXPECT_EQ((int32_t)2222, output.getValues()[2].mValue.int_value);
139 EXPECT_EQ((int32_t)0x02010202, output.getValues()[3].mField.getField());
140 EXPECT_EQ("location2", output.getValues()[3].mValue.str_value);
141
142 EXPECT_EQ((int32_t)0x02010301, output.getValues()[4].mField.getField());
143 EXPECT_EQ((int32_t)3333, output.getValues()[4].mValue.int_value);
144 EXPECT_EQ((int32_t)0x02010302, output.getValues()[5].mField.getField());
145 EXPECT_EQ("location3", output.getValues()[5].mValue.str_value);
146
147 EXPECT_EQ((int32_t)0x00020000, output.getValues()[6].mField.getField());
148 EXPECT_EQ("some value", output.getValues()[6].mValue.str_value);
149 }
150
TEST(AtomMatcherTest,TestSubDimension)151 TEST(AtomMatcherTest, TestSubDimension) {
152 HashableDimensionKey dim;
153
154 int pos1[] = {1, 1, 1};
155 int pos2[] = {1, 1, 2};
156 int pos3[] = {1, 1, 3};
157 int pos4[] = {2, 0, 0};
158 Field field1(10, pos1, 2);
159 Field field2(10, pos2, 2);
160
161 Field field3(10, pos3, 2);
162 Field field4(10, pos4, 0);
163
164 Value value1((int32_t)10025);
165 Value value2("tag");
166
167 Value value11((int32_t)10026);
168 Value value22("tag2");
169
170 dim.addValue(FieldValue(field1, value1));
171 dim.addValue(FieldValue(field2, value2));
172
173 HashableDimensionKey subDim1;
174 subDim1.addValue(FieldValue(field1, value1));
175
176 HashableDimensionKey subDim2;
177 subDim1.addValue(FieldValue(field2, value2));
178
179 EXPECT_TRUE(dim.contains(dim));
180 EXPECT_TRUE(dim.contains(subDim1));
181 EXPECT_TRUE(dim.contains(subDim2));
182
183 HashableDimensionKey subDim3;
184 subDim3.addValue(FieldValue(field1, value11));
185 EXPECT_FALSE(dim.contains(subDim3));
186
187 HashableDimensionKey subDim4;
188 // Empty dimension is always a sub dimension of other dimensions
189 EXPECT_TRUE(dim.contains(subDim4));
190 }
191
TEST(AtomMatcherTest,TestMetric2ConditionLink)192 TEST(AtomMatcherTest, TestMetric2ConditionLink) {
193 std::vector<int> attributionUids = {1111, 2222, 3333};
194 std::vector<string> attributionTags = {"location1", "location2", "location3"};
195
196 LogEvent event(/*uid=*/0, /*pid=*/0);
197 makeLogEvent(&event, 10 /*atomId*/, 12345, attributionUids, attributionTags, "some value");
198
199 FieldMatcher whatMatcher;
200 whatMatcher.set_field(10);
201 FieldMatcher* child11 = whatMatcher.add_child();
202 child11->set_field(1);
203 child11->set_position(Position::ANY);
204 child11 = child11->add_child();
205 child11->set_field(1);
206
207 FieldMatcher conditionMatcher;
208 conditionMatcher.set_field(27);
209 FieldMatcher* child2 = conditionMatcher.add_child();
210 child2->set_field(2);
211 child2->set_position(Position::LAST);
212
213 child2 = child2->add_child();
214 child2->set_field(2);
215
216 Metric2Condition link;
217
218 translateFieldMatcher(whatMatcher, &link.metricFields);
219 translateFieldMatcher(conditionMatcher, &link.conditionFields);
220
221 ASSERT_EQ((size_t)1, link.metricFields.size());
222 EXPECT_EQ((int32_t)0x02010001, link.metricFields[0].mMatcher.getField());
223 EXPECT_EQ((int32_t)0xff7f007f, link.metricFields[0].mMask);
224 EXPECT_EQ((int32_t)10, link.metricFields[0].mMatcher.getTag());
225
226 ASSERT_EQ((size_t)1, link.conditionFields.size());
227 EXPECT_EQ((int32_t)0x02028002, link.conditionFields[0].mMatcher.getField());
228 EXPECT_EQ((int32_t)0xff7f807f, link.conditionFields[0].mMask);
229 EXPECT_EQ((int32_t)27, link.conditionFields[0].mMatcher.getTag());
230 }
231
TEST(AtomMatcherTest,TestWriteDimensionPath)232 TEST(AtomMatcherTest, TestWriteDimensionPath) {
233 for (auto position : {Position::ANY, Position::ALL, Position::FIRST, Position::LAST}) {
234 FieldMatcher matcher1;
235 matcher1.set_field(10);
236 FieldMatcher* child = matcher1.add_child();
237 child->set_field(2);
238 child->set_position(position);
239 child->add_child()->set_field(1);
240 child->add_child()->set_field(3);
241
242 child = matcher1.add_child();
243 child->set_field(4);
244
245 child = matcher1.add_child();
246 child->set_field(6);
247 child->add_child()->set_field(2);
248
249 vector<Matcher> matchers;
250 translateFieldMatcher(matcher1, &matchers);
251
252 android::util::ProtoOutputStream protoOut;
253 writeDimensionPathToProto(matchers, &protoOut);
254
255 vector<uint8_t> outData;
256 outData.resize(protoOut.size());
257 size_t pos = 0;
258 sp<ProtoReader> reader = protoOut.data();
259 while (reader->readBuffer() != NULL) {
260 size_t toRead = reader->currentToRead();
261 std::memcpy(&(outData[pos]), reader->readBuffer(), toRead);
262 pos += toRead;
263 reader->move(toRead);
264 }
265
266 DimensionsValue result;
267 ASSERT_EQ(true, result.ParseFromArray(&outData[0], outData.size()));
268
269 EXPECT_EQ(10, result.field());
270 EXPECT_EQ(DimensionsValue::ValueCase::kValueTuple, result.value_case());
271 ASSERT_EQ(3, result.value_tuple().dimensions_value_size());
272
273 const auto& dim1 = result.value_tuple().dimensions_value(0);
274 EXPECT_EQ(2, dim1.field());
275 ASSERT_EQ(2, dim1.value_tuple().dimensions_value_size());
276
277 const auto& dim11 = dim1.value_tuple().dimensions_value(0);
278 EXPECT_EQ(1, dim11.field());
279
280 const auto& dim12 = dim1.value_tuple().dimensions_value(1);
281 EXPECT_EQ(3, dim12.field());
282
283 const auto& dim2 = result.value_tuple().dimensions_value(1);
284 EXPECT_EQ(4, dim2.field());
285
286 const auto& dim3 = result.value_tuple().dimensions_value(2);
287 EXPECT_EQ(6, dim3.field());
288 ASSERT_EQ(1, dim3.value_tuple().dimensions_value_size());
289 const auto& dim31 = dim3.value_tuple().dimensions_value(0);
290 EXPECT_EQ(2, dim31.field());
291 }
292 }
293
checkAttributionNodeInDimensionsValueParcel(StatsDimensionsValueParcel & attributionNodeParcel,int32_t nodeDepthInAttributionChain,int32_t uid,string tag)294 void checkAttributionNodeInDimensionsValueParcel(StatsDimensionsValueParcel& attributionNodeParcel,
295 int32_t nodeDepthInAttributionChain,
296 int32_t uid, string tag) {
297 EXPECT_EQ(attributionNodeParcel.field, nodeDepthInAttributionChain /*position at depth 1*/);
298 ASSERT_EQ(attributionNodeParcel.valueType, STATS_DIMENSIONS_VALUE_TUPLE_TYPE);
299 ASSERT_EQ(attributionNodeParcel.tupleValue.size(), 2);
300
301 StatsDimensionsValueParcel uidParcel = attributionNodeParcel.tupleValue[0];
302 EXPECT_EQ(uidParcel.field, 1 /*position at depth 2*/);
303 EXPECT_EQ(uidParcel.valueType, STATS_DIMENSIONS_VALUE_INT_TYPE);
304 EXPECT_EQ(uidParcel.intValue, uid);
305
306 StatsDimensionsValueParcel tagParcel = attributionNodeParcel.tupleValue[1];
307 EXPECT_EQ(tagParcel.field, 2 /*position at depth 2*/);
308 EXPECT_EQ(tagParcel.valueType, STATS_DIMENSIONS_VALUE_STRING_TYPE);
309 EXPECT_EQ(tagParcel.stringValue, tag);
310 }
311
312 // Test conversion of a HashableDimensionKey into a StatsDimensionValueParcel
TEST(AtomMatcherTest,TestSubscriberDimensionWrite)313 TEST(AtomMatcherTest, TestSubscriberDimensionWrite) {
314 int atomId = 10;
315 // First four fields form an attribution chain
316 int pos1[] = {1, 1, 1};
317 int pos2[] = {1, 1, 2};
318 int pos3[] = {1, 2, 1};
319 int pos4[] = {1, 2, 2};
320 int pos5[] = {2, 1, 1};
321
322 Field field1(atomId, pos1, /*depth=*/2);
323 Field field2(atomId, pos2, /*depth=*/2);
324 Field field3(atomId, pos3, /*depth=*/2);
325 Field field4(atomId, pos4, /*depth=*/2);
326 Field field5(atomId, pos5, /*depth=*/0);
327
328 Value value1((int32_t)1);
329 Value value2("string2");
330 Value value3((int32_t)3);
331 Value value4("string4");
332 Value value5((float)5.0);
333
334 HashableDimensionKey dimensionKey;
335 dimensionKey.addValue(FieldValue(field1, value1));
336 dimensionKey.addValue(FieldValue(field2, value2));
337 dimensionKey.addValue(FieldValue(field3, value3));
338 dimensionKey.addValue(FieldValue(field4, value4));
339 dimensionKey.addValue(FieldValue(field5, value5));
340
341 StatsDimensionsValueParcel rootParcel = dimensionKey.toStatsDimensionsValueParcel();
342 EXPECT_EQ(rootParcel.field, atomId);
343 ASSERT_EQ(rootParcel.valueType, STATS_DIMENSIONS_VALUE_TUPLE_TYPE);
344 ASSERT_EQ(rootParcel.tupleValue.size(), 2);
345
346 // Check that attribution chain is populated correctly
347 StatsDimensionsValueParcel attributionChainParcel = rootParcel.tupleValue[0];
348 EXPECT_EQ(attributionChainParcel.field, 1 /*position at depth 0*/);
349 ASSERT_EQ(attributionChainParcel.valueType, STATS_DIMENSIONS_VALUE_TUPLE_TYPE);
350 ASSERT_EQ(attributionChainParcel.tupleValue.size(), 2);
351 checkAttributionNodeInDimensionsValueParcel(attributionChainParcel.tupleValue[0],
352 /*nodeDepthInAttributionChain=*/1,
353 value1.int_value, value2.str_value);
354 checkAttributionNodeInDimensionsValueParcel(attributionChainParcel.tupleValue[1],
355 /*nodeDepthInAttributionChain=*/2,
356 value3.int_value, value4.str_value);
357
358 // Check that the float is populated correctly
359 StatsDimensionsValueParcel floatParcel = rootParcel.tupleValue[1];
360 EXPECT_EQ(floatParcel.field, 2 /*position at depth 0*/);
361 EXPECT_EQ(floatParcel.valueType, STATS_DIMENSIONS_VALUE_FLOAT_TYPE);
362 EXPECT_EQ(floatParcel.floatValue, value5.float_value);
363 }
364
TEST(AtomMatcherTest,TestWriteDimensionToProto)365 TEST(AtomMatcherTest, TestWriteDimensionToProto) {
366 HashableDimensionKey dim;
367 int pos1[] = {1, 1, 1};
368 int pos2[] = {1, 1, 2};
369 int pos3[] = {1, 1, 3};
370 int pos4[] = {2, 0, 0};
371 Field field1(10, pos1, 2);
372 Field field2(10, pos2, 2);
373 Field field3(10, pos3, 2);
374 Field field4(10, pos4, 0);
375
376 Value value1((int32_t)10025);
377 Value value2("tag");
378 Value value3((int32_t)987654);
379 Value value4((int32_t)99999);
380
381 dim.addValue(FieldValue(field1, value1));
382 dim.addValue(FieldValue(field2, value2));
383 dim.addValue(FieldValue(field3, value3));
384 dim.addValue(FieldValue(field4, value4));
385
386 android::util::ProtoOutputStream protoOut;
387 writeDimensionToProto(dim, nullptr /* include strings */, &protoOut);
388
389 vector<uint8_t> outData;
390 outData.resize(protoOut.size());
391 size_t pos = 0;
392 sp<ProtoReader> reader = protoOut.data();
393 while (reader->readBuffer() != NULL) {
394 size_t toRead = reader->currentToRead();
395 std::memcpy(&(outData[pos]), reader->readBuffer(), toRead);
396 pos += toRead;
397 reader->move(toRead);
398 }
399
400 DimensionsValue result;
401 ASSERT_EQ(true, result.ParseFromArray(&outData[0], outData.size()));
402 EXPECT_EQ(10, result.field());
403 EXPECT_EQ(DimensionsValue::ValueCase::kValueTuple, result.value_case());
404 ASSERT_EQ(2, result.value_tuple().dimensions_value_size());
405
406 const auto& dim1 = result.value_tuple().dimensions_value(0);
407 EXPECT_EQ(DimensionsValue::ValueCase::kValueTuple, dim1.value_case());
408 ASSERT_EQ(3, dim1.value_tuple().dimensions_value_size());
409
410 const auto& dim11 = dim1.value_tuple().dimensions_value(0);
411 EXPECT_EQ(DimensionsValue::ValueCase::kValueInt, dim11.value_case());
412 EXPECT_EQ(10025, dim11.value_int());
413
414 const auto& dim12 = dim1.value_tuple().dimensions_value(1);
415 EXPECT_EQ(DimensionsValue::ValueCase::kValueStr, dim12.value_case());
416 EXPECT_EQ("tag", dim12.value_str());
417
418 const auto& dim13 = dim1.value_tuple().dimensions_value(2);
419 EXPECT_EQ(DimensionsValue::ValueCase::kValueInt, dim13.value_case());
420 EXPECT_EQ(987654, dim13.value_int());
421
422 const auto& dim2 = result.value_tuple().dimensions_value(1);
423 EXPECT_EQ(DimensionsValue::ValueCase::kValueInt, dim2.value_case());
424 EXPECT_EQ(99999, dim2.value_int());
425 }
426
TEST(AtomMatcherTest,TestWriteDimensionLeafNodesToProto)427 TEST(AtomMatcherTest, TestWriteDimensionLeafNodesToProto) {
428 HashableDimensionKey dim;
429 int pos1[] = {1, 1, 1};
430 int pos2[] = {1, 1, 2};
431 int pos3[] = {1, 1, 3};
432 int pos4[] = {2, 0, 0};
433 Field field1(10, pos1, 2);
434 Field field2(10, pos2, 2);
435 Field field3(10, pos3, 2);
436 Field field4(10, pos4, 0);
437
438 Value value1((int32_t)10025);
439 Value value2("tag");
440 Value value3((int32_t)987654);
441 Value value4((int64_t)99999);
442
443 dim.addValue(FieldValue(field1, value1));
444 dim.addValue(FieldValue(field2, value2));
445 dim.addValue(FieldValue(field3, value3));
446 dim.addValue(FieldValue(field4, value4));
447
448 android::util::ProtoOutputStream protoOut;
449 writeDimensionLeafNodesToProto(dim, 1, nullptr /* include strings */, &protoOut);
450
451 vector<uint8_t> outData;
452 outData.resize(protoOut.size());
453 size_t pos = 0;
454 sp<ProtoReader> reader = protoOut.data();
455 while (reader->readBuffer() != NULL) {
456 size_t toRead = reader->currentToRead();
457 std::memcpy(&(outData[pos]), reader->readBuffer(), toRead);
458 pos += toRead;
459 reader->move(toRead);
460 }
461
462 DimensionsValueTuple result;
463 ASSERT_EQ(true, result.ParseFromArray(&outData[0], outData.size()));
464 ASSERT_EQ(4, result.dimensions_value_size());
465
466 const auto& dim1 = result.dimensions_value(0);
467 EXPECT_EQ(DimensionsValue::ValueCase::kValueInt, dim1.value_case());
468 EXPECT_EQ(10025, dim1.value_int());
469
470 const auto& dim2 = result.dimensions_value(1);
471 EXPECT_EQ(DimensionsValue::ValueCase::kValueStr, dim2.value_case());
472 EXPECT_EQ("tag", dim2.value_str());
473
474 const auto& dim3 = result.dimensions_value(2);
475 EXPECT_EQ(DimensionsValue::ValueCase::kValueInt, dim3.value_case());
476 EXPECT_EQ(987654, dim3.value_int());
477
478 const auto& dim4 = result.dimensions_value(3);
479 EXPECT_EQ(DimensionsValue::ValueCase::kValueLong, dim4.value_case());
480 EXPECT_EQ(99999, dim4.value_long());
481 }
482
TEST(AtomMatcherTest,TestWriteAtomToProto)483 TEST(AtomMatcherTest, TestWriteAtomToProto) {
484 std::vector<int> attributionUids = {1111, 2222};
485 std::vector<string> attributionTags = {"location1", "location2"};
486
487 LogEvent event(/*uid=*/0, /*pid=*/0);
488 makeLogEvent(&event, 4 /*atomId*/, 12345, attributionUids, attributionTags, 999);
489
490 android::util::ProtoOutputStream protoOutput;
491 writeFieldValueTreeToStream(event.GetTagId(), event.getValues(), &protoOutput);
492
493 vector<uint8_t> outData;
494 outData.resize(protoOutput.size());
495 size_t pos = 0;
496 sp<ProtoReader> reader = protoOutput.data();
497 while (reader->readBuffer() != NULL) {
498 size_t toRead = reader->currentToRead();
499 std::memcpy(&(outData[pos]), reader->readBuffer(), toRead);
500 pos += toRead;
501 reader->move(toRead);
502 }
503
504 Atom result;
505 ASSERT_EQ(true, result.ParseFromArray(&outData[0], outData.size()));
506 EXPECT_EQ(Atom::PushedCase::kBleScanResultReceived, result.pushed_case());
507 const auto& atom = result.ble_scan_result_received();
508 ASSERT_EQ(2, atom.attribution_node_size());
509 EXPECT_EQ(1111, atom.attribution_node(0).uid());
510 EXPECT_EQ("location1", atom.attribution_node(0).tag());
511 EXPECT_EQ(2222, atom.attribution_node(1).uid());
512 EXPECT_EQ("location2", atom.attribution_node(1).tag());
513 EXPECT_EQ(999, atom.num_results());
514 }
515
516 /*
517 * Test two Matchers is not a subset of one Matcher.
518 * Test one Matcher is subset of two Matchers.
519 */
TEST(AtomMatcherTest,TestSubsetDimensions1)520 TEST(AtomMatcherTest, TestSubsetDimensions1) {
521 // Initialize first set of matchers
522 FieldMatcher matcher1;
523 matcher1.set_field(10);
524
525 FieldMatcher* child = matcher1.add_child();
526 child->set_field(1);
527 child->set_position(Position::ALL);
528 child->add_child()->set_field(1);
529 child->add_child()->set_field(2);
530
531 vector<Matcher> matchers1;
532 translateFieldMatcher(matcher1, &matchers1);
533 ASSERT_EQ(2, matchers1.size());
534
535 // Initialize second set of matchers
536 FieldMatcher matcher2;
537 matcher2.set_field(10);
538
539 child = matcher2.add_child();
540 child->set_field(1);
541 child->set_position(Position::ALL);
542 child->add_child()->set_field(1);
543
544 vector<Matcher> matchers2;
545 translateFieldMatcher(matcher2, &matchers2);
546 ASSERT_EQ(1, matchers2.size());
547
548 EXPECT_FALSE(subsetDimensions(matchers1, matchers2));
549 EXPECT_TRUE(subsetDimensions(matchers2, matchers1));
550 }
551 /*
552 * Test not a subset with one matching Matcher, one non-matching Matcher.
553 */
TEST(AtomMatcherTest,TestSubsetDimensions2)554 TEST(AtomMatcherTest, TestSubsetDimensions2) {
555 // Initialize first set of matchers
556 FieldMatcher matcher1;
557 matcher1.set_field(10);
558
559 FieldMatcher* child = matcher1.add_child();
560 child->set_field(1);
561
562 child = matcher1.add_child();
563 child->set_field(2);
564
565 vector<Matcher> matchers1;
566 translateFieldMatcher(matcher1, &matchers1);
567
568 // Initialize second set of matchers
569 FieldMatcher matcher2;
570 matcher2.set_field(10);
571
572 child = matcher2.add_child();
573 child->set_field(1);
574
575 child = matcher2.add_child();
576 child->set_field(3);
577
578 vector<Matcher> matchers2;
579 translateFieldMatcher(matcher2, &matchers2);
580
581 EXPECT_FALSE(subsetDimensions(matchers1, matchers2));
582 }
583
584 /*
585 * Test not a subset if parent field is not equal.
586 */
TEST(AtomMatcherTest,TestSubsetDimensions3)587 TEST(AtomMatcherTest, TestSubsetDimensions3) {
588 // Initialize first set of matchers
589 FieldMatcher matcher1;
590 matcher1.set_field(10);
591
592 FieldMatcher* child = matcher1.add_child();
593 child->set_field(1);
594
595 vector<Matcher> matchers1;
596 translateFieldMatcher(matcher1, &matchers1);
597
598 // Initialize second set of matchers
599 FieldMatcher matcher2;
600 matcher2.set_field(5);
601
602 child = matcher2.add_child();
603 child->set_field(1);
604
605 vector<Matcher> matchers2;
606 translateFieldMatcher(matcher2, &matchers2);
607
608 EXPECT_FALSE(subsetDimensions(matchers1, matchers2));
609 }
610
611 /*
612 * Test is subset with two matching Matchers.
613 */
TEST(AtomMatcherTest,TestSubsetDimensions4)614 TEST(AtomMatcherTest, TestSubsetDimensions4) {
615 // Initialize first set of matchers
616 FieldMatcher matcher1;
617 matcher1.set_field(10);
618
619 FieldMatcher* child = matcher1.add_child();
620 child->set_field(1);
621
622 child = matcher1.add_child();
623 child->set_field(2);
624
625 vector<Matcher> matchers1;
626 translateFieldMatcher(matcher1, &matchers1);
627
628 // Initialize second set of matchers
629 FieldMatcher matcher2;
630 matcher2.set_field(10);
631
632 child = matcher2.add_child();
633 child->set_field(1);
634
635 child = matcher2.add_child();
636 child->set_field(2);
637
638 child = matcher2.add_child();
639 child->set_field(3);
640
641 vector<Matcher> matchers2;
642 translateFieldMatcher(matcher2, &matchers2);
643
644 EXPECT_TRUE(subsetDimensions(matchers1, matchers2));
645 EXPECT_FALSE(subsetDimensions(matchers2, matchers1));
646 }
647
648 } // namespace statsd
649 } // namespace os
650 } // namespace android
651 #else
652 GTEST_LOG_(INFO) << "This test does nothing.\n";
653 #endif
654