blob: ef28da853e341fc3b81f73c824e902145d85a727 [file] [log] [blame]
// Copyright 2018 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "oobe_config/load_oobe_config_rollback.h"
#include <memory>
#include <string>
#include <utility>
#include <base/files/scoped_temp_dir.h>
#include <base/test/scoped_chromeos_version_info.h>
#include <base/version.h>
#include <gtest/gtest.h>
#include <metrics/structured/event_base.h>
#include <metrics/structured/mock_recorder.h>
#include <metrics/structured/recorder_singleton.h>
#include <metrics/structured_events.h>
#include "oobe_config/filesystem/file_handler_for_testing.h"
#include "oobe_config/metrics/enterprise_rollback_metrics_handler_for_testing.h"
#include "oobe_config/oobe_config.h"
#include "oobe_config/oobe_config_test.h"
namespace oobe_config {
namespace {
const char kDeviceVersionM108LsbRelease[] = "15183.1.2";
const base::Version kDeviceVersionM108("15183.1.2");
const base::Version kTargetVersionM107("15117.0.0");
} // namespace
class LoadOobeConfigRollbackTest : public OobeConfigTest {
protected:
void SetUp() override {
OobeConfigTest::SetUp();
// Set mock recorder for structured metrics.
auto recorder = std::make_unique<metrics::structured::MockRecorder>();
recorder_ = recorder.get();
metrics::structured::RecorderSingleton::GetInstance()->SetRecorderForTest(
std::move(recorder));
rollback_metrics_ = std::make_unique<
oobe_config::EnterpriseRollbackMetricsHandlerForTesting>();
load_config_ = std::make_unique<LoadOobeConfigRollback>(
oobe_config_.get(), rollback_metrics_.get(), file_handler_);
}
void TearDown() override {
// Free recorder to ensure the expectations are run and avoid leaks.
metrics::structured::RecorderSingleton::GetInstance()
->DestroyRecorderForTest();
OobeConfigTest::TearDown();
}
void FakePreceedingRollback() {
ASSERT_TRUE(oobe_config_->EncryptedRollbackSave());
SimulatePowerwash();
load_config_ = std::make_unique<LoadOobeConfigRollback>(
oobe_config_.get(), rollback_metrics_.get(), file_handler_);
}
void EnableRollbackMetricsReporting() {
ASSERT_TRUE(rollback_metrics_->EnableMetrics());
ASSERT_TRUE(rollback_metrics_->StartTrackingRollback(kDeviceVersionM108,
kTargetVersionM107));
ASSERT_TRUE(rollback_metrics_->IsTrackingRollback());
}
void ExpectOobeConfigRestoreMetricRecord(int times) {
EXPECT_CALL(*recorder_,
Record(testing::Property(
&metrics::structured::EventBase::name_hash,
metrics::structured::events::rollback_enterprise::
RollbackOobeConfigRestore::kEventNameHash)))
.Times(times);
}
void DeletePstoreData() { ASSERT_TRUE(file_handler_.RemoveRamoopsData()); }
std::unique_ptr<LoadOobeConfigRollback> load_config_;
std::unique_ptr<oobe_config::EnterpriseRollbackMetricsHandlerForTesting>
rollback_metrics_;
metrics::structured::MockRecorder* recorder_;
// Need to keep the variable around for the test version to be read. These
// tests do not verify the version is read because the reporting works anyway
// but this is the way.
base::test::ScopedChromeOSVersionInfo version_info_{
base::StringPrintf("CHROMEOS_RELEASE_VERSION=%s",
kDeviceVersionM108LsbRelease),
base::Time()};
};
TEST_F(LoadOobeConfigRollbackTest, NoRollbackNoJson) {
EnableRollbackMetricsReporting();
ExpectOobeConfigRestoreMetricRecord(0);
std::string config;
ASSERT_FALSE(load_config_->GetOobeConfigJson(&config));
}
TEST_F(LoadOobeConfigRollbackTest, DecryptAndParse) {
FakePreceedingRollback();
EnableRollbackMetricsReporting();
ExpectOobeConfigRestoreMetricRecord(1);
std::string config;
ASSERT_TRUE(load_config_->GetOobeConfigJson(&config));
}
TEST_F(LoadOobeConfigRollbackTest, SecondRequestDoesNotNeedPstore) {
FakePreceedingRollback();
EnableRollbackMetricsReporting();
ExpectOobeConfigRestoreMetricRecord(2);
std::string config;
ASSERT_TRUE(load_config_->GetOobeConfigJson(&config));
// Delete pstore data to make decryption impossible. This fakes the scenario
// where a reboot happens during rollback OOBE.
DeletePstoreData();
// Requesting config should still work because it re-uses previous data.
std::string config_saved;
ASSERT_TRUE(load_config_->GetOobeConfigJson(&config_saved));
ASSERT_EQ(config_saved, config);
}
TEST_F(LoadOobeConfigRollbackTest, DecryptionFailsGracefully) {
FakePreceedingRollback();
EnableRollbackMetricsReporting();
// Delete pstore data to fake the scenario where the device crashed or shut
// down during rollback. Pstore data is gone, so decryption will fail.
DeletePstoreData();
ExpectOobeConfigRestoreMetricRecord(1);
std::string config, enrollment_domain;
ASSERT_FALSE(load_config_->GetOobeConfigJson(&config));
}
} // namespace oobe_config