/*
 * 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 SkNEW_ARGS(SkCachedData, (size, dm));
    } else {
        return SkNEW_ARGS(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() : NULL);
        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() : NULL);
        check_data(reporter, data, 2, kInCache, kLocked);
        data->unref();
        check_data(reporter, data, 1, kInCache, kUnlocked);
        data->detachFromCacheAndUnref();
    }
}

