use std::io::{Cursor, Read, Write};
use flate2::{Compression, write::GzEncoder};
use super::*;
use crate::error::MuninError;
fn make_binlog(version: i32, min_reader: i32, body: &[u8]) -> Vec<u8> {
let mut uncompressed = Vec::new();
uncompressed.extend_from_slice(&version.to_le_bytes());
uncompressed.extend_from_slice(&min_reader.to_le_bytes());
uncompressed.extend_from_slice(body);
let mut encoder = GzEncoder::new(Vec::new(), Compression::fast());
encoder.write_all(&uncompressed).unwrap();
encoder.finish().unwrap()
}
#[test]
fn open_valid_v25_header() {
let data = make_binlog(25, 18, &[0x00]); let (header, _reader) = open_binlog(Cursor::new(data)).unwrap();
assert_eq!(header.file_format_version, 25);
assert_eq!(header.min_reader_version, 18);
}
#[test]
fn open_valid_v18_header() {
let data = make_binlog(18, 18, &[0x00]);
let (header, _reader) = open_binlog(Cursor::new(data)).unwrap();
assert_eq!(header.file_format_version, 18);
assert_eq!(header.min_reader_version, 18);
}
#[test]
fn open_valid_v22_header() {
let data = make_binlog(22, 18, &[0x00]);
let (header, _reader) = open_binlog(Cursor::new(data)).unwrap();
assert_eq!(header.file_format_version, 22);
assert_eq!(header.min_reader_version, 18);
}
#[test]
fn reject_version_below_18() {
let data = make_binlog(17, 17, &[0x00]);
let err = open_binlog(Cursor::new(data)).unwrap_err();
assert!(matches!(
err,
MuninError::UnsupportedVersion {
file_version: 17,
..
}
));
}
#[test]
fn reject_version_1() {
let data = make_binlog(1, 0, &[0x00]);
let err = open_binlog(Cursor::new(data)).unwrap_err();
assert!(matches!(
err,
MuninError::UnsupportedVersion {
file_version: 1,
..
}
));
}
#[test]
fn reject_version_0() {
let data = make_binlog(0, 0, &[0x00]);
let err = open_binlog(Cursor::new(data)).unwrap_err();
assert!(matches!(
err,
MuninError::UnsupportedVersion {
file_version: 0,
..
}
));
}
#[test]
fn decompress_body_after_open() {
let body = b"MSBuild test payload";
let data = make_binlog(25, 18, body);
let (_header, mut reader) = open_binlog(Cursor::new(data)).unwrap();
let mut buf = vec![0u8; body.len()];
reader.read_exact(&mut buf).unwrap();
assert_eq!(&buf, body);
}
#[test]
fn empty_body_reads_eof() {
let data = make_binlog(25, 18, &[]);
let (_header, mut reader) = open_binlog(Cursor::new(data)).unwrap();
let mut buf = [0u8; 1];
let n = reader.read(&mut buf).unwrap();
assert_eq!(n, 0);
}
#[test]
fn truncated_header_4_bytes() {
let data = 25i32.to_le_bytes().to_vec();
let err = open_binlog(Cursor::new(data)).unwrap_err();
assert!(matches!(err, MuninError::Io(_)));
}
#[test]
fn truncated_header_0_bytes() {
let data: Vec<u8> = Vec::new();
let err = open_binlog(Cursor::new(data)).unwrap_err();
assert!(matches!(err, MuninError::Io(_)));
}
#[test]
fn future_version_accepted_if_above_min() {
let data = make_binlog(30, 18, &[0x00]);
let (header, _reader) = open_binlog(Cursor::new(data)).unwrap();
assert_eq!(header.file_format_version, 30);
assert_eq!(header.min_reader_version, 18);
}
#[test]
fn header_struct_debug_format() {
let h = BinlogHeader {
file_format_version: 25,
min_reader_version: 18,
};
let dbg = format!("{h:?}");
assert!(dbg.contains("25"));
assert!(dbg.contains("18"));
}