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

204 lines
5.8 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
use std::sync::Arc;
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(&Arc::new(module))
}
fn to_str(vm: &Vm, val: JsValue) -> String {
vm.lookup_str(val).unwrap_or_default()
}
#[test]
fn data_view_global_and_methods_exist() {
let mut vm = Vm::new();
let result = eval(
&mut vm,
"typeof DataView === 'function' && typeof DataView.prototype.getInt32 === 'function'",
)
.unwrap();
assert!(result.as_bool());
}
#[test]
fn data_view_properties_reference_buffer_offset_and_length() {
let mut vm = Vm::new();
let result = eval(
&mut vm,
"var buf = new ArrayBuffer(16); var dv = new DataView(buf, 4, 8); \
dv.buffer === buf && dv.byteOffset === 4 && dv.byteLength === 8",
)
.unwrap();
assert!(result.as_bool());
}
#[test]
fn data_view_set_get_int32_big_endian() {
let mut vm = Vm::new();
let result = eval(
&mut vm,
"var buf = new ArrayBuffer(16); var dv = new DataView(buf); \
dv.setInt32(0, 305419896, false); dv.getInt32(0, false)",
)
.unwrap();
assert_eq!(result.as_int(), 305419896);
}
#[test]
fn data_view_set_get_int32_little_endian_exposes_first_byte() {
let mut vm = Vm::new();
let result = eval(
&mut vm,
"var buf = new ArrayBuffer(16); var dv = new DataView(buf); \
dv.setInt32(0, 305419896, true); dv.getUint8(0)",
)
.unwrap();
assert_eq!(result.as_int(), 120);
}
#[test]
fn data_view_set_get_uint16_and_int8() {
let mut vm = Vm::new();
let result = eval(
&mut vm,
"var buf = new ArrayBuffer(4); var dv = new DataView(buf); \
var neg = -1; dv.setUint16(0, 65535, false); dv.setInt8(2, neg); \
dv.getUint16(0, false) === 65535 && dv.getInt8(2) === -1",
)
.unwrap();
assert!(result.as_bool());
}
#[test]
fn data_view_float64_roundtrip() {
let mut vm = Vm::new();
let result = eval(
&mut vm,
"var buf = new ArrayBuffer(8); var dv = new DataView(buf); \
dv.setFloat64(0, 3.5, true); dv.getFloat64(0, true)",
)
.unwrap();
assert_eq!(result.as_double(), 3.5);
}
#[test]
fn data_view_offset_view_writes_into_underlying_buffer() {
let mut vm = Vm::new();
let result = eval(
&mut vm,
"var buf = new ArrayBuffer(16); var base = new DataView(buf); var dv = new DataView(buf, 4, 8); \
dv.setUint8(0, 77); base.getUint8(4)",
)
.unwrap();
assert_eq!(result.as_int(), 77);
}
#[test]
fn data_view_is_array_buffer_view() {
let mut vm = Vm::new();
let result = eval(&mut vm, "var dv = new DataView(new ArrayBuffer(1)); ArrayBuffer.isView(dv)").unwrap();
assert!(result.as_bool());
}
#[test]
fn data_view_rejects_non_array_buffer() {
let mut vm = Vm::new();
let result = eval(&mut vm, "try { new DataView({}) } catch (e) { e instanceof TypeError }").unwrap();
assert!(result.as_bool());
}
#[test]
fn data_view_rejects_out_of_bounds_access() {
let mut vm = Vm::new();
let result = eval(
&mut vm,
"try { var dv = new DataView(new ArrayBuffer(4)); dv.getInt32(2); } catch (e) { e instanceof RangeError }",
)
.unwrap();
assert!(result.as_bool());
}
#[test]
fn data_view_to_string_is_identifiable() {
let mut vm = Vm::new();
let result = eval(&mut vm, "var dv = new DataView(new ArrayBuffer(1)); dv.toString()").unwrap();
assert_eq!(to_str(&vm, result), "[object DataView]");
}
#[test]
fn data_view_get_big_int64_returns_bigint() {
let mut vm = Vm::new();
let result = eval(&mut vm, "new DataView(new ArrayBuffer(8)).getBigInt64(0)").unwrap();
assert!(result.is_bigint());
}
#[test]
fn data_view_set_big_int64_with_number_throws() {
let mut vm = Vm::new();
// ToBigInt 语义:Number 入参抛 TypeError。
let result = eval(
&mut vm,
"try { new DataView(new ArrayBuffer(8)).setBigInt64(0, 1); false } catch (e) { e instanceof TypeError }",
)
.unwrap();
assert!(result.as_bool());
}
#[test]
fn data_view_big_int64_precision_roundtrip() {
let mut vm = Vm::new();
// 2^63-1(i64::MAX)超出 f64 精确范围,真 BigInt 语义读回必须原值。
let result = eval(
&mut vm,
"var dv = new DataView(new ArrayBuffer(8)); \
dv.setBigInt64(0, 9223372036854775807n); dv.getBigInt64(0) === 9223372036854775807n",
)
.unwrap();
assert!(result.as_bool());
}
#[test]
fn data_view_big_uint64_precision_roundtrip() {
let mut vm = Vm::new();
let result = eval(
&mut vm,
"var dv = new DataView(new ArrayBuffer(8)); \
dv.setBigUint64(0, 18446744073709551615n, true); dv.getBigUint64(0, true) === 18446744073709551615n",
)
.unwrap();
assert!(result.as_bool());
}
#[test]
fn data_view_big_int64_little_endian_byte_order() {
let mut vm = Vm::new();
// 小端写入后首字节为低字节;同一字节序读回原值。
let result = eval(
&mut vm,
"var dv = new DataView(new ArrayBuffer(8)); \
dv.setBigInt64(0, 0x0102030405060708n, true); \
dv.getUint8(0) === 8 && dv.getBigInt64(0, true) === 0x0102030405060708n",
)
.unwrap();
assert!(result.as_bool());
}
#[test]
fn data_view_set_big_int64_mod_2_64_truncation() {
let mut vm = Vm::new();
// 超 64 位值按 mod 2^64 截断写入。
let result = eval(
&mut vm,
"var dv = new DataView(new ArrayBuffer(8)); \
dv.setBigInt64(0, 1180591620717411303429n); dv.getBigInt64(0) === 5n",
)
.unwrap();
assert!(result.as_bool());
}