// Copyright 2017 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 <lib/async-loop/cpp/loop.h>
#include <lib/fdio/fd.h>
#include <lib/fdio/fdio.h>
#include <lib/fdio/directory.h>
#include <fs/synchronous-vfs.h>
#include <fs/pseudo-dir.h>
#include <fs/service.h>

#include <unittest/unittest.h>

#include <utility>

namespace {

bool test_service() {
    BEGIN_TEST;

    // set up a service which can only be bound once (to make it easy to
    // simulate an error to test error reporting behavior from the connector)
    zx::channel bound_channel;
    auto svc = fbl::AdoptRef<fs::Service>(new fs::Service(
        [&bound_channel](zx::channel channel) {
            if (bound_channel)
                return ZX_ERR_IO;
            bound_channel = std::move(channel);
            return ZX_OK;
        }));

    // open
    fbl::RefPtr<fs::Vnode> redirect;
    EXPECT_EQ(ZX_OK, svc->ValidateFlags(ZX_FS_RIGHT_READABLE));
    EXPECT_EQ(ZX_OK, svc->Open(ZX_FS_RIGHT_READABLE, &redirect));
    EXPECT_NULL(redirect);

    // get attr
    vnattr_t attr;
    EXPECT_EQ(ZX_OK, svc->Getattr(&attr));
    EXPECT_EQ(V_TYPE_FILE, attr.mode);
    EXPECT_EQ(1, attr.nlink);

    // make some channels we can use for testing
    zx::channel c1, c2;
    EXPECT_EQ(ZX_OK, zx::channel::create(0u, &c1, &c2));
    zx_handle_t hc1 = c1.get();

    // serve, the connector will return success the first time
    fs::SynchronousVfs vfs;
    EXPECT_EQ(ZX_OK, svc->Serve(&vfs, std::move(c1), ZX_FS_RIGHT_READABLE));
    EXPECT_EQ(hc1, bound_channel.get());

    // the connector will return failure because bound_channel is still valid
    // we test that the error is propagated back up through Serve
    EXPECT_EQ(ZX_ERR_IO, svc->Serve(&vfs, std::move(c2), ZX_FS_RIGHT_READABLE));
    EXPECT_EQ(hc1, bound_channel.get());

    END_TEST;
}

bool TestServeDirectory() {
    BEGIN_TEST;

    zx::channel client, server;
    EXPECT_EQ(ZX_OK, zx::channel::create(0u, &client, &server));

    // open client
    zx::channel c1, c2;
    EXPECT_EQ(ZX_OK, zx::channel::create(0u, &c1, &c2));
    EXPECT_EQ(ZX_OK,
              fdio_service_connect_at(client.get(), "abc", c2.release()));

    // close client
    // We test the semantic that a pending open is processed even if the client
    // has been closed.
    client.reset();

    // serve
     async::Loop loop(&kAsyncLoopConfigNoAttachToThread);
    fs::SynchronousVfs vfs(loop.dispatcher());

    auto directory = fbl::AdoptRef<fs::PseudoDir>(new fs::PseudoDir());
    auto vnode = fbl::AdoptRef<fs::Service>(new fs::Service(
        [&loop](zx::channel channel) {
            loop.Shutdown();
            return ZX_OK;
        }));
    directory->AddEntry("abc", vnode);

    EXPECT_EQ(ZX_OK, vfs.ServeDirectory(directory, std::move(server)));
    EXPECT_EQ(ZX_ERR_BAD_STATE, loop.RunUntilIdle());

    END_TEST;
}

} // namespace

BEGIN_TEST_CASE(service_tests)
RUN_TEST(test_service)
RUN_TEST(TestServeDirectory)
END_TEST_CASE(service_tests)
