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/dawncpp.h"
18
19 class Object : public dawn::ObjectBase<Object, int*> {
20 public:
21 using ObjectBase::ObjectBase;
22 using ObjectBase::operator=;
23
DawnReference(int * handle)24 static void DawnReference(int* handle) {
25 ASSERT_LE(0, *handle);
26 *handle += 1;
27 }
DawnRelease(int * handle)28 static void DawnRelease(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 copy assignment of C++ objects onto themselves
TEST(ObjectBase,CopyAssignmentSelf)124 TEST(ObjectBase, CopyAssignmentSelf) {
125 int refcount = 1;
126
127 Object obj(&refcount);
128
129 // Fool the compiler to avoid a -Wself-assign-overload
130 Object* objPtr = &obj;
131 obj = *objPtr;
132
133 ASSERT_EQ(obj.Get(), &refcount);
134 ASSERT_EQ(refcount, 2);
135 }
136
137 // Test the move constructor of C++ objects
TEST(ObjectBase,MoveConstructor)138 TEST(ObjectBase, MoveConstructor) {
139 int refcount = 1;
140 Object source(&refcount);
141 Object destination(std::move(source));
142
143 ASSERT_EQ(source.Get(), nullptr);
144 ASSERT_EQ(destination.Get(), &refcount);
145 ASSERT_EQ(2, refcount);
146
147 destination = Object();
148 ASSERT_EQ(refcount, 1);
149 }
150
151 // Test the move assignment of C++ objects
TEST(ObjectBase,MoveAssignment)152 TEST(ObjectBase, MoveAssignment) {
153 int refcount = 1;
154 Object source(&refcount);
155
156 Object destination;
157 destination = std::move(source);
158
159 ASSERT_EQ(source.Get(), nullptr);
160 ASSERT_EQ(destination.Get(), &refcount);
161 ASSERT_EQ(2, refcount);
162
163 destination = Object();
164 ASSERT_EQ(refcount, 1);
165 }
166
167 // Test the move assignment of C++ objects onto themselves
TEST(ObjectBase,MoveAssignmentSelf)168 TEST(ObjectBase, MoveAssignmentSelf) {
169 int refcount = 1;
170
171 Object obj(&refcount);
172
173 // Fool the compiler to avoid a -Wself-move
174 Object* objPtr = &obj;
175 obj = std::move(*objPtr);
176
177 ASSERT_EQ(obj.Get(), &refcount);
178 ASSERT_EQ(refcount, 2);
179 }
180
181 // Test the constructor using nullptr
TEST(ObjectBase,NullptrConstructor)182 TEST(ObjectBase, NullptrConstructor) {
183 Object obj(nullptr);
184 ASSERT_EQ(obj.Get(), nullptr);
185 }
186
187 // Test assigning nullptr to the object
TEST(ObjectBase,AssignNullptr)188 TEST(ObjectBase, AssignNullptr) {
189 int refcount = 1;
190
191 Object obj(&refcount);
192 ASSERT_EQ(refcount, 2);
193
194 obj = nullptr;
195 ASSERT_EQ(refcount, 1);
196 }
197
198