glsl-array-bounds: set out-of-bounds array index inside shader
[piglit.git] / tests / cl / program / program-tester.c
blobf70497b08493c1cc7880e5acaed51557f2305de1
1 /*
2 * Copyright © 2012 Blaž Tomažič <blaz.tomazic@gmail.com>
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
24 /**
25 * @file program_tester.c
27 * Parser and runner for building programs and executing kernels.
30 #include <stdio.h>
31 #include <inttypes.h>
32 #include <math.h>
33 #include <regex.h>
34 #include <libgen.h>
36 #include "piglit-framework-cl-program.h"
38 /* Regexes */
41 * IMPORTANT:
42 * Watch on subexpressions when modifying regexes, because some of them are
43 * used to retrieve the strings matching them!
47 * Section (section can include whitespace):
48 * <whitespace>[<whitespace>section<whitespace>]<whitespace>
50 #define REGEX_SECTION "^[[:space:]]*\\[[[:space:]]*([[:alnum:]_]+[[:alnum:][:space:]_]*[[:alnum:]_]+|[[:alnum:]_]+)[[:space:]]*\\][[:space:]]*$" /* section */
52 * Key-value (value can have whitespace):
53 * <whitespace>key<whitespace>:<whitespace>value<whitespace>
55 #define REGEX_KEY_VALUE "^[[:space:]]*([[:alnum:]_]+)[[:space:]]*" /* key */ \
56 ":" \
57 "[[:space:]]*([^[:space:]#]+[^#]*[^[:space:]#]+|[^[:space:]#]+)[[:space:]]*$" /* value */
59 * Ignored:
60 * <whitespace>
62 #define REGEX_IGNORE "^[[:space:]]*$"
64 /* Values */
65 #define REGEX_ARRAY_DELIMITER "[[:space:]]+"
66 #define REGEX_DEFINE_ARRAY(element) "((" element REGEX_ARRAY_DELIMITER ")*" element ")"
67 #define REGEX_NAN "(nan|NAN|NaN)"
68 #define REGEX_PNAN "([+]?" REGEX_NAN ")"
69 #define REGEX_NNAN "([-]" REGEX_NAN ")"
70 #define REGEX_INF "(infinity|INFINITY|Infinity|inf|INF|Inf)"
71 #define REGEX_PINF "([+]?" REGEX_INF ")"
72 #define REGEX_NINF "([-]" REGEX_INF ")"
73 #define REGEX_NULL "(NULL|null)"
74 #define REGEX_BOOL "(0|1|false|true)"
75 #define REGEX_BOOL_TRUE "(1|true)"
76 #define REGEX_BOOL_FALSE "(0|false)"
77 #define REGEX_INT "(([+-]?[[:digit:]]+)|([+-]?0[Xx][[:digit:]abcdefABCDEF]+))"
78 #define REGEX_UINT "(([+]?[[:digit:]]+)|([+]?0[Xx][[:digit:]abcdefABCDEF]+))"
79 #define REGEX_FLOAT_HEX "([+-]?0[Xx][[:digit:]abcdefABCDEF.]+[[:digit:]pP+-]*)"
80 #define REGEX_FLOAT "(([+-]?[[:digit:]]+(\\.[[:digit:]]+)?e*[+-]*[[:digit:]]*)|" \
81 REGEX_FLOAT_HEX "|" REGEX_PNAN "|" REGEX_NNAN "|" REGEX_PINF "|" \
82 REGEX_NINF ")"
83 #define REGEX_BOOL_ARRAY REGEX_DEFINE_ARRAY(REGEX_BOOL)
84 #define REGEX_INT_ARRAY REGEX_DEFINE_ARRAY(REGEX_INT)
85 #define REGEX_UINT_ARRAY REGEX_DEFINE_ARRAY(REGEX_UINT)
86 #define REGEX_FLOAT_ARRAY REGEX_DEFINE_ARRAY(REGEX_FLOAT)
87 #define REGEX_VALUE "(" REGEX_NULL "|" REGEX_BOOL "|" REGEX_INT "|" \
88 REGEX_UINT "|" REGEX_FLOAT ")"
89 #define REGEX_ARRAY "(" REGEX_NULL "|" REGEX_BOOL_ARRAY "|" \
90 REGEX_INT_ARRAY "|" REGEX_UINT_ARRAY "|" \
91 REGEX_FLOAT_ARRAY ")"
92 #define REGEX_ARRAY_VALUE "(" REGEX_BOOL "|" REGEX_INT "|" REGEX_UINT "|" \
93 REGEX_FLOAT ")"
94 #define REGEX_RANDOM "(RANDOM|random)"
95 #define REGEX_REPEAT "(REPEAT|repeat)[[:space:]]+" \
96 REGEX_DEFINE_ARRAY(REGEX_ARRAY_VALUE)
98 /* Types */
99 #define REGEX_DEFINE_TYPE(type) type"|"type"2|"type"3|"type"4|"type"8|"type"16"
100 #define REGEX_TYPE_CHAR REGEX_DEFINE_TYPE("char")
101 #define REGEX_TYPE_UCHAR REGEX_DEFINE_TYPE("uchar")
102 #define REGEX_TYPE_SHORT REGEX_DEFINE_TYPE("short")
103 #define REGEX_TYPE_USHORT REGEX_DEFINE_TYPE("ushort")
104 #define REGEX_TYPE_INT REGEX_DEFINE_TYPE("int")
105 #define REGEX_TYPE_UINT REGEX_DEFINE_TYPE("uint")
106 #define REGEX_TYPE_LONG REGEX_DEFINE_TYPE("long")
107 #define REGEX_TYPE_ULONG REGEX_DEFINE_TYPE("ulong")
108 // half is defined as unsigned short and C can't read/write its value.
109 // Also half is only used as a storage format unless device supports
110 // cl_khr_fp16
111 // TODO: probably we could use libmpdec to handle this
112 // http://www.bytereef.org/mpdecimal/index.html
113 //#define REGEX_TYPE_HALF "buffer half[1]"
114 #define REGEX_TYPE_HALF REGEX_DEFINE_TYPE("half")
115 #define REGEX_TYPE_FLOAT REGEX_DEFINE_TYPE("float")
116 #define REGEX_TYPE_DOUBLE REGEX_DEFINE_TYPE("double")
117 #define REGEX_TYPE REGEX_TYPE_CHAR "|" REGEX_TYPE_UCHAR "|" \
118 REGEX_TYPE_SHORT "|" REGEX_TYPE_USHORT "|" \
119 REGEX_TYPE_INT "|" REGEX_TYPE_UINT "|" \
120 REGEX_TYPE_LONG "|" REGEX_TYPE_ULONG "|" \
121 REGEX_TYPE_HALF "|" REGEX_TYPE_FLOAT "|" REGEX_TYPE_DOUBLE
123 /* Image types */
124 /* TODO: add OpenCL 1.2+ types */
125 #define REGEX_IMGT_2D "2D|2d"
126 #define REGEX_IMGT_3D "3D|3d"
127 #define REGEX_IMAGE_TYPE REGEX_IMGT_2D "|" REGEX_IMGT_3D
129 /* Image formats */
130 /* TODO: add OpenCL 2.0 formats */
131 #define REGEX_CHO_R "R|r"
132 #define REGEX_CHO_RX "RX|Rx|rx"
133 #define REGEX_CHO_A "A|a"
134 #define REGEX_CHO_INTENSITY "INTENSITY|intensity"
135 #define REGEX_CHO_LUMINANCE "LUMINANCE|luminance"
136 #define REGEX_CHO_RG "RG|rg"
137 #define REGEX_CHO_RGX "RGX|RGx|rgx"
138 #define REGEX_CHO_RA "RA|ra"
139 #define REGEX_CHO_RGB "RGB|rgb"
140 #define REGEX_CHO_RGBX "RGBX|rgbx"
141 #define REGEX_CHO_RGBA "RGBA|rgba"
142 #define REGEX_CHO_ARGB "ARGB|argb"
143 #define REGEX_CHO_BGRA "BGRA|bgra"
144 #define REGEX_CHANNEL_ORDER REGEX_CHO_R "|" REGEX_CHO_RX "|" REGEX_CHO_A "|" \
145 REGEX_CHO_INTENSITY "|" REGEX_CHO_LUMINANCE "|" \
146 REGEX_CHO_RG "|" REGEX_CHO_RGX "|" \
147 REGEX_CHO_RA "|" REGEX_CHO_RGB "|" \
148 REGEX_CHO_RGBX "|" REGEX_CHO_RGBA "|" \
149 REGEX_CHO_ARGB "|" REGEX_CHO_BGRA
151 #define REGEX_CHT_SNORM_INT8 "SNORM_INT8|snorm_int8"
152 #define REGEX_CHT_SNORM_INT16 "SNORM_INT16|snorm_int16"
153 #define REGEX_CHT_UNORM_INT8 "UNORM_INT8|unorm_int8"
154 #define REGEX_CHT_UNORM_INT16 "UNORM_INT16|unorm_int16"
155 #define REGEX_CHT_UNORM_SHORT_565 "UNORM_SHORT_565|unorm_short_565"
156 #define REGEX_CHT_UNORM_SHORT_555 "UNORM_SHORT_555|unorm_short_555"
157 #define REGEX_CHT_UNORM_INT_101010 "UNORM_INT_101010|unorm_int_101010"
158 #define REGEX_CHT_SIGNED_INT8 "SIGNED_INT8|signed_int8"
159 #define REGEX_CHT_SIGNED_INT16 "SIGNED_INT16|signed_int16"
160 #define REGEX_CHT_SIGNED_INT32 "SIGNED_INT32|signed_int32"
161 #define REGEX_CHT_UNSIGNED_INT8 "UNSIGNED_INT8|unsigned_int8"
162 #define REGEX_CHT_UNSIGNED_INT16 "UNSIGNED_INT16|unsigned_int16"
163 #define REGEX_CHT_UNSIGNED_INT32 "UNSIGNED_INT32|unsigned_int32"
164 #define REGEX_CHT_HALF_FLOAT "HALF_FLOAT|half_float"
165 #define REGEX_CHT_FLOAT "FLOAT|float"
166 #define REGEX_CHANNEL_DATA_TYPE REGEX_CHT_SNORM_INT8 "|" \
167 REGEX_CHT_SNORM_INT16 "|" \
168 REGEX_CHT_UNORM_INT8 "|" \
169 REGEX_CHT_UNORM_INT16 "|" \
170 REGEX_CHT_UNORM_SHORT_565 "|" \
171 REGEX_CHT_UNORM_SHORT_555 "|" \
172 REGEX_CHT_UNORM_INT_101010 "|" \
173 REGEX_CHT_SIGNED_INT8 "|" \
174 REGEX_CHT_SIGNED_INT16 "|" \
175 REGEX_CHT_SIGNED_INT32 "|" \
176 REGEX_CHT_UNSIGNED_INT8 "|" \
177 REGEX_CHT_UNSIGNED_INT16 "|" \
178 REGEX_CHT_UNSIGNED_INT32 "|" \
179 REGEX_CHT_HALF_FLOAT "|" \
180 REGEX_CHT_FLOAT
182 /* Sampler */
183 #define REGEX_SAMP_ADDR_NONE "NONE|none"
184 #define REGEX_SAMP_ADDR_CLAMP_TO_EDGE "CLAMP_TO_EDGE|clamp_to_edge"
185 #define REGEX_SAMP_ADDR_CLAMP "CLAMP|clamp"
186 #define REGEX_SAMP_ADDR_REPEAT "REPEAT|repeat"
187 #define REGEX_SAMP_ADDR_MIRRORED_REPEAT "MIRRORED_REPEAT|mirrored_repeat"
188 #define REGEX_SAMPLER_ADDRESSING_MODE REGEX_SAMP_ADDR_NONE "|"\
189 REGEX_SAMP_ADDR_CLAMP_TO_EDGE "|" \
190 REGEX_SAMP_ADDR_CLAMP "|" \
191 REGEX_SAMP_ADDR_REPEAT "|" \
192 REGEX_SAMP_ADDR_MIRRORED_REPEAT
194 #define REGEX_SAMP_FILT_NEAREST "NEAREST|nearest"
195 #define REGEX_SAMP_FILT_LINEAR "LINEAR|linear"
196 #define REGEX_SAMPLER_FILTER_MODE REGEX_SAMP_FILT_NEAREST "|" \
197 REGEX_SAMP_FILT_LINEAR
200 * Value argument:
201 * index<whitespace>type<whitespace>value
202 * Buffer argument:
203 * index<whitespace>buffer<whitespace>type[size]<whitespace>(value|random|repeat value)<whitespace>tolerance<whitespace>value
204 * Image argument:
205 * index<whitespace>image<whitespace>type<whitespace>
206 * (value|random|repeat value)<whitespace>
207 * image_type<whitespace>(2d|3d)<whitespace>i
208 * image_width<whitespace>value<whitespace>
209 * image_height<whitespace>value<whitespace>
210 * image_channel_order<whitespace>value<whitespace>
211 * image_channel_data_type<whitespace>value<whitespace>
212 * tolerance<whitespace>value
213 * Sampler argument:
214 * index<whitespace>sampler<whitespace>
215 * normalized_coords<whitespace>bool<whitespace>
216 * addressing_mode<whitespace>(none|clamp_to_edge|repeat|mirrored_repeat)<whitespace>
217 * filter_mode<whitespace>(nearest|linear)<whitespace>
219 #define REGEX_DEFINE_ARG(type, value) "([[:digit:]]+)[[:space:]]+" type \
220 "[[:space:]]+(" value ")"
221 #define REGEX_ARG_TOLERANCE "tolerance[[:space:]]+(" REGEX_VALUE ")"
222 #define REGEX_ARG_TOLERANCE_ULP REGEX_ARG_TOLERANCE "[[:space:]]+ulp"
223 #define REGEX_ARG_IMAGE_TYPE "image_type[[:space:]]+(" REGEX_IMAGE_TYPE ")"
224 #define REGEX_ARG_IMAGE_WIDTH "image_width[[:space:]]+(" REGEX_UINT ")"
225 #define REGEX_ARG_IMAGE_HEIGHT "image_height[[:space:]]+(" REGEX_UINT ")"
226 #define REGEX_ARG_IMAGE_CHANNEL_ORDER "image_channel_order[[:space:]]+(" REGEX_CHANNEL_ORDER ")"
227 #define REGEX_ARG_IMAGE_CHANNEL_DATA_TYPE "image_channel_data_type[[:space:]]+(" REGEX_CHANNEL_DATA_TYPE ")"
228 #define REGEX_ARG_SAMPLER_NORMALIZED_COORDS "normalized_coords[[:space:]]+" REGEX_BOOL
229 #define REGEX_ARG_SAMPLER_ADDERSSING_MODE "addressing_mode[[:space:]]+(" REGEX_SAMPLER_ADDRESSING_MODE ")"
230 #define REGEX_ARG_SAMPLER_FILTER_MODE "filter_mode[[:space:]]+(" REGEX_SAMPLER_FILTER_MODE ")"
231 #define REGEX_ARG_VALUE REGEX_DEFINE_ARG( "(" REGEX_TYPE ")", REGEX_ARRAY )
232 #define REGEX_ARG_BUFFER REGEX_DEFINE_ARG( "buffer[[:space:]]+(" REGEX_TYPE ")\\[([[:digit:]]+)\\]", \
233 REGEX_ARRAY "|" REGEX_RANDOM "|" REGEX_REPEAT ) \
234 "([[:space:]]+" "("REGEX_ARG_TOLERANCE "|" REGEX_ARG_TOLERANCE_ULP")" ")?"
235 #define REGEX_ARG_IMAGE REGEX_DEFINE_ARG( "image[[:space:]]+(" REGEX_TYPE ")", \
236 REGEX_ARRAY "|" REGEX_RANDOM "|" REGEX_REPEAT ) \
237 "[[:space:]]+"REGEX_ARG_IMAGE_TYPE \
238 "[[:space:]]+"REGEX_ARG_IMAGE_WIDTH \
239 "[[:space:]]+"REGEX_ARG_IMAGE_HEIGHT \
240 "[[:space:]]+"REGEX_ARG_IMAGE_CHANNEL_ORDER \
241 "[[:space:]]+"REGEX_ARG_IMAGE_CHANNEL_DATA_TYPE \
242 "([[:space:]]+" "("REGEX_ARG_TOLERANCE "|" REGEX_ARG_TOLERANCE_ULP")" ")?"
243 #define REGEX_ARG_SAMPLER "([[:digit:]]+)[[:space:]]+sampler" \
244 "[[:space:]]+"REGEX_ARG_SAMPLER_NORMALIZED_COORDS \
245 "[[:space:]]+"REGEX_ARG_SAMPLER_ADDERSSING_MODE \
246 "[[:space:]]+"REGEX_ARG_SAMPLER_FILTER_MODE
247 #define REGEX_ARG "(" REGEX_ARG_VALUE "|" REGEX_ARG_BUFFER "|" \
248 REGEX_ARG_IMAGE "|" REGEX_ARG_SAMPLER ")"
250 /* Match whole line */
251 #define REGEX_FULL_MATCH(content) "^"content"$"
253 /* Comment config */
254 #define REGEX_COMMENT_CONFIG "/\\*!(.*)!\\*/"
256 /* Other */
257 #define REGEX_LINE "^([^#]*)(#.*)?$"
258 #define REGEX_MULTILINE "^([^#]*)\\\\[[:space:]]*$"
260 /* Config function */
261 void init(const int argc,
262 const char** argv,
263 struct piglit_cl_program_test_config* config);
264 void clean(const int argc,
265 const char** argv,
266 const struct piglit_cl_program_test_config* config);
269 /* Kernel test configuration */
271 // Framework options
272 PIGLIT_CL_PROGRAM_TEST_CONFIG_BEGIN
274 config.init_func = (piglit_cl_test_init_t*)init;
275 config.clean_func = (piglit_cl_test_clean_t*)clean;
277 PIGLIT_CL_PROGRAM_TEST_CONFIG_END
279 // Additional options
280 bool expect_test_fail = false;
281 cl_uint work_dimensions = 1;
282 size_t global_work_size[3] = {1, 1, 1};
283 size_t local_work_size[3] = {1, 1, 1};
284 size_t global_offset[3] = {0, 0, 0};
285 bool local_work_size_null = false;
286 bool global_offset_null = true;
288 /* Helper functions */
290 void
291 add_dynamic_array(void** array,
292 unsigned int* count,
293 size_t element_size,
294 void* data)
296 #define GROW_SIZE 8
297 if(((*count)%GROW_SIZE) == 0) {
298 void* old_array = *array;
300 *array = malloc(((*count)/GROW_SIZE + 1)*GROW_SIZE * element_size);
301 memcpy(*array, old_array, (*count) * element_size);
303 free(old_array);
306 memcpy((char *)(*array) + ((*count)*element_size), data, element_size);
307 (*count)++;
308 #undef GROW_SIZE
311 /* Tests */
313 enum test_arg_type {
314 TEST_ARG_VALUE,
315 TEST_ARG_BUFFER,
316 TEST_ARG_IMAGE,
317 TEST_ARG_SAMPLER
320 enum cl_type {
321 TYPE_CHAR,
322 TYPE_UCHAR,
323 TYPE_SHORT,
324 TYPE_USHORT,
325 TYPE_INT,
326 TYPE_UINT,
327 TYPE_LONG,
328 TYPE_ULONG,
329 TYPE_HALF,
330 TYPE_FLOAT,
331 TYPE_DOUBLE,
334 struct test_arg {
335 enum test_arg_type type;
337 enum cl_type cl_type;
338 size_t cl_size; // 1 for int, 3 for int3
339 size_t cl_mem_size; // 1 for int, 4 for int3
340 size_t length; // for buffers
342 /* kernel arg data */
343 cl_uint index;
344 size_t size;
345 void* value;
347 /* tolerance */
348 int64_t toli;
349 uint64_t tolu;
350 uint64_t ulp;
352 /* image data */
353 piglit_image_desc image_desc;
354 cl_image_format image_format;
356 /* sampler data */
357 cl_bool sampler_normalized_coords;
358 cl_addressing_mode sampler_addressing_mode;
359 cl_filter_mode sampler_filter_mode;
362 struct test_arg create_test_arg()
364 struct test_arg ta = {
365 .type = TEST_ARG_VALUE,
367 .cl_type = TYPE_CHAR,
368 .cl_size = 1,
369 .cl_mem_size = 1,
370 .length = 0,
372 .index = 0,
373 .size = 0,
374 .value = NULL,
376 .toli = 0,
377 .tolu = 0,
378 .ulp = 0,
381 return ta;
384 struct test {
385 char* name;
387 char* kernel_name;
388 cl_uint work_dimensions;
389 size_t global_work_size[3];
390 size_t local_work_size[3];
391 bool local_work_size_null;
392 size_t global_offset[3];
393 bool global_offset_null;
395 bool expect_test_fail;
397 unsigned int num_args_in;
398 struct test_arg* args_in;
400 unsigned int num_args_out;
401 struct test_arg* args_out;
404 unsigned int num_tests = 0;
405 struct test* tests = NULL;
407 struct test create_test()
409 struct test t = {
410 .name = NULL,
412 .kernel_name = NULL,
413 .work_dimensions = work_dimensions,
414 //.global_work_size = global_work_size,
415 //.local_work_size = local_work_size,
416 .local_work_size_null = local_work_size_null,
417 .global_offset_null = global_offset_null,
419 .expect_test_fail = expect_test_fail,
421 .num_args_in = 0,
422 .args_in = NULL,
424 .num_args_out = 0,
425 .args_out = NULL,
428 memcpy(t.global_work_size, global_work_size, sizeof(global_work_size));
429 memcpy(t.local_work_size, local_work_size, sizeof(local_work_size));
430 memcpy(t.global_offset, global_offset, sizeof(global_offset));
432 return t;
435 void
436 add_test(struct test t)
438 add_dynamic_array((void**)&tests, &num_tests, sizeof(struct test), &t);
441 bool
442 add_test_arg(struct test* t, struct test_arg ta, bool arg_in)
444 unsigned i;
445 struct test_arg* this_args;
446 size_t num_this_args;
447 struct test_arg* other_args;
448 size_t num_other_args;
450 if(arg_in) {
451 this_args = t->args_in;
452 num_this_args = t->num_args_in;
453 other_args = t->args_out;
454 num_other_args = t->num_args_out;
455 } else {
456 this_args = t->args_out;
457 num_this_args = t->num_args_out;
458 other_args = t->args_in;
459 num_other_args = t->num_args_in;
462 // Check that argument is new
463 for(i = 0; i < num_this_args; i++) {
464 struct test_arg ta_this = this_args[i];
466 if(ta.index == ta_this.index) {
467 fprintf(stderr,
468 "Invalid configuration, %s argument with index %d is already defined\n",
469 arg_in ? "In" : "Out",
470 ta.index);
471 return false;
474 // Check that types correspond
475 for(i = 0; i < num_other_args; i++) {
476 struct test_arg ta_other = other_args[i];
478 if(ta.index == ta_other.index) {
479 if(ta.type != ta_other.type) {
480 fprintf(stderr,
481 "Invalid configuration, in argument at index %d isn't compatible with out argument\n",
482 ta.index);
483 return false;
485 if(ta.size != ta_other.size) {
486 fprintf(stderr,
487 "Invalid configuration, Size of in argument (%zu) at index %d isn't the same as size of out argument (%zu)\n",
488 arg_in ? ta.size : ta_other.size,
489 ta.index,
490 arg_in ? ta_other.size : ta.size);
491 return false;
496 if(arg_in) {
497 add_dynamic_array((void**)&t->args_in,
498 &t->num_args_in,
499 sizeof(struct test_arg),
500 &ta);
501 } else {
502 add_dynamic_array((void**)&t->args_out,
503 &t->num_args_out,
504 sizeof(struct test_arg),
505 &ta);
508 return true;
511 bool
512 add_test_arg_in(struct test* t, struct test_arg ta)
514 return add_test_arg(t, ta, true);
517 bool
518 add_test_arg_out(struct test* t, struct test_arg ta)
520 return add_test_arg(t, ta, false);
523 void
524 free_tests()
526 unsigned i,j;
528 for(i = 0; i < num_tests; i++) {
529 for(j = 0; j < tests[i].num_args_in; j++) {
530 free(tests[i].args_in[j].value);
532 free(tests[i].args_in);
533 for(j = 0; j < tests[i].num_args_out; j++) {
534 free(tests[i].args_out[j].value);
536 free(tests[i].args_out);
540 /* Strings */
541 unsigned int num_dynamic_strs = 0;
542 char** dynamic_strs = NULL;
544 void
545 add_dynamic_str(char* str)
547 add_dynamic_array((void**)&dynamic_strs, &num_dynamic_strs, sizeof(char*), &str);
550 char*
551 add_dynamic_str_copy(const char* src)
553 char* dst = malloc((strlen(src)+1) * sizeof(char));
555 strcpy(dst, src);
556 add_dynamic_str(dst);
558 return dst;
561 void
562 free_dynamic_strs()
564 if(dynamic_strs != NULL) {
565 unsigned i;
567 for(i = 0; i < num_dynamic_strs; i++) {
568 free(dynamic_strs[i]);
571 free(dynamic_strs);
575 /* Clean */
577 void
578 clean(const int argc,
579 const char** argv,
580 const struct piglit_cl_program_test_config* config)
582 free_dynamic_strs();
583 free_tests();
586 NORETURN void
587 exit_report_result(enum piglit_result result)
589 free_dynamic_strs();
590 free_tests();
591 piglit_report_result(result);
594 /* Regex functions */
596 bool
597 regex_get_matches(const char* src,
598 const char* pattern,
599 regmatch_t* pmatch,
600 size_t size,
601 int cflags)
603 int errcode;
604 regex_t r;
606 /* Build regex */
607 errcode = regcomp(&r, pattern, REG_EXTENDED | cflags);
608 if(errcode) {
609 fprintf(stderr, "Invalid regular expression: '%s'\n", pattern);
610 return false;
613 /* Match regex and if pmatch != NULL && size > 0 return matched */
614 if(pmatch == NULL || size == 0) {
615 errcode = regexec(&r, src, 0, NULL, 0);
616 } else {
617 errcode = regexec(&r, src, size, pmatch, 0);
620 regfree(&r);
622 return errcode == 0;
625 bool
626 regex_get_match_str(char** dst,
627 const char* src,
628 regmatch_t* pmatch,
629 unsigned int index)
631 size_t size = pmatch[index].rm_eo - pmatch[index].rm_so;
633 if(size > 0) {
634 *dst = malloc((size+1) * sizeof(char));
635 strncpy(*dst, src+pmatch[index].rm_so, size);
636 (*dst)[size] = '\0';
638 return true;
641 return false;
644 bool
645 regex_get_str(char** dst,
646 const char* src,
647 const char* pattern,
648 unsigned int index,
649 int cflags)
651 regmatch_t *pmatch = calloc(index+1, sizeof(*pmatch));
652 bool ret = false;
654 if(regex_get_matches(src, pattern, pmatch, index+1, cflags)) {
655 ret = regex_get_match_str(dst, src, pmatch, index);
658 free(pmatch);
659 return ret;
662 bool
663 regex_match(const char* src, const char* pattern)
665 return regex_get_matches(src, pattern, NULL, 0, REG_NEWLINE);
668 bool
669 regex_section(const char* src, char** section)
671 regmatch_t pmatch[2];
673 if(regex_get_matches(src, REGEX_SECTION, pmatch, 2, REG_NEWLINE)) {
674 return regex_get_match_str(section, src, pmatch, 1);
677 return false;
680 bool
681 regex_key_value(const char* src, char** key, char** value)
683 regmatch_t pmatch[3];
685 if(regex_get_matches(src, REGEX_KEY_VALUE, pmatch, 3, REG_NEWLINE)) {
686 *key = NULL;
687 *value = NULL;
688 if( regex_get_match_str(key, src, pmatch, 1)
689 && regex_get_match_str(value, src, pmatch, 2)) {
690 return true;
691 } else {
692 free(*key);
693 free(*value);
697 return false;
700 bool
701 get_bool(const char* src)
703 if(regex_match(src, REGEX_FULL_MATCH(REGEX_BOOL_TRUE))) {
704 return true;
705 } else if(regex_match(src, REGEX_FULL_MATCH(REGEX_BOOL_FALSE))) {
706 return false;
707 } else {
708 fprintf(stderr,
709 "Invalid configuration, could not convert to bool: %s\n",
710 src);
711 exit_report_result(PIGLIT_WARN);
712 return false;
716 int64_t
717 get_int(const char* src)
719 if(regex_match(src, REGEX_FULL_MATCH(REGEX_UINT))) {
720 return strtoull(src, NULL, 0);
721 } else if(regex_match(src, REGEX_FULL_MATCH(REGEX_INT))) {
722 return strtoll(src, NULL, 0);
723 } else {
724 fprintf(stderr,
725 "Invalid configuration, could not convert to long: %s\n",
726 src);
727 exit_report_result(PIGLIT_WARN);
728 return -1;
732 uint64_t
733 get_uint(const char* src)
735 if(regex_match(src, REGEX_FULL_MATCH(REGEX_UINT))) {
736 return strtoull(src, NULL, 0);
737 } else {
738 fprintf(stderr,
739 "Invalid configuration, could not convert to ulong: %s\n",
740 src);
741 exit_report_result(PIGLIT_WARN);
742 return 0;
746 double
747 get_float(const char* src)
749 if(regex_match(src, REGEX_FULL_MATCH(REGEX_FLOAT))) {
750 if(regex_match(src, REGEX_FULL_MATCH(REGEX_PNAN))) {
751 return NAN;
752 } else if(regex_match(src, REGEX_FULL_MATCH(REGEX_NNAN))) {
753 return -NAN;
754 } else if(regex_match(src, REGEX_FULL_MATCH(REGEX_PINF))) {
755 return INFINITY;
756 } else if(regex_match(src, REGEX_FULL_MATCH(REGEX_NINF))) {
757 return -INFINITY;
758 } else {
759 return strtod(src, NULL);
761 } else {
762 fprintf(stderr,
763 "Invalid configuration, could not convert to double: %s\n",
764 src);
765 exit_report_result(PIGLIT_WARN);
766 return 0;
770 size_t
771 get_array_length(const char* src)
773 size_t size = 0;
775 if(regex_match(src, REGEX_FULL_MATCH(REGEX_ARRAY))) {
776 regmatch_t pmatch[1];
778 while(regex_get_matches(src,
779 REGEX_ARRAY_VALUE REGEX_ARRAY_DELIMITER,
780 pmatch,
782 REG_NEWLINE)) {
783 src += pmatch[0].rm_eo;
784 size++;
786 if(regex_match(src, REGEX_ARRAY_VALUE)) {
787 size++;
789 } else {
790 fprintf(stderr,
791 "Invalid configuration, could not convert to an array: %s\n",
792 src);
793 exit_report_result(PIGLIT_WARN);
796 return size;
799 size_t
800 get_array(const char* src, void** array, size_t size, char* array_pattern)
802 bool regex_matched;
803 size_t i = 0;
804 size_t actual_size;
805 char* type;
806 char* value;
807 char* value_pattern;
808 regmatch_t pmatch[2];
810 actual_size = get_array_length(src);
812 if(!strcmp(array_pattern, REGEX_BOOL_ARRAY)) {
813 type = "bool";
814 value_pattern = REGEX_BOOL REGEX_ARRAY_DELIMITER;
815 *(bool**)array = malloc(actual_size * sizeof(bool));
816 regex_matched = regex_match(src, REGEX_FULL_MATCH(REGEX_BOOL_ARRAY));
817 } else if(!strcmp(array_pattern, REGEX_INT_ARRAY)) {
818 type = "long";
819 value_pattern = REGEX_INT REGEX_ARRAY_DELIMITER;
820 *(int64_t**)array = malloc(actual_size * sizeof(int64_t));
821 regex_matched = regex_match(src, REGEX_FULL_MATCH(REGEX_INT_ARRAY));
822 } else if(!strcmp(array_pattern, REGEX_UINT_ARRAY)) {
823 type = "ulong";
824 value_pattern = REGEX_UINT REGEX_ARRAY_DELIMITER;
825 *(uint64_t**)array = malloc(actual_size * sizeof(uint64_t));
826 regex_matched = regex_match(src, REGEX_FULL_MATCH(REGEX_UINT_ARRAY));
827 } else if(!strcmp(array_pattern, REGEX_FLOAT_ARRAY)) {
828 type = "double";
829 value_pattern = REGEX_FLOAT REGEX_ARRAY_DELIMITER;
830 *(double**)array = malloc(actual_size * sizeof(double));
831 regex_matched = regex_match(src, REGEX_FULL_MATCH(REGEX_FLOAT_ARRAY));
832 } else {
833 fprintf(stderr,
834 "Internal error, invalid array pattern: %s\n",
835 array_pattern);
836 exit_report_result(PIGLIT_WARN);
839 if(size > 0 && actual_size != size) {
840 fprintf(stderr,
841 "Invalid configuration, could not convert %s[%zu] to %s[%zu]: %s\n",
842 type, actual_size, type, size, src);
843 exit_report_result(PIGLIT_WARN);
846 if(regex_match(src, REGEX_FULL_MATCH(REGEX_NULL))) {
847 free(*array);
848 *array = NULL;
849 return 0;
852 if(!regex_matched) {
853 fprintf(stderr,
854 "Invalid configuration, could not convert to %s array: %s\n",
855 type, src);
856 exit_report_result(PIGLIT_WARN);
859 while(regex_get_matches(src, value_pattern, pmatch, 2, 0)) {
860 if(regex_get_match_str(&value, src, pmatch, 1)) {
861 if(!strcmp(array_pattern, REGEX_BOOL_ARRAY)) {
862 (*(bool**)array)[i] = get_bool(value);
863 } else if(!strcmp(array_pattern, REGEX_INT_ARRAY)) {
864 (*(int64_t**)array)[i] = get_int(value);
865 } else if(!strcmp(array_pattern, REGEX_UINT_ARRAY)) {
866 (*(uint64_t**)array)[i] = get_uint(value);
867 } else if(!strcmp(array_pattern, REGEX_FLOAT_ARRAY)) {
868 (*(double**)array)[i] = get_float(value);
870 free(value);
871 } else {
872 fprintf(stderr,
873 "Invalid configuration, could not read %s on index %zu: %s\n",
874 type, i, src);
875 exit_report_result(PIGLIT_WARN);
878 src += pmatch[0].rm_eo;
879 i++;
882 if(!strcmp(array_pattern, REGEX_BOOL_ARRAY)) {
883 (*(bool**)array)[i] = get_bool(src);
884 } else if(!strcmp(array_pattern, REGEX_INT_ARRAY)) {
885 (*(int64_t**)array)[i] = get_int(src);
886 } else if(!strcmp(array_pattern, REGEX_UINT_ARRAY)) {
887 (*(uint64_t**)array)[i] = get_uint(src);
888 } else if(!strcmp(array_pattern, REGEX_FLOAT_ARRAY)) {
889 (*(double**)array)[i] = get_float(src);
892 return actual_size;
895 size_t
896 get_bool_array(const char* src, bool** array, size_t size)
898 return get_array(src, (void**)array, size, REGEX_BOOL_ARRAY);
901 size_t
902 get_int_array(const char* src, int64_t** array, size_t size)
904 return get_array(src, (void**)array, size, REGEX_INT_ARRAY);
907 size_t
908 get_uint_array(const char* src, uint64_t** array, size_t size)
910 return get_array(src, (void**)array, size, REGEX_UINT_ARRAY);
913 size_t
914 get_float_array(const char* src, double** array, size_t size)
916 return get_array(src, (void**)array, size, REGEX_FLOAT_ARRAY);
919 /* Help */
921 void
922 print_usage(const int argc, const char** argv)
924 printf("Usage:\n" \
925 " %s [options] CONFIG.program_test\n"
926 " %s [options] [-config CONFIG.program_test] PROGRAM.cl|PROGRAM.bin\n"
927 "\n"
928 "Notes:\n"
929 " - If CONFIG is not specified and PROGRAM has a comment config then a\n"
930 " comment config is used.\n"
931 " - If there is no CONFIG or comment config, then the program is only\n"
932 " tested to build properly.\n",
933 argv[0], argv[0]);
936 void
937 print_usage_and_warn(const int argc, const char** argv, const char* fmt, ...)
939 va_list args;
941 fprintf(stderr, "ERROR: ");
942 va_start(args, fmt);
943 vfprintf(stderr, fmt, args);
944 va_end(args);
946 printf("\n\n");
947 print_usage(argc, argv);
949 exit_report_result(PIGLIT_WARN);
952 /* Parse configuration */
954 size_t
955 get_section_content(const char* src, char** content)
957 size_t size = 0;
958 size_t section_name_length = strcspn(src, "\n\0");
959 regmatch_t pmatch[2];
961 if(src[section_name_length] != '\0') {
962 src += section_name_length+1;
963 } else {
964 src += section_name_length;
967 if(regex_get_matches(src, REGEX_SECTION, pmatch, 2, REG_NEWLINE)) { // found next section
968 size = pmatch[1].rm_so-1;
969 } else { // no next section
970 size = strlen(src);
973 *content = malloc((size+1) * sizeof(char));
974 strncpy(*content, src, size);
975 (*content)[size] = '\0';
977 return size;
980 void
981 get_test_arg_value(struct test_arg* test_arg, const char* value, size_t length)
983 size_t i; // index in array
984 size_t c; // component in element
985 size_t ra; // offset from the beginning of array
986 size_t rb; // offset from the beginning of bufffer
988 int64_t* int_array = NULL;
989 uint64_t* uint_array = NULL;
990 double* float_array = NULL;
992 test_arg->value = malloc(test_arg->size);
995 * We fill the buffer with calculating the right offsets in the buffer (rb)
996 * and in the array (ra). Buffers of type3 have have stride of
997 * 4*sizeof(type) while array has a stride of 3*sizeof(parsed_type).
998 * Also the array index is inside length parameter modulo, so we can fill
999 * the buffer with repeateable values.
1001 #define CASE(enum_type, cl_type, get_func, array) \
1002 case enum_type: \
1003 get_func(value, &array, length); \
1004 for(i = 0; i < test_arg->length; i++) { \
1005 for(c = 0; c < test_arg->cl_size; c++) { \
1006 ra = i*test_arg->cl_size + c; \
1007 rb = i*test_arg->cl_mem_size + c; \
1008 ((cl_type*)test_arg->value)[rb] = convert_##cl_type(array[ra%length]); \
1011 break;
1013 switch(test_arg->cl_type) {
1014 CASE(TYPE_CHAR, cl_char, get_int_array, int_array)
1015 CASE(TYPE_UCHAR, cl_uchar, get_uint_array, uint_array)
1016 CASE(TYPE_SHORT, cl_short, get_int_array, int_array)
1017 CASE(TYPE_USHORT, cl_ushort, get_uint_array, uint_array)
1018 CASE(TYPE_INT, cl_int, get_int_array, int_array)
1019 CASE(TYPE_UINT, cl_uint, get_uint_array, uint_array)
1020 CASE(TYPE_LONG, cl_long, get_int_array, int_array)
1021 CASE(TYPE_ULONG, cl_ulong, get_uint_array, uint_array)
1022 CASE(TYPE_HALF, cl_half, get_float_array, float_array)
1023 CASE(TYPE_FLOAT, cl_float, get_float_array, float_array)
1024 CASE(TYPE_DOUBLE, cl_double, get_float_array, float_array)
1027 #undef CASE
1029 free(int_array);
1030 free(uint_array);
1031 free(float_array);
1034 void
1035 get_test_arg_tolerance(struct test_arg* test_arg, const char* tolerance_str)
1037 regmatch_t pmatch[2];
1038 char* value_str = NULL;
1040 if(regex_get_matches(tolerance_str,
1041 REGEX_ARG_TOLERANCE_ULP,
1042 pmatch,
1044 REG_NEWLINE)) {
1045 regex_get_match_str(&value_str, tolerance_str, pmatch, 1);
1046 switch(test_arg->cl_type) {
1047 case TYPE_HALF:
1048 case TYPE_FLOAT:
1049 case TYPE_DOUBLE:
1050 test_arg->ulp = get_uint(value_str);
1051 return;
1052 default:
1053 fprintf(stderr, "ulp not value for integer types\n");
1054 exit_report_result(PIGLIT_WARN);
1058 if(regex_get_matches(tolerance_str,
1059 REGEX_ARG_TOLERANCE,
1060 pmatch,
1062 REG_NEWLINE)) {
1063 regex_get_match_str(&value_str, tolerance_str, pmatch, 1);
1065 switch(test_arg->cl_type) {
1066 case TYPE_CHAR:
1067 case TYPE_SHORT:
1068 case TYPE_INT:
1069 case TYPE_LONG:
1070 test_arg->toli = get_int(value_str);
1071 break;
1072 case TYPE_UCHAR:
1073 case TYPE_USHORT:
1074 case TYPE_UINT:
1075 case TYPE_ULONG:
1076 test_arg->tolu = get_uint(value_str);
1077 break;
1078 case TYPE_HALF:
1079 case TYPE_FLOAT:
1080 case TYPE_DOUBLE: {
1081 float value = get_float(value_str);
1082 test_arg->ulp = *((uint64_t*)(&value));
1083 break;
1087 free(value_str);
1088 } else {
1089 fprintf(stderr,
1090 "Invalid configuration, could not parse tolerance: %s\n",
1091 tolerance_str);
1092 exit_report_result(PIGLIT_WARN);
1096 void
1097 get_test_arg(const char* src, struct test* test, bool arg_in)
1099 regmatch_t pmatch[5];
1100 char* index_str = NULL;
1101 char* type = NULL;
1102 char* value = NULL;
1103 struct test_arg test_arg = create_test_arg();
1104 bool has_type = true;
1106 /* Get matches */
1107 if(regex_get_matches(src, REGEX_FULL_MATCH(REGEX_ARG_VALUE),
1108 pmatch, 5, REG_NEWLINE)) { // value
1109 // do nothing
1110 } else if(regex_get_matches(src, REGEX_FULL_MATCH(REGEX_ARG_BUFFER),
1111 pmatch, 5, REG_NEWLINE)) { // buffer
1112 // do nothing
1113 } else if(regex_get_matches(src, REGEX_FULL_MATCH(REGEX_ARG_IMAGE),
1114 pmatch, 5, REG_NEWLINE)) { // image
1115 // do nothing
1116 } else if(regex_get_matches(src, REGEX_FULL_MATCH(REGEX_ARG_SAMPLER),
1117 pmatch, 5, REG_NEWLINE)) { // sampler
1118 has_type = false;
1119 } else {
1120 fprintf(stderr,
1121 "Invalid configuration, invalid test argument: %s\n",
1122 src);
1123 exit_report_result(PIGLIT_WARN);
1126 /* Get index */
1127 regex_get_match_str(&index_str, src, pmatch, 1);
1128 test_arg.index = get_int(index_str);
1129 free(index_str);
1131 if(has_type) {
1132 /* Set type, cl_size, cl_mem_size and size (partially for buffers) */
1133 regex_get_match_str(&type, src, pmatch, 2);
1134 if(regex_match(type, "[[:digit:]]+")) {
1135 char* type_size_str;
1136 regex_get_str(&type_size_str, type, "[[:digit:]]+", 0, REG_NEWLINE);
1137 test_arg.cl_size = get_int(type_size_str);
1138 test_arg.cl_mem_size = test_arg.cl_size != 3 ? test_arg.cl_size : 4; // test if we have type3
1139 free(type_size_str);
1140 } else {
1141 test_arg.cl_size = 1;
1142 test_arg.cl_mem_size = 1;
1145 #define IF(regex_type, enum_type, main_type) \
1146 if(regex_match(type, REGEX_FULL_MATCH(regex_type))) { \
1147 test_arg.cl_type = enum_type; \
1148 test_arg.size = sizeof(main_type) * test_arg.cl_mem_size; \
1150 #define ELSEIF(regex_type, enum_type, main_type) \
1151 else IF(regex_type, enum_type, main_type)
1153 IF (REGEX_TYPE_CHAR, TYPE_CHAR, cl_char)
1154 ELSEIF(REGEX_TYPE_UCHAR, TYPE_UCHAR, cl_uchar)
1155 ELSEIF(REGEX_TYPE_SHORT, TYPE_SHORT, cl_short)
1156 ELSEIF(REGEX_TYPE_USHORT, TYPE_USHORT, cl_ushort)
1157 ELSEIF(REGEX_TYPE_INT, TYPE_INT, cl_int)
1158 ELSEIF(REGEX_TYPE_UINT, TYPE_UINT, cl_uint)
1159 ELSEIF(REGEX_TYPE_LONG, TYPE_LONG, cl_long)
1160 ELSEIF(REGEX_TYPE_ULONG, TYPE_ULONG, cl_ulong)
1161 ELSEIF(REGEX_TYPE_HALF, TYPE_HALF, cl_half)
1162 ELSEIF(REGEX_TYPE_FLOAT, TYPE_FLOAT, cl_float)
1163 ELSEIF(REGEX_TYPE_DOUBLE, TYPE_DOUBLE, cl_double)
1165 #undef IF
1166 #undef ELSEIF
1168 free(type);
1171 /* Get arg type, size and value */
1172 if(regex_match(src, REGEX_FULL_MATCH(REGEX_ARG_VALUE))) { // value
1173 /* Values are only allowed for in arguments */
1174 if(!arg_in) {
1175 fprintf(stderr,
1176 "Invalid configuration, only arg_in values are allowed: %s\n",
1177 src);
1178 exit_report_result(PIGLIT_WARN);
1181 /* Set arg type */
1182 test_arg.type = TEST_ARG_VALUE;
1184 /* Set length */
1185 test_arg.length = 1;
1187 /* Get value */
1188 regex_get_match_str(&value, src, pmatch, 3);
1189 if(regex_match(value, REGEX_FULL_MATCH(REGEX_NULL))) {
1190 test_arg.value = NULL;
1191 } else {
1192 get_test_arg_value(&test_arg, value, test_arg.cl_size);
1194 free(value);
1195 } else if(regex_match(src, REGEX_FULL_MATCH(REGEX_ARG_BUFFER))) { // buffer
1196 char* array_length_str = NULL;
1197 const char* tolerance_str = NULL;
1199 /* Set arg type */
1200 test_arg.type = TEST_ARG_BUFFER;
1202 /* Set length */
1203 regex_get_match_str(&array_length_str, src, pmatch, 3);
1204 test_arg.length = get_int(array_length_str);
1205 free(array_length_str);
1207 /* Set size */
1208 test_arg.size = test_arg.size * test_arg.length;
1210 /* Set tolerance */
1211 tolerance_str = src+pmatch[4].rm_eo;
1212 if(regex_match(tolerance_str, REGEX_ARG_TOLERANCE)) {
1213 if(arg_in) {
1214 fprintf(stderr,
1215 "Invalid configuration, in argument buffer can't have tolerance: %s\n",
1216 src);
1217 exit_report_result(PIGLIT_WARN);
1219 get_test_arg_tolerance(&test_arg, tolerance_str);
1222 /* Get value */
1223 regex_get_match_str(&value, src, pmatch, 4);
1224 if(regex_match(value, REGEX_FULL_MATCH(REGEX_NULL))) {
1225 test_arg.value = NULL;
1226 if(!arg_in) {
1227 fprintf(stderr,
1228 "Invalid configuration, out argument buffer value can not be NULL: %s\n",
1229 src);
1230 exit_report_result(PIGLIT_WARN);
1232 } else {
1233 if(regex_match(value, REGEX_FULL_MATCH(REGEX_RANDOM))) {
1234 test_arg.value = malloc(test_arg.size);
1235 if(!arg_in) {
1236 fprintf(stderr,
1237 "Invalid configuration, out argument buffer can not be random: %s\n",
1238 src);
1239 exit_report_result(PIGLIT_WARN);
1241 } else if(regex_match(value, REGEX_FULL_MATCH(REGEX_REPEAT))) {
1242 regmatch_t rmatch[3];
1243 char* repeat_value_str;
1245 regex_get_matches(value, REGEX_REPEAT, rmatch, 3, 0);
1246 regex_get_match_str(&repeat_value_str, value, rmatch, 2);
1248 get_test_arg_value(&test_arg,
1249 repeat_value_str,
1250 get_array_length(repeat_value_str));
1252 free(repeat_value_str);
1253 } else if(regex_match(value, REGEX_ARRAY)) {
1254 get_test_arg_value(&test_arg,
1255 value,
1256 test_arg.length * test_arg.cl_size);
1259 free(value);
1260 } else if(regex_match(src, REGEX_FULL_MATCH(REGEX_ARG_IMAGE))) { // image
1261 char* str = NULL;
1262 const char* properties_str = src + pmatch[3].rm_eo;
1263 const char* tolerance_str = NULL;
1264 size_t image_elems = 0;
1265 cl_channel_order cho;
1266 cl_channel_type cht;
1267 regmatch_t pmatch_prop[2];
1269 /* Set arg type */
1270 test_arg.type = TEST_ARG_IMAGE;
1272 /* Image type */
1273 regex_get_matches(properties_str, REGEX_ARG_IMAGE_TYPE,
1274 pmatch_prop, 2, REG_NEWLINE);
1275 regex_get_match_str(&str, properties_str, pmatch_prop, 1);
1276 properties_str += pmatch_prop[1].rm_eo;
1277 if(regex_match(str, REGEX_FULL_MATCH("("REGEX_IMGT_2D")"))) {
1278 test_arg.image_desc.image_type = CL_MEM_OBJECT_IMAGE2D;
1279 } else {
1280 /* TODO: Implement other image types */
1281 fprintf(stderr, "Image type not supported: %s\n", str);
1282 exit_report_result(PIGLIT_WARN);
1284 free(str);
1286 /* Image width */
1287 regex_get_matches(properties_str, REGEX_ARG_IMAGE_WIDTH,
1288 pmatch_prop, 2, REG_NEWLINE);
1289 regex_get_match_str(&str, properties_str, pmatch_prop, 1);
1290 properties_str += pmatch_prop[1].rm_eo;
1291 test_arg.image_desc.image_width = get_int(str);
1292 free(str);
1294 /* Image height */
1295 regex_get_matches(properties_str, REGEX_ARG_IMAGE_HEIGHT,
1296 pmatch_prop, 2, REG_NEWLINE);
1297 regex_get_match_str(&str, properties_str, pmatch_prop, 1);
1298 properties_str += pmatch_prop[1].rm_eo;
1299 test_arg.image_desc.image_height = get_int(str);
1300 free(str);
1302 /* Image descriptor defaults */
1303 test_arg.image_desc.image_depth = 1;
1304 test_arg.image_desc.image_array_size = 1;
1305 test_arg.image_desc.image_row_pitch = 0;
1306 test_arg.image_desc.image_slice_pitch = 0;
1307 test_arg.image_desc.num_mip_levels = 0;
1308 test_arg.image_desc.num_samples = 0;
1309 test_arg.image_desc.buffer = NULL;
1311 /* Image channel order */
1312 regex_get_matches(properties_str, REGEX_ARG_IMAGE_CHANNEL_ORDER,
1313 pmatch_prop, 2, REG_NEWLINE);
1314 regex_get_match_str(&str, properties_str, pmatch_prop, 1);
1315 properties_str += pmatch_prop[1].rm_eo;
1316 if(regex_match(str, REGEX_FULL_MATCH("("REGEX_CHO_R")"))) {
1317 cho = CL_R;
1318 } else if(regex_match(str, REGEX_FULL_MATCH("("REGEX_CHO_RX")"))) {
1319 cho = CL_Rx;
1320 } else if(regex_match(str, REGEX_FULL_MATCH("("REGEX_CHO_A")"))) {
1321 cho = CL_A;
1322 } else if(regex_match(str, REGEX_FULL_MATCH("("REGEX_CHO_INTENSITY")"))) {
1323 cho = CL_INTENSITY;
1324 } else if(regex_match(str, REGEX_FULL_MATCH("("REGEX_CHO_LUMINANCE")"))) {
1325 cho = CL_LUMINANCE;
1326 } else if(regex_match(str, REGEX_FULL_MATCH("("REGEX_CHO_RG")"))) {
1327 cho = CL_RG;
1328 } else if(regex_match(str, REGEX_FULL_MATCH("("REGEX_CHO_RGX")"))) {
1329 cho = CL_RGx;
1330 } else if(regex_match(str, REGEX_FULL_MATCH("("REGEX_CHO_RA")"))) {
1331 cho = CL_RA;
1332 } else if(regex_match(str, REGEX_FULL_MATCH("("REGEX_CHO_RGB")"))) {
1333 cho = CL_RGB;
1334 } else if(regex_match(str, REGEX_FULL_MATCH("("REGEX_CHO_RGBX")"))) {
1335 cho = CL_RGBx;
1336 } else if(regex_match(str, REGEX_FULL_MATCH("("REGEX_CHO_RGBA")"))) {
1337 cho = CL_RGBA;
1338 } else if(regex_match(str, REGEX_FULL_MATCH("("REGEX_CHO_ARGB")"))) {
1339 cho = CL_ARGB;
1340 } else if(regex_match(str, REGEX_FULL_MATCH("("REGEX_CHO_BGRA")"))) {
1341 cho = CL_BGRA;
1342 } else {
1343 fprintf(stderr, "Image channel order not supported: %s\n", str);
1344 exit_report_result(PIGLIT_WARN);
1346 free(str);
1347 test_arg.image_format.image_channel_order = cho;
1349 /* Image channel data type */
1350 regex_get_matches(properties_str, REGEX_ARG_IMAGE_CHANNEL_DATA_TYPE,
1351 pmatch_prop, 2, REG_NEWLINE);
1352 regex_get_match_str(&str, properties_str, pmatch_prop, 1);
1353 properties_str += pmatch_prop[1].rm_eo;
1354 if(regex_match(str, REGEX_FULL_MATCH("("REGEX_CHT_SNORM_INT8")"))) {
1355 cht = CL_SNORM_INT8;
1356 } else if(regex_match(str, REGEX_FULL_MATCH("("REGEX_CHT_SNORM_INT16")"))) {
1357 cht = CL_SNORM_INT16;
1358 } else if(regex_match(str, REGEX_FULL_MATCH("("REGEX_CHT_UNORM_INT8")"))) {
1359 cht = CL_UNORM_INT8;
1360 } else if(regex_match(str, REGEX_FULL_MATCH("("REGEX_CHT_UNORM_INT16")"))) {
1361 cht = CL_UNORM_INT16;
1362 } else if(regex_match(str, REGEX_FULL_MATCH("("REGEX_CHT_UNORM_SHORT_565")"))) {
1363 cht = CL_UNORM_SHORT_565;
1364 } else if(regex_match(str, REGEX_FULL_MATCH("("REGEX_CHT_UNORM_SHORT_555")"))) {
1365 cht = CL_UNORM_SHORT_555;
1366 } else if(regex_match(str, REGEX_FULL_MATCH("("REGEX_CHT_UNORM_INT_101010")"))) {
1367 cht = CL_UNORM_INT_101010;
1368 } else if(regex_match(str, REGEX_FULL_MATCH("("REGEX_CHT_SIGNED_INT8")"))) {
1369 cht = CL_SIGNED_INT8;
1370 } else if(regex_match(str, REGEX_FULL_MATCH("("REGEX_CHT_SIGNED_INT16")"))) {
1371 cht = CL_SIGNED_INT16;
1372 } else if(regex_match(str, REGEX_FULL_MATCH("("REGEX_CHT_SIGNED_INT32")"))) {
1373 cht = CL_SIGNED_INT32;
1374 } else if(regex_match(str, REGEX_FULL_MATCH("("REGEX_CHT_UNSIGNED_INT8")"))) {
1375 cht = CL_UNSIGNED_INT8;
1376 } else if(regex_match(str, REGEX_FULL_MATCH("("REGEX_CHT_UNSIGNED_INT16")"))) {
1377 cht = CL_UNSIGNED_INT16;
1378 } else if(regex_match(str, REGEX_FULL_MATCH("("REGEX_CHT_UNSIGNED_INT32")"))) {
1379 cht = CL_UNSIGNED_INT32;
1380 } else if(regex_match(str, REGEX_FULL_MATCH("("REGEX_CHT_HALF_FLOAT")"))) {
1381 cht = CL_HALF_FLOAT;
1382 } else if(regex_match(str, REGEX_FULL_MATCH("("REGEX_CHT_FLOAT")"))) {
1383 cht = CL_FLOAT;
1384 } else {
1385 fprintf(stderr, "Image channel data type not supported: %s\n", str);
1386 exit_report_result(PIGLIT_WARN);
1388 free(str);
1389 test_arg.image_format.image_channel_data_type = cht;
1391 /* Set size */
1392 image_elems = test_arg.image_desc.image_width *
1393 test_arg.image_desc.image_height *
1394 test_arg.image_desc.image_depth *
1395 test_arg.image_desc.image_array_size;
1396 test_arg.length = image_elems;
1397 test_arg.size *= image_elems;
1399 /* Set tolerance */
1400 tolerance_str = properties_str;
1401 if(regex_match(tolerance_str, REGEX_ARG_TOLERANCE)) {
1402 if(arg_in) {
1403 fprintf(stderr,
1404 "Invalid configuration, in argument buffer can't have tolerance: %s\n",
1405 src);
1406 exit_report_result(PIGLIT_WARN);
1408 get_test_arg_tolerance(&test_arg, tolerance_str);
1411 /* Get value */
1412 regex_get_match_str(&value, src, pmatch, 3);
1413 if(regex_match(value, REGEX_FULL_MATCH(REGEX_NULL))) {
1414 test_arg.value = NULL;
1415 if(!arg_in) {
1416 fprintf(stderr,
1417 "Invalid configuration, out argument buffer value can not be NULL: %s\n",
1418 src);
1419 exit_report_result(PIGLIT_WARN);
1421 } else {
1422 if(regex_match(value, REGEX_FULL_MATCH(REGEX_RANDOM))) {
1423 test_arg.value = malloc(test_arg.size);
1424 if(!arg_in) {
1425 fprintf(stderr,
1426 "Invalid configuration, out argument buffer can not be random: %s\n",
1427 src);
1428 exit_report_result(PIGLIT_WARN);
1430 } else if(regex_match(value, REGEX_FULL_MATCH(REGEX_REPEAT))) {
1431 regmatch_t rmatch[3];
1432 char* repeat_value_str;
1434 regex_get_matches(value, REGEX_REPEAT, rmatch, 3, 0);
1435 regex_get_match_str(&repeat_value_str, value, rmatch, 2);
1437 get_test_arg_value(&test_arg,
1438 repeat_value_str,
1439 get_array_length(repeat_value_str));
1441 free(repeat_value_str);
1442 } else if(regex_match(value, REGEX_ARRAY)) {
1443 get_test_arg_value(&test_arg, value,
1444 image_elems * test_arg.cl_size);
1447 free(value);
1449 } else if(regex_match(src, REGEX_FULL_MATCH(REGEX_ARG_SAMPLER))) { // sampler
1450 char* str = NULL;
1452 /* Samplers are only allowed for in arguments */
1453 if(!arg_in) {
1454 fprintf(stderr,
1455 "Invalid configuration, only arg_in samplers are allowed: %s\n",
1456 src);
1457 exit_report_result(PIGLIT_WARN);
1460 test_arg.size = sizeof(cl_sampler);
1462 /* Set arg type */
1463 test_arg.type = TEST_ARG_SAMPLER;
1465 /* Normalized coords */
1466 regex_get_match_str(&str, src, pmatch, 2);
1467 test_arg.sampler_normalized_coords = get_bool(str);
1468 free(str);
1470 /* Addressing mode */
1471 regex_get_match_str(&str, src, pmatch, 3);
1472 if(regex_match(str, REGEX_FULL_MATCH("("REGEX_SAMP_ADDR_NONE")"))) {
1473 test_arg.sampler_addressing_mode = CL_ADDRESS_NONE;
1474 } else if(regex_match(str, REGEX_FULL_MATCH("("REGEX_SAMP_ADDR_CLAMP_TO_EDGE")"))) {
1475 test_arg.sampler_addressing_mode = CL_ADDRESS_CLAMP_TO_EDGE;
1476 } else if(regex_match(str, REGEX_FULL_MATCH("("REGEX_SAMP_ADDR_CLAMP")"))) {
1477 test_arg.sampler_addressing_mode = CL_ADDRESS_CLAMP;
1478 } else if(regex_match(str, REGEX_FULL_MATCH("("REGEX_SAMP_ADDR_REPEAT))) {
1479 test_arg.sampler_addressing_mode = CL_ADDRESS_REPEAT;
1480 } else if(regex_match(str, REGEX_FULL_MATCH("("REGEX_SAMP_ADDR_MIRRORED_REPEAT))) {
1481 test_arg.sampler_addressing_mode = CL_ADDRESS_MIRRORED_REPEAT;
1482 } else {
1483 fprintf(stderr, "Sampler addressing mode not supported: %s\n", str);
1484 exit_report_result(PIGLIT_WARN);
1486 free(str);
1488 /* Filter mode */
1489 regex_get_match_str(&str, src, pmatch, 4);
1490 if(regex_match(str, REGEX_FULL_MATCH("("REGEX_SAMP_FILT_NEAREST")"))) {
1491 test_arg.sampler_filter_mode = CL_FILTER_NEAREST;
1492 } else if(regex_match(str, REGEX_FULL_MATCH("("REGEX_SAMP_FILT_LINEAR")"))) {
1493 test_arg.sampler_filter_mode = CL_FILTER_LINEAR;
1494 } else {
1495 fprintf(stderr, "Sampler filter mode not supported: %s\n", str);
1496 exit_report_result(PIGLIT_WARN);
1498 free(str);
1501 if(arg_in) {
1502 if(!add_test_arg_in(test, test_arg)) {
1503 fprintf(stderr,
1504 "Invalid configuration, could not add in argument: %s\n",
1505 src);
1506 exit_report_result(PIGLIT_WARN);
1508 } else {
1509 if(!add_test_arg_out(test, test_arg)) {
1510 fprintf(stderr,
1511 "Invalid configuration, could not add out argument: %s\n",
1512 src);
1513 exit_report_result(PIGLIT_WARN);
1519 * Helper function for parsing a test name and checking for illegal characters.
1521 static char*
1522 parse_name(const char *input)
1524 char *name = add_dynamic_str_copy(input);
1525 int error;
1526 regex_t regex;
1527 regmatch_t pmatch[1];
1530 if ((error = regcomp(&regex, "\\([/%]\\)",0))) {
1531 char errbuf[100];
1532 regerror(error, &regex, errbuf, 100);
1533 fprintf(stderr, "Failed to compile regex for parse_name():%s\n", errbuf);
1534 return NULL;
1537 if (!regexec(&regex, input, 1, pmatch, 0)) {
1538 char bad_char = *(input + pmatch[0].rm_so);
1539 fprintf(stderr, "Illegal character in test name '%s': %c\n",
1540 input, bad_char);
1541 return NULL;
1544 regfree(&regex);
1545 return name;
1548 void
1549 parse_config(const char* config_str,
1550 struct piglit_cl_program_test_config* config)
1552 const char* pch;
1553 size_t length = strlen(config_str);
1555 char* line = NULL;
1556 char* section = NULL;
1557 char* key = NULL;
1558 char* value = NULL;
1560 struct test* test = NULL;
1562 bool config_found = false;
1563 bool test_found = false;
1565 enum state_t {
1566 SECTION_NONE,
1567 SECTION_CONFIG,
1568 SECTION_TEST,
1569 } state = SECTION_NONE;
1571 /* parse config string by each line */
1572 pch = config_str;
1573 while(pch < (config_str+length)) {
1574 regmatch_t pmatch[2];
1575 size_t line_length;
1577 /* Get line */
1578 regex_get_matches(pch, REGEX_LINE, pmatch, 2, REG_NEWLINE);
1579 line_length = pmatch[0].rm_eo - pmatch[0].rm_so;
1580 if(!regex_get_match_str(&line, pch, pmatch, 1)) {
1581 /* Line is empty */
1582 pch += line_length + 1;
1583 continue;
1586 /* Get more lines if it is a multiline */
1587 if( regex_match(line, REGEX_KEY_VALUE)
1588 && regex_match(line, REGEX_MULTILINE)) {
1589 char* multiline = malloc(sizeof(char));
1590 multiline[0] = '\0';
1592 free(line); line = NULL;
1594 while((pch <= (config_str+length))) {
1595 regmatch_t mmatch[2];
1596 char* old_multiline = multiline;
1597 char* new_multiline;
1599 /* Get line */
1600 regex_get_matches(pch, REGEX_LINE, pmatch, 2, REG_NEWLINE);
1601 line_length = pmatch[0].rm_eo - pmatch[0].rm_so;
1602 if(!regex_get_match_str(&line, pch, pmatch, 1)) {
1603 /* Line is empty */
1604 break;
1607 if(regex_match(line, REGEX_MULTILINE)) { // not last line
1608 regex_get_matches(line, REGEX_MULTILINE,
1609 mmatch, 2, REG_NEWLINE);
1610 if(!regex_get_match_str(&new_multiline, pch, mmatch, 1)) {
1611 /* Multiline is empty */
1612 pch += line_length + 1;
1613 continue;
1616 multiline = malloc(strlen(old_multiline) + strlen(new_multiline) + 1);
1617 strncpy(multiline, old_multiline, strlen(old_multiline));
1618 strcpy(multiline+strlen(old_multiline), new_multiline);
1620 pch += line_length+1;
1622 free(line); free(old_multiline); free(new_multiline);
1623 } else { // last line
1624 multiline = malloc(strlen(old_multiline) + strlen(line) + 1);
1625 strncpy(multiline, old_multiline, strlen(old_multiline));
1626 strcpy(multiline+strlen(old_multiline), line);
1628 free(line); free(old_multiline);
1629 break;
1633 line = multiline;
1636 /* parse line */
1637 if(regex_section(line, &section)) { // SECTION
1638 if(regex_match(section, "^config$")) { // config
1639 if(config_found) {
1640 fprintf(stderr, "Invalid configuration, [config] section can be defined only once\n");
1641 free(section); section = NULL;
1642 exit_report_result(PIGLIT_WARN);
1644 if(test_found) {
1645 fprintf(stderr, "Invalid configuration, [config] section must be declared before any [test] section\n");
1646 free(section); section = NULL;
1647 exit_report_result(PIGLIT_WARN);
1649 config_found = true;
1650 state = SECTION_CONFIG;
1651 } else if(regex_match(section, "^test$")) { // test
1652 if(!config_found) {
1653 fprintf(stderr, "Invalid configuration, [config] section must be declared before any [test] section\n");
1654 free(section); section = NULL;
1655 exit_report_result(PIGLIT_WARN);
1657 if(config->expect_build_fail) {
1658 fprintf(stderr, "Invalid configuration, no tests can be defined when expect_build_fail is true\n");
1659 free(section); section = NULL;
1660 exit_report_result(PIGLIT_WARN);
1662 test_found = true;
1663 add_test(create_test());
1664 test = &tests[num_tests-1];
1665 state = SECTION_TEST;
1666 } else if(regex_match(section, "^program source$")) { // program source
1667 pch += get_section_content(pch, &config->program_source);
1668 add_dynamic_str(config->program_source);
1669 state = SECTION_NONE;
1670 } else if(regex_match(section, "^program binary$")) { // program binary
1671 pch += get_section_content(pch, (char**)&config->program_binary);
1672 add_dynamic_str((char*)config->program_binary);
1673 state = SECTION_NONE;
1674 } else {
1675 fprintf(stderr,
1676 "Invalid configuration, configuration has an invalid section: [%s]\n",
1677 section);
1678 free(section); section = NULL;
1679 exit_report_result(PIGLIT_WARN);
1682 free(section); section = NULL;
1683 } else if(regex_key_value(line, &key, &value)) { // KEY : VALUE
1684 switch(state) {
1685 case SECTION_NONE:
1686 fprintf(stderr,
1687 "Invalid configuration, this key-value does not belong to any section: %s\n",
1688 line);
1689 free(key); key = NULL;
1690 free(value); value = NULL;
1691 exit_report_result(PIGLIT_WARN);
1692 break;
1693 case SECTION_CONFIG:
1694 if(regex_match(key, "^name$")) {
1695 config->name = parse_name(value);
1696 if (!config->name) {
1697 exit_report_result(PIGLIT_FAIL);
1699 } else if(regex_match(key, "^clc_version_min$")) {
1700 config->clc_version_min = get_int(value);
1701 } else if(regex_match(key, "clc_version_max$")) {
1702 config->clc_version_max = get_int(value);
1703 } else if(regex_match(key, "^platform_regex$")) {
1704 config->platform_regex = add_dynamic_str_copy(value);
1705 } else if(regex_match(key, "^device_regex$")) {
1706 config->device_regex = add_dynamic_str_copy(value);
1707 } else if(regex_match(key, "^require_platform_extensions$")) {
1708 config->require_platform_extensions =
1709 add_dynamic_str_copy(value);
1710 } else if(regex_match(key, "^require_device_extensions$")) {
1711 config->require_device_extensions =
1712 add_dynamic_str_copy(value);
1713 } else if(regex_match(key, "^program_source_file$")) {
1714 config->program_source_file = add_dynamic_str_copy(value);
1715 } else if(regex_match(key, "^program_binary_file$")) {
1716 config->program_binary_file = add_dynamic_str_copy(value);
1717 } else if(regex_match(key, "^build_options$")) {
1718 config->build_options = add_dynamic_str_copy(value);
1719 } else if(regex_match(key, "^kernel_name$")) {
1720 if(!regex_match(value, REGEX_NULL)) {
1721 config->kernel_name = add_dynamic_str_copy(value);
1722 } else {
1723 config->kernel_name = NULL;
1725 } else if(regex_match(key, "^expect_build_fail$")) {
1726 config->expect_build_fail = get_bool(value);
1727 } else if(regex_match(key, "^expect_test_fail$")) {
1728 expect_test_fail = get_bool(value);
1729 } else if(regex_match(key, "^need_image_support$")) {
1730 config->need_image_support = get_bool(value);
1731 } else if(regex_match(key, "^dimensions$")) {
1732 work_dimensions = get_uint(value);
1733 } else if(regex_match(key, "^global_size$")) {
1734 int i;
1735 uint64_t* int_global_work_size;
1736 get_uint_array(value, &int_global_work_size, 3);
1737 for(i = 0; i < 3; i++) {
1738 global_work_size[i] = int_global_work_size[i];
1740 free(int_global_work_size);
1741 } else if(regex_match(key, "^local_size$")) {
1742 if(!regex_match(value, REGEX_FULL_MATCH(REGEX_NULL))) {
1743 int i;
1744 uint64_t* int_local_work_size;
1745 get_uint_array(value, &int_local_work_size, 3);
1746 for(i = 0; i < 3; i++) {
1747 local_work_size[i] = int_local_work_size[i];
1749 local_work_size_null = false;
1750 free(int_local_work_size);
1751 } else {
1752 local_work_size_null = true;
1754 } else if(regex_match(key, "^global_offset$")) {
1755 if(!regex_match(value, REGEX_FULL_MATCH(REGEX_NULL))) {
1756 int i;
1757 uint64_t* int_global_offset;
1758 get_uint_array(value, &int_global_offset, 3);
1759 for(i = 0; i < 3; i++) {
1760 global_offset[i] = int_global_offset[i];
1762 global_offset_null = false;
1763 free(int_global_offset);
1764 } else {
1765 global_offset_null = true;
1767 } else {
1768 fprintf(stderr,
1769 "Invalid configuration, key '%s' does not belong to a [config] section: %s\n",
1770 key, line);
1771 free(key); key = NULL;
1772 free(value); value = NULL;
1773 exit_report_result(PIGLIT_WARN);
1775 break;
1776 case SECTION_TEST:
1777 if(regex_match(key, "^name$")) {
1778 test->name = parse_name(value);
1779 if (!test->name) {
1780 exit_report_result(PIGLIT_FAIL);
1782 } else if(regex_match(key, "^kernel_name$")) {
1783 test->kernel_name = add_dynamic_str_copy(value); // test can't have kernel_name == NULL like config section
1784 } else if(regex_match(key, "^expect_test_fail$")) {
1785 test->expect_test_fail = get_bool(value);
1786 } else if(regex_match(key, "^dimensions$")) {
1787 test->work_dimensions = get_uint(value);
1788 } else if(regex_match(key, "^global_size$")) {
1789 int i;
1790 uint64_t* int_global_work_size;
1791 get_uint_array(value, &int_global_work_size, 3);
1792 for(i = 0; i < 3; i++) {
1793 test->global_work_size[i] = int_global_work_size[i];
1795 free(int_global_work_size);
1796 } else if(regex_match(key, "^local_size$")) {
1797 if(!regex_match(value, REGEX_FULL_MATCH(REGEX_NULL))) {
1798 int i;
1799 uint64_t* int_local_work_size;
1800 get_uint_array(value, &int_local_work_size, 3);
1801 for(i = 0; i < 3; i++) {
1802 test->local_work_size[i] = int_local_work_size[i];
1804 test->local_work_size_null = false;
1805 free(int_local_work_size);
1806 } else {
1807 test->local_work_size_null = true;
1809 } else if(regex_match(key, "^global_offset$")) {
1810 if(!regex_match(value, REGEX_FULL_MATCH(REGEX_NULL))) {
1811 int i;
1812 uint64_t* int_global_offset;
1813 get_uint_array(value, &int_global_offset, 3);
1814 for(i = 0; i < 3; i++) {
1815 test->global_offset[i] = int_global_offset[i];
1817 test->global_offset_null = false;
1818 free(int_global_offset);
1819 } else {
1820 test->global_offset_null = true;
1822 } else if(regex_match(key, "^arg_in$")) {
1823 get_test_arg(value, test, true);
1824 } else if(regex_match(key, "^arg_out$")) {
1825 get_test_arg(value, test, false);
1826 } else {
1827 fprintf(stderr,
1828 "Invalid configuration, key '%s' does not belong to a [test] section: %s\n",
1829 key, line);
1830 free(key); key = NULL;
1831 free(value); value = NULL;
1832 exit_report_result(PIGLIT_WARN);
1834 break;
1837 free(key); key = NULL;
1838 free(value); value = NULL;
1839 } else if(!regex_match(line, REGEX_IGNORE)){ // not WHITESPACE or COMMENT
1840 fprintf(stderr,
1841 "Invalid configuration, configuration could not be parsed: %s\n",
1842 line);
1843 exit_report_result(PIGLIT_WARN);
1846 /* Go to next line */
1847 free(line); line = NULL;
1848 pch += line_length+1;
1851 if(!config_found) {
1852 fprintf(stderr, "Invalid configuration, configuration is missing a [config] section.\n");
1853 exit_report_result(PIGLIT_WARN);
1857 /* Get configuration from comment */
1859 char*
1860 get_comment_config_str(const char* src)
1862 char* config_str = NULL;
1863 regmatch_t pmatch[2];
1865 if(regex_get_matches(src, REGEX_COMMENT_CONFIG, pmatch, 2, 0)) {
1866 if(regex_get_match_str(&config_str, src, pmatch, 1)) {
1867 return config_str;
1871 return NULL;
1874 /* Init */
1876 void
1877 init(const int argc,
1878 const char** argv,
1879 struct piglit_cl_program_test_config* config)
1881 const char * main_argument = piglit_cl_get_unnamed_arg(argc, argv, 0);
1882 const char * config_file = NULL;
1884 char* config_str = NULL;
1885 unsigned int config_str_size;
1886 bool config_arg_present = piglit_cl_is_arg_defined(argc, argv, "config");
1888 enum main_argument_type_t {
1889 ARG_CONFIG,
1890 ARG_SOURCE,
1891 ARG_BINARY
1892 } main_argument_type;
1894 FILE* temp_file;
1896 int program_count = 0;
1898 /* Check if arguments are valid */
1899 // valid main argument
1900 if(main_argument == NULL) {
1901 if(argc == 1) {
1902 print_usage(argc, argv);
1903 exit_report_result(PIGLIT_WARN);
1904 } else {
1905 print_usage_and_warn(argc, argv, "No main argument.");
1908 if(!regex_match(main_argument, "\\.(cl|program_test|bin)$")) {
1909 print_usage_and_warn(argc, argv, "Invalid main argument.");
1911 temp_file = fopen(main_argument, "r");
1912 if(temp_file == NULL) {
1913 print_usage_and_warn(argc, argv, "%s does not exist.", main_argument);
1915 fclose(temp_file);
1916 // valid config argument
1917 if(config_arg_present) {
1918 config_file = piglit_cl_get_arg_value(argc, argv, "config");
1919 if(!regex_match(config_file, "\\.program_test$")) {
1920 print_usage_and_warn(argc, argv, "Invalid config argument.");
1922 temp_file = fopen(config_file, "r");
1923 if(temp_file == NULL) {
1924 print_usage_and_warn(argc, argv, "%s does not exist.", config_file);
1926 fclose(temp_file);
1928 // no config argument if using .program_test
1929 if(regex_match(main_argument, "\\.program_test$") && config_arg_present) {
1930 print_usage_and_warn(argc,
1931 argv,
1932 "Cannot use config argument if main argument is already a config file.");
1935 /* Get main_argument type and config string */
1936 if(regex_match(main_argument, "\\.program_test$")) {
1937 main_argument_type = ARG_CONFIG;
1939 config_file = main_argument;
1940 config_str = piglit_load_text_file(config_file, &config_str_size);
1941 } else if(regex_match(main_argument, "\\.cl$")) {
1942 main_argument_type = ARG_SOURCE;
1944 if(config_arg_present) {
1945 config_file = piglit_cl_get_arg_value(argc, argv, "config");
1946 config_str = piglit_load_text_file(config_file, &config_str_size);
1947 } else {
1948 char* source_str;
1950 config_file = main_argument;
1951 source_str = piglit_load_text_file(config_file, &config_str_size);
1952 config_str = get_comment_config_str(source_str);
1954 free(source_str);
1956 } else if(regex_match(main_argument, "\\.bin$")) {
1957 main_argument_type = ARG_BINARY;
1959 config_file = piglit_cl_get_arg_value(argc, argv, "config");
1960 config_str = piglit_load_text_file(config_file, &config_str_size);
1961 } else {
1962 fprintf(stderr, "Ops, this should not happen!\n");
1963 exit_report_result(PIGLIT_WARN);
1966 /* Parse test configuration */
1967 if(config_str != NULL) {
1968 parse_config(config_str, config);
1969 free(config_str);
1970 } else {
1971 fprintf(stderr, "No configuration found.\n");
1974 /* Set program */
1975 switch(main_argument_type) {
1976 case ARG_CONFIG:
1977 if( config->program_source_file != NULL
1978 || config->program_binary_file != NULL) {
1979 const char* program_file = NULL;
1980 char* main_arg_copy = NULL;
1981 char* dname = NULL;
1982 char* full_path_file = NULL;
1984 if(config->program_source_file != NULL) {
1985 program_file = config->program_source_file;
1986 } else {
1987 program_file = config->program_binary_file;
1990 main_arg_copy = strdup(main_argument);
1991 dname = dirname(main_arg_copy);
1992 full_path_file = malloc(strlen(dname) + strlen(program_file) + 2); // +2 for '/' and '\0'
1993 strcpy(full_path_file, dname);
1994 full_path_file[strlen(dname)] = '/';
1995 strcpy(full_path_file+strlen(dname)+1, program_file);
1997 if(config->program_source_file != NULL) {
1998 config->program_source_file = full_path_file;
1999 } else {
2000 config->program_binary_file = full_path_file;
2003 add_dynamic_str(full_path_file);
2004 free(main_arg_copy);
2006 break;
2007 case ARG_SOURCE:
2008 config->program_source_file = add_dynamic_str_copy(main_argument);
2009 break;
2010 case ARG_BINARY:
2011 config->program_binary_file = add_dynamic_str_copy(main_argument);
2012 break;
2015 /* Check if there is one program_* set */
2016 if(config->program_source != NULL) program_count++;
2017 if(config->program_source_file != NULL) program_count++;
2018 if(config->program_binary != NULL) program_count++;
2019 if(config->program_binary_file != NULL) program_count++;
2020 if(program_count == 0) {
2021 fprintf(stderr, "Invalid configuration, no program defined.\n");
2022 exit_report_result(PIGLIT_WARN);
2023 } else if (program_count > 1) {
2024 fprintf(stderr, "Invalid configuration, multiple programs defined.\n");
2025 exit_report_result(PIGLIT_WARN);
2028 /* Run test per device */
2029 config->run_per_device = true;
2032 /* Memory object functions */
2034 struct mem_arg {
2035 cl_uint index;
2036 cl_mem mem;
2037 cl_mem_object_type type;
2040 void
2041 free_mem_args(struct mem_arg** mem_args, unsigned int* num_mem_args)
2043 unsigned i;
2045 for(i = 0; i < *num_mem_args; i++) {
2046 clReleaseMemObject((*mem_args)[i].mem);
2049 free(*mem_args); *mem_args = NULL;
2050 *num_mem_args = 0;
2053 void
2054 free_sampler_args(cl_sampler** sampler_args, unsigned int* num_sampler_args)
2056 unsigned i;
2058 for(i = 0; i < *num_sampler_args; i++) {
2059 clReleaseSampler((*sampler_args)[i]);
2062 free(*sampler_args); *sampler_args = NULL;
2063 *num_sampler_args = 0;
2066 bool
2067 check_test_arg_value(struct test_arg test_arg,
2068 void* value)
2070 size_t i; // index in array
2071 size_t c; // component in element
2072 size_t ra; // offset from the beginning of parsed array
2073 size_t rb; // offset from the beginning of buffer
2075 #define CASEI(enum_type, type, cl_type) \
2076 case enum_type: \
2077 for(i = 0; i < test_arg.length; i++) { \
2078 for(c = 0; c < test_arg.cl_size; c++) { \
2079 rb = i*test_arg.cl_mem_size + c; \
2080 if(!piglit_cl_probe_integer(((cl_type*)value)[rb], \
2081 ((cl_type*)test_arg.value)[rb], \
2082 test_arg.toli)) { \
2083 ra = i*test_arg.cl_size + c; \
2084 printf("Error at %s[%zu]\n", type, ra); \
2085 return false; \
2089 return true;
2090 #define CASEU(enum_type, type, cl_type) \
2091 case enum_type: \
2092 for(i = 0; i < test_arg.length; i++) { \
2093 for(c = 0; c < test_arg.cl_size; c++) { \
2094 rb = i*test_arg.cl_mem_size + c; \
2095 if(!piglit_cl_probe_uinteger(((cl_type*)value)[rb], \
2096 ((cl_type*)test_arg.value)[rb], \
2097 test_arg.tolu)) { \
2098 ra = i*test_arg.cl_size + c; \
2099 printf("Error at %s[%zu]\n", type, ra); \
2100 return false; \
2104 return true;
2105 #define CASEH(enum_type, type, cl_type) \
2106 case enum_type: \
2107 for(i = 0; i < test_arg.length; i++) { \
2108 for(c = 0; c < test_arg.cl_size; c++) { \
2109 rb = i*test_arg.cl_mem_size + c; \
2110 if(!piglit_cl_probe_half(((cl_type*)value)[rb], \
2111 ((cl_type*)test_arg.value)[rb], \
2112 test_arg.ulp)) { \
2113 ra = i*test_arg.cl_size + c; \
2114 printf("Error at %s[%zu]\n", type, ra); \
2115 return false; \
2119 return true;
2120 #define CASEF(enum_type, type, cl_type, testfn) \
2121 case enum_type: \
2122 for(i = 0; i < test_arg.length; i++) { \
2123 for(c = 0; c < test_arg.cl_size; c++) { \
2124 rb = i*test_arg.cl_mem_size + c; \
2125 if(!testfn(((cl_type*)value)[rb], \
2126 ((cl_type*)test_arg.value)[rb], \
2127 test_arg.ulp)) { \
2128 ra = i*test_arg.cl_size + c; \
2129 printf("Error at %s[%zu]\n", type, ra); \
2130 return false; \
2134 return true;
2136 switch(test_arg.cl_type) {
2137 CASEI(TYPE_CHAR, "char", cl_char)
2138 CASEU(TYPE_UCHAR, "uchar", cl_uchar)
2139 CASEI(TYPE_SHORT, "short", cl_short)
2140 CASEU(TYPE_USHORT, "ushort", cl_ushort)
2141 CASEI(TYPE_INT, "int", cl_int)
2142 CASEU(TYPE_UINT, "uint", cl_uint)
2143 CASEI(TYPE_LONG, "long", cl_long)
2144 CASEU(TYPE_ULONG, "ulong", cl_ulong)
2145 CASEH(TYPE_HALF, "half", cl_half)
2146 CASEF(TYPE_FLOAT, "float", cl_float, piglit_cl_probe_floating)
2147 CASEF(TYPE_DOUBLE, "double", cl_double, piglit_cl_probe_double)
2150 #undef CASEF
2151 #undef CASEU
2152 #undef CASEI
2154 return true;
2157 /* Run the kernel test */
2158 enum piglit_result
2159 test_kernel(const struct piglit_cl_program_test_config* config,
2160 const struct piglit_cl_program_test_env* env,
2161 struct test test)
2163 enum piglit_result result = PIGLIT_PASS;
2165 // all
2166 unsigned j;
2167 char* kernel_name;
2168 cl_kernel kernel;
2170 // setting/validating arguments
2171 struct mem_arg* mem_args = NULL;
2172 unsigned int num_mem_args = 0;
2174 cl_sampler *sampler_args = NULL;
2175 unsigned int num_sampler_args = 0;
2177 /* Check if this device supports the local work size. */
2178 if (!piglit_cl_framework_check_local_work_size(env->device_id,
2179 test.local_work_size)) {
2180 return PIGLIT_SKIP;
2183 /* Create or use apropriate kernel */
2184 if(test.kernel_name == NULL) {
2185 kernel_name = config->kernel_name;
2186 kernel = env->kernel;
2188 if(config->kernel_name == NULL) {
2189 printf("No kernel_name defined\n");
2190 return PIGLIT_WARN;
2191 } else {
2192 clRetainKernel(kernel);
2194 } else {
2195 kernel_name = test.kernel_name;
2196 kernel = piglit_cl_create_kernel(env->program, test.kernel_name);
2198 if(kernel == NULL) {
2199 printf("Could not create kernel %s\n", kernel_name);
2200 return PIGLIT_FAIL;
2204 printf("Using kernel %s\n", kernel_name);
2206 /* Set kernel args */
2207 printf("Setting kernel arguments...\n");
2209 for(j = 0; j < test.num_args_in; j++) {
2210 bool arg_set = false;
2211 struct test_arg test_arg = test.args_in[j];
2213 switch(test_arg.type) {
2214 case TEST_ARG_VALUE:
2215 arg_set = piglit_cl_set_kernel_arg(kernel,
2216 test_arg.index,
2217 test_arg.size,
2218 test_arg.value);
2219 break;
2220 case TEST_ARG_BUFFER: {
2221 struct mem_arg mem_arg;
2222 mem_arg.index = test_arg.index;
2223 mem_arg.type = CL_MEM_OBJECT_BUFFER;
2225 if(test_arg.value != NULL) {
2226 mem_arg.mem = piglit_cl_create_buffer(env->context,
2227 CL_MEM_READ_WRITE,
2228 test_arg.size);
2229 if( mem_arg.mem != NULL
2230 && piglit_cl_write_buffer(env->context->command_queues[0],
2231 mem_arg.mem,
2233 test_arg.size,
2234 test_arg.value)
2235 && piglit_cl_set_kernel_arg(kernel,
2236 mem_arg.index,
2237 sizeof(cl_mem),
2238 &mem_arg.mem)) {
2239 arg_set = true;
2241 } else {
2242 mem_arg.mem = NULL;
2243 arg_set = piglit_cl_set_kernel_arg(kernel,
2244 mem_arg.index,
2245 sizeof(cl_mem),
2246 NULL);
2249 if(arg_set) {
2250 add_dynamic_array((void**)&mem_args,
2251 &num_mem_args,
2252 sizeof(struct mem_arg),
2253 &mem_arg);
2255 break;
2257 case TEST_ARG_IMAGE: {
2258 struct mem_arg mem_arg;
2259 mem_arg.index = test_arg.index;
2260 mem_arg.type = test_arg.image_desc.image_type;
2262 if(!test_arg.value) {
2263 printf("Image argument cannot be null.\n");
2264 arg_set = false;
2265 break;
2268 mem_arg.mem = piglit_cl_create_image(env->context,
2269 CL_MEM_READ_ONLY,
2270 &test_arg.image_format,
2271 &test_arg.image_desc);
2272 if( mem_arg.mem != NULL
2273 && piglit_cl_write_whole_image(env->context->command_queues[0],
2274 mem_arg.mem,
2275 test_arg.value)
2276 && piglit_cl_set_kernel_arg(kernel,
2277 mem_arg.index,
2278 sizeof(cl_mem),
2279 &mem_arg.mem)) {
2280 arg_set = true;
2283 if(arg_set) {
2284 add_dynamic_array((void**)&mem_args,
2285 &num_mem_args,
2286 sizeof(struct mem_arg),
2287 &mem_arg);
2289 break;
2291 case TEST_ARG_SAMPLER: {
2292 cl_sampler sampler = piglit_cl_create_sampler(
2293 env->context,
2294 test_arg.sampler_normalized_coords,
2295 test_arg.sampler_addressing_mode,
2296 test_arg.sampler_filter_mode);
2298 if(!sampler) {
2299 arg_set = false;
2300 break;
2303 arg_set = piglit_cl_set_kernel_arg(kernel,
2304 test_arg.index,
2305 test_arg.size,
2306 &sampler);
2308 if(arg_set) {
2309 add_dynamic_array((void**)&sampler_args,
2310 &num_sampler_args,
2311 sizeof(cl_sampler),
2312 &sampler);
2314 break;
2317 if(!arg_set) {
2318 printf("Failed to set kernel argument with index %u\n",
2319 test_arg.index);
2320 clReleaseKernel(kernel);
2321 free_mem_args(&mem_args, &num_mem_args);
2322 free_sampler_args(&sampler_args, &num_sampler_args);
2323 return PIGLIT_FAIL;
2327 for(j = 0; j < test.num_args_out; j++) {
2328 bool arg_set = false;
2329 struct test_arg test_arg = test.args_out[j];
2331 switch(test_arg.type) {
2332 case TEST_ARG_VALUE:
2333 // not accepted by parser
2334 break;
2335 case TEST_ARG_BUFFER: {
2336 unsigned k;
2337 bool fail = false;
2338 struct mem_arg mem_arg;
2339 mem_arg.index = test_arg.index;
2340 mem_arg.type = CL_MEM_OBJECT_BUFFER;
2342 for(k = 0; k < num_mem_args; k++) {
2343 if(mem_args[k].index != mem_arg.index)
2344 continue;
2346 if(mem_args[k].type != mem_arg.type) {
2347 printf("Inconsistent types specified for in-out"
2348 "argument %d: arg_in: %s, arg_out: %s.\n",
2349 mem_arg.index,
2350 piglit_cl_get_enum_name(mem_args[k].type),
2351 piglit_cl_get_enum_name(mem_arg.type));
2352 arg_set = false;
2353 fail = true;
2354 break;
2356 arg_set = true;
2358 if(arg_set || fail) {
2359 break;
2362 if(test_arg.value != NULL) {
2363 mem_arg.mem = piglit_cl_create_buffer(env->context,
2364 CL_MEM_READ_WRITE,
2365 test_arg.size);
2366 if( mem_arg.mem != NULL
2367 && piglit_cl_set_kernel_arg(kernel,
2368 mem_arg.index,
2369 sizeof(cl_mem),
2370 &mem_arg.mem)) {
2371 arg_set = true;
2373 } else {
2374 mem_arg.mem = NULL;
2375 arg_set = piglit_cl_set_kernel_arg(kernel,
2376 mem_arg.index,
2377 sizeof(cl_mem),
2378 NULL);
2381 if(arg_set) {
2382 add_dynamic_array((void**)&mem_args,
2383 &num_mem_args,
2384 sizeof(struct mem_arg),
2385 &mem_arg);
2387 break;
2389 case TEST_ARG_IMAGE: {
2390 unsigned k;
2391 bool fail = false;
2392 struct mem_arg mem_arg;
2393 mem_arg.index = test_arg.index;
2394 mem_arg.type = test_arg.image_desc.image_type;
2396 for(k = 0; k < num_mem_args; k++) {
2397 if(mem_args[k].index == mem_arg.index) {
2398 printf("Argument %d: images cannot be in-out arguments.",
2399 mem_arg.index);
2400 arg_set = false;
2401 fail = true;
2402 break;
2405 if(fail) {
2406 break;
2409 if(!test_arg.value) {
2410 printf("Image argument cannot be null.\n");
2411 arg_set = false;
2412 break;
2415 mem_arg.mem = piglit_cl_create_image(env->context,
2416 CL_MEM_WRITE_ONLY,
2417 &test_arg.image_format,
2418 &test_arg.image_desc);
2419 if( mem_arg.mem != NULL
2420 && piglit_cl_set_kernel_arg(kernel,
2421 mem_arg.index,
2422 sizeof(cl_mem),
2423 &mem_arg.mem)) {
2424 arg_set = true;
2427 if(arg_set) {
2428 add_dynamic_array((void**)&mem_args,
2429 &num_mem_args,
2430 sizeof(struct mem_arg),
2431 &mem_arg);
2433 break;
2435 case TEST_ARG_SAMPLER:
2436 // not accepted by parser
2437 break;
2440 if(!arg_set) {
2441 printf("Failed to set kernel argument with index %u\n",
2442 test_arg.index);
2443 clReleaseKernel(kernel);
2444 free_mem_args(&mem_args, &num_mem_args);
2445 free_sampler_args(&sampler_args, &num_sampler_args);
2446 return PIGLIT_FAIL;
2450 /* Execute kernel */
2451 printf("Running the kernel...\n");
2453 if(!piglit_cl_execute_ND_range_kernel(env->context->command_queues[0],
2454 kernel,
2455 test.work_dimensions,
2456 test.global_offset_null ? NULL : test.global_offset,
2457 test.global_work_size,
2458 test.local_work_size_null ? NULL : test.local_work_size)) {
2459 printf("Failed to enqueue the kernel\n");
2460 clReleaseKernel(kernel);
2461 free_mem_args(&mem_args, &num_mem_args);
2462 free_sampler_args(&sampler_args, &num_sampler_args);
2463 return PIGLIT_FAIL;
2466 /* Check results */
2467 printf("Validating results...\n");
2469 for(j = 0; j < test.num_args_out; j++) {
2470 unsigned k;
2471 bool arg_valid = false;
2472 struct test_arg test_arg = test.args_out[j];
2474 switch(test_arg.type) {
2475 case TEST_ARG_VALUE:
2476 // Not accepted by parser
2477 break;
2478 case TEST_ARG_BUFFER: {
2479 struct mem_arg mem_arg;
2481 /* Find the right buffer */
2482 for(k = 0; k < num_mem_args; k++) {
2483 if(mem_args[k].index == test_arg.index) {
2484 mem_arg = mem_args[k];
2488 if(test_arg.value != NULL) {
2489 void* read_value = malloc(test_arg.size);
2491 if(piglit_cl_read_buffer(env->context->command_queues[0],
2492 mem_arg.mem,
2494 test_arg.size,
2495 read_value)) {
2496 arg_valid = true;
2497 if(check_test_arg_value(test_arg, read_value)) {
2498 printf(" Argument %u: PASS%s\n",
2499 test_arg.index,
2500 !test.expect_test_fail ? "" : " (not expected)");
2501 if(test.expect_test_fail) {
2502 piglit_merge_result(&result, PIGLIT_FAIL);
2504 } else {
2505 printf(" Argument %u: FAIL%s\n",
2506 test_arg.index,
2507 !test.expect_test_fail ? "" : " (expected)");
2508 if(!test.expect_test_fail) {
2509 piglit_merge_result(&result, PIGLIT_FAIL);
2514 free(read_value);
2517 break;
2519 case TEST_ARG_IMAGE: {
2520 struct mem_arg mem_arg;
2522 /* Find the right buffer */
2523 for(k = 0; k < num_mem_args; k++) {
2524 if(mem_args[k].index == test_arg.index) {
2525 mem_arg = mem_args[k];
2529 if(test_arg.value != NULL) {
2530 void* read_value = malloc(test_arg.size);
2532 if(piglit_cl_read_whole_image(env->context->command_queues[0],
2533 mem_arg.mem,
2534 read_value)) {
2535 arg_valid = true;
2536 if(check_test_arg_value(test_arg, read_value)) {
2537 printf(" Argument %u: PASS%s\n",
2538 test_arg.index,
2539 !test.expect_test_fail ? "" : " (not expected)");
2540 if(test.expect_test_fail) {
2541 piglit_merge_result(&result, PIGLIT_FAIL);
2543 } else {
2544 printf(" Argument %u: FAIL%s\n",
2545 test_arg.index,
2546 !test.expect_test_fail ? "" : " (expected)");
2547 if(!test.expect_test_fail) {
2548 piglit_merge_result(&result, PIGLIT_FAIL);
2553 free(read_value);
2556 break;
2558 case TEST_ARG_SAMPLER:
2559 // Not accepted by parser
2560 break;
2563 if(!arg_valid) {
2564 printf("Failed to validate kernel argument with index %u\n",
2565 test_arg.index);
2566 clReleaseKernel(kernel);
2567 free_mem_args(&mem_args, &num_mem_args);
2568 free_sampler_args(&sampler_args, &num_sampler_args);
2569 return PIGLIT_FAIL;
2573 /* Clean memory used by test */
2574 clReleaseKernel(kernel);
2575 free_mem_args(&mem_args, &num_mem_args);
2576 free_sampler_args(&sampler_args, &num_sampler_args);
2577 return result;
2580 /* Run test */
2582 enum piglit_result
2583 piglit_cl_test(const int argc,
2584 const char** argv,
2585 const struct piglit_cl_program_test_config* config,
2586 const struct piglit_cl_program_test_env* env)
2588 enum piglit_result result = PIGLIT_SKIP;
2590 unsigned i;
2592 /* Print building status */
2593 if(!config->expect_build_fail) {
2594 printf("Program has been built successfully\n");
2595 } else {
2596 printf("Program has failed to build as expected\n");
2599 /* If num_tests is 0, then we are running a build test and the fact
2600 * that we have made it this far means that the program has built
2601 * successfully, so we can report PIGLIT_PASS.
2603 if (num_tests == 0) {
2604 result = PIGLIT_PASS;
2607 /* Run the tests */
2608 for(i = 0; i< num_tests; i++) {
2609 enum piglit_result test_result;
2610 char* test_name = tests[i].name != NULL ? tests[i].name : "";
2612 printf("> Running kernel test: %s\n", test_name);
2614 test_result = test_kernel(config, env, tests[i]);
2615 piglit_merge_result(&result, test_result);
2617 piglit_report_subtest_result(test_result, "%s", tests[i].name);
2620 /* Print result */
2621 if(num_tests > 0) {
2622 switch(result) {
2623 case PIGLIT_FAIL:
2624 printf(">> Some or all of the tests FAILED\n");
2625 break;
2626 case PIGLIT_SKIP:
2627 printf(">> Tests skipped\n");
2628 break;
2629 case PIGLIT_WARN:
2630 printf(">> Some or all of the tests produced a WARNING\n");
2631 break;
2632 case PIGLIT_PASS:
2633 printf(">> All of the tests PASSED\n");
2634 break;
2638 return result;