Callback reentrancy tests

Some tests to make sure new requests inside user callback
is okay.

Bug: dawn:1091
Change-Id: I4c53d7fb6637f77e5af6fd0a78d879a2431d4ac8
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/63041
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Commit-Queue: Shrek Shao <shrekshao@google.com>
This commit is contained in:
shrekshao 2021-08-31 15:18:54 +00:00 committed by Dawn LUCI CQ
parent 67fc6aeb82
commit 3fdfa82f7b
3 changed files with 181 additions and 1 deletions

View File

@ -751,3 +751,67 @@ TEST_F(WireBufferMappingTests, MapAfterDisconnect) {
EXPECT_CALL(*mockBufferMapCallback, Call(WGPUBufferMapAsyncStatus_DeviceLost, this)).Times(1); EXPECT_CALL(*mockBufferMapCallback, Call(WGPUBufferMapAsyncStatus_DeviceLost, this)).Times(1);
wgpuBufferMapAsync(buffer, WGPUMapMode_Read, 0, kBufferSize, ToMockBufferMapCallback, this); wgpuBufferMapAsync(buffer, WGPUMapMode_Read, 0, kBufferSize, ToMockBufferMapCallback, this);
} }
// Hack to pass in test context into user callback
struct TestData {
WireBufferMappingTests* pTest;
WGPUBuffer* pTestBuffer;
size_t numRequests;
};
static void ToMockBufferMapCallbackWithNewRequests(WGPUBufferMapAsyncStatus status,
void* userdata) {
TestData* testData = reinterpret_cast<TestData*>(userdata);
// Mimic the user callback is sending new requests
ASSERT_NE(testData, nullptr);
ASSERT_NE(testData->pTest, nullptr);
ASSERT_NE(testData->pTestBuffer, nullptr);
mockBufferMapCallback->Call(status, testData->pTest);
// Send the requests a number of times
for (size_t i = 0; i < testData->numRequests; i++) {
wgpuBufferMapAsync(*(testData->pTestBuffer), WGPUMapMode_Write, 0, sizeof(uint32_t),
ToMockBufferMapCallback, testData->pTest);
}
}
// Test that requests inside user callbacks before disconnect are called
TEST_F(WireBufferMappingTests, MapInsideCallbackBeforeDisconnect) {
SetupBuffer(WGPUMapMode_Write);
TestData testData = {this, &buffer, 10};
wgpuBufferMapAsync(buffer, WGPUMapMode_Write, 0, kBufferSize,
ToMockBufferMapCallbackWithNewRequests, &testData);
EXPECT_CALL(api, OnBufferMapAsync(apiBuffer, WGPUMapMode_Write, 0, kBufferSize, _, _))
.WillOnce(InvokeWithoutArgs([&]() {
api.CallBufferMapAsyncCallback(apiBuffer, WGPUBufferMapAsyncStatus_Success);
}));
EXPECT_CALL(api, BufferGetMappedRange(apiBuffer, 0, kBufferSize)).Times(1);
FlushClient();
EXPECT_CALL(*mockBufferMapCallback, Call(WGPUBufferMapAsyncStatus_DeviceLost, this))
.Times(1 + testData.numRequests);
GetWireClient()->Disconnect();
}
// Test that requests inside user callbacks before object destruction are called
TEST_F(WireBufferMappingWriteTests, MapInsideCallbackBeforeDestruction) {
TestData testData = {this, &buffer, 10};
wgpuBufferMapAsync(buffer, WGPUMapMode_Write, 0, kBufferSize,
ToMockBufferMapCallbackWithNewRequests, &testData);
EXPECT_CALL(api, OnBufferMapAsync(apiBuffer, WGPUMapMode_Write, 0, kBufferSize, _, _))
.WillOnce(InvokeWithoutArgs([&]() {
api.CallBufferMapAsyncCallback(apiBuffer, WGPUBufferMapAsyncStatus_Success);
}));
EXPECT_CALL(api, BufferGetMappedRange(apiBuffer, 0, kBufferSize)).Times(1);
FlushClient();
EXPECT_CALL(*mockBufferMapCallback,
Call(WGPUBufferMapAsyncStatus_DestroyedBeforeCallback, this))
.Times(1 + testData.numRequests);
wgpuBufferRelease(buffer);
}

View File

@ -37,8 +37,8 @@ class WireQueueTests : public WireTest {
} }
void TearDown() override { void TearDown() override {
mockQueueWorkDoneCallback = nullptr;
WireTest::TearDown(); WireTest::TearDown();
mockQueueWorkDoneCallback = nullptr;
} }
void FlushServer() { void FlushServer() {
@ -97,3 +97,44 @@ TEST_F(WireQueueTests, OnSubmittedWorkDoneAfterDisconnect) {
.Times(1); .Times(1);
wgpuQueueOnSubmittedWorkDone(queue, 0u, ToMockQueueWorkDone, this); wgpuQueueOnSubmittedWorkDone(queue, 0u, ToMockQueueWorkDone, this);
} }
// Hack to pass in test context into user callback
struct TestData {
WireQueueTests* pTest;
WGPUQueue* pTestQueue;
size_t numRequests;
};
static void ToMockQueueWorkDoneWithNewRequests(WGPUQueueWorkDoneStatus status, void* userdata) {
TestData* testData = reinterpret_cast<TestData*>(userdata);
// Mimic the user callback is sending new requests
ASSERT_NE(testData, nullptr);
ASSERT_NE(testData->pTest, nullptr);
ASSERT_NE(testData->pTestQueue, nullptr);
mockQueueWorkDoneCallback->Call(status, testData->pTest);
// Send the requests a number of times
for (size_t i = 0; i < testData->numRequests; i++) {
wgpuQueueOnSubmittedWorkDone(*(testData->pTestQueue), 0u, ToMockQueueWorkDone,
testData->pTest);
}
}
// Test that requests inside user callbacks before disconnect are called
TEST_F(WireQueueTests, OnSubmittedWorkDoneInsideCallbackBeforeDisconnect) {
TestData testData = {this, &queue, 10};
wgpuQueueOnSubmittedWorkDone(queue, 0u, ToMockQueueWorkDoneWithNewRequests, &testData);
EXPECT_CALL(api, OnQueueOnSubmittedWorkDone(apiQueue, 0u, _, _))
.WillOnce(InvokeWithoutArgs([&]() {
api.CallQueueOnSubmittedWorkDoneCallback(apiQueue, WGPUQueueWorkDoneStatus_Error);
}));
FlushClient();
EXPECT_CALL(*mockQueueWorkDoneCallback, Call(WGPUQueueWorkDoneStatus_DeviceLost, this))
.Times(1 + testData.numRequests);
GetWireClient()->Disconnect();
}
// Only one default queue is supported now so we cannot test ~Queue triggering ClearAllCallbacks
// since it is always destructed after the test TearDown, and we cannot create a new queue obj
// with wgpuDeviceGetQueue

View File

@ -149,3 +149,78 @@ TEST_F(WireShaderModuleTests, GetCompilationInfoAfterDisconnect) {
Call(WGPUCompilationInfoRequestStatus_DeviceLost, nullptr, _)); Call(WGPUCompilationInfoRequestStatus_DeviceLost, nullptr, _));
wgpuShaderModuleGetCompilationInfo(shaderModule, ToMockGetCompilationInfoCallback, nullptr); wgpuShaderModuleGetCompilationInfo(shaderModule, ToMockGetCompilationInfoCallback, nullptr);
} }
// Hack to pass in test context into user callback
struct TestData {
WireShaderModuleTests* pTest;
WGPUShaderModule* pTestShaderModule;
size_t numRequests;
};
static void ToMockBufferMapCallbackWithNewRequests(WGPUCompilationInfoRequestStatus status,
const WGPUCompilationInfo* info,
void* userdata) {
TestData* testData = reinterpret_cast<TestData*>(userdata);
// Mimic the user callback is sending new requests
ASSERT_NE(testData, nullptr);
ASSERT_NE(testData->pTest, nullptr);
ASSERT_NE(testData->pTestShaderModule, nullptr);
mockCompilationInfoCallback->Call(status, info, testData->pTest);
// Send the requests a number of times
for (size_t i = 0; i < testData->numRequests; i++) {
wgpuShaderModuleGetCompilationInfo(*(testData->pTestShaderModule),
ToMockGetCompilationInfoCallback, nullptr);
}
}
// Test that requests inside user callbacks before disconnect are called
TEST_F(WireShaderModuleTests, GetCompilationInfoInsideCallbackBeforeDisconnect) {
TestData testData = {this, &shaderModule, 10};
wgpuShaderModuleGetCompilationInfo(shaderModule, ToMockBufferMapCallbackWithNewRequests,
&testData);
WGPUCompilationMessage message = {"Test Message", WGPUCompilationMessageType_Info, 2, 4, 6, 8};
WGPUCompilationInfo compilationInfo;
compilationInfo.messageCount = 1;
compilationInfo.messages = &message;
EXPECT_CALL(api, OnShaderModuleGetCompilationInfo(apiShaderModule, _, _))
.WillOnce(InvokeWithoutArgs([&]() {
api.CallShaderModuleGetCompilationInfoCallback(
apiShaderModule, WGPUCompilationInfoRequestStatus_Success, &compilationInfo);
}));
FlushClient();
EXPECT_CALL(*mockCompilationInfoCallback,
Call(WGPUCompilationInfoRequestStatus_DeviceLost, nullptr, _))
.Times(1 + testData.numRequests);
GetWireClient()->Disconnect();
}
// Test that requests inside user callbacks before object destruction are called
TEST_F(WireShaderModuleTests, GetCompilationInfoInsideCallbackBeforeDestruction) {
TestData testData = {this, &shaderModule, 10};
wgpuShaderModuleGetCompilationInfo(shaderModule, ToMockBufferMapCallbackWithNewRequests,
&testData);
WGPUCompilationMessage message = {"Test Message", WGPUCompilationMessageType_Info, 2, 4, 6, 8};
WGPUCompilationInfo compilationInfo;
compilationInfo.messageCount = 1;
compilationInfo.messages = &message;
EXPECT_CALL(api, OnShaderModuleGetCompilationInfo(apiShaderModule, _, _))
.WillOnce(InvokeWithoutArgs([&]() {
api.CallShaderModuleGetCompilationInfoCallback(
apiShaderModule, WGPUCompilationInfoRequestStatus_Success, &compilationInfo);
}));
FlushClient();
EXPECT_CALL(*mockCompilationInfoCallback,
Call(WGPUCompilationInfoRequestStatus_Unknown, nullptr, _))
.Times(1 + testData.numRequests);
wgpuShaderModuleRelease(shaderModule);
}