Skip to content

Commit 58a9633

Browse files
authored
Merge pull request #833 from rtk-ai/fix/truncation-accuracy-tests
fix(truncation): accurate overflow counts and omission indicators
2 parents 599ad25 + 23f4fee commit 58a9633

6 files changed

Lines changed: 263 additions & 48 deletions

File tree

CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,14 @@ All notable changes to rtk (Rust Token Killer) will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

8+
## [Unreleased]
9+
10+
### Bug Fixes
11+
12+
* **diff:** correct truncation overflow count in condense_unified_diff ([#833](https://github.com/rtk-ai/rtk/pull/833)) ([5399f83](https://github.com/rtk-ai/rtk/commit/5399f83))
13+
* **git:** replace vague truncation markers with exact counts in log and grep output ([#833](https://github.com/rtk-ai/rtk/pull/833)) ([185fb97](https://github.com/rtk-ai/rtk/commit/185fb97))
14+
15+
816
## [0.33.0-rc.54](https://github.com/rtk-ai/rtk/compare/v0.32.0-rc.54...v0.33.0-rc.54) (2026-03-24)
917

1018

src/diff_cmd.rs

Lines changed: 62 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,10 @@ fn condense_unified_diff(diff: &str) -> String {
168168
for c in &changes {
169169
result.push(format!(" {}", c));
170170
}
171+
let total = added + removed;
172+
if total > 10 {
173+
result.push(format!(" ... +{} more", total - 10));
174+
}
171175
}
172176
current_file = line
173177
.trim_start_matches("+++ ")
@@ -192,6 +196,10 @@ fn condense_unified_diff(diff: &str) -> String {
192196
for c in &changes {
193197
result.push(format!(" {}", c));
194198
}
199+
let total = added + removed;
200+
if total > 10 {
201+
result.push(format!(" ... +{} more", total - 10));
202+
}
195203
}
196204

197205
result.join("\n")
@@ -334,9 +342,57 @@ diff --git a/b.rs b/b.rs
334342
assert!(result.is_empty());
335343
}
336344

345+
// --- truncation accuracy ---
346+
347+
fn make_large_unified_diff(added: usize, removed: usize) -> String {
348+
let mut lines = vec![
349+
"diff --git a/config.yaml b/config.yaml".to_string(),
350+
"--- a/config.yaml".to_string(),
351+
"+++ b/config.yaml".to_string(),
352+
"@@ -1,200 +1,200 @@".to_string(),
353+
];
354+
for i in 0..removed {
355+
lines.push(format!("-old_value_{}", i));
356+
}
357+
for i in 0..added {
358+
lines.push(format!("+new_value_{}", i));
359+
}
360+
lines.join("\n")
361+
}
362+
363+
#[test]
364+
fn test_condense_unified_diff_overflow_count_accuracy() {
365+
// 100 added + 100 removed = 200 total changes, only 10 shown
366+
// True overflow = 200 - 10 = 190
367+
// Bug: changes vec capped at 15, so old code showed "+5 more" (15-10) instead of "+190 more"
368+
let diff = make_large_unified_diff(100, 100);
369+
let result = condense_unified_diff(&diff);
370+
assert!(
371+
result.contains("+190 more"),
372+
"Expected '+190 more' but got:\n{}",
373+
result
374+
);
375+
assert!(
376+
!result.contains("+5 more"),
377+
"Bug still present: showing '+5 more' instead of true overflow"
378+
);
379+
}
380+
381+
#[test]
382+
fn test_condense_unified_diff_no_false_overflow() {
383+
// 8 changes total — all fit within the 10-line display cap, no overflow message
384+
let diff = make_large_unified_diff(4, 4);
385+
let result = condense_unified_diff(&diff);
386+
assert!(
387+
!result.contains("more"),
388+
"No overflow message expected for 8 changes, got:\n{}",
389+
result
390+
);
391+
}
392+
337393
#[test]
338394
fn test_no_truncation_large_diff() {
339-
// Verify all changes are shown, not truncated
395+
// Verify compute_diff returns all changes without truncation
340396
let mut a = Vec::new();
341397
let mut b = Vec::new();
342398
for i in 0..500 {
@@ -351,9 +407,11 @@ diff --git a/b.rs b/b.rs
351407
let b_refs: Vec<&str> = b.iter().map(|s| s.as_str()).collect();
352408
let result = compute_diff(&a_refs, &b_refs);
353409

354-
// Should have ~167 changes (every 3rd line), all present
355-
assert!(result.changes.len() > 100, "Expected 100+ changes, got {}", result.changes.len());
356-
// No truncation — changes count matches what we generate
410+
assert!(
411+
result.changes.len() > 100,
412+
"Expected 100+ changes, got {}",
413+
result.changes.len()
414+
);
357415
assert!(!result.changes.is_empty());
358416
}
359417

@@ -363,7 +421,6 @@ diff --git a/b.rs b/b.rs
363421
let a = vec![long_line.as_str()];
364422
let b = vec!["short"];
365423
let result = compute_diff(&a, &b);
366-
// The removed line should contain the full 500-char string
367424
match &result.changes[0] {
368425
DiffChange::Removed(_, content) | DiffChange::Added(_, content) => {
369426
assert_eq!(content.len(), 500, "Line was truncated!");
@@ -373,24 +430,4 @@ diff --git a/b.rs b/b.rs
373430
}
374431
}
375432
}
376-
377-
#[test]
378-
fn test_condense_unified_no_truncation() {
379-
// Generate a large unified diff
380-
let mut lines = Vec::new();
381-
lines.push("diff --git a/big.yaml b/big.yaml".to_string());
382-
lines.push("--- a/big.yaml".to_string());
383-
lines.push("+++ b/big.yaml".to_string());
384-
for i in 0..200 {
385-
lines.push(format!("+added_line_{}", i));
386-
}
387-
let diff = lines.join("\n");
388-
let result = condense_unified_diff(&diff);
389-
390-
// All 200 added lines should be present
391-
assert!(result.contains("added_line_0"));
392-
assert!(result.contains("added_line_199"));
393-
assert!(!result.contains("not shown"), "Should not truncate");
394-
assert!(!result.contains("more"), "Should not have '... more'");
395-
}
396433
}

src/filter.rs

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -491,4 +491,49 @@ fn main() {
491491
assert!(!result.contains("// This is a comment"));
492492
assert!(result.contains("fn main()"));
493493
}
494+
495+
// --- truncation accuracy ---
496+
497+
#[test]
498+
fn test_smart_truncate_overflow_count_exact() {
499+
// 200 plain-text lines with max_lines=20.
500+
// smart_truncate keeps the first max_lines/2=10 lines, then skips the rest.
501+
// The overflow message "// ... N more lines (total: T)" must satisfy:
502+
// kept_count + N == T
503+
let total_lines = 200usize;
504+
let max_lines = 20usize;
505+
let content: String = (0..total_lines)
506+
.map(|i| format!("plain text line number {}", i))
507+
.collect::<Vec<_>>()
508+
.join("\n");
509+
510+
let output = smart_truncate(&content, max_lines, &Language::Rust);
511+
512+
// Extract the overflow message
513+
let overflow_line = output
514+
.lines()
515+
.find(|l| l.contains("more lines"))
516+
.unwrap_or_else(|| panic!("No overflow message found in:\n{}", output));
517+
518+
// Parse "// ... N more lines (total: T)"
519+
let reported_more: usize = overflow_line
520+
.split_whitespace()
521+
.find(|w| w.parse::<usize>().is_ok())
522+
.and_then(|w| w.parse().ok())
523+
.unwrap_or_else(|| panic!("Could not parse overflow count from: {}", overflow_line));
524+
525+
let kept_count = output
526+
.lines()
527+
.filter(|l| !l.contains("more lines") && !l.contains("omitted"))
528+
.count();
529+
530+
assert_eq!(
531+
kept_count + reported_more,
532+
total_lines,
533+
"kept ({}) + reported_more ({}) must equal total ({})",
534+
kept_count,
535+
reported_more,
536+
total_lines
537+
);
538+
}
494539
}

0 commit comments

Comments
 (0)