blob: affb69d5af31d50117a73a3121d2f2be8f152fc3 [file] [log] [blame]
// Copyright 2021 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "rmad/state_handler/provision_device_state_handler.h"
#include <base/memory/scoped_refptr.h>
#include <base/test/task_environment.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include <memory>
#include <set>
#include <string>
#include <utility>
#include <vector>
#include "rmad/constants.h"
#include "rmad/proto_bindings/rmad.pb.h"
#include "rmad/state_handler/state_handler_test_common.h"
#include "rmad/system/mock_power_manager_client.h"
#include "rmad/utils/json_store.h"
#include "rmad/utils/mock_cbi_utils.h"
#include "rmad/utils/mock_cros_config_utils.h"
#include "rmad/utils/mock_crossystem_utils.h"
#include "rmad/utils/mock_iio_sensor_probe_utils.h"
#include "rmad/utils/mock_ssfc_utils.h"
#include "rmad/utils/mock_vpd_utils.h"
using testing::_;
using testing::Assign;
using testing::DoAll;
using testing::Eq;
using testing::Invoke;
using testing::NiceMock;
using testing::Return;
using testing::SetArgPointee;
using testing::WithArg;
namespace {
constexpr char kTestModelName[] = "TestModelName";
constexpr uint32_t kTestSSFC = 0x1234;
// crossystem HWWP property name.
constexpr char kHwwpProperty[] = "wpsw_cur";
} // namespace
namespace rmad {
class ProvisionDeviceStateHandlerTest : public StateHandlerTest {
public:
// Helper class to mock the callback function to send signal.
class SignalSender {
public:
MOCK_METHOD(void,
SendProvisionProgressSignal,
(const ProvisionStatus&),
(const));
};
void QueueStatus(const ProvisionStatus& status) {
status_history_.push_back(status);
}
scoped_refptr<ProvisionDeviceStateHandler> CreateStateHandler(
bool get_model_name = true,
bool get_ssfc = true,
bool need_update_ssfc = true,
bool set_ssfc = true,
bool set_stable_dev_secret = true,
bool flush_vpd = true,
bool hw_wp_enabled = false,
const std::set<RmadComponent>& probed_components = {
RMAD_COMPONENT_BASE_ACCELEROMETER, RMAD_COMPONENT_LID_ACCELEROMETER,
RMAD_COMPONENT_BASE_GYROSCOPE, RMAD_COMPONENT_LID_GYROSCOPE}) {
// Expect signal is always sent.
ON_CALL(signal_sender_, SendProvisionProgressSignal(_))
.WillByDefault(WithArg<0>(
Invoke(this, &ProvisionDeviceStateHandlerTest::QueueStatus)));
// Mock |PowerManagerClient|.
reboot_called_ = false;
auto mock_power_manager_client =
std::make_unique<NiceMock<MockPowerManagerClient>>();
ON_CALL(*mock_power_manager_client, Restart())
.WillByDefault(DoAll(Assign(&reboot_called_, true), Return(true)));
auto cbi_utils = std::make_unique<NiceMock<MockCbiUtils>>();
auto cros_config_utils = std::make_unique<NiceMock<MockCrosConfigUtils>>();
if (get_model_name) {
ON_CALL(*cros_config_utils, GetModelName(_))
.WillByDefault(DoAll(SetArgPointee<0>(std::string(kTestModelName)),
Return(true)));
} else {
ON_CALL(*cros_config_utils, GetModelName(_)).WillByDefault(Return(false));
}
auto crossystem_utils = std::make_unique<NiceMock<MockCrosSystemUtils>>();
ON_CALL(*crossystem_utils, GetInt(Eq(kHwwpProperty), _))
.WillByDefault(DoAll(SetArgPointee<1>(hw_wp_enabled), Return(true)));
auto iio_sensor_probe_utils =
std::make_unique<NiceMock<MockIioSensorProbeUtils>>();
ON_CALL(*iio_sensor_probe_utils, Probe())
.WillByDefault(Return(probed_components));
auto ssfc_utils = std::make_unique<NiceMock<MockSsfcUtils>>();
if (need_update_ssfc) {
ON_CALL(*ssfc_utils, GetSSFC(_, _, _))
.WillByDefault(DoAll(SetArgPointee<1>(true),
SetArgPointee<2>(kTestSSFC), Return(get_ssfc)));
ON_CALL(*cbi_utils, SetSSFC(_)).WillByDefault(Return(set_ssfc));
} else {
ON_CALL(*ssfc_utils, GetSSFC(_, _, _))
.WillByDefault(DoAll(SetArgPointee<1>(false), Return(true)));
}
auto vpd_utils = std::make_unique<NiceMock<MockVpdUtils>>();
ON_CALL(*vpd_utils, SetStableDeviceSecret(_))
.WillByDefault(Return(set_stable_dev_secret));
ON_CALL(*vpd_utils, FlushOutRoVpdCache()).WillByDefault(Return(flush_vpd));
// Fake |HardwareVerifierUtils|.
auto handler = base::MakeRefCounted<ProvisionDeviceStateHandler>(
json_store_, std::move(mock_power_manager_client), std::move(cbi_utils),
std::move(cros_config_utils), std::move(crossystem_utils),
std::move(iio_sensor_probe_utils), std::move(ssfc_utils),
std::move(vpd_utils));
auto callback =
base::BindRepeating(&SignalSender::SendProvisionProgressSignal,
base::Unretained(&signal_sender_));
handler->RegisterSignalSender(callback);
return handler;
}
void RunHandlerTaskRunner(
scoped_refptr<ProvisionDeviceStateHandler> handler) {
handler->GetTaskRunner()->PostTask(FROM_HERE, run_loop_.QuitClosure());
run_loop_.Run();
}
protected:
NiceMock<SignalSender> signal_sender_;
std::vector<ProvisionStatus> status_history_;
bool reboot_called_;
// Variables for TaskRunner.
base::test::TaskEnvironment task_environment_{
base::test::TaskEnvironment::ThreadPoolExecutionMode::ASYNC,
base::test::TaskEnvironment::TimeSource::MOCK_TIME};
base::RunLoop run_loop_;
};
TEST_F(ProvisionDeviceStateHandlerTest, InitializeState_Success) {
auto handler = CreateStateHandler();
EXPECT_EQ(handler->InitializeState(), RMAD_ERROR_OK);
handler->RunState();
RunHandlerTaskRunner(handler);
}
TEST_F(ProvisionDeviceStateHandlerTest, Clenaup_Success) {
auto handler = CreateStateHandler();
EXPECT_EQ(handler->InitializeState(), RMAD_ERROR_OK);
handler->RunState();
handler->CleanUpState();
RunHandlerTaskRunner(handler);
}
TEST_F(ProvisionDeviceStateHandlerTest, GetNextStateCase_Success) {
auto handler = CreateStateHandler();
json_store_->SetValue(kSameOwner, false);
json_store_->SetValue(kWipeDevice, true);
EXPECT_EQ(handler->InitializeState(), RMAD_ERROR_OK);
handler->RunState();
task_environment_.FastForwardBy(
ProvisionDeviceStateHandler::kReportStatusInterval);
EXPECT_GE(status_history_.size(), 1);
EXPECT_EQ(status_history_.back().status(),
ProvisionStatus::RMAD_PROVISION_STATUS_COMPLETE);
auto provision = std::make_unique<ProvisionDeviceState>();
provision->set_choice(ProvisionDeviceState::RMAD_PROVISION_CHOICE_CONTINUE);
RmadState state;
state.set_allocated_provision_device(provision.release());
auto [error, state_case] = handler->GetNextStateCase(state);
EXPECT_EQ(error, RMAD_ERROR_EXPECT_REBOOT);
task_environment_.FastForwardBy(ProvisionDeviceStateHandler::kRebootDelay);
EXPECT_EQ(reboot_called_, true);
EXPECT_EQ(state_case, RmadState::StateCase::kProvisionDevice);
RunHandlerTaskRunner(handler);
}
TEST_F(ProvisionDeviceStateHandlerTest, TryGetNextStateCaseAtBoot_Failed) {
auto handler = CreateStateHandler();
json_store_->SetValue(kSameOwner, false);
EXPECT_EQ(handler->InitializeState(), RMAD_ERROR_OK);
handler->RunState();
auto [error, state] = handler->TryGetNextStateCaseAtBoot();
EXPECT_EQ(error, RMAD_ERROR_TRANSITION_FAILED);
EXPECT_EQ(state, RmadState::StateCase::kProvisionDevice);
RunHandlerTaskRunner(handler);
}
TEST_F(ProvisionDeviceStateHandlerTest,
TryGetNextStateCaseAtBoot_NeedCalibrationSuccess) {
auto handler = CreateStateHandler();
json_store_->SetValue(kSameOwner, false);
json_store_->SetValue(
kReplacedComponentNames,
std::vector<std::string>{
RmadComponent_Name(RMAD_COMPONENT_BATTERY),
RmadComponent_Name(RMAD_COMPONENT_BASE_ACCELEROMETER),
RmadComponent_Name(RMAD_COMPONENT_LID_ACCELEROMETER),
RmadComponent_Name(RMAD_COMPONENT_BASE_GYROSCOPE),
RmadComponent_Name(RMAD_COMPONENT_LID_GYROSCOPE)});
EXPECT_EQ(handler->InitializeState(), RMAD_ERROR_OK);
handler->RunState();
task_environment_.FastForwardBy(
ProvisionDeviceStateHandler::kReportStatusInterval);
EXPECT_GE(status_history_.size(), 1);
EXPECT_EQ(status_history_.back().status(),
ProvisionStatus::RMAD_PROVISION_STATUS_COMPLETE);
auto provision = std::make_unique<ProvisionDeviceState>();
provision->set_choice(ProvisionDeviceState::RMAD_PROVISION_CHOICE_CONTINUE);
RmadState state;
state.set_allocated_provision_device(provision.release());
auto [error, state_case] = handler->GetNextStateCase(state);
EXPECT_EQ(error, RMAD_ERROR_EXPECT_REBOOT);
task_environment_.FastForwardBy(ProvisionDeviceStateHandler::kRebootDelay);
EXPECT_EQ(reboot_called_, true);
EXPECT_EQ(state_case, RmadState::StateCase::kProvisionDevice);
auto handler_after_reboot = CreateStateHandler();
EXPECT_EQ(handler_after_reboot->InitializeState(), RMAD_ERROR_OK);
handler_after_reboot->RunState();
auto [error_try_boot, state_case_try_boot] =
handler_after_reboot->TryGetNextStateCaseAtBoot();
EXPECT_EQ(error_try_boot, RMAD_ERROR_OK);
EXPECT_EQ(state_case_try_boot, RmadState::StateCase::kSetupCalibration);
RunHandlerTaskRunner(handler);
}
TEST_F(ProvisionDeviceStateHandlerTest,
TryGetNextStateCaseAtBoot_NoNeedCalibrationSuccess) {
auto handler = CreateStateHandler();
json_store_->SetValue(kSameOwner, false);
json_store_->SetValue(
kReplacedComponentNames,
std::vector<std::string>{RmadComponent_Name(RMAD_COMPONENT_BATTERY)});
EXPECT_EQ(handler->InitializeState(), RMAD_ERROR_OK);
handler->RunState();
task_environment_.FastForwardBy(
ProvisionDeviceStateHandler::kReportStatusInterval);
EXPECT_GE(status_history_.size(), 1);
EXPECT_EQ(status_history_.back().status(),
ProvisionStatus::RMAD_PROVISION_STATUS_COMPLETE);
auto provision = std::make_unique<ProvisionDeviceState>();
provision->set_choice(ProvisionDeviceState::RMAD_PROVISION_CHOICE_CONTINUE);
RmadState state;
state.set_allocated_provision_device(provision.release());
auto [error, state_case] = handler->GetNextStateCase(state);
EXPECT_EQ(error, RMAD_ERROR_EXPECT_REBOOT);
task_environment_.FastForwardBy(ProvisionDeviceStateHandler::kRebootDelay);
EXPECT_EQ(reboot_called_, true);
EXPECT_EQ(state_case, RmadState::StateCase::kProvisionDevice);
auto handler_after_reboot = CreateStateHandler();
EXPECT_EQ(handler_after_reboot->InitializeState(), RMAD_ERROR_OK);
handler_after_reboot->RunState();
auto [error_try_boot, state_case_try_boot] =
handler_after_reboot->TryGetNextStateCaseAtBoot();
EXPECT_EQ(error_try_boot, RMAD_ERROR_OK);
EXPECT_EQ(state_case_try_boot, RmadState::StateCase::kFinalize);
RunHandlerTaskRunner(handler);
}
TEST_F(ProvisionDeviceStateHandlerTest,
TryGetNextStateCaseAtBoot_BaseAccNotProbedComplete) {
auto handler = CreateStateHandler();
json_store_->SetValue(kSameOwner, false);
json_store_->SetValue(
kReplacedComponentNames,
std::vector<std::string>{
RmadComponent_Name(RMAD_COMPONENT_BATTERY),
RmadComponent_Name(RMAD_COMPONENT_BASE_ACCELEROMETER),
RmadComponent_Name(RMAD_COMPONENT_LID_ACCELEROMETER),
RmadComponent_Name(RMAD_COMPONENT_BASE_GYROSCOPE),
RmadComponent_Name(RMAD_COMPONENT_LID_GYROSCOPE)});
json_store_->SetValue(kMlbRepair, false);
EXPECT_EQ(handler->InitializeState(), RMAD_ERROR_OK);
handler->RunState();
task_environment_.FastForwardBy(
ProvisionDeviceStateHandler::kReportStatusInterval);
EXPECT_GE(status_history_.size(), 1);
EXPECT_EQ(status_history_.back().status(),
ProvisionStatus::RMAD_PROVISION_STATUS_COMPLETE);
auto provision = std::make_unique<ProvisionDeviceState>();
provision->set_choice(ProvisionDeviceState::RMAD_PROVISION_CHOICE_CONTINUE);
RmadState state;
state.set_allocated_provision_device(provision.release());
auto [error, state_case] = handler->GetNextStateCase(state);
EXPECT_EQ(error, RMAD_ERROR_EXPECT_REBOOT);
task_environment_.FastForwardBy(ProvisionDeviceStateHandler::kRebootDelay);
EXPECT_EQ(reboot_called_, true);
EXPECT_EQ(state_case, RmadState::StateCase::kProvisionDevice);
auto handler_after_reboot = CreateStateHandler(
true, true, true, true, true, true, false,
{RMAD_COMPONENT_LID_ACCELEROMETER, RMAD_COMPONENT_BASE_GYROSCOPE,
RMAD_COMPONENT_LID_GYROSCOPE});
EXPECT_EQ(handler_after_reboot->InitializeState(), RMAD_ERROR_OK);
handler_after_reboot->RunState();
task_environment_.FastForwardBy(
ProvisionDeviceStateHandler::kReportStatusInterval);
EXPECT_GE(status_history_.size(), 2);
EXPECT_EQ(status_history_.back().status(),
ProvisionStatus::RMAD_PROVISION_STATUS_COMPLETE);
auto [error_try_boot, state_case_try_boot] =
handler_after_reboot->TryGetNextStateCaseAtBoot();
EXPECT_EQ(error_try_boot, RMAD_ERROR_OK);
EXPECT_EQ(state_case_try_boot, RmadState::StateCase::kSetupCalibration);
InstructionCalibrationStatusMap calibration_map;
EXPECT_EQ(GetCalibrationMap(json_store_, &calibration_map), true);
EXPECT_EQ(calibration_map[GetCalibrationSetupInstruction(
RMAD_COMPONENT_BASE_ACCELEROMETER)]
.count(RMAD_COMPONENT_BASE_ACCELEROMETER),
0);
EXPECT_EQ(
calibration_map[GetCalibrationSetupInstruction(
RMAD_COMPONENT_LID_ACCELEROMETER)][RMAD_COMPONENT_LID_ACCELEROMETER],
CalibrationComponentStatus::RMAD_CALIBRATION_WAITING);
EXPECT_EQ(calibration_map[GetCalibrationSetupInstruction(
RMAD_COMPONENT_BASE_GYROSCOPE)][RMAD_COMPONENT_BASE_GYROSCOPE],
CalibrationComponentStatus::RMAD_CALIBRATION_WAITING);
EXPECT_EQ(calibration_map[GetCalibrationSetupInstruction(
RMAD_COMPONENT_LID_GYROSCOPE)][RMAD_COMPONENT_LID_GYROSCOPE],
CalibrationComponentStatus::RMAD_CALIBRATION_WAITING);
RunHandlerTaskRunner(handler);
}
TEST_F(ProvisionDeviceStateHandlerTest,
TryGetNextStateCaseAtBoot_LidAccNotProbedComplete) {
auto handler = CreateStateHandler();
json_store_->SetValue(kSameOwner, false);
json_store_->SetValue(
kReplacedComponentNames,
std::vector<std::string>{
RmadComponent_Name(RMAD_COMPONENT_BATTERY),
RmadComponent_Name(RMAD_COMPONENT_BASE_ACCELEROMETER),
RmadComponent_Name(RMAD_COMPONENT_LID_ACCELEROMETER),
RmadComponent_Name(RMAD_COMPONENT_BASE_GYROSCOPE),
RmadComponent_Name(RMAD_COMPONENT_LID_GYROSCOPE)});
json_store_->SetValue(kMlbRepair, false);
EXPECT_EQ(handler->InitializeState(), RMAD_ERROR_OK);
handler->RunState();
task_environment_.FastForwardBy(
ProvisionDeviceStateHandler::kReportStatusInterval);
EXPECT_GE(status_history_.size(), 1);
EXPECT_EQ(status_history_.back().status(),
ProvisionStatus::RMAD_PROVISION_STATUS_COMPLETE);
auto provision = std::make_unique<ProvisionDeviceState>();
provision->set_choice(ProvisionDeviceState::RMAD_PROVISION_CHOICE_CONTINUE);
RmadState state;
state.set_allocated_provision_device(provision.release());
auto [error, state_case] = handler->GetNextStateCase(state);
EXPECT_EQ(error, RMAD_ERROR_EXPECT_REBOOT);
task_environment_.FastForwardBy(ProvisionDeviceStateHandler::kRebootDelay);
EXPECT_EQ(reboot_called_, true);
EXPECT_EQ(state_case, RmadState::StateCase::kProvisionDevice);
auto handler_after_reboot = CreateStateHandler(
true, true, true, true, true, true, false,
{RMAD_COMPONENT_BASE_ACCELEROMETER, RMAD_COMPONENT_BASE_GYROSCOPE,
RMAD_COMPONENT_LID_GYROSCOPE});
EXPECT_EQ(handler_after_reboot->InitializeState(), RMAD_ERROR_OK);
handler_after_reboot->RunState();
task_environment_.FastForwardBy(
ProvisionDeviceStateHandler::kReportStatusInterval);
EXPECT_GE(status_history_.size(), 2);
EXPECT_EQ(status_history_.back().status(),
ProvisionStatus::RMAD_PROVISION_STATUS_COMPLETE);
auto [error_try_boot, state_case_try_boot] =
handler_after_reboot->TryGetNextStateCaseAtBoot();
EXPECT_EQ(error_try_boot, RMAD_ERROR_OK);
EXPECT_EQ(state_case_try_boot, RmadState::StateCase::kSetupCalibration);
InstructionCalibrationStatusMap calibration_map;
EXPECT_EQ(GetCalibrationMap(json_store_, &calibration_map), true);
EXPECT_EQ(calibration_map[GetCalibrationSetupInstruction(
RMAD_COMPONENT_BASE_ACCELEROMETER)]
[RMAD_COMPONENT_BASE_ACCELEROMETER],
CalibrationComponentStatus::RMAD_CALIBRATION_WAITING);
EXPECT_EQ(calibration_map[GetCalibrationSetupInstruction(
RMAD_COMPONENT_LID_ACCELEROMETER)]
.count(RMAD_COMPONENT_LID_ACCELEROMETER),
0);
EXPECT_EQ(calibration_map[GetCalibrationSetupInstruction(
RMAD_COMPONENT_BASE_GYROSCOPE)][RMAD_COMPONENT_BASE_GYROSCOPE],
CalibrationComponentStatus::RMAD_CALIBRATION_WAITING);
EXPECT_EQ(calibration_map[GetCalibrationSetupInstruction(
RMAD_COMPONENT_LID_GYROSCOPE)][RMAD_COMPONENT_LID_GYROSCOPE],
CalibrationComponentStatus::RMAD_CALIBRATION_WAITING);
RunHandlerTaskRunner(handler);
}
TEST_F(ProvisionDeviceStateHandlerTest,
TryGetNextStateCaseAtBoot_BaseGyroNotProbedComplete) {
auto handler = CreateStateHandler();
json_store_->SetValue(kSameOwner, false);
json_store_->SetValue(
kReplacedComponentNames,
std::vector<std::string>{
RmadComponent_Name(RMAD_COMPONENT_BATTERY),
RmadComponent_Name(RMAD_COMPONENT_BASE_ACCELEROMETER),
RmadComponent_Name(RMAD_COMPONENT_LID_ACCELEROMETER),
RmadComponent_Name(RMAD_COMPONENT_BASE_GYROSCOPE),
RmadComponent_Name(RMAD_COMPONENT_LID_GYROSCOPE)});
json_store_->SetValue(kMlbRepair, false);
EXPECT_EQ(handler->InitializeState(), RMAD_ERROR_OK);
handler->RunState();
task_environment_.FastForwardBy(
ProvisionDeviceStateHandler::kReportStatusInterval);
EXPECT_GE(status_history_.size(), 1);
EXPECT_EQ(status_history_.back().status(),
ProvisionStatus::RMAD_PROVISION_STATUS_COMPLETE);
auto provision = std::make_unique<ProvisionDeviceState>();
provision->set_choice(ProvisionDeviceState::RMAD_PROVISION_CHOICE_CONTINUE);
RmadState state;
state.set_allocated_provision_device(provision.release());
auto [error, state_case] = handler->GetNextStateCase(state);
EXPECT_EQ(error, RMAD_ERROR_EXPECT_REBOOT);
task_environment_.FastForwardBy(ProvisionDeviceStateHandler::kRebootDelay);
EXPECT_EQ(reboot_called_, true);
EXPECT_EQ(state_case, RmadState::StateCase::kProvisionDevice);
auto handler_after_reboot = CreateStateHandler(
true, true, true, true, true, true, false,
{RMAD_COMPONENT_BASE_ACCELEROMETER, RMAD_COMPONENT_LID_ACCELEROMETER,
RMAD_COMPONENT_LID_GYROSCOPE});
EXPECT_EQ(handler_after_reboot->InitializeState(), RMAD_ERROR_OK);
handler_after_reboot->RunState();
task_environment_.FastForwardBy(
ProvisionDeviceStateHandler::kReportStatusInterval);
EXPECT_GE(status_history_.size(), 2);
EXPECT_EQ(status_history_.back().status(),
ProvisionStatus::RMAD_PROVISION_STATUS_COMPLETE);
auto [error_try_boot, state_case_try_boot] =
handler_after_reboot->TryGetNextStateCaseAtBoot();
EXPECT_EQ(error_try_boot, RMAD_ERROR_OK);
EXPECT_EQ(state_case_try_boot, RmadState::StateCase::kSetupCalibration);
InstructionCalibrationStatusMap calibration_map;
EXPECT_EQ(GetCalibrationMap(json_store_, &calibration_map), true);
EXPECT_EQ(GetCalibrationMap(json_store_, &calibration_map), true);
EXPECT_EQ(calibration_map[GetCalibrationSetupInstruction(
RMAD_COMPONENT_BASE_ACCELEROMETER)]
[RMAD_COMPONENT_BASE_ACCELEROMETER],
CalibrationComponentStatus::RMAD_CALIBRATION_WAITING);
EXPECT_EQ(
calibration_map[GetCalibrationSetupInstruction(
RMAD_COMPONENT_LID_ACCELEROMETER)][RMAD_COMPONENT_LID_ACCELEROMETER],
CalibrationComponentStatus::RMAD_CALIBRATION_WAITING);
EXPECT_EQ(calibration_map[GetCalibrationSetupInstruction(
RMAD_COMPONENT_BASE_GYROSCOPE)]
.count(RMAD_COMPONENT_BASE_GYROSCOPE),
0);
EXPECT_EQ(calibration_map[GetCalibrationSetupInstruction(
RMAD_COMPONENT_LID_GYROSCOPE)][RMAD_COMPONENT_LID_GYROSCOPE],
CalibrationComponentStatus::RMAD_CALIBRATION_WAITING);
RunHandlerTaskRunner(handler);
}
TEST_F(ProvisionDeviceStateHandlerTest,
TryGetNextStateCaseAtBoot_LidGyroNotProbedComplete) {
auto handler = CreateStateHandler();
json_store_->SetValue(kSameOwner, false);
json_store_->SetValue(
kReplacedComponentNames,
std::vector<std::string>{
RmadComponent_Name(RMAD_COMPONENT_BATTERY),
RmadComponent_Name(RMAD_COMPONENT_BASE_ACCELEROMETER),
RmadComponent_Name(RMAD_COMPONENT_LID_ACCELEROMETER),
RmadComponent_Name(RMAD_COMPONENT_BASE_GYROSCOPE),
RmadComponent_Name(RMAD_COMPONENT_LID_GYROSCOPE)});
json_store_->SetValue(kMlbRepair, false);
EXPECT_EQ(handler->InitializeState(), RMAD_ERROR_OK);
handler->RunState();
task_environment_.FastForwardBy(
ProvisionDeviceStateHandler::kReportStatusInterval);
EXPECT_GE(status_history_.size(), 1);
EXPECT_EQ(status_history_.back().status(),
ProvisionStatus::RMAD_PROVISION_STATUS_COMPLETE);
auto provision = std::make_unique<ProvisionDeviceState>();
provision->set_choice(ProvisionDeviceState::RMAD_PROVISION_CHOICE_CONTINUE);
RmadState state;
state.set_allocated_provision_device(provision.release());
auto [error, state_case] = handler->GetNextStateCase(state);
EXPECT_EQ(error, RMAD_ERROR_EXPECT_REBOOT);
task_environment_.FastForwardBy(ProvisionDeviceStateHandler::kRebootDelay);
EXPECT_EQ(reboot_called_, true);
EXPECT_EQ(state_case, RmadState::StateCase::kProvisionDevice);
auto handler_after_reboot = CreateStateHandler(
true, true, true, true, true, true, false,
{RMAD_COMPONENT_BASE_ACCELEROMETER, RMAD_COMPONENT_LID_ACCELEROMETER,
RMAD_COMPONENT_BASE_GYROSCOPE});
EXPECT_EQ(handler_after_reboot->InitializeState(), RMAD_ERROR_OK);
handler_after_reboot->RunState();
task_environment_.FastForwardBy(
ProvisionDeviceStateHandler::kReportStatusInterval);
EXPECT_GE(status_history_.size(), 2);
EXPECT_EQ(status_history_.back().status(),
ProvisionStatus::RMAD_PROVISION_STATUS_COMPLETE);
auto [error_try_boot, state_case_try_boot] =
handler_after_reboot->TryGetNextStateCaseAtBoot();
EXPECT_EQ(error_try_boot, RMAD_ERROR_OK);
EXPECT_EQ(state_case_try_boot, RmadState::StateCase::kSetupCalibration);
InstructionCalibrationStatusMap calibration_map;
EXPECT_EQ(GetCalibrationMap(json_store_, &calibration_map), true);
EXPECT_EQ(calibration_map[GetCalibrationSetupInstruction(
RMAD_COMPONENT_BASE_ACCELEROMETER)]
[RMAD_COMPONENT_BASE_ACCELEROMETER],
CalibrationComponentStatus::RMAD_CALIBRATION_WAITING);
EXPECT_EQ(
calibration_map[GetCalibrationSetupInstruction(
RMAD_COMPONENT_LID_ACCELEROMETER)][RMAD_COMPONENT_LID_ACCELEROMETER],
CalibrationComponentStatus::RMAD_CALIBRATION_WAITING);
EXPECT_EQ(calibration_map[GetCalibrationSetupInstruction(
RMAD_COMPONENT_BASE_GYROSCOPE)][RMAD_COMPONENT_BASE_GYROSCOPE],
CalibrationComponentStatus::RMAD_CALIBRATION_WAITING);
EXPECT_EQ(calibration_map[GetCalibrationSetupInstruction(
RMAD_COMPONENT_LID_GYROSCOPE)]
.count(RMAD_COMPONENT_LID_GYROSCOPE),
0);
RunHandlerTaskRunner(handler);
}
TEST_F(ProvisionDeviceStateHandlerTest,
TryGetNextStateCaseAtBoot_PartialNeedCalibrationSuccess) {
auto handler = CreateStateHandler();
json_store_->SetValue(kSameOwner, false);
json_store_->SetValue(
kReplacedComponentNames,
std::vector<std::string>{
RmadComponent_Name(RMAD_COMPONENT_BATTERY),
RmadComponent_Name(RMAD_COMPONENT_LID_ACCELEROMETER),
RmadComponent_Name(RMAD_COMPONENT_BASE_GYROSCOPE)});
EXPECT_EQ(handler->InitializeState(), RMAD_ERROR_OK);
handler->RunState();
task_environment_.FastForwardBy(
ProvisionDeviceStateHandler::kReportStatusInterval);
EXPECT_GE(status_history_.size(), 1);
EXPECT_EQ(status_history_.back().status(),
ProvisionStatus::RMAD_PROVISION_STATUS_COMPLETE);
auto provision = std::make_unique<ProvisionDeviceState>();
provision->set_choice(ProvisionDeviceState::RMAD_PROVISION_CHOICE_CONTINUE);
RmadState state;
state.set_allocated_provision_device(provision.release());
auto [error, state_case] = handler->GetNextStateCase(state);
EXPECT_EQ(error, RMAD_ERROR_EXPECT_REBOOT);
task_environment_.FastForwardBy(ProvisionDeviceStateHandler::kRebootDelay);
EXPECT_EQ(reboot_called_, true);
EXPECT_EQ(state_case, RmadState::StateCase::kProvisionDevice);
auto handler_after_reboot = CreateStateHandler();
EXPECT_EQ(handler_after_reboot->InitializeState(), RMAD_ERROR_OK);
handler_after_reboot->RunState();
auto [error_try_boot, state_case_try_boot] =
handler_after_reboot->TryGetNextStateCaseAtBoot();
EXPECT_EQ(error_try_boot, RMAD_ERROR_OK);
EXPECT_EQ(state_case_try_boot, RmadState::StateCase::kSetupCalibration);
RunHandlerTaskRunner(handler);
}
TEST_F(ProvisionDeviceStateHandlerTest,
TryGetNextStateCaseAtBoot_KeepDevOpenSuccess) {
auto handler = CreateStateHandler();
json_store_->SetValue(kSameOwner, true);
json_store_->SetValue(
kReplacedComponentNames,
std::vector<std::string>{RmadComponent_Name(RMAD_COMPONENT_BATTERY)});
json_store_->SetValue(kWipeDevice, false);
EXPECT_EQ(handler->InitializeState(), RMAD_ERROR_OK);
handler->RunState();
task_environment_.FastForwardBy(
ProvisionDeviceStateHandler::kReportStatusInterval);
EXPECT_GE(status_history_.size(), 1);
EXPECT_EQ(status_history_.back().status(),
ProvisionStatus::RMAD_PROVISION_STATUS_COMPLETE);
auto provision = std::make_unique<ProvisionDeviceState>();
provision->set_choice(ProvisionDeviceState::RMAD_PROVISION_CHOICE_CONTINUE);
RmadState state;
state.set_allocated_provision_device(provision.release());
auto [error, state_case] = handler->GetNextStateCase(state);
EXPECT_EQ(error, RMAD_ERROR_EXPECT_REBOOT);
task_environment_.FastForwardBy(ProvisionDeviceStateHandler::kRebootDelay);
EXPECT_EQ(reboot_called_, true);
EXPECT_EQ(state_case, RmadState::StateCase::kProvisionDevice);
auto handler_after_reboot = CreateStateHandler();
EXPECT_EQ(handler_after_reboot->InitializeState(), RMAD_ERROR_OK);
handler_after_reboot->RunState();
auto [error_try_boot, state_case_try_boot] =
handler_after_reboot->TryGetNextStateCaseAtBoot();
EXPECT_EQ(error_try_boot, RMAD_ERROR_OK);
EXPECT_EQ(state_case_try_boot, RmadState::StateCase::kWpEnablePhysical);
RunHandlerTaskRunner(handler);
}
TEST_F(ProvisionDeviceStateHandlerTest,
GetNextStateCase_UnknownDestinationFailedBlocking) {
auto handler = CreateStateHandler();
EXPECT_EQ(handler->InitializeState(), RMAD_ERROR_OK);
handler->RunState();
task_environment_.FastForwardBy(
ProvisionDeviceStateHandler::kReportStatusInterval);
EXPECT_GE(status_history_.size(), 1);
EXPECT_EQ(status_history_.back().status(),
ProvisionStatus::RMAD_PROVISION_STATUS_FAILED_BLOCKING);
EXPECT_EQ(status_history_.back().error(),
ProvisionStatus::RMAD_PROVISION_ERROR_CANNOT_READ);
auto provision = std::make_unique<ProvisionDeviceState>();
provision->set_choice(ProvisionDeviceState::RMAD_PROVISION_CHOICE_CONTINUE);
RmadState state;
state.set_allocated_provision_device(provision.release());
auto [error, state_case] = handler->GetNextStateCase(state);
EXPECT_EQ(error, RMAD_ERROR_PROVISIONING_FAILED);
EXPECT_EQ(state_case, RmadState::StateCase::kProvisionDevice);
RunHandlerTaskRunner(handler);
}
TEST_F(ProvisionDeviceStateHandlerTest, GetNextStateCase_Retry) {
auto handler = CreateStateHandler();
EXPECT_EQ(handler->InitializeState(), RMAD_ERROR_OK);
handler->RunState();
task_environment_.FastForwardBy(
ProvisionDeviceStateHandler::kReportStatusInterval);
EXPECT_GE(status_history_.size(), 1);
EXPECT_EQ(status_history_.back().status(),
ProvisionStatus::RMAD_PROVISION_STATUS_FAILED_BLOCKING);
EXPECT_EQ(status_history_.back().error(),
ProvisionStatus::RMAD_PROVISION_ERROR_CANNOT_READ);
auto provision = std::make_unique<ProvisionDeviceState>();
provision->set_choice(ProvisionDeviceState::RMAD_PROVISION_CHOICE_RETRY);
RmadState state;
state.set_allocated_provision_device(provision.release());
json_store_->SetValue(kSameOwner, false);
auto [error, state_case] = handler->GetNextStateCase(state);
EXPECT_EQ(error, RMAD_ERROR_WAIT);
EXPECT_EQ(state_case, RmadState::StateCase::kProvisionDevice);
task_environment_.FastForwardBy(
ProvisionDeviceStateHandler::kReportStatusInterval);
EXPECT_GE(status_history_.size(), 2);
EXPECT_EQ(status_history_.back().status(),
ProvisionStatus::RMAD_PROVISION_STATUS_COMPLETE);
EXPECT_EQ(status_history_.back().error(),
ProvisionStatus::RMAD_PROVISION_ERROR_UNKNOWN);
RunHandlerTaskRunner(handler);
}
TEST_F(ProvisionDeviceStateHandlerTest,
GetNextStateCase_SetStableDeviceSecretFailedBlocking) {
auto handler = CreateStateHandler(true, true, true, true, false, true);
json_store_->SetValue(kSameOwner, false);
json_store_->SetValue(kWipeDevice, true);
EXPECT_EQ(handler->InitializeState(), RMAD_ERROR_OK);
handler->RunState();
task_environment_.FastForwardBy(
ProvisionDeviceStateHandler::kReportStatusInterval);
EXPECT_GE(status_history_.size(), 1);
EXPECT_EQ(status_history_.back().status(),
ProvisionStatus::RMAD_PROVISION_STATUS_FAILED_BLOCKING);
EXPECT_EQ(status_history_.back().error(),
ProvisionStatus::RMAD_PROVISION_ERROR_INTERNAL);
RunHandlerTaskRunner(handler);
}
TEST_F(ProvisionDeviceStateHandlerTest,
GetNextStateCase_GetModelNameFailedBlocking) {
auto handler = CreateStateHandler(false, true, true, true, true, true);
json_store_->SetValue(kSameOwner, false);
EXPECT_EQ(handler->InitializeState(), RMAD_ERROR_OK);
handler->RunState();
task_environment_.FastForwardBy(
ProvisionDeviceStateHandler::kReportStatusInterval);
EXPECT_GE(status_history_.size(), 1);
EXPECT_EQ(status_history_.back().status(),
ProvisionStatus::RMAD_PROVISION_STATUS_FAILED_BLOCKING);
EXPECT_EQ(status_history_.back().error(),
ProvisionStatus::RMAD_PROVISION_ERROR_CANNOT_READ);
RunHandlerTaskRunner(handler);
}
TEST_F(ProvisionDeviceStateHandlerTest,
GetNextStateCase_SsfcNotRequiredSuccess) {
auto handler = CreateStateHandler(true, true, false, true, true, true);
json_store_->SetValue(kSameOwner, false);
json_store_->SetValue(kWipeDevice, true);
json_store_->SetValue(
kReplacedComponentNames,
std::vector<std::string>{
RmadComponent_Name(RMAD_COMPONENT_BATTERY),
RmadComponent_Name(RMAD_COMPONENT_BASE_ACCELEROMETER),
RmadComponent_Name(RMAD_COMPONENT_LID_ACCELEROMETER),
RmadComponent_Name(RMAD_COMPONENT_BASE_GYROSCOPE),
RmadComponent_Name(RMAD_COMPONENT_LID_GYROSCOPE)});
EXPECT_EQ(handler->InitializeState(), RMAD_ERROR_OK);
handler->RunState();
task_environment_.FastForwardBy(
ProvisionDeviceStateHandler::kReportStatusInterval);
EXPECT_GE(status_history_.size(), 1);
EXPECT_EQ(status_history_.back().status(),
ProvisionStatus::RMAD_PROVISION_STATUS_COMPLETE);
auto provision = std::make_unique<ProvisionDeviceState>();
provision->set_choice(ProvisionDeviceState::RMAD_PROVISION_CHOICE_CONTINUE);
RmadState state;
state.set_allocated_provision_device(provision.release());
auto [error, state_case] = handler->GetNextStateCase(state);
EXPECT_EQ(error, RMAD_ERROR_EXPECT_REBOOT);
task_environment_.FastForwardBy(ProvisionDeviceStateHandler::kRebootDelay);
EXPECT_EQ(reboot_called_, true);
EXPECT_EQ(state_case, RmadState::StateCase::kProvisionDevice);
auto handler_after_reboot = CreateStateHandler();
EXPECT_EQ(handler_after_reboot->InitializeState(), RMAD_ERROR_OK);
handler_after_reboot->RunState();
auto [error_try_boot, state_case_try_boot] =
handler_after_reboot->TryGetNextStateCaseAtBoot();
EXPECT_EQ(error_try_boot, RMAD_ERROR_OK);
EXPECT_EQ(state_case_try_boot, RmadState::StateCase::kSetupCalibration);
RunHandlerTaskRunner(handler);
}
TEST_F(ProvisionDeviceStateHandlerTest,
GetNextStateCase_GetSsfcFailedBlocking) {
auto handler = CreateStateHandler(true, false, true, true, true, true);
json_store_->SetValue(kSameOwner, false);
EXPECT_EQ(handler->InitializeState(), RMAD_ERROR_OK);
handler->RunState();
task_environment_.FastForwardBy(
ProvisionDeviceStateHandler::kReportStatusInterval);
EXPECT_GE(status_history_.size(), 1);
EXPECT_EQ(status_history_.back().status(),
ProvisionStatus::RMAD_PROVISION_STATUS_FAILED_BLOCKING);
EXPECT_EQ(status_history_.back().error(),
ProvisionStatus::RMAD_PROVISION_ERROR_CANNOT_READ);
}
TEST_F(ProvisionDeviceStateHandlerTest,
GetNextStateCase_SetSsfcFailedBlockingCannotWrite) {
auto handler = CreateStateHandler(true, true, true, false, true, true);
json_store_->SetValue(kSameOwner, false);
EXPECT_EQ(handler->InitializeState(), RMAD_ERROR_OK);
handler->RunState();
task_environment_.FastForwardBy(
ProvisionDeviceStateHandler::kReportStatusInterval);
EXPECT_GE(status_history_.size(), 1);
EXPECT_EQ(status_history_.back().status(),
ProvisionStatus::RMAD_PROVISION_STATUS_FAILED_BLOCKING);
EXPECT_EQ(status_history_.back().error(),
ProvisionStatus::RMAD_PROVISION_ERROR_CANNOT_WRITE);
RunHandlerTaskRunner(handler);
}
TEST_F(ProvisionDeviceStateHandlerTest,
GetNextStateCase_SetSsfcFailedBlockingWpEnabled) {
auto handler = CreateStateHandler(true, true, true, false, true, true, true);
json_store_->SetValue(kSameOwner, false);
EXPECT_EQ(handler->InitializeState(), RMAD_ERROR_OK);
handler->RunState();
task_environment_.FastForwardBy(
ProvisionDeviceStateHandler::kReportStatusInterval);
EXPECT_GE(status_history_.size(), 1);
EXPECT_EQ(status_history_.back().status(),
ProvisionStatus::RMAD_PROVISION_STATUS_FAILED_BLOCKING);
EXPECT_EQ(status_history_.back().error(),
ProvisionStatus::RMAD_PROVISION_ERROR_WP_ENABLED);
RunHandlerTaskRunner(handler);
}
TEST_F(ProvisionDeviceStateHandlerTest,
GetNextStateCase_VpdFlushFailedBlocking) {
auto handler = CreateStateHandler(true, true, true, true, true, false);
json_store_->SetValue(kSameOwner, false);
EXPECT_EQ(handler->InitializeState(), RMAD_ERROR_OK);
handler->RunState();
task_environment_.FastForwardBy(
ProvisionDeviceStateHandler::kReportStatusInterval);
EXPECT_GE(status_history_.size(), 1);
EXPECT_EQ(status_history_.back().status(),
ProvisionStatus::RMAD_PROVISION_STATUS_FAILED_BLOCKING);
EXPECT_EQ(status_history_.back().error(),
ProvisionStatus::RMAD_PROVISION_ERROR_CANNOT_WRITE);
RunHandlerTaskRunner(handler);
}
TEST_F(ProvisionDeviceStateHandlerTest, GetNextStateCase_MissingState) {
auto handler = CreateStateHandler();
json_store_->SetValue(kSameOwner, false);
EXPECT_EQ(handler->InitializeState(), RMAD_ERROR_OK);
handler->RunState();
// No WelcomeScreenState.
RmadState state;
auto [error, state_case] = handler->GetNextStateCase(state);
EXPECT_EQ(error, RMAD_ERROR_REQUEST_INVALID);
EXPECT_EQ(state_case, RmadState::StateCase::kProvisionDevice);
RunHandlerTaskRunner(handler);
}
TEST_F(ProvisionDeviceStateHandlerTest, GetNextStateCase_MissingArgs) {
auto handler = CreateStateHandler();
json_store_->SetValue(kSameOwner, false);
EXPECT_EQ(handler->InitializeState(), RMAD_ERROR_OK);
handler->RunState();
auto provision = std::make_unique<ProvisionDeviceState>();
provision->set_choice(ProvisionDeviceState::RMAD_PROVISION_CHOICE_UNKNOWN);
RmadState state;
state.set_allocated_provision_device(provision.release());
auto [error, state_case] = handler->GetNextStateCase(state);
EXPECT_EQ(error, RMAD_ERROR_REQUEST_ARGS_MISSING);
EXPECT_EQ(state_case, RmadState::StateCase::kProvisionDevice);
RunHandlerTaskRunner(handler);
}
} // namespace rmad