protest_derive/
lib.rs

1//! Derive macros for the Protest property testing library
2//!
3//! This crate provides procedural macros for automatically implementing traits
4//! in the Protest library.
5
6use proc_macro::TokenStream;
7
8mod derive;
9mod property_test;
10
11/// Derive macro for automatically implementing the Generator trait
12///
13/// This macro can be applied to structs and enums to automatically generate
14/// implementations of the Generator trait.
15///
16/// # Basic Usage
17///
18/// ```rust
19/// use protest::Generator;
20///
21/// #[derive(Generator)]
22/// struct User {
23///     id: u32,
24///     name: String,
25///     active: bool,
26/// }
27/// ```
28///
29/// # Customization
30///
31/// The derive macro supports various customization attributes:
32///
33/// ```rust
34/// use protest::Generator;
35///
36/// #[derive(Generator)]
37/// struct CustomUser {
38///     #[generator(range = "1..1000")]
39///     id: u32,
40///     #[generator(length = "5..20")]
41///     name: String,
42///     #[generator(custom = "always_true")]
43///     active: bool,
44/// }
45///
46/// fn always_true() -> bool {
47///     true
48/// }
49/// ```
50///
51/// # Supported Attributes
52///
53/// - `range = "min..max"`: For numeric types, specifies the range of generated values
54/// - `length = "min..max"`: For collections and strings, specifies the length range
55/// - `custom = "function_name"`: Uses a custom function to generate the field value
56///
57/// # Generic Types
58///
59/// The derive macro supports generic types with appropriate bounds:
60///
61/// ```rust
62/// use protest::Generator;
63///
64/// #[derive(Generator)]
65/// struct GenericStruct<T, U> {
66///     first: T,
67///     second: U,
68/// }
69/// ```
70///
71/// # Enums
72///
73/// The derive macro supports enums with all variant types:
74///
75/// ```rust
76/// use protest::Generator;
77///
78/// #[derive(Generator)]
79/// enum Status {
80///     Active,
81///     Inactive(String),
82///     Pending { reason: String },
83/// }
84/// ```
85#[proc_macro_derive(Generator, attributes(generator))]
86pub fn derive_generator(input: TokenStream) -> TokenStream {
87    derive::derive_generator_impl(input)
88}
89
90/// Attribute macro for creating property-based tests
91///
92/// This macro transforms a regular test function into a property-based test by automatically
93/// generating test data and integrating with the Protest testing framework.
94///
95/// # Basic Usage
96///
97/// ```rust
98/// use protest::property_test;
99///
100/// #[property_test]
101/// fn test_addition_commutative(a: i32, b: i32) {
102///     assert_eq!(a + b, b + a);
103/// }
104/// ```
105///
106/// # Configuration Attributes
107///
108/// The macro supports various configuration attributes:
109///
110/// ```rust
111/// use protest::property_test;
112///
113/// #[property_test(iterations = 1000, seed = 42)]
114/// fn test_with_config(x: u32) {
115///     assert!(x >= 0);
116/// }
117/// ```
118///
119/// # Supported Attributes
120///
121/// - `iterations = N`: Number of test iterations (default: 100)
122/// - `seed = N`: Random seed for reproducible tests
123/// - `max_shrink_iterations = N`: Maximum shrinking attempts (default: 1000)
124/// - `shrink_timeout_secs = N`: Shrinking timeout in seconds (default: 10)
125///
126/// # Async Support
127///
128/// The macro automatically detects async functions and uses async property testing:
129///
130/// ```rust
131/// use protest::property_test;
132///
133/// #[property_test]
134/// async fn test_async_operation(data: String) {
135///     let result = some_async_operation(&data).await;
136///     assert!(!result.is_empty());
137/// }
138/// ```
139///
140/// # Generator Inference
141///
142/// The macro automatically infers generators for function parameters based on their types.
143/// For custom types, ensure they implement the `Generator` trait or derive it.
144#[proc_macro_attribute]
145pub fn property_test(args: TokenStream, input: TokenStream) -> TokenStream {
146    property_test::property_test_impl(args, input)
147}
148
149/// Macro for creating fluent property test builders
150///
151/// This macro provides shortcuts for common property test patterns and configurations.
152///
153/// # Basic Usage
154///
155/// ```rust
156/// use protest::test_builder;
157///
158/// test_builder! {
159///     iterations: 1000,
160///     seed: 42,
161///     test_name: my_property_test,
162///     generator: range(1, 100),
163///     property: |x: i32| x > 0
164/// }
165/// ```
166///
167/// # Supported Options
168///
169/// - `iterations`: Number of test iterations
170/// - `seed`: Random seed for reproducible tests
171/// - `max_shrink_iterations`: Maximum shrinking attempts
172/// - `shrink_timeout_secs`: Shrinking timeout in seconds
173/// - `test_name`: Name of the generated test function
174/// - `generator`: Generator expression
175/// - `property`: Property closure or function
176#[proc_macro]
177pub fn test_builder(input: TokenStream) -> TokenStream {
178    property_test::test_builder_impl(input)
179}