#![allow(clippy::unwrap_used, clippy::expect_used)]
#![allow(clippy::approx_constant)]
use blob_decoder::v8_value::{deserialize, V8Value};
use blob_decoder::{identify, BlobKind, Confidence};
macro_rules! v8 {
($name:literal) => {
include_bytes!(concat!("data/v8/", $name, ".v8"))
};
}
fn s(x: &str) -> V8Value {
V8Value::String(x.to_owned())
}
#[test]
fn primitives() {
assert_eq!(deserialize(v8!("undefined")).unwrap(), V8Value::Undefined);
assert_eq!(deserialize(v8!("null")).unwrap(), V8Value::Null);
assert_eq!(deserialize(v8!("bool_true")).unwrap(), V8Value::Bool(true));
assert_eq!(
deserialize(v8!("bool_false")).unwrap(),
V8Value::Bool(false)
);
}
#[test]
fn integers() {
assert_eq!(deserialize(v8!("int_42")).unwrap(), V8Value::Int(42));
assert_eq!(deserialize(v8!("int_neg7")).unwrap(), V8Value::Int(-7));
assert_eq!(deserialize(v8!("int_zero")).unwrap(), V8Value::Int(0));
}
#[test]
fn doubles() {
assert_eq!(
deserialize(v8!("double_pi")).unwrap(),
V8Value::Double(3.14)
);
assert_eq!(
deserialize(v8!("double_neg")).unwrap(),
V8Value::Double(-2.5)
);
assert_eq!(
deserialize(v8!("uint_big")).unwrap(),
V8Value::Double(4_000_000_000.0)
);
}
#[test]
fn strings() {
assert_eq!(deserialize(v8!("string_ascii")).unwrap(), s("hello"));
assert_eq!(deserialize(v8!("string_empty")).unwrap(), s(""));
assert_eq!(deserialize(v8!("string_unicode")).unwrap(), s("héllo→世界"));
}
#[test]
fn bigints() {
assert_eq!(
deserialize(v8!("bigint_pos")).unwrap(),
V8Value::BigInt("123456789012345678901234567890".to_owned())
);
assert_eq!(
deserialize(v8!("bigint_neg")).unwrap(),
V8Value::BigInt("-42".to_owned())
);
}
#[test]
fn date() {
assert_eq!(
deserialize(v8!("date")).unwrap(),
V8Value::Date(1_600_000_000_000.0)
);
}
#[test]
fn arrays() {
assert_eq!(
deserialize(v8!("array_ints")).unwrap(),
V8Value::Array(vec![V8Value::Int(1), V8Value::Int(2), V8Value::Int(3)])
);
assert_eq!(
deserialize(v8!("array_mixed")).unwrap(),
V8Value::Array(vec![
V8Value::Int(1),
s("two"),
V8Value::Bool(true),
V8Value::Null,
])
);
assert_eq!(
deserialize(v8!("array_empty")).unwrap(),
V8Value::Array(vec![])
);
assert_eq!(
deserialize(v8!("array_holes")).unwrap(),
V8Value::Array(vec![
V8Value::Int(1),
V8Value::Hole,
V8Value::Hole,
V8Value::Int(4),
])
);
}
#[test]
fn objects() {
assert_eq!(
deserialize(v8!("object_simple")).unwrap(),
V8Value::Object(vec![
("a".to_owned(), V8Value::Int(1)),
("b".to_owned(), s("two")),
("c".to_owned(), V8Value::Bool(true)),
])
);
assert_eq!(
deserialize(v8!("object_empty")).unwrap(),
V8Value::Object(vec![])
);
assert_eq!(
deserialize(v8!("object_nested")).unwrap(),
V8Value::Object(vec![
("name".to_owned(), s("x")),
(
"list".to_owned(),
V8Value::Array(vec![
V8Value::Int(1),
V8Value::Int(2),
V8Value::Object(vec![("deep".to_owned(), s("y"))]),
])
),
("when".to_owned(), V8Value::Date(1_600_000_000_000.0)),
])
);
}
#[test]
fn maps_and_sets() {
assert_eq!(
deserialize(v8!("map")).unwrap(),
V8Value::Map(vec![(s("k1"), V8Value::Int(1)), (s("k2"), V8Value::Int(2)),])
);
assert_eq!(
deserialize(v8!("set")).unwrap(),
V8Value::Set(vec![V8Value::Int(1), V8Value::Int(2), V8Value::Int(3)])
);
}
#[test]
fn regexp() {
assert_eq!(
deserialize(v8!("regexp")).unwrap(),
V8Value::RegExp {
source: "ab+c".to_owned(),
flags: 3, }
);
}
#[test]
fn boxed_primitive_objects() {
assert_eq!(
deserialize(v8!("number_object")).unwrap(),
V8Value::NumberObject(7.0)
);
assert_eq!(
deserialize(v8!("string_object")).unwrap(),
V8Value::StringObject("wrap".to_owned())
);
assert_eq!(
deserialize(v8!("boolean_object")).unwrap(),
V8Value::BooleanObject(true)
);
}
#[test]
fn arraybuffer() {
assert_eq!(
deserialize(v8!("arraybuffer")).unwrap(),
V8Value::ArrayBuffer(vec![1, 2, 3, 4])
);
}
#[test]
fn shared_reference_is_resolved() {
let obj = V8Value::Object(vec![("v".to_owned(), V8Value::Int(1))]);
assert_eq!(
deserialize(v8!("shared_ref")).unwrap(),
V8Value::Array(vec![obj.clone(), obj])
);
}
#[test]
fn host_objects_fail_loud() {
let err = deserialize(v8!("uint8array")).unwrap_err();
assert!(
format!("{err}").to_lowercase().contains("host"),
"expected a host-object error, got: {err}"
);
assert!(deserialize(v8!("int32array")).is_err());
}
#[test]
fn identify_surfaces_v8() {
let cands = identify(v8!("object_simple"));
assert_eq!(cands[0].kind, BlobKind::V8Serialized);
assert_eq!(cands[0].score, Confidence::High);
}
#[test]
fn truncated_input_does_not_panic() {
let full = v8!("object_nested");
for cut in 0..full.len() {
let _ = deserialize(&full[..cut]);
}
}