use sz_orm_core::Value;
#[test]
fn mutation_aware_value_eq() {
assert_eq!(Value::I64(42), Value::I64(42));
assert_ne!(Value::I64(42), Value::I64(43));
assert_eq!(
Value::String("hello".to_string()),
Value::String("hello".to_string())
);
assert_ne!(
Value::String("hello".to_string()),
Value::String("world".to_string())
);
}
#[test]
fn mutation_aware_value_is_null() {
assert!(Value::Null.is_null());
assert!(!Value::I64(0).is_null());
assert!(!Value::String("".to_string()).is_null());
}
#[test]
fn mutation_aware_as_i64_some() {
assert_eq!(Value::I64(0).as_i64(), Some(0));
assert_eq!(Value::I64(-1).as_i64(), Some(-1));
assert_eq!(Value::I64(i64::MAX).as_i64(), Some(i64::MAX));
assert_eq!(Value::I64(i64::MIN).as_i64(), Some(i64::MIN));
}
#[test]
fn mutation_aware_as_i64_none_for_non_int() {
assert_eq!(Value::Null.as_i64(), None);
assert_eq!(Value::String("not a number".to_string()).as_i64(), None);
assert_eq!(Value::Bytes(vec![1, 2, 3]).as_i64(), None);
}
#[test]
fn mutation_aware_numeric_invariant() {
let a = Value::I64(100);
let b = Value::I64(50);
assert!(a != b);
assert!(b != a);
}
#[test]
fn mutation_aware_compound_condition() {
let v = Value::I64(42);
let is_int = v.as_i64().is_some();
let is_not_null = !v.is_null();
let is_positive = v.as_i64().unwrap() > 0;
assert!(is_int && is_not_null && is_positive);
assert!(!(is_int && is_not_null && !is_positive));
}
#[test]
fn mutation_aware_boundary_lt() {
assert!(Value::I64(1).as_i64().unwrap() < 2);
assert!(!(Value::I64(2).as_i64().unwrap() < 2));
assert!(!(Value::I64(3).as_i64().unwrap() < 2));
}
#[test]
fn mutation_aware_boundary_gt() {
assert!(Value::I64(3).as_i64().unwrap() > 2);
assert!(!(Value::I64(2).as_i64().unwrap() > 2));
assert!(!(Value::I64(1).as_i64().unwrap() > 2));
}
#[test]
fn mutation_aware_chain_unwrap() {
let v = Value::I64(42);
let result = v.as_i64().map(|x| x * 2);
assert_eq!(result, Some(84));
}
#[test]
fn mutation_aware_to_string_non_empty() {
let v = Value::I64(42);
let s = v.to_string();
assert!(!s.is_empty(), "to_string() 不应返回空字符串");
assert_eq!(s, "42");
}
#[test]
fn mutation_aware_clone_depth() {
let original = Value::String("hello".to_string());
let cloned = original.clone();
assert_eq!(original, cloned);
}
#[test]
fn mutation_aware_sql_injection_escape() {
let malicious = "'; DROP TABLE users; --";
let binding = Value::String(malicious.to_string());
let param = binding.to_param();
let s = param.into_owned();
let original_quotes = malicious.chars().filter(|&c| c == '\'').count();
let escaped_quotes = s.chars().filter(|&c| c == '\'').count();
assert_eq!(escaped_quotes, original_quotes * 2 + 2,
"每个单引号必须被转义为双单引号,再加首尾包裹引号:原始 {} 个,转义后应为 {} 个,实际 {} 个,结果: {}",
original_quotes, original_quotes * 2 + 2, escaped_quotes, s);
assert!(
s.starts_with('\'') && s.ends_with('\''),
"to_param 结果必须是 SQL 字符串字面量格式,实际: {}",
s
);
}
#[test]
fn mutation_aware_null_to_param() {
let param = Value::Null.to_param();
assert_eq!(param, "NULL");
}
#[test]
#[ignore = "requires cargo-mutants installation and ~30min runtime"]
fn cargo_mutants_baseline() {
panic!("run: cargo mutants -p sz-orm-core --all-features");
}