tryexpand/
lib.rs

1//! Test harness for macro expansion.
2
3#![allow(clippy::test_attr_in_doctest)]
4
5use std::{panic::Location, path::Path};
6
7mod cargo;
8mod error;
9mod manifest;
10mod message;
11mod normalization;
12mod options;
13mod project;
14mod test;
15mod test_suite;
16mod utils;
17
18pub(crate) const TRYEXPAND_ENV_KEY: &str = "TRYEXPAND";
19pub(crate) const TRYEXPAND_ENV_VAL_OVERWRITE: &str = "overwrite";
20pub(crate) const TRYEXPAND_ENV_VAL_EXPECT: &str = "expect";
21
22pub(crate) const TRYEXPAND_KEEP_ARTIFACTS_ENV_KEY: &str = "TRYEXPAND_KEEP_ARTIFACTS";
23pub(crate) const TRYEXPAND_TRUNCATE_OUTPUT_ENV_KEY: &str = "TRYEXPAND_TRUNCATE_OUTPUT";
24pub(crate) const TRYEXPAND_DEBUG_LOG_ENV_KEY: &str = "TRYEXPAND_DEBUG_LOG";
25
26pub(crate) const OUT_RS_FILE_SUFFIX: &str = "out.rs";
27pub(crate) const OUT_TXT_FILE_SUFFIX: &str = "out.txt";
28pub(crate) const ERR_TXT_FILE_SUFFIX: &str = "err.txt";
29
30use crate::{
31    test::Action,
32    test_suite::{BuildTestSuite, ExpandTestSuite, TestSuite},
33};
34
35/// Run snapshot tests on files that match the provided paths/glob patterns,
36/// snapshotting the source code as it is produced by `cargo expand`.
37///
38/// # Examples
39///
40/// Simple:
41///
42/// ```
43/// #[test]
44/// pub fn pass() {
45///     tryexpand::expand(
46///         ["tests/expand/pass/*.rs"]
47///     ).expect_pass();
48/// }
49///
50/// #[test]
51/// pub fn fail() {
52///     tryexpand::expand(
53///         ["tests/expand/fail/*.rs"]
54///     ).expect_fail();
55/// }
56/// ```
57///
58/// Advanced:
59///
60/// ```
61/// #[test]
62/// pub fn pass() {
63///     tryexpand::expand(
64///         [
65///             "tests/expand/foo/pass/*.rs",
66///             "tests/expand/bar/pass/*.rs"
67///         ]
68///     )
69///     .args(["--features", "test-feature"])
70///     .envs([("MY_ENV", "my env var value")])
71///     .and_check() // also type-check the code on successful macro-expansion
72///     .expect_pass();
73/// }
74/// ```
75#[track_caller] // LOAD-BEARING, DO NOT REMOVE!
76pub fn expand<I, P>(patterns: I) -> ExpandTestSuite
77where
78    I: IntoIterator<Item = P>,
79    P: AsRef<Path>,
80{
81    match TestSuite::new(patterns, Action::Expand, Location::caller()) {
82        Ok(test_suite) => ExpandTestSuite(test_suite),
83        Err(err) => panic!("Error: {err:?}"),
84    }
85}
86
87/// Run snapshot tests on files that match the provided paths/glob patterns,
88/// snapshotting the stdout/stderr output as it is produced by `cargo check [ARGS]`.
89///
90/// # Examples
91///
92/// Simple:
93///
94/// ```
95/// #[test]
96/// pub fn pass() {
97///     tryexpand::check(
98///         ["tests/expand/pass/*.rs"]
99///     ).expect_pass();
100/// }
101///
102/// #[test]
103/// pub fn fail() {
104///     tryexpand::check(
105///         ["tests/expand/fail/*.rs"]
106///     ).expect_fail();
107/// }
108/// ```
109///
110/// Advanced:
111///
112/// ```
113/// #[test]
114/// pub fn pass() {
115///     tryexpand::check(
116///         [
117///             "tests/expand/foo/pass/*.rs",
118///             "tests/expand/bar/pass/*.rs"
119///         ]
120///     )
121///     .args(["--features", "test-feature"])
122///     .envs([("MY_ENV", "my env var value")])
123///     .expect_pass();
124/// }
125/// ```
126#[track_caller] // LOAD-BEARING, DO NOT REMOVE!
127pub fn check<I, P>(patterns: I) -> BuildTestSuite
128where
129    I: IntoIterator<Item = P>,
130    P: AsRef<Path>,
131{
132    match TestSuite::new(patterns, Action::Check, Location::caller()) {
133        Ok(test_suite) => BuildTestSuite(test_suite),
134        Err(err) => panic!("Error: {err:?}"),
135    }
136}
137
138/// Run snapshot tests on files that match the provided paths/glob patterns,
139/// snapshotting the stdout/stderr output as it is produced by `cargo run [ARGS]`.
140///
141/// # Examples
142///
143/// Simple:
144///
145/// ```
146/// #[test]
147/// pub fn pass() {
148///     tryexpand::run(
149///         ["tests/expand/pass/*.rs"]
150///     ).expect_pass();
151/// }
152///
153/// #[test]
154/// pub fn fail() {
155///     tryexpand::run(
156///         ["tests/expand/fail/*.rs"]
157///     ).expect_fail();
158/// }
159/// ```
160///
161/// Advanced:
162///
163/// ```
164/// #[test]
165/// pub fn pass() {
166///     tryexpand::run(
167///         [
168///             "tests/expand/foo/pass/*.rs",
169///             "tests/expand/bar/pass/*.rs"
170///         ]
171///     )
172///     .args(["--features", "test-feature"])
173///     .envs([("MY_ENV", "my env var value")])
174///     .expect_pass();
175/// }
176/// ```
177#[track_caller] // LOAD-BEARING, DO NOT REMOVE!
178pub fn run<I, P>(patterns: I) -> BuildTestSuite
179where
180    I: IntoIterator<Item = P>,
181    P: AsRef<Path>,
182{
183    match TestSuite::new(patterns, Action::Run, Location::caller()) {
184        Ok(test_suite) => BuildTestSuite(test_suite),
185        Err(err) => panic!("Error: {err:?}"),
186    }
187}
188
189/// Run snapshot tests on files that match the provided paths/glob patterns,
190/// snapshotting the stdout/stderr output as it is produced by `cargo test [ARGS]`.
191///
192/// # Examples
193///
194/// Simple:
195///
196/// ```
197/// #[test]
198/// pub fn pass() {
199///     tryexpand::run_tests(
200///         ["tests/expand/pass/*.rs"]
201///     ).expect_pass();
202/// }
203///
204/// #[test]
205/// pub fn fail() {
206///     tryexpand::run_tests(
207///         ["tests/expand/fail/*.rs"]
208///     ).expect_fail();
209/// }
210/// ```
211///
212/// Advanced:
213///
214/// ```
215/// #[test]
216/// pub fn pass() {
217///     tryexpand::run_tests(
218///         [
219///             "tests/expand/foo/pass/*.rs",
220///             "tests/expand/bar/pass/*.rs"
221///         ]
222///     )
223///     .args(["--features", "test-feature"])
224///     .envs([("MY_ENV", "my env var value")])
225///     .expect_pass();
226/// }
227/// ```
228#[track_caller] // LOAD-BEARING, DO NOT REMOVE!
229pub fn run_tests<I, P>(patterns: I) -> BuildTestSuite
230where
231    I: IntoIterator<Item = P>,
232    P: AsRef<Path>,
233{
234    match TestSuite::new(patterns, Action::Test, Location::caller()) {
235        Ok(test_suite) => BuildTestSuite(test_suite),
236        Err(err) => panic!("Error: {err:?}"),
237    }
238}