test(remote,scm): hold both halves of the backlog and completeness rules

Two compound conditions where one half decided every existing fixture, so
the other was never asked anything.

`remote.rs` exempts a frame larger than the whole backlog bound — a paste is
whatever the clipboard holds — but only onto an *empty* queue: a second one
arriving before the first has moved a byte is a link that has stopped
reading, and letting it through too trades the bound for a heap that grows
five megabytes at a time. The existing paste test drains the peer, so the
bound is never reached and the empty-queue half never matters. Dropping it
left a stalled link accepting oversize frames forever, and nothing failed.

`log.rs::load_page` calls a page complete only when git answered with fewer
commits than asked for *and* the parse read everything git answered with.
The truncation half had a test — of `parse_log`, whose doc comment promises
`load_page` turns the flag into `complete: false` while asserting only the
flag. Nothing checked the promise. A graph cut at MAX_RECORD would have read
as the end of history and frozen paging there, the commits below it
unreachable with nothing on screen to say why.

Both tests fail against the mutation and pass against the code as written.
No production change: the conditions were right, only unheld.
This commit is contained in:
l0ng-ai
2026-08-23 23:38:21 +08:00
parent 83544bf822
commit d42fae9de8
2 changed files with 84 additions and 0 deletions
+47
View File
@@ -2112,6 +2112,53 @@ mod tests {
assert!(run(host, repo, &["commit", "--quiet", "-m", message]));
}
/// The other half of `a_stream_the_parse_cannot_finish_is_never_called_complete`,
/// which asserted only that the *parse* raises the flag. What the flag is
/// for is `load_page`, and both halves of its test are needed: git answered
/// with fewer commits than asked for, which on its own reads as the end of
/// history, *and* a record the parse had to drop. Taking the count alone
/// would call a graph missing its middle complete, and paging would stop
/// there for good — the history below it unreachable, with nothing on
/// screen to say so.
#[test]
fn a_page_the_parse_had_to_cut_is_not_the_end_of_history() {
let host = crate::host::local::LocalHost::new();
let Some(scratch) = scratch("cut-page") else {
return;
};
let repo = scratch.0.as_path();
if !init_repo(&*host, repo) {
return;
}
commit_file(&*host, repo, "a.txt", "1\n", "first");
// A commit message past MAX_RECORD, which the splitter drops whole.
// Written through a file: an argument this size is over the exec limit
// on macOS, and would fail as a bad command rather than a big commit.
let huge = repo.join("msg.txt");
std::fs::write(&huge, "z".repeat(super::super::MAX_RECORD + 1)).unwrap();
std::fs::write(repo.join("b.txt"), "2\n").unwrap();
assert!(run(&*host, repo, &["add", "--", "b.txt"]));
assert!(run(
&*host,
repo,
&["commit", "--quiet", "-F", huge.to_str().unwrap()]
));
// Thirty asked for and two exist, so the count alone says complete.
let page =
load_page(&*host, repo, &GraphScope::Head, 30).expect("a repository was just created");
assert_eq!(
page.commits.len(),
1,
"the record over the bound is dropped, the readable one survives"
);
assert!(
!page.complete,
"a page the parse had to cut is not the end of history, however few commits came back"
);
}
#[test]
fn a_real_repository_answers_for_one_commit_and_its_files() {
let host = crate::host::local::LocalHost::new();
+37
View File
@@ -3802,6 +3802,43 @@ mod tests {
draining.join().unwrap();
}
/// The exemption a huge frame gets is for *one* of them. A paste larger
/// than the whole bound goes onto an empty queue and lifts the bound by its
/// own size while it is outstanding — but a second one arriving before the
/// first has moved a byte is not a paste, it is a link that has stopped
/// taking input, and letting it through too would trade the bound for a
/// heap that grows by five megabytes a go for as long as the peer is gone.
///
/// The empty-queue half of that rule is the whole of it: without it every
/// oversize frame is exempt, and a stalled link accepts them forever.
#[test]
fn a_second_oversize_frame_onto_a_stalled_link_is_still_a_backlog() {
crate::core::config::pin_test_config_dir();
let (client_side, daemon_side) = UnixStream::pair().unwrap();
let term = RemoteTerminal::from_stream(client_side, TermSize::new(80, 24)).unwrap();
// Held open and never read from: the peer is parked, not gone. A closed
// peer would fail the write outright and report the link lost for a
// different reason than the one under test.
let frame = MAX_BACKLOG + (1 << 20);
term.write(vec![b'x'; frame]);
assert!(
!term.exited_flag.load(Ordering::SeqCst),
"the first oversize frame is a paste and goes through"
);
// Nothing has drained, so the first frame is still charged in full —
// the sender parks inside `write_all` and discounts a frame only once
// it is out. The bound stands at MAX_BACKLOG + this frame, and a second
// frame of the same size is over it.
term.write(vec![b'x'; frame]);
assert!(
term.exited_flag.load(Ordering::SeqCst),
"a second oversize frame with the first still outstanding is a link nothing is reading"
);
drop(daemon_side);
}
/// Input the link refuses used to vanish: `write` threw the error away, so a
/// pane whose daemon had stopped reading kept taking keystrokes into
/// nothing. The refusal now marks the pane exited by the reader's own signal