1 // Copyright 2017 The Dawn Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 #ifndef TESTS_UNITTESTS_VALIDATIONTEST_H_ 16 #define TESTS_UNITTESTS_VALIDATIONTEST_H_ 17 18 #include "common/Log.h" 19 #include "dawn/webgpu_cpp.h" 20 #include "dawn_native/DawnNative.h" 21 22 #include <gmock/gmock.h> 23 #include <gtest/gtest.h> 24 25 // Argument helpers to allow macro overriding. 26 #define UNIMPLEMENTED_MACRO(...) UNREACHABLE() 27 #define GET_3RD_ARG_HELPER_(_1, _2, NAME, ...) NAME 28 #define GET_3RD_ARG_(args) GET_3RD_ARG_HELPER_ args 29 30 // Overloaded to allow further validation of the error messages given an error is expected. 31 // Especially useful to verify that the expected errors are occuring, not just any error. 32 // 33 // Example usages: 34 // 1 Argument Case: 35 // ASSERT_DEVICE_ERROR(FunctionThatExpectsError()); 36 // 37 // 2 Argument Case: 38 // ASSERT_DEVICE_ERROR(FunctionThatHasLongError(), HasSubstr("partial match")) 39 // ASSERT_DEVICE_ERROR(FunctionThatHasShortError(), Eq("exact match")); 40 #define ASSERT_DEVICE_ERROR(...) \ 41 GET_3RD_ARG_((__VA_ARGS__, ASSERT_DEVICE_ERROR_IMPL_2_, ASSERT_DEVICE_ERROR_IMPL_1_, \ 42 UNIMPLEMENTED_MACRO)) \ 43 (__VA_ARGS__) 44 45 #define ASSERT_DEVICE_ERROR_IMPL_1_(statement) \ 46 StartExpectDeviceError(); \ 47 statement; \ 48 FlushWire(); \ 49 if (!EndExpectDeviceError()) { \ 50 FAIL() << "Expected device error in:\n " << #statement; \ 51 } \ 52 do { \ 53 } while (0) 54 55 #define ASSERT_DEVICE_ERROR_IMPL_2_(statement, matcher) \ 56 StartExpectDeviceError(matcher); \ 57 statement; \ 58 FlushWire(); \ 59 if (!EndExpectDeviceError()) { \ 60 FAIL() << "Expected device error in:\n " << #statement; \ 61 } \ 62 do { \ 63 } while (0) 64 65 // Skip a test when the given condition is satisfied. 66 #define DAWN_SKIP_TEST_IF(condition) \ 67 do { \ 68 if (condition) { \ 69 dawn::InfoLog() << "Test skipped: " #condition "."; \ 70 GTEST_SKIP(); \ 71 return; \ 72 } \ 73 } while (0) 74 75 #define EXPECT_DEPRECATION_WARNINGS(statement, n) \ 76 do { \ 77 FlushWire(); \ 78 size_t warningsBefore = dawn_native::GetDeprecationWarningCountForTesting(backendDevice); \ 79 EXPECT_EQ(mLastWarningCount, warningsBefore); \ 80 statement; \ 81 FlushWire(); \ 82 size_t warningsAfter = dawn_native::GetDeprecationWarningCountForTesting(backendDevice); \ 83 EXPECT_EQ(warningsAfter, warningsBefore + n); \ 84 mLastWarningCount = warningsAfter; \ 85 } while (0) 86 #define EXPECT_DEPRECATION_WARNING(statement) EXPECT_DEPRECATION_WARNINGS(statement, 1) 87 88 namespace utils { 89 class WireHelper; 90 } // namespace utils 91 92 void InitDawnValidationTestEnvironment(int argc, char** argv); 93 94 class ValidationTest : public testing::Test { 95 public: 96 ValidationTest(); 97 ~ValidationTest() override; 98 99 void SetUp() override; 100 void TearDown() override; 101 102 void StartExpectDeviceError(testing::Matcher<std::string> errorMatcher); 103 void StartExpectDeviceError(); 104 bool EndExpectDeviceError(); 105 std::string GetLastDeviceErrorMessage() const; 106 107 wgpu::Device RegisterDevice(WGPUDevice backendDevice); 108 109 bool UsesWire() const; 110 111 void FlushWire(); 112 void WaitForAllOperations(const wgpu::Device& device); 113 114 // Helper functions to create objects to test validation. 115 116 struct DummyRenderPass : public wgpu::RenderPassDescriptor { 117 public: 118 DummyRenderPass(const wgpu::Device& device); 119 wgpu::Texture attachment; 120 wgpu::TextureFormat attachmentFormat; 121 uint32_t width; 122 uint32_t height; 123 124 private: 125 wgpu::RenderPassColorAttachment mColorAttachment; 126 }; 127 128 bool HasToggleEnabled(const char* toggle) const; 129 130 // TODO(crbug.com/dawn/689): Use limits returned from the wire 131 // This is implemented here because tests need to always query 132 // the |backendDevice| since limits are not implemented in the wire. 133 wgpu::SupportedLimits GetSupportedLimits(); 134 135 protected: 136 virtual WGPUDevice CreateTestDevice(); 137 138 std::unique_ptr<dawn_native::Instance> instance; 139 dawn_native::Adapter adapter; 140 wgpu::Device device; 141 WGPUDevice backendDevice; 142 143 size_t mLastWarningCount = 0; 144 145 private: 146 std::unique_ptr<utils::WireHelper> mWireHelper; 147 148 static void OnDeviceError(WGPUErrorType type, const char* message, void* userdata); 149 std::string mDeviceErrorMessage; 150 bool mExpectError = false; 151 bool mError = false; 152 testing::Matcher<std::string> mErrorMatcher; 153 }; 154 155 #endif // TESTS_UNITTESTS_VALIDATIONTEST_H_ 156