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