/*
 * 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
        SK_ALWAYSBREAK(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();
    }
}

