• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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