Add empty implementations of Push/PopErrorScope
This adds Push/PopErrorScope to the API with empty implementations which just call the error callback. Also adds unittests that the wire callbacks return as expected. Bug: dawn:153 Change-Id: I63826360e39fbac4c9855d3d55a05b5ca26db450 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/10543 Commit-Queue: Austin Eng <enga@chromium.org> Reviewed-by: Kai Ninomiya <kainino@chromium.org>
This commit is contained in:
parent
f5c44772a6
commit
45238d775a
22
dawn.json
22
dawn.json
|
@ -527,6 +527,20 @@
|
||||||
{"name": "callback", "type": "error callback"},
|
{"name": "callback", "type": "error callback"},
|
||||||
{"name": "userdata", "type": "void", "annotation": "*"}
|
{"name": "userdata", "type": "void", "annotation": "*"}
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "push error scope",
|
||||||
|
"args": [
|
||||||
|
{"name": "filter", "type": "error filter"}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "pop error scope",
|
||||||
|
"returns": "bool",
|
||||||
|
"args": [
|
||||||
|
{"name": "callback", "type": "error callback"},
|
||||||
|
{"name": "userdata", "type": "void", "annotation": "*"}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -546,6 +560,14 @@
|
||||||
"error callback": {
|
"error callback": {
|
||||||
"category": "natively defined"
|
"category": "natively defined"
|
||||||
},
|
},
|
||||||
|
"error filter": {
|
||||||
|
"category": "enum",
|
||||||
|
"values": [
|
||||||
|
{"value": 0, "name": "none"},
|
||||||
|
{"value": 1, "name": "validation"},
|
||||||
|
{"value": 2, "name": "out of memory"}
|
||||||
|
]
|
||||||
|
},
|
||||||
"error type": {
|
"error type": {
|
||||||
"category": "enum",
|
"category": "enum",
|
||||||
"values": [
|
"values": [
|
||||||
|
|
|
@ -48,6 +48,10 @@
|
||||||
{ "name": "handle create info length", "type": "uint64_t" },
|
{ "name": "handle create info length", "type": "uint64_t" },
|
||||||
{ "name": "handle create info", "type": "uint8_t", "annotation": "const*", "length": "handle create info length", "skip_serialize": true}
|
{ "name": "handle create info", "type": "uint8_t", "annotation": "const*", "length": "handle create info length", "skip_serialize": true}
|
||||||
],
|
],
|
||||||
|
"device pop error scope": [
|
||||||
|
{ "name": "device", "type": "device" },
|
||||||
|
{ "name": "request serial", "type": "uint64_t" }
|
||||||
|
],
|
||||||
"destroy object": [
|
"destroy object": [
|
||||||
{ "name": "object type", "type": "ObjectType" },
|
{ "name": "object type", "type": "ObjectType" },
|
||||||
{ "name": "object id", "type": "ObjectId" }
|
{ "name": "object id", "type": "ObjectId" }
|
||||||
|
@ -70,6 +74,11 @@
|
||||||
{ "name": "type", "type": "error type"},
|
{ "name": "type", "type": "error type"},
|
||||||
{ "name": "message", "type": "char", "annotation": "const*", "length": "strlen" }
|
{ "name": "message", "type": "char", "annotation": "const*", "length": "strlen" }
|
||||||
],
|
],
|
||||||
|
"device pop error scope callback": [
|
||||||
|
{ "name": "request serial", "type": "uint64_t" },
|
||||||
|
{ "name": "type", "type": "error type" },
|
||||||
|
{ "name": "message", "type": "char", "annotation": "const*", "length": "strlen" }
|
||||||
|
],
|
||||||
"fence update completed value": [
|
"fence update completed value": [
|
||||||
{ "name": "fence", "type": "ObjectHandle", "handle_type": "fence" },
|
{ "name": "fence", "type": "ObjectHandle", "handle_type": "fence" },
|
||||||
{ "name": "value", "type": "uint64_t" }
|
{ "name": "value", "type": "uint64_t" }
|
||||||
|
@ -89,6 +98,8 @@
|
||||||
"DeviceCreateBuffer",
|
"DeviceCreateBuffer",
|
||||||
"DeviceCreateBufferMapped",
|
"DeviceCreateBufferMapped",
|
||||||
"DeviceCreateBufferMappedAsync",
|
"DeviceCreateBufferMappedAsync",
|
||||||
|
"DevicePushErrorScope",
|
||||||
|
"DevicePopErrorScope",
|
||||||
"QueueCreateFence",
|
"QueueCreateFence",
|
||||||
"FenceGetCompletedValue",
|
"FenceGetCompletedValue",
|
||||||
"QueueSignal"
|
"QueueSignal"
|
||||||
|
|
|
@ -60,6 +60,10 @@ void ProcTableAsClass::DeviceSetUncapturedErrorCallback(DawnDevice self,
|
||||||
OnDeviceSetUncapturedErrorCallback(self, callback, userdata);
|
OnDeviceSetUncapturedErrorCallback(self, callback, userdata);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ProcTableAsClass::DevicePopErrorScope(DawnDevice self, DawnErrorCallback callback, void* userdata) {
|
||||||
|
return OnDevicePopErrorScopeCallback(self, callback, userdata);
|
||||||
|
}
|
||||||
|
|
||||||
void ProcTableAsClass::DeviceCreateBufferMappedAsync(DawnDevice self,
|
void ProcTableAsClass::DeviceCreateBufferMappedAsync(DawnDevice self,
|
||||||
const DawnBufferDescriptor* descriptor,
|
const DawnBufferDescriptor* descriptor,
|
||||||
DawnBufferCreateMappedCallback callback,
|
DawnBufferCreateMappedCallback callback,
|
||||||
|
|
|
@ -54,6 +54,7 @@ class ProcTableAsClass {
|
||||||
void DeviceSetUncapturedErrorCallback(DawnDevice self,
|
void DeviceSetUncapturedErrorCallback(DawnDevice self,
|
||||||
DawnErrorCallback callback,
|
DawnErrorCallback callback,
|
||||||
void* userdata);
|
void* userdata);
|
||||||
|
bool DevicePopErrorScope(DawnDevice self, DawnErrorCallback callback, void* userdata);
|
||||||
void DeviceCreateBufferMappedAsync(DawnDevice self,
|
void DeviceCreateBufferMappedAsync(DawnDevice self,
|
||||||
const DawnBufferDescriptor* descriptor,
|
const DawnBufferDescriptor* descriptor,
|
||||||
DawnBufferCreateMappedCallback callback,
|
DawnBufferCreateMappedCallback callback,
|
||||||
|
@ -73,6 +74,9 @@ class ProcTableAsClass {
|
||||||
virtual void OnDeviceSetUncapturedErrorCallback(DawnDevice device,
|
virtual void OnDeviceSetUncapturedErrorCallback(DawnDevice device,
|
||||||
DawnErrorCallback callback,
|
DawnErrorCallback callback,
|
||||||
void* userdata) = 0;
|
void* userdata) = 0;
|
||||||
|
virtual bool OnDevicePopErrorScopeCallback(DawnDevice device,
|
||||||
|
DawnErrorCallback callback,
|
||||||
|
void* userdata) = 0;
|
||||||
virtual void OnDeviceCreateBufferMappedAsyncCallback(DawnDevice self,
|
virtual void OnDeviceCreateBufferMappedAsyncCallback(DawnDevice self,
|
||||||
const DawnBufferDescriptor* descriptor,
|
const DawnBufferDescriptor* descriptor,
|
||||||
DawnBufferCreateMappedCallback callback,
|
DawnBufferCreateMappedCallback callback,
|
||||||
|
@ -134,6 +138,7 @@ class MockProcTable : public ProcTableAsClass {
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
||||||
MOCK_METHOD3(OnDeviceSetUncapturedErrorCallback, void(DawnDevice device, DawnErrorCallback callback, void* userdata));
|
MOCK_METHOD3(OnDeviceSetUncapturedErrorCallback, void(DawnDevice device, DawnErrorCallback callback, void* userdata));
|
||||||
|
MOCK_METHOD3(OnDevicePopErrorScopeCallback, bool(DawnDevice device, DawnErrorCallback callback, void* userdata));
|
||||||
MOCK_METHOD4(OnDeviceCreateBufferMappedAsyncCallback, void(DawnDevice device, const DawnBufferDescriptor* descriptor, DawnBufferCreateMappedCallback callback, void* userdata));
|
MOCK_METHOD4(OnDeviceCreateBufferMappedAsyncCallback, void(DawnDevice device, const DawnBufferDescriptor* descriptor, DawnBufferCreateMappedCallback callback, void* userdata));
|
||||||
MOCK_METHOD3(OnBufferMapReadAsyncCallback, void(DawnBuffer buffer, DawnBufferMapReadCallback callback, void* userdata));
|
MOCK_METHOD3(OnBufferMapReadAsyncCallback, void(DawnBuffer buffer, DawnBufferMapReadCallback callback, void* userdata));
|
||||||
MOCK_METHOD3(OnBufferMapWriteAsyncCallback, void(DawnBuffer buffer, DawnBufferMapWriteCallback callback, void* userdata));
|
MOCK_METHOD3(OnBufferMapWriteAsyncCallback, void(DawnBuffer buffer, DawnBufferMapWriteCallback callback, void* userdata));
|
||||||
|
|
|
@ -99,6 +99,17 @@ namespace dawn_native {
|
||||||
mErrorUserdata = userdata;
|
mErrorUserdata = userdata;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DeviceBase::PushErrorScope(dawn::ErrorFilter filter) {
|
||||||
|
// TODO(crbug.com/dawn/153): Implement error scopes.
|
||||||
|
HandleError(dawn::ErrorType::Validation, "Error scopes not implemented");
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DeviceBase::PopErrorScope(dawn::ErrorCallback callback, void* userdata) {
|
||||||
|
// TODO(crbug.com/dawn/153): Implement error scopes.
|
||||||
|
HandleError(dawn::ErrorType::Validation, "Error scopes not implemented");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
MaybeError DeviceBase::ValidateObject(const ObjectBase* object) const {
|
MaybeError DeviceBase::ValidateObject(const ObjectBase* object) const {
|
||||||
if (DAWN_UNLIKELY(object->GetDevice() != this)) {
|
if (DAWN_UNLIKELY(object->GetDevice() != this)) {
|
||||||
return DAWN_VALIDATION_ERROR("Object from a different device.");
|
return DAWN_VALIDATION_ERROR("Object from a different device.");
|
||||||
|
|
|
@ -149,6 +149,9 @@ namespace dawn_native {
|
||||||
void Tick();
|
void Tick();
|
||||||
|
|
||||||
void SetUncapturedErrorCallback(dawn::ErrorCallback callback, void* userdata);
|
void SetUncapturedErrorCallback(dawn::ErrorCallback callback, void* userdata);
|
||||||
|
void PushErrorScope(dawn::ErrorFilter filter);
|
||||||
|
bool PopErrorScope(dawn::ErrorCallback callback, void* userdata);
|
||||||
|
|
||||||
void Reference();
|
void Reference();
|
||||||
void Release();
|
void Release();
|
||||||
|
|
||||||
|
|
|
@ -264,6 +264,16 @@ namespace dawn_wire { namespace client {
|
||||||
writeHandle->SerializeCreate(allocatedBuffer + commandSize);
|
writeHandle->SerializeCreate(allocatedBuffer + commandSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ClientDevicePushErrorScope(DawnDevice cDevice, DawnErrorFilter filter) {
|
||||||
|
Device* device = reinterpret_cast<Device*>(cDevice);
|
||||||
|
device->PushErrorScope(filter);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ClientDevicePopErrorScope(DawnDevice cDevice, DawnErrorCallback callback, void* userdata) {
|
||||||
|
Device* device = reinterpret_cast<Device*>(cDevice);
|
||||||
|
return device->RequestPopErrorScope(callback, userdata);
|
||||||
|
}
|
||||||
|
|
||||||
uint64_t ClientFenceGetCompletedValue(DawnFence cSelf) {
|
uint64_t ClientFenceGetCompletedValue(DawnFence cSelf) {
|
||||||
auto fence = reinterpret_cast<Fence*>(cSelf);
|
auto fence = reinterpret_cast<Fence*>(cSelf);
|
||||||
return fence->completedValue;
|
return fence->completedValue;
|
||||||
|
|
|
@ -33,6 +33,12 @@ namespace dawn_wire { namespace client {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Client::DoDevicePopErrorScopeCallback(uint64_t requestSerial,
|
||||||
|
DawnErrorType errorType,
|
||||||
|
const char* message) {
|
||||||
|
return mDevice->PopErrorScope(requestSerial, errorType, message);
|
||||||
|
}
|
||||||
|
|
||||||
bool Client::DoBufferMapReadAsyncCallback(Buffer* buffer,
|
bool Client::DoBufferMapReadAsyncCallback(Buffer* buffer,
|
||||||
uint32_t requestSerial,
|
uint32_t requestSerial,
|
||||||
uint32_t status,
|
uint32_t status,
|
||||||
|
|
|
@ -14,6 +14,10 @@
|
||||||
|
|
||||||
#include "dawn_wire/client/Device.h"
|
#include "dawn_wire/client/Device.h"
|
||||||
|
|
||||||
|
#include "common/Assert.h"
|
||||||
|
#include "dawn_wire/WireCmd_autogen.h"
|
||||||
|
#include "dawn_wire/client/Client.h"
|
||||||
|
|
||||||
namespace dawn_wire { namespace client {
|
namespace dawn_wire { namespace client {
|
||||||
|
|
||||||
Device::Device(Client* client, uint32_t refcount, uint32_t id)
|
Device::Device(Client* client, uint32_t refcount, uint32_t id)
|
||||||
|
@ -21,6 +25,13 @@ namespace dawn_wire { namespace client {
|
||||||
this->device = this;
|
this->device = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Device::~Device() {
|
||||||
|
auto errorScopes = std::move(mErrorScopes);
|
||||||
|
for (const auto& it : errorScopes) {
|
||||||
|
it.second.callback(DAWN_ERROR_TYPE_UNKNOWN, "Device destroyed", it.second.userdata);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Client* Device::GetClient() {
|
Client* Device::GetClient() {
|
||||||
return mClient;
|
return mClient;
|
||||||
}
|
}
|
||||||
|
@ -36,4 +47,64 @@ namespace dawn_wire { namespace client {
|
||||||
mErrorUserdata = errorUserdata;
|
mErrorUserdata = errorUserdata;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Device::PushErrorScope(DawnErrorFilter filter) {
|
||||||
|
mErrorScopeStackSize++;
|
||||||
|
|
||||||
|
DevicePushErrorScopeCmd cmd;
|
||||||
|
cmd.self = reinterpret_cast<DawnDevice>(this);
|
||||||
|
cmd.filter = filter;
|
||||||
|
|
||||||
|
Client* wireClient = GetClient();
|
||||||
|
size_t requiredSize = cmd.GetRequiredSize();
|
||||||
|
char* allocatedBuffer = static_cast<char*>(wireClient->GetCmdSpace(requiredSize));
|
||||||
|
cmd.Serialize(allocatedBuffer, *wireClient);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Device::RequestPopErrorScope(DawnErrorCallback callback, void* userdata) {
|
||||||
|
if (mErrorScopeStackSize == 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
mErrorScopeStackSize--;
|
||||||
|
|
||||||
|
uint64_t serial = mErrorScopeRequestSerial++;
|
||||||
|
ASSERT(mErrorScopes.find(serial) == mErrorScopes.end());
|
||||||
|
|
||||||
|
mErrorScopes[serial] = {callback, userdata};
|
||||||
|
|
||||||
|
DevicePopErrorScopeCmd cmd;
|
||||||
|
cmd.device = reinterpret_cast<DawnDevice>(this);
|
||||||
|
cmd.requestSerial = serial;
|
||||||
|
|
||||||
|
Client* wireClient = GetClient();
|
||||||
|
size_t requiredSize = cmd.GetRequiredSize();
|
||||||
|
char* allocatedBuffer = static_cast<char*>(wireClient->GetCmdSpace(requiredSize));
|
||||||
|
cmd.Serialize(allocatedBuffer, *wireClient);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Device::PopErrorScope(uint64_t requestSerial, DawnErrorType type, const char* message) {
|
||||||
|
switch (type) {
|
||||||
|
case DAWN_ERROR_TYPE_NO_ERROR:
|
||||||
|
case DAWN_ERROR_TYPE_VALIDATION:
|
||||||
|
case DAWN_ERROR_TYPE_OUT_OF_MEMORY:
|
||||||
|
case DAWN_ERROR_TYPE_UNKNOWN:
|
||||||
|
case DAWN_ERROR_TYPE_DEVICE_LOST:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto requestIt = mErrorScopes.find(requestSerial);
|
||||||
|
if (requestIt == mErrorScopes.end()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ErrorScopeData request = std::move(requestIt->second);
|
||||||
|
|
||||||
|
mErrorScopes.erase(requestIt);
|
||||||
|
request.callback(type, message, request.userdata);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
}} // namespace dawn_wire::client
|
}} // namespace dawn_wire::client
|
||||||
|
|
|
@ -19,6 +19,8 @@
|
||||||
|
|
||||||
#include "dawn_wire/client/ObjectBase.h"
|
#include "dawn_wire/client/ObjectBase.h"
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
|
||||||
namespace dawn_wire { namespace client {
|
namespace dawn_wire { namespace client {
|
||||||
|
|
||||||
class Client;
|
class Client;
|
||||||
|
@ -26,12 +28,25 @@ namespace dawn_wire { namespace client {
|
||||||
class Device : public ObjectBase {
|
class Device : public ObjectBase {
|
||||||
public:
|
public:
|
||||||
Device(Client* client, uint32_t refcount, uint32_t id);
|
Device(Client* client, uint32_t refcount, uint32_t id);
|
||||||
|
~Device();
|
||||||
|
|
||||||
Client* GetClient();
|
Client* GetClient();
|
||||||
void HandleError(DawnErrorType errorType, const char* message);
|
void HandleError(DawnErrorType errorType, const char* message);
|
||||||
void SetUncapturedErrorCallback(DawnErrorCallback errorCallback, void* errorUserdata);
|
void SetUncapturedErrorCallback(DawnErrorCallback errorCallback, void* errorUserdata);
|
||||||
|
|
||||||
|
void PushErrorScope(DawnErrorFilter filter);
|
||||||
|
bool RequestPopErrorScope(DawnErrorCallback callback, void* userdata);
|
||||||
|
bool PopErrorScope(uint64_t requestSerial, DawnErrorType type, const char* message);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
struct ErrorScopeData {
|
||||||
|
DawnErrorCallback callback = nullptr;
|
||||||
|
void* userdata = nullptr;
|
||||||
|
};
|
||||||
|
std::map<uint64_t, ErrorScopeData> mErrorScopes;
|
||||||
|
uint64_t mErrorScopeRequestSerial = 0;
|
||||||
|
uint64_t mErrorScopeStackSize = 0;
|
||||||
|
|
||||||
Client* mClient = nullptr;
|
Client* mClient = nullptr;
|
||||||
DawnErrorCallback mErrorCallback = nullptr;
|
DawnErrorCallback mErrorCallback = nullptr;
|
||||||
void* mErrorUserdata;
|
void* mErrorUserdata;
|
||||||
|
|
|
@ -32,6 +32,13 @@ namespace dawn_wire { namespace server {
|
||||||
std::unique_ptr<MemoryTransferService::WriteHandle> writeHandle = nullptr;
|
std::unique_ptr<MemoryTransferService::WriteHandle> writeHandle = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct ErrorScopeUserdata {
|
||||||
|
Server* server;
|
||||||
|
// TODO(enga): ObjectHandle device;
|
||||||
|
// when the wire supports multiple devices.
|
||||||
|
uint32_t requestSerial;
|
||||||
|
};
|
||||||
|
|
||||||
struct FenceCompletionUserdata {
|
struct FenceCompletionUserdata {
|
||||||
Server* server;
|
Server* server;
|
||||||
ObjectHandle fence;
|
ObjectHandle fence;
|
||||||
|
@ -55,6 +62,7 @@ namespace dawn_wire { namespace server {
|
||||||
|
|
||||||
// Forwarding callbacks
|
// Forwarding callbacks
|
||||||
static void ForwardUncapturedError(DawnErrorType type, const char* message, void* userdata);
|
static void ForwardUncapturedError(DawnErrorType type, const char* message, void* userdata);
|
||||||
|
static void ForwardPopErrorScope(DawnErrorType type, const char* message, void* userdata);
|
||||||
static void ForwardBufferMapReadAsync(DawnBufferMapAsyncStatus status,
|
static void ForwardBufferMapReadAsync(DawnBufferMapAsyncStatus status,
|
||||||
const void* ptr,
|
const void* ptr,
|
||||||
uint64_t dataLength,
|
uint64_t dataLength,
|
||||||
|
@ -67,6 +75,9 @@ namespace dawn_wire { namespace server {
|
||||||
|
|
||||||
// Error callbacks
|
// Error callbacks
|
||||||
void OnUncapturedError(DawnErrorType type, const char* message);
|
void OnUncapturedError(DawnErrorType type, const char* message);
|
||||||
|
void OnDevicePopErrorScope(DawnErrorType type,
|
||||||
|
const char* message,
|
||||||
|
ErrorScopeUserdata* userdata);
|
||||||
void OnBufferMapReadAsyncCallback(DawnBufferMapAsyncStatus status,
|
void OnBufferMapReadAsyncCallback(DawnBufferMapAsyncStatus status,
|
||||||
const void* ptr,
|
const void* ptr,
|
||||||
uint64_t dataLength,
|
uint64_t dataLength,
|
||||||
|
|
|
@ -31,4 +31,33 @@ namespace dawn_wire { namespace server {
|
||||||
cmd.Serialize(allocatedBuffer);
|
cmd.Serialize(allocatedBuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Server::DoDevicePopErrorScope(DawnDevice cDevice, uint64_t requestSerial) {
|
||||||
|
ErrorScopeUserdata* userdata = new ErrorScopeUserdata;
|
||||||
|
userdata->server = this;
|
||||||
|
userdata->requestSerial = requestSerial;
|
||||||
|
|
||||||
|
return mProcs.devicePopErrorScope(cDevice, ForwardPopErrorScope, userdata);
|
||||||
|
}
|
||||||
|
|
||||||
|
// static
|
||||||
|
void Server::ForwardPopErrorScope(DawnErrorType type, const char* message, void* userdata) {
|
||||||
|
auto* data = reinterpret_cast<ErrorScopeUserdata*>(userdata);
|
||||||
|
data->server->OnDevicePopErrorScope(type, message, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Server::OnDevicePopErrorScope(DawnErrorType type,
|
||||||
|
const char* message,
|
||||||
|
ErrorScopeUserdata* userdata) {
|
||||||
|
std::unique_ptr<ErrorScopeUserdata> data{userdata};
|
||||||
|
|
||||||
|
ReturnDevicePopErrorScopeCallbackCmd cmd;
|
||||||
|
cmd.requestSerial = data->requestSerial;
|
||||||
|
cmd.type = type;
|
||||||
|
cmd.message = message;
|
||||||
|
|
||||||
|
size_t requiredSize = cmd.GetRequiredSize();
|
||||||
|
char* allocatedBuffer = static_cast<char*>(GetCmdSpace(requiredSize));
|
||||||
|
cmd.Serialize(allocatedBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
}} // namespace dawn_wire::server
|
}} // namespace dawn_wire::server
|
||||||
|
|
|
@ -30,6 +30,16 @@ namespace {
|
||||||
mockDeviceErrorCallback->Call(type, message, userdata);
|
mockDeviceErrorCallback->Call(type, message, userdata);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class MockDevicePopErrorScopeCallback {
|
||||||
|
public:
|
||||||
|
MOCK_METHOD3(Call, void(DawnErrorType type, const char* message, void* userdata));
|
||||||
|
};
|
||||||
|
|
||||||
|
std::unique_ptr<StrictMock<MockDevicePopErrorScopeCallback>> mockDevicePopErrorScopeCallback;
|
||||||
|
void ToMockDevicePopErrorScopeCallback(DawnErrorType type, const char* message, void* userdata) {
|
||||||
|
mockDevicePopErrorScopeCallback->Call(type, message, userdata);
|
||||||
|
}
|
||||||
|
|
||||||
} // anonymous namespace
|
} // anonymous namespace
|
||||||
|
|
||||||
class WireErrorCallbackTests : public WireTest {
|
class WireErrorCallbackTests : public WireTest {
|
||||||
|
@ -42,18 +52,21 @@ class WireErrorCallbackTests : public WireTest {
|
||||||
WireTest::SetUp();
|
WireTest::SetUp();
|
||||||
|
|
||||||
mockDeviceErrorCallback = std::make_unique<StrictMock<MockDeviceErrorCallback>>();
|
mockDeviceErrorCallback = std::make_unique<StrictMock<MockDeviceErrorCallback>>();
|
||||||
|
mockDevicePopErrorScopeCallback = std::make_unique<StrictMock<MockDevicePopErrorScopeCallback>>();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TearDown() override {
|
void TearDown() override {
|
||||||
WireTest::TearDown();
|
WireTest::TearDown();
|
||||||
|
|
||||||
mockDeviceErrorCallback = nullptr;
|
mockDeviceErrorCallback = nullptr;
|
||||||
|
mockDevicePopErrorScopeCallback = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FlushServer() {
|
void FlushServer() {
|
||||||
WireTest::FlushServer();
|
WireTest::FlushServer();
|
||||||
|
|
||||||
Mock::VerifyAndClearExpectations(&mockDeviceErrorCallback);
|
Mock::VerifyAndClearExpectations(&mockDeviceErrorCallback);
|
||||||
|
Mock::VerifyAndClearExpectations(&mockDevicePopErrorScopeCallback);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -72,3 +85,142 @@ TEST_F(WireErrorCallbackTests, DeviceErrorCallback) {
|
||||||
|
|
||||||
FlushServer();
|
FlushServer();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Test the return wire for error scopes.
|
||||||
|
TEST_F(WireErrorCallbackTests, PushPopErrorScopeCallback) {
|
||||||
|
dawnDevicePushErrorScope(device, DAWN_ERROR_FILTER_VALIDATION);
|
||||||
|
EXPECT_CALL(api, DevicePushErrorScope(apiDevice, DAWN_ERROR_FILTER_VALIDATION)).Times(1);
|
||||||
|
|
||||||
|
FlushClient();
|
||||||
|
|
||||||
|
dawnDevicePopErrorScope(device, ToMockDevicePopErrorScopeCallback, this);
|
||||||
|
|
||||||
|
DawnErrorCallback callback;
|
||||||
|
void* userdata;
|
||||||
|
EXPECT_CALL(api, OnDevicePopErrorScopeCallback(apiDevice, _, _))
|
||||||
|
.WillOnce(DoAll(SaveArg<1>(&callback), SaveArg<2>(&userdata), Return(true)));
|
||||||
|
|
||||||
|
FlushClient();
|
||||||
|
|
||||||
|
callback(DAWN_ERROR_TYPE_VALIDATION, "Some error message", userdata);
|
||||||
|
EXPECT_CALL(*mockDevicePopErrorScopeCallback, Call(DAWN_ERROR_TYPE_VALIDATION, StrEq("Some error message"), this)).Times(1);
|
||||||
|
|
||||||
|
FlushServer();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test the return wire for error scopes when callbacks return in a various orders.
|
||||||
|
TEST_F(WireErrorCallbackTests, PopErrorScopeCallbackOrdering) {
|
||||||
|
// Two error scopes are popped, and the first one returns first.
|
||||||
|
{
|
||||||
|
dawnDevicePushErrorScope(device, DAWN_ERROR_FILTER_VALIDATION);
|
||||||
|
dawnDevicePushErrorScope(device, DAWN_ERROR_FILTER_VALIDATION);
|
||||||
|
EXPECT_CALL(api, DevicePushErrorScope(apiDevice, DAWN_ERROR_FILTER_VALIDATION)).Times(2);
|
||||||
|
|
||||||
|
FlushClient();
|
||||||
|
|
||||||
|
dawnDevicePopErrorScope(device, ToMockDevicePopErrorScopeCallback, this);
|
||||||
|
dawnDevicePopErrorScope(device, ToMockDevicePopErrorScopeCallback, this + 1);
|
||||||
|
|
||||||
|
DawnErrorCallback callback1;
|
||||||
|
DawnErrorCallback callback2;
|
||||||
|
void* userdata1;
|
||||||
|
void* userdata2;
|
||||||
|
EXPECT_CALL(api, OnDevicePopErrorScopeCallback(apiDevice, _, _))
|
||||||
|
.WillOnce(DoAll(SaveArg<1>(&callback1), SaveArg<2>(&userdata1), Return(true)))
|
||||||
|
.WillOnce(DoAll(SaveArg<1>(&callback2), SaveArg<2>(&userdata2), Return(true)));
|
||||||
|
|
||||||
|
FlushClient();
|
||||||
|
|
||||||
|
callback1(DAWN_ERROR_TYPE_VALIDATION, "First error message", userdata1);
|
||||||
|
EXPECT_CALL(*mockDevicePopErrorScopeCallback,
|
||||||
|
Call(DAWN_ERROR_TYPE_VALIDATION,
|
||||||
|
StrEq("First error message"), this)).Times(1);
|
||||||
|
FlushServer();
|
||||||
|
|
||||||
|
callback2(DAWN_ERROR_TYPE_VALIDATION, "Second error message", userdata2);
|
||||||
|
EXPECT_CALL(*mockDevicePopErrorScopeCallback,
|
||||||
|
Call(DAWN_ERROR_TYPE_VALIDATION,
|
||||||
|
StrEq("Second error message"), this + 1)).Times(1);
|
||||||
|
FlushServer();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Two error scopes are popped, and the second one returns first.
|
||||||
|
{
|
||||||
|
dawnDevicePushErrorScope(device, DAWN_ERROR_FILTER_VALIDATION);
|
||||||
|
dawnDevicePushErrorScope(device, DAWN_ERROR_FILTER_VALIDATION);
|
||||||
|
EXPECT_CALL(api, DevicePushErrorScope(apiDevice, DAWN_ERROR_FILTER_VALIDATION)).Times(2);
|
||||||
|
|
||||||
|
FlushClient();
|
||||||
|
|
||||||
|
dawnDevicePopErrorScope(device, ToMockDevicePopErrorScopeCallback, this);
|
||||||
|
dawnDevicePopErrorScope(device, ToMockDevicePopErrorScopeCallback, this + 1);
|
||||||
|
|
||||||
|
DawnErrorCallback callback1;
|
||||||
|
DawnErrorCallback callback2;
|
||||||
|
void* userdata1;
|
||||||
|
void* userdata2;
|
||||||
|
EXPECT_CALL(api, OnDevicePopErrorScopeCallback(apiDevice, _, _))
|
||||||
|
.WillOnce(DoAll(SaveArg<1>(&callback1), SaveArg<2>(&userdata1), Return(true)))
|
||||||
|
.WillOnce(DoAll(SaveArg<1>(&callback2), SaveArg<2>(&userdata2), Return(true)));
|
||||||
|
|
||||||
|
FlushClient();
|
||||||
|
|
||||||
|
callback2(DAWN_ERROR_TYPE_VALIDATION, "Second error message", userdata2);
|
||||||
|
EXPECT_CALL(*mockDevicePopErrorScopeCallback,
|
||||||
|
Call(DAWN_ERROR_TYPE_VALIDATION,
|
||||||
|
StrEq("Second error message"), this + 1)).Times(1);
|
||||||
|
FlushServer();
|
||||||
|
|
||||||
|
callback1(DAWN_ERROR_TYPE_VALIDATION, "First error message", userdata1);
|
||||||
|
EXPECT_CALL(*mockDevicePopErrorScopeCallback,
|
||||||
|
Call(DAWN_ERROR_TYPE_VALIDATION,
|
||||||
|
StrEq("First error message"), this)).Times(1);
|
||||||
|
FlushServer();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test the return wire for error scopes in flight when the device is destroyed.
|
||||||
|
TEST_F(WireErrorCallbackTests, PopErrorScopeDeviceDestroyed) {
|
||||||
|
dawnDevicePushErrorScope(device, DAWN_ERROR_FILTER_VALIDATION);
|
||||||
|
EXPECT_CALL(api, DevicePushErrorScope(apiDevice, DAWN_ERROR_FILTER_VALIDATION)).Times(1);
|
||||||
|
|
||||||
|
FlushClient();
|
||||||
|
|
||||||
|
EXPECT_TRUE(dawnDevicePopErrorScope(device, ToMockDevicePopErrorScopeCallback, this));
|
||||||
|
|
||||||
|
EXPECT_CALL(api, OnDevicePopErrorScopeCallback(apiDevice, _, _))
|
||||||
|
.WillOnce(Return(true));
|
||||||
|
FlushClient();
|
||||||
|
|
||||||
|
// Incomplete callback called in Device destructor.
|
||||||
|
EXPECT_CALL(*mockDevicePopErrorScopeCallback, Call(DAWN_ERROR_TYPE_UNKNOWN, _, this)).Times(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test that PopErrorScope returns false if there are no error scopes.
|
||||||
|
TEST_F(WireErrorCallbackTests, PopErrorScopeEmptyStack) {
|
||||||
|
// Empty stack
|
||||||
|
{
|
||||||
|
EXPECT_FALSE(dawnDevicePopErrorScope(device, ToMockDevicePopErrorScopeCallback, this));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pop too many times
|
||||||
|
{
|
||||||
|
dawnDevicePushErrorScope(device, DAWN_ERROR_FILTER_VALIDATION);
|
||||||
|
EXPECT_CALL(api, DevicePushErrorScope(apiDevice, DAWN_ERROR_FILTER_VALIDATION)).Times(1);
|
||||||
|
|
||||||
|
EXPECT_TRUE(dawnDevicePopErrorScope(device, ToMockDevicePopErrorScopeCallback, this));
|
||||||
|
EXPECT_FALSE(dawnDevicePopErrorScope(device, ToMockDevicePopErrorScopeCallback, this + 1));
|
||||||
|
|
||||||
|
DawnErrorCallback callback;
|
||||||
|
void* userdata;
|
||||||
|
EXPECT_CALL(api, OnDevicePopErrorScopeCallback(apiDevice, _, _))
|
||||||
|
.WillOnce(DoAll(SaveArg<1>(&callback), SaveArg<2>(&userdata), Return(true)));
|
||||||
|
|
||||||
|
FlushClient();
|
||||||
|
|
||||||
|
callback(DAWN_ERROR_TYPE_VALIDATION, "Some error message", userdata);
|
||||||
|
EXPECT_CALL(*mockDevicePopErrorScopeCallback, Call(DAWN_ERROR_TYPE_VALIDATION, StrEq("Some error message"), this)).Times(1);
|
||||||
|
|
||||||
|
FlushServer();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue