test(stage2a): the reconciliation acceptance suite
`tests/resource_reconciliation_acceptance.rs`, 23 rows, no dired content — items 23–37 and 50–55 driven through the real entry points: `pmacs.fs.rename` / `pmacs.fs.remove` fire-and-forget for the drain harvest, `pmacs.buffer.apply_resource_op` for the synchronous arm, and the fake server's `workspace/applyEdit` for the applier. The rows that took design rather than transcription: Item 27 opens two descendants AND two buffers on one exact path, since one child would not defeat a first-match lookup. Item 29 tests name provenance in both directions, including a name explicitly set to a string that normalizes to the file's own path — the case a path-equivalence heuristic gets wrong. Item 30 paints a real frame and counts diagnostic underlines per window rect, because `DiagnosticView.uri` is private and a store assertion would prove nothing about re-rooting; it also pins each overlay's index in the composition order, which is what a remove-and-re-push breaks. Item 53b states its three assertions individually, since a compound check can pass on two of the three. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Lv428Fth9LRtffwJSsqH7T
This commit is contained in:
parent
aa813ec3b6
commit
3c66370b8c
12
src/diag.rs
12
src/diag.rs
|
|
@ -512,7 +512,7 @@ impl View for DiagnosticView {
|
|||
/// position in the window's composition order.
|
||||
fn rename_resource(&mut self, old_uri: &str, new_uri: &str) {
|
||||
if self.uri == old_uri {
|
||||
self.uri = new_uri.to_owned();
|
||||
new_uri.clone_into(&mut self.uri);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -781,7 +781,10 @@ mod tests {
|
|||
#[test]
|
||||
fn forget_drops_the_epoch_while_clear_deliberately_bumps_it() {
|
||||
let mut store = DiagnosticStore::new();
|
||||
store.set("file:///a.rs", vec![diag(0, DiagnosticSeverity::Error, "boom")]);
|
||||
store.set(
|
||||
"file:///a.rs",
|
||||
vec![diag(0, DiagnosticSeverity::Error, "boom")],
|
||||
);
|
||||
store.mark_stale("file:///a.rs");
|
||||
assert_eq!(store.epoch_for("file:///a.rs"), 1);
|
||||
|
||||
|
|
@ -792,7 +795,10 @@ mod tests {
|
|||
"clear announces the removal to epoch-keyed caches"
|
||||
);
|
||||
|
||||
store.set("file:///a.rs", vec![diag(0, DiagnosticSeverity::Error, "boom")]);
|
||||
store.set(
|
||||
"file:///a.rs",
|
||||
vec![diag(0, DiagnosticSeverity::Error, "boom")],
|
||||
);
|
||||
store.mark_stale("file:///a.rs");
|
||||
store.forget("file:///a.rs");
|
||||
assert!(store.for_uri("file:///a.rs").is_empty(), "diagnostics");
|
||||
|
|
|
|||
23
src/lsp.rs
23
src/lsp.rs
|
|
@ -3171,6 +3171,10 @@ impl LspManager {
|
|||
/// attachment need not have any pending route or populated result
|
||||
/// store, and cleanup can be repeated after an earlier partial
|
||||
/// teardown.
|
||||
#[allow(
|
||||
clippy::too_many_lines,
|
||||
reason = "the fourteen store families are a flat inventory; splitting it is how one of them gets forgotten, which is the defect this method exists to prevent"
|
||||
)]
|
||||
pub fn forget_uri(&mut self, sid: LspServerId, uri: &str) -> Result<(), String> {
|
||||
if !self.clients.contains_key(&sid) {
|
||||
return Err(format!("unknown server: {sid}"));
|
||||
|
|
@ -4233,13 +4237,18 @@ mod resource_reconciliation_tests {
|
|||
"data": [0, 0, 1, 0, 0],
|
||||
})),
|
||||
);
|
||||
mgr.documents.insert((sid, uri.to_owned()), "text".to_owned());
|
||||
mgr.documents
|
||||
.insert((sid, uri.to_owned()), "text".to_owned());
|
||||
}
|
||||
|
||||
/// Which of the fourteen families still hold an entry for
|
||||
/// `(sid, uri)`, by name. An empty vector is the post-forget
|
||||
/// expectation; naming the survivors is what makes a failure
|
||||
/// actionable instead of "assert!(false)".
|
||||
#[allow(
|
||||
clippy::too_many_lines,
|
||||
reason = "one probe per store family, mirroring the inventory under test"
|
||||
)]
|
||||
fn populated_families(mgr: &LspManager, sid: LspServerId, uri: &str) -> Vec<&'static str> {
|
||||
let server = sid.raw().to_string();
|
||||
let mut out = Vec::new();
|
||||
|
|
@ -4560,9 +4569,10 @@ mod resource_reconciliation_tests {
|
|||
.expect_err("unknown server must raise, matching `forget`");
|
||||
assert!(err.contains("unknown server"), "{err}");
|
||||
|
||||
mgr.forget_uri(a, "file:///tmp/never-touched.rs")
|
||||
.expect("a URI with no state under a known server is an \
|
||||
idempotent success, not an error");
|
||||
mgr.forget_uri(a, "file:///tmp/never-touched.rs").expect(
|
||||
"a URI with no state under a known server is an \
|
||||
idempotent success, not an error",
|
||||
);
|
||||
mgr.forget_uri(a, "file:///tmp/never-touched.rs")
|
||||
.expect("and repeating it stays safe");
|
||||
}
|
||||
|
|
@ -4613,10 +4623,7 @@ mod resource_reconciliation_tests {
|
|||
|
||||
mgr.mark_document_stale(a, old);
|
||||
|
||||
assert!(
|
||||
!mgr.diag_store.lock().unwrap().is_stale(old),
|
||||
"diagnostics"
|
||||
);
|
||||
assert!(!mgr.diag_store.lock().unwrap().is_stale(old), "diagnostics");
|
||||
assert!(
|
||||
!mgr.semantic_token_store.lock().unwrap().is_stale(old),
|
||||
"semantic tokens"
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue