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

#include "include/private/SkTemplates.h"
#include "tests/Test.h"

#include <cstddef>
#include <utility>

using namespace skia_private;

// Tests for some of the helpers in SkTemplates.h
static void test_automalloc_realloc(skiatest::Reporter* reporter) {
    AutoSTMalloc<1, int> array;

    // test we have a valid pointer, should not crash
    array[0] = 1;
    REPORTER_ASSERT(reporter, array[0] == 1);

    // using realloc for init
    array.realloc(1);

    array[0] = 1;
    REPORTER_ASSERT(reporter, array[0] == 1);

    // verify realloc can grow
    array.realloc(2);
    REPORTER_ASSERT(reporter, array[0] == 1);

    // realloc can shrink
    array.realloc(1);
    REPORTER_ASSERT(reporter, array[0] == 1);

    // should not crash
    array.realloc(0);

    // grow and shrink again
    array.realloc(10);
    for (int i = 0; i < 10; i++) {
        array[i] = 10 - i;
    }
    array.realloc(20);
    for (int i = 0; i < 10; i++) {
        REPORTER_ASSERT(reporter, array[i] == 10 - i);
    }
    array.realloc(10);
    for (int i = 0; i < 10; i++) {
        REPORTER_ASSERT(reporter, array[i] == 10 - i);
    }

    array.realloc(1);
    REPORTER_ASSERT(reporter, array[0] = 10);

    // resets mixed with realloc, below stack alloc size
    array.reset(0);
    array.realloc(1);
    array.reset(1);

    array[0] = 1;
    REPORTER_ASSERT(reporter, array[0] == 1);

    // reset and realloc > stack size
    array.reset(2);
    array.realloc(3);
    array[0] = 1;
    REPORTER_ASSERT(reporter, array[0] == 1);
    array.realloc(1);
    REPORTER_ASSERT(reporter, array[0] == 1);
}

DEF_TEST(Templates, reporter) {
    test_automalloc_realloc(reporter);
}

constexpr int static kStackPreallocCount = 10;

// Ensures the containers in SkTemplates.h all have a consistent api.
template<typename TContainer, typename TCount>
static void test_container_apis(skiatest::Reporter* reporter) {
    REPORTER_ASSERT(reporter, !TContainer((TCount)0).get());
    REPORTER_ASSERT(reporter, !TContainer((TCount)0).data());
    REPORTER_ASSERT(reporter, TContainer((TCount)1).get());
    REPORTER_ASSERT(reporter, TContainer((TCount)1).data());
    REPORTER_ASSERT(reporter, TContainer((TCount)kStackPreallocCount).get());
    REPORTER_ASSERT(reporter, TContainer((TCount)kStackPreallocCount).data());
    REPORTER_ASSERT(reporter, TContainer((TCount)kStackPreallocCount + 1).get());
    REPORTER_ASSERT(reporter, TContainer((TCount)kStackPreallocCount + 1).data());

    TContainer container;
    // The default constructor may or may not init to empty, depending on the type of container.

    container.reset((TCount)1);
    REPORTER_ASSERT(reporter, container.get());
    REPORTER_ASSERT(reporter, container.get() == container.data());

    container.reset((TCount)kStackPreallocCount);
    REPORTER_ASSERT(reporter, container.get());
    REPORTER_ASSERT(reporter, container.get() == container.data());

    container.reset((TCount)kStackPreallocCount + 1);
    REPORTER_ASSERT(reporter, container.get());
    REPORTER_ASSERT(reporter, container.get() == container.data());

    container.reset((TCount)0);
    REPORTER_ASSERT(reporter, !container.get());
    REPORTER_ASSERT(reporter, !container.data());
}

DEF_TEST(TemplateContainerAPIs, reporter) {
    test_container_apis<SkAutoTArray<int>, int>(reporter);
    test_container_apis<SkAutoSTArray<kStackPreallocCount, int>, int>(reporter);
    test_container_apis<AutoTMalloc<int>, size_t>(reporter);
    test_container_apis<AutoSTMalloc<kStackPreallocCount, int>, size_t>(reporter);
}

// Ensures that realloc(0) results in a null pointer.
template<typename TAutoMalloc> static void test_realloc_to_zero(skiatest::Reporter* reporter) {
    TAutoMalloc autoMalloc(kStackPreallocCount);
    REPORTER_ASSERT(reporter, autoMalloc.get());

    autoMalloc.realloc(0);
    REPORTER_ASSERT(reporter, !autoMalloc.get());

    autoMalloc.realloc(kStackPreallocCount + 1);
    REPORTER_ASSERT(reporter, autoMalloc.get());

    autoMalloc.realloc(0);
    REPORTER_ASSERT(reporter, !autoMalloc.get());

    autoMalloc.realloc(kStackPreallocCount);
    REPORTER_ASSERT(reporter, autoMalloc.get());
}

DEF_TEST(AutoReallocToZero, reporter) {
    test_realloc_to_zero<AutoTMalloc<int> >(reporter);
    test_realloc_to_zero<AutoSTMalloc<kStackPreallocCount, int> >(reporter);
}

DEF_TEST(AutoTMallocSelfMove, r) {
#if defined(__clang__)
    #pragma clang diagnostic push
    #pragma clang diagnostic ignored "-Wself-move"
#endif

    AutoTMalloc<int> foo(20);
    REPORTER_ASSERT(r, foo.get());

    foo = std::move(foo);
    REPORTER_ASSERT(r, foo.get());  // NOLINT(bugprone-use-after-move)

#if defined(__clang__)
    #pragma clang diagnostic pop
#endif
}
