use oxgraph_layout_util::crc32c_append;
use oxgraph_snapshot::{
CRC32C_CHECK_INPUT, CRC32C_CHECK_VALUE, FORMAT_MAGIC, FORMAT_MAJOR, FORMAT_MINOR, HEADER_SIZE,
SECTION_ENTRY_SIZE, SnapshotWriter,
};
#[test]
fn empty_snapshot_is_exactly_header_size() {
let writer = match SnapshotWriter::new(0, crc32c_append) {
Ok(value) => value,
Err(error) => panic!("empty writer: {error:?}"),
};
let bytes = match writer.finish() {
Ok(value) => value,
Err(error) => panic!("empty writer finish: {error:?}"),
};
assert_eq!(bytes.len(), HEADER_SIZE);
}
#[test]
fn snapshot_magic_is_at_offset_zero() {
let writer = match SnapshotWriter::new(0, crc32c_append) {
Ok(value) => value,
Err(error) => panic!("empty writer: {error:?}"),
};
let bytes = match writer.finish() {
Ok(value) => value,
Err(error) => panic!("empty writer finish: {error:?}"),
};
assert!(bytes.len() >= FORMAT_MAGIC.len());
assert_eq!(&bytes[..FORMAT_MAGIC.len()], &FORMAT_MAGIC[..]);
}
#[test]
fn format_magic_is_oxgtopo_nul() {
assert_eq!(FORMAT_MAGIC, *b"OXGTOPO\0");
}
#[test]
fn header_and_section_entry_sizes_are_pinned() {
assert_eq!(HEADER_SIZE, 32);
assert_eq!(SECTION_ENTRY_SIZE, 32);
}
#[test]
fn format_versions_are_pinned() {
assert_eq!(FORMAT_MAJOR, 1);
assert_eq!(FORMAT_MINOR, 0);
}
#[test]
fn crc32c_check_vector_is_pinned() {
assert_eq!(CRC32C_CHECK_INPUT, b"123456789");
assert_eq!(CRC32C_CHECK_VALUE, 0xE306_9283);
assert_eq!(crc32c_append(0, CRC32C_CHECK_INPUT), CRC32C_CHECK_VALUE);
assert_eq!(crc32c_append(0, b""), 0, "empty sections store a zero CRC");
}
#[test]
fn one_section_is_header_plus_entry_plus_payload() {
let mut writer = match SnapshotWriter::new(1, crc32c_append) {
Ok(value) => value,
Err(error) => panic!("writer: {error:?}"),
};
let payload = vec![0xABu8; 17];
if let Err(error) = writer.section_bytes(0x1234, 0, 0, &payload) {
panic!("section_bytes: {error:?}");
}
let bytes = match writer.finish() {
Ok(value) => value,
Err(error) => panic!("writer finish: {error:?}"),
};
assert_eq!(
bytes.len(),
HEADER_SIZE + SECTION_ENTRY_SIZE + payload.len()
);
}
#[test]
fn checksum_words_are_at_pinned_offsets() {
let payload = vec![0xABu8; 17];
let mut writer = match SnapshotWriter::new(1, crc32c_append) {
Ok(value) => value,
Err(error) => panic!("writer: {error:?}"),
};
if let Err(error) = writer.section_bytes(0x1234, 0, 0, &payload) {
panic!("section_bytes: {error:?}");
}
let bytes = match writer.finish() {
Ok(value) => value,
Err(error) => panic!("writer finish: {error:?}"),
};
let entry_crc_offset = HEADER_SIZE + 24;
let stored_entry_crc = u32::from_le_bytes([
bytes[entry_crc_offset],
bytes[entry_crc_offset + 1],
bytes[entry_crc_offset + 2],
bytes[entry_crc_offset + 3],
]);
assert_eq!(stored_entry_crc, crc32c_append(0, &payload));
let table_bytes = &bytes[HEADER_SIZE..HEADER_SIZE + SECTION_ENTRY_SIZE];
let stored_table_crc = u32::from_le_bytes([bytes[24], bytes[25], bytes[26], bytes[27]]);
assert_eq!(stored_table_crc, crc32c_append(0, table_bytes));
}
#[test]
fn three_sections_is_header_plus_three_entries_plus_payloads() {
let mut writer = match SnapshotWriter::new(3, crc32c_append) {
Ok(value) => value,
Err(error) => panic!("writer: {error:?}"),
};
let payloads: [Vec<u8>; 3] = [vec![1u8; 4], vec![2u8; 8], vec![3u8; 12]];
for (kind, payload) in payloads.iter().enumerate() {
let kind = match u32::try_from(kind) {
Ok(value) => value,
Err(error) => panic!("kind index out of u32 range: {error:?}"),
};
if let Err(error) = writer.section_bytes(kind, 0, 0, payload) {
panic!("section_bytes({kind}): {error:?}");
}
}
let bytes = match writer.finish() {
Ok(value) => value,
Err(error) => panic!("writer finish: {error:?}"),
};
let payload_total: usize = payloads.iter().map(Vec::len).sum();
assert_eq!(
bytes.len(),
HEADER_SIZE + 3 * SECTION_ENTRY_SIZE + payload_total
);
}