9c9813a1a2
Major bug fixes and improvements. Thanks to @0xROOTPLS and @Karkas66. Closes #1 , #2 .
85 lines
2.7 KiB
Rust
85 lines
2.7 KiB
Rust
use rustpacker::polymorph::{BuildSeed, Polymorph};
|
|
|
|
#[test]
|
|
fn same_seed_same_idents() {
|
|
let mut a = Polymorph::from_seed(BuildSeed(0xDEADBEEF));
|
|
let mut b = Polymorph::from_seed(BuildSeed(0xDEADBEEF));
|
|
for _ in 0..16 {
|
|
assert_eq!(a.random_ident("fn"), b.random_ident("fn"));
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn different_seeds_different_idents() {
|
|
let mut a = Polymorph::from_seed(BuildSeed(1));
|
|
let mut b = Polymorph::from_seed(BuildSeed(2));
|
|
let a_ids: Vec<_> = (0..16).map(|_| a.random_ident("fn")).collect();
|
|
let b_ids: Vec<_> = (0..16).map(|_| b.random_ident("fn")).collect();
|
|
assert_ne!(a_ids, b_ids);
|
|
}
|
|
|
|
#[test]
|
|
fn random_ident_is_valid_rust_ident() {
|
|
let mut p = Polymorph::from_seed(BuildSeed(42));
|
|
for _ in 0..256 {
|
|
let id = p.random_ident("x");
|
|
let first = id.chars().next().unwrap();
|
|
assert!(first.is_ascii_lowercase() || first == '_', "ident: {id}");
|
|
assert!(id.chars().all(|c| c.is_ascii_lowercase() || c.is_ascii_digit() || c == '_'),
|
|
"ident: {id}");
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn random_ident_no_reserved_words() {
|
|
let mut p = Polymorph::from_seed(BuildSeed(42));
|
|
for _ in 0..1024 {
|
|
let id = p.random_ident("x");
|
|
assert!(!matches!(id.as_str(),
|
|
"fn" | "let" | "mut" | "pub" | "use" | "mod" | "as" | "if" | "in" |
|
|
"for" | "while" | "loop" | "match" | "ref" | "self" | "Self" | "super" |
|
|
"type" | "trait" | "impl" | "struct" | "enum" | "where" | "true" | "false" |
|
|
"static" | "const" | "extern" | "unsafe" | "move" | "box" | "do" | "yield"
|
|
));
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn random_ident_unique_within_polymorph() {
|
|
let mut p = Polymorph::from_seed(BuildSeed(42));
|
|
let mut seen = std::collections::HashSet::new();
|
|
for _ in 0..512 {
|
|
let id = p.random_ident("x");
|
|
assert!(seen.insert(id.clone()), "duplicate ident: {id}");
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn jitter_within_range() {
|
|
let mut p = Polymorph::from_seed(BuildSeed(7));
|
|
for _ in 0..256 {
|
|
let j = p.jitter(200, 25);
|
|
assert!(j >= 150 && j <= 250, "jitter out of range: {j}");
|
|
assert_eq!(j % 25, 0, "jitter not quantised to 25ms: {j}");
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn xor_bytes_literal_roundtrip() {
|
|
let p = Polymorph::from_seed(BuildSeed(99));
|
|
let lit = p.xor_bytes_literal(b"hello\0", 0x42);
|
|
// Format: "[0x.., 0x.., ...]"
|
|
assert!(lit.starts_with('[') && lit.ends_with(']'));
|
|
assert_eq!(lit.matches(", ").count(), 5); // 6 bytes -> 5 commas
|
|
}
|
|
|
|
#[test]
|
|
fn pick_is_deterministic() {
|
|
let mut a = Polymorph::from_seed(BuildSeed(123));
|
|
let mut b = Polymorph::from_seed(BuildSeed(123));
|
|
let choices = ["red", "green", "blue", "yellow"];
|
|
for _ in 0..32 {
|
|
assert_eq!(a.pick(&choices), b.pick(&choices));
|
|
}
|
|
}
|