#![allow(clippy::expect_used)]
use prikk_object::{
CanonicalEncode, CreateFile, NodeId, ObjectId, Operation, OperationKind, PatchPayload,
PatchPurpose,
};
use crate::patch_replay::decode::decode_patch_operations;
fn valid_patch_payload_bytes() -> Vec<u8> {
let patch = PatchPayload {
operations: vec![Operation {
op_seq: 1,
op_id: None,
preconditions: Vec::new(),
kind: OperationKind::CreateFile(CreateFile {
path: "a.txt".to_string(),
node_id: NodeId::from_bytes([0x74; 32]),
blob_id: ObjectId::from_bytes([0x11; 32]),
mode: 0o100_644,
}),
}],
intent: None,
preconditions: Vec::new(),
purpose: PatchPurpose::Normal,
};
patch.to_canonical_bytes().expect("patch encodes")
}
#[test]
fn decoder_accepts_record_list_item_framing() {
let bytes = valid_patch_payload_bytes();
assert_eq!(
bytes.get(2).copied(),
Some(0x21),
"expected record_list_item"
);
assert!(decode_patch_operations(&bytes, 1).is_ok());
}
#[test]
fn decoder_rejects_old_record_framing() {
let mut bytes = valid_patch_payload_bytes();
assert_eq!(bytes.get(2).copied(), Some(0x21));
if let Some(byte) = bytes.get_mut(2) {
*byte = 0x20;
}
assert!(decode_patch_operations(&bytes, 1).is_err());
}
#[test]
fn decoder_rejects_empty_payload() {
assert!(decode_patch_operations(b"", 1).is_err());
}
#[test]
fn decoder_rejects_payload_without_operations() {
let mut bytes = Vec::new();
bytes.extend_from_slice(&2_u16.to_be_bytes()); bytes.push(0x12); bytes.extend_from_slice(&32_u64.to_be_bytes()); bytes.extend_from_slice(&[0x11_u8; 32]); assert!(decode_patch_operations(&bytes, 1).is_err());
}