// 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/util.h>
#include <fs/synchronous-vfs.h>
#include <fs/pseudo-dir.h>
#include <fs/service.h>

#include <unittest/unittest.h>

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 = fbl::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);
    EXPECT_EQ(ZX_ERR_NOT_DIR, svc->ValidateFlags(ZX_FS_FLAG_DIRECTORY));

    // 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, fbl::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, fbl::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, fbl::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)
