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
//! Fixtures shared by the driver's unit tests.
//!
//! A module of its own so the three test modules can build the same
//! capability-scoped directories, and assert against the same two tables,
//! without an ambient filesystem write apiece. Every item is `pub(super)`
//! because the only modules that use them are `super`'s descendants.
use camino::{Utf8Path, Utf8PathBuf};
use cap_std::{ambient_authority, fs_utf8::Dir};
use mdtablefix::io::SourceDocument;
use tempfile::{TempDir, tempdir};
use super::ReadOnlyDir;
/// A ragged table, whose every line the aligning formatter below replaces.
pub(super) const RAGGED: &str = "|A|B|\n|---|---|\n|1|2|\n";
/// The aligned table the same formatter produces.
pub(super) const ALIGNED: &str = "| A | B |\n| --- | --- |\n| 1 | 2 |\n";
/// A formatter that reproduces its input.
///
/// A true fixed point for these fixtures: the document boundary re-renders the
/// body with its own mark and line endings, so an unchanged assessment is
/// distinguishable from a changed one.
pub(super) fn identity(document: &SourceDocument<'_>) -> String {
document.render(
document
.body()
.lines()
.map(str::to_string)
.collect::<Vec<_>>()
.as_slice(),
)
}
/// A formatter that always produces the aligned table.
///
/// Every line of a ragged fixture differs from its aligned counterpart, so the
/// counts these tests assert are the three replacements `--check` reports.
pub(super) fn align(document: &SourceDocument<'_>) -> String {
document.render(
ALIGNED
.lines()
.map(str::to_string)
.collect::<Vec<_>>()
.as_slice(),
)
}
/// Writes `content` as `name` in a fresh capability-scoped directory, creating
/// the directory `name` names if it has one.
///
/// The fixture is created through the capability rather than beside it, so a
/// test's only view of the file is the one every mode under test is handed.
/// The [`TempDir`] is returned so the caller keeps it alive for the length of
/// the test; dropping it would delete the directory the capability names.
pub(super) fn fixture(name: &str, content: &str) -> (TempDir, Dir) {
let dir = tempdir().expect("create temporary directory");
let path = Utf8PathBuf::from_path_buf(dir.path().to_path_buf())
.expect("the temporary directory path is UTF-8");
let directory =
Dir::open_ambient_dir(&path, ambient_authority()).expect("open directory capability");
let name = Utf8Path::new(name);
if let Some(parent) = name.parent().filter(|parent| !parent.as_str().is_empty()) {
directory
.create_dir_all(parent)
.expect("create the fixture's parent directory");
}
directory.write(name, content).expect("write fixture");
(dir, directory)
}
/// Reads `name` through the capability, so a rewrite is observed as the
/// capability sees it rather than through an ambient path.
pub(super) fn read(directory: &Dir, name: &str) -> String {
directory
.read_to_string(Utf8Path::new(name))
.expect("read fixture")
}
/// A read-only view of `directory`.
pub(super) fn readable(directory: &Dir) -> ReadOnlyDir {
ReadOnlyDir::new(
directory
.try_clone()
.expect("duplicate directory capability"),
)
}