Skip to content

Commit ea14e86

Browse files
committed
Auto merge of #14272 - epage:test-docs, r=weihanglo
docs(test): Expand documentation of cargo-test-support ### What does this PR try to resolve? In wanting to document #14039, I felt it would be good to put that documentation in `cargo-test-support`. To do so, I wanted a baseline of existing documentation for it to build on top of. I was tempted to move more of "Writing tests" contrib documentation here, as its more about using `cargo-test-support` but I decided to hold off for now as most of that was long-form documentation and this is mostly focused on reference documentation. ### How should we test and review this PR? ### Additional information
2 parents 693d49c + 83cbca0 commit ea14e86

File tree

10 files changed

+523
-228
lines changed

10 files changed

+523
-228
lines changed

crates/cargo-test-macro/src/lib.rs

+43
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,49 @@ use std::path::Path;
1414
use std::process::Command;
1515
use std::sync::Once;
1616

17+
/// Replacement for `#[test]`
18+
///
19+
/// The `#[cargo_test]` attribute extends `#[test]` with some setup before starting the test.
20+
/// It will create a filesystem "sandbox" under the "cargo integration test" directory for each test, such as `/path/to/cargo/target/tmp/cit/t123/`.
21+
/// The sandbox will contain a `home` directory that will be used instead of your normal home directory.
22+
///
23+
/// The `#[cargo_test]` attribute takes several options that will affect how the test is generated.
24+
/// They are listed in parentheses separated with commas, such as:
25+
///
26+
/// ```rust,ignore
27+
/// #[cargo_test(nightly, reason = "-Zfoo is unstable")]
28+
/// ```
29+
///
30+
/// The options it supports are:
31+
///
32+
/// * `>=1.64` --- This indicates that the test will only run with the given version of `rustc` or newer.
33+
/// This can be used when a new `rustc` feature has been stabilized that the test depends on.
34+
/// If this is specified, a `reason` is required to explain why it is being checked.
35+
/// * `nightly` --- This will cause the test to be ignored if not running on the nightly toolchain.
36+
/// This is useful for tests that use unstable options in `rustc` or `rustdoc`.
37+
/// These tests are run in Cargo's CI, but are disabled in rust-lang/rust's CI due to the difficulty of updating both repos simultaneously.
38+
/// A `reason` field is required to explain why it is nightly-only.
39+
/// * `requires_<cmd>` --- This indicates a command that is required to be installed to be run.
40+
/// For example, `requires_rustfmt` means the test will only run if the executable `rustfmt` is installed.
41+
/// These tests are *always* run on CI.
42+
/// This is mainly used to avoid requiring contributors from having every dependency installed.
43+
/// * `build_std_real` --- This is a "real" `-Zbuild-std` test (in the `build_std` integration test).
44+
/// This only runs on nightly, and only if the environment variable `CARGO_RUN_BUILD_STD_TESTS` is set (these tests on run on Linux).
45+
/// * `build_std_mock` --- This is a "mock" `-Zbuild-std` test (which uses a mock standard library).
46+
/// This only runs on nightly, and is disabled for windows-gnu.
47+
/// * `public_network_test` --- This tests contacts the public internet.
48+
/// These tests are disabled unless the `CARGO_PUBLIC_NETWORK_TESTS` environment variable is set.
49+
/// Use of this should be *extremely rare*, please avoid using it if possible.
50+
/// The hosts it contacts should have a relatively high confidence that they are reliable and stable (such as github.com), especially in CI.
51+
/// The tests should be carefully considered for developer security and privacy as well.
52+
/// * `container_test` --- This indicates that it is a test that uses Docker.
53+
/// These tests are disabled unless the `CARGO_CONTAINER_TESTS` environment variable is set.
54+
/// This requires that you have Docker installed.
55+
/// The SSH tests also assume that you have OpenSSH installed.
56+
/// These should work on Linux, macOS, and Windows where possible.
57+
/// Unfortunately these tests are not run in CI for macOS or Windows (no Docker on macOS, and Windows does not support Linux images).
58+
/// See [`cargo-test-support::containers`](https://doc.rust-lang.org/nightly/nightly-rustc/cargo_test_support/containers) for more on writing these tests.
59+
/// * `ignore_windows="reason"` --- Indicates that the test should be ignored on windows for the given reason.
1760
#[proc_macro_attribute]
1861
pub fn cargo_test(attr: TokenStream, item: TokenStream) -> TokenStream {
1962
// Ideally these options would be embedded in the test itself. However, I

crates/cargo-test-support/Cargo.toml

-3
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,6 @@ homepage.workspace = true
88
repository.workspace = true
99
description = "Testing framework for Cargo's testsuite."
1010

11-
[lib]
12-
doctest = false
13-
1411
[dependencies]
1512
anstream.workspace = true
1613
anstyle.workspace = true

crates/cargo-test-support/src/compare.rs

+32-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
//! Routines for comparing and diffing output.
22
//!
3-
//! # Patterns
3+
//! # Deprecated comparisons
4+
//!
5+
//! Cargo's tests are in transition from internal-only pattern and normalization routines used in
6+
//! asserts like [`crate::Execs::with_stdout`] to [`assert_e2e`] and [`assert_ui`].
7+
//!
8+
//! ## Patterns
49
//!
510
//! Many of these functions support special markup to assist with comparing
611
//! text that may vary or is otherwise uninteresting for the test at hand. The
@@ -22,7 +27,7 @@
2227
//! can use this to avoid duplicating the `with_stderr` call like:
2328
//! `if cfg!(target_env = "msvc") {e.with_stderr("...[DIRTY]...");} else {e.with_stderr("...");}`.
2429
//!
25-
//! # Normalization
30+
//! ## Normalization
2631
//!
2732
//! In addition to the patterns described above, the strings are normalized
2833
//! in such a way to avoid unwanted differences. The normalizations are:
@@ -86,6 +91,19 @@ macro_rules! regex {
8691
/// Other heuristics are applied to try to ensure Windows-style paths aren't
8792
/// a problem.
8893
/// - Carriage returns are removed, which can help when running on Windows.
94+
///
95+
/// # Example
96+
///
97+
/// ```no_run
98+
/// # use cargo_test_support::compare::assert_e2e;
99+
/// # use cargo_test_support::file;
100+
/// # let p = cargo_test_support::project().build();
101+
/// # let stdout = "";
102+
/// assert_e2e().eq(stdout, file!["stderr.term.svg"]);
103+
/// ```
104+
/// ```console
105+
/// $ SNAPSHOTS=overwrite cargo test
106+
/// ```
89107
pub fn assert_ui() -> snapbox::Assert {
90108
let mut subs = snapbox::Redactions::new();
91109
subs.extend(MIN_LITERAL_REDACTIONS.into_iter().cloned())
@@ -129,6 +147,18 @@ pub fn assert_ui() -> snapbox::Assert {
129147
/// Other heuristics are applied to try to ensure Windows-style paths aren't
130148
/// a problem.
131149
/// - Carriage returns are removed, which can help when running on Windows.
150+
///
151+
/// # Example
152+
///
153+
/// ```no_run
154+
/// # use cargo_test_support::compare::assert_e2e;
155+
/// # use cargo_test_support::str;
156+
/// # let p = cargo_test_support::project().build();
157+
/// assert_e2e().eq(p.read_lockfile(), str![]);
158+
/// ```
159+
/// ```console
160+
/// $ SNAPSHOTS=overwrite cargo test
161+
/// ```
132162
pub fn assert_e2e() -> snapbox::Assert {
133163
let mut subs = snapbox::Redactions::new();
134164
subs.extend(MIN_LITERAL_REDACTIONS.into_iter().cloned())

crates/cargo-test-support/src/git.rs

+54-49
Original file line numberDiff line numberDiff line change
@@ -1,60 +1,66 @@
1-
/*
2-
# Git Testing Support
3-
4-
## Creating a git dependency
5-
`git::new()` is an easy way to create a new git repository containing a
6-
project that you can then use as a dependency. It will automatically add all
7-
the files you specify in the project and commit them to the repository.
8-
Example:
9-
10-
```
11-
let git_project = git::new("dep1", |project| {
12-
project
13-
.file("Cargo.toml", &basic_manifest("dep1", "1.0.0"))
14-
.file("src/lib.rs", r#"pub fn f() { println!("hi!"); } "#)
15-
});
16-
17-
// Use the `url()` method to get the file url to the new repository.
18-
let p = project()
19-
.file("Cargo.toml", &format!(r#"
20-
[package]
21-
name = "a"
22-
version = "1.0.0"
23-
24-
[dependencies]
25-
dep1 = {{ git = '{}' }}
26-
"#, git_project.url()))
27-
.file("src/lib.rs", "extern crate dep1;")
28-
.build();
29-
```
30-
31-
## Manually creating repositories
32-
`git::repo()` can be used to create a `RepoBuilder` which provides a way of
33-
adding files to a blank repository and committing them.
34-
35-
If you want to then manipulate the repository (such as adding new files or
36-
tags), you can use `git2::Repository::open()` to open the repository and then
37-
use some of the helper functions in this file to interact with the repository.
38-
39-
*/
1+
//! # Git Testing Support
2+
//!
3+
//! ## Creating a git dependency
4+
//! [`new()`] is an easy way to create a new git repository containing a
5+
//! project that you can then use as a dependency. It will automatically add all
6+
//! the files you specify in the project and commit them to the repository.
7+
//!
8+
//! ### Example:
9+
//!
10+
//! ```no_run
11+
//! # use cargo_test_support::project;
12+
//! # use cargo_test_support::basic_manifest;
13+
//! # use cargo_test_support::git;
14+
//! let git_project = git::new("dep1", |project| {
15+
//! project
16+
//! .file("Cargo.toml", &basic_manifest("dep1", "1.0.0"))
17+
//! .file("src/lib.rs", r#"pub fn f() { println!("hi!"); } "#)
18+
//! });
19+
//!
20+
//! // Use the `url()` method to get the file url to the new repository.
21+
//! let p = project()
22+
//! .file("Cargo.toml", &format!(r#"
23+
//! [package]
24+
//! name = "a"
25+
//! version = "1.0.0"
26+
//!
27+
//! [dependencies]
28+
//! dep1 = {{ git = '{}' }}
29+
//! "#, git_project.url()))
30+
//! .file("src/lib.rs", "extern crate dep1;")
31+
//! .build();
32+
//! ```
33+
//!
34+
//! ## Manually creating repositories
35+
//!
36+
//! [`repo()`] can be used to create a [`RepoBuilder`] which provides a way of
37+
//! adding files to a blank repository and committing them.
38+
//!
39+
//! If you want to then manipulate the repository (such as adding new files or
40+
//! tags), you can use `git2::Repository::open()` to open the repository and then
41+
//! use some of the helper functions in this file to interact with the repository.
4042
4143
use crate::{paths::CargoPathExt, project, Project, ProjectBuilder, SymlinkBuilder};
4244
use std::fs;
4345
use std::path::{Path, PathBuf};
4446
use std::sync::Once;
4547
use url::Url;
4648

49+
/// Manually construct a [`Repository`]
50+
///
51+
/// See also [`new`], [`repo`]
4752
#[must_use]
4853
pub struct RepoBuilder {
4954
repo: git2::Repository,
5055
files: Vec<PathBuf>,
5156
}
5257

58+
/// See [`new`]
5359
pub struct Repository(git2::Repository);
5460

55-
/// Create a `RepoBuilder` to build a new git repository.
61+
/// Create a [`RepoBuilder`] to build a new git repository.
5662
///
57-
/// Call `build()` to finalize and create the repository.
63+
/// Call [`RepoBuilder::build()`] to finalize and create the repository.
5864
pub fn repo(p: &Path) -> RepoBuilder {
5965
RepoBuilder::init(p)
6066
}
@@ -130,7 +136,7 @@ impl Repository {
130136
}
131137
}
132138

133-
/// Initialize a new repository at the given path.
139+
/// *(`git2`)* Initialize a new repository at the given path.
134140
pub fn init(path: &Path) -> git2::Repository {
135141
default_search_path();
136142
let repo = t!(git2::Repository::init(path));
@@ -158,16 +164,15 @@ fn default_repo_cfg(repo: &git2::Repository) {
158164
t!(cfg.set_str("user.name", "Foo Bar"));
159165
}
160166

161-
/// Create a new git repository with a project.
167+
/// Create a new [`Project`] in a git [`Repository`]
162168
pub fn new<F>(name: &str, callback: F) -> Project
163169
where
164170
F: FnOnce(ProjectBuilder) -> ProjectBuilder,
165171
{
166172
new_repo(name, callback).0
167173
}
168174

169-
/// Create a new git repository with a project.
170-
/// Returns both the Project and the git Repository.
175+
/// Create a new [`Project`] with access to the [`Repository`]
171176
pub fn new_repo<F>(name: &str, callback: F) -> (Project, git2::Repository)
172177
where
173178
F: FnOnce(ProjectBuilder) -> ProjectBuilder,
@@ -182,14 +187,14 @@ where
182187
(git_project, repo)
183188
}
184189

185-
/// Add all files in the working directory to the git index.
190+
/// *(`git2`)* Add all files in the working directory to the git index
186191
pub fn add(repo: &git2::Repository) {
187192
let mut index = t!(repo.index());
188193
t!(index.add_all(["*"].iter(), git2::IndexAddOption::DEFAULT, None));
189194
t!(index.write());
190195
}
191196

192-
/// Add a git submodule to the repository.
197+
/// *(`git2`)* Add a git submodule to the repository
193198
pub fn add_submodule<'a>(
194199
repo: &'a git2::Repository,
195200
url: &str,
@@ -207,7 +212,7 @@ pub fn add_submodule<'a>(
207212
s
208213
}
209214

210-
/// Commit changes to the git repository.
215+
/// *(`git2`)* Commit changes to the git repository
211216
pub fn commit(repo: &git2::Repository) -> git2::Oid {
212217
let tree_id = t!(t!(repo.index()).write_tree());
213218
let sig = t!(repo.signature());
@@ -226,7 +231,7 @@ pub fn commit(repo: &git2::Repository) -> git2::Oid {
226231
))
227232
}
228233

229-
/// Create a new tag in the git repository.
234+
/// *(`git2`)* Create a new tag in the git repository
230235
pub fn tag(repo: &git2::Repository, name: &str) {
231236
let head = repo.head().unwrap().target().unwrap();
232237
t!(repo.tag(

crates/cargo-test-support/src/install.rs

+3
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
//! Helpers for testing `cargo install`
2+
13
use std::env::consts::EXE_SUFFIX;
24
use std::path::Path;
35

@@ -23,6 +25,7 @@ fn check_has_installed_exe<P: AsRef<Path>>(path: P, name: &'static str) -> bool
2325
path.as_ref().join("bin").join(exe(name)).is_file()
2426
}
2527

28+
/// `$name$EXE`
2629
pub fn exe(name: &str) -> String {
2730
format!("{}{}", name, EXE_SUFFIX)
2831
}

0 commit comments

Comments
 (0)