1 // Copyright (C) 2017 The Android Open Source Project 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 #include "src/matchers/SimpleLogMatchingTracker.h" 16 #include "src/metrics/ValueMetricProducer.h" 17 #include "src/stats_log_util.h" 18 #include "metrics_test_helper.h" 19 #include "tests/statsd_test_util.h" 20 21 #include <gmock/gmock.h> 22 #include <gtest/gtest.h> 23 #include <math.h> 24 #include <stdio.h> 25 #include <vector> 26 27 using namespace testing; 28 using android::sp; 29 using android::util::ProtoReader; 30 using std::make_shared; 31 using std::set; 32 using std::shared_ptr; 33 using std::unordered_map; 34 using std::vector; 35 36 #ifdef __ANDROID__ 37 38 namespace android { 39 namespace os { 40 namespace statsd { 41 42 const ConfigKey kConfigKey(0, 12345); 43 const int tagId = 1; 44 const int64_t metricId = 123; 45 const int64_t atomMatcherId = 678; 46 const int logEventMatcherIndex = 0; 47 const int64_t bucketStartTimeNs = 10000000000; 48 const int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL; 49 const int64_t bucket2StartTimeNs = bucketStartTimeNs + bucketSizeNs; 50 const int64_t bucket3StartTimeNs = bucketStartTimeNs + 2 * bucketSizeNs; 51 const int64_t bucket4StartTimeNs = bucketStartTimeNs + 3 * bucketSizeNs; 52 const int64_t bucket5StartTimeNs = bucketStartTimeNs + 4 * bucketSizeNs; 53 const int64_t bucket6StartTimeNs = bucketStartTimeNs + 5 * bucketSizeNs; 54 double epsilon = 0.001; 55 56 static void assertPastBucketValuesSingleKey( 57 const std::unordered_map<MetricDimensionKey, std::vector<ValueBucket>>& mPastBuckets, 58 const std::initializer_list<int>& expectedValuesList, 59 const std::initializer_list<int64_t>& expectedDurationNsList) { 60 std::vector<int> expectedValues(expectedValuesList); 61 std::vector<int64_t> expectedDurationNs(expectedDurationNsList); 62 ASSERT_EQ(expectedValues.size(), expectedDurationNs.size()); 63 if (expectedValues.size() == 0) { 64 ASSERT_EQ(0, mPastBuckets.size()); 65 return; 66 } 67 68 ASSERT_EQ(1, mPastBuckets.size()); 69 ASSERT_EQ(expectedValues.size(), mPastBuckets.begin()->second.size()); 70 71 auto buckets = mPastBuckets.begin()->second; 72 for (int i = 0; i < expectedValues.size(); i++) { 73 EXPECT_EQ(expectedValues[i], buckets[i].values[0].long_value) 74 << "Values differ at index " << i; 75 EXPECT_EQ(expectedDurationNs[i], buckets[i].mConditionTrueNs) 76 << "Condition duration value differ at index " << i; 77 } 78 } 79 80 class ValueMetricProducerTestHelper { 81 82 public: 83 static shared_ptr<LogEvent> createEvent(int64_t eventTimeNs, int64_t value) { 84 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, eventTimeNs); 85 event->write(tagId); 86 event->write(value); 87 event->write(value); 88 event->init(); 89 return event; 90 } 91 92 static sp<ValueMetricProducer> createValueProducerNoConditions( 93 sp<MockStatsPullerManager>& pullerManager, ValueMetric& metric) { 94 UidMap uidMap; 95 SimpleAtomMatcher atomMatcher; 96 atomMatcher.set_atom_id(tagId); 97 sp<EventMatcherWizard> eventMatcherWizard = 98 new EventMatcherWizard({new SimpleLogMatchingTracker( 99 atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)}); 100 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>(); 101 EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return()); 102 EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return()); 103 104 sp<ValueMetricProducer> valueProducer = new ValueMetricProducer( 105 kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard, 106 logEventMatcherIndex, eventMatcherWizard, tagId, 107 bucketStartTimeNs, bucketStartTimeNs, pullerManager); 108 valueProducer->prepareFirstBucket(); 109 return valueProducer; 110 } 111 112 static sp<ValueMetricProducer> createValueProducerWithCondition( 113 sp<MockStatsPullerManager>& pullerManager, ValueMetric& metric) { 114 UidMap uidMap; 115 SimpleAtomMatcher atomMatcher; 116 atomMatcher.set_atom_id(tagId); 117 sp<EventMatcherWizard> eventMatcherWizard = 118 new EventMatcherWizard({new SimpleLogMatchingTracker( 119 atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)}); 120 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>(); 121 EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return()); 122 EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return()); 123 124 sp<ValueMetricProducer> valueProducer = 125 new ValueMetricProducer(kConfigKey, metric, 1, wizard, logEventMatcherIndex, 126 eventMatcherWizard, tagId, bucketStartTimeNs, 127 bucketStartTimeNs, pullerManager); 128 valueProducer->prepareFirstBucket(); 129 valueProducer->mCondition = ConditionState::kFalse; 130 return valueProducer; 131 } 132 133 static ValueMetric createMetric() { 134 ValueMetric metric; 135 metric.set_id(metricId); 136 metric.set_bucket(ONE_MINUTE); 137 metric.mutable_value_field()->set_field(tagId); 138 metric.mutable_value_field()->add_child()->set_field(2); 139 metric.set_max_pull_delay_sec(INT_MAX); 140 return metric; 141 } 142 143 static ValueMetric createMetricWithCondition() { 144 ValueMetric metric = ValueMetricProducerTestHelper::createMetric(); 145 metric.set_condition(StringToId("SCREEN_ON")); 146 return metric; 147 } 148 }; 149 150 151 /* 152 * Tests that the first bucket works correctly 153 */ 154 TEST(ValueMetricProducerTest, TestCalcPreviousBucketEndTime) { 155 ValueMetric metric = ValueMetricProducerTestHelper::createMetric(); 156 157 int64_t startTimeBase = 11; 158 UidMap uidMap; 159 SimpleAtomMatcher atomMatcher; 160 atomMatcher.set_atom_id(tagId); 161 sp<EventMatcherWizard> eventMatcherWizard = 162 new EventMatcherWizard({new SimpleLogMatchingTracker( 163 atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)}); 164 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>(); 165 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); 166 167 // statsd started long ago. 168 // The metric starts in the middle of the bucket 169 ValueMetricProducer valueProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard, 170 logEventMatcherIndex, eventMatcherWizard, -1, startTimeBase, 171 22, pullerManager); 172 valueProducer.prepareFirstBucket(); 173 174 EXPECT_EQ(startTimeBase, valueProducer.calcPreviousBucketEndTime(60 * NS_PER_SEC + 10)); 175 EXPECT_EQ(startTimeBase, valueProducer.calcPreviousBucketEndTime(60 * NS_PER_SEC + 10)); 176 EXPECT_EQ(60 * NS_PER_SEC + startTimeBase, 177 valueProducer.calcPreviousBucketEndTime(2 * 60 * NS_PER_SEC)); 178 EXPECT_EQ(2 * 60 * NS_PER_SEC + startTimeBase, 179 valueProducer.calcPreviousBucketEndTime(3 * 60 * NS_PER_SEC)); 180 } 181 182 /* 183 * Tests that the first bucket works correctly 184 */ 185 TEST(ValueMetricProducerTest, TestFirstBucket) { 186 ValueMetric metric = ValueMetricProducerTestHelper::createMetric(); 187 188 UidMap uidMap; 189 SimpleAtomMatcher atomMatcher; 190 atomMatcher.set_atom_id(tagId); 191 sp<EventMatcherWizard> eventMatcherWizard = 192 new EventMatcherWizard({new SimpleLogMatchingTracker( 193 atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)}); 194 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>(); 195 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); 196 197 // statsd started long ago. 198 // The metric starts in the middle of the bucket 199 ValueMetricProducer valueProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard, 200 logEventMatcherIndex, eventMatcherWizard, -1, 5, 201 600 * NS_PER_SEC + NS_PER_SEC / 2, pullerManager); 202 valueProducer.prepareFirstBucket(); 203 204 EXPECT_EQ(600500000000, valueProducer.mCurrentBucketStartTimeNs); 205 EXPECT_EQ(10, valueProducer.mCurrentBucketNum); 206 EXPECT_EQ(660000000005, valueProducer.getCurrentBucketEndTimeNs()); 207 } 208 209 /* 210 * Tests pulled atoms with no conditions 211 */ 212 TEST(ValueMetricProducerTest, TestPulledEventsNoCondition) { 213 ValueMetric metric = ValueMetricProducerTestHelper::createMetric(); 214 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); 215 EXPECT_CALL(*pullerManager, Pull(tagId, _)) 216 .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) { 217 data->clear(); 218 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs); 219 event->write(tagId); 220 event->write(3); 221 event->init(); 222 data->push_back(event); 223 return true; 224 })); 225 226 sp<ValueMetricProducer> valueProducer = 227 ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric); 228 229 vector<shared_ptr<LogEvent>> allData; 230 allData.clear(); 231 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1); 232 event->write(tagId); 233 event->write(11); 234 event->init(); 235 allData.push_back(event); 236 237 valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs); 238 // has one slice 239 EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size()); 240 ValueMetricProducer::Interval curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0]; 241 242 EXPECT_EQ(true, curInterval.hasBase); 243 EXPECT_EQ(11, curInterval.base.long_value); 244 EXPECT_EQ(false, curInterval.hasValue); 245 EXPECT_EQ(8, curInterval.value.long_value); 246 EXPECT_EQ(1UL, valueProducer->mPastBuckets.size()); 247 EXPECT_EQ(8, valueProducer->mPastBuckets.begin()->second[0].values[0].long_value); 248 EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second[0].mConditionTrueNs); 249 250 allData.clear(); 251 event = make_shared<LogEvent>(tagId, bucket3StartTimeNs + 1); 252 event->write(tagId); 253 event->write(23); 254 event->init(); 255 allData.push_back(event); 256 valueProducer->onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs); 257 // has one slice 258 EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size()); 259 curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0]; 260 261 EXPECT_EQ(true, curInterval.hasBase); 262 EXPECT_EQ(23, curInterval.base.long_value); 263 EXPECT_EQ(false, curInterval.hasValue); 264 EXPECT_EQ(12, curInterval.value.long_value); 265 EXPECT_EQ(1UL, valueProducer->mPastBuckets.size()); 266 EXPECT_EQ(2UL, valueProducer->mPastBuckets.begin()->second.size()); 267 EXPECT_EQ(8, valueProducer->mPastBuckets.begin()->second[0].values[0].long_value); 268 EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second[0].mConditionTrueNs); 269 EXPECT_EQ(12, valueProducer->mPastBuckets.begin()->second.back().values[0].long_value); 270 EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second.back().mConditionTrueNs); 271 272 allData.clear(); 273 event = make_shared<LogEvent>(tagId, bucket4StartTimeNs + 1); 274 event->write(tagId); 275 event->write(36); 276 event->init(); 277 allData.push_back(event); 278 valueProducer->onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs); 279 EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size()); 280 curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0]; 281 282 EXPECT_EQ(true, curInterval.hasBase); 283 EXPECT_EQ(36, curInterval.base.long_value); 284 EXPECT_EQ(false, curInterval.hasValue); 285 EXPECT_EQ(13, curInterval.value.long_value); 286 EXPECT_EQ(1UL, valueProducer->mPastBuckets.size()); 287 EXPECT_EQ(3UL, valueProducer->mPastBuckets.begin()->second.size()); 288 EXPECT_EQ(8, valueProducer->mPastBuckets.begin()->second[0].values[0].long_value); 289 EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second[0].mConditionTrueNs); 290 EXPECT_EQ(12, valueProducer->mPastBuckets.begin()->second[1].values[0].long_value); 291 EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second[1].mConditionTrueNs); 292 EXPECT_EQ(13, valueProducer->mPastBuckets.begin()->second[2].values[0].long_value); 293 EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second[2].mConditionTrueNs); 294 } 295 296 TEST(ValueMetricProducerTest, TestPartialBucketCreated) { 297 ValueMetric metric = ValueMetricProducerTestHelper::createMetric(); 298 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); 299 EXPECT_CALL(*pullerManager, Pull(tagId, _)) 300 // Initialize bucket. 301 .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) { 302 data->clear(); 303 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 1); 304 event->write(tagId); 305 event->write(1); 306 event->init(); 307 data->push_back(event); 308 return true; 309 })) 310 // Partial bucket. 311 .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) { 312 data->clear(); 313 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 10); 314 event->write(tagId); 315 event->write(5); 316 event->init(); 317 data->push_back(event); 318 return true; 319 })); 320 321 sp<ValueMetricProducer> valueProducer = 322 ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric); 323 324 // First bucket ends. 325 vector<shared_ptr<LogEvent>> allData; 326 allData.clear(); 327 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 10); 328 event->write(tagId); 329 event->write(2); 330 event->init(); 331 allData.push_back(event); 332 valueProducer->onDataPulled(allData, /** success */ true, bucket2StartTimeNs); 333 334 // Partial buckets created in 2nd bucket. 335 valueProducer->notifyAppUpgrade(bucket2StartTimeNs + 2, "com.foo", 10000, 1); 336 337 // One full bucket and one partial bucket. 338 EXPECT_EQ(1UL, valueProducer->mPastBuckets.size()); 339 vector<ValueBucket> buckets = valueProducer->mPastBuckets.begin()->second; 340 EXPECT_EQ(2UL, buckets.size()); 341 // Full bucket (2 - 1) 342 EXPECT_EQ(1, buckets[0].values[0].long_value); 343 EXPECT_EQ(bucketSizeNs, buckets[0].mConditionTrueNs); 344 // Full bucket (5 - 3) 345 EXPECT_EQ(3, buckets[1].values[0].long_value); 346 // partial bucket [bucket2StartTimeNs, bucket2StartTimeNs + 2] 347 EXPECT_EQ(2, buckets[1].mConditionTrueNs); 348 } 349 350 /* 351 * Tests pulled atoms with filtering 352 */ 353 TEST(ValueMetricProducerTest, TestPulledEventsWithFiltering) { 354 ValueMetric metric = ValueMetricProducerTestHelper::createMetric(); 355 356 UidMap uidMap; 357 SimpleAtomMatcher atomMatcher; 358 atomMatcher.set_atom_id(tagId); 359 auto keyValue = atomMatcher.add_field_value_matcher(); 360 keyValue->set_field(1); 361 keyValue->set_eq_int(3); 362 sp<EventMatcherWizard> eventMatcherWizard = 363 new EventMatcherWizard({new SimpleLogMatchingTracker( 364 atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)}); 365 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>(); 366 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); 367 EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return()); 368 EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return()); 369 EXPECT_CALL(*pullerManager, Pull(tagId, _)) 370 .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) { 371 data->clear(); 372 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs); 373 event->write(3); 374 event->write(3); 375 event->init(); 376 data->push_back(event); 377 return true; 378 })); 379 380 sp<ValueMetricProducer> valueProducer = new ValueMetricProducer( 381 kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard, 382 logEventMatcherIndex, eventMatcherWizard, tagId, 383 bucketStartTimeNs, bucketStartTimeNs, pullerManager); 384 valueProducer->prepareFirstBucket(); 385 386 vector<shared_ptr<LogEvent>> allData; 387 allData.clear(); 388 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1); 389 event->write(3); 390 event->write(11); 391 event->init(); 392 allData.push_back(event); 393 394 valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs); 395 // has one slice 396 EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size()); 397 ValueMetricProducer::Interval curInterval = 398 valueProducer->mCurrentSlicedBucket.begin()->second[0]; 399 400 EXPECT_EQ(true, curInterval.hasBase); 401 EXPECT_EQ(11, curInterval.base.long_value); 402 EXPECT_EQ(false, curInterval.hasValue); 403 EXPECT_EQ(8, curInterval.value.long_value); 404 EXPECT_EQ(1UL, valueProducer->mPastBuckets.size()); 405 EXPECT_EQ(8, valueProducer->mPastBuckets.begin()->second[0].values[0].long_value); 406 EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second[0].mConditionTrueNs); 407 408 allData.clear(); 409 event = make_shared<LogEvent>(tagId, bucket3StartTimeNs + 1); 410 event->write(4); 411 event->write(23); 412 event->init(); 413 allData.push_back(event); 414 valueProducer->onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs); 415 // No new data seen, so data has been cleared. 416 EXPECT_EQ(0UL, valueProducer->mCurrentSlicedBucket.size()); 417 418 EXPECT_EQ(true, curInterval.hasBase); 419 EXPECT_EQ(11, curInterval.base.long_value); 420 EXPECT_EQ(false, curInterval.hasValue); 421 EXPECT_EQ(8, curInterval.value.long_value); 422 EXPECT_EQ(1UL, valueProducer->mPastBuckets.size()); 423 EXPECT_EQ(8, valueProducer->mPastBuckets.begin()->second[0].values[0].long_value); 424 EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second[0].mConditionTrueNs); 425 426 allData.clear(); 427 event = make_shared<LogEvent>(tagId, bucket4StartTimeNs + 1); 428 event->write(3); 429 event->write(36); 430 event->init(); 431 allData.push_back(event); 432 valueProducer->onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs); 433 EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size()); 434 curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0]; 435 436 // the base was reset 437 EXPECT_EQ(true, curInterval.hasBase); 438 EXPECT_EQ(36, curInterval.base.long_value); 439 EXPECT_EQ(false, curInterval.hasValue); 440 EXPECT_EQ(1UL, valueProducer->mPastBuckets.size()); 441 EXPECT_EQ(1UL, valueProducer->mPastBuckets.begin()->second.size()); 442 EXPECT_EQ(8, valueProducer->mPastBuckets.begin()->second.back().values[0].long_value); 443 EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second.back().mConditionTrueNs); 444 } 445 446 /* 447 * Tests pulled atoms with no conditions and take absolute value after reset 448 */ 449 TEST(ValueMetricProducerTest, TestPulledEventsTakeAbsoluteValueOnReset) { 450 ValueMetric metric = ValueMetricProducerTestHelper::createMetric(); 451 metric.set_use_absolute_value_on_reset(true); 452 453 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); 454 EXPECT_CALL(*pullerManager, Pull(tagId, _)).WillOnce(Return(true)); 455 sp<ValueMetricProducer> valueProducer = 456 ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric); 457 458 vector<shared_ptr<LogEvent>> allData; 459 allData.clear(); 460 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1); 461 event->write(tagId); 462 event->write(11); 463 event->init(); 464 allData.push_back(event); 465 466 valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs); 467 // has one slice 468 EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size()); 469 ValueMetricProducer::Interval curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0]; 470 471 EXPECT_EQ(true, curInterval.hasBase); 472 EXPECT_EQ(11, curInterval.base.long_value); 473 EXPECT_EQ(false, curInterval.hasValue); 474 EXPECT_EQ(0UL, valueProducer->mPastBuckets.size()); 475 476 allData.clear(); 477 event = make_shared<LogEvent>(tagId, bucket3StartTimeNs + 1); 478 event->write(tagId); 479 event->write(10); 480 event->init(); 481 allData.push_back(event); 482 valueProducer->onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs); 483 // has one slice 484 EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size()); 485 curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0]; 486 EXPECT_EQ(true, curInterval.hasBase); 487 EXPECT_EQ(10, curInterval.base.long_value); 488 EXPECT_EQ(false, curInterval.hasValue); 489 EXPECT_EQ(10, curInterval.value.long_value); 490 EXPECT_EQ(1UL, valueProducer->mPastBuckets.size()); 491 EXPECT_EQ(10, valueProducer->mPastBuckets.begin()->second.back().values[0].long_value); 492 EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second.back().mConditionTrueNs); 493 494 allData.clear(); 495 event = make_shared<LogEvent>(tagId, bucket4StartTimeNs + 1); 496 event->write(tagId); 497 event->write(36); 498 event->init(); 499 allData.push_back(event); 500 valueProducer->onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs); 501 EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size()); 502 curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0]; 503 EXPECT_EQ(true, curInterval.hasBase); 504 EXPECT_EQ(36, curInterval.base.long_value); 505 EXPECT_EQ(false, curInterval.hasValue); 506 EXPECT_EQ(26, curInterval.value.long_value); 507 EXPECT_EQ(1UL, valueProducer->mPastBuckets.size()); 508 EXPECT_EQ(2UL, valueProducer->mPastBuckets.begin()->second.size()); 509 EXPECT_EQ(10, valueProducer->mPastBuckets.begin()->second[0].values[0].long_value); 510 EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second[0].mConditionTrueNs); 511 EXPECT_EQ(26, valueProducer->mPastBuckets.begin()->second[1].values[0].long_value); 512 EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second[1].mConditionTrueNs); 513 } 514 515 /* 516 * Tests pulled atoms with no conditions and take zero value after reset 517 */ 518 TEST(ValueMetricProducerTest, TestPulledEventsTakeZeroOnReset) { 519 ValueMetric metric = ValueMetricProducerTestHelper::createMetric(); 520 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); 521 EXPECT_CALL(*pullerManager, Pull(tagId, _)).WillOnce(Return(false)); 522 sp<ValueMetricProducer> valueProducer = 523 ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric); 524 525 vector<shared_ptr<LogEvent>> allData; 526 allData.clear(); 527 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1); 528 event->write(tagId); 529 event->write(11); 530 event->init(); 531 allData.push_back(event); 532 533 valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs); 534 // has one slice 535 EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size()); 536 ValueMetricProducer::Interval curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0]; 537 538 EXPECT_EQ(true, curInterval.hasBase); 539 EXPECT_EQ(11, curInterval.base.long_value); 540 EXPECT_EQ(false, curInterval.hasValue); 541 EXPECT_EQ(0UL, valueProducer->mPastBuckets.size()); 542 543 allData.clear(); 544 event = make_shared<LogEvent>(tagId, bucket3StartTimeNs + 1); 545 event->write(tagId); 546 event->write(10); 547 event->init(); 548 allData.push_back(event); 549 valueProducer->onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs); 550 // has one slice 551 EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size()); 552 curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0]; 553 EXPECT_EQ(true, curInterval.hasBase); 554 EXPECT_EQ(10, curInterval.base.long_value); 555 EXPECT_EQ(false, curInterval.hasValue); 556 EXPECT_EQ(0UL, valueProducer->mPastBuckets.size()); 557 558 allData.clear(); 559 event = make_shared<LogEvent>(tagId, bucket4StartTimeNs + 1); 560 event->write(tagId); 561 event->write(36); 562 event->init(); 563 allData.push_back(event); 564 valueProducer->onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs); 565 EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size()); 566 curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0]; 567 EXPECT_EQ(true, curInterval.hasBase); 568 EXPECT_EQ(36, curInterval.base.long_value); 569 EXPECT_EQ(false, curInterval.hasValue); 570 EXPECT_EQ(26, curInterval.value.long_value); 571 EXPECT_EQ(1UL, valueProducer->mPastBuckets.size()); 572 EXPECT_EQ(26, valueProducer->mPastBuckets.begin()->second[0].values[0].long_value); 573 EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second[0].mConditionTrueNs); 574 } 575 576 /* 577 * Test pulled event with non sliced condition. 578 */ 579 TEST(ValueMetricProducerTest, TestEventsWithNonSlicedCondition) { 580 ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition(); 581 582 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); 583 584 EXPECT_CALL(*pullerManager, Pull(tagId, _)) 585 .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) { 586 data->clear(); 587 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 8); 588 event->write(tagId); 589 event->write(100); 590 event->init(); 591 data->push_back(event); 592 return true; 593 })) 594 .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) { 595 data->clear(); 596 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1); 597 event->write(tagId); 598 event->write(130); 599 event->init(); 600 data->push_back(event); 601 return true; 602 })) 603 .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) { 604 data->clear(); 605 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket3StartTimeNs + 1); 606 event->write(tagId); 607 event->write(180); 608 event->init(); 609 data->push_back(event); 610 return true; 611 })); 612 613 sp<ValueMetricProducer> valueProducer = 614 ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric); 615 616 valueProducer->onConditionChanged(true, bucketStartTimeNs + 8); 617 618 // has one slice 619 EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size()); 620 ValueMetricProducer::Interval curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0]; 621 // startUpdated:false sum:0 start:100 622 EXPECT_EQ(true, curInterval.hasBase); 623 EXPECT_EQ(100, curInterval.base.long_value); 624 EXPECT_EQ(false, curInterval.hasValue); 625 EXPECT_EQ(0UL, valueProducer->mPastBuckets.size()); 626 627 vector<shared_ptr<LogEvent>> allData; 628 allData.clear(); 629 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1); 630 event->write(1); 631 event->write(110); 632 event->init(); 633 allData.push_back(event); 634 valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs); 635 assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {10}, {bucketSizeNs - 8}); 636 637 // has one slice 638 EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size()); 639 curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0]; 640 EXPECT_EQ(true, curInterval.hasBase); 641 EXPECT_EQ(110, curInterval.base.long_value); 642 EXPECT_EQ(false, curInterval.hasValue); 643 EXPECT_EQ(10, curInterval.value.long_value); 644 645 valueProducer->onConditionChanged(false, bucket2StartTimeNs + 1); 646 assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {10}, {bucketSizeNs - 8}); 647 648 // has one slice 649 EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size()); 650 curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0]; 651 EXPECT_EQ(true, curInterval.hasValue); 652 EXPECT_EQ(20, curInterval.value.long_value); 653 EXPECT_EQ(false, curInterval.hasBase); 654 655 valueProducer->onConditionChanged(true, bucket3StartTimeNs + 1); 656 assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {10, 20}, {bucketSizeNs - 8, 1}); 657 } 658 659 TEST(ValueMetricProducerTest, TestPushedEventsWithUpgrade) { 660 ValueMetric metric = ValueMetricProducerTestHelper::createMetric(); 661 662 UidMap uidMap; 663 SimpleAtomMatcher atomMatcher; 664 atomMatcher.set_atom_id(tagId); 665 sp<EventMatcherWizard> eventMatcherWizard = 666 new EventMatcherWizard({new SimpleLogMatchingTracker( 667 atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)}); 668 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>(); 669 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); 670 ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex, 671 eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs, 672 pullerManager); 673 valueProducer.prepareFirstBucket(); 674 675 shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10); 676 event1->write(1); 677 event1->write(10); 678 event1->init(); 679 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event1); 680 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size()); 681 682 valueProducer.notifyAppUpgrade(bucketStartTimeNs + 150, "ANY.APP", 1, 1); 683 EXPECT_EQ(1UL, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size()); 684 EXPECT_EQ(bucketStartTimeNs + 150, valueProducer.mCurrentBucketStartTimeNs); 685 686 shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 59 * NS_PER_SEC); 687 event2->write(1); 688 event2->write(10); 689 event2->init(); 690 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event2); 691 EXPECT_EQ(1UL, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size()); 692 EXPECT_EQ(bucketStartTimeNs + 150, valueProducer.mCurrentBucketStartTimeNs); 693 694 // Next value should create a new bucket. 695 shared_ptr<LogEvent> event3 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 65 * NS_PER_SEC); 696 event3->write(1); 697 event3->write(10); 698 event3->init(); 699 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event3); 700 EXPECT_EQ(2UL, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size()); 701 EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, valueProducer.mCurrentBucketStartTimeNs); 702 } 703 704 TEST(ValueMetricProducerTest, TestPulledValueWithUpgrade) { 705 ValueMetric metric = ValueMetricProducerTestHelper::createMetric(); 706 707 UidMap uidMap; 708 SimpleAtomMatcher atomMatcher; 709 atomMatcher.set_atom_id(tagId); 710 sp<EventMatcherWizard> eventMatcherWizard = 711 new EventMatcherWizard({new SimpleLogMatchingTracker( 712 atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)}); 713 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>(); 714 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); 715 EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return()); 716 EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return()); 717 EXPECT_CALL(*pullerManager, Pull(tagId, _)) 718 .WillOnce(Return(true)) 719 .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) { 720 data->clear(); 721 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 149); 722 event->write(tagId); 723 event->write(120); 724 event->init(); 725 data->push_back(event); 726 return true; 727 })); 728 ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex, 729 eventMatcherWizard, tagId, bucketStartTimeNs, 730 bucketStartTimeNs, pullerManager); 731 valueProducer.prepareFirstBucket(); 732 733 vector<shared_ptr<LogEvent>> allData; 734 allData.clear(); 735 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1); 736 event->write(tagId); 737 event->write(100); 738 event->init(); 739 allData.push_back(event); 740 741 valueProducer.onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs); 742 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size()); 743 744 valueProducer.notifyAppUpgrade(bucket2StartTimeNs + 150, "ANY.APP", 1, 1); 745 EXPECT_EQ(1UL, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size()); 746 EXPECT_EQ(bucket2StartTimeNs + 150, valueProducer.mCurrentBucketStartTimeNs); 747 assertPastBucketValuesSingleKey(valueProducer.mPastBuckets, {20}, {150}); 748 749 allData.clear(); 750 event = make_shared<LogEvent>(tagId, bucket3StartTimeNs + 1); 751 event->write(tagId); 752 event->write(150); 753 event->init(); 754 allData.push_back(event); 755 valueProducer.onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs); 756 EXPECT_EQ(2UL, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size()); 757 EXPECT_EQ(bucket3StartTimeNs, valueProducer.mCurrentBucketStartTimeNs); 758 EXPECT_EQ(20L, 759 valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][0].values[0].long_value); 760 assertPastBucketValuesSingleKey(valueProducer.mPastBuckets, {20, 30}, 761 {150, bucketSizeNs - 150}); 762 } 763 764 TEST(ValueMetricProducerTest, TestPulledWithAppUpgradeDisabled) { 765 ValueMetric metric = ValueMetricProducerTestHelper::createMetric(); 766 metric.set_split_bucket_for_app_upgrade(false); 767 768 UidMap uidMap; 769 SimpleAtomMatcher atomMatcher; 770 atomMatcher.set_atom_id(tagId); 771 sp<EventMatcherWizard> eventMatcherWizard = 772 new EventMatcherWizard({new SimpleLogMatchingTracker( 773 atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)}); 774 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>(); 775 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); 776 EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return()); 777 EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return()); 778 EXPECT_CALL(*pullerManager, Pull(tagId, _)).WillOnce(Return(true)); 779 ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex, 780 eventMatcherWizard, tagId, bucketStartTimeNs, 781 bucketStartTimeNs, pullerManager); 782 valueProducer.prepareFirstBucket(); 783 784 vector<shared_ptr<LogEvent>> allData; 785 allData.clear(); 786 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1); 787 event->write(tagId); 788 event->write(100); 789 event->init(); 790 allData.push_back(event); 791 792 valueProducer.onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs); 793 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size()); 794 795 valueProducer.notifyAppUpgrade(bucket2StartTimeNs + 150, "ANY.APP", 1, 1); 796 EXPECT_EQ(0UL, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size()); 797 EXPECT_EQ(bucket2StartTimeNs, valueProducer.mCurrentBucketStartTimeNs); 798 } 799 800 TEST(ValueMetricProducerTest, TestPulledValueWithUpgradeWhileConditionFalse) { 801 ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition(); 802 803 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); 804 EXPECT_CALL(*pullerManager, Pull(tagId, _)) 805 .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) { 806 data->clear(); 807 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 1); 808 event->write(tagId); 809 event->write(100); 810 event->init(); 811 data->push_back(event); 812 return true; 813 })) 814 .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) { 815 data->clear(); 816 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs - 100); 817 event->write(tagId); 818 event->write(120); 819 event->init(); 820 data->push_back(event); 821 return true; 822 })); 823 sp<ValueMetricProducer> valueProducer = 824 ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric); 825 826 valueProducer->onConditionChanged(true, bucketStartTimeNs + 1); 827 828 valueProducer->onConditionChanged(false, bucket2StartTimeNs-100); 829 EXPECT_FALSE(valueProducer->mCondition); 830 831 valueProducer->notifyAppUpgrade(bucket2StartTimeNs-50, "ANY.APP", 1, 1); 832 // Expect one full buckets already done and starting a partial bucket. 833 EXPECT_EQ(bucket2StartTimeNs-50, valueProducer->mCurrentBucketStartTimeNs); 834 EXPECT_EQ(1UL, valueProducer->mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size()); 835 EXPECT_EQ(bucketStartTimeNs, 836 valueProducer->mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][0].mBucketStartNs); 837 assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {20}, 838 {(bucket2StartTimeNs - 100) - (bucketStartTimeNs + 1)}); 839 EXPECT_FALSE(valueProducer->mCondition); 840 } 841 842 TEST(ValueMetricProducerTest, TestPushedEventsWithoutCondition) { 843 ValueMetric metric = ValueMetricProducerTestHelper::createMetric(); 844 845 UidMap uidMap; 846 SimpleAtomMatcher atomMatcher; 847 atomMatcher.set_atom_id(tagId); 848 sp<EventMatcherWizard> eventMatcherWizard = 849 new EventMatcherWizard({new SimpleLogMatchingTracker( 850 atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)}); 851 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>(); 852 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); 853 854 ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex, 855 eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs, 856 pullerManager); 857 valueProducer.prepareFirstBucket(); 858 859 shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10); 860 event1->write(1); 861 event1->write(10); 862 event1->init(); 863 shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 20); 864 event2->write(1); 865 event2->write(20); 866 event2->init(); 867 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event1); 868 // has one slice 869 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size()); 870 ValueMetricProducer::Interval curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0]; 871 EXPECT_EQ(10, curInterval.value.long_value); 872 EXPECT_EQ(true, curInterval.hasValue); 873 874 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event2); 875 876 // has one slice 877 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size()); 878 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0]; 879 EXPECT_EQ(30, curInterval.value.long_value); 880 881 valueProducer.flushIfNeededLocked(bucket2StartTimeNs); 882 assertPastBucketValuesSingleKey(valueProducer.mPastBuckets, {30}, {bucketSizeNs}); 883 } 884 885 TEST(ValueMetricProducerTest, TestPushedEventsWithCondition) { 886 ValueMetric metric = ValueMetricProducerTestHelper::createMetric(); 887 888 UidMap uidMap; 889 SimpleAtomMatcher atomMatcher; 890 atomMatcher.set_atom_id(tagId); 891 sp<EventMatcherWizard> eventMatcherWizard = 892 new EventMatcherWizard({new SimpleLogMatchingTracker( 893 atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)}); 894 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>(); 895 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); 896 897 ValueMetricProducer valueProducer(kConfigKey, metric, 1, wizard, logEventMatcherIndex, 898 eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs, 899 pullerManager); 900 valueProducer.prepareFirstBucket(); 901 valueProducer.mCondition = ConditionState::kFalse; 902 903 shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10); 904 event1->write(1); 905 event1->write(10); 906 event1->init(); 907 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event1); 908 // has 1 slice 909 EXPECT_EQ(0UL, valueProducer.mCurrentSlicedBucket.size()); 910 911 valueProducer.onConditionChangedLocked(true, bucketStartTimeNs + 15); 912 shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 20); 913 event2->write(1); 914 event2->write(20); 915 event2->init(); 916 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event2); 917 918 // has one slice 919 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size()); 920 ValueMetricProducer::Interval curInterval = 921 valueProducer.mCurrentSlicedBucket.begin()->second[0]; 922 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0]; 923 EXPECT_EQ(20, curInterval.value.long_value); 924 925 shared_ptr<LogEvent> event3 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 30); 926 event3->write(1); 927 event3->write(30); 928 event3->init(); 929 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event3); 930 931 // has one slice 932 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size()); 933 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0]; 934 EXPECT_EQ(50, curInterval.value.long_value); 935 936 valueProducer.onConditionChangedLocked(false, bucketStartTimeNs + 35); 937 shared_ptr<LogEvent> event4 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 40); 938 event4->write(1); 939 event4->write(40); 940 event4->init(); 941 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event4); 942 943 // has one slice 944 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size()); 945 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0]; 946 EXPECT_EQ(50, curInterval.value.long_value); 947 948 valueProducer.flushIfNeededLocked(bucket2StartTimeNs); 949 assertPastBucketValuesSingleKey(valueProducer.mPastBuckets, {50}, {20}); 950 } 951 952 TEST(ValueMetricProducerTest, TestAnomalyDetection) { 953 sp<AlarmMonitor> alarmMonitor; 954 Alert alert; 955 alert.set_id(101); 956 alert.set_metric_id(metricId); 957 alert.set_trigger_if_sum_gt(130); 958 alert.set_num_buckets(2); 959 const int32_t refPeriodSec = 3; 960 alert.set_refractory_period_secs(refPeriodSec); 961 962 ValueMetric metric = ValueMetricProducerTestHelper::createMetric(); 963 964 UidMap uidMap; 965 SimpleAtomMatcher atomMatcher; 966 atomMatcher.set_atom_id(tagId); 967 sp<EventMatcherWizard> eventMatcherWizard = 968 new EventMatcherWizard({new SimpleLogMatchingTracker( 969 atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)}); 970 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>(); 971 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); 972 ValueMetricProducer valueProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard, 973 logEventMatcherIndex, eventMatcherWizard, -1 /*not pulled*/, 974 bucketStartTimeNs, bucketStartTimeNs, pullerManager); 975 valueProducer.prepareFirstBucket(); 976 977 sp<AnomalyTracker> anomalyTracker = valueProducer.addAnomalyTracker(alert, alarmMonitor); 978 979 980 shared_ptr<LogEvent> event1 981 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 1 * NS_PER_SEC); 982 event1->write(161); 983 event1->write(10); // value of interest 984 event1->init(); 985 shared_ptr<LogEvent> event2 986 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 2 + NS_PER_SEC); 987 event2->write(162); 988 event2->write(20); // value of interest 989 event2->init(); 990 shared_ptr<LogEvent> event3 991 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 2 * bucketSizeNs + 1 * NS_PER_SEC); 992 event3->write(163); 993 event3->write(130); // value of interest 994 event3->init(); 995 shared_ptr<LogEvent> event4 996 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 3 * bucketSizeNs + 1 * NS_PER_SEC); 997 event4->write(35); 998 event4->write(1); // value of interest 999 event4->init(); 1000 shared_ptr<LogEvent> event5 1001 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 3 * bucketSizeNs + 2 * NS_PER_SEC); 1002 event5->write(45); 1003 event5->write(150); // value of interest 1004 event5->init(); 1005 shared_ptr<LogEvent> event6 1006 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 3 * bucketSizeNs + 10 * NS_PER_SEC); 1007 event6->write(25); 1008 event6->write(160); // value of interest 1009 event6->init(); 1010 1011 // Two events in bucket #0. 1012 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event1); 1013 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event2); 1014 // Value sum == 30 <= 130. 1015 EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY), 0U); 1016 1017 // One event in bucket #2. No alarm as bucket #0 is trashed out. 1018 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event3); 1019 // Value sum == 130 <= 130. 1020 EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY), 0U); 1021 1022 // Three events in bucket #3. 1023 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event4); 1024 // Anomaly at event 4 since Value sum == 131 > 130! 1025 EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY), 1026 std::ceil(1.0 * event4->GetElapsedTimestampNs() / NS_PER_SEC + refPeriodSec)); 1027 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event5); 1028 // Event 5 is within 3 sec refractory period. Thus last alarm timestamp is still event4. 1029 EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY), 1030 std::ceil(1.0 * event4->GetElapsedTimestampNs() / NS_PER_SEC + refPeriodSec)); 1031 1032 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event6); 1033 // Anomaly at event 6 since Value sum == 160 > 130 and after refractory period. 1034 EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY), 1035 std::ceil(1.0 * event6->GetElapsedTimestampNs() / NS_PER_SEC + refPeriodSec)); 1036 } 1037 1038 // Test value metric no condition, the pull on bucket boundary come in time and too late 1039 TEST(ValueMetricProducerTest, TestBucketBoundaryNoCondition) { 1040 ValueMetric metric = ValueMetricProducerTestHelper::createMetric(); 1041 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); 1042 EXPECT_CALL(*pullerManager, Pull(tagId, _)).WillOnce(Return(true)); 1043 sp<ValueMetricProducer> valueProducer = 1044 ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric); 1045 1046 vector<shared_ptr<LogEvent>> allData; 1047 // pull 1 1048 allData.clear(); 1049 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1); 1050 event->write(tagId); 1051 event->write(11); 1052 event->init(); 1053 allData.push_back(event); 1054 1055 valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs); 1056 // has one slice 1057 EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size()); 1058 ValueMetricProducer::Interval curInterval = 1059 valueProducer->mCurrentSlicedBucket.begin()->second[0]; 1060 1061 // startUpdated:true sum:0 start:11 1062 EXPECT_EQ(true, curInterval.hasBase); 1063 EXPECT_EQ(11, curInterval.base.long_value); 1064 EXPECT_EQ(false, curInterval.hasValue); 1065 EXPECT_EQ(0UL, valueProducer->mPastBuckets.size()); 1066 1067 // pull 2 at correct time 1068 allData.clear(); 1069 event = make_shared<LogEvent>(tagId, bucket3StartTimeNs + 1); 1070 event->write(tagId); 1071 event->write(23); 1072 event->init(); 1073 allData.push_back(event); 1074 valueProducer->onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs); 1075 // has one slice 1076 EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size()); 1077 curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0]; 1078 // tartUpdated:false sum:12 1079 EXPECT_EQ(true, curInterval.hasBase); 1080 EXPECT_EQ(23, curInterval.base.long_value); 1081 EXPECT_EQ(false, curInterval.hasValue); 1082 assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {12}, {bucketSizeNs}); 1083 1084 // pull 3 come late. 1085 // The previous bucket gets closed with error. (Has start value 23, no ending) 1086 // Another bucket gets closed with error. (No start, but ending with 36) 1087 // The new bucket is back to normal. 1088 allData.clear(); 1089 event = make_shared<LogEvent>(tagId, bucket6StartTimeNs + 1); 1090 event->write(tagId); 1091 event->write(36); 1092 event->init(); 1093 allData.push_back(event); 1094 valueProducer->onDataPulled(allData, /** succeed */ true, bucket6StartTimeNs); 1095 EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size()); 1096 curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0]; 1097 // startUpdated:false sum:12 1098 EXPECT_EQ(true, curInterval.hasBase); 1099 EXPECT_EQ(36, curInterval.base.long_value); 1100 EXPECT_EQ(false, curInterval.hasValue); 1101 assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {12}, {bucketSizeNs}); 1102 } 1103 1104 /* 1105 * Test pulled event with non sliced condition. The pull on boundary come late because the alarm 1106 * was delivered late. 1107 */ 1108 TEST(ValueMetricProducerTest, TestBucketBoundaryWithCondition) { 1109 ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition(); 1110 1111 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); 1112 EXPECT_CALL(*pullerManager, Pull(tagId, _)) 1113 // condition becomes true 1114 .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) { 1115 data->clear(); 1116 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 8); 1117 event->write(tagId); 1118 event->write(100); 1119 event->init(); 1120 data->push_back(event); 1121 return true; 1122 })) 1123 // condition becomes false 1124 .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) { 1125 data->clear(); 1126 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1); 1127 event->write(tagId); 1128 event->write(120); 1129 event->init(); 1130 data->push_back(event); 1131 return true; 1132 })); 1133 sp<ValueMetricProducer> valueProducer = 1134 ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric); 1135 1136 valueProducer->onConditionChanged(true, bucketStartTimeNs + 8); 1137 1138 // has one slice 1139 EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size()); 1140 ValueMetricProducer::Interval curInterval = 1141 valueProducer->mCurrentSlicedBucket.begin()->second[0]; 1142 EXPECT_EQ(true, curInterval.hasBase); 1143 EXPECT_EQ(100, curInterval.base.long_value); 1144 EXPECT_EQ(false, curInterval.hasValue); 1145 EXPECT_EQ(0UL, valueProducer->mPastBuckets.size()); 1146 1147 // pull on bucket boundary come late, condition change happens before it 1148 valueProducer->onConditionChanged(false, bucket2StartTimeNs + 1); 1149 curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0]; 1150 assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {20}, {bucketSizeNs - 8}); 1151 EXPECT_EQ(false, curInterval.hasBase); 1152 1153 // Now the alarm is delivered. 1154 // since the condition turned to off before this pull finish, it has no effect 1155 vector<shared_ptr<LogEvent>> allData; 1156 allData.push_back(ValueMetricProducerTestHelper::createEvent(bucket2StartTimeNs + 30, 110)); 1157 valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs); 1158 1159 assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {20}, {bucketSizeNs - 8}); 1160 curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0]; 1161 EXPECT_EQ(false, curInterval.hasBase); 1162 EXPECT_EQ(false, curInterval.hasValue); 1163 } 1164 1165 /* 1166 * Test pulled event with non sliced condition. The pull on boundary come late, after the condition 1167 * change to false, and then true again. This is due to alarm delivered late. 1168 */ 1169 TEST(ValueMetricProducerTest, TestBucketBoundaryWithCondition2) { 1170 ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition(); 1171 1172 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); 1173 EXPECT_CALL(*pullerManager, Pull(tagId, _)) 1174 // condition becomes true 1175 .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) { 1176 data->clear(); 1177 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 8); 1178 event->write(tagId); 1179 event->write(100); 1180 event->init(); 1181 data->push_back(event); 1182 return true; 1183 })) 1184 // condition becomes false 1185 .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) { 1186 data->clear(); 1187 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1); 1188 event->write(tagId); 1189 event->write(120); 1190 event->init(); 1191 data->push_back(event); 1192 return true; 1193 })) 1194 // condition becomes true again 1195 .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) { 1196 data->clear(); 1197 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 25); 1198 event->write(tagId); 1199 event->write(130); 1200 event->init(); 1201 data->push_back(event); 1202 return true; 1203 })); 1204 1205 sp<ValueMetricProducer> valueProducer = 1206 ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric); 1207 1208 valueProducer->onConditionChanged(true, bucketStartTimeNs + 8); 1209 1210 // has one slice 1211 EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size()); 1212 ValueMetricProducer::Interval curInterval = 1213 valueProducer->mCurrentSlicedBucket.begin()->second[0]; 1214 // startUpdated:false sum:0 start:100 1215 EXPECT_EQ(true, curInterval.hasBase); 1216 EXPECT_EQ(100, curInterval.base.long_value); 1217 EXPECT_EQ(false, curInterval.hasValue); 1218 EXPECT_EQ(0UL, valueProducer->mPastBuckets.size()); 1219 1220 // pull on bucket boundary come late, condition change happens before it 1221 valueProducer->onConditionChanged(false, bucket2StartTimeNs + 1); 1222 assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {20}, {bucketSizeNs - 8}); 1223 EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size()); 1224 curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0]; 1225 EXPECT_EQ(false, curInterval.hasBase); 1226 EXPECT_EQ(false, curInterval.hasValue); 1227 1228 // condition changed to true again, before the pull alarm is delivered 1229 valueProducer->onConditionChanged(true, bucket2StartTimeNs + 25); 1230 assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {20}, {bucketSizeNs - 8}); 1231 curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0]; 1232 EXPECT_EQ(true, curInterval.hasBase); 1233 EXPECT_EQ(130, curInterval.base.long_value); 1234 EXPECT_EQ(false, curInterval.hasValue); 1235 1236 // Now the alarm is delivered, but it is considered late, the data will be used 1237 // for the new bucket since it was just pulled. 1238 vector<shared_ptr<LogEvent>> allData; 1239 allData.push_back(ValueMetricProducerTestHelper::createEvent(bucket2StartTimeNs + 50, 140)); 1240 valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs + 50); 1241 1242 curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0]; 1243 EXPECT_EQ(true, curInterval.hasBase); 1244 EXPECT_EQ(140, curInterval.base.long_value); 1245 EXPECT_EQ(true, curInterval.hasValue); 1246 EXPECT_EQ(10, curInterval.value.long_value); 1247 assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {20}, {bucketSizeNs - 8}); 1248 1249 allData.clear(); 1250 allData.push_back(ValueMetricProducerTestHelper::createEvent(bucket3StartTimeNs, 160)); 1251 valueProducer->onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs); 1252 assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {20, 30}, 1253 {bucketSizeNs - 8, bucketSizeNs - 24}); 1254 } 1255 1256 TEST(ValueMetricProducerTest, TestPushedAggregateMin) { 1257 ValueMetric metric = ValueMetricProducerTestHelper::createMetric(); 1258 metric.set_aggregation_type(ValueMetric::MIN); 1259 1260 UidMap uidMap; 1261 SimpleAtomMatcher atomMatcher; 1262 atomMatcher.set_atom_id(tagId); 1263 sp<EventMatcherWizard> eventMatcherWizard = 1264 new EventMatcherWizard({new SimpleLogMatchingTracker( 1265 atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)}); 1266 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>(); 1267 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); 1268 1269 ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex, 1270 eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs, 1271 pullerManager); 1272 valueProducer.prepareFirstBucket(); 1273 1274 shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10); 1275 event1->write(1); 1276 event1->write(10); 1277 event1->init(); 1278 shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 20); 1279 event2->write(1); 1280 event2->write(20); 1281 event2->init(); 1282 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event1); 1283 // has one slice 1284 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size()); 1285 ValueMetricProducer::Interval curInterval = 1286 valueProducer.mCurrentSlicedBucket.begin()->second[0]; 1287 EXPECT_EQ(10, curInterval.value.long_value); 1288 EXPECT_EQ(true, curInterval.hasValue); 1289 1290 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event2); 1291 1292 // has one slice 1293 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size()); 1294 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0]; 1295 EXPECT_EQ(10, curInterval.value.long_value); 1296 1297 valueProducer.flushIfNeededLocked(bucket2StartTimeNs); 1298 assertPastBucketValuesSingleKey(valueProducer.mPastBuckets, {10}, {bucketSizeNs}); 1299 } 1300 1301 TEST(ValueMetricProducerTest, TestPushedAggregateMax) { 1302 ValueMetric metric = ValueMetricProducerTestHelper::createMetric(); 1303 metric.set_aggregation_type(ValueMetric::MAX); 1304 1305 UidMap uidMap; 1306 SimpleAtomMatcher atomMatcher; 1307 atomMatcher.set_atom_id(tagId); 1308 sp<EventMatcherWizard> eventMatcherWizard = 1309 new EventMatcherWizard({new SimpleLogMatchingTracker( 1310 atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)}); 1311 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>(); 1312 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); 1313 1314 ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex, 1315 eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs, 1316 pullerManager); 1317 valueProducer.prepareFirstBucket(); 1318 1319 shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10); 1320 event1->write(1); 1321 event1->write(10); 1322 event1->init(); 1323 shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 20); 1324 event2->write(1); 1325 event2->write(20); 1326 event2->init(); 1327 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event1); 1328 // has one slice 1329 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size()); 1330 ValueMetricProducer::Interval curInterval = 1331 valueProducer.mCurrentSlicedBucket.begin()->second[0]; 1332 EXPECT_EQ(10, curInterval.value.long_value); 1333 EXPECT_EQ(true, curInterval.hasValue); 1334 1335 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event2); 1336 1337 // has one slice 1338 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size()); 1339 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0]; 1340 EXPECT_EQ(20, curInterval.value.long_value); 1341 1342 valueProducer.flushIfNeededLocked(bucket3StartTimeNs); 1343 /* EXPECT_EQ(1UL, valueProducer.mPastBuckets.size()); */ 1344 /* EXPECT_EQ(1UL, valueProducer.mPastBuckets.begin()->second.size()); */ 1345 /* EXPECT_EQ(20, valueProducer.mPastBuckets.begin()->second.back().values[0].long_value); */ 1346 } 1347 1348 TEST(ValueMetricProducerTest, TestPushedAggregateAvg) { 1349 ValueMetric metric = ValueMetricProducerTestHelper::createMetric(); 1350 metric.set_aggregation_type(ValueMetric::AVG); 1351 1352 UidMap uidMap; 1353 SimpleAtomMatcher atomMatcher; 1354 atomMatcher.set_atom_id(tagId); 1355 sp<EventMatcherWizard> eventMatcherWizard = 1356 new EventMatcherWizard({new SimpleLogMatchingTracker( 1357 atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)}); 1358 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>(); 1359 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); 1360 1361 ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex, 1362 eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs, 1363 pullerManager); 1364 valueProducer.prepareFirstBucket(); 1365 1366 shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10); 1367 event1->write(1); 1368 event1->write(10); 1369 event1->init(); 1370 shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 20); 1371 event2->write(1); 1372 event2->write(15); 1373 event2->init(); 1374 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event1); 1375 // has one slice 1376 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size()); 1377 ValueMetricProducer::Interval curInterval; 1378 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0]; 1379 EXPECT_EQ(10, curInterval.value.long_value); 1380 EXPECT_EQ(true, curInterval.hasValue); 1381 EXPECT_EQ(1, curInterval.sampleSize); 1382 1383 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event2); 1384 1385 // has one slice 1386 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size()); 1387 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0]; 1388 EXPECT_EQ(25, curInterval.value.long_value); 1389 EXPECT_EQ(2, curInterval.sampleSize); 1390 1391 valueProducer.flushIfNeededLocked(bucket2StartTimeNs); 1392 EXPECT_EQ(1UL, valueProducer.mPastBuckets.size()); 1393 EXPECT_EQ(1UL, valueProducer.mPastBuckets.begin()->second.size()); 1394 1395 EXPECT_TRUE(std::abs(valueProducer.mPastBuckets.begin()->second.back().values[0].double_value - 1396 12.5) < epsilon); 1397 } 1398 1399 TEST(ValueMetricProducerTest, TestPushedAggregateSum) { 1400 ValueMetric metric = ValueMetricProducerTestHelper::createMetric(); 1401 metric.set_aggregation_type(ValueMetric::SUM); 1402 1403 UidMap uidMap; 1404 SimpleAtomMatcher atomMatcher; 1405 atomMatcher.set_atom_id(tagId); 1406 sp<EventMatcherWizard> eventMatcherWizard = 1407 new EventMatcherWizard({new SimpleLogMatchingTracker( 1408 atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)}); 1409 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>(); 1410 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); 1411 1412 ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex, 1413 eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs, 1414 pullerManager); 1415 valueProducer.prepareFirstBucket(); 1416 1417 shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10); 1418 event1->write(1); 1419 event1->write(10); 1420 event1->init(); 1421 shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 20); 1422 event2->write(1); 1423 event2->write(15); 1424 event2->init(); 1425 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event1); 1426 // has one slice 1427 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size()); 1428 ValueMetricProducer::Interval curInterval = 1429 valueProducer.mCurrentSlicedBucket.begin()->second[0]; 1430 EXPECT_EQ(10, curInterval.value.long_value); 1431 EXPECT_EQ(true, curInterval.hasValue); 1432 1433 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event2); 1434 1435 // has one slice 1436 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size()); 1437 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0]; 1438 EXPECT_EQ(25, curInterval.value.long_value); 1439 1440 valueProducer.flushIfNeededLocked(bucket2StartTimeNs); 1441 assertPastBucketValuesSingleKey(valueProducer.mPastBuckets, {25}, {bucketSizeNs}); 1442 } 1443 1444 TEST(ValueMetricProducerTest, TestSkipZeroDiffOutput) { 1445 ValueMetric metric = ValueMetricProducerTestHelper::createMetric(); 1446 metric.set_aggregation_type(ValueMetric::MIN); 1447 metric.set_use_diff(true); 1448 1449 UidMap uidMap; 1450 SimpleAtomMatcher atomMatcher; 1451 atomMatcher.set_atom_id(tagId); 1452 sp<EventMatcherWizard> eventMatcherWizard = 1453 new EventMatcherWizard({new SimpleLogMatchingTracker( 1454 atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)}); 1455 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>(); 1456 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); 1457 1458 ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex, 1459 eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs, 1460 pullerManager); 1461 valueProducer.prepareFirstBucket(); 1462 1463 shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10); 1464 event1->write(1); 1465 event1->write(10); 1466 event1->init(); 1467 shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 15); 1468 event2->write(1); 1469 event2->write(15); 1470 event2->init(); 1471 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event1); 1472 // has one slice 1473 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size()); 1474 ValueMetricProducer::Interval curInterval = 1475 valueProducer.mCurrentSlicedBucket.begin()->second[0]; 1476 EXPECT_EQ(true, curInterval.hasBase); 1477 EXPECT_EQ(10, curInterval.base.long_value); 1478 EXPECT_EQ(false, curInterval.hasValue); 1479 1480 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event2); 1481 1482 // has one slice 1483 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size()); 1484 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0]; 1485 EXPECT_EQ(true, curInterval.hasValue); 1486 EXPECT_EQ(5, curInterval.value.long_value); 1487 1488 // no change in data. 1489 shared_ptr<LogEvent> event3 = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 10); 1490 event3->write(1); 1491 event3->write(15); 1492 event3->init(); 1493 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event3); 1494 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size()); 1495 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0]; 1496 EXPECT_EQ(true, curInterval.hasBase); 1497 EXPECT_EQ(15, curInterval.base.long_value); 1498 EXPECT_EQ(true, curInterval.hasValue); 1499 1500 shared_ptr<LogEvent> event4 = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 15); 1501 event4->write(1); 1502 event4->write(15); 1503 event4->init(); 1504 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event4); 1505 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size()); 1506 curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0]; 1507 EXPECT_EQ(true, curInterval.hasBase); 1508 EXPECT_EQ(15, curInterval.base.long_value); 1509 EXPECT_EQ(true, curInterval.hasValue); 1510 1511 valueProducer.flushIfNeededLocked(bucket3StartTimeNs); 1512 EXPECT_EQ(1UL, valueProducer.mPastBuckets.size()); 1513 EXPECT_EQ(1UL, valueProducer.mPastBuckets.begin()->second.size()); 1514 assertPastBucketValuesSingleKey(valueProducer.mPastBuckets, {5}, {bucketSizeNs}); 1515 } 1516 1517 TEST(ValueMetricProducerTest, TestSkipZeroDiffOutputMultiValue) { 1518 ValueMetric metric = ValueMetricProducerTestHelper::createMetric(); 1519 metric.mutable_value_field()->add_child()->set_field(3); 1520 metric.set_aggregation_type(ValueMetric::MIN); 1521 metric.set_use_diff(true); 1522 1523 UidMap uidMap; 1524 SimpleAtomMatcher atomMatcher; 1525 atomMatcher.set_atom_id(tagId); 1526 sp<EventMatcherWizard> eventMatcherWizard = 1527 new EventMatcherWizard({new SimpleLogMatchingTracker( 1528 atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)}); 1529 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>(); 1530 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); 1531 1532 ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex, 1533 eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs, 1534 pullerManager); 1535 valueProducer.prepareFirstBucket(); 1536 1537 shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10); 1538 event1->write(1); 1539 event1->write(10); 1540 event1->write(20); 1541 event1->init(); 1542 shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 15); 1543 event2->write(1); 1544 event2->write(15); 1545 event2->write(22); 1546 event2->init(); 1547 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event1); 1548 // has one slice 1549 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size()); 1550 ValueMetricProducer::Interval curInterval0 = 1551 valueProducer.mCurrentSlicedBucket.begin()->second[0]; 1552 ValueMetricProducer::Interval curInterval1 = 1553 valueProducer.mCurrentSlicedBucket.begin()->second[1]; 1554 EXPECT_EQ(true, curInterval0.hasBase); 1555 EXPECT_EQ(10, curInterval0.base.long_value); 1556 EXPECT_EQ(false, curInterval0.hasValue); 1557 EXPECT_EQ(true, curInterval1.hasBase); 1558 EXPECT_EQ(20, curInterval1.base.long_value); 1559 EXPECT_EQ(false, curInterval1.hasValue); 1560 1561 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event2); 1562 1563 // has one slice 1564 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size()); 1565 curInterval0 = valueProducer.mCurrentSlicedBucket.begin()->second[0]; 1566 curInterval1 = valueProducer.mCurrentSlicedBucket.begin()->second[1]; 1567 EXPECT_EQ(true, curInterval0.hasValue); 1568 EXPECT_EQ(5, curInterval0.value.long_value); 1569 EXPECT_EQ(true, curInterval1.hasValue); 1570 EXPECT_EQ(2, curInterval1.value.long_value); 1571 1572 // no change in first value field 1573 shared_ptr<LogEvent> event3 = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 10); 1574 event3->write(1); 1575 event3->write(15); 1576 event3->write(25); 1577 event3->init(); 1578 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event3); 1579 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size()); 1580 curInterval0 = valueProducer.mCurrentSlicedBucket.begin()->second[0]; 1581 curInterval1 = valueProducer.mCurrentSlicedBucket.begin()->second[1]; 1582 EXPECT_EQ(true, curInterval0.hasBase); 1583 EXPECT_EQ(15, curInterval0.base.long_value); 1584 EXPECT_EQ(true, curInterval0.hasValue); 1585 EXPECT_EQ(true, curInterval1.hasBase); 1586 EXPECT_EQ(25, curInterval1.base.long_value); 1587 EXPECT_EQ(true, curInterval1.hasValue); 1588 1589 shared_ptr<LogEvent> event4 = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 15); 1590 event4->write(1); 1591 event4->write(15); 1592 event4->write(29); 1593 event4->init(); 1594 valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event4); 1595 EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size()); 1596 curInterval0 = valueProducer.mCurrentSlicedBucket.begin()->second[0]; 1597 curInterval1 = valueProducer.mCurrentSlicedBucket.begin()->second[1]; 1598 EXPECT_EQ(true, curInterval0.hasBase); 1599 EXPECT_EQ(15, curInterval0.base.long_value); 1600 EXPECT_EQ(true, curInterval0.hasValue); 1601 EXPECT_EQ(true, curInterval1.hasBase); 1602 EXPECT_EQ(29, curInterval1.base.long_value); 1603 EXPECT_EQ(true, curInterval1.hasValue); 1604 1605 valueProducer.flushIfNeededLocked(bucket3StartTimeNs); 1606 1607 EXPECT_EQ(1UL, valueProducer.mPastBuckets.size()); 1608 EXPECT_EQ(2UL, valueProducer.mPastBuckets.begin()->second.size()); 1609 EXPECT_EQ(2UL, valueProducer.mPastBuckets.begin()->second[0].values.size()); 1610 EXPECT_EQ(1UL, valueProducer.mPastBuckets.begin()->second[1].values.size()); 1611 1612 EXPECT_EQ(bucketSizeNs, valueProducer.mPastBuckets.begin()->second[0].mConditionTrueNs); 1613 EXPECT_EQ(5, valueProducer.mPastBuckets.begin()->second[0].values[0].long_value); 1614 EXPECT_EQ(0, valueProducer.mPastBuckets.begin()->second[0].valueIndex[0]); 1615 EXPECT_EQ(2, valueProducer.mPastBuckets.begin()->second[0].values[1].long_value); 1616 EXPECT_EQ(1, valueProducer.mPastBuckets.begin()->second[0].valueIndex[1]); 1617 1618 EXPECT_EQ(bucketSizeNs, valueProducer.mPastBuckets.begin()->second[1].mConditionTrueNs); 1619 EXPECT_EQ(3, valueProducer.mPastBuckets.begin()->second[1].values[0].long_value); 1620 EXPECT_EQ(1, valueProducer.mPastBuckets.begin()->second[1].valueIndex[0]); 1621 } 1622 1623 /* 1624 * Tests zero default base. 1625 */ 1626 TEST(ValueMetricProducerTest, TestUseZeroDefaultBase) { 1627 ValueMetric metric = ValueMetricProducerTestHelper::createMetric(); 1628 metric.mutable_dimensions_in_what()->set_field(tagId); 1629 metric.mutable_dimensions_in_what()->add_child()->set_field(1); 1630 metric.set_use_zero_default_base(true); 1631 1632 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); 1633 EXPECT_CALL(*pullerManager, Pull(tagId, _)) 1634 .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) { 1635 data->clear(); 1636 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs); 1637 event->write(1); 1638 event->write(3); 1639 event->init(); 1640 data->push_back(event); 1641 return true; 1642 })); 1643 1644 sp<ValueMetricProducer> valueProducer = 1645 ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric); 1646 1647 EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size()); 1648 auto iter = valueProducer->mCurrentSlicedBucket.begin(); 1649 auto& interval1 = iter->second[0]; 1650 EXPECT_EQ(1, iter->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value); 1651 EXPECT_EQ(true, interval1.hasBase); 1652 EXPECT_EQ(3, interval1.base.long_value); 1653 EXPECT_EQ(false, interval1.hasValue); 1654 EXPECT_EQ(true, valueProducer->mHasGlobalBase); 1655 EXPECT_EQ(0UL, valueProducer->mPastBuckets.size()); 1656 vector<shared_ptr<LogEvent>> allData; 1657 1658 allData.clear(); 1659 shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1); 1660 event1->write(2); 1661 event1->write(4); 1662 event1->init(); 1663 shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1); 1664 event2->write(1); 1665 event2->write(11); 1666 event2->init(); 1667 allData.push_back(event1); 1668 allData.push_back(event2); 1669 1670 valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs); 1671 EXPECT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size()); 1672 EXPECT_EQ(true, interval1.hasBase); 1673 EXPECT_EQ(11, interval1.base.long_value); 1674 EXPECT_EQ(false, interval1.hasValue); 1675 EXPECT_EQ(8, interval1.value.long_value); 1676 1677 auto it = valueProducer->mCurrentSlicedBucket.begin(); 1678 for (; it != valueProducer->mCurrentSlicedBucket.end(); it++) { 1679 if (it != iter) { 1680 break; 1681 } 1682 } 1683 EXPECT_TRUE(it != iter); 1684 auto& interval2 = it->second[0]; 1685 EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value); 1686 EXPECT_EQ(true, interval2.hasBase); 1687 EXPECT_EQ(4, interval2.base.long_value); 1688 EXPECT_EQ(false, interval2.hasValue); 1689 EXPECT_EQ(4, interval2.value.long_value); 1690 1691 EXPECT_EQ(2UL, valueProducer->mPastBuckets.size()); 1692 auto iterator = valueProducer->mPastBuckets.begin(); 1693 EXPECT_EQ(bucketSizeNs, iterator->second[0].mConditionTrueNs); 1694 EXPECT_EQ(8, iterator->second[0].values[0].long_value); 1695 iterator++; 1696 EXPECT_EQ(bucketSizeNs, iterator->second[0].mConditionTrueNs); 1697 EXPECT_EQ(4, iterator->second[0].values[0].long_value); 1698 } 1699 1700 /* 1701 * Tests using zero default base with failed pull. 1702 */ 1703 TEST(ValueMetricProducerTest, TestUseZeroDefaultBaseWithPullFailures) { 1704 ValueMetric metric = ValueMetricProducerTestHelper::createMetric(); 1705 metric.mutable_dimensions_in_what()->set_field(tagId); 1706 metric.mutable_dimensions_in_what()->add_child()->set_field(1); 1707 metric.set_use_zero_default_base(true); 1708 1709 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); 1710 EXPECT_CALL(*pullerManager, Pull(tagId, _)) 1711 .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) { 1712 data->clear(); 1713 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs); 1714 event->write(1); 1715 event->write(3); 1716 event->init(); 1717 data->push_back(event); 1718 return true; 1719 })); 1720 1721 sp<ValueMetricProducer> valueProducer = 1722 ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric); 1723 1724 EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size()); 1725 auto iter = valueProducer->mCurrentSlicedBucket.begin(); 1726 auto& interval1 = iter->second[0]; 1727 EXPECT_EQ(1, iter->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value); 1728 EXPECT_EQ(true, interval1.hasBase); 1729 EXPECT_EQ(3, interval1.base.long_value); 1730 EXPECT_EQ(false, interval1.hasValue); 1731 EXPECT_EQ(true, valueProducer->mHasGlobalBase); 1732 EXPECT_EQ(0UL, valueProducer->mPastBuckets.size()); 1733 vector<shared_ptr<LogEvent>> allData; 1734 1735 allData.clear(); 1736 shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1); 1737 event1->write(2); 1738 event1->write(4); 1739 event1->init(); 1740 shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1); 1741 event2->write(1); 1742 event2->write(11); 1743 event2->init(); 1744 allData.push_back(event1); 1745 allData.push_back(event2); 1746 1747 valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs); 1748 EXPECT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size()); 1749 EXPECT_EQ(true, interval1.hasBase); 1750 EXPECT_EQ(11, interval1.base.long_value); 1751 EXPECT_EQ(false, interval1.hasValue); 1752 EXPECT_EQ(8, interval1.value.long_value); 1753 1754 auto it = valueProducer->mCurrentSlicedBucket.begin(); 1755 for (; it != valueProducer->mCurrentSlicedBucket.end(); it++) { 1756 if (it != iter) { 1757 break; 1758 } 1759 } 1760 EXPECT_TRUE(it != iter); 1761 auto& interval2 = it->second[0]; 1762 EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value); 1763 EXPECT_EQ(true, interval2.hasBase); 1764 EXPECT_EQ(4, interval2.base.long_value); 1765 EXPECT_EQ(false, interval2.hasValue); 1766 EXPECT_EQ(4, interval2.value.long_value); 1767 EXPECT_EQ(2UL, valueProducer->mPastBuckets.size()); 1768 1769 // next pull somehow did not happen, skip to end of bucket 3 1770 allData.clear(); 1771 event1 = make_shared<LogEvent>(tagId, bucket4StartTimeNs + 1); 1772 event1->write(2); 1773 event1->write(5); 1774 event1->init(); 1775 allData.push_back(event1); 1776 valueProducer->onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs); 1777 1778 EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size()); 1779 EXPECT_EQ(true, interval2.hasBase); 1780 EXPECT_EQ(5, interval2.base.long_value); 1781 EXPECT_EQ(false, interval2.hasValue); 1782 EXPECT_EQ(true, valueProducer->mHasGlobalBase); 1783 EXPECT_EQ(2UL, valueProducer->mPastBuckets.size()); 1784 1785 allData.clear(); 1786 event1 = make_shared<LogEvent>(tagId, bucket5StartTimeNs + 1); 1787 event1->write(2); 1788 event1->write(13); 1789 event1->init(); 1790 allData.push_back(event1); 1791 event2 = make_shared<LogEvent>(tagId, bucket5StartTimeNs + 1); 1792 event2->write(1); 1793 event2->write(5); 1794 event2->init(); 1795 allData.push_back(event2); 1796 valueProducer->onDataPulled(allData, /** succeed */ true, bucket5StartTimeNs); 1797 1798 EXPECT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size()); 1799 auto it1 = std::next(valueProducer->mCurrentSlicedBucket.begin())->second[0]; 1800 EXPECT_EQ(true, it1.hasBase); 1801 EXPECT_EQ(13, it1.base.long_value); 1802 EXPECT_EQ(false, it1.hasValue); 1803 EXPECT_EQ(8, it1.value.long_value); 1804 auto it2 = valueProducer->mCurrentSlicedBucket.begin()->second[0]; 1805 EXPECT_EQ(true, it2.hasBase); 1806 EXPECT_EQ(5, it2.base.long_value); 1807 EXPECT_EQ(false, it2.hasValue); 1808 EXPECT_EQ(5, it2.value.long_value); 1809 EXPECT_EQ(true, valueProducer->mHasGlobalBase); 1810 EXPECT_EQ(2UL, valueProducer->mPastBuckets.size()); 1811 } 1812 1813 /* 1814 * Tests trim unused dimension key if no new data is seen in an entire bucket. 1815 */ 1816 TEST(ValueMetricProducerTest, TestTrimUnusedDimensionKey) { 1817 ValueMetric metric = ValueMetricProducerTestHelper::createMetric(); 1818 metric.mutable_dimensions_in_what()->set_field(tagId); 1819 metric.mutable_dimensions_in_what()->add_child()->set_field(1); 1820 1821 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); 1822 EXPECT_CALL(*pullerManager, Pull(tagId, _)) 1823 .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) { 1824 data->clear(); 1825 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs); 1826 event->write(1); 1827 event->write(3); 1828 event->init(); 1829 data->push_back(event); 1830 return true; 1831 })); 1832 1833 sp<ValueMetricProducer> valueProducer = 1834 ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric); 1835 1836 EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size()); 1837 auto iter = valueProducer->mCurrentSlicedBucket.begin(); 1838 auto& interval1 = iter->second[0]; 1839 EXPECT_EQ(1, iter->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value); 1840 EXPECT_EQ(true, interval1.hasBase); 1841 EXPECT_EQ(3, interval1.base.long_value); 1842 EXPECT_EQ(false, interval1.hasValue); 1843 EXPECT_EQ(0UL, valueProducer->mPastBuckets.size()); 1844 vector<shared_ptr<LogEvent>> allData; 1845 1846 allData.clear(); 1847 shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1); 1848 event1->write(2); 1849 event1->write(4); 1850 event1->init(); 1851 shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1); 1852 event2->write(1); 1853 event2->write(11); 1854 event2->init(); 1855 allData.push_back(event1); 1856 allData.push_back(event2); 1857 1858 valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs); 1859 EXPECT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size()); 1860 EXPECT_EQ(true, interval1.hasBase); 1861 EXPECT_EQ(11, interval1.base.long_value); 1862 EXPECT_EQ(false, interval1.hasValue); 1863 EXPECT_EQ(8, interval1.value.long_value); 1864 EXPECT_FALSE(interval1.seenNewData); 1865 assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {8}, {bucketSizeNs}); 1866 1867 auto it = valueProducer->mCurrentSlicedBucket.begin(); 1868 for (; it != valueProducer->mCurrentSlicedBucket.end(); it++) { 1869 if (it != iter) { 1870 break; 1871 } 1872 } 1873 EXPECT_TRUE(it != iter); 1874 auto& interval2 = it->second[0]; 1875 EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value); 1876 EXPECT_EQ(true, interval2.hasBase); 1877 EXPECT_EQ(4, interval2.base.long_value); 1878 EXPECT_EQ(false, interval2.hasValue); 1879 EXPECT_FALSE(interval2.seenNewData); 1880 assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {8}, {bucketSizeNs}); 1881 1882 // next pull somehow did not happen, skip to end of bucket 3 1883 allData.clear(); 1884 event1 = make_shared<LogEvent>(tagId, bucket4StartTimeNs + 1); 1885 event1->write(2); 1886 event1->write(5); 1887 event1->init(); 1888 allData.push_back(event1); 1889 valueProducer->onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs); 1890 // Only one interval left. One was trimmed. 1891 EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size()); 1892 interval2 = valueProducer->mCurrentSlicedBucket.begin()->second[0]; 1893 EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value); 1894 EXPECT_EQ(true, interval2.hasBase); 1895 EXPECT_EQ(5, interval2.base.long_value); 1896 EXPECT_EQ(false, interval2.hasValue); 1897 EXPECT_FALSE(interval2.seenNewData); 1898 assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {8}, {bucketSizeNs}); 1899 1900 allData.clear(); 1901 event1 = make_shared<LogEvent>(tagId, bucket5StartTimeNs + 1); 1902 event1->write(2); 1903 event1->write(14); 1904 event1->init(); 1905 allData.push_back(event1); 1906 valueProducer->onDataPulled(allData, /** succeed */ true, bucket5StartTimeNs); 1907 1908 interval2 = valueProducer->mCurrentSlicedBucket.begin()->second[0]; 1909 EXPECT_EQ(true, interval2.hasBase); 1910 EXPECT_EQ(14, interval2.base.long_value); 1911 EXPECT_EQ(false, interval2.hasValue); 1912 EXPECT_FALSE(interval2.seenNewData); 1913 ASSERT_EQ(2UL, valueProducer->mPastBuckets.size()); 1914 auto iterator = valueProducer->mPastBuckets.begin(); 1915 EXPECT_EQ(9, iterator->second[0].values[0].long_value); 1916 EXPECT_EQ(bucketSizeNs, iterator->second[0].mConditionTrueNs); 1917 iterator++; 1918 EXPECT_EQ(8, iterator->second[0].values[0].long_value); 1919 EXPECT_EQ(bucketSizeNs, iterator->second[0].mConditionTrueNs); 1920 } 1921 1922 TEST(ValueMetricProducerTest, TestResetBaseOnPullFailAfterConditionChange_EndOfBucket) { 1923 ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition(); 1924 1925 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); 1926 // Used by onConditionChanged. 1927 EXPECT_CALL(*pullerManager, Pull(tagId, _)) 1928 .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) { 1929 data->clear(); 1930 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 8); 1931 event->write(tagId); 1932 event->write(100); 1933 event->init(); 1934 data->push_back(event); 1935 return true; 1936 })); 1937 1938 sp<ValueMetricProducer> valueProducer = 1939 ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric); 1940 1941 valueProducer->onConditionChanged(true, bucketStartTimeNs + 8); 1942 // has one slice 1943 EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size()); 1944 ValueMetricProducer::Interval& curInterval = 1945 valueProducer->mCurrentSlicedBucket.begin()->second[0]; 1946 EXPECT_EQ(true, curInterval.hasBase); 1947 EXPECT_EQ(100, curInterval.base.long_value); 1948 EXPECT_EQ(false, curInterval.hasValue); 1949 1950 vector<shared_ptr<LogEvent>> allData; 1951 valueProducer->onDataPulled(allData, /** succeed */ false, bucket2StartTimeNs); 1952 EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size()); 1953 EXPECT_EQ(false, curInterval.hasBase); 1954 EXPECT_EQ(false, curInterval.hasValue); 1955 EXPECT_EQ(false, valueProducer->mHasGlobalBase); 1956 } 1957 1958 TEST(ValueMetricProducerTest, TestResetBaseOnPullFailAfterConditionChange) { 1959 ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition(); 1960 1961 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); 1962 EXPECT_CALL(*pullerManager, Pull(tagId, _)) 1963 .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) { 1964 data->clear(); 1965 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 8); 1966 event->write(tagId); 1967 event->write(100); 1968 event->init(); 1969 data->push_back(event); 1970 return true; 1971 })) 1972 .WillOnce(Return(false)); 1973 1974 sp<ValueMetricProducer> valueProducer = 1975 ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric); 1976 1977 valueProducer->onConditionChanged(true, bucketStartTimeNs + 8); 1978 1979 // has one slice 1980 EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size()); 1981 ValueMetricProducer::Interval& curInterval = 1982 valueProducer->mCurrentSlicedBucket.begin()->second[0]; 1983 EXPECT_EQ(true, curInterval.hasBase); 1984 EXPECT_EQ(100, curInterval.base.long_value); 1985 EXPECT_EQ(false, curInterval.hasValue); 1986 EXPECT_EQ(0UL, valueProducer->mPastBuckets.size()); 1987 1988 valueProducer->onConditionChanged(false, bucketStartTimeNs + 20); 1989 1990 // has one slice 1991 EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size()); 1992 EXPECT_EQ(false, curInterval.hasValue); 1993 EXPECT_EQ(false, curInterval.hasBase); 1994 EXPECT_EQ(false, valueProducer->mHasGlobalBase); 1995 } 1996 1997 TEST(ValueMetricProducerTest, TestResetBaseOnPullFailBeforeConditionChange) { 1998 ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition(); 1999 2000 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); 2001 EXPECT_CALL(*pullerManager, Pull(tagId, _)) 2002 .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) { 2003 data->clear(); 2004 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs); 2005 event->write(tagId); 2006 event->write(50); 2007 event->init(); 2008 data->push_back(event); 2009 return false; 2010 })) 2011 .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) { 2012 data->clear(); 2013 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 8); 2014 event->write(tagId); 2015 event->write(100); 2016 event->init(); 2017 data->push_back(event); 2018 return true; 2019 })); 2020 2021 sp<ValueMetricProducer> valueProducer = 2022 ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric); 2023 2024 // Don't directly set mCondition; the real code never does that. Go through regular code path 2025 // to avoid unexpected behaviors. 2026 // valueProducer->mCondition = ConditionState::kTrue; 2027 valueProducer->onConditionChanged(true, bucketStartTimeNs); 2028 2029 EXPECT_EQ(0UL, valueProducer->mCurrentSlicedBucket.size()); 2030 2031 valueProducer->onConditionChanged(false, bucketStartTimeNs + 1); 2032 EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size()); 2033 ValueMetricProducer::Interval& curInterval = 2034 valueProducer->mCurrentSlicedBucket.begin()->second[0]; 2035 EXPECT_EQ(false, curInterval.hasBase); 2036 EXPECT_EQ(false, curInterval.hasValue); 2037 EXPECT_EQ(false, valueProducer->mHasGlobalBase); 2038 } 2039 2040 TEST(ValueMetricProducerTest, TestResetBaseOnPullDelayExceeded) { 2041 ValueMetric metric = ValueMetricProducerTestHelper::createMetric(); 2042 metric.set_condition(StringToId("SCREEN_ON")); 2043 metric.set_max_pull_delay_sec(0); 2044 2045 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); 2046 EXPECT_CALL(*pullerManager, Pull(tagId, _)) 2047 .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) { 2048 data->clear(); 2049 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 1); 2050 event->write(tagId); 2051 event->write(120); 2052 event->init(); 2053 data->push_back(event); 2054 return true; 2055 })); 2056 2057 sp<ValueMetricProducer> valueProducer = 2058 ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric); 2059 2060 valueProducer->mCondition = ConditionState::kFalse; 2061 2062 // Max delay is set to 0 so pull will exceed max delay. 2063 valueProducer->onConditionChanged(true, bucketStartTimeNs + 1); 2064 EXPECT_EQ(0UL, valueProducer->mCurrentSlicedBucket.size()); 2065 } 2066 2067 TEST(ValueMetricProducerTest, TestResetBaseOnPullTooLate) { 2068 ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition(); 2069 2070 UidMap uidMap; 2071 SimpleAtomMatcher atomMatcher; 2072 atomMatcher.set_atom_id(tagId); 2073 sp<EventMatcherWizard> eventMatcherWizard = 2074 new EventMatcherWizard({new SimpleLogMatchingTracker( 2075 atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)}); 2076 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>(); 2077 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); 2078 EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return()); 2079 EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return()); 2080 2081 ValueMetricProducer valueProducer(kConfigKey, metric, 1, wizard, logEventMatcherIndex, 2082 eventMatcherWizard, tagId, bucket2StartTimeNs, 2083 bucket2StartTimeNs, pullerManager); 2084 valueProducer.prepareFirstBucket(); 2085 valueProducer.mCondition = ConditionState::kFalse; 2086 2087 // Event should be skipped since it is from previous bucket. 2088 // Pull should not be called. 2089 valueProducer.onConditionChanged(true, bucketStartTimeNs); 2090 EXPECT_EQ(0UL, valueProducer.mCurrentSlicedBucket.size()); 2091 } 2092 2093 TEST(ValueMetricProducerTest, TestBaseSetOnConditionChange) { 2094 ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition(); 2095 2096 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); 2097 EXPECT_CALL(*pullerManager, Pull(tagId, _)) 2098 .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) { 2099 data->clear(); 2100 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 1); 2101 event->write(tagId); 2102 event->write(100); 2103 event->init(); 2104 data->push_back(event); 2105 return true; 2106 })); 2107 2108 sp<ValueMetricProducer> valueProducer = 2109 ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric); 2110 2111 valueProducer->mCondition = ConditionState::kFalse; 2112 valueProducer->mHasGlobalBase = false; 2113 2114 valueProducer->onConditionChanged(true, bucketStartTimeNs + 1); 2115 valueProducer->mHasGlobalBase = true; 2116 EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size()); 2117 ValueMetricProducer::Interval& curInterval = 2118 valueProducer->mCurrentSlicedBucket.begin()->second[0]; 2119 EXPECT_EQ(true, curInterval.hasBase); 2120 EXPECT_EQ(100, curInterval.base.long_value); 2121 EXPECT_EQ(false, curInterval.hasValue); 2122 EXPECT_EQ(true, valueProducer->mHasGlobalBase); 2123 } 2124 2125 TEST(ValueMetricProducerTest, TestInvalidBucketWhenOneConditionFailed) { 2126 ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition(); 2127 2128 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); 2129 EXPECT_CALL(*pullerManager, Pull(tagId, _)) 2130 // First onConditionChanged 2131 .WillOnce(Return(false)) 2132 // Second onConditionChanged 2133 .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) { 2134 data->clear(); 2135 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 8); 2136 event->write(tagId); 2137 event->write(130); 2138 event->init(); 2139 data->push_back(event); 2140 return true; 2141 })); 2142 2143 sp<ValueMetricProducer> valueProducer = 2144 ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric); 2145 2146 valueProducer->mCondition = ConditionState::kTrue; 2147 2148 // Bucket start. 2149 vector<shared_ptr<LogEvent>> allData; 2150 allData.clear(); 2151 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 1); 2152 event->write(1); 2153 event->write(110); 2154 event->init(); 2155 allData.push_back(event); 2156 valueProducer->onDataPulled(allData, /** succeed */ true, bucketStartTimeNs); 2157 2158 // This will fail and should invalidate the whole bucket since we do not have all the data 2159 // needed to compute the metric value when the screen was on. 2160 valueProducer->onConditionChanged(false, bucketStartTimeNs + 2); 2161 valueProducer->onConditionChanged(true, bucketStartTimeNs + 3); 2162 2163 // Bucket end. 2164 allData.clear(); 2165 shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1); 2166 event2->write(1); 2167 event2->write(140); 2168 event2->init(); 2169 allData.push_back(event2); 2170 valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs); 2171 2172 valueProducer->flushIfNeededLocked(bucket2StartTimeNs + 1); 2173 2174 EXPECT_EQ(0UL, valueProducer->mPastBuckets.size()); 2175 // Contains base from last pull which was successful. 2176 EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size()); 2177 ValueMetricProducer::Interval& curInterval = 2178 valueProducer->mCurrentSlicedBucket.begin()->second[0]; 2179 EXPECT_EQ(true, curInterval.hasBase); 2180 EXPECT_EQ(140, curInterval.base.long_value); 2181 EXPECT_EQ(false, curInterval.hasValue); 2182 EXPECT_EQ(true, valueProducer->mHasGlobalBase); 2183 } 2184 2185 TEST(ValueMetricProducerTest, TestInvalidBucketWhenGuardRailHit) { 2186 ValueMetric metric = ValueMetricProducerTestHelper::createMetric(); 2187 metric.mutable_dimensions_in_what()->set_field(tagId); 2188 metric.mutable_dimensions_in_what()->add_child()->set_field(1); 2189 metric.set_condition(StringToId("SCREEN_ON")); 2190 2191 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); 2192 EXPECT_CALL(*pullerManager, Pull(tagId, _)) 2193 // First onConditionChanged 2194 .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) { 2195 for (int i = 0; i < 2000; i++) { 2196 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 1); 2197 event->write(i); 2198 event->write(i); 2199 event->init(); 2200 data->push_back(event); 2201 } 2202 return true; 2203 })); 2204 2205 sp<ValueMetricProducer> valueProducer = 2206 ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric); 2207 valueProducer->mCondition = ConditionState::kFalse; 2208 2209 valueProducer->onConditionChanged(true, bucketStartTimeNs + 2); 2210 EXPECT_EQ(true, valueProducer->mCurrentBucketIsInvalid); 2211 EXPECT_EQ(0UL, valueProducer->mCurrentSlicedBucket.size()); 2212 } 2213 2214 TEST(ValueMetricProducerTest, TestInvalidBucketWhenInitialPullFailed) { 2215 ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition(); 2216 2217 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); 2218 EXPECT_CALL(*pullerManager, Pull(tagId, _)) 2219 // First onConditionChanged 2220 .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) { 2221 data->clear(); 2222 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 8); 2223 event->write(tagId); 2224 event->write(120); 2225 event->init(); 2226 data->push_back(event); 2227 return true; 2228 })) 2229 // Second onConditionChanged 2230 .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) { 2231 data->clear(); 2232 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 8); 2233 event->write(tagId); 2234 event->write(130); 2235 event->init(); 2236 data->push_back(event); 2237 return true; 2238 })); 2239 2240 sp<ValueMetricProducer> valueProducer = 2241 ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric); 2242 2243 valueProducer->mCondition = ConditionState::kTrue; 2244 2245 // Bucket start. 2246 vector<shared_ptr<LogEvent>> allData; 2247 allData.clear(); 2248 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 1); 2249 event->write(1); 2250 event->write(110); 2251 event->init(); 2252 allData.push_back(event); 2253 valueProducer->onDataPulled(allData, /** succeed */ false, bucketStartTimeNs); 2254 2255 valueProducer->onConditionChanged(false, bucketStartTimeNs + 2); 2256 valueProducer->onConditionChanged(true, bucketStartTimeNs + 3); 2257 2258 // Bucket end. 2259 allData.clear(); 2260 shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1); 2261 event2->write(1); 2262 event2->write(140); 2263 event2->init(); 2264 allData.push_back(event2); 2265 valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs); 2266 2267 valueProducer->flushIfNeededLocked(bucket2StartTimeNs + 1); 2268 2269 EXPECT_EQ(0UL, valueProducer->mPastBuckets.size()); 2270 // Contains base from last pull which was successful. 2271 EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size()); 2272 ValueMetricProducer::Interval& curInterval = 2273 valueProducer->mCurrentSlicedBucket.begin()->second[0]; 2274 EXPECT_EQ(true, curInterval.hasBase); 2275 EXPECT_EQ(140, curInterval.base.long_value); 2276 EXPECT_EQ(false, curInterval.hasValue); 2277 EXPECT_EQ(true, valueProducer->mHasGlobalBase); 2278 } 2279 2280 TEST(ValueMetricProducerTest, TestInvalidBucketWhenLastPullFailed) { 2281 ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition(); 2282 2283 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); 2284 EXPECT_CALL(*pullerManager, Pull(tagId, _)) 2285 // First onConditionChanged 2286 .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) { 2287 data->clear(); 2288 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 8); 2289 event->write(tagId); 2290 event->write(120); 2291 event->init(); 2292 data->push_back(event); 2293 return true; 2294 })) 2295 // Second onConditionChanged 2296 .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) { 2297 data->clear(); 2298 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 8); 2299 event->write(tagId); 2300 event->write(130); 2301 event->init(); 2302 data->push_back(event); 2303 return true; 2304 })); 2305 2306 sp<ValueMetricProducer> valueProducer = 2307 ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric); 2308 2309 valueProducer->mCondition = ConditionState::kTrue; 2310 2311 // Bucket start. 2312 vector<shared_ptr<LogEvent>> allData; 2313 allData.clear(); 2314 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 1); 2315 event->write(1); 2316 event->write(110); 2317 event->init(); 2318 allData.push_back(event); 2319 valueProducer->onDataPulled(allData, /** succeed */ true, bucketStartTimeNs); 2320 2321 // This will fail and should invalidate the whole bucket since we do not have all the data 2322 // needed to compute the metric value when the screen was on. 2323 valueProducer->onConditionChanged(false, bucketStartTimeNs + 2); 2324 valueProducer->onConditionChanged(true, bucketStartTimeNs + 3); 2325 2326 // Bucket end. 2327 allData.clear(); 2328 shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1); 2329 event2->write(1); 2330 event2->write(140); 2331 event2->init(); 2332 allData.push_back(event2); 2333 valueProducer->onDataPulled(allData, /** succeed */ false, bucket2StartTimeNs); 2334 2335 valueProducer->flushIfNeededLocked(bucket2StartTimeNs + 1); 2336 2337 EXPECT_EQ(0UL, valueProducer->mPastBuckets.size()); 2338 // Last pull failed so based has been reset. 2339 EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size()); 2340 ValueMetricProducer::Interval& curInterval = 2341 valueProducer->mCurrentSlicedBucket.begin()->second[0]; 2342 EXPECT_EQ(false, curInterval.hasBase); 2343 EXPECT_EQ(false, curInterval.hasValue); 2344 EXPECT_EQ(false, valueProducer->mHasGlobalBase); 2345 } 2346 2347 TEST(ValueMetricProducerTest, TestEmptyDataResetsBase_onDataPulled) { 2348 ValueMetric metric = ValueMetricProducerTestHelper::createMetric(); 2349 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); 2350 EXPECT_CALL(*pullerManager, Pull(tagId, _)) 2351 // Start bucket. 2352 .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) { 2353 data->clear(); 2354 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs); 2355 event->write(tagId); 2356 event->write(3); 2357 event->init(); 2358 data->push_back(event); 2359 return true; 2360 })); 2361 2362 sp<ValueMetricProducer> valueProducer = 2363 ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric); 2364 2365 // Bucket 2 start. 2366 vector<shared_ptr<LogEvent>> allData; 2367 allData.clear(); 2368 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1); 2369 event->write(tagId); 2370 event->write(110); 2371 event->init(); 2372 allData.push_back(event); 2373 valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs); 2374 EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size()); 2375 EXPECT_EQ(1UL, valueProducer->mPastBuckets.size()); 2376 2377 // Bucket 3 empty. 2378 allData.clear(); 2379 shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucket3StartTimeNs + 1); 2380 event2->init(); 2381 allData.push_back(event2); 2382 valueProducer->onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs); 2383 // Data has been trimmed. 2384 EXPECT_EQ(0UL, valueProducer->mCurrentSlicedBucket.size()); 2385 EXPECT_EQ(1UL, valueProducer->mPastBuckets.size()); 2386 } 2387 2388 TEST(ValueMetricProducerTest, TestEmptyDataResetsBase_onConditionChanged) { 2389 ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition(); 2390 2391 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); 2392 EXPECT_CALL(*pullerManager, Pull(tagId, _)) 2393 // First onConditionChanged 2394 .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) { 2395 data->clear(); 2396 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs); 2397 event->write(tagId); 2398 event->write(3); 2399 event->init(); 2400 data->push_back(event); 2401 return true; 2402 })) 2403 .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) { 2404 data->clear(); 2405 return true; 2406 })); 2407 2408 sp<ValueMetricProducer> valueProducer = 2409 ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric); 2410 2411 valueProducer->onConditionChanged(true, bucketStartTimeNs + 10); 2412 EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size()); 2413 ValueMetricProducer::Interval& curInterval = 2414 valueProducer->mCurrentSlicedBucket.begin()->second[0]; 2415 EXPECT_EQ(true, curInterval.hasBase); 2416 EXPECT_EQ(false, curInterval.hasValue); 2417 EXPECT_EQ(true, valueProducer->mHasGlobalBase); 2418 2419 // Empty pull. 2420 valueProducer->onConditionChanged(false, bucketStartTimeNs + 10); 2421 EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size()); 2422 curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0]; 2423 EXPECT_EQ(false, curInterval.hasBase); 2424 EXPECT_EQ(false, curInterval.hasValue); 2425 EXPECT_EQ(false, valueProducer->mHasGlobalBase); 2426 } 2427 2428 TEST(ValueMetricProducerTest, TestEmptyDataResetsBase_onBucketBoundary) { 2429 ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition(); 2430 2431 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); 2432 EXPECT_CALL(*pullerManager, Pull(tagId, _)) 2433 // First onConditionChanged 2434 .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) { 2435 data->clear(); 2436 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs); 2437 event->write(tagId); 2438 event->write(1); 2439 event->init(); 2440 data->push_back(event); 2441 return true; 2442 })) 2443 .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) { 2444 data->clear(); 2445 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs); 2446 event->write(tagId); 2447 event->write(2); 2448 event->init(); 2449 data->push_back(event); 2450 return true; 2451 })) 2452 .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) { 2453 data->clear(); 2454 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs); 2455 event->write(tagId); 2456 event->write(5); 2457 event->init(); 2458 data->push_back(event); 2459 return true; 2460 })); 2461 2462 sp<ValueMetricProducer> valueProducer = 2463 ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric); 2464 2465 valueProducer->onConditionChanged(true, bucketStartTimeNs + 10); 2466 valueProducer->onConditionChanged(false, bucketStartTimeNs + 11); 2467 valueProducer->onConditionChanged(true, bucketStartTimeNs + 12); 2468 EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size()); 2469 ValueMetricProducer::Interval& curInterval = 2470 valueProducer->mCurrentSlicedBucket.begin()->second[0]; 2471 EXPECT_EQ(true, curInterval.hasBase); 2472 EXPECT_EQ(true, curInterval.hasValue); 2473 EXPECT_EQ(true, valueProducer->mHasGlobalBase); 2474 2475 // End of bucket 2476 vector<shared_ptr<LogEvent>> allData; 2477 allData.clear(); 2478 valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs); 2479 EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size()); 2480 curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0]; 2481 // Data is empty, base should be reset. 2482 EXPECT_EQ(false, curInterval.hasBase); 2483 EXPECT_EQ(5, curInterval.base.long_value); 2484 EXPECT_EQ(false, curInterval.hasValue); 2485 EXPECT_EQ(true, valueProducer->mHasGlobalBase); 2486 2487 EXPECT_EQ(1UL, valueProducer->mPastBuckets.size()); 2488 assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {1}, {bucketSizeNs - 12 + 1}); 2489 } 2490 2491 TEST(ValueMetricProducerTest, TestPartialResetOnBucketBoundaries) { 2492 ValueMetric metric = ValueMetricProducerTestHelper::createMetric(); 2493 metric.mutable_dimensions_in_what()->set_field(tagId); 2494 metric.mutable_dimensions_in_what()->add_child()->set_field(1); 2495 metric.set_condition(StringToId("SCREEN_ON")); 2496 2497 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); 2498 EXPECT_CALL(*pullerManager, Pull(tagId, _)) 2499 // First onConditionChanged 2500 .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) { 2501 data->clear(); 2502 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs); 2503 event->write(tagId); 2504 event->write(1); 2505 event->write(1); 2506 event->init(); 2507 data->push_back(event); 2508 return true; 2509 })); 2510 2511 sp<ValueMetricProducer> valueProducer = 2512 ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric); 2513 2514 valueProducer->onConditionChanged(true, bucketStartTimeNs + 10); 2515 EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size()); 2516 2517 // End of bucket 2518 vector<shared_ptr<LogEvent>> allData; 2519 allData.clear(); 2520 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1); 2521 event->write(2); 2522 event->write(2); 2523 event->init(); 2524 allData.push_back(event); 2525 valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs); 2526 2527 // Key 1 should be reset since in not present in the most pull. 2528 EXPECT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size()); 2529 auto iterator = valueProducer->mCurrentSlicedBucket.begin(); 2530 EXPECT_EQ(true, iterator->second[0].hasBase); 2531 EXPECT_EQ(2, iterator->second[0].base.long_value); 2532 EXPECT_EQ(false, iterator->second[0].hasValue); 2533 iterator++; 2534 EXPECT_EQ(false, iterator->second[0].hasBase); 2535 EXPECT_EQ(1, iterator->second[0].base.long_value); 2536 EXPECT_EQ(false, iterator->second[0].hasValue); 2537 2538 EXPECT_EQ(true, valueProducer->mHasGlobalBase); 2539 } 2540 2541 TEST(ValueMetricProducerTest, TestBucketIncludingUnknownConditionIsInvalid) { 2542 ValueMetric metric = ValueMetricProducerTestHelper::createMetric(); 2543 metric.mutable_dimensions_in_what()->set_field(tagId); 2544 metric.mutable_dimensions_in_what()->add_child()->set_field(1); 2545 metric.set_condition(StringToId("SCREEN_ON")); 2546 2547 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); 2548 EXPECT_CALL(*pullerManager, Pull(tagId, _)) 2549 // Second onConditionChanged. 2550 .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) { 2551 data->clear(); 2552 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs); 2553 event->write(tagId); 2554 event->write(2); 2555 event->write(2); 2556 event->init(); 2557 data->push_back(event); 2558 return true; 2559 })); 2560 2561 sp<ValueMetricProducer> valueProducer = 2562 ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric); 2563 valueProducer->mCondition = ConditionState::kUnknown; 2564 2565 valueProducer->onConditionChanged(false, bucketStartTimeNs + 10); 2566 valueProducer->onConditionChanged(true, bucketStartTimeNs + 20); 2567 2568 // End of bucket 2569 vector<shared_ptr<LogEvent>> allData; 2570 allData.clear(); 2571 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1); 2572 event->write(4); 2573 event->write(4); 2574 event->init(); 2575 allData.push_back(event); 2576 valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs); 2577 2578 // Bucket is incomplete so it is mark as invalid, however the base is fine since the last pull 2579 // succeeded. 2580 EXPECT_EQ(0UL, valueProducer->mPastBuckets.size()); 2581 } 2582 2583 TEST(ValueMetricProducerTest, TestFullBucketResetWhenLastBucketInvalid) { 2584 ValueMetric metric = ValueMetricProducerTestHelper::createMetric(); 2585 2586 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); 2587 EXPECT_CALL(*pullerManager, Pull(tagId, _)) 2588 // Initialization. 2589 .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) { 2590 data->clear(); 2591 data->push_back(ValueMetricProducerTestHelper::createEvent(bucketStartTimeNs, 1)); 2592 return true; 2593 })) 2594 // notifyAppUpgrade. 2595 .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) { 2596 data->clear(); 2597 data->push_back(ValueMetricProducerTestHelper::createEvent( 2598 bucketStartTimeNs + bucketSizeNs / 2, 10)); 2599 return true; 2600 })); 2601 sp<ValueMetricProducer> valueProducer = 2602 ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric); 2603 ASSERT_EQ(0UL, valueProducer->mCurrentFullBucket.size()); 2604 2605 valueProducer->notifyAppUpgrade(bucketStartTimeNs + bucketSizeNs / 2, "com.foo", 10000, 1); 2606 ASSERT_EQ(1UL, valueProducer->mCurrentFullBucket.size()); 2607 2608 vector<shared_ptr<LogEvent>> allData; 2609 allData.push_back(ValueMetricProducerTestHelper::createEvent(bucket3StartTimeNs + 1, 4)); 2610 valueProducer->onDataPulled(allData, /** fails */ false, bucket3StartTimeNs + 1); 2611 ASSERT_EQ(0UL, valueProducer->mCurrentFullBucket.size()); 2612 } 2613 2614 TEST(ValueMetricProducerTest, TestBucketBoundariesOnConditionChange) { 2615 ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition(); 2616 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); 2617 EXPECT_CALL(*pullerManager, Pull(tagId, _)) 2618 // Second onConditionChanged. 2619 .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) { 2620 data->clear(); 2621 data->push_back( 2622 ValueMetricProducerTestHelper::createEvent(bucket2StartTimeNs + 10, 5)); 2623 return true; 2624 })) 2625 // Third onConditionChanged. 2626 .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) { 2627 data->clear(); 2628 data->push_back( 2629 ValueMetricProducerTestHelper::createEvent(bucket3StartTimeNs + 10, 7)); 2630 return true; 2631 })); 2632 2633 sp<ValueMetricProducer> valueProducer = 2634 ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric); 2635 valueProducer->mCondition = ConditionState::kUnknown; 2636 2637 valueProducer->onConditionChanged(false, bucketStartTimeNs); 2638 ASSERT_EQ(0UL, valueProducer->mCurrentSlicedBucket.size()); 2639 2640 // End of first bucket 2641 vector<shared_ptr<LogEvent>> allData; 2642 allData.push_back(ValueMetricProducerTestHelper::createEvent(bucket2StartTimeNs + 1, 4)); 2643 valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs + 1); 2644 ASSERT_EQ(0UL, valueProducer->mCurrentSlicedBucket.size()); 2645 2646 valueProducer->onConditionChanged(true, bucket2StartTimeNs + 10); 2647 ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size()); 2648 auto curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0]; 2649 EXPECT_EQ(true, curInterval.hasBase); 2650 EXPECT_EQ(5, curInterval.base.long_value); 2651 EXPECT_EQ(false, curInterval.hasValue); 2652 2653 valueProducer->onConditionChanged(false, bucket3StartTimeNs + 10); 2654 2655 // Bucket should have been completed. 2656 assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {2}, {bucketSizeNs - 10}); 2657 } 2658 2659 TEST(ValueMetricProducerTest, TestLateOnDataPulledWithoutDiff) { 2660 ValueMetric metric = ValueMetricProducerTestHelper::createMetric(); 2661 metric.set_use_diff(false); 2662 2663 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); 2664 sp<ValueMetricProducer> valueProducer = 2665 ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric); 2666 2667 vector<shared_ptr<LogEvent>> allData; 2668 allData.push_back(ValueMetricProducerTestHelper::createEvent(bucketStartTimeNs + 30, 10)); 2669 valueProducer->onDataPulled(allData, /** succeed */ true, bucketStartTimeNs + 30); 2670 2671 allData.clear(); 2672 allData.push_back(ValueMetricProducerTestHelper::createEvent(bucket2StartTimeNs, 20)); 2673 valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs); 2674 2675 // Bucket should have been completed. 2676 assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {30}, {bucketSizeNs}); 2677 } 2678 2679 TEST(ValueMetricProducerTest, TestLateOnDataPulledWithDiff) { 2680 ValueMetric metric = ValueMetricProducerTestHelper::createMetric(); 2681 2682 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); 2683 EXPECT_CALL(*pullerManager, Pull(tagId, _)) 2684 // Initialization. 2685 .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) { 2686 data->clear(); 2687 data->push_back(ValueMetricProducerTestHelper::createEvent(bucketStartTimeNs, 1)); 2688 return true; 2689 })); 2690 2691 sp<ValueMetricProducer> valueProducer = 2692 ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric); 2693 2694 vector<shared_ptr<LogEvent>> allData; 2695 allData.push_back(ValueMetricProducerTestHelper::createEvent(bucketStartTimeNs + 30, 10)); 2696 valueProducer->onDataPulled(allData, /** succeed */ true, bucketStartTimeNs + 30); 2697 2698 allData.clear(); 2699 allData.push_back(ValueMetricProducerTestHelper::createEvent(bucket2StartTimeNs, 20)); 2700 valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs); 2701 2702 // Bucket should have been completed. 2703 assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {19}, {bucketSizeNs}); 2704 } 2705 2706 TEST(ValueMetricProducerTest, TestBucketBoundariesOnAppUpgrade) { 2707 ValueMetric metric = ValueMetricProducerTestHelper::createMetric(); 2708 2709 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); 2710 EXPECT_CALL(*pullerManager, Pull(tagId, _)) 2711 // Initialization. 2712 .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) { 2713 data->clear(); 2714 data->push_back(ValueMetricProducerTestHelper::createEvent(bucketStartTimeNs, 1)); 2715 return true; 2716 })) 2717 // notifyAppUpgrade. 2718 .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) { 2719 data->clear(); 2720 data->push_back( 2721 ValueMetricProducerTestHelper::createEvent(bucket2StartTimeNs + 2, 10)); 2722 return true; 2723 })); 2724 2725 sp<ValueMetricProducer> valueProducer = 2726 ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric); 2727 2728 valueProducer->notifyAppUpgrade(bucket2StartTimeNs + 2, "com.foo", 10000, 1); 2729 2730 // Bucket should have been completed. 2731 assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {9}, {bucketSizeNs}); 2732 } 2733 2734 TEST(ValueMetricProducerTest, TestDataIsNotUpdatedWhenNoConditionChanged) { 2735 ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition(); 2736 2737 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); 2738 EXPECT_CALL(*pullerManager, Pull(tagId, _)) 2739 // First on condition changed. 2740 .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) { 2741 data->clear(); 2742 data->push_back(ValueMetricProducerTestHelper::createEvent(bucketStartTimeNs, 1)); 2743 return true; 2744 })) 2745 // Second on condition changed. 2746 .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) { 2747 data->clear(); 2748 data->push_back(ValueMetricProducerTestHelper::createEvent(bucketStartTimeNs, 3)); 2749 return true; 2750 })); 2751 2752 sp<ValueMetricProducer> valueProducer = 2753 ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric); 2754 2755 valueProducer->onConditionChanged(true, bucketStartTimeNs + 8); 2756 valueProducer->onConditionChanged(false, bucketStartTimeNs + 10); 2757 valueProducer->onConditionChanged(false, bucketStartTimeNs + 10); 2758 2759 EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size()); 2760 auto curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0]; 2761 EXPECT_EQ(true, curInterval.hasValue); 2762 EXPECT_EQ(2, curInterval.value.long_value); 2763 2764 vector<shared_ptr<LogEvent>> allData; 2765 allData.push_back(ValueMetricProducerTestHelper::createEvent(bucket2StartTimeNs + 1, 10)); 2766 valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs + 1); 2767 2768 assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {2}, {2}); 2769 } 2770 2771 TEST(ValueMetricProducerTest, TestBucketInvalidIfGlobalBaseIsNotSet) { 2772 ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition(); 2773 2774 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); 2775 EXPECT_CALL(*pullerManager, Pull(tagId, _)) 2776 // First condition change. 2777 .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) { 2778 data->clear(); 2779 data->push_back(ValueMetricProducerTestHelper::createEvent(bucketStartTimeNs, 1)); 2780 return true; 2781 })) 2782 // 2nd condition change. 2783 .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) { 2784 data->clear(); 2785 data->push_back(ValueMetricProducerTestHelper::createEvent(bucket2StartTimeNs, 1)); 2786 return true; 2787 })) 2788 // 3rd condition change. 2789 .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) { 2790 data->clear(); 2791 data->push_back(ValueMetricProducerTestHelper::createEvent(bucket2StartTimeNs, 1)); 2792 return true; 2793 })); 2794 2795 sp<ValueMetricProducer> valueProducer = 2796 ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric); 2797 valueProducer->onConditionChanged(true, bucket2StartTimeNs + 10); 2798 2799 vector<shared_ptr<LogEvent>> allData; 2800 allData.push_back(ValueMetricProducerTestHelper::createEvent(bucketStartTimeNs + 3, 10)); 2801 valueProducer->onDataPulled(allData, /** succeed */ false, bucketStartTimeNs + 3); 2802 2803 allData.clear(); 2804 allData.push_back(ValueMetricProducerTestHelper::createEvent(bucket2StartTimeNs, 20)); 2805 valueProducer->onDataPulled(allData, /** succeed */ false, bucket2StartTimeNs); 2806 2807 valueProducer->onConditionChanged(false, bucket2StartTimeNs + 8); 2808 valueProducer->onConditionChanged(true, bucket2StartTimeNs + 10); 2809 2810 allData.clear(); 2811 allData.push_back(ValueMetricProducerTestHelper::createEvent(bucket3StartTimeNs, 30)); 2812 valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs); 2813 2814 // There was not global base available so all buckets are invalid. 2815 assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {}, {}); 2816 } 2817 2818 static StatsLogReport outputStreamToProto(ProtoOutputStream* proto) { 2819 vector<uint8_t> bytes; 2820 bytes.resize(proto->size()); 2821 size_t pos = 0; 2822 sp<ProtoReader> reader = proto->data(); 2823 while (reader->readBuffer() != NULL) { 2824 size_t toRead = reader->currentToRead(); 2825 std::memcpy(&((bytes)[pos]), reader->readBuffer(), toRead); 2826 pos += toRead; 2827 reader->move(toRead); 2828 } 2829 2830 StatsLogReport report; 2831 report.ParseFromArray(bytes.data(), bytes.size()); 2832 return report; 2833 } 2834 2835 TEST(ValueMetricProducerTest, TestPullNeededFastDump) { 2836 ValueMetric metric = ValueMetricProducerTestHelper::createMetric(); 2837 2838 UidMap uidMap; 2839 SimpleAtomMatcher atomMatcher; 2840 atomMatcher.set_atom_id(tagId); 2841 sp<EventMatcherWizard> eventMatcherWizard = 2842 new EventMatcherWizard({new SimpleLogMatchingTracker( 2843 atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)}); 2844 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>(); 2845 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); 2846 EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return()); 2847 EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return()); 2848 2849 EXPECT_CALL(*pullerManager, Pull(tagId, _)) 2850 // Initial pull. 2851 .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) { 2852 data->clear(); 2853 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs); 2854 event->write(tagId); 2855 event->write(1); 2856 event->write(1); 2857 event->init(); 2858 data->push_back(event); 2859 return true; 2860 })); 2861 2862 ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex, 2863 eventMatcherWizard, tagId, bucketStartTimeNs, 2864 bucketStartTimeNs, pullerManager); 2865 valueProducer.prepareFirstBucket(); 2866 2867 ProtoOutputStream output; 2868 std::set<string> strSet; 2869 valueProducer.onDumpReport(bucketStartTimeNs + 10, 2870 true /* include recent buckets */, true, 2871 FAST, &strSet, &output); 2872 2873 StatsLogReport report = outputStreamToProto(&output); 2874 // Bucket is invalid since we did not pull when dump report was called. 2875 EXPECT_EQ(0, report.value_metrics().data_size()); 2876 } 2877 2878 TEST(ValueMetricProducerTest, TestFastDumpWithoutCurrentBucket) { 2879 ValueMetric metric = ValueMetricProducerTestHelper::createMetric(); 2880 2881 UidMap uidMap; 2882 SimpleAtomMatcher atomMatcher; 2883 atomMatcher.set_atom_id(tagId); 2884 sp<EventMatcherWizard> eventMatcherWizard = 2885 new EventMatcherWizard({new SimpleLogMatchingTracker( 2886 atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)}); 2887 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>(); 2888 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); 2889 EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return()); 2890 EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return()); 2891 2892 EXPECT_CALL(*pullerManager, Pull(tagId, _)) 2893 // Initial pull. 2894 .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) { 2895 data->clear(); 2896 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs); 2897 event->write(tagId); 2898 event->write(1); 2899 event->write(1); 2900 event->init(); 2901 data->push_back(event); 2902 return true; 2903 })); 2904 2905 ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex, 2906 eventMatcherWizard, tagId, bucketStartTimeNs, 2907 bucketStartTimeNs, pullerManager); 2908 valueProducer.prepareFirstBucket(); 2909 2910 vector<shared_ptr<LogEvent>> allData; 2911 allData.clear(); 2912 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1); 2913 event->write(tagId); 2914 event->write(2); 2915 event->write(2); 2916 event->init(); 2917 allData.push_back(event); 2918 valueProducer.onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs); 2919 2920 ProtoOutputStream output; 2921 std::set<string> strSet; 2922 valueProducer.onDumpReport(bucket4StartTimeNs, 2923 false /* include recent buckets */, true, 2924 FAST, &strSet, &output); 2925 2926 StatsLogReport report = outputStreamToProto(&output); 2927 // Previous bucket is part of the report. 2928 EXPECT_EQ(1, report.value_metrics().data_size()); 2929 EXPECT_EQ(0, report.value_metrics().data(0).bucket_info(0).bucket_num()); 2930 } 2931 2932 TEST(ValueMetricProducerTest, TestPullNeededNoTimeConstraints) { 2933 ValueMetric metric = ValueMetricProducerTestHelper::createMetric(); 2934 2935 UidMap uidMap; 2936 SimpleAtomMatcher atomMatcher; 2937 atomMatcher.set_atom_id(tagId); 2938 sp<EventMatcherWizard> eventMatcherWizard = 2939 new EventMatcherWizard({new SimpleLogMatchingTracker( 2940 atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)}); 2941 sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>(); 2942 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); 2943 EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return()); 2944 EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return()); 2945 2946 EXPECT_CALL(*pullerManager, Pull(tagId, _)) 2947 // Initial pull. 2948 .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) { 2949 data->clear(); 2950 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs); 2951 event->write(tagId); 2952 event->write(1); 2953 event->write(1); 2954 event->init(); 2955 data->push_back(event); 2956 return true; 2957 })) 2958 .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) { 2959 data->clear(); 2960 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10); 2961 event->write(tagId); 2962 event->write(3); 2963 event->write(3); 2964 event->init(); 2965 data->push_back(event); 2966 return true; 2967 })); 2968 2969 ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex, 2970 eventMatcherWizard, tagId, bucketStartTimeNs, 2971 bucketStartTimeNs, pullerManager); 2972 valueProducer.prepareFirstBucket(); 2973 2974 ProtoOutputStream output; 2975 std::set<string> strSet; 2976 valueProducer.onDumpReport(bucketStartTimeNs + 10, 2977 true /* include recent buckets */, true, 2978 NO_TIME_CONSTRAINTS, &strSet, &output); 2979 2980 StatsLogReport report = outputStreamToProto(&output); 2981 EXPECT_EQ(1, report.value_metrics().data_size()); 2982 EXPECT_EQ(1, report.value_metrics().data(0).bucket_info_size()); 2983 EXPECT_EQ(2, report.value_metrics().data(0).bucket_info(0).values(0).value_long()); 2984 } 2985 2986 TEST(ValueMetricProducerTest, TestPulledData_noDiff_withoutCondition) { 2987 ValueMetric metric = ValueMetricProducerTestHelper::createMetric(); 2988 metric.set_use_diff(false); 2989 2990 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); 2991 sp<ValueMetricProducer> valueProducer = 2992 ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric); 2993 2994 vector<shared_ptr<LogEvent>> allData; 2995 allData.push_back(ValueMetricProducerTestHelper::createEvent(bucket2StartTimeNs + 30, 10)); 2996 valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs + 30); 2997 2998 // Bucket should have been completed. 2999 assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {10}, {bucketSizeNs}); 3000 } 3001 3002 TEST(ValueMetricProducerTest, TestPulledData_noDiff_withMultipleConditionChanges) { 3003 ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition(); 3004 metric.set_use_diff(false); 3005 3006 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); 3007 EXPECT_CALL(*pullerManager, Pull(tagId, _)) 3008 // condition becomes true 3009 .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) { 3010 data->clear(); 3011 data->push_back(ValueMetricProducerTestHelper::createEvent( 3012 bucketStartTimeNs + 30, 10)); 3013 return true; 3014 })) 3015 // condition becomes false 3016 .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) { 3017 data->clear(); 3018 data->push_back(ValueMetricProducerTestHelper::createEvent( 3019 bucketStartTimeNs + 50, 20)); 3020 return true; 3021 })); 3022 sp<ValueMetricProducer> valueProducer = 3023 ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric); 3024 valueProducer->mCondition = ConditionState::kFalse; 3025 3026 valueProducer->onConditionChanged(true, bucketStartTimeNs + 8); 3027 valueProducer->onConditionChanged(false, bucketStartTimeNs + 50); 3028 // has one slice 3029 EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size()); 3030 ValueMetricProducer::Interval curInterval = 3031 valueProducer->mCurrentSlicedBucket.begin()->second[0]; 3032 EXPECT_EQ(false, curInterval.hasBase); 3033 EXPECT_EQ(true, curInterval.hasValue); 3034 EXPECT_EQ(20, curInterval.value.long_value); 3035 3036 3037 // Now the alarm is delivered. Condition is off though. 3038 vector<shared_ptr<LogEvent>> allData; 3039 allData.push_back(ValueMetricProducerTestHelper::createEvent(bucket2StartTimeNs + 30, 110)); 3040 valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs); 3041 3042 assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {20}, {50 - 8}); 3043 curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0]; 3044 EXPECT_EQ(false, curInterval.hasBase); 3045 EXPECT_EQ(false, curInterval.hasValue); 3046 } 3047 3048 TEST(ValueMetricProducerTest, TestPulledData_noDiff_bucketBoundaryTrue) { 3049 ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition(); 3050 metric.set_use_diff(false); 3051 3052 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); 3053 EXPECT_CALL(*pullerManager, Pull(tagId, _)) 3054 // condition becomes true 3055 .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) { 3056 data->clear(); 3057 data->push_back(ValueMetricProducerTestHelper::createEvent( 3058 bucketStartTimeNs + 30, 10)); 3059 return true; 3060 })); 3061 sp<ValueMetricProducer> valueProducer = 3062 ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric); 3063 valueProducer->mCondition = ConditionState::kFalse; 3064 3065 valueProducer->onConditionChanged(true, bucketStartTimeNs + 8); 3066 3067 // Now the alarm is delivered. Condition is off though. 3068 vector<shared_ptr<LogEvent>> allData; 3069 allData.push_back(ValueMetricProducerTestHelper::createEvent(bucket2StartTimeNs + 30, 30)); 3070 valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs); 3071 3072 assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {30}, {bucketSizeNs - 8}); 3073 ValueMetricProducer::Interval curInterval = 3074 valueProducer->mCurrentSlicedBucket.begin()->second[0]; 3075 EXPECT_EQ(false, curInterval.hasBase); 3076 EXPECT_EQ(false, curInterval.hasValue); 3077 } 3078 3079 TEST(ValueMetricProducerTest, TestPulledData_noDiff_bucketBoundaryFalse) { 3080 ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition(); 3081 metric.set_use_diff(false); 3082 3083 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); 3084 sp<ValueMetricProducer> valueProducer = 3085 ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric); 3086 valueProducer->mCondition = ConditionState::kFalse; 3087 3088 // Now the alarm is delivered. Condition is off though. 3089 vector<shared_ptr<LogEvent>> allData; 3090 allData.push_back(ValueMetricProducerTestHelper::createEvent(bucket2StartTimeNs + 30, 30)); 3091 valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs); 3092 3093 // Condition was always false. 3094 assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {}, {}); 3095 } 3096 3097 TEST(ValueMetricProducerTest, TestPulledData_noDiff_withFailure) { 3098 ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition(); 3099 metric.set_use_diff(false); 3100 3101 sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); 3102 EXPECT_CALL(*pullerManager, Pull(tagId, _)) 3103 // condition becomes true 3104 .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) { 3105 data->clear(); 3106 data->push_back(ValueMetricProducerTestHelper::createEvent( 3107 bucketStartTimeNs + 30, 10)); 3108 return true; 3109 })) 3110 .WillOnce(Return(false)); 3111 sp<ValueMetricProducer> valueProducer = 3112 ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric); 3113 valueProducer->mCondition = ConditionState::kFalse; 3114 3115 valueProducer->onConditionChanged(true, bucketStartTimeNs + 8); 3116 valueProducer->onConditionChanged(false, bucketStartTimeNs + 50); 3117 3118 // Now the alarm is delivered. Condition is off though. 3119 vector<shared_ptr<LogEvent>> allData; 3120 allData.push_back(ValueMetricProducerTestHelper::createEvent(bucket2StartTimeNs + 30, 30)); 3121 valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs); 3122 3123 // No buckets, we had a failure. 3124 assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {}, {}); 3125 } 3126 3127 } // namespace statsd 3128 } // namespace os 3129 } // namespace android 3130 #else 3131 GTEST_LOG_(INFO) << "This test does nothing.\n"; 3132 #endif 3133