// Copyright 2021 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 SRC_DEVICES_BIN_DRIVER_RUNTIME_RUNTIME_TEST_CASE_H_
#define SRC_DEVICES_BIN_DRIVER_RUNTIME_RUNTIME_TEST_CASE_H_

#include <lib/fdf/arena.h>
#include <lib/fdf/cpp/channel_read.h>
#include <lib/fdf/dispatcher.h>
#include <lib/fdf/types.h>
#include <lib/sync/completion.h>
#include <lib/sync/cpp/completion.h>
#include <lib/zx/event.h>

#include <zxtest/zxtest.h>

class RuntimeTestCase : public zxtest::Test {
 public:
  // Registers a wait_async request on |ch| and signals |completion| once it
  // is ready for reading.
  static void SignalOnChannelReadable(fdf_handle_t ch, fdf_dispatcher_t* dispatcher,
                                      sync_completion_t* completion);

  // Registers a wait_async request on |ch| and blocks until it is ready for reading.
  static void WaitUntilReadReady(fdf_handle_t ch, fdf_dispatcher_t* dispatcher);

  // Reads a message from |ch| and asserts that it matches the wanted parameters.
  // If |out_arena| is provided, it will be populated with the transferred arena.
  static void AssertRead(fdf_handle_t ch, void* want_data, size_t want_num_bytes,
                         zx_handle_t* want_handles, uint32_t want_num_handles,
                         fdf_arena_t** out_arena = nullptr);

  // Returns a fake driver pointer that can be used with driver_context APIs.
  // Do not try to access the internals of the pointer.
  const void* CreateFakeDriver() {
    // We don't actually need a real pointer.
    int driver = next_driver_;
    next_driver_++;
    return reinterpret_cast<const void*>(driver);
  }

  // Example usage:
  //   DispatcherShutdownObserver observer;
  //   driver_runtime::Dispatcher* dispatcher;
  //   fdf_status_t status =
  //       driver_runtime::Dispatcher::Create(..., observer.fdf_observer(), &dispatcher);
  //   ...
  //   dispatcher->Destroy();
  //   ASSERT_OK(observer.WaitUntilShutdown());
  class DispatcherShutdownObserver {
   public:
    // |require_callback| specifies whether the destructor will check that the callback was called.
    // This can be set to false for tests that expect construction of the dispatcher to fail,
    // but want to pass in a valid observer.
    explicit DispatcherShutdownObserver(bool require_callback = true)
        : require_callback_(require_callback) {
      observer_.fdf_observer.handler = DispatcherDestructedHandler;
    }

    ~DispatcherShutdownObserver() {
      if (require_callback_) {
        ASSERT_TRUE(observer_.signal.signaled());
      }
    }

    DispatcherShutdownObserver(const DispatcherShutdownObserver&) = delete;
    DispatcherShutdownObserver& operator=(const DispatcherShutdownObserver&) = delete;
    DispatcherShutdownObserver& operator=(DispatcherShutdownObserver&&) = delete;
    DispatcherShutdownObserver(DispatcherShutdownObserver&&) = delete;

    zx_status_t WaitUntilShutdown() { return observer_.signal.Wait(zx::time::infinite()); }

    // Returns the observer that can be passed to |driver_runtime::Dispatcher::Create|.
    fdf_dispatcher_shutdown_observer_t* fdf_observer() { return &observer_.fdf_observer; }

    // Returns the dispatcher that was shutdown, nullptr if no shutdown event has occurred.
    fdf_dispatcher_t* shutdown_dispatcher() { return shutdown_dispatcher_; }

   private:
    struct ShutdownObserver {
      fdf_dispatcher_shutdown_observer_t fdf_observer;
      libsync::Completion signal;
    };

    static void DispatcherDestructedHandler(fdf_dispatcher_t* dispatcher,
                                            fdf_dispatcher_shutdown_observer_t* fdf_observer) {
      DispatcherShutdownObserver* observer =
          reinterpret_cast<DispatcherShutdownObserver*>(fdf_observer);
      observer->shutdown_dispatcher_ = dispatcher;
      observer->observer_.signal.Signal();
    }

    ShutdownObserver observer_;
    bool require_callback_;
    fdf_dispatcher_t* shutdown_dispatcher_ = nullptr;
  };

 private:
  int next_driver_ = 1;
};

#endif  // SRC_DEVICES_BIN_DRIVER_RUNTIME_RUNTIME_TEST_CASE_H_
