diff --git a/.gitignore b/.gitignore index cb5fee19..c8e956ac 100644 --- a/.gitignore +++ b/.gitignore @@ -6,12 +6,17 @@ configure libtool Makefile Makefile.in +test-suite.log vkd3d-*.tar.gz +*.exe *.la *.lo +*.log +*.o *.pc +*.trs *~ .deps diff --git a/Makefile.am b/Makefile.am index 7f9fc5cf..3dd39101 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,6 +1,6 @@ ACLOCAL_AMFLAGS = -I m4 AM_CFLAGS = @VKD3D_CFLAGS@ -AM_CPPFLAGS = -I$(srcdir)/include -I$(srcdir)/include/dummy +AM_CPPFLAGS = -I$(srcdir)/include -I$(srcdir)/include/dummy -I$(srcdir)/include/private widl_headers = \ include/d3d12.h @@ -12,6 +12,9 @@ vkd3d_public_headers = \ include/dxgibase.h \ include/vkd3d_windows.h +vkd3d_tests = \ + tests/d3d12 + BUILT_SOURCES = $(widl_headers) CLEANFILES = $(widl_headers) @@ -26,6 +29,11 @@ pkgconfigdir = $(libdir)/pkgconfig pkginclude_HEADERS = $(vkd3d_public_headers) nodist_pkgconfig_DATA = libvkd3d.pc +LDADD = libvkd3d.la +check_PROGRAMS = $(vkd3d_tests) +AM_DEFAULT_SOURCE_EXT = .c +TESTS = $(vkd3d_tests) + $(widl_headers): %.h: %.idl $(WIDL) -o $@ $< diff --git a/include/private/vkd3d_test.h b/include/private/vkd3d_test.h new file mode 100644 index 00000000..bb78e31f --- /dev/null +++ b/include/private/vkd3d_test.h @@ -0,0 +1,139 @@ +/* + * Copyright 2016 Józef Kucia for CodeWeavers + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#ifndef __VKD3D_TEST_H +#define __VKD3D_TEST_H + +#include +#include +#include +#include + +static void vkd3d_test_main(void); +static const char *vkd3d_test_name; + +#define START_TEST(name) static const char *vkd3d_test_name = #name; \ + static void vkd3d_test_main(void) + +#ifdef __GNUC__ +# define VKD3D_PRINTF_FUNC(fmt, args) __attribute__((format(printf, fmt, args))) +# define VKD3D_UNUSED __attribute__((unused)) +#else +# define VKD3D_PRINTF_FUNC(fmt, args) +# define VKD3D_UNUSED +#endif /* __GNUC__ */ + + +#define ok ok_(__LINE__) +#define skip skip_(__LINE__) +#define trace trace_(__LINE__) + +#define ok_(line) \ + do { \ + unsigned int __line = line; \ + VKD3D_TEST_OK + +#define VKD3D_TEST_OK(args...) \ + vkd3d_test_ok(__line, args); } while (0) + +#define skip_(line) \ + do { \ + unsigned int __line = line; \ + VKD3D_TEST_SKIP + +#define VKD3D_TEST_SKIP(args...) \ + vkd3d_test_skip(__line, args); } while (0) + +#define trace_(line) \ + do { \ + unsigned int __line = line; \ + VKD3D_TEST_TRACE + +#define VKD3D_TEST_TRACE(args...) \ + vkd3d_test_trace(__line, args); } while (0) + +static struct +{ + unsigned int success_count; + unsigned int failure_count; + unsigned int skip_count; +} vkd3d_test_state; + +static void vkd3d_test_ok(unsigned int line, + int result, const char *fmt, ...) VKD3D_PRINTF_FUNC(3, 4) VKD3D_UNUSED; +static void vkd3d_test_skip(unsigned int line, + const char *fmt, ...) VKD3D_PRINTF_FUNC(2, 3) VKD3D_UNUSED; +static void vkd3d_test_trace(unsigned int line, + const char *fmt, ...) VKD3D_PRINTF_FUNC(2, 3) VKD3D_UNUSED; + +static void vkd3d_test_ok(unsigned int line, int result, const char *fmt, ...) +{ + if (result) + { + printf("%s:%d: Test succeeded.\n", vkd3d_test_name, line); + ++vkd3d_test_state.success_count; + } + else + { + va_list args; + va_start(args, fmt); + printf("%s:%d: Test failed: ", vkd3d_test_name, line); + vprintf(fmt, args); + va_end(args); + ++vkd3d_test_state.failure_count; + } +} + +static void vkd3d_test_skip(unsigned int line, const char *fmt, ...) +{ + va_list args; + va_start(args, fmt); + printf("%s:%d: Test skipped: ", vkd3d_test_name, line); + vprintf(fmt, args); + va_end(args); + ++vkd3d_test_state.skip_count; +} + +static void vkd3d_test_trace(unsigned int line, const char *fmt, ...) +{ + va_list args; + va_start(args, fmt); + printf("%s:%d: ", vkd3d_test_name, line); + vprintf(fmt, args); + va_end(args); +} + +int main(int argc, char **argv) +{ + memset(&vkd3d_test_state, 0, sizeof(vkd3d_test_state)); + + vkd3d_test_main(); + + printf("%s: %u tests executed (%u failures, %u skipped).\n", + vkd3d_test_name, + vkd3d_test_state.success_count + vkd3d_test_state.failure_count, + vkd3d_test_state.failure_count, vkd3d_test_state.skip_count); + + return !!vkd3d_test_state.failure_count; +} + +#endif /* __VKD3D_TEST__H */ diff --git a/tests/.gitignore b/tests/.gitignore new file mode 100644 index 00000000..2ea34ba2 --- /dev/null +++ b/tests/.gitignore @@ -0,0 +1 @@ +d3d12 diff --git a/tests/d3d12.c b/tests/d3d12.c new file mode 100644 index 00000000..3e00a1ab --- /dev/null +++ b/tests/d3d12.c @@ -0,0 +1,117 @@ +/* + * Copyright 2016 Józef Kucia for CodeWeavers + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#define INITGUID +#include "vkd3d_test.h" +#include "vkd3d_windows.h" + +/* Hack for MinGW-w64 headers. + * + * We want to use WIDL C inline wrappers because some methods + * in D3D12 interfaces return aggregate objects. Unfortunately, + * WIDL C inline wrappers are broken when used with MinGW-w64 + * headers because FORCEINLINE expands to extern inline + * which leads to the "multiple storage classes in declaration + * specifiers" compiler error. + */ +#ifdef __MINGW32__ +#include <_mingw.h> +# ifdef __MINGW64_VERSION_MAJOR +# undef __forceinline +# define __forceinline __inline__ __attribute__((__always_inline__,__gnu_inline__)) +# endif +#endif + +#define COBJMACROS +#define WIDL_C_INLINE_WRAPPERS +#include "d3d12.h" + +#define check_interface(a, b, c) check_interface_(__LINE__, (IUnknown *)a, b, c) +static void check_interface_(unsigned int line, IUnknown *iface, REFIID riid, BOOL supported) +{ + HRESULT hr, expected_hr; + IUnknown *unk; + + expected_hr = supported ? S_OK : E_NOINTERFACE; + + hr = IUnknown_QueryInterface(iface, riid, (void **)&unk); + ok_(line)(hr == expected_hr, "Got hr %#x, expected %#x.\n", hr, expected_hr); + if (SUCCEEDED(hr)) + IUnknown_Release(unk); +} + +static ID3D12Device *create_device(void) +{ + ID3D12Device *device; + HRESULT hr; + + if (FAILED(hr = D3D12CreateDevice(NULL, D3D_FEATURE_LEVEL_11_0, &IID_ID3D12Device, (void **)&device))) + return NULL; + + return device; +} + +static void test_create_device(void) +{ + ID3D12Device *device; + ULONG refcount; + HRESULT hr; + + if (!(device = create_device())) + { + skip("Failed to create device.\n"); + return; + } + + check_interface(device, &IID_ID3D12Object, TRUE); + check_interface(device, &IID_ID3D12DeviceChild, FALSE); + check_interface(device, &IID_ID3D12Pageable, FALSE); + check_interface(device, &IID_ID3D12Device, TRUE); + + refcount = ID3D12Device_Release(device); + ok(!refcount, "ID3D12Device has %u references left.\n", refcount); + + hr = D3D12CreateDevice(NULL, D3D_FEATURE_LEVEL_11_0, &IID_ID3D12Device, (void **)&device); + ok(hr == S_OK, "D3D12CreateDevice failed, hr %#x.\n", hr); + ID3D12Device_Release(device); + + hr = D3D12CreateDevice(NULL, D3D_FEATURE_LEVEL_9_1, &IID_ID3D12Device, (void **)&device); + ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr); + hr = D3D12CreateDevice(NULL, D3D_FEATURE_LEVEL_9_2, &IID_ID3D12Device, (void **)&device); + ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr); + hr = D3D12CreateDevice(NULL, D3D_FEATURE_LEVEL_9_3, &IID_ID3D12Device, (void **)&device); + ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr); + hr = D3D12CreateDevice(NULL, D3D_FEATURE_LEVEL_10_0, &IID_ID3D12Device, (void **)&device); + ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr); + hr = D3D12CreateDevice(NULL, D3D_FEATURE_LEVEL_10_1, &IID_ID3D12Device, (void **)&device); + ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr); + + hr = D3D12CreateDevice(NULL, 0, &IID_ID3D12Device, (void **)&device); + ok(hr == E_INVALIDARG, "D3D12CreateDevice failed, hr %#x.\n", hr); + hr = D3D12CreateDevice(NULL, ~0u, &IID_ID3D12Device, (void **)&device); + ok(hr == E_INVALIDARG, "D3D12CreateDevice failed, hr %#x.\n", hr); +} + +START_TEST(d3d12) +{ + test_create_device(); +}