From 7111cea5492ff90c6b38f0500519618c64fc34f2 Mon Sep 17 00:00:00 2001 From: Jeroen Schweitzer Date: Fri, 17 Jul 2026 10:42:06 +0200 Subject: [PATCH] =?UTF-8?q?fix(engine):=20clippy=20items=5Fafter=5Ftest=5F?= =?UTF-8?q?module=20=E2=80=94=20tests=20mod=20to=20end=20of=20main.rs?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Fable 5 --- server/src/main.rs | 282 ++++++++++++++++++++++----------------------- 1 file changed, 141 insertions(+), 141 deletions(-) diff --git a/server/src/main.rs b/server/src/main.rs index db4a5ee7c..891f0deac 100644 --- a/server/src/main.rs +++ b/server/src/main.rs @@ -517,147 +517,6 @@ fn systems_db_candidates(exe_path: Option<&std::path::Path>) -> Vec std::path::PathBuf { - let mut out = std::path::PathBuf::new(); - for component in path.components() { - match component { - std::path::Component::ParentDir => { - out.pop(); - } - std::path::Component::CurDir => {} - other => out.push(other.as_os_str()), - } - } - out - } -} - /// Resolve `systems.db`'s path, ANCHORED TO THE EXECUTABLE rather than the /// current working directory (T-1131 follow-up). /// @@ -1071,3 +930,144 @@ fn setup_proof_room(app: &mut App, world_seed: u64) { app.insert_resource(registry); } + +#[cfg(test)] +mod tests { + use super::*; + + /// T-1131 follow-up: the exe-anchored candidate must resolve to + /// `server/data/systems.db` from the DEV BUILD LAYOUT exe path + /// (`server/target/debug/settled-reach-server`) — this is the whole + /// point of the fix, so pin the exact join shape, not just "some path + /// containing systems.db". + #[test] + fn exe_anchored_candidate_targets_server_data_from_dev_build_layout() { + let exe = std::path::Path::new("/repo/server/target/debug/settled-reach-server"); + let candidates = systems_db_candidates(Some(exe)); + + assert_eq!( + candidates.len(), + 3, + "exe with a parent dir must produce all three candidates" + ); + assert_eq!( + candidates[0], + std::path::PathBuf::from("/repo/server/target/debug/../../data/systems.db"), + "exe-anchored candidate must be unjoined (caller canonicalizes) \ + but built from exe_dir/../../data/systems.db" + ); + + // The whole point: once normalized (what canonicalize() does at + // runtime against a real filesystem), this lands on + // /repo/server/data/systems.db — the actual DB location — not + // /repo/data/systems.db (the pre-fix cwd-relative bug's target). + let normalized = normalize_lexically(&candidates[0]); + assert_eq!( + normalized, + std::path::PathBuf::from("/repo/server/data/systems.db") + ); + } + + /// The two cwd-relative fallback candidates are present regardless of + /// whether an exe path resolved, in the documented order: `data/systems.db` + /// before `server/data/systems.db` (today's pre-fix behavior stays the + /// first fallback, not silently reordered behind the new repo-root case). + #[test] + fn cwd_relative_candidates_present_and_ordered_when_exe_path_is_some() { + let exe = std::path::Path::new("/repo/server/target/debug/settled-reach-server"); + let candidates = systems_db_candidates(Some(exe)); + assert_eq!(candidates[1], std::path::PathBuf::from("data/systems.db")); + assert_eq!( + candidates[2], + std::path::PathBuf::from("server/data/systems.db") + ); + } + + /// `current_exe()` can fail (documented caveat, e.g. sandboxed + /// environments) — `None` must degrade to exactly the two cwd-relative + /// candidates, not panic or produce a malformed exe-anchored entry. + #[test] + fn no_exe_path_yields_only_the_two_cwd_relative_candidates() { + let candidates = systems_db_candidates(None); + assert_eq!(candidates.len(), 2); + assert_eq!(candidates[0], std::path::PathBuf::from("data/systems.db")); + assert_eq!( + candidates[1], + std::path::PathBuf::from("server/data/systems.db") + ); + } + + /// An exe path that IS genuinely parentless (`Path::parent()` returns + /// `None` only for the empty path or filesystem root — confirmed against + /// the standard library, not assumed) must not panic and must degrade + /// the same as `exe_path: None`. + #[test] + fn genuinely_parentless_exe_path_degrades_like_no_exe_path() { + let exe = std::path::Path::new(""); + assert!( + exe.parent().is_none(), + "test premise: Path::new(\"\").parent() must be None" + ); + let candidates = systems_db_candidates(Some(exe)); + assert_eq!(candidates.len(), 2); + assert_eq!(candidates[0], std::path::PathBuf::from("data/systems.db")); + } + + /// A bare relative filename with no directory separator (e.g. the exe + /// path Godot's `OS.create_process` might report on some platform/launch + /// combination) is NOT the parentless case above — `Path::parent()` + /// returns `Some("")` for it (an empty-but-present parent), a real + /// standard-library quirk worth pinning explicitly since it's easy to + /// assume `.parent()` is `None` whenever there's "no directory in the + /// string". The exe-anchored candidate still gets produced (joined onto + /// the empty parent), just degenerately — `../../data/systems.db` + /// relative to cwd, which is harmless: it'll fail existence-checks + /// exactly like any other wrong candidate and fall through the loop. + #[test] + fn bare_filename_exe_path_has_an_empty_but_present_parent() { + let exe = std::path::Path::new("settled-reach-server"); + assert_eq!( + exe.parent(), + Some(std::path::Path::new("")), + "Path::parent() of a bare filename is Some(\"\"), not None — \ + pinning this stdlib behavior since it's the reason a bare \ + filename still produces 3 candidates, not 2" + ); + let candidates = systems_db_candidates(Some(exe)); + assert_eq!( + candidates.len(), + 3, + "a present-but-empty parent still yields an exe-anchored candidate" + ); + assert_eq!( + candidates[0], + std::path::PathBuf::from("../../data/systems.db"), + "joined onto an empty parent, the exe-anchored candidate is bare \ + ../../data/systems.db (cwd-relative in practice, but still a \ + DISTINCT candidate from candidates[1]'s exact data/systems.db)" + ); + } + + /// Lexical `..`/`.` normalization for test assertions ONLY — a stand-in + /// for `Path::canonicalize()` (which needs a real filesystem + cwd, + /// which unit tests must not depend on per the coordinator's "don't + /// build a process-spawning/filesystem harness for this" guidance). + /// `resolve_systems_db_path` itself still uses the real + /// `canonicalize()` at runtime — this helper exists only so + /// `exe_anchored_candidate_targets_server_data_from_dev_build_layout` + /// can assert the join shape actually lands on the right final path + /// without touching disk. + fn normalize_lexically(path: &std::path::Path) -> std::path::PathBuf { + let mut out = std::path::PathBuf::new(); + for component in path.components() { + match component { + std::path::Component::ParentDir => { + out.pop(); + } + std::path::Component::CurDir => {} + other => out.push(other.as_os_str()), + } + } + out + } +}