Corentin Wallez | 4a9ef4e | 2018-07-18 11:40:26 +0200 | [diff] [blame] | 1 | // Copyright 2017 The Dawn Authors |
Corentin Wallez | 2d64114 | 2017-05-30 11:10:47 -0400 | [diff] [blame] | 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 | |
Corentin Wallez | 45b51f5 | 2019-10-28 22:15:47 +0000 | [diff] [blame] | 17 | #include "dawn/webgpu_cpp.h" |
Corentin Wallez | 2d64114 | 2017-05-30 11:10:47 -0400 | [diff] [blame] | 18 | |
Corentin Wallez | 2c8b5c6 | 2019-10-21 20:04:10 +0000 | [diff] [blame] | 19 | class Object : public wgpu::ObjectBase<Object, int*> { |
| 20 | public: |
| 21 | using ObjectBase::ObjectBase; |
| 22 | using ObjectBase::operator=; |
Corentin Wallez | 2d64114 | 2017-05-30 11:10:47 -0400 | [diff] [blame] | 23 | |
Corentin Wallez | 2c8b5c6 | 2019-10-21 20:04:10 +0000 | [diff] [blame] | 24 | static void WGPUReference(int* handle) { |
| 25 | ASSERT_LE(0, *handle); |
| 26 | *handle += 1; |
| 27 | } |
| 28 | static void WGPURelease(int* handle) { |
| 29 | ASSERT_LT(0, *handle); |
| 30 | *handle -= 1; |
| 31 | } |
Corentin Wallez | 2d64114 | 2017-05-30 11:10:47 -0400 | [diff] [blame] | 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. |
| 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. |
| 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 | |
Corentin Wallez | aa7109c | 2018-10-25 10:42:49 +0000 | [diff] [blame] | 55 | // Test .Get(). |
| 56 | TEST(ObjectBase, Get) { |
Corentin Wallez | 2d64114 | 2017-05-30 11:10:47 -0400 | [diff] [blame] | 57 | int refcount = 1; |
| 58 | { |
| 59 | Object obj1(&refcount); |
Corentin Wallez | 2d64114 | 2017-05-30 11:10:47 -0400 | [diff] [blame] | 60 | |
Corentin Wallez | aa7109c | 2018-10-25 10:42:49 +0000 | [diff] [blame] | 61 | ASSERT_EQ(2, refcount); |
Corentin Wallez | 2d64114 | 2017-05-30 11:10:47 -0400 | [diff] [blame] | 62 | ASSERT_EQ(&refcount, obj1.Get()); |
Corentin Wallez | 2d64114 | 2017-05-30 11:10:47 -0400 | [diff] [blame] | 63 | } |
| 64 | ASSERT_EQ(1, refcount); |
| 65 | } |
| 66 | |
| 67 | // Test that Release consumes the C++ object into a C object and doesn't 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 |
| 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 | |
Corentin Wallez | aa7109c | 2018-10-25 10:42:49 +0000 | [diff] [blame] | 92 | // Test the copy constructor of C++ objects |
| 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 |
| 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 | |
Ben Clayton | db7def5 | 2021-06-28 10:26:08 +0000 | [diff] [blame] | 123 | // Test the repeated copy assignment of C++ objects |
| 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 | |
Corentin Wallez | aa7109c | 2018-10-25 10:42:49 +0000 | [diff] [blame] | 141 | // Test the copy assignment of C++ objects onto themselves |
| 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 | |
Corentin Wallez | 2d64114 | 2017-05-30 11:10:47 -0400 | [diff] [blame] | 155 | // Test the move constructor of C++ objects |
| 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 |
| 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 | |
Corentin Wallez | aa7109c | 2018-10-25 10:42:49 +0000 | [diff] [blame] | 185 | // Test the move assignment of C++ objects onto themselves |
| 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 | } |
Corentin Wallez | f48e6b7 | 2018-12-04 12:13:03 +0000 | [diff] [blame] | 198 | |
| 199 | // Test the constructor using nullptr |
| 200 | TEST(ObjectBase, NullptrConstructor) { |
| 201 | Object obj(nullptr); |
| 202 | ASSERT_EQ(obj.Get(), nullptr); |
| 203 | } |
| 204 | |
| 205 | // Test assigning nullptr to the object |
| 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 | } |