DawnTest: Allow checking for device errors. The previous assumption is that all validation tests would be unittests and that the end2end tests would always produce valid sequences of commands. This not true because we can't test the validation of backend-specific entrypoints in the unittests. BUG=dawn:112 Change-Id: I89e2fe017bf3ecf6a83c9e8cdf4324c33f95a721 Reviewed-on: https://dawn-review.googlesource.com/c/5100 Reviewed-by: Kai Ninomiya <kainino@chromium.org> Reviewed-by: Austin Eng <enga@chromium.org> Commit-Queue: Corentin Wallez <cwallez@chromium.org>
diff --git a/src/tests/DawnTest.cpp b/src/tests/DawnTest.cpp index cc667e4..f512c8a 100644 --- a/src/tests/DawnTest.cpp +++ b/src/tests/DawnTest.cpp
@@ -52,12 +52,6 @@ } } - // End2end tests should test valid commands produce the expected result so no error - // should happen. Failure cases should be tested in the validation tests. - void DeviceErrorCauseTestFailure(const char* message, dawnCallbackUserdata) { - FAIL() << "Device level failure: " << message; - } - struct MapReadUserdata { DawnTest* test; size_t slot; @@ -315,8 +309,8 @@ static_cast<dawn::TextureFormat>(mBinding->GetPreferredSwapChainTextureFormat()), dawn::TextureUsageBit::OutputAttachment, 400, 400); - // The end2end tests should never cause validation errors. These should be tested in unittests. - device.SetErrorCallback(DeviceErrorCauseTestFailure, 0); + device.SetErrorCallback(OnDeviceError, + static_cast<dawnCallbackUserdata>(reinterpret_cast<uintptr_t>(this))); } void DawnTest::TearDown() { @@ -330,6 +324,24 @@ } } +void DawnTest::StartExpectDeviceError() { + mExpectError = true; + mError = false; +} +bool DawnTest::EndExpectDeviceError() { + mExpectError = false; + return mError; +} + +// static +void DawnTest::OnDeviceError(const char* message, dawnCallbackUserdata userdata) { + DawnTest* self = reinterpret_cast<DawnTest*>(static_cast<uintptr_t>(userdata)); + + ASSERT_TRUE(self->mExpectError) << "Got unexpected device error: " << message; + ASSERT_FALSE(self->mError) << "Got two errors in expect block"; + self->mError = true; +} + std::ostringstream& DawnTest::AddBufferExpectation(const char* file, int line, const dawn::Buffer& buffer,
diff --git a/src/tests/DawnTest.h b/src/tests/DawnTest.h index d2daa4b..3d2b879 100644 --- a/src/tests/DawnTest.h +++ b/src/tests/DawnTest.h
@@ -41,6 +41,13 @@ sizeof(RGBA8), \ new detail::ExpectEq<RGBA8>(expected, (width) * (height))) +// Should only be used to test validation of function that can't be tested by regular validation +// tests; +#define ASSERT_DEVICE_ERROR(statement) \ + StartExpectDeviceError(); \ + statement; \ + ASSERT_TRUE(EndExpectDeviceError()); + struct RGBA8 { constexpr RGBA8() : RGBA8(0, 0, 0, 0) { } @@ -124,6 +131,9 @@ bool IsLinux() const; bool IsMacOS() const; + void StartExpectDeviceError(); + bool EndExpectDeviceError(); + protected: dawn::Device device; dawn::Queue queue; @@ -160,6 +170,11 @@ std::unique_ptr<utils::TerribleCommandBuffer> mS2cBuf; void FlushWire(); + // Tracking for validation errors + static void OnDeviceError(const char* message, dawnCallbackUserdata userdata); + bool mExpectError = false; + bool mError = false; + // MapRead buffers used to get data for the expectations struct ReadbackSlot { dawn::Buffer buffer;
diff --git a/src/tests/end2end/BasicTests.cpp b/src/tests/end2end/BasicTests.cpp index 0400e06..cd8c373 100644 --- a/src/tests/end2end/BasicTests.cpp +++ b/src/tests/end2end/BasicTests.cpp
@@ -33,4 +33,16 @@ EXPECT_BUFFER_U32_EQ(value, buffer, 0); } +// Test a validation error for buffer setSubData, but really this is the most basic test possible +// for ASSERT_DEVICE_ERROR +TEST_P(BasicTests, BufferSetSubDataError) { + dawn::BufferDescriptor descriptor; + descriptor.size = 4; + descriptor.usage = dawn::BufferUsageBit::TransferSrc | dawn::BufferUsageBit::TransferDst; + dawn::Buffer buffer = device.CreateBuffer(&descriptor); + + uint8_t value = 187; + ASSERT_DEVICE_ERROR(buffer.SetSubData(1000, sizeof(value), &value)); +} + DAWN_INSTANTIATE_TEST(BasicTests, D3D12Backend, MetalBackend, OpenGLBackend, VulkanBackend);
diff --git a/src/tests/unittests/validation/ValidationTest.cpp b/src/tests/unittests/validation/ValidationTest.cpp index e14a014..db344ef 100644 --- a/src/tests/unittests/validation/ValidationTest.cpp +++ b/src/tests/unittests/validation/ValidationTest.cpp
@@ -84,6 +84,7 @@ return mDeviceErrorMessage; } +// static void ValidationTest::OnDeviceError(const char* message, dawnCallbackUserdata userdata) { auto self = reinterpret_cast<ValidationTest*>(static_cast<uintptr_t>(userdata)); self->mDeviceErrorMessage = message; @@ -100,6 +101,7 @@ self->mError = true; } +// static void ValidationTest::OnBuilderErrorStatus(dawnBuilderErrorStatus status, const char* message, dawn::CallbackUserdata userdata1, dawn::CallbackUserdata userdata2) { auto* self = reinterpret_cast<ValidationTest*>(static_cast<uintptr_t>(userdata1)); size_t index = static_cast<size_t>(userdata2);