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

#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);
    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, 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)
