11# Guide
22
33This is a short guide to chaos_theory basics. It covers how to write properties with
4- ` Source ` , with a focus on the two core building blocks after ` any ` : ` repeat ` and ` select ` ,
5- and includes an overview of generators.
4+ [ ` Source ` ] [ source ] , with a focus on the two core building blocks after [ ` any ` ] [ source_any ] :
5+ [ ` repeat ` ] [ source_repeat ] and [ ` select ` ] [ source_select ] , and includes an overview of generators.
66
7- * This is an AI-generated document that was manually reviewed and edited .*
7+ * Note: original version of this document was AI-generated .*
88
99## The Shape Of A Property
1010
@@ -20,17 +20,18 @@ check(|src| {
2020});
2121```
2222
23- ` Source ` gives you structured randomness. Your job is to explore the system using it.
23+ [ ` Source ` ] [ source ] gives you structured randomness. Your job is to explore the system using it.
2424
2525## Working With ` Source `
2626
2727The basic operations:
2828
29- - ` any ` / ` any_of ` generate values from ` Arbitrary ` or from a generator.
30- - ` choose ` selects an element from a slice.
31- - ` select ` chooses a labeled variant and runs a branch.
32- - ` repeat ` repeats a step, using ` Effect ` to report what happened.
33- - ` maybe ` and ` find ` are for optional steps and recoverable failures.
29+ - [ ` any ` ] [ source_any ] / [ ` any_of ` ] [ source_any_of ] generate values from [ ` Arbitrary ` ] [ arbitrary ]
30+ or from a generator.
31+ - [ ` choose ` ] [ source_choose ] selects an element from a slice.
32+ - [ ` select ` ] [ source_select ] chooses a labeled variant and runs a branch.
33+ - [ ` repeat ` ] [ source_repeat ] repeats a step, using [ ` Effect ` ] [ effect ] to report what happened.
34+ - [ ` maybe ` ] [ source_maybe ] and [ ` find ` ] [ source_find ] are for optional steps and recoverable failures.
3435
3536Labels matter. Use short, stable labels (like ` "action" ` or ` "key" ` ). They are
3637not required for chaos_theory to work, but they make replay output and
@@ -39,7 +40,7 @@ often enough to spot the issue immediately.
3940
4041## ` select ` : Variants With Meaning
4142
42- ` select ` is how you define structured choices:
43+ [ ` select ` ] [ source_select ] is how you define structured choices:
4344
4445``` rust
4546# fn prop (src : & mut chaos_theory :: Source ) {
@@ -55,11 +56,12 @@ src.select("action", &["insert", "remove", "get"], |src, action, _ix| {
5556```
5657
5758You should not encode a variant choice as ` any::<u8>() ` or a random number. Use
58- ` select ` so replay and minimization can preserve the variant choice when necessary.
59+ [ ` select ` ] [ source_select ] so replay and minimization can preserve the variant choice
60+ when necessary.
5961
6062## ` repeat ` : Exploration Over Time
6163
62- ` repeat ` is the right way to explore sequences:
64+ [ ` repeat ` ] [ source_repeat ] is the right way to explore sequences:
6365
6466``` rust
6567use chaos_theory :: Effect ;
@@ -72,13 +74,13 @@ src.repeat("step", |src| {
7274# }
7375```
7476
75- ` Effect ` matters:
77+ [ ` Effect ` ] [ effect ] matters:
7678
77- - ` Success ` : useful work was done.
78- - ` Change ` : state may have changed, but no clear progress.
79- - ` Noop ` : nothing happened to the system (example: action was non-applicable).
79+ - [ ` Success ` ] [ effect_success ] : useful work was done.
80+ - [ ` Change ` ] [ effect_change ] : state may have changed, but no clear progress.
81+ - [ ` Noop ` ] [ effect_noop ] : nothing happened to the system (example: action was non-applicable).
8082
81- Honest ` Effect ` values make exploration and minimization much more efficient.
83+ Honest [ ` Effect ` ] [ effect ] values make exploration and minimization much more efficient.
8284
8385### Common Anti-Pattern: Manual Random Loops
8486
@@ -93,8 +95,8 @@ for _ in 0..n {
9395# }
9496```
9597
96- Use ` repeat ` instead. ` repeat ` is structured and minimizes well, while manual
97- random loops are opaque and minimize poorly.
98+ Use [ ` repeat ` ] [ source_repeat ] instead. ` repeat ` is structured and minimizes
99+ well, while manual random loops are opaque and minimize poorly.
98100
99101Another version of the same issue is:
100102
@@ -105,7 +107,8 @@ if do_it { /* use src here */ }
105107# }
106108```
107109
108- Prefer ` maybe ` or ` select ` so the execution shape is tracked structurally.
110+ Prefer [ ` maybe ` ] [ source_maybe ] or [ ` select ` ] [ source_select ] so the execution shape is tracked
111+ structurally.
109112
110113## Stateful Testing (State Machines)
111114
@@ -115,7 +118,7 @@ already the "advanced" mode.
115118The most common pattern is:
116119
1171201 . Build the system under test and a reference model.
118- 2 . ` repeat ` a step that selects and applies an action.
121+ 2 . [ ` repeat ` ] [ source_repeat ] a step that selects and applies an action.
1191223 . Assert invariants or compare against the model.
120123
121124Example shape:
@@ -134,29 +137,33 @@ src.repeat("step", |src| {
134137# }
135138```
136139
137- Nested ` repeat ` and ` select ` are normal and encouraged for complex stateful systems.
140+ Nested [ ` repeat ` ] [ source_repeat ] and [ ` select ` ] [ source_select ] are normal and encouraged
141+ for complex stateful systems.
138142
139143## Filtering And Validity
140144
141145If you need to reject invalid values, prefer recoverable filtering:
142146
143- - ` Generator::filter ` returns ` Option ` so you can handle failure without panicking.
144- - ` filter_assume ` and ` assume! ` mark the whole test case as invalid when the condition fails.
147+ - [ ` Generator::filter ` ] [ generator_filter ] returns ` Option ` so you can handle failure
148+ without panicking.
149+ - [ ` filter_assume ` ] [ generator_filter_assume ] and [ ` assume! ` ] [ assume ] mark the whole test case as
150+ invalid when the condition fails.
145151
146- Too many invalid cases will make ` check ` fail early because it cannot generate enough valid tests.
152+ Too many invalid cases will make [ ` check ` ] [ check ] fail early because it cannot generate enough
153+ valid tests.
147154
148155## Debugging Output
149156
150- Use ` should_log ` , ` vdbg! ` , and ` vprintln! ` so output appears only for the
151- failing case. It keeps tests fast and logs focused.
157+ Use [ ` should_log ` ] [ source_should_log ] , [ ` vdbg! ` ] [ vdbg ] , and [ ` vprintln! ` ] [ vprintln ] so output
158+ appears only for the failing case. It keeps tests fast and logs focused.
152159
153160## Generators
154161
155162Most users never write custom generators. You can get far with:
156163
157- - built-in generators in ` make::* ` ,
158- - composing with ` select ` , ` repeat ` , and ` any ` ,
159- - occasional use of ` from_fn ` if needed.
164+ - built-in generators in [ ` make::* ` ] [ make ] ,
165+ - composing with [ ` select ` ] [ source_select ] , [ ` repeat ` ] [ source_repeat ] , and [ ` any ` ] [ source_any ] ,
166+ - occasional use of [ ` from_fn ` ] [ make_from_fn ] if needed.
160167
161168Custom generators are useful for domain types or complex invariants, but they
162169are not required for everyday property tests.
@@ -175,14 +182,22 @@ let v: Vec<String> = src.any("v");
175182
176183Common categories:
177184
178- - Core: ` just ` , ` one_of ` , ` mix_of ` , ` option ` , ` result `
179- - Numbers: ` int_in_range ` , ` float_in_range `
180- - Strings and chars: ` string ` , ` string_with_size ` , ` char_ascii ` , ` byte_ascii `
181- - Collections: ` vec ` , ` vec_with_size ` , ` btree_map ` , ` hash_map ` , ` btree_set ` , ` hash_set `
182- - Time: ` duration_in_range ` , ` system_time_in_range `
183- - Sync and cells: ` mutex ` , ` rw_lock ` , ` once_lock ` , ` cell ` , ` ref_cell `
184- - Regex (feature-gated): ` string_matching ` , ` bytes_matching `
185- - Extra crates (feature-gated): ` hashbrown ` , ` indexmap ` , ` ordered_float ` , ` tinyvec ` , ` ecow `
185+ - Core: [ ` just ` ] [ make_just ] , [ ` one_of ` ] [ make_one_of ] , [ ` mix_of ` ] [ make_mix_of ] ,
186+ [ ` option ` ] [ make_option ] , [ ` result ` ] [ make_result ]
187+ - Numbers: [ ` int_in_range ` ] [ make_int_in_range ] , [ ` float_in_range ` ] [ make_float_in_range ]
188+ - Strings and chars: [ ` string ` ] [ make_string ] , [ ` string_with_size ` ] [ make_string_with_size ] ,
189+ [ ` char_ascii ` ] [ make_char_ascii ] , [ ` byte_ascii ` ] [ make_byte_ascii ]
190+ - Collections: [ ` vec ` ] [ make_vec ] , [ ` vec_with_size ` ] [ make_vec_with_size ] ,
191+ [ ` btree_map ` ] [ make_btree_map ] , [ ` hash_map ` ] [ make_hash_map ] ,
192+ [ ` btree_set ` ] [ make_btree_set ] , [ ` hash_set ` ] [ make_hash_set ]
193+ - Time: [ ` duration_in_range ` ] [ make_duration_in_range ] ,
194+ [ ` system_time_in_range ` ] [ make_system_time_in_range ]
195+ - Sync and cells: [ ` mutex ` ] [ make_mutex ] , [ ` rw_lock ` ] [ make_rw_lock ] ,
196+ [ ` once_lock ` ] [ make_once_lock ] , [ ` cell ` ] [ make_cell ] , [ ` ref_cell ` ] [ make_ref_cell ]
197+ - Regex (feature-gated): [ ` string_matching ` ] [ make_string_matching ] ,
198+ [ ` bytes_matching ` ] [ make_bytes_matching ]
199+ - Extra crates (feature-gated): [ ` hashbrown ` ] [ make_hashbrown ] , [ ` indexmap ` ] [ make_indexmap ] ,
200+ [ ` ordered_float ` ] [ make_ordered_float ] , [ ` tinyvec ` ] [ make_tinyvec ] , [ ` ecow ` ] [ make_ecow ]
186201
187202If a generator exists, prefer using it instead of re-implementing the logic.
188203
@@ -198,10 +213,10 @@ without you having to tune distributions by hand.
198213
199214Useful combinators:
200215
201- - ` map ` and ` map_reversible ` for transforms
202- - ` or ` and ` mix_of ` for alternatives
203- - ` collect ` and ` collect_n ` for collections
204- - ` and_then ` for flat-map style composition
216+ - [ ` map ` ] [ generator_map ] and [ ` map_reversible ` ] [ generator_map_reversible ] for transforms
217+ - [ ` or ` ] [ generator_or ] and [ ` mix_of ` ] [ make_mix_of ] for alternatives
218+ - [ ` collect ` ] [ generator_collect ] and [ ` collect_n ` ] [ generator_collect_n ] for collections
219+ - [ ` and_then ` ] [ generator_and_then ] for flat-map style composition
205220
206221### Seeded Generation
207222
@@ -216,17 +231,17 @@ let city = make::string_matching("[A-Za-z '-]+", true).seeded(&cities, true);
216231# }
217232```
218233
219- Built-in generators already have seeds pre-configured internally,
220- so use ` seeded ` only to provide seeds that are specific to your domain.
234+ Built-in generators already have seeds pre-configured internally, so use [ ` seeded ` ] [ generator_seeded ]
235+ only to provide seeds that are specific to your domain.
221236
222237### Writing Custom Generators
223238
224239There are two main approaches:
225240
226- - Use ` make::from_fn ` for small generators
227- - Implement ` Generator ` directly for full control
241+ - Use [ ` make::from_fn ` ] [ make_from_fn ] for small generators
242+ - Implement [ ` Generator ` ] [ generator ] directly for full control
228243
229- Most of this becomes unnecessary once a derive macro for ` Arbitrary ` exists, but
244+ Most of this becomes unnecessary once a derive macro for [ ` Arbitrary ` ] [ arbitrary ] exists, but
230245it is still useful for domain-specific logic.
231246
232247#### Struct-Like Types
@@ -258,7 +273,7 @@ impl Generator for PointGen {
258273
259274#### Enum-Like Types
260275
261- Use ` select ` to choose a variant with a stable label:
276+ Use [ ` select ` ] [ sourceraw_select ] to choose a variant with a stable label:
262277
263278``` rust
264279use core :: num :: NonZero ;
@@ -305,7 +320,7 @@ impl Generator for OpGen {
305320
306321#### Collection-Like Types
307322
308- Use ` repeat ` to build the collection:
323+ Use [ ` repeat ` ] [ sourceraw_repeat ] to build the collection:
309324
310325``` rust
311326use chaos_theory :: {Arbitrary , Effect , Generator , SourceRaw };
@@ -344,4 +359,74 @@ The rule is simple: if you generate sub-values, pass the corresponding `example`
344359sub-values into their generators. This is how chaos_theory reconstructs known
345360values and minimizes effectively.
346361
347- Avoid calling ` Generator::next ` directly. Use ` Source::any ` or ` Source::any_of ` instead.
362+ Avoid calling [ ` Generator::next ` ] [ generator_next ] directly. Use [ ` Source::any ` ] [ source_any ] or
363+ [ ` Source::any_of ` ] [ source_any_of ] instead.
364+
365+ [ source ] : crate::Source
366+ [ source_any ] : crate::Source::any
367+ [ source_any_of ] : crate::Source::any_of
368+ [ source_choose ] : crate::Source::choose
369+ [ source_select ] : crate::Source::select
370+ [ source_repeat ] : crate::Source::repeat
371+ [ source_maybe ] : crate::Source::maybe
372+ [ source_find ] : crate::Source::find
373+ [ source_should_log ] : crate::Source::should_log
374+ [ sourceraw_select ] : crate::SourceRaw::select
375+ [ sourceraw_repeat ] : crate::SourceRaw::repeat
376+
377+ [ effect ] : crate::Effect
378+ [ effect_success ] : crate::Effect::Success
379+ [ effect_change ] : crate::Effect::Change
380+ [ effect_noop ] : crate::Effect::Noop
381+
382+ [ arbitrary ] : crate::Arbitrary
383+ [ generator ] : crate::Generator
384+ [ generator_filter ] : crate::Generator::filter
385+ [ generator_filter_assume ] : crate::Generator::filter_assume
386+ [ generator_map ] : crate::Generator::map
387+ [ generator_map_reversible ] : crate::Generator::map_reversible
388+ [ generator_or ] : crate::Generator::or
389+ [ generator_collect ] : crate::Generator::collect
390+ [ generator_collect_n ] : crate::Generator::collect_n
391+ [ generator_and_then ] : crate::Generator::and_then
392+ [ generator_seeded ] : crate::Generator::seeded
393+ [ generator_next ] : crate::Generator::next
394+
395+ [ check ] : crate::check
396+ [ assume ] : crate::assume
397+ [ vdbg ] : crate::vdbg
398+ [ vprintln ] : crate::vprintln
399+
400+ [ make ] : crate::make
401+ [ make_from_fn ] : crate::make::from_fn
402+ [ make_mix_of ] : crate::make::mix_of
403+ [ make_just ] : crate::make::just
404+ [ make_one_of ] : crate::make::one_of
405+ [ make_option ] : crate::make::option
406+ [ make_result ] : crate::make::result
407+ [ make_int_in_range ] : crate::make::int_in_range
408+ [ make_float_in_range ] : crate::make::float_in_range
409+ [ make_string ] : crate::make::string
410+ [ make_string_with_size ] : crate::make::string_with_size
411+ [ make_char_ascii ] : crate::make::char_ascii
412+ [ make_byte_ascii ] : crate::make::byte_ascii
413+ [ make_vec ] : crate::make::vec
414+ [ make_vec_with_size ] : crate::make::vec_with_size
415+ [ make_btree_map ] : crate::make::btree_map
416+ [ make_hash_map ] : crate::make::hash_map
417+ [ make_btree_set ] : crate::make::btree_set
418+ [ make_hash_set ] : crate::make::hash_set
419+ [ make_duration_in_range ] : crate::make::duration_in_range
420+ [ make_system_time_in_range ] : crate::make::system_time_in_range
421+ [ make_mutex ] : crate::make::mutex
422+ [ make_rw_lock ] : crate::make::rw_lock
423+ [ make_once_lock ] : crate::make::once_lock
424+ [ make_cell ] : crate::make::cell
425+ [ make_ref_cell ] : crate::make::ref_cell
426+ [ make_string_matching ] : crate::make::string_matching
427+ [ make_bytes_matching ] : crate::make::bytes_matching
428+ [ make_hashbrown ] : crate::make::hashbrown
429+ [ make_indexmap ] : crate::make::indexmap
430+ [ make_ordered_float ] : crate::make::ordered_float
431+ [ make_tinyvec ] : crate::make::tinyvec
432+ [ make_ecow ] : crate::make::ecow
0 commit comments