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 <iostream> 22 #include <vector> 23 24 namespace android { 25 namespace os { 26 namespace statsd { 27 28 #ifdef __ANDROID__ 29 30 namespace { 31 32 StatsdConfig CreateStatsdConfig(const Position position) { 33 StatsdConfig config; 34 config.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root. 35 auto wakelockAcquireMatcher = CreateAcquireWakelockAtomMatcher(); 36 auto attributionNodeMatcher = 37 wakelockAcquireMatcher.mutable_simple_atom_matcher()->add_field_value_matcher(); 38 attributionNodeMatcher->set_field(1); 39 attributionNodeMatcher->set_position(Position::ANY); 40 auto uidMatcher = attributionNodeMatcher->mutable_matches_tuple()->add_field_value_matcher(); 41 uidMatcher->set_field(1); // uid field. 42 uidMatcher->set_eq_string("com.android.gmscore"); 43 44 *config.add_atom_matcher() = wakelockAcquireMatcher; 45 46 auto countMetric = config.add_count_metric(); 47 countMetric->set_id(123456); 48 countMetric->set_what(wakelockAcquireMatcher.id()); 49 *countMetric->mutable_dimensions_in_what() = 50 CreateAttributionUidAndTagDimensions( 51 android::util::WAKELOCK_STATE_CHANGED, {position}); 52 countMetric->set_bucket(FIVE_MINUTES); 53 return config; 54 } 55 56 } // namespace 57 58 TEST(AttributionE2eTest, TestAttributionMatchAndSliceByFirstUid) { 59 auto config = CreateStatsdConfig(Position::FIRST); 60 int64_t bucketStartTimeNs = 10000000000; 61 int64_t bucketSizeNs = 62 TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000000; 63 64 ConfigKey cfgKey; 65 auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey); 66 EXPECT_EQ(processor->mMetricsManagers.size(), 1u); 67 EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid()); 68 69 // Here it assumes that GMS core has two uids. 70 processor->getUidMap()->updateMap( 71 1, {222, 444, 111, 333}, {1, 1, 2, 2}, 72 {String16("v1"), String16("v1"), String16("v2"), String16("v2")}, 73 {String16("com.android.gmscore"), String16("com.android.gmscore"), String16("app1"), 74 String16("APP3")}, 75 {String16(""), String16(""), String16(""), String16("")}); 76 77 // GMS core node is in the middle. 78 std::vector<AttributionNodeInternal> attributions1 = {CreateAttribution(111, "App1"), 79 CreateAttribution(222, "GMSCoreModule1"), 80 CreateAttribution(333, "App3")}; 81 82 // GMS core node is the last one. 83 std::vector<AttributionNodeInternal> attributions2 = {CreateAttribution(111, "App1"), 84 CreateAttribution(333, "App3"), 85 CreateAttribution(222, "GMSCoreModule1")}; 86 87 // GMS core node is the first one. 88 std::vector<AttributionNodeInternal> attributions3 = {CreateAttribution(222, "GMSCoreModule1"), 89 CreateAttribution(333, "App3")}; 90 91 // Single GMS core node. 92 std::vector<AttributionNodeInternal> attributions4 = {CreateAttribution(222, "GMSCoreModule1")}; 93 94 // GMS core has another uid. 95 std::vector<AttributionNodeInternal> attributions5 = {CreateAttribution(111, "App1"), 96 CreateAttribution(444, "GMSCoreModule2"), 97 CreateAttribution(333, "App3")}; 98 99 // Multiple GMS core nodes. 100 std::vector<AttributionNodeInternal> attributions6 = {CreateAttribution(444, "GMSCoreModule2"), 101 CreateAttribution(222, "GMSCoreModule1")}; 102 103 // No GMS core nodes. 104 std::vector<AttributionNodeInternal> attributions7 = {CreateAttribution(111, "App1"), 105 CreateAttribution(333, "App3")}; 106 std::vector<AttributionNodeInternal> attributions8 = {CreateAttribution(111, "App1")}; 107 108 // GMS core node with isolated uid. 109 const int isolatedUid = 666; 110 std::vector<AttributionNodeInternal> attributions9 = { 111 CreateAttribution(isolatedUid, "GMSCoreModule3")}; 112 113 std::vector<std::unique_ptr<LogEvent>> events; 114 // Events 1~4 are in the 1st bucket. 115 events.push_back(CreateAcquireWakelockEvent( 116 attributions1, "wl1", bucketStartTimeNs + 2)); 117 events.push_back(CreateAcquireWakelockEvent( 118 attributions2, "wl1", bucketStartTimeNs + 200)); 119 events.push_back(CreateAcquireWakelockEvent( 120 attributions3, "wl1", bucketStartTimeNs + bucketSizeNs - 1)); 121 events.push_back(CreateAcquireWakelockEvent( 122 attributions4, "wl1", bucketStartTimeNs + bucketSizeNs)); 123 124 // Events 5~8 are in the 3rd bucket. 125 events.push_back(CreateAcquireWakelockEvent( 126 attributions5, "wl2", bucketStartTimeNs + 2 * bucketSizeNs + 1)); 127 events.push_back(CreateAcquireWakelockEvent( 128 attributions6, "wl2", bucketStartTimeNs + 2 * bucketSizeNs + 100)); 129 events.push_back(CreateAcquireWakelockEvent( 130 attributions7, "wl2", bucketStartTimeNs + 3 * bucketSizeNs - 2)); 131 events.push_back(CreateAcquireWakelockEvent( 132 attributions8, "wl2", bucketStartTimeNs + 3 * bucketSizeNs)); 133 events.push_back(CreateAcquireWakelockEvent( 134 attributions9, "wl2", bucketStartTimeNs + 3 * bucketSizeNs + 1)); 135 events.push_back(CreateAcquireWakelockEvent( 136 attributions9, "wl2", bucketStartTimeNs + 3 * bucketSizeNs + 100)); 137 events.push_back(CreateIsolatedUidChangedEvent( 138 isolatedUid, 222, true/* is_create*/, bucketStartTimeNs + 3 * bucketSizeNs - 1)); 139 events.push_back(CreateIsolatedUidChangedEvent( 140 isolatedUid, 222, false/* is_create*/, bucketStartTimeNs + 3 * bucketSizeNs + 10)); 141 142 sortLogEventsByTimestamp(&events); 143 144 for (const auto& event : events) { 145 processor->OnLogEvent(event.get()); 146 } 147 ConfigMetricsReportList reports; 148 vector<uint8_t> buffer; 149 processor->onDumpReport(cfgKey, bucketStartTimeNs + 4 * bucketSizeNs + 1, false, true, 150 ADB_DUMP, FAST, &buffer); 151 EXPECT_TRUE(buffer.size() > 0); 152 EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size())); 153 backfillDimensionPath(&reports); 154 backfillStringInReport(&reports); 155 backfillStartEndTimestamp(&reports); 156 EXPECT_EQ(reports.reports_size(), 1); 157 EXPECT_EQ(reports.reports(0).metrics_size(), 1); 158 159 StatsLogReport::CountMetricDataWrapper countMetrics; 160 sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).count_metrics(), &countMetrics); 161 EXPECT_EQ(countMetrics.data_size(), 4); 162 163 auto data = countMetrics.data(0); 164 ValidateAttributionUidAndTagDimension( 165 data.dimensions_in_what(), android::util::WAKELOCK_STATE_CHANGED, 111, 166 "App1"); 167 EXPECT_EQ(data.bucket_info_size(), 2); 168 EXPECT_EQ(data.bucket_info(0).count(), 2); 169 EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs); 170 EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), bucketStartTimeNs + bucketSizeNs); 171 EXPECT_EQ(data.bucket_info(1).count(), 1); 172 EXPECT_EQ(data.bucket_info(1).start_bucket_elapsed_nanos(), bucketStartTimeNs + 2 * bucketSizeNs); 173 EXPECT_EQ(data.bucket_info(1).end_bucket_elapsed_nanos(), bucketStartTimeNs + 3 * bucketSizeNs); 174 175 data = countMetrics.data(1); 176 ValidateAttributionUidAndTagDimension( 177 data.dimensions_in_what(), android::util::WAKELOCK_STATE_CHANGED, 222, 178 "GMSCoreModule1"); 179 EXPECT_EQ(data.bucket_info_size(), 2); 180 EXPECT_EQ(data.bucket_info(0).count(), 1); 181 EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs); 182 EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), bucketStartTimeNs + bucketSizeNs); 183 EXPECT_EQ(data.bucket_info(1).count(), 1); 184 EXPECT_EQ(data.bucket_info(1).start_bucket_elapsed_nanos(), bucketStartTimeNs + bucketSizeNs); 185 EXPECT_EQ(data.bucket_info(1).end_bucket_elapsed_nanos(), bucketStartTimeNs + 2 * bucketSizeNs); 186 187 data = countMetrics.data(2); 188 ValidateAttributionUidAndTagDimension( 189 data.dimensions_in_what(), android::util::WAKELOCK_STATE_CHANGED, 222, 190 "GMSCoreModule3"); 191 EXPECT_EQ(data.bucket_info_size(), 1); 192 EXPECT_EQ(data.bucket_info(0).count(), 1); 193 EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs + 3 * bucketSizeNs); 194 EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), bucketStartTimeNs + 4 * bucketSizeNs); 195 196 data = countMetrics.data(3); 197 ValidateAttributionUidAndTagDimension( 198 data.dimensions_in_what(), android::util::WAKELOCK_STATE_CHANGED, 444, 199 "GMSCoreModule2"); 200 EXPECT_EQ(data.bucket_info_size(), 1); 201 EXPECT_EQ(data.bucket_info(0).count(), 1); 202 EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs + 2 * bucketSizeNs); 203 EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), bucketStartTimeNs + 3 * bucketSizeNs); 204 } 205 206 TEST(AttributionE2eTest, TestAttributionMatchAndSliceByChain) { 207 auto config = CreateStatsdConfig(Position::ALL); 208 int64_t bucketStartTimeNs = 10000000000; 209 int64_t bucketSizeNs = 210 TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000000; 211 212 ConfigKey cfgKey; 213 auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey); 214 EXPECT_EQ(processor->mMetricsManagers.size(), 1u); 215 EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid()); 216 217 // Here it assumes that GMS core has two uids. 218 processor->getUidMap()->updateMap( 219 1, {222, 444, 111, 333}, {1, 1, 2, 2}, 220 {String16("v1"), String16("v1"), String16("v2"), String16("v2")}, 221 {String16("com.android.gmscore"), String16("com.android.gmscore"), String16("app1"), 222 String16("APP3")}, 223 {String16(""), String16(""), String16(""), String16("")}); 224 225 // GMS core node is in the middle. 226 std::vector<AttributionNodeInternal> attributions1 = {CreateAttribution(111, "App1"), 227 CreateAttribution(222, "GMSCoreModule1"), 228 CreateAttribution(333, "App3")}; 229 230 // GMS core node is the last one. 231 std::vector<AttributionNodeInternal> attributions2 = {CreateAttribution(111, "App1"), 232 CreateAttribution(333, "App3"), 233 CreateAttribution(222, "GMSCoreModule1")}; 234 235 // GMS core node is the first one. 236 std::vector<AttributionNodeInternal> attributions3 = {CreateAttribution(222, "GMSCoreModule1"), 237 CreateAttribution(333, "App3")}; 238 239 // Single GMS core node. 240 std::vector<AttributionNodeInternal> attributions4 = {CreateAttribution(222, "GMSCoreModule1")}; 241 242 // GMS core has another uid. 243 std::vector<AttributionNodeInternal> attributions5 = {CreateAttribution(111, "App1"), 244 CreateAttribution(444, "GMSCoreModule2"), 245 CreateAttribution(333, "App3")}; 246 247 // Multiple GMS core nodes. 248 std::vector<AttributionNodeInternal> attributions6 = {CreateAttribution(444, "GMSCoreModule2"), 249 CreateAttribution(222, "GMSCoreModule1")}; 250 251 // No GMS core nodes. 252 std::vector<AttributionNodeInternal> attributions7 = {CreateAttribution(111, "App1"), 253 CreateAttribution(333, "App3")}; 254 std::vector<AttributionNodeInternal> attributions8 = {CreateAttribution(111, "App1")}; 255 256 // GMS core node with isolated uid. 257 const int isolatedUid = 666; 258 std::vector<AttributionNodeInternal> attributions9 = { 259 CreateAttribution(isolatedUid, "GMSCoreModule1")}; 260 261 std::vector<std::unique_ptr<LogEvent>> events; 262 // Events 1~4 are in the 1st bucket. 263 events.push_back(CreateAcquireWakelockEvent( 264 attributions1, "wl1", bucketStartTimeNs + 2)); 265 events.push_back(CreateAcquireWakelockEvent( 266 attributions2, "wl1", bucketStartTimeNs + 200)); 267 events.push_back(CreateAcquireWakelockEvent( 268 attributions3, "wl1", bucketStartTimeNs + bucketSizeNs - 1)); 269 events.push_back(CreateAcquireWakelockEvent( 270 attributions4, "wl1", bucketStartTimeNs + bucketSizeNs)); 271 272 // Events 5~8 are in the 3rd bucket. 273 events.push_back(CreateAcquireWakelockEvent( 274 attributions5, "wl2", bucketStartTimeNs + 2 * bucketSizeNs + 1)); 275 events.push_back(CreateAcquireWakelockEvent( 276 attributions6, "wl2", bucketStartTimeNs + 2 * bucketSizeNs + 100)); 277 events.push_back(CreateAcquireWakelockEvent( 278 attributions7, "wl2", bucketStartTimeNs + 3 * bucketSizeNs - 2)); 279 events.push_back(CreateAcquireWakelockEvent( 280 attributions8, "wl2", bucketStartTimeNs + 3 * bucketSizeNs)); 281 events.push_back(CreateAcquireWakelockEvent( 282 attributions9, "wl2", bucketStartTimeNs + 3 * bucketSizeNs + 1)); 283 events.push_back(CreateAcquireWakelockEvent( 284 attributions9, "wl2", bucketStartTimeNs + 3 * bucketSizeNs + 100)); 285 events.push_back(CreateIsolatedUidChangedEvent( 286 isolatedUid, 222, true/* is_create*/, bucketStartTimeNs + 3 * bucketSizeNs - 1)); 287 events.push_back(CreateIsolatedUidChangedEvent( 288 isolatedUid, 222, false/* is_create*/, bucketStartTimeNs + 3 * bucketSizeNs + 10)); 289 290 sortLogEventsByTimestamp(&events); 291 292 for (const auto& event : events) { 293 processor->OnLogEvent(event.get()); 294 } 295 ConfigMetricsReportList reports; 296 vector<uint8_t> buffer; 297 processor->onDumpReport(cfgKey, bucketStartTimeNs + 4 * bucketSizeNs + 1, false, true, 298 ADB_DUMP, FAST, &buffer); 299 EXPECT_TRUE(buffer.size() > 0); 300 EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size())); 301 backfillDimensionPath(&reports); 302 backfillStringInReport(&reports); 303 backfillStartEndTimestamp(&reports); 304 EXPECT_EQ(reports.reports_size(), 1); 305 EXPECT_EQ(reports.reports(0).metrics_size(), 1); 306 307 StatsLogReport::CountMetricDataWrapper countMetrics; 308 sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).count_metrics(), &countMetrics); 309 EXPECT_EQ(countMetrics.data_size(), 6); 310 311 auto data = countMetrics.data(0); 312 ValidateAttributionUidAndTagDimension( 313 data.dimensions_in_what(), android::util::WAKELOCK_STATE_CHANGED, 222, "GMSCoreModule1"); 314 EXPECT_EQ(2, data.bucket_info_size()); 315 EXPECT_EQ(1, data.bucket_info(0).count()); 316 EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, 317 data.bucket_info(0).start_bucket_elapsed_nanos()); 318 EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs, 319 data.bucket_info(0).end_bucket_elapsed_nanos()); 320 EXPECT_EQ(1, data.bucket_info(1).count()); 321 EXPECT_EQ(bucketStartTimeNs + 3 * bucketSizeNs, 322 data.bucket_info(1).start_bucket_elapsed_nanos()); 323 EXPECT_EQ(bucketStartTimeNs + 4 * bucketSizeNs, 324 data.bucket_info(1).end_bucket_elapsed_nanos()); 325 326 data = countMetrics.data(1); 327 ValidateUidDimension( 328 data.dimensions_in_what(), 0, android::util::WAKELOCK_STATE_CHANGED, 222); 329 ValidateAttributionUidAndTagDimension( 330 data.dimensions_in_what(), 0, android::util::WAKELOCK_STATE_CHANGED, 222, "GMSCoreModule1"); 331 ValidateUidDimension( 332 data.dimensions_in_what(), 1, android::util::WAKELOCK_STATE_CHANGED, 333); 333 ValidateAttributionUidAndTagDimension( 334 data.dimensions_in_what(), 1, android::util::WAKELOCK_STATE_CHANGED, 333, "App3"); 335 EXPECT_EQ(data.bucket_info_size(), 1); 336 EXPECT_EQ(data.bucket_info(0).count(), 1); 337 EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs); 338 EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), bucketStartTimeNs + bucketSizeNs); 339 340 data = countMetrics.data(2); 341 ValidateUidDimension( 342 data.dimensions_in_what(), 0, android::util::WAKELOCK_STATE_CHANGED, 444); 343 ValidateAttributionUidAndTagDimension( 344 data.dimensions_in_what(), 0, android::util::WAKELOCK_STATE_CHANGED, 444, "GMSCoreModule2"); 345 ValidateUidDimension( 346 data.dimensions_in_what(), 1, android::util::WAKELOCK_STATE_CHANGED, 222); 347 ValidateAttributionUidAndTagDimension( 348 data.dimensions_in_what(), 1, android::util::WAKELOCK_STATE_CHANGED, 222, "GMSCoreModule1"); 349 EXPECT_EQ(data.bucket_info_size(), 1); 350 EXPECT_EQ(data.bucket_info(0).count(), 1); 351 EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs, 352 data.bucket_info(0).start_bucket_elapsed_nanos()); 353 EXPECT_EQ(bucketStartTimeNs + 3 * bucketSizeNs, 354 data.bucket_info(0).end_bucket_elapsed_nanos()); 355 356 data = countMetrics.data(3); 357 ValidateUidDimension( 358 data.dimensions_in_what(), 0, android::util::WAKELOCK_STATE_CHANGED, 111); 359 ValidateAttributionUidAndTagDimension( 360 data.dimensions_in_what(), 0, android::util::WAKELOCK_STATE_CHANGED, 111, "App1"); 361 ValidateUidDimension( 362 data.dimensions_in_what(), 1, android::util::WAKELOCK_STATE_CHANGED, 222); 363 ValidateAttributionUidAndTagDimension( 364 data.dimensions_in_what(), 1, android::util::WAKELOCK_STATE_CHANGED, 222, "GMSCoreModule1"); 365 ValidateUidDimension( 366 data.dimensions_in_what(), 2, android::util::WAKELOCK_STATE_CHANGED, 333); 367 ValidateAttributionUidAndTagDimension( 368 data.dimensions_in_what(), 2, android::util::WAKELOCK_STATE_CHANGED, 333, "App3"); 369 EXPECT_EQ(data.bucket_info_size(), 1); 370 EXPECT_EQ(data.bucket_info(0).count(), 1); 371 EXPECT_EQ(bucketStartTimeNs, 372 data.bucket_info(0).start_bucket_elapsed_nanos()); 373 EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, 374 data.bucket_info(0).end_bucket_elapsed_nanos()); 375 376 data = countMetrics.data(4); 377 ValidateUidDimension( 378 data.dimensions_in_what(), 0, android::util::WAKELOCK_STATE_CHANGED, 111); 379 ValidateAttributionUidAndTagDimension( 380 data.dimensions_in_what(), 0, android::util::WAKELOCK_STATE_CHANGED, 111, "App1"); 381 ValidateUidDimension( 382 data.dimensions_in_what(), 1, android::util::WAKELOCK_STATE_CHANGED, 333); 383 ValidateAttributionUidAndTagDimension( 384 data.dimensions_in_what(), 1, android::util::WAKELOCK_STATE_CHANGED, 333, "App3"); 385 ValidateUidDimension( 386 data.dimensions_in_what(), 2, android::util::WAKELOCK_STATE_CHANGED, 222); 387 ValidateAttributionUidAndTagDimension( 388 data.dimensions_in_what(), 2, android::util::WAKELOCK_STATE_CHANGED, 222, "GMSCoreModule1"); 389 EXPECT_EQ(data.bucket_info_size(), 1); 390 EXPECT_EQ(data.bucket_info(0).count(), 1); 391 EXPECT_EQ(bucketStartTimeNs, 392 data.bucket_info(0).start_bucket_elapsed_nanos()); 393 EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, 394 data.bucket_info(0).end_bucket_elapsed_nanos()); 395 396 data = countMetrics.data(5); 397 ValidateUidDimension( 398 data.dimensions_in_what(), 0, android::util::WAKELOCK_STATE_CHANGED, 111); 399 ValidateAttributionUidAndTagDimension( 400 data.dimensions_in_what(), 0, android::util::WAKELOCK_STATE_CHANGED, 111, "App1"); 401 ValidateUidDimension( 402 data.dimensions_in_what(), 1, android::util::WAKELOCK_STATE_CHANGED, 444); 403 ValidateAttributionUidAndTagDimension( 404 data.dimensions_in_what(), 1, android::util::WAKELOCK_STATE_CHANGED, 444, "GMSCoreModule2"); 405 ValidateUidDimension( 406 data.dimensions_in_what(), 2, android::util::WAKELOCK_STATE_CHANGED, 333); 407 ValidateAttributionUidAndTagDimension( 408 data.dimensions_in_what(), 2, android::util::WAKELOCK_STATE_CHANGED, 333, "App3"); 409 EXPECT_EQ(data.bucket_info_size(), 1); 410 EXPECT_EQ(data.bucket_info(0).count(), 1); 411 EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs, 412 data.bucket_info(0).start_bucket_elapsed_nanos()); 413 EXPECT_EQ(bucketStartTimeNs + 3 * bucketSizeNs, 414 data.bucket_info(0).end_bucket_elapsed_nanos()); 415 } 416 417 #else 418 GTEST_LOG_(INFO) << "This test does nothing.\n"; 419 #endif 420 421 } // namespace statsd 422 } // namespace os 423 } // namespace android 424