paircomp-core 1.0.0

File inspection and comparison logic for Paircomp
Documentation
use super::*;

struct InterruptedReader<'a> {
    bytes: &'a [u8],
    calls: u8,
}

impl Read for InterruptedReader<'_> {
    fn read(&mut self, buffer: &mut [u8]) -> io::Result<usize> {
        self.calls += 1;
        match self.calls {
            1 | 3 => Err(io::ErrorKind::Interrupted.into()),
            2 => self.bytes.read(&mut buffer[..2]),
            _ => self.bytes.read(buffer),
        }
    }
}

#[test]
fn interrupted_reads_preserve_full_and_prefix_scans() {
    let bytes = b"a\nb\nc\n";
    let reader = || InterruptedReader { bytes, calls: 0 };

    let full = scan_reader(reader(), None).unwrap();
    assert_eq!(full.byte_len, 6);
    assert_eq!(full.line_count, 3);
    assert_eq!(full.fingerprint.as_bytes(), blake3::hash(bytes).as_bytes());

    let prefix = scan_reader(reader(), Some(2)).unwrap();
    assert_eq!(prefix.byte_len, 4);
    assert_eq!(prefix.line_count, 2);
    assert_eq!(
        prefix.fingerprint.as_bytes(),
        blake3::hash(b"a\nb\n").as_bytes()
    );
}

#[test]
fn other_read_errors_are_returned() {
    struct FailingReader(u8);

    impl Read for FailingReader {
        fn read(&mut self, buffer: &mut [u8]) -> io::Result<usize> {
            self.0 += 1;
            match self.0 {
                1 => (&b"a\n"[..]).read(buffer),
                2 => Err(io::ErrorKind::Interrupted.into()),
                _ => Err(io::ErrorKind::PermissionDenied.into()),
            }
        }
    }

    assert!(matches!(
        scan_reader(FailingReader(0), None),
        Err(Error::Io(error)) if error.kind() == io::ErrorKind::PermissionDenied
    ));
}