#include <memory>
#include <utility>
#include "dawn/common/FutureUtils.h"
#include "dawn/tests/unittests/wire/WireFutureTest.h"
#include "dawn/tests/unittests/wire/WireTest.h"
#include "dawn/wire/WireClient.h"
namespace dawn::wire {
namespace {
using testing::_;
using testing::DoAll;
using testing::InvokeWithoutArgs;
using testing::Mock;
using testing::Return;
using testing::SaveArg;
using testing::StrEq;
using testing::StrictMock;
class MockDeviceErrorCallback { … };
std::unique_ptr<StrictMock<MockDeviceErrorCallback>> mockDeviceErrorCallback;
void ToMockDeviceErrorCallback(WGPUErrorType type, const char* message, void* userdata) { … }
class MockDeviceLoggingCallback { … };
std::unique_ptr<StrictMock<MockDeviceLoggingCallback>> mockDeviceLoggingCallback;
void ToMockDeviceLoggingCallback(WGPULoggingType type, const char* message, void* userdata) { … }
class MockDeviceLostCallback { … };
std::unique_ptr<StrictMock<MockDeviceLostCallback>> mockDeviceLostCallback;
void ToMockDeviceLostCallback(WGPUDeviceLostReason reason, const char* message, void* userdata) { … }
class WireErrorCallbackTests : public WireTest { … };
TEST_F(WireErrorCallbackTests, DeviceValidationErrorCallback) { … }
TEST_F(WireErrorCallbackTests, DeviceOutOfMemoryErrorCallback) { … }
TEST_F(WireErrorCallbackTests, DeviceInternalErrorCallback) { … }
TEST_F(WireErrorCallbackTests, DeviceLoggingCallback) { … }
TEST_F(WireErrorCallbackTests, DeviceLostCallback) { … }
class WirePopErrorScopeCallbackTests : public WireFutureTestWithParamsBase<> { … };
DAWN_INSTANTIATE_WIRE_FUTURE_TEST_P(WirePopErrorScopeCallbackTests);
TEST_P(WirePopErrorScopeCallbackTests, TypeAndFilters) {
static constexpr std::array<std::pair<WGPUErrorType, wgpu::ErrorFilter>, 3>
kErrorTypeAndFilters = {{{WGPUErrorType_Validation, wgpu::ErrorFilter::Validation},
{WGPUErrorType_OutOfMemory, wgpu::ErrorFilter::OutOfMemory},
{WGPUErrorType_Internal, wgpu::ErrorFilter::Internal}}};
for (const auto& [type, filter] : kErrorTypeAndFilters) {
PushErrorScope(filter);
DevicePopErrorScope(device, this);
EXPECT_CALL(api, OnDevicePopErrorScope2(apiDevice, _)).WillOnce([&] {
api.CallDevicePopErrorScope2Callback(apiDevice, WGPUPopErrorScopeStatus_Success, type,
"Some error message");
});
FlushClient();
FlushFutures();
ExpectWireCallbacksWhen(
[&](auto& oldMockCb) {
EXPECT_CALL(oldMockCb, Call(type, StrEq("Some error message"), this)).Times(1);
FlushCallbacks();
},
[&](auto& mockCb) {
EXPECT_CALL(mockCb, Call(WGPUPopErrorScopeStatus_Success, type,
StrEq("Some error message"), this))
.Times(1);
FlushCallbacks();
});
}
}
TEST_P(WirePopErrorScopeCallbackTests, DisconnectBeforeServerReply) {
PushErrorScope(wgpu::ErrorFilter::Validation);
DevicePopErrorScope(device, this);
EXPECT_CALL(api, OnDevicePopErrorScope2(apiDevice, _)).Times(1);
FlushClient();
FlushFutures();
ExpectWireCallbacksWhen(
[&](auto& oldMockCb) {
EXPECT_CALL(oldMockCb, Call(WGPUErrorType_Unknown, nullptr, this)).Times(1);
GetWireClient()->Disconnect();
},
[&](auto& mockCb) {
EXPECT_CALL(mockCb, Call(WGPUPopErrorScopeStatus_InstanceDropped, WGPUErrorType_Unknown,
nullptr, this))
.Times(1);
GetWireClient()->Disconnect();
});
}
TEST_P(WirePopErrorScopeCallbackTests, DisconnectAfterServerReply) {
DAWN_SKIP_TEST_IF(IsSpontaneous());
PushErrorScope(wgpu::ErrorFilter::Validation);
DevicePopErrorScope(device, this);
EXPECT_CALL(api, OnDevicePopErrorScope2(apiDevice, _)).WillOnce(InvokeWithoutArgs([&] {
api.CallDevicePopErrorScope2Callback(apiDevice, WGPUPopErrorScopeStatus_Success,
WGPUErrorType_Validation, "Some error message");
}));
FlushClient();
FlushFutures();
ExpectWireCallbacksWhen(
[&](auto& oldMockCb) {
EXPECT_CALL(oldMockCb, Call(WGPUErrorType_Validation, nullptr, this)).Times(1);
GetWireClient()->Disconnect();
},
[&](auto& mockCb) {
EXPECT_CALL(mockCb, Call(WGPUPopErrorScopeStatus_InstanceDropped,
WGPUErrorType_Validation, nullptr, this))
.Times(1);
GetWireClient()->Disconnect();
});
}
TEST_P(WirePopErrorScopeCallbackTests, EmptyStack) {
DevicePopErrorScope(cDevice, this);
EXPECT_CALL(api, OnDevicePopErrorScope2(apiDevice, _)).WillOnce(InvokeWithoutArgs([&] {
api.CallDevicePopErrorScope2Callback(apiDevice, WGPUPopErrorScopeStatus_Success,
WGPUErrorType_Validation, "No error scopes to pop");
}));
FlushClient();
FlushFutures();
ExpectWireCallbacksWhen(
[&](auto& oldMockCb) {
EXPECT_CALL(oldMockCb,
Call(WGPUErrorType_Validation, StrEq("No error scopes to pop"), this))
.Times(1);
FlushCallbacks();
},
[&](auto& mockCb) {
EXPECT_CALL(mockCb, Call(WGPUPopErrorScopeStatus_Success, WGPUErrorType_Validation,
StrEq("No error scopes to pop"), this))
.Times(1);
FlushCallbacks();
});
}
}
}