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

#ifndef SRC_DEVICES_TESTS_LIBDRIVER_INTEGRATION_TEST_INTEGRATION_TEST_H_
#define SRC_DEVICES_TESTS_LIBDRIVER_INTEGRATION_TEST_INTEGRATION_TEST_H_

#include <fuchsia/io/cpp/fidl.h>
#include <lib/async-loop/cpp/loop.h>
#include <lib/async-loop/default.h>
#include <lib/async/cpp/wait.h>
#include <lib/devmgr-integration-test/fixture.h>
#include <lib/fit/promise.h>
#include <lib/zx/channel.h>
#include <lib/zx/time.h>

#include <memory>

#include <gtest/gtest.h>

#include "mock-device-hooks.h"
#include "mock-device.h"
#include "root-mock-device.h"

// Wrapper for an assert that converts a failure to a return of a // fit::promise<void, const char*>
// that resolves immediately to a fit::error()
#define PROMISE_ASSERT(assertion)                                       \
  do {                                                                  \
    [&]() { assertion; }();                                             \
    if (testing::Test::HasFatalFailure()) {                             \
      return fit::make_error_promise(std::string("Assertion failure")); \
    }                                                                   \
  } while (0)

// Wrapper for an assert that converts a failure to a return of a fit::error()
#define ERROR_ASSERT(assertion)                            \
  do {                                                     \
    [&]() { assertion; }();                                \
    if (testing::Test::HasFatalFailure()) {                \
      return fit::error(std::string("Assertion failure")); \
    }                                                      \
  } while (0)

namespace libdriver_integration_test {

class IntegrationTest : public testing::Test {
 public:
  static void SetUpTestCase();
  static void TearDownTestCase();

  IntegrationTest();
  ~IntegrationTest();

  void SetUp() override;

  using Error = std::string;
  template <class T>
  using Result = fit::result<T, Error>;
  template <class T>
  using Promise = fit::promise<T, Error>;
  template <class T>
  using Completer = fit::completer<T, Error>;
  using HookInvocation = fuchsia::device::mock::HookInvocation;

  // Convenience method on top of ExpectBind for having bind create a child
  // and return success.
  Promise<void> CreateFirstChild(std::unique_ptr<RootMockDevice>* root_mock_device,
                                 std::unique_ptr<MockDevice>* child_device);

  // Convenience method on top of ExpectUnbind and ExpectRelease for having
  // unbind invoke device_remove(), with the belief that that will drop the
  // last reference to the device and Release() will be called.
  Promise<void> ExpectUnbindThenRelease(const std::unique_ptr<MockDevice>& device);

  // Initializes |root_mock_device| and returns a promise that will be complete after
  // the root mock device's bind hook has been called.  The bind hook will
  // perform the given |actions|.
  Promise<void> ExpectBind(std::unique_ptr<RootMockDevice>* root_mock_device,
                           BindOnce::Callback actions_callback);

  // Returns a promise that will be complete after the device invokes its
  // unbind() hook and performs the given |actions|.  |device| must outlive
  // this promise.
  Promise<void> ExpectUnbind(const std::unique_ptr<MockDevice>& device,
                             UnbindOnce::Callback actions_callback);

  // Returns a promise that will be complete after the device invokes its
  // open() hook and performs the given |actions|.  |device| must outlive
  // this promise.
  Promise<void> ExpectOpen(const std::unique_ptr<MockDevice>& device,
                           OpenOnce::Callback actions_callback);

  // Returns a promise that will be complete after the device invokes its
  // close() hook and performs the given |actions|.  |device| must outlive
  // this promise.
  Promise<void> ExpectClose(const std::unique_ptr<MockDevice>& device,
                            CloseOnce::Callback actions_callback);

  // Returns a promise that will be complete after the device invokes its
  // release() hook. |device| must outive this promise.
  Promise<void> ExpectRelease(const std::unique_ptr<MockDevice>& device);

  // Performs an open of the given |path| relative to the devfs, and puts the
  // connection into |client|.  The promise returned completes when the open
  // result is sent.  We must setup an open hook handler in order for that
  // promise to be completed.
  Promise<void> DoOpen(const std::string& path, fidl::InterfacePtr<fuchsia::io::Node>* client,
                       uint32_t flags = fuchsia::io::OPEN_RIGHT_READABLE |
                                        fuchsia::io::OPEN_RIGHT_WRITABLE);

  // Waits for the given |path| relative to devfs to be available.  Currently
  // waiting for paths in which non-terminal directories don't yet exist is
  // not supported.
  Promise<void> DoWaitForPath(const std::string& path);

  // Joins two promises and collapses the results such that if either failed
  // the returned promise fails.
  auto JoinPromises(Promise<void> promise1, Promise<void> promise2) {
    return join_promises(std::move(promise1), std::move(promise2))
        .then([](fit::result<std::tuple<Result<void>, Result<void>>>& wrapped_results)
                  -> Result<void> {
          // join_promises() can't fail, so just extract the value
          auto results = wrapped_results.value();
          if (std::get<0>(results).is_error()) {
            return std::get<0>(results);
          }
          return std::get<1>(results);
        });
  }

  // Run the given promise and transform its error case into a test failure.
  void RunPromise(Promise<void> promise);

 protected:
  static void DoSetup(bool should_create_composite);

  using IsolatedDevmgr = devmgr_integration_test::IsolatedDevmgr;
  static IsolatedDevmgr devmgr_;

  static async::Loop loop_;
  fidl::InterfacePtr<fuchsia::io::Directory> devfs_;

 private:
  // Function that will be called whenever we see an exception from devmgr
  static void DevmgrException();
};

}  // namespace libdriver_integration_test

#endif  // SRC_DEVICES_TESTS_LIBDRIVER_INTEGRATION_TEST_INTEGRATION_TEST_H_
