FFmpeg
Loading...
Searching...
No Matches
test.h
Go to the documentation of this file.
1/*
2 * Copyright © 2025, Niklas Haas
3 * Copyright © 2018, VideoLAN and dav1d authors
4 * Copyright © 2018, Two Orioles, LLC
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright notice, this
11 * list of conditions and the following disclaimer.
12 *
13 * 2. Redistributions in binary form must reproduce the above copyright notice,
14 * this list of conditions and the following disclaimer in the documentation
15 * and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
21 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/**
30 * @file test.h
31 * @brief Test writing API for checkasm
32 *
33 * This header provides the API used within test functions to declare, call,
34 * report, and benchmark different implementations of functions.
35 */
36
37#ifndef CHECKASM_TEST_H
38#define CHECKASM_TEST_H
39
40#include <stdint.h>
41
42#include "checkasm/attributes.h"
43#include "checkasm/checkasm.h"
44#include "checkasm/perf.h"
45#include "checkasm/platform.h"
46
47/**
48 * @def checkasm_check_func(func, name, ...)
49 * @brief Check if a function should be tested and set up function references
50 *
51 * Determines if the given function implementation should be tested, identified
52 * by the function pointer, and if so, sets up the function pointers for
53 * subsequent calls to checkasm_call_ref() and checkasm_call_new().
54 *
55 * @param[in] func Function pointer to test, or 0 to skip
56 * @param[in] name Printf-style format string for the function name
57 * @param[in] ... Format arguments for the function name
58 * @return Non-zero if testing should proceed, 0 if this function should be skipped
59 *
60 * @code
61 * if (checkasm_check_func(get_my_func(checkasm_get_cpu_flags()), "my_func")) {
62 * // checkasm_call_ref() and checkasm_call_new() are now ready to use
63 * int ref_result = checkasm_call_ref(args...);
64 * int new_result = checkasm_call_new(args...);
65 * if (ref_result != new_result) {
66 * if (checkasm_fail())
67 * fprintf(stderr, "expected %d, got %d\n", ref_result, new_result);
68 * }
69 * }
70 * checkasm_report("my_func");
71 * @endcode
72 *
73 * @see checkasm_func_ref, checkasm_func_new
74 * @see checkasm_call_ref(), checkasm_call_new()
75 * @see checkasm_check_key()
76 */
77#define checkasm_check_func(func, ...) \
78 (checkasm_key_ref \
79 = checkasm_check_key((checkasm_key_new = (CheckasmKey) (func)), __VA_ARGS__))
80
81/**
82 * @brief Check if a key should be tested
83 *
84 * Determines if the given implementation should be tested, identified by an
85 * arbitrary CheckasmKey.
86 *
87 * @note Unlike checkasm_check_func(), this does not set up any references for
88 * checkasm_call_ref() or checkasm_call_new(), and is intended for use
89 * with e.g. nontrivial function wrappers.
90 *
91 * @param[in] key Arbitrary CheckasmKey to test, or 0 to skip
92 * @param[in] name Printf-style format string for the function name
93 * @param[in] ... Format arguments for the function name
94 * @return Non-zero if testing should proceed, 0 if this function should be skipped
95 *
96 * @return Reference key if testing should proceed, 0 to skip
97 * @see checkasm_check_func()
98 */
100 CHECKASM_PRINTF(2, 3);
101
102/**
103 * @brief Set a custom variant identifier for the next checkasm_check_func() call
104 *
105 * Mark the next call to checkasm_check_func() or checkasm_check_key() as a
106 * variant, with a customizable suffix. This will be used in reports instead of
107 * the default suffix (equivalent to checkasm_get_cpu_suffix()).
108 *
109 * @note Variant functions are ineligible for being used as references for other
110 * functions, and are intended to test non-standard behavior such as
111 * non-bitexact, uncached or aligned implementations.
112 *
113 * @param[in] id Printf-style format string for the variant identifier
114 * @param[in] ... Format arguments for the identifier
115 * @since v1.2.0
116 */
118
119/**
120 * @brief Mark the current function as failed with a custom message
121 *
122 * Records a test failure with a printf-style formatted message.
123 *
124 * @param[in] msg Printf-style format string describing the failure
125 * @param[in] ... Format arguments
126 * @return 1 if the failure details should be printed verbosely, 0 otherwise
127 *
128 * @code
129 * if (output != expected)
130 * checkasm_fail_func("%s:%d", filename, line);
131 * @endcode
132 *
133 * @note This is typically called via checkasm_fail() rather than directly.
134 * @see checkasm_fail()
135 */
136CHECKASM_API int checkasm_fail_func(const char *msg, ...) CHECKASM_PRINTF(1, 2);
137
138/**
139 * @def checkasm_fail()
140 * @brief Mark the current test as failed
141 *
142 * Records a test failure with the current file and line number. This is the
143 * most common way to indicate test failure. The test will continue executing,
144 * but any future calls to checkasm_check_func() for this function will return 0.
145 *
146 * @return 1 if the failure details should be printed verbosely, 0 otherwise
147 *
148 * @code
149 * if (output != expected) {
150 * if (checkasm_fail())
151 * fprintf(stderr, "expected %d, got %d\n", expected, output);
152 * }
153 * @endcode
154 */
155#define checkasm_fail() checkasm_fail_func("%s:%d", __FILE__, __LINE__)
156
157/**
158 * @brief Report test outcome for a named group of functions.
159 *
160 * Prints the result (pass/fail) for a named group of functions. Typically
161 * called at the end of a test, as well as after any larger block of similar
162 * functions.
163 *
164 * @note Since v1.0.1, this is optional. If not called before the end of a
165 * test, any remaining results will be reported directly under the name of the
166 * associated test itself.
167 *
168 * @param[in] name Printf-style format string for the test case name
169 * @param[in] ... Format arguments
170 *
171 * @code
172 * for (int w = 4; w < 128; w <<= 1) {
173 * if (checkasm_check_func(.., "blockcopy_%dbpc_w%d", bits, w)) {
174 * // ...
175 * }
176 * }
177 *
178 * checkasm_report("blockcopy_%dbpc", bits);
179 * @endcode
180 */
182
183/**
184 * @def checkasm_declare(ret, ...)
185 * @brief Declare a function signature for testing
186 *
187 * Declares the function prototype that will be tested. This must be called
188 * before using checkasm_call_checked(), checkasm_call_ref(), or
189 * checkasm_call_new(). The first argument is the return type, and remaining
190 * arguments are the function parameters (naming parameters is optional).
191 *
192 * @param ret Return type of the function
193 * @param ... Function parameter types
194 *
195 * @code
196 * // Declare signature for: int add(int a, int b)
197 * declare_func(int, int a, int b);
198 *
199 * // Can also omit parameter names for brevity:
200 * declare_func(int, int, int);
201 * @endcode
202 *
203 * @see checkasm_call_checked(), checkasm_call_call_ref(), checkasm_call_new()
204 */
205#define checkasm_declare(ret, ...) \
206 checkasm_declare_impl(ret, __VA_ARGS__); \
207 typedef ret func_type(__VA_ARGS__); \
208 (void) ((func_type *) NULL)
209
210/**
211 * @def checkasm_declare_emms(cpu_flags, ret, ...)
212 * @brief Declare signature for non-ABI compliant MMX functions (x86 only)
213 *
214 * Variant of checkasm_declare() for MMX functions that omit calling emms
215 * before returning to the caller. This is used for optimized MMX kernels
216 * that expect the caller to run emms manually.
217 *
218 * @param cpu_flags Mask of CPU flags under which to enable the extra emms call
219 * @param ret Return type of the function
220 * @param ... Function parameter types
221 *
222 * @note MMX code normally needs to call emms before any floating-point code
223 * can be executed. Since this instruction can be very slow, many MMX
224 * kernels (used inside loops) are designed to omit emms and instead
225 * expect the caller to run emms manually after the loop. This macro
226 * will omit the emms check and instead explicitly run emms after calling
227 * the function (only when any of the specified cpu_flags are active).
228 *
229 * @note On non-x86 platforms, this is equivalent to checkasm_declare().
230 *
231 * @see checkasm_declare()
232 */
233#ifndef checkasm_declare_emms
234 #define checkasm_declare_emms(cpu_flags, ret, ...) checkasm_declare(ret, __VA_ARGS__)
235#endif
236
237/**
238 * @def checkasm_call(func, ...)
239 * @brief Call a function with signal handling
240 *
241 * Calls an arbitrary function while handling signals (crashes, segfaults, etc.).
242 * Use this for calling the reference implementation or other nominally-safe code.
243 * For testing assembly/optimized implementations, use checkasm_call_checked()
244 * instead, which provides additional validation for common assembly mistakes.
245 *
246 * @param func Function pointer to call
247 * @param ... Arguments to pass to the function
248 *
249 * @note This only handles signals; use checkasm_call_checked() for full validation.
250 * @see checkasm_call_checked()
251 */
252#define checkasm_call(func, ...) \
253 (checkasm_set_signal_handler_state(1), (func) (__VA_ARGS__)); \
254 checkasm_clear_cpu_state(); \
255 checkasm_set_signal_handler_state(0)
256
257/**
258 * @def checkasm_call_checked(func, ...)
259 * @brief Call an assembly function with full validation
260 *
261 * Calls an assembly/optimized function (matching the signature declared by
262 * checkasm_declare()) while handling signals and checking for common assembly
263 * errors like stack corruption, clobbered registers, register size mismatches
264 * and ABI violations. Use this for calling the implementation being tested.
265 *
266 * @param func Function pointer to call (must match declared signature)
267 * @param ... Arguments to pass to the function
268 *
269 * @note Requires prior call to checkasm_declare().
270 * @see checkasm_declare(), checkasm_call_ref(), checkasm_call_new()
271 */
272#ifndef checkasm_call_checked
273 #define checkasm_call_checked(func, ...) \
274 (checkasm_set_signal_handler_state(1), \
275 checkasm_push_stack_guard((uintptr_t[16]) { 0, 0 }), \
276 ((func_type *) (func))(__VA_ARGS__)); \
277 checkasm_pop_stack_guard(); \
278 checkasm_set_signal_handler_state(0)
279#endif
280
281/**
282 * @brief Mark a block of tests as expected to fail
283 *
284 * Marks the following test functions as expected to fail when any of the
285 * specified CPU flags are set. Returns whether these functions should be
286 * executed.
287 *
288 * @param[in] cpu_flags CPU flags for which failure is expected (or -1 for all)
289 * @return 1 if functions should be executed, 0 if they should be skipped
290 *
291 * @note All functions inside such a block *must* fail, otherwise the whole
292 * test will be considered failed. This is used for testing that known-broken
293 * implementations are properly detected as broken.
294 *
295 * @note This is not normally useful for end users; it is mainly defined for
296 * use inside checkasm's internal test suite.
297 *
298 * @code
299 * if (checkasm_should_fail(CPU_FLAG_SSE2)) {
300 * // This implementation is known to be broken on SSE2
301 * if (checkasm_check_func(broken_func_sse2, "broken_func")) {
302 * checkasm_call_new(); // should fail
303 * }
304 * }
305 * @endcode
306 */
308
309/**
310 * @brief Key identifying the reference implementation
311 *
312 * Set by checkasm_check_func() to point to the reference key for the function
313 * currently being tested.
314 *
315 * @see checkasm_check_func(), checkasm_func_ref, checkasm_key_new
316 * @since v1.0.1
317 */
319
320/**
321 * @brief Key identifying the implementation being tested
322 *
323 * Set by checkasm_check_func() to point to the key passed to it.
324 *
325 * @see checkasm_check_func(), checkasm_func_new, checkasm_key_ref
326 * @since v1.0.1
327 */
329
330/**
331 * @def checkasm_func_ref
332 * @brief Function pointer to the reference implementation
333 *
334 * This is just a typed version of checkasm_key_ref, cast to the type declared
335 * by checkasm_declare().
336 *
337 * @see checkasm_func_new(), checkasm_check_func()
338 */
339#define checkasm_func_ref ((func_type *) checkasm_key_ref)
340
341/**
342 * @def checkasm_func_new
343 * @brief Function pointer to the implementation being tested
344 *
345 * This is just a typed version of checkasm_key_new, cast to the type declared
346 * by checkasm_declare().
347 *
348 * @note This is read-only. To test a different function, use
349 * checkasm_call_checked() instead of checkasm_call_new().
350 *
351 * @see checkasm_func_ref(), checkasm_check_func()
352 */
353#define checkasm_func_new ((func_type *) checkasm_key_new)
354
355/**
356 * @def checkasm_call_ref(...)
357 * @brief Call the reference implementation
358 *
359 * Calls the reference (C) implementation with the specified arguments.
360 * Must be preceded by a successful checkasm_check_func() call.
361 *
362 * @param ... Arguments to pass to the function
363 * @return Return value from the reference implementation
364 *
365 * @see checkasm_check_func(), checkasm_call_new()
366 */
367#define checkasm_call_ref(...) checkasm_call(checkasm_func_ref, __VA_ARGS__)
368
369/**
370 * @def checkasm_call_new(...)
371 * @brief Call the implementation being tested with validation
372 *
373 * Calls the optimized implementation being tested with the specified arguments,
374 * including full validation for register clobbering, stack corruption, etc.
375 * Must be preceded by a successful checkasm_check_func() call.
376 *
377 * @param ... Arguments to pass to the function
378 * @return Return value from the optimized implementation
379 *
380 * @see checkasm_check_func(), checkasm_call_ref()
381 */
382#define checkasm_call_new(...) checkasm_call_checked(checkasm_func_new, __VA_ARGS__)
383
384/**
385 * @def checkasm_bench(func, ...)
386 * @brief Benchmark a function
387 *
388 * Repeatedly calls a function to measure its performance. If benchmarking is
389 * enabled, runs the function many times and collects timing statistics. If
390 * benchmarking is disabled, simply calls the function once with validation.
391 *
392 * @param func Function pointer to benchmark
393 * @param ... Arguments to pass to the function
394 *
395 * @note This function may be called multiple times within the same
396 * checkasm_check_func() block. If done, the timing results will be
397 * accumulated and reported as a geometric mean. This is useful for
398 * benchmarking multiple different input sizes or configurations that
399 * should be reported as a single average figure.
400 *
401 * @see checkasm_bench_new(), checkasm_alternate()
402 */
403#define checkasm_bench(func, ...) \
404 do { \
405 if (checkasm_bench_func()) { \
406 func_type *const bench_func = (func); \
407 checkasm_set_signal_handler_state(1); \
408 for (int truns; (truns = checkasm_bench_runs());) { \
409 uint64_t time; \
410 CHECKASM_PERF_BENCH(truns, time, __VA_ARGS__); \
411 checkasm_clear_cpu_state(); \
412 checkasm_bench_update(truns, time); \
413 } \
414 checkasm_set_signal_handler_state(0); \
415 checkasm_bench_finish(); \
416 } else { \
417 const int tidx = 0; \
418 (void) tidx; \
419 checkasm_call_checked(func, __VA_ARGS__); \
420 } \
421 } while (0)
422
423/**
424 * @def checkasm_bench_new(...)
425 * @brief Benchmark the optimized implementation
426 *
427 * Convenience macro that benchmarks the optimized implementation set up by
428 * checkasm_check_func(). Equivalent to checkasm_bench(checkasm_func_new, ...).
429 *
430 * @param ... Arguments to pass to the function
431 *
432 * @code
433 * if (checkasm_check_func(get_my_func(checkasm_get_cpu_flags()), "my_func")) {
434 * // Test correctness
435 * checkasm_call_ref(output_ref, input);
436 * checkasm_call_new(output_new, input);
437 * checkasm_check(type, output_ref, output_new);
438 *
439 * // Benchmark performance
440 * checkasm_bench_new(output_new, input);
441 * }
442 * checkasm_report("my_func");
443 * @endcode
444 *
445 * @see checkasm_bench(), checkasm_check_func()
446 */
447#define checkasm_bench_new(...) checkasm_bench(checkasm_func_new, __VA_ARGS__)
448
449/**
450 * @def checkasm_alternate(a, b)
451 * @brief Alternate between two values during benchmarking
452 *
453 * Returns one of two values, alternating between them across benchmark
454 * iterations. Intended for use within bench_new() calls for functions that
455 * modify their input buffers. This ensures throughput (not latency) is
456 * measured by preventing data dependencies between iterations.
457 *
458 * @param a First value
459 * @param b Second value
460 * @return Either a or b depending on the current benchmark iteration
461 *
462 * @code
463 * CHECKASM_ALIGN(uint8_t buf0[SIZE]);
464 * CHECKASM_ALIGN(uint8_t buf1[SIZE]);
465 * bench_new(alternate(buf0, buf1), size);
466 * // Each iteration uses a different buffer, preventing stalls
467 * @endcode
468 */
469#define checkasm_alternate(a, b) ((tidx & 1) ? (b) : (a))
470
471/**
472 * @addtogroup aliases Short-hand Aliases
473 * @brief Convenience aliases for common checkasm functions and macros
474 *
475 * These shorter names are provided for convenience and backwards compatibility.
476 * They are functionally identical to their checkasm_* counterparts.
477 * @{
478 */
479#define fail checkasm_fail
480#define report checkasm_report
481#define check_func checkasm_check_func
482#define check_key checkasm_check_key
483#define func_ref checkasm_func_ref
484#define func_new checkasm_func_new
485#define call_ref checkasm_call_ref
486#define call_new checkasm_call_new
487#define bench_new checkasm_bench_new
488#define alternate checkasm_alternate
489#define declare_func checkasm_declare
490#define declare_func_emms checkasm_declare_emms
491/** @} */
492
493/**
494 * @addtogroup internal Internal Implementation Details
495 * @brief Internal functions and structures not part of the public API
496 *
497 * These functions and types are used internally by checkasm macros and should
498 * not be called or referenced directly by test code.
499 * @{
500 */
501
502/**
503 * @brief Enable or disable signal handling
504 * @param[in] enabled Non-zero to enable signal handling, 0 to disable
505 */
507
508/**
509 * @brief Push stack guard values for corruption detection
510 * @param[in] guard Array of guard values to push
511 */
512CHECKASM_API void checkasm_push_stack_guard(uintptr_t guard[2]);
514
515/**
516 * @def checkasm_clear_cpu_state()
517 * @brief Clear CPU state after running a function
518 *
519 * Clears any processor state that might be left over after running a function.
520 * On x86, this typically includes running EMMS to clear MMX state.
521 */
522#ifndef checkasm_clear_cpu_state
523 #define checkasm_clear_cpu_state() \
524 do { \
525 } while (0)
526#endif
527
528typedef struct CheckasmPerf {
529 /**
530 * @brief Start timing measurement
531 * @return Timestamp value to pass to stop()
532 * @note Only used when ASM timers are not available
533 */
534 uint64_t (*start)(void);
535
536 /**
537 * @brief Stop timing measurement
538 * @param[in] start_time Timestamp from start()
539 * @return Elapsed time in the specified unit
540 */
541 uint64_t (*stop)(uint64_t start_time);
542
543 /** @brief Name of the timing mechanism (e.g., "clock_gettime") */
544 const char *name;
545
546 /** @brief Unit of measurement (e.g., "ns", "cycles") */
547 const char *unit;
548
549#ifdef CHECKASM_PERF_ASM
550 /** @brief Whether inline ASM timing instructions are usable */
551 int asm_usable;
552#endif
554
555#define CHECKASM_PERF_CALL4(...) \
556 do { \
557 int tidx = 0; \
558 bench_func(__VA_ARGS__); \
559 tidx = 1; \
560 bench_func(__VA_ARGS__); \
561 tidx = 2; \
562 bench_func(__VA_ARGS__); \
563 tidx = 3; \
564 bench_func(__VA_ARGS__); \
565 (void) tidx; \
566 } while (0)
567
568#define CHECKASM_PERF_CALL16(...) \
569 do { \
570 CHECKASM_PERF_CALL4(__VA_ARGS__); \
571 CHECKASM_PERF_CALL4(__VA_ARGS__); \
572 CHECKASM_PERF_CALL4(__VA_ARGS__); \
573 CHECKASM_PERF_CALL4(__VA_ARGS__); \
574 } while (0)
575
576/* Naive loop; used when perf.start/stop() is expected to be slow or imprecise, or when
577 * we have no ASM cycle counters, or when the number of iterations is low */
578#define CHECKASM_PERF_BENCH_SIMPLE(count, time, ...) \
579 do { \
580 time = perf.start(); \
581 for (int tidx = 0; tidx < count; tidx++) \
582 bench_func(__VA_ARGS__); \
583 time = perf.stop(time); \
584 } while (0)
585
586/* Unrolled loop with inline outlier rejection; used when we have asm cycle counters */
587#define CHECKASM_PERF_BENCH_ASM(total_count, time, ...) \
588 do { \
589 int tcount_trim = 0; \
590 uint64_t tsum_trim = 0; \
591 for (int titer = 0; titer < total_count; titer += 32) { \
592 uint64_t t = CHECKASM_PERF_ASM(); \
593 CHECKASM_PERF_CALL16(__VA_ARGS__); \
594 CHECKASM_PERF_CALL16(__VA_ARGS__); \
595 t = CHECKASM_PERF_ASM() - t; \
596 if (t * tcount_trim <= tsum_trim * 4 && (titer > 0 || total_count < 1000)) { \
597 tsum_trim += t; \
598 tcount_trim++; \
599 } \
600 } \
601 time = tsum_trim; \
602 total_count = tcount_trim << 5; \
603 } while (0)
604
605/* Select the best benchmarking method at runtime */
607
608#ifdef CHECKASM_PERF_ASM
609 #ifndef CHECKASM_PERF_ASM_USABLE
610 #define CHECKASM_PERF_ASM_USABLE perf.asm_usable
611 #endif
612 #define CHECKASM_PERF_BENCH(count, time, ...) \
613 do { \
614 const CheckasmPerf perf = *checkasm_get_perf(); \
615 if (CHECKASM_PERF_ASM_USABLE && count >= 128) { \
616 CHECKASM_PERF_BENCH_ASM(count, time, __VA_ARGS__); \
617 } else { \
618 CHECKASM_PERF_BENCH_SIMPLE(count, time, __VA_ARGS__); \
619 } \
620 } while (0)
621#else /* !CHECKASM_PERF_ASM */
622 #define CHECKASM_PERF_BENCH(count, time, ...) \
623 do { \
624 const CheckasmPerf perf = *checkasm_get_perf(); \
625 CHECKASM_PERF_BENCH_SIMPLE(count, time, __VA_ARGS__); \
626 } while (0)
627#endif
628
629/**
630 * @brief Check if current function should be benchmarked
631 * @return Non-zero if benchmarking is enabled for the current function
632 */
634
635/**
636 * @brief Get number of iterations for current benchmark run
637 * @return Number of iterations to run, or 0 if benchmarking is complete
638 */
640
641/**
642 * @brief Update benchmark statistics with timing results
643 * @param[in] iterations Number of iterations that were run
644 * @param[in] cycles Sum of elapsed time/cycles for those iterations
645 */
646CHECKASM_API void checkasm_bench_update(int iterations, uint64_t cycles);
647
648/**
649 * @brief Finalize and store benchmark results
650 */
652
653/**
654 * @brief Suppress unused variable warnings
655 */
656static inline void checkasm_unused(void)
657{
658 (void) checkasm_key_ref;
659 (void) checkasm_key_new;
660}
661
662/** @} */ /* internal */
663
664#endif /* CHECKASM_TEST_H */
uint64_t CheckasmCpu
Opaque type representing a set of CPU feature flags.
Definition checkasm.h:88
uintptr_t CheckasmKey
Opaque type used to identify function implementations.
Definition checkasm.h:96
uint64_t cycles
Definition checkasm.c:94
const char * key
static int64_t start_time
Definition ffplay.c:329
CHECKASM_API const CheckasmPerf * checkasm_get_perf(void)
Definition perf.c:54
CHECKASM_API int checkasm_bench_func(void)
Check if current function should be benchmarked.
Definition checkasm.c:466
static void checkasm_unused(void)
Suppress unused variable warnings.
Definition test.h:656
CHECKASM_API void checkasm_bench_finish(void)
Finalize and store benchmark results.
Definition checkasm.c:503
CHECKASM_API void checkasm_bench_update(int iterations, uint64_t cycles)
Update benchmark statistics with timing results.
Definition checkasm.c:489
CHECKASM_API void checkasm_pop_stack_guard(void)
Definition stackguard.c:66
CHECKASM_API int checkasm_bench_runs(void)
Get number of iterations for current benchmark run.
Definition checkasm.c:471
CHECKASM_API void checkasm_push_stack_guard(uintptr_t guard[2])
Push stack guard values for corruption detection.
Definition stackguard.c:41
CHECKASM_API void checkasm_set_signal_handler_state(int enabled)
Enable or disable signal handling.
Definition signal.c:52
static atomic_int cpu_flags
Definition cpu.c:56
const char * name
Definition qsvenc.c:142
uint64_t(* start)(void)
Start timing measurement.
Definition test.h:534
const char * unit
Unit of measurement (e.g., "ns", "cycles")
Definition test.h:547
const char * name
Name of the timing mechanism (e.g., "clock_gettime")
Definition test.h:544
uint64_t(* stop)(uint64_t start_time)
Stop timing measurement.
Definition test.h:541
static CheckasmKey checkasm_key_ref
Key identifying the reference implementation.
Definition test.h:318
static CheckasmKey checkasm_key_new
Key identifying the implementation being tested.
Definition test.h:328
CHECKASM_API void checkasm_report(const char *name,...) CHECKASM_PRINTF(1
Report test outcome for a named group of functions.
CHECKASM_API CheckasmKey checkasm_check_key(CheckasmKey key, const char *name,...) CHECKASM_PRINTF(2
Check if a key should be tested.
CHECKASM_API int checkasm_should_fail(CheckasmCpu cpu_flags)
Mark a block of tests as expected to fail.
Definition checkasm.c:1085
CHECKASM_API CheckasmKey CHECKASM_API void checkasm_set_func_variant(const char *id,...) CHECKASM_PRINTF(1
Set a custom variant identifier for the next checkasm_check_func() call.
CHECKASM_API CheckasmKey CHECKASM_API void CHECKASM_API int checkasm_fail_func(const char *msg,...) CHECKASM_PRINTF(1
Mark the current function as failed with a custom message.
Platform and compiler attribute macros.
#define CHECKASM_PRINTF(fmt, attr)
Printf-style format string checking attribute.
Definition attributes.h:59
#define CHECKASM_API
Symbol visibility attribute for public API functions.
Definition attributes.h:90