Home | History | Annotate | Download | only in tests
      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 
     12 namespace {
     13 static void* gGlobalAddress;
     14 struct TestingKey : public SkResourceCache::Key {
     15     intptr_t    fValue;
     16 
     17     TestingKey(intptr_t value, uint64_t sharedID = 0) : fValue(value) {
     18         this->init(&gGlobalAddress, sharedID, sizeof(fValue));
     19     }
     20 };
     21 struct TestingRec : public SkResourceCache::Rec {
     22     TestingRec(const TestingKey& key, uint32_t value) : fKey(key), fValue(value) {}
     23 
     24     TestingKey  fKey;
     25     intptr_t    fValue;
     26 
     27     const Key& getKey() const override { return fKey; }
     28     size_t bytesUsed() const override { return sizeof(fKey) + sizeof(fValue); }
     29     const char* getCategory() const override { return "test_cache"; }
     30     SkDiscardableMemory* diagnostic_only_getDiscardable() const override { return nullptr; }
     31 
     32     static bool Visitor(const SkResourceCache::Rec& baseRec, void* context) {
     33         const TestingRec& rec = static_cast<const TestingRec&>(baseRec);
     34         intptr_t* result = (intptr_t*)context;
     35 
     36         *result = rec.fValue;
     37         return true;
     38     }
     39 };
     40 }
     41 
     42 static const int COUNT = 10;
     43 static const int DIM = 256;
     44 
     45 static void test_cache(skiatest::Reporter* reporter, SkResourceCache& cache, bool testPurge) {
     46     for (int i = 0; i < COUNT; ++i) {
     47         TestingKey key(i);
     48         intptr_t value = -1;
     49 
     50         REPORTER_ASSERT(reporter, !cache.find(key, TestingRec::Visitor, &value));
     51         REPORTER_ASSERT(reporter, -1 == value);
     52 
     53         cache.add(new TestingRec(key, i));
     54 
     55         REPORTER_ASSERT(reporter, cache.find(key, TestingRec::Visitor, &value));
     56         REPORTER_ASSERT(reporter, i == value);
     57     }
     58 
     59     if (testPurge) {
     60         // stress test, should trigger purges
     61         for (int i = 0; i < COUNT * 100; ++i) {
     62             TestingKey key(i);
     63             cache.add(new TestingRec(key, i));
     64         }
     65     }
     66 
     67     // test the originals after all that purging
     68     for (int i = 0; i < COUNT; ++i) {
     69         intptr_t value;
     70         (void)cache.find(TestingKey(i), TestingRec::Visitor, &value);
     71     }
     72 
     73     cache.setTotalByteLimit(0);
     74 }
     75 
     76 static void test_cache_purge_shared_id(skiatest::Reporter* reporter, SkResourceCache& cache) {
     77     for (int i = 0; i < COUNT; ++i) {
     78         TestingKey key(i, i & 1);   // every other key will have a 1 for its sharedID
     79         cache.add(new TestingRec(key, i));
     80     }
     81 
     82     // Ensure that everyone is present
     83     for (int i = 0; i < COUNT; ++i) {
     84         TestingKey key(i, i & 1);   // every other key will have a 1 for its sharedID
     85         intptr_t value = -1;
     86 
     87         REPORTER_ASSERT(reporter, cache.find(key, TestingRec::Visitor, &value));
     88         REPORTER_ASSERT(reporter, value == i);
     89     }
     90 
     91     // Now purge the ones that had a non-zero sharedID (the odd-indexed ones)
     92     cache.purgeSharedID(1);
     93 
     94     // Ensure that only the even ones are still present
     95     for (int i = 0; i < COUNT; ++i) {
     96         TestingKey key(i, i & 1);   // every other key will have a 1 for its sharedID
     97         intptr_t value = -1;
     98 
     99         if (i & 1) {
    100             REPORTER_ASSERT(reporter, !cache.find(key, TestingRec::Visitor, &value));
    101         } else {
    102             REPORTER_ASSERT(reporter, cache.find(key, TestingRec::Visitor, &value));
    103             REPORTER_ASSERT(reporter, value == i);
    104         }
    105     }
    106 }
    107 
    108 #include "SkDiscardableMemoryPool.h"
    109 
    110 static SkDiscardableMemoryPool* gPool;
    111 static SkDiscardableMemory* pool_factory(size_t bytes) {
    112     SkASSERT(gPool);
    113     return gPool->create(bytes);
    114 }
    115 
    116 DEF_TEST(ImageCache, reporter) {
    117     static const size_t defLimit = DIM * DIM * 4 * COUNT + 1024;    // 1K slop
    118 
    119     {
    120         SkResourceCache cache(defLimit);
    121         test_cache(reporter, cache, true);
    122     }
    123     {
    124         SkAutoTUnref<SkDiscardableMemoryPool> pool(
    125                 SkDiscardableMemoryPool::Create(defLimit, nullptr));
    126         gPool = pool.get();
    127         SkResourceCache cache(pool_factory);
    128         test_cache(reporter, cache, true);
    129     }
    130     {
    131         SkResourceCache cache(SkDiscardableMemory::Create);
    132         test_cache(reporter, cache, false);
    133     }
    134     {
    135         SkResourceCache cache(defLimit);
    136         test_cache_purge_shared_id(reporter, cache);
    137     }
    138 }
    139 
    140 DEF_TEST(ImageCache_doubleAdd, r) {
    141     // Adding the same key twice should be safe.
    142     SkResourceCache cache(4096);
    143 
    144     TestingKey key(1);
    145 
    146     cache.add(new TestingRec(key, 2));
    147     cache.add(new TestingRec(key, 3));
    148 
    149     // Lookup can return either value.
    150     intptr_t value = -1;
    151     REPORTER_ASSERT(r, cache.find(key, TestingRec::Visitor, &value));
    152     REPORTER_ASSERT(r, 2 == value || 3 == value);
    153 }
    154