aboutsummaryrefslogtreecommitdiffhomepage
path: root/tests/ImageCacheTest.cpp
blob: bda10a040a9137f0598008c110718cf500ae82cb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
 /*
 * Copyright 2013 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "SkDiscardableMemory.h"
#include "SkResourceCache.h"
#include "Test.h"

namespace {
static void* gGlobalAddress;
struct TestingKey : public SkResourceCache::Key {
    void*       fPtr;
    intptr_t    fValue;

    TestingKey(intptr_t value) : fPtr(&gGlobalAddress), fValue(value) {
        this->init(sizeof(fPtr) + sizeof(fValue));
    }
};
struct TestingRec : public SkResourceCache::Rec {
    TestingRec(const TestingKey& key, uint32_t value) : fKey(key), fValue(value) {}

    TestingKey  fKey;
    intptr_t    fValue;

    virtual const Key& getKey() const SK_OVERRIDE { return fKey; }
    virtual size_t bytesUsed() const SK_OVERRIDE { return sizeof(fKey) + sizeof(fValue); }
};
}

static const int COUNT = 10;
static const int DIM = 256;

static void test_cache(skiatest::Reporter* reporter, SkResourceCache& cache,
                       bool testPurge) {
    SkResourceCache::ID id;

    for (int i = 0; i < COUNT; ++i) {
        TestingKey key(i);

        const TestingRec* rec = (const TestingRec*)cache.findAndLock(key);
        REPORTER_ASSERT(reporter, NULL == rec);

        TestingRec* newRec = SkNEW_ARGS(TestingRec, (key, i));
        const TestingRec* addedRec = (const TestingRec*)cache.addAndLock(newRec);
        REPORTER_ASSERT(reporter, NULL != addedRec);

        const TestingRec* foundRec = (const TestingRec*)cache.findAndLock(key);
        REPORTER_ASSERT(reporter, foundRec == addedRec);
        REPORTER_ASSERT(reporter, foundRec->fValue == i);
        cache.unlock(foundRec);
        cache.unlock(addedRec);
    }

    if (testPurge) {
        // stress test, should trigger purges
        for (size_t i = 0; i < COUNT * 100; ++i) {
            TestingKey key(i);
            SkResourceCache::ID id = cache.addAndLock(SkNEW_ARGS(TestingRec, (key, i)));
            REPORTER_ASSERT(reporter, NULL != id);
            cache.unlock(id);
        }
    }

    // test the originals after all that purging
    for (int i = 0; i < COUNT; ++i) {
        id = cache.findAndLock(TestingKey(i));
        if (id) {
            cache.unlock(id);
        }
    }

    cache.setTotalByteLimit(0);
}

#include "SkDiscardableMemoryPool.h"

static SkDiscardableMemoryPool* gPool;
static SkDiscardableMemory* pool_factory(size_t bytes) {
    SkASSERT(gPool);
    return gPool->create(bytes);
}

DEF_TEST(ImageCache, reporter) {
    static const size_t defLimit = DIM * DIM * 4 * COUNT + 1024;    // 1K slop

    {
        SkResourceCache cache(defLimit);
        test_cache(reporter, cache, true);
    }
    {
        SkAutoTUnref<SkDiscardableMemoryPool> pool(
                SkDiscardableMemoryPool::Create(defLimit, NULL));
        gPool = pool.get();
        SkResourceCache cache(pool_factory);
        test_cache(reporter, cache, true);
    }
    {
        SkResourceCache cache(SkDiscardableMemory::Create);
        test_cache(reporter, cache, false);
    }
}

DEF_TEST(ImageCache_doubleAdd, r) {
    // Adding the same key twice should be safe.
    SkResourceCache cache(4096);

    TestingKey key(1);

    SkResourceCache::ID id1 = cache.addAndLock(SkNEW_ARGS(TestingRec, (key, 2)));
    SkResourceCache::ID id2 = cache.addAndLock(SkNEW_ARGS(TestingRec, (key, 3)));
    // We don't really care if id1 == id2 as long as unlocking both works.
    cache.unlock(id1);
    cache.unlock(id2);

    // Lookup can return either value.
    const TestingRec* rec = (const TestingRec*)cache.findAndLock(key);
    REPORTER_ASSERT(r, NULL != rec);
    REPORTER_ASSERT(r, 2 == rec->fValue || 3 == rec->fValue);
    cache.unlock(rec);
}