| // Copyright 2021 The ChromiumOS Authors | |
| // Use of this source code is governed by a BSD-style license that can be | |
| // found in the LICENSE file. | |
| #include "rmad/daemon/dbus_service.h" | |
| #include <sysexits.h> | |
| #include <string> | |
| #include <base/files/file_util.h> | |
| #include <base/files/scoped_temp_dir.h> | |
| #include <brillo/dbus/dbus_object_test_helpers.h> | |
| #include <brillo/file_utils.h> | |
| #include <dbus/mock_bus.h> | |
| #include <dbus/mock_exported_object.h> | |
| #include <dbus/rmad/dbus-constants.h> | |
| #include <gmock/gmock.h> | |
| #include <gtest/gtest.h> | |
| #include "rmad/interface/mock_rmad_interface.h" | |
| #include "rmad/system/mock_tpm_manager_client.h" | |
| #include "rmad/utils/mock_cros_config_utils.h" | |
| #include "rmad/utils/mock_crossystem_utils.h" | |
| using brillo::dbus_utils::AsyncEventSequencer; | |
| using testing::_; | |
| using testing::A; | |
| using testing::AnyNumber; | |
| using testing::DoAll; | |
| using testing::Eq; | |
| using testing::Invoke; | |
| using testing::NiceMock; | |
| using testing::Return; | |
| using testing::SetArgPointee; | |
| using testing::StrictMock; | |
| namespace rmad { | |
| class DBusServiceTestBase : public testing::Test { | |
| public: | |
| struct RmadOptions { | |
| bool is_state_file_exist = false; | |
| RoVerificationStatus ro_verification_status = | |
| RMAD_RO_VERIFICATION_NOT_TRIGGERED; | |
| bool is_rmad_enabled_in_cros_config = true; | |
| std::string main_fw_type = "normal"; | |
| bool rmad_setup_result = true; | |
| // Sets to std::nullopt makes getter return error. | |
| std::optional<bool> is_cros_debug = false; | |
| bool is_test_directory_exist = false; | |
| }; | |
| DBusServiceTestBase() { | |
| dbus::Bus::Options options; | |
| mock_bus_ = base::MakeRefCounted<NiceMock<dbus::MockBus>>(options); | |
| dbus::ObjectPath path(kRmadServicePath); | |
| mock_exported_object_ = | |
| base::MakeRefCounted<StrictMock<dbus::MockExportedObject>>( | |
| mock_bus_.get(), path); | |
| ON_CALL(*mock_bus_, GetExportedObject(path)) | |
| .WillByDefault(Return(mock_exported_object_.get())); | |
| EXPECT_CALL(*mock_exported_object_, ExportMethod(_, _, _, _)) | |
| .WillRepeatedly(Return()); | |
| EXPECT_CALL(*mock_exported_object_, Unregister()).WillRepeatedly(Return()); | |
| } | |
| ~DBusServiceTestBase() override = default; | |
| base::FilePath GetStateFilePath() const { | |
| return temp_dir_.GetPath().AppendASCII("state"); | |
| } | |
| base::FilePath GetTestDirecotryPath() const { | |
| return temp_dir_.GetPath().AppendASCII(".test"); | |
| } | |
| void StartDBusService(const RmadOptions& options) { | |
| auto mock_tpm_manager_client = | |
| std::make_unique<NiceMock<MockTpmManagerClient>>(); | |
| auto mock_cros_config_utils = | |
| std::make_unique<NiceMock<MockCrosConfigUtils>>(); | |
| auto mock_crossystem_utils = | |
| std::make_unique<NiceMock<MockCrosSystemUtils>>(); | |
| base::FilePath state_file_path = GetStateFilePath(); | |
| if (options.is_state_file_exist) { | |
| brillo::TouchFile(state_file_path); | |
| } | |
| // It is ok to use file instead of directory here because we only check if | |
| // it exists. | |
| base::FilePath test_dir_path = GetTestDirecotryPath(); | |
| if (options.is_test_directory_exist) { | |
| brillo::TouchFile(test_dir_path); | |
| } | |
| ON_CALL(*mock_tpm_manager_client, GetRoVerificationStatus(_)) | |
| .WillByDefault(DoAll(SetArgPointee<0>(options.ro_verification_status), | |
| Return(true))); | |
| ON_CALL(*mock_cros_config_utils, GetRmadConfig(_)) | |
| .WillByDefault( | |
| DoAll(SetArgPointee<0>(RmadConfig( | |
| {.enabled = options.is_rmad_enabled_in_cros_config})), | |
| Return(true))); | |
| if (options.is_cros_debug.has_value()) { | |
| ON_CALL(*mock_crossystem_utils, | |
| GetInt(Eq(CrosSystemUtils::kCrosDebugProperty), _)) | |
| .WillByDefault(DoAll(SetArgPointee<1>(options.is_cros_debug.value()), | |
| Return(true))); | |
| } else { | |
| ON_CALL(*mock_crossystem_utils, | |
| GetString(Eq(CrosSystemUtils::kCrosDebugProperty), _)) | |
| .WillByDefault(Return(false)); | |
| } | |
| ON_CALL(*mock_crossystem_utils, | |
| GetString(Eq(CrosSystemUtils::kMainFwTypeProperty), _)) | |
| .WillByDefault( | |
| DoAll(SetArgPointee<1>(options.main_fw_type), Return(true))); | |
| ON_CALL(mock_rmad_service_, SetUp(_)) | |
| .WillByDefault(Return(options.rmad_setup_result)); | |
| dbus_service_ = std::make_unique<DBusService>( | |
| mock_bus_, &mock_rmad_service_, state_file_path, test_dir_path, | |
| std::move(mock_tpm_manager_client), std::move(mock_cros_config_utils), | |
| std::move(mock_crossystem_utils)); | |
| ASSERT_EQ(dbus_service_->OnEventLoopStarted(), EX_OK); | |
| auto sequencer = base::MakeRefCounted<AsyncEventSequencer>(); | |
| dbus_service_->RegisterDBusObjectsAsync(sequencer.get()); | |
| } | |
| template <typename RequestProtobufType, typename ReplyProtobufType> | |
| void ExecuteMethod(const std::string& method_name, | |
| const RequestProtobufType& request, | |
| ReplyProtobufType* reply) { | |
| std::unique_ptr<dbus::MethodCall> call = CreateMethodCall(method_name); | |
| dbus::MessageWriter writer(call.get()); | |
| writer.AppendProtoAsArrayOfBytes(request); | |
| auto response = brillo::dbus_utils::testing::CallMethod( | |
| *dbus_service_->dbus_object_, call.get()); | |
| if (response.get()) { | |
| dbus::MessageReader reader(response.get()); | |
| EXPECT_TRUE(reader.PopArrayOfBytesAsProto(reply)); | |
| } | |
| } | |
| template <typename ReplyProtobufType> | |
| void ExecuteMethod(const std::string& method_name, | |
| const std::string request, | |
| ReplyProtobufType* reply) { | |
| std::unique_ptr<dbus::MethodCall> call = CreateMethodCall(method_name); | |
| dbus::MessageWriter writer(call.get()); | |
| writer.AppendString(request); | |
| auto response = brillo::dbus_utils::testing::CallMethod( | |
| *dbus_service_->dbus_object_, call.get()); | |
| if (response.get()) { | |
| dbus::MessageReader reader(response.get()); | |
| EXPECT_TRUE(reader.PopArrayOfBytesAsProto(reply)); | |
| } | |
| } | |
| template <typename ReplyProtobufType> | |
| void ExecuteMethod(const std::string& method_name, ReplyProtobufType* reply) { | |
| std::unique_ptr<dbus::MethodCall> call = CreateMethodCall(method_name); | |
| auto response = brillo::dbus_utils::testing::CallMethod( | |
| *dbus_service_->dbus_object_, call.get()); | |
| if (response.get()) { | |
| dbus::MessageReader reader(response.get()); | |
| EXPECT_TRUE(reader.PopArrayOfBytesAsProto(reply)); | |
| } | |
| } | |
| void ExecuteMethod(const std::string& method_name, std::string* reply) { | |
| std::unique_ptr<dbus::MethodCall> call = CreateMethodCall(method_name); | |
| auto response = brillo::dbus_utils::testing::CallMethod( | |
| *dbus_service_->dbus_object_, call.get()); | |
| if (response.get()) { | |
| dbus::MessageReader reader(response.get()); | |
| EXPECT_TRUE(reader.PopString(reply)); | |
| } | |
| } | |
| void ExecuteMethod(const std::string& method_name, bool* reply) { | |
| std::unique_ptr<dbus::MethodCall> call = CreateMethodCall(method_name); | |
| auto response = brillo::dbus_utils::testing::CallMethod( | |
| *dbus_service_->dbus_object_, call.get()); | |
| if (response.get()) { | |
| dbus::MessageReader reader(response.get()); | |
| EXPECT_TRUE(reader.PopBool(reply)); | |
| } | |
| } | |
| void SignalError(RmadErrorCode error) { | |
| dbus_service_->SendErrorSignal(error); | |
| } | |
| void SignalHardwareVerification(const HardwareVerificationResult& result) { | |
| dbus_service_->SendHardwareVerificationResultSignal(result); | |
| } | |
| void SignalUpdateRoFirmwareStatus(const UpdateRoFirmwareStatus status) { | |
| dbus_service_->SendUpdateRoFirmwareStatusSignal(status); | |
| } | |
| void SignalCalibrationOverall(CalibrationOverallStatus overall_status) { | |
| dbus_service_->SendCalibrationOverallSignal(overall_status); | |
| } | |
| void SignalCalibrationComponent(CalibrationComponentStatus component_status) { | |
| dbus_service_->SendCalibrationProgressSignal(component_status); | |
| } | |
| void SignalProvision(const ProvisionStatus& status) { | |
| dbus_service_->SendProvisionProgressSignal(status); | |
| } | |
| void SignalFinalize(const FinalizeStatus& status) { | |
| dbus_service_->SendFinalizeProgressSignal(status); | |
| } | |
| void SignalHardwareWriteProtection(bool enabled) { | |
| dbus_service_->SendHardwareWriteProtectionStateSignal(enabled); | |
| } | |
| void SignalPowerCableState(bool plugged_in) { | |
| dbus_service_->SendPowerCableStateSignal(plugged_in); | |
| } | |
| void SignalExternalDisk(bool detected) { | |
| dbus_service_->SendExternalDiskSignal(detected); | |
| } | |
| dbus::MockExportedObject* GetMockExportedObject() { | |
| return mock_exported_object_.get(); | |
| } | |
| protected: | |
| void SetUp() override { ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); } | |
| std::unique_ptr<dbus::MethodCall> CreateMethodCall( | |
| const std::string& method_name) { | |
| auto call = | |
| std::make_unique<dbus::MethodCall>(kRmadInterfaceName, method_name); | |
| call->SetSerial(1); | |
| return call; | |
| } | |
| scoped_refptr<dbus::MockBus> mock_bus_; | |
| scoped_refptr<dbus::MockExportedObject> mock_exported_object_; | |
| base::ScopedTempDir temp_dir_; | |
| StrictMock<MockRmadInterface> mock_rmad_service_; | |
| std::unique_ptr<DBusService> dbus_service_; | |
| }; | |
| class DBusServiceIsRequiredTest : public DBusServiceTestBase {}; | |
| class DBusServiceTest : public DBusServiceTestBase { | |
| protected: | |
| void SetUp() override { | |
| DBusServiceTestBase::SetUp(); | |
| EXPECT_CALL(mock_rmad_service_, SetUp(_)).Times(AnyNumber()); | |
| EXPECT_CALL(mock_rmad_service_, TryTransitionNextStateFromCurrentState()) | |
| .Times(AnyNumber()); | |
| StartDBusService({.is_state_file_exist = true}); | |
| } | |
| }; | |
| TEST_F(DBusServiceIsRequiredTest, IsRmaRequired_NotRequired) { | |
| StartDBusService({.is_state_file_exist = false}); | |
| bool is_rma_required; | |
| ExecuteMethod(kIsRmaRequiredMethod, &is_rma_required); | |
| EXPECT_EQ(is_rma_required, false); | |
| EXPECT_FALSE(base::PathExists(GetStateFilePath())); | |
| } | |
| TEST_F(DBusServiceIsRequiredTest, IsRmaRequired_RoVerificationPass) { | |
| StartDBusService({ | |
| .ro_verification_status = RMAD_RO_VERIFICATION_PASS, | |
| }); | |
| bool is_rma_required; | |
| ExecuteMethod(kIsRmaRequiredMethod, &is_rma_required); | |
| EXPECT_EQ(is_rma_required, true); | |
| EXPECT_TRUE(base::PathExists(GetStateFilePath())); | |
| } | |
| TEST_F(DBusServiceIsRequiredTest, | |
| IsRmaRequired_RoVerificationUnsupportedTriggered) { | |
| StartDBusService({ | |
| .ro_verification_status = RMAD_RO_VERIFICATION_UNSUPPORTED_TRIGGERED, | |
| }); | |
| bool is_rma_required; | |
| ExecuteMethod(kIsRmaRequiredMethod, &is_rma_required); | |
| EXPECT_EQ(is_rma_required, true); | |
| EXPECT_TRUE(base::PathExists(GetStateFilePath())); | |
| } | |
| TEST_F(DBusServiceIsRequiredTest, IsRmaRequired_StateFileExists) { | |
| StartDBusService({.is_state_file_exist = true}); | |
| bool is_rma_required; | |
| ExecuteMethod(kIsRmaRequiredMethod, &is_rma_required); | |
| EXPECT_EQ(is_rma_required, true); | |
| EXPECT_TRUE(base::PathExists(GetStateFilePath())); | |
| } | |
| TEST_F(DBusServiceIsRequiredTest, IsRmaRequired_InterfaceSetUpFailed) { | |
| StartDBusService({ | |
| .is_state_file_exist = true, | |
| // The method call doesn't set up the interface so it works normally. | |
| .rmad_setup_result = false, | |
| }); | |
| bool is_rma_required; | |
| ExecuteMethod(kIsRmaRequiredMethod, &is_rma_required); | |
| EXPECT_EQ(is_rma_required, true); | |
| EXPECT_TRUE(base::PathExists(GetStateFilePath())); | |
| } | |
| TEST_F(DBusServiceIsRequiredTest, IsRmaRequired_IsNotAllowed) { | |
| StartDBusService({ | |
| .is_state_file_exist = true, | |
| .is_rmad_enabled_in_cros_config = false, // Disable rmad by cros_config. | |
| }); | |
| bool is_rma_required; | |
| ExecuteMethod(kIsRmaRequiredMethod, &is_rma_required); | |
| EXPECT_EQ(is_rma_required, false); | |
| } | |
| TEST_F(DBusServiceIsRequiredTest, IsRmaRequired_IsNotNormalMode) { | |
| StartDBusService({ | |
| .is_state_file_exist = true, | |
| .main_fw_type = "not_normal", // Disable rmad by fw type. | |
| }); | |
| bool is_rma_required; | |
| ExecuteMethod(kIsRmaRequiredMethod, &is_rma_required); | |
| EXPECT_EQ(is_rma_required, false); | |
| } | |
| TEST_F(DBusServiceIsRequiredTest, IsRmaRequired_IsDevMode) { | |
| // Set cros debug and test directory to override the check of cros_config and | |
| // fw_type. | |
| StartDBusService({ | |
| .is_state_file_exist = true, | |
| .is_rmad_enabled_in_cros_config = false, | |
| .main_fw_type = "not_normal", | |
| .is_cros_debug = true, | |
| .is_test_directory_exist = true, | |
| }); | |
| bool is_rma_required; | |
| ExecuteMethod(kIsRmaRequiredMethod, &is_rma_required); | |
| EXPECT_EQ(is_rma_required, true); | |
| } | |
| TEST_F(DBusServiceIsRequiredTest, IsRmaRequired_IsNotDevModeNoCrosDebug) { | |
| // Failed to get cros_debug should not bypass the check of cros_config and | |
| // fw_type. | |
| StartDBusService({ | |
| .is_state_file_exist = true, | |
| .is_rmad_enabled_in_cros_config = false, | |
| .main_fw_type = "not_normal", | |
| .is_cros_debug = std::nullopt, | |
| .is_test_directory_exist = true, | |
| }); | |
| bool is_rma_required; | |
| ExecuteMethod(kIsRmaRequiredMethod, &is_rma_required); | |
| EXPECT_EQ(is_rma_required, false); | |
| } | |
| TEST_F(DBusServiceIsRequiredTest, IsRmaRequired_IsNotDevModeCrosDebugIsFalse) { | |
| // cros_debug sets to false should not bypass the check of cros_config and | |
| // fw_type. | |
| StartDBusService({ | |
| .is_state_file_exist = true, | |
| .is_rmad_enabled_in_cros_config = false, | |
| .main_fw_type = "not_normal", | |
| .is_cros_debug = false, | |
| .is_test_directory_exist = true, | |
| }); | |
| bool is_rma_required; | |
| ExecuteMethod(kIsRmaRequiredMethod, &is_rma_required); | |
| EXPECT_EQ(is_rma_required, false); | |
| } | |
| TEST_F(DBusServiceIsRequiredTest, IsRmaRequired_IsNotDevModeNoTestDir) { | |
| // No test directory should not bypass the check of cros_config and fw_type. | |
| StartDBusService({ | |
| .is_state_file_exist = true, | |
| .is_rmad_enabled_in_cros_config = false, | |
| .main_fw_type = "not_normal", | |
| .is_cros_debug = true, | |
| .is_test_directory_exist = false, | |
| }); | |
| bool is_rma_required; | |
| ExecuteMethod(kIsRmaRequiredMethod, &is_rma_required); | |
| EXPECT_EQ(is_rma_required, false); | |
| } | |
| TEST_F(DBusServiceIsRequiredTest, GetCurrentState_Success) { | |
| EXPECT_CALL(mock_rmad_service_, SetUp(_)); | |
| EXPECT_CALL(mock_rmad_service_, TryTransitionNextStateFromCurrentState()); | |
| EXPECT_CALL(mock_rmad_service_, GetCurrentState(_)) | |
| .WillOnce(Invoke([](RmadInterface::GetStateCallback callback) { | |
| GetStateReply reply; | |
| reply.set_error(RMAD_ERROR_RMA_NOT_REQUIRED); | |
| std::move(callback).Run(reply, false); | |
| })); | |
| StartDBusService({.is_state_file_exist = true}); | |
| GetStateReply reply; | |
| ExecuteMethod(kGetCurrentStateMethod, &reply); | |
| EXPECT_EQ(RMAD_ERROR_RMA_NOT_REQUIRED, reply.error()); | |
| EXPECT_EQ(RmadState::STATE_NOT_SET, reply.state().state_case()); | |
| } | |
| TEST_F(DBusServiceIsRequiredTest, GetCurrentState_RmaNotRequired) { | |
| EXPECT_CALL(mock_rmad_service_, SetUp(_)).Times(0); | |
| EXPECT_CALL(mock_rmad_service_, TryTransitionNextStateFromCurrentState()) | |
| .Times(0); | |
| StartDBusService({.is_state_file_exist = false}); | |
| GetStateReply reply; | |
| ExecuteMethod(kGetCurrentStateMethod, &reply); | |
| EXPECT_EQ(RMAD_ERROR_RMA_NOT_REQUIRED, reply.error()); | |
| EXPECT_EQ(RmadState::STATE_NOT_SET, reply.state().state_case()); | |
| } | |
| TEST_F(DBusServiceIsRequiredTest, GetCurrentState_InterfaceSetUpFailed) { | |
| EXPECT_CALL(mock_rmad_service_, SetUp(_)); | |
| EXPECT_CALL(mock_rmad_service_, TryTransitionNextStateFromCurrentState()) | |
| .Times(0); | |
| StartDBusService({ | |
| .is_state_file_exist = true, | |
| .rmad_setup_result = false, | |
| }); | |
| GetStateReply reply; | |
| ExecuteMethod(kGetCurrentStateMethod, &reply); | |
| EXPECT_EQ(RMAD_ERROR_DAEMON_INITIALIZATION_FAILED, reply.error()); | |
| EXPECT_EQ(RmadState::STATE_NOT_SET, reply.state().state_case()); | |
| } | |
| TEST_F(DBusServiceTest, TransitionNextState) { | |
| EXPECT_CALL(mock_rmad_service_, TransitionNextState(_, _)) | |
| .WillOnce(Invoke([](const TransitionNextStateRequest& request, | |
| RmadInterface::GetStateCallback callback) { | |
| GetStateReply reply; | |
| reply.set_error(RMAD_ERROR_OK); | |
| RmadState* state = new RmadState(); | |
| state->set_allocated_welcome(new WelcomeState()); | |
| reply.set_allocated_state(state); | |
| std::move(callback).Run(reply, false); | |
| })); | |
| TransitionNextStateRequest request; | |
| GetStateReply reply; | |
| ExecuteMethod(kTransitionNextStateMethod, request, &reply); | |
| EXPECT_EQ(RMAD_ERROR_OK, reply.error()); | |
| EXPECT_EQ(RmadState::kWelcome, reply.state().state_case()); | |
| } | |
| TEST_F(DBusServiceTest, TransitionPreviousState) { | |
| EXPECT_CALL(mock_rmad_service_, TransitionPreviousState(_)) | |
| .WillOnce(Invoke([](RmadInterface::GetStateCallback callback) { | |
| GetStateReply reply; | |
| reply.set_error(RMAD_ERROR_TRANSITION_FAILED); | |
| std::move(callback).Run(reply, false); | |
| })); | |
| GetStateReply reply; | |
| ExecuteMethod(kTransitionPreviousStateMethod, &reply); | |
| EXPECT_EQ(RMAD_ERROR_TRANSITION_FAILED, reply.error()); | |
| EXPECT_EQ(RmadState::STATE_NOT_SET, reply.state().state_case()); | |
| } | |
| TEST_F(DBusServiceTest, AbortRma) { | |
| EXPECT_CALL(mock_rmad_service_, AbortRma(_)) | |
| .WillOnce(Invoke([](RmadInterface::AbortRmaCallback callback) { | |
| AbortRmaReply reply; | |
| reply.set_error(RMAD_ERROR_ABORT_FAILED); | |
| std::move(callback).Run(reply, false); | |
| })); | |
| AbortRmaReply reply; | |
| ExecuteMethod(kAbortRmaMethod, &reply); | |
| EXPECT_EQ(RMAD_ERROR_ABORT_FAILED, reply.error()); | |
| } | |
| TEST_F(DBusServiceTest, GetLog) { | |
| EXPECT_CALL(mock_rmad_service_, GetLog(_)) | |
| .WillOnce(Invoke([](RmadInterface::GetLogCallback callback) { | |
| GetLogReply reply; | |
| reply.set_error(RMAD_ERROR_OK); | |
| reply.set_log("RMA log"); | |
| std::move(callback).Run(reply, false); | |
| })); | |
| GetLogReply reply; | |
| ExecuteMethod(kGetLogMethod, &reply); | |
| EXPECT_EQ(RMAD_ERROR_OK, reply.error()); | |
| EXPECT_EQ("RMA log", reply.log()); | |
| } | |
| TEST_F(DBusServiceTest, SaveLog) { | |
| EXPECT_CALL(mock_rmad_service_, SaveLog(_, _)) | |
| .WillOnce(Invoke([](const std::string& diagnostics_log_text, | |
| RmadInterface::SaveLogCallback callback) { | |
| SaveLogReply reply; | |
| reply.set_error(RMAD_ERROR_OK); | |
| reply.set_save_path("/save/path"); | |
| std::move(callback).Run(reply, false); | |
| })); | |
| const std::string text = "A sample diagnostics log."; | |
| SaveLogReply reply; | |
| ExecuteMethod(kSaveLogMethod, text, &reply); | |
| EXPECT_EQ(RMAD_ERROR_OK, reply.error()); | |
| EXPECT_EQ("/save/path", reply.save_path()); | |
| } | |
| TEST_F(DBusServiceTest, ExtractExternalDiagnosticsApp) { | |
| EXPECT_CALL(mock_rmad_service_, ExtractExternalDiagnosticsApp(_)) | |
| .WillOnce(Invoke( | |
| [](RmadInterface::ExtractExternalDiagnosticsAppCallback callback) { | |
| ExtractExternalDiagnosticsAppReply reply; | |
| reply.set_error(RMAD_ERROR_OK); | |
| reply.set_diagnostics_app_swbn_path("diagnostics_app.swbn"); | |
| reply.set_diagnostics_app_crx_path("diagnostics_app.crx"); | |
| std::move(callback).Run(reply, false); | |
| })); | |
| ExtractExternalDiagnosticsAppReply reply; | |
| ExecuteMethod(kExtractExternalDiagnosticsAppMethod, &reply); | |
| EXPECT_EQ(RMAD_ERROR_OK, reply.error()); | |
| EXPECT_EQ("diagnostics_app.swbn", reply.diagnostics_app_swbn_path()); | |
| EXPECT_EQ("diagnostics_app.crx", reply.diagnostics_app_crx_path()); | |
| } | |
| TEST_F(DBusServiceTest, InstallExtractedDiagnosticsApp) { | |
| EXPECT_CALL(mock_rmad_service_, InstallExtractedDiagnosticsApp(_)) | |
| .WillOnce(Invoke( | |
| [](RmadInterface::InstallExtractedDiagnosticsAppCallback callback) { | |
| InstallExtractedDiagnosticsAppReply reply; | |
| reply.set_error(RMAD_ERROR_OK); | |
| std::move(callback).Run(reply, false); | |
| })); | |
| InstallExtractedDiagnosticsAppReply reply; | |
| ExecuteMethod(kInstallExtractedDiagnosticsAppMethod, &reply); | |
| EXPECT_EQ(RMAD_ERROR_OK, reply.error()); | |
| } | |
| TEST_F(DBusServiceTest, GetInstalledDiagnosticsApp) { | |
| EXPECT_CALL(mock_rmad_service_, GetInstalledDiagnosticsApp(_)) | |
| .WillOnce(Invoke( | |
| [](RmadInterface::GetInstalledDiagnosticsAppCallback callback) { | |
| GetInstalledDiagnosticsAppReply reply; | |
| reply.set_error(RMAD_ERROR_OK); | |
| reply.set_diagnostics_app_swbn_path("diagnostics_app.swbn"); | |
| reply.set_diagnostics_app_crx_path("diagnostics_app.crx"); | |
| std::move(callback).Run(reply, false); | |
| })); | |
| GetInstalledDiagnosticsAppReply reply; | |
| ExecuteMethod(kGetInstalledDiagnosticsAppMethod, &reply); | |
| EXPECT_EQ(RMAD_ERROR_OK, reply.error()); | |
| EXPECT_EQ("diagnostics_app.swbn", reply.diagnostics_app_swbn_path()); | |
| EXPECT_EQ("diagnostics_app.crx", reply.diagnostics_app_crx_path()); | |
| } | |
| TEST_F(DBusServiceTest, SignalError) { | |
| EXPECT_CALL(*GetMockExportedObject(), SendSignal(_)) | |
| .WillOnce(Invoke([](dbus::Signal* signal) { | |
| EXPECT_EQ(signal->GetInterface(), "org.chromium.Rmad"); | |
| EXPECT_EQ(signal->GetMember(), "Error"); | |
| EXPECT_EQ("i", signal->GetSignature()); | |
| dbus::MessageReader reader(signal); | |
| int error = 0; | |
| ASSERT_TRUE(brillo::dbus_utils::DBusType<int>::Read(&reader, &error)); | |
| EXPECT_EQ(RMAD_ERROR_RMA_NOT_REQUIRED, | |
| static_cast<RmadErrorCode>(error)); | |
| })); | |
| SignalError(RMAD_ERROR_RMA_NOT_REQUIRED); | |
| } | |
| TEST_F(DBusServiceTest, SignalHardwareVerification) { | |
| EXPECT_CALL(*GetMockExportedObject(), SendSignal(_)) | |
| .WillOnce(Invoke([](dbus::Signal* signal) { | |
| EXPECT_EQ(signal->GetInterface(), "org.chromium.Rmad"); | |
| EXPECT_EQ(signal->GetMember(), "HardwareVerificationResult"); | |
| EXPECT_EQ("(bs)", signal->GetSignature()); | |
| dbus::MessageReader reader(signal); | |
| std::tuple<bool, std::string> result; | |
| ASSERT_TRUE( | |
| (brillo::dbus_utils::DBusType<std::tuple<bool, std::string>>::Read( | |
| &reader, &result))); | |
| EXPECT_TRUE(std::get<0>(result)); | |
| EXPECT_EQ("test_error_string", std::get<1>(result)); | |
| })); | |
| HardwareVerificationResult result; | |
| result.set_is_compliant(true); | |
| result.set_error_str("test_error_string"); | |
| SignalHardwareVerification(result); | |
| } | |
| TEST_F(DBusServiceTest, SignalUpdateRoFirmwareStatus) { | |
| EXPECT_CALL(*GetMockExportedObject(), SendSignal(_)) | |
| .WillOnce(Invoke([](dbus::Signal* signal) { | |
| EXPECT_EQ(signal->GetInterface(), "org.chromium.Rmad"); | |
| EXPECT_EQ(signal->GetMember(), "UpdateRoFirmwareStatus"); | |
| EXPECT_EQ("i", signal->GetSignature()); | |
| dbus::MessageReader reader(signal); | |
| int status; | |
| ASSERT_TRUE(brillo::dbus_utils::DBusType<int>::Read(&reader, &status)); | |
| EXPECT_EQ(RMAD_UPDATE_RO_FIRMWARE_WAIT_USB, | |
| static_cast<UpdateRoFirmwareStatus>(status)); | |
| })); | |
| SignalUpdateRoFirmwareStatus(RMAD_UPDATE_RO_FIRMWARE_WAIT_USB); | |
| } | |
| TEST_F(DBusServiceTest, SignalCalibrationOverall) { | |
| EXPECT_CALL(*GetMockExportedObject(), SendSignal(_)) | |
| .WillOnce(Invoke([](dbus::Signal* signal) { | |
| EXPECT_EQ(signal->GetInterface(), "org.chromium.Rmad"); | |
| EXPECT_EQ(signal->GetMember(), "CalibrationOverall"); | |
| EXPECT_EQ("i", signal->GetSignature()); | |
| dbus::MessageReader reader(signal); | |
| int status; | |
| ASSERT_TRUE(brillo::dbus_utils::DBusType<int>::Read(&reader, &status)); | |
| EXPECT_EQ(RMAD_CALIBRATION_OVERALL_CURRENT_ROUND_COMPLETE, | |
| static_cast<CalibrationOverallStatus>(status)); | |
| })); | |
| SignalCalibrationOverall(RMAD_CALIBRATION_OVERALL_CURRENT_ROUND_COMPLETE); | |
| } | |
| TEST_F(DBusServiceTest, SignalCalibrationComponent) { | |
| EXPECT_CALL(*GetMockExportedObject(), SendSignal(_)) | |
| .WillOnce(Invoke([](dbus::Signal* signal) { | |
| EXPECT_EQ(signal->GetInterface(), "org.chromium.Rmad"); | |
| EXPECT_EQ(signal->GetMember(), "CalibrationProgress"); | |
| EXPECT_EQ("(iid)", signal->GetSignature()); | |
| dbus::MessageReader reader(signal); | |
| std::tuple<int, int, double> status; | |
| ASSERT_TRUE( | |
| (brillo::dbus_utils::DBusType<std::tuple<int, int, double>>::Read( | |
| &reader, &status))); | |
| EXPECT_EQ(RmadComponent::RMAD_COMPONENT_BASE_ACCELEROMETER, | |
| std::get<0>(status)); | |
| EXPECT_EQ(CalibrationComponentStatus::RMAD_CALIBRATION_IN_PROGRESS, | |
| std::get<1>(status)); | |
| EXPECT_DOUBLE_EQ(0.3, std::get<2>(status)); | |
| })); | |
| CalibrationComponentStatus component_status; | |
| component_status.set_component( | |
| RmadComponent::RMAD_COMPONENT_BASE_ACCELEROMETER); | |
| component_status.set_status( | |
| CalibrationComponentStatus::RMAD_CALIBRATION_IN_PROGRESS); | |
| component_status.set_progress(0.3); | |
| SignalCalibrationComponent(component_status); | |
| } | |
| TEST_F(DBusServiceTest, SignalProvision) { | |
| EXPECT_CALL(*GetMockExportedObject(), SendSignal(_)) | |
| .WillOnce(Invoke([](dbus::Signal* signal) { | |
| EXPECT_EQ(signal->GetInterface(), "org.chromium.Rmad"); | |
| EXPECT_EQ(signal->GetMember(), "ProvisioningProgress"); | |
| EXPECT_EQ("(idi)", signal->GetSignature()); | |
| dbus::MessageReader reader(signal); | |
| std::tuple<int, double, int> status; | |
| ASSERT_TRUE( | |
| (brillo::dbus_utils::DBusType<std::tuple<int, double, int>>::Read( | |
| &reader, &status))); | |
| EXPECT_EQ(ProvisionStatus::RMAD_PROVISION_STATUS_IN_PROGRESS, | |
| std::get<0>(status)); | |
| EXPECT_DOUBLE_EQ(0.5, std::get<1>(status)); | |
| EXPECT_EQ(ProvisionStatus::RMAD_PROVISION_ERROR_INTERNAL, | |
| std::get<2>(status)); | |
| })); | |
| ProvisionStatus status; | |
| status.set_status(ProvisionStatus::RMAD_PROVISION_STATUS_IN_PROGRESS); | |
| status.set_progress(0.5); | |
| status.set_error(ProvisionStatus::RMAD_PROVISION_ERROR_INTERNAL); | |
| SignalProvision(status); | |
| } | |
| TEST_F(DBusServiceTest, SignalFinalize) { | |
| EXPECT_CALL(*GetMockExportedObject(), SendSignal(_)) | |
| .WillOnce(Invoke([](dbus::Signal* signal) { | |
| EXPECT_EQ(signal->GetInterface(), "org.chromium.Rmad"); | |
| EXPECT_EQ(signal->GetMember(), "FinalizeProgress"); | |
| EXPECT_EQ("(idi)", signal->GetSignature()); | |
| dbus::MessageReader reader(signal); | |
| std::tuple<int, double, int> status; | |
| ASSERT_TRUE( | |
| (brillo::dbus_utils::DBusType<std::tuple<int, double, int>>::Read( | |
| &reader, &status))); | |
| EXPECT_EQ(FinalizeStatus::RMAD_FINALIZE_STATUS_IN_PROGRESS, | |
| std::get<0>(status)); | |
| EXPECT_DOUBLE_EQ(0.5, std::get<1>(status)); | |
| EXPECT_EQ(FinalizeStatus::RMAD_FINALIZE_ERROR_INTERNAL, | |
| std::get<2>(status)); | |
| })); | |
| FinalizeStatus status; | |
| status.set_status(FinalizeStatus::RMAD_FINALIZE_STATUS_IN_PROGRESS); | |
| status.set_progress(0.5); | |
| status.set_error(FinalizeStatus::RMAD_FINALIZE_ERROR_INTERNAL); | |
| SignalFinalize(status); | |
| } | |
| TEST_F(DBusServiceTest, SignalHardwareWriteProtection) { | |
| EXPECT_CALL(*GetMockExportedObject(), SendSignal(_)) | |
| .WillOnce(Invoke([](dbus::Signal* signal) { | |
| EXPECT_EQ(signal->GetInterface(), "org.chromium.Rmad"); | |
| EXPECT_EQ(signal->GetMember(), "HardwareWriteProtectionState"); | |
| EXPECT_EQ("b", signal->GetSignature()); | |
| dbus::MessageReader reader(signal); | |
| bool wp_status = false; | |
| ASSERT_TRUE( | |
| brillo::dbus_utils::DBusType<bool>::Read(&reader, &wp_status)); | |
| EXPECT_TRUE(wp_status); | |
| })); | |
| SignalHardwareWriteProtection(true); | |
| } | |
| TEST_F(DBusServiceTest, SignalPowerCableState) { | |
| EXPECT_CALL(*GetMockExportedObject(), SendSignal(_)) | |
| .WillOnce(Invoke([](dbus::Signal* signal) { | |
| EXPECT_EQ(signal->GetInterface(), "org.chromium.Rmad"); | |
| EXPECT_EQ(signal->GetMember(), "PowerCableState"); | |
| EXPECT_EQ("b", signal->GetSignature()); | |
| dbus::MessageReader reader(signal); | |
| bool power_cable_status = false; | |
| ASSERT_TRUE(brillo::dbus_utils::DBusType<bool>::Read( | |
| &reader, &power_cable_status)); | |
| EXPECT_TRUE(power_cable_status); | |
| })); | |
| SignalPowerCableState(true); | |
| } | |
| TEST_F(DBusServiceTest, SignalExternalDisk) { | |
| EXPECT_CALL(*GetMockExportedObject(), SendSignal(_)) | |
| .WillOnce(Invoke([](dbus::Signal* signal) { | |
| EXPECT_EQ(signal->GetInterface(), "org.chromium.Rmad"); | |
| EXPECT_EQ(signal->GetMember(), "ExternalDiskDetected"); | |
| EXPECT_EQ("b", signal->GetSignature()); | |
| dbus::MessageReader reader(signal); | |
| bool external_disk_status = false; | |
| ASSERT_TRUE(brillo::dbus_utils::DBusType<bool>::Read( | |
| &reader, &external_disk_status)); | |
| EXPECT_TRUE(external_disk_status); | |
| })); | |
| SignalExternalDisk(true); | |
| } | |
| } // namespace rmad |