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