普通文本  |  542行  |  19.16 KB

//
// 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(&params);

  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(&params);

  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