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

#include "SkCachedData.h"
#include "SkDiscardableMemoryPool.h"
#include "Test.h"

enum LockedState {
    kUnlocked,
    kLocked,
};

enum CachedState {
    kNotInCache,
    kInCache,
};

static void check_data(skiatest::Reporter* reporter, SkCachedData* data,
                       int refcnt, CachedState cacheState, LockedState lockedState) {
    REPORTER_ASSERT(reporter, data->testing_only_getRefCnt() == refcnt);
    REPORTER_ASSERT(reporter, data->testing_only_isInCache() == (kInCache == cacheState));
    REPORTER_ASSERT(reporter, data->testing_only_isLocked() == (lockedState == kLocked));
}

static SkCachedData* make_data(size_t size, SkDiscardableMemoryPool* pool) {
    if (pool) {
        SkDiscardableMemory* dm = pool->create(size);
        // the pool "can" return null, but it shouldn't in these controlled conditions
        SkASSERT_RELEASE(dm);
        return new SkCachedData(size, dm);
    } else {
        return new SkCachedData(sk_malloc_throw(size), size);
    }
}

// returns with the data locked by client and cache
static SkCachedData* test_locking(skiatest::Reporter* reporter,
                                  size_t size, SkDiscardableMemoryPool* pool) {
    SkCachedData* data = make_data(size, pool);

    memset(data->writable_data(), 0x80, size);  // just to use writable_data()

    check_data(reporter, data, 1, kNotInCache, kLocked);

    data->ref();
    check_data(reporter, data, 2, kNotInCache, kLocked);
    data->unref();
    check_data(reporter, data, 1, kNotInCache, kLocked);

    data->attachToCacheAndRef();
    check_data(reporter, data, 2, kInCache, kLocked);

    data->unref();
    check_data(reporter, data, 1, kInCache, kUnlocked);

    data->ref();
    check_data(reporter, data, 2, kInCache, kLocked);

    return data;
}

/*
 *  SkCachedData behaves differently (regarding its locked/unlocked state) depending on
 *  when it is in the cache or not. Being in the cache is signaled by calling attachToCacheAndRef()
 *  instead of ref(). (and balanced by detachFromCacheAndUnref).
 *
 *  Thus, among other things, we test the end-of-life behavior when the client is the last owner
 *  and when the cache is.
 */
DEF_TEST(CachedData, reporter) {
    SkAutoTUnref<SkDiscardableMemoryPool> pool(SkDiscardableMemoryPool::Create(1000));

    for (int useDiscardable = 0; useDiscardable <= 1; ++useDiscardable) {
        const size_t size = 100;

        // test with client as last owner
        SkCachedData* data = test_locking(reporter, size, useDiscardable ? pool.get() : nullptr);
        check_data(reporter, data, 2, kInCache, kLocked);
        data->detachFromCacheAndUnref();
        check_data(reporter, data, 1, kNotInCache, kLocked);
        data->unref();

        // test with cache as last owner
        data = test_locking(reporter, size, useDiscardable ? pool.get() : nullptr);
        check_data(reporter, data, 2, kInCache, kLocked);
        data->unref();
        check_data(reporter, data, 1, kInCache, kUnlocked);
        data->detachFromCacheAndUnref();
    }
}
