Index: tests/CachedDataTest.cpp |
diff --git a/tests/CachedDataTest.cpp b/tests/CachedDataTest.cpp |
new file mode 100644 |
index 0000000000000000000000000000000000000000..f65a46b770d0ecabda70654036e70e8ec86c90f8 |
--- /dev/null |
+++ b/tests/CachedDataTest.cpp |
@@ -0,0 +1,95 @@ |
+/* |
+ * Copyright 2014 Google Inc. |
+ * |
+ * Use of this source code is governed by a BSD-style license that can be |
+ * found in the LICENSE file. |
+ */ |
+ |
+#include "SkCachedData.h" |
+#include "SkDiscardableMemoryPool.h" |
+#include "Test.h" |
+ |
+enum LockedState { |
+ kUnlocked, |
+ kLocked, |
+}; |
+ |
+enum CachedState { |
+ kNotInCache, |
+ kInCache, |
+}; |
+ |
+static void check_data(skiatest::Reporter* reporter, SkCachedData* data, |
+ int refcnt, CachedState cacheState, LockedState lockedState) { |
+ REPORTER_ASSERT(reporter, data->testing_only_getRefCnt() == refcnt); |
+ REPORTER_ASSERT(reporter, data->testing_only_isInCache() == (kInCache == cacheState)); |
+ REPORTER_ASSERT(reporter, data->testing_only_isLocked() == (lockedState == kLocked)); |
+} |
+ |
+static SkCachedData* make_data(size_t size, SkDiscardableMemoryPool* pool) { |
+ if (pool) { |
+ SkDiscardableMemory* dm = pool->create(size); |
+ // the pool "can" return null, but it shouldn't in these controlled conditions |
+ SK_ALWAYSBREAK(dm); |
+ return SkNEW_ARGS(SkCachedData, (size, dm)); |
+ } else { |
+ return SkNEW_ARGS(SkCachedData, (sk_malloc_throw(size), size)); |
+ } |
+} |
+ |
+// returns with the data locked by client and cache |
+static SkCachedData* test_locking(skiatest::Reporter* reporter, |
+ size_t size, SkDiscardableMemoryPool* pool) { |
+ SkCachedData* data = make_data(size, pool); |
+ |
+ memset(data->writable_data(), 0x80, size); // just to use writable_data() |
+ |
+ check_data(reporter, data, 1, kNotInCache, kLocked); |
+ |
+ data->ref(); |
+ check_data(reporter, data, 2, kNotInCache, kLocked); |
+ data->unref(); |
+ check_data(reporter, data, 1, kNotInCache, kLocked); |
+ |
+ data->attachToCacheAndRef(); |
+ check_data(reporter, data, 2, kInCache, kLocked); |
+ |
+ data->unref(); |
+ check_data(reporter, data, 1, kInCache, kUnlocked); |
+ |
+ data->ref(); |
+ check_data(reporter, data, 2, kInCache, kLocked); |
+ |
+ return data; |
+} |
+ |
+/* |
+ * SkCachedData behaves differently (regarding its locked/unlocked state) depending on |
+ * when it is in the cache or not. Being in the cache is signaled by calling attachToCacheAndRef() |
+ * instead of ref(). (and balanced by detachFromCacheAndUnref). |
+ * |
+ * Thus, among other things, we test the end-of-life behavior when the client is the last owner |
+ * and when the cache is. |
+ */ |
+DEF_TEST(CachedData, reporter) { |
+ SkAutoTUnref<SkDiscardableMemoryPool> pool(SkDiscardableMemoryPool::Create(1000)); |
+ |
+ for (int useDiscardable = 0; useDiscardable <= 1; ++useDiscardable) { |
+ const size_t size = 100; |
+ |
+ // test with client as last owner |
+ SkCachedData* data = test_locking(reporter, size, useDiscardable ? pool.get() : NULL); |
+ check_data(reporter, data, 2, kInCache, kLocked); |
+ data->detachFromCacheAndUnref(); |
+ check_data(reporter, data, 1, kNotInCache, kLocked); |
+ data->unref(); |
+ |
+ // test with cache as last owner |
+ data = test_locking(reporter, size, useDiscardable ? pool.get() : NULL); |
+ check_data(reporter, data, 2, kInCache, kLocked); |
+ data->unref(); |
+ check_data(reporter, data, 1, kInCache, kUnlocked); |
+ data->detachFromCacheAndUnref(); |
+ } |
+} |
+ |