// 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 "integration-test.h"

#include <fcntl.h>

#include <lib/async_promise/executor.h>
#include <lib/fdio/unsafe.h>
#include <lib/fdio/util.h>
#include <lib/fit/bridge.h>
#include <zircon/status.h>

namespace libdriver_integration_test {

std::unique_ptr<IntegrationTest::IsolatedDevmgr> IntegrationTest::devmgr_;
const zx::duration IntegrationTest::kDefaultTimeout = zx::sec(5);

void IntegrationTest::SetUpTestCase() {
    // Set up the isolated devmgr instance for this test suite.  Note that we
    // only do this once for the whole suite, because it is currently an
    // expensive process.  Ideally we'd do this between every test.
    auto args = IsolatedDevmgr::DefaultArgs();
    args.stdio = fbl::unique_fd(open("/dev/null", O_RDWR));

    fbl::unique_ptr<IsolatedDevmgr> tmp;
    zx_status_t status = IsolatedDevmgr::Create(std::move(args), &tmp);
    if (status != ZX_OK) {
        printf("libdriver-integration-tests: failed to create isolated devmgr\n");
        return;
    }
    IntegrationTest::devmgr_.reset(tmp.release());
}

void IntegrationTest::TearDownTestCase() {
    IntegrationTest::devmgr_.reset();
}

IntegrationTest::IntegrationTest()
    : loop_(&kAsyncLoopConfigNoAttachToThread),
      devmgr_exception_(this, devmgr_->containing_job().get(), 0) {

    zx_status_t status = devmgr_exception_.Bind(loop_.dispatcher());
    if (status != ZX_OK) {
        printf("libdriver-integration-tests: failed to watch isolated devmgr for crashes: %s\n",
               zx_status_get_string(status));
        return;
    }

    fdio_t* io = fdio_unsafe_fd_to_io(IntegrationTest::devmgr_->devfs_root().get());
    status = devfs_.Bind(zx::channel(fdio_service_clone(fdio_unsafe_borrow_channel(io))),
                         loop_.dispatcher());
    fdio_unsafe_release(io);
    if (status != ZX_OK) {
        printf("libdriver-integration-tests: failed to connect to devfs\n");
        return;
    }
}

IntegrationTest::~IntegrationTest() = default;

void IntegrationTest::DevmgrException(async_dispatcher_t* dispatcher,
                                      async::ExceptionBase* exception, zx_status_t status,
                                      const zx_port_packet_t* report) {
    // Log an error in the currently running test
    ADD_FAILURE() << "Crash inside devmgr job";
    exception->Unbind();
    loop_.Quit();
}

void IntegrationTest::RunPromise(Promise<void> promise) {
    RunPromise(std::move(promise), zx::deadline_after(kDefaultTimeout));
}

void IntegrationTest::RunPromise(Promise<void> promise, zx::time deadline) {
    async::Executor executor(loop_.dispatcher());

    auto new_promise = promise.then([&](Promise<void>::result_type result) {
        if (result.is_error()) {
            ADD_FAILURE() << result.error();
        }
        loop_.Quit();
        return result;
    });

    executor.schedule_task(std::move(new_promise));

    zx_status_t status = loop_.Run(deadline);
    ASSERT_EQ(status, ZX_ERR_CANCELED);
}

IntegrationTest::Promise<void> IntegrationTest::CreateFirstChild(
        std::unique_ptr<RootMockDevice>* root_mock_device,
        std::unique_ptr<MockDevice>* child_device) {
    return ExpectBind(root_mock_device,
        [this, root_mock_device, child_device](HookInvocation record,
                                               Completer<void> completer) {
            ActionList actions;
            actions.AppendAddMockDevice(loop_.dispatcher(), (*root_mock_device)->path(),
                                        "first_child", std::move(completer), child_device);
            actions.AppendReturnStatus(ZX_OK);
            return actions;
        });
}

IntegrationTest::Promise<void> IntegrationTest::ExpectUnbindThenRelease(
        const std::unique_ptr<MockDevice>& device) {
    fit::bridge<void, Error> bridge;
    auto unbind = ExpectUnbind(device,
        [remove_completer = std::move(bridge.completer)](HookInvocation record,
                                                         Completer<void> completer) mutable {
            completer.complete_ok();
            ActionList actions;
            actions.AppendRemoveDevice(std::move(remove_completer));
            return actions;
        });
    auto remove_done = bridge.consumer.promise_or(::fit::error("remove_completer abandoned"));
    return unbind.and_then(JoinPromises(std::move(remove_done), ExpectRelease(device)));
}

IntegrationTest::Promise<void> IntegrationTest::ExpectBind(
        std::unique_ptr<RootMockDevice>* root_mock_device, BindOnce::Callback actions_callback) {
    fit::bridge<void, Error> bridge;
    auto bind_hook = std::make_unique<BindOnce>(std::move(bridge.completer),
                                                std::move(actions_callback));
    zx_status_t status = RootMockDevice::Create(devmgr_, loop_.dispatcher(),
                                                std::move(bind_hook), root_mock_device);
    PROMISE_ASSERT(ASSERT_EQ(status, ZX_OK));
    return bridge.consumer.promise_or(::fit::error("bind abandoned"));
}

IntegrationTest::Promise<void> IntegrationTest::ExpectUnbind(
        const std::unique_ptr<MockDevice>& device, UnbindOnce::Callback actions_callback) {
    fit::bridge<void, Error> bridge;
    auto unbind_hook = std::make_unique<UnbindOnce>(
            std::move(bridge.completer), std::move(actions_callback));
    // Wrap the body in a promise, since we want to defer the evaluation of
    // device->set_hooks.
    return fit::make_promise([consumer = std::move(bridge.consumer), &device,
                             unbind_hook = std::move(unbind_hook)]() mutable {
                                 device->set_hooks(std::move(unbind_hook));
                                 return consumer.promise_or(::fit::error("unbind abandoned"));
                             });
}

IntegrationTest::Promise<void> IntegrationTest::ExpectOpen(
        const std::unique_ptr<MockDevice>& device, OpenOnce::Callback actions_callback) {
    fit::bridge<void, Error> bridge;
    auto open_hook = std::make_unique<OpenOnce>(
            std::move(bridge.completer), std::move(actions_callback));
    // Wrap the body in a promise, since we want to defer the evaluation of
    // device->set_hooks.
    return fit::make_promise([consumer = std::move(bridge.consumer), &device,
                             open_hook = std::move(open_hook)]() mutable {
                                 device->set_hooks(std::move(open_hook));
                                 return consumer.promise_or(::fit::error("open abandoned"));
                             });
}

IntegrationTest::Promise<void> IntegrationTest::ExpectClose(
        const std::unique_ptr<MockDevice>& device, CloseOnce::Callback actions_callback) {
    fit::bridge<void, Error> bridge;
    auto close_hook = std::make_unique<CloseOnce>(
            std::move(bridge.completer), std::move(actions_callback));
    // Wrap the body in a promise, since we want to defer the evaluation of
    // device->set_hooks.
    return fit::make_promise([consumer = std::move(bridge.consumer), &device,
                             close_hook = std::move(close_hook)]() mutable {
                                 device->set_hooks(std::move(close_hook));
                                 return consumer.promise_or(::fit::error("close abandoned"));
                             });
}

IntegrationTest::Promise<void> IntegrationTest::ExpectRelease(
        const std::unique_ptr<MockDevice>& device) {
    // Wrap the body in a promise, since we want to defer the evaluation of
    // device->set_hooks.
    return fit::make_promise([&device]() {
        fit::bridge<void, Error> bridge;
        ReleaseOnce::Callback func = [](HookInvocation record, Completer<void> completer) {
            completer.complete_ok();
        };
        auto release_hook = std::make_unique<ReleaseOnce>(std::move(bridge.completer),
                                                          std::move(func));
        device->set_hooks(std::move(release_hook));
        return bridge.consumer.promise_or(::fit::error("release abandoned"));
    });
}

IntegrationTest::Promise<void> IntegrationTest::DoOpen(
        const std::string& path, fidl::InterfacePtr<fuchsia::io::Node>* client) {
    fidl::InterfaceRequest<fuchsia::io::Node> server(client->NewRequest(loop_.dispatcher()));
    PROMISE_ASSERT(ASSERT_TRUE(server.is_valid()));

    PROMISE_ASSERT(ASSERT_EQ(client->events().OnOpen, nullptr));
    fit::bridge<void, Error> bridge;
    client->events().OnOpen = [client, completer = std::move(bridge.completer)](
            zx_status_t status, std::unique_ptr<fuchsia::io::NodeInfo> info) mutable {
        if (status != ZX_OK) {
            std::string error("failed to open node: ");
            error.append(zx_status_get_string(status));
            completer.complete_error(std::move(error));
            client->events().OnOpen = nullptr;
            return;
        }
        completer.complete_ok();
        client->events().OnOpen = nullptr;
    };
    devfs_->Open(fuchsia::io::OPEN_FLAG_DESCRIBE, 0, path, std::move(server));
    return bridge.consumer.promise_or(::fit::error("devfs open abandoned"));
}

} // namespace libdriver_integration_test
