Skip to content

Commit d99404d

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 0633af2 commit d99404d

File tree

3 files changed

+307
-0
lines changed

3 files changed

+307
-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_map_image.cpp
1011
test_api_consistency.cpp
1112
test_bool.cpp
Lines changed: 300 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,300 @@
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+
if (get_device_cl_version(device) >= Version(1, 1))
34+
{
35+
props[0] = reinterpret_cast<cl_context_properties>("INVALID_PROPERTY");
36+
37+
props[1] = reinterpret_cast<cl_context_properties>(nullptr);
38+
ctx = clCreateContext(props, 1, &device, nullptr, nullptr, &err);
39+
test_object_failure_ret(
40+
ctx, err, CL_INVALID_PROPERTY,
41+
"clCreateContext should return CL_INVALID_PROPERTY when: \"context "
42+
"property name in properties is not a supported property name\"",
43+
TEST_FAIL);
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+
props[0] = CL_DEVICE_TYPE;
56+
props[1] = 0;
57+
ctx = clCreateContext(props, 1, &device, nullptr, nullptr, &err);
58+
test_object_failure_ret(
59+
ctx, err, CL_INVALID_PROPERTY,
60+
"clCreateContext should return CL_INVALID_PROPERTY when: \"the "
61+
"context property name in properties is not a supported property "
62+
"name\"",
63+
TEST_FAIL);
64+
65+
cl_bool property_value = CL_FALSE;
66+
cl_context_properties duplicated_property[5] = {
67+
CL_CONTEXT_INTEROP_USER_SYNC,
68+
static_cast<cl_context_properties>(property_value),
69+
CL_CONTEXT_INTEROP_USER_SYNC,
70+
static_cast<cl_context_properties>(property_value), 0
71+
};
72+
ctx = clCreateContext(duplicated_property, 1, &device, nullptr, nullptr,
73+
&err);
74+
test_object_failure_ret(
75+
ctx, err, CL_INVALID_PROPERTY,
76+
"clCreateContext should return CL_INVALID_PROPERTY when: \"the "
77+
"same property name is specified more than once\"",
78+
TEST_FAIL);
79+
}
80+
81+
ctx = clCreateContext(nullptr, 1, nullptr, nullptr, nullptr, &err);
82+
test_object_failure_ret(ctx, err, CL_INVALID_VALUE,
83+
"clCreateContext should return CL_INVALID_VALUE "
84+
"when: \"devices is NULL\"",
85+
TEST_FAIL);
86+
87+
ctx = clCreateContext(nullptr, 0, &device, nullptr, nullptr, &err);
88+
test_object_failure_ret(ctx, err, CL_INVALID_VALUE,
89+
"clCreateContext should return CL_INVALID_VALUE "
90+
"when: \"num_devices is equal to zero\"",
91+
TEST_FAIL);
92+
93+
int user_data = 1; // Arbitrary non-NULL value
94+
ctx = clCreateContext(nullptr, 1, &device, nullptr, &user_data, &err);
95+
test_object_failure_ret(
96+
ctx, err, CL_INVALID_VALUE,
97+
"clCreateContext should return CL_INVALID_VALUE when: \"pfn_notify is "
98+
"NULL but user_data is not NULL\"",
99+
TEST_FAIL);
100+
101+
cl_device_id invalid_device = nullptr;
102+
ctx = clCreateContext(nullptr, 1, &invalid_device, nullptr, nullptr, &err);
103+
test_object_failure_ret(
104+
ctx, err, CL_INVALID_DEVICE,
105+
"clCreateContext should return CL_INVALID_DEVICE when: \"any device in "
106+
"devices is not a valid device\" using a device set to nullptr",
107+
TEST_FAIL);
108+
109+
return TEST_PASS;
110+
}
111+
112+
/* Negative Tests for clCreateContextFromType */
113+
REGISTER_TEST(negative_create_context_from_type)
114+
{
115+
cl_platform_id platform = getPlatformFromDevice(device);
116+
117+
cl_context_properties props[5] = {
118+
CL_CONTEXT_PLATFORM, reinterpret_cast<cl_context_properties>(nullptr),
119+
0, 0, 0
120+
};
121+
cl_int err = 0;
122+
cl_context ctx = clCreateContextFromType(props, CL_DEVICE_TYPE_DEFAULT,
123+
nullptr, nullptr, &err);
124+
test_object_failure_ret(
125+
ctx, err, CL_INVALID_PLATFORM,
126+
"clCreateContextFromType should return CL_INVALID_PLATFORM when: \"an "
127+
"invalid platform object is used with the CL_CONTEXT_PLATFORM "
128+
"property\" using a nullptr",
129+
TEST_FAIL);
130+
131+
ctx = clCreateContextFromType(props, CL_DEVICE_TYPE_DEFAULT, nullptr,
132+
nullptr, &err);
133+
test_object_failure_ret(
134+
ctx, err, CL_INVALID_PLATFORM,
135+
"clCreateContextFromType should return CL_INVALID_PLATFORM when: \"an "
136+
"invalid platform object is used with the CL_CONTEXT_PLATFORM "
137+
"property\" using a valid object that is NOT a platform",
138+
TEST_FAIL);
139+
140+
if (get_device_cl_version(device) >= Version(1, 1))
141+
{
142+
props[1] = reinterpret_cast<cl_context_properties>(platform);
143+
props[2] = reinterpret_cast<cl_context_properties>("INVALID_PROPERTY");
144+
props[3] = reinterpret_cast<cl_context_properties>(nullptr);
145+
146+
ctx = clCreateContextFromType(props, CL_DEVICE_TYPE_DEFAULT, nullptr,
147+
nullptr, &err);
148+
test_object_failure_ret(
149+
ctx, err, CL_INVALID_PROPERTY,
150+
"clCreateContextFromType should return CL_INVALID_PROPERTY when: "
151+
"\"context property name in properties is not a supported property "
152+
"name\"",
153+
TEST_FAIL);
154+
155+
cl_context_properties invalid_value{ -1 };
156+
props[2] = CL_CONTEXT_INTEROP_USER_SYNC;
157+
props[3] = invalid_value;
158+
ctx = clCreateContextFromType(props, CL_DEVICE_TYPE_DEFAULT, nullptr,
159+
nullptr, &err);
160+
test_object_failure_ret(
161+
ctx, err, CL_INVALID_PROPERTY,
162+
"clCreateContextFromType should return CL_INVALID_PROPERTY when: "
163+
"\"the value specified for a supported property name is not "
164+
"valid\"",
165+
TEST_FAIL);
166+
167+
props[2] = CL_CONTEXT_PLATFORM;
168+
props[3] = reinterpret_cast<cl_context_properties>(platform);
169+
ctx = clCreateContextFromType(props, CL_DEVICE_TYPE_DEFAULT, nullptr,
170+
nullptr, &err);
171+
test_object_failure_ret(
172+
ctx, err, CL_INVALID_PROPERTY,
173+
"clCreateContextFromType should return CL_INVALID_PROPERTY when: "
174+
"\"the same property name is specified more than once\"",
175+
TEST_FAIL);
176+
}
177+
178+
int user_data = 1; // Arbitrary non-NULL value
179+
ctx = clCreateContextFromType(nullptr, CL_DEVICE_TYPE_DEFAULT, nullptr,
180+
&user_data, &err);
181+
test_object_failure_ret(
182+
ctx, err, CL_INVALID_VALUE,
183+
"clCreateContextFromType should return CL_INVALID_VALUE when: "
184+
"\"pfn_notify is NULL but user_data is not NULL\"",
185+
TEST_FAIL);
186+
187+
cl_device_type INVALID_DEVICE_TYPE = 0;
188+
ctx = clCreateContextFromType(nullptr, INVALID_DEVICE_TYPE, nullptr,
189+
nullptr, &err);
190+
test_object_failure_ret(
191+
ctx, err, CL_INVALID_DEVICE_TYPE,
192+
"clCreateContextFromType should return CL_INVALID_DEVICE_TYPE when: "
193+
"\"device_type is not a valid value\"",
194+
TEST_FAIL);
195+
196+
std::vector<cl_device_type> device_types = { CL_DEVICE_TYPE_CPU,
197+
CL_DEVICE_TYPE_GPU,
198+
CL_DEVICE_TYPE_ACCELERATOR };
199+
if (get_device_cl_version(device) >= Version(1, 2))
200+
{
201+
device_types.push_back(CL_DEVICE_TYPE_CUSTOM);
202+
}
203+
for (auto type : device_types)
204+
{
205+
clContextWrapper tmp_context =
206+
clCreateContextFromType(nullptr, type, nullptr, nullptr, &err);
207+
if (err != CL_SUCCESS)
208+
{
209+
test_object_failure_ret(
210+
tmp_context, err, CL_DEVICE_NOT_FOUND,
211+
"clCreateContextFromType should return CL_DEVICE_NOT_AVAILABLE "
212+
"when: \"no devices that match device_type and property values "
213+
"specified in properties are currently available\"",
214+
TEST_FAIL);
215+
break;
216+
}
217+
}
218+
219+
return TEST_PASS;
220+
}
221+
222+
/* Negative Tests for clRetainContext */
223+
REGISTER_TEST(negative_retain_context)
224+
{
225+
cl_int err = clRetainContext(nullptr);
226+
test_failure_error_ret(
227+
err, CL_INVALID_CONTEXT,
228+
"clRetainContext should return CL_INVALID_CONTEXT when: \"context is "
229+
"not a valid OpenCL context\" using a nullptr",
230+
TEST_FAIL);
231+
232+
return TEST_PASS;
233+
}
234+
235+
/* Negative Tests for clReleaseContext */
236+
REGISTER_TEST(negative_release_context)
237+
{
238+
cl_int err = clReleaseContext(nullptr);
239+
test_failure_error_ret(
240+
err, CL_INVALID_CONTEXT,
241+
"clReleaseContext should return CL_INVALID_CONTEXT when: \"context is "
242+
"not a valid OpenCL context\" using a nullptr",
243+
TEST_FAIL);
244+
245+
return TEST_PASS;
246+
}
247+
248+
/* Negative Tests for clGetContextInfo */
249+
REGISTER_TEST(negative_get_context_info)
250+
{
251+
252+
cl_uint param_value = 0;
253+
cl_int err = clGetContextInfo(nullptr, CL_CONTEXT_REFERENCE_COUNT,
254+
sizeof(param_value), &param_value, nullptr);
255+
test_failure_error_ret(
256+
err, CL_INVALID_CONTEXT,
257+
"clGetContextInfo should return CL_INVALID_CONTEXT when: \"context is "
258+
"not a valid context\" using a nullptr",
259+
TEST_FAIL);
260+
261+
cl_context_info INVALID_PARAM_VALUE = 0;
262+
err = clGetContextInfo(context, INVALID_PARAM_VALUE, 0, nullptr, nullptr);
263+
test_failure_error_ret(
264+
err, CL_INVALID_VALUE,
265+
"clGetContextInfo should return CL_INVALID_VALUE when: \"param_name is "
266+
"not one of the supported values\"",
267+
TEST_FAIL);
268+
269+
err = clGetContextInfo(context, CL_CONTEXT_REFERENCE_COUNT, 0, &param_value,
270+
nullptr);
271+
test_failure_error_ret(
272+
err, CL_INVALID_VALUE,
273+
"clGetContextInfo should return CL_INVALID_VALUE when: \"size in bytes "
274+
"specified by param_value_size is < size of return type and "
275+
"param_value is not a NULL value\"",
276+
TEST_FAIL);
277+
278+
return TEST_PASS;
279+
}
280+
281+
/* Negative Tests for clSetContextDestructorCallback */
282+
static void CL_CALLBACK callback(cl_context context, void* user_data) {}
283+
284+
REGISTER_TEST_VERSION(negative_set_context_destructor_callback, Version(3, 0))
285+
{
286+
cl_int err = clSetContextDestructorCallback(nullptr, callback, nullptr);
287+
test_failure_error_ret(
288+
err, CL_INVALID_CONTEXT,
289+
"clSetContextDestructorCallback should return CL_INVALID_CONTEXT when: "
290+
"\"context is not a valid context\" using a nullptr",
291+
TEST_FAIL);
292+
293+
err = clSetContextDestructorCallback(context, nullptr, nullptr);
294+
test_failure_error_ret(err, CL_INVALID_VALUE,
295+
"clSetContextDestructorCallback should return "
296+
"CL_INVALID_VALUE when: \"pfn_notify is NULL\"",
297+
TEST_FAIL);
298+
299+
return TEST_PASS;
300+
}

0 commit comments

Comments
 (0)