//
|
// 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::_;
|
using testing::AnyNumber;
|
using testing::Return;
|
|
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);
|
|
// Not pinned nor rollback
|
EXPECT_CALL(*mock_metrics_lib_,
|
SendSparseToUMA(metrics::kMetricCheckTargetVersion, _))
|
.Times(0);
|
EXPECT_CALL(*mock_metrics_lib_,
|
SendSparseToUMA(metrics::kMetricCheckRollbackTargetVersion, _))
|
.Times(0);
|
|
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));
|
// Allow rollback
|
reporter_.ReportUpdateCheckMetrics(
|
&fake_system_state, result, reaction, error_code);
|
}
|
|
TEST_F(MetricsReporterOmahaTest, ReportUpdateCheckMetricsPinned) {
|
FakeSystemState fake_system_state;
|
|
OmahaRequestParams params(&fake_system_state);
|
params.set_target_version_prefix("10575.");
|
params.set_rollback_allowed(false);
|
fake_system_state.set_request_params(¶ms);
|
|
metrics::CheckResult result = metrics::CheckResult::kUpdateAvailable;
|
metrics::CheckReaction reaction = metrics::CheckReaction::kIgnored;
|
metrics::DownloadErrorCode error_code =
|
metrics::DownloadErrorCode::kHttpStatus200;
|
|
EXPECT_CALL(*mock_metrics_lib_,
|
SendSparseToUMA(metrics::kMetricCheckDownloadErrorCode, _));
|
// Target version set, but not a rollback.
|
EXPECT_CALL(*mock_metrics_lib_,
|
SendSparseToUMA(metrics::kMetricCheckTargetVersion, 10575))
|
.Times(1);
|
EXPECT_CALL(*mock_metrics_lib_,
|
SendSparseToUMA(metrics::kMetricCheckRollbackTargetVersion, _))
|
.Times(0);
|
|
reporter_.ReportUpdateCheckMetrics(
|
&fake_system_state, result, reaction, error_code);
|
}
|
|
TEST_F(MetricsReporterOmahaTest, ReportUpdateCheckMetricsRollback) {
|
FakeSystemState fake_system_state;
|
|
OmahaRequestParams params(&fake_system_state);
|
params.set_target_version_prefix("10575.");
|
params.set_rollback_allowed(true);
|
fake_system_state.set_request_params(¶ms);
|
|
metrics::CheckResult result = metrics::CheckResult::kUpdateAvailable;
|
metrics::CheckReaction reaction = metrics::CheckReaction::kIgnored;
|
metrics::DownloadErrorCode error_code =
|
metrics::DownloadErrorCode::kHttpStatus200;
|
|
EXPECT_CALL(*mock_metrics_lib_,
|
SendSparseToUMA(metrics::kMetricCheckDownloadErrorCode, _));
|
// Rollback.
|
EXPECT_CALL(*mock_metrics_lib_,
|
SendSparseToUMA(metrics::kMetricCheckTargetVersion, 10575))
|
.Times(1);
|
EXPECT_CALL(
|
*mock_metrics_lib_,
|
SendSparseToUMA(metrics::kMetricCheckRollbackTargetVersion, 10575))
|
.Times(1);
|
|
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);
|
TimeDelta total_duration_uptime = TimeDelta::FromMinutes(20);
|
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::kMetricSuccessfulUpdateTotalDurationUptimeMinutes,
|
20,
|
_,
|
_,
|
_))
|
.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,
|
total_duration_uptime,
|
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, ReportEnterpriseRollbackMetrics) {
|
EXPECT_CALL(*mock_metrics_lib_,
|
SendSparseToUMA(metrics::kMetricEnterpriseRollbackSuccess, 10575))
|
.Times(1);
|
EXPECT_CALL(*mock_metrics_lib_,
|
SendSparseToUMA(metrics::kMetricEnterpriseRollbackFailure, 10323))
|
.Times(1);
|
|
reporter_.ReportEnterpriseRollbackMetrics(/*success=*/true, "10575.39.2");
|
reporter_.ReportEnterpriseRollbackMetrics(/*success=*/false, "10323.67.7");
|
}
|
|
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);
|
}
|
|
TEST_F(MetricsReporterOmahaTest, ReportKeyVersionMetrics) {
|
int kernel_min_version = 0x00040002;
|
int kernel_max_rollforward_version = 0xfffffffe;
|
bool kernel_max_rollforward_success = true;
|
EXPECT_CALL(
|
*mock_metrics_lib_,
|
SendSparseToUMA(metrics::kMetricKernelMinVersion, kernel_min_version))
|
.Times(1);
|
EXPECT_CALL(*mock_metrics_lib_,
|
SendSparseToUMA(metrics::kMetricKernelMaxRollforwardVersion,
|
kernel_max_rollforward_version))
|
.Times(1);
|
EXPECT_CALL(*mock_metrics_lib_,
|
SendBoolToUMA(metrics::kMetricKernelMaxRollforwardSetSuccess,
|
kernel_max_rollforward_success))
|
.Times(1);
|
|
reporter_.ReportKeyVersionMetrics(kernel_min_version,
|
kernel_max_rollforward_version,
|
kernel_max_rollforward_success);
|
}
|
|
TEST_F(MetricsReporterOmahaTest, ReportEnterpriseUpdateSeenToDownloadDays) {
|
constexpr int kDaysToUpdate = 10;
|
constexpr int kMinBucket = 1;
|
constexpr int kMaxBucket = 6 * 30; // approximately 6 months
|
constexpr int kNumBuckets = 50;
|
|
EXPECT_CALL(*mock_metrics_lib_,
|
SendToUMA(metrics::kMetricSuccessfulUpdateDurationFromSeenDays,
|
kDaysToUpdate,
|
kMinBucket,
|
kMaxBucket,
|
kNumBuckets))
|
.Times(1);
|
|
reporter_.ReportEnterpriseUpdateSeenToDownloadDays(
|
false /* has_time_restriction_policy */, kDaysToUpdate);
|
}
|
|
TEST_F(MetricsReporterOmahaTest,
|
ReportEnterpriseTimeRestrictedUpdateSeenToDownloadTime) {
|
const int kDaysToUpdate = 15;
|
constexpr int kMinBucket = 1;
|
constexpr int kMaxBucket = 6 * 30; // approximately 6 months
|
constexpr int kNumBuckets = 50;
|
|
EXPECT_CALL(
|
*mock_metrics_lib_,
|
SendToUMA(
|
metrics::kMetricSuccessfulUpdateDurationFromSeenTimeRestrictedDays,
|
kDaysToUpdate,
|
kMinBucket,
|
kMaxBucket,
|
kNumBuckets))
|
.Times(1);
|
|
reporter_.ReportEnterpriseUpdateSeenToDownloadDays(
|
true /* has_time_restriction_policy */, kDaysToUpdate);
|
}
|
|
} // namespace chromeos_update_engine
|