use crate::branch::Branch;
use crate::mangle::Mangled;
use crate::utils::{checksum, split_array, xor};
#[test]
fn branch_obscure_hides_mask_target_and_selector_from_the_optimizer() {
let branch: Branch = syn::parse2(quote::quote! { cond { 1 } else { 2 } }).unwrap();
let tokens = branch.obscure(0).to_string();
assert_eq!(tokens.matches("black_box").count(), 3);
}
#[test]
fn xor_round_trips_with_a_salt() {
let original = [0, 1, 2, 3];
let mut source = original;
xor(&mut source, &[34, 52], 42);
assert_ne!(source, original);
xor(&mut source, &[34, 52], 42);
assert_eq!(source, original);
}
#[test]
fn xor_round_trips_with_one_byte_key() {
let original = [0, 1, 2, 3];
let mut source = original;
xor(&mut source, &[47], 7);
xor(&mut source, &[47], 7);
assert_eq!(source, original);
}
#[test]
fn xor_empty_key_is_a_no_op_regardless_of_salt() {
let mut source = [0, 1, 2, 3];
xor(&mut source, &[], 99);
assert_eq!(source, [0, 1, 2, 3]);
}
#[test]
fn xor_empty_source() {
let mut source = [];
xor(&mut source, &[45, 32, 56], 1);
assert!(source.is_empty());
}
#[test]
fn different_salts_produce_different_ciphertext() {
let key = [34, 52];
let mut a = [0, 1, 2, 3];
let mut b = [0, 1, 2, 3];
xor(&mut a, &key, 1);
xor(&mut b, &key, 2);
assert_ne!(a, b);
}
#[test]
fn wrong_salt_does_not_recover_the_plaintext() {
let original = [10, 20, 30, 40];
let mut source = original;
xor(&mut source, &[34, 52], 1);
xor(&mut source, &[34, 52], 2);
assert_ne!(source, original);
}
#[test]
fn split_array_valid_result() {
let original = [1, 2, 3, 4, 5];
let (left, right): ([u8; 2], [u8; 3]) = split_array(original);
assert_eq!(left, [1, 2]);
assert_eq!(right, [3, 4, 5]);
}
#[test]
fn checksum_is_deterministic() {
let bytes = [10, 20, 30, 40];
assert_eq!(checksum(&bytes), checksum(&bytes));
}
#[test]
fn checksum_detects_a_single_flipped_byte() {
let original = [10, 20, 30, 40];
let mut tampered = original;
tampered[2] ^= 1;
assert_ne!(checksum(&original), checksum(&tampered));
}
#[test]
fn checksum_detects_a_length_change() {
assert_ne!(checksum(&[1, 2, 3]), checksum(&[1, 2, 3, 0]));
}
#[test]
fn checksum_of_empty_slice_does_not_panic() {
let _ = checksum(&[]);
}
#[test]
fn mangle_round_trips() {
let original = [1u8, 2, 3, 4, 5, 6, 7, 8];
let mangled = Mangled::new(original);
mangled.reveal_with(|plain| assert_eq!(*plain, original));
}
#[test]
fn mangle_matches_a_pointer_sized_value() {
let original = 0x0011_2233_4455_6677_u64.to_ne_bytes();
let mangled = Mangled::new(original);
mangled.reveal_with(|plain| assert_eq!(*plain, original));
}
#[test]
fn mangle_covers_a_value_longer_than_the_cookie() {
let original = [7u8; 64];
let mangled = Mangled::new(original);
mangled.reveal_with(|plain| assert_eq!(*plain, original));
}
#[test]
fn mangle_does_not_repeat_its_keystream_within_one_value() {
let original = [7u8; 64];
let mangled = Mangled::new(original);
assert_ne!(mangled.bytes[..32], mangled.bytes[32..]);
}
#[test]
fn mangle_never_reuses_a_keystream_across_two_values() {
let original = [9u8, 8, 7, 6];
let a = Mangled::new(original);
let b = Mangled::new(original);
assert_ne!(a.bytes, b.bytes);
a.reveal_with(|plain| assert_eq!(*plain, original));
b.reveal_with(|plain| assert_eq!(*plain, original));
}