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 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()); 48 EXPECT_EQ((int32_t)0x02010001, matcher12.mMatcher.getField()); 49 EXPECT_EQ((int32_t)0xff7f007f, matcher12.mMask); 50} 51 52TEST(AtomMatcherTest, TestFieldTranslation_ALL) { 53 FieldMatcher matcher1; 54 matcher1.set_field(10); 55 FieldMatcher* child = matcher1.add_child(); 56 child->set_field(1); 57 child->set_position(Position::ALL); 58 59 child = child->add_child(); 60 child->set_field(1); 61 62 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 83 child = matcher1.add_child(); 84 child->set_field(2); 85 86 vector<Matcher> matchers; 87 translateFieldMatcher(matcher1, &matchers); 88 89 AttributionNodeInternal attribution_node1; 90 attribution_node1.set_uid(1111); 91 attribution_node1.set_tag("location1"); 92 93 AttributionNodeInternal attribution_node2; 94 attribution_node2.set_uid(2222); 95 attribution_node2.set_tag("location2"); 96 97 AttributionNodeInternal attribution_node3; 98 attribution_node3.set_uid(3333); 99 attribution_node3.set_tag("location3"); 100 std::vector<AttributionNodeInternal> attribution_nodes = {attribution_node1, attribution_node2, 101 attribution_node3}; 102 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(); 109 HashableDimensionKey output; 110 111 filterValues(matchers, event.getValues(), &output); 112 113 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); 118 119 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); 123 124 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); 128 129 EXPECT_EQ((int32_t)0x00020000, output.getValues()[6].mField.getField()); 130 EXPECT_EQ("some value", output.getValues()[6].mValue.str_value); 131} 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) { 175 AttributionNodeInternal attribution_node1; 176 attribution_node1.set_uid(1111); 177 attribution_node1.set_tag("location1"); 178 179 AttributionNodeInternal attribution_node2; 180 attribution_node2.set_uid(2222); 181 attribution_node2.set_tag("location2"); 182 183 AttributionNodeInternal attribution_node3; 184 attribution_node3.set_uid(3333); 185 attribution_node3.set_tag("location3"); 186 std::vector<AttributionNodeInternal> attribution_nodes = {attribution_node1, attribution_node2, 187 attribution_node3}; 188 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 229TEST(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 291TEST(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); 315 // TODO: can't test anything here because SubscriberReport class doesn't have any read api. 316} 317 318TEST(AtomMatcherTest, TestWriteDimensionToProto) { 319 HashableDimensionKey dim; 320 int pos1[] = {1, 1, 1}; 321 int pos2[] = {1, 1, 2}; 322 int pos3[] = {1, 1, 3}; 323 int pos4[] = {2, 0, 0}; 324 Field field1(10, pos1, 2); 325 Field field2(10, pos2, 2); 326 Field field3(10, pos3, 2); 327 Field field4(10, pos4, 0); 328 329 Value value1((int32_t)10025); 330 Value value2("tag"); 331 Value value3((int32_t)987654); 332 Value value4((int32_t)99999); 333 334 dim.addValue(FieldValue(field1, value1)); 335 dim.addValue(FieldValue(field2, value2)); 336 dim.addValue(FieldValue(field3, value3)); 337 dim.addValue(FieldValue(field4, value4)); 338 339 android::util::ProtoOutputStream protoOut; 340 writeDimensionToProto(dim, nullptr /* include strings */, &protoOut); 341 342 vector<uint8_t> outData; 343 outData.resize(protoOut.size()); 344 size_t pos = 0; 345 auto iter = protoOut.data(); 346 while (iter.readBuffer() != NULL) { 347 size_t toRead = iter.currentToRead(); 348 std::memcpy(&(outData[pos]), iter.readBuffer(), toRead); 349 pos += toRead; 350 iter.rp()->move(toRead); 351 } 352 353 DimensionsValue result; 354 EXPECT_EQ(true, result.ParseFromArray(&outData[0], outData.size())); 355 EXPECT_EQ(10, result.field()); 356 EXPECT_EQ(DimensionsValue::ValueCase::kValueTuple, result.value_case()); 357 EXPECT_EQ(2, result.value_tuple().dimensions_value_size()); 358 359 const auto& dim1 = result.value_tuple().dimensions_value(0); 360 EXPECT_EQ(DimensionsValue::ValueCase::kValueTuple, dim1.value_case()); 361 EXPECT_EQ(3, dim1.value_tuple().dimensions_value_size()); 362 363 const auto& dim11 = dim1.value_tuple().dimensions_value(0); 364 EXPECT_EQ(DimensionsValue::ValueCase::kValueInt, dim11.value_case()); 365 EXPECT_EQ(10025, dim11.value_int()); 366 367 const auto& dim12 = dim1.value_tuple().dimensions_value(1); 368 EXPECT_EQ(DimensionsValue::ValueCase::kValueStr, dim12.value_case()); 369 EXPECT_EQ("tag", dim12.value_str()); 370 371 const auto& dim13 = dim1.value_tuple().dimensions_value(2); 372 EXPECT_EQ(DimensionsValue::ValueCase::kValueInt, dim13.value_case()); 373 EXPECT_EQ(987654, dim13.value_int()); 374 375 const auto& dim2 = result.value_tuple().dimensions_value(1); 376 EXPECT_EQ(DimensionsValue::ValueCase::kValueInt, dim2.value_case()); 377 EXPECT_EQ(99999, dim2.value_int()); 378} 379 380TEST(AtomMatcherTest, TestWriteDimensionLeafNodesToProto) { 381 HashableDimensionKey dim; 382 int pos1[] = {1, 1, 1}; 383 int pos2[] = {1, 1, 2}; 384 int pos3[] = {1, 1, 3}; 385 int pos4[] = {2, 0, 0}; 386 Field field1(10, pos1, 2); 387 Field field2(10, pos2, 2); 388 Field field3(10, pos3, 2); 389 Field field4(10, pos4, 0); 390 391 Value value1((int32_t)10025); 392 Value value2("tag"); 393 Value value3((int32_t)987654); 394 Value value4((int64_t)99999); 395 396 dim.addValue(FieldValue(field1, value1)); 397 dim.addValue(FieldValue(field2, value2)); 398 dim.addValue(FieldValue(field3, value3)); 399 dim.addValue(FieldValue(field4, value4)); 400 401 android::util::ProtoOutputStream protoOut; 402 writeDimensionLeafNodesToProto(dim, 1, nullptr /* include strings */, &protoOut); 403 404 vector<uint8_t> outData; 405 outData.resize(protoOut.size()); 406 size_t pos = 0; 407 auto iter = protoOut.data(); 408 while (iter.readBuffer() != NULL) { 409 size_t toRead = iter.currentToRead(); 410 std::memcpy(&(outData[pos]), iter.readBuffer(), toRead); 411 pos += toRead; 412 iter.rp()->move(toRead); 413 } 414 415 DimensionsValueTuple result; 416 EXPECT_EQ(true, result.ParseFromArray(&outData[0], outData.size())); 417 EXPECT_EQ(4, result.dimensions_value_size()); 418 419 const auto& dim1 = result.dimensions_value(0); 420 EXPECT_EQ(DimensionsValue::ValueCase::kValueInt, dim1.value_case()); 421 EXPECT_EQ(10025, dim1.value_int()); 422 423 const auto& dim2 = result.dimensions_value(1); 424 EXPECT_EQ(DimensionsValue::ValueCase::kValueStr, dim2.value_case()); 425 EXPECT_EQ("tag", dim2.value_str()); 426 427 const auto& dim3 = result.dimensions_value(2); 428 EXPECT_EQ(DimensionsValue::ValueCase::kValueInt, dim3.value_case()); 429 EXPECT_EQ(987654, dim3.value_int()); 430 431 const auto& dim4 = result.dimensions_value(3); 432 EXPECT_EQ(DimensionsValue::ValueCase::kValueLong, dim4.value_case()); 433 EXPECT_EQ(99999, dim4.value_long()); 434} 435 436TEST(AtomMatcherTest, TestWriteAtomToProto) { 437 AttributionNodeInternal attribution_node1; 438 attribution_node1.set_uid(1111); 439 attribution_node1.set_tag("location1"); 440 441 AttributionNodeInternal attribution_node2; 442 attribution_node2.set_uid(2222); 443 attribution_node2.set_tag("location2"); 444 445 std::vector<AttributionNodeInternal> attribution_nodes = {attribution_node1, attribution_node2}; 446 447 // Set up the event 448 LogEvent event(4, 12345); 449 event.write(attribution_nodes); 450 event.write((int32_t)999); 451 // Convert to a LogEvent 452 event.init(); 453 454 android::util::ProtoOutputStream protoOutput; 455 writeFieldValueTreeToStream(event.GetTagId(), event.getValues(), &protoOutput); 456 457 vector<uint8_t> outData; 458 outData.resize(protoOutput.size()); 459 size_t pos = 0; 460 auto iter = protoOutput.data(); 461 while (iter.readBuffer() != NULL) { 462 size_t toRead = iter.currentToRead(); 463 std::memcpy(&(outData[pos]), iter.readBuffer(), toRead); 464 pos += toRead; 465 iter.rp()->move(toRead); 466 } 467 468 Atom result; 469 EXPECT_EQ(true, result.ParseFromArray(&outData[0], outData.size())); 470 EXPECT_EQ(Atom::PushedCase::kBleScanResultReceived, result.pushed_case()); 471 const auto& atom = result.ble_scan_result_received(); 472 EXPECT_EQ(2, atom.attribution_node_size()); 473 EXPECT_EQ(1111, atom.attribution_node(0).uid()); 474 EXPECT_EQ("location1", atom.attribution_node(0).tag()); 475 EXPECT_EQ(2222, atom.attribution_node(1).uid()); 476 EXPECT_EQ("location2", atom.attribution_node(1).tag()); 477 EXPECT_EQ(999, atom.num_results()); 478} 479 480 481} // namespace statsd 482} // namespace os 483} // namespace android 484#else 485GTEST_LOG_(INFO) << "This test does nothing.\n"; 486#endif