Skip to content

Commit 536a8dd

Browse files
Implement Negative Tests for cl_context Functions
This change adds negative tests to `cl_context`-related APIs: - clCreateContext - clCreateContextFromType - clRetainContext - clReleaseContext - clSetContextDestructorCallback It also adds a verification macro: `test_object_failure_ret`. It verifies that an expected error code is returned and the CL object is `NULL`. Signed-off-by: Michael Rizkalla <michael.rizkalla@arm.com>
1 parent bd16775 commit 536a8dd

File tree

3 files changed

+297
-0
lines changed

3 files changed

+297
-0
lines changed

test_common/harness/errorHelpers.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,12 @@ static int vlog_win32(const char *format, ...);
120120
return retValue; \
121121
} \
122122
}
123+
#define test_object_failure_ret(object, errCode, expectedErrCode, msg, \
124+
retValue) \
125+
{ \
126+
test_assert_error_ret(object == nullptr, msg, retValue); \
127+
test_failure_error_ret(errCode, expectedErrCode, msg, retValue); \
128+
}
123129
#define print_failure_error(errCode, expectedErrCode, msg) \
124130
log_error("ERROR: %s! (Got %s, expected %s from %s:%d)\n", msg, \
125131
IGetErrorString(errCode), IGetErrorString(expectedErrCode), \

test_conformance/api/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ set(${MODULE_NAME}_SOURCES
66
main.cpp
77
negative_platform.cpp
88
negative_queue.cpp
9+
negative_context.cpp
910
negative_enqueue_marker.cpp
1011
negative_enqueue_map_image.cpp
1112
negative_device.cpp
Lines changed: 290 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,290 @@
1+
//
2+
// Copyright (c) 2025 The Khronos Group Inc.
3+
//
4+
// Licensed under the Apache License, Version 2.0 (the "License");
5+
// you may not use this file except in compliance with the License.
6+
// You may obtain a copy of the License at
7+
//
8+
// http://www.apache.org/licenses/LICENSE-2.0
9+
//
10+
// Unless required by applicable law or agreed to in writing, software
11+
// distributed under the License is distributed on an "AS IS" BASIS,
12+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
// See the License for the specific language governing permissions and
14+
// limitations under the License.
15+
//
16+
#include "testBase.h"
17+
18+
/* Negative Tests for clCreateContext */
19+
REGISTER_TEST(negative_create_context)
20+
{
21+
cl_context_properties props[3] = {
22+
CL_CONTEXT_PLATFORM, reinterpret_cast<cl_context_properties>(nullptr), 0
23+
};
24+
cl_int err = 0;
25+
cl_context ctx = clCreateContext(props, 1, &device, nullptr, nullptr, &err);
26+
test_object_failure_ret(
27+
ctx, err, CL_INVALID_PLATFORM,
28+
"clCreateContext should return CL_INVALID_PLATFORM when:\"an invalid "
29+
"platform object is used with the CL_CONTEXT_PLATFORM property\" using "
30+
"a nullptr",
31+
TEST_FAIL);
32+
33+
props[0] = reinterpret_cast<cl_context_properties>("INVALID_PROPERTY");
34+
35+
props[1] = reinterpret_cast<cl_context_properties>(nullptr);
36+
ctx = clCreateContext(props, 1, &device, nullptr, nullptr, &err);
37+
test_object_failure_ret(
38+
ctx, err, CL_INVALID_PROPERTY,
39+
"clCreateContext should return CL_INVALID_PROPERTY when: \"context "
40+
"property name in properties is not a supported property name\"",
41+
TEST_FAIL);
42+
43+
if (get_device_cl_version(device) >= Version(1, 2))
44+
{
45+
cl_context_properties invalid_value{ -1 };
46+
props[0] = CL_CONTEXT_INTEROP_USER_SYNC;
47+
props[1] = invalid_value;
48+
ctx = clCreateContext(props, 1, &device, nullptr, nullptr, &err);
49+
test_object_failure_ret(
50+
ctx, err, CL_INVALID_PROPERTY,
51+
"clCreateContext should return CL_INVALID_PROPERTY when: \"the "
52+
"value specified for a supported property name is not valid\"",
53+
TEST_FAIL);
54+
55+
cl_bool property_value = CL_FALSE;
56+
cl_context_properties duplicated_property[5] = {
57+
CL_CONTEXT_INTEROP_USER_SYNC,
58+
static_cast<cl_context_properties>(property_value),
59+
CL_CONTEXT_INTEROP_USER_SYNC,
60+
static_cast<cl_context_properties>(property_value), 0
61+
};
62+
ctx = clCreateContext(duplicated_property, 1, &device, nullptr, nullptr,
63+
&err);
64+
test_object_failure_ret(
65+
ctx, err, CL_INVALID_PROPERTY,
66+
"clCreateContext should return CL_INVALID_PROPERTY when: \"the "
67+
"same property name is specified more than once\"",
68+
TEST_FAIL);
69+
}
70+
71+
ctx = clCreateContext(nullptr, 1, nullptr, nullptr, nullptr, &err);
72+
test_object_failure_ret(ctx, err, CL_INVALID_VALUE,
73+
"clCreateContext should return CL_INVALID_VALUE "
74+
"when: \"devices is NULL\"",
75+
TEST_FAIL);
76+
77+
ctx = clCreateContext(nullptr, 0, &device, nullptr, nullptr, &err);
78+
test_object_failure_ret(ctx, err, CL_INVALID_VALUE,
79+
"clCreateContext should return CL_INVALID_VALUE "
80+
"when: \"num_devices is equal to zero\"",
81+
TEST_FAIL);
82+
83+
int user_data = 1; // Arbitrary non-NULL value
84+
ctx = clCreateContext(nullptr, 1, &device, nullptr, &user_data, &err);
85+
test_object_failure_ret(
86+
ctx, err, CL_INVALID_VALUE,
87+
"clCreateContext should return CL_INVALID_VALUE when: \"pfn_notify is "
88+
"NULL but user_data is not NULL\"",
89+
TEST_FAIL);
90+
91+
cl_device_id invalid_device = nullptr;
92+
ctx = clCreateContext(nullptr, 1, &invalid_device, nullptr, nullptr, &err);
93+
test_object_failure_ret(
94+
ctx, err, CL_INVALID_DEVICE,
95+
"clCreateContext should return CL_INVALID_DEVICE when: \"any device in "
96+
"devices is not a valid device\" using a device set to nullptr",
97+
TEST_FAIL);
98+
99+
return TEST_PASS;
100+
}
101+
102+
/* Negative Tests for clCreateContextFromType */
103+
REGISTER_TEST(negative_create_context_from_type)
104+
{
105+
cl_platform_id platform = getPlatformFromDevice(device);
106+
107+
cl_context_properties props[5] = {
108+
CL_CONTEXT_PLATFORM, reinterpret_cast<cl_context_properties>(nullptr),
109+
0, 0, 0
110+
};
111+
cl_int err = 0;
112+
cl_context ctx = clCreateContextFromType(props, CL_DEVICE_TYPE_DEFAULT,
113+
nullptr, nullptr, &err);
114+
test_object_failure_ret(
115+
ctx, err, CL_INVALID_PLATFORM,
116+
"clCreateContextFromType should return CL_INVALID_PLATFORM when: \"an "
117+
"invalid platform object is used with the CL_CONTEXT_PLATFORM "
118+
"property\" using a nullptr",
119+
TEST_FAIL);
120+
121+
ctx = clCreateContextFromType(props, CL_DEVICE_TYPE_DEFAULT, nullptr,
122+
nullptr, &err);
123+
test_object_failure_ret(
124+
ctx, err, CL_INVALID_PLATFORM,
125+
"clCreateContextFromType should return CL_INVALID_PLATFORM when: \"an "
126+
"invalid platform object is used with the CL_CONTEXT_PLATFORM "
127+
"property\" using a valid object that is NOT a platform",
128+
TEST_FAIL);
129+
130+
props[1] = reinterpret_cast<cl_context_properties>(platform);
131+
props[2] = reinterpret_cast<cl_context_properties>("INVALID_PROPERTY");
132+
props[3] = reinterpret_cast<cl_context_properties>(nullptr);
133+
134+
ctx = clCreateContextFromType(props, CL_DEVICE_TYPE_DEFAULT, nullptr,
135+
nullptr, &err);
136+
test_object_failure_ret(
137+
ctx, err, CL_INVALID_PROPERTY,
138+
"clCreateContextFromType should return CL_INVALID_PROPERTY when: "
139+
"\"context property name in properties is not a supported property "
140+
"name\"",
141+
TEST_FAIL);
142+
143+
if (get_device_cl_version(device) >= Version(1, 2))
144+
{
145+
cl_context_properties invalid_value{ -1 };
146+
props[2] = CL_CONTEXT_INTEROP_USER_SYNC;
147+
props[3] = invalid_value;
148+
ctx = clCreateContextFromType(props, CL_DEVICE_TYPE_DEFAULT, nullptr,
149+
nullptr, &err);
150+
test_object_failure_ret(
151+
ctx, err, CL_INVALID_PROPERTY,
152+
"clCreateContextFromType should return CL_INVALID_PROPERTY when: "
153+
"\"the value specified for a supported property name is not "
154+
"valid\"",
155+
TEST_FAIL);
156+
157+
props[2] = CL_CONTEXT_PLATFORM;
158+
props[3] = reinterpret_cast<cl_context_properties>(platform);
159+
ctx = clCreateContextFromType(props, CL_DEVICE_TYPE_DEFAULT, nullptr,
160+
nullptr, &err);
161+
test_object_failure_ret(
162+
ctx, err, CL_INVALID_PROPERTY,
163+
"clCreateContextFromType should return CL_INVALID_PROPERTY when: "
164+
"\"the same property name is specified more than once\"",
165+
TEST_FAIL);
166+
}
167+
168+
int user_data = 1; // Arbitrary non-NULL value
169+
ctx = clCreateContextFromType(nullptr, CL_DEVICE_TYPE_DEFAULT, nullptr,
170+
&user_data, &err);
171+
test_object_failure_ret(
172+
ctx, err, CL_INVALID_VALUE,
173+
"clCreateContextFromType should return CL_INVALID_VALUE when: "
174+
"\"pfn_notify is NULL but user_data is not NULL\"",
175+
TEST_FAIL);
176+
177+
cl_device_type INVALID_DEVICE_TYPE = 0;
178+
ctx = clCreateContextFromType(nullptr, INVALID_DEVICE_TYPE, nullptr,
179+
nullptr, &err);
180+
test_object_failure_ret(
181+
ctx, err, CL_INVALID_DEVICE_TYPE,
182+
"clCreateContextFromType should return CL_INVALID_DEVICE_TYPE when: "
183+
"\"device_type is not a valid value\"",
184+
TEST_FAIL);
185+
186+
std::vector<cl_device_type> device_types = { CL_DEVICE_TYPE_CPU,
187+
CL_DEVICE_TYPE_GPU,
188+
CL_DEVICE_TYPE_ACCELERATOR };
189+
if (get_device_cl_version(device) >= Version(1, 2))
190+
{
191+
device_types.push_back(CL_DEVICE_TYPE_CUSTOM);
192+
}
193+
for (auto type : device_types)
194+
{
195+
clContextWrapper tmp_context =
196+
clCreateContextFromType(nullptr, type, nullptr, nullptr, &err);
197+
if (err != CL_SUCCESS)
198+
{
199+
test_object_failure_ret(
200+
tmp_context, err, CL_DEVICE_NOT_FOUND,
201+
"clCreateContextFromType should return CL_DEVICE_NOT_AVAILABLE "
202+
"when: \"no devices that match device_type and property values "
203+
"specified in properties are currently available\"",
204+
TEST_FAIL);
205+
break;
206+
}
207+
}
208+
209+
return TEST_PASS;
210+
}
211+
212+
/* Negative Tests for clRetainContext */
213+
REGISTER_TEST(negative_retain_context)
214+
{
215+
cl_int err = clRetainContext(nullptr);
216+
test_failure_error_ret(
217+
err, CL_INVALID_CONTEXT,
218+
"clRetainContext should return CL_INVALID_CONTEXT when: \"context is "
219+
"not a valid OpenCL context\" using a nullptr",
220+
TEST_FAIL);
221+
222+
return TEST_PASS;
223+
}
224+
225+
/* Negative Tests for clReleaseContext */
226+
REGISTER_TEST(negative_release_context)
227+
{
228+
cl_int err = clReleaseContext(nullptr);
229+
test_failure_error_ret(
230+
err, CL_INVALID_CONTEXT,
231+
"clReleaseContext should return CL_INVALID_CONTEXT when: \"context is "
232+
"not a valid OpenCL context\" using a nullptr",
233+
TEST_FAIL);
234+
235+
return TEST_PASS;
236+
}
237+
238+
/* Negative Tests for clGetContextInfo */
239+
REGISTER_TEST(negative_get_context_info)
240+
{
241+
242+
cl_uint param_value = 0;
243+
cl_int err = clGetContextInfo(nullptr, CL_CONTEXT_REFERENCE_COUNT,
244+
sizeof(param_value), &param_value, nullptr);
245+
test_failure_error_ret(
246+
err, CL_INVALID_CONTEXT,
247+
"clGetContextInfo should return CL_INVALID_CONTEXT when: \"context is "
248+
"not a valid context\" using a nullptr",
249+
TEST_FAIL);
250+
251+
cl_context_info INVALID_PARAM_VALUE = 0;
252+
err = clGetContextInfo(context, INVALID_PARAM_VALUE, 0, nullptr, nullptr);
253+
test_failure_error_ret(
254+
err, CL_INVALID_VALUE,
255+
"clGetContextInfo should return CL_INVALID_VALUE when: \"param_name is "
256+
"not one of the supported values\"",
257+
TEST_FAIL);
258+
259+
err = clGetContextInfo(context, CL_CONTEXT_REFERENCE_COUNT,
260+
sizeof(param_value) - 1, &param_value, nullptr);
261+
test_failure_error_ret(
262+
err, CL_INVALID_VALUE,
263+
"clGetContextInfo should return CL_INVALID_VALUE when: \"size in bytes "
264+
"specified by param_value_size is < size of return type and "
265+
"param_value is not a NULL value\"",
266+
TEST_FAIL);
267+
268+
return TEST_PASS;
269+
}
270+
271+
/* Negative Tests for clSetContextDestructorCallback */
272+
static void CL_CALLBACK callback(cl_context context, void* user_data) {}
273+
274+
REGISTER_TEST_VERSION(negative_set_context_destructor_callback, Version(3, 0))
275+
{
276+
cl_int err = clSetContextDestructorCallback(nullptr, callback, nullptr);
277+
test_failure_error_ret(
278+
err, CL_INVALID_CONTEXT,
279+
"clSetContextDestructorCallback should return CL_INVALID_CONTEXT when: "
280+
"\"context is not a valid context\" using a nullptr",
281+
TEST_FAIL);
282+
283+
err = clSetContextDestructorCallback(context, nullptr, nullptr);
284+
test_failure_error_ret(err, CL_INVALID_VALUE,
285+
"clSetContextDestructorCallback should return "
286+
"CL_INVALID_VALUE when: \"pfn_notify is NULL\"",
287+
TEST_FAIL);
288+
289+
return TEST_PASS;
290+
}

0 commit comments

Comments
 (0)