1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
use TokenStream;
use ;
/// Derive a generator for a struct or enum.
///
/// This implements [`DefaultGenerator`](hegel::generators::DefaultGenerator) for the type,
/// allowing it to be used with [`default`](hegel::generators::default) via `default::<T>()`.
///
/// For structs, the generated generator has:
/// - `<field>(generator)` - builder method to customize each field's generator
///
/// For enums, the generated generator has:
/// - `default_<VariantName>()` - methods returning default variant generators
/// - `<VariantName>(generator)` - builder methods to customize variant generation
///
/// # Struct Example
///
/// ```ignore
/// use hegel::DefaultGenerator;
/// use hegel::generators::{self, DefaultGenerator as _, Generator as _};
///
/// #[derive(DefaultGenerator)]
/// struct Person {
/// name: String,
/// age: u32,
/// }
///
/// #[hegel::test]
/// fn generates_people(tc: hegel::TestCase) {
/// let generator = generators::default::<Person>()
/// .age(generators::integers::<u32>().min_value(0).max_value(120));
/// let person: Person = tc.draw(generator);
/// }
/// ```
///
/// # Enum Example
///
/// ```ignore
/// use hegel::DefaultGenerator;
/// use hegel::generators::{self, DefaultGenerator as _, Generator as _};
///
/// #[derive(DefaultGenerator)]
/// enum Status {
/// Pending,
/// Active { since: String },
/// Error { code: i32, message: String },
/// }
///
/// #[hegel::test]
/// fn generates_statuses(tc: hegel::TestCase) {
/// let generator = generators::default::<Status>()
/// .Active(
/// generators::default::<Status>()
/// .default_Active()
/// .since(generators::text().max_size(20))
/// );
/// let status: Status = tc.draw(generator);
/// }
/// ```
/// The main entrypoint into Hegel.
///
/// The function must take exactly one parameter of type `hegel::TestCase`. The test case can be
/// used to generate values via `tc.draw()`.
///
/// The `#[test]` attribute is added automatically and must not be present on the function.
///
/// ```ignore
/// #[hegel::test]
/// fn my_test(tc: TestCase) {
/// let x: i32 = tc.draw(integers());
/// assert!(x + 0 == x);
/// }
///
/// You can set settings with on `hegel::test`, corresponding to methods on [`Settings`](hegel::Settings):
///
/// #[hegel::test(test_cases = 500)]
/// fn test_runs_many_more_times(tc: TestCase) {
/// let x: i32 = tc.draw(integers());
/// assert!(x + 0 == x);
/// }
/// ```
/// Define a composite generator from a function.
///
/// The first parameter must be `tc: TestCase` and is passed automatically
/// when the generator is drawn. Any additional parameters become parameters
/// of the returned factory function. The function must have an explicit
/// return type.
///
/// ```ignore
/// use hegel::generators;
///
/// #[hegel::composite]
/// fn sorted_vec(tc: hegel::TestCase, min_len: usize) -> Vec<i32> {
/// let mut v: Vec<i32> = tc.draw(generators::vecs(generators::integers()).min_size(min_len));
/// v.sort();
/// v
/// }
///
/// #[hegel::test]
/// fn test_sorted(tc: hegel::TestCase) {
/// let v = tc.draw(sorted_vec(3));
/// assert!(v.len() >= 3);
/// assert!(v.windows(2).all(|w| w[0] <= w[1]));
/// }
/// ```