Add tests for SWF6 numerical coercions.

This commit is contained in:
David Wendt 2019-11-28 14:18:30 -05:00
parent f856243247
commit 9ec85c3892
3 changed files with 127 additions and 16 deletions

View File

@ -171,7 +171,7 @@ pub fn create_globals<'gc>(
Some(movie_clip_proto),
);
let mut globals = ScriptObject::object(gc_context, Some(object_proto));
let mut globals = ScriptObject::bare_object();
globals.define_value("Object", object.into(), EnumSet::empty());
globals.define_value("Function", function.into(), EnumSet::empty());
globals.define_value("MovieClip", movie_clip.into(), EnumSet::empty());

View File

@ -142,10 +142,10 @@ mod tests {
use crate::avm1::Error;
macro_rules! test_std {
( $test: ident, $name: expr, $([$($arg: expr),*] => $out: expr),* ) => {
( $test: ident, $avm_ver: expr, $name: expr, $([$($arg: expr),*] => $out: expr),* ) => {
#[test]
fn $test() -> Result<(), Error> {
with_avm(19, |avm, context, _root| {
with_avm($avm_ver, |avm, context, _root| {
let math = create(context.gc_context, Some(avm.prototypes().object), Some(avm.prototypes().function));
let function = math.read().get($name, avm, context, math)?.unwrap_immediate();
@ -164,14 +164,14 @@ mod tests {
};
}
test_std!(test_abs, "abs",
test_std!(test_abs, 19, "abs",
[] => NAN,
[Value::Null] => NAN,
[-50.0] => 50.0,
[25.0] => 25.0
);
test_std!(test_acos, "acos",
test_std!(test_acos, 19, "acos",
[] => NAN,
[Value::Null] => NAN,
[-1.0] => f64::acos(-1.0),
@ -179,7 +179,7 @@ mod tests {
[1.0] => f64::acos(1.0)
);
test_std!(test_asin, "asin",
test_std!(test_asin, 19, "asin",
[] => NAN,
[Value::Null] => NAN,
[-1.0] => f64::asin(-1.0),
@ -187,7 +187,7 @@ mod tests {
[1.0] => f64::asin(1.0)
);
test_std!(test_atan, "atan",
test_std!(test_atan, 19, "atan",
[] => NAN,
[Value::Null] => NAN,
[-1.0] => f64::atan(-1.0),
@ -195,54 +195,66 @@ mod tests {
[1.0] => f64::atan(1.0)
);
test_std!(test_ceil, "ceil",
test_std!(test_ceil, 19, "ceil",
[] => NAN,
[Value::Null] => NAN,
[12.5] => 13.0
);
test_std!(test_cos, "cos",
test_std!(test_cos, 19, "cos",
[] => NAN,
[Value::Null] => NAN,
[0.0] => 1.0,
[std::f64::consts::PI] => f64::cos(std::f64::consts::PI)
);
test_std!(test_exp, "exp",
test_std!(test_exp, 19, "exp",
[] => NAN,
[Value::Null] => NAN,
[1.0] => f64::exp(1.0),
[2.0] => f64::exp(2.0)
);
test_std!(test_floor, "floor",
test_std!(test_floor, 19, "floor",
[] => NAN,
[Value::Undefined] => NAN,
[Value::Null] => NAN,
[Value::Bool(false)] => 0.0,
[Value::Bool(true)] => 1.0,
[12.5] => 12.0
);
test_std!(test_round, "round",
test_std!(test_floor_swf6, 6, "floor",
[] => NAN,
[Value::Undefined] => 0.0,
[Value::Null] => 0.0,
[Value::Bool(false)] => 0.0,
[Value::Bool(true)] => 1.0,
[12.5] => 12.0
);
test_std!(test_round, 19, "round",
[] => NAN,
[Value::Null] => NAN,
[12.5] => 13.0,
[23.2] => 23.0
);
test_std!(test_sin, "sin",
test_std!(test_sin, 19, "sin",
[] => NAN,
[Value::Null] => NAN,
[0.0] => f64::sin(0.0),
[std::f64::consts::PI / 2.0] => f64::sin(std::f64::consts::PI / 2.0)
);
test_std!(test_sqrt, "sqrt",
test_std!(test_sqrt, 19, "sqrt",
[] => NAN,
[Value::Null] => NAN,
[0.0] => f64::sqrt(0.0),
[5.0] => f64::sqrt(5.0)
);
test_std!(test_tan, "tan",
test_std!(test_tan, 19, "tan",
[] => NAN,
[Value::Null] => NAN,
[0.0] => f64::tan(0.0),

View File

@ -490,10 +490,109 @@ impl<'gc> Value<'gc> {
#[cfg(test)]
mod test {
use crate::avm1::function::Executable;
use crate::avm1::globals::create_globals;
use crate::avm1::object::ObjectCell;
use crate::avm1::return_value::ReturnValue;
use crate::avm1::script_object::ScriptObject;
use crate::avm1::test_utils::with_avm;
use crate::avm1::Value;
use crate::avm1::{Avm1, Error, Value};
use crate::context::UpdateContext;
use enumset::EnumSet;
use gc_arena::GcCell;
use std::f64::{INFINITY, NAN, NEG_INFINITY};
#[test]
fn to_primitive_num() {
with_avm(6, |avm, context, _this| {
let t = Value::Bool(true);
let u = Value::Undefined;
let f = Value::Bool(false);
let n = Value::Null;
assert_eq!(t.to_primitive_num(avm, context).unwrap(), t);
assert_eq!(u.to_primitive_num(avm, context).unwrap(), u);
assert_eq!(f.to_primitive_num(avm, context).unwrap(), f);
assert_eq!(n.to_primitive_num(avm, context).unwrap(), n);
let (protos, global) = create_globals(context.gc_context);
let vglobal = Value::Object(GcCell::allocate(context.gc_context, global));
assert_eq!(vglobal.to_primitive_num(avm, context).unwrap(), u);
fn value_of_impl<'gc>(
_: &mut Avm1<'gc>,
_: &mut UpdateContext<'_, 'gc, '_>,
_: ObjectCell<'gc>,
_: &[Value<'gc>],
) -> Result<ReturnValue<'gc>, Error> {
Ok(5.0.into())
}
let valueof = ScriptObject::function(
context.gc_context,
Executable::Native(value_of_impl),
Some(protos.function),
None,
);
let o = ScriptObject::object_cell(context.gc_context, Some(protos.object));
o.write(context.gc_context)
.define_value("valueOf", valueof.into(), EnumSet::empty());
assert_eq!(
Value::Object(o).to_primitive_num(avm, context).unwrap(),
Value::Number(5.0)
);
});
}
#[test]
#[allow(clippy::float_cmp)]
fn to_number_swf7() {
with_avm(7, |avm, context, _this| {
let t = Value::Bool(true);
let u = Value::Undefined;
let f = Value::Bool(false);
let n = Value::Null;
assert_eq!(t.as_number(avm, context).unwrap(), 1.0);
assert!(u.as_number(avm, context).unwrap().is_nan());
assert_eq!(f.as_number(avm, context).unwrap(), 0.0);
assert!(n.as_number(avm, context).unwrap().is_nan());
let bo = Value::Object(GcCell::allocate(
context.gc_context,
Box::new(ScriptObject::bare_object()),
));
assert!(bo.as_number(avm, context).unwrap().is_nan());
});
}
#[test]
#[allow(clippy::float_cmp)]
fn to_number_swf6() {
with_avm(6, |avm, context, _this| {
let t = Value::Bool(true);
let u = Value::Undefined;
let f = Value::Bool(false);
let n = Value::Null;
assert_eq!(t.as_number(avm, context).unwrap(), 1.0);
assert_eq!(u.as_number(avm, context).unwrap(), 0.0);
assert_eq!(f.as_number(avm, context).unwrap(), 0.0);
assert_eq!(n.as_number(avm, context).unwrap(), 0.0);
let bo = Value::Object(GcCell::allocate(
context.gc_context,
Box::new(ScriptObject::bare_object()),
));
assert_eq!(bo.as_number(avm, context).unwrap(), 0.0);
});
}
#[test]
fn abstract_lt_num() {
with_avm(8, |avm, context, _this| {