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 SkAutoTUnref<SkDiscardableMemoryPool> pool(SkDiscardableMemoryPool::Create(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 96