cmake: respect indentation
[piglit.git] / tests / util / piglit-util.h
blobde999980b6fd21f4d81c0d91d0278dc74df47ae3
1 /*
2 * Copyright (c) The Piglit project 2007
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 * on the rights to use, copy, modify, merge, publish, distribute, sub
8 * license, and/or sell copies of the Software, and to permit persons to whom
9 * the 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 NON-INFRINGEMENT. IN NO EVENT SHALL
18 * VA LINUX SYSTEM, IBM AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
19 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
20 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
21 * USE OR OTHER DEALINGS IN THE SOFTWARE.
24 #pragma once
25 #ifndef PIGLIT_UTIL_H
26 #define PIGLIT_UTIL_H
28 #ifdef __cplusplus
29 extern "C" {
30 #endif
32 #include "config.h"
34 #if defined(_WIN32)
36 #include <windows.h>
38 /* Another two macros provided by windows.h which conflict with piglit */
39 #undef near
40 #undef far
41 #define strdup _strdup
43 #endif
45 #include <assert.h>
46 #include <stdbool.h>
47 #include <stdint.h>
48 #include <string.h>
49 #include <stdio.h>
50 #include <stdlib.h>
51 #include <stdarg.h>
52 #include <math.h>
53 #include <float.h>
55 #ifdef HAVE_LIBGEN_H
56 # include <libgen.h> // for basename
57 #elif defined(_MSC_VER)
59 static inline char *
60 basename(const char *path)
62 static char path_buffer[_MAX_PATH];
63 char drive[_MAX_DRIVE];
64 char dir[_MAX_DIR];
65 char fname[_MAX_FNAME];
66 char ext[_MAX_EXT];
68 _splitpath(path, drive, dir, fname, ext);
69 _makepath(path_buffer, NULL , NULL, fname, ext);
70 return path_buffer;
73 #endif
75 #include "piglit-log.h"
77 #ifndef __has_attribute
78 #define __has_attribute(x) 0
79 #endif
81 #if defined(__GNUC__) || __has_attribute(noreturn)
82 #define NORETURN __attribute__((noreturn))
83 #elif defined(_MSC_VER)
84 #define NORETURN __declspec(noreturn)
85 #else
86 #define NORETURN
87 #endif
89 #ifndef HAVE_ASPRINTF
90 int asprintf(char **strp, const char *fmt, ...) PRINTFLIKE(2, 3);
91 #endif /* HAVE_ASPRINTF */
93 #ifndef HAVE_FFS
94 #ifdef __MINGW32__
95 #define ffs __builtin_ffs
96 #else /* !__MINGW32__ */
98 /**
99 * Find the first bit set in i and return the index set of that bit.
101 static inline int
102 ffs(int i)
104 int bit;
106 if (i == 0) {
107 return 0;
110 for (bit = 1; !(i & 1); bit++) {
111 i = i >> 1;
114 return bit;
117 #endif /* !__MINGW32__ */
118 #endif /* !HAVE_FFS*/
120 #ifndef HAVE_HTOBE32
121 static inline uint32_t
122 htobe32(uint32_t host_32bits)
124 #ifdef __BIG_ENDIAN__
125 return host_32bits;
126 #else
127 return ((host_32bits >> 24) & 0x000000FF) |
128 ((host_32bits >> 16) & 0x0000FF00) |
129 ((host_32bits >> 8) & 0x00FF0000) |
130 (host_32bits & 0xFF000000);
131 #endif
133 #endif /* HAVE_ASPRINTF */
135 #ifdef _WIN32
136 # define PIGLIT_PATH_SEP '\\'
137 #else
138 # define PIGLIT_PATH_SEP '/'
139 #endif
141 enum piglit_result {
142 PIGLIT_PASS,
143 PIGLIT_FAIL,
144 PIGLIT_SKIP,
145 PIGLIT_WARN
149 * An individual subtest that makes up part of a test group.
151 struct piglit_subtest {
152 /** Name of the subtest as it will appear in the log. */
153 const char *name;
155 /** Command line name used to select this test. */
156 const char *option;
158 /** Function that implements the test. */
159 enum piglit_result (*subtest_func)(void *data);
161 /** Passed as the data parameter to subtest_func.*/
162 void *data;
166 * Detect the end of an array of piglit_subtest structures
168 * The array of subtests is terminated by structure with a \c NULL \c
169 * name pointer.
171 #define PIGLIT_SUBTEST_END(s) ((s)->name == NULL)
173 const struct piglit_subtest*
174 piglit_find_subtest(const struct piglit_subtest *subtests, const char *name);
176 enum piglit_result
177 piglit_run_selected_subtests(const struct piglit_subtest *all_subtests,
178 const char **selected_subtests,
179 size_t num_selected_subtests,
180 enum piglit_result previous_result);
182 void
183 piglit_register_subtests(const char *names[]);
185 #define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
187 #define CLAMP( X, MIN, MAX ) ( (X)<(MIN) ? (MIN) : ((X)>(MAX) ? (MAX) : (X)) )
188 #define MIN2(a, b) ((a) > (b) ? (b) : (a))
189 #define MAX2(a, b) ((a) > (b) ? (a) : (b))
190 #define MIN3(a, b, c) MIN2(MIN2((a), (b)), (c))
191 #define MAX3(a, b, c) MAX2(MAX2((a), (b)), (c))
192 #define ALIGN(value, alignment) (((value) + alignment - 1) & ~(alignment - 1))
195 * Utility macro that checks for a given opengl error, and report a
196 * subtest result.
198 #define PIGLIT_SUBTEST_ERROR(error, global, ...) \
199 do { \
200 bool local = piglit_check_gl_error((error)); \
201 global = global && local; \
202 piglit_report_subtest_result(local ? PIGLIT_PASS : PIGLIT_FAIL, \
203 __VA_ARGS__); \
204 } while (0)
207 * Utility macro that checks for a given condition, and report a
208 * subtest result.
210 #define PIGLIT_SUBTEST_CONDITION(condition, global, ...) \
211 do { \
212 bool cond = (condition); \
213 global = global && cond; \
214 piglit_report_subtest_result(cond ? PIGLIT_PASS : PIGLIT_FAIL, \
215 __VA_ARGS__); \
216 } while (0)
218 static inline unsigned
219 log2u(unsigned v)
221 #ifdef __GCC__
222 return v == 0 ? 0 : 31 - __builtin_clz(v);
223 #else
224 unsigned res = 0;
226 while (v >>= 1)
227 res++;
229 return res;
230 #endif
234 * Returns the smallest power-of-two integer greater than or equal to v
236 static inline unsigned
237 next_power_of_two(unsigned v)
239 /* Special case zero because 1U << 32 is undefined. */
240 return v == 0 ? 1 : 1U << (log2u(v - 1) + 1);
245 * Return true if and only if two string are equal according to strcmp().
247 static inline bool
248 streq(const char *a, const char *b)
250 return strcmp(a, b) == 0;
254 * Wrapper for strtod() which also handles +/-inf with MSVC.
255 * Note: we only check for "inf" and not "INF".
257 static inline double
258 strtod_inf(const char *nptr, char **endptr)
260 return strtod(nptr, endptr);
264 * Wrapper for strtod_inf() which allows using an exact hex bit
265 * pattern to generate a float value.
267 static inline float
268 strtof_hex(const char *nptr, char **endptr)
270 /* skip spaces and tabs */
271 while (*nptr == ' ' || *nptr == '\t')
272 nptr++;
274 if (strncmp(nptr, "0x", 2) == 0) {
275 union {
276 uint32_t u;
277 float f;
278 } x;
280 x.u = strtoul(nptr, endptr, 16);
281 return x.f;
282 } else {
283 return strtod_inf(nptr, endptr);
288 * Wrapper for strtod_inf() which allows using an exact hex bit
289 * pattern to generate a double value.
291 static inline double
292 strtod_hex(const char *nptr, char **endptr)
294 /* skip spaces and tabs */
295 while (*nptr == ' ' || *nptr == '\t')
296 nptr++;
298 if (strncmp(nptr, "0x", 2) == 0) {
299 union {
300 uint64_t u64;
301 double d;
302 } x;
304 x.u64 = strtoull(nptr, endptr, 16);
305 return x.d;
306 } else {
307 return strtod_inf(nptr, endptr);
312 * Wrapper for strtol() which allows using an exact hex bit pattern to
313 * generate a signed int value.
315 static inline int
316 strtol_hex(const char *nptr, char **endptr)
318 /* skip spaces and tabs */
319 while (*nptr == ' ' || *nptr == '\t')
320 nptr++;
322 if (strncmp(nptr, "0x", 2) == 0) {
323 union {
324 uint32_t u;
325 int32_t i;
326 } x;
328 x.u = strtoul(nptr, endptr, 16);
329 return x.i;
330 } else {
331 return strtol(nptr, endptr, 0);
335 #ifndef HAVE_STRCHRNUL
336 static inline char *
337 strchrnul(const char *s, int c)
339 const char *t = strchr(s, c);
341 return (t == NULL) ? ((char *) s + strlen(s)) : (char *) t;
343 #endif
346 #ifndef HAVE_STRNDUP
347 static inline char *
348 strndup(const char *s, size_t n)
350 const size_t len = strlen(s);
351 const size_t size_to_copy = MIN2(n, len);
353 char *const copy = (char *const) malloc(size_to_copy + 1);
354 if (copy != NULL) {
355 memcpy(copy, s, size_to_copy);
356 copy[size_to_copy] = '\0';
359 return copy;
361 #endif
363 #ifdef _MSC_VER
364 static inline int
365 vasprintf(char **strp, const char *fmt, va_list ap)
367 int len = _vscprintf(fmt, ap);
368 if (len < 0)
369 return -1;
371 char *str = (char *)malloc(len + 1);
372 if (!str)
373 return -1;
375 int r = vsprintf_s(str, len + 1, fmt, ap);
376 if (r < 0) {
377 free(str);
378 return -1;
381 *strp = str;
382 return r;
384 #endif
387 * Determine if an extension is listed in an extension string
389 * \param haystack List of all extensions to be searched
390 * \param needle Extension whose presens is to be detected
392 * \precondition \c haystack is not null
394 * \sa piglit_is_extension_supported, piglit_is_glx_extension_supported
396 bool piglit_is_extension_in_string(const char *haystack, const char *needle);
399 * Determine if an extension is listed in an extension string array
401 * \param haystack Array of all extensions to be searched
402 * \param needle Extension whose presens is to be detected
404 * \precondition \c haystack is not null
406 * \sa piglit_is_extension_supported, piglit_is_glx_extension_supported
408 bool piglit_is_extension_in_array(const char **haystack, const char *needle);
410 int piglit_find_line(const char *program, int position);
411 void piglit_merge_result(enum piglit_result *all, enum piglit_result subtest);
412 const char * piglit_result_to_string(enum piglit_result result);
413 NORETURN void piglit_report_result(enum piglit_result result);
414 void piglit_set_timeout(double seconds, enum piglit_result timeout_result);
415 void piglit_report_subtest_result(enum piglit_result result,
416 const char *format, ...) PRINTFLIKE(2, 3);
418 void piglit_general_init(void);
420 extern void piglit_set_rlimit(unsigned long lim);
422 char *piglit_load_text_file(const char *file_name, unsigned *size);
425 * \brief Read environment variable PIGLIT_SOURCE_DIR.
427 * If environment is not defined, then report failure. The intention is
428 * that tests should use this to construct the path to any needed data files.
430 const char*
431 piglit_source_dir(void);
434 * \brief Join paths together with the system path separator.
436 * On Unix, the path separator is '/'. On Windows, '\\'.
438 * The variable argument consists of \a n null-terminated strings. The
439 * resultant path is written to \a buf. No more than \a buf_size bytes are
440 * written to \a buf. The last byte written is always the null character.
441 * Returned is the number of bytes written, including the terminating null.
443 size_t
444 piglit_join_paths(char buf[], size_t buf_size, int n, ...);
447 * \brief Reads an environment variable and interprets its value as a boolean.
449 * Recognizes 0/false/no and 1/true/yes. Other values result in the
450 * \a default_value.
452 bool
453 piglit_env_var_as_boolean(const char *var_name, bool default_value);
456 * \brief Whether piglit_time_get* return monotonically increasing time.
458 * Can be used to determine how accurate/reliable the time returned by the
459 * function(s) is.
461 bool
462 piglit_time_is_monotonic();
465 * \brief Get the time in nanoseconds
467 * This time can be used for relative time measurements.
469 * A negative return value indicates an error.
471 * \sa piglit_time_is_monotonic
473 int64_t
474 piglit_time_get_nano(void);
477 * \brief Try to delay for a given duration
479 * \param time_ns The requested duration to wait for
481 * Returns the time elapsed which may be cut short or overrun the requested
482 * duration, e.g. due to signal handling or scheduling.
484 * \sa on Linux nanosleep is used and restarted on SIGINT
485 * \sa usleep() is use on other OSs
486 * \sa the returned duration is timed using piglit_time_get_nano()
488 int64_t
489 piglit_delay_ns(int64_t time_ns);
491 const char**
492 piglit_split_string_to_array(const char *string, const char *separators);
494 bool
495 piglit_strip_arg(int *argc, char *argv[], const char *arg);
497 void
498 piglit_parse_subtest_args(int *argc, char *argv[],
499 const struct piglit_subtest *subtests,
500 const char ***out_selected_subtests,
501 size_t *out_num_selected_subtests);
504 * \brief Return the thread id.
506 * On Linux, this functions wraps the gettid() syscall.
507 * On unsupported systems, this returns 0.
509 uint64_t
510 piglit_gettid(void);
512 size_t
513 piglit_get_page_size(void);
515 void *
516 piglit_alloc_aligned(size_t alignment, size_t size);
518 void
519 piglit_free_aligned(void *p);
521 union uif {
522 float f;
523 unsigned int ui;
526 static inline unsigned int
527 fui(float f)
529 union uif bits;
530 bits.f = f;
531 return bits.ui;
534 static inline float
535 uif(unsigned int ui)
537 union uif bits;
538 bits.ui = ui;
539 return bits.f;
542 #ifdef __cplusplus
543 } /* end extern "C" */
544 #endif
546 #endif /* PIGLIT_UTIL_H */