// Copyright 2019 The Fuchsia 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 <fuchsia/device/manager/c/fidl.h>
#include <fuchsia/driver/test/c/fidl.h>
#include <lib/async-loop/cpp/loop.h>
#include <lib/async-loop/default.h>
#include <lib/fdio/directory.h>
#include <lib/fidl/coding.h>
#include <lib/fidl/cpp/message.h>
#include <lib/fidl/cpp/message_builder.h>
#include <string.h>
#include <threads.h>
#include <zircon/fidl.h>

#include <vector>

#include <ddk/binding.h>
#include <ddk/driver.h>
#include <fbl/algorithm.h>
#include <fbl/vector.h>
#include <zxtest/zxtest.h>

#include "coordinator_test_utils.h"
#include "devfs.h"
#include "driver_host.h"
#include "driver_test_reporter.h"
#include "fdio.h"

constexpr char kDriverPath[] = "/pkg/driver/test/mock-device.so";
constexpr char kLogMessage[] = "log message text";
constexpr char kLogTestCaseName[] = "log test case";

static CoordinatorConfig NullConfig() { return DefaultConfig(nullptr, nullptr, nullptr); }

// Reads a BindDriver request from remote, checks that it is for the expected
// driver, and then sends a ZX_OK response.
void BindDriverTestOutput(const zx::channel& remote, zx::channel test_output) {
  // Read the BindDriver request.
  FIDL_ALIGNDECL uint8_t bytes[ZX_CHANNEL_MAX_MSG_BYTES];
  zx_handle_t handles[ZX_CHANNEL_MAX_MSG_HANDLES];
  uint32_t actual_bytes;
  uint32_t actual_handles;
  zx_status_t status = remote.read(0, bytes, handles, sizeof(bytes), std::size(handles),
                                   &actual_bytes, &actual_handles);
  ASSERT_OK(status);
  ASSERT_LT(0, actual_bytes);
  ASSERT_EQ(1, actual_handles);
  status = zx_handle_close(handles[0]);
  ASSERT_OK(status);

  // Validate the BindDriver request.
  auto hdr = reinterpret_cast<fidl_message_header_t*>(bytes);
  ASSERT_EQ(fuchsia_device_manager_DeviceControllerBindDriverOrdinal, hdr->ordinal);
  status = fidl_decode(&fuchsia_device_manager_DeviceControllerBindDriverRequestTable, bytes,
                       actual_bytes, handles, actual_handles, nullptr);
  zx_txid_t txid = hdr->txid;
  ASSERT_OK(status);

  // Write the BindDriver response.
  memset(bytes, 0, sizeof(bytes));
  auto resp = reinterpret_cast<fuchsia_device_manager_DeviceControllerBindDriverResponse*>(bytes);
  fidl_init_txn_header(&resp->hdr, txid, fuchsia_device_manager_DeviceControllerBindDriverOrdinal);
  resp->status = ZX_OK;
  resp->test_output = test_output.release();
  status = fidl_encode(&fuchsia_device_manager_DeviceControllerBindDriverResponseTable, bytes,
                       sizeof(*resp), handles, std::size(handles), &actual_handles, nullptr);
  ASSERT_OK(status);
  ASSERT_EQ(1, actual_handles);
  status = remote.write(0, bytes, sizeof(*resp), handles, actual_handles);
  ASSERT_OK(status);
}

void WriteTestLog(const zx::channel& output) {
  uint32_t len =
      sizeof(fuchsia_driver_test_LoggerLogMessageRequest) + FIDL_ALIGN(strlen(kLogMessage));
  FIDL_ALIGNDECL uint8_t bytes[len];
  fidl::Builder builder(bytes, len);

  auto* req = builder.New<fuchsia_driver_test_LoggerLogMessageRequest>();
  fidl_init_txn_header(&req->hdr, FIDL_TXID_NO_RESPONSE,
                       fuchsia_driver_test_LoggerLogMessageOrdinal);

  auto* data = builder.NewArray<char>(static_cast<uint32_t>(strlen(kLogMessage)));
  req->msg.data = data;
  req->msg.size = strlen(kLogMessage);
  memcpy(data, kLogMessage, strlen(kLogMessage));

  fidl::HLCPPOutgoingMessage msg(builder.Finalize(), fidl::HandlePart());
  const char* err = nullptr;
  zx_status_t status = msg.Encode(&fuchsia_driver_test_LoggerLogMessageRequestTable, &err);
  ASSERT_OK(status);
  status = msg.Write(output.get(), 0);
  ASSERT_OK(status);
}

void WriteTestCase(const zx::channel& output) {
  uint32_t len =
      sizeof(fuchsia_driver_test_LoggerLogTestCaseRequest) + FIDL_ALIGN(strlen(kLogTestCaseName));
  FIDL_ALIGNDECL uint8_t bytes[len];
  fidl::Builder builder(bytes, len);

  auto* req = builder.New<fuchsia_driver_test_LoggerLogTestCaseRequest>();
  fidl_init_txn_header(&req->hdr, FIDL_TXID_NO_RESPONSE,
                       fuchsia_driver_test_LoggerLogTestCaseOrdinal);

  auto* data = builder.NewArray<char>(static_cast<uint32_t>(strlen(kLogTestCaseName)));
  req->name.data = data;
  req->name.size = strlen(kLogTestCaseName);
  memcpy(data, kLogTestCaseName, strlen(kLogTestCaseName));

  req->result.passed = 1;
  req->result.failed = 2;
  req->result.skipped = 3;

  fidl::HLCPPOutgoingMessage msg(builder.Finalize(), fidl::HandlePart());
  const char* err = nullptr;
  zx_status_t status = msg.Encode(&fuchsia_driver_test_LoggerLogTestCaseRequestTable, &err);
  ASSERT_OK(status);
  status = msg.Write(output.get(), 0);
  ASSERT_OK(status);
}

// Reads a BindDriver request from remote, checks that it is for the expected
// driver, and then sends a ZX_OK response.
void CheckBindDriverReceived(const zx::channel& remote, const char* expected_driver) {
  // Read the BindDriver request.
  FIDL_ALIGNDECL uint8_t bytes[ZX_CHANNEL_MAX_MSG_BYTES];
  zx_handle_t handles[ZX_CHANNEL_MAX_MSG_HANDLES];
  uint32_t actual_bytes;
  uint32_t actual_handles;
  zx_status_t status = remote.read(0, bytes, handles, sizeof(bytes), std::size(handles),
                                   &actual_bytes, &actual_handles);
  ASSERT_OK(status);
  ASSERT_LT(0, actual_bytes);
  ASSERT_EQ(1, actual_handles);
  status = zx_handle_close(handles[0]);
  ASSERT_OK(status);

  // Validate the BindDriver request.
  auto hdr = reinterpret_cast<fidl_message_header_t*>(bytes);
  ASSERT_EQ(fuchsia_device_manager_DeviceControllerBindDriverOrdinal, hdr->ordinal);
  status = fidl_decode(&fuchsia_device_manager_DeviceControllerBindDriverRequestTable, bytes,
                       actual_bytes, handles, actual_handles, nullptr);
  zx_txid_t txid = hdr->txid;
  ASSERT_OK(status);
  auto req = reinterpret_cast<fuchsia_device_manager_DeviceControllerBindDriverRequest*>(bytes);
  ASSERT_EQ(req->driver_path.size, strlen(expected_driver));
  ASSERT_BYTES_EQ(reinterpret_cast<const uint8_t*>(expected_driver),
                  reinterpret_cast<const uint8_t*>(req->driver_path.data), req->driver_path.size,
                  "");

  // Write the BindDriver response.
  memset(bytes, 0, sizeof(bytes));
  auto resp = reinterpret_cast<fuchsia_device_manager_DeviceControllerBindDriverResponse*>(bytes);
  fidl_init_txn_header(&resp->hdr, txid, fuchsia_device_manager_DeviceControllerBindDriverOrdinal);
  resp->status = ZX_OK;
  status = fidl_encode(&fuchsia_device_manager_DeviceControllerBindDriverResponseTable, bytes,
                       sizeof(*resp), handles, std::size(handles), &actual_handles, nullptr);
  ASSERT_OK(status);
  ASSERT_EQ(0, actual_handles);
  status = remote.write(0, bytes, sizeof(*resp), nullptr, 0);
  ASSERT_OK(status);
}

class TestDriverTestReporter : public DriverTestReporter {
 public:
  explicit TestDriverTestReporter(const fbl::String& driver_name)
      : DriverTestReporter(driver_name) {}

  void LogMessage(const char* msg, size_t size) override {
    if (size != strlen(kLogMessage)) {
      return;
    }
    if (strncmp(msg, kLogMessage, size)) {
      return;
    }
    log_message_called = true;
  }

  void LogTestCase(const char* name, size_t name_size,
                   const fuchsia_driver_test_TestCaseResult* result) override {
    if (name_size != strlen(kLogTestCaseName)) {
      return;
    }
    if (strncmp(name, kLogTestCaseName, name_size)) {
      return;
    }
    if (result->passed != 1 || result->failed != 2 || result->skipped != 3) {
      return;
    }
    log_test_case_called = true;
  }

  void TestStart() override { start_called = true; }

  void TestFinished() override { finished_called = true; }

  bool log_message_called = false;
  bool log_test_case_called = false;
  bool start_called = false;
  bool finished_called = false;
};

TEST(MiscTestCase, InitCoreDevices) {
  Coordinator coordinator(NullConfig(), nullptr);

  zx_status_t status = coordinator.InitCoreDevices(kSystemDriverPath);
  ASSERT_OK(status);
}

TEST(MiscTestCase, DumpState) {
  Coordinator coordinator(NullConfig(), nullptr);

  zx_status_t status = coordinator.InitCoreDevices(kSystemDriverPath);
  ASSERT_OK(status);

  constexpr int32_t kBufSize = 256;
  char buf[kBufSize + 1] = {0};

  zx::vmo vmo;
  ASSERT_OK(zx::vmo::create(kBufSize, 0, &vmo));
  VmoWriter writer(std::move(vmo));

  coordinator.DumpState(&writer);

  ASSERT_EQ(writer.written(), writer.available());
  ASSERT_LT(writer.written(), kBufSize);
  ASSERT_GT(writer.written(), 0);
  ASSERT_OK(writer.vmo().read(buf, 0, writer.written()));

  ASSERT_NE(nullptr, strstr(buf, "[root]"));
}

TEST(MiscTestCase, LoadDriver) {
  bool found_driver = false;
  auto callback = [&found_driver](Driver* drv, const char* version) {
    delete drv;
    found_driver = true;
  };
  load_driver(kDriverPath, callback);
  ASSERT_TRUE(found_driver);
}

TEST(MiscTestCase, BindDrivers) {
  async::Loop loop(&kAsyncLoopConfigNoAttachToCurrentThread);
  Coordinator coordinator(NullConfig(), loop.dispatcher());

  zx_status_t status = coordinator.InitCoreDevices(kSystemDriverPath);
  ASSERT_OK(status);
  coordinator.set_running(true);

  Driver* driver;
  auto callback = [&coordinator, &driver](Driver* drv, const char* version) {
    driver = drv;
    return coordinator.DriverAdded(drv, version);
  };
  load_driver(kDriverPath, callback);
  loop.RunUntilIdle();
  ASSERT_EQ(1, coordinator.drivers().size_slow());
  ASSERT_EQ(driver, &coordinator.drivers().front());
}

// Test binding drivers against the root/test/misc devices
TEST(MiscTestCase, BindDriversForBuiltins) {
  async::Loop loop(&kAsyncLoopConfigNoAttachToCurrentThread);
  Coordinator coordinator(NullConfig(), loop.dispatcher());

  zx_status_t status = coordinator.InitCoreDevices(kSystemDriverPath);
  ASSERT_OK(status);

  // AttemptBind function that asserts it has only been called once
  class CallOnce {
   public:
    explicit CallOnce(size_t line) : line_number_(line) {}
    CallOnce(const CallOnce&) = delete;
    CallOnce& operator=(const CallOnce&) = delete;

    CallOnce(CallOnce&& other) { *this = std::move(other); }
    CallOnce& operator=(CallOnce&& other) {
      if (this != &other) {
        line_number_ = other.line_number_;
        call_count_ = other.call_count_;
        // Ensure the dtor for the other one doesn't run
        other.call_count_ = 1;
      }
      return *this;
    }

    ~CallOnce() { EXPECT_EQ(1, call_count_, "Mismatch from line %zu\n", line_number_); }
    zx_status_t operator()(const Driver* drv, const fbl::RefPtr<Device>& dev) {
      ++call_count_;
      return ZX_OK;
    }

   private:
    size_t line_number_;
    size_t call_count_ = 0;
  };

  auto make_fake_driver = [](auto&& instructions) -> std::unique_ptr<Driver> {
    size_t instruction_count = std::size(instructions);
    auto binding = std::make_unique<zx_bind_inst_t[]>(instruction_count);
    memcpy(binding.get(), instructions, instruction_count * sizeof(instructions[0]));
    auto drv = std::make_unique<Driver>();
    drv->binding.reset(binding.release());
    drv->binding_size = static_cast<uint32_t>(instruction_count * sizeof(instructions[0]));
    return drv;
  };

  {
    zx_bind_inst_t test_drv_bind[] = {
        BI_MATCH_IF(EQ, BIND_PROTOCOL, ZX_PROTOCOL_TEST_PARENT),
    };
    auto test_drv = make_fake_driver(test_drv_bind);
    ASSERT_OK(coordinator.BindDriver(test_drv.get(), CallOnce{__LINE__}));
  }

  {
    zx_bind_inst_t misc_drv_bind[] = {
        BI_MATCH_IF(EQ, BIND_PROTOCOL, ZX_PROTOCOL_MISC_PARENT),
    };
    auto misc_drv = make_fake_driver(misc_drv_bind);
    ASSERT_OK(coordinator.BindDriver(misc_drv.get(), CallOnce{__LINE__}));
  }

  {
    zx_bind_inst_t root_drv_bind[] = {
        BI_MATCH_IF(EQ, BIND_PROTOCOL, ZX_PROTOCOL_ROOT),
    };
    auto root_drv = make_fake_driver(root_drv_bind);
    ASSERT_OK(coordinator.BindDriver(root_drv.get(), CallOnce{__LINE__}));
  }

  {
    zx_bind_inst_t test_drv_bind[] = {
        BI_MATCH_IF(EQ, BIND_PROTOCOL, ZX_PROTOCOL_TEST_PARENT),
        BI_MATCH_IF(EQ, BIND_PROTOCOL, ZX_PROTOCOL_I2C),
    };
    auto test_drv = make_fake_driver(test_drv_bind);
    ASSERT_OK(coordinator.BindDriver(test_drv.get(), CallOnce{__LINE__}));
  }

  {
    zx_bind_inst_t misc_drv_bind[] = {
        BI_MATCH_IF(EQ, BIND_PROTOCOL, ZX_PROTOCOL_MISC_PARENT),
        BI_MATCH_IF(EQ, BIND_PROTOCOL, ZX_PROTOCOL_I2C),
    };
    auto misc_drv = make_fake_driver(misc_drv_bind);
    ASSERT_OK(coordinator.BindDriver(misc_drv.get(), CallOnce{__LINE__}));
  }

  {
    zx_bind_inst_t root_drv_bind[] = {
        BI_MATCH_IF(EQ, BIND_PROTOCOL, ZX_PROTOCOL_ROOT),
        BI_MATCH_IF(EQ, BIND_PROTOCOL, ZX_PROTOCOL_I2C),
    };
    auto root_drv = make_fake_driver(root_drv_bind);
    ASSERT_OK(coordinator.BindDriver(root_drv.get(), CallOnce{__LINE__}));
  }
}

TEST(MiscTestCase, BindDevices) {
  async::Loop loop(&kAsyncLoopConfigNoAttachToCurrentThread);
  Coordinator coordinator(NullConfig(), loop.dispatcher());

  ASSERT_NO_FATAL_FAILURES(InitializeCoordinator(&coordinator));

  // Add the device.
  zx::channel coordinator_local, coordinator_remote;
  zx_status_t status = zx::channel::create(0, &coordinator_local, &coordinator_remote);
  ASSERT_OK(status);

  zx::channel controller_local, controller_remote;
  status = zx::channel::create(0, &controller_local, &controller_remote);
  ASSERT_OK(status);

  fbl::RefPtr<Device> device;
  status = coordinator.AddDevice(
      coordinator.test_device(), std::move(controller_local), std::move(coordinator_local),
      nullptr /* props_data */, 0 /* props_count */, "mock-device", ZX_PROTOCOL_TEST,
      {} /* driver_path */, {} /* args */, false /* invisible */, false /* skip_autobind */,
      false /* has_init */, true /* always_init */, zx::vmo() /*inspect*/,
      zx::channel() /* client_remote */, &device);
  ASSERT_OK(status);
  ASSERT_EQ(1, coordinator.devices().size_slow());

  // Add the driver.
  load_driver(kDriverPath, fit::bind_member(&coordinator, &Coordinator::DriverAdded));
  loop.RunUntilIdle();
  ASSERT_FALSE(coordinator.drivers().is_empty());

  // The device has no driver_host, so the init task should automatically complete.
  ASSERT_TRUE(device->is_visible());
  ASSERT_EQ(Device::State::kActive, device->state());

  // Bind the device to a fake driver_host.
  fbl::RefPtr<Device> dev = fbl::RefPtr(&coordinator.devices().front());
  auto host =
      fbl::MakeRefCounted<DriverHost>(&coordinator, zx::channel{}, zx::channel{}, zx::process{});
  dev->set_host(std::move(host));
  status = coordinator.BindDevice(dev, kDriverPath, true /* new device */);
  ASSERT_OK(status);

  // Check the BindDriver request.
  ASSERT_NO_FATAL_FAILURES(CheckBindDriverReceived(controller_remote, kDriverPath));
  loop.RunUntilIdle();

  // Reset the fake driver_host connection.
  dev->set_host(nullptr);
  coordinator_remote.reset();
  controller_remote.reset();
  loop.RunUntilIdle();
}

TEST(MiscTestCase, TestOutput) {
  async::Loop loop(&kAsyncLoopConfigNoAttachToCurrentThread);
  Coordinator coordinator(NullConfig(), loop.dispatcher());

  ASSERT_NO_FATAL_FAILURES(InitializeCoordinator(&coordinator));

  // Add the device.
  zx::channel coordinator_local, coordinator_remote;
  zx_status_t status = zx::channel::create(0, &coordinator_local, &coordinator_remote);
  ASSERT_OK(status);

  zx::channel controller_local, controller_remote;
  status = zx::channel::create(0, &controller_local, &controller_remote);
  ASSERT_OK(status);

  fbl::RefPtr<Device> device;
  status = coordinator.AddDevice(
      coordinator.test_device(), std::move(controller_local), std::move(coordinator_local),
      nullptr /* props_data */, 0 /* props_count */, "mock-device", ZX_PROTOCOL_TEST,
      {} /* driver_path */, {} /* args */, false /* invisible */, false /* skip_autobind */,
      false /* has_init */, true /* always_init */, zx::vmo() /*inspect*/,
      zx::channel() /* client_remote */, &device);
  ASSERT_OK(status);
  ASSERT_EQ(1, coordinator.devices().size_slow());

  fbl::String driver_name;
  auto test_reporter_ = std::make_unique<TestDriverTestReporter>(driver_name);
  auto* test_reporter = test_reporter_.get();
  device->test_reporter = std::move(test_reporter_);

  // Add the driver.
  load_driver(kDriverPath, fit::bind_member(&coordinator, &Coordinator::DriverAdded));
  loop.RunUntilIdle();
  ASSERT_FALSE(coordinator.drivers().is_empty());

  // The device has no driver_host, so the init task should automatically complete.
  ASSERT_TRUE(device->is_visible());
  ASSERT_EQ(Device::State::kActive, device->state());

  // Bind the device to a fake driver_host.
  fbl::RefPtr<Device> dev = fbl::RefPtr(&coordinator.devices().front());
  auto host =
      fbl::MakeRefCounted<DriverHost>(&coordinator, zx::channel{}, zx::channel{}, zx::process{});
  dev->set_host(std::move(host));
  status = coordinator.BindDevice(dev, kDriverPath, true /* new device */);
  ASSERT_OK(status);

  // Check the BindDriver request.
  zx::channel test_device, test_coordinator;
  zx::channel::create(0, &test_device, &test_coordinator);
  ASSERT_NO_FATAL_FAILURES(BindDriverTestOutput(controller_remote, std::move(test_coordinator)));
  loop.RunUntilIdle();

  ASSERT_NO_FATAL_FAILURES(WriteTestLog(test_device));
  ASSERT_NO_FATAL_FAILURES(WriteTestCase(test_device));
  loop.RunUntilIdle();

  // The test logging handlers should not be called until the test is finished and the channel is
  // closed.
  EXPECT_FALSE(test_reporter->start_called);
  EXPECT_FALSE(test_reporter->log_message_called);
  EXPECT_FALSE(test_reporter->log_test_case_called);
  EXPECT_FALSE(test_reporter->finished_called);

  test_device.reset();
  loop.RunUntilIdle();
  EXPECT_TRUE(test_reporter->start_called);
  EXPECT_TRUE(test_reporter->log_message_called);
  EXPECT_TRUE(test_reporter->log_test_case_called);
  EXPECT_TRUE(test_reporter->finished_called);

  // Reset the fake driver_host connection.
  dev->set_host(nullptr);
  controller_remote.reset();
  coordinator_remote.reset();
  loop.RunUntilIdle();
}

// Adds a device with the given properties to the device coordinator, then checks that the
// coordinator contains the device, and that its properties are correct.
void AddDeviceWithProperties(const llcpp::fuchsia::device::manager::DeviceProperty* props_data,
                             size_t props_count) {
  async::Loop loop(&kAsyncLoopConfigNoAttachToCurrentThread);
  Coordinator coordinator(NullConfig(), loop.dispatcher());

  ASSERT_NO_FATAL_FAILURES(InitializeCoordinator(&coordinator));

  zx::channel coordinator_local, coordinator_remote;
  zx_status_t status = zx::channel::create(0, &coordinator_local, &coordinator_remote);
  ASSERT_OK(status);

  zx::channel controller_local, controller_remote;
  status = zx::channel::create(0, &controller_local, &controller_remote);
  ASSERT_OK(status);

  fbl::RefPtr<Device> device;
  status = coordinator.AddDevice(
      coordinator.test_device(), std::move(controller_local), std::move(coordinator_local),
      props_data, props_count, "mock-device", ZX_PROTOCOL_TEST, {} /* driver_path */, {} /* args */,
      false /* invisible */, false /* skip_autobind */, false /* has_init */,
      true /* always_init */, zx::vmo() /*inspect*/, zx::channel() /* client_remote */, &device);
  ASSERT_OK(status);

  // Check that the device has been added to the coordinator, with the correct properties.
  ASSERT_EQ(1, coordinator.devices().size_slow());
  const Device& dev = coordinator.devices().front();
  ASSERT_EQ(dev.props().size(), props_count);
  for (size_t i = 0; i < props_count; i++) {
    ASSERT_EQ(dev.props()[i].id, props_data[i].id);
    ASSERT_EQ(dev.props()[i].reserved, props_data[i].reserved);
    ASSERT_EQ(dev.props()[i].value, props_data[i].value);
  }

  controller_remote.reset();
  coordinator_remote.reset();
  loop.RunUntilIdle();
}

TEST(MiscTestCase, DeviceProperties) {
  // No properties.
  AddDeviceWithProperties(nullptr, 0);

  // Multiple properties.
  llcpp::fuchsia::device::manager::DeviceProperty props[] = {
      llcpp::fuchsia::device::manager::DeviceProperty{1, 0, 1},
      llcpp::fuchsia::device::manager::DeviceProperty{2, 0, 1},
  };
  AddDeviceWithProperties(props, std::size(props));
}

int main(int argc, char** argv) { return RUN_ALL_TESTS(argc, argv); }
