diff options
Diffstat (limited to 'deps/theft/theft_types.h')
-rw-r--r-- | deps/theft/theft_types.h | 197 |
1 files changed, 197 insertions, 0 deletions
diff --git a/deps/theft/theft_types.h b/deps/theft/theft_types.h new file mode 100644 index 0000000..a966b04 --- /dev/null +++ b/deps/theft/theft_types.h @@ -0,0 +1,197 @@ +#ifndef THEFT_TYPES_H +#define THEFT_TYPES_H + +/* A pseudo-random number/seed, used to generate instances. */ +typedef uint64_t theft_seed; + +/* A hash of an instance. */ +typedef uint64_t theft_hash; + +/* These are opaque, as far as the API is concerned. */ +struct theft_bloom; /* bloom filter */ +struct theft_mt; /* mersenne twister PRNG */ + +/* Struct for property-testing state. */ +struct theft { + FILE *out; + theft_seed seed; + uint8_t requested_bloom_bits; + struct theft_bloom *bloom; /* bloom filter */ + struct theft_mt *mt; /* random number generator */ +}; + +/* Special sentinel values returned instead of instance pointers. */ +#define THEFT_SKIP ((void *)-1) +#define THEFT_ERROR ((void *)-2) +#define THEFT_DEAD_END ((void *)-1) +#define THEFT_NO_MORE_TACTICS ((void *)-3) + +/* Explicitly disable using the bloom filter. + * Note that if you do this, you must be sure your simplify function + * *always* returns a simpler value, or it will loop forever. */ +#define THEFT_BLOOM_DISABLE ((uint8_t)-1) + +/* Allocate and return an instance of the type, based on a known + * pseudo-random number seed. To get additional seeds, use + * theft_random(t); this stream of numbers will be deterministic, so if + * the alloc callback is constructed appropriately, an identical + * instance can be constructed later from the same initial seed. + * + * Returns a pointer to the instance, THEFT_ERROR, or THEFT_SKIP. */ +typedef void *(theft_alloc_cb)(struct theft *t, theft_seed seed, void *env); + +/* Free an instance. */ +typedef void (theft_free_cb)(void *instance, void *env); + +/* Hash an instance. Used to skip combinations of arguments which + * have probably already been checked. */ +typedef theft_hash (theft_hash_cb)(void *instance, void *env); + +/* Attempt to shrink an instance to a simpler instance. + * + * For a given INSTANCE, there are likely to be multiple ways in which + * it can be simplified. For example, a list of unsigned ints could have + * the first element decremented, divided by 2, or dropped. This + * callback should return a pointer to a freshly allocated, simplified + * instance, or should return THEFT_DEAD_END to indicate that the + * instance cannot be simplified further by this method. + * + * These tactics will be lazily explored breadth-first, to + * try to find simpler versions of arguments that cause the + * property to no longer hold. + * + * If this callback is NULL, it is equivalent to always returning + * THEFT_NO_MORE_TACTICS. */ +typedef void *(theft_shrink_cb)(void *instance, uint32_t tactic, void *env); + +/* Print INSTANCE to output stream F. + * Used for displaying counter-examples. Can be NULL. */ +typedef void (theft_print_cb)(FILE *f, void *instance, void *env); + +/* Result from a single trial. */ +typedef enum { + THEFT_TRIAL_PASS, /* property held */ + THEFT_TRIAL_FAIL, /* property contradicted */ + THEFT_TRIAL_SKIP, /* user requested skip; N/A */ + THEFT_TRIAL_DUP, /* args probably already tried */ + THEFT_TRIAL_ERROR, /* unrecoverable error, halt */ +} theft_trial_res; + +/* A test property function. Arguments must match the types specified by + * theft_cfg.type_info, or the result will be undefined. For example, a + * propfun `prop_foo(A x, B y, C z)` must have a type_info array of + * `{ info_A, info_B, info_C }`. + * + * Should return: + * THEFT_TRIAL_PASS if the property holds, + * THEFT_TRIAL_FAIL if a counter-example is found, + * THEFT_TRIAL_SKIP if the combination of args isn't applicable, + * or THEFT_TRIAL_ERROR if the whole run should be halted. */ +typedef theft_trial_res (theft_propfun)( /* arguments unconstrained */ ); + +/* Callbacks used for testing with random instances of a type. + * For more information, see comments on their typedefs. */ +struct theft_type_info { + /* Required: */ + theft_alloc_cb *alloc; /* gen random instance from seed */ + + /* Optional, but recommended: */ + theft_free_cb *free; /* free instance */ + theft_hash_cb *hash; /* instance -> hash */ + theft_shrink_cb *shrink; /* shrink instance */ + theft_print_cb *print; /* fprintf instance */ +}; + +/* Result from an individual trial. */ +struct theft_trial_info { + const char *name; /* property name */ + int trial; /* N'th trial */ + theft_seed seed; /* Seed used */ + theft_trial_res status; /* Run status */ + uint8_t arity; /* Number of arguments */ + void **args; /* Arguments used */ +}; + +/* Whether to keep running trials after N failures/skips/etc. */ +typedef enum { + THEFT_PROGRESS_CONTINUE, /* keep running trials */ + THEFT_PROGRESS_HALT, /* no need to continue */ +} theft_progress_callback_res; + +/* Handle test results. + * Can be used to halt after too many failures, print '.' after + * every N trials, etc. */ +typedef theft_progress_callback_res +(theft_progress_cb)(struct theft_trial_info *info, void *env); + +/* Result from a trial run. */ +typedef enum { + THEFT_RUN_PASS = 0, /* no failures */ + THEFT_RUN_FAIL = 1, /* 1 or more failures */ + THEFT_RUN_ERROR = 2, /* an error occurred */ + THEFT_RUN_ERROR_BAD_ARGS = -1, /* API misuse */ + /* Missing required callback for 1 or more types */ + THEFT_RUN_ERROR_MISSING_CALLBACK = -2, +} theft_run_res; + +/* Optional report from a trial run; same meanings as theft_trial_res. */ +struct theft_trial_report { + size_t pass; + size_t fail; + size_t skip; + size_t dup; +}; + +/* Configuration struct for a theft test. + * In C99, this struct can be specified as a literal, like this: + * + * struct theft_cfg cfg = { + * .name = "example", + * .fun = prop_fun, + * .type_info = { type_arg_a, type_arg_b }, + * .seed = 0x7he5eed, + * }; + * + * and omitted fields will be set to defaults. + * */ +struct theft_cfg { + /* Property function under test, and info about its arguments. + * The function is called with as many arguments are there + * are values in TYPE_INFO, so it can crash if that is wrong. */ + theft_propfun *fun; + struct theft_type_info *type_info[THEFT_MAX_ARITY]; + + /* -- All fields after this point are optional. -- */ + + /* Property name, displayed in test runner output. */ + const char *name; + + /* Array of seeds to always run, and its length. + * Can be used for regression tests. */ + int always_seed_count; /* number of seeds */ + theft_seed *always_seeds; /* seeds to always run */ + + /* Number of trials to run. Defaults to THEFT_DEF_TRIALS. */ + int trials; + + /* Progress callback, used to display progress in + * slow-running tests, halt early under certain conditions, etc. */ + theft_progress_cb *progress_cb; + + /* Environment pointer. This is completely opaque to theft itself, + * but will be passed along to all callbacks. */ + void *env; + + /* Struct to populate with more detailed test results. */ + struct theft_trial_report *report; + + /* Seed for the random number generator. */ + theft_seed seed; +}; + +/* Internal state for incremental hashing. */ +struct theft_hasher { + theft_hash accum; +}; + +#endif |