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": "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": {
|
||||
"category": "natively defined"
|
||||
},
|
||||
"error filter": {
|
||||
"category": "enum",
|
||||
"values": [
|
||||
{"value": 0, "name": "none"},
|
||||
{"value": 1, "name": "validation"},
|
||||
{"value": 2, "name": "out of memory"}
|
||||
]
|
||||
},
|
||||
"error type": {
|
||||
"category": "enum",
|
||||
"values": [
|
||||
|
|
|
@ -48,6 +48,10 @@
|
|||
{ "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}
|
||||
],
|
||||
"device pop error scope": [
|
||||
{ "name": "device", "type": "device" },
|
||||
{ "name": "request serial", "type": "uint64_t" }
|
||||
],
|
||||
"destroy object": [
|
||||
{ "name": "object type", "type": "ObjectType" },
|
||||
{ "name": "object id", "type": "ObjectId" }
|
||||
|
@ -70,6 +74,11 @@
|
|||
{ "name": "type", "type": "error type"},
|
||||
{ "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": [
|
||||
{ "name": "fence", "type": "ObjectHandle", "handle_type": "fence" },
|
||||
{ "name": "value", "type": "uint64_t" }
|
||||
|
@ -89,6 +98,8 @@
|
|||
"DeviceCreateBuffer",
|
||||
"DeviceCreateBufferMapped",
|
||||
"DeviceCreateBufferMappedAsync",
|
||||
"DevicePushErrorScope",
|
||||
"DevicePopErrorScope",
|
||||
"QueueCreateFence",
|
||||
"FenceGetCompletedValue",
|
||||
"QueueSignal"
|
||||
|
|
|
@ -60,6 +60,10 @@ void ProcTableAsClass::DeviceSetUncapturedErrorCallback(DawnDevice self,
|
|||
OnDeviceSetUncapturedErrorCallback(self, callback, userdata);
|
||||
}
|
||||
|
||||
bool ProcTableAsClass::DevicePopErrorScope(DawnDevice self, DawnErrorCallback callback, void* userdata) {
|
||||
return OnDevicePopErrorScopeCallback(self, callback, userdata);
|
||||
}
|
||||
|
||||
void ProcTableAsClass::DeviceCreateBufferMappedAsync(DawnDevice self,
|
||||
const DawnBufferDescriptor* descriptor,
|
||||
DawnBufferCreateMappedCallback callback,
|
||||
|
|
|
@ -54,6 +54,7 @@ class ProcTableAsClass {
|
|||
void DeviceSetUncapturedErrorCallback(DawnDevice self,
|
||||
DawnErrorCallback callback,
|
||||
void* userdata);
|
||||
bool DevicePopErrorScope(DawnDevice self, DawnErrorCallback callback, void* userdata);
|
||||
void DeviceCreateBufferMappedAsync(DawnDevice self,
|
||||
const DawnBufferDescriptor* descriptor,
|
||||
DawnBufferCreateMappedCallback callback,
|
||||
|
@ -73,6 +74,9 @@ class ProcTableAsClass {
|
|||
virtual void OnDeviceSetUncapturedErrorCallback(DawnDevice device,
|
||||
DawnErrorCallback callback,
|
||||
void* userdata) = 0;
|
||||
virtual bool OnDevicePopErrorScopeCallback(DawnDevice device,
|
||||
DawnErrorCallback callback,
|
||||
void* userdata) = 0;
|
||||
virtual void OnDeviceCreateBufferMappedAsyncCallback(DawnDevice self,
|
||||
const DawnBufferDescriptor* descriptor,
|
||||
DawnBufferCreateMappedCallback callback,
|
||||
|
@ -134,6 +138,7 @@ class MockProcTable : public ProcTableAsClass {
|
|||
{% endfor %}
|
||||
|
||||
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_METHOD3(OnBufferMapReadAsyncCallback, void(DawnBuffer buffer, DawnBufferMapReadCallback callback, void* userdata));
|
||||
MOCK_METHOD3(OnBufferMapWriteAsyncCallback, void(DawnBuffer buffer, DawnBufferMapWriteCallback callback, void* userdata));
|
||||
|
|
|
@ -99,6 +99,17 @@ namespace dawn_native {
|
|||
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 {
|
||||
if (DAWN_UNLIKELY(object->GetDevice() != this)) {
|
||||
return DAWN_VALIDATION_ERROR("Object from a different device.");
|
||||
|
|
|
@ -149,6 +149,9 @@ namespace dawn_native {
|
|||
void Tick();
|
||||
|
||||
void SetUncapturedErrorCallback(dawn::ErrorCallback callback, void* userdata);
|
||||
void PushErrorScope(dawn::ErrorFilter filter);
|
||||
bool PopErrorScope(dawn::ErrorCallback callback, void* userdata);
|
||||
|
||||
void Reference();
|
||||
void Release();
|
||||
|
||||
|
|
|
@ -264,6 +264,16 @@ namespace dawn_wire { namespace client {
|
|||
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) {
|
||||
auto fence = reinterpret_cast<Fence*>(cSelf);
|
||||
return fence->completedValue;
|
||||
|
|
|
@ -33,6 +33,12 @@ namespace dawn_wire { namespace client {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool Client::DoDevicePopErrorScopeCallback(uint64_t requestSerial,
|
||||
DawnErrorType errorType,
|
||||
const char* message) {
|
||||
return mDevice->PopErrorScope(requestSerial, errorType, message);
|
||||
}
|
||||
|
||||
bool Client::DoBufferMapReadAsyncCallback(Buffer* buffer,
|
||||
uint32_t requestSerial,
|
||||
uint32_t status,
|
||||
|
|
|
@ -14,6 +14,10 @@
|
|||
|
||||
#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 {
|
||||
|
||||
Device::Device(Client* client, uint32_t refcount, uint32_t id)
|
||||
|
@ -21,6 +25,13 @@ namespace dawn_wire { namespace client {
|
|||
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() {
|
||||
return mClient;
|
||||
}
|
||||
|
@ -36,4 +47,64 @@ namespace dawn_wire { namespace client {
|
|||
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
|
||||
|
|
|
@ -19,6 +19,8 @@
|
|||
|
||||
#include "dawn_wire/client/ObjectBase.h"
|
||||
|
||||
#include <map>
|
||||
|
||||
namespace dawn_wire { namespace client {
|
||||
|
||||
class Client;
|
||||
|
@ -26,12 +28,25 @@ namespace dawn_wire { namespace client {
|
|||
class Device : public ObjectBase {
|
||||
public:
|
||||
Device(Client* client, uint32_t refcount, uint32_t id);
|
||||
~Device();
|
||||
|
||||
Client* GetClient();
|
||||
void HandleError(DawnErrorType errorType, const char* message);
|
||||
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:
|
||||
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;
|
||||
DawnErrorCallback mErrorCallback = nullptr;
|
||||
void* mErrorUserdata;
|
||||
|
|
|
@ -32,6 +32,13 @@ namespace dawn_wire { namespace server {
|
|||
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 {
|
||||
Server* server;
|
||||
ObjectHandle fence;
|
||||
|
@ -55,6 +62,7 @@ namespace dawn_wire { namespace server {
|
|||
|
||||
// Forwarding callbacks
|
||||
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,
|
||||
const void* ptr,
|
||||
uint64_t dataLength,
|
||||
|
@ -67,6 +75,9 @@ namespace dawn_wire { namespace server {
|
|||
|
||||
// Error callbacks
|
||||
void OnUncapturedError(DawnErrorType type, const char* message);
|
||||
void OnDevicePopErrorScope(DawnErrorType type,
|
||||
const char* message,
|
||||
ErrorScopeUserdata* userdata);
|
||||
void OnBufferMapReadAsyncCallback(DawnBufferMapAsyncStatus status,
|
||||
const void* ptr,
|
||||
uint64_t dataLength,
|
||||
|
|
|
@ -31,4 +31,33 @@ namespace dawn_wire { namespace server {
|
|||
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
|
||||
|
|
|
@ -30,6 +30,16 @@ namespace {
|
|||
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
|
||||
|
||||
class WireErrorCallbackTests : public WireTest {
|
||||
|
@ -42,18 +52,21 @@ class WireErrorCallbackTests : public WireTest {
|
|||
WireTest::SetUp();
|
||||
|
||||
mockDeviceErrorCallback = std::make_unique<StrictMock<MockDeviceErrorCallback>>();
|
||||
mockDevicePopErrorScopeCallback = std::make_unique<StrictMock<MockDevicePopErrorScopeCallback>>();
|
||||
}
|
||||
|
||||
void TearDown() override {
|
||||
WireTest::TearDown();
|
||||
|
||||
mockDeviceErrorCallback = nullptr;
|
||||
mockDevicePopErrorScopeCallback = nullptr;
|
||||
}
|
||||
|
||||
void FlushServer() {
|
||||
WireTest::FlushServer();
|
||||
|
||||
Mock::VerifyAndClearExpectations(&mockDeviceErrorCallback);
|
||||
Mock::VerifyAndClearExpectations(&mockDevicePopErrorScopeCallback);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -72,3 +85,142 @@ TEST_F(WireErrorCallbackTests, DeviceErrorCallback) {
|
|||
|
||||
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