// 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 <memory>
#include <string>
#include <utility>
#include <vector>

#include <base/bind.h>
#include <base/files/file_util.h>
#include <base/files/scoped_temp_dir.h>
#include <base/memory/scoped_refptr.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>

#include "rmad/metrics/mock_metrics_utils.h"
#include "rmad/rmad_interface_impl.h"
#include "rmad/state_handler/mock_state_handler.h"
#include "rmad/state_handler/state_handler_manager.h"
#include "rmad/system/mock_power_manager_client.h"
#include "rmad/system/mock_runtime_probe_client.h"
#include "rmad/system/mock_shill_client.h"
#include "rmad/system/mock_tpm_manager_client.h"
#include "rmad/utils/json_store.h"
#include "rmad/utils/mock_cmd_utils.h"

using testing::_;
using testing::Assign;
using testing::DoAll;
using testing::NiceMock;
using testing::Return;
using testing::ReturnRef;
using testing::SetArgPointee;

namespace rmad {

constexpr char kJsonStoreFileName[] = "json_store_file";
constexpr char kCurrentStateSetJson[] = R"({"state_history": [ 1 ]})";
constexpr char kCurrentStateNotSetJson[] = "{}";
constexpr char kCurrentStateInvalidStateJson[] = R"("state_history": [0])";
constexpr char kCurrentStateWithRepeatableHistoryJson[] =
    R"({"state_history": [ 1, 2 ]})";
constexpr char kCurrentStateWithUnrepeatableHistoryJson[] =
    R"({"state_history": [ 1, 2, 3 ]})";
constexpr char kCurrentStateWithUnsupportedStateJson[] =
    R"({"state_history": [ 1, 2, 4 ]})";
constexpr char kInitializeCurrentStateFailJson[] =
    R"({"state_history": [ 1 ]})";
constexpr char kInitializeNextStateFailJson[] =
    R"({"state_history": [ 1, 2 ]})";
constexpr char kInitializePreviousStateFailJson[] =
    R"({"state_history": [ 1, 2 ]})";
constexpr char kInvalidJson[] = R"(alfkjklsfsgdkjnbknd^^)";

class RmadInterfaceImplTest : public testing::Test {
 public:
  RmadInterfaceImplTest() : quit_daemon_requested_(false) {
    welcome_proto_.set_allocated_welcome(new WelcomeState());
    components_repair_proto_.set_allocated_components_repair(
        new ComponentsRepairState());
    device_destination_proto_.set_allocated_device_destination(
        new DeviceDestinationState());
  }

  base::FilePath CreateInputFile(std::string filename,
                                 const char* str,
                                 int size) {
    base::FilePath file_path = temp_dir_.GetPath().AppendASCII(filename);
    base::WriteFile(file_path, str, size);
    return file_path;
  }

  scoped_refptr<BaseStateHandler> CreateMockHandler(
      scoped_refptr<JsonStore> json_store,
      const RmadState& state,
      bool is_repeatable,
      RmadErrorCode initialize_error,
      RmadState::StateCase next_state) {
    auto mock_handler =
        base::MakeRefCounted<NiceMock<MockStateHandler>>(json_store);
    RmadState::StateCase state_case = state.state_case();
    ON_CALL(*mock_handler, GetStateCase()).WillByDefault(Return(state_case));
    ON_CALL(*mock_handler, GetState(_)).WillByDefault(ReturnRef(state));
    ON_CALL(*mock_handler, IsRepeatable()).WillByDefault(Return(is_repeatable));
    ON_CALL(*mock_handler, InitializeState())
        .WillByDefault(Return(initialize_error));
    ON_CALL(*mock_handler, GetNextStateCase(_))
        .WillByDefault(Return(BaseStateHandler::GetNextStateCaseReply{
            .error = RMAD_ERROR_OK, .state_case = next_state}));
    return mock_handler;
  }

  std::unique_ptr<StateHandlerManager> CreateStateHandlerManagerWithHandlers(
      scoped_refptr<JsonStore> json_store,
      std::vector<scoped_refptr<BaseStateHandler>> mock_handlers) {
    auto state_handler_manager =
        std::make_unique<StateHandlerManager>(json_store);
    // TODO(gavindodd): Work out how to create RmadState objects and have them
    // scoped to the test.
    for (auto mock_handler : mock_handlers) {
      state_handler_manager->RegisterStateHandler(mock_handler);
    }
    return state_handler_manager;
  }

  std::unique_ptr<StateHandlerManager> CreateStateHandlerManager(
      scoped_refptr<JsonStore> json_store) {
    // TODO(gavindodd): Work out how to create RmadState objects and have them
    // scoped to the test.
    std::vector<scoped_refptr<BaseStateHandler>> mock_handlers;
    mock_handlers.push_back(CreateMockHandler(json_store, welcome_proto_, true,
                                              RMAD_ERROR_OK,
                                              RmadState::kComponentsRepair));
    mock_handlers.push_back(
        CreateMockHandler(json_store, components_repair_proto_, true,
                          RMAD_ERROR_OK, RmadState::kDeviceDestination));
    mock_handlers.push_back(
        CreateMockHandler(json_store, device_destination_proto_, false,
                          RMAD_ERROR_OK, RmadState::kWpDisableMethod));
    return CreateStateHandlerManagerWithHandlers(json_store, mock_handlers);
  }

  std::unique_ptr<StateHandlerManager> CreateStateHandlerManagerMissingHandler(
      scoped_refptr<JsonStore> json_store) {
    // TODO(gavindodd): Work out how to create RmadState objects and have them
    // scoped to the test.
    std::vector<scoped_refptr<BaseStateHandler>> mock_handlers;
    mock_handlers.push_back(CreateMockHandler(json_store, welcome_proto_, true,
                                              RMAD_ERROR_OK,
                                              RmadState::kComponentsRepair));
    return CreateStateHandlerManagerWithHandlers(json_store, mock_handlers);
  }

  std::unique_ptr<StateHandlerManager>
  CreateStateHandlerManagerInitializeStateFail(
      scoped_refptr<JsonStore> json_store) {
    std::vector<scoped_refptr<BaseStateHandler>> mock_handlers;
    mock_handlers.push_back(CreateMockHandler(json_store, welcome_proto_, true,
                                              RMAD_ERROR_MISSING_COMPONENT,
                                              RmadState::kComponentsRepair));
    mock_handlers.push_back(
        CreateMockHandler(json_store, components_repair_proto_, true,
                          RMAD_ERROR_OK, RmadState::kDeviceDestination));
    mock_handlers.push_back(CreateMockHandler(
        json_store, device_destination_proto_, false,
        RMAD_ERROR_DEVICE_INFO_INVALID, RmadState::kWpDisableMethod));
    return CreateStateHandlerManagerWithHandlers(json_store, mock_handlers);
  }

  std::unique_ptr<RuntimeProbeClient> CreateRuntimeProbeClient(
      bool has_cellular) {
    auto mock_runtime_probe_client =
        std::make_unique<NiceMock<MockRuntimeProbeClient>>();
    ComponentsWithIdentifier components;
    if (has_cellular) {
      components.push_back(std::make_pair(RMAD_COMPONENT_CELLULAR, ""));
    }
    ON_CALL(*mock_runtime_probe_client, ProbeCategories(_, _))
        .WillByDefault(DoAll(SetArgPointee<1>(components), Return(true)));
    return mock_runtime_probe_client;
  }

  std::unique_ptr<ShillClient> CreateShillClient(bool* cellular_disabled) {
    auto mock_shill_client = std::make_unique<NiceMock<MockShillClient>>();
    if (cellular_disabled) {
      ON_CALL(*mock_shill_client, DisableCellular())
          .WillByDefault(DoAll(Assign(cellular_disabled, true), Return(true)));
    } else {
      ON_CALL(*mock_shill_client, DisableCellular())
          .WillByDefault(Return(true));
    }
    return mock_shill_client;
  }

  std::unique_ptr<TpmManagerClient> CreateTpmManagerClient(
      RoVerificationStatus ro_verification_status) {
    auto mock_tpm_manager_client =
        std::make_unique<NiceMock<MockTpmManagerClient>>();
    ON_CALL(*mock_tpm_manager_client, GetRoVerificationStatus(_))
        .WillByDefault(
            DoAll(SetArgPointee<0>(ro_verification_status), Return(true)));
    return mock_tpm_manager_client;
  }

  std::unique_ptr<PowerManagerClient> CreatePowerManagerClient() {
    return std::make_unique<NiceMock<MockPowerManagerClient>>();
  }

  std::unique_ptr<CmdUtils> CreateCmdUtils() {
    auto mock_cmd_utils = std::make_unique<NiceMock<MockCmdUtils>>();
    ON_CALL(*mock_cmd_utils,
            GetOutput(std::vector<std::string>(
                          {"/usr/sbin/croslog", "--identifier=rmad"}),
                      _))
        .WillByDefault(DoAll(SetArgPointee<1>("fake_log"), Return(true)));
    ON_CALL(*mock_cmd_utils,
            GetOutput(std::vector<std::string>(
                          {"/sbin/initctl", "status", "system-services"}),
                      _))
        .WillByDefault(DoAll(SetArgPointee<1>("running"), Return(true)));
    return mock_cmd_utils;
  }

  std::unique_ptr<MetricsUtils> CreateMetricsUtils(bool success) {
    auto mock_metrics_utils = std::make_unique<NiceMock<MockMetricsUtils>>();
    ON_CALL(*mock_metrics_utils, Record(_, _)).WillByDefault(Return(success));
    return mock_metrics_utils;
  }

  void RequestQuitDaemon() { quit_daemon_requested_ = true; }

 protected:
  void SetUp() override { ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); }

  RmadState welcome_proto_;
  RmadState components_repair_proto_;
  RmadState device_destination_proto_;
  base::ScopedTempDir temp_dir_;

  bool quit_daemon_requested_;
};

TEST_F(RmadInterfaceImplTest, GetCurrentState_Set_HasCellular) {
  base::FilePath json_store_file_path =
      CreateInputFile(kJsonStoreFileName, kCurrentStateSetJson,
                      std::size(kCurrentStateSetJson) - 1);
  auto json_store = base::MakeRefCounted<JsonStore>(json_store_file_path);
  bool cellular_disabled = false;
  RmadInterfaceImpl rmad_interface(
      json_store, CreateStateHandlerManager(json_store),
      CreateRuntimeProbeClient(true), CreateShillClient(&cellular_disabled),
      CreateTpmManagerClient(RoVerificationStatus::NOT_TRIGGERED),
      CreatePowerManagerClient(), CreateCmdUtils(), CreateMetricsUtils(true));
  EXPECT_TRUE(rmad_interface.SetUp());

  EXPECT_TRUE(cellular_disabled);

  auto callback = [](const GetStateReply& reply) {
    EXPECT_EQ(RMAD_ERROR_OK, reply.error());
    EXPECT_EQ(RmadState::kWelcome, reply.state().state_case());
    EXPECT_EQ(false, reply.can_go_back());
    EXPECT_EQ(true, reply.can_abort());
  };
  rmad_interface.GetCurrentState(base::BindOnce(callback));
}

TEST_F(RmadInterfaceImplTest, GetCurrentState_Set_NoCellular) {
  base::FilePath json_store_file_path =
      CreateInputFile(kJsonStoreFileName, kCurrentStateSetJson,
                      std::size(kCurrentStateSetJson) - 1);
  auto json_store = base::MakeRefCounted<JsonStore>(json_store_file_path);
  bool cellular_disabled = false;
  RmadInterfaceImpl rmad_interface(
      json_store, CreateStateHandlerManager(json_store),
      CreateRuntimeProbeClient(false), CreateShillClient(&cellular_disabled),
      CreateTpmManagerClient(RoVerificationStatus::NOT_TRIGGERED),
      CreatePowerManagerClient(), CreateCmdUtils(), CreateMetricsUtils(true));
  EXPECT_TRUE(rmad_interface.SetUp());

  EXPECT_FALSE(cellular_disabled);

  auto callback = [](const GetStateReply& reply) {
    EXPECT_EQ(RMAD_ERROR_OK, reply.error());
    EXPECT_EQ(RmadState::kWelcome, reply.state().state_case());
    EXPECT_EQ(false, reply.can_go_back());
    EXPECT_EQ(true, reply.can_abort());
  };
  rmad_interface.GetCurrentState(base::BindOnce(callback));
}

TEST_F(RmadInterfaceImplTest,
       GetCurrentState_NotInRma_RoVerificationNotTriggered) {
  base::FilePath json_store_file_path =
      temp_dir_.GetPath().AppendASCII("missing.json");
  auto json_store = base::MakeRefCounted<JsonStore>(json_store_file_path);
  bool cellular_disabled = false;
  RmadInterfaceImpl rmad_interface(
      json_store, CreateStateHandlerManager(json_store),
      CreateRuntimeProbeClient(false), CreateShillClient(&cellular_disabled),
      CreateTpmManagerClient(RoVerificationStatus::NOT_TRIGGERED),
      CreatePowerManagerClient(), CreateCmdUtils(), CreateMetricsUtils(true));
  EXPECT_TRUE(rmad_interface.SetUp());

  EXPECT_FALSE(cellular_disabled);

  auto callback = [](const GetStateReply& reply) {
    EXPECT_EQ(RMAD_ERROR_RMA_NOT_REQUIRED, reply.error());
    EXPECT_EQ(RmadState::STATE_NOT_SET, reply.state().state_case());
  };
  rmad_interface.RegisterRequestQuitDaemonCallback(base::BindRepeating(
      &RmadInterfaceImplTest::RequestQuitDaemon, base::Unretained(this)));
  rmad_interface.GetCurrentState(base::BindOnce(callback));

  // Check that we request to quit the daemon.
  EXPECT_TRUE(quit_daemon_requested_);
}

TEST_F(RmadInterfaceImplTest, GetCurrentState_NotInRma_RoVerificationPass) {
  base::FilePath json_store_file_path =
      temp_dir_.GetPath().AppendASCII("missing.json");
  auto json_store = base::MakeRefCounted<JsonStore>(json_store_file_path);
  RmadInterfaceImpl rmad_interface(
      json_store, CreateStateHandlerManager(json_store),
      CreateRuntimeProbeClient(false), CreateShillClient(nullptr),
      CreateTpmManagerClient(RoVerificationStatus::PASS),
      CreatePowerManagerClient(), CreateCmdUtils(), CreateMetricsUtils(true));
  EXPECT_TRUE(rmad_interface.SetUp());

  auto callback = [](const GetStateReply& reply) {
    EXPECT_EQ(RMAD_ERROR_OK, reply.error());
    EXPECT_EQ(RmadState::kWelcome, reply.state().state_case());
    EXPECT_EQ(false, reply.can_go_back());
    EXPECT_EQ(true, reply.can_abort());
  };
  rmad_interface.GetCurrentState(base::BindOnce(callback));
}

TEST_F(RmadInterfaceImplTest,
       GetCurrentState_NotInRma_RoVerificationUnsupportedTriggered) {
  base::FilePath json_store_file_path =
      temp_dir_.GetPath().AppendASCII("missing.json");
  auto json_store = base::MakeRefCounted<JsonStore>(json_store_file_path);
  RmadInterfaceImpl rmad_interface(
      json_store, CreateStateHandlerManager(json_store),
      CreateRuntimeProbeClient(false), CreateShillClient(nullptr),
      CreateTpmManagerClient(RoVerificationStatus::UNSUPPORTED_TRIGGERED),
      CreatePowerManagerClient(), CreateCmdUtils(), CreateMetricsUtils(true));
  EXPECT_TRUE(rmad_interface.SetUp());

  auto callback = [](const GetStateReply& reply) {
    EXPECT_EQ(RMAD_ERROR_OK, reply.error());
    EXPECT_EQ(RmadState::kWelcome, reply.state().state_case());
    EXPECT_EQ(false, reply.can_go_back());
    EXPECT_EQ(true, reply.can_abort());
  };
  rmad_interface.GetCurrentState(base::BindOnce(callback));
}

TEST_F(RmadInterfaceImplTest, GetCurrentState_CorruptedFile) {
  base::FilePath json_store_file_path =
      CreateInputFile(kJsonStoreFileName, "", 0);
  // Make the file read-only.
  base::SetPosixFilePermissions(json_store_file_path, 0444);
  auto json_store = base::MakeRefCounted<JsonStore>(json_store_file_path);
  RmadInterfaceImpl rmad_interface(
      json_store, CreateStateHandlerManager(json_store),
      CreateRuntimeProbeClient(false), CreateShillClient(nullptr),
      CreateTpmManagerClient(RoVerificationStatus::NOT_TRIGGERED),
      CreatePowerManagerClient(), CreateCmdUtils(), CreateMetricsUtils(true));
  EXPECT_FALSE(rmad_interface.SetUp());
}

TEST_F(RmadInterfaceImplTest, GetCurrentState_EmptyFile) {
  base::FilePath json_store_file_path =
      CreateInputFile(kJsonStoreFileName, "", 0);
  auto json_store = base::MakeRefCounted<JsonStore>(json_store_file_path);
  RmadInterfaceImpl rmad_interface(
      json_store, CreateStateHandlerManager(json_store),
      CreateRuntimeProbeClient(false), CreateShillClient(nullptr),
      CreateTpmManagerClient(RoVerificationStatus::NOT_TRIGGERED),
      CreatePowerManagerClient(), CreateCmdUtils(), CreateMetricsUtils(true));
  EXPECT_TRUE(rmad_interface.SetUp());

  auto callback = [](const GetStateReply& reply) {
    EXPECT_EQ(RMAD_ERROR_OK, reply.error());
    EXPECT_EQ(RmadState::kWelcome, reply.state().state_case());
    EXPECT_EQ(false, reply.can_go_back());
    EXPECT_EQ(true, reply.can_abort());
  };
  rmad_interface.GetCurrentState(base::BindOnce(callback));
}

TEST_F(RmadInterfaceImplTest, GetCurrentState_NotSet) {
  base::FilePath json_store_file_path =
      CreateInputFile(kJsonStoreFileName, kCurrentStateNotSetJson,
                      std::size(kCurrentStateNotSetJson) - 1);
  auto json_store = base::MakeRefCounted<JsonStore>(json_store_file_path);
  RmadInterfaceImpl rmad_interface(
      json_store, CreateStateHandlerManager(json_store),
      CreateRuntimeProbeClient(false), CreateShillClient(nullptr),
      CreateTpmManagerClient(RoVerificationStatus::NOT_TRIGGERED),
      CreatePowerManagerClient(), CreateCmdUtils(), CreateMetricsUtils(true));
  EXPECT_TRUE(rmad_interface.SetUp());

  auto callback = [](const GetStateReply& reply) {
    EXPECT_EQ(RMAD_ERROR_OK, reply.error());
    EXPECT_EQ(RmadState::kWelcome, reply.state().state_case());
    EXPECT_EQ(false, reply.can_go_back());
    EXPECT_EQ(true, reply.can_abort());
  };
  rmad_interface.GetCurrentState(base::BindOnce(callback));
}

TEST_F(RmadInterfaceImplTest, GetCurrentState_WithHistory) {
  base::FilePath json_store_file_path = CreateInputFile(
      kJsonStoreFileName, kCurrentStateWithRepeatableHistoryJson,
      std::size(kCurrentStateWithRepeatableHistoryJson) - 1);
  auto json_store = base::MakeRefCounted<JsonStore>(json_store_file_path);
  RmadInterfaceImpl rmad_interface(
      json_store, CreateStateHandlerManager(json_store),
      CreateRuntimeProbeClient(false), CreateShillClient(nullptr),
      CreateTpmManagerClient(RoVerificationStatus::NOT_TRIGGERED),
      CreatePowerManagerClient(), CreateCmdUtils(), CreateMetricsUtils(true));
  EXPECT_TRUE(rmad_interface.SetUp());

  auto callback = [](const GetStateReply& reply) {
    EXPECT_EQ(RMAD_ERROR_OK, reply.error());
    EXPECT_EQ(RmadState::kComponentsRepair, reply.state().state_case());
    EXPECT_EQ(true, reply.can_go_back());
    EXPECT_EQ(true, reply.can_abort());
  };
  rmad_interface.GetCurrentState(base::BindOnce(callback));
}

TEST_F(RmadInterfaceImplTest, GetCurrentState_WithUnsupportedState) {
  base::FilePath json_store_file_path =
      CreateInputFile(kJsonStoreFileName, kCurrentStateWithUnsupportedStateJson,
                      std::size(kCurrentStateWithUnsupportedStateJson) - 1);
  auto json_store = base::MakeRefCounted<JsonStore>(json_store_file_path);
  RmadInterfaceImpl rmad_interface(
      json_store, CreateStateHandlerManager(json_store),
      CreateRuntimeProbeClient(false), CreateShillClient(nullptr),
      CreateTpmManagerClient(RoVerificationStatus::NOT_TRIGGERED),
      CreatePowerManagerClient(), CreateCmdUtils(), CreateMetricsUtils(true));
  EXPECT_TRUE(rmad_interface.SetUp());

  auto callback = [](const GetStateReply& reply) {
    EXPECT_EQ(RMAD_ERROR_OK, reply.error());
    EXPECT_EQ(RmadState::kComponentsRepair, reply.state().state_case());
    EXPECT_EQ(true, reply.can_go_back());
    EXPECT_EQ(true, reply.can_abort());
  };
  // TODO(gavindodd): Use mock log to check for expected error.
  rmad_interface.GetCurrentState(base::BindOnce(callback));
}

TEST_F(RmadInterfaceImplTest, GetCurrentState_InvalidState) {
  base::FilePath json_store_file_path =
      CreateInputFile(kJsonStoreFileName, kCurrentStateInvalidStateJson,
                      std::size(kCurrentStateInvalidStateJson) - 1);
  auto json_store = base::MakeRefCounted<JsonStore>(json_store_file_path);
  RmadInterfaceImpl rmad_interface(
      json_store, CreateStateHandlerManager(json_store),
      CreateRuntimeProbeClient(false), CreateShillClient(nullptr),
      CreateTpmManagerClient(RoVerificationStatus::NOT_TRIGGERED),
      CreatePowerManagerClient(), CreateCmdUtils(), CreateMetricsUtils(true));
  EXPECT_TRUE(rmad_interface.SetUp());

  auto callback = [](const GetStateReply& reply) {
    EXPECT_EQ(RMAD_ERROR_OK, reply.error());
    EXPECT_EQ(RmadState::kWelcome, reply.state().state_case());
    EXPECT_EQ(false, reply.can_go_back());
    EXPECT_EQ(true, reply.can_abort());
  };
  rmad_interface.GetCurrentState(base::BindOnce(callback));
}

TEST_F(RmadInterfaceImplTest, GetCurrentState_InvalidJson) {
  base::FilePath json_store_file_path = CreateInputFile(
      kJsonStoreFileName, kInvalidJson, std::size(kInvalidJson) - 1);
  auto json_store = base::MakeRefCounted<JsonStore>(json_store_file_path);
  RmadInterfaceImpl rmad_interface(
      json_store, CreateStateHandlerManager(json_store),
      CreateRuntimeProbeClient(false), CreateShillClient(nullptr),
      CreateTpmManagerClient(RoVerificationStatus::NOT_TRIGGERED),
      CreatePowerManagerClient(), CreateCmdUtils(), CreateMetricsUtils(true));
  EXPECT_TRUE(rmad_interface.SetUp());

  auto callback = [](const GetStateReply& reply) {
    EXPECT_EQ(RMAD_ERROR_OK, reply.error());
    EXPECT_EQ(RmadState::kWelcome, reply.state().state_case());
    EXPECT_EQ(false, reply.can_go_back());
    EXPECT_EQ(true, reply.can_abort());
  };
  rmad_interface.GetCurrentState(base::BindOnce(callback));
}

TEST_F(RmadInterfaceImplTest, GetCurrentState_InitializeStateFail) {
  base::FilePath json_store_file_path =
      CreateInputFile(kJsonStoreFileName, kInitializeCurrentStateFailJson,
                      std::size(kInitializeCurrentStateFailJson) - 1);
  auto json_store = base::MakeRefCounted<JsonStore>(json_store_file_path);
  RmadInterfaceImpl rmad_interface(
      json_store, CreateStateHandlerManagerInitializeStateFail(json_store),
      CreateRuntimeProbeClient(false), CreateShillClient(nullptr),
      CreateTpmManagerClient(RoVerificationStatus::NOT_TRIGGERED),
      CreatePowerManagerClient(), CreateCmdUtils(), CreateMetricsUtils(true));
  EXPECT_TRUE(rmad_interface.SetUp());

  auto callback = [](const GetStateReply& reply) {
    EXPECT_EQ(RMAD_ERROR_MISSING_COMPONENT, reply.error());
    EXPECT_EQ(RmadState::STATE_NOT_SET, reply.state().state_case());
  };
  rmad_interface.GetCurrentState(base::BindOnce(callback));
}

TEST_F(RmadInterfaceImplTest, TransitionNextState) {
  base::FilePath json_store_file_path =
      CreateInputFile(kJsonStoreFileName, kCurrentStateSetJson,
                      std::size(kCurrentStateSetJson) - 1);
  auto json_store = base::MakeRefCounted<JsonStore>(json_store_file_path);
  RmadInterfaceImpl rmad_interface(
      json_store, CreateStateHandlerManager(json_store),
      CreateRuntimeProbeClient(false), CreateShillClient(nullptr),
      CreateTpmManagerClient(RoVerificationStatus::NOT_TRIGGERED),
      CreatePowerManagerClient(), CreateCmdUtils(), CreateMetricsUtils(true));
  EXPECT_TRUE(rmad_interface.SetUp());
  EXPECT_EQ(true, rmad_interface.CanAbort());

  TransitionNextStateRequest request;
  auto callback1 = [](const GetStateReply& reply) {
    EXPECT_EQ(RMAD_ERROR_OK, reply.error());
    EXPECT_EQ(RmadState::kComponentsRepair, reply.state().state_case());
    EXPECT_EQ(true, reply.can_go_back());
    EXPECT_EQ(true, reply.can_abort());
  };
  rmad_interface.TransitionNextState(request, base::BindOnce(callback1));
  EXPECT_EQ(true, rmad_interface.CanAbort());

  auto callback2 = [](const GetStateReply& reply) {
    EXPECT_EQ(RMAD_ERROR_OK, reply.error());
    EXPECT_EQ(RmadState::kDeviceDestination, reply.state().state_case());
    EXPECT_EQ(false, reply.can_go_back());
    EXPECT_EQ(false, reply.can_abort());
  };
  rmad_interface.TransitionNextState(request, base::BindOnce(callback2));
  EXPECT_EQ(false, rmad_interface.CanAbort());
}

TEST_F(RmadInterfaceImplTest, TransitionNextState_MissingHandler) {
  base::FilePath json_store_file_path =
      CreateInputFile(kJsonStoreFileName, kCurrentStateSetJson,
                      std::size(kCurrentStateSetJson) - 1);
  auto json_store = base::MakeRefCounted<JsonStore>(json_store_file_path);
  RmadInterfaceImpl rmad_interface(
      json_store, CreateStateHandlerManagerMissingHandler(json_store),
      CreateRuntimeProbeClient(false), CreateShillClient(nullptr),
      CreateTpmManagerClient(RoVerificationStatus::NOT_TRIGGERED),
      CreatePowerManagerClient(), CreateCmdUtils(), CreateMetricsUtils(true));
  EXPECT_TRUE(rmad_interface.SetUp());

  TransitionNextStateRequest request;
  auto callback = [](const GetStateReply& reply) {
    FAIL() << "Unexpected call to callback";
  };
  EXPECT_DEATH(
      rmad_interface.TransitionNextState(request, base::BindOnce(callback)),
      "No registered state handler");
}

TEST_F(RmadInterfaceImplTest, TransitionNextState_InitializeNextStateFail) {
  base::FilePath json_store_file_path =
      CreateInputFile(kJsonStoreFileName, kInitializeNextStateFailJson,
                      std::size(kInitializeNextStateFailJson) - 1);
  auto json_store = base::MakeRefCounted<JsonStore>(json_store_file_path);
  RmadInterfaceImpl rmad_interface(
      json_store, CreateStateHandlerManagerInitializeStateFail(json_store),
      CreateRuntimeProbeClient(false), CreateShillClient(nullptr),
      CreateTpmManagerClient(RoVerificationStatus::NOT_TRIGGERED),
      CreatePowerManagerClient(), CreateCmdUtils(), CreateMetricsUtils(true));
  EXPECT_TRUE(rmad_interface.SetUp());

  TransitionNextStateRequest request;
  auto callback = [](const GetStateReply& reply) {
    EXPECT_EQ(RMAD_ERROR_DEVICE_INFO_INVALID, reply.error());
    EXPECT_EQ(RmadState::kComponentsRepair, reply.state().state_case());
    EXPECT_EQ(true, reply.can_go_back());
    EXPECT_EQ(true, reply.can_abort());
  };
  rmad_interface.TransitionNextState(request, base::BindOnce(callback));
}

TEST_F(RmadInterfaceImplTest, TransitionPreviousState) {
  base::FilePath json_store_file_path = CreateInputFile(
      kJsonStoreFileName, kCurrentStateWithRepeatableHistoryJson,
      std::size(kCurrentStateWithRepeatableHistoryJson) - 1);
  auto json_store = base::MakeRefCounted<JsonStore>(json_store_file_path);
  RmadInterfaceImpl rmad_interface(
      json_store, CreateStateHandlerManager(json_store),
      CreateRuntimeProbeClient(false), CreateShillClient(nullptr),
      CreateTpmManagerClient(RoVerificationStatus::NOT_TRIGGERED),
      CreatePowerManagerClient(), CreateCmdUtils(), CreateMetricsUtils(true));
  EXPECT_TRUE(rmad_interface.SetUp());

  auto callback = [](const GetStateReply& reply) {
    EXPECT_EQ(RMAD_ERROR_OK, reply.error());
    EXPECT_EQ(RmadState::kWelcome, reply.state().state_case());
    EXPECT_EQ(false, reply.can_go_back());
    EXPECT_EQ(true, reply.can_abort());
  };
  rmad_interface.TransitionPreviousState(base::BindOnce(callback));
}

TEST_F(RmadInterfaceImplTest, TransitionPreviousState_NoHistory) {
  base::FilePath json_store_file_path =
      CreateInputFile(kJsonStoreFileName, kCurrentStateSetJson,
                      std::size(kCurrentStateSetJson) - 1);
  auto json_store = base::MakeRefCounted<JsonStore>(json_store_file_path);
  RmadInterfaceImpl rmad_interface(
      json_store, CreateStateHandlerManager(json_store),
      CreateRuntimeProbeClient(false), CreateShillClient(nullptr),
      CreateTpmManagerClient(RoVerificationStatus::NOT_TRIGGERED),
      CreatePowerManagerClient(), CreateCmdUtils(), CreateMetricsUtils(true));
  EXPECT_TRUE(rmad_interface.SetUp());

  auto callback = [](const GetStateReply& reply) {
    EXPECT_EQ(RMAD_ERROR_TRANSITION_FAILED, reply.error());
    EXPECT_EQ(RmadState::kWelcome, reply.state().state_case());
    EXPECT_EQ(false, reply.can_go_back());
    EXPECT_EQ(true, reply.can_abort());
  };
  rmad_interface.TransitionPreviousState(base::BindOnce(callback));
}

TEST_F(RmadInterfaceImplTest, TransitionPreviousState_MissingHandler) {
  base::FilePath json_store_file_path = CreateInputFile(
      kJsonStoreFileName, kCurrentStateWithRepeatableHistoryJson,
      std::size(kCurrentStateWithRepeatableHistoryJson) - 1);
  auto json_store = base::MakeRefCounted<JsonStore>(json_store_file_path);
  RmadInterfaceImpl rmad_interface(
      json_store, CreateStateHandlerManagerMissingHandler(json_store),
      CreateRuntimeProbeClient(false), CreateShillClient(nullptr),
      CreateTpmManagerClient(RoVerificationStatus::NOT_TRIGGERED),
      CreatePowerManagerClient(), CreateCmdUtils(), CreateMetricsUtils(true));
  EXPECT_TRUE(rmad_interface.SetUp());

  auto callback = [](const GetStateReply& reply) {
    EXPECT_EQ(RMAD_ERROR_TRANSITION_FAILED, reply.error());
    EXPECT_EQ(RmadState::kWelcome, reply.state().state_case());
    EXPECT_EQ(false, reply.can_go_back());
    EXPECT_EQ(true, reply.can_abort());
  };
  rmad_interface.TransitionPreviousState(base::BindOnce(callback));
}

TEST_F(RmadInterfaceImplTest,
       TransitionPreviousState_InitializePreviousStateFail) {
  base::FilePath json_store_file_path =
      CreateInputFile(kJsonStoreFileName, kInitializePreviousStateFailJson,
                      std::size(kInitializePreviousStateFailJson) - 1);
  auto json_store = base::MakeRefCounted<JsonStore>(json_store_file_path);
  RmadInterfaceImpl rmad_interface(
      json_store, CreateStateHandlerManagerInitializeStateFail(json_store),
      CreateRuntimeProbeClient(false), CreateShillClient(nullptr),
      CreateTpmManagerClient(RoVerificationStatus::NOT_TRIGGERED),
      CreatePowerManagerClient(), CreateCmdUtils(), CreateMetricsUtils(true));
  EXPECT_TRUE(rmad_interface.SetUp());

  auto callback = [](const GetStateReply& reply) {
    EXPECT_EQ(RMAD_ERROR_MISSING_COMPONENT, reply.error());
    EXPECT_EQ(RmadState::kComponentsRepair, reply.state().state_case());
    EXPECT_EQ(true, reply.can_go_back());
    EXPECT_EQ(true, reply.can_abort());
  };
  rmad_interface.TransitionPreviousState(base::BindOnce(callback));
}

TEST_F(RmadInterfaceImplTest, AbortRma) {
  base::FilePath json_store_file_path = CreateInputFile(
      kJsonStoreFileName, kCurrentStateWithRepeatableHistoryJson,
      std::size(kCurrentStateWithRepeatableHistoryJson) - 1);
  auto json_store = base::MakeRefCounted<JsonStore>(json_store_file_path);
  RmadInterfaceImpl rmad_interface(
      json_store, CreateStateHandlerManager(json_store),
      CreateRuntimeProbeClient(false), CreateShillClient(nullptr),
      CreateTpmManagerClient(RoVerificationStatus::NOT_TRIGGERED),
      CreatePowerManagerClient(), CreateCmdUtils(), CreateMetricsUtils(true));
  EXPECT_TRUE(rmad_interface.SetUp());

  // Check that the state file exists now.
  EXPECT_TRUE(base::PathExists(json_store_file_path));

  auto callback = [](const AbortRmaReply& reply) {
    EXPECT_EQ(RMAD_ERROR_RMA_NOT_REQUIRED, reply.error());
  };
  rmad_interface.RegisterRequestQuitDaemonCallback(base::BindRepeating(
      &RmadInterfaceImplTest::RequestQuitDaemon, base::Unretained(this)));
  rmad_interface.AbortRma(base::BindOnce(callback));

  // Check the the state file is cleared.
  EXPECT_FALSE(base::PathExists(json_store_file_path));

  // Check that we request to quit the daemon.
  EXPECT_TRUE(quit_daemon_requested_);
}

TEST_F(RmadInterfaceImplTest, AbortRma_NoHistory) {
  base::FilePath json_store_file_path =
      CreateInputFile(kJsonStoreFileName, kCurrentStateSetJson,
                      std::size(kCurrentStateSetJson) - 1);
  auto json_store = base::MakeRefCounted<JsonStore>(json_store_file_path);
  RmadInterfaceImpl rmad_interface(
      json_store, CreateStateHandlerManager(json_store),
      CreateRuntimeProbeClient(false), CreateShillClient(nullptr),
      CreateTpmManagerClient(RoVerificationStatus::NOT_TRIGGERED),
      CreatePowerManagerClient(), CreateCmdUtils(), CreateMetricsUtils(true));
  EXPECT_TRUE(rmad_interface.SetUp());

  // Check that the state file exists now.
  EXPECT_TRUE(base::PathExists(json_store_file_path));

  auto callback = [](const AbortRmaReply& reply) {
    EXPECT_EQ(RMAD_ERROR_RMA_NOT_REQUIRED, reply.error());
  };
  rmad_interface.RegisterRequestQuitDaemonCallback(base::BindRepeating(
      &RmadInterfaceImplTest::RequestQuitDaemon, base::Unretained(this)));
  rmad_interface.AbortRma(base::BindOnce(callback));

  // Check the the state file is cleared.
  EXPECT_FALSE(base::PathExists(json_store_file_path));

  // Check that we request to quit the daemon.
  EXPECT_TRUE(quit_daemon_requested_);
}

TEST_F(RmadInterfaceImplTest, AbortRma_Failed) {
  base::FilePath json_store_file_path = CreateInputFile(
      kJsonStoreFileName, kCurrentStateWithUnrepeatableHistoryJson,
      std::size(kCurrentStateWithUnrepeatableHistoryJson) - 1);
  auto json_store = base::MakeRefCounted<JsonStore>(json_store_file_path);
  RmadInterfaceImpl rmad_interface(
      json_store, CreateStateHandlerManager(json_store),
      CreateRuntimeProbeClient(false), CreateShillClient(nullptr),
      CreateTpmManagerClient(RoVerificationStatus::NOT_TRIGGERED),
      CreatePowerManagerClient(), CreateCmdUtils(), CreateMetricsUtils(true));
  EXPECT_TRUE(rmad_interface.SetUp());

  // Check that the state file exists now.
  EXPECT_TRUE(base::PathExists(json_store_file_path));

  auto callback = [](const AbortRmaReply& reply) {
    EXPECT_EQ(RMAD_ERROR_ABORT_FAILED, reply.error());
  };
  rmad_interface.AbortRma(base::BindOnce(callback));

  // Check the the state file still exists.
  EXPECT_TRUE(base::PathExists(json_store_file_path));
}

TEST_F(RmadInterfaceImplTest, GetLog) {
  base::FilePath json_store_file_path =
      CreateInputFile(kJsonStoreFileName, "", 0);
  auto json_store = base::MakeRefCounted<JsonStore>(json_store_file_path);
  RmadInterfaceImpl rmad_interface(
      json_store, CreateStateHandlerManager(json_store),
      CreateRuntimeProbeClient(false), CreateShillClient(nullptr),
      CreateTpmManagerClient(RoVerificationStatus::NOT_TRIGGERED),
      CreatePowerManagerClient(), CreateCmdUtils(), CreateMetricsUtils(true));
  EXPECT_TRUE(rmad_interface.SetUp());

  auto callback = [](const GetLogReply& reply) {
    EXPECT_EQ("fake_log", reply.log());
  };
  rmad_interface.GetLog(base::BindOnce(callback));
}

TEST_F(RmadInterfaceImplTest, SaveLog) {
  base::FilePath json_store_file_path =
      CreateInputFile(kJsonStoreFileName, "", 0);
  auto json_store = base::MakeRefCounted<JsonStore>(json_store_file_path);
  RmadInterfaceImpl rmad_interface(
      json_store, CreateStateHandlerManager(json_store),
      CreateRuntimeProbeClient(false), CreateShillClient(nullptr),
      CreateTpmManagerClient(RoVerificationStatus::NOT_TRIGGERED),
      CreatePowerManagerClient(), CreateCmdUtils(), CreateMetricsUtils(true));
  EXPECT_TRUE(rmad_interface.SetUp());

  auto callback = [](const SaveLogReply& reply) {
    EXPECT_EQ(RMAD_ERROR_OK, reply.error());
    EXPECT_EQ("fake_path", reply.save_path());
  };
  rmad_interface.SaveLog("", base::BindOnce(callback));
}

TEST_F(RmadInterfaceImplTest, RecordBrowserActionMetric) {
  base::FilePath json_store_file_path =
      CreateInputFile(kJsonStoreFileName, "", 0);
  auto json_store = base::MakeRefCounted<JsonStore>(json_store_file_path);
  RmadInterfaceImpl rmad_interface(
      json_store, CreateStateHandlerManager(json_store),
      CreateRuntimeProbeClient(false), CreateShillClient(nullptr),
      CreateTpmManagerClient(RoVerificationStatus::NOT_TRIGGERED),
      CreatePowerManagerClient(), CreateCmdUtils(), CreateMetricsUtils(true));
  EXPECT_TRUE(rmad_interface.SetUp());

  auto callback = [](const RecordBrowserActionMetricReply& reply) {
    EXPECT_EQ(RMAD_ERROR_OK, reply.error());
  };
  RecordBrowserActionMetricRequest request;
  request.set_diagnostics(true);
  request.set_os_update(true);

  rmad_interface.RecordBrowserActionMetric(request, base::BindOnce(callback));

  std::vector<int> additional_activities;
  EXPECT_TRUE(
      json_store->GetValue(kAdditionalActivities, &additional_activities));
  EXPECT_EQ(
      additional_activities,
      std::vector<int>({static_cast<int>(AdditionalActivity::DIAGNOSTICS),
                        static_cast<int>(AdditionalActivity::OS_UPDATE)}));
}

}  // namespace rmad
