// 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 <memory>
#include <type_traits>

#include <base/bind.h>
#include <base/files/scoped_temp_dir.h>
#include <base/strings/stringprintf.h>
#include <base/threading/thread_task_runner_handle.h>
#include <brillo/grpc/async_grpc_client.h>
#include <gmock/gmock.h>
#include <google/protobuf/util/message_differencer.h>
#include <gtest/gtest.h>

#include "diagnostics/common/protobuf_test_utils.h"
#include "diagnostics/constants/grpc_constants.h"
#include "diagnostics/dpsl/internal/dpsl_global_context_impl.h"
#include "diagnostics/dpsl/internal/dpsl_rpc_server_impl.h"
#include "diagnostics/dpsl/internal/dpsl_thread_context_impl.h"
#include "diagnostics/dpsl/internal/test_dpsl_background_thread.h"
#include "diagnostics/dpsl/public/dpsl_global_context.h"
#include "diagnostics/dpsl/public/dpsl_rpc_handler.h"
#include "diagnostics/dpsl/public/dpsl_rpc_server.h"
#include "diagnostics/dpsl/public/dpsl_thread_context.h"
#include "diagnostics/dpsl/test_utils/common.h"

#include "wilco_dtc.grpc.pb.h"           // NOLINT(build/include)
#include "wilco_dtc_supportd.grpc.pb.h"  // NOLINT(build/include)

using testing::_;
using testing::ReturnRef;
using testing::StrictMock;

namespace diagnostics {

namespace {

constexpr DpslRpcServer::GrpcServerUri kGrpcServerUriInvalidValue =
    static_cast<DpslRpcServer::GrpcServerUri>(
        std::numeric_limits<
            std::underlying_type<DpslRpcServer::GrpcServerUri>::type>::max());

class MockDpslRpcHandler : public DpslRpcHandler {
 public:
  void HandleMessageFromUi(
      std::unique_ptr<grpc_api::HandleMessageFromUiRequest> request,
      HandleMessageFromUiCallback callback) override {
    DCHECK(request);
    callback(std::make_unique<grpc_api::HandleMessageFromUiResponse>(
        HandleMessageFromUiImpl(*request)));
  }

  void HandleEcNotification(
      std::unique_ptr<grpc_api::HandleEcNotificationRequest> request,
      HandleEcNotificationCallback callback) override {
    DCHECK(request);
    callback(std::make_unique<grpc_api::HandleEcNotificationResponse>(
        HandleEcNotificationImpl(*request)));
  }

  void HandlePowerNotification(
      std::unique_ptr<grpc_api::HandlePowerNotificationRequest> request,
      HandlePowerNotificationCallback callback) override {
    DCHECK(request);
    callback(std::make_unique<grpc_api::HandlePowerNotificationResponse>(
        HandlePowerNotificationImpl(*request)));
  }

  void HandleConfigurationDataChanged(
      std::unique_ptr<grpc_api::HandleConfigurationDataChangedRequest> request,
      HandleConfigurationDataChangedCallback callback) override {
    DCHECK(request);
    callback(std::make_unique<grpc_api::HandleConfigurationDataChangedResponse>(
        HandleConfigurationDataChangedImpl(*request)));
  }

  void HandleBluetoothDataChanged(
      std::unique_ptr<grpc_api::HandleBluetoothDataChangedRequest> request,
      HandleBluetoothDataChangedCallback callback) override {
    DCHECK(request);
    callback(std::make_unique<grpc_api::HandleBluetoothDataChangedResponse>(
        HandleBluetoothDataChangedImpl(*request)));
  }

  MOCK_METHOD(const grpc_api::HandleMessageFromUiResponse&,
              HandleMessageFromUiImpl,
              (const grpc_api::HandleMessageFromUiRequest& request));
  MOCK_METHOD(const grpc_api::HandleEcNotificationResponse&,
              HandleEcNotificationImpl,
              (const grpc_api::HandleEcNotificationRequest& request));
  MOCK_METHOD(const grpc_api::HandlePowerNotificationResponse&,
              HandlePowerNotificationImpl,
              (const grpc_api::HandlePowerNotificationRequest& request));
  MOCK_METHOD(const grpc_api::HandleConfigurationDataChangedResponse&,
              HandleConfigurationDataChangedImpl,
              (const grpc_api::HandleConfigurationDataChangedRequest& request));
  MOCK_METHOD(const grpc_api::HandleBluetoothDataChangedResponse&,
              HandleBluetoothDataChangedImpl,
              (const grpc_api::HandleBluetoothDataChangedRequest& request));
};

}  // namespace

class DpslRpcServerImplBaseTest : public testing::Test {
 public:
  DpslRpcServerImplBaseTest() = default;
  DpslRpcServerImplBaseTest(const DpslRpcServerImplBaseTest&) = delete;
  DpslRpcServerImplBaseTest& operator=(const DpslRpcServerImplBaseTest&) =
      delete;

  ~DpslRpcServerImplBaseTest() override {
    DpslThreadContextImpl::CleanThreadCounterForTesting();
    DpslGlobalContextImpl::CleanGlobalCounterForTesting();
  }

  void SetUp() override {
    global_context_ = DpslGlobalContext::Create();
    ASSERT_TRUE(global_context_);
    thread_context_ = DpslThreadContext::Create(global_context_.get());
    ASSERT_TRUE(thread_context_);
  }

 protected:
  StrictMock<MockDpslRpcHandler> mock_handler_;

  std::unique_ptr<DpslGlobalContext> global_context_;
  std::unique_ptr<DpslThreadContext> thread_context_;
};

class DpslRpcServerImplBaseDeathTest : public DpslRpcServerImplBaseTest {
 public:
  DpslRpcServerImplBaseDeathTest() {
    // Using EXPECT_DEATH, gtest creates child process, which re-executes the
    // unit test binary just as it was originally invoked.
    // https://github.com/google/googletest/blob/master/googletest/docs/advanced.md#how-it-works
    //
    // Otherwise, EXPECT_DEATH statement will be called in forked child
    // immediately. It means that at least
    // DpslThreadContextImpl::BelongsToCurrentThread does fail. But somehow
    // CHECK(sequence_checker_.CalledOnValidSequence()) does not.
    ::testing::FLAGS_gtest_death_test_style = "threadsafe";
  }
  DpslRpcServerImplBaseDeathTest(const DpslRpcServerImplBaseDeathTest&) =
      delete;
  DpslRpcServerImplBaseDeathTest& operator=(
      const DpslRpcServerImplBaseDeathTest&) = delete;
};

TEST_F(DpslRpcServerImplBaseDeathTest, CreateWithNullThreadContext) {
  EXPECT_DEATH(DpslRpcServer::Create(nullptr, &mock_handler_,
                                     DpslRpcServer::GrpcServerUri::kVmVsock),
               "Thread context is nullptr");
}

TEST_F(DpslRpcServerImplBaseDeathTest, CreateWithNullRpcHandler) {
  EXPECT_DEATH(DpslRpcServer::Create(thread_context_.get(), nullptr,
                                     DpslRpcServer::GrpcServerUri::kVmVsock),
               "Rpc handler is nullptr");
}

TEST_F(DpslRpcServerImplBaseDeathTest, CreateWithInvalidServerUri) {
  EXPECT_DEATH(DpslRpcServer::Create(thread_context_.get(), &mock_handler_,
                                     kGrpcServerUriInvalidValue),
               "Unexpected GrpcServerUri");
}

TEST_F(DpslRpcServerImplBaseDeathTest, MultiThreadInvalidThreadContext) {
  TestDpslBackgroundThread background_thread(
      "background", global_context_.get(), thread_context_.get());

  EXPECT_DEATH(
      DpslRpcServer::Create(background_thread.thread_context(), &mock_handler_,
                            kGrpcServerUriInvalidValue),
      "Called from wrong thread");
}

// This is a parameterized test with the following parameters:
// * |grpc_server_uri| - gRPC server URI.
class DpslRpcServerImplTest
    : public DpslRpcServerImplBaseTest,
      public testing::WithParamInterface<DpslRpcServer::GrpcServerUri> {
 public:
  DpslRpcServerImplTest() = default;
  DpslRpcServerImplTest(const DpslRpcServerImplTest&) = delete;
  DpslRpcServerImplTest& operator=(const DpslRpcServerImplTest&) = delete;

  DpslRpcServer::GrpcServerUri grpc_server_uri() const { return GetParam(); }
};

TEST_P(DpslRpcServerImplTest, CreateUsingVsock) {
  EXPECT_TRUE(DpslRpcServer::Create(thread_context_.get(), &mock_handler_,
                                    grpc_server_uri()));
}

TEST_P(DpslRpcServerImplTest, CreateUsingVsockTwiceOnAvailableAddress) {
  // DpslRpcServer will be destroyed before the next call.
  EXPECT_TRUE(DpslRpcServer::Create(thread_context_.get(), &mock_handler_,
                                    grpc_server_uri()));

  EXPECT_TRUE(DpslRpcServer::Create(thread_context_.get(), &mock_handler_,
                                    grpc_server_uri()));
}

TEST_P(DpslRpcServerImplTest, CreateUsingVsockTwiceOnInUseAddress) {
  auto dpsl_rpc_server = DpslRpcServer::Create(
      thread_context_.get(), &mock_handler_, grpc_server_uri());
  EXPECT_TRUE(dpsl_rpc_server);

  EXPECT_FALSE(DpslRpcServer::Create(thread_context_.get(), &mock_handler_,
                                     grpc_server_uri()));
}

INSTANTIATE_TEST_SUITE_P(
    ,
    DpslRpcServerImplTest,
    testing::Values(DpslRpcServer::GrpcServerUri::kVmVsock,
                    DpslRpcServer::GrpcServerUri::kUiMessageReceiverVmVsock));

// This is a parameterized test with the following parameters:
// * |grpc_server_uri| - gRPC server URI.
//
// Use UNIX socket for actual communication in tests between server(HOST) and
// client(HOST) since VSOCK can be used only for real HOST-VM communication.
//
// This class is still parameterized, because the behavior of DpslRpcServer
// depends on the URI.
class DpslRpcServerImplUnixSocketTest : public DpslRpcServerImplTest {
 public:
  DpslRpcServerImplUnixSocketTest() = default;
  DpslRpcServerImplUnixSocketTest(const DpslRpcServerImplUnixSocketTest&) =
      delete;
  DpslRpcServerImplUnixSocketTest& operator=(
      const DpslRpcServerImplUnixSocketTest&) = delete;

  ~DpslRpcServerImplUnixSocketTest() override = default;

  void SetUp() override {
    DpslRpcServerImplBaseTest::SetUp();

    ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());

    dpsl_rpc_server_ = std::make_unique<DpslRpcServerImpl>(
        &mock_handler_, grpc_server_uri(), grpc_server_uri_string());
    ASSERT_TRUE(dpsl_rpc_server_->Init());

    wilco_dtc_grpc_client_ =
        std::make_unique<brillo::AsyncGrpcClient<grpc_api::WilcoDtc>>(
            base::ThreadTaskRunnerHandle::Get(), grpc_server_uri_string());
  }

  void TearDown() override {
    wilco_dtc_grpc_client_->ShutDown(base::Bind(
        [](DpslThreadContext* thread_context) {
          ASSERT_TRUE(thread_context);
          thread_context->QuitEventLoop();
        },
        thread_context_.get()));
    thread_context_->RunEventLoop();

    DpslRpcServerImplTest::TearDown();
  }

  std::string grpc_server_uri_string() const {
    return base::StringPrintf("unix:%s/test_wilco_dtc_socket",
                              temp_dir_.GetPath().value().c_str());
  }

  template <typename ClientRpcPtr,
            typename ProtoRequest,
            typename ProtoResponse>
  void SendGrpcRequestAndCheckResponse(const ClientRpcPtr client_rpc_ptr,
                                       const ProtoRequest& request,
                                       const ProtoResponse& response) {
    wilco_dtc_grpc_client_->CallRpc(
        client_rpc_ptr, request,
        base::Bind(
            [](DpslThreadContext* thread_context,
               const ProtoResponse& expected_response, grpc::Status status,
               std::unique_ptr<ProtoResponse> response) {
              ASSERT_TRUE(thread_context);
              EXPECT_TRUE(status.ok());
              ASSERT_TRUE(response);
              EXPECT_TRUE(google::protobuf::util::MessageDifferencer::Equals(
                  *response, expected_response));
              thread_context->QuitEventLoop();
            },
            thread_context_.get(), response));
    thread_context_->RunEventLoop();
  }

 protected:
  base::ScopedTempDir temp_dir_;

  std::unique_ptr<brillo::AsyncGrpcClient<grpc_api::WilcoDtc>>
      wilco_dtc_grpc_client_;
  std::unique_ptr<DpslRpcServerImpl> dpsl_rpc_server_;
};

TEST_P(DpslRpcServerImplUnixSocketTest, HandleMessageFromUi) {
  grpc_api::HandleMessageFromUiRequest request;
  request.set_json_message("{'message': 'ping'}");

  // Only RPC server which using kUiMessageReceiverVmVsock URI can receive
  // HandleMessageFromUiRequest messages.
  if (grpc_server_uri() !=
      DpslRpcServer::GrpcServerUri::kUiMessageReceiverVmVsock) {
    wilco_dtc_grpc_client_->CallRpc(
        &grpc_api::WilcoDtc::Stub::AsyncHandleMessageFromUi, request,
        base::Bind(
            [](DpslThreadContext* thread_context, grpc::Status status,
               std::unique_ptr<grpc_api::HandleMessageFromUiResponse>
                   response) {
              ASSERT_TRUE(thread_context);
              EXPECT_FALSE(status.ok());
              thread_context->QuitEventLoop();
            },
            thread_context_.get()));
    thread_context_->RunEventLoop();
    return;
  }

  grpc_api::HandleMessageFromUiResponse response;
  response.set_response_json_message("{'message': 'pong'}");

  EXPECT_CALL(mock_handler_, HandleMessageFromUiImpl(ProtobufEquals(request)))
      .WillOnce(ReturnRef(response));
  SendGrpcRequestAndCheckResponse(
      &grpc_api::WilcoDtc::Stub::AsyncHandleMessageFromUi, request, response);
}

TEST_P(DpslRpcServerImplUnixSocketTest, HandleEcNotification) {
  grpc_api::HandleEcNotificationRequest request;
  request.set_type(20);
  request.set_payload("abcdef");

  grpc_api::HandleEcNotificationResponse response;

  EXPECT_CALL(mock_handler_, HandleEcNotificationImpl(ProtobufEquals(request)))
      .WillOnce(ReturnRef(response));
  SendGrpcRequestAndCheckResponse(
      &grpc_api::WilcoDtc::Stub::AsyncHandleEcNotification, request, response);
}

TEST_P(DpslRpcServerImplUnixSocketTest, HandlePowerNotification) {
  grpc_api::HandlePowerNotificationRequest request;
  request.set_power_event(grpc_api::HandlePowerNotificationRequest::OS_SUSPEND);

  grpc_api::HandlePowerNotificationResponse response;

  EXPECT_CALL(mock_handler_,
              HandlePowerNotificationImpl(ProtobufEquals(request)))
      .WillOnce(ReturnRef(response));
  SendGrpcRequestAndCheckResponse(
      &grpc_api::WilcoDtc::Stub::AsyncHandlePowerNotification, request,
      response);
}

TEST_P(DpslRpcServerImplUnixSocketTest, HandleConfigurationDataChanged) {
  grpc_api::HandleConfigurationDataChangedRequest request;

  grpc_api::HandleConfigurationDataChangedResponse response;

  EXPECT_CALL(mock_handler_,
              HandleConfigurationDataChangedImpl(ProtobufEquals(request)))
      .WillOnce(ReturnRef(response));
  SendGrpcRequestAndCheckResponse(
      &grpc_api::WilcoDtc::Stub::AsyncHandleConfigurationDataChanged, request,
      response);
}

TEST_P(DpslRpcServerImplUnixSocketTest, HandleBluetoothDataChanged) {
  grpc_api::HandleBluetoothDataChangedRequest request;
  grpc_api::HandleBluetoothDataChangedRequest::AdapterData* adapter_data =
      request.add_adapters();

  adapter_data->set_adapter_name("sarien");
  adapter_data->set_adapter_mac_address("00:11:22:33:44:55");
  adapter_data->set_carrier_status(
      grpc_api::HandleBluetoothDataChangedRequest::AdapterData::STATUS_UP);
  adapter_data->set_connected_devices_count(1);

  grpc_api::HandleBluetoothDataChangedResponse response;

  EXPECT_CALL(mock_handler_,
              HandleBluetoothDataChangedImpl(ProtobufEquals(request)))
      .WillOnce(ReturnRef(response));
  SendGrpcRequestAndCheckResponse(
      &grpc_api::WilcoDtc::Stub::AsyncHandleBluetoothDataChanged, request,
      response);
}

INSTANTIATE_TEST_SUITE_P(
    ,
    DpslRpcServerImplUnixSocketTest,
    testing::Values(DpslRpcServer::GrpcServerUri::kVmVsock,
                    DpslRpcServer::GrpcServerUri::kUiMessageReceiverVmVsock));

}  // namespace diagnostics
