rhai/tests/internal_fn.rs

325 lines
6.8 KiB
Rust
Raw Normal View History

#![cfg(not(feature = "no_function"))]
use rhai::{Engine, EvalAltResult, ParseErrorType, INT};
2017-11-03 17:58:51 +01:00
#[test]
fn test_internal_fn() -> Result<(), Box<EvalAltResult>> {
let engine = Engine::new();
2017-11-03 17:58:51 +01:00
assert_eq!(
engine.eval::<INT>("fn add_me(a, b) { a+b } add_me(3, 4)")?,
7
);
2020-06-16 16:14:46 +02:00
assert_eq!(
engine.eval::<INT>("fn add_me(a, b,) { a+b } add_me(3, 4,)")?,
7
);
assert_eq!(engine.eval::<INT>("fn bob() { return 4; 5 } bob()")?, 4);
2020-03-02 15:11:56 +01:00
assert_eq!(engine.eval::<INT>("fn add(x, n) { x + n } add(40, 2)")?, 42);
assert_eq!(
engine.eval::<INT>("fn add(x, n,) { x + n } add(40, 2,)")?,
42
);
assert_eq!(
engine.eval::<INT>("fn add(x, n) { x + n } let a = 40; add(a, 2); a")?,
40
);
#[cfg(not(feature = "no_object"))]
assert_eq!(
engine.eval::<INT>("fn add(n) { this + n } let x = 40; x.add(2)")?,
42
);
#[cfg(not(feature = "no_object"))]
assert_eq!(
engine.eval::<INT>("fn add(n) { this += n; } let x = 40; x.add(2); x")?,
42
);
assert_eq!(engine.eval::<INT>("fn mul2(x) { x * 2 } mul2(21)")?, 42);
assert_eq!(
engine.eval::<INT>("fn mul2(x) { x *= 2 } let a = 21; mul2(a); a")?,
21
);
#[cfg(not(feature = "no_object"))]
assert_eq!(
engine.eval::<INT>("fn mul2() { this * 2 } let x = 21; x.mul2()")?,
42
);
#[cfg(not(feature = "no_object"))]
assert_eq!(
engine.eval::<INT>("fn mul2() { this *= 2; } let x = 21; x.mul2(); x")?,
42
);
2020-03-02 15:11:56 +01:00
Ok(())
2017-11-03 17:58:51 +01:00
}
2023-05-13 03:31:57 +02:00
#[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_internal_fn_take() -> Result<(), Box<EvalAltResult>> {
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
",
)?,
TestStruct(42)
);
assert_eq!(
engine.eval::<TestStruct>(
"
let x = new_ts(0);
for n in 0..41 { x = take(x) }
take(x)
",
)?,
TestStruct(0)
);
Ok(())
}
2017-11-03 17:58:51 +01:00
#[test]
fn test_internal_fn_big() -> Result<(), Box<EvalAltResult>> {
let engine = Engine::new();
2017-11-03 17:58:51 +01:00
assert_eq!(
engine.eval::<INT>(
2021-04-20 06:01:35 +02:00
"
fn math_me(a, b, c, d, e, f) {
2020-03-02 15:11:56 +01:00
a - b * c + d * e - f
}
math_me(100, 5, 2, 9, 6, 32)
2020-03-02 15:11:56 +01:00
",
)?,
112
);
2020-03-02 15:11:56 +01:00
Ok(())
2017-11-03 17:58:51 +01:00
}
2020-03-12 06:02:13 +01:00
#[test]
fn test_internal_fn_overloading() -> Result<(), Box<EvalAltResult>> {
let engine = Engine::new();
2020-03-12 06:02:13 +01:00
assert_eq!(
engine.eval::<INT>(
2021-04-20 06:01:35 +02:00
"
2020-03-12 06:02:13 +01:00
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 }
2020-03-12 06:02:13 +01:00
abc() + abc(1) + abc(1,2) + abc(1,2,3)
"
2020-03-12 06:02:13 +01:00
)?,
1002
);
assert_eq!(
*engine
.compile(
2021-04-20 06:01:35 +02:00
"
2021-01-24 14:21:15 +01:00
fn abc(x) { x + 42 }
fn abc(x) { x - 42 }
"
)
2023-04-10 17:23:59 +02:00
.unwrap_err()
.err_type(),
ParseErrorType::FnDuplicatedDefinition("abc".to_string(), 1)
);
2020-03-12 06:02:13 +01:00
Ok(())
}
#[test]
fn test_internal_fn_params() -> Result<(), Box<EvalAltResult>> {
let engine = Engine::new();
// Expect duplicated parameters error
assert_eq!(
*engine
.compile("fn hello(x, x) { x }")
2023-04-10 17:23:59 +02:00
.unwrap_err()
.err_type(),
ParseErrorType::FnDuplicatedParam("hello".to_string(), "x".to_string())
);
Ok(())
}
#[test]
fn test_function_pointers() -> Result<(), Box<EvalAltResult>> {
let engine = Engine::new();
assert_eq!(engine.eval::<String>(r#"type_of(Fn("abc"))"#)?, "Fn");
assert_eq!(
engine.eval::<INT>(
r#"
fn foo(x) { 40 + x }
let f = Fn("foo");
call(f, 2)
"#
)?,
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)
"#
)?,
42
);
#[cfg(not(feature = "no_object"))]
assert!(matches!(
2023-04-10 17:23:59 +02:00
*engine.eval::<INT>(r#"let f = Fn("abc"); f.call(0)"#).unwrap_err(),
2022-02-08 02:02:15 +01:00
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)
"#
)?,
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
"#
)?,
42
);
Ok(())
}
#[test]
fn test_internal_fn_bang() -> Result<(), Box<EvalAltResult>> {
let engine = Engine::new();
assert_eq!(
engine.eval::<INT>(
2021-06-05 09:26:43 +02:00
"
fn foo(y) { x += y; x }
let x = 41;
let y = 999;
foo!(1) + x
2021-06-05 09:26:43 +02:00
"
)?,
84
);
assert!(engine
.eval::<INT>(
2021-06-05 09:26:43 +02:00
"
fn foo(y) { x += y; x }
let x = 41;
let y = 999;
foo(1) + x
2021-06-05 09:26:43 +02:00
"
)
.is_err());
#[cfg(not(feature = "no_object"))]
assert!(matches!(
engine
.compile(
2021-06-05 09:26:43 +02:00
"
fn foo() { this += x; }
let x = 41;
let y = 999;
y.foo!();
2021-06-05 09:26:43 +02:00
"
)
2023-04-10 17:23:59 +02:00
.unwrap_err()
.err_type(),
2022-02-08 02:46:14 +01:00
ParseErrorType::MalformedCapture(..)
));
Ok(())
}
#[test]
fn test_internal_fn_is_def() -> Result<(), Box<EvalAltResult>> {
let engine = Engine::new();
assert!(engine.eval::<bool>(
r#"
fn foo(x) { x + 1 }
is_def_fn("foo", 1)
"#
)?);
assert!(!engine.eval::<bool>(
r#"
fn foo(x) { x + 1 }
is_def_fn("bar", 1)
"#
)?);
assert!(!engine.eval::<bool>(
r#"
fn foo(x) { x + 1 }
is_def_fn("foo", 0)
"#
)?);
Ok(())
}