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

#include "Test.h"
// This is a GPU-backend specific test
#if SK_SUPPORT_GPU
#include "GrMemoryPool.h"
#include "SkRandom.h"
#include "SkTDArray.h"
#include "SkTemplates.h"

// A is the top of an inheritance tree of classes that overload op new and
// and delete to use a GrMemoryPool. The objects have values of different types
// that can be set and checked.
class A {
public:
    A() {};
    virtual void setValues(int v) {
        fChar = static_cast<char>(v);
    }
    virtual bool checkValues(int v) {
        return fChar == static_cast<char>(v);
    }
    virtual ~A() {};

    void* operator new(size_t size) {
        if (!gPool.get()) {
            return ::operator new(size);
        } else {
            return gPool->allocate(size);
        }
    }

    void operator delete(void* p) {
        if (!gPool.get()) {
            ::operator delete(p);
        } else {
            return gPool->release(p);
        }
    }

    static A* Create(SkRandom* r);

    static void SetAllocator(size_t preallocSize, size_t minAllocSize) {
        GrMemoryPool* pool = new GrMemoryPool(preallocSize, minAllocSize);
        gPool.reset(pool);
    }

    static void ResetAllocator() {
        gPool.reset(nullptr);
    }

private:
    static SkAutoTDelete<GrMemoryPool> gPool;
    char fChar;
};

SkAutoTDelete<GrMemoryPool> A::gPool;

class B : public A {
public:
    B() {};
    virtual void setValues(int v) {
        fDouble = static_cast<double>(v);
        this->INHERITED::setValues(v);
    }
    virtual bool checkValues(int v) {
        return fDouble == static_cast<double>(v) &&
               this->INHERITED::checkValues(v);
    }
    virtual ~B() {};

private:
    double fDouble;

    typedef A INHERITED;
};

class C : public A {
public:
    C() {};
    virtual void setValues(int v) {
        fInt64 = static_cast<int64_t>(v);
        this->INHERITED::setValues(v);
    }
    virtual bool checkValues(int v) {
        return fInt64 == static_cast<int64_t>(v) &&
               this->INHERITED::checkValues(v);
    }
    virtual ~C() {};

private:
    int64_t fInt64;

    typedef A INHERITED;
};

// D derives from C and owns a dynamically created B
class D : public C {
public:
    D() {
        fB = new B();
    }
    virtual void setValues(int v) {
        fVoidStar = reinterpret_cast<void*>(static_cast<intptr_t>(v));
        this->INHERITED::setValues(v);
        fB->setValues(v);
    }
    virtual bool checkValues(int v) {
        return fVoidStar == reinterpret_cast<void*>(static_cast<intptr_t>(v)) &&
               fB->checkValues(v) &&
               this->INHERITED::checkValues(v);
    }
    virtual ~D() {
        delete fB;
    }
private:
    void*   fVoidStar;
    B*      fB;

    typedef C INHERITED;
};

class E : public A {
public:
    E() {}
    virtual void setValues(int v) {
        for (size_t i = 0; i < SK_ARRAY_COUNT(fIntArray); ++i) {
            fIntArray[i] = v;
        }
        this->INHERITED::setValues(v);
    }
    virtual bool checkValues(int v) {
        bool ok = true;
        for (size_t i = 0; ok && i < SK_ARRAY_COUNT(fIntArray); ++i) {
            if (fIntArray[i] != v) {
                ok = false;
            }
        }
        return ok && this->INHERITED::checkValues(v);
    }
    virtual ~E() {}
private:
    int   fIntArray[20];

    typedef A INHERITED;
};

A* A::Create(SkRandom* r) {
    switch (r->nextRangeU(0, 4)) {
        case 0:
            return new A;
        case 1:
            return new B;
        case 2:
            return new C;
        case 3:
            return new D;
        case 4:
            return new E;
        default:
            // suppress warning
            return nullptr;
    }
}

struct Rec {
    A* fInstance;
    int fValue;
};

DEF_TEST(GrMemoryPool, reporter) {
    // prealloc and min alloc sizes for the pool
    static const size_t gSizes[][2] = {
        {0, 0},
        {10 * sizeof(A), 20 * sizeof(A)},
        {100 * sizeof(A), 100 * sizeof(A)},
        {500 * sizeof(A), 500 * sizeof(A)},
        {10000 * sizeof(A), 0},
        {1, 100 * sizeof(A)},
    };
    // different percentages of creation vs deletion
    static const float gCreateFraction[] = {1.f, .95f, 0.75f, .5f};
    // number of create/destroys per test
    static const int kNumIters = 20000;
    // check that all the values stored in A objects are correct after this
    // number of iterations
    static const int kCheckPeriod = 500;

    SkRandom r;
    for (size_t s = 0; s < SK_ARRAY_COUNT(gSizes); ++s) {
        A::SetAllocator(gSizes[s][0], gSizes[s][1]);
        for (size_t c = 0; c < SK_ARRAY_COUNT(gCreateFraction); ++c) {
            SkTDArray<Rec> instanceRecs;
            for (int i = 0; i < kNumIters; ++i) {
                float createOrDestroy = r.nextUScalar1();
                if (createOrDestroy < gCreateFraction[c] ||
                    0 == instanceRecs.count()) {
                    Rec* rec = instanceRecs.append();
                    rec->fInstance = A::Create(&r);
                    rec->fValue = static_cast<int>(r.nextU());
                    rec->fInstance->setValues(rec->fValue);
                } else {
                    int d = r.nextRangeU(0, instanceRecs.count() - 1);
                    Rec& rec = instanceRecs[d];
                    REPORTER_ASSERT(reporter, rec.fInstance->checkValues(rec.fValue));
                    delete rec.fInstance;
                    instanceRecs.removeShuffle(d);
                }
                if (0 == i % kCheckPeriod) {
                    for (int r = 0; r < instanceRecs.count(); ++r) {
                        Rec& rec = instanceRecs[r];
                        REPORTER_ASSERT(reporter, rec.fInstance->checkValues(rec.fValue));
                    }
                }
            }
            for (int i = 0; i < instanceRecs.count(); ++i) {
                Rec& rec = instanceRecs[i];
                REPORTER_ASSERT(reporter, rec.fInstance->checkValues(rec.fValue));
                delete rec.fInstance;
            }
        }
    }
}

#endif
