| // |
| // Copyright (C) 2017 The Android Open Source Project |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| // |
| |
| #include "update_engine/metrics_reporter_omaha.h" |
| |
| #include <memory> |
| #include <string> |
| |
| #include <base/time/time.h> |
| #include <gmock/gmock.h> |
| #include <gtest/gtest.h> |
| #include <metrics/metrics_library_mock.h> |
| |
| #include "update_engine/common/fake_clock.h" |
| #include "update_engine/common/fake_prefs.h" |
| #include "update_engine/fake_system_state.h" |
| |
| using base::TimeDelta; |
| using testing::AnyNumber; |
| using testing::_; |
| |
| namespace chromeos_update_engine { |
| class MetricsReporterOmahaTest : public ::testing::Test { |
| protected: |
| MetricsReporterOmahaTest() = default; |
| |
| // Reset the metrics_lib_ to a mock library. |
| void SetUp() override { |
| mock_metrics_lib_ = new testing::NiceMock<MetricsLibraryMock>(); |
| reporter_.metrics_lib_.reset(mock_metrics_lib_); |
| } |
| |
| testing::NiceMock<MetricsLibraryMock>* mock_metrics_lib_; |
| MetricsReporterOmaha reporter_; |
| }; |
| |
| TEST_F(MetricsReporterOmahaTest, ReportDailyMetrics) { |
| TimeDelta age = TimeDelta::FromDays(10); |
| EXPECT_CALL(*mock_metrics_lib_, |
| SendToUMA(metrics::kMetricDailyOSAgeDays, _, _, _, _)) |
| .Times(1); |
| |
| reporter_.ReportDailyMetrics(age); |
| } |
| |
| TEST_F(MetricsReporterOmahaTest, ReportUpdateCheckMetrics) { |
| FakeSystemState fake_system_state; |
| FakeClock fake_clock; |
| FakePrefs fake_prefs; |
| |
| // We need to execute the report twice to test the time since last report. |
| fake_system_state.set_clock(&fake_clock); |
| fake_system_state.set_prefs(&fake_prefs); |
| fake_clock.SetWallclockTime(base::Time::FromInternalValue(1000000)); |
| fake_clock.SetMonotonicTime(base::Time::FromInternalValue(1000000)); |
| |
| metrics::CheckResult result = metrics::CheckResult::kUpdateAvailable; |
| metrics::CheckReaction reaction = metrics::CheckReaction::kIgnored; |
| metrics::DownloadErrorCode error_code = |
| metrics::DownloadErrorCode::kHttpStatus200; |
| |
| EXPECT_CALL( |
| *mock_metrics_lib_, |
| SendEnumToUMA(metrics::kMetricCheckResult, static_cast<int>(result), _)) |
| .Times(2); |
| EXPECT_CALL(*mock_metrics_lib_, |
| SendEnumToUMA( |
| metrics::kMetricCheckReaction, static_cast<int>(reaction), _)) |
| .Times(2); |
| EXPECT_CALL(*mock_metrics_lib_, |
| SendSparseToUMA(metrics::kMetricCheckDownloadErrorCode, |
| static_cast<int>(error_code))) |
| .Times(2); |
| |
| EXPECT_CALL( |
| *mock_metrics_lib_, |
| SendToUMA(metrics::kMetricCheckTimeSinceLastCheckMinutes, 1, _, _, _)) |
| .Times(1); |
| EXPECT_CALL( |
| *mock_metrics_lib_, |
| SendToUMA( |
| metrics::kMetricCheckTimeSinceLastCheckUptimeMinutes, 1, _, _, _)) |
| .Times(1); |
| |
| reporter_.ReportUpdateCheckMetrics( |
| &fake_system_state, result, reaction, error_code); |
| |
| // Advance the clock by 1 minute and report the same metrics again. |
| fake_clock.SetWallclockTime(base::Time::FromInternalValue(61000000)); |
| fake_clock.SetMonotonicTime(base::Time::FromInternalValue(61000000)); |
| reporter_.ReportUpdateCheckMetrics( |
| &fake_system_state, result, reaction, error_code); |
| } |
| |
| TEST_F(MetricsReporterOmahaTest, |
| ReportAbnormallyTerminatedUpdateAttemptMetrics) { |
| EXPECT_CALL(*mock_metrics_lib_, |
| SendEnumToUMA(metrics::kMetricAttemptResult, |
| static_cast<int>( |
| metrics::AttemptResult::kAbnormalTermination), |
| _)) |
| .Times(1); |
| |
| reporter_.ReportAbnormallyTerminatedUpdateAttemptMetrics(); |
| } |
| |
| TEST_F(MetricsReporterOmahaTest, ReportUpdateAttemptMetrics) { |
| FakeSystemState fake_system_state; |
| FakeClock fake_clock; |
| FakePrefs fake_prefs; |
| |
| fake_system_state.set_clock(&fake_clock); |
| fake_system_state.set_prefs(&fake_prefs); |
| fake_clock.SetWallclockTime(base::Time::FromInternalValue(1000000)); |
| fake_clock.SetMonotonicTime(base::Time::FromInternalValue(1000000)); |
| |
| int attempt_number = 1; |
| PayloadType payload_type = kPayloadTypeFull; |
| TimeDelta duration = TimeDelta::FromMinutes(1000); |
| TimeDelta duration_uptime = TimeDelta::FromMinutes(1000); |
| |
| int64_t payload_size = 100 * kNumBytesInOneMiB; |
| |
| metrics::AttemptResult attempt_result = |
| metrics::AttemptResult::kInternalError; |
| ErrorCode internal_error_code = ErrorCode::kDownloadInvalidMetadataSignature; |
| |
| EXPECT_CALL(*mock_metrics_lib_, |
| SendToUMA(metrics::kMetricAttemptNumber, attempt_number, _, _, _)) |
| .Times(2); |
| EXPECT_CALL(*mock_metrics_lib_, |
| SendEnumToUMA(metrics::kMetricAttemptPayloadType, |
| static_cast<int>(payload_type), |
| _)) |
| .Times(2); |
| EXPECT_CALL(*mock_metrics_lib_, |
| SendToUMA(metrics::kMetricAttemptDurationMinutes, |
| duration.InMinutes(), |
| _, |
| _, |
| _)) |
| .Times(2); |
| EXPECT_CALL(*mock_metrics_lib_, |
| SendToUMA(metrics::kMetricAttemptDurationUptimeMinutes, |
| duration_uptime.InMinutes(), |
| _, |
| _, |
| _)) |
| .Times(2); |
| |
| |
| // Check the report of attempt result. |
| EXPECT_CALL( |
| *mock_metrics_lib_, |
| SendEnumToUMA( |
| metrics::kMetricAttemptResult, static_cast<int>(attempt_result), _)) |
| .Times(2); |
| EXPECT_CALL(*mock_metrics_lib_, |
| SendEnumToUMA(metrics::kMetricAttemptInternalErrorCode, |
| static_cast<int>(internal_error_code), |
| _)) |
| .Times(2); |
| EXPECT_CALL(*mock_metrics_lib_, |
| SendToUMA(metrics::kMetricAttemptPayloadSizeMiB, 100, _, _, _)) |
| .Times(2); |
| |
| // Check the duration between two reports. |
| EXPECT_CALL( |
| *mock_metrics_lib_, |
| SendToUMA(metrics::kMetricAttemptTimeSinceLastAttemptMinutes, 1, _, _, _)) |
| .Times(1); |
| EXPECT_CALL( |
| *mock_metrics_lib_, |
| SendToUMA( |
| metrics::kMetricAttemptTimeSinceLastAttemptUptimeMinutes, 1, _, _, _)) |
| .Times(1); |
| |
| reporter_.ReportUpdateAttemptMetrics(&fake_system_state, |
| attempt_number, |
| payload_type, |
| duration, |
| duration_uptime, |
| payload_size, |
| attempt_result, |
| internal_error_code); |
| |
| // Advance the clock by 1 minute and report the same metrics again. |
| fake_clock.SetWallclockTime(base::Time::FromInternalValue(61000000)); |
| fake_clock.SetMonotonicTime(base::Time::FromInternalValue(61000000)); |
| reporter_.ReportUpdateAttemptMetrics(&fake_system_state, |
| attempt_number, |
| payload_type, |
| duration, |
| duration_uptime, |
| payload_size, |
| attempt_result, |
| internal_error_code); |
| } |
| |
| TEST_F(MetricsReporterOmahaTest, ReportUpdateAttemptDownloadMetrics) { |
| int64_t payload_bytes_downloaded = 200 * kNumBytesInOneMiB; |
| int64_t payload_download_speed_bps = 100 * 1000; |
| DownloadSource download_source = kDownloadSourceHttpServer; |
| metrics::DownloadErrorCode payload_download_error_code = |
| metrics::DownloadErrorCode::kDownloadError; |
| metrics::ConnectionType connection_type = metrics::ConnectionType::kCellular; |
| |
| EXPECT_CALL( |
| *mock_metrics_lib_, |
| SendToUMA(metrics::kMetricAttemptPayloadBytesDownloadedMiB, 200, _, _, _)) |
| .Times(1); |
| EXPECT_CALL( |
| *mock_metrics_lib_, |
| SendToUMA(metrics::kMetricAttemptPayloadDownloadSpeedKBps, 100, _, _, _)) |
| .Times(1); |
| EXPECT_CALL(*mock_metrics_lib_, |
| SendEnumToUMA(metrics::kMetricAttemptDownloadSource, |
| static_cast<int>(download_source), |
| _)) |
| .Times(1); |
| EXPECT_CALL(*mock_metrics_lib_, |
| SendSparseToUMA(metrics::kMetricAttemptDownloadErrorCode, |
| static_cast<int>(payload_download_error_code))) |
| .Times(1); |
| EXPECT_CALL(*mock_metrics_lib_, |
| SendEnumToUMA(metrics::kMetricAttemptConnectionType, |
| static_cast<int>(connection_type), |
| _)) |
| .Times(1); |
| |
| reporter_.ReportUpdateAttemptDownloadMetrics(payload_bytes_downloaded, |
| payload_download_speed_bps, |
| download_source, |
| payload_download_error_code, |
| connection_type); |
| } |
| |
| TEST_F(MetricsReporterOmahaTest, ReportSuccessfulUpdateMetrics) { |
| int attempt_count = 3; |
| int updates_abandoned_count = 2; |
| PayloadType payload_type = kPayloadTypeDelta; |
| int64_t payload_size = 200 * kNumBytesInOneMiB; |
| int64_t num_bytes_downloaded[kNumDownloadSources] = {}; |
| // 200MiB payload downloaded from HttpsServer. |
| num_bytes_downloaded[0] = 200 * kNumBytesInOneMiB; |
| int download_overhead_percentage = 20; |
| TimeDelta total_duration = TimeDelta::FromMinutes(30); |
| int reboot_count = 2; |
| int url_switch_count = 2; |
| |
| EXPECT_CALL( |
| *mock_metrics_lib_, |
| SendToUMA(metrics::kMetricSuccessfulUpdatePayloadSizeMiB, 200, _, _, _)) |
| .Times(1); |
| |
| // Check the report to both BytesDownloadedMiBHttpsServer and |
| // BytesDownloadedMiB |
| std::string DownloadedMiBMetric = |
| metrics::kMetricSuccessfulUpdateBytesDownloadedMiB; |
| DownloadedMiBMetric += "HttpsServer"; |
| EXPECT_CALL(*mock_metrics_lib_, SendToUMA(DownloadedMiBMetric, 200, _, _, _)) |
| .Times(1); |
| EXPECT_CALL( |
| *mock_metrics_lib_, |
| SendToUMA( |
| metrics::kMetricSuccessfulUpdateBytesDownloadedMiB, 200, _, _, _)) |
| .Times(1); |
| |
| EXPECT_CALL( |
| *mock_metrics_lib_, |
| SendToUMA( |
| metrics::kMetricSuccessfulUpdateDownloadSourcesUsed, 1, _, _, _)) |
| .Times(1); |
| EXPECT_CALL( |
| *mock_metrics_lib_, |
| SendToUMA(metrics::kMetricSuccessfulUpdateDownloadOverheadPercentage, |
| 20, |
| _, |
| _, |
| _)); |
| |
| EXPECT_CALL(*mock_metrics_lib_, |
| SendToUMA(metrics::kMetricSuccessfulUpdateUrlSwitchCount, |
| url_switch_count, |
| _, |
| _, |
| _)) |
| .Times(1); |
| EXPECT_CALL( |
| *mock_metrics_lib_, |
| SendToUMA( |
| metrics::kMetricSuccessfulUpdateTotalDurationMinutes, 30, _, _, _)) |
| .Times(1); |
| EXPECT_CALL( |
| *mock_metrics_lib_, |
| SendToUMA( |
| metrics::kMetricSuccessfulUpdateRebootCount, reboot_count, _, _, _)) |
| .Times(1); |
| EXPECT_CALL(*mock_metrics_lib_, |
| SendEnumToUMA( |
| metrics::kMetricSuccessfulUpdatePayloadType, payload_type, _)) |
| .Times(1); |
| EXPECT_CALL( |
| *mock_metrics_lib_, |
| SendToUMA( |
| metrics::kMetricSuccessfulUpdateAttemptCount, attempt_count, _, _, _)) |
| .Times(1); |
| EXPECT_CALL(*mock_metrics_lib_, |
| SendToUMA(metrics::kMetricSuccessfulUpdateUpdatesAbandonedCount, |
| updates_abandoned_count, |
| _, |
| _, |
| _)) |
| .Times(1); |
| |
| reporter_.ReportSuccessfulUpdateMetrics(attempt_count, |
| updates_abandoned_count, |
| payload_type, |
| payload_size, |
| num_bytes_downloaded, |
| download_overhead_percentage, |
| total_duration, |
| reboot_count, |
| url_switch_count); |
| } |
| |
| TEST_F(MetricsReporterOmahaTest, ReportRollbackMetrics) { |
| metrics::RollbackResult result = metrics::RollbackResult::kSuccess; |
| EXPECT_CALL(*mock_metrics_lib_, |
| SendEnumToUMA( |
| metrics::kMetricRollbackResult, static_cast<int>(result), _)) |
| .Times(1); |
| |
| reporter_.ReportRollbackMetrics(result); |
| } |
| |
| TEST_F(MetricsReporterOmahaTest, ReportCertificateCheckMetrics) { |
| ServerToCheck server_to_check = ServerToCheck::kUpdate; |
| CertificateCheckResult result = CertificateCheckResult::kValid; |
| EXPECT_CALL(*mock_metrics_lib_, |
| SendEnumToUMA(metrics::kMetricCertificateCheckUpdateCheck, |
| static_cast<int>(result), |
| _)) |
| .Times(1); |
| |
| reporter_.ReportCertificateCheckMetrics(server_to_check, result); |
| } |
| |
| TEST_F(MetricsReporterOmahaTest, ReportFailedUpdateCount) { |
| int target_attempt = 3; |
| EXPECT_CALL( |
| *mock_metrics_lib_, |
| SendToUMA(metrics::kMetricFailedUpdateCount, target_attempt, _, _, _)) |
| .Times(1); |
| |
| reporter_.ReportFailedUpdateCount(target_attempt); |
| } |
| |
| TEST_F(MetricsReporterOmahaTest, ReportTimeToReboot) { |
| int time_to_reboot_minutes = 1000; |
| EXPECT_CALL( |
| *mock_metrics_lib_, |
| SendToUMA( |
| metrics::kMetricTimeToRebootMinutes, time_to_reboot_minutes, _, _, _)) |
| .Times(1); |
| |
| reporter_.ReportTimeToReboot(time_to_reboot_minutes); |
| } |
| |
| TEST_F(MetricsReporterOmahaTest, ReportInstallDateProvisioningSource) { |
| int source = 2; |
| int max = 5; |
| EXPECT_CALL( |
| *mock_metrics_lib_, |
| SendEnumToUMA(metrics::kMetricInstallDateProvisioningSource, source, max)) |
| .Times(1); |
| |
| reporter_.ReportInstallDateProvisioningSource(source, max); |
| } |
| |
| } // namespace chromeos_update_engine |