derive_deftly_tests/tests.rs
1#![allow(clippy::style, clippy::complexity, clippy::perf)]
2//! Tests for derive-deftly
3//!
4//! **Internal, unpublished crate.**
5//!
6//! Separating these tests into their own crate arranges that they
7//! can go through the "front door" of `use derive_deftly::...`,
8//! and in particular makes the cross-crate tests uniform with the others.
9//!
10//! ## Invoking the tests
11//!
12//! When running the full test suite,
13//! you should use a particular version of Nightly Rust:
14//! ```text
15//! rustup toolchain add nightly-2025-02-10
16//! cargo +nightly-2025-02-10 test --locked --workspace --all-features
17//! ```
18//! With other versions, the pretty printing of the macro expansions,
19//! or the results of standard library macros, can change,
20//! causing the tests to break.
21//!
22//! After your first run, it will probably be helpful to say
23//! ```text
24//! CARGO_NET_OFFLINE=true cargo +nightly-2025-02-10 test --locked --workspace --all-features
25//!```
26//! This is because otherwise cargo
27//! will uselessly re-update the cargo index,
28//! when it is reinvoked by some of the tests.
29//!
30//! ## Updating the expected outputs
31//!
32//! Many of the test cases compare an actual with expected output.
33//! For example, an expected macro expansion, or error message.
34//!
35//! If this is expected
36//! (for example, you added to the tests, or fixed a bug)
37//! can update the expected output files from the actual output.
38//!
39//! ```text
40//! TRYBUILD=overwrite MACROTEST=overwrite STDERRTEST=overwrite \
41//! CARGO_NET_OFFLINE=true cargo +nightly-2025-02-10 test --locked --workspace --all-features
42//! ```
43//!
44//! *Check that the actual output is as desired!*
45//! This is easily done with `git diff` before committing.
46//!
47//! ### Slight discrepancies in output, due to reformatting unfaithfulness
48//!
49//! The outputs in `tests/expand/` come from `cargo expand`,
50//! which reformats them for legibility.
51//! This reformatting is not always 100% faithful.
52//! For example, it can insert or remove `::` tokens.
53//!
54//! The output from `dbg_all_keywords` is completely faithful.
55//! This appears in `tests/stderr/recent.real-stderr`, for example.
56//!
57//! See
58//! [#13](https://gitlab.torproject.org/Diziet/rust-derive-deftly/-/issues/13)
59//! for some more discussion.
60//!
61//! ## Classes of test in the derive-deftly workspace
62//!
63//! Testing proc macros is not entirely straightforward,
64//! so there are multiple classes of test with different approaches.
65//!
66//! ### `tests/expand/*.rs`
67//!
68//! - Run with [`trybuild`], and expected to pass.
69//! - Expanded with `macrotest`, compared with `expand/*.expanded.rs`.
70//!
71//! Invoked from `tests/macrotest.rs`,
72//! using [`list_expand_test_paths`]
73//! and [`list_expand_test_paths_for_macrotest`].
74//!
75//! Tests with `recent` somewhere in their name are only run
76//! if the `recent` cargo feature is enabled for `derive-deftly-tests`.
77//! This is enabled in CI for the newer compilers, but not for the MSRV.
78//!
79//! ### `tests/ui/*.rs`
80//!
81//! - Run with trybuild and expected to fail.
82//! - Errors compared with `tests/ui/*.stderr`.
83//!
84//! Invoked from `tests/trybuild.rs`.
85//!
86//! Some of these `.rs` files are reused for `tests/stderr/`.
87//!
88//! #### `tests/minimal-ui/*.rs`
89//!
90//! As above, but used when feature `full` isn't enabled.
91//! This just tests errors from features being disabled.
92//! (In the tests, we include `beta` in `full`.)
93//!
94//! ### `tests/stderr/`
95//!
96//! Test cases listed in `tests/stderr/stderr-lib.rs`.
97//!
98//! - Compile attempted, and stderr captured
99//! - Output compared with `tests/stderr/combined.real-stderr`
100//!
101//! Invoked from `tests/stderr.rs`,
102//! which builds the crate `derive-deftly-stderr-tests`.
103//! See the doc comment there for details and rationale.
104//!
105//! ### `tests/pub-a/`, `tests/pub-b/`
106//!
107//! Tests of cross-crate exports of macros and templates.
108//! `pub-a` exports things, and `pub-b` imports and uses them.
109//!
110//! `pub-a` uses a special `bizarre` version of derive-deftly,
111//! to test that the right template expander is used in each case.
112//! See the [`pub-b` doc comment](../pub_b/index.html) for details.
113//!
114//! ### `tests/compat/`
115//!
116//! Tests compatibility with old, published, versions of derive-deftly.
117//! See `tests/compat/README.md`.
118//!
119//! ### The normal-ish `#[cfg(test)]` modules listed in here `tests/tests.rs`
120//!
121//! Each module is compiled, and its `#[test]` functions are run.
122//!
123//! ### `tests/directly/`
124//!
125//! Tests that go through the "back door",
126//! to use the innards of derive-deftly.
127//!
128//! Currently this is the tests in `directly::check_examples`
129//! which extract examples from `doc/reference.md`
130//! and check that they match real output.
131
132// We don't want to have to cfg-mark all the imports
133#![cfg_attr(
134 not(all(test, feature = "full", feature = "ui", feature = "recent")),
135 allow(unused_imports, dead_code)
136)]
137
138use std::cell::RefCell;
139use std::collections::HashMap;
140use std::fmt::Debug;
141use std::fmt::Display;
142use std::fs::File;
143use std::io::{BufRead, BufReader};
144use std::iter;
145use std::path::PathBuf;
146use std::rc::Rc;
147
148use easy_ext::ext;
149use educe::Educe;
150use itertools::Itertools;
151use regex::Regex;
152use static_assertions::assert_not_impl_any;
153
154pub mod tutils;
155pub use tutils::*;
156
157// These mostly serve to avoid rustdoc warnings from directly::macros,
158// which is macros.rs re-built outside the proc macro system.
159#[allow(unused_imports)]
160use derive_deftly::{define_derive_deftly, derive_deftly_adhoc, Deftly};
161
162//---------- modules containing straightforwrad `#[test]` tests ----------
163
164#[cfg(test)]
165mod list_names;
166
167#[cfg(test)]
168mod modules;
169
170// This is special, and contains tests that use a clone of the d-d-m crate
171#[cfg(not(doc))]
172mod directly;