// Copyright 2024 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.

#ifndef LIB_DRIVER_TESTING_CPP_DRIVER_TEST_H_
#define LIB_DRIVER_TESTING_CPP_DRIVER_TEST_H_

#include <lib/async_patterns/testing/cpp/dispatcher_bound.h>
#include <lib/driver/testing/cpp/internal/internals.h>

// This library provides RAII-style classes for writing driver unit tests. It contains two classes,
// |ForegroundDriverTest| and |BackgroundDriverTest| that contain all the logic for a driver test.
// These classes can also be used directly in a test as a test fixture field, or as a local in a
// non-fixture based test method. This should be the first field or local that is being created.
//
// The choice between foreground and background driver tests lies in how the test plans to
// communicate with the driver-under-test. If the test will be calling public methods on the driver
// a lot, the foreground driver test should be chosen. If the test will be calling through the
// driver's exposed FIDL more often, then the background driver test should be chosen.
//
// Both test kinds can be configured through a struct/class provided through a template parameter.
// This configuration must define two types through using statements:
//
//   DriverType: The type of the driver under test.
//     If using a test-specific driver, ensure the DriverType contains a static function
//     in the format below. This registration is what the test uses to manage the driver.
//       `static DriverRegistration GetDriverRegistration()`
//     If the driver type is not known to the test, or is not needed by the test, then use the
//     |EmptyDriverType| class as a placeholder.
//
//   EnvironmentType: A class that contains environment dependencies of the driver-under-test.
//     This must inherit from the |Environment| base class and provide the |Serve| method.
//     It must also contain a default constructor.
//     The environment will live on a background dispatcher during the lifetime of the test.
namespace fdf_testing {

// The configuration must be given a non-void DriverType, but not all tests need access to a
// driver type (eg. they don't need to access or call anything on the driver class). This can be
// used as a placeholder to avoid build errors. The driver lifecycle is managed separately, through
// the `__fuchsia_driver_registration__` symbol, or through its custom registration provided with
// GetDriverRegistration.
class EmptyDriverType {};

// The EnvironmentType must implement this class.
class Environment {
 public:
  virtual ~Environment() = default;
  // This function is called on the dispatcher context of the environment. The class should serve
  // its elements (eg. compat::DeviceServer, FIDL servers, etc...) to the |to_driver_vfs|.
  // This object is serving the incoming directory of the driver under test.
  virtual zx::result<> Serve(fdf::OutgoingDirectory& to_driver_vfs) = 0;
};

namespace internal {
// Common logic for both background and foreground driver tests.
//
// Both foreground and background test classes inherit from this common class and provide
// workflows for their specific threading-model.
//
// This class is not meant for direct use so its in the internal namespace.
template <typename Configuration>
class DriverTestCommon {
 public:
  using DriverType = typename ConfigurationExtractor<Configuration>::DriverType;
  using EnvironmentType = typename ConfigurationExtractor<Configuration>::EnvironmentType;

  DriverTestCommon()
      : env_dispatcher_(runtime_.StartBackgroundDispatcher()),
        env_wrapper_(env_dispatcher_->async_dispatcher(), std::in_place) {}

  virtual ~DriverTestCommon() = default;

  // Access the driver runtime object. This can be used to create new background dispatchers
  // or to run the foreground dispatcher.
  fdf_testing::DriverRuntime& runtime() { return runtime_; }

  // Connects to a service member that the driver under test provides.
  template <typename ServiceMember,
            typename = std::enable_if_t<fidl::IsServiceMemberV<ServiceMember>>>
  zx::result<fidl::internal::ClientEndType<typename ServiceMember::ProtocolType>> Connect(
      std::string_view instance = component::kDefaultInstance) {
    if constexpr (std::is_same_v<typename ServiceMember::ProtocolType::Transport,
                                 fidl::internal::ChannelTransport>) {
      return component::ConnectAtMember<ServiceMember>(ConnectToDriverSvcDir(), instance);
    } else if constexpr (std::is_same_v<typename ServiceMember::ProtocolType::Transport,
                                        fidl::internal::DriverTransport>) {
      return fdf::internal::DriverTransportConnect<ServiceMember>(ConnectToDriverSvcDir(),
                                                                  instance);
    } else {
      static_assert(std::false_type{});
    }
  }

  // Runs a task on the dispatcher context of the EnvironmentType. This will be a different thread
  // than the main test thread, so be careful when capturing and returning pointers to objects that
  // live on different dispatchers like test fixture properties, or the driver.
  //
  // Returns the result of the given task once it has completed.
  template <typename T>
  T RunInEnvironmentTypeContext(fit::callback<T(EnvironmentType&)> task) {
    return env_wrapper_.SyncCall(
        [env_task = std::move(task)](EnvWrapper<EnvironmentType>* env_ptr) mutable {
          return env_task(env_ptr->user_env());
        });
  }

  // Runs a task on the dispatcher context of the EnvironmentType. This will be a different thread
  // than the main test thread, so be careful when capturing and returning pointers to objects that
  // live on different dispatchers like test fixture properties, or the driver.
  //
  // Returns when the given task has completed.
  void RunInEnvironmentTypeContext(fit::callback<void(EnvironmentType&)> task) {
    env_wrapper_.SyncCall(
        [env_task = std::move(task)](EnvWrapper<EnvironmentType>* env_ptr) mutable {
          env_task(env_ptr->user_env());
        });
  }

  // Runs a task on the dispatcher context of the TestNode. This will be a different thread than
  // the main test thread, so be careful when capturing and returning pointers to objects that live
  // on different dispatchers like test fixture properties, or the driver.
  //
  // Returns the result of the given task once it has completed.
  template <typename T>
  T RunInNodeContext(fit::callback<T(fdf_testing::TestNode&)> task) {
    return env_wrapper_.SyncCall(
        [node_task = std::move(task)](EnvWrapper<EnvironmentType>* env_ptr) mutable {
          return node_task(env_ptr->node_server());
        });
  }

  // Runs a task on the dispatcher context of the TestNode. This will be a different thread than
  // the main test thread, so be careful when capturing and returning pointers to objects that live
  // on different dispatchers like test fixture properties, or the driver.
  //
  // Returns when the given task has completed.
  void RunInNodeContext(fit::callback<void(fdf_testing::TestNode&)> task) {
    env_wrapper_.SyncCall(
        [node_task = std::move(task)](EnvWrapper<EnvironmentType>* env_ptr) mutable {
          node_task(env_ptr->node_server());
        });
  }

  // Connect to a zircon transport based protocol through a devfs node that the driver under test
  // exports. The |devfs_node_name| is the name of the created node with the 'devfs_args'. This
  // node must have been created through the driver's immediate node. If the devfs node is nested,
  // use the variant that takes a vector of strings.
  template <typename ProtocolType, typename = std::enable_if_t<fidl::IsProtocolV<ProtocolType>>>
  zx::result<fidl::ClientEnd<ProtocolType>> ConnectThroughDevfs(std::string_view devfs_node_name) {
    return ConnectThroughDevfs<ProtocolType>(std::vector{std::string(devfs_node_name)});
  }

  // Connect to a zircon transport based protocol through a devfs node that the driver under test
  // exports. The |devfs_node_name_path| is a list of node names that should be traversed to reach
  // the devfs node. The last element in the vector is the name of the created node with the
  // 'devfs_args'.
  template <typename ProtocolType, typename = std::enable_if_t<fidl::IsProtocolV<ProtocolType>>>
  zx::result<fidl::ClientEnd<ProtocolType>> ConnectThroughDevfs(
      std::vector<std::string> devfs_node_name_path) {
    zx::result<zx::channel> raw_channel_result =
        env_wrapper_.SyncCall([devfs_node_name_path = std::move(devfs_node_name_path)](
                                  EnvWrapper<EnvironmentType>* env_ptr) mutable {
          fdf_testing::TestNode* current = &env_ptr->node_server();
          for (auto& node : devfs_node_name_path) {
            current = &current->children().at(node);
          }

          return current->ConnectToDevice();
        });
    if (raw_channel_result.is_error()) {
      return raw_channel_result.take_error();
    }

    return zx::ok(fidl::ClientEnd<ProtocolType>(std::move(raw_channel_result.value())));
  }

  // Start the driver.
  zx::result<> StartDriver() {
    ZX_ASSERT_MSG(
        !start_result_.has_value(),
        "Cannot call |StartDriver| multiple times in a row. If multiple starts are needed, "
        "ensure to go through |StopDriver| and |ShutdownAndDestroyDriver| first.");

    fdf::DriverStartArgs start_args = env_wrapper_.SyncCall(&EnvWrapper<EnvironmentType>::Init);
    outgoing_directory_client_ =
        env_wrapper_.SyncCall(&EnvWrapper<EnvironmentType>::TakeOutgoingClient);

    AddServiceValidation(start_args);

    start_result_ = StartDriverInner(std::move(start_args));
    return *start_result_;
  }

  // Start the driver with modified DriverStartArgs. This is done through the |args_modifier|
  // which is called with a reference to the start args that will be used to start the driver.
  // Modifications can happen in-place with this reference.
  zx::result<> StartDriverWithCustomStartArgs(
      fit::callback<void(fdf::DriverStartArgs&)> args_modifier) {
    ZX_ASSERT_MSG(
        !start_result_.has_value(),
        "Cannot call |StartDriver| multiple times in a row. If multiple starts are needed, "
        "ensure to go through |StopDriver| and |ShutdownAndDestroyDriver| first.");

    fdf::DriverStartArgs start_args = env_wrapper_.SyncCall(&EnvWrapper<EnvironmentType>::Init);
    outgoing_directory_client_ =
        env_wrapper_.SyncCall(&EnvWrapper<EnvironmentType>::TakeOutgoingClient);
    args_modifier(start_args);

    AddServiceValidation(start_args);

    start_result_ = StartDriverInner(std::move(start_args));
    return *start_result_;
  }

  // Stops the driver by calling the driver's PrepareStop hook and waiting for it to complete.
  zx::result<> StopDriver() {
    ZX_ASSERT_MSG(start_result_.has_value(), "Cannot stop without having started.");
    ZX_ASSERT_MSG(!prepare_stop_result_.has_value(),
                  "Ensure |StopDriver| is only called once after a |StartDriver| call.");

    if (StartedSuccessfully()) {
      prepare_stop_result_ = StopDriverInner();
    } else {
      // Drivers that failed to stop don't receive a PrepareStop call. Set the result as ok so
      // that the teardown continues successfully.
      prepare_stop_result_ = zx::ok();
    }

    return *prepare_stop_result_;
  }

  // Shuts down the driver dispatchers fully, and then calls the driver's destroy hook.
  // Can be called multiple times, but it will only do the required work the first time.
  //
  // If the driver running was started successfully, this must be called after |StopDriver|.
  void ShutdownAndDestroyDriver() {
    // Allow for calling this method multiple times, but only do this work the first time.
    if (DriverExists()) {
      if (StartedSuccessfully()) {
        ZX_ASSERT_MSG(prepare_stop_result_.has_value(),
                      "Ensure |ShutdownAndDestroyDriver| is only called once after "
                      "a |StopDriver| call when start was successful.");
      }

      // This will shut down the driver dispatcher (and sub-dispatchers) and call the driver's
      // destroy hook.
      ShutdownAndDestroyDriverInner();

      // Reset the start_result_ and prepare_stop_result_ to allow another iteration of the driver.
      start_result_.reset();
      prepare_stop_result_.reset();
    }
  }

  fidl::ClientEnd<fuchsia_io::Directory> ConnectToDriverSvcDir() {
    auto [client_end, server_end] = fidl::Endpoints<fuchsia_io::Directory>::Create();
    zx_status_t status = fdio_open3_at(
        outgoing_directory_client_.handle()->get(), "/svc",
        uint64_t{fuchsia_io::wire::kPermReadable | fuchsia_io::wire::Flags::kProtocolDirectory},
        server_end.TakeChannel().release());
    ZX_ASSERT_MSG(ZX_OK == status, "Failed to fdio_open3_at '/svc' on the driver's outgoing: %s.",
                  zx_status_get_string(status));
    return std::move(client_end);
  }

  // This will enable the service instance validation on the driver. Equivalent to setting
  // `service_connect_validation: "true"` in the cml of the driver.
  // This must be called before |StartDriver|/|StartDriverWithCustomStartArgs| as it will only
  // take affect on the next start of the driver and cannot modify an already started driver.
  void SetServiceValidator(bool enable) { enable_service_connect_validation_ = enable; }

 private:
  virtual zx::result<> StartDriverInner(fdf::DriverStartArgs start_args) = 0;
  virtual zx::result<> StopDriverInner() = 0;
  virtual bool DriverExists() = 0;
  virtual void ShutdownAndDestroyDriverInner() = 0;

  bool StartedSuccessfully() const { return start_result_.has_value() && start_result_->is_ok(); }

  void AddServiceValidation(fdf::DriverStartArgs& start_args) {
    if (enable_service_connect_validation_) {
      if (start_args.program() == std::nullopt) {
        start_args.program(fuchsia_data::Dictionary{});
      }

      if (start_args.program()->entries() == std::nullopt) {
        start_args.program().value().entries(std::vector<fuchsia_data::DictionaryEntry>{});
      }

      start_args.program()->entries()->push_back(fuchsia_data::DictionaryEntry(
          "service_connect_validation", std::make_unique<fuchsia_data::DictionaryValue>(
                                            fuchsia_data::DictionaryValue::WithStr("true"))));
    }
  }

  fdf_testing::DriverRuntime runtime_;
  fdf::UnownedSynchronizedDispatcher env_dispatcher_;

  async_patterns::TestDispatcherBound<EnvWrapper<EnvironmentType>> env_wrapper_;

  fidl::ClientEnd<fuchsia_io::Directory> outgoing_directory_client_;
  std::optional<zx::result<>> start_result_;
  std::optional<zx::result<>> prepare_stop_result_;

  bool enable_service_connect_validation_ = false;
};

}  // namespace internal

// Background driver tests have the driver-under-test executing on a background driver dispatcher.
// This allows for tests to use sync FIDL clients directly from their main test thread.
// This is good for unit tests that more heavily exercise the driver-under-test through its exposed
// FIDL services, rather than its public methods.
//
// The test can run tasks on the driver context using the |RunInDriverContext()| methods, but sync
// client tasks can be run directly on the main test thread.
template <typename Configuration>
class BackgroundDriverTest final : public internal::DriverTestCommon<Configuration> {
  using DriverType = typename Configuration::DriverType;

 public:
  ~BackgroundDriverTest() { this->ShutdownAndDestroyDriver(); }

  // Runs a task on the dispatcher context of the driver under test. This will be a different
  // thread than the main test thread, so be careful when capturing and returning pointers to
  // objects that live on different dispatchers like test fixture properties, or the environment.
  //
  // Returns the result of the given task once it has completed.
  template <typename T>
  T RunInDriverContext(fit::callback<T(DriverType&)> task) {
    ZX_ASSERT_MSG(dut_.has_value(),
                  "Cannot call RunInDriverContext after |ShutdownAndDestroyDriver|.");
    return dut_->SyncCall([driver_task = std::move(task)](
                              fdf_testing::internal::DriverUnderTest<DriverType>* dut_ptr) mutable {
      return driver_task(***dut_ptr);
    });
  }

  // Runs a task on the dispatcher context of the driver under test. This will be a different
  // thread than the main test thread, so be careful when capturing and returning pointers to
  // objects that live on different dispatchers like test fixture properties, or the environment.
  //
  // Returns when the given task has completed.
  void RunInDriverContext(fit::callback<void(DriverType&)> task) {
    ZX_ASSERT_MSG(dut_.has_value(),
                  "Cannot call RunInDriverContext after |ShutdownAndDestroyDriver|.");
    dut_->SyncCall([driver_task = std::move(task)](
                       fdf_testing::internal::DriverUnderTest<DriverType>* dut_ptr) mutable {
      driver_task(***dut_ptr);
    });
  }

 private:
  zx::result<> StartDriverInner(fdf::DriverStartArgs start_args) override {
    DriverRegistration symbol;
    if constexpr (internal::HasGetDriverRegistrationV<DriverType>) {
      symbol = DriverType::GetDriverRegistration();
    } else {
      symbol = __fuchsia_driver_registration__;
    }

    dut_dispatcher_ = this->runtime().StartBackgroundDispatcher();
    dut_.emplace(dut_dispatcher_->async_dispatcher(), std::in_place, symbol);

    return this->runtime().RunToCompletion(dut_->SyncCall(
        &fdf_testing::internal::DriverUnderTest<DriverType>::Start, std::move(start_args)));
  }

  zx::result<> StopDriverInner() override {
    return this->runtime().RunToCompletion(
        dut_->SyncCall(&fdf_testing::internal::DriverUnderTest<DriverType>::PrepareStop));
  }

  bool DriverExists() override { return dut_.has_value(); }

  void ShutdownAndDestroyDriverInner() override {
    this->runtime().ShutdownBackgroundDispatcher(dut_dispatcher_->get(),
                                                 [this]() { dut_.reset(); });
  }

  fdf::UnownedSynchronizedDispatcher dut_dispatcher_;
  std::optional<
      async_patterns::TestDispatcherBound<fdf_testing::internal::DriverUnderTest<DriverType>>>
      dut_;
};

// Foreground driver tests have the driver-under-test executing on the foreground (main) test
// thread. This allows for the test to directly reach into the driver to call methods on it.
// This is good for unit tests that more heavily test a driver through its public methods,
// rather than its exposed FIDL services.
//
// The test can access the driver under test using the |driver()| method and directly make calls
// into it, but sync client tasks must go through |RunOnBackgroundDispatcherSync()|.
template <typename Configuration>
class ForegroundDriverTest final : public internal::DriverTestCommon<Configuration> {
  using DriverType = typename Configuration::DriverType;

 public:
  ~ForegroundDriverTest() { this->ShutdownAndDestroyDriver(); }

  // Runs a task in a background context while running the foreground driver. This must be used
  // if calling synchronously into the driver (eg. a fidl call through a SyncClient).
  //
  // Returns the result of the given task once it has completed.
  template <typename T>
  zx::result<T> RunOnBackgroundDispatcherSync(fit::callback<T()> task) {
    if (!bg_task_dispatcher_.has_value()) {
      bg_task_dispatcher_.emplace(this->runtime().StartBackgroundDispatcher());
    }

    libsync::Completion completion;
    std::optional<T> result_container;
    zx_status_t status =
        async::PostTask(bg_task_dispatcher_.value()->async_dispatcher(), [&]() mutable {
          result_container.emplace(task());
          completion.Signal();
        });

    if (status != ZX_OK) {
      return zx::error(status);
    }

    while (!completion.signaled()) {
      this->runtime().RunUntilIdle();
    }

    return zx::ok(std::move(result_container.value()));
  }

  // Runs a task in a background context while running the foreground driver. This must be used
  // if calling synchronously into the driver (eg. a fidl call through a SyncClient).
  //
  // Returns when the given task has completed.
  zx::result<> RunOnBackgroundDispatcherSync(fit::callback<void()> task) {
    if (!bg_task_dispatcher_.has_value()) {
      bg_task_dispatcher_.emplace(this->runtime().StartBackgroundDispatcher());
    }

    libsync::Completion completion;
    zx_status_t status =
        async::PostTask(bg_task_dispatcher_.value()->async_dispatcher(), [&]() mutable {
          task();
          completion.Signal();
        });

    if (status != ZX_OK) {
      return zx::error(status);
    }

    while (!completion.signaled()) {
      this->runtime().RunUntilIdle();
    }

    return zx::ok();
  }

  // Access the driver under test. Can only be called while the driver is active, after
  // |StartDriver| has been called, but before |ShutdownAndDestroyDriver|.
  DriverType* driver() {
    ZX_ASSERT_MSG(dut_.has_value(), "Cannot call |driver| after |ShutdownAndDestroyDriver|.");
    return *dut_.value();
  }

 private:
  zx::result<> StartDriverInner(fdf::DriverStartArgs start_args) override {
    DriverRegistration symbol;
    if constexpr (internal::HasGetDriverRegistrationV<DriverType>) {
      symbol = DriverType::GetDriverRegistration();
    } else {
      symbol = __fuchsia_driver_registration__;
    }

    dut_.emplace(symbol);
    return this->runtime().RunToCompletion(dut_->Start(std::move(start_args)));
  }

  zx::result<> StopDriverInner() override {
    return this->runtime().RunToCompletion(dut_->PrepareStop());
  }

  bool DriverExists() override { return dut_.has_value(); }
  void ShutdownAndDestroyDriverInner() override {
    this->runtime().ResetForegroundDispatcher([this]() { dut_.reset(); });
  }

  std::optional<fdf::UnownedSynchronizedDispatcher> bg_task_dispatcher_;
  std::optional<fdf_testing::internal::DriverUnderTest<DriverType>> dut_;
};

}  // namespace fdf_testing

#endif  // LIB_DRIVER_TESTING_CPP_DRIVER_TEST_H_
