aboutsummaryrefslogtreecommitdiffhomepage
path: root/tests/ImageCacheTest.cpp
blob: 89d2f8d5ddbfb7f29d0875d0d837a5c45cdac5d3 (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
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
 /*
 * 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 {
    intptr_t    fValue;

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

    TestingKey  fKey;
    intptr_t    fValue;

    const Key& getKey() const override { return fKey; }
    size_t bytesUsed() const override { return sizeof(fKey) + sizeof(fValue); }
    const char* getCategory() const override { return "test_cache"; }
    SkDiscardableMemory* diagnostic_only_getDiscardable() const override { return nullptr; }

    static bool Visitor(const SkResourceCache::Rec& baseRec, void* context) {
        const TestingRec& rec = static_cast<const TestingRec&>(baseRec);
        intptr_t* result = (intptr_t*)context;
        
        *result = rec.fValue;
        return true;
    }
};
}

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

static void test_cache(skiatest::Reporter* reporter, SkResourceCache& cache, bool testPurge) {
    for (int i = 0; i < COUNT; ++i) {
        TestingKey key(i);
        intptr_t value = -1;

        REPORTER_ASSERT(reporter, !cache.find(key, TestingRec::Visitor, &value));
        REPORTER_ASSERT(reporter, -1 == value);

        cache.add(new TestingRec(key, i));

        REPORTER_ASSERT(reporter, cache.find(key, TestingRec::Visitor, &value));
        REPORTER_ASSERT(reporter, i == value);
    }

    if (testPurge) {
        // stress test, should trigger purges
        for (int i = 0; i < COUNT * 100; ++i) {
            TestingKey key(i);
            cache.add(new TestingRec(key, i));
        }
    }

    // test the originals after all that purging
    for (int i = 0; i < COUNT; ++i) {
        intptr_t value;
        (void)cache.find(TestingKey(i), TestingRec::Visitor, &value);
    }

    cache.setTotalByteLimit(0);
}

static void test_cache_purge_shared_id(skiatest::Reporter* reporter, SkResourceCache& cache) {
    for (int i = 0; i < COUNT; ++i) {
        TestingKey key(i, i & 1);   // every other key will have a 1 for its sharedID
        cache.add(new TestingRec(key, i));
    }

    // Ensure that everyone is present
    for (int i = 0; i < COUNT; ++i) {
        TestingKey key(i, i & 1);   // every other key will have a 1 for its sharedID
        intptr_t value = -1;

        REPORTER_ASSERT(reporter, cache.find(key, TestingRec::Visitor, &value));
        REPORTER_ASSERT(reporter, value == i);
    }

    // Now purge the ones that had a non-zero sharedID (the odd-indexed ones)
    cache.purgeSharedID(1);

    // Ensure that only the even ones are still present
    for (int i = 0; i < COUNT; ++i) {
        TestingKey key(i, i & 1);   // every other key will have a 1 for its sharedID
        intptr_t value = -1;

        if (i & 1) {
            REPORTER_ASSERT(reporter, !cache.find(key, TestingRec::Visitor, &value));
        } else {
            REPORTER_ASSERT(reporter, cache.find(key, TestingRec::Visitor, &value));
            REPORTER_ASSERT(reporter, value == i);
        }
    }
}

#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, nullptr));
        gPool = pool.get();
        SkResourceCache cache(pool_factory);
        test_cache(reporter, cache, true);
    }
    {
        SkResourceCache cache(SkDiscardableMemory::Create);
        test_cache(reporter, cache, false);
    }
    {
        SkResourceCache cache(defLimit);
        test_cache_purge_shared_id(reporter, cache);
    }
}

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

    TestingKey key(1);

    cache.add(new TestingRec(key, 2));
    cache.add(new TestingRec(key, 3));

    // Lookup can return either value.
    intptr_t value = -1;
    REPORTER_ASSERT(r, cache.find(key, TestingRec::Visitor, &value));
    REPORTER_ASSERT(r, 2 == value || 3 == value);
}