use crate::lua_vm::{LuaVM, SafeOption};
#[test]
fn test_call_with_table_constructor() {
let mut vm = LuaVM::new(SafeOption::default());
vm.open_stdlib(crate::stdlib::Stdlib::All).unwrap();
let result = vm.execute(
r#"
local function process(t)
return t.a + t.b
end
assert(process({a = 3, b = 4}) == 7)
"#,
);
assert!(result.is_ok());
}
#[test]
fn test_call_with_nested_table_constructor() {
let mut vm = LuaVM::new(SafeOption::default());
vm.open_stdlib(crate::stdlib::Stdlib::All).unwrap();
let result = vm.execute(
r#"
local function sum_nested(t)
return t.x.a + t.y.b
end
assert(sum_nested({x = {a = 1}, y = {b = 2}}) == 3)
"#,
);
assert!(result.is_ok());
}
#[test]
fn test_call_with_spread_operator_simple() {
let mut vm = LuaVM::new(SafeOption::default());
vm.open_stdlib(crate::stdlib::Stdlib::All).unwrap();
let result = vm.execute(
r#"
local function sum(a, b, c)
return a + b + c
end
local args = {1, 2, 3}
local a, b, c = table.unpack(args)
assert(sum(a, b, c) == 6)
"#,
);
assert!(result.is_ok());
}
#[test]
fn test_call_chaining_methods() {
let mut vm = LuaVM::new(SafeOption::default());
vm.open_stdlib(crate::stdlib::Stdlib::All).unwrap();
let result = vm.execute(
r#"
local builder = {
value = ""
}
function builder:append(s)
self.value = self.value .. s
return self
end
function builder:upper()
self.value = string.upper(self.value)
return self
end
function builder:get()
return self.value
end
local result = builder:append("hello"):append(" "):append("world"):upper():get()
assert(result == "HELLO WORLD")
"#,
);
assert!(result.is_ok());
}
#[test]
fn test_call_with_assignment_expression() {
let mut vm = LuaVM::new(SafeOption::default());
vm.open_stdlib(crate::stdlib::Stdlib::All).unwrap();
let result = vm.execute(
r#"
local x
local function set_and_return(v)
x = v
return v * 2
end
local y = set_and_return(5)
assert(x == 5 and y == 10)
"#,
);
assert!(result.is_ok());
}
#[test]
fn test_call_in_table_constructor() {
let mut vm = LuaVM::new(SafeOption::default());
vm.open_stdlib(crate::stdlib::Stdlib::All).unwrap();
let result = vm.execute(
r#"
local function double(x) return x * 2 end
local t = {
a = double(5),
b = double(10),
c = double(15)
}
assert(t.a == 10 and t.b == 20 and t.c == 30)
"#,
);
assert!(result.is_ok());
}
#[test]
fn test_call_as_array_index() {
let mut vm = LuaVM::new(SafeOption::default());
vm.open_stdlib(crate::stdlib::Stdlib::All).unwrap();
let result = vm.execute(
r#"
local function get_index() return 2 end
local t = {10, 20, 30}
assert(t[get_index()] == 20)
"#,
);
assert!(result.is_ok());
}
#[test]
fn test_call_with_conditional_return() {
let mut vm = LuaVM::new(SafeOption::default());
vm.open_stdlib(crate::stdlib::Stdlib::All).unwrap();
let result = vm.execute(
r#"
local function maybe(b, x, y)
return b and x or y
end
assert(maybe(true, 10, 20) == 10)
assert(maybe(false, 10, 20) == 20)
"#,
);
assert!(result.is_ok());
}
#[test]
fn test_call_recursive_fibonacci() {
let mut vm = LuaVM::new(SafeOption::default());
vm.open_stdlib(crate::stdlib::Stdlib::All).unwrap();
let result = vm.execute(
r#"
local function fib(n)
if n <= 1 then return n end
return fib(n - 1) + fib(n - 2)
end
assert(fib(10) == 55)
"#,
);
assert!(result.is_ok());
}
#[test]
fn test_call_with_boolean_logic() {
let mut vm = LuaVM::new(SafeOption::default());
vm.open_stdlib(crate::stdlib::Stdlib::All).unwrap();
let result = vm.execute(
r#"
local function is_valid(x)
if x == nil then return false end
if x > 0 then return true end
return false
end
assert(is_valid(5) == true)
assert(is_valid(0) == false)
"#,
);
assert!(result.is_ok());
}
#[test]
fn test_call_string_function_on_literal() {
let mut vm = LuaVM::new(SafeOption::default());
vm.open_stdlib(crate::stdlib::Stdlib::All).unwrap();
let result = vm.execute(
r#"
local result = ("hello"):upper()
assert(result == "HELLO")
"#,
);
assert!(result.is_ok());
}
#[test]
fn test_call_table_method_on_literal() {
let mut vm = LuaVM::new(SafeOption::default());
vm.open_stdlib(crate::stdlib::Stdlib::All).unwrap();
let result = vm.execute(
r#"
local len = table.concat({"a", "b", "c"}, ",")
assert(len == "a,b,c")
"#,
);
assert!(result.is_ok());
}
#[test]
fn test_call_in_loop_condition() {
let mut vm = LuaVM::new(SafeOption::default());
vm.open_stdlib(crate::stdlib::Stdlib::All).unwrap();
let result = vm.execute(
r#"
local counter = 0
local function increment()
counter = counter + 1
return counter
end
while increment() < 5 do
-- loop body
end
assert(counter == 5)
"#,
);
assert!(result.is_ok());
}
#[test]
fn test_call_generator_pattern() {
let mut vm = LuaVM::new(SafeOption::default());
vm.open_stdlib(crate::stdlib::Stdlib::All).unwrap();
let result = vm.execute(
r#"
local function range(n)
local i = 0
return function()
i = i + 1
if i <= n then return i end
end
end
local sum = 0
for x in range(5) do
sum = sum + x
end
assert(sum == 15)
"#,
);
assert!(result.is_ok());
}
#[test]
fn test_call_with_error_handling() {
let mut vm = LuaVM::new(SafeOption::default());
vm.open_stdlib(crate::stdlib::Stdlib::All).unwrap();
let result = vm.execute(
r#"
local function add_func(x, y)
return x + y
end
local ok, result = pcall(add_func, 3, 4)
assert(ok == true)
assert(result == 7)
"#,
);
assert!(result.is_ok());
}
#[test]
fn test_call_curry_pattern() {
let mut vm = LuaVM::new(SafeOption::default());
vm.open_stdlib(crate::stdlib::Stdlib::All).unwrap();
let result = vm.execute(
r#"
local function add(x, y)
return x + y
end
local function curry(f, a)
return function(b)
return f(a, b)
end
end
local add5 = curry(add, 5)
assert(add5(10) == 15)
assert(add5(20) == 25)
"#,
);
assert!(result.is_ok());
}
#[test]
fn test_call_compose_pattern() {
let mut vm = LuaVM::new(SafeOption::default());
vm.open_stdlib(crate::stdlib::Stdlib::All).unwrap();
let result = vm.execute(
r#"
local function double(x) return x * 2 end
local function increment(x) return x + 1 end
local function compose(f, g)
return function(x)
return f(g(x))
end
end
local f = compose(double, increment)
assert(f(5) == 12)
"#,
);
assert!(result.is_ok());
}
#[test]
fn test_call_with_default_parameters() {
let mut vm = LuaVM::new(SafeOption::default());
vm.open_stdlib(crate::stdlib::Stdlib::All).unwrap();
let result = vm.execute(
r#"
local function greet(name, greeting)
greeting = greeting or "Hello"
return greeting .. ", " .. name
end
assert(greet("World") == "Hello, World")
assert(greet("World", "Hi") == "Hi, World")
"#,
);
assert!(result.is_ok());
}
#[test]
fn test_call_with_named_parameters_pattern() {
let mut vm = LuaVM::new(SafeOption::default());
vm.open_stdlib(crate::stdlib::Stdlib::All).unwrap();
let result = vm.execute(
r#"
local function create_obj(params)
return {
name = params.name or "unknown",
age = params.age or 0,
city = params.city or "nowhere"
}
end
local obj = create_obj({name = "John", age = 30})
assert(obj.name == "John" and obj.age == 30 and obj.city == "nowhere")
"#,
);
assert!(result.is_ok());
}
#[test]
fn test_call_immediate_function_expression() {
let mut vm = LuaVM::new(SafeOption::default());
vm.open_stdlib(crate::stdlib::Stdlib::All).unwrap();
let result = vm.execute(
r#"
local result = (function()
local x = 10
local y = 20
return x + y
end)()
assert(result == 30)
"#,
);
assert!(result.is_ok());
}
#[test]
fn test_call_with_side_effects() {
let mut vm = LuaVM::new(SafeOption::default());
vm.open_stdlib(crate::stdlib::Stdlib::All).unwrap();
let result = vm.execute(
r#"
local log = {}
local function logger(msg)
table.insert(log, msg)
return #log
end
local a = logger("first")
local b = logger("second")
local c = logger("third")
assert(a == 1 and b == 2 and c == 3)
assert(#log == 3)
"#,
);
assert!(result.is_ok());
}
#[test]
fn test_call_retry_pattern() {
let mut vm = LuaVM::new(SafeOption::default());
vm.open_stdlib(crate::stdlib::Stdlib::All).unwrap();
let result = vm.execute(
r#"
local function retry(f, times)
for i = 1, times do
local ok, result = pcall(f)
if ok then return result end
end
error("all retries failed")
end
local attempt = 0
local result = retry(function()
attempt = attempt + 1
if attempt < 3 then
error("not ready")
end
return "success"
end, 5)
assert(result == "success")
assert(attempt == 3)
"#,
);
assert!(result.is_ok());
}
#[test]
fn test_call_callback_pattern() {
let mut vm = LuaVM::new(SafeOption::default());
vm.open_stdlib(crate::stdlib::Stdlib::All).unwrap();
let result = vm.execute(
r#"
local function async_operation(callback)
local result = 42
callback(result)
end
local received = nil
async_operation(function(value)
received = value
end)
assert(received == 42)
"#,
);
assert!(result.is_ok());
}
#[test]
fn test_call_event_handler_pattern() {
let mut vm = LuaVM::new(SafeOption::default());
vm.open_stdlib(crate::stdlib::Stdlib::All).unwrap();
let result = vm.execute(
r#"
local event_system = {
handlers = {}
}
function event_system:on(event, handler)
if not self.handlers[event] then
self.handlers[event] = {}
end
table.insert(self.handlers[event], handler)
end
function event_system:emit(event, ...)
if self.handlers[event] then
for i, handler in ipairs(self.handlers[event]) do
handler(...)
end
end
end
local sum = 0
event_system:on("add", function(x) sum = sum + x end)
event_system:on("add", function(x) sum = sum + x * 2 end)
event_system:emit("add", 5)
assert(sum == 15)
"#,
);
assert!(result.is_ok());
}