Home | History | Annotate | Download | only in tests
      1 /*
      2  * Copyright 2014 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 "SkCachedData.h"
      9 #include "SkDiscardableMemoryPool.h"
     10 #include "Test.h"
     11 
     12 enum LockedState {
     13     kUnlocked,
     14     kLocked,
     15 };
     16 
     17 enum CachedState {
     18     kNotInCache,
     19     kInCache,
     20 };
     21 
     22 static void check_data(skiatest::Reporter* reporter, SkCachedData* data,
     23                        int refcnt, CachedState cacheState, LockedState lockedState) {
     24     REPORTER_ASSERT(reporter, data->testing_only_getRefCnt() == refcnt);
     25     REPORTER_ASSERT(reporter, data->testing_only_isInCache() == (kInCache == cacheState));
     26     REPORTER_ASSERT(reporter, data->testing_only_isLocked() == (lockedState == kLocked));
     27 }
     28 
     29 static SkCachedData* make_data(size_t size, SkDiscardableMemoryPool* pool) {
     30     if (pool) {
     31         SkDiscardableMemory* dm = pool->create(size);
     32         // the pool "can" return null, but it shouldn't in these controlled conditions
     33         SkASSERT_RELEASE(dm);
     34         return new SkCachedData(size, dm);
     35     } else {
     36         return new SkCachedData(sk_malloc_throw(size), size);
     37     }
     38 }
     39 
     40 // returns with the data locked by client and cache
     41 static SkCachedData* test_locking(skiatest::Reporter* reporter,
     42                                   size_t size, SkDiscardableMemoryPool* pool) {
     43     SkCachedData* data = make_data(size, pool);
     44 
     45     memset(data->writable_data(), 0x80, size);  // just to use writable_data()
     46 
     47     check_data(reporter, data, 1, kNotInCache, kLocked);
     48 
     49     data->ref();
     50     check_data(reporter, data, 2, kNotInCache, kLocked);
     51     data->unref();
     52     check_data(reporter, data, 1, kNotInCache, kLocked);
     53 
     54     data->attachToCacheAndRef();
     55     check_data(reporter, data, 2, kInCache, kLocked);
     56 
     57     data->unref();
     58     check_data(reporter, data, 1, kInCache, kUnlocked);
     59 
     60     data->ref();
     61     check_data(reporter, data, 2, kInCache, kLocked);
     62 
     63     return data;
     64 }
     65 
     66 /*
     67  *  SkCachedData behaves differently (regarding its locked/unlocked state) depending on
     68  *  when it is in the cache or not. Being in the cache is signaled by calling attachToCacheAndRef()
     69  *  instead of ref(). (and balanced by detachFromCacheAndUnref).
     70  *
     71  *  Thus, among other things, we test the end-of-life behavior when the client is the last owner
     72  *  and when the cache is.
     73  */
     74 DEF_TEST(CachedData, reporter) {
     75     sk_sp<SkDiscardableMemoryPool> pool(SkDiscardableMemoryPool::Make(1000));
     76 
     77     for (int useDiscardable = 0; useDiscardable <= 1; ++useDiscardable) {
     78         const size_t size = 100;
     79 
     80         // test with client as last owner
     81         SkCachedData* data = test_locking(reporter, size, useDiscardable ? pool.get() : nullptr);
     82         check_data(reporter, data, 2, kInCache, kLocked);
     83         data->detachFromCacheAndUnref();
     84         check_data(reporter, data, 1, kNotInCache, kLocked);
     85         data->unref();
     86 
     87         // test with cache as last owner
     88         data = test_locking(reporter, size, useDiscardable ? pool.get() : nullptr);
     89         check_data(reporter, data, 2, kInCache, kLocked);
     90         data->unref();
     91         check_data(reporter, data, 1, kInCache, kUnlocked);
     92         data->detachFromCacheAndUnref();
     93     }
     94 }
     95