// Copyright 2018 The Fuchsia Authors
//
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT

#include <object/buffer_chain.h>

#include <lib/unittest/unittest.h>
#include <lib/unittest/user_memory.h>
#include <lib/user_copy/user_ptr.h>
#include <stdio.h>

namespace {

using testing::UserMemory;

static bool alloc_free_basic() {
    BEGIN_TEST;
    BufferChainFreeList fl(1);

    // An empty chain requires one buffer
    BufferChain* bc = fl.Alloc(0);
    ASSERT_NE(bc, nullptr, "");
    ASSERT_FALSE(bc->buffers()->is_empty(), "");
    ASSERT_EQ(bc->buffers()->size_slow(), 1u, "");
    fl.Free(bc);

    // One Buffer is enough to hold one byte.
    bc = fl.Alloc(1);
    ASSERT_FALSE(bc->buffers()->is_empty(), "");
    ASSERT_EQ(bc->buffers()->size_slow(), 1u, "");
    ASSERT_NE(bc, nullptr, "");
    fl.Free(bc);

    // One Buffer is still enough.
    bc = fl.Alloc(BufferChain::kContig);
    ASSERT_FALSE(bc->buffers()->is_empty(), "");
    ASSERT_EQ(bc->buffers()->size_slow(), 1u, "");
    ASSERT_NE(bc, nullptr, "");
    fl.Free(bc);

    // Two Buffers required.
    bc = fl.Alloc(BufferChain::kContig + 1);
    ASSERT_FALSE(bc->buffers()->is_empty(), "");
    ASSERT_EQ(bc->buffers()->size_slow(), 2u, "");
    ASSERT_NE(bc, nullptr, "");
    fl.Free(bc);

    // Many Buffers required.
    bc = fl.Alloc(10000 * BufferChain::kRawSize);
    ASSERT_FALSE(bc->buffers()->is_empty(), "");
    ASSERT_EQ(bc->buffers()->size_slow(), 1u + 10000u, "");
    ASSERT_NE(bc, nullptr, "");
    fl.Free(bc);

    END_TEST;
}

static bool copy_in_copy_out() {
    BEGIN_TEST;
    constexpr size_t kSize = BufferChain::kContig + 2 * BufferChain::kRawSize;
    fbl::AllocChecker ac;
    auto buf = fbl::unique_ptr<char[]>(new (&ac) char[kSize]);
    ASSERT_TRUE(ac.check(), "");
    fbl::unique_ptr<UserMemory> mem = UserMemory::Create(kSize);
    auto mem_in = make_user_in_ptr(mem->in());
    auto mem_out = make_user_out_ptr(mem->out());

    BufferChainFreeList fl(1);
    BufferChain* bc = fl.Alloc(kSize);
    ASSERT_NE(nullptr, bc, "");
    ASSERT_FALSE(bc->buffers()->is_empty(), "");

    // Fill the chain with 'A'.
    memset(buf.get(), 'A', kSize);
    ASSERT_EQ(ZX_OK, mem_out.copy_array_to_user(buf.get(), kSize), "");
    ASSERT_EQ(ZX_OK, bc->CopyIn(mem_in, 0, kSize), "");

    // Verify it.
    ASSERT_EQ(3u, bc->buffers()->size_slow(), "");
    for (auto& b : *bc->buffers()) {
        char* data = b.data();
        for (size_t i = 0; i < b.size(); ++i) {
            ASSERT_EQ('A', data[i], "");
        }
    }

    // Write a chunk of 'B' straddling all three buffers.
    memset(buf.get(), 'B', kSize);
    ASSERT_EQ(ZX_OK, mem_out.copy_array_to_user(buf.get(), kSize), "");
    size_t offset = BufferChain::kContig - 1;
    size_t size = BufferChain::kRawSize + 2;
    ASSERT_EQ(ZX_OK, bc->CopyIn(mem_in, offset, size), "");

    // Verify it.
    auto iter = bc->buffers()->begin();
    for (size_t i = 0; i < offset; ++i) {
        char* data = iter->data();
        ASSERT_EQ('A', data[i], "");
    }
    ASSERT_EQ('B', *(iter->data() + offset), "");
    ++iter;
    for (size_t i = 0; i < BufferChain::kRawSize; ++i) {
        char* data = iter->data();
        ASSERT_EQ('B', data[i], "");
    }
    ++iter;
    ASSERT_EQ('B', *iter->data(), "");
    for (size_t i = 1; i < BufferChain::kRawSize; ++i) {
        char* data = iter->data();
        EXPECT_EQ('A', data[i], "");
    }
    ASSERT_TRUE(++iter == bc->buffers()->end(), "");

    // Copy it all out.
    memset(buf.get(), 0, kSize);
    ASSERT_EQ(ZX_OK, mem_out.copy_array_to_user(buf.get(), kSize), "");
    ASSERT_EQ(ZX_OK, bc->CopyOut(mem_out, 0, kSize), "");

    // Verify it.
    memset(buf.get(), 0, kSize);
    ASSERT_EQ(ZX_OK, mem_in.copy_array_from_user(buf.get(), kSize), "");
    size_t index = 0;
    for (size_t i = 0; i < offset; ++i) {
        ASSERT_EQ('A', buf[index++], "");
    }
    EXPECT_EQ('B', buf[index++], "");
    for (size_t i = 0; i < BufferChain::kRawSize; ++i) {
        ASSERT_EQ('B', buf[index++], "");
    }
    ASSERT_EQ('B', buf[index++], "");
    for (size_t i = 1; i < BufferChain::kRawSize; ++i) {
        EXPECT_EQ('A', buf[index++], "");
    }

    fl.Free(bc);
    END_TEST;
}

// TODO(maniscalco): Write a multi-threaded stress test for BufferChainFreeList's Alloc/Free.

}  // namespace

UNITTEST_START_TESTCASE(buffer_chain_tests)
UNITTEST("alloc_free_basic", alloc_free_basic)
UNITTEST("copy_in_copy_out", copy_in_copy_out)
UNITTEST_END_TESTCASE(buffer_chain_tests, "buffer_chain", "BufferChain tests");
