// 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 <fs/pseudo-dir.h>

#include <fs/pseudo-file.h>
#include <unittest/unittest.h>

namespace {

class DirentChecker {
public:
    DirentChecker(const void* buffer, size_t length)
        : current_(reinterpret_cast<const uint8_t*>(buffer)), remaining_(length) {}

    bool ExpectEnd() {
        BEGIN_HELPER;

        EXPECT_EQ(0u, remaining_);

        END_HELPER;
    }

    bool ExpectEntry(const char* name, uint32_t vtype) {
        BEGIN_HELPER;

        ASSERT_NE(0u, remaining_);
        auto entry = reinterpret_cast<const vdirent_t*>(current_);
        size_t entry_size = entry->size + sizeof(vdirent_t);
        ASSERT_GE(remaining_, entry_size);
        current_ += entry_size;
        remaining_ -= entry_size;
        EXPECT_BYTES_EQ(reinterpret_cast<const uint8_t*>(name),
                        reinterpret_cast<const uint8_t*>(entry->name), strlen(name), "name");
        EXPECT_EQ(VTYPE_TO_DTYPE(vtype), entry->type);

        END_HELPER;
    }

private:
    const uint8_t* current_;
    size_t remaining_;
};

bool TestPseudoDir() {
    BEGIN_TEST;

    auto dir = fbl::AdoptRef<fs::PseudoDir>(new fs::PseudoDir());
    auto subdir = fbl::AdoptRef<fs::Vnode>(new fs::PseudoDir());
    auto file1 = fbl::AdoptRef<fs::Vnode>(new fs::UnbufferedPseudoFile());
    auto file2 = fbl::AdoptRef<fs::Vnode>(new fs::UnbufferedPseudoFile());

    // add entries
    EXPECT_EQ(ZX_OK, dir->AddEntry("subdir", subdir));
    EXPECT_EQ(ZX_OK, dir->AddEntry("file1", file1));
    EXPECT_EQ(ZX_OK, dir->AddEntry("file2", file2));
    EXPECT_EQ(ZX_OK, dir->AddEntry("file2b", file2));

    // try to add duplicates
    EXPECT_EQ(ZX_ERR_ALREADY_EXISTS, dir->AddEntry("subdir", subdir));
    EXPECT_EQ(ZX_ERR_ALREADY_EXISTS, dir->AddEntry("file1", subdir));

    // remove entries
    EXPECT_EQ(ZX_OK, dir->RemoveEntry("file2"));
    EXPECT_EQ(ZX_ERR_NOT_FOUND, dir->RemoveEntry("file2"));

    // open as directory
    fbl::RefPtr<fs::Vnode> redirect;
    EXPECT_EQ(ZX_OK, dir->ValidateFlags(ZX_FS_FLAG_DIRECTORY));
    EXPECT_EQ(ZX_OK, dir->Open(ZX_FS_FLAG_DIRECTORY, &redirect));
    EXPECT_NULL(redirect);

    // get attributes
    vnattr_t attr;
    EXPECT_EQ(ZX_OK, dir->Getattr(&attr));
    EXPECT_EQ(V_TYPE_DIR | V_IRUSR, attr.mode);
    EXPECT_EQ(1, attr.nlink);

    // lookup entries
    fbl::RefPtr<fs::Vnode> node;
    EXPECT_EQ(ZX_OK, dir->Lookup(&node, "subdir"));
    EXPECT_EQ(subdir.get(), node.get());
    EXPECT_EQ(ZX_OK, dir->Lookup(&node, "file1"));
    EXPECT_EQ(file1.get(), node.get());
    EXPECT_EQ(ZX_ERR_NOT_FOUND, dir->Lookup(&node, "file2"));
    EXPECT_EQ(ZX_OK, dir->Lookup(&node, "file2b"));
    EXPECT_EQ(file2.get(), node.get());

    // readdir
    {
        fs::vdircookie_t cookie = {};
        uint8_t buffer[4096];
        size_t length;
        EXPECT_EQ(dir->Readdir(&cookie, buffer, sizeof(buffer), &length), ZX_OK);
        DirentChecker dc(buffer, length);
        EXPECT_TRUE(dc.ExpectEntry(".", V_TYPE_DIR));
        EXPECT_TRUE(dc.ExpectEntry("subdir", V_TYPE_DIR));
        EXPECT_TRUE(dc.ExpectEntry("file1", V_TYPE_FILE));
        EXPECT_TRUE(dc.ExpectEntry("file2b", V_TYPE_FILE));
        EXPECT_TRUE(dc.ExpectEnd());
    }

    // readdir with small buffer
    {
        fs::vdircookie_t cookie = {};
        uint8_t buffer[2*sizeof(vdirent) + 13];
        size_t length;
        EXPECT_EQ(dir->Readdir(&cookie, buffer, sizeof(buffer), &length), ZX_OK);
        DirentChecker dc(buffer, length);
        EXPECT_TRUE(dc.ExpectEntry(".", V_TYPE_DIR));
        EXPECT_TRUE(dc.ExpectEntry("subdir", V_TYPE_DIR));
        EXPECT_TRUE(dc.ExpectEnd());

        // readdir again
        EXPECT_EQ(dir->Readdir(&cookie, buffer, sizeof(buffer), &length), ZX_OK);
        DirentChecker dc1(buffer, length);
        EXPECT_TRUE(dc1.ExpectEntry("file1", V_TYPE_FILE));
        EXPECT_TRUE(dc1.ExpectEntry("file2b", V_TYPE_FILE));
        EXPECT_TRUE(dc1.ExpectEnd());
    }

    // test removed entries do not appear in readdir or lookup
    dir->RemoveEntry("file1");
    {
        fs::vdircookie_t cookie = {};
        uint8_t buffer[4096];
        size_t length;
        EXPECT_EQ(dir->Readdir(&cookie, buffer, sizeof(buffer), &length), ZX_OK);
        DirentChecker dc(buffer, length);
        EXPECT_TRUE(dc.ExpectEntry(".", V_TYPE_DIR));
        EXPECT_TRUE(dc.ExpectEntry("subdir", V_TYPE_DIR));
        EXPECT_TRUE(dc.ExpectEntry("file2b", V_TYPE_FILE));
        EXPECT_TRUE(dc.ExpectEnd());
    }
    EXPECT_EQ(ZX_ERR_NOT_FOUND, dir->Lookup(&node, "file1"));

    // remove all entries
    dir->RemoveAllEntries();

    // readdir again
    {
        fs::vdircookie_t cookie = {};
        uint8_t buffer[4096];
        size_t length;
        EXPECT_EQ(dir->Readdir(&cookie, buffer, sizeof(buffer), &length), ZX_OK);
        DirentChecker dc(buffer, length);
        EXPECT_TRUE(dc.ExpectEntry(".", V_TYPE_DIR));
        EXPECT_TRUE(dc.ExpectEnd());
    }

    // FIXME(ZX-1186): Can't unittest watch/notify (hard to isolate right now).

    END_TEST;
}

} // namespace

BEGIN_TEST_CASE(pseudo_dir_tests)
RUN_TEST(TestPseudoDir)
END_TEST_CASE(pseudo_dir_tests)
