Skip to content

Commit

Permalink
Merge function tests.
Browse files Browse the repository at this point in the history
  • Loading branch information
schungx committed Nov 28, 2023
1 parent f3b4918 commit 02ea03e
Show file tree
Hide file tree
Showing 2 changed files with 300 additions and 290 deletions.
301 changes: 300 additions & 1 deletion tests/functions.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,47 @@
#![cfg(not(feature = "no_function"))]
use rhai::{Engine, EvalAltResult, FnNamespace, Module, NativeCallContext, Shared, INT};
use rhai::{Dynamic, Engine, EvalAltResult, FnNamespace, Module, NativeCallContext, ParseErrorType, Shared, INT};

#[test]
fn test_functions() {
let engine = Engine::new();

assert_eq!(engine.eval::<INT>("fn add_me(a, b) { a+b } add_me(3, 4)").unwrap(), 7);
assert_eq!(engine.eval::<INT>("fn add_me(a, b,) { a+b } add_me(3, 4,)").unwrap(), 7);
assert_eq!(engine.eval::<INT>("fn bob() { return 4; 5 } bob()").unwrap(), 4);
assert_eq!(engine.eval::<INT>("fn add(x, n) { x + n } add(40, 2)").unwrap(), 42);
assert_eq!(engine.eval::<INT>("fn add(x, n,) { x + n } add(40, 2,)").unwrap(), 42);
assert_eq!(engine.eval::<INT>("fn add(x, n) { x + n } let a = 40; add(a, 2); a").unwrap(), 40);
#[cfg(not(feature = "no_object"))]
assert_eq!(engine.eval::<INT>("fn add(n) { this + n } let x = 40; x.add(2)").unwrap(), 42);
#[cfg(not(feature = "no_object"))]
assert_eq!(engine.eval::<INT>("fn add(n) { this += n; } let x = 40; x.add(2); x").unwrap(), 42);
assert_eq!(engine.eval::<INT>("fn mul2(x) { x * 2 } mul2(21)").unwrap(), 42);
assert_eq!(engine.eval::<INT>("fn mul2(x) { x *= 2 } let a = 21; mul2(a); a").unwrap(), 21);
#[cfg(not(feature = "no_object"))]
assert_eq!(engine.eval::<INT>("fn mul2() { this * 2 } let x = 21; x.mul2()").unwrap(), 42);
#[cfg(not(feature = "no_object"))]
assert_eq!(engine.eval::<INT>("fn mul2() { this *= 2; } let x = 21; x.mul2(); x").unwrap(), 42);

assert!(engine.eval::<INT>("fn/*\0„").is_err());
}

#[test]
fn test_functions_dynamic() {
let mut engine = Engine::new();

engine.register_fn(
"foo",
|a: INT, b: Dynamic, c: INT, d: INT, e: INT, f: INT, g: INT, h: INT, i: INT, j: INT, k: INT, l: INT, m: INT, n: INT, o: INT, p: INT, q: INT, r: INT, s: INT, t: INT| match b.try_cast::<bool>() {
Some(true) => a + c + d + e + f + g + h + i + j + k + l + m + n + o + p + q + r + s + t,
Some(false) => 0,
None => 42,
},
);

assert_eq!(engine.eval::<INT>("foo(1, true, 3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20)").unwrap(), 208);
assert_eq!(engine.eval::<INT>("foo(1, false, 3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20)").unwrap(), 0);
assert_eq!(engine.eval::<INT>("foo(1, 2, 3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20)").unwrap(), 42);
}

#[cfg(not(feature = "no_object"))]
#[test]
Expand Down Expand Up @@ -237,4 +279,261 @@ fn test_functions_bang() {
.unwrap(),
123
);
assert_eq!(
engine
.eval::<INT>(
"
fn foo(y) { x += y; x }
let x = 41;
let y = 999;
foo!(1) + x
"
)
.unwrap(),
84
);

assert!(engine
.eval::<INT>(
"
fn foo(y) { x += y; x }
let x = 41;
let y = 999;
foo(1) + x
"
)
.is_err());

#[cfg(not(feature = "no_object"))]
assert!(matches!(
engine
.compile(
"
fn foo() { this += x; }
let x = 41;
let y = 999;
y.foo!();
"
)
.unwrap_err()
.err_type(),
ParseErrorType::MalformedCapture(..)
));
}

#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Default)]
struct TestStruct(INT);

impl Clone for TestStruct {
fn clone(&self) -> Self {
Self(self.0 + 1)
}
}

#[test]
fn test_functions_take() {
let mut engine = Engine::new();

engine.register_type_with_name::<TestStruct>("TestStruct").register_fn("new_ts", |x: INT| TestStruct(x));

assert_eq!(
engine
.eval::<TestStruct>(
"
let x = new_ts(0);
for n in 0..41 { x = x }
x
",
)
.unwrap(),
TestStruct(42)
);

assert_eq!(
engine
.eval::<TestStruct>(
"
let x = new_ts(0);
for n in 0..41 { x = take(x) }
take(x)
",
)
.unwrap(),
TestStruct(0)
);
}

#[test]
fn test_functions_big() {
let engine = Engine::new();

assert_eq!(
engine
.eval::<INT>(
"
fn math_me(a, b, c, d, e, f) {
a - b * c + d * e - f
}
math_me(100, 5, 2, 9, 6, 32)
",
)
.unwrap(),
112
);
}

#[test]
fn test_functions_overloading() {
let engine = Engine::new();

assert_eq!(
engine
.eval::<INT>(
"
fn abc(x,y,z) { 2*x + 3*y + 4*z + 888 }
fn abc(x,y) { x + 2*y + 88 }
fn abc() { 42 }
fn abc(x) { x - 42 }
abc() + abc(1) + abc(1,2) + abc(1,2,3)
"
)
.unwrap(),
1002
);

assert_eq!(
*engine
.compile(
"
fn abc(x) { x + 42 }
fn abc(x) { x - 42 }
"
)
.unwrap_err()
.err_type(),
ParseErrorType::FnDuplicatedDefinition("abc".to_string(), 1)
);
}

#[test]
fn test_functions_params() {
let engine = Engine::new();

// Expect duplicated parameters error
assert!(matches!(
engine.compile("fn hello(x, x) { x }").unwrap_err().err_type(),
ParseErrorType::FnDuplicatedParam(a, b) if a == "hello" && b == "x"));
}

#[test]
fn test_function_pointers() {
let engine = Engine::new();

assert_eq!(engine.eval::<String>(r#"type_of(Fn("abc"))"#).unwrap(), "Fn");

assert_eq!(
engine
.eval::<INT>(
r#"
fn foo(x) { 40 + x }
let f = Fn("foo");
call(f, 2)
"#
)
.unwrap(),
42
);

#[cfg(not(feature = "no_object"))]
assert_eq!(
engine
.eval::<INT>(
r#"
fn foo(x) { 40 + x }
let fn_name = "f";
fn_name += "oo";
let f = Fn(fn_name);
f.call(2)
"#
)
.unwrap(),
42
);

#[cfg(not(feature = "no_object"))]
assert!(matches!(
*engine.eval::<INT>(r#"let f = Fn("abc"); f.call(0)"#).unwrap_err(),
EvalAltResult::ErrorFunctionNotFound(f, ..) if f.starts_with("abc (")
));

#[cfg(not(feature = "no_object"))]
assert_eq!(
engine
.eval::<INT>(
r#"
fn foo(x) { 40 + x }
let x = #{ action: Fn("foo") };
x.action.call(2)
"#
)
.unwrap(),
42
);

#[cfg(not(feature = "no_object"))]
assert_eq!(
engine
.eval::<INT>(
r#"
fn foo(x) { this.data += x; }
let x = #{ data: 40, action: Fn("foo") };
x.action(2);
x.data
"#
)
.unwrap(),
42
);
}

#[test]
fn test_functions_is_def() {
let engine = Engine::new();

assert!(engine
.eval::<bool>(
r#"
fn foo(x) { x + 1 }
is_def_fn("foo", 1)
"#
)
.unwrap());
assert!(!engine
.eval::<bool>(
r#"
fn foo(x) { x + 1 }
is_def_fn("bar", 1)
"#
)
.unwrap());
assert!(!engine
.eval::<bool>(
r#"
fn foo(x) { x + 1 }
is_def_fn("foo", 0)
"#
)
.unwrap());
}
Loading

0 comments on commit 02ea03e

Please sign in to comment.