blob: d7274baccf4428893dd5766ee951924ba17530e5 [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/setup_calibration_state_handler.h"
#include <map>
#include <memory>
#include <set>
#include <string>
#include <base/files/file_util.h>
#include <base/strings/string_number_conversions.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include "rmad/state_handler/state_handler_test_common.h"
#include "rmad/utils/calibration_utils.h"
using testing::_;
using testing::Assign;
using testing::DoAll;
using testing::NiceMock;
using testing::Return;
using testing::StrictMock;
namespace {
constexpr char kBaseInstructionName[] =
"RMAD_CALIBRATION_INSTRUCTION_PLACE_BASE_ON_FLAT_SURFACE";
constexpr char kLidInstructionName[] =
"RMAD_CALIBRATION_INSTRUCTION_PLACE_LID_ON_FLAT_SURFACE";
constexpr char kBaseAccName[] = "RMAD_COMPONENT_BASE_ACCELEROMETER";
constexpr char kLidAccName[] = "RMAD_COMPONENT_LID_ACCELEROMETER";
constexpr char kBaseGyroName[] = "RMAD_COMPONENT_BASE_GYROSCOPE";
constexpr char kLidGyroName[] = "RMAD_COMPONENT_LID_GYROSCOPE";
constexpr char kStatusWaitingName[] = "RMAD_CALIBRATION_WAITING";
constexpr char kStatusCompleteName[] = "RMAD_CALIBRATION_COMPLETE";
constexpr char kStatusInProgressName[] = "RMAD_CALIBRATION_IN_PROGRESS";
constexpr char kStatusSkipName[] = "RMAD_CALIBRATION_SKIP";
constexpr char kStatusFailedName[] = "RMAD_CALIBRATION_FAILED";
} // namespace
namespace rmad {
class SetupCalibrationStateHandlerTest : public StateHandlerTest {
public:
scoped_refptr<SetupCalibrationStateHandler> CreateStateHandler() {
return base::MakeRefCounted<SetupCalibrationStateHandler>(json_store_);
}
};
TEST_F(SetupCalibrationStateHandlerTest, InitializeState_Success) {
const std::map<std::string, std::map<std::string, std::string>>
predefined_calibration_map = {{kBaseInstructionName,
{{kBaseAccName, kStatusWaitingName},
{kBaseGyroName, kStatusWaitingName}}},
{kLidInstructionName,
{{kLidAccName, kStatusWaitingName},
{kLidGyroName, kStatusWaitingName}}}};
EXPECT_TRUE(
json_store_->SetValue(kCalibrationMap, predefined_calibration_map));
auto handler = CreateStateHandler();
EXPECT_EQ(handler->InitializeState(), RMAD_ERROR_OK);
}
TEST_F(SetupCalibrationStateHandlerTest,
InitializeState_FailedCalibrationMapNotSet) {
auto handler = CreateStateHandler();
EXPECT_EQ(handler->InitializeState(),
RMAD_ERROR_STATE_HANDLER_INITIALIZATION_FAILED);
}
TEST_F(SetupCalibrationStateHandlerTest,
InitializeState_SuccessNotFinishedComponent) {
const std::map<std::string, std::map<std::string, std::string>>
predefined_calibration_map = {{kBaseInstructionName,
{{kBaseAccName, kStatusInProgressName},
{kBaseGyroName, kStatusInProgressName}}},
{kLidInstructionName,
{{kLidAccName, kStatusWaitingName},
{kLidGyroName, kStatusWaitingName}}}};
EXPECT_TRUE(
json_store_->SetValue(kCalibrationMap, predefined_calibration_map));
auto handler = CreateStateHandler();
EXPECT_EQ(handler->InitializeState(), RMAD_ERROR_OK);
}
TEST_F(SetupCalibrationStateHandlerTest, InitializeState_JsonFailed) {
// Since we are not allowed to be in-progress in the setup state, we can set
// base acc to in-progress to ensure that the change (in-progress -> failed)
// will happen in the calibration map. Then, we can test the writing part of
// the json file.
const std::map<std::string, std::map<std::string, std::string>>
predefined_calibration_map = {{kBaseInstructionName,
{{kBaseAccName, kStatusInProgressName},
{kBaseGyroName, kStatusWaitingName}}},
{kLidInstructionName,
{{kLidAccName, kStatusWaitingName},
{kLidGyroName, kStatusWaitingName}}}};
EXPECT_TRUE(
json_store_->SetValue(kCalibrationMap, predefined_calibration_map));
base::SetPosixFilePermissions(GetStateFilePath(), 0444);
auto handler = CreateStateHandler();
EXPECT_EQ(handler->InitializeState(),
RMAD_ERROR_STATE_HANDLER_INITIALIZATION_FAILED);
}
TEST_F(SetupCalibrationStateHandlerTest, GetNextStateCase_Success) {
EXPECT_TRUE(json_store_->SetValue(kWipeDevice, true));
const std::map<std::string, std::map<std::string, std::string>>
predefined_calibration_map = {{kBaseInstructionName,
{{kBaseAccName, kStatusWaitingName},
{kBaseGyroName, kStatusWaitingName}}},
{kLidInstructionName,
{{kLidAccName, kStatusWaitingName},
{kLidGyroName, kStatusWaitingName}}}};
EXPECT_TRUE(
json_store_->SetValue(kCalibrationMap, predefined_calibration_map));
auto handler = CreateStateHandler();
EXPECT_EQ(handler->InitializeState(), RMAD_ERROR_OK);
RmadState state = handler->GetState();
auto [error, state_case] = handler->GetNextStateCase(state);
EXPECT_EQ(error, RMAD_ERROR_OK);
EXPECT_EQ(state_case, RmadState::StateCase::kRunCalibration);
}
TEST_F(SetupCalibrationStateHandlerTest,
GetNextStateCase_SuccessNoNeedCalibration) {
EXPECT_TRUE(json_store_->SetValue(kWipeDevice, true));
const std::map<std::string, std::map<std::string, std::string>>
predefined_calibration_map = {{kBaseInstructionName,
{{kBaseAccName, kStatusCompleteName},
{kBaseGyroName, kStatusCompleteName}}},
{kLidInstructionName,
{{kLidAccName, kStatusSkipName},
{kLidGyroName, kStatusCompleteName}}}};
EXPECT_TRUE(
json_store_->SetValue(kCalibrationMap, predefined_calibration_map));
auto handler = CreateStateHandler();
EXPECT_EQ(handler->InitializeState(), RMAD_ERROR_OK);
RmadState state = handler->GetState();
auto [error, state_case] = handler->GetNextStateCase(state);
EXPECT_EQ(error, RMAD_ERROR_OK);
EXPECT_EQ(state_case, RmadState::StateCase::kFinalize);
}
TEST_F(SetupCalibrationStateHandlerTest,
GetNextStateCase_SuccessNoNeedCalibration_NoWipeDevice) {
EXPECT_TRUE(json_store_->SetValue(kWipeDevice, false));
const std::map<std::string, std::map<std::string, std::string>>
predefined_calibration_map = {{kBaseInstructionName,
{{kBaseAccName, kStatusCompleteName},
{kBaseGyroName, kStatusCompleteName}}},
{kLidInstructionName,
{{kLidAccName, kStatusSkipName},
{kLidGyroName, kStatusCompleteName}}}};
EXPECT_TRUE(
json_store_->SetValue(kCalibrationMap, predefined_calibration_map));
auto handler = CreateStateHandler();
EXPECT_EQ(handler->InitializeState(), RMAD_ERROR_OK);
RmadState state = handler->GetState();
auto [error, state_case] = handler->GetNextStateCase(state);
EXPECT_EQ(error, RMAD_ERROR_OK);
EXPECT_EQ(state_case, RmadState::StateCase::kWpEnablePhysical);
}
TEST_F(SetupCalibrationStateHandlerTest, GetNextStateCase_SuccessNoSensor) {
EXPECT_TRUE(json_store_->SetValue(kWipeDevice, true));
EXPECT_TRUE(SetCalibrationMap(json_store_, {}));
auto handler = CreateStateHandler();
EXPECT_EQ(handler->InitializeState(), RMAD_ERROR_OK);
RmadState state = handler->GetState();
auto [error, state_case] = handler->GetNextStateCase(state);
EXPECT_EQ(error, RMAD_ERROR_OK);
EXPECT_EQ(state_case, RmadState::StateCase::kFinalize);
}
TEST_F(SetupCalibrationStateHandlerTest,
GetNextStateCase_SuccessNoSensor_NoWipeDevice) {
EXPECT_TRUE(json_store_->SetValue(kWipeDevice, false));
EXPECT_TRUE(SetCalibrationMap(json_store_, {}));
auto handler = CreateStateHandler();
EXPECT_EQ(handler->InitializeState(), RMAD_ERROR_OK);
RmadState state = handler->GetState();
auto [error, state_case] = handler->GetNextStateCase(state);
EXPECT_EQ(error, RMAD_ERROR_OK);
EXPECT_EQ(state_case, RmadState::StateCase::kWpEnablePhysical);
}
TEST_F(SetupCalibrationStateHandlerTest, GetNextStateCase_SuccessNeedToCheck) {
EXPECT_TRUE(json_store_->SetValue(kWipeDevice, true));
const std::map<std::string, std::map<std::string, std::string>>
predefined_calibration_map = {{kBaseInstructionName,
{{kBaseAccName, kStatusFailedName},
{kBaseGyroName, kStatusCompleteName}}},
{kLidInstructionName,
{{kLidAccName, kStatusFailedName},
{kLidGyroName, kStatusCompleteName}}}};
EXPECT_TRUE(
json_store_->SetValue(kCalibrationMap, predefined_calibration_map));
auto handler = CreateStateHandler();
EXPECT_EQ(handler->InitializeState(), RMAD_ERROR_OK);
RmadState state = handler->GetState();
auto [error, state_case] = handler->GetNextStateCase(state);
EXPECT_EQ(error, RMAD_ERROR_OK);
EXPECT_EQ(state_case, RmadState::StateCase::kCheckCalibration);
}
TEST_F(SetupCalibrationStateHandlerTest,
GetNextStateCase_SuccessNeedToCheckAutoTransition) {
EXPECT_TRUE(json_store_->SetValue(kWipeDevice, true));
const std::map<std::string, std::map<std::string, std::string>>
predefined_calibration_map = {{kBaseInstructionName,
{{kBaseAccName, kStatusFailedName},
{kBaseGyroName, kStatusCompleteName}}},
{kLidInstructionName,
{{kLidAccName, kStatusFailedName},
{kLidGyroName, kStatusCompleteName}}}};
EXPECT_TRUE(
json_store_->SetValue(kCalibrationMap, predefined_calibration_map));
auto handler = CreateStateHandler();
EXPECT_EQ(handler->InitializeState(), RMAD_ERROR_OK);
// Simulate the auto-transition scenario
RmadState state = handler->GetState();
auto [error, state_case] = handler->GetNextStateCase(state);
EXPECT_EQ(error, RMAD_ERROR_OK);
EXPECT_EQ(state_case, RmadState::StateCase::kCheckCalibration);
}
TEST_F(SetupCalibrationStateHandlerTest, GetNextStateCase_MissingState) {
EXPECT_TRUE(json_store_->SetValue(kWipeDevice, true));
EXPECT_TRUE(SetCalibrationMap(json_store_, {}));
auto handler = CreateStateHandler();
EXPECT_EQ(handler->InitializeState(), RMAD_ERROR_OK);
// No SetupCalibrationState.
RmadState state;
auto [error, state_case] = handler->GetNextStateCase(state);
EXPECT_EQ(error, RMAD_ERROR_REQUEST_INVALID);
EXPECT_EQ(state_case, RmadState::StateCase::kSetupCalibration);
}
TEST_F(SetupCalibrationStateHandlerTest,
GetNextStateCase_MissingWipeDeviceVar) {
// No kWipeDevice set.
const std::map<std::string, std::map<std::string, std::string>>
predefined_calibration_map = {{kBaseInstructionName,
{{kBaseAccName, kStatusFailedName},
{kBaseGyroName, kStatusCompleteName}}},
{kLidInstructionName,
{{kLidAccName, kStatusFailedName},
{kLidGyroName, kStatusCompleteName}}}};
EXPECT_TRUE(
json_store_->SetValue(kCalibrationMap, predefined_calibration_map));
auto handler = CreateStateHandler();
EXPECT_EQ(handler->InitializeState(), RMAD_ERROR_OK);
RmadState state = handler->GetState();
auto [error, state_case] = handler->GetNextStateCase(state);
EXPECT_EQ(error, RMAD_ERROR_TRANSITION_FAILED);
EXPECT_EQ(state_case, RmadState::StateCase::kSetupCalibration);
}
TEST_F(SetupCalibrationStateHandlerTest,
GetNextStateCase_ReadOnlyInstructionChanged) {
EXPECT_TRUE(json_store_->SetValue(kWipeDevice, true));
const std::map<std::string, std::map<std::string, std::string>>
predefined_calibration_map = {{kBaseInstructionName,
{{kBaseAccName, kStatusWaitingName},
{kBaseGyroName, kStatusWaitingName}}},
{kLidInstructionName,
{{kLidAccName, kStatusCompleteName},
{kLidGyroName, kStatusCompleteName}}}};
EXPECT_TRUE(
json_store_->SetValue(kCalibrationMap, predefined_calibration_map));
auto handler = CreateStateHandler();
EXPECT_EQ(handler->InitializeState(), RMAD_ERROR_OK);
RmadState state = handler->GetState();
auto setup_calibration_state =
std::make_unique<SetupCalibrationState>(state.setup_calibration());
setup_calibration_state->set_instruction(
RMAD_CALIBRATION_INSTRUCTION_PLACE_LID_ON_FLAT_SURFACE);
state.set_allocated_setup_calibration(setup_calibration_state.release());
auto [error, state_case] = handler->GetNextStateCase(state);
EXPECT_EQ(error, RMAD_ERROR_REQUEST_INVALID);
EXPECT_EQ(state_case, RmadState::StateCase::kSetupCalibration);
}
TEST_F(SetupCalibrationStateHandlerTest, GetNextStateCase_NotInitialized) {
EXPECT_TRUE(json_store_->SetValue(kWipeDevice, true));
const std::map<std::string, std::map<std::string, std::string>>
predefined_calibration_map = {{kBaseInstructionName,
{{kBaseAccName, kStatusWaitingName},
{kBaseGyroName, kStatusWaitingName}}},
{kLidInstructionName,
{{kLidAccName, kStatusCompleteName},
{kLidGyroName, kStatusCompleteName}}}};
EXPECT_TRUE(
json_store_->SetValue(kCalibrationMap, predefined_calibration_map));
auto handler = CreateStateHandler();
RmadState state;
auto setup_calibration_state = std::make_unique<SetupCalibrationState>();
state.set_allocated_setup_calibration(setup_calibration_state.release());
// In order to be further checked by the user in kCheckCalibration, it should
// return OK for transition.
auto [error, state_case] = handler->GetNextStateCase(state);
EXPECT_EQ(error, RMAD_ERROR_OK);
EXPECT_EQ(state_case, RmadState::StateCase::kCheckCalibration);
}
TEST_F(SetupCalibrationStateHandlerTest, TryGetNextStateCaseAtBoot_Success) {
EXPECT_TRUE(json_store_->SetValue(kWipeDevice, true));
const std::map<std::string, std::map<std::string, std::string>>
predefined_calibration_map = {{kBaseInstructionName,
{{kBaseAccName, kStatusWaitingName},
{kBaseGyroName, kStatusWaitingName}}},
{kLidInstructionName,
{{kLidAccName, kStatusWaitingName},
{kLidGyroName, kStatusWaitingName}}}};
EXPECT_TRUE(
json_store_->SetValue(kCalibrationMap, predefined_calibration_map));
auto handler = CreateStateHandler();
EXPECT_EQ(handler->InitializeState(), RMAD_ERROR_OK);
auto [error, state_case] = handler->TryGetNextStateCaseAtBoot();
EXPECT_EQ(error, RMAD_ERROR_TRANSITION_FAILED);
EXPECT_EQ(state_case, RmadState::StateCase::kSetupCalibration);
}
TEST_F(SetupCalibrationStateHandlerTest,
TryGetNextStateCaseAtBoot_SuccessNeedToCheck) {
EXPECT_TRUE(json_store_->SetValue(kWipeDevice, true));
const std::map<std::string, std::map<std::string, std::string>>
predefined_calibration_map = {{kBaseInstructionName,
{{kBaseAccName, kStatusFailedName},
{kBaseGyroName, kStatusCompleteName}}},
{kLidInstructionName,
{{kLidAccName, kStatusFailedName},
{kLidGyroName, kStatusCompleteName}}}};
EXPECT_TRUE(
json_store_->SetValue(kCalibrationMap, predefined_calibration_map));
auto handler = CreateStateHandler();
EXPECT_EQ(handler->InitializeState(), RMAD_ERROR_OK);
auto [error, state_case] = handler->TryGetNextStateCaseAtBoot();
EXPECT_EQ(error, RMAD_ERROR_OK);
EXPECT_EQ(state_case, RmadState::StateCase::kCheckCalibration);
}
} // namespace rmad