derive_deftly_tests/
tests.rs

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
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
#![allow(clippy::style, clippy::complexity, clippy::perf)]
//! Tests for derive-deftly
//!
//! **Internal, unpublished crate.**
//!
//! Separating these tests into their own crate arranges that they
//! can go through the "front door" of `use derive_deftly::...`,
//! and in particular makes the cross-crate tests uniform with the others.
//!
//! ## Invoking the tests
//!
//! When running the full test suite,
//! you should use a particular version of Nightly Rust:
//! ```text
//! rustup toolchain add nightly-2024-06-06
//! cargo +nightly-2024-06-06 test --locked --workspace --all-features
//! ```
//! With other versions, the pretty printing of the macro expansions,
//! or the results of standard library macros, can change,
//! causing the tests to break.
//!
//! After your first run, it will probably be helpful to say
//! ```text
//! CARGO_NET_OFFLINE=true cargo +nightly-2024-06-06 test --locked --workspace --all-features
//!```
//! This is because otherwise cargo
//! will uselessly re-update the cargo index,
//! when it is reinvoked by some of the tests.
//!
//! ## Updating the expected outputs
//!
//! Many of the test cases compare an actual with expected output.
//! For example, an expected macro expansion, or error message.
//!
//! If this is expected
//! (for example, you added to the tests, or fixed a bug)
//! can update the expected output files from the actual output.
//!
//! ```text
//! TRYBUILD=overwrite MACROTEST=overwrite STDERRTEST=overwrite \
//! CARGO_NET_OFFLINE=true cargo +nightly-2024-06-06 test --locked --workspace --all-features
//! ```
//!
//! *Check that the actual output is as desired!*
//! This is easily done with `git diff` before committing.
//!
//! ### Slight discrepancies in output, due to reformatting unfaithfulness
//!
//! The outputs in `tests/expand/` come from `cargo expand`,
//! which reformats them for legibility.
//! This reformatting is not always 100% faithful.
//! For example, it can insert or remove `::` tokens.
//!
//! The output from `dbg_all_keywords` is completely faithful.
//! This appears in `tests/stderr/recent.real-stderr`, for example.
//!
//! See
//! [#13](https://gitlab.torproject.org/Diziet/rust-derive-deftly/-/issues/13)
//! for some more discussion.
//!
//! ## Classes of test in the derive-deftly workspace
//!
//! Testing proc macros is not entirely straightforward,
//! so there are multiple classes of test with different approaches.
//!
//! ### `tests/expand/*.rs`
//!
//!  - Run with [`trybuild`], and expected to pass.
//!  - Expanded with `macrotest`, compared with `expand/*.expanded.rs`.
//!
//! Invoked from `tests/macrotest.rs`,
//! using [`list_expand_test_paths`]
//! and [`list_expand_test_paths_for_macrotest`].
//!
//! Tests with `recent` somewhere in their name are only run
//! if the `recent` cargo feature is enabled for `derive-deftly-tests`.
//! This is enabled in CI for the newer compilers, but not for the MSRV.
//!
//! ### `tests/ui/*.rs`
//!
//!  - Run with trybuild and expected to fail.
//!  - Errors compared with `tests/ui/*.stderr`.
//!
//! Invoked from `tests/trybuild.rs`.
//!
//! Some of these `.rs` files are reused for `tests/stderr/`.
//!
//! #### `tests/minimal-ui/*.rs`
//!
//! As above, but used when feature `full` isn't enabled.
//! This just tests errors from features being disabled.
//! (In the tests, we include `beta` in `full`.)
//!
//! ### `tests/stderr/`
//!
//! Test cases listed in `tests/stderr/stderr-lib.rs`.
//!
//!  - Compile attempted, and stderr captured
//!  - Output compared with `tests/stderr/combined.real-stderr`
//!
//! Invoked from `tests/stderr.rs`,
//! which builds the crate `derive-deftly-stderr-tests`.
//! See the doc comment there for details and rationale.
//!
//! ### `tests/pub-a/`, `tests/pub-b/`
//!
//! Tests of cross-crate exports of macros and templates.
//! `pub-a` exports things, and `pub-b` imports and uses them.
//!
//! `pub-a` uses a special `bizarre` version of derive-deftly,
//! to test that the right template expander is used in each case.
//! See the [`pub-b` doc comment](../pub_b/index.html) for details.
//!
//! ### `tests/compat/`
//!
//! Tests compatibility with old, published, versions of derive-deftly.
//! See `tests/compat/README.md`.
//!
//! ### The normal-ish `#[cfg(test)]` modules listed in here `tests/tests.rs`
//!
//! Each module is compiled, and its `#[test]` functions are run.
//!
//! ### `tests/directly/`
//!
//! Tests that go through the "back door",
//! to use the innards of derive-deftly.
//!
//! Currently this is the tests in `directly::check_examples`
//! which extract examples from `doc/reference.md`
//! and check that they match real output.

// We don't want to have to cfg-mark all the imports
#![cfg_attr(
    not(all(test, feature = "full", feature = "ui", feature = "recent")),
    allow(unused_imports, dead_code)
)]

use std::cell::RefCell;
use std::collections::HashMap;
use std::fmt::Debug;
use std::fmt::Display;
use std::fs::File;
use std::io::{BufRead, BufReader};
use std::iter;
use std::path::PathBuf;
use std::rc::Rc;

use easy_ext::ext;
use educe::Educe;
use itertools::Itertools;
use regex::Regex;
use static_assertions::assert_not_impl_any;

pub mod tutils;
pub use tutils::*;

// These mostly serve to avoid rustdoc warnings from directly::macros,
// which is macros.rs re-built outside the proc macro system.
#[allow(unused_imports)]
use derive_deftly::{define_derive_deftly, derive_deftly_adhoc, Deftly};

//---------- modules containing straightforwrad `#[test]` tests ----------

#[cfg(test)]
mod list_names;

#[cfg(test)]
mod modules;

// This is special, and contains tests that use a clone of the d-d-m crate
#[cfg(not(doc))]
mod directly;