//
// 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/update_attempter_android.h"
#include <memory>
#include <string>
#include <android-base/properties.h>
#include <base/time/time.h>
#include <gtest/gtest.h>
#include "update_engine/common/fake_boot_control.h"
#include "update_engine/common/fake_clock.h"
#include "update_engine/common/fake_hardware.h"
#include "update_engine/common/fake_prefs.h"
#include "update_engine/common/mock_action_processor.h"
#include "update_engine/common/test_utils.h"
#include "update_engine/common/utils.h"
#include "update_engine/daemon_state_android.h"
#include "update_engine/mock_metrics_reporter.h"
using base::Time;
using base::TimeDelta;
using testing::_;
using update_engine::UpdateStatus;
namespace chromeos_update_engine {
class UpdateAttempterAndroidTest : public ::testing::Test {
protected:
UpdateAttempterAndroidTest() = default;
void SetUp() override {
clock_ = new FakeClock();
metrics_reporter_ = new testing::NiceMock<MockMetricsReporter>();
update_attempter_android_.metrics_reporter_.reset(metrics_reporter_);
update_attempter_android_.clock_.reset(clock_);
update_attempter_android_.processor_.reset(
new testing::NiceMock<MockActionProcessor>());
}
void SetUpdateStatus(update_engine::UpdateStatus status) {
update_attempter_android_.status_ = status;
}
UpdateAttempterAndroid update_attempter_android_{
&daemon_state_, &prefs_, &boot_control_, &hardware_};
DaemonStateAndroid daemon_state_;
FakePrefs prefs_;
FakeBootControl boot_control_;
FakeHardware hardware_;
FakeClock* clock_;
testing::NiceMock<MockMetricsReporter>* metrics_reporter_;
};
TEST_F(UpdateAttempterAndroidTest, UpdatePrefsSameBuildVersionOnInit) {
std::string build_version =
android::base::GetProperty("ro.build.version.incremental", "");
prefs_.SetString(kPrefsPreviousVersion, build_version);
prefs_.SetString(kPrefsBootId, "oldboot");
prefs_.SetInt64(kPrefsNumReboots, 1);
EXPECT_CALL(*metrics_reporter_, ReportTimeToReboot(_)).Times(0);
update_attempter_android_.Init();
// Check that the boot_id and reboot_count are updated.
std::string boot_id;
utils::GetBootId(&boot_id);
EXPECT_TRUE(prefs_.Exists(kPrefsBootId));
std::string prefs_boot_id;
EXPECT_TRUE(prefs_.GetString(kPrefsBootId, &prefs_boot_id));
EXPECT_EQ(boot_id, prefs_boot_id);
EXPECT_TRUE(prefs_.Exists(kPrefsNumReboots));
int64_t reboot_count;
EXPECT_TRUE(prefs_.GetInt64(kPrefsNumReboots, &reboot_count));
EXPECT_EQ(2, reboot_count);
}
TEST_F(UpdateAttempterAndroidTest, UpdatePrefsBuildVersionChangeOnInit) {
prefs_.SetString(kPrefsPreviousVersion, "00001"); // Set the fake version
prefs_.SetInt64(kPrefsPayloadAttemptNumber, 1);
prefs_.SetInt64(kPrefsSystemUpdatedMarker, 23456);
EXPECT_CALL(*metrics_reporter_,
ReportAbnormallyTerminatedUpdateAttemptMetrics())
.Times(1);
Time now = Time::FromInternalValue(34456);
clock_->SetMonotonicTime(now);
TimeDelta duration = now - Time::FromInternalValue(23456);
EXPECT_CALL(*metrics_reporter_, ReportTimeToReboot(duration.InMinutes()))
.Times(1);
update_attempter_android_.Init();
// Check that we reset the metric prefs.
EXPECT_FALSE(prefs_.Exists(kPrefsNumReboots));
EXPECT_FALSE(prefs_.Exists(kPrefsPayloadAttemptNumber));
EXPECT_FALSE(prefs_.Exists(kPrefsUpdateTimestampStart));
EXPECT_FALSE(prefs_.Exists(kPrefsSystemUpdatedMarker));
}
TEST_F(UpdateAttempterAndroidTest, ReportMetricsOnUpdateTerminated) {
prefs_.SetInt64(kPrefsNumReboots, 3);
prefs_.SetInt64(kPrefsPayloadAttemptNumber, 2);
prefs_.SetString(kPrefsPreviousVersion, "56789");
prefs_.SetInt64(kPrefsUpdateTimestampStart, 12345);
Time boot_time = Time::FromInternalValue(22345);
Time up_time = Time::FromInternalValue(21345);
clock_->SetBootTime(boot_time);
clock_->SetMonotonicTime(up_time);
TimeDelta duration = boot_time - Time::FromInternalValue(12345);
TimeDelta duration_uptime = up_time - Time::FromInternalValue(12345);
EXPECT_CALL(
*metrics_reporter_,
ReportUpdateAttemptMetrics(_,
2,
_,
duration,
duration_uptime,
_,
metrics::AttemptResult::kUpdateSucceeded,
ErrorCode::kSuccess))
.Times(1);
EXPECT_CALL(*metrics_reporter_,
ReportSuccessfulUpdateMetrics(2, 0, _, _, _, _, duration, 3, _))
.Times(1);
SetUpdateStatus(UpdateStatus::UPDATE_AVAILABLE);
update_attempter_android_.ProcessingDone(nullptr, ErrorCode::kSuccess);
EXPECT_FALSE(prefs_.Exists(kPrefsNumReboots));
EXPECT_FALSE(prefs_.Exists(kPrefsPayloadAttemptNumber));
EXPECT_FALSE(prefs_.Exists(kPrefsUpdateTimestampStart));
EXPECT_TRUE(prefs_.Exists(kPrefsSystemUpdatedMarker));
}
TEST_F(UpdateAttempterAndroidTest, ReportMetricsForBytesDownloaded) {
// Check both prefs are updated correctly.
update_attempter_android_.BytesReceived(20, 50, 200);
EXPECT_EQ(
20,
metrics_utils::GetPersistedValue(kPrefsCurrentBytesDownloaded, &prefs_));
EXPECT_EQ(
20,
metrics_utils::GetPersistedValue(kPrefsTotalBytesDownloaded, &prefs_));
EXPECT_CALL(*metrics_reporter_,
ReportUpdateAttemptDownloadMetrics(50, _, _, _, _))
.Times(1);
EXPECT_CALL(*metrics_reporter_,
ReportUpdateAttemptDownloadMetrics(40, _, _, _, _))
.Times(1);
int64_t total_bytes[kNumDownloadSources] = {};
total_bytes[kDownloadSourceHttpsServer] = 90;
EXPECT_CALL(*metrics_reporter_,
ReportSuccessfulUpdateMetrics(
_,
_,
_,
_,
test_utils::DownloadSourceMatcher(total_bytes),
125,
_,
_,
_))
.Times(1);
// The first update fails after receving 50 bytes in total.
update_attempter_android_.BytesReceived(30, 50, 200);
update_attempter_android_.ProcessingDone(nullptr, ErrorCode::kError);
EXPECT_EQ(
0,
metrics_utils::GetPersistedValue(kPrefsCurrentBytesDownloaded, &prefs_));
EXPECT_EQ(
50,
metrics_utils::GetPersistedValue(kPrefsTotalBytesDownloaded, &prefs_));
// The second update succeeds after receiving 40 bytes, which leads to a
// overhead of 50 / 40 = 125%.
update_attempter_android_.BytesReceived(40, 40, 50);
update_attempter_android_.ProcessingDone(nullptr, ErrorCode::kSuccess);
// Both prefs should be cleared.
EXPECT_EQ(
0,
metrics_utils::GetPersistedValue(kPrefsCurrentBytesDownloaded, &prefs_));
EXPECT_EQ(
0, metrics_utils::GetPersistedValue(kPrefsTotalBytesDownloaded, &prefs_));
}
} // namespace chromeos_update_engine