1 // Copyright 2017 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 "dawn/webgpu_cpp.h"
18
19 class Object : public wgpu::ObjectBase<Object, int*> {
20 public:
21 using ObjectBase::ObjectBase;
22 using ObjectBase::operator=;
23
WGPUReference(int * handle)24 static void WGPUReference(int* handle) {
25 ASSERT_LE(0, *handle);
26 *handle += 1;
27 }
WGPURelease(int * handle)28 static void WGPURelease(int* handle) {
29 ASSERT_LT(0, *handle);
30 *handle -= 1;
31 }
32 };
33
34 // Test that creating an C++ object from a C object takes a ref.
35 // Also test that the C++ object destructor removes a ref.
TEST(ObjectBase,CTypeConstructor)36 TEST(ObjectBase, CTypeConstructor) {
37 int refcount = 1;
38 {
39 Object obj(&refcount);
40 ASSERT_EQ(2, refcount);
41 }
42 ASSERT_EQ(1, refcount);
43 }
44
45 // Test consuming a C object into a C++ object doesn't take a ref.
TEST(ObjectBase,AcquireConstruction)46 TEST(ObjectBase, AcquireConstruction) {
47 int refcount = 1;
48 {
49 Object object = Object::Acquire(&refcount);
50 ASSERT_EQ(1, refcount);
51 }
52 ASSERT_EQ(0, refcount);
53 }
54
55 // Test .Get().
TEST(ObjectBase,Get)56 TEST(ObjectBase, Get) {
57 int refcount = 1;
58 {
59 Object obj1(&refcount);
60
61 ASSERT_EQ(2, refcount);
62 ASSERT_EQ(&refcount, obj1.Get());
63 }
64 ASSERT_EQ(1, refcount);
65 }
66
67 // Test that Release consumes the C++ object into a C object and doesn't release
TEST(ObjectBase,Release)68 TEST(ObjectBase, Release) {
69 int refcount = 1;
70 {
71 Object obj(&refcount);
72 ASSERT_EQ(2, refcount);
73
74 ASSERT_EQ(&refcount, obj.Release());
75 ASSERT_EQ(nullptr, obj.Get());
76 ASSERT_EQ(2, refcount);
77 }
78 ASSERT_EQ(2, refcount);
79 }
80
81 // Test using C++ objects in conditions
TEST(ObjectBase,OperatorBool)82 TEST(ObjectBase, OperatorBool) {
83 int refcount = 1;
84 Object trueObj(&refcount);
85 Object falseObj;
86
87 if (falseObj || !trueObj) {
88 ASSERT_TRUE(false);
89 }
90 }
91
92 // Test the copy constructor of C++ objects
TEST(ObjectBase,CopyConstructor)93 TEST(ObjectBase, CopyConstructor) {
94 int refcount = 1;
95
96 Object source(&refcount);
97 Object destination(source);
98
99 ASSERT_EQ(source.Get(), &refcount);
100 ASSERT_EQ(destination.Get(), &refcount);
101 ASSERT_EQ(3, refcount);
102
103 destination = Object();
104 ASSERT_EQ(refcount, 2);
105 }
106
107 // Test the copy assignment of C++ objects
TEST(ObjectBase,CopyAssignment)108 TEST(ObjectBase, CopyAssignment) {
109 int refcount = 1;
110 Object source(&refcount);
111
112 Object destination;
113 destination = source;
114
115 ASSERT_EQ(source.Get(), &refcount);
116 ASSERT_EQ(destination.Get(), &refcount);
117 ASSERT_EQ(3, refcount);
118
119 destination = Object();
120 ASSERT_EQ(refcount, 2);
121 }
122
123 // Test the repeated copy assignment of C++ objects
TEST(ObjectBase,RepeatedCopyAssignment)124 TEST(ObjectBase, RepeatedCopyAssignment) {
125 int refcount = 1;
126 Object source(&refcount);
127
128 Object destination;
129 for (int i = 0; i < 10; i++) {
130 destination = source;
131 }
132
133 ASSERT_EQ(source.Get(), &refcount);
134 ASSERT_EQ(destination.Get(), &refcount);
135 ASSERT_EQ(3, refcount);
136
137 destination = Object();
138 ASSERT_EQ(refcount, 2);
139 }
140
141 // Test the copy assignment of C++ objects onto themselves
TEST(ObjectBase,CopyAssignmentSelf)142 TEST(ObjectBase, CopyAssignmentSelf) {
143 int refcount = 1;
144
145 Object obj(&refcount);
146
147 // Fool the compiler to avoid a -Wself-assign-overload
148 Object* objPtr = &obj;
149 obj = *objPtr;
150
151 ASSERT_EQ(obj.Get(), &refcount);
152 ASSERT_EQ(refcount, 2);
153 }
154
155 // Test the move constructor of C++ objects
TEST(ObjectBase,MoveConstructor)156 TEST(ObjectBase, MoveConstructor) {
157 int refcount = 1;
158 Object source(&refcount);
159 Object destination(std::move(source));
160
161 ASSERT_EQ(source.Get(), nullptr);
162 ASSERT_EQ(destination.Get(), &refcount);
163 ASSERT_EQ(2, refcount);
164
165 destination = Object();
166 ASSERT_EQ(refcount, 1);
167 }
168
169 // Test the move assignment of C++ objects
TEST(ObjectBase,MoveAssignment)170 TEST(ObjectBase, MoveAssignment) {
171 int refcount = 1;
172 Object source(&refcount);
173
174 Object destination;
175 destination = std::move(source);
176
177 ASSERT_EQ(source.Get(), nullptr);
178 ASSERT_EQ(destination.Get(), &refcount);
179 ASSERT_EQ(2, refcount);
180
181 destination = Object();
182 ASSERT_EQ(refcount, 1);
183 }
184
185 // Test the move assignment of C++ objects onto themselves
TEST(ObjectBase,MoveAssignmentSelf)186 TEST(ObjectBase, MoveAssignmentSelf) {
187 int refcount = 1;
188
189 Object obj(&refcount);
190
191 // Fool the compiler to avoid a -Wself-move
192 Object* objPtr = &obj;
193 obj = std::move(*objPtr);
194
195 ASSERT_EQ(obj.Get(), &refcount);
196 ASSERT_EQ(refcount, 2);
197 }
198
199 // Test the constructor using nullptr
TEST(ObjectBase,NullptrConstructor)200 TEST(ObjectBase, NullptrConstructor) {
201 Object obj(nullptr);
202 ASSERT_EQ(obj.Get(), nullptr);
203 }
204
205 // Test assigning nullptr to the object
TEST(ObjectBase,AssignNullptr)206 TEST(ObjectBase, AssignNullptr) {
207 int refcount = 1;
208
209 Object obj(&refcount);
210 ASSERT_EQ(refcount, 2);
211
212 obj = nullptr;
213 ASSERT_EQ(refcount, 1);
214 }
215