dicetest/macros.rs
1/// Adds a hint that contains the arguments applied to the [`format`] macro.
2///
3/// # Examples
4///
5/// ```
6/// use dicetest::hint;
7///
8/// let unknown_value = 42;
9/// hint!("Revealing the unknown value: {}", unknown_value);
10/// ```
11#[macro_export]
12macro_rules! hint {
13 ($($arg:tt)*) => {
14 $crate::hints::add(|| format!($($arg)*));
15 }
16}
17
18/// Adds a hint that contains the stringified argument and the argument value converted with
19/// [`Debug`].
20///
21/// [`Debug`]: std::fmt::Debug
22///
23/// # Examples
24///
25/// ```
26/// use dicetest::hint_debug;
27///
28/// let unknown_value = 42;
29/// hint_debug!(unknown_value);
30/// ```
31#[macro_export]
32macro_rules! hint_debug {
33 ($arg:tt) => {
34 $crate::hints::add(|| format!(concat!("{} = {:?}"), stringify!($arg), $arg));
35 };
36}
37
38/// Indents all hints in the caller's code block after this macro is called.
39///
40/// If arguments are specified, a (not indented) hint will be added with the arguments applied
41/// to the [`format`] macro. This hint is meant as the title of the section.
42///
43/// # Examples
44///
45/// ```
46/// use dicetest::{hint, hint_section};
47///
48/// hint!("Start test"); // This hint is not indented
49///
50/// {
51/// hint_section!("Test foo"); // This hint is not indented
52/// hint!("foo"); // This hint is indented
53/// }
54///
55/// {
56/// hint_section!("Test bar"); // This hint is not indented
57/// hint!("bar"); // This hint is indented
58///
59/// hint_section!(); // No hint
60/// hint!("bar"); // This hint is indented twice
61/// }
62///
63/// hint!("Test finished"); // This hint is not indented
64/// ```
65#[macro_export]
66macro_rules! hint_section {
67 () => {
68 let _block_ident = $crate::hints::Section::start();
69 };
70 ($($arg:tt)*) => {
71 $crate::hints::add(|| format!($($arg)*));
72 let _block_ident = $crate::hints::Section::start();
73 }
74}
75
76/// Creates a stat with the first argument as stat key and the remaining arguments applied to the
77/// [`format`] macro as stat value.
78///
79/// # Examples
80///
81/// ```
82/// use dicetest::stat;
83///
84/// let random_number = 4;
85/// stat!("Is random number even?", "{}", random_number % 2 == 0);
86/// ```
87#[macro_export]
88macro_rules! stat {
89 ($key:tt, $($arg:tt)*) => {
90 $crate::stats::inc($key, || format!($($arg)*))
91 }
92}
93
94/// Creates a stat with the stringified argument as stat key and the argument value converted with
95/// [`Debug`] as stat value.
96///
97/// [`Debug`]: std::fmt::Debug
98///
99/// # Examples
100///
101/// ```
102/// use dicetest::stat_debug;
103///
104/// let random_number = 4;
105/// stat_debug!({ random_number % 2 == 0 });
106/// ```
107#[macro_export]
108macro_rules! stat_debug {
109 ($arg:tt) => {
110 $crate::stats::inc(stringify!($arg), || format!("{:?}", $arg))
111 };
112}
113
114#[cfg(test)]
115mod tests {
116 #[test]
117 fn macro_hint_produces_valid_code() {
118 if false {
119 hint!("foo");
120 hint!("bar {}", 42);
121 }
122 }
123
124 #[test]
125 fn macro_hint_debug_produces_valid_code() {
126 if false {
127 hint_debug!(42);
128 hint_debug!((0 < 20));
129 hint_debug!((if true { 1 } else { 2 }));
130 }
131 }
132
133 #[test]
134 fn macro_hint_section_produces_valid_code() {
135 if false {
136 hint_section!();
137 hint_section!("foo");
138 hint_section!("bar {}", 42);
139 }
140 }
141
142 #[test]
143 #[cfg(feature = "hints")]
144 fn macro_hint_section_produces_correct_indent() {
145 let (_, actual_hints) = crate::hints::collect(|| {
146 {
147 hint!("foo1");
148 hint_section!();
149 hint!("foo2");
150 hint_section!("bar");
151 hint!("foo3");
152 };
153 hint!("foo4");
154 });
155 let expected_hints = crate::hints::Hints(vec![
156 crate::hints::Hint {
157 indent: 0,
158 text: "foo1".to_owned(),
159 },
160 crate::hints::Hint {
161 indent: 1,
162 text: "foo2".to_owned(),
163 },
164 crate::hints::Hint {
165 indent: 1,
166 text: "bar".to_owned(),
167 },
168 crate::hints::Hint {
169 indent: 2,
170 text: "foo3".to_owned(),
171 },
172 crate::hints::Hint {
173 indent: 0,
174 text: "foo4".to_owned(),
175 },
176 ]);
177 assert_eq!(expected_hints, actual_hints)
178 }
179
180 #[test]
181 fn macro_stat_produces_valid_code() {
182 if false {
183 stat!("A", "foo");
184 stat!("B", "bar {}", 42);
185 }
186 }
187
188 #[test]
189 fn macro_stat_debug_produces_valid_code() {
190 if false {
191 stat_debug!(42);
192 stat_debug!((0 < 20));
193 stat_debug!((if true { 1 } else { 2 }));
194 }
195 }
196}