first pass of merging in warp (doesn't build)

This commit is contained in:
Ryan Ward
2026-07-01 16:08:58 -05:00
parent 2f64909469
commit 4770ac06b5
3662 changed files with 414574 additions and 89772 deletions
@@ -2,9 +2,8 @@
use std::io::Write as _;
use crate::FileModel;
use super::*;
use crate::FileModel;
fn make_accumulator(ranges: &[std::ops::Range<usize>], max_bytes: usize) -> TextFileAccumulator {
TextFileAccumulator::new("test.txt".to_string(), None, ranges, max_bytes)
@@ -118,14 +117,52 @@ fn unsorted_ranges_are_sorted() {
}
#[test]
fn empty_file_with_ranges_produces_no_segment() {
fn empty_file_with_ranges_produces_empty_segment() {
let acc = make_accumulator(&[1..5], 1000);
let (segments, bytes_read) = acc.finalize();
assert_eq!(segments.len(), 0);
assert_eq!(segments.len(), 1);
assert_eq!(segments[0].content, "");
assert_eq!(segments[0].line_range, Some(1..5));
assert_eq!(segments[0].line_count, 0);
assert_eq!(bytes_read, 0);
}
#[test]
fn range_past_eof_produces_empty_segment() {
// File has 5 lines, but range requests lines 10..15 which are all past EOF.
let mut acc = make_accumulator(&[10..15], 1000);
for i in 1..=5 {
push(&mut acc, &format!("line{i}"));
}
let (segments, bytes_read) = acc.finalize();
assert_eq!(segments.len(), 1);
assert_eq!(segments[0].content, "");
assert_eq!(segments[0].line_range, Some(10..15));
assert_eq!(segments[0].line_count, 5);
assert_eq!(bytes_read, 0);
}
#[test]
fn multiple_ranges_some_past_eof() {
// First range is valid, second is entirely past EOF.
let mut acc = make_accumulator(&[1..3, 10..15], 1000);
for i in 1..=5 {
push(&mut acc, &format!("line{i}"));
}
let (segments, _bytes_read) = acc.finalize();
assert_eq!(segments.len(), 2);
assert_eq!(segments[0].content, "line1\nline2");
assert_eq!(segments[0].line_range, Some(1..3));
assert_eq!(segments[1].content, "");
assert_eq!(segments[1].line_range, Some(10..15));
for seg in &segments {
assert_eq!(seg.line_count, 5);
}
}
#[test]
fn line_count_reflects_total_file_lines() {
let mut acc = make_accumulator(&[2..4], 1000);
@@ -156,6 +193,43 @@ fn range_truncated_at_byte_limit() {
assert_eq!(bytes_read, 4);
}
#[test]
fn whole_file_truncated_on_first_line_yields_empty_range() {
// Budget smaller than the very first line, so nothing is ever buffered.
// The truncated range must be a valid empty `1..1`, not a reversed `1..0`.
let mut acc = make_accumulator(&[], 4);
push(&mut acc, "hello"); // 5 bytes > 4 → truncated, nothing buffered
push(&mut acc, "world");
let (segments, bytes_read) = acc.finalize();
assert_eq!(segments.len(), 1);
assert_eq!(segments[0].content, "");
assert_eq!(segments[0].line_range, Some(1..1));
assert_eq!(segments[0].line_count, 2);
assert_eq!(bytes_read, 0);
}
#[test]
fn range_truncated_on_first_in_range_line_yields_empty_range() {
// The first line that falls inside the requested range already exceeds the
// budget, so nothing is buffered for this range. The range must be the
// empty `2..2`, not a reversed `2..0`.
let mut acc = make_accumulator(&[2..6], 4);
push(&mut acc, "skip"); // line 1, outside range
push(&mut acc, "hello"); // line 2, 5 bytes > 4 → truncated, nothing buffered
push(&mut acc, "world"); // line 3
let (segments, bytes_read) = acc.finalize();
assert_eq!(segments.len(), 1);
assert_eq!(segments[0].content, "");
assert_eq!(segments[0].line_range, Some(2..2));
let Some(range) = &segments[0].line_range else {
panic!("expected a line range");
};
assert!(range.start <= range.end, "range must not be reversed");
assert_eq!(bytes_read, 0);
}
#[test]
fn global_budget_shared_across_ranges() {
// Budget of 12 bytes. First range uses 5, leaving 7 for the second.