1 // 2 // Copyright (C) 2017 The Android Open Source Project 3 // 4 // Licensed under the Apache License, Version 2.0 (the "License"); 5 // you may not use this file except in compliance with the License. 6 // You may obtain a copy of the License at 7 // 8 // http://www.apache.org/licenses/LICENSE-2.0 9 // 10 // Unless required by applicable law or agreed to in writing, software 11 // distributed under the License is distributed on an "AS IS" BASIS, 12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 // See the License for the specific language governing permissions and 14 // limitations under the License. 15 // 16 17 #include "update_engine/metrics_reporter_omaha.h" 18 19 #include <memory> 20 #include <string> 21 22 #include <base/time/time.h> 23 #include <gmock/gmock.h> 24 #include <gtest/gtest.h> 25 #include <metrics/metrics_library_mock.h> 26 27 #include "update_engine/common/fake_clock.h" 28 #include "update_engine/common/fake_prefs.h" 29 #include "update_engine/fake_system_state.h" 30 31 using base::TimeDelta; 32 using testing::_; 33 using testing::AnyNumber; 34 using testing::Return; 35 36 namespace chromeos_update_engine { 37 class MetricsReporterOmahaTest : public ::testing::Test { 38 protected: 39 MetricsReporterOmahaTest() = default; 40 41 // Reset the metrics_lib_ to a mock library. 42 void SetUp() override { 43 mock_metrics_lib_ = new testing::NiceMock<MetricsLibraryMock>(); 44 reporter_.metrics_lib_.reset(mock_metrics_lib_); 45 } 46 47 testing::NiceMock<MetricsLibraryMock>* mock_metrics_lib_; 48 MetricsReporterOmaha reporter_; 49 }; 50 51 TEST_F(MetricsReporterOmahaTest, ReportDailyMetrics) { 52 TimeDelta age = TimeDelta::FromDays(10); 53 EXPECT_CALL(*mock_metrics_lib_, 54 SendToUMA(metrics::kMetricDailyOSAgeDays, _, _, _, _)) 55 .Times(1); 56 57 reporter_.ReportDailyMetrics(age); 58 } 59 60 TEST_F(MetricsReporterOmahaTest, ReportUpdateCheckMetrics) { 61 FakeSystemState fake_system_state; 62 FakeClock fake_clock; 63 FakePrefs fake_prefs; 64 65 // We need to execute the report twice to test the time since last report. 66 fake_system_state.set_clock(&fake_clock); 67 fake_system_state.set_prefs(&fake_prefs); 68 fake_clock.SetWallclockTime(base::Time::FromInternalValue(1000000)); 69 fake_clock.SetMonotonicTime(base::Time::FromInternalValue(1000000)); 70 71 metrics::CheckResult result = metrics::CheckResult::kUpdateAvailable; 72 metrics::CheckReaction reaction = metrics::CheckReaction::kIgnored; 73 metrics::DownloadErrorCode error_code = 74 metrics::DownloadErrorCode::kHttpStatus200; 75 76 EXPECT_CALL( 77 *mock_metrics_lib_, 78 SendEnumToUMA(metrics::kMetricCheckResult, static_cast<int>(result), _)) 79 .Times(2); 80 EXPECT_CALL(*mock_metrics_lib_, 81 SendEnumToUMA( 82 metrics::kMetricCheckReaction, static_cast<int>(reaction), _)) 83 .Times(2); 84 EXPECT_CALL(*mock_metrics_lib_, 85 SendSparseToUMA(metrics::kMetricCheckDownloadErrorCode, 86 static_cast<int>(error_code))) 87 .Times(2); 88 89 // Not pinned nor rollback 90 EXPECT_CALL(*mock_metrics_lib_, 91 SendSparseToUMA(metrics::kMetricCheckTargetVersion, _)) 92 .Times(0); 93 EXPECT_CALL(*mock_metrics_lib_, 94 SendSparseToUMA(metrics::kMetricCheckRollbackTargetVersion, _)) 95 .Times(0); 96 97 EXPECT_CALL( 98 *mock_metrics_lib_, 99 SendToUMA(metrics::kMetricCheckTimeSinceLastCheckMinutes, 1, _, _, _)) 100 .Times(1); 101 EXPECT_CALL( 102 *mock_metrics_lib_, 103 SendToUMA( 104 metrics::kMetricCheckTimeSinceLastCheckUptimeMinutes, 1, _, _, _)) 105 .Times(1); 106 107 reporter_.ReportUpdateCheckMetrics( 108 &fake_system_state, result, reaction, error_code); 109 110 // Advance the clock by 1 minute and report the same metrics again. 111 fake_clock.SetWallclockTime(base::Time::FromInternalValue(61000000)); 112 fake_clock.SetMonotonicTime(base::Time::FromInternalValue(61000000)); 113 // Allow rollback 114 reporter_.ReportUpdateCheckMetrics( 115 &fake_system_state, result, reaction, error_code); 116 } 117 118 TEST_F(MetricsReporterOmahaTest, ReportUpdateCheckMetricsPinned) { 119 FakeSystemState fake_system_state; 120 121 OmahaRequestParams params(&fake_system_state); 122 params.set_target_version_prefix("10575."); 123 params.set_rollback_allowed(false); 124 fake_system_state.set_request_params(¶ms); 125 126 metrics::CheckResult result = metrics::CheckResult::kUpdateAvailable; 127 metrics::CheckReaction reaction = metrics::CheckReaction::kIgnored; 128 metrics::DownloadErrorCode error_code = 129 metrics::DownloadErrorCode::kHttpStatus200; 130 131 EXPECT_CALL(*mock_metrics_lib_, 132 SendSparseToUMA(metrics::kMetricCheckDownloadErrorCode, _)); 133 // Target version set, but not a rollback. 134 EXPECT_CALL(*mock_metrics_lib_, 135 SendSparseToUMA(metrics::kMetricCheckTargetVersion, 10575)) 136 .Times(1); 137 EXPECT_CALL(*mock_metrics_lib_, 138 SendSparseToUMA(metrics::kMetricCheckRollbackTargetVersion, _)) 139 .Times(0); 140 141 reporter_.ReportUpdateCheckMetrics( 142 &fake_system_state, result, reaction, error_code); 143 } 144 145 TEST_F(MetricsReporterOmahaTest, ReportUpdateCheckMetricsRollback) { 146 FakeSystemState fake_system_state; 147 148 OmahaRequestParams params(&fake_system_state); 149 params.set_target_version_prefix("10575."); 150 params.set_rollback_allowed(true); 151 fake_system_state.set_request_params(¶ms); 152 153 metrics::CheckResult result = metrics::CheckResult::kUpdateAvailable; 154 metrics::CheckReaction reaction = metrics::CheckReaction::kIgnored; 155 metrics::DownloadErrorCode error_code = 156 metrics::DownloadErrorCode::kHttpStatus200; 157 158 EXPECT_CALL(*mock_metrics_lib_, 159 SendSparseToUMA(metrics::kMetricCheckDownloadErrorCode, _)); 160 // Rollback. 161 EXPECT_CALL(*mock_metrics_lib_, 162 SendSparseToUMA(metrics::kMetricCheckTargetVersion, 10575)) 163 .Times(1); 164 EXPECT_CALL( 165 *mock_metrics_lib_, 166 SendSparseToUMA(metrics::kMetricCheckRollbackTargetVersion, 10575)) 167 .Times(1); 168 169 reporter_.ReportUpdateCheckMetrics( 170 &fake_system_state, result, reaction, error_code); 171 } 172 173 TEST_F(MetricsReporterOmahaTest, 174 ReportAbnormallyTerminatedUpdateAttemptMetrics) { 175 EXPECT_CALL(*mock_metrics_lib_, 176 SendEnumToUMA(metrics::kMetricAttemptResult, 177 static_cast<int>( 178 metrics::AttemptResult::kAbnormalTermination), 179 _)) 180 .Times(1); 181 182 reporter_.ReportAbnormallyTerminatedUpdateAttemptMetrics(); 183 } 184 185 TEST_F(MetricsReporterOmahaTest, ReportUpdateAttemptMetrics) { 186 FakeSystemState fake_system_state; 187 FakeClock fake_clock; 188 FakePrefs fake_prefs; 189 190 fake_system_state.set_clock(&fake_clock); 191 fake_system_state.set_prefs(&fake_prefs); 192 fake_clock.SetWallclockTime(base::Time::FromInternalValue(1000000)); 193 fake_clock.SetMonotonicTime(base::Time::FromInternalValue(1000000)); 194 195 int attempt_number = 1; 196 PayloadType payload_type = kPayloadTypeFull; 197 TimeDelta duration = TimeDelta::FromMinutes(1000); 198 TimeDelta duration_uptime = TimeDelta::FromMinutes(1000); 199 200 int64_t payload_size = 100 * kNumBytesInOneMiB; 201 202 metrics::AttemptResult attempt_result = 203 metrics::AttemptResult::kInternalError; 204 ErrorCode internal_error_code = ErrorCode::kDownloadInvalidMetadataSignature; 205 206 EXPECT_CALL(*mock_metrics_lib_, 207 SendToUMA(metrics::kMetricAttemptNumber, attempt_number, _, _, _)) 208 .Times(2); 209 EXPECT_CALL(*mock_metrics_lib_, 210 SendEnumToUMA(metrics::kMetricAttemptPayloadType, 211 static_cast<int>(payload_type), 212 _)) 213 .Times(2); 214 EXPECT_CALL(*mock_metrics_lib_, 215 SendToUMA(metrics::kMetricAttemptDurationMinutes, 216 duration.InMinutes(), 217 _, 218 _, 219 _)) 220 .Times(2); 221 EXPECT_CALL(*mock_metrics_lib_, 222 SendToUMA(metrics::kMetricAttemptDurationUptimeMinutes, 223 duration_uptime.InMinutes(), 224 _, 225 _, 226 _)) 227 .Times(2); 228 229 // Check the report of attempt result. 230 EXPECT_CALL( 231 *mock_metrics_lib_, 232 SendEnumToUMA( 233 metrics::kMetricAttemptResult, static_cast<int>(attempt_result), _)) 234 .Times(2); 235 EXPECT_CALL(*mock_metrics_lib_, 236 SendEnumToUMA(metrics::kMetricAttemptInternalErrorCode, 237 static_cast<int>(internal_error_code), 238 _)) 239 .Times(2); 240 EXPECT_CALL(*mock_metrics_lib_, 241 SendToUMA(metrics::kMetricAttemptPayloadSizeMiB, 100, _, _, _)) 242 .Times(2); 243 244 // Check the duration between two reports. 245 EXPECT_CALL( 246 *mock_metrics_lib_, 247 SendToUMA(metrics::kMetricAttemptTimeSinceLastAttemptMinutes, 1, _, _, _)) 248 .Times(1); 249 EXPECT_CALL( 250 *mock_metrics_lib_, 251 SendToUMA( 252 metrics::kMetricAttemptTimeSinceLastAttemptUptimeMinutes, 1, _, _, _)) 253 .Times(1); 254 255 reporter_.ReportUpdateAttemptMetrics(&fake_system_state, 256 attempt_number, 257 payload_type, 258 duration, 259 duration_uptime, 260 payload_size, 261 attempt_result, 262 internal_error_code); 263 264 // Advance the clock by 1 minute and report the same metrics again. 265 fake_clock.SetWallclockTime(base::Time::FromInternalValue(61000000)); 266 fake_clock.SetMonotonicTime(base::Time::FromInternalValue(61000000)); 267 reporter_.ReportUpdateAttemptMetrics(&fake_system_state, 268 attempt_number, 269 payload_type, 270 duration, 271 duration_uptime, 272 payload_size, 273 attempt_result, 274 internal_error_code); 275 } 276 277 TEST_F(MetricsReporterOmahaTest, ReportUpdateAttemptDownloadMetrics) { 278 int64_t payload_bytes_downloaded = 200 * kNumBytesInOneMiB; 279 int64_t payload_download_speed_bps = 100 * 1000; 280 DownloadSource download_source = kDownloadSourceHttpServer; 281 metrics::DownloadErrorCode payload_download_error_code = 282 metrics::DownloadErrorCode::kDownloadError; 283 metrics::ConnectionType connection_type = metrics::ConnectionType::kCellular; 284 285 EXPECT_CALL( 286 *mock_metrics_lib_, 287 SendToUMA(metrics::kMetricAttemptPayloadBytesDownloadedMiB, 200, _, _, _)) 288 .Times(1); 289 EXPECT_CALL( 290 *mock_metrics_lib_, 291 SendToUMA(metrics::kMetricAttemptPayloadDownloadSpeedKBps, 100, _, _, _)) 292 .Times(1); 293 EXPECT_CALL(*mock_metrics_lib_, 294 SendEnumToUMA(metrics::kMetricAttemptDownloadSource, 295 static_cast<int>(download_source), 296 _)) 297 .Times(1); 298 EXPECT_CALL(*mock_metrics_lib_, 299 SendSparseToUMA(metrics::kMetricAttemptDownloadErrorCode, 300 static_cast<int>(payload_download_error_code))) 301 .Times(1); 302 EXPECT_CALL(*mock_metrics_lib_, 303 SendEnumToUMA(metrics::kMetricAttemptConnectionType, 304 static_cast<int>(connection_type), 305 _)) 306 .Times(1); 307 308 reporter_.ReportUpdateAttemptDownloadMetrics(payload_bytes_downloaded, 309 payload_download_speed_bps, 310 download_source, 311 payload_download_error_code, 312 connection_type); 313 } 314 315 TEST_F(MetricsReporterOmahaTest, ReportSuccessfulUpdateMetrics) { 316 int attempt_count = 3; 317 int updates_abandoned_count = 2; 318 PayloadType payload_type = kPayloadTypeDelta; 319 int64_t payload_size = 200 * kNumBytesInOneMiB; 320 int64_t num_bytes_downloaded[kNumDownloadSources] = {}; 321 // 200MiB payload downloaded from HttpsServer. 322 num_bytes_downloaded[0] = 200 * kNumBytesInOneMiB; 323 int download_overhead_percentage = 20; 324 TimeDelta total_duration = TimeDelta::FromMinutes(30); 325 TimeDelta total_duration_uptime = TimeDelta::FromMinutes(20); 326 int reboot_count = 2; 327 int url_switch_count = 2; 328 329 EXPECT_CALL( 330 *mock_metrics_lib_, 331 SendToUMA(metrics::kMetricSuccessfulUpdatePayloadSizeMiB, 200, _, _, _)) 332 .Times(1); 333 334 // Check the report to both BytesDownloadedMiBHttpsServer and 335 // BytesDownloadedMiB 336 std::string DownloadedMiBMetric = 337 metrics::kMetricSuccessfulUpdateBytesDownloadedMiB; 338 DownloadedMiBMetric += "HttpsServer"; 339 EXPECT_CALL(*mock_metrics_lib_, SendToUMA(DownloadedMiBMetric, 200, _, _, _)) 340 .Times(1); 341 EXPECT_CALL( 342 *mock_metrics_lib_, 343 SendToUMA( 344 metrics::kMetricSuccessfulUpdateBytesDownloadedMiB, 200, _, _, _)) 345 .Times(1); 346 347 EXPECT_CALL( 348 *mock_metrics_lib_, 349 SendToUMA( 350 metrics::kMetricSuccessfulUpdateDownloadSourcesUsed, 1, _, _, _)) 351 .Times(1); 352 EXPECT_CALL( 353 *mock_metrics_lib_, 354 SendToUMA(metrics::kMetricSuccessfulUpdateDownloadOverheadPercentage, 355 20, 356 _, 357 _, 358 _)); 359 360 EXPECT_CALL(*mock_metrics_lib_, 361 SendToUMA(metrics::kMetricSuccessfulUpdateUrlSwitchCount, 362 url_switch_count, 363 _, 364 _, 365 _)) 366 .Times(1); 367 EXPECT_CALL( 368 *mock_metrics_lib_, 369 SendToUMA( 370 metrics::kMetricSuccessfulUpdateTotalDurationMinutes, 30, _, _, _)) 371 .Times(1); 372 EXPECT_CALL( 373 *mock_metrics_lib_, 374 SendToUMA(metrics::kMetricSuccessfulUpdateTotalDurationUptimeMinutes, 375 20, 376 _, 377 _, 378 _)) 379 .Times(1); 380 EXPECT_CALL( 381 *mock_metrics_lib_, 382 SendToUMA( 383 metrics::kMetricSuccessfulUpdateRebootCount, reboot_count, _, _, _)) 384 .Times(1); 385 EXPECT_CALL(*mock_metrics_lib_, 386 SendEnumToUMA( 387 metrics::kMetricSuccessfulUpdatePayloadType, payload_type, _)) 388 .Times(1); 389 EXPECT_CALL( 390 *mock_metrics_lib_, 391 SendToUMA( 392 metrics::kMetricSuccessfulUpdateAttemptCount, attempt_count, _, _, _)) 393 .Times(1); 394 EXPECT_CALL(*mock_metrics_lib_, 395 SendToUMA(metrics::kMetricSuccessfulUpdateUpdatesAbandonedCount, 396 updates_abandoned_count, 397 _, 398 _, 399 _)) 400 .Times(1); 401 402 reporter_.ReportSuccessfulUpdateMetrics(attempt_count, 403 updates_abandoned_count, 404 payload_type, 405 payload_size, 406 num_bytes_downloaded, 407 download_overhead_percentage, 408 total_duration, 409 total_duration_uptime, 410 reboot_count, 411 url_switch_count); 412 } 413 414 TEST_F(MetricsReporterOmahaTest, ReportRollbackMetrics) { 415 metrics::RollbackResult result = metrics::RollbackResult::kSuccess; 416 EXPECT_CALL(*mock_metrics_lib_, 417 SendEnumToUMA( 418 metrics::kMetricRollbackResult, static_cast<int>(result), _)) 419 .Times(1); 420 421 reporter_.ReportRollbackMetrics(result); 422 } 423 424 TEST_F(MetricsReporterOmahaTest, ReportEnterpriseRollbackMetrics) { 425 EXPECT_CALL(*mock_metrics_lib_, 426 SendSparseToUMA(metrics::kMetricEnterpriseRollbackSuccess, 10575)) 427 .Times(1); 428 EXPECT_CALL(*mock_metrics_lib_, 429 SendSparseToUMA(metrics::kMetricEnterpriseRollbackFailure, 10323)) 430 .Times(1); 431 432 reporter_.ReportEnterpriseRollbackMetrics(/*success=*/true, "10575.39.2"); 433 reporter_.ReportEnterpriseRollbackMetrics(/*success=*/false, "10323.67.7"); 434 } 435 436 TEST_F(MetricsReporterOmahaTest, ReportCertificateCheckMetrics) { 437 ServerToCheck server_to_check = ServerToCheck::kUpdate; 438 CertificateCheckResult result = CertificateCheckResult::kValid; 439 EXPECT_CALL(*mock_metrics_lib_, 440 SendEnumToUMA(metrics::kMetricCertificateCheckUpdateCheck, 441 static_cast<int>(result), 442 _)) 443 .Times(1); 444 445 reporter_.ReportCertificateCheckMetrics(server_to_check, result); 446 } 447 448 TEST_F(MetricsReporterOmahaTest, ReportFailedUpdateCount) { 449 int target_attempt = 3; 450 EXPECT_CALL( 451 *mock_metrics_lib_, 452 SendToUMA(metrics::kMetricFailedUpdateCount, target_attempt, _, _, _)) 453 .Times(1); 454 455 reporter_.ReportFailedUpdateCount(target_attempt); 456 } 457 458 TEST_F(MetricsReporterOmahaTest, ReportTimeToReboot) { 459 int time_to_reboot_minutes = 1000; 460 EXPECT_CALL( 461 *mock_metrics_lib_, 462 SendToUMA( 463 metrics::kMetricTimeToRebootMinutes, time_to_reboot_minutes, _, _, _)) 464 .Times(1); 465 466 reporter_.ReportTimeToReboot(time_to_reboot_minutes); 467 } 468 469 TEST_F(MetricsReporterOmahaTest, ReportInstallDateProvisioningSource) { 470 int source = 2; 471 int max = 5; 472 EXPECT_CALL( 473 *mock_metrics_lib_, 474 SendEnumToUMA(metrics::kMetricInstallDateProvisioningSource, source, max)) 475 .Times(1); 476 477 reporter_.ReportInstallDateProvisioningSource(source, max); 478 } 479 480 TEST_F(MetricsReporterOmahaTest, ReportKeyVersionMetrics) { 481 int kernel_min_version = 0x00040002; 482 int kernel_max_rollforward_version = 0xfffffffe; 483 bool kernel_max_rollforward_success = true; 484 EXPECT_CALL( 485 *mock_metrics_lib_, 486 SendSparseToUMA(metrics::kMetricKernelMinVersion, kernel_min_version)) 487 .Times(1); 488 EXPECT_CALL(*mock_metrics_lib_, 489 SendSparseToUMA(metrics::kMetricKernelMaxRollforwardVersion, 490 kernel_max_rollforward_version)) 491 .Times(1); 492 EXPECT_CALL(*mock_metrics_lib_, 493 SendBoolToUMA(metrics::kMetricKernelMaxRollforwardSetSuccess, 494 kernel_max_rollforward_success)) 495 .Times(1); 496 497 reporter_.ReportKeyVersionMetrics(kernel_min_version, 498 kernel_max_rollforward_version, 499 kernel_max_rollforward_success); 500 } 501 502 TEST_F(MetricsReporterOmahaTest, ReportEnterpriseUpdateSeenToDownloadDays) { 503 constexpr int kDaysToUpdate = 10; 504 constexpr int kMinBucket = 1; 505 constexpr int kMaxBucket = 6 * 30; // approximately 6 months 506 constexpr int kNumBuckets = 50; 507 508 EXPECT_CALL(*mock_metrics_lib_, 509 SendToUMA(metrics::kMetricSuccessfulUpdateDurationFromSeenDays, 510 kDaysToUpdate, 511 kMinBucket, 512 kMaxBucket, 513 kNumBuckets)) 514 .Times(1); 515 516 reporter_.ReportEnterpriseUpdateSeenToDownloadDays( 517 false /* has_time_restriction_policy */, kDaysToUpdate); 518 } 519 520 TEST_F(MetricsReporterOmahaTest, 521 ReportEnterpriseTimeRestrictedUpdateSeenToDownloadTime) { 522 const int kDaysToUpdate = 15; 523 constexpr int kMinBucket = 1; 524 constexpr int kMaxBucket = 6 * 30; // approximately 6 months 525 constexpr int kNumBuckets = 50; 526 527 EXPECT_CALL( 528 *mock_metrics_lib_, 529 SendToUMA( 530 metrics::kMetricSuccessfulUpdateDurationFromSeenTimeRestrictedDays, 531 kDaysToUpdate, 532 kMinBucket, 533 kMaxBucket, 534 kNumBuckets)) 535 .Times(1); 536 537 reporter_.ReportEnterpriseUpdateSeenToDownloadDays( 538 true /* has_time_restriction_policy */, kDaysToUpdate); 539 } 540 541 } // namespace chromeos_update_engine 542