perf/pixel-rate: new pixel throughput microbenchmark
[piglit.git] / tests / cl / program / program-tester.c
blobe47fb5aacc6ad8b1fe919cde3723b8821e8c7f73
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>
35 #include "piglit-framework-cl-program.h"
37 #ifdef HAVE_LIBGEN_H
38 #include <libgen.h>
39 #endif
41 /* Regexes */
44 * IMPORTANT:
45 * Watch on subexpressions when modifying regexes, because some of them are
46 * used to retrieve the strings matching them!
50 * Section (section can include whitespace):
51 * <whitespace>[<whitespace>section<whitespace>]<whitespace>
53 #define REGEX_SECTION "^[[:space:]]*\\[[[:space:]]*([[:alnum:]_]+[[:alnum:][:space:]_]*[[:alnum:]_]+|[[:alnum:]_]+)[[:space:]]*\\][[:space:]]*$" /* section */
55 * Key-value (value can have whitespace):
56 * <whitespace>key<whitespace>:<whitespace>value<whitespace>
58 #define REGEX_KEY_VALUE "^[[:space:]]*([[:alnum:]_]+)[[:space:]]*" /* key */ \
59 ":" \
60 "[[:space:]]*([^[:space:]#]+[^#]*[^[:space:]#]+|[^[:space:]#]+)[[:space:]]*$" /* value */
62 * Ignored:
63 * <whitespace>
65 #define REGEX_IGNORE "^[[:space:]]*$"
67 /* Values */
68 #define REGEX_ARRAY_DELIMITER "[[:space:]]+"
69 #define REGEX_DEFINE_ARRAY(element) "((" element REGEX_ARRAY_DELIMITER ")*" element ")"
70 #define REGEX_NAN "(nan|NAN|NaN)"
71 #define REGEX_PNAN "([+]?" REGEX_NAN ")"
72 #define REGEX_NNAN "([-]" REGEX_NAN ")"
73 #define REGEX_INF "(infinity|INFINITY|Infinity|inf|INF|Inf)"
74 #define REGEX_PINF "([+]?" REGEX_INF ")"
75 #define REGEX_NINF "([-]" REGEX_INF ")"
76 #define REGEX_NULL "(NULL|null)"
77 #define REGEX_BOOL "(0|1|false|true)"
78 #define REGEX_BOOL_TRUE "(1|true)"
79 #define REGEX_BOOL_FALSE "(0|false)"
80 #define REGEX_INT "(([+-]?[[:digit:]]+)|([+-]?0[Xx][[:digit:]abcdefABCDEF]+))"
81 #define REGEX_UINT "(([+]?[[:digit:]]+)|([+]?0[Xx][[:digit:]abcdefABCDEF]+))"
82 #define REGEX_FLOAT_HEX "([+-]?0[Xx][[:digit:]abcdefABCDEF.]+[[:digit:]pP+-]*)"
83 #define REGEX_FLOAT "(([+-]?[[:digit:]]+(\\.[[:digit:]]+)?e*[+-]*[[:digit:]]*)|" \
84 REGEX_FLOAT_HEX "|" REGEX_PNAN "|" REGEX_NNAN "|" REGEX_PINF "|" \
85 REGEX_NINF ")"
86 #define REGEX_BOOL_ARRAY REGEX_DEFINE_ARRAY(REGEX_BOOL)
87 #define REGEX_INT_ARRAY REGEX_DEFINE_ARRAY(REGEX_INT)
88 #define REGEX_UINT_ARRAY REGEX_DEFINE_ARRAY(REGEX_UINT)
89 #define REGEX_FLOAT_ARRAY REGEX_DEFINE_ARRAY(REGEX_FLOAT)
90 #define REGEX_VALUE "(" REGEX_NULL "|" REGEX_BOOL "|" REGEX_INT "|" \
91 REGEX_UINT "|" REGEX_FLOAT ")"
92 #define REGEX_ARRAY "(" REGEX_NULL "|" REGEX_BOOL_ARRAY "|" \
93 REGEX_INT_ARRAY "|" REGEX_UINT_ARRAY "|" \
94 REGEX_FLOAT_ARRAY ")"
95 #define REGEX_ARRAY_VALUE "(" REGEX_BOOL "|" REGEX_INT "|" REGEX_UINT "|" \
96 REGEX_FLOAT ")"
97 #define REGEX_RANDOM "(RANDOM|random)"
98 #define REGEX_REPEAT "(REPEAT|repeat)[[:space:]]+" \
99 REGEX_DEFINE_ARRAY(REGEX_ARRAY_VALUE)
101 /* Types */
102 #define REGEX_DEFINE_TYPE(type) type"|"type"2|"type"3|"type"4|"type"8|"type"16"
103 #define REGEX_TYPE_CHAR REGEX_DEFINE_TYPE("char")
104 #define REGEX_TYPE_UCHAR REGEX_DEFINE_TYPE("uchar")
105 #define REGEX_TYPE_SHORT REGEX_DEFINE_TYPE("short")
106 #define REGEX_TYPE_USHORT REGEX_DEFINE_TYPE("ushort")
107 #define REGEX_TYPE_INT REGEX_DEFINE_TYPE("int")
108 #define REGEX_TYPE_UINT REGEX_DEFINE_TYPE("uint")
109 #define REGEX_TYPE_LONG REGEX_DEFINE_TYPE("long")
110 #define REGEX_TYPE_ULONG REGEX_DEFINE_TYPE("ulong")
111 // half is defined as unsigned short and C can't read/write its value.
112 // Also half is only used as a storage format unless device supports
113 // cl_khr_fp16
114 // TODO: probably we could use libmpdec to handle this
115 // http://www.bytereef.org/mpdecimal/index.html
116 //#define REGEX_TYPE_HALF "buffer half[1]"
117 #define REGEX_TYPE_HALF REGEX_DEFINE_TYPE("half")
118 #define REGEX_TYPE_FLOAT REGEX_DEFINE_TYPE("float")
119 #define REGEX_TYPE_DOUBLE REGEX_DEFINE_TYPE("double")
120 #define REGEX_TYPE REGEX_TYPE_CHAR "|" REGEX_TYPE_UCHAR "|" \
121 REGEX_TYPE_SHORT "|" REGEX_TYPE_USHORT "|" \
122 REGEX_TYPE_INT "|" REGEX_TYPE_UINT "|" \
123 REGEX_TYPE_LONG "|" REGEX_TYPE_ULONG "|" \
124 REGEX_TYPE_HALF "|" REGEX_TYPE_FLOAT "|" REGEX_TYPE_DOUBLE
126 /* Image types */
127 /* TODO: add OpenCL 1.2+ types */
128 #define REGEX_IMGT_2D "2D|2d"
129 #define REGEX_IMGT_3D "3D|3d"
130 #define REGEX_IMAGE_TYPE REGEX_IMGT_2D "|" REGEX_IMGT_3D
132 /* Image formats */
133 /* TODO: add OpenCL 2.0 formats */
134 #define REGEX_CHO_R "R|r"
135 #define REGEX_CHO_RX "RX|Rx|rx"
136 #define REGEX_CHO_A "A|a"
137 #define REGEX_CHO_INTENSITY "INTENSITY|intensity"
138 #define REGEX_CHO_LUMINANCE "LUMINANCE|luminance"
139 #define REGEX_CHO_RG "RG|rg"
140 #define REGEX_CHO_RGX "RGX|RGx|rgx"
141 #define REGEX_CHO_RA "RA|ra"
142 #define REGEX_CHO_RGB "RGB|rgb"
143 #define REGEX_CHO_RGBX "RGBX|rgbx"
144 #define REGEX_CHO_RGBA "RGBA|rgba"
145 #define REGEX_CHO_ARGB "ARGB|argb"
146 #define REGEX_CHO_BGRA "BGRA|bgra"
147 #define REGEX_CHANNEL_ORDER REGEX_CHO_R "|" REGEX_CHO_RX "|" REGEX_CHO_A "|" \
148 REGEX_CHO_INTENSITY "|" REGEX_CHO_LUMINANCE "|" \
149 REGEX_CHO_RG "|" REGEX_CHO_RGX "|" \
150 REGEX_CHO_RA "|" REGEX_CHO_RGB "|" \
151 REGEX_CHO_RGBX "|" REGEX_CHO_RGBA "|" \
152 REGEX_CHO_ARGB "|" REGEX_CHO_BGRA
154 #define REGEX_CHT_SNORM_INT8 "SNORM_INT8|snorm_int8"
155 #define REGEX_CHT_SNORM_INT16 "SNORM_INT16|snorm_int16"
156 #define REGEX_CHT_UNORM_INT8 "UNORM_INT8|unorm_int8"
157 #define REGEX_CHT_UNORM_INT16 "UNORM_INT16|unorm_int16"
158 #define REGEX_CHT_UNORM_SHORT_565 "UNORM_SHORT_565|unorm_short_565"
159 #define REGEX_CHT_UNORM_SHORT_555 "UNORM_SHORT_555|unorm_short_555"
160 #define REGEX_CHT_UNORM_INT_101010 "UNORM_INT_101010|unorm_int_101010"
161 #define REGEX_CHT_SIGNED_INT8 "SIGNED_INT8|signed_int8"
162 #define REGEX_CHT_SIGNED_INT16 "SIGNED_INT16|signed_int16"
163 #define REGEX_CHT_SIGNED_INT32 "SIGNED_INT32|signed_int32"
164 #define REGEX_CHT_UNSIGNED_INT8 "UNSIGNED_INT8|unsigned_int8"
165 #define REGEX_CHT_UNSIGNED_INT16 "UNSIGNED_INT16|unsigned_int16"
166 #define REGEX_CHT_UNSIGNED_INT32 "UNSIGNED_INT32|unsigned_int32"
167 #define REGEX_CHT_HALF_FLOAT "HALF_FLOAT|half_float"
168 #define REGEX_CHT_FLOAT "FLOAT|float"
169 #define REGEX_CHANNEL_DATA_TYPE REGEX_CHT_SNORM_INT8 "|" \
170 REGEX_CHT_SNORM_INT16 "|" \
171 REGEX_CHT_UNORM_INT8 "|" \
172 REGEX_CHT_UNORM_INT16 "|" \
173 REGEX_CHT_UNORM_SHORT_565 "|" \
174 REGEX_CHT_UNORM_SHORT_555 "|" \
175 REGEX_CHT_UNORM_INT_101010 "|" \
176 REGEX_CHT_SIGNED_INT8 "|" \
177 REGEX_CHT_SIGNED_INT16 "|" \
178 REGEX_CHT_SIGNED_INT32 "|" \
179 REGEX_CHT_UNSIGNED_INT8 "|" \
180 REGEX_CHT_UNSIGNED_INT16 "|" \
181 REGEX_CHT_UNSIGNED_INT32 "|" \
182 REGEX_CHT_HALF_FLOAT "|" \
183 REGEX_CHT_FLOAT
185 /* Sampler */
186 #define REGEX_SAMP_ADDR_NONE "NONE|none"
187 #define REGEX_SAMP_ADDR_CLAMP_TO_EDGE "CLAMP_TO_EDGE|clamp_to_edge"
188 #define REGEX_SAMP_ADDR_CLAMP "CLAMP|clamp"
189 #define REGEX_SAMP_ADDR_REPEAT "REPEAT|repeat"
190 #define REGEX_SAMP_ADDR_MIRRORED_REPEAT "MIRRORED_REPEAT|mirrored_repeat"
191 #define REGEX_SAMPLER_ADDRESSING_MODE REGEX_SAMP_ADDR_NONE "|"\
192 REGEX_SAMP_ADDR_CLAMP_TO_EDGE "|" \
193 REGEX_SAMP_ADDR_CLAMP "|" \
194 REGEX_SAMP_ADDR_REPEAT "|" \
195 REGEX_SAMP_ADDR_MIRRORED_REPEAT
197 #define REGEX_SAMP_FILT_NEAREST "NEAREST|nearest"
198 #define REGEX_SAMP_FILT_LINEAR "LINEAR|linear"
199 #define REGEX_SAMPLER_FILTER_MODE REGEX_SAMP_FILT_NEAREST "|" \
200 REGEX_SAMP_FILT_LINEAR
203 * Value argument:
204 * index<whitespace>type<whitespace>value
205 * Buffer argument:
206 * index<whitespace>buffer<whitespace>type[size]<whitespace>(value|random|repeat value)<whitespace>tolerance<whitespace>value
207 * Image argument:
208 * index<whitespace>image<whitespace>type<whitespace>
209 * (value|random|repeat value)<whitespace>
210 * image_type<whitespace>(2d|3d)<whitespace>i
211 * image_width<whitespace>value<whitespace>
212 * image_height<whitespace>value<whitespace>
213 * image_channel_order<whitespace>value<whitespace>
214 * image_channel_data_type<whitespace>value<whitespace>
215 * tolerance<whitespace>value
216 * Sampler argument:
217 * index<whitespace>sampler<whitespace>
218 * normalized_coords<whitespace>bool<whitespace>
219 * addressing_mode<whitespace>(none|clamp_to_edge|repeat|mirrored_repeat)<whitespace>
220 * filter_mode<whitespace>(nearest|linear)<whitespace>
222 #define REGEX_DEFINE_ARG(type, value) "([[:digit:]]+)[[:space:]]+" type \
223 "[[:space:]]+(" value ")"
224 #define REGEX_ARG_TOLERANCE "tolerance[[:space:]]+(" REGEX_VALUE ")"
225 #define REGEX_ARG_TOLERANCE_ULP REGEX_ARG_TOLERANCE "[[:space:]]+ulp"
226 #define REGEX_ARG_IMAGE_TYPE "image_type[[:space:]]+(" REGEX_IMAGE_TYPE ")"
227 #define REGEX_ARG_IMAGE_WIDTH "image_width[[:space:]]+(" REGEX_UINT ")"
228 #define REGEX_ARG_IMAGE_HEIGHT "image_height[[:space:]]+(" REGEX_UINT ")"
229 #define REGEX_ARG_IMAGE_CHANNEL_ORDER "image_channel_order[[:space:]]+(" REGEX_CHANNEL_ORDER ")"
230 #define REGEX_ARG_IMAGE_CHANNEL_DATA_TYPE "image_channel_data_type[[:space:]]+(" REGEX_CHANNEL_DATA_TYPE ")"
231 #define REGEX_ARG_SAMPLER_NORMALIZED_COORDS "normalized_coords[[:space:]]+" REGEX_BOOL
232 #define REGEX_ARG_SAMPLER_ADDERSSING_MODE "addressing_mode[[:space:]]+(" REGEX_SAMPLER_ADDRESSING_MODE ")"
233 #define REGEX_ARG_SAMPLER_FILTER_MODE "filter_mode[[:space:]]+(" REGEX_SAMPLER_FILTER_MODE ")"
234 #define REGEX_ARG_VALUE REGEX_DEFINE_ARG( "(" REGEX_TYPE ")", REGEX_ARRAY )
235 #define REGEX_ARG_BUFFER REGEX_DEFINE_ARG( "buffer[[:space:]]+(" REGEX_TYPE ")\\[([[:digit:]]+)\\]", \
236 REGEX_ARRAY "|" REGEX_RANDOM "|" REGEX_REPEAT ) \
237 "([[:space:]]+" "("REGEX_ARG_TOLERANCE "|" REGEX_ARG_TOLERANCE_ULP")" ")?"
238 #define REGEX_ARG_IMAGE REGEX_DEFINE_ARG( "image[[:space:]]+(" REGEX_TYPE ")", \
239 REGEX_ARRAY "|" REGEX_RANDOM "|" REGEX_REPEAT ) \
240 "[[:space:]]+"REGEX_ARG_IMAGE_TYPE \
241 "[[:space:]]+"REGEX_ARG_IMAGE_WIDTH \
242 "[[:space:]]+"REGEX_ARG_IMAGE_HEIGHT \
243 "[[:space:]]+"REGEX_ARG_IMAGE_CHANNEL_ORDER \
244 "[[:space:]]+"REGEX_ARG_IMAGE_CHANNEL_DATA_TYPE \
245 "([[:space:]]+" "("REGEX_ARG_TOLERANCE "|" REGEX_ARG_TOLERANCE_ULP")" ")?"
246 #define REGEX_ARG_SAMPLER "([[:digit:]]+)[[:space:]]+sampler" \
247 "[[:space:]]+"REGEX_ARG_SAMPLER_NORMALIZED_COORDS \
248 "[[:space:]]+"REGEX_ARG_SAMPLER_ADDERSSING_MODE \
249 "[[:space:]]+"REGEX_ARG_SAMPLER_FILTER_MODE
250 #define REGEX_ARG "(" REGEX_ARG_VALUE "|" REGEX_ARG_BUFFER "|" \
251 REGEX_ARG_IMAGE "|" REGEX_ARG_SAMPLER ")"
253 /* Match whole line */
254 #define REGEX_FULL_MATCH(content) "^"content"$"
256 /* Comment config */
257 #define REGEX_COMMENT_CONFIG "/\\*!(.*)!\\*/"
259 /* Other */
260 #define REGEX_LINE "^([^#]*)(#.*)?$"
261 #define REGEX_MULTILINE "^([^#]*)\\\\[[:space:]]*$"
263 /* Config function */
264 void init(const int argc,
265 const char** argv,
266 struct piglit_cl_program_test_config* config);
267 void clean(const int argc,
268 const char** argv,
269 const struct piglit_cl_program_test_config* config);
272 /* Kernel test configuration */
274 // Framework options
275 PIGLIT_CL_PROGRAM_TEST_CONFIG_BEGIN
277 config.init_func = (piglit_cl_test_init_t*)init;
278 config.clean_func = (piglit_cl_test_clean_t*)clean;
280 PIGLIT_CL_PROGRAM_TEST_CONFIG_END
282 // Additional options
283 bool expect_test_fail = false;
284 cl_uint work_dimensions = 1;
285 size_t global_work_size[3] = {1, 1, 1};
286 size_t local_work_size[3] = {1, 1, 1};
287 size_t global_offset[3] = {0, 0, 0};
288 bool local_work_size_null = false;
289 bool global_offset_null = true;
291 /* Helper functions */
293 void
294 add_dynamic_array(void** array,
295 unsigned int* count,
296 size_t element_size,
297 void* data)
299 #define GROW_SIZE 8
300 if(((*count)%GROW_SIZE) == 0) {
301 void* old_array = *array;
303 *array = malloc(((*count)/GROW_SIZE + 1)*GROW_SIZE * element_size);
304 memcpy(*array, old_array, (*count) * element_size);
306 free(old_array);
309 memcpy((char *)(*array) + ((*count)*element_size), data, element_size);
310 (*count)++;
311 #undef GROW_SIZE
314 /* Tests */
316 enum test_arg_type {
317 TEST_ARG_VALUE,
318 TEST_ARG_BUFFER,
319 TEST_ARG_IMAGE,
320 TEST_ARG_SAMPLER
323 enum cl_type {
324 TYPE_CHAR,
325 TYPE_UCHAR,
326 TYPE_SHORT,
327 TYPE_USHORT,
328 TYPE_INT,
329 TYPE_UINT,
330 TYPE_LONG,
331 TYPE_ULONG,
332 TYPE_HALF,
333 TYPE_FLOAT,
334 TYPE_DOUBLE,
337 struct test_arg {
338 enum test_arg_type type;
340 enum cl_type cl_type;
341 size_t cl_size; // 1 for int, 3 for int3
342 size_t cl_mem_size; // 1 for int, 4 for int3
343 size_t length; // for buffers
345 /* kernel arg data */
346 cl_uint index;
347 size_t size;
348 void* value;
350 /* tolerance */
351 int64_t toli;
352 uint64_t tolu;
353 uint64_t ulp;
355 /* image data */
356 piglit_image_desc image_desc;
357 cl_image_format image_format;
359 /* sampler data */
360 cl_bool sampler_normalized_coords;
361 cl_addressing_mode sampler_addressing_mode;
362 cl_filter_mode sampler_filter_mode;
365 struct test_arg create_test_arg()
367 struct test_arg ta = {
368 .type = TEST_ARG_VALUE,
370 .cl_type = TYPE_CHAR,
371 .cl_size = 1,
372 .cl_mem_size = 1,
373 .length = 0,
375 .index = 0,
376 .size = 0,
377 .value = NULL,
379 .toli = 0,
380 .tolu = 0,
381 .ulp = 0,
384 return ta;
387 struct test {
388 char* name;
390 char* kernel_name;
391 cl_uint work_dimensions;
392 size_t global_work_size[3];
393 size_t local_work_size[3];
394 bool local_work_size_null;
395 size_t global_offset[3];
396 bool global_offset_null;
398 bool expect_test_fail;
400 unsigned int num_args_in;
401 struct test_arg* args_in;
403 unsigned int num_args_out;
404 struct test_arg* args_out;
407 unsigned int num_tests = 0;
408 struct test* tests = NULL;
410 struct test create_test()
412 struct test t = {
413 .name = NULL,
415 .kernel_name = NULL,
416 .work_dimensions = work_dimensions,
417 //.global_work_size = global_work_size,
418 //.local_work_size = local_work_size,
419 .local_work_size_null = local_work_size_null,
420 .global_offset_null = global_offset_null,
422 .expect_test_fail = expect_test_fail,
424 .num_args_in = 0,
425 .args_in = NULL,
427 .num_args_out = 0,
428 .args_out = NULL,
431 memcpy(t.global_work_size, global_work_size, sizeof(global_work_size));
432 memcpy(t.local_work_size, local_work_size, sizeof(local_work_size));
433 memcpy(t.global_offset, global_offset, sizeof(global_offset));
435 return t;
438 void
439 add_test(struct test t)
441 add_dynamic_array((void**)&tests, &num_tests, sizeof(struct test), &t);
444 bool
445 add_test_arg(struct test* t, struct test_arg ta, bool arg_in)
447 unsigned i;
448 struct test_arg* this_args;
449 size_t num_this_args;
450 struct test_arg* other_args;
451 size_t num_other_args;
453 if(arg_in) {
454 this_args = t->args_in;
455 num_this_args = t->num_args_in;
456 other_args = t->args_out;
457 num_other_args = t->num_args_out;
458 } else {
459 this_args = t->args_out;
460 num_this_args = t->num_args_out;
461 other_args = t->args_in;
462 num_other_args = t->num_args_in;
465 // Check that argument is new
466 for(i = 0; i < num_this_args; i++) {
467 struct test_arg ta_this = this_args[i];
469 if(ta.index == ta_this.index) {
470 fprintf(stderr,
471 "Invalid configuration, %s argument with index %d is already defined\n",
472 arg_in ? "In" : "Out",
473 ta.index);
474 return false;
477 // Check that types correspond
478 for(i = 0; i < num_other_args; i++) {
479 struct test_arg ta_other = other_args[i];
481 if(ta.index == ta_other.index) {
482 if(ta.type != ta_other.type) {
483 fprintf(stderr,
484 "Invalid configuration, in argument at index %d isn't compatible with out argument\n",
485 ta.index);
486 return false;
488 if(ta.size != ta_other.size) {
489 fprintf(stderr,
490 "Invalid configuration, Size of in argument (%zu) at index %d isn't the same as size of out argument (%zu)\n",
491 arg_in ? ta.size : ta_other.size,
492 ta.index,
493 arg_in ? ta_other.size : ta.size);
494 return false;
499 if(arg_in) {
500 add_dynamic_array((void**)&t->args_in,
501 &t->num_args_in,
502 sizeof(struct test_arg),
503 &ta);
504 } else {
505 add_dynamic_array((void**)&t->args_out,
506 &t->num_args_out,
507 sizeof(struct test_arg),
508 &ta);
511 return true;
514 bool
515 add_test_arg_in(struct test* t, struct test_arg ta)
517 return add_test_arg(t, ta, true);
520 bool
521 add_test_arg_out(struct test* t, struct test_arg ta)
523 return add_test_arg(t, ta, false);
526 void
527 free_tests()
529 unsigned i,j;
531 for(i = 0; i < num_tests; i++) {
532 for(j = 0; j < tests[i].num_args_in; j++) {
533 free(tests[i].args_in[j].value);
535 free(tests[i].args_in);
536 for(j = 0; j < tests[i].num_args_out; j++) {
537 free(tests[i].args_out[j].value);
539 free(tests[i].args_out);
543 /* Strings */
544 unsigned int num_dynamic_strs = 0;
545 char** dynamic_strs = NULL;
547 void
548 add_dynamic_str(char* str)
550 add_dynamic_array((void**)&dynamic_strs, &num_dynamic_strs, sizeof(char*), &str);
553 char*
554 add_dynamic_str_copy(const char* src)
556 char* dst = malloc((strlen(src)+1) * sizeof(char));
558 strcpy(dst, src);
559 add_dynamic_str(dst);
561 return dst;
564 void
565 free_dynamic_strs()
567 if(dynamic_strs != NULL) {
568 unsigned i;
570 for(i = 0; i < num_dynamic_strs; i++) {
571 free(dynamic_strs[i]);
574 free(dynamic_strs);
578 /* Clean */
580 void
581 clean(const int argc,
582 const char** argv,
583 const struct piglit_cl_program_test_config* config)
585 free_dynamic_strs();
586 free_tests();
589 NORETURN void
590 exit_report_result(enum piglit_result result)
592 free_dynamic_strs();
593 free_tests();
594 piglit_report_result(result);
597 /* Regex functions */
599 bool
600 regex_get_matches(const char* src,
601 const char* pattern,
602 regmatch_t* pmatch,
603 size_t size,
604 int cflags)
606 int errcode;
607 regex_t r;
609 /* Build regex */
610 errcode = regcomp(&r, pattern, REG_EXTENDED | cflags);
611 if(errcode) {
612 fprintf(stderr, "Invalid regular expression: '%s'\n", pattern);
613 return false;
616 /* Match regex and if pmatch != NULL && size > 0 return matched */
617 if(pmatch == NULL || size == 0) {
618 errcode = regexec(&r, src, 0, NULL, 0);
619 } else {
620 errcode = regexec(&r, src, size, pmatch, 0);
623 regfree(&r);
625 return errcode == 0;
628 bool
629 regex_get_match_str(char** dst,
630 const char* src,
631 regmatch_t* pmatch,
632 unsigned int index)
634 size_t size = pmatch[index].rm_eo - pmatch[index].rm_so;
636 if(size > 0) {
637 *dst = malloc((size+1) * sizeof(char));
638 strncpy(*dst, src+pmatch[index].rm_so, size);
639 (*dst)[size] = '\0';
641 return true;
644 return false;
647 bool
648 regex_get_str(char** dst,
649 const char* src,
650 const char* pattern,
651 unsigned int index,
652 int cflags)
654 regmatch_t *pmatch = calloc(index+1, sizeof(*pmatch));
655 bool ret = false;
657 if(regex_get_matches(src, pattern, pmatch, index+1, cflags)) {
658 ret = regex_get_match_str(dst, src, pmatch, index);
661 free(pmatch);
662 return ret;
665 bool
666 regex_match(const char* src, const char* pattern)
668 return regex_get_matches(src, pattern, NULL, 0, REG_NEWLINE);
671 bool
672 regex_section(const char* src, char** section)
674 regmatch_t pmatch[2];
676 if(regex_get_matches(src, REGEX_SECTION, pmatch, 2, REG_NEWLINE)) {
677 return regex_get_match_str(section, src, pmatch, 1);
680 return false;
683 bool
684 regex_key_value(const char* src, char** key, char** value)
686 regmatch_t pmatch[3];
688 if(regex_get_matches(src, REGEX_KEY_VALUE, pmatch, 3, REG_NEWLINE)) {
689 *key = NULL;
690 *value = NULL;
691 if( regex_get_match_str(key, src, pmatch, 1)
692 && regex_get_match_str(value, src, pmatch, 2)) {
693 return true;
694 } else {
695 free(*key);
696 free(*value);
700 return false;
703 bool
704 get_bool(const char* src)
706 if(regex_match(src, REGEX_FULL_MATCH(REGEX_BOOL_TRUE))) {
707 return true;
708 } else if(regex_match(src, REGEX_FULL_MATCH(REGEX_BOOL_FALSE))) {
709 return false;
710 } else {
711 fprintf(stderr,
712 "Invalid configuration, could not convert to bool: %s\n",
713 src);
714 exit_report_result(PIGLIT_WARN);
715 return false;
719 int64_t
720 get_int(const char* src)
722 if(regex_match(src, REGEX_FULL_MATCH(REGEX_UINT))) {
723 return strtoull(src, NULL, 0);
724 } else if(regex_match(src, REGEX_FULL_MATCH(REGEX_INT))) {
725 return strtoll(src, NULL, 0);
726 } else {
727 fprintf(stderr,
728 "Invalid configuration, could not convert to long: %s\n",
729 src);
730 exit_report_result(PIGLIT_WARN);
731 return -1;
735 uint64_t
736 get_uint(const char* src)
738 if(regex_match(src, REGEX_FULL_MATCH(REGEX_UINT))) {
739 return strtoull(src, NULL, 0);
740 } else {
741 fprintf(stderr,
742 "Invalid configuration, could not convert to ulong: %s\n",
743 src);
744 exit_report_result(PIGLIT_WARN);
745 return 0;
749 double
750 get_float(const char* src)
752 if(regex_match(src, REGEX_FULL_MATCH(REGEX_FLOAT))) {
753 if(regex_match(src, REGEX_FULL_MATCH(REGEX_PNAN))) {
754 return NAN;
755 } else if(regex_match(src, REGEX_FULL_MATCH(REGEX_NNAN))) {
756 return -NAN;
757 } else if(regex_match(src, REGEX_FULL_MATCH(REGEX_PINF))) {
758 return INFINITY;
759 } else if(regex_match(src, REGEX_FULL_MATCH(REGEX_NINF))) {
760 return -INFINITY;
761 } else {
762 return strtod(src, NULL);
764 } else {
765 fprintf(stderr,
766 "Invalid configuration, could not convert to double: %s\n",
767 src);
768 exit_report_result(PIGLIT_WARN);
769 return 0;
773 size_t
774 get_array_length(const char* src)
776 size_t size = 0;
778 if(regex_match(src, REGEX_FULL_MATCH(REGEX_ARRAY))) {
779 regmatch_t pmatch[1];
781 while(regex_get_matches(src,
782 REGEX_ARRAY_VALUE REGEX_ARRAY_DELIMITER,
783 pmatch,
785 REG_NEWLINE)) {
786 src += pmatch[0].rm_eo;
787 size++;
789 if(regex_match(src, REGEX_ARRAY_VALUE)) {
790 size++;
792 } else {
793 fprintf(stderr,
794 "Invalid configuration, could not convert to an array: %s\n",
795 src);
796 exit_report_result(PIGLIT_WARN);
799 return size;
802 size_t
803 get_array(const char* src, void** array, size_t size, char* array_pattern)
805 bool regex_matched;
806 size_t i = 0;
807 size_t actual_size;
808 char* type;
809 char* value;
810 char* value_pattern;
811 regmatch_t pmatch[2];
813 actual_size = get_array_length(src);
815 if(!strcmp(array_pattern, REGEX_BOOL_ARRAY)) {
816 type = "bool";
817 value_pattern = REGEX_BOOL REGEX_ARRAY_DELIMITER;
818 *(bool**)array = malloc(actual_size * sizeof(bool));
819 regex_matched = regex_match(src, REGEX_FULL_MATCH(REGEX_BOOL_ARRAY));
820 } else if(!strcmp(array_pattern, REGEX_INT_ARRAY)) {
821 type = "long";
822 value_pattern = REGEX_INT REGEX_ARRAY_DELIMITER;
823 *(int64_t**)array = malloc(actual_size * sizeof(int64_t));
824 regex_matched = regex_match(src, REGEX_FULL_MATCH(REGEX_INT_ARRAY));
825 } else if(!strcmp(array_pattern, REGEX_UINT_ARRAY)) {
826 type = "ulong";
827 value_pattern = REGEX_UINT REGEX_ARRAY_DELIMITER;
828 *(uint64_t**)array = malloc(actual_size * sizeof(uint64_t));
829 regex_matched = regex_match(src, REGEX_FULL_MATCH(REGEX_UINT_ARRAY));
830 } else if(!strcmp(array_pattern, REGEX_FLOAT_ARRAY)) {
831 type = "double";
832 value_pattern = REGEX_FLOAT REGEX_ARRAY_DELIMITER;
833 *(double**)array = malloc(actual_size * sizeof(double));
834 regex_matched = regex_match(src, REGEX_FULL_MATCH(REGEX_FLOAT_ARRAY));
835 } else {
836 fprintf(stderr,
837 "Internal error, invalid array pattern: %s\n",
838 array_pattern);
839 exit_report_result(PIGLIT_WARN);
842 if(size > 0 && actual_size != size) {
843 fprintf(stderr,
844 "Invalid configuration, could not convert %s[%zu] to %s[%zu]: %s\n",
845 type, actual_size, type, size, src);
846 exit_report_result(PIGLIT_WARN);
849 if(regex_match(src, REGEX_FULL_MATCH(REGEX_NULL))) {
850 free(*array);
851 *array = NULL;
852 return 0;
855 if(!regex_matched) {
856 fprintf(stderr,
857 "Invalid configuration, could not convert to %s array: %s\n",
858 type, src);
859 exit_report_result(PIGLIT_WARN);
862 while(regex_get_matches(src, value_pattern, pmatch, 2, 0)) {
863 if(regex_get_match_str(&value, src, pmatch, 1)) {
864 if(!strcmp(array_pattern, REGEX_BOOL_ARRAY)) {
865 (*(bool**)array)[i] = get_bool(value);
866 } else if(!strcmp(array_pattern, REGEX_INT_ARRAY)) {
867 (*(int64_t**)array)[i] = get_int(value);
868 } else if(!strcmp(array_pattern, REGEX_UINT_ARRAY)) {
869 (*(uint64_t**)array)[i] = get_uint(value);
870 } else if(!strcmp(array_pattern, REGEX_FLOAT_ARRAY)) {
871 (*(double**)array)[i] = get_float(value);
873 free(value);
874 } else {
875 fprintf(stderr,
876 "Invalid configuration, could not read %s on index %zu: %s\n",
877 type, i, src);
878 exit_report_result(PIGLIT_WARN);
881 src += pmatch[0].rm_eo;
882 i++;
885 if(!strcmp(array_pattern, REGEX_BOOL_ARRAY)) {
886 (*(bool**)array)[i] = get_bool(src);
887 } else if(!strcmp(array_pattern, REGEX_INT_ARRAY)) {
888 (*(int64_t**)array)[i] = get_int(src);
889 } else if(!strcmp(array_pattern, REGEX_UINT_ARRAY)) {
890 (*(uint64_t**)array)[i] = get_uint(src);
891 } else if(!strcmp(array_pattern, REGEX_FLOAT_ARRAY)) {
892 (*(double**)array)[i] = get_float(src);
895 return actual_size;
898 size_t
899 get_bool_array(const char* src, bool** array, size_t size)
901 return get_array(src, (void**)array, size, REGEX_BOOL_ARRAY);
904 size_t
905 get_int_array(const char* src, int64_t** array, size_t size)
907 return get_array(src, (void**)array, size, REGEX_INT_ARRAY);
910 size_t
911 get_uint_array(const char* src, uint64_t** array, size_t size)
913 return get_array(src, (void**)array, size, REGEX_UINT_ARRAY);
916 size_t
917 get_float_array(const char* src, double** array, size_t size)
919 return get_array(src, (void**)array, size, REGEX_FLOAT_ARRAY);
922 /* Help */
924 void
925 print_usage(const int argc, const char** argv)
927 printf("Usage:\n" \
928 " %s [options] CONFIG.program_test\n"
929 " %s [options] [-config CONFIG.program_test] PROGRAM.cl|PROGRAM.bin\n"
930 "\n"
931 "Notes:\n"
932 " - If CONFIG is not specified and PROGRAM has a comment config then a\n"
933 " comment config is used.\n"
934 " - If there is no CONFIG or comment config, then the program is only\n"
935 " tested to build properly.\n",
936 argv[0], argv[0]);
939 void
940 print_usage_and_warn(const int argc, const char** argv, const char* fmt, ...)
942 va_list args;
944 fprintf(stderr, "ERROR: ");
945 va_start(args, fmt);
946 vfprintf(stderr, fmt, args);
947 va_end(args);
949 printf("\n\n");
950 print_usage(argc, argv);
952 exit_report_result(PIGLIT_WARN);
955 /* Parse configuration */
957 size_t
958 get_section_content(const char* src, char** content)
960 size_t size = 0;
961 size_t section_name_length = strcspn(src, "\n\0");
962 regmatch_t pmatch[2];
964 if(src[section_name_length] != '\0') {
965 src += section_name_length+1;
966 } else {
967 src += section_name_length;
970 if(regex_get_matches(src, REGEX_SECTION, pmatch, 2, REG_NEWLINE)) { // found next section
971 size = pmatch[1].rm_so-1;
972 } else { // no next section
973 size = strlen(src);
976 *content = malloc((size+1) * sizeof(char));
977 strncpy(*content, src, size);
978 (*content)[size] = '\0';
980 return size;
983 void
984 get_test_arg_value(struct test_arg* test_arg, const char* value, size_t length)
986 size_t i; // index in array
987 size_t c; // component in element
988 size_t ra; // offset from the beginning of array
989 size_t rb; // offset from the beginning of buffer
991 int64_t* int_array = NULL;
992 uint64_t* uint_array = NULL;
993 double* float_array = NULL;
995 test_arg->value = malloc(test_arg->size);
998 * We fill the buffer with calculating the right offsets in the buffer (rb)
999 * and in the array (ra). Buffers of type3 have have stride of
1000 * 4*sizeof(type) while array has a stride of 3*sizeof(parsed_type).
1001 * Also the array index is inside length parameter modulo, so we can fill
1002 * the buffer with repeateable values.
1004 #define CASE(enum_type, cl_type, get_func, array) \
1005 case enum_type: \
1006 get_func(value, &array, length); \
1007 for(i = 0; i < test_arg->length; i++) { \
1008 for(c = 0; c < test_arg->cl_size; c++) { \
1009 ra = i*test_arg->cl_size + c; \
1010 rb = i*test_arg->cl_mem_size + c; \
1011 ((cl_type*)test_arg->value)[rb] = convert_##cl_type(array[ra%length]); \
1014 break;
1016 switch(test_arg->cl_type) {
1017 CASE(TYPE_CHAR, cl_char, get_int_array, int_array)
1018 CASE(TYPE_UCHAR, cl_uchar, get_uint_array, uint_array)
1019 CASE(TYPE_SHORT, cl_short, get_int_array, int_array)
1020 CASE(TYPE_USHORT, cl_ushort, get_uint_array, uint_array)
1021 CASE(TYPE_INT, cl_int, get_int_array, int_array)
1022 CASE(TYPE_UINT, cl_uint, get_uint_array, uint_array)
1023 CASE(TYPE_LONG, cl_long, get_int_array, int_array)
1024 CASE(TYPE_ULONG, cl_ulong, get_uint_array, uint_array)
1025 CASE(TYPE_HALF, cl_half, get_float_array, float_array)
1026 CASE(TYPE_FLOAT, cl_float, get_float_array, float_array)
1027 CASE(TYPE_DOUBLE, cl_double, get_float_array, float_array)
1030 #undef CASE
1032 free(int_array);
1033 free(uint_array);
1034 free(float_array);
1037 void
1038 get_test_arg_tolerance(struct test_arg* test_arg, const char* tolerance_str)
1040 regmatch_t pmatch[2];
1041 char* value_str = NULL;
1043 if(regex_get_matches(tolerance_str,
1044 REGEX_ARG_TOLERANCE_ULP,
1045 pmatch,
1047 REG_NEWLINE)) {
1048 regex_get_match_str(&value_str, tolerance_str, pmatch, 1);
1049 switch(test_arg->cl_type) {
1050 case TYPE_HALF:
1051 case TYPE_FLOAT:
1052 case TYPE_DOUBLE:
1053 test_arg->ulp = get_uint(value_str);
1054 return;
1055 default:
1056 fprintf(stderr, "ulp not value for integer types\n");
1057 exit_report_result(PIGLIT_WARN);
1061 if(regex_get_matches(tolerance_str,
1062 REGEX_ARG_TOLERANCE,
1063 pmatch,
1065 REG_NEWLINE)) {
1066 regex_get_match_str(&value_str, tolerance_str, pmatch, 1);
1068 switch(test_arg->cl_type) {
1069 case TYPE_CHAR:
1070 case TYPE_SHORT:
1071 case TYPE_INT:
1072 case TYPE_LONG:
1073 test_arg->toli = get_int(value_str);
1074 break;
1075 case TYPE_UCHAR:
1076 case TYPE_USHORT:
1077 case TYPE_UINT:
1078 case TYPE_ULONG:
1079 test_arg->tolu = get_uint(value_str);
1080 break;
1081 case TYPE_HALF:
1082 case TYPE_FLOAT:
1083 case TYPE_DOUBLE: {
1084 float value = get_float(value_str);
1085 test_arg->ulp = *((uint64_t*)(&value));
1086 break;
1090 free(value_str);
1091 } else {
1092 fprintf(stderr,
1093 "Invalid configuration, could not parse tolerance: %s\n",
1094 tolerance_str);
1095 exit_report_result(PIGLIT_WARN);
1099 void
1100 get_test_arg(const char* src, struct test* test, bool arg_in)
1102 regmatch_t pmatch[5];
1103 char* index_str = NULL;
1104 char* type = NULL;
1105 char* value = NULL;
1106 struct test_arg test_arg = create_test_arg();
1107 bool has_type = true;
1109 /* Get matches */
1110 if(regex_get_matches(src, REGEX_FULL_MATCH(REGEX_ARG_VALUE),
1111 pmatch, 5, REG_NEWLINE)) { // value
1112 // do nothing
1113 } else if(regex_get_matches(src, REGEX_FULL_MATCH(REGEX_ARG_BUFFER),
1114 pmatch, 5, REG_NEWLINE)) { // buffer
1115 // do nothing
1116 } else if(regex_get_matches(src, REGEX_FULL_MATCH(REGEX_ARG_IMAGE),
1117 pmatch, 5, REG_NEWLINE)) { // image
1118 // do nothing
1119 } else if(regex_get_matches(src, REGEX_FULL_MATCH(REGEX_ARG_SAMPLER),
1120 pmatch, 5, REG_NEWLINE)) { // sampler
1121 has_type = false;
1122 } else {
1123 fprintf(stderr,
1124 "Invalid configuration, invalid test argument: %s\n",
1125 src);
1126 exit_report_result(PIGLIT_WARN);
1129 /* Get index */
1130 regex_get_match_str(&index_str, src, pmatch, 1);
1131 test_arg.index = get_int(index_str);
1132 free(index_str);
1134 if(has_type) {
1135 /* Set type, cl_size, cl_mem_size and size (partially for buffers) */
1136 regex_get_match_str(&type, src, pmatch, 2);
1137 if(regex_match(type, "[[:digit:]]+")) {
1138 char* type_size_str;
1139 regex_get_str(&type_size_str, type, "[[:digit:]]+", 0, REG_NEWLINE);
1140 test_arg.cl_size = get_int(type_size_str);
1141 test_arg.cl_mem_size = test_arg.cl_size != 3 ? test_arg.cl_size : 4; // test if we have type3
1142 free(type_size_str);
1143 } else {
1144 test_arg.cl_size = 1;
1145 test_arg.cl_mem_size = 1;
1148 #define IF(regex_type, enum_type, main_type) \
1149 if(regex_match(type, REGEX_FULL_MATCH(regex_type))) { \
1150 test_arg.cl_type = enum_type; \
1151 test_arg.size = sizeof(main_type) * test_arg.cl_mem_size; \
1153 #define ELSEIF(regex_type, enum_type, main_type) \
1154 else IF(regex_type, enum_type, main_type)
1156 IF (REGEX_TYPE_CHAR, TYPE_CHAR, cl_char)
1157 ELSEIF(REGEX_TYPE_UCHAR, TYPE_UCHAR, cl_uchar)
1158 ELSEIF(REGEX_TYPE_SHORT, TYPE_SHORT, cl_short)
1159 ELSEIF(REGEX_TYPE_USHORT, TYPE_USHORT, cl_ushort)
1160 ELSEIF(REGEX_TYPE_INT, TYPE_INT, cl_int)
1161 ELSEIF(REGEX_TYPE_UINT, TYPE_UINT, cl_uint)
1162 ELSEIF(REGEX_TYPE_LONG, TYPE_LONG, cl_long)
1163 ELSEIF(REGEX_TYPE_ULONG, TYPE_ULONG, cl_ulong)
1164 ELSEIF(REGEX_TYPE_HALF, TYPE_HALF, cl_half)
1165 ELSEIF(REGEX_TYPE_FLOAT, TYPE_FLOAT, cl_float)
1166 ELSEIF(REGEX_TYPE_DOUBLE, TYPE_DOUBLE, cl_double)
1168 #undef IF
1169 #undef ELSEIF
1171 free(type);
1174 /* Get arg type, size and value */
1175 if(regex_match(src, REGEX_FULL_MATCH(REGEX_ARG_VALUE))) { // value
1176 /* Values are only allowed for in arguments */
1177 if(!arg_in) {
1178 fprintf(stderr,
1179 "Invalid configuration, only arg_in values are allowed: %s\n",
1180 src);
1181 exit_report_result(PIGLIT_WARN);
1184 /* Set arg type */
1185 test_arg.type = TEST_ARG_VALUE;
1187 /* Set length */
1188 test_arg.length = 1;
1190 /* Get value */
1191 regex_get_match_str(&value, src, pmatch, 3);
1192 if(regex_match(value, REGEX_FULL_MATCH(REGEX_NULL))) {
1193 test_arg.value = NULL;
1194 } else {
1195 get_test_arg_value(&test_arg, value, test_arg.cl_size);
1197 free(value);
1198 } else if(regex_match(src, REGEX_FULL_MATCH(REGEX_ARG_BUFFER))) { // buffer
1199 char* array_length_str = NULL;
1200 const char* tolerance_str = NULL;
1202 /* Set arg type */
1203 test_arg.type = TEST_ARG_BUFFER;
1205 /* Set length */
1206 regex_get_match_str(&array_length_str, src, pmatch, 3);
1207 test_arg.length = get_int(array_length_str);
1208 free(array_length_str);
1210 /* Set size */
1211 test_arg.size = test_arg.size * test_arg.length;
1213 /* Set tolerance */
1214 tolerance_str = src+pmatch[4].rm_eo;
1215 if(regex_match(tolerance_str, REGEX_ARG_TOLERANCE)) {
1216 if(arg_in) {
1217 fprintf(stderr,
1218 "Invalid configuration, in argument buffer can't have tolerance: %s\n",
1219 src);
1220 exit_report_result(PIGLIT_WARN);
1222 get_test_arg_tolerance(&test_arg, tolerance_str);
1225 /* Get value */
1226 regex_get_match_str(&value, src, pmatch, 4);
1227 if(regex_match(value, REGEX_FULL_MATCH(REGEX_NULL))) {
1228 test_arg.value = NULL;
1229 if(!arg_in) {
1230 fprintf(stderr,
1231 "Invalid configuration, out argument buffer value can not be NULL: %s\n",
1232 src);
1233 exit_report_result(PIGLIT_WARN);
1235 } else {
1236 if(regex_match(value, REGEX_FULL_MATCH(REGEX_RANDOM))) {
1237 test_arg.value = malloc(test_arg.size);
1238 if(!arg_in) {
1239 fprintf(stderr,
1240 "Invalid configuration, out argument buffer can not be random: %s\n",
1241 src);
1242 exit_report_result(PIGLIT_WARN);
1244 } else if(regex_match(value, REGEX_FULL_MATCH(REGEX_REPEAT))) {
1245 regmatch_t rmatch[3];
1246 char* repeat_value_str;
1248 regex_get_matches(value, REGEX_REPEAT, rmatch, 3, 0);
1249 regex_get_match_str(&repeat_value_str, value, rmatch, 2);
1251 get_test_arg_value(&test_arg,
1252 repeat_value_str,
1253 get_array_length(repeat_value_str));
1255 free(repeat_value_str);
1256 } else if(regex_match(value, REGEX_ARRAY)) {
1257 get_test_arg_value(&test_arg,
1258 value,
1259 test_arg.length * test_arg.cl_size);
1262 free(value);
1263 } else if(regex_match(src, REGEX_FULL_MATCH(REGEX_ARG_IMAGE))) { // image
1264 char* str = NULL;
1265 const char* properties_str = src + pmatch[3].rm_eo;
1266 const char* tolerance_str = NULL;
1267 size_t image_elems = 0;
1268 cl_channel_order cho;
1269 cl_channel_type cht;
1270 regmatch_t pmatch_prop[2];
1272 /* Set arg type */
1273 test_arg.type = TEST_ARG_IMAGE;
1275 /* Image type */
1276 regex_get_matches(properties_str, REGEX_ARG_IMAGE_TYPE,
1277 pmatch_prop, 2, REG_NEWLINE);
1278 regex_get_match_str(&str, properties_str, pmatch_prop, 1);
1279 properties_str += pmatch_prop[1].rm_eo;
1280 if(regex_match(str, REGEX_FULL_MATCH("("REGEX_IMGT_2D")"))) {
1281 test_arg.image_desc.image_type = CL_MEM_OBJECT_IMAGE2D;
1282 } else {
1283 /* TODO: Implement other image types */
1284 fprintf(stderr, "Image type not supported: %s\n", str);
1285 exit_report_result(PIGLIT_WARN);
1287 free(str);
1289 /* Image width */
1290 regex_get_matches(properties_str, REGEX_ARG_IMAGE_WIDTH,
1291 pmatch_prop, 2, REG_NEWLINE);
1292 regex_get_match_str(&str, properties_str, pmatch_prop, 1);
1293 properties_str += pmatch_prop[1].rm_eo;
1294 test_arg.image_desc.image_width = get_int(str);
1295 free(str);
1297 /* Image height */
1298 regex_get_matches(properties_str, REGEX_ARG_IMAGE_HEIGHT,
1299 pmatch_prop, 2, REG_NEWLINE);
1300 regex_get_match_str(&str, properties_str, pmatch_prop, 1);
1301 properties_str += pmatch_prop[1].rm_eo;
1302 test_arg.image_desc.image_height = get_int(str);
1303 free(str);
1305 /* Image descriptor defaults */
1306 test_arg.image_desc.image_depth = 1;
1307 test_arg.image_desc.image_array_size = 1;
1308 test_arg.image_desc.image_row_pitch = 0;
1309 test_arg.image_desc.image_slice_pitch = 0;
1310 test_arg.image_desc.num_mip_levels = 0;
1311 test_arg.image_desc.num_samples = 0;
1312 test_arg.image_desc.buffer = NULL;
1314 /* Image channel order */
1315 regex_get_matches(properties_str, REGEX_ARG_IMAGE_CHANNEL_ORDER,
1316 pmatch_prop, 2, REG_NEWLINE);
1317 regex_get_match_str(&str, properties_str, pmatch_prop, 1);
1318 properties_str += pmatch_prop[1].rm_eo;
1319 if(regex_match(str, REGEX_FULL_MATCH("("REGEX_CHO_R")"))) {
1320 cho = CL_R;
1321 } else if(regex_match(str, REGEX_FULL_MATCH("("REGEX_CHO_RX")"))) {
1322 cho = CL_Rx;
1323 } else if(regex_match(str, REGEX_FULL_MATCH("("REGEX_CHO_A")"))) {
1324 cho = CL_A;
1325 } else if(regex_match(str, REGEX_FULL_MATCH("("REGEX_CHO_INTENSITY")"))) {
1326 cho = CL_INTENSITY;
1327 } else if(regex_match(str, REGEX_FULL_MATCH("("REGEX_CHO_LUMINANCE")"))) {
1328 cho = CL_LUMINANCE;
1329 } else if(regex_match(str, REGEX_FULL_MATCH("("REGEX_CHO_RG")"))) {
1330 cho = CL_RG;
1331 } else if(regex_match(str, REGEX_FULL_MATCH("("REGEX_CHO_RGX")"))) {
1332 cho = CL_RGx;
1333 } else if(regex_match(str, REGEX_FULL_MATCH("("REGEX_CHO_RA")"))) {
1334 cho = CL_RA;
1335 } else if(regex_match(str, REGEX_FULL_MATCH("("REGEX_CHO_RGB")"))) {
1336 cho = CL_RGB;
1337 } else if(regex_match(str, REGEX_FULL_MATCH("("REGEX_CHO_RGBX")"))) {
1338 cho = CL_RGBx;
1339 } else if(regex_match(str, REGEX_FULL_MATCH("("REGEX_CHO_RGBA")"))) {
1340 cho = CL_RGBA;
1341 } else if(regex_match(str, REGEX_FULL_MATCH("("REGEX_CHO_ARGB")"))) {
1342 cho = CL_ARGB;
1343 } else if(regex_match(str, REGEX_FULL_MATCH("("REGEX_CHO_BGRA")"))) {
1344 cho = CL_BGRA;
1345 } else {
1346 fprintf(stderr, "Image channel order not supported: %s\n", str);
1347 exit_report_result(PIGLIT_WARN);
1349 free(str);
1350 test_arg.image_format.image_channel_order = cho;
1352 /* Image channel data type */
1353 regex_get_matches(properties_str, REGEX_ARG_IMAGE_CHANNEL_DATA_TYPE,
1354 pmatch_prop, 2, REG_NEWLINE);
1355 regex_get_match_str(&str, properties_str, pmatch_prop, 1);
1356 properties_str += pmatch_prop[1].rm_eo;
1357 if(regex_match(str, REGEX_FULL_MATCH("("REGEX_CHT_SNORM_INT8")"))) {
1358 cht = CL_SNORM_INT8;
1359 } else if(regex_match(str, REGEX_FULL_MATCH("("REGEX_CHT_SNORM_INT16")"))) {
1360 cht = CL_SNORM_INT16;
1361 } else if(regex_match(str, REGEX_FULL_MATCH("("REGEX_CHT_UNORM_INT8")"))) {
1362 cht = CL_UNORM_INT8;
1363 } else if(regex_match(str, REGEX_FULL_MATCH("("REGEX_CHT_UNORM_INT16")"))) {
1364 cht = CL_UNORM_INT16;
1365 } else if(regex_match(str, REGEX_FULL_MATCH("("REGEX_CHT_UNORM_SHORT_565")"))) {
1366 cht = CL_UNORM_SHORT_565;
1367 } else if(regex_match(str, REGEX_FULL_MATCH("("REGEX_CHT_UNORM_SHORT_555")"))) {
1368 cht = CL_UNORM_SHORT_555;
1369 } else if(regex_match(str, REGEX_FULL_MATCH("("REGEX_CHT_UNORM_INT_101010")"))) {
1370 cht = CL_UNORM_INT_101010;
1371 } else if(regex_match(str, REGEX_FULL_MATCH("("REGEX_CHT_SIGNED_INT8")"))) {
1372 cht = CL_SIGNED_INT8;
1373 } else if(regex_match(str, REGEX_FULL_MATCH("("REGEX_CHT_SIGNED_INT16")"))) {
1374 cht = CL_SIGNED_INT16;
1375 } else if(regex_match(str, REGEX_FULL_MATCH("("REGEX_CHT_SIGNED_INT32")"))) {
1376 cht = CL_SIGNED_INT32;
1377 } else if(regex_match(str, REGEX_FULL_MATCH("("REGEX_CHT_UNSIGNED_INT8")"))) {
1378 cht = CL_UNSIGNED_INT8;
1379 } else if(regex_match(str, REGEX_FULL_MATCH("("REGEX_CHT_UNSIGNED_INT16")"))) {
1380 cht = CL_UNSIGNED_INT16;
1381 } else if(regex_match(str, REGEX_FULL_MATCH("("REGEX_CHT_UNSIGNED_INT32")"))) {
1382 cht = CL_UNSIGNED_INT32;
1383 } else if(regex_match(str, REGEX_FULL_MATCH("("REGEX_CHT_HALF_FLOAT")"))) {
1384 cht = CL_HALF_FLOAT;
1385 } else if(regex_match(str, REGEX_FULL_MATCH("("REGEX_CHT_FLOAT")"))) {
1386 cht = CL_FLOAT;
1387 } else {
1388 fprintf(stderr, "Image channel data type not supported: %s\n", str);
1389 exit_report_result(PIGLIT_WARN);
1391 free(str);
1392 test_arg.image_format.image_channel_data_type = cht;
1394 /* Set size */
1395 image_elems = test_arg.image_desc.image_width *
1396 test_arg.image_desc.image_height *
1397 test_arg.image_desc.image_depth *
1398 test_arg.image_desc.image_array_size;
1399 test_arg.length = image_elems;
1400 test_arg.size *= image_elems;
1402 /* Set tolerance */
1403 tolerance_str = properties_str;
1404 if(regex_match(tolerance_str, REGEX_ARG_TOLERANCE)) {
1405 if(arg_in) {
1406 fprintf(stderr,
1407 "Invalid configuration, in argument buffer can't have tolerance: %s\n",
1408 src);
1409 exit_report_result(PIGLIT_WARN);
1411 get_test_arg_tolerance(&test_arg, tolerance_str);
1414 /* Get value */
1415 regex_get_match_str(&value, src, pmatch, 3);
1416 if(regex_match(value, REGEX_FULL_MATCH(REGEX_NULL))) {
1417 test_arg.value = NULL;
1418 if(!arg_in) {
1419 fprintf(stderr,
1420 "Invalid configuration, out argument buffer value can not be NULL: %s\n",
1421 src);
1422 exit_report_result(PIGLIT_WARN);
1424 } else {
1425 if(regex_match(value, REGEX_FULL_MATCH(REGEX_RANDOM))) {
1426 test_arg.value = malloc(test_arg.size);
1427 if(!arg_in) {
1428 fprintf(stderr,
1429 "Invalid configuration, out argument buffer can not be random: %s\n",
1430 src);
1431 exit_report_result(PIGLIT_WARN);
1433 } else if(regex_match(value, REGEX_FULL_MATCH(REGEX_REPEAT))) {
1434 regmatch_t rmatch[3];
1435 char* repeat_value_str;
1437 regex_get_matches(value, REGEX_REPEAT, rmatch, 3, 0);
1438 regex_get_match_str(&repeat_value_str, value, rmatch, 2);
1440 get_test_arg_value(&test_arg,
1441 repeat_value_str,
1442 get_array_length(repeat_value_str));
1444 free(repeat_value_str);
1445 } else if(regex_match(value, REGEX_ARRAY)) {
1446 get_test_arg_value(&test_arg, value,
1447 image_elems * test_arg.cl_size);
1450 free(value);
1452 } else if(regex_match(src, REGEX_FULL_MATCH(REGEX_ARG_SAMPLER))) { // sampler
1453 char* str = NULL;
1455 /* Samplers are only allowed for in arguments */
1456 if(!arg_in) {
1457 fprintf(stderr,
1458 "Invalid configuration, only arg_in samplers are allowed: %s\n",
1459 src);
1460 exit_report_result(PIGLIT_WARN);
1463 test_arg.size = sizeof(cl_sampler);
1465 /* Set arg type */
1466 test_arg.type = TEST_ARG_SAMPLER;
1468 /* Normalized coords */
1469 regex_get_match_str(&str, src, pmatch, 2);
1470 test_arg.sampler_normalized_coords = get_bool(str);
1471 free(str);
1473 /* Addressing mode */
1474 regex_get_match_str(&str, src, pmatch, 3);
1475 if(regex_match(str, REGEX_FULL_MATCH("("REGEX_SAMP_ADDR_NONE")"))) {
1476 test_arg.sampler_addressing_mode = CL_ADDRESS_NONE;
1477 } else if(regex_match(str, REGEX_FULL_MATCH("("REGEX_SAMP_ADDR_CLAMP_TO_EDGE")"))) {
1478 test_arg.sampler_addressing_mode = CL_ADDRESS_CLAMP_TO_EDGE;
1479 } else if(regex_match(str, REGEX_FULL_MATCH("("REGEX_SAMP_ADDR_CLAMP")"))) {
1480 test_arg.sampler_addressing_mode = CL_ADDRESS_CLAMP;
1481 } else if(regex_match(str, REGEX_FULL_MATCH("("REGEX_SAMP_ADDR_REPEAT))) {
1482 test_arg.sampler_addressing_mode = CL_ADDRESS_REPEAT;
1483 } else if(regex_match(str, REGEX_FULL_MATCH("("REGEX_SAMP_ADDR_MIRRORED_REPEAT))) {
1484 test_arg.sampler_addressing_mode = CL_ADDRESS_MIRRORED_REPEAT;
1485 } else {
1486 fprintf(stderr, "Sampler addressing mode not supported: %s\n", str);
1487 exit_report_result(PIGLIT_WARN);
1489 free(str);
1491 /* Filter mode */
1492 regex_get_match_str(&str, src, pmatch, 4);
1493 if(regex_match(str, REGEX_FULL_MATCH("("REGEX_SAMP_FILT_NEAREST")"))) {
1494 test_arg.sampler_filter_mode = CL_FILTER_NEAREST;
1495 } else if(regex_match(str, REGEX_FULL_MATCH("("REGEX_SAMP_FILT_LINEAR")"))) {
1496 test_arg.sampler_filter_mode = CL_FILTER_LINEAR;
1497 } else {
1498 fprintf(stderr, "Sampler filter mode not supported: %s\n", str);
1499 exit_report_result(PIGLIT_WARN);
1501 free(str);
1504 if(arg_in) {
1505 if(!add_test_arg_in(test, test_arg)) {
1506 fprintf(stderr,
1507 "Invalid configuration, could not add in argument: %s\n",
1508 src);
1509 exit_report_result(PIGLIT_WARN);
1511 } else {
1512 if(!add_test_arg_out(test, test_arg)) {
1513 fprintf(stderr,
1514 "Invalid configuration, could not add out argument: %s\n",
1515 src);
1516 exit_report_result(PIGLIT_WARN);
1522 * Helper function for parsing a test name and checking for illegal characters.
1524 static char*
1525 parse_name(const char *input)
1527 char *name = add_dynamic_str_copy(input);
1528 int error;
1529 regex_t regex;
1530 regmatch_t pmatch[1];
1533 if ((error = regcomp(&regex, "\\([/%]\\)",0))) {
1534 char errbuf[100];
1535 regerror(error, &regex, errbuf, 100);
1536 fprintf(stderr, "Failed to compile regex for parse_name():%s\n", errbuf);
1537 return NULL;
1540 if (!regexec(&regex, input, 1, pmatch, 0)) {
1541 char bad_char = *(input + pmatch[0].rm_so);
1542 fprintf(stderr, "Illegal character in test name '%s': %c\n",
1543 input, bad_char);
1544 return NULL;
1547 regfree(&regex);
1548 return name;
1551 void
1552 parse_config(const char* config_str,
1553 struct piglit_cl_program_test_config* config)
1555 const char* pch;
1556 size_t length = strlen(config_str);
1558 char* line = NULL;
1559 char* section = NULL;
1560 char* key = NULL;
1561 char* value = NULL;
1563 struct test* test = NULL;
1565 bool config_found = false;
1566 bool test_found = false;
1568 enum state_t {
1569 SECTION_NONE,
1570 SECTION_CONFIG,
1571 SECTION_TEST,
1572 } state = SECTION_NONE;
1574 /* parse config string by each line */
1575 pch = config_str;
1576 while(pch < (config_str+length)) {
1577 regmatch_t pmatch[2];
1578 size_t line_length;
1580 /* Get line */
1581 regex_get_matches(pch, REGEX_LINE, pmatch, 2, REG_NEWLINE);
1582 line_length = pmatch[0].rm_eo - pmatch[0].rm_so;
1583 if(!regex_get_match_str(&line, pch, pmatch, 1)) {
1584 /* Line is empty */
1585 pch += line_length + 1;
1586 continue;
1589 /* Get more lines if it is a multiline */
1590 if( regex_match(line, REGEX_KEY_VALUE)
1591 && regex_match(line, REGEX_MULTILINE)) {
1592 char* multiline = malloc(sizeof(char));
1593 multiline[0] = '\0';
1595 free(line); line = NULL;
1597 while((pch <= (config_str+length))) {
1598 regmatch_t mmatch[2];
1599 char* old_multiline = multiline;
1600 char* new_multiline;
1602 /* Get line */
1603 regex_get_matches(pch, REGEX_LINE, pmatch, 2, REG_NEWLINE);
1604 line_length = pmatch[0].rm_eo - pmatch[0].rm_so;
1605 if(!regex_get_match_str(&line, pch, pmatch, 1)) {
1606 /* Line is empty */
1607 break;
1610 if(regex_match(line, REGEX_MULTILINE)) { // not last line
1611 regex_get_matches(line, REGEX_MULTILINE,
1612 mmatch, 2, REG_NEWLINE);
1613 if(!regex_get_match_str(&new_multiline, pch, mmatch, 1)) {
1614 /* Multiline is empty */
1615 pch += line_length + 1;
1616 continue;
1619 multiline = malloc(strlen(old_multiline) + strlen(new_multiline) + 1);
1620 strncpy(multiline, old_multiline, strlen(old_multiline));
1621 strcpy(multiline+strlen(old_multiline), new_multiline);
1623 pch += line_length+1;
1625 free(line); free(old_multiline); free(new_multiline);
1626 } else { // last line
1627 multiline = malloc(strlen(old_multiline) + strlen(line) + 1);
1628 strncpy(multiline, old_multiline, strlen(old_multiline));
1629 strcpy(multiline+strlen(old_multiline), line);
1631 free(line); free(old_multiline);
1632 break;
1636 line = multiline;
1639 /* parse line */
1640 if(regex_section(line, &section)) { // SECTION
1641 if(regex_match(section, "^config$")) { // config
1642 if(config_found) {
1643 fprintf(stderr, "Invalid configuration, [config] section can be defined only once\n");
1644 free(section); section = NULL;
1645 exit_report_result(PIGLIT_WARN);
1647 if(test_found) {
1648 fprintf(stderr, "Invalid configuration, [config] section must be declared before any [test] section\n");
1649 free(section); section = NULL;
1650 exit_report_result(PIGLIT_WARN);
1652 config_found = true;
1653 state = SECTION_CONFIG;
1654 } else if(regex_match(section, "^test$")) { // test
1655 if(!config_found) {
1656 fprintf(stderr, "Invalid configuration, [config] section must be declared before any [test] section\n");
1657 free(section); section = NULL;
1658 exit_report_result(PIGLIT_WARN);
1660 if(config->expect_build_fail) {
1661 fprintf(stderr, "Invalid configuration, no tests can be defined when expect_build_fail is true\n");
1662 free(section); section = NULL;
1663 exit_report_result(PIGLIT_WARN);
1665 test_found = true;
1666 add_test(create_test());
1667 test = &tests[num_tests-1];
1668 state = SECTION_TEST;
1669 } else if(regex_match(section, "^program source$")) { // program source
1670 pch += get_section_content(pch, &config->program_source);
1671 add_dynamic_str(config->program_source);
1672 state = SECTION_NONE;
1673 } else if(regex_match(section, "^program binary$")) { // program binary
1674 pch += get_section_content(pch, (char**)&config->program_binary);
1675 add_dynamic_str((char*)config->program_binary);
1676 state = SECTION_NONE;
1677 } else {
1678 fprintf(stderr,
1679 "Invalid configuration, configuration has an invalid section: [%s]\n",
1680 section);
1681 free(section); section = NULL;
1682 exit_report_result(PIGLIT_WARN);
1685 free(section); section = NULL;
1686 } else if(regex_key_value(line, &key, &value)) { // KEY : VALUE
1687 switch(state) {
1688 case SECTION_NONE:
1689 fprintf(stderr,
1690 "Invalid configuration, this key-value does not belong to any section: %s\n",
1691 line);
1692 free(key); key = NULL;
1693 free(value); value = NULL;
1694 exit_report_result(PIGLIT_WARN);
1695 break;
1696 case SECTION_CONFIG:
1697 if(regex_match(key, "^name$")) {
1698 config->name = parse_name(value);
1699 if (!config->name) {
1700 exit_report_result(PIGLIT_FAIL);
1702 } else if(regex_match(key, "^clc_version_min$")) {
1703 config->clc_version_min = get_int(value);
1704 } else if(regex_match(key, "clc_version_max$")) {
1705 config->clc_version_max = get_int(value);
1706 } else if(regex_match(key, "^platform_regex$")) {
1707 config->platform_regex = add_dynamic_str_copy(value);
1708 } else if(regex_match(key, "^device_regex$")) {
1709 config->device_regex = add_dynamic_str_copy(value);
1710 } else if(regex_match(key, "^require_platform_extensions$")) {
1711 config->require_platform_extensions =
1712 add_dynamic_str_copy(value);
1713 } else if(regex_match(key, "^require_device_extensions$")) {
1714 config->require_device_extensions =
1715 add_dynamic_str_copy(value);
1716 } else if(regex_match(key, "^program_source_file$")) {
1717 config->program_source_file = add_dynamic_str_copy(value);
1718 } else if(regex_match(key, "^program_binary_file$")) {
1719 config->program_binary_file = add_dynamic_str_copy(value);
1720 } else if(regex_match(key, "^build_options$")) {
1721 config->build_options = add_dynamic_str_copy(value);
1722 } else if(regex_match(key, "^kernel_name$")) {
1723 if(!regex_match(value, REGEX_NULL)) {
1724 config->kernel_name = add_dynamic_str_copy(value);
1725 } else {
1726 config->kernel_name = NULL;
1728 } else if(regex_match(key, "^expect_build_fail$")) {
1729 config->expect_build_fail = get_bool(value);
1730 } else if(regex_match(key, "^expect_test_fail$")) {
1731 expect_test_fail = get_bool(value);
1732 } else if(regex_match(key, "^need_image_support$")) {
1733 config->need_image_support = get_bool(value);
1734 } else if(regex_match(key, "^dimensions$")) {
1735 work_dimensions = get_uint(value);
1736 } else if(regex_match(key, "^global_size$")) {
1737 int i;
1738 uint64_t* int_global_work_size;
1739 get_uint_array(value, &int_global_work_size, 3);
1740 for(i = 0; i < 3; i++) {
1741 global_work_size[i] = int_global_work_size[i];
1743 free(int_global_work_size);
1744 } else if(regex_match(key, "^local_size$")) {
1745 if(!regex_match(value, REGEX_FULL_MATCH(REGEX_NULL))) {
1746 int i;
1747 uint64_t* int_local_work_size;
1748 get_uint_array(value, &int_local_work_size, 3);
1749 for(i = 0; i < 3; i++) {
1750 local_work_size[i] = int_local_work_size[i];
1752 local_work_size_null = false;
1753 free(int_local_work_size);
1754 } else {
1755 local_work_size_null = true;
1757 } else if(regex_match(key, "^global_offset$")) {
1758 if(!regex_match(value, REGEX_FULL_MATCH(REGEX_NULL))) {
1759 int i;
1760 uint64_t* int_global_offset;
1761 get_uint_array(value, &int_global_offset, 3);
1762 for(i = 0; i < 3; i++) {
1763 global_offset[i] = int_global_offset[i];
1765 global_offset_null = false;
1766 free(int_global_offset);
1767 } else {
1768 global_offset_null = true;
1770 } else {
1771 fprintf(stderr,
1772 "Invalid configuration, key '%s' does not belong to a [config] section: %s\n",
1773 key, line);
1774 free(key); key = NULL;
1775 free(value); value = NULL;
1776 exit_report_result(PIGLIT_WARN);
1778 break;
1779 case SECTION_TEST:
1780 if(regex_match(key, "^name$")) {
1781 test->name = parse_name(value);
1782 if (!test->name) {
1783 exit_report_result(PIGLIT_FAIL);
1785 } else if(regex_match(key, "^kernel_name$")) {
1786 test->kernel_name = add_dynamic_str_copy(value); // test can't have kernel_name == NULL like config section
1787 } else if(regex_match(key, "^expect_test_fail$")) {
1788 test->expect_test_fail = get_bool(value);
1789 } else if(regex_match(key, "^dimensions$")) {
1790 test->work_dimensions = get_uint(value);
1791 } else if(regex_match(key, "^global_size$")) {
1792 int i;
1793 uint64_t* int_global_work_size;
1794 get_uint_array(value, &int_global_work_size, 3);
1795 for(i = 0; i < 3; i++) {
1796 test->global_work_size[i] = int_global_work_size[i];
1798 free(int_global_work_size);
1799 } else if(regex_match(key, "^local_size$")) {
1800 if(!regex_match(value, REGEX_FULL_MATCH(REGEX_NULL))) {
1801 int i;
1802 uint64_t* int_local_work_size;
1803 get_uint_array(value, &int_local_work_size, 3);
1804 for(i = 0; i < 3; i++) {
1805 test->local_work_size[i] = int_local_work_size[i];
1807 test->local_work_size_null = false;
1808 free(int_local_work_size);
1809 } else {
1810 test->local_work_size_null = true;
1812 } else if(regex_match(key, "^global_offset$")) {
1813 if(!regex_match(value, REGEX_FULL_MATCH(REGEX_NULL))) {
1814 int i;
1815 uint64_t* int_global_offset;
1816 get_uint_array(value, &int_global_offset, 3);
1817 for(i = 0; i < 3; i++) {
1818 test->global_offset[i] = int_global_offset[i];
1820 test->global_offset_null = false;
1821 free(int_global_offset);
1822 } else {
1823 test->global_offset_null = true;
1825 } else if(regex_match(key, "^arg_in$")) {
1826 get_test_arg(value, test, true);
1827 } else if(regex_match(key, "^arg_out$")) {
1828 get_test_arg(value, test, false);
1829 } else {
1830 fprintf(stderr,
1831 "Invalid configuration, key '%s' does not belong to a [test] section: %s\n",
1832 key, line);
1833 free(key); key = NULL;
1834 free(value); value = NULL;
1835 exit_report_result(PIGLIT_WARN);
1837 break;
1840 free(key); key = NULL;
1841 free(value); value = NULL;
1842 } else if(!regex_match(line, REGEX_IGNORE)){ // not WHITESPACE or COMMENT
1843 fprintf(stderr,
1844 "Invalid configuration, configuration could not be parsed: %s\n",
1845 line);
1846 exit_report_result(PIGLIT_WARN);
1849 /* Go to next line */
1850 free(line); line = NULL;
1851 pch += line_length+1;
1854 if(!config_found) {
1855 fprintf(stderr, "Invalid configuration, configuration is missing a [config] section.\n");
1856 exit_report_result(PIGLIT_WARN);
1860 /* Get configuration from comment */
1862 char*
1863 get_comment_config_str(const char* src)
1865 char* config_str = NULL;
1866 regmatch_t pmatch[2];
1868 if(regex_get_matches(src, REGEX_COMMENT_CONFIG, pmatch, 2, 0)) {
1869 if(regex_get_match_str(&config_str, src, pmatch, 1)) {
1870 return config_str;
1874 return NULL;
1877 /* Init */
1879 void
1880 init(const int argc,
1881 const char** argv,
1882 struct piglit_cl_program_test_config* config)
1884 const char * main_argument = piglit_cl_get_unnamed_arg(argc, argv, 0);
1885 const char * config_file = NULL;
1887 char* config_str = NULL;
1888 unsigned int config_str_size;
1889 bool config_arg_present = piglit_cl_is_arg_defined(argc, argv, "config");
1891 enum main_argument_type_t {
1892 ARG_CONFIG,
1893 ARG_SOURCE,
1894 ARG_BINARY
1895 } main_argument_type;
1897 FILE* temp_file;
1899 int program_count = 0;
1901 /* Check if arguments are valid */
1902 // valid main argument
1903 if(main_argument == NULL) {
1904 if(argc == 1) {
1905 print_usage(argc, argv);
1906 exit_report_result(PIGLIT_WARN);
1907 } else {
1908 print_usage_and_warn(argc, argv, "No main argument.");
1911 if(!regex_match(main_argument, "\\.(cl|program_test|bin)$")) {
1912 print_usage_and_warn(argc, argv, "Invalid main argument.");
1914 temp_file = fopen(main_argument, "r");
1915 if(temp_file == NULL) {
1916 print_usage_and_warn(argc, argv, "%s does not exist.", main_argument);
1918 fclose(temp_file);
1919 // valid config argument
1920 if(config_arg_present) {
1921 config_file = piglit_cl_get_arg_value(argc, argv, "config");
1922 if(!regex_match(config_file, "\\.program_test$")) {
1923 print_usage_and_warn(argc, argv, "Invalid config argument.");
1925 temp_file = fopen(config_file, "r");
1926 if(temp_file == NULL) {
1927 print_usage_and_warn(argc, argv, "%s does not exist.", config_file);
1929 fclose(temp_file);
1931 // no config argument if using .program_test
1932 if(regex_match(main_argument, "\\.program_test$") && config_arg_present) {
1933 print_usage_and_warn(argc,
1934 argv,
1935 "Cannot use config argument if main argument is already a config file.");
1938 /* Get main_argument type and config string */
1939 if(regex_match(main_argument, "\\.program_test$")) {
1940 main_argument_type = ARG_CONFIG;
1942 config_file = main_argument;
1943 config_str = piglit_load_text_file(config_file, &config_str_size);
1944 } else if(regex_match(main_argument, "\\.cl$")) {
1945 main_argument_type = ARG_SOURCE;
1947 if(config_arg_present) {
1948 config_file = piglit_cl_get_arg_value(argc, argv, "config");
1949 config_str = piglit_load_text_file(config_file, &config_str_size);
1950 } else {
1951 char* source_str;
1953 config_file = main_argument;
1954 source_str = piglit_load_text_file(config_file, &config_str_size);
1955 config_str = get_comment_config_str(source_str);
1957 free(source_str);
1959 } else if(regex_match(main_argument, "\\.bin$")) {
1960 main_argument_type = ARG_BINARY;
1962 config_file = piglit_cl_get_arg_value(argc, argv, "config");
1963 config_str = piglit_load_text_file(config_file, &config_str_size);
1964 } else {
1965 fprintf(stderr, "Ops, this should not happen!\n");
1966 exit_report_result(PIGLIT_WARN);
1969 /* Parse test configuration */
1970 if(config_str != NULL) {
1971 parse_config(config_str, config);
1972 free(config_str);
1973 } else {
1974 fprintf(stderr, "No configuration found.\n");
1977 /* Set program */
1978 switch(main_argument_type) {
1979 case ARG_CONFIG:
1980 if( config->program_source_file != NULL
1981 || config->program_binary_file != NULL) {
1982 const char* program_file = NULL;
1983 char* main_arg_copy = NULL;
1984 char* dname = NULL;
1985 char* full_path_file = NULL;
1987 if(config->program_source_file != NULL) {
1988 program_file = config->program_source_file;
1989 } else {
1990 program_file = config->program_binary_file;
1993 main_arg_copy = strdup(main_argument);
1994 dname = dirname(main_arg_copy);
1995 full_path_file = malloc(strlen(dname) + strlen(program_file) + 2); // +2 for '/' and '\0'
1996 strcpy(full_path_file, dname);
1997 full_path_file[strlen(dname)] = '/';
1998 strcpy(full_path_file+strlen(dname)+1, program_file);
2000 if(config->program_source_file != NULL) {
2001 config->program_source_file = full_path_file;
2002 } else {
2003 config->program_binary_file = full_path_file;
2006 add_dynamic_str(full_path_file);
2007 free(main_arg_copy);
2009 break;
2010 case ARG_SOURCE:
2011 config->program_source_file = add_dynamic_str_copy(main_argument);
2012 break;
2013 case ARG_BINARY:
2014 config->program_binary_file = add_dynamic_str_copy(main_argument);
2015 break;
2018 /* Check if there is one program_* set */
2019 if(config->program_source != NULL) program_count++;
2020 if(config->program_source_file != NULL) program_count++;
2021 if(config->program_binary != NULL) program_count++;
2022 if(config->program_binary_file != NULL) program_count++;
2023 if(program_count == 0) {
2024 fprintf(stderr, "Invalid configuration, no program defined.\n");
2025 exit_report_result(PIGLIT_WARN);
2026 } else if (program_count > 1) {
2027 fprintf(stderr, "Invalid configuration, multiple programs defined.\n");
2028 exit_report_result(PIGLIT_WARN);
2031 /* Run test per device */
2032 config->run_per_device = true;
2035 /* Memory object functions */
2037 struct mem_arg {
2038 cl_uint index;
2039 cl_mem mem;
2040 cl_mem_object_type type;
2043 void
2044 free_mem_args(struct mem_arg** mem_args, unsigned int* num_mem_args)
2046 unsigned i;
2048 for(i = 0; i < *num_mem_args; i++) {
2049 clReleaseMemObject((*mem_args)[i].mem);
2052 free(*mem_args); *mem_args = NULL;
2053 *num_mem_args = 0;
2056 void
2057 free_sampler_args(cl_sampler** sampler_args, unsigned int* num_sampler_args)
2059 unsigned i;
2061 for(i = 0; i < *num_sampler_args; i++) {
2062 clReleaseSampler((*sampler_args)[i]);
2065 free(*sampler_args); *sampler_args = NULL;
2066 *num_sampler_args = 0;
2069 bool
2070 check_test_arg_value(struct test_arg test_arg,
2071 void* value)
2073 size_t i; // index in array
2074 size_t c; // component in element
2075 size_t ra; // offset from the beginning of parsed array
2076 size_t rb; // offset from the beginning of buffer
2078 #define CASEI(enum_type, type, cl_type) \
2079 case enum_type: \
2080 for(i = 0; i < test_arg.length; i++) { \
2081 for(c = 0; c < test_arg.cl_size; c++) { \
2082 rb = i*test_arg.cl_mem_size + c; \
2083 if(!piglit_cl_probe_integer(((cl_type*)value)[rb], \
2084 ((cl_type*)test_arg.value)[rb], \
2085 test_arg.toli)) { \
2086 ra = i*test_arg.cl_size + c; \
2087 printf("Error at %s[%zu]\n", type, ra); \
2088 return false; \
2092 return true;
2093 #define CASEU(enum_type, type, cl_type) \
2094 case enum_type: \
2095 for(i = 0; i < test_arg.length; i++) { \
2096 for(c = 0; c < test_arg.cl_size; c++) { \
2097 rb = i*test_arg.cl_mem_size + c; \
2098 if(!piglit_cl_probe_uinteger(((cl_type*)value)[rb], \
2099 ((cl_type*)test_arg.value)[rb], \
2100 test_arg.tolu)) { \
2101 ra = i*test_arg.cl_size + c; \
2102 printf("Error at %s[%zu]\n", type, ra); \
2103 return false; \
2107 return true;
2108 #define CASEH(enum_type, type, cl_type) \
2109 case enum_type: \
2110 for(i = 0; i < test_arg.length; i++) { \
2111 for(c = 0; c < test_arg.cl_size; c++) { \
2112 rb = i*test_arg.cl_mem_size + c; \
2113 if(!piglit_cl_probe_half(((cl_type*)value)[rb], \
2114 ((cl_type*)test_arg.value)[rb], \
2115 test_arg.ulp)) { \
2116 ra = i*test_arg.cl_size + c; \
2117 printf("Error at %s[%zu]\n", type, ra); \
2118 return false; \
2122 return true;
2123 #define CASEF(enum_type, type, cl_type, testfn) \
2124 case enum_type: \
2125 for(i = 0; i < test_arg.length; i++) { \
2126 for(c = 0; c < test_arg.cl_size; c++) { \
2127 rb = i*test_arg.cl_mem_size + c; \
2128 if(!testfn(((cl_type*)value)[rb], \
2129 ((cl_type*)test_arg.value)[rb], \
2130 test_arg.ulp)) { \
2131 ra = i*test_arg.cl_size + c; \
2132 printf("Error at %s[%zu]\n", type, ra); \
2133 return false; \
2137 return true;
2139 switch(test_arg.cl_type) {
2140 CASEI(TYPE_CHAR, "char", cl_char)
2141 CASEU(TYPE_UCHAR, "uchar", cl_uchar)
2142 CASEI(TYPE_SHORT, "short", cl_short)
2143 CASEU(TYPE_USHORT, "ushort", cl_ushort)
2144 CASEI(TYPE_INT, "int", cl_int)
2145 CASEU(TYPE_UINT, "uint", cl_uint)
2146 CASEI(TYPE_LONG, "long", cl_long)
2147 CASEU(TYPE_ULONG, "ulong", cl_ulong)
2148 CASEH(TYPE_HALF, "half", cl_half)
2149 CASEF(TYPE_FLOAT, "float", cl_float, piglit_cl_probe_floating)
2150 CASEF(TYPE_DOUBLE, "double", cl_double, piglit_cl_probe_double)
2153 #undef CASEF
2154 #undef CASEU
2155 #undef CASEI
2157 return true;
2160 /* Run the kernel test */
2161 enum piglit_result
2162 test_kernel(const struct piglit_cl_program_test_config* config,
2163 const struct piglit_cl_program_test_env* env,
2164 struct test test)
2166 enum piglit_result result = PIGLIT_PASS;
2168 // all
2169 unsigned j;
2170 char* kernel_name;
2171 cl_kernel kernel;
2173 // setting/validating arguments
2174 struct mem_arg* mem_args = NULL;
2175 unsigned int num_mem_args = 0;
2177 cl_sampler *sampler_args = NULL;
2178 unsigned int num_sampler_args = 0;
2180 /* Check if this device supports the local work size. */
2181 if (!piglit_cl_framework_check_local_work_size(env->device_id,
2182 test.local_work_size)) {
2183 return PIGLIT_SKIP;
2186 /* Create or use appropriate kernel */
2187 if(test.kernel_name == NULL) {
2188 kernel_name = config->kernel_name;
2189 kernel = env->kernel;
2191 if(config->kernel_name == NULL) {
2192 printf("No kernel_name defined\n");
2193 return PIGLIT_WARN;
2194 } else {
2195 clRetainKernel(kernel);
2197 } else {
2198 kernel_name = test.kernel_name;
2199 kernel = piglit_cl_create_kernel(env->program, test.kernel_name);
2201 if(kernel == NULL) {
2202 printf("Could not create kernel %s\n", kernel_name);
2203 return PIGLIT_FAIL;
2207 printf("Using kernel %s\n", kernel_name);
2209 /* Set kernel args */
2210 printf("Setting kernel arguments...\n");
2212 for(j = 0; j < test.num_args_in; j++) {
2213 bool arg_set = false;
2214 struct test_arg test_arg = test.args_in[j];
2216 switch(test_arg.type) {
2217 case TEST_ARG_VALUE:
2218 arg_set = piglit_cl_set_kernel_arg(kernel,
2219 test_arg.index,
2220 test_arg.size,
2221 test_arg.value);
2222 break;
2223 case TEST_ARG_BUFFER: {
2224 struct mem_arg mem_arg;
2225 mem_arg.index = test_arg.index;
2226 mem_arg.type = CL_MEM_OBJECT_BUFFER;
2228 if(test_arg.value != NULL) {
2229 mem_arg.mem = piglit_cl_create_buffer(env->context,
2230 CL_MEM_READ_WRITE,
2231 test_arg.size);
2232 if( mem_arg.mem != NULL
2233 && piglit_cl_write_buffer(env->context->command_queues[0],
2234 mem_arg.mem,
2236 test_arg.size,
2237 test_arg.value)
2238 && piglit_cl_set_kernel_arg(kernel,
2239 mem_arg.index,
2240 sizeof(cl_mem),
2241 &mem_arg.mem)) {
2242 arg_set = true;
2244 } else {
2245 mem_arg.mem = NULL;
2246 arg_set = piglit_cl_set_kernel_arg(kernel,
2247 mem_arg.index,
2248 sizeof(cl_mem),
2249 NULL);
2252 if(arg_set) {
2253 add_dynamic_array((void**)&mem_args,
2254 &num_mem_args,
2255 sizeof(struct mem_arg),
2256 &mem_arg);
2258 break;
2260 case TEST_ARG_IMAGE: {
2261 struct mem_arg mem_arg;
2262 mem_arg.index = test_arg.index;
2263 mem_arg.type = test_arg.image_desc.image_type;
2265 if(!test_arg.value) {
2266 printf("Image argument cannot be null.\n");
2267 arg_set = false;
2268 break;
2271 mem_arg.mem = piglit_cl_create_image(env->context,
2272 CL_MEM_READ_ONLY,
2273 &test_arg.image_format,
2274 &test_arg.image_desc);
2275 if( mem_arg.mem != NULL
2276 && piglit_cl_write_whole_image(env->context->command_queues[0],
2277 mem_arg.mem,
2278 test_arg.value)
2279 && piglit_cl_set_kernel_arg(kernel,
2280 mem_arg.index,
2281 sizeof(cl_mem),
2282 &mem_arg.mem)) {
2283 arg_set = true;
2286 if(arg_set) {
2287 add_dynamic_array((void**)&mem_args,
2288 &num_mem_args,
2289 sizeof(struct mem_arg),
2290 &mem_arg);
2292 break;
2294 case TEST_ARG_SAMPLER: {
2295 cl_sampler sampler = piglit_cl_create_sampler(
2296 env->context,
2297 test_arg.sampler_normalized_coords,
2298 test_arg.sampler_addressing_mode,
2299 test_arg.sampler_filter_mode);
2301 if(!sampler) {
2302 arg_set = false;
2303 break;
2306 arg_set = piglit_cl_set_kernel_arg(kernel,
2307 test_arg.index,
2308 test_arg.size,
2309 &sampler);
2311 if(arg_set) {
2312 add_dynamic_array((void**)&sampler_args,
2313 &num_sampler_args,
2314 sizeof(cl_sampler),
2315 &sampler);
2317 break;
2320 if(!arg_set) {
2321 printf("Failed to set kernel argument with index %u\n",
2322 test_arg.index);
2323 clReleaseKernel(kernel);
2324 free_mem_args(&mem_args, &num_mem_args);
2325 free_sampler_args(&sampler_args, &num_sampler_args);
2326 return PIGLIT_FAIL;
2330 for(j = 0; j < test.num_args_out; j++) {
2331 bool arg_set = false;
2332 struct test_arg test_arg = test.args_out[j];
2334 switch(test_arg.type) {
2335 case TEST_ARG_VALUE:
2336 // not accepted by parser
2337 break;
2338 case TEST_ARG_BUFFER: {
2339 unsigned k;
2340 bool fail = false;
2341 struct mem_arg mem_arg;
2342 mem_arg.index = test_arg.index;
2343 mem_arg.type = CL_MEM_OBJECT_BUFFER;
2345 for(k = 0; k < num_mem_args; k++) {
2346 if(mem_args[k].index != mem_arg.index)
2347 continue;
2349 if(mem_args[k].type != mem_arg.type) {
2350 printf("Inconsistent types specified for in-out"
2351 "argument %d: arg_in: %s, arg_out: %s.\n",
2352 mem_arg.index,
2353 piglit_cl_get_enum_name(mem_args[k].type),
2354 piglit_cl_get_enum_name(mem_arg.type));
2355 arg_set = false;
2356 fail = true;
2357 break;
2359 arg_set = true;
2361 if(arg_set || fail) {
2362 break;
2365 if(test_arg.value != NULL) {
2366 mem_arg.mem = piglit_cl_create_buffer(env->context,
2367 CL_MEM_READ_WRITE,
2368 test_arg.size);
2369 if( mem_arg.mem != NULL
2370 && piglit_cl_set_kernel_arg(kernel,
2371 mem_arg.index,
2372 sizeof(cl_mem),
2373 &mem_arg.mem)) {
2374 arg_set = true;
2376 } else {
2377 mem_arg.mem = NULL;
2378 arg_set = piglit_cl_set_kernel_arg(kernel,
2379 mem_arg.index,
2380 sizeof(cl_mem),
2381 NULL);
2384 if(arg_set) {
2385 add_dynamic_array((void**)&mem_args,
2386 &num_mem_args,
2387 sizeof(struct mem_arg),
2388 &mem_arg);
2390 break;
2392 case TEST_ARG_IMAGE: {
2393 unsigned k;
2394 bool fail = false;
2395 struct mem_arg mem_arg;
2396 mem_arg.index = test_arg.index;
2397 mem_arg.type = test_arg.image_desc.image_type;
2399 for(k = 0; k < num_mem_args; k++) {
2400 if(mem_args[k].index == mem_arg.index) {
2401 printf("Argument %d: images cannot be in-out arguments.",
2402 mem_arg.index);
2403 arg_set = false;
2404 fail = true;
2405 break;
2408 if(fail) {
2409 break;
2412 if(!test_arg.value) {
2413 printf("Image argument cannot be null.\n");
2414 arg_set = false;
2415 break;
2418 mem_arg.mem = piglit_cl_create_image(env->context,
2419 CL_MEM_WRITE_ONLY,
2420 &test_arg.image_format,
2421 &test_arg.image_desc);
2422 if( mem_arg.mem != NULL
2423 && piglit_cl_set_kernel_arg(kernel,
2424 mem_arg.index,
2425 sizeof(cl_mem),
2426 &mem_arg.mem)) {
2427 arg_set = true;
2430 if(arg_set) {
2431 add_dynamic_array((void**)&mem_args,
2432 &num_mem_args,
2433 sizeof(struct mem_arg),
2434 &mem_arg);
2436 break;
2438 case TEST_ARG_SAMPLER:
2439 // not accepted by parser
2440 break;
2443 if(!arg_set) {
2444 printf("Failed to set kernel argument with index %u\n",
2445 test_arg.index);
2446 clReleaseKernel(kernel);
2447 free_mem_args(&mem_args, &num_mem_args);
2448 free_sampler_args(&sampler_args, &num_sampler_args);
2449 return PIGLIT_FAIL;
2453 /* Execute kernel */
2454 printf("Running the kernel...\n");
2456 if(!piglit_cl_execute_ND_range_kernel(env->context->command_queues[0],
2457 kernel,
2458 test.work_dimensions,
2459 test.global_offset_null ? NULL : test.global_offset,
2460 test.global_work_size,
2461 test.local_work_size_null ? NULL : test.local_work_size)) {
2462 printf("Failed to enqueue the kernel\n");
2463 clReleaseKernel(kernel);
2464 free_mem_args(&mem_args, &num_mem_args);
2465 free_sampler_args(&sampler_args, &num_sampler_args);
2466 return PIGLIT_FAIL;
2469 /* Check results */
2470 printf("Validating results...\n");
2472 for(j = 0; j < test.num_args_out; j++) {
2473 unsigned k;
2474 bool arg_valid = false;
2475 struct test_arg test_arg = test.args_out[j];
2477 switch(test_arg.type) {
2478 case TEST_ARG_VALUE:
2479 // Not accepted by parser
2480 break;
2481 case TEST_ARG_BUFFER: {
2482 struct mem_arg mem_arg;
2484 /* Find the right buffer */
2485 for(k = 0; k < num_mem_args; k++) {
2486 if(mem_args[k].index == test_arg.index) {
2487 mem_arg = mem_args[k];
2491 if(test_arg.value != NULL) {
2492 void* read_value = malloc(test_arg.size);
2494 if(piglit_cl_read_buffer(env->context->command_queues[0],
2495 mem_arg.mem,
2497 test_arg.size,
2498 read_value)) {
2499 arg_valid = true;
2500 if(check_test_arg_value(test_arg, read_value)) {
2501 printf(" Argument %u: PASS%s\n",
2502 test_arg.index,
2503 !test.expect_test_fail ? "" : " (not expected)");
2504 if(test.expect_test_fail) {
2505 piglit_merge_result(&result, PIGLIT_FAIL);
2507 } else {
2508 printf(" Argument %u: FAIL%s\n",
2509 test_arg.index,
2510 !test.expect_test_fail ? "" : " (expected)");
2511 if(!test.expect_test_fail) {
2512 piglit_merge_result(&result, PIGLIT_FAIL);
2517 free(read_value);
2520 break;
2522 case TEST_ARG_IMAGE: {
2523 struct mem_arg mem_arg;
2525 /* Find the right buffer */
2526 for(k = 0; k < num_mem_args; k++) {
2527 if(mem_args[k].index == test_arg.index) {
2528 mem_arg = mem_args[k];
2532 if(test_arg.value != NULL) {
2533 void* read_value = malloc(test_arg.size);
2535 if(piglit_cl_read_whole_image(env->context->command_queues[0],
2536 mem_arg.mem,
2537 read_value)) {
2538 arg_valid = true;
2539 if(check_test_arg_value(test_arg, read_value)) {
2540 printf(" Argument %u: PASS%s\n",
2541 test_arg.index,
2542 !test.expect_test_fail ? "" : " (not expected)");
2543 if(test.expect_test_fail) {
2544 piglit_merge_result(&result, PIGLIT_FAIL);
2546 } else {
2547 printf(" Argument %u: FAIL%s\n",
2548 test_arg.index,
2549 !test.expect_test_fail ? "" : " (expected)");
2550 if(!test.expect_test_fail) {
2551 piglit_merge_result(&result, PIGLIT_FAIL);
2556 free(read_value);
2559 break;
2561 case TEST_ARG_SAMPLER:
2562 // Not accepted by parser
2563 break;
2566 if(!arg_valid) {
2567 printf("Failed to validate kernel argument with index %u\n",
2568 test_arg.index);
2569 clReleaseKernel(kernel);
2570 free_mem_args(&mem_args, &num_mem_args);
2571 free_sampler_args(&sampler_args, &num_sampler_args);
2572 return PIGLIT_FAIL;
2576 /* Clean memory used by test */
2577 clReleaseKernel(kernel);
2578 free_mem_args(&mem_args, &num_mem_args);
2579 free_sampler_args(&sampler_args, &num_sampler_args);
2580 return result;
2583 /* Run test */
2585 enum piglit_result
2586 piglit_cl_test(const int argc,
2587 const char** argv,
2588 const struct piglit_cl_program_test_config* config,
2589 const struct piglit_cl_program_test_env* env)
2591 enum piglit_result result = PIGLIT_SKIP;
2593 unsigned i;
2595 /* Print building status */
2596 if(!config->expect_build_fail) {
2597 printf("Program has been built successfully\n");
2598 } else {
2599 printf("Program has failed to build as expected\n");
2602 /* If num_tests is 0, then we are running a build test and the fact
2603 * that we have made it this far means that the program has built
2604 * successfully, so we can report PIGLIT_PASS.
2606 if (num_tests == 0) {
2607 result = PIGLIT_PASS;
2610 /* Run the tests */
2611 for(i = 0; i< num_tests; i++) {
2612 enum piglit_result test_result;
2613 char* test_name = tests[i].name != NULL ? tests[i].name : "";
2615 printf("> Running kernel test: %s\n", test_name);
2617 test_result = test_kernel(config, env, tests[i]);
2618 piglit_merge_result(&result, test_result);
2620 piglit_report_subtest_result(test_result, "%s", tests[i].name);
2623 /* Print result */
2624 if(num_tests > 0) {
2625 switch(result) {
2626 case PIGLIT_FAIL:
2627 printf(">> Some or all of the tests FAILED\n");
2628 break;
2629 case PIGLIT_SKIP:
2630 printf(">> Tests skipped\n");
2631 break;
2632 case PIGLIT_WARN:
2633 printf(">> Some or all of the tests produced a WARNING\n");
2634 break;
2635 case PIGLIT_PASS:
2636 printf(">> All of the tests PASSED\n");
2637 break;
2641 return result;