FFmpeg
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  */
117 CHECKASM_API void checkasm_set_func_variant(const char *id, ...) CHECKASM_PRINTF(1, 2);
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  */
136 CHECKASM_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  */
181 CHECKASM_API void checkasm_report(const char *name, ...) CHECKASM_PRINTF(1, 2);
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_set_signal_handler_state(0)
255 
256 /**
257  * @def checkasm_call_checked(func, ...)
258  * @brief Call an assembly function with full validation
259  *
260  * Calls an assembly/optimized function (matching the signature declared by
261  * checkasm_declare()) while handling signals and checking for common assembly
262  * errors like stack corruption, clobbered registers, register size mismatches
263  * and ABI violations. Use this for calling the implementation being tested.
264  *
265  * @param func Function pointer to call (must match declared signature)
266  * @param ... Arguments to pass to the function
267  *
268  * @note Requires prior call to checkasm_declare().
269  * @see checkasm_declare(), checkasm_call_ref(), checkasm_call_new()
270  */
271 #ifndef checkasm_call_checked
272  #define checkasm_call_checked(func, ...) \
273  (checkasm_set_signal_handler_state(1), \
274  checkasm_push_stack_guard((uintptr_t[16]) { 0, 0 }), \
275  ((func_type *) (func))(__VA_ARGS__)); \
276  checkasm_pop_stack_guard(); \
277  checkasm_set_signal_handler_state(0)
278 #endif
279 
280 /**
281  * @brief Mark a block of tests as expected to fail
282  *
283  * Marks the following test functions as expected to fail when any of the
284  * specified CPU flags are set. Returns whether these functions should be
285  * executed.
286  *
287  * @param[in] cpu_flags CPU flags for which failure is expected (or -1 for all)
288  * @return 1 if functions should be executed, 0 if they should be skipped
289  *
290  * @note All functions inside such a block *must* fail, otherwise the whole
291  * test will be considered failed. This is used for testing that known-broken
292  * implementations are properly detected as broken.
293  *
294  * @note This is not normally useful for end users; it is mainly defined for
295  * use inside checkasm's internal test suite.
296  *
297  * @code
298  * if (checkasm_should_fail(CPU_FLAG_SSE2)) {
299  * // This implementation is known to be broken on SSE2
300  * if (checkasm_check_func(broken_func_sse2, "broken_func")) {
301  * checkasm_call_new(); // should fail
302  * }
303  * }
304  * @endcode
305  */
307 
308 /**
309  * @brief Key identifying the reference implementation
310  *
311  * Set by checkasm_check_func() to point to the reference key for the function
312  * currently being tested.
313  *
314  * @see checkasm_check_func(), checkasm_func_ref, checkasm_key_new
315  * @since v1.0.1
316  */
318 
319 /**
320  * @brief Key identifying the implementation being tested
321  *
322  * Set by checkasm_check_func() to point to the key passed to it.
323  *
324  * @see checkasm_check_func(), checkasm_func_new, checkasm_key_ref
325  * @since v1.0.1
326  */
328 
329 /**
330  * @def checkasm_func_ref
331  * @brief Function pointer to the reference implementation
332  *
333  * This is just a typed version of checkasm_key_ref, cast to the type declared
334  * by checkasm_declare().
335  *
336  * @see checkasm_func_new(), checkasm_check_func()
337  */
338 #define checkasm_func_ref ((func_type *) checkasm_key_ref)
339 
340 /**
341  * @def checkasm_func_new
342  * @brief Function pointer to the implementation being tested
343  *
344  * This is just a typed version of checkasm_key_new, cast to the type declared
345  * by checkasm_declare().
346  *
347  * @note This is read-only. To test a different function, use
348  * checkasm_call_checked() instead of checkasm_call_new().
349  *
350  * @see checkasm_func_ref(), checkasm_check_func()
351  */
352 #define checkasm_func_new ((func_type *) checkasm_key_new)
353 
354 /**
355  * @def checkasm_call_ref(...)
356  * @brief Call the reference implementation
357  *
358  * Calls the reference (C) implementation with the specified arguments.
359  * Must be preceded by a successful checkasm_check_func() call.
360  *
361  * @param ... Arguments to pass to the function
362  * @return Return value from the reference implementation
363  *
364  * @see checkasm_check_func(), checkasm_call_new()
365  */
366 #define checkasm_call_ref(...) checkasm_call(checkasm_func_ref, __VA_ARGS__)
367 
368 /**
369  * @def checkasm_call_new(...)
370  * @brief Call the implementation being tested with validation
371  *
372  * Calls the optimized implementation being tested with the specified arguments,
373  * including full validation for register clobbering, stack corruption, etc.
374  * Must be preceded by a successful checkasm_check_func() call.
375  *
376  * @param ... Arguments to pass to the function
377  * @return Return value from the optimized implementation
378  *
379  * @see checkasm_check_func(), checkasm_call_ref()
380  */
381 #define checkasm_call_new(...) checkasm_call_checked(checkasm_func_new, __VA_ARGS__)
382 
383 /**
384  * @def checkasm_bench(func, ...)
385  * @brief Benchmark a function
386  *
387  * Repeatedly calls a function to measure its performance. If benchmarking is
388  * enabled, runs the function many times and collects timing statistics. If
389  * benchmarking is disabled, simply calls the function once with validation.
390  *
391  * @param func Function pointer to benchmark
392  * @param ... Arguments to pass to the function
393  *
394  * @note This function may be called multiple times within the same
395  * checkasm_check_func() block. If done, the timing results will be
396  * accumulated and reported as a geometric mean. This is useful for
397  * benchmarking multiple different input sizes or configurations that
398  * should be reported as a single average figure.
399  *
400  * @see checkasm_bench_new(), checkasm_alternate()
401  */
402 #define checkasm_bench(func, ...) \
403  do { \
404  if (checkasm_bench_func()) { \
405  func_type *const bench_func = (func); \
406  checkasm_set_signal_handler_state(1); \
407  for (int truns; (truns = checkasm_bench_runs());) { \
408  uint64_t time; \
409  CHECKASM_PERF_BENCH(truns, time, __VA_ARGS__); \
410  checkasm_clear_cpu_state(); \
411  checkasm_bench_update(truns, time); \
412  } \
413  checkasm_set_signal_handler_state(0); \
414  checkasm_bench_finish(); \
415  } else { \
416  const int tidx = 0; \
417  (void) tidx; \
418  checkasm_call_checked(func, __VA_ARGS__); \
419  } \
420  } while (0)
421 
422 /**
423  * @def checkasm_bench_new(...)
424  * @brief Benchmark the optimized implementation
425  *
426  * Convenience macro that benchmarks the optimized implementation set up by
427  * checkasm_check_func(). Equivalent to checkasm_bench(checkasm_func_new, ...).
428  *
429  * @param ... Arguments to pass to the function
430  *
431  * @code
432  * if (checkasm_check_func(get_my_func(checkasm_get_cpu_flags()), "my_func")) {
433  * // Test correctness
434  * checkasm_call_ref(output_ref, input);
435  * checkasm_call_new(output_new, input);
436  * checkasm_check(type, output_ref, output_new);
437  *
438  * // Benchmark performance
439  * checkasm_bench_new(output_new, input);
440  * }
441  * checkasm_report("my_func");
442  * @endcode
443  *
444  * @see checkasm_bench(), checkasm_check_func()
445  */
446 #define checkasm_bench_new(...) checkasm_bench(checkasm_func_new, __VA_ARGS__)
447 
448 /**
449  * @def checkasm_alternate(a, b)
450  * @brief Alternate between two values during benchmarking
451  *
452  * Returns one of two values, alternating between them across benchmark
453  * iterations. Intended for use within bench_new() calls for functions that
454  * modify their input buffers. This ensures throughput (not latency) is
455  * measured by preventing data dependencies between iterations.
456  *
457  * @param a First value
458  * @param b Second value
459  * @return Either a or b depending on the current benchmark iteration
460  *
461  * @code
462  * CHECKASM_ALIGN(uint8_t buf0[SIZE]);
463  * CHECKASM_ALIGN(uint8_t buf1[SIZE]);
464  * bench_new(alternate(buf0, buf1), size);
465  * // Each iteration uses a different buffer, preventing stalls
466  * @endcode
467  */
468 #define checkasm_alternate(a, b) ((tidx & 1) ? (b) : (a))
469 
470 /**
471  * @addtogroup aliases Short-hand Aliases
472  * @brief Convenience aliases for common checkasm functions and macros
473  *
474  * These shorter names are provided for convenience and backwards compatibility.
475  * They are functionally identical to their checkasm_* counterparts.
476  * @{
477  */
478 #define fail checkasm_fail
479 #define report checkasm_report
480 #define check_func checkasm_check_func
481 #define check_key checkasm_check_key
482 #define func_ref checkasm_func_ref
483 #define func_new checkasm_func_new
484 #define call_ref checkasm_call_ref
485 #define call_new checkasm_call_new
486 #define bench_new checkasm_bench_new
487 #define alternate checkasm_alternate
488 #define declare_func checkasm_declare
489 #define declare_func_emms checkasm_declare_emms
490 /** @} */
491 
492 /**
493  * @addtogroup internal Internal Implementation Details
494  * @brief Internal functions and structures not part of the public API
495  *
496  * These functions and types are used internally by checkasm macros and should
497  * not be called or referenced directly by test code.
498  * @{
499  */
500 
501 /**
502  * @brief Enable or disable signal handling
503  * @param[in] enabled Non-zero to enable signal handling, 0 to disable
504  */
506 
507 /**
508  * @brief Push stack guard values for corruption detection
509  * @param[in] guard Array of guard values to push
510  */
511 CHECKASM_API void checkasm_push_stack_guard(uintptr_t guard[2]);
513 
514 /**
515  * @def checkasm_clear_cpu_state()
516  * @brief Clear CPU state after running a function
517  *
518  * Clears any processor state that might be left over after running a function.
519  * On x86, this typically includes running EMMS to clear MMX state.
520  */
521 #ifndef checkasm_clear_cpu_state
522  #define checkasm_clear_cpu_state() \
523  do { \
524  } while (0)
525 #endif
526 
527 typedef struct CheckasmPerf {
528  /**
529  * @brief Start timing measurement
530  * @return Timestamp value to pass to stop()
531  * @note Only used when ASM timers are not available
532  */
533  uint64_t (*start)(void);
534 
535  /**
536  * @brief Stop timing measurement
537  * @param[in] start_time Timestamp from start()
538  * @return Elapsed time in the specified unit
539  */
540  uint64_t (*stop)(uint64_t start_time);
541 
542  /** @brief Name of the timing mechanism (e.g., "clock_gettime") */
543  const char *name;
544 
545  /** @brief Unit of measurement (e.g., "ns", "cycles") */
546  const char *unit;
547 
548 #ifdef CHECKASM_PERF_ASM
549  /** @brief Whether inline ASM timing instructions are usable */
550  int asm_usable;
551 #endif
552 } CheckasmPerf;
553 
554 #define CHECKASM_PERF_CALL4(...) \
555  do { \
556  int tidx = 0; \
557  bench_func(__VA_ARGS__); \
558  tidx = 1; \
559  bench_func(__VA_ARGS__); \
560  tidx = 2; \
561  bench_func(__VA_ARGS__); \
562  tidx = 3; \
563  bench_func(__VA_ARGS__); \
564  (void) tidx; \
565  } while (0)
566 
567 #define CHECKASM_PERF_CALL16(...) \
568  do { \
569  CHECKASM_PERF_CALL4(__VA_ARGS__); \
570  CHECKASM_PERF_CALL4(__VA_ARGS__); \
571  CHECKASM_PERF_CALL4(__VA_ARGS__); \
572  CHECKASM_PERF_CALL4(__VA_ARGS__); \
573  } while (0)
574 
575 /* Naive loop; used when perf.start/stop() is expected to be slow or imprecise, or when
576  * we have no ASM cycle counters, or when the number of iterations is low */
577 #define CHECKASM_PERF_BENCH_SIMPLE(count, time, ...) \
578  do { \
579  time = perf.start(); \
580  for (int tidx = 0; tidx < count; tidx++) \
581  bench_func(__VA_ARGS__); \
582  time = perf.stop(time); \
583  } while (0)
584 
585 /* Unrolled loop with inline outlier rejection; used when we have asm cycle counters */
586 #define CHECKASM_PERF_BENCH_ASM(total_count, time, ...) \
587  do { \
588  int tcount_trim = 0; \
589  uint64_t tsum_trim = 0; \
590  for (int titer = 0; titer < total_count; titer += 32) { \
591  uint64_t t = CHECKASM_PERF_ASM(); \
592  CHECKASM_PERF_CALL16(__VA_ARGS__); \
593  CHECKASM_PERF_CALL16(__VA_ARGS__); \
594  t = CHECKASM_PERF_ASM() - t; \
595  if (t * tcount_trim <= tsum_trim * 4 && (titer > 0 || total_count < 1000)) { \
596  tsum_trim += t; \
597  tcount_trim++; \
598  } \
599  } \
600  time = tsum_trim; \
601  total_count = tcount_trim << 5; \
602  } while (0)
603 
604 /* Select the best benchmarking method at runtime */
606 
607 #ifdef CHECKASM_PERF_ASM
608  #ifndef CHECKASM_PERF_ASM_USABLE
609  #define CHECKASM_PERF_ASM_USABLE perf.asm_usable
610  #endif
611  #define CHECKASM_PERF_BENCH(count, time, ...) \
612  do { \
613  const CheckasmPerf perf = *checkasm_get_perf(); \
614  if (CHECKASM_PERF_ASM_USABLE && count >= 128) { \
615  CHECKASM_PERF_BENCH_ASM(count, time, __VA_ARGS__); \
616  } else { \
617  CHECKASM_PERF_BENCH_SIMPLE(count, time, __VA_ARGS__); \
618  } \
619  } while (0)
620 #else /* !CHECKASM_PERF_ASM */
621  #define CHECKASM_PERF_BENCH(count, time, ...) \
622  do { \
623  const CheckasmPerf perf = *checkasm_get_perf(); \
624  CHECKASM_PERF_BENCH_SIMPLE(count, time, __VA_ARGS__); \
625  } while (0)
626 #endif
627 
628 /**
629  * @brief Check if current function should be benchmarked
630  * @return Non-zero if benchmarking is enabled for the current function
631  */
633 
634 /**
635  * @brief Get number of iterations for current benchmark run
636  * @return Number of iterations to run, or 0 if benchmarking is complete
637  */
639 
640 /**
641  * @brief Update benchmark statistics with timing results
642  * @param[in] iterations Number of iterations that were run
643  * @param[in] cycles Sum of elapsed time/cycles for those iterations
644  */
645 CHECKASM_API void checkasm_bench_update(int iterations, uint64_t cycles);
646 
647 /**
648  * @brief Finalize and store benchmark results
649  */
651 
652 /**
653  * @brief Suppress unused variable warnings
654  */
655 static inline void checkasm_unused(void)
656 {
657  (void) checkasm_key_ref;
658  (void) checkasm_key_new;
659 }
660 
661 /** @} */ /* internal */
662 
663 #endif /* CHECKASM_TEST_H */
name
it s the only field you need to keep assuming you have a context There is some magic you don t need to care about around this just let it vf default minimum maximum flags name is the option name
Definition: writing_filters.txt:88
checkasm_key_new
static CheckasmKey checkasm_key_new
Key identifying the implementation being tested.
Definition: test.h:327
CheckasmPerf::start
uint64_t(* start)(void)
Start timing measurement.
Definition: test.h:533
checkasm_unused
static void checkasm_unused(void)
Suppress unused variable warnings.
Definition: test.h:655
CheckasmPerf
Definition: test.h:527
checkasm_fail_func
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.
attributes.h
Platform and compiler attribute macros.
CheckasmPerf::stop
uint64_t(* stop)(uint64_t start_time)
Stop timing measurement.
Definition: test.h:540
CheckasmPerf::name
const char * name
Name of the timing mechanism (e.g., "clock_gettime")
Definition: test.h:543
checkasm_set_signal_handler_state
CHECKASM_API void checkasm_set_signal_handler_state(int enabled)
Enable or disable signal handling.
Definition: signal.c:52
checkasm_check_key
CHECKASM_API CheckasmKey checkasm_check_key(CheckasmKey key, const char *name,...) CHECKASM_PRINTF(2
Check if a key should be tested.
checkasm_set_func_variant
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_bench_update
CHECKASM_API void checkasm_bench_update(int iterations, uint64_t cycles)
Update benchmark statistics with timing results.
Definition: checkasm.c:472
key
const char * key
Definition: hwcontext_opencl.c:189
checkasm_push_stack_guard
CHECKASM_API void checkasm_push_stack_guard(uintptr_t guard[2])
Push stack guard values for corruption detection.
Definition: stackguard.c:41
checkasm_key_ref
static CheckasmKey checkasm_key_ref
Key identifying the reference implementation.
Definition: test.h:317
cycles
uint64_t cycles
Definition: checkasm.c:94
start_time
static int64_t start_time
Definition: ffplay.c:328
cpu_flags
CheckasmCpu cpu_flags
Definition: checkasm.c:84
platform.h
checkasm_bench_func
CHECKASM_API int checkasm_bench_func(void)
Check if current function should be benchmarked.
Definition: checkasm.c:449
checkasm_report
CHECKASM_API void checkasm_report(const char *name,...) CHECKASM_PRINTF(1
Report test outcome for a named group of functions.
perf.h
CheckasmPerf::unit
const char * unit
Unit of measurement (e.g., "ns", "cycles")
Definition: test.h:546
checkasm_bench_runs
CHECKASM_API int checkasm_bench_runs(void)
Get number of iterations for current benchmark run.
Definition: checkasm.c:454
CHECKASM_API
#define CHECKASM_API
Symbol visibility attribute for public API functions.
Definition: attributes.h:90
checkasm_get_perf
const CHECKASM_API CheckasmPerf * checkasm_get_perf(void)
Definition: perf.c:54
CheckasmKey
uintptr_t CheckasmKey
Opaque type used to identify function implementations.
Definition: checkasm.h:96
checkasm_pop_stack_guard
CHECKASM_API void checkasm_pop_stack_guard(void)
Definition: stackguard.c:66
checkasm_bench_finish
CHECKASM_API void checkasm_bench_finish(void)
Finalize and store benchmark results.
Definition: checkasm.c:486
checkasm_should_fail
CHECKASM_API int checkasm_should_fail(CheckasmCpu cpu_flags)
Mark a block of tests as expected to fail.
Definition: checkasm.c:1017
CheckasmCpu
uint64_t CheckasmCpu
Opaque type representing a set of CPU feature flags.
Definition: checkasm.h:88
CHECKASM_PRINTF
#define CHECKASM_PRINTF(fmt, attr)
Printf-style format string checking attribute.
Definition: attributes.h:59