summaryrefslogtreecommitdiff
path: root/deps/theft/theft_types.h
diff options
context:
space:
mode:
Diffstat (limited to 'deps/theft/theft_types.h')
-rw-r--r--deps/theft/theft_types.h197
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