71 lines
2 KiB
Rust
71 lines
2 KiB
Rust
// SPDX-License-Identifier: AGPL-3.0-only
|
|
|
|
use super::*;
|
|
use crate::world::{BlockId, ChunkPos};
|
|
|
|
/// Builds a representative modified chunk with a few edits spanning the local index range.
|
|
fn sample() -> ChunkData {
|
|
let mut data = ChunkData::new(ChunkPos::new(1, -2, 3), 7);
|
|
data.set(0, BlockId(4));
|
|
data.set(1000, BlockId(9));
|
|
data.set(32_767, BlockId(2));
|
|
data
|
|
}
|
|
|
|
#[test]
|
|
fn round_trips_payload_and_metadata() -> Result<(), SaveError> {
|
|
let data = sample();
|
|
let bytes = encode(&data, 123_456)?;
|
|
let (meta, decoded) = decode(&bytes)?;
|
|
|
|
assert_eq!(decoded, data);
|
|
assert_eq!(meta.chunk_format_version, CHUNK_FORMAT_VERSION);
|
|
assert_eq!(meta.flags, 0);
|
|
assert_eq!(meta.last_modified, 123_456);
|
|
Ok(())
|
|
}
|
|
|
|
#[test]
|
|
fn rejects_bad_magic() -> Result<(), SaveError> {
|
|
let mut bytes = encode(&sample(), 0)?;
|
|
bytes[0] = b'X';
|
|
assert!(matches!(decode(&bytes), Err(SaveError::BadMagic { .. })));
|
|
Ok(())
|
|
}
|
|
|
|
#[test]
|
|
fn rejects_truncated_header() -> Result<(), SaveError> {
|
|
let bytes = encode(&sample(), 0)?;
|
|
// A buffer shorter than the fixed header cannot yield a full record.
|
|
assert!(matches!(
|
|
decode(&bytes[..HEADER_LEN - 1]),
|
|
Err(SaveError::Truncated { .. })
|
|
));
|
|
Ok(())
|
|
}
|
|
|
|
#[test]
|
|
fn rejects_truncated_payload() -> Result<(), SaveError> {
|
|
let bytes = encode(&sample(), 0)?;
|
|
// Keep the whole header but cut the compressed payload short.
|
|
assert!(matches!(
|
|
decode(&bytes[..=HEADER_LEN]),
|
|
Err(SaveError::Truncated { .. })
|
|
));
|
|
Ok(())
|
|
}
|
|
|
|
#[test]
|
|
fn detects_declared_length_mismatch() -> Result<(), SaveError> {
|
|
let mut bytes = encode(&sample(), 0)?;
|
|
// The uncompressed-length field is the u32 at offset 16 (after magic, version,
|
|
// flags, and the timestamp). Overwriting it with a value the payload cannot
|
|
// decompress to must be caught by the post-decompression length check.
|
|
bytes[16..20].copy_from_slice(&1u32.to_le_bytes());
|
|
assert!(matches!(
|
|
decode(&bytes),
|
|
Err(SaveError::LengthMismatch { .. })
|
|
));
|
|
Ok(())
|
|
}
|