Skip to content

Commit

Permalink
Added new test to verify negative results of clGetSemaphoreInfoKHR
Browse files Browse the repository at this point in the history
  • Loading branch information
shajder committed Jun 18, 2024
1 parent d379b58 commit 7fa9ec9
Show file tree
Hide file tree
Showing 5 changed files with 344 additions and 0 deletions.
2 changes: 2 additions & 0 deletions test_conformance/extensions/cl_khr_semaphore/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ set(MODULE_NAME CL_KHR_SEMAPHORE)
set(${MODULE_NAME}_SOURCES
main.cpp
test_semaphores.cpp
test_semaphores_negative_getinfo.cpp
semaphore_base.h
)

include(../../CMakeCommon.txt)
3 changes: 3 additions & 0 deletions test_conformance/extensions/cl_khr_semaphore/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ test_definition test_list[] = {
ADD_TEST_VERSION(semaphores_multi_wait, Version(1, 2)),
ADD_TEST_VERSION(semaphores_queries, Version(1, 2)),
ADD_TEST_VERSION(semaphores_import_export_fd, Version(1, 2)),
ADD_TEST_VERSION(semaphores_negative_get_info_invalid_semaphore,
Version(1, 2)),
ADD_TEST_VERSION(semaphores_negative_get_info_invalid_value, Version(1, 2)),
};

const int test_num = ARRAY_SIZE(test_list);
Expand Down
6 changes: 6 additions & 0 deletions test_conformance/extensions/cl_khr_semaphore/procs.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,3 +45,9 @@ extern int test_semaphores_import_export_fd(cl_device_id deviceID,
cl_context context,
cl_command_queue queue,
int num_elements);
extern int test_semaphores_negative_get_info_invalid_semaphore(
cl_device_id device, cl_context context, cl_command_queue queue,
int num_elements);
extern int test_semaphores_negative_get_info_invalid_value(
cl_device_id device, cl_context context, cl_command_queue queue,
int num_elements);
202 changes: 202 additions & 0 deletions test_conformance/extensions/cl_khr_semaphore/semaphore_base.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,202 @@
//
// Copyright (c) 2024 The Khronos Group Inc.
//
// 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.

#ifndef CL_KHR_SEMAPHORE_BASE_H
#define CL_KHR_SEMAPHORE_BASE_H

#include <CL/cl_ext.h>
#include "harness/deviceInfo.h"
#include "harness/testHarness.h"

#include "harness/typeWrappers.h"

struct SemaphoreBase
{
SemaphoreBase(cl_device_id device): device(device) {}

cl_int init_extension_functions()
{
cl_platform_id platform;
cl_int error =
clGetDeviceInfo(device, CL_DEVICE_PLATFORM, sizeof(cl_platform_id),
&platform, nullptr);
test_error(error, "clGetDeviceInfo for CL_DEVICE_PLATFORM failed");

// If it is supported get the addresses of all the APIs here.
// clang-format off
#define GET_EXTENSION_ADDRESS(FUNC) \
FUNC = reinterpret_cast<FUNC##_fn>( \
clGetExtensionFunctionAddressForPlatform(platform, #FUNC)); \
if (FUNC == nullptr) \
{ \
log_error("ERROR: clGetExtensionFunctionAddressForPlatform failed" \
" with " #FUNC "\n"); \
return TEST_FAIL; \
}
// clang-format on

GET_EXTENSION_ADDRESS(clCreateSemaphoreWithPropertiesKHR);
GET_EXTENSION_ADDRESS(clEnqueueSignalSemaphoresKHR);
GET_EXTENSION_ADDRESS(clEnqueueWaitSemaphoresKHR);
GET_EXTENSION_ADDRESS(clReleaseSemaphoreKHR);
GET_EXTENSION_ADDRESS(clGetSemaphoreInfoKHR);
GET_EXTENSION_ADDRESS(clRetainSemaphoreKHR);
GET_EXTENSION_ADDRESS(clGetSemaphoreHandleForTypeKHR);

#undef GET_EXTENSION_ADDRESS
return CL_SUCCESS;
}

clCreateSemaphoreWithPropertiesKHR_fn clCreateSemaphoreWithPropertiesKHR =
nullptr;
clEnqueueSignalSemaphoresKHR_fn clEnqueueSignalSemaphoresKHR = nullptr;
clEnqueueWaitSemaphoresKHR_fn clEnqueueWaitSemaphoresKHR = nullptr;
clReleaseSemaphoreKHR_fn clReleaseSemaphoreKHR = nullptr;
clGetSemaphoreInfoKHR_fn clGetSemaphoreInfoKHR = nullptr;
clRetainSemaphoreKHR_fn clRetainSemaphoreKHR = nullptr;
clGetSemaphoreHandleForTypeKHR_fn clGetSemaphoreHandleForTypeKHR = nullptr;

cl_device_id device = nullptr;
};

// Wrapper class based off generic typeWrappers.h wrappers. However, because
// the release/retain functions are queried at runtime from the platform,
// rather than known at compile time we cannot link the instantiated template.
// Instead, pass an instance of `SemaphoreTestBase` on wrapper construction
// to access the release/retain functions.
class clSemaphoreWrapper {
cl_semaphore_khr object = nullptr;

void retain()
{
if (!object) return;

auto err = base->clRetainSemaphoreKHR(object);
if (err != CL_SUCCESS)
{
print_error(err, "clRetainCommandBufferKHR() failed");
std::abort();
}
}

void release()
{
if (!object) return;

auto err = base->clReleaseSemaphoreKHR(object);
if (err != CL_SUCCESS)
{
print_error(err, "clReleaseCommandBufferKHR() failed");
std::abort();
}
}

// Used to access release/retain functions
SemaphoreBase *base;

public:
// We always want to have base available to dereference
clSemaphoreWrapper() = delete;

clSemaphoreWrapper(SemaphoreBase *base): base(base) {}

// On assignment, assume the object has a refcount of one.
clSemaphoreWrapper &operator=(cl_semaphore_khr rhs)
{
reset(rhs);
return *this;
}

// Copy semantics, increase retain count.
clSemaphoreWrapper(clSemaphoreWrapper const &w) { *this = w; }
clSemaphoreWrapper &operator=(clSemaphoreWrapper const &w)
{
reset(w.object);
retain();
return *this;
}

// Move semantics, directly take ownership.
clSemaphoreWrapper(clSemaphoreWrapper &&w) { *this = std::move(w); }
clSemaphoreWrapper &operator=(clSemaphoreWrapper &&w)
{
reset(w.object);
w.object = nullptr;
return *this;
}

~clSemaphoreWrapper() { reset(); }

// Release the existing object, if any, and own the new one, if any.
void reset(cl_semaphore_khr new_object = nullptr)
{
release();
object = new_object;
}

operator cl_semaphore_khr() const { return object; }
operator const cl_semaphore_khr *() { return &object; }
};

struct SemaphoreTestBase : public SemaphoreBase
{
SemaphoreTestBase(cl_device_id device, cl_context context,
cl_command_queue queue)
: SemaphoreBase(device), context(context), semaphore(this)
{
cl_int error = init_extension_functions();
if (error != CL_SUCCESS)
throw std::runtime_error("init_extension_functions failed\n");

error = clRetainCommandQueue(queue);
if (error != CL_SUCCESS)
throw std::runtime_error("clRetainCommandQueue failed\n");
this->queue = queue;
}

virtual cl_int Run() = 0;

protected:
cl_context context = nullptr;
clCommandQueueWrapper queue = nullptr;
clSemaphoreWrapper semaphore = nullptr;
};

template <class T>
int MakeAndRunTest(cl_device_id device, cl_context context,
cl_command_queue queue)
{
if (!is_extension_available(device, "cl_khr_semaphore"))
{
log_info(
"Device does not support 'cl_khr_semaphore'. Skipping the test.\n");
return TEST_SKIPPED_ITSELF;
}

cl_int status = TEST_PASS;
try
{
auto test_fixture = T(device, context, queue);
status = test_fixture.Run();
} catch (const std::runtime_error &e)
{
log_error("%s", e.what());
return TEST_FAIL;
}

return status;
}

#endif // CL_KHR_SEMAPHORE_BASE_H
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
//
// Copyright (c) 2024 The Khronos Group Inc.
//
// 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 "semaphore_base.h"

#include "harness/errorHelpers.h"

namespace {

// sema_object is not a valid semaphore.

struct GetInfoInvalidSemaphore : public SemaphoreTestBase
{
GetInfoInvalidSemaphore(cl_device_id device, cl_context context,
cl_command_queue queue)
: SemaphoreTestBase(device, context, queue)
{}

cl_int Run() override
{
// Wait semaphore
cl_semaphore_type_khr type = 0;
size_t ret_size = 0;
cl_int err = clGetSemaphoreInfoKHR(nullptr, CL_SEMAPHORE_TYPE_KHR,
sizeof(cl_semaphore_type_khr), &type,
&ret_size);
test_failure_error(err, CL_INVALID_SEMAPHORE_KHR,
"Unexpected clGetSemaphoreInfoKHR return");

return CL_SUCCESS;
}
};

// 1) param_name is not one of the attribute defined in the Semaphore Queries
// table

// 2) param_value_size is less than the size of Return Type of the corresponding
// param_name attribute as defined in the Semaphore Queries table.

struct GetInfoInvalidValue : public SemaphoreTestBase
{
GetInfoInvalidValue(cl_device_id device, cl_context context,
cl_command_queue queue)
: SemaphoreTestBase(device, context, queue)
{}

cl_int Run() override
{
// Create semaphore
cl_semaphore_properties_khr sema_props[] = {
static_cast<cl_semaphore_properties_khr>(CL_SEMAPHORE_TYPE_KHR),
static_cast<cl_semaphore_properties_khr>(
CL_SEMAPHORE_TYPE_BINARY_KHR),
static_cast<cl_semaphore_properties_khr>(
CL_SEMAPHORE_DEVICE_HANDLE_LIST_KHR),
(cl_semaphore_properties_khr)device,
CL_SEMAPHORE_DEVICE_HANDLE_LIST_END_KHR,
0
};

cl_int err = CL_SUCCESS;
semaphore =
clCreateSemaphoreWithPropertiesKHR(context, sema_props, &err);
test_error(err, "Could not create semaphore");

// (1)
cl_semaphore_info_khr param_name = ~0;
err = clGetSemaphoreInfoKHR(semaphore, param_name, 0, nullptr, nullptr);
test_failure_error(err, CL_INVALID_VALUE,
"Unexpected clGetSemaphoreInfoKHR return");

// (2)
size_t size = 0;
err = clGetSemaphoreInfoKHR(semaphore, CL_SEMAPHORE_PROPERTIES_KHR, 0,
nullptr, &size);
test_error(err, "Could not query semaphore");

// make sure that first test provides too small param size
if (size != sizeof(sema_props)
&& size <= sizeof(cl_semaphore_properties_khr))
test_fail("Error: expected size %d, returned %d",
sizeof(sema_props), size);

// first test with non-zero property size but not enough
cl_semaphore_properties_khr ret_props = 0;
err = clGetSemaphoreInfoKHR(semaphore, CL_SEMAPHORE_PROPERTIES_KHR,
sizeof(ret_props), &ret_props, nullptr);
test_failure_error(err, CL_INVALID_VALUE,
"Unexpected clGetSemaphoreInfoKHR return");

// second test with zero property size
cl_semaphore_type_khr type = 0;
err = clGetSemaphoreInfoKHR(semaphore, CL_SEMAPHORE_TYPE_KHR, 0, &type,
nullptr);
test_failure_error(err, CL_INVALID_VALUE,
"Unexpected clGetSemaphoreInfoKHR return");

return CL_SUCCESS;
}
};

}

int test_semaphores_negative_get_info_invalid_semaphore(cl_device_id device,
cl_context context,
cl_command_queue queue,
int num_elements)
{
return MakeAndRunTest<GetInfoInvalidSemaphore>(device, context, queue);
}

int test_semaphores_negative_get_info_invalid_value(cl_device_id device,
cl_context context,
cl_command_queue queue,
int num_elements)
{
return MakeAndRunTest<GetInfoInvalidValue>(device, context, queue);
}

0 comments on commit 7fa9ec9

Please sign in to comment.