• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2019 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 "tests/unittests/wire/WireTest.h"
16 
17 #include "dawn_wire/WireClient.h"
18 
19 using namespace testing;
20 using namespace dawn_wire;
21 
22 namespace {
23 
24     // Mock class to add expectations on the wire calling callbacks
25     class MockBufferMapCallback {
26       public:
27         MOCK_METHOD(void,
28                     Call,
29                     (WGPUBufferMapAsyncStatus status,
30                      void* userdata));
31     };
32 
33     std::unique_ptr<StrictMock<MockBufferMapCallback>> mockBufferMapCallback;
ToMockBufferMapCallback(WGPUBufferMapAsyncStatus status,void * userdata)34     void ToMockBufferMapCallback(WGPUBufferMapAsyncStatus status, void* userdata) {
35         mockBufferMapCallback->Call(status, userdata);
36     }
37 
38 }  // anonymous namespace
39 
40 class WireBufferMappingTests : public WireTest {
41   public:
WireBufferMappingTests()42     WireBufferMappingTests() {
43     }
44     ~WireBufferMappingTests() override = default;
45 
SetUp()46     void SetUp() override {
47         WireTest::SetUp();
48 
49         mockBufferMapCallback = std::make_unique<StrictMock<MockBufferMapCallback>>();
50         apiBuffer = api.GetNewBuffer();
51     }
52 
TearDown()53     void TearDown() override {
54         WireTest::TearDown();
55 
56         // Delete mock so that expectations are checked
57         mockBufferMapCallback = nullptr;
58     }
59 
FlushClient()60     void FlushClient() {
61         WireTest::FlushClient();
62         Mock::VerifyAndClearExpectations(&mockBufferMapCallback);
63     }
64 
FlushServer()65     void FlushServer() {
66         WireTest::FlushServer();
67         Mock::VerifyAndClearExpectations(&mockBufferMapCallback);
68     }
69 
SetupBuffer(WGPUBufferUsageFlags usage)70     void SetupBuffer(WGPUBufferUsageFlags usage) {
71         WGPUBufferDescriptor descriptor = {};
72         descriptor.size = kBufferSize;
73         descriptor.usage = usage;
74 
75         buffer = wgpuDeviceCreateBuffer(device, &descriptor);
76 
77         EXPECT_CALL(api, DeviceCreateBuffer(apiDevice, _))
78             .WillOnce(Return(apiBuffer))
79             .RetiresOnSaturation();
80         FlushClient();
81     }
82 
83   protected:
84     static constexpr uint64_t kBufferSize = sizeof(uint32_t);
85     // A successfully created buffer
86     WGPUBuffer buffer;
87     WGPUBuffer apiBuffer;
88 };
89 
90 // Tests specific to mapping for reading
91 class WireBufferMappingReadTests : public WireBufferMappingTests {
92   public:
WireBufferMappingReadTests()93     WireBufferMappingReadTests() {
94     }
95     ~WireBufferMappingReadTests() override = default;
96 
SetUp()97     void SetUp() override {
98         WireBufferMappingTests::SetUp();
99 
100         SetupBuffer(WGPUBufferUsage_MapRead);
101     }
102 };
103 
104 // Check mapping for reading a succesfully created buffer
TEST_F(WireBufferMappingReadTests,MappingForReadSuccessBuffer)105 TEST_F(WireBufferMappingReadTests, MappingForReadSuccessBuffer) {
106     wgpuBufferMapAsync(buffer, WGPUMapMode_Read, 0, kBufferSize, ToMockBufferMapCallback, nullptr);
107 
108     uint32_t bufferContent = 31337;
109     EXPECT_CALL(api, OnBufferMapAsync(apiBuffer, WGPUMapMode_Read, 0, kBufferSize, _, _))
110         .WillOnce(InvokeWithoutArgs([&]() {
111             api.CallBufferMapAsyncCallback(apiBuffer, WGPUBufferMapAsyncStatus_Success);
112         }));
113     EXPECT_CALL(api, BufferGetConstMappedRange(apiBuffer, 0, kBufferSize))
114         .WillOnce(Return(&bufferContent));
115 
116     FlushClient();
117 
118     EXPECT_CALL(*mockBufferMapCallback, Call(WGPUBufferMapAsyncStatus_Success, _)).Times(1);
119 
120     FlushServer();
121 
122     EXPECT_EQ(bufferContent,
123               *static_cast<const uint32_t*>(wgpuBufferGetConstMappedRange(buffer, 0, kBufferSize)));
124 
125     wgpuBufferUnmap(buffer);
126     EXPECT_CALL(api, BufferUnmap(apiBuffer)).Times(1);
127 
128     FlushClient();
129 }
130 
131 // Check that things work correctly when a validation error happens when mapping the buffer for
132 // reading
TEST_F(WireBufferMappingReadTests,ErrorWhileMappingForRead)133 TEST_F(WireBufferMappingReadTests, ErrorWhileMappingForRead) {
134     wgpuBufferMapAsync(buffer, WGPUMapMode_Read, 0, kBufferSize, ToMockBufferMapCallback, nullptr);
135 
136     EXPECT_CALL(api, OnBufferMapAsync(apiBuffer, WGPUMapMode_Read, 0, kBufferSize, _, _))
137         .WillOnce(InvokeWithoutArgs(
138             [&]() { api.CallBufferMapAsyncCallback(apiBuffer, WGPUBufferMapAsyncStatus_Error); }));
139 
140     FlushClient();
141 
142     EXPECT_CALL(*mockBufferMapCallback, Call(WGPUBufferMapAsyncStatus_Error, _)).Times(1);
143 
144     FlushServer();
145 
146     EXPECT_EQ(nullptr, wgpuBufferGetConstMappedRange(buffer, 0, kBufferSize));
147 }
148 
149 // Check that the map read callback is called with UNKNOWN when the buffer is destroyed before the
150 // request is finished
TEST_F(WireBufferMappingReadTests,DestroyBeforeReadRequestEnd)151 TEST_F(WireBufferMappingReadTests, DestroyBeforeReadRequestEnd) {
152     wgpuBufferMapAsync(buffer, WGPUMapMode_Read, 0, kBufferSize, ToMockBufferMapCallback, nullptr);
153 
154     // Return success
155     uint32_t bufferContent = 0;
156     EXPECT_CALL(api, OnBufferMapAsync(apiBuffer, WGPUMapMode_Read, 0, kBufferSize, _, _))
157         .WillOnce(InvokeWithoutArgs([&]() {
158             api.CallBufferMapAsyncCallback(apiBuffer, WGPUBufferMapAsyncStatus_Success);
159         }));
160     EXPECT_CALL(api, BufferGetConstMappedRange(apiBuffer, 0, kBufferSize))
161         .WillOnce(Return(&bufferContent));
162 
163     // Destroy before the client gets the success, so the callback is called with
164     // DestroyedBeforeCallback.
165     EXPECT_CALL(*mockBufferMapCallback, Call(WGPUBufferMapAsyncStatus_DestroyedBeforeCallback, _))
166         .Times(1);
167     wgpuBufferRelease(buffer);
168     EXPECT_CALL(api, BufferRelease(apiBuffer));
169 
170     FlushClient();
171     FlushServer();
172 }
173 
174 // Check the map read callback is called with "UnmappedBeforeCallback" when the map request would
175 // have worked, but Unmap was called
TEST_F(WireBufferMappingReadTests,UnmapCalledTooEarlyForRead)176 TEST_F(WireBufferMappingReadTests, UnmapCalledTooEarlyForRead) {
177     wgpuBufferMapAsync(buffer, WGPUMapMode_Read, 0, kBufferSize, ToMockBufferMapCallback, nullptr);
178 
179     uint32_t bufferContent = 31337;
180     EXPECT_CALL(api, OnBufferMapAsync(apiBuffer, WGPUMapMode_Read, 0, kBufferSize, _, _))
181         .WillOnce(InvokeWithoutArgs([&]() {
182             api.CallBufferMapAsyncCallback(apiBuffer, WGPUBufferMapAsyncStatus_Success);
183         }));
184     EXPECT_CALL(api, BufferGetConstMappedRange(apiBuffer, 0, kBufferSize))
185         .WillOnce(Return(&bufferContent));
186 
187     // Oh no! We are calling Unmap too early! However the callback gets fired only after we get
188     // an answer from the server.
189     wgpuBufferUnmap(buffer);
190     EXPECT_CALL(api, BufferUnmap(apiBuffer));
191 
192     FlushClient();
193 
194     // The callback shouldn't get called with success, even when the request succeeded on the
195     // server side
196     EXPECT_CALL(*mockBufferMapCallback, Call(WGPUBufferMapAsyncStatus_UnmappedBeforeCallback, _))
197         .Times(1);
198 
199     FlushServer();
200 }
201 
202 // Check that even if Unmap() was called early client-side, we correctly surface server-side
203 // validation errors.
TEST_F(WireBufferMappingReadTests,UnmapCalledTooEarlyForReadButServerSideError)204 TEST_F(WireBufferMappingReadTests, UnmapCalledTooEarlyForReadButServerSideError) {
205     wgpuBufferMapAsync(buffer, WGPUMapMode_Read, 0, kBufferSize, ToMockBufferMapCallback, nullptr);
206 
207     EXPECT_CALL(api, OnBufferMapAsync(apiBuffer, WGPUMapMode_Read, 0, kBufferSize, _, _))
208         .WillOnce(InvokeWithoutArgs(
209             [&]() { api.CallBufferMapAsyncCallback(apiBuffer, WGPUBufferMapAsyncStatus_Error); }));
210 
211     // Oh no! We are calling Unmap too early! However the callback gets fired only after we get
212     // an answer from the server that the mapAsync call was an error.
213     wgpuBufferUnmap(buffer);
214     EXPECT_CALL(api, BufferUnmap(apiBuffer));
215 
216     FlushClient();
217 
218     // The callback should be called with the server-side error and not the UnmappedBeforeCallback.
219     EXPECT_CALL(*mockBufferMapCallback, Call(WGPUBufferMapAsyncStatus_Error, _))
220         .Times(1);
221 
222     FlushServer();
223 }
224 
225 // Check the map read callback is called with "DestroyedBeforeCallback" when the map request would
226 // have worked, but Destroy was called
TEST_F(WireBufferMappingReadTests,DestroyCalledTooEarlyForRead)227 TEST_F(WireBufferMappingReadTests, DestroyCalledTooEarlyForRead) {
228     wgpuBufferMapAsync(buffer, WGPUMapMode_Read, 0, kBufferSize, ToMockBufferMapCallback, nullptr);
229 
230     uint32_t bufferContent = 31337;
231     EXPECT_CALL(api, OnBufferMapAsync(apiBuffer, WGPUMapMode_Read, 0, kBufferSize, _, _))
232         .WillOnce(InvokeWithoutArgs([&]() {
233             api.CallBufferMapAsyncCallback(apiBuffer, WGPUBufferMapAsyncStatus_Success);
234         }));
235     EXPECT_CALL(api, BufferGetConstMappedRange(apiBuffer, 0, kBufferSize))
236         .WillOnce(Return(&bufferContent));
237 
238     // Oh no! We are calling Unmap too early! However the callback gets fired only after we get
239     // an answer from the server.
240     wgpuBufferDestroy(buffer);
241     EXPECT_CALL(api, BufferDestroy(apiBuffer));
242 
243     FlushClient();
244 
245     // The callback shouldn't get called with success, even when the request succeeded on the
246     // server side
247     EXPECT_CALL(*mockBufferMapCallback, Call(WGPUBufferMapAsyncStatus_DestroyedBeforeCallback, _))
248         .Times(1);
249 
250     FlushServer();
251 }
252 
253 // Check that even if Destroy() was called early client-side, we correctly surface server-side
254 // validation errors.
TEST_F(WireBufferMappingReadTests,DestroyCalledTooEarlyForReadButServerSideError)255 TEST_F(WireBufferMappingReadTests, DestroyCalledTooEarlyForReadButServerSideError) {
256     wgpuBufferMapAsync(buffer, WGPUMapMode_Read, 0, kBufferSize, ToMockBufferMapCallback, nullptr);
257 
258     EXPECT_CALL(api, OnBufferMapAsync(apiBuffer, WGPUMapMode_Read, 0, kBufferSize, _, _))
259         .WillOnce(InvokeWithoutArgs(
260             [&]() { api.CallBufferMapAsyncCallback(apiBuffer, WGPUBufferMapAsyncStatus_Error); }));
261 
262     // Oh no! We are calling Destroy too early! However the callback gets fired only after we get
263     // an answer from the server that the mapAsync call was an error.
264     wgpuBufferDestroy(buffer);
265     EXPECT_CALL(api, BufferDestroy(apiBuffer));
266 
267     FlushClient();
268 
269     // The callback should be called with the server-side error and not the DestroyedBeforCallback..
270     EXPECT_CALL(*mockBufferMapCallback, Call(WGPUBufferMapAsyncStatus_Error, _))
271         .Times(1);
272 
273     FlushServer();
274 }
275 
276 // Check that an error map read while a buffer is already mapped won't changed the result of get
277 // mapped range
TEST_F(WireBufferMappingReadTests,MappingForReadingErrorWhileAlreadyMappedUnchangeMapData)278 TEST_F(WireBufferMappingReadTests, MappingForReadingErrorWhileAlreadyMappedUnchangeMapData) {
279     // Successful map
280     wgpuBufferMapAsync(buffer, WGPUMapMode_Read, 0, kBufferSize, ToMockBufferMapCallback, nullptr);
281 
282     uint32_t bufferContent = 31337;
283     EXPECT_CALL(api, OnBufferMapAsync(apiBuffer, WGPUMapMode_Read, 0, kBufferSize, _, _))
284         .WillOnce(InvokeWithoutArgs([&]() {
285             api.CallBufferMapAsyncCallback(apiBuffer, WGPUBufferMapAsyncStatus_Success);
286         }));
287     EXPECT_CALL(api, BufferGetConstMappedRange(apiBuffer, 0, kBufferSize))
288         .WillOnce(Return(&bufferContent));
289 
290     FlushClient();
291 
292     EXPECT_CALL(*mockBufferMapCallback, Call(WGPUBufferMapAsyncStatus_Success, _)).Times(1);
293 
294     FlushServer();
295 
296     // Map failure while the buffer is already mapped
297     wgpuBufferMapAsync(buffer, WGPUMapMode_Read, 0, kBufferSize, ToMockBufferMapCallback, nullptr);
298     EXPECT_CALL(api, OnBufferMapAsync(apiBuffer, WGPUMapMode_Read, 0, kBufferSize, _, _))
299         .WillOnce(InvokeWithoutArgs(
300             [&]() { api.CallBufferMapAsyncCallback(apiBuffer, WGPUBufferMapAsyncStatus_Error); }));
301 
302     FlushClient();
303 
304     EXPECT_CALL(*mockBufferMapCallback, Call(WGPUBufferMapAsyncStatus_Error, _)).Times(1);
305 
306     FlushServer();
307 
308     EXPECT_EQ(bufferContent,
309               *static_cast<const uint32_t*>(wgpuBufferGetConstMappedRange(buffer, 0, kBufferSize)));
310 }
311 
312 // Test that the MapReadCallback isn't fired twice when unmap() is called inside the callback
TEST_F(WireBufferMappingReadTests,UnmapInsideMapReadCallback)313 TEST_F(WireBufferMappingReadTests, UnmapInsideMapReadCallback) {
314     wgpuBufferMapAsync(buffer, WGPUMapMode_Read, 0, kBufferSize, ToMockBufferMapCallback, nullptr);
315 
316     uint32_t bufferContent = 31337;
317     EXPECT_CALL(api, OnBufferMapAsync(apiBuffer, WGPUMapMode_Read, 0, kBufferSize, _, _))
318         .WillOnce(InvokeWithoutArgs([&]() {
319             api.CallBufferMapAsyncCallback(apiBuffer, WGPUBufferMapAsyncStatus_Success);
320         }));
321     EXPECT_CALL(api, BufferGetConstMappedRange(apiBuffer, 0, kBufferSize))
322         .WillOnce(Return(&bufferContent));
323 
324     FlushClient();
325 
326     EXPECT_CALL(*mockBufferMapCallback, Call(WGPUBufferMapAsyncStatus_Success, _))
327         .WillOnce(InvokeWithoutArgs([&]() { wgpuBufferUnmap(buffer); }));
328 
329     FlushServer();
330 
331     EXPECT_CALL(api, BufferUnmap(apiBuffer)).Times(1);
332 
333     FlushClient();
334 }
335 
336 // Test that the MapReadCallback isn't fired twice the buffer external refcount reaches 0 in the
337 // callback
TEST_F(WireBufferMappingReadTests,DestroyInsideMapReadCallback)338 TEST_F(WireBufferMappingReadTests, DestroyInsideMapReadCallback) {
339     wgpuBufferMapAsync(buffer, WGPUMapMode_Read, 0, kBufferSize, ToMockBufferMapCallback, nullptr);
340 
341     uint32_t bufferContent = 31337;
342     EXPECT_CALL(api, OnBufferMapAsync(apiBuffer, WGPUMapMode_Read, 0, kBufferSize, _, _))
343         .WillOnce(InvokeWithoutArgs([&]() {
344             api.CallBufferMapAsyncCallback(apiBuffer, WGPUBufferMapAsyncStatus_Success);
345         }));
346     EXPECT_CALL(api, BufferGetConstMappedRange(apiBuffer, 0, kBufferSize))
347         .WillOnce(Return(&bufferContent));
348 
349     FlushClient();
350 
351     EXPECT_CALL(*mockBufferMapCallback, Call(WGPUBufferMapAsyncStatus_Success, _))
352         .WillOnce(InvokeWithoutArgs([&]() { wgpuBufferRelease(buffer); }));
353 
354     FlushServer();
355 
356     EXPECT_CALL(api, BufferRelease(apiBuffer));
357 
358     FlushClient();
359 }
360 
361 // Tests specific to mapping for writing
362 class WireBufferMappingWriteTests : public WireBufferMappingTests {
363   public:
WireBufferMappingWriteTests()364     WireBufferMappingWriteTests() {
365     }
366     ~WireBufferMappingWriteTests() override = default;
367 
SetUp()368     void SetUp() override {
369         WireBufferMappingTests::SetUp();
370 
371         SetupBuffer(WGPUBufferUsage_MapWrite);
372     }
373 };
374 
375 // Check mapping for writing a succesfully created buffer
TEST_F(WireBufferMappingWriteTests,MappingForWriteSuccessBuffer)376 TEST_F(WireBufferMappingWriteTests, MappingForWriteSuccessBuffer) {
377     wgpuBufferMapAsync(buffer, WGPUMapMode_Write, 0, kBufferSize, ToMockBufferMapCallback, nullptr);
378 
379     uint32_t serverBufferContent = 31337;
380     uint32_t updatedContent = 4242;
381 
382     EXPECT_CALL(api, OnBufferMapAsync(apiBuffer, WGPUMapMode_Write, 0, kBufferSize, _, _))
383         .WillOnce(InvokeWithoutArgs([&]() {
384             api.CallBufferMapAsyncCallback(apiBuffer, WGPUBufferMapAsyncStatus_Success);
385         }));
386     EXPECT_CALL(api, BufferGetMappedRange(apiBuffer, 0, kBufferSize))
387         .WillOnce(Return(&serverBufferContent));
388 
389     FlushClient();
390 
391     // The map write callback always gets a buffer full of zeroes.
392     EXPECT_CALL(*mockBufferMapCallback, Call(WGPUBufferMapAsyncStatus_Success, _)).Times(1);
393 
394     FlushServer();
395 
396     uint32_t* lastMapWritePointer =
397         static_cast<uint32_t*>(wgpuBufferGetMappedRange(buffer, 0, kBufferSize));
398     ASSERT_EQ(0u, *lastMapWritePointer);
399 
400     // Write something to the mapped pointer
401     *lastMapWritePointer = updatedContent;
402 
403     wgpuBufferUnmap(buffer);
404     EXPECT_CALL(api, BufferUnmap(apiBuffer)).Times(1);
405 
406     FlushClient();
407 
408     // After the buffer is unmapped, the content of the buffer is updated on the server
409     ASSERT_EQ(serverBufferContent, updatedContent);
410 }
411 
412 // Check that things work correctly when a validation error happens when mapping the buffer for
413 // writing
TEST_F(WireBufferMappingWriteTests,ErrorWhileMappingForWrite)414 TEST_F(WireBufferMappingWriteTests, ErrorWhileMappingForWrite) {
415     wgpuBufferMapAsync(buffer, WGPUMapMode_Write, 0, kBufferSize, ToMockBufferMapCallback, nullptr);
416 
417     EXPECT_CALL(api, OnBufferMapAsync(apiBuffer, WGPUMapMode_Write, 0, kBufferSize, _, _))
418         .WillOnce(InvokeWithoutArgs(
419             [&]() { api.CallBufferMapAsyncCallback(apiBuffer, WGPUBufferMapAsyncStatus_Error); }));
420 
421     FlushClient();
422 
423     EXPECT_CALL(*mockBufferMapCallback, Call(WGPUBufferMapAsyncStatus_Error, _)).Times(1);
424 
425     FlushServer();
426 
427     EXPECT_EQ(nullptr, wgpuBufferGetMappedRange(buffer, 0, kBufferSize));
428 }
429 
430 // Check that the map write callback is called with "DestroyedBeforeCallback" when the buffer is
431 // destroyed before the request is finished
TEST_F(WireBufferMappingWriteTests,DestroyBeforeWriteRequestEnd)432 TEST_F(WireBufferMappingWriteTests, DestroyBeforeWriteRequestEnd) {
433     wgpuBufferMapAsync(buffer, WGPUMapMode_Write, 0, kBufferSize, ToMockBufferMapCallback, nullptr);
434 
435     // Return success
436     uint32_t bufferContent = 31337;
437     EXPECT_CALL(api, OnBufferMapAsync(apiBuffer, WGPUMapMode_Write, 0, kBufferSize, _, _))
438         .WillOnce(InvokeWithoutArgs([&]() {
439             api.CallBufferMapAsyncCallback(apiBuffer, WGPUBufferMapAsyncStatus_Success);
440         }));
441     EXPECT_CALL(api, BufferGetMappedRange(apiBuffer, 0, kBufferSize))
442         .WillOnce(Return(&bufferContent));
443 
444     // Destroy before the client gets the success, so the callback is called with
445     // DestroyedBeforeCallback.
446     EXPECT_CALL(*mockBufferMapCallback, Call(WGPUBufferMapAsyncStatus_DestroyedBeforeCallback, _))
447         .Times(1);
448     wgpuBufferRelease(buffer);
449     EXPECT_CALL(api, BufferRelease(apiBuffer));
450 
451     FlushClient();
452     FlushServer();
453 }
454 
455 // Check the map write callback is called with "UnmappedBeforeCallback" when the map request would
456 // have worked, but Unmap was called
TEST_F(WireBufferMappingWriteTests,UnmapCalledTooEarlyForWrite)457 TEST_F(WireBufferMappingWriteTests, UnmapCalledTooEarlyForWrite) {
458     wgpuBufferMapAsync(buffer, WGPUMapMode_Write, 0, kBufferSize, ToMockBufferMapCallback, nullptr);
459 
460     uint32_t bufferContent = 31337;
461     EXPECT_CALL(api, OnBufferMapAsync(apiBuffer, WGPUMapMode_Write, 0, kBufferSize, _, _))
462         .WillOnce(InvokeWithoutArgs([&]() {
463             api.CallBufferMapAsyncCallback(apiBuffer, WGPUBufferMapAsyncStatus_Success);
464         }));
465     EXPECT_CALL(api, BufferGetMappedRange(apiBuffer, 0, kBufferSize))
466         .WillOnce(Return(&bufferContent));
467 
468     FlushClient();
469 
470     // Oh no! We are calling Unmap too early!
471     EXPECT_CALL(*mockBufferMapCallback, Call(WGPUBufferMapAsyncStatus_UnmappedBeforeCallback, _))
472         .Times(1);
473     wgpuBufferUnmap(buffer);
474 
475     // The callback shouldn't get called, even when the request succeeded on the server side
476     FlushServer();
477 }
478 
479 // Check that an error map write while a buffer is already mapped
TEST_F(WireBufferMappingWriteTests,MappingForWritingErrorWhileAlreadyMapped)480 TEST_F(WireBufferMappingWriteTests, MappingForWritingErrorWhileAlreadyMapped) {
481     // Successful map
482     wgpuBufferMapAsync(buffer, WGPUMapMode_Write, 0, kBufferSize, ToMockBufferMapCallback, nullptr);
483 
484     uint32_t bufferContent = 31337;
485     EXPECT_CALL(api, OnBufferMapAsync(apiBuffer, WGPUMapMode_Write, 0, kBufferSize, _, _))
486         .WillOnce(InvokeWithoutArgs([&]() {
487             api.CallBufferMapAsyncCallback(apiBuffer, WGPUBufferMapAsyncStatus_Success);
488         }));
489     EXPECT_CALL(api, BufferGetMappedRange(apiBuffer, 0, kBufferSize))
490         .WillOnce(Return(&bufferContent));
491 
492     FlushClient();
493 
494     EXPECT_CALL(*mockBufferMapCallback, Call(WGPUBufferMapAsyncStatus_Success, _)).Times(1);
495 
496     FlushServer();
497 
498     // Map failure while the buffer is already mapped
499     wgpuBufferMapAsync(buffer, WGPUMapMode_Write, 0, kBufferSize, ToMockBufferMapCallback, nullptr);
500     EXPECT_CALL(api, OnBufferMapAsync(apiBuffer, WGPUMapMode_Write, 0, kBufferSize, _, _))
501         .WillOnce(InvokeWithoutArgs(
502             [&]() { api.CallBufferMapAsyncCallback(apiBuffer, WGPUBufferMapAsyncStatus_Error); }));
503 
504     FlushClient();
505 
506     EXPECT_CALL(*mockBufferMapCallback, Call(WGPUBufferMapAsyncStatus_Error, _)).Times(1);
507 
508     FlushServer();
509 
510     EXPECT_NE(nullptr,
511               static_cast<const uint32_t*>(wgpuBufferGetConstMappedRange(buffer, 0, kBufferSize)));
512 }
513 
514 // Test that the MapWriteCallback isn't fired twice when unmap() is called inside the callback
TEST_F(WireBufferMappingWriteTests,UnmapInsideMapWriteCallback)515 TEST_F(WireBufferMappingWriteTests, UnmapInsideMapWriteCallback) {
516     wgpuBufferMapAsync(buffer, WGPUMapMode_Write, 0, kBufferSize, ToMockBufferMapCallback, nullptr);
517 
518     uint32_t bufferContent = 31337;
519     EXPECT_CALL(api, OnBufferMapAsync(apiBuffer, WGPUMapMode_Write, 0, kBufferSize, _, _))
520         .WillOnce(InvokeWithoutArgs([&]() {
521             api.CallBufferMapAsyncCallback(apiBuffer, WGPUBufferMapAsyncStatus_Success);
522         }));
523     EXPECT_CALL(api, BufferGetMappedRange(apiBuffer, 0, kBufferSize))
524         .WillOnce(Return(&bufferContent));
525 
526     FlushClient();
527 
528     EXPECT_CALL(*mockBufferMapCallback, Call(WGPUBufferMapAsyncStatus_Success, _))
529         .WillOnce(InvokeWithoutArgs([&]() { wgpuBufferUnmap(buffer); }));
530 
531     FlushServer();
532 
533     EXPECT_CALL(api, BufferUnmap(apiBuffer)).Times(1);
534 
535     FlushClient();
536 }
537 
538 // Test that the MapWriteCallback isn't fired twice the buffer external refcount reaches 0 in the
539 // callback
TEST_F(WireBufferMappingWriteTests,DestroyInsideMapWriteCallback)540 TEST_F(WireBufferMappingWriteTests, DestroyInsideMapWriteCallback) {
541     wgpuBufferMapAsync(buffer, WGPUMapMode_Write, 0, kBufferSize, ToMockBufferMapCallback, nullptr);
542 
543     uint32_t bufferContent = 31337;
544     EXPECT_CALL(api, OnBufferMapAsync(apiBuffer, WGPUMapMode_Write, 0, kBufferSize, _, _))
545         .WillOnce(InvokeWithoutArgs([&]() {
546             api.CallBufferMapAsyncCallback(apiBuffer, WGPUBufferMapAsyncStatus_Success);
547         }));
548     EXPECT_CALL(api, BufferGetMappedRange(apiBuffer, 0, kBufferSize))
549         .WillOnce(Return(&bufferContent));
550 
551     FlushClient();
552 
553     EXPECT_CALL(*mockBufferMapCallback, Call(WGPUBufferMapAsyncStatus_Success, _))
554         .WillOnce(InvokeWithoutArgs([&]() { wgpuBufferRelease(buffer); }));
555 
556     FlushServer();
557 
558     EXPECT_CALL(api, BufferRelease(apiBuffer));
559 
560     FlushClient();
561 }
562 
563 // Test successful buffer creation with mappedAtCreation=true
TEST_F(WireBufferMappingTests,MappedAtCreationSuccess)564 TEST_F(WireBufferMappingTests, MappedAtCreationSuccess) {
565     WGPUBufferDescriptor descriptor = {};
566     descriptor.size = 4;
567     descriptor.mappedAtCreation = true;
568 
569     WGPUBuffer apiBuffer = api.GetNewBuffer();
570     uint32_t apiBufferData = 1234;
571 
572     WGPUBuffer buffer = wgpuDeviceCreateBuffer(device, &descriptor);
573 
574     EXPECT_CALL(api, DeviceCreateBuffer(apiDevice, _)).WillOnce(Return(apiBuffer));
575     EXPECT_CALL(api, BufferGetMappedRange(apiBuffer, 0, 4)).WillOnce(Return(&apiBufferData));
576 
577     FlushClient();
578 
579     wgpuBufferUnmap(buffer);
580     EXPECT_CALL(api, BufferUnmap(apiBuffer)).Times(1);
581 
582     FlushClient();
583 }
584 
585 // Test that releasing a buffer mapped at creation does not call Unmap
TEST_F(WireBufferMappingTests,MappedAtCreationReleaseBeforeUnmap)586 TEST_F(WireBufferMappingTests, MappedAtCreationReleaseBeforeUnmap) {
587     WGPUBufferDescriptor descriptor = {};
588     descriptor.size = 4;
589     descriptor.mappedAtCreation = true;
590 
591     WGPUBuffer apiBuffer = api.GetNewBuffer();
592     uint32_t apiBufferData = 1234;
593 
594     WGPUBuffer buffer = wgpuDeviceCreateBuffer(device, &descriptor);
595 
596     EXPECT_CALL(api, DeviceCreateBuffer(apiDevice, _)).WillOnce(Return(apiBuffer));
597     EXPECT_CALL(api, BufferGetMappedRange(apiBuffer, 0, 4)).WillOnce(Return(&apiBufferData));
598 
599     FlushClient();
600 
601     wgpuBufferRelease(buffer);
602     EXPECT_CALL(api, BufferRelease(apiBuffer)).Times(1);
603 
604     FlushClient();
605 }
606 
607 // Test that it is valid to map a buffer after it is mapped at creation and unmapped
TEST_F(WireBufferMappingTests,MappedAtCreationThenMapSuccess)608 TEST_F(WireBufferMappingTests, MappedAtCreationThenMapSuccess) {
609     WGPUBufferDescriptor descriptor = {};
610     descriptor.size = 4;
611     descriptor.usage = WGPUMapMode_Write;
612     descriptor.mappedAtCreation = true;
613 
614     WGPUBuffer apiBuffer = api.GetNewBuffer();
615     uint32_t apiBufferData = 1234;
616 
617     WGPUBuffer buffer = wgpuDeviceCreateBuffer(device, &descriptor);
618 
619     EXPECT_CALL(api, DeviceCreateBuffer(apiDevice, _)).WillOnce(Return(apiBuffer));
620     EXPECT_CALL(api, BufferGetMappedRange(apiBuffer, 0, 4)).WillOnce(Return(&apiBufferData));
621 
622     FlushClient();
623 
624     wgpuBufferUnmap(buffer);
625     EXPECT_CALL(api, BufferUnmap(apiBuffer)).Times(1);
626 
627     FlushClient();
628 
629     wgpuBufferMapAsync(buffer, WGPUMapMode_Write, 0, kBufferSize, ToMockBufferMapCallback, nullptr);
630 
631     EXPECT_CALL(api, OnBufferMapAsync(apiBuffer, WGPUMapMode_Write, 0, kBufferSize, _, _))
632         .WillOnce(InvokeWithoutArgs([&]() {
633             api.CallBufferMapAsyncCallback(apiBuffer, WGPUBufferMapAsyncStatus_Success);
634         }));
635     EXPECT_CALL(api, BufferGetMappedRange(apiBuffer, 0, kBufferSize))
636         .WillOnce(Return(&apiBufferData));
637 
638     FlushClient();
639 
640     EXPECT_CALL(*mockBufferMapCallback, Call(WGPUBufferMapAsyncStatus_Success, _)).Times(1);
641 
642     FlushServer();
643 }
644 
645 // Test that it is invalid to map a buffer after mappedAtCreation but before Unmap
TEST_F(WireBufferMappingTests,MappedAtCreationThenMapFailure)646 TEST_F(WireBufferMappingTests, MappedAtCreationThenMapFailure) {
647     WGPUBufferDescriptor descriptor = {};
648     descriptor.size = 4;
649     descriptor.mappedAtCreation = true;
650 
651     WGPUBuffer apiBuffer = api.GetNewBuffer();
652     uint32_t apiBufferData = 1234;
653 
654     WGPUBuffer buffer = wgpuDeviceCreateBuffer(device, &descriptor);
655 
656     EXPECT_CALL(api, DeviceCreateBuffer(apiDevice, _)).WillOnce(Return(apiBuffer));
657     EXPECT_CALL(api, BufferGetMappedRange(apiBuffer, 0, 4)).WillOnce(Return(&apiBufferData));
658 
659     FlushClient();
660 
661     wgpuBufferMapAsync(buffer, WGPUMapMode_Write, 0, kBufferSize, ToMockBufferMapCallback, nullptr);
662 
663     EXPECT_CALL(api, OnBufferMapAsync(apiBuffer, WGPUMapMode_Write, 0, kBufferSize, _, _))
664         .WillOnce(InvokeWithoutArgs(
665             [&]() { api.CallBufferMapAsyncCallback(apiBuffer, WGPUBufferMapAsyncStatus_Error); }));
666 
667     FlushClient();
668 
669     EXPECT_CALL(*mockBufferMapCallback, Call(WGPUBufferMapAsyncStatus_Error, _)).Times(1);
670 
671     FlushServer();
672 
673     EXPECT_NE(nullptr,
674               static_cast<const uint32_t*>(wgpuBufferGetConstMappedRange(buffer, 0, kBufferSize)));
675 
676     wgpuBufferUnmap(buffer);
677     EXPECT_CALL(api, BufferUnmap(apiBuffer)).Times(1);
678 
679     FlushClient();
680 }
681 
682 // Check that trying to create a buffer of size MAX_SIZE_T is an error handling in the client and
683 // never gets to the server-side.
TEST_F(WireBufferMappingTests,MaxSizeMappableBufferOOMDirectly)684 TEST_F(WireBufferMappingTests, MaxSizeMappableBufferOOMDirectly) {
685     size_t kOOMSize = std::numeric_limits<size_t>::max();
686     WGPUBuffer apiBuffer = api.GetNewBuffer();
687 
688     // Check for CreateBufferMapped.
689     {
690         WGPUBufferDescriptor descriptor = {};
691         descriptor.usage = WGPUBufferUsage_CopySrc;
692         descriptor.size = kOOMSize;
693         descriptor.mappedAtCreation = true;
694 
695         wgpuDeviceCreateBuffer(device, &descriptor);
696         EXPECT_CALL(api, DeviceInjectError(apiDevice, WGPUErrorType_OutOfMemory, _));
697         EXPECT_CALL(api, DeviceCreateErrorBuffer(apiDevice)).WillOnce(Return(apiBuffer));
698         FlushClient();
699     }
700 
701     // Check for MapRead usage.
702     {
703         WGPUBufferDescriptor descriptor = {};
704         descriptor.usage = WGPUBufferUsage_MapRead;
705         descriptor.size = kOOMSize;
706 
707         wgpuDeviceCreateBuffer(device, &descriptor);
708         EXPECT_CALL(api, DeviceInjectError(apiDevice, WGPUErrorType_OutOfMemory, _));
709         EXPECT_CALL(api, DeviceCreateErrorBuffer(apiDevice)).WillOnce(Return(apiBuffer));
710         FlushClient();
711     }
712 
713     // Check for MapWrite usage.
714     {
715         WGPUBufferDescriptor descriptor = {};
716         descriptor.usage = WGPUBufferUsage_MapWrite;
717         descriptor.size = kOOMSize;
718 
719         wgpuDeviceCreateBuffer(device, &descriptor);
720         EXPECT_CALL(api, DeviceInjectError(apiDevice, WGPUErrorType_OutOfMemory, _));
721         EXPECT_CALL(api, DeviceCreateErrorBuffer(apiDevice)).WillOnce(Return(apiBuffer));
722         FlushClient();
723     }
724 }
725 
726 // Test that registering a callback then wire disconnect calls the callback with
727 // DeviceLost.
TEST_F(WireBufferMappingTests,MapThenDisconnect)728 TEST_F(WireBufferMappingTests, MapThenDisconnect) {
729     SetupBuffer(WGPUMapMode_Write);
730     wgpuBufferMapAsync(buffer, WGPUMapMode_Write, 0, kBufferSize, ToMockBufferMapCallback, this);
731 
732     EXPECT_CALL(api, OnBufferMapAsync(apiBuffer, WGPUMapMode_Write, 0, kBufferSize, _, _))
733         .WillOnce(InvokeWithoutArgs([&]() {
734             api.CallBufferMapAsyncCallback(apiBuffer, WGPUBufferMapAsyncStatus_Success);
735         }));
736     EXPECT_CALL(api, BufferGetMappedRange(apiBuffer, 0, kBufferSize)).Times(1);
737 
738     FlushClient();
739 
740     EXPECT_CALL(*mockBufferMapCallback, Call(WGPUBufferMapAsyncStatus_DeviceLost, this)).Times(1);
741     GetWireClient()->Disconnect();
742 }
743 
744 // Test that registering a callback after wire disconnect calls the callback with
745 // DeviceLost.
TEST_F(WireBufferMappingTests,MapAfterDisconnect)746 TEST_F(WireBufferMappingTests, MapAfterDisconnect) {
747     SetupBuffer(WGPUMapMode_Read);
748 
749     GetWireClient()->Disconnect();
750 
751     EXPECT_CALL(*mockBufferMapCallback, Call(WGPUBufferMapAsyncStatus_DeviceLost, this)).Times(1);
752     wgpuBufferMapAsync(buffer, WGPUMapMode_Read, 0, kBufferSize, ToMockBufferMapCallback, this);
753 }
754 
755 // Hack to pass in test context into user callback
756 struct TestData {
757     WireBufferMappingTests* pTest;
758     WGPUBuffer* pTestBuffer;
759     size_t numRequests;
760 };
761 
ToMockBufferMapCallbackWithNewRequests(WGPUBufferMapAsyncStatus status,void * userdata)762 static void ToMockBufferMapCallbackWithNewRequests(WGPUBufferMapAsyncStatus status,
763                                                    void* userdata) {
764     TestData* testData = reinterpret_cast<TestData*>(userdata);
765     // Mimic the user callback is sending new requests
766     ASSERT_NE(testData, nullptr);
767     ASSERT_NE(testData->pTest, nullptr);
768     ASSERT_NE(testData->pTestBuffer, nullptr);
769 
770     mockBufferMapCallback->Call(status, testData->pTest);
771 
772     // Send the requests a number of times
773     for (size_t i = 0; i < testData->numRequests; i++) {
774         wgpuBufferMapAsync(*(testData->pTestBuffer), WGPUMapMode_Write, 0, sizeof(uint32_t),
775                            ToMockBufferMapCallback, testData->pTest);
776     }
777 }
778 
779 // Test that requests inside user callbacks before disconnect are called
TEST_F(WireBufferMappingTests,MapInsideCallbackBeforeDisconnect)780 TEST_F(WireBufferMappingTests, MapInsideCallbackBeforeDisconnect) {
781     SetupBuffer(WGPUMapMode_Write);
782     TestData testData = {this, &buffer, 10};
783     wgpuBufferMapAsync(buffer, WGPUMapMode_Write, 0, kBufferSize,
784                        ToMockBufferMapCallbackWithNewRequests, &testData);
785 
786     EXPECT_CALL(api, OnBufferMapAsync(apiBuffer, WGPUMapMode_Write, 0, kBufferSize, _, _))
787         .WillOnce(InvokeWithoutArgs([&]() {
788             api.CallBufferMapAsyncCallback(apiBuffer, WGPUBufferMapAsyncStatus_Success);
789         }));
790     EXPECT_CALL(api, BufferGetMappedRange(apiBuffer, 0, kBufferSize)).Times(1);
791 
792     FlushClient();
793 
794     EXPECT_CALL(*mockBufferMapCallback, Call(WGPUBufferMapAsyncStatus_DeviceLost, this))
795         .Times(1 + testData.numRequests);
796     GetWireClient()->Disconnect();
797 }
798 
799 // Test that requests inside user callbacks before object destruction are called
TEST_F(WireBufferMappingWriteTests,MapInsideCallbackBeforeDestruction)800 TEST_F(WireBufferMappingWriteTests, MapInsideCallbackBeforeDestruction) {
801     TestData testData = {this, &buffer, 10};
802     wgpuBufferMapAsync(buffer, WGPUMapMode_Write, 0, kBufferSize,
803                        ToMockBufferMapCallbackWithNewRequests, &testData);
804 
805     EXPECT_CALL(api, OnBufferMapAsync(apiBuffer, WGPUMapMode_Write, 0, kBufferSize, _, _))
806         .WillOnce(InvokeWithoutArgs([&]() {
807             api.CallBufferMapAsyncCallback(apiBuffer, WGPUBufferMapAsyncStatus_Success);
808         }));
809     EXPECT_CALL(api, BufferGetMappedRange(apiBuffer, 0, kBufferSize)).Times(1);
810 
811     FlushClient();
812 
813     EXPECT_CALL(*mockBufferMapCallback,
814                 Call(WGPUBufferMapAsyncStatus_DestroyedBeforeCallback, this))
815         .Times(1 + testData.numRequests);
816     wgpuBufferRelease(buffer);
817 }