From f7bfaeaca0d7e059622b35af0275c9e3ff25b316 Mon Sep 17 00:00:00 2001 From: Martin Morrison-Grant Date: Wed, 12 Feb 2025 11:28:17 +0000 Subject: [PATCH] Improvements to align CTS and Spec for Program: - All error returns for urProgramCreateWithIL are now covered, and a Success case with different properties has been added - Passing properties to urProgramCreateWithBinary - Added tests for passing options to urProgramCompile/Link - Added extra validation for urProgramRetain/Release - Added unowned native handle test for urProgramCreateWithNativeHandle --- test/conformance/program/urProgramCompile.cpp | 14 ++ .../program/urProgramCreateWithBinary.cpp | 41 ++++++ .../program/urProgramCreateWithIL.cpp | 92 ++++++++++-- .../urProgramCreateWithNativeHandle.cpp | 22 +++ test/conformance/program/urProgramLink.cpp | 136 +++++++++--------- test/conformance/program/urProgramRelease.cpp | 9 ++ test/conformance/program/urProgramRetain.cpp | 11 +- .../testing/include/uur/fixtures.h | 32 ++++- 8 files changed, 276 insertions(+), 81 deletions(-) diff --git a/test/conformance/program/urProgramCompile.cpp b/test/conformance/program/urProgramCompile.cpp index 26e8709e31..c70641500f 100644 --- a/test/conformance/program/urProgramCompile.cpp +++ b/test/conformance/program/urProgramCompile.cpp @@ -6,6 +6,20 @@ #include +using urProgramCompileWithParamTest = uur::urProgramTestWithParam; + +UUR_DEVICE_TEST_SUITE_WITH_PARAM(urProgramCompileWithParamTest, + ::testing::Values("-O0", "-O1", "-O2", "-O3"), + uur::deviceTestWithParamPrinter); + +TEST_P(urProgramCompileWithParamTest, Success) { + const char *platformOption = nullptr; + ASSERT_SUCCESS(urPlatformGetBackendOption(platform, getParam().c_str(), + &platformOption)); + + ASSERT_SUCCESS(urProgramCompile(context, program, platformOption)); +} + using urProgramCompileTest = uur::urProgramTest; UUR_INSTANTIATE_DEVICE_TEST_SUITE(urProgramCompileTest); diff --git a/test/conformance/program/urProgramCreateWithBinary.cpp b/test/conformance/program/urProgramCreateWithBinary.cpp index 62aad1a364..bd3a6b8870 100644 --- a/test/conformance/program/urProgramCreateWithBinary.cpp +++ b/test/conformance/program/urProgramCreateWithBinary.cpp @@ -44,6 +44,47 @@ TEST_P(urProgramCreateWithBinaryTest, Success) { nullptr, &binary_program)); } +TEST_P(urProgramCreateWithBinaryTest, SuccessWithProperties) { + auto size = binary.size(); + const uint8_t *data = binary.data(); + + std::string string = "test metadata"; + ur_program_metadata_value_t md_value_string; + md_value_string.pString = string.data(); + ur_program_metadata_t meta_string = {string.data(), + UR_PROGRAM_METADATA_TYPE_STRING, + string.size(), md_value_string}; + + ur_program_metadata_value_t md_value_32; + md_value_32.data32 = 32; + ur_program_metadata_t meta_32 = {string.data(), + UR_PROGRAM_METADATA_TYPE_UINT32, + sizeof(uint32_t), md_value_32}; + + ur_program_metadata_value_t md_value_64; + md_value_64.data64 = 64; + ur_program_metadata_t meta_64 = {string.data(), + UR_PROGRAM_METADATA_TYPE_UINT64, + sizeof(uint64_t), md_value_64}; + + ur_program_metadata_value_t md_value_data; + std::vector metadataValue = {0xDE, 0xAD, 0xBE, 0xEF}; + md_value_data.pData = metadataValue.data(); + ur_program_metadata_t meta_data = {string.data(), + UR_PROGRAM_METADATA_TYPE_BYTE_ARRAY, + metadataValue.size(), md_value_data}; + + std::vector metadatas = {meta_string, meta_32, meta_64, + meta_data}; + + ur_program_properties_t properties{ + UR_STRUCTURE_TYPE_PROGRAM_PROPERTIES, nullptr, + static_cast(metadatas.size()), metadatas.data()}; + + ASSERT_SUCCESS(urProgramCreateWithBinary(context, 1, &device, &size, &data, + &properties, &binary_program)); +} + TEST_P(urProgramCreateWithBinaryTest, InvalidNullHandleContext) { auto size = binary.size(); const uint8_t *data = binary.data(); diff --git a/test/conformance/program/urProgramCreateWithIL.cpp b/test/conformance/program/urProgramCreateWithIL.cpp index e70ae0a922..98c5171065 100644 --- a/test/conformance/program/urProgramCreateWithIL.cpp +++ b/test/conformance/program/urProgramCreateWithIL.cpp @@ -46,8 +46,39 @@ TEST_P(urProgramCreateWithILTest, Success) { TEST_P(urProgramCreateWithILTest, SuccessWithProperties) { UUR_KNOWN_FAILURE_ON(uur::CUDA{}); - ur_program_properties_t properties{UR_STRUCTURE_TYPE_PROGRAM_PROPERTIES, - nullptr, 0, nullptr}; + std::string string = "test metadata"; + ur_program_metadata_value_t md_value_string; + md_value_string.pString = string.data(); + ur_program_metadata_t meta_string = {string.data(), + UR_PROGRAM_METADATA_TYPE_STRING, + string.size(), md_value_string}; + + ur_program_metadata_value_t md_value_32; + md_value_32.data32 = 32; + ur_program_metadata_t meta_32 = {string.data(), + UR_PROGRAM_METADATA_TYPE_UINT32, + sizeof(uint32_t), md_value_32}; + + ur_program_metadata_value_t md_value_64; + md_value_64.data64 = 64; + ur_program_metadata_t meta_64 = {string.data(), + UR_PROGRAM_METADATA_TYPE_UINT64, + sizeof(uint64_t), md_value_64}; + + ur_program_metadata_value_t md_value_data; + std::vector metadataValue = {0xDE, 0xAD, 0xBE, 0xEF}; + md_value_data.pData = metadataValue.data(); + ur_program_metadata_t meta_data = {string.data(), + UR_PROGRAM_METADATA_TYPE_BYTE_ARRAY, + metadataValue.size(), md_value_data}; + + std::vector metadatas = {meta_string, meta_32, meta_64, + meta_data}; + + ur_program_properties_t properties{ + UR_STRUCTURE_TYPE_PROGRAM_PROPERTIES, nullptr, + static_cast(metadatas.size()), metadatas.data()}; + ur_program_handle_t program = nullptr; ASSERT_SUCCESS(urProgramCreateWithIL( context, il_binary->data(), il_binary->size(), &properties, &program)); @@ -56,33 +87,51 @@ TEST_P(urProgramCreateWithILTest, SuccessWithProperties) { } TEST_P(urProgramCreateWithILTest, InvalidNullHandle) { - ur_program_handle_t program = nullptr; ASSERT_EQ_RESULT(UR_RESULT_ERROR_INVALID_NULL_HANDLE, urProgramCreateWithIL(nullptr, il_binary->data(), - il_binary->size(), nullptr, &program)); + il_binary->size(), nullptr, nullptr)); } -TEST_P(urProgramCreateWithILTest, InvalidNullPointerSource) { - ur_program_handle_t program = nullptr; +TEST_P(urProgramCreateWithILTest, InvalidNullPointer) { + ASSERT_EQ_RESULT(UR_RESULT_ERROR_INVALID_NULL_POINTER, urProgramCreateWithIL(context, nullptr, il_binary->size(), - nullptr, &program)); + nullptr, nullptr)); + + ASSERT_EQ_RESULT(UR_RESULT_ERROR_INVALID_NULL_POINTER, + urProgramCreateWithIL(context, il_binary->data(), + il_binary->size(), nullptr, nullptr)); + + ur_program_properties_t properties{UR_STRUCTURE_TYPE_PROGRAM_PROPERTIES, + nullptr, 1, nullptr}; + ASSERT_EQ_RESULT(UR_RESULT_ERROR_INVALID_NULL_POINTER, + urProgramCreateWithIL(context, il_binary->data(), + il_binary->size(), &properties, + nullptr)); } -TEST_P(urProgramCreateWithILTest, InvalidSizeLength) { +TEST_P(urProgramCreateWithILTest, InvalidSize) { ur_program_handle_t program = nullptr; ASSERT_EQ_RESULT( UR_RESULT_ERROR_INVALID_SIZE, urProgramCreateWithIL(context, il_binary->data(), 0, nullptr, &program)); -} -TEST_P(urProgramCreateWithILTest, InvalidNullPointerProgram) { - ASSERT_EQ_RESULT(UR_RESULT_ERROR_INVALID_NULL_POINTER, - urProgramCreateWithIL(context, il_binary->data(), - il_binary->size(), nullptr, nullptr)); + std::string md_string = "test metadata"; + ur_program_metadata_value_t md_value = {}; + md_value.pString = md_string.data(); + ur_program_metadata_t metadata = {md_string.data(), + UR_PROGRAM_METADATA_TYPE_STRING, + md_string.size(), md_value}; + + ur_program_properties_t properties{UR_STRUCTURE_TYPE_PROGRAM_PROPERTIES, + nullptr, 0, &metadata}; + + ASSERT_EQ_RESULT(UR_RESULT_ERROR_INVALID_SIZE, + urProgramCreateWithIL(context, il_binary->data(), 1, + &properties, &program)); } -TEST_P(urProgramCreateWithILTest, BuildInvalidProgram) { +TEST_P(urProgramCreateWithILTest, InvalidBinary) { UUR_KNOWN_FAILURE_ON(uur::CUDA{}); ur_program_handle_t program = nullptr; @@ -92,3 +141,18 @@ TEST_P(urProgramCreateWithILTest, BuildInvalidProgram) { ASSERT_TRUE(result == UR_RESULT_ERROR_INVALID_BINARY || result == UR_RESULT_SUCCESS); } + +TEST_P(urProgramCreateWithILTest, CompilerNotAvailable) { + UUR_KNOWN_FAILURE_ON(uur::CUDA{}); + + ur_bool_t compiler_available = false; + urDeviceGetInfo(device, UR_DEVICE_INFO_COMPILER_AVAILABLE, sizeof(ur_bool_t), + &compiler_available, nullptr); + + if (!compiler_available) { + ur_program_handle_t program = nullptr; + ASSERT_EQ_RESULT(UR_RESULT_ERROR_COMPILER_NOT_AVAILABLE, + urProgramCreateWithIL(context, il_binary->data(), 1, + nullptr, &program)); + } +} diff --git a/test/conformance/program/urProgramCreateWithNativeHandle.cpp b/test/conformance/program/urProgramCreateWithNativeHandle.cpp index 9726f7f53e..28c2dfdb59 100644 --- a/test/conformance/program/urProgramCreateWithNativeHandle.cpp +++ b/test/conformance/program/urProgramCreateWithNativeHandle.cpp @@ -47,6 +47,28 @@ TEST_P(urProgramCreateWithNativeHandleTest, Success) { ASSERT_NE(ref_count, 0); } +TEST_P(urProgramCreateWithNativeHandleTest, + SuccessWithExplicitUnOwnedNativeHandle) { + ur_native_handle_t native_handle = 0; + UUR_ASSERT_SUCCESS_OR_UNSUPPORTED( + urProgramGetNativeHandle(program, &native_handle)); + + ur_program_native_properties_t props = { + /*.stype =*/UR_STRUCTURE_TYPE_PROGRAM_NATIVE_PROPERTIES, + /*.pNext =*/nullptr, + /*.isNativeHandleOwned =*/false, + }; + UUR_ASSERT_SUCCESS_OR_UNSUPPORTED(urProgramCreateWithNativeHandle( + native_handle, context, &props, &native_program)); + ASSERT_NE(nullptr, native_program); + + ur_context_handle_t program_context = nullptr; + ASSERT_SUCCESS(urProgramGetInfo(native_program, UR_PROGRAM_INFO_CONTEXT, + sizeof(ur_context_handle_t), &program_context, + nullptr)); + ASSERT_EQ(context, program_context); +} + TEST_P(urProgramCreateWithNativeHandleTest, SuccessWithProperties) { // We can't pass isNativeHandleOwned = true in the generic tests since // we always get the native handle from a UR object, and transferring diff --git a/test/conformance/program/urProgramLink.cpp b/test/conformance/program/urProgramLink.cpp index c7eecfed54..b3022a52cc 100644 --- a/test/conformance/program/urProgramLink.cpp +++ b/test/conformance/program/urProgramLink.cpp @@ -7,73 +7,37 @@ #include #include -struct urProgramLinkTest : uur::urProgramTest { - void SetUp() override { - UUR_RETURN_ON_FATAL_FAILURE(urProgramTest::SetUp()); - // TODO: This should use a query for urProgramCreateWithIL support or - // rely on UR_RESULT_ERROR_UNSUPPORTED_FEATURE being returned. - ur_platform_backend_t backend; - ASSERT_SUCCESS(urPlatformGetInfo(platform, UR_PLATFORM_INFO_BACKEND, - sizeof(ur_platform_backend_t), &backend, - nullptr)); - if (backend == UR_PLATFORM_BACKEND_HIP) { - GTEST_SKIP(); - } - ASSERT_SUCCESS(urProgramCompile(context, program, nullptr)); - } +using urProgramLinkWithParam = uur::urProgramLinkWithParamBaseTest; - void TearDown() override { - if (linked_program) { - EXPECT_SUCCESS(urProgramRelease(linked_program)); - } - UUR_RETURN_ON_FATAL_FAILURE(urProgramTest::TearDown()); - } +UUR_DEVICE_TEST_SUITE_WITH_PARAM(urProgramLinkWithParam, + ::testing::Values("-O0", "-O1", "-O2", "-O3"), + uur::deviceTestWithParamPrinter); - ur_program_handle_t linked_program = nullptr; -}; -UUR_INSTANTIATE_DEVICE_TEST_SUITE(urProgramLinkTest); +TEST_P(urProgramLinkWithParam, Success) { + UUR_KNOWN_FAILURE_ON(uur::OpenCL{"Intel(R) Core(TM) i9-12900K"}); -struct urProgramLinkErrorTest : uur::urQueueTest { - const std::string linker_error_program_name = "linker_error"; + size_t property_size = 0; + const ur_platform_info_t property_name = UR_PLATFORM_INFO_BACKEND; - void SetUp() override { - // We haven't got device code tests working on native cpu yet. - UUR_KNOWN_FAILURE_ON(uur::NativeCPU{}); + ASSERT_SUCCESS_OR_OPTIONAL_QUERY( + urPlatformGetInfo(platform, property_name, 0, nullptr, &property_size), + property_name); + ASSERT_EQ(property_size, sizeof(ur_platform_backend_t)); - UUR_RETURN_ON_FATAL_FAILURE(urQueueTest::SetUp()); - // TODO: This should use a query for urProgramCreateWithIL support or - // rely on UR_RESULT_ERROR_UNSUPPORTED_FEATURE being returned. - ur_platform_backend_t backend; - ASSERT_SUCCESS(urPlatformGetInfo(platform, UR_PLATFORM_INFO_BACKEND, - sizeof(ur_platform_backend_t), &backend, - nullptr)); - if (backend == UR_PLATFORM_BACKEND_HIP) { - GTEST_SKIP(); - } - // Don't know how to produce alinker error on CUDA - if (backend == UR_PLATFORM_BACKEND_CUDA) { - GTEST_SKIP(); - } + ur_platform_backend_t backend = UR_PLATFORM_BACKEND_UNKNOWN; + ASSERT_SUCCESS(urPlatformGetInfo(platform, property_name, property_size, + &backend, nullptr)); - std::shared_ptr> il_binary{}; - UUR_RETURN_ON_FATAL_FAILURE(uur::KernelsEnvironment::instance->LoadSource( - linker_error_program_name, platform, il_binary)); - ASSERT_SUCCESS(uur::KernelsEnvironment::instance->CreateProgram( - platform, context, device, *il_binary, nullptr, &program)); - ASSERT_SUCCESS(urProgramCompile(context, program, nullptr)); - } + const char *platformOption = nullptr; + ASSERT_SUCCESS(urPlatformGetBackendOption(platform, getParam().c_str(), + &platformOption)); - void TearDown() override { - if (linked_program) { - EXPECT_SUCCESS(urProgramRelease(linked_program)); - } - UUR_RETURN_ON_FATAL_FAILURE(urQueueTest::TearDown()); - } + ASSERT_SUCCESS( + urProgramLink(context, 1, &program, platformOption, &linked_program)); +} - ur_program_handle_t program = nullptr; - ur_program_handle_t linked_program = nullptr; -}; -UUR_INSTANTIATE_DEVICE_TEST_SUITE(urProgramLinkErrorTest); +using urProgramLinkTest = uur::urProgramLinkBaseTest; +UUR_INSTANTIATE_DEVICE_TEST_SUITE(urProgramLinkTest); TEST_P(urProgramLinkTest, Success) { // This entry point isn't implemented for HIP. @@ -110,12 +74,6 @@ TEST_P(urProgramLinkTest, InvalidSizeCount) { urProgramLink(context, 0, &program, nullptr, &linked_program)); } -TEST_P(urProgramLinkErrorTest, LinkFailure) { - ASSERT_EQ_RESULT( - UR_RESULT_ERROR_PROGRAM_LINK_FAILURE, - urProgramLink(context, 1, &program, nullptr, &linked_program)); -} - TEST_P(urProgramLinkTest, SetOutputOnZeroCount) { uintptr_t invalid_pointer; linked_program = reinterpret_cast(&invalid_pointer); @@ -126,6 +84,54 @@ TEST_P(urProgramLinkTest, SetOutputOnZeroCount) { reinterpret_cast(&invalid_pointer)); } +struct urProgramLinkErrorTest : uur::urQueueTest { + const std::string linker_error_program_name = "linker_error"; + + void SetUp() override { + // We haven't got device code tests working on native cpu yet. + UUR_KNOWN_FAILURE_ON(uur::NativeCPU{}); + + UUR_RETURN_ON_FATAL_FAILURE(urQueueTest::SetUp()); + // TODO: This should use a query for urProgramCreateWithIL support or + // rely on UR_RESULT_ERROR_UNSUPPORTED_FEATURE being returned. + ur_platform_backend_t backend; + ASSERT_SUCCESS(urPlatformGetInfo(platform, UR_PLATFORM_INFO_BACKEND, + sizeof(ur_platform_backend_t), &backend, + nullptr)); + if (backend == UR_PLATFORM_BACKEND_HIP) { + GTEST_SKIP(); + } + // Don't know how to produce alinker error on CUDA + if (backend == UR_PLATFORM_BACKEND_CUDA) { + GTEST_SKIP(); + } + + std::shared_ptr> il_binary{}; + UUR_RETURN_ON_FATAL_FAILURE(uur::KernelsEnvironment::instance->LoadSource( + linker_error_program_name, platform, il_binary)); + ASSERT_SUCCESS(uur::KernelsEnvironment::instance->CreateProgram( + platform, context, device, *il_binary, nullptr, &program)); + ASSERT_SUCCESS(urProgramCompile(context, program, nullptr)); + } + + void TearDown() override { + if (linked_program) { + EXPECT_SUCCESS(urProgramRelease(linked_program)); + } + UUR_RETURN_ON_FATAL_FAILURE(urQueueTest::TearDown()); + } + + ur_program_handle_t program = nullptr; + ur_program_handle_t linked_program = nullptr; +}; +UUR_INSTANTIATE_DEVICE_TEST_SUITE(urProgramLinkErrorTest); + +TEST_P(urProgramLinkErrorTest, LinkFailure) { + ASSERT_EQ_RESULT( + UR_RESULT_ERROR_PROGRAM_LINK_FAILURE, + urProgramLink(context, 1, &program, nullptr, &linked_program)); +} + TEST_P(urProgramLinkErrorTest, SetOutputOnLinkError) { uintptr_t invalid_pointer; linked_program = reinterpret_cast(&invalid_pointer); diff --git a/test/conformance/program/urProgramRelease.cpp b/test/conformance/program/urProgramRelease.cpp index 24f9d9f764..e58b17883e 100644 --- a/test/conformance/program/urProgramRelease.cpp +++ b/test/conformance/program/urProgramRelease.cpp @@ -11,7 +11,16 @@ UUR_INSTANTIATE_DEVICE_TEST_SUITE(urProgramReleaseTest); TEST_P(urProgramReleaseTest, Success) { ASSERT_SUCCESS(urProgramRetain(program)); + + uint32_t prevRefCount = 0; + ASSERT_SUCCESS(uur::GetObjectReferenceCount(program, prevRefCount)); + ASSERT_SUCCESS(urProgramRelease(program)); + + uint32_t refCount = 0; + ASSERT_SUCCESS(uur::GetObjectReferenceCount(program, refCount)); + + ASSERT_GT(prevRefCount, refCount); } TEST_P(urProgramReleaseTest, InvalidNullHandleProgram) { diff --git a/test/conformance/program/urProgramRetain.cpp b/test/conformance/program/urProgramRetain.cpp index efce89bbdb..b9a4bcdeb6 100644 --- a/test/conformance/program/urProgramRetain.cpp +++ b/test/conformance/program/urProgramRetain.cpp @@ -10,8 +10,17 @@ using urProgramRetainTest = uur::urProgramTest; UUR_INSTANTIATE_DEVICE_TEST_SUITE(urProgramRetainTest); TEST_P(urProgramRetainTest, Success) { + uint32_t prevRefCount = 0; + ASSERT_SUCCESS(uur::GetObjectReferenceCount(program, prevRefCount)); + ASSERT_SUCCESS(urProgramRetain(program)); - EXPECT_SUCCESS(urProgramRelease(program)); + + uint32_t refCount = 0; + ASSERT_SUCCESS(uur::GetObjectReferenceCount(program, refCount)); + + ASSERT_LT(prevRefCount, refCount); + + EXPECT_SUCCESS(urProgramRetain(program)); } TEST_P(urProgramRetainTest, InvalidNullHandleProgram) { diff --git a/test/conformance/testing/include/uur/fixtures.h b/test/conformance/testing/include/uur/fixtures.h index 22de17f567..db19ae016c 100644 --- a/test/conformance/testing/include/uur/fixtures.h +++ b/test/conformance/testing/include/uur/fixtures.h @@ -1196,7 +1196,8 @@ std::string deviceTestWithParamPrinter( std::stringstream ss; ss << param; - return uur::GetPlatformAndDeviceName(device) + "__" + ss.str(); + return uur::GetPlatformAndDeviceName(device) + "__" + + GTestSanitizeString(ss.str()); } template <> @@ -1312,6 +1313,35 @@ template struct urProgramTestWithParam : urQueueTestWithParam { std::vector metadatas{}; }; +template struct urProgramLinkBaseTest : public Derived { + void SetUp() override { + UUR_RETURN_ON_FATAL_FAILURE(Derived::SetUp()); + // TODO: This should use a query for urProgramCreateWithIL support or + // rely on UR_RESULT_ERROR_UNSUPPORTED_FEATURE being returned. + ur_platform_backend_t backend; + ASSERT_SUCCESS(urPlatformGetInfo(this->platform, UR_PLATFORM_INFO_BACKEND, + sizeof(ur_platform_backend_t), &backend, + nullptr)); + if (backend == UR_PLATFORM_BACKEND_HIP) { + GTEST_SKIP(); + } + ASSERT_SUCCESS(urProgramCompile(this->context, this->program, nullptr)); + } + + void TearDown() override { + if (linked_program) { + EXPECT_SUCCESS(urProgramRelease(linked_program)); + } + UUR_RETURN_ON_FATAL_FAILURE(Derived::TearDown()); + } + + ur_program_handle_t linked_program = nullptr; +}; + +template +struct urProgramLinkWithParamBaseTest + : urProgramLinkBaseTest> {}; + // This fixture can provide a kernel, but it doesn't build the kernel at SetUp, // instead Build() must be invoked separately. This is for tests that wish to // check device capabilities to determine whether the test should run before