1 // Copyright 2021 The Dawn Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include <gtest/gtest.h>
16
17 #include "common/ConcurrentCache.h"
18 #include "dawn_native/AsyncTask.h"
19 #include "dawn_platform/DawnPlatform.h"
20 #include "utils/SystemUtils.h"
21
22 namespace {
23 class SimpleCachedObject {
24 public:
SimpleCachedObject(size_t value)25 explicit SimpleCachedObject(size_t value) : mValue(value) {
26 }
27
GetValue() const28 size_t GetValue() const {
29 return mValue;
30 }
31
32 struct EqualityFunc {
operator ()__anond37b7da60111::SimpleCachedObject::EqualityFunc33 bool operator()(const SimpleCachedObject* a, const SimpleCachedObject* b) const {
34 return a->mValue == b->mValue;
35 }
36 };
37
38 struct HashFunc {
operator ()__anond37b7da60111::SimpleCachedObject::HashFunc39 size_t operator()(const SimpleCachedObject* obj) const {
40 return obj->mValue;
41 }
42 };
43
44 private:
45 size_t mValue;
46 };
47
48 } // anonymous namespace
49
50 class ConcurrentCacheTest : public testing::Test {
51 public:
ConcurrentCacheTest()52 ConcurrentCacheTest() : mPool(mPlatform.CreateWorkerTaskPool()), mTaskManager(mPool.get()) {
53 }
54
55 protected:
56 dawn_platform::Platform mPlatform;
57 std::unique_ptr<dawn_platform::WorkerTaskPool> mPool;
58 dawn_native::AsyncTaskManager mTaskManager;
59 ConcurrentCache<SimpleCachedObject> mCache;
60 };
61
62 // Test inserting two objects that are equal to each other into the concurrent cache works as
63 // expected.
TEST_F(ConcurrentCacheTest,InsertAtSameTime)64 TEST_F(ConcurrentCacheTest, InsertAtSameTime) {
65 SimpleCachedObject cachedObject(1);
66 SimpleCachedObject anotherCachedObject(1);
67
68 std::pair<SimpleCachedObject*, bool> insertOutput = {};
69 std::pair<SimpleCachedObject*, bool> anotherInsertOutput = {};
70
71 ConcurrentCache<SimpleCachedObject>* cachePtr = &mCache;
72 dawn_native::AsyncTask asyncTask1([&insertOutput, cachePtr, &cachedObject] {
73 insertOutput = cachePtr->Insert(&cachedObject);
74 });
75 dawn_native::AsyncTask asyncTask2([&anotherInsertOutput, cachePtr, &anotherCachedObject] {
76 anotherInsertOutput = cachePtr->Insert(&anotherCachedObject);
77 });
78 mTaskManager.PostTask(std::move(asyncTask1));
79 mTaskManager.PostTask(std::move(asyncTask2));
80
81 mTaskManager.WaitAllPendingTasks();
82
83 ASSERT_TRUE(insertOutput.first == &cachedObject || insertOutput.first == &anotherCachedObject);
84 ASSERT_EQ(insertOutput.first, anotherInsertOutput.first);
85 ASSERT_EQ(insertOutput.second, !anotherInsertOutput.second);
86 }
87
88 // Testing erasing an object after inserting into the cache works as expected.
TEST_F(ConcurrentCacheTest,EraseAfterInsertion)89 TEST_F(ConcurrentCacheTest, EraseAfterInsertion) {
90 SimpleCachedObject cachedObject(1);
91
92 std::pair<SimpleCachedObject*, bool> insertOutput = {};
93 ConcurrentCache<SimpleCachedObject>* cachePtr = &mCache;
94 dawn_native::AsyncTask insertTask([&insertOutput, cachePtr, &cachedObject] {
95 insertOutput = cachePtr->Insert(&cachedObject);
96 });
97
98 size_t erasedObjectCount = 0;
99 dawn_native::AsyncTask eraseTask([&erasedObjectCount, cachePtr, &cachedObject] {
100 while (cachePtr->Find(&cachedObject) == nullptr) {
101 utils::USleep(100);
102 }
103 erasedObjectCount = cachePtr->Erase(&cachedObject);
104 });
105
106 mTaskManager.PostTask(std::move(insertTask));
107 mTaskManager.PostTask(std::move(eraseTask));
108
109 mTaskManager.WaitAllPendingTasks();
110
111 ASSERT_EQ(&cachedObject, insertOutput.first);
112 ASSERT_TRUE(insertOutput.second);
113 ASSERT_EQ(1u, erasedObjectCount);
114 }
115