ImageCacheTest.cpp revision 49f085dddff10473b6ebf832a974288300224e60
1 /*
2 * Copyright 2013 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#include "SkDiscardableMemory.h"
9#include "SkResourceCache.h"
10#include "Test.h"
11
12namespace {
13static void* gGlobalAddress;
14struct TestingKey : public SkResourceCache::Key {
15    void*       fPtr;
16    intptr_t    fValue;
17
18    TestingKey(intptr_t value) : fPtr(&gGlobalAddress), fValue(value) {
19        this->init(sizeof(fPtr) + sizeof(fValue));
20    }
21};
22struct TestingRec : public SkResourceCache::Rec {
23    TestingRec(const TestingKey& key, uint32_t value) : fKey(key), fValue(value) {}
24
25    TestingKey  fKey;
26    intptr_t    fValue;
27
28    virtual const Key& getKey() const SK_OVERRIDE { return fKey; }
29    virtual size_t bytesUsed() const SK_OVERRIDE { return sizeof(fKey) + sizeof(fValue); }
30};
31}
32
33static const int COUNT = 10;
34static const int DIM = 256;
35
36static void test_cache(skiatest::Reporter* reporter, SkResourceCache& cache,
37                       bool testPurge) {
38    SkResourceCache::ID id;
39
40    for (int i = 0; i < COUNT; ++i) {
41        TestingKey key(i);
42
43        const TestingRec* rec = (const TestingRec*)cache.findAndLock(key);
44        REPORTER_ASSERT(reporter, NULL == rec);
45
46        TestingRec* newRec = SkNEW_ARGS(TestingRec, (key, i));
47        const TestingRec* addedRec = (const TestingRec*)cache.addAndLock(newRec);
48        REPORTER_ASSERT(reporter, addedRec);
49
50        const TestingRec* foundRec = (const TestingRec*)cache.findAndLock(key);
51        REPORTER_ASSERT(reporter, foundRec == addedRec);
52        REPORTER_ASSERT(reporter, foundRec->fValue == i);
53        cache.unlock(foundRec);
54        cache.unlock(addedRec);
55    }
56
57    if (testPurge) {
58        // stress test, should trigger purges
59        for (size_t i = 0; i < COUNT * 100; ++i) {
60            TestingKey key(i);
61            SkResourceCache::ID id = cache.addAndLock(SkNEW_ARGS(TestingRec, (key, i)));
62            REPORTER_ASSERT(reporter, id);
63            cache.unlock(id);
64        }
65    }
66
67    // test the originals after all that purging
68    for (int i = 0; i < COUNT; ++i) {
69        id = cache.findAndLock(TestingKey(i));
70        if (id) {
71            cache.unlock(id);
72        }
73    }
74
75    cache.setTotalByteLimit(0);
76}
77
78#include "SkDiscardableMemoryPool.h"
79
80static SkDiscardableMemoryPool* gPool;
81static SkDiscardableMemory* pool_factory(size_t bytes) {
82    SkASSERT(gPool);
83    return gPool->create(bytes);
84}
85
86DEF_TEST(ImageCache, reporter) {
87    static const size_t defLimit = DIM * DIM * 4 * COUNT + 1024;    // 1K slop
88
89    {
90        SkResourceCache cache(defLimit);
91        test_cache(reporter, cache, true);
92    }
93    {
94        SkAutoTUnref<SkDiscardableMemoryPool> pool(
95                SkDiscardableMemoryPool::Create(defLimit, NULL));
96        gPool = pool.get();
97        SkResourceCache cache(pool_factory);
98        test_cache(reporter, cache, true);
99    }
100    {
101        SkResourceCache cache(SkDiscardableMemory::Create);
102        test_cache(reporter, cache, false);
103    }
104}
105
106DEF_TEST(ImageCache_doubleAdd, r) {
107    // Adding the same key twice should be safe.
108    SkResourceCache cache(4096);
109
110    TestingKey key(1);
111
112    SkResourceCache::ID id1 = cache.addAndLock(SkNEW_ARGS(TestingRec, (key, 2)));
113    SkResourceCache::ID id2 = cache.addAndLock(SkNEW_ARGS(TestingRec, (key, 3)));
114    // We don't really care if id1 == id2 as long as unlocking both works.
115    cache.unlock(id1);
116    cache.unlock(id2);
117
118    // Lookup can return either value.
119    const TestingRec* rec = (const TestingRec*)cache.findAndLock(key);
120    REPORTER_ASSERT(r, rec);
121    REPORTER_ASSERT(r, 2 == rec->fValue || 3 == rec->fValue);
122    cache.unlock(rec);
123}
124