175 lines
7.0 KiB
C++
175 lines
7.0 KiB
C++
// Copyright 2020 The Dawn Authors
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
#include "dawn/tests/unittests/wire/WireTest.h"
|
|
|
|
#include "dawn/common/Assert.h"
|
|
#include "dawn/tests/MockCallback.h"
|
|
#include "dawn/wire/WireClient.h"
|
|
|
|
using namespace testing;
|
|
using namespace dawn::wire;
|
|
|
|
namespace {
|
|
|
|
class WireDisconnectTests : public WireTest {};
|
|
|
|
} // anonymous namespace
|
|
|
|
// Test that commands are not received if the client disconnects.
|
|
TEST_F(WireDisconnectTests, CommandsAfterDisconnect) {
|
|
// Check that commands work at all.
|
|
wgpuDeviceCreateCommandEncoder(device, nullptr);
|
|
|
|
WGPUCommandEncoder apiCmdBufEncoder = api.GetNewCommandEncoder();
|
|
EXPECT_CALL(api, DeviceCreateCommandEncoder(apiDevice, nullptr))
|
|
.WillOnce(Return(apiCmdBufEncoder));
|
|
FlushClient();
|
|
|
|
// Disconnect.
|
|
GetWireClient()->Disconnect();
|
|
|
|
// Command is not received because client disconnected.
|
|
wgpuDeviceCreateCommandEncoder(device, nullptr);
|
|
EXPECT_CALL(api, DeviceCreateCommandEncoder(_, _)).Times(Exactly(0));
|
|
FlushClient();
|
|
}
|
|
|
|
// Test that commands that are serialized before a disconnect but flushed
|
|
// after are received.
|
|
TEST_F(WireDisconnectTests, FlushAfterDisconnect) {
|
|
// Check that commands work at all.
|
|
wgpuDeviceCreateCommandEncoder(device, nullptr);
|
|
|
|
// Disconnect.
|
|
GetWireClient()->Disconnect();
|
|
|
|
// Already-serialized commmands are still received.
|
|
WGPUCommandEncoder apiCmdBufEncoder = api.GetNewCommandEncoder();
|
|
EXPECT_CALL(api, DeviceCreateCommandEncoder(apiDevice, nullptr))
|
|
.WillOnce(Return(apiCmdBufEncoder));
|
|
FlushClient();
|
|
}
|
|
|
|
// Check that disconnecting the wire client calls the device lost callback exacty once.
|
|
TEST_F(WireDisconnectTests, CallsDeviceLostCallback) {
|
|
MockCallback<WGPUDeviceLostCallback> mockDeviceLostCallback;
|
|
wgpuDeviceSetDeviceLostCallback(device, mockDeviceLostCallback.Callback(),
|
|
mockDeviceLostCallback.MakeUserdata(this));
|
|
|
|
// Disconnect the wire client. We should receive device lost only once.
|
|
EXPECT_CALL(mockDeviceLostCallback, Call(WGPUDeviceLostReason_Undefined, _, this))
|
|
.Times(Exactly(1));
|
|
GetWireClient()->Disconnect();
|
|
GetWireClient()->Disconnect();
|
|
}
|
|
|
|
// Check that disconnecting the wire client after a device loss does not trigger the callback again.
|
|
TEST_F(WireDisconnectTests, ServerLostThenDisconnect) {
|
|
MockCallback<WGPUDeviceLostCallback> mockDeviceLostCallback;
|
|
wgpuDeviceSetDeviceLostCallback(device, mockDeviceLostCallback.Callback(),
|
|
mockDeviceLostCallback.MakeUserdata(this));
|
|
|
|
api.CallDeviceSetDeviceLostCallbackCallback(apiDevice, WGPUDeviceLostReason_Undefined,
|
|
"some reason");
|
|
|
|
// Flush the device lost return command.
|
|
EXPECT_CALL(mockDeviceLostCallback,
|
|
Call(WGPUDeviceLostReason_Undefined, StrEq("some reason"), this))
|
|
.Times(Exactly(1));
|
|
FlushServer();
|
|
|
|
// Disconnect the client. We shouldn't see the lost callback again.
|
|
EXPECT_CALL(mockDeviceLostCallback, Call(_, _, _)).Times(Exactly(0));
|
|
GetWireClient()->Disconnect();
|
|
}
|
|
|
|
// Check that disconnecting the wire client inside the device loss callback does not trigger the
|
|
// callback again.
|
|
TEST_F(WireDisconnectTests, ServerLostThenDisconnectInCallback) {
|
|
MockCallback<WGPUDeviceLostCallback> mockDeviceLostCallback;
|
|
wgpuDeviceSetDeviceLostCallback(device, mockDeviceLostCallback.Callback(),
|
|
mockDeviceLostCallback.MakeUserdata(this));
|
|
|
|
api.CallDeviceSetDeviceLostCallbackCallback(apiDevice, WGPUDeviceLostReason_Undefined,
|
|
"lost reason");
|
|
|
|
// Disconnect the client inside the lost callback. We should see the callback
|
|
// only once.
|
|
EXPECT_CALL(mockDeviceLostCallback,
|
|
Call(WGPUDeviceLostReason_Undefined, StrEq("lost reason"), this))
|
|
.WillOnce(InvokeWithoutArgs([&]() {
|
|
EXPECT_CALL(mockDeviceLostCallback, Call(_, _, _)).Times(Exactly(0));
|
|
GetWireClient()->Disconnect();
|
|
}));
|
|
FlushServer();
|
|
}
|
|
|
|
// Check that a device loss after a disconnect does not trigger the callback again.
|
|
TEST_F(WireDisconnectTests, DisconnectThenServerLost) {
|
|
MockCallback<WGPUDeviceLostCallback> mockDeviceLostCallback;
|
|
wgpuDeviceSetDeviceLostCallback(device, mockDeviceLostCallback.Callback(),
|
|
mockDeviceLostCallback.MakeUserdata(this));
|
|
|
|
// Disconnect the client. We should see the callback once.
|
|
EXPECT_CALL(mockDeviceLostCallback, Call(WGPUDeviceLostReason_Undefined, _, this))
|
|
.Times(Exactly(1));
|
|
GetWireClient()->Disconnect();
|
|
|
|
// Lose the device on the server. The client callback shouldn't be
|
|
// called again.
|
|
api.CallDeviceSetDeviceLostCallbackCallback(apiDevice, WGPUDeviceLostReason_Undefined,
|
|
"lost reason");
|
|
EXPECT_CALL(mockDeviceLostCallback, Call(_, _, _)).Times(Exactly(0));
|
|
FlushServer();
|
|
}
|
|
|
|
// Test that client objects are all destroyed if the WireClient is destroyed.
|
|
TEST_F(WireDisconnectTests, DeleteClientDestroysObjects) {
|
|
WGPUSamplerDescriptor desc = {};
|
|
wgpuDeviceCreateCommandEncoder(device, nullptr);
|
|
wgpuDeviceCreateSampler(device, &desc);
|
|
|
|
WGPUCommandEncoder apiCommandEncoder = api.GetNewCommandEncoder();
|
|
EXPECT_CALL(api, DeviceCreateCommandEncoder(apiDevice, nullptr))
|
|
.WillOnce(Return(apiCommandEncoder));
|
|
|
|
WGPUSampler apiSampler = api.GetNewSampler();
|
|
EXPECT_CALL(api, DeviceCreateSampler(apiDevice, _)).WillOnce(Return(apiSampler));
|
|
|
|
FlushClient();
|
|
|
|
DeleteClient();
|
|
|
|
// Expect release on all objects created by the client.
|
|
Sequence s1, s2, s3;
|
|
EXPECT_CALL(api, QueueRelease(apiQueue)).Times(1).InSequence(s1);
|
|
EXPECT_CALL(api, CommandEncoderRelease(apiCommandEncoder)).Times(1).InSequence(s2);
|
|
EXPECT_CALL(api, SamplerRelease(apiSampler)).Times(1).InSequence(s3);
|
|
EXPECT_CALL(api, OnDeviceSetUncapturedErrorCallback(apiDevice, nullptr, nullptr))
|
|
.Times(1)
|
|
.InSequence(s1, s2);
|
|
EXPECT_CALL(api, OnDeviceSetLoggingCallback(apiDevice, nullptr, nullptr))
|
|
.Times(1)
|
|
.InSequence(s1, s2);
|
|
EXPECT_CALL(api, OnDeviceSetDeviceLostCallback(apiDevice, nullptr, nullptr))
|
|
.Times(1)
|
|
.InSequence(s1, s2);
|
|
EXPECT_CALL(api, DeviceRelease(apiDevice)).Times(1).InSequence(s1, s2, s3);
|
|
FlushClient();
|
|
|
|
// Signal that we already released and cleared callbacks for |apiDevice|
|
|
DefaultApiDeviceWasReleased();
|
|
}
|