CachedDataTest.cpp 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  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. #include "include/core/SkRefCnt.h"
  8. #include "include/core/SkTypes.h"
  9. #include "include/private/SkMalloc.h"
  10. #include "src/core/SkCachedData.h"
  11. #include "src/lazy/SkDiscardableMemoryPool.h"
  12. #include "tests/Test.h"
  13. #include <cstring>
  14. class SkDiscardableMemory;
  15. enum LockedState {
  16. kUnlocked,
  17. kLocked,
  18. };
  19. enum CachedState {
  20. kNotInCache,
  21. kInCache,
  22. };
  23. static void check_data(skiatest::Reporter* reporter, SkCachedData* data,
  24. int refcnt, CachedState cacheState, LockedState lockedState) {
  25. REPORTER_ASSERT(reporter, data->testing_only_getRefCnt() == refcnt);
  26. REPORTER_ASSERT(reporter, data->testing_only_isInCache() == (kInCache == cacheState));
  27. REPORTER_ASSERT(reporter, data->testing_only_isLocked() == (lockedState == kLocked));
  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. // returns with the data locked by client and cache
  40. static SkCachedData* test_locking(skiatest::Reporter* reporter,
  41. size_t size, SkDiscardableMemoryPool* pool) {
  42. SkCachedData* data = make_data(size, pool);
  43. memset(data->writable_data(), 0x80, size); // just to use writable_data()
  44. check_data(reporter, data, 1, kNotInCache, kLocked);
  45. data->ref();
  46. check_data(reporter, data, 2, kNotInCache, kLocked);
  47. data->unref();
  48. check_data(reporter, data, 1, kNotInCache, kLocked);
  49. data->attachToCacheAndRef();
  50. check_data(reporter, data, 2, kInCache, kLocked);
  51. data->unref();
  52. check_data(reporter, data, 1, kInCache, kUnlocked);
  53. data->ref();
  54. check_data(reporter, data, 2, kInCache, kLocked);
  55. return data;
  56. }
  57. /*
  58. * SkCachedData behaves differently (regarding its locked/unlocked state) depending on
  59. * when it is in the cache or not. Being in the cache is signaled by calling attachToCacheAndRef()
  60. * instead of ref(). (and balanced by detachFromCacheAndUnref).
  61. *
  62. * Thus, among other things, we test the end-of-life behavior when the client is the last owner
  63. * and when the cache is.
  64. */
  65. DEF_TEST(CachedData, reporter) {
  66. sk_sp<SkDiscardableMemoryPool> pool(SkDiscardableMemoryPool::Make(1000));
  67. for (int useDiscardable = 0; useDiscardable <= 1; ++useDiscardable) {
  68. const size_t size = 100;
  69. // test with client as last owner
  70. SkCachedData* data = test_locking(reporter, size, useDiscardable ? pool.get() : nullptr);
  71. check_data(reporter, data, 2, kInCache, kLocked);
  72. data->detachFromCacheAndUnref();
  73. check_data(reporter, data, 1, kNotInCache, kLocked);
  74. data->unref();
  75. // test with cache as last owner
  76. data = test_locking(reporter, size, useDiscardable ? pool.get() : nullptr);
  77. check_data(reporter, data, 2, kInCache, kLocked);
  78. data->unref();
  79. check_data(reporter, data, 1, kInCache, kUnlocked);
  80. data->detachFromCacheAndUnref();
  81. }
  82. }