/*
 * Copyright 2016 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "include/core/SkTypes.h"
#include "src/base/SkArenaAlloc.h"
#include "tests/Test.h"

#include <cstddef>
#include <cstdint>
#include <initializer_list>
#include <limits>
#include <memory>
#include <new>

DEF_TEST(ArenaAlloc, r) {
    static int created = 0,
               destroyed = 0;

    struct Foo {
        Foo() : x(-2), y(-3.0f) { created++; }
        Foo(int X, float Y) : x(X), y(Y) { created++; }
        ~Foo() { destroyed++; }
        int x;
        float y;
    };

    struct alignas(8) OddAlignment {
        char buf[10];
    };

    // Check construction/destruction counts from SkArenaAlloc.
    created = 0;
    destroyed = 0;
    {
        SkArenaAlloc arena{0};
        REPORTER_ASSERT(r, *arena.make<int>(3) == 3);
        Foo* foo = arena.make<Foo>(3, 4.0f);
        REPORTER_ASSERT(r, foo->x == 3);
        REPORTER_ASSERT(r, foo->y == 4.0f);
        REPORTER_ASSERT(r, created == 1);
        REPORTER_ASSERT(r, destroyed == 0);
        arena.makeArrayDefault<int>(10);
        int* zeroed = arena.makeArray<int>(10);
        for (int i = 0; i < 10; i++) {
            REPORTER_ASSERT(r, zeroed[i] == 0);
        }
        Foo* fooArray = arena.makeArrayDefault<Foo>(10);
        REPORTER_ASSERT(r, fooArray[3].x == -2);
        REPORTER_ASSERT(r, fooArray[4].y == -3.0f);
        REPORTER_ASSERT(r, created == 11);
        REPORTER_ASSERT(r, destroyed == 0);
        arena.make<OddAlignment>();
    }
    REPORTER_ASSERT(r, created == 11);
    REPORTER_ASSERT(r, destroyed == 11);

    // Check construction/destruction counts from SkSTArenaAlloc.
    created = 0;
    destroyed = 0;
    {
        SkSTArenaAlloc<64> arena;
        REPORTER_ASSERT(r, *arena.make<int>(3) == 3);
        Foo* foo = arena.make<Foo>(3, 4.0f);
        REPORTER_ASSERT(r, foo->x == 3);
        REPORTER_ASSERT(r, foo->y == 4.0f);
        REPORTER_ASSERT(r, created == 1);
        REPORTER_ASSERT(r, destroyed == 0);
        arena.makeArrayDefault<int>(10);
        int* zeroed = arena.makeArray<int>(10);
        for (int i = 0; i < 10; i++) {
            REPORTER_ASSERT(r, zeroed[i] == 0);
        }
        Foo* fooArray = arena.makeArrayDefault<Foo>(10);
        REPORTER_ASSERT(r, fooArray[3].x == -2);
        REPORTER_ASSERT(r, fooArray[4].y == -3.0f);
        REPORTER_ASSERT(r, created == 11);
        REPORTER_ASSERT(r, destroyed == 0);
        arena.make<OddAlignment>();
    }
    REPORTER_ASSERT(r, created == 11);
    REPORTER_ASSERT(r, destroyed == 11);

    // Check construction/destruction counts from SkArenaAlloc when passed an initial block.
    created = 0;
    destroyed = 0;
    {
        std::unique_ptr<char[]> block{new char[1024]};
        SkArenaAlloc arena{block.get(), 1024, 0};
        REPORTER_ASSERT(r, *arena.make<int>(3) == 3);
        Foo* foo = arena.make<Foo>(3, 4.0f);
        REPORTER_ASSERT(r, foo->x == 3);
        REPORTER_ASSERT(r, foo->y == 4.0f);
        REPORTER_ASSERT(r, created == 1);
        REPORTER_ASSERT(r, destroyed == 0);
        arena.makeArrayDefault<int>(10);
        int* zeroed = arena.makeArray<int>(10);
        for (int i = 0; i < 10; i++) {
            REPORTER_ASSERT(r, zeroed[i] == 0);
        }
        Foo* fooArray = arena.makeArrayDefault<Foo>(10);
        REPORTER_ASSERT(r, fooArray[3].x == -2);
        REPORTER_ASSERT(r, fooArray[4].y == -3.0f);
        REPORTER_ASSERT(r, created == 11);
        REPORTER_ASSERT(r, destroyed == 0);
        arena.make<OddAlignment>();
    }
    REPORTER_ASSERT(r, created == 11);
    REPORTER_ASSERT(r, destroyed == 11);
}

DEF_TEST(ArenaAllocReset, r) {
    SkSTArenaAllocWithReset<64> arena;
    arena.makeArrayDefault<char>(256);
    arena.reset();
    arena.reset();
}

DEF_TEST(ArenaAllocIsEmpty, r) {
    char storage[1000];
    for (int arenaSize : {1, 2, 3, 10, 100, 1000}) {
        for (int alloc1Size : {1, 10, 100, 1000}) {
            for (int alloc2Size : {1, 10, 100, 1000}) {
                SkArenaAllocWithReset arena(storage, arenaSize, 1000);
                REPORTER_ASSERT(r, arena.isEmpty());

                [[maybe_unused]] char* alloc1 = arena.makeArray<char>(alloc1Size);
                REPORTER_ASSERT(r, !arena.isEmpty());

                [[maybe_unused]] char* alloc2 = arena.makeArray<char>(alloc2Size);
                REPORTER_ASSERT(r, !arena.isEmpty());

                arena.reset();
                REPORTER_ASSERT(r, arena.isEmpty());
            }
        }
    }
}

DEF_TEST(ArenaAllocWithMultipleBlocks, r) {
    // Make sure that multiple blocks are handled correctly.
    static int created = 0,
               destroyed = 0;
    {
        struct Node {
            Node(Node* n) : next(n) { created++; }
            ~Node() { destroyed++; }
            Node *next;
            char filler[64];
        };

        SkSTArenaAlloc<64> arena;
        Node* current = nullptr;
        for (int i = 0; i < 128; i++) {
            current = arena.make<Node>(current);
        }
    }
    REPORTER_ASSERT(r, created == 128);
    REPORTER_ASSERT(r, destroyed == 128);
}

DEF_TEST(ArenaAllocDestructionOrder, r) {
    // Make sure that objects and blocks are destroyed in the correct order. If they are not,
    // then there will be a use after free error in asan.
    static int created = 0,
               destroyed = 0;
    {
        struct Node {
            Node(Node* n) : next(n) { created++; }
            ~Node() {
                destroyed++;
                if (next) {
                    next->~Node();
                }
            }
            Node *next;
        };

        SkSTArenaAlloc<64> arena;
        Node* current = nullptr;
        for (int i = 0; i < 128; i++) {
            uint64_t* temp = arena.makeArrayDefault<uint64_t>(sizeof(Node) / sizeof(Node*));
            current = new (temp)Node(current);
        }
        current->~Node();
    }
    REPORTER_ASSERT(r, created == 128);
    REPORTER_ASSERT(r, destroyed == 128);

    {
        SkSTArenaAlloc<64> arena;
        auto a = arena.makeInitializedArray<int>(8, [](size_t i ) { return i; });
        for (size_t i = 0; i < 8; i++) {
            REPORTER_ASSERT(r, a[i] == (int)i);
        }
    }
}

DEF_TEST(ArenaAllocUnusualAlignment, r) {
    SkArenaAlloc arena(4096);
    // Move to a 1 character boundary.
    arena.make<char>();
    // Allocate something with interesting alignment.
    void* ptr = arena.makeBytesAlignedTo(4081, 8);
    REPORTER_ASSERT(r, ((intptr_t)ptr & 7) == 0);
}

DEF_TEST(SkFibBlockSizes, r) {
    {
        SkFibBlockSizes<std::numeric_limits<uint32_t>::max()> fibs{1, 1};
        uint32_t lastSize = 1;
        for (int i = 0; i < 64; i++) {
            uint32_t size = fibs.nextBlockSize();
            REPORTER_ASSERT(r, lastSize <= size);
            lastSize = size;
        }
        REPORTER_ASSERT(r, lastSize == 2971215073u);
    }
    {
        SkFibBlockSizes<std::numeric_limits<uint32_t>::max()> fibs{0, 1024};
        uint32_t lastSize = 1;
        for (int i = 0; i < 64; i++) {
            uint32_t size = fibs.nextBlockSize();
            REPORTER_ASSERT(r, lastSize <= size);
            lastSize = size;
            REPORTER_ASSERT(r, lastSize <= std::numeric_limits<uint32_t>::max());
        }
        REPORTER_ASSERT(r, lastSize == 3524578u * 1024);
    }

    {
        SkFibBlockSizes<std::numeric_limits<uint32_t>::max() / 2> fibs{1024, 0};
        uint32_t lastSize = 1;
        for (int i = 0; i < 64; i++) {
            uint32_t size = fibs.nextBlockSize();
            REPORTER_ASSERT(r, lastSize <= size);
            lastSize = size;
            REPORTER_ASSERT(r, lastSize <= std::numeric_limits<uint32_t>::max() / 2);
        }
        REPORTER_ASSERT(r, lastSize == 1346269u * 1024);
    }
}
