Files
OxideJS-New/crates/oxide_vm/tests/json_tests.rs
T

277 lines
7.2 KiB
Rust

use oxide_compiler::compiler::Compiler;
use oxide_types::value::JsValue;
use oxide_vm::vm::Vm;
fn eval(vm: &mut Vm, source: &str) -> Result<JsValue, String> {
let allocator = oxide_parser::Allocator::default();
let program = oxide_parser::parse(&allocator, source).map_err(|e| format!("Parse error: {:?}", e))?;
let module = Compiler::new().compile(&program).map_err(|e| format!("Compile error: {}", e))?;
vm.run(&module)
}
fn string_value(vm: &Vm, val: JsValue) -> String {
vm.kernel_core().string_forge().lookup(val.as_string_index()).unwrap_or_default()
}
// -- JSON.parse --
#[test]
fn json_parse_object() {
let mut vm = Vm::new();
let result = eval(&mut vm, "JSON.parse('{\"a\":1,\"b\":2}')").unwrap();
assert!(result.is_object());
let obj = unsafe { &*result.as_js_object_ptr() };
assert_eq!(obj.prop_count(), 2);
}
#[test]
fn json_parse_array() {
let mut vm = Vm::new();
let result = eval(&mut vm, "JSON.parse('[1,2,3]')").unwrap();
assert!(result.is_object());
let obj = unsafe { &*result.as_js_object_ptr() };
assert!(obj.is_array());
assert_eq!(obj.prop_count(), 3);
assert_eq!(obj.get_prop_at(2).as_double(), 3.0);
}
#[test]
fn json_parse_string() {
let mut vm = Vm::new();
let result = eval(&mut vm, "JSON.parse('\"hello\"')").unwrap();
assert!(result.is_string());
let s = string_value(&vm, result);
assert_eq!(s, "hello");
}
#[test]
fn json_parse_number() {
let mut vm = Vm::new();
let result = eval(&mut vm, "JSON.parse('42')").unwrap();
assert!(result.is_double());
}
#[test]
fn json_parse_float() {
let mut vm = Vm::new();
let result = eval(&mut vm, "JSON.parse('3.14')").unwrap();
assert!(result.is_double());
}
#[test]
fn json_parse_true() {
let mut vm = Vm::new();
let result = eval(&mut vm, "JSON.parse('true')").unwrap();
assert!(result.is_bool());
assert!(result.as_bool());
}
#[test]
fn json_parse_false() {
let mut vm = Vm::new();
let result = eval(&mut vm, "JSON.parse('false')").unwrap();
assert!(result.is_bool());
assert!(!result.as_bool());
}
#[test]
fn json_parse_null() {
let mut vm = Vm::new();
let result = eval(&mut vm, "JSON.parse('null')").unwrap();
assert!(result.is_null());
}
#[test]
fn json_parse_nested() {
let mut vm = Vm::new();
let result = eval(&mut vm, "JSON.parse('{\"a\":1,\"b\":[1,2],\"c\":{\"d\":\"hello\"}}')").unwrap();
assert!(result.is_object());
}
#[test]
fn json_parse_invalid_throws() {
let mut vm = Vm::new();
let err = eval(&mut vm, "JSON.parse('not json')");
assert!(err.is_err());
}
// -- JSON.stringify --
#[test]
fn json_stringify_object() {
let mut vm = Vm::new();
let result = eval(&mut vm, "JSON.stringify({a:1})").unwrap();
assert!(result.is_string());
let s = string_value(&vm, result);
assert_eq!(s, "{\"a\":1}");
}
#[test]
fn json_stringify_array() {
let mut vm = Vm::new();
let result = eval(&mut vm, "JSON.stringify([1,2,3])").unwrap();
assert!(result.is_string());
let s = string_value(&vm, result);
assert_eq!(s, "[1,2,3]");
}
#[test]
fn json_stringify_string() {
let mut vm = Vm::new();
let result = eval(&mut vm, "JSON.stringify('hello')").unwrap();
assert!(result.is_string());
let s = string_value(&vm, result);
assert_eq!(s, "\"hello\"");
}
#[test]
fn json_stringify_number() {
let mut vm = Vm::new();
let result = eval(&mut vm, "JSON.stringify(42)").unwrap();
assert!(result.is_string());
let s = string_value(&vm, result);
assert_eq!(s, "42");
}
#[test]
fn json_stringify_float() {
let mut vm = Vm::new();
let result = eval(&mut vm, "JSON.stringify(3.14)").unwrap();
assert!(result.is_string());
let s = string_value(&vm, result);
assert!(s.starts_with("3.14"));
}
#[test]
fn json_stringify_true() {
let mut vm = Vm::new();
let result = eval(&mut vm, "JSON.stringify(true)").unwrap();
assert!(result.is_string());
let s = string_value(&vm, result);
assert_eq!(s, "true");
}
#[test]
fn json_stringify_false() {
let mut vm = Vm::new();
let result = eval(&mut vm, "JSON.stringify(false)").unwrap();
assert!(result.is_string());
let s = string_value(&vm, result);
assert_eq!(s, "false");
}
#[test]
fn json_stringify_null() {
let mut vm = Vm::new();
let result = eval(&mut vm, "JSON.stringify(null)").unwrap();
assert!(result.is_string());
let s = string_value(&vm, result);
assert_eq!(s, "null");
}
#[test]
fn json_stringify_undefined() {
let mut vm = Vm::new();
let result = eval(&mut vm, "JSON.stringify(undefined)").unwrap();
assert!(result.is_undefined());
}
// -- Roundtrip --
#[test]
fn json_parse_stringify_roundtrip() {
let mut vm = Vm::new();
let result = eval(&mut vm, "JSON.parse(JSON.stringify({a:1,b:2}))").unwrap();
assert!(result.is_object());
let obj = unsafe { &*result.as_js_object_ptr() };
assert_eq!(obj.prop_vec_len(), 2);
}
#[test]
fn json_roundtrip_array() {
let mut vm = Vm::new();
let _ = eval(&mut vm, "var arr = JSON.parse(JSON.stringify([1,2,3])); arr").unwrap();
}
// -- Edge cases --
#[test]
fn json_stringify_empty_object() {
let mut vm = Vm::new();
let result = eval(&mut vm, "JSON.stringify({})").unwrap();
assert!(result.is_string());
let s = string_value(&vm, result);
assert_eq!(s, "{}");
}
#[test]
fn json_stringify_empty_array() {
let mut vm = Vm::new();
let result = eval(&mut vm, "JSON.stringify([])").unwrap();
assert!(result.is_string());
let s = string_value(&vm, result);
assert_eq!(s, "[]");
}
#[test]
fn json_stringify_escape_quotes() {
let mut vm = Vm::new();
let result = eval(&mut vm, "JSON.stringify('he\"llo')").unwrap();
assert!(result.is_string());
let s = string_value(&vm, result);
assert_eq!(s, "\"he\\\"llo\"");
}
#[test]
fn json_stringify_escape_backslash() {
let mut vm = Vm::new();
let result = eval(&mut vm, "JSON.stringify('a\\\\b')").unwrap();
assert!(result.is_string());
let s = string_value(&vm, result);
assert_eq!(s, "\"a\\\\b\"");
}
#[test]
fn json_stringify_nested_objects() {
let mut vm = Vm::new();
let result = eval(&mut vm, "JSON.stringify({a: {b: 1}})").unwrap();
assert!(result.is_string());
let s = string_value(&vm, result);
assert_eq!(s, "{\"a\":{\"b\":1}}");
}
#[test]
fn json_parse_empty_object() {
let mut vm = Vm::new();
let result = eval(&mut vm, "JSON.parse('{}')").unwrap();
assert!(result.is_object());
let obj = unsafe { &*result.as_js_object_ptr() };
assert_eq!(obj.prop_vec_len(), 0);
}
#[test]
fn json_parse_empty_array() {
let mut vm = Vm::new();
let result = eval(&mut vm, "JSON.parse('[]')").unwrap();
assert!(result.is_object());
let obj = unsafe { &*result.as_js_object_ptr() };
assert!(obj.is_array());
assert_eq!(obj.prop_vec_len(), 0);
}
#[test]
fn json_parse_int_is_double() {
let mut vm = Vm::new();
let result = eval(&mut vm, "JSON.parse('123')").unwrap();
assert!((result.as_double() - 123.0).abs() < 0.0001);
}
// -- Cycle detection --
#[test]
fn json_stringify_cycle_throws_type_error() {
let mut vm = Vm::new();
let err = eval(&mut vm, "var a = {}; a.self = a; JSON.stringify(a)");
assert!(err.is_err());
}