diff --git a/src/bin/reencode.rs b/src/bin/reencode.rs index fcdcfc1..eb80475 100644 --- a/src/bin/reencode.rs +++ b/src/bin/reencode.rs @@ -45,8 +45,15 @@ fn main() -> Result<(), MainError> { } header.write(&mut out_stream)?; + // ParserState defaults to protocol 24 (DemoHandler::default -> + // ParserState::new(24, ..)); without this the demo's own protocol is + // never applied and older demos are parsed with the wrong field widths. + // DemoParser::ticker does this for us, but this binary drives the + // DemoHandler directly. let mut handler = DemoHandler::default(); + handler.handle_header(&header); let mut encode_handler = DemoHandler::default(); + encode_handler.handle_header(&header); let mut has_stop = false; let mut last_tick = DemoTick::default(); diff --git a/tests/reencode.rs b/tests/reencode.rs index a94a732..2930856 100644 --- a/tests/reencode.rs +++ b/tests/reencode.rs @@ -44,6 +44,7 @@ fn re_encode_test(input_file: &str) { let mut packets = RawPacketStream::new(stream); let mut handler = DemoHandler::parse_all_with_analyser(NullHandler); + handler.handle_header(&header); { let mut out_stream = BitWriteStream::new(&mut out_buffer, LittleEndian); @@ -150,4 +151,36 @@ fn re_encode_test(input_file: &str) { handler.handle_packet(packet).unwrap(); } + + // a desync shows up as the packet loop quietly stopping early, so the + // round trip above passes while most of the demo is never looked at + assert!(!packets.incomplete, "{} was not read to the end", input_file); +} + +/// A demo recorded on an older protocol must be parsed with that protocol, not +/// the protocol 24 that `ParserState` starts out with. Getting it wrong shifts +/// the width of a handful of fields (`ServerInfo`'s map hash, `PreFetch`), the +/// message stream desyncs, and `RawPacketStream` quietly stops early rather +/// than returning an error - so this checks the whole demo was actually read. +#[cfg(feature = "write")] +#[test] +fn parse_with_header_protocol() { + let file = fs::read("test_data/protocol23.dem").expect("Unable to read file"); + let demo = Demo::new(&file); + let mut stream = demo.get_stream(); + let header = Header::read(&mut stream).unwrap(); + assert_eq!(23, header.protocol); + + let mut packets = RawPacketStream::new(stream); + let mut handler = DemoHandler::parse_all_with_analyser(NullHandler); + handler.handle_header(&header); + + let mut count = 0; + while let Some(packet) = packets.next(&handler.state_handler).unwrap() { + handler.handle_packet(packet).unwrap(); + count += 1; + } + + assert!(!packets.incomplete, "demo was not read to the end"); + assert_eq!(128235, count); }