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_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  */
512 CHECKASM_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 
528 typedef 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
553 } CheckasmPerf;
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  */
646 CHECKASM_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  */
656 static 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 */
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:328
CheckasmPerf::start
uint64_t(* start)(void)
Start timing measurement.
Definition: test.h:534
checkasm_unused
static void checkasm_unused(void)
Suppress unused variable warnings.
Definition: test.h:656
key
const char * key
Definition: ffmpeg_mux_init.c:2971
CheckasmPerf
Definition: test.h:528
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:541
CheckasmPerf::name
const char * name
Name of the timing mechanism (e.g., "clock_gettime")
Definition: test.h:544
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:489
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:318
cycles
uint64_t cycles
Definition: checkasm.c:94
start_time
static int64_t start_time
Definition: ffplay.c:329
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:466
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:547
checkasm_bench_runs
CHECKASM_API int checkasm_bench_runs(void)
Get number of iterations for current benchmark run.
Definition: checkasm.c:471
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:503
checkasm_should_fail
CHECKASM_API int checkasm_should_fail(CheckasmCpu cpu_flags)
Mark a block of tests as expected to fail.
Definition: checkasm.c:1085
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