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

#include "SkRefCnt.h"
#include "SkTypes.h"
#include "SkWeakRefCnt.h"
#include "Test.h"

#include <thread>

static void bounce_ref(void* data) {
    SkRefCnt* ref = static_cast<SkRefCnt*>(data);
    for (int i = 0; i < 100000; ++i) {
        ref->ref();
        ref->unref();
    }
}

static void test_refCnt(skiatest::Reporter* reporter) {
    SkRefCnt* ref = new SkRefCnt();

    std::thread thing1(bounce_ref, ref);
    std::thread thing2(bounce_ref, ref);

    thing1.join();
    thing2.join();

    REPORTER_ASSERT(reporter, ref->unique());
    ref->unref();
}

static void bounce_weak_ref(void* data) {
    SkWeakRefCnt* ref = static_cast<SkWeakRefCnt*>(data);
    for (int i = 0; i < 100000; ++i) {
        if (ref->try_ref()) {
            ref->unref();
        }
    }
}

static void bounce_weak_weak_ref(void* data) {
    SkWeakRefCnt* ref = static_cast<SkWeakRefCnt*>(data);
    for (int i = 0; i < 100000; ++i) {
        ref->weak_ref();
        ref->weak_unref();
    }
}

static void test_weakRefCnt(skiatest::Reporter* reporter) {
    SkWeakRefCnt* ref = new SkWeakRefCnt();

    std::thread thing1(bounce_ref, ref);
    std::thread thing2(bounce_ref, ref);
    std::thread thing3(bounce_weak_ref, ref);
    std::thread thing4(bounce_weak_weak_ref, ref);

    thing1.join();
    thing2.join();
    thing3.join();
    thing4.join();

    REPORTER_ASSERT(reporter, ref->unique());
    SkDEBUGCODE(REPORTER_ASSERT(reporter, ref->getWeakCnt() == 1));
    ref->unref();
}

DEF_TEST(RefCnt, reporter) {
    test_refCnt(reporter);
    test_weakRefCnt(reporter);
}

///////////////////////////////////////////////////////////////////////////////////////////////////

static int gRefCounter;
static int gUnrefCounter;
static int gNewCounter;
static int gDeleteCounter;

#define check(reporter, ref, unref, make, kill)             \
    REPORTER_ASSERT(reporter, gRefCounter == ref);          \
    REPORTER_ASSERT(reporter, gUnrefCounter == unref);      \
    REPORTER_ASSERT(reporter, gNewCounter == make);         \
    REPORTER_ASSERT(reporter, gDeleteCounter == kill);


class Effect {
public:
    Effect() : fRefCnt(1) {
        gNewCounter += 1;
    }
    virtual ~Effect() {}

    int fRefCnt;

    void ref() {
        gRefCounter += 1;
        fRefCnt += 1;
    }
    void unref() {
        gUnrefCounter += 1;

        SkASSERT(fRefCnt > 0);
        if (0 == --fRefCnt) {
            gDeleteCounter += 1;
            delete this;
        }
    }

    int* method() const { return new int; }
};

static sk_sp<Effect> Create() {
    return sk_make_sp<Effect>();
}

class Paint {
public:
    sk_sp<Effect> fEffect;

    const sk_sp<Effect>& get() const { return fEffect; }

    void set(sk_sp<Effect> value) {
        fEffect = std::move(value);
    }
};

struct EffectImpl : public Effect {
    ~EffectImpl() override {}

    static sk_sp<EffectImpl> Create() {
        return sk_sp<EffectImpl>(new EffectImpl);
    }
    int fValue;
};
static sk_sp<Effect> make_effect() {
    auto foo = EffectImpl::Create();
    foo->fValue = 42;
    return std::move(foo);
}

static void reset_counters() {
    gRefCounter = 0;
    gUnrefCounter = 0;
    gNewCounter = 0;
    gDeleteCounter = 0;
}
DEF_TEST(sk_sp, reporter) {
    reset_counters();

    Paint paint;
    REPORTER_ASSERT(reporter, paint.fEffect.get() == nullptr);
    REPORTER_ASSERT(reporter, !paint.get());
    check(reporter, 0, 0, 0, 0);

    paint.set(Create());
    check(reporter, 0, 0, 1, 0);
    REPORTER_ASSERT(reporter, paint.fEffect.get()->fRefCnt == 1);

    if (paint.get()) {
        REPORTER_ASSERT(reporter, true);
    } else {
        REPORTER_ASSERT(reporter, false);
    }
    if (!paint.get()) {
        REPORTER_ASSERT(reporter, false);
    } else {
        REPORTER_ASSERT(reporter, true);
    }

    paint.set(nullptr);
    check(reporter, 0, 1, 1, 1);

    if (paint.get()) {
        REPORTER_ASSERT(reporter, false);
    } else {
        REPORTER_ASSERT(reporter, true);
    }
    if (!paint.get()) {
        REPORTER_ASSERT(reporter, true);
    } else {
        REPORTER_ASSERT(reporter, false);
    }

    auto e = Create();
    REPORTER_ASSERT(reporter, sizeof(e) == sizeof(void*));

    check(reporter, 0, 1, 2, 1);
    paint.set(e);
    check(reporter, 1, 1, 2, 1);
    REPORTER_ASSERT(reporter, paint.fEffect.get()->fRefCnt == 2);

    Paint paint2;
    paint2.set(paint.get());
    check(reporter, 2, 1, 2, 1);
    REPORTER_ASSERT(reporter, paint.fEffect.get()->fRefCnt == 3);

    // Test sk_sp::operator->
    delete paint.get()->method();
    check(reporter, 2, 1, 2, 1);

    // Test sk_sp::operator*
    delete (*paint.get()).method();
    check(reporter, 2, 1, 2, 1);

    paint.set(nullptr);
    e = nullptr;
    paint2.set(nullptr);
    check(reporter, 2, 4, 2, 2);

    reset_counters();
    {
        // Test convertible sk_sp assignment.
        check(reporter, 0, 0, 0, 0);
        sk_sp<Effect> foo(nullptr);
        REPORTER_ASSERT(reporter, !foo);
        foo = make_effect();
        REPORTER_ASSERT(reporter, foo);
        check(reporter, 0, 0, 1, 0);
    }
    check(reporter, 0, 1, 1, 1);

    // Test passing convertible rvalue into funtion.
    reset_counters();
    paint.set(EffectImpl::Create());
    check(reporter, 0, 0, 1, 0);
    paint.set(nullptr);
    check(reporter, 0, 1, 1, 1);

    reset_counters();
    auto baz = EffectImpl::Create();
    check(reporter, 0, 0, 1, 0);
    paint.set(std::move(baz));
    check(reporter, 0, 0, 1, 0);
    REPORTER_ASSERT(reporter, !baz);
    paint.set(nullptr);
    check(reporter, 0, 1, 1, 1);

    reset_counters();
    {
        // test comparison operator with convertible type.
        sk_sp<EffectImpl> bar1 = EffectImpl::Create();
        sk_sp<Effect> bar2(bar1);  // convertible copy constructor
        check(reporter, 1, 0, 1, 0);
        REPORTER_ASSERT(reporter, bar1);
        REPORTER_ASSERT(reporter, bar2);
        REPORTER_ASSERT(reporter, bar1 == bar2);
        REPORTER_ASSERT(reporter, bar2 == bar1);
        REPORTER_ASSERT(reporter, !(bar1 != bar2));
        REPORTER_ASSERT(reporter, !(bar2 != bar1));
        sk_sp<Effect> bar3(nullptr);
        bar3 = bar1;  // convertible copy assignment
        check(reporter, 2, 0, 1, 0);

    }
    check(reporter, 2, 3, 1, 1);

    // test passing convertible copy into funtion.
    reset_counters();
    baz = EffectImpl::Create();
    check(reporter, 0, 0, 1, 0);
    paint.set(baz);
    check(reporter, 1, 0, 1, 0);
    baz = nullptr;
    check(reporter, 1, 1, 1, 0);
    paint.set(nullptr);
    check(reporter, 1, 2, 1, 1);

    {
        sk_sp<SkRefCnt> empty;
        sk_sp<SkRefCnt> notEmpty = sk_make_sp<SkRefCnt>();
        REPORTER_ASSERT(reporter, empty == sk_sp<SkRefCnt>());

        REPORTER_ASSERT(reporter, notEmpty != empty);
        REPORTER_ASSERT(reporter, empty != notEmpty);

        REPORTER_ASSERT(reporter, nullptr == empty);
        REPORTER_ASSERT(reporter, empty == nullptr);
        REPORTER_ASSERT(reporter, empty == empty);

        REPORTER_ASSERT(reporter, nullptr <= empty);
        REPORTER_ASSERT(reporter, empty <= nullptr);
        REPORTER_ASSERT(reporter, empty <= empty);

        REPORTER_ASSERT(reporter, nullptr >= empty);
        REPORTER_ASSERT(reporter, empty >= nullptr);
        REPORTER_ASSERT(reporter, empty >= empty);
    }

    {
        sk_sp<SkRefCnt> a = sk_make_sp<SkRefCnt>();
        sk_sp<SkRefCnt> b = sk_make_sp<SkRefCnt>();
        REPORTER_ASSERT(reporter, a != b);
        REPORTER_ASSERT(reporter, (a < b) != (b < a));
        REPORTER_ASSERT(reporter, (b > a) != (a > b));
        REPORTER_ASSERT(reporter, (a <= b) != (b <= a));
        REPORTER_ASSERT(reporter, (b >= a) != (a >= b));

        REPORTER_ASSERT(reporter, a == a);
        REPORTER_ASSERT(reporter, a <= a);
        REPORTER_ASSERT(reporter, a >= a);
    }

    // http://wg21.cmeerw.net/lwg/issue998
    {
        class foo : public SkRefCnt {
        public:
            foo() : bar(this) {}
            void reset() { bar.reset(); }
        private:
            sk_sp<foo> bar;
        };
        // The following should properly delete the object and not cause undefined behavior.
        // This is an ugly example, but the same issue can arise in more subtle ways.
        (new foo)->reset();
    }

    // https://crrev.com/0d4ef2583a6f19c3e61be04d36eb1a60b133832c
    {
        struct StructB;
        struct StructA : public SkRefCnt {
            sk_sp<StructB> b;
        };

        struct StructB : public SkRefCnt {
            sk_sp<StructA> a;
            ~StructB() override {} // Some clang versions don't emit this implicitly.
        };

        // Create a reference cycle.
        StructA* a = new StructA;
        a->b.reset(new StructB);
        a->b->a.reset(a);

        // Break the cycle by calling reset(). This will cause |a| (and hence, |a.b|)
        // to be deleted before the call to reset() returns. This tests that the
        // implementation of sk_sp::reset() doesn't access |this| after it
        // deletes the underlying pointer. This behaviour is consistent with the
        // definition of unique_ptr::reset in C++11.
        a->b.reset();
    }
}

namespace {
struct FooAbstract : public SkRefCnt {
    virtual void f() = 0;
};
struct FooConcrete : public FooAbstract {
    void f() override {}
};
}
static sk_sp<FooAbstract> make_foo() {
    // can not cast FooConcrete to FooAbstract.
    // can cast FooConcrete* to FooAbstract*.
    return sk_make_sp<FooConcrete>();
}
DEF_TEST(sk_make_sp, r) {
    auto x = make_foo();
}

// Test that reset() "adopts" ownership from the caller, even if we are given the same ptr twice
//
DEF_TEST(sk_sp_reset, r) {
    SkRefCnt* rc = new SkRefCnt;
    REPORTER_ASSERT(r, rc->unique());

    sk_sp<SkRefCnt> sp;
    sp.reset(rc);
    // We have transfered our ownership over to sp
    REPORTER_ASSERT(r, rc->unique());

    rc->ref();  // now "rc" is also an owner
    REPORTER_ASSERT(r, !rc->unique());

    sp.reset(rc);   // this should transfer our ownership over to sp
    REPORTER_ASSERT(r, rc->unique());
}

DEF_TEST(sk_sp_ref, r) {
    SkRefCnt* rc = new SkRefCnt;
    REPORTER_ASSERT(r, rc->unique());

    {
        sk_sp<SkRefCnt> sp = sk_ref_sp(rc);
        REPORTER_ASSERT(r, !rc->unique());
    }

    REPORTER_ASSERT(r, rc->unique());
    rc->unref();
}
