use luau::{Error, Function, Lua, Table, Variadic};
#[test]
fn function_call_grows_stack_for_variadic_arguments() -> Result<(), Error> {
let lua = Lua::new()?;
let function = lua
.load("return function(...) return select('#', ...) end")
.eval::<Function>()?;
let count: i32 = function.call(Variadic::from_iter(0..254))?;
assert_eq!(count, 254);
Ok(())
}
#[test]
fn function_bind() -> Result<(), Error> {
let lua = Lua::new()?;
let function = lua
.load(
r#"
return function(...)
return table.concat({...})
end
"#,
)
.eval::<Function>()?;
let function = function.bind("foo")?;
let function = function.bind("bar")?;
let function = function.bind(("baz", "baf"))?;
assert_eq!(function.call::<String>(())?, "foobarbazbaf");
assert_eq!(function.call::<String>(("hi", "wut"))?, "foobarbazbafhiwut");
Ok(())
}
#[test]
fn function_bind_rejects_too_many_arguments() -> Result<(), Error> {
let lua = Lua::new()?;
let function = lua.load("return function(...) end").eval::<Function>()?;
function
.bind(Variadic::from_iter(0..u8::MAX as usize - 1))?
.call::<()>(())?;
assert!(matches!(
function.bind(Variadic::from_iter(0..u8::MAX as usize)),
Err(Error::BindError)
));
Ok(())
}
#[test]
fn changing_a_function_environment_invalidates_dependent_imports() -> Result<(), Error> {
let lua = Lua::new()?;
lua.globals()?.set("x", 1)?;
let getter = lua
.load("return function() return x end")
.eval::<Function<'_>>()?;
let module = lua.create_table()?;
let metatable = lua.create_table()?;
metatable.set("__index", &getter)?;
module.set_metatable(Some(&metatable))?;
lua.globals()?.set("module", module)?;
lua.sandbox(true)?;
let read = lua.load("return module.value").into_function()?;
assert_eq!(read.call::<i32>(())?, 1);
let environment = lua.create_table()?;
environment.set("x", 2)?;
environment.set_safe_env(true);
assert!(getter.set_environment(&environment)?);
assert_eq!(read.call::<i32>(())?, 2);
Ok(())
}
#[test]
fn mutable_callbacks_invalidate_imports_resolved_through_them() -> Result<(), Error> {
let lua = Lua::new()?;
let module = lua.create_table()?;
let metatable = lua.create_table()?;
let mut value = 0;
metatable.set(
"__index",
lua.create_function_mut(luau::callback!(
move |_lua, _table: Table<'_>, _key: String| {
value += 1;
Ok(value)
}
))?,
)?;
module.set_metatable(Some(&metatable))?;
lua.globals()?.set("module", module)?;
lua.sandbox(true)?;
let read = lua.load("return module.value").into_function()?;
assert_eq!(read.call::<i32>(())?, 2);
Ok(())
}