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 <gtest/gtest.h> 16 17#include "src/StatsLogProcessor.h" 18#include "src/stats_log_util.h" 19#include "tests/statsd_test_util.h" 20 21#include <vector> 22 23namespace android { 24namespace os { 25namespace statsd { 26 27#ifdef __ANDROID__ 28 29namespace { 30 31StatsdConfig CreateStatsdConfig() { 32 StatsdConfig config; 33 config.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root. 34 auto temperatureAtomMatcher = CreateTemperatureAtomMatcher(); 35 *config.add_atom_matcher() = temperatureAtomMatcher; 36 *config.add_atom_matcher() = CreateScreenTurnedOnAtomMatcher(); 37 *config.add_atom_matcher() = CreateScreenTurnedOffAtomMatcher(); 38 39 auto screenIsOffPredicate = CreateScreenIsOffPredicate(); 40 *config.add_predicate() = screenIsOffPredicate; 41 42 auto valueMetric = config.add_value_metric(); 43 valueMetric->set_id(123456); 44 valueMetric->set_what(temperatureAtomMatcher.id()); 45 valueMetric->set_condition(screenIsOffPredicate.id()); 46 *valueMetric->mutable_value_field() = 47 CreateDimensions(android::util::TEMPERATURE, {3/* temperature degree field */ }); 48 *valueMetric->mutable_dimensions_in_what() = 49 CreateDimensions(android::util::TEMPERATURE, {2/* sensor name field */ }); 50 valueMetric->set_bucket(FIVE_MINUTES); 51 valueMetric->set_use_absolute_value_on_reset(true); 52 return config; 53} 54 55} // namespace 56 57TEST(ValueMetricE2eTest, TestPulledEvents) { 58 auto config = CreateStatsdConfig(); 59 int64_t baseTimeNs = 10 * NS_PER_SEC; 60 int64_t configAddedTimeNs = 10 * 60 * NS_PER_SEC + baseTimeNs; 61 int64_t bucketSizeNs = 62 TimeUnitToBucketSizeInMillis(config.value_metric(0).bucket()) * 1000000; 63 64 ConfigKey cfgKey; 65 auto processor = CreateStatsLogProcessor( 66 baseTimeNs, configAddedTimeNs, config, cfgKey); 67 EXPECT_EQ(processor->mMetricsManagers.size(), 1u); 68 EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid()); 69 processor->mStatsPullerManager.ForceClearPullerCache(); 70 71 int startBucketNum = processor->mMetricsManagers.begin()->second-> 72 mAllMetricProducers[0]->getCurrentBucketNum(); 73 EXPECT_GT(startBucketNum, (int64_t)0); 74 75 // When creating the config, the gauge metric producer should register the alarm at the 76 // end of the current bucket. 77 EXPECT_EQ((size_t)1, StatsPullerManagerImpl::GetInstance().mReceivers.size()); 78 EXPECT_EQ(bucketSizeNs, 79 StatsPullerManagerImpl::GetInstance().mReceivers.begin()-> 80 second.front().intervalNs); 81 int64_t& expectedPullTimeNs = StatsPullerManagerImpl::GetInstance().mReceivers.begin()-> 82 second.front().nextPullTimeNs; 83 EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + bucketSizeNs, expectedPullTimeNs); 84 85 auto screenOffEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF, 86 configAddedTimeNs + 55); 87 processor->OnLogEvent(screenOffEvent.get()); 88 89 auto screenOnEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON, 90 configAddedTimeNs + 65); 91 processor->OnLogEvent(screenOnEvent.get()); 92 93 screenOffEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF, 94 configAddedTimeNs + 75); 95 processor->OnLogEvent(screenOffEvent.get()); 96 97 // Pulling alarm arrives on time and reset the sequential pulling alarm. 98 processor->informPullAlarmFired(expectedPullTimeNs + 1); 99 EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 2 * bucketSizeNs, expectedPullTimeNs); 100 101 processor->informPullAlarmFired(expectedPullTimeNs + 1); 102 103 screenOnEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON, 104 configAddedTimeNs + 2 * bucketSizeNs + 15); 105 processor->OnLogEvent(screenOnEvent.get()); 106 107 processor->informPullAlarmFired(expectedPullTimeNs + 1); 108 109 processor->informPullAlarmFired(expectedPullTimeNs + 1); 110 111 screenOffEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF, 112 configAddedTimeNs + 4 * bucketSizeNs + 11); 113 processor->OnLogEvent(screenOffEvent.get()); 114 115 processor->informPullAlarmFired(expectedPullTimeNs + 1); 116 117 processor->informPullAlarmFired(expectedPullTimeNs + 1); 118 119 ConfigMetricsReportList reports; 120 vector<uint8_t> buffer; 121 processor->onDumpReport(cfgKey, configAddedTimeNs + 7 * bucketSizeNs + 10, false, ADB_DUMP, 122 &buffer); 123 EXPECT_TRUE(buffer.size() > 0); 124 EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size())); 125 backfillDimensionPath(&reports); 126 backfillStringInReport(&reports); 127 backfillStartEndTimestamp(&reports); 128 EXPECT_EQ(1, reports.reports_size()); 129 EXPECT_EQ(1, reports.reports(0).metrics_size()); 130 StatsLogReport::ValueMetricDataWrapper valueMetrics; 131 sortMetricDataByDimensionsValue( 132 reports.reports(0).metrics(0).value_metrics(), &valueMetrics); 133 EXPECT_GT((int)valueMetrics.data_size(), 1); 134 135 auto data = valueMetrics.data(0); 136 EXPECT_EQ(android::util::TEMPERATURE, data.dimensions_in_what().field()); 137 EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size()); 138 EXPECT_EQ(2 /* sensor name field */, 139 data.dimensions_in_what().value_tuple().dimensions_value(0).field()); 140 EXPECT_FALSE(data.dimensions_in_what().value_tuple().dimensions_value(0).value_str().empty()); 141 EXPECT_EQ(5, data.bucket_info_size()); 142 143 EXPECT_EQ(baseTimeNs + 2 * bucketSizeNs, data.bucket_info(0).start_bucket_elapsed_nanos()); 144 EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos()); 145 EXPECT_TRUE(data.bucket_info(0).has_value()); 146 147 EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs, data.bucket_info(1).start_bucket_elapsed_nanos()); 148 EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs, data.bucket_info(1).end_bucket_elapsed_nanos()); 149 EXPECT_TRUE(data.bucket_info(1).has_value()); 150 151 EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs, data.bucket_info(2).start_bucket_elapsed_nanos()); 152 EXPECT_EQ(baseTimeNs + 5 * bucketSizeNs, data.bucket_info(2).end_bucket_elapsed_nanos()); 153 EXPECT_TRUE(data.bucket_info(2).has_value()); 154 155 EXPECT_EQ(baseTimeNs + 6 * bucketSizeNs, data.bucket_info(3).start_bucket_elapsed_nanos()); 156 EXPECT_EQ(baseTimeNs + 7 * bucketSizeNs, data.bucket_info(3).end_bucket_elapsed_nanos()); 157 EXPECT_TRUE(data.bucket_info(3).has_value()); 158 159 EXPECT_EQ(baseTimeNs + 7 * bucketSizeNs, data.bucket_info(4).start_bucket_elapsed_nanos()); 160 EXPECT_EQ(baseTimeNs + 8 * bucketSizeNs, data.bucket_info(4).end_bucket_elapsed_nanos()); 161 EXPECT_TRUE(data.bucket_info(4).has_value()); 162} 163 164TEST(ValueMetricE2eTest, TestPulledEvents_LateAlarm) { 165 auto config = CreateStatsdConfig(); 166 int64_t baseTimeNs = 10 * NS_PER_SEC; 167 int64_t configAddedTimeNs = 10 * 60 * NS_PER_SEC + baseTimeNs; 168 int64_t bucketSizeNs = 169 TimeUnitToBucketSizeInMillis(config.value_metric(0).bucket()) * 1000000; 170 171 ConfigKey cfgKey; 172 auto processor = CreateStatsLogProcessor( 173 baseTimeNs, configAddedTimeNs, config, cfgKey); 174 EXPECT_EQ(processor->mMetricsManagers.size(), 1u); 175 EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid()); 176 processor->mStatsPullerManager.ForceClearPullerCache(); 177 178 int startBucketNum = processor->mMetricsManagers.begin()->second-> 179 mAllMetricProducers[0]->getCurrentBucketNum(); 180 EXPECT_GT(startBucketNum, (int64_t)0); 181 182 // When creating the config, the gauge metric producer should register the alarm at the 183 // end of the current bucket. 184 EXPECT_EQ((size_t)1, StatsPullerManagerImpl::GetInstance().mReceivers.size()); 185 EXPECT_EQ(bucketSizeNs, 186 StatsPullerManagerImpl::GetInstance().mReceivers.begin()-> 187 second.front().intervalNs); 188 int64_t& expectedPullTimeNs = StatsPullerManagerImpl::GetInstance().mReceivers.begin()-> 189 second.front().nextPullTimeNs; 190 EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + bucketSizeNs, expectedPullTimeNs); 191 192 // Screen off/on/off events. 193 auto screenOffEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF, 194 configAddedTimeNs + 55); 195 processor->OnLogEvent(screenOffEvent.get()); 196 197 auto screenOnEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON, 198 configAddedTimeNs + 65); 199 processor->OnLogEvent(screenOnEvent.get()); 200 201 screenOffEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF, 202 configAddedTimeNs + 75); 203 processor->OnLogEvent(screenOffEvent.get()); 204 205 // Pulling alarm arrives late by 2 buckets and 1 ns. 206 processor->informPullAlarmFired(expectedPullTimeNs + 2 * bucketSizeNs + 1); 207 EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 4 * bucketSizeNs, expectedPullTimeNs); 208 209 screenOnEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON, 210 configAddedTimeNs + 4 * bucketSizeNs + 65); 211 processor->OnLogEvent(screenOnEvent.get()); 212 213 // Pulling alarm arrives late by one bucket size + 21ns. 214 processor->informPullAlarmFired(expectedPullTimeNs + bucketSizeNs + 21); 215 EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 6 * bucketSizeNs, expectedPullTimeNs); 216 217 screenOffEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF, 218 configAddedTimeNs + 6 * bucketSizeNs + 31); 219 processor->OnLogEvent(screenOffEvent.get()); 220 221 processor->informPullAlarmFired(expectedPullTimeNs + bucketSizeNs + 21); 222 EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 8 * bucketSizeNs, expectedPullTimeNs); 223 224 processor->informPullAlarmFired(expectedPullTimeNs + 1); 225 EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 9 * bucketSizeNs, expectedPullTimeNs); 226 227 ConfigMetricsReportList reports; 228 vector<uint8_t> buffer; 229 processor->onDumpReport(cfgKey, configAddedTimeNs + 9 * bucketSizeNs + 10, false, ADB_DUMP, 230 &buffer); 231 EXPECT_TRUE(buffer.size() > 0); 232 EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size())); 233 backfillDimensionPath(&reports); 234 backfillStringInReport(&reports); 235 backfillStartEndTimestamp(&reports); 236 EXPECT_EQ(1, reports.reports_size()); 237 EXPECT_EQ(1, reports.reports(0).metrics_size()); 238 StatsLogReport::ValueMetricDataWrapper valueMetrics; 239 sortMetricDataByDimensionsValue( 240 reports.reports(0).metrics(0).value_metrics(), &valueMetrics); 241 EXPECT_GT((int)valueMetrics.data_size(), 1); 242 243 auto data = valueMetrics.data(0); 244 EXPECT_EQ(android::util::TEMPERATURE, data.dimensions_in_what().field()); 245 EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size()); 246 EXPECT_EQ(2 /* sensor name field */, 247 data.dimensions_in_what().value_tuple().dimensions_value(0).field()); 248 EXPECT_FALSE(data.dimensions_in_what().value_tuple().dimensions_value(0).value_str().empty()); 249 EXPECT_EQ(3, data.bucket_info_size()); 250 251 EXPECT_EQ(baseTimeNs + 2 * bucketSizeNs, data.bucket_info(0).start_bucket_elapsed_nanos()); 252 EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos()); 253 EXPECT_TRUE(data.bucket_info(0).has_value()); 254 255 EXPECT_EQ(baseTimeNs + 8 * bucketSizeNs, data.bucket_info(1).start_bucket_elapsed_nanos()); 256 EXPECT_EQ(baseTimeNs + 9 * bucketSizeNs, data.bucket_info(1).end_bucket_elapsed_nanos()); 257 EXPECT_TRUE(data.bucket_info(1).has_value()); 258 259 EXPECT_EQ(baseTimeNs + 9 * bucketSizeNs, data.bucket_info(2).start_bucket_elapsed_nanos()); 260 EXPECT_EQ(baseTimeNs + 10 * bucketSizeNs, data.bucket_info(2).end_bucket_elapsed_nanos()); 261 EXPECT_TRUE(data.bucket_info(2).has_value()); 262} 263 264#else 265GTEST_LOG_(INFO) << "This test does nothing.\n"; 266#endif 267 268} // namespace statsd 269} // namespace os 270} // namespace android 271