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
// SPDX-License-Identifier: GPL-3.0-only
//! Test-only helpers shared across the lib unit tests and the integration tests.
//!
//! CHR-014: resolve the repo root at RUNTIME, never via the compile-time
//! `env!("CARGO_MANIFEST_DIR")` macro. The jail shares one `CARGO_TARGET_DIR` across
//! worktrees, so a binary compiled in tree W (with W's path baked by `env!`) can be
//! reused when tests run from another tree — pointing reads at a dead/wrong path once
//! W is reaped. Cargo sets `CARGO_MANIFEST_DIR` in the test process's *runtime* env to
//! the invoking tree, so a runtime read is always correct regardless of which tree
//! compiled the binary.
//!
//! One source: declared `#[cfg(test)] mod test_support;` in `main.rs` for the lib unit
//! tests, and `#[path]`-included by `tests/common/mod.rs` for the integration tests
//! (separate compilation units that cannot see `cfg(test)` items in the lib).
use std::path::PathBuf;
/// Doctrine entity schema keys — single-source per STD-001.
pub(crate) const SCHEMA_BACKLOG: &str = "doctrine.backlog";
pub(crate) const SCHEMA_KNOWLEDGE: &str = "doctrine.knowledge";
pub(crate) const SCHEMA_ADR: &str = "doctrine.adr";
pub(crate) const SCHEMA_RFC: &str = "doctrine.rfc";
pub(crate) const SCHEMA_MEMORY: &str = "doctrine.memory";
pub(crate) const SCHEMA_PLAN: &str = "doctrine.plan";
pub(crate) const SCHEMA_PLAN_OVERVIEW: &str = "doctrine.plan.overview";
/// The repo root, resolved at runtime. Prefers cargo's runtime `CARGO_MANIFEST_DIR`
/// (set to the invoking tree); falls back to walking up from the CWD to the directory
/// holding `Cargo.toml`, for the rare non-cargo-driven run.
pub(crate) fn repo_root() -> PathBuf {
if let Ok(dir) = std::env::var("CARGO_MANIFEST_DIR") {
return PathBuf::from(dir);
}
let mut cur = std::env::current_dir().expect("resolve current dir");
loop {
if cur.join("Cargo.toml").is_file() {
return cur;
}
if !cur.pop() {
panic!("repo_root: no runtime CARGO_MANIFEST_DIR and no Cargo.toml ancestor of CWD");
}
}
}
/// The built `doctrine` binary, resolved at RUNTIME from the running test exe.
/// SL-162 / CHR-014: never bake the path via `env!("CARGO_BIN_EXE_doctrine")` —
/// a shared target serves one artifact across namespaces/profiles, so the baked
/// path NotFounds in the namespace that did not compile it.
pub(crate) fn doctrine_bin() -> PathBuf {
let mut p = std::env::current_exe().expect("resolve current_exe for doctrine_bin");
p.pop(); // drop test-exe name → …/deps/
p.pop(); // drop deps/ → …/<profile>/
p.push(format!("doctrine{}", std::env::consts::EXE_SUFFIX));
p
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn doctrine_bin_returns_existing_executable() {
let path = doctrine_bin();
// File name ends with "doctrine" (+ ".exe" on Windows).
let name = path.file_name().expect("doctrine_bin path has a file name");
let name_str = name
.to_str()
.expect("doctrine_bin file name is valid UTF-8");
assert!(
name_str.starts_with("doctrine"),
"doctrine_bin file name starts with 'doctrine': {name_str}"
);
// The resolved path exists.
assert!(
path.exists(),
"doctrine_bin path exists: {}",
path.display()
);
// It is a file, not a directory.
let meta = path.metadata().expect("doctrine_bin metadata readable");
assert!(meta.is_file(), "doctrine_bin is a file: {}", path.display());
// File size > 0 (non-zero binary).
assert!(
meta.len() > 0,
"doctrine_bin non-zero size: {}",
path.display()
);
}
}