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