// Copyright 2019 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 <limits>
#include <string>
#include <tuple>
#include <type_traits>
#include <vector>

#include <base/bind.h>
#include <base/callback.h>
#include <base/run_loop.h>
#include <base/test/task_environment.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>

#include "diagnostics/wilco_dtc_supportd/fake_diagnostics_service.h"
#include "diagnostics/wilco_dtc_supportd/routine_service.h"
#include "mojo/cros_healthd_diagnostics.mojom.h"

using testing::ElementsAreArray;

namespace diagnostics {
namespace mojo_ipc = ::chromeos::cros_healthd::mojom;

namespace {

grpc_api::RunRoutineRequest MakeBatteryRoutineRequest() {
  grpc_api::RunRoutineRequest request;
  request.set_routine(grpc_api::ROUTINE_BATTERY);
  request.mutable_battery_params()->set_low_mah(10);
  request.mutable_battery_params()->set_high_mah(100);
  return request;
}

grpc_api::RunRoutineRequest MakeDefaultBatteryRoutineRequest() {
  grpc_api::RunRoutineRequest request;
  request.set_routine(grpc_api::ROUTINE_BATTERY);
  request.mutable_battery_params();
  return request;
}

grpc_api::RunRoutineRequest MakeBatterySysfsRoutineRequest() {
  grpc_api::RunRoutineRequest request;
  request.set_routine(grpc_api::ROUTINE_BATTERY_SYSFS);
  request.mutable_battery_sysfs_params()->set_maximum_cycle_count(2);
  request.mutable_battery_sysfs_params()->set_percent_battery_wear_allowed(30);
  return request;
}

grpc_api::RunRoutineRequest MakeUrandomRoutineRequest() {
  grpc_api::RunRoutineRequest request;
  request.set_routine(grpc_api::ROUTINE_URANDOM);
  request.mutable_urandom_params()->set_length_seconds(10);
  return request;
}

grpc_api::RunRoutineRequest MakeSmartctlCheckRoutineRequest() {
  grpc_api::RunRoutineRequest request;
  request.set_routine(grpc_api::ROUTINE_SMARTCTL_CHECK);
  request.mutable_smartctl_check_params();
  return request;
}

grpc_api::RunRoutineRequest MakeCpuCacheRoutineRequest() {
  grpc_api::RunRoutineRequest request;
  request.set_routine(grpc_api::ROUTINE_CPU_CACHE);
  request.mutable_cpu_params()->set_length_seconds(10);
  return request;
}

grpc_api::RunRoutineRequest MakeCpuStressRoutineRequest() {
  grpc_api::RunRoutineRequest request;
  request.set_routine(grpc_api::ROUTINE_CPU_STRESS);
  request.mutable_cpu_params()->set_length_seconds(300);
  return request;
}

grpc_api::RunRoutineRequest MakeFloatingPointAccuracyRoutineRequest() {
  grpc_api::RunRoutineRequest request;
  request.set_routine(grpc_api::ROUTINE_FLOATING_POINT_ACCURACY);
  request.mutable_floating_point_accuracy_params()->set_length_seconds(2);
  return request;
}

grpc_api::RunRoutineRequest MakeNvmeWearLevelRoutineRequest() {
  grpc_api::RunRoutineRequest request;
  request.set_routine(grpc_api::ROUTINE_NVME_WEAR_LEVEL);
  request.mutable_nvme_wear_level_params()->set_wear_level_threshold(50);
  return request;
}
grpc_api::RunRoutineRequest MakeNvmeSelfTestShortRoutineRequest() {
  grpc_api::RunRoutineRequest request;
  request.set_routine(grpc_api::ROUTINE_NVME_SHORT_SELF_TEST);
  request.mutable_nvme_short_self_test_params();
  return request;
}

grpc_api::RunRoutineRequest MakeNvmeSelfTestLongRoutineRequest() {
  grpc_api::RunRoutineRequest request;
  request.set_routine(grpc_api::ROUTINE_NVME_LONG_SELF_TEST);
  request.mutable_nvme_long_self_test_params();
  return request;
}

grpc_api::RunRoutineRequest MakeDiskLinearReadRoutineRequest() {
  grpc_api::RunRoutineRequest request;
  request.set_routine(grpc_api::ROUTINE_DISK_LINEAR_READ);
  request.mutable_disk_linear_read_params()->set_length_seconds(10);
  request.mutable_disk_linear_read_params()->set_file_size_mb(1024);
  return request;
}

grpc_api::RunRoutineRequest MakeDiskRandomReadRoutineRequest() {
  grpc_api::RunRoutineRequest request;
  request.set_routine(grpc_api::ROUTINE_DISK_RANDOM_READ);
  request.mutable_disk_random_read_params()->set_length_seconds(10);
  request.mutable_disk_random_read_params()->set_file_size_mb(1024);
  return request;
}

void SaveGetAvailableRoutinesResponse(
    base::Closure callback,
    grpc_api::GetAvailableRoutinesResponse* response,
    const std::vector<grpc_api::DiagnosticRoutine>& returned_routines,
    grpc_api::RoutineServiceStatus service_status) {
  for (const auto& routine : returned_routines)
    response->add_routines(routine);
  response->set_service_status(service_status);
  callback.Run();
}

void SaveRunRoutineResponse(base::Closure callback,
                            grpc_api::RunRoutineResponse* response,
                            int uuid,
                            grpc_api::DiagnosticRoutineStatus status,
                            grpc_api::RoutineServiceStatus service_status) {
  response->set_uuid(uuid);
  response->set_status(status);
  response->set_service_status(service_status);
  callback.Run();
}

void SaveGetRoutineUpdateResponse(
    base::Closure callback,
    grpc_api::GetRoutineUpdateResponse* response,
    int uuid,
    grpc_api::DiagnosticRoutineStatus status,
    int progress_percent,
    grpc_api::DiagnosticRoutineUserMessage user_message,
    const std::string& output,
    const std::string& status_message,
    grpc_api::RoutineServiceStatus service_status) {
  response->set_uuid(uuid);
  response->set_status(status);
  response->set_progress_percent(progress_percent);
  response->set_user_message(user_message);
  response->set_output(output);
  response->set_status_message(status_message);
  response->set_service_status(service_status);
  callback.Run();
}

// Tests for the RoutineService class.
class RoutineServiceTest : public testing::Test {
 protected:
  RoutineServiceTest() = default;

  FakeDiagnosticsService* diagnostics_service() {
    return &diagnostics_service_;
  }

  grpc_api::GetAvailableRoutinesResponse ExecuteGetAvailableRoutines() {
    base::RunLoop run_loop;
    grpc_api::GetAvailableRoutinesResponse response;
    service_.GetAvailableRoutines(base::Bind(
        &SaveGetAvailableRoutinesResponse, run_loop.QuitClosure(), &response));
    run_loop.Run();
    return response;
  }

  grpc_api::RunRoutineResponse ExecuteRunRoutine(
      const grpc_api::RunRoutineRequest& request) {
    base::RunLoop run_loop;
    grpc_api::RunRoutineResponse response;
    service_.RunRoutine(request, base::Bind(&SaveRunRoutineResponse,
                                            run_loop.QuitClosure(), &response));
    run_loop.Run();
    return response;
  }

  grpc_api::GetRoutineUpdateResponse ExecuteGetRoutineUpdate(
      const int uuid,
      const grpc_api::GetRoutineUpdateRequest::Command command,
      const bool include_output) {
    base::RunLoop run_loop;
    grpc_api::GetRoutineUpdateResponse response;
    service_.GetRoutineUpdate(uuid, command, include_output,
                              base::Bind(&SaveGetRoutineUpdateResponse,
                                         run_loop.QuitClosure(), &response));
    run_loop.Run();
    return response;
  }

 private:
  base::test::TaskEnvironment task_environment_{
      base::test::TaskEnvironment::ThreadingMode::MAIN_THREAD_ONLY};
  FakeDiagnosticsService diagnostics_service_;
  RoutineService service_{&diagnostics_service_};
};

// Test that GetAvailableRoutines returns the expected list of routines.
TEST_F(RoutineServiceTest, GetAvailableRoutines) {
  diagnostics_service()->SetGetAvailableRoutinesResponse(
      {mojo_ipc::DiagnosticRoutineEnum::kBatteryCapacity,
       mojo_ipc::DiagnosticRoutineEnum::kBatteryHealth,
       mojo_ipc::DiagnosticRoutineEnum::kSmartctlCheck,
       mojo_ipc::DiagnosticRoutineEnum::kUrandom,
       mojo_ipc::DiagnosticRoutineEnum::kCpuCache,
       mojo_ipc::DiagnosticRoutineEnum::kCpuStress,
       mojo_ipc::DiagnosticRoutineEnum::kFloatingPointAccuracy,
       mojo_ipc::DiagnosticRoutineEnum::kNvmeWearLevel,
       mojo_ipc::DiagnosticRoutineEnum::kNvmeSelfTest,
       mojo_ipc::DiagnosticRoutineEnum::kDiskRead});

  const auto reply = ExecuteGetAvailableRoutines();
  EXPECT_THAT(reply.routines(),
              ElementsAreArray(
                  {grpc_api::ROUTINE_BATTERY, grpc_api::ROUTINE_BATTERY_SYSFS,
                   grpc_api::ROUTINE_SMARTCTL_CHECK, grpc_api::ROUTINE_URANDOM,
                   grpc_api::ROUTINE_CPU_CACHE, grpc_api::ROUTINE_CPU_STRESS,
                   grpc_api::ROUTINE_FLOATING_POINT_ACCURACY,
                   grpc_api::ROUTINE_NVME_WEAR_LEVEL,
                   grpc_api::ROUTINE_NVME_SHORT_SELF_TEST,
                   grpc_api::ROUTINE_NVME_LONG_SELF_TEST,
                   grpc_api::ROUTINE_DISK_LINEAR_READ,
                   grpc_api::ROUTINE_DISK_RANDOM_READ}));
  EXPECT_EQ(reply.service_status(), grpc_api::ROUTINE_SERVICE_STATUS_OK);
}

// Test that an unknown mojo routine enum is handled sanely.
TEST_F(RoutineServiceTest, GetAvailableRoutinesInvalidMojoRoutineEnum) {
  diagnostics_service()->SetGetAvailableRoutinesResponse(
      std::vector<mojo_ipc::DiagnosticRoutineEnum>{
          static_cast<mojo_ipc::DiagnosticRoutineEnum>(
              std::numeric_limits<std::underlying_type<
                  mojo_ipc::DiagnosticRoutineEnum>::type>::max()),
          mojo_ipc::DiagnosticRoutineEnum::kBatteryCapacity});

  const auto reply = ExecuteGetAvailableRoutines();
  EXPECT_THAT(reply.routines(), ElementsAreArray({grpc_api::ROUTINE_BATTERY}));
  EXPECT_EQ(reply.service_status(), grpc_api::ROUTINE_SERVICE_STATUS_OK);
}

// Test that an invalid RunRoutineRequest is handled sanely.
TEST_F(RoutineServiceTest, InvalidRunRoutineRequest) {
  grpc_api::RunRoutineRequest request;
  request.set_routine(static_cast<grpc_api::DiagnosticRoutine>(
      std::numeric_limits<
          std::underlying_type<grpc_api::DiagnosticRoutine>::type>::max()));

  const auto reply = ExecuteRunRoutine(request);
  EXPECT_EQ(reply.uuid(), 0);
  EXPECT_EQ(reply.status(), grpc_api::ROUTINE_STATUS_INVALID_FIELD);
  EXPECT_EQ(reply.service_status(), grpc_api::ROUTINE_SERVICE_STATUS_OK);
}

// Test that a routine reporting an invalid user message is handled sanely.
TEST_F(RoutineServiceTest, GetRoutineUpdateInvalidUserMessage) {
  diagnostics_service()->SetInteractiveUpdate(
      static_cast<mojo_ipc::DiagnosticRoutineUserMessageEnum>(
          std::numeric_limits<std::underlying_type<
              mojo_ipc::DiagnosticRoutineUserMessageEnum>::type>::max()),
      0 /* progress_percent */, "" /* output */);

  const auto update_response = ExecuteGetRoutineUpdate(
      0 /* uuid */, grpc_api::GetRoutineUpdateRequest::GET_STATUS,
      false /* include_output */);
  EXPECT_EQ(update_response.status(), grpc_api::ROUTINE_STATUS_ERROR);
  EXPECT_EQ(update_response.service_status(),
            grpc_api::ROUTINE_SERVICE_STATUS_OK);
}

// Test that a routine update reporting an invalid status is handled sanely.
TEST_F(RoutineServiceTest, InvalidGetRoutineUpdateStatus) {
  diagnostics_service()->SetNonInteractiveUpdate(
      static_cast<mojo_ipc::DiagnosticRoutineStatusEnum>(
          std::numeric_limits<std::underlying_type<
              mojo_ipc::DiagnosticRoutineStatusEnum>::type>::max()),
      "" /* status_message */, 0 /* progress_percent */, "" /* output */);

  const auto update_response = ExecuteGetRoutineUpdate(
      0 /* uuid */, grpc_api::GetRoutineUpdateRequest::GET_STATUS,
      false /* include_output */);
  EXPECT_EQ(update_response.status(), grpc_api::ROUTINE_STATUS_ERROR);
  EXPECT_EQ(update_response.service_status(),
            grpc_api::ROUTINE_SERVICE_STATUS_OK);
}

// Test that a run routine response reporting an invalid status is handled
// sanely.
TEST_F(RoutineServiceTest, InvalidRunRoutineResponseStatus) {
  diagnostics_service()->SetRunSomeRoutineResponse(
      0 /* uuid */,
      static_cast<mojo_ipc::DiagnosticRoutineStatusEnum>(
          std::numeric_limits<std::underlying_type<
              mojo_ipc::DiagnosticRoutineStatusEnum>::type>::max()));

  const auto response = ExecuteRunRoutine(MakeSmartctlCheckRoutineRequest());
  EXPECT_EQ(response.status(), grpc_api::ROUTINE_STATUS_ERROR);
  EXPECT_EQ(response.uuid(), 0);
  EXPECT_EQ(response.service_status(), grpc_api::ROUTINE_SERVICE_STATUS_OK);
}

// Test that an invalid command passed to the routine service is handled sanely.
TEST_F(RoutineServiceTest, GetRoutineUpdateInvalidCommand) {
  diagnostics_service()->SetNonInteractiveUpdate(
      mojo_ipc::DiagnosticRoutineStatusEnum::kReady, "" /* status_message */,
      0 /* progress_percent */, "" /* output */);

  const auto update_response = ExecuteGetRoutineUpdate(
      0 /* uuid */,
      static_cast<grpc_api::GetRoutineUpdateRequest::Command>(
          std::numeric_limits<std::underlying_type<
              grpc_api::GetRoutineUpdateRequest::Command>::type>::max()),
      false /* include_output */);
  EXPECT_EQ(update_response.status(), grpc_api::ROUTINE_STATUS_INVALID_FIELD);
  EXPECT_EQ(update_response.progress_percent(), 0);
  EXPECT_EQ(update_response.user_message(),
            grpc_api::ROUTINE_USER_MESSAGE_UNSET);
  EXPECT_EQ(update_response.output(), "");
  EXPECT_EQ(update_response.status_message(), "");
  EXPECT_EQ(update_response.service_status(),
            grpc_api::ROUTINE_SERVICE_STATUS_OK);
}

// Test that the routine service doesn't attempt to rebind a valid mojo service
// pointer.
TEST_F(RoutineServiceTest, NoRebindService) {
  constexpr uint32_t kExpectedId = 55;
  diagnostics_service()->SetRunSomeRoutineResponse(
      kExpectedId, mojo_ipc::DiagnosticRoutineStatusEnum::kRunning);
  // Send the first mojo IPC to the diagnostics service. This IPC should
  // bootstrap the mojo connection. Ignore the response, because we're only
  // interested in whether or not the next request tries to bootstrap the mojo
  // connection again.
  ExecuteRunRoutine(MakeSmartctlCheckRoutineRequest());

  // Tell the service to respond with an error if a second bootstrapping is
  // requested.
  diagnostics_service()->SetMojoServiceIsAvailable(false);

  // Send another request. This shouldn't see an error, because it shouldn't try
  // to bootstrap the mojo connection a second time.
  const auto reply = ExecuteRunRoutine(MakeSmartctlCheckRoutineRequest());

  // If the bootstrap was requested a second time, we would receive a uuid of 0
  // and a status of grpc_api::FAILED_TO_START.
  EXPECT_EQ(reply.uuid(), kExpectedId);
  EXPECT_EQ(reply.status(), grpc_api::ROUTINE_STATUS_RUNNING);
  EXPECT_EQ(reply.service_status(), grpc_api::ROUTINE_SERVICE_STATUS_OK);
}

// Test that the routine service handles a GetAvailableRoutines request sent
// before wilco_dtc_supportd's mojo service is established.
TEST_F(RoutineServiceTest, GetAvailableRoutinesNoService) {
  diagnostics_service()->SetMojoServiceIsAvailable(false);

  const auto reply = ExecuteGetAvailableRoutines();
  EXPECT_EQ(reply.routines_size(), 0);
  EXPECT_EQ(reply.service_status(),
            grpc_api::ROUTINE_SERVICE_STATUS_UNAVAILABLE);
}

// Test that the routine service handles a RunRoutine request sent before
// wilco_dtc_supportd's mojo service is established.
TEST_F(RoutineServiceTest, RunRoutineNoService) {
  diagnostics_service()->SetMojoServiceIsAvailable(false);

  const auto response = ExecuteRunRoutine(MakeSmartctlCheckRoutineRequest());
  EXPECT_EQ(response.status(), grpc_api::ROUTINE_STATUS_FAILED_TO_START);
  EXPECT_EQ(response.uuid(), 0);
  EXPECT_EQ(response.service_status(),
            grpc_api::ROUTINE_SERVICE_STATUS_UNAVAILABLE);
}

// Test that the routine service handles a GetRoutineUpdate request sent before
// wilco_dtc_supportd's mojo service is established.
TEST_F(RoutineServiceTest, GetRoutineUpdateNoService) {
  diagnostics_service()->SetMojoServiceIsAvailable(false);

  const auto update_response = ExecuteGetRoutineUpdate(
      0 /* uuid */, grpc_api::GetRoutineUpdateRequest::GET_STATUS,
      false /* include_output */);
  EXPECT_EQ(update_response.status(), grpc_api::ROUTINE_STATUS_ERROR);
  EXPECT_EQ(update_response.progress_percent(), 0);
  EXPECT_EQ(update_response.user_message(),
            grpc_api::ROUTINE_USER_MESSAGE_UNSET);
  EXPECT_EQ(update_response.output(), "");
  EXPECT_EQ(update_response.status_message(), "");
  EXPECT_EQ(update_response.service_status(),
            grpc_api::ROUTINE_SERVICE_STATUS_UNAVAILABLE);
}

// Test that the routine service can recover from an early gRPC request if
// wilco_dtc_supportd's mojo service is established later.
TEST_F(RoutineServiceTest, RecoverFromNoServiceRequest) {
  // Deal with a request sent before the mojo service is available.
  diagnostics_service()->SetMojoServiceIsAvailable(false);

  const auto unavailable_reply = ExecuteGetAvailableRoutines();
  EXPECT_EQ(unavailable_reply.routines_size(), 0);
  EXPECT_EQ(unavailable_reply.service_status(),
            grpc_api::ROUTINE_SERVICE_STATUS_UNAVAILABLE);
  base::RunLoop().RunUntilIdle();

  // Make the mojo service available, and make sure a valid response is
  // received.
  diagnostics_service()->SetMojoServiceIsAvailable(true);
  diagnostics_service()->SetGetAvailableRoutinesResponse(
      {mojo_ipc::DiagnosticRoutineEnum::kBatteryCapacity,
       mojo_ipc::DiagnosticRoutineEnum::kBatteryHealth,
       mojo_ipc::DiagnosticRoutineEnum::kSmartctlCheck,
       mojo_ipc::DiagnosticRoutineEnum::kUrandom,
       mojo_ipc::DiagnosticRoutineEnum::kCpuCache,
       mojo_ipc::DiagnosticRoutineEnum::kCpuStress,
       mojo_ipc::DiagnosticRoutineEnum::kFloatingPointAccuracy,
       mojo_ipc::DiagnosticRoutineEnum::kNvmeWearLevel,
       mojo_ipc::DiagnosticRoutineEnum::kNvmeSelfTest,
       mojo_ipc::DiagnosticRoutineEnum::kDiskRead});

  const auto reply = ExecuteGetAvailableRoutines();
  EXPECT_THAT(reply.routines(),
              ElementsAreArray(
                  {grpc_api::ROUTINE_BATTERY, grpc_api::ROUTINE_BATTERY_SYSFS,
                   grpc_api::ROUTINE_SMARTCTL_CHECK, grpc_api::ROUTINE_URANDOM,
                   grpc_api::ROUTINE_CPU_CACHE, grpc_api::ROUTINE_CPU_STRESS,
                   grpc_api::ROUTINE_FLOATING_POINT_ACCURACY,
                   grpc_api::ROUTINE_NVME_WEAR_LEVEL,
                   grpc_api::ROUTINE_NVME_SHORT_SELF_TEST,
                   grpc_api::ROUTINE_NVME_LONG_SELF_TEST,
                   grpc_api::ROUTINE_DISK_LINEAR_READ,
                   grpc_api::ROUTINE_DISK_RANDOM_READ}));
  EXPECT_EQ(reply.service_status(), grpc_api::ROUTINE_SERVICE_STATUS_OK);
}

// Test that the routine service handles a GetAvailableRoutines request sent
// when cros_healthd is unresponsive.
TEST_F(RoutineServiceTest, GetAvailableRoutinesUnresponsiveService) {
  diagnostics_service()->SetMojoServiceIsResponsive(false);

  const auto reply = ExecuteGetAvailableRoutines();
  EXPECT_EQ(reply.routines_size(), 0);
  EXPECT_EQ(reply.service_status(),
            grpc_api::ROUTINE_SERVICE_STATUS_UNAVAILABLE);
}

// Test that the routine service handles a RunRoutine request sent when
// cros_healthd is unresponsive.
TEST_F(RoutineServiceTest, RunRoutineUnresponsiveService) {
  diagnostics_service()->SetMojoServiceIsResponsive(false);

  const auto response = ExecuteRunRoutine(MakeSmartctlCheckRoutineRequest());
  EXPECT_EQ(response.status(), grpc_api::ROUTINE_STATUS_FAILED_TO_START);
  EXPECT_EQ(response.uuid(), 0);
  EXPECT_EQ(response.service_status(),
            grpc_api::ROUTINE_SERVICE_STATUS_UNAVAILABLE);
}

// Test that the routine service handles a GetRoutineUpdate request sent when
// cros_healthd is unresponsive.
TEST_F(RoutineServiceTest, GetRoutineUpdateUnresponsiveService) {
  diagnostics_service()->SetMojoServiceIsResponsive(false);

  constexpr int kUuid = 11;
  const auto update_response = ExecuteGetRoutineUpdate(
      kUuid, grpc_api::GetRoutineUpdateRequest::GET_STATUS,
      false /* include_output */);
  EXPECT_EQ(update_response.uuid(), kUuid);
  EXPECT_EQ(update_response.status(), grpc_api::ROUTINE_STATUS_ERROR);
  EXPECT_EQ(update_response.progress_percent(), 0);
  EXPECT_EQ(update_response.user_message(),
            grpc_api::ROUTINE_USER_MESSAGE_UNSET);
  EXPECT_EQ(update_response.output(), "");
  EXPECT_EQ(update_response.status_message(), "");
  EXPECT_EQ(update_response.service_status(),
            grpc_api::ROUTINE_SERVICE_STATUS_UNAVAILABLE);
}

// Test that the routine service can recover from a dropped connection.
TEST_F(RoutineServiceTest, RecoverFromDroppedConnection) {
  // Establish a valid connection.
  diagnostics_service()->SetGetAvailableRoutinesResponse(
      {mojo_ipc::DiagnosticRoutineEnum::kBatteryCapacity,
       mojo_ipc::DiagnosticRoutineEnum::kBatteryHealth,
       mojo_ipc::DiagnosticRoutineEnum::kSmartctlCheck,
       mojo_ipc::DiagnosticRoutineEnum::kUrandom,
       mojo_ipc::DiagnosticRoutineEnum::kCpuCache,
       mojo_ipc::DiagnosticRoutineEnum::kCpuStress,
       mojo_ipc::DiagnosticRoutineEnum::kFloatingPointAccuracy,
       mojo_ipc::DiagnosticRoutineEnum::kNvmeWearLevel,
       mojo_ipc::DiagnosticRoutineEnum::kNvmeSelfTest,
       mojo_ipc::DiagnosticRoutineEnum::kDiskRead});

  const auto reply = ExecuteGetAvailableRoutines();
  EXPECT_THAT(reply.routines(),
              ElementsAreArray(
                  {grpc_api::ROUTINE_BATTERY, grpc_api::ROUTINE_BATTERY_SYSFS,
                   grpc_api::ROUTINE_SMARTCTL_CHECK, grpc_api::ROUTINE_URANDOM,
                   grpc_api::ROUTINE_CPU_CACHE, grpc_api::ROUTINE_CPU_STRESS,
                   grpc_api::ROUTINE_FLOATING_POINT_ACCURACY,
                   grpc_api::ROUTINE_NVME_WEAR_LEVEL,
                   grpc_api::ROUTINE_NVME_SHORT_SELF_TEST,
                   grpc_api::ROUTINE_NVME_LONG_SELF_TEST,
                   grpc_api::ROUTINE_DISK_LINEAR_READ,
                   grpc_api::ROUTINE_DISK_RANDOM_READ}));
  EXPECT_EQ(reply.service_status(), grpc_api::ROUTINE_SERVICE_STATUS_OK);

  // Reset the connection, make cros_healthd unresponsive, and check to see that
  // the routine service responds appropriately.
  diagnostics_service()->ResetMojoConnection();
  diagnostics_service()->SetMojoServiceIsResponsive(false);

  const auto dropped_reply = ExecuteGetAvailableRoutines();
  EXPECT_EQ(dropped_reply.routines_size(), 0);
  EXPECT_EQ(dropped_reply.service_status(),
            grpc_api::ROUTINE_SERVICE_STATUS_UNAVAILABLE);

  // Set cros_healthd as available again, and make sure the routine service can
  // get valid responses.
  diagnostics_service()->SetMojoServiceIsResponsive(true);
  constexpr uint32_t kExpectedId = 77;
  diagnostics_service()->SetRunSomeRoutineResponse(
      kExpectedId, mojo_ipc::DiagnosticRoutineStatusEnum::kRunning);

  const auto reconnected_reply =
      ExecuteRunRoutine(MakeSmartctlCheckRoutineRequest());
  EXPECT_EQ(reconnected_reply.uuid(), kExpectedId);
  EXPECT_EQ(reconnected_reply.status(), grpc_api::ROUTINE_STATUS_RUNNING);
  EXPECT_EQ(reconnected_reply.service_status(),
            grpc_api::ROUTINE_SERVICE_STATUS_OK);
}

// Tests for the GetRoutineUpdate() method of RoutineService when an
// interactive update is returned.
//
// This is a parameterized test with the following parameters:
// * |mojo_message| - mojo's DiagnosticRoutineUserMessageEnum returned in the
//                    routine's update.
// * |grpc_message| - gRPC's DiagnosticRoutineUserMessage expected to be
//                    returned by the routine service.
class GetInteractiveUpdateTest
    : public RoutineServiceTest,
      public testing::WithParamInterface<
          std::tuple<mojo_ipc::DiagnosticRoutineUserMessageEnum,
                     grpc_api::DiagnosticRoutineUserMessage>> {
 protected:
  // Accessors to individual test parameters from the test parameter tuple
  // returned by gtest's GetParam():

  mojo_ipc::DiagnosticRoutineUserMessageEnum mojo_message() const {
    return std::get<0>(GetParam());
  }

  grpc_api::DiagnosticRoutineUserMessage grpc_message() const {
    return std::get<1>(GetParam());
  }
};

// Test that after a routine has started, we can access its interactive data.
TEST_P(GetInteractiveUpdateTest, AccessInteractiveRunningRoutine) {
  constexpr uint32_t kExpectedProgressPercent = 17;
  constexpr char kExpectedOutput[] = "Expected output.";
  diagnostics_service()->SetInteractiveUpdate(
      mojo_message(), kExpectedProgressPercent, kExpectedOutput);

  const auto update_response = ExecuteGetRoutineUpdate(
      0 /* uuid */, grpc_api::GetRoutineUpdateRequest::GET_STATUS,
      true /* include_output */);
  EXPECT_EQ(update_response.user_message(), grpc_message());
  EXPECT_EQ(update_response.progress_percent(), kExpectedProgressPercent);
  EXPECT_EQ(update_response.output(), kExpectedOutput);
  EXPECT_EQ(update_response.service_status(),
            grpc_api::ROUTINE_SERVICE_STATUS_OK);
}

INSTANTIATE_TEST_SUITE_P(
    ,
    GetInteractiveUpdateTest,
    testing::Values(std::make_tuple(
        mojo_ipc::DiagnosticRoutineUserMessageEnum::kUnplugACPower,
        grpc_api::ROUTINE_USER_MESSAGE_UNPLUG_AC_POWER)));

// Tests for the GetRoutineUpdate() method of RoutineService when a
// noninteractive update is returned.
//
// This is a parameterized test with the following parameters:
// * |mojo_status| - mojo's DiagnosticRoutineStatusEnum returned in the
//                   routine's update.
// * |grpc_status| - gRPC's DiagnosticRoutineStatus expected to be
//                   returned by the routine service.
class GetNonInteractiveUpdateTest
    : public RoutineServiceTest,
      public testing::WithParamInterface<
          std::tuple<mojo_ipc::DiagnosticRoutineStatusEnum,
                     grpc_api::DiagnosticRoutineStatus>> {
 protected:
  // Accessors to individual test parameters from the test parameter tuple
  // returned by gtest's GetParam():

  mojo_ipc::DiagnosticRoutineStatusEnum mojo_status() const {
    return std::get<0>(GetParam());
  }

  grpc_api::DiagnosticRoutineStatus grpc_status() const {
    return std::get<1>(GetParam());
  }
};

// Test that after a routine has started, we can access its noninteractive data.
TEST_P(GetNonInteractiveUpdateTest, AccessNonInteractiveRunningRoutine) {
  constexpr char kExpectedStatusMessage[] = "Expected status message.";
  constexpr uint32_t kExpectedProgressPercent = 18;
  constexpr char kExpectedOutput[] = "Expected output.";
  diagnostics_service()->SetNonInteractiveUpdate(
      mojo_status(), kExpectedStatusMessage, kExpectedProgressPercent,
      kExpectedOutput);

  const auto update_response = ExecuteGetRoutineUpdate(
      0 /* uuid */, grpc_api::GetRoutineUpdateRequest::GET_STATUS,
      true /* include_output */);
  EXPECT_EQ(update_response.status(), grpc_status());
  EXPECT_EQ(update_response.status_message(), kExpectedStatusMessage);
  EXPECT_EQ(update_response.progress_percent(), kExpectedProgressPercent);
  EXPECT_EQ(update_response.output(), kExpectedOutput);
  EXPECT_EQ(update_response.service_status(),
            grpc_api::ROUTINE_SERVICE_STATUS_OK);
}

INSTANTIATE_TEST_SUITE_P(
    ,
    GetNonInteractiveUpdateTest,
    testing::Values(
        std::make_tuple(mojo_ipc::DiagnosticRoutineStatusEnum::kReady,
                        grpc_api::ROUTINE_STATUS_READY),
        std::make_tuple(mojo_ipc::DiagnosticRoutineStatusEnum::kRunning,
                        grpc_api::ROUTINE_STATUS_RUNNING),
        std::make_tuple(mojo_ipc::DiagnosticRoutineStatusEnum::kWaiting,
                        grpc_api::ROUTINE_STATUS_WAITING),
        std::make_tuple(mojo_ipc::DiagnosticRoutineStatusEnum::kPassed,
                        grpc_api::ROUTINE_STATUS_PASSED),
        std::make_tuple(mojo_ipc::DiagnosticRoutineStatusEnum::kFailed,
                        grpc_api::ROUTINE_STATUS_FAILED),
        std::make_tuple(mojo_ipc::DiagnosticRoutineStatusEnum::kError,
                        grpc_api::ROUTINE_STATUS_ERROR),
        std::make_tuple(mojo_ipc::DiagnosticRoutineStatusEnum::kCancelled,
                        grpc_api::ROUTINE_STATUS_CANCELLED),
        std::make_tuple(mojo_ipc::DiagnosticRoutineStatusEnum::kFailedToStart,
                        grpc_api::ROUTINE_STATUS_FAILED_TO_START),
        std::make_tuple(mojo_ipc::DiagnosticRoutineStatusEnum::kRemoved,
                        grpc_api::ROUTINE_STATUS_REMOVED),
        std::make_tuple(mojo_ipc::DiagnosticRoutineStatusEnum::kCancelling,
                        grpc_api::ROUTINE_STATUS_CANCELLING)));

// Tests for the GetRoutineUpdate() method of RoutineService with different
// commands.
//
// This is a parameterized test with the following parameters:
// * |command| - gRPC's GetRoutineUpdateRequest::Command included in the
//               GetRoutineUpdateRequest.
class GetRoutineUpdateCommandTest
    : public RoutineServiceTest,
      public testing::WithParamInterface<
          grpc_api::GetRoutineUpdateRequest::Command> {
 protected:
  // Accessors to the test parameter returned by gtest's GetParam():

  grpc_api::GetRoutineUpdateRequest::Command command() const {
    return GetParam();
  }
};

// Test that we can send the given command.
TEST_P(GetRoutineUpdateCommandTest, SendCommand) {
  constexpr char kExpectedStatusMessage[] = "Expected status message.";
  constexpr uint32_t kExpectedProgressPercent = 19;
  constexpr char kExpectedOutput[] = "Expected output.";
  constexpr mojo_ipc::DiagnosticRoutineStatusEnum kMojoStatus =
      mojo_ipc::DiagnosticRoutineStatusEnum::kRunning;
  constexpr grpc_api::DiagnosticRoutineStatus kExpectedStatus =
      grpc_api::ROUTINE_STATUS_RUNNING;
  diagnostics_service()->SetNonInteractiveUpdate(
      kMojoStatus, kExpectedStatusMessage, kExpectedProgressPercent,
      kExpectedOutput);

  const auto update_response = ExecuteGetRoutineUpdate(
      0 /* uuid */, command(), true /* include_output */);
  EXPECT_EQ(update_response.status(), kExpectedStatus);
  EXPECT_EQ(update_response.status_message(), kExpectedStatusMessage);
  EXPECT_EQ(update_response.progress_percent(), kExpectedProgressPercent);
  EXPECT_EQ(update_response.output(), kExpectedOutput);
  EXPECT_EQ(update_response.service_status(),
            grpc_api::ROUTINE_SERVICE_STATUS_OK);
}

INSTANTIATE_TEST_SUITE_P(
    ,
    GetRoutineUpdateCommandTest,
    testing::Values(grpc_api::GetRoutineUpdateRequest::RESUME,
                    grpc_api::GetRoutineUpdateRequest::CANCEL,
                    grpc_api::GetRoutineUpdateRequest::REMOVE,
                    grpc_api::GetRoutineUpdateRequest::GET_STATUS));

// Tests for the RunRoutine() method of RoutineService with different requests.
//
// This is a parameterized test with the following parameters:
// * |request| - gRPC's RunRoutineRequest to be requested.
class RunRoutineTest
    : public RoutineServiceTest,
      public testing::WithParamInterface<grpc_api::RunRoutineRequest> {
 public:
  RunRoutineTest() = default;
  RunRoutineTest(const RunRoutineTest&) = delete;
  RunRoutineTest& operator=(const RunRoutineTest&) = delete;

  // Accessors to the test parameter returned by gtest's GetParam():

  grpc_api::RunRoutineRequest request() const { return GetParam(); }
};

// Test that we can request that the given routine is run.
TEST_P(RunRoutineTest, RunRoutine) {
  constexpr uint32_t kExpectedId = 77;
  diagnostics_service()->SetRunSomeRoutineResponse(
      kExpectedId, mojo_ipc::DiagnosticRoutineStatusEnum::kRunning);

  const auto reply = ExecuteRunRoutine(request());
  EXPECT_EQ(reply.uuid(), kExpectedId);
  EXPECT_EQ(reply.status(), grpc_api::ROUTINE_STATUS_RUNNING);
  EXPECT_EQ(reply.service_status(), grpc_api::ROUTINE_SERVICE_STATUS_OK);
}

INSTANTIATE_TEST_SUITE_P(
    ,
    RunRoutineTest,
    testing::Values(MakeBatteryRoutineRequest(),
                    MakeDefaultBatteryRoutineRequest(),
                    MakeBatterySysfsRoutineRequest(),
                    MakeUrandomRoutineRequest(),
                    MakeSmartctlCheckRoutineRequest(),
                    MakeCpuCacheRoutineRequest(),
                    MakeCpuStressRoutineRequest(),
                    MakeFloatingPointAccuracyRoutineRequest(),
                    MakeNvmeWearLevelRoutineRequest(),
                    MakeNvmeSelfTestShortRoutineRequest(),
                    MakeNvmeSelfTestLongRoutineRequest(),
                    MakeDiskLinearReadRoutineRequest(),
                    MakeDiskRandomReadRoutineRequest()));

}  // namespace

}  // namespace diagnostics
