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

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

#include "diagnostics/wilco_dtc_supportd/fake_wilco_dtc_supportd_routine_factory.h"
#include "diagnostics/wilco_dtc_supportd/wilco_dtc_supportd_routine_service.h"

using testing::ElementsAreArray;

namespace diagnostics {

namespace {
constexpr char kInvalidRoutineOutput[] = "Specified routine does not exist.";

constexpr grpc_api::DiagnosticRoutine kAvailableRoutines[] = {
    grpc_api::ROUTINE_BATTERY, grpc_api::ROUTINE_BATTERY_SYSFS,
    grpc_api::ROUTINE_BAD_BLOCKS, grpc_api::ROUTINE_URANDOM};

void CopyAvailableRoutines(
    base::Closure callback,
    std::vector<grpc_api::DiagnosticRoutine>* routines,
    const std::vector<grpc_api::DiagnosticRoutine>& returned_routines) {
  routines->assign(returned_routines.begin(), returned_routines.end());
  callback.Run();
}

void SaveRunRoutineResponse(base::Closure callback,
                            grpc_api::RunRoutineResponse* response,
                            int uuid,
                            grpc_api::DiagnosticRoutineStatus status) {
  response->set_uuid(uuid);
  response->set_status(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) {
  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);
  callback.Run();
}

}  // namespace

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

  WilcoDtcSupportdRoutineService* service() { return &service_; }

  void SetAvailableRoutines() {
    std::vector<grpc_api::DiagnosticRoutine> routines_to_add;
    for (auto routine : kAvailableRoutines)
      routines_to_add.push_back(routine);
    service_.SetAvailableRoutinesForTesting(routines_to_add);
  }

  std::vector<grpc_api::DiagnosticRoutine> ExecuteGetAvailableRoutines() {
    std::vector<grpc_api::DiagnosticRoutine> routines;
    base::RunLoop run_loop;
    service_.GetAvailableRoutines(
        base::Bind(&CopyAvailableRoutines, run_loop.QuitClosure(), &routines));
    run_loop.Run();
    return routines;
  }

  grpc_api::RunRoutineResponse ExecuteRunRoutine() {
    base::RunLoop run_loop;
    grpc_api::RunRoutineRequest request;
    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::MessageLoop message_loop_;
  FakeWilcoDtcSupportdRoutineFactory routine_factory_;
  WilcoDtcSupportdRoutineService service_{&routine_factory_};
};

// Test that GetAvailableRoutines returns the expected list of routines.
TEST_F(WilcoDtcSupportdRoutineServiceTest, GetAvailableRoutines) {
  SetAvailableRoutines();
  auto reply = ExecuteGetAvailableRoutines();
  EXPECT_THAT(reply, ElementsAreArray(kAvailableRoutines));
}

// Test that getting the status of a routine that doesn't exist returns an
// error.
TEST_F(WilcoDtcSupportdRoutineServiceTest, BadRoutineStatus) {
  auto response = ExecuteGetRoutineUpdate(
      0 /* uuid */, grpc_api::GetRoutineUpdateRequest::GET_STATUS,
      false /* include_output */);
  EXPECT_EQ(response.status(), grpc_api::ROUTINE_STATUS_ERROR);
  EXPECT_EQ(response.status_message(), kInvalidRoutineOutput);
}

// Test that a routine can be run.
TEST_F(WilcoDtcSupportdRoutineServiceTest, RunRoutine) {
  auto response = ExecuteRunRoutine();
  EXPECT_EQ(response.status(), grpc_api::ROUTINE_STATUS_RUNNING);
}

// Test that after a routine has started, we can access its data.
TEST_F(WilcoDtcSupportdRoutineServiceTest, AccessRunningRoutine) {
  auto run_routine_response = ExecuteRunRoutine();
  auto update_response =
      ExecuteGetRoutineUpdate(run_routine_response.uuid(),
                              grpc_api::GetRoutineUpdateRequest::GET_STATUS,
                              false /* include_output */);
  EXPECT_EQ(update_response.status(), grpc_api::ROUTINE_STATUS_RUNNING);
}

// Test that after a routine has been removed, we cannot access its data.
TEST_F(WilcoDtcSupportdRoutineServiceTest, AccessStoppedRoutine) {
  auto run_routine_response = ExecuteRunRoutine();
  ExecuteGetRoutineUpdate(run_routine_response.uuid(),
                          grpc_api::GetRoutineUpdateRequest::REMOVE,
                          false /* include_output */);
  auto update_response = ExecuteGetRoutineUpdate(
      run_routine_response.uuid(),
      grpc_api::GetRoutineUpdateRequest::GET_STATUS, true /* include_output */);
  EXPECT_EQ(update_response.status(), grpc_api::ROUTINE_STATUS_ERROR);
  EXPECT_EQ(update_response.status_message(), kInvalidRoutineOutput);
}

}  // namespace diagnostics
