179 lines
4.1 KiB
Go
179 lines
4.1 KiB
Go
package luajit_test
|
|
|
|
import (
|
|
"testing"
|
|
|
|
luajit "git.sharkk.net/Sky/LuaJIT-to-Go"
|
|
)
|
|
|
|
func TestPushGoFunction(t *testing.T) {
|
|
state := luajit.New()
|
|
if state == nil {
|
|
t.Fatal("Failed to create Lua state")
|
|
}
|
|
defer state.Close()
|
|
|
|
// Define a simple function that adds two numbers
|
|
add := func(s *luajit.State) int {
|
|
a := s.ToNumber(1)
|
|
b := s.ToNumber(2)
|
|
s.PushNumber(a + b)
|
|
return 1 // Return one result
|
|
}
|
|
|
|
// Push the function onto the stack
|
|
if err := state.PushGoFunction(add); err != nil {
|
|
t.Fatalf("PushGoFunction failed: %v", err)
|
|
}
|
|
|
|
// Verify that a function is on the stack
|
|
if !state.IsFunction(-1) {
|
|
t.Fatalf("Expected function at top of stack")
|
|
}
|
|
|
|
// Push arguments
|
|
state.PushNumber(3)
|
|
state.PushNumber(4)
|
|
|
|
// Call the function
|
|
if err := state.Call(2, 1); err != nil {
|
|
t.Fatalf("Failed to call function: %v", err)
|
|
}
|
|
|
|
// Check the result
|
|
if state.ToNumber(-1) != 7 {
|
|
t.Fatalf("Function returned %f, expected 7", state.ToNumber(-1))
|
|
}
|
|
state.Pop(1)
|
|
}
|
|
|
|
func TestRegisterGoFunction(t *testing.T) {
|
|
state := luajit.New()
|
|
if state == nil {
|
|
t.Fatal("Failed to create Lua state")
|
|
}
|
|
defer state.Close()
|
|
|
|
// Define a function that squares a number
|
|
square := func(s *luajit.State) int {
|
|
x := s.ToNumber(1)
|
|
s.PushNumber(x * x)
|
|
return 1
|
|
}
|
|
|
|
// Register the function
|
|
if err := state.RegisterGoFunction("square", square); err != nil {
|
|
t.Fatalf("RegisterGoFunction failed: %v", err)
|
|
}
|
|
|
|
// Call the function from Lua
|
|
if err := state.DoString("result = square(5)"); err != nil {
|
|
t.Fatalf("Failed to call registered function: %v", err)
|
|
}
|
|
|
|
// Check the result
|
|
state.GetGlobal("result")
|
|
if state.ToNumber(-1) != 25 {
|
|
t.Fatalf("Function returned %f, expected 25", state.ToNumber(-1))
|
|
}
|
|
state.Pop(1)
|
|
|
|
// Test UnregisterGoFunction
|
|
state.UnregisterGoFunction("square")
|
|
|
|
// Function should no longer exist
|
|
err := state.DoString("result = square(5)")
|
|
if err == nil {
|
|
t.Fatalf("Expected error after unregistering function, got nil")
|
|
}
|
|
}
|
|
|
|
func TestGoFunctionWithErrorHandling(t *testing.T) {
|
|
state := luajit.New()
|
|
if state == nil {
|
|
t.Fatal("Failed to create Lua state")
|
|
}
|
|
defer state.Close()
|
|
|
|
// Function that returns an error in Lua
|
|
errFunc := func(s *luajit.State) int {
|
|
s.PushString("error from Go function")
|
|
return -1 // Signal error
|
|
}
|
|
|
|
// Register the function
|
|
if err := state.RegisterGoFunction("errorFunc", errFunc); err != nil {
|
|
t.Fatalf("RegisterGoFunction failed: %v", err)
|
|
}
|
|
|
|
// Call the function expecting an error
|
|
err := state.DoString("result = errorFunc()")
|
|
if err == nil {
|
|
t.Fatalf("Expected error from function, got nil")
|
|
}
|
|
|
|
// Error message should contain our message
|
|
luaErr, ok := err.(*luajit.LuaError)
|
|
if !ok {
|
|
t.Fatalf("Expected LuaError, got %T: %v", err, err)
|
|
}
|
|
|
|
if luaErr.Message == "" {
|
|
t.Fatalf("Expected non-empty error message from Go function")
|
|
}
|
|
}
|
|
|
|
func TestCleanup(t *testing.T) {
|
|
state := luajit.New()
|
|
if state == nil {
|
|
t.Fatal("Failed to create Lua state")
|
|
}
|
|
|
|
// Register several functions
|
|
for i := 0; i < 5; i++ {
|
|
dummy := func(s *luajit.State) int { return 0 }
|
|
if err := state.RegisterGoFunction("dummy", dummy); err != nil {
|
|
t.Fatalf("RegisterGoFunction failed: %v", err)
|
|
}
|
|
}
|
|
|
|
// Call Cleanup explicitly
|
|
state.Cleanup()
|
|
|
|
// Make sure we can still close the state
|
|
state.Close()
|
|
|
|
// Also test that Close can be called after Cleanup
|
|
state = luajit.New()
|
|
if state == nil {
|
|
t.Fatal("Failed to create second Lua state")
|
|
}
|
|
|
|
state.Close() // Should call Cleanup internally
|
|
}
|
|
|
|
func TestGoFunctionErrorPointer(t *testing.T) {
|
|
state := luajit.New()
|
|
if state == nil {
|
|
t.Fatal("Failed to create Lua state")
|
|
}
|
|
defer state.Close()
|
|
|
|
// Create a Lua function that calls a non-existent Go function pointer
|
|
// This isn't a direct test of internal implementation, but tries to cover
|
|
// error cases in the goFunctionWrapper
|
|
code := `
|
|
function test()
|
|
-- This is a stub that doesn't actually call the wrapper,
|
|
-- but we're testing error handling in our State.DoString
|
|
return "test"
|
|
end
|
|
`
|
|
if err := state.DoString(code); err != nil {
|
|
t.Fatalf("Failed to define test function: %v", err)
|
|
}
|
|
|
|
// The real test is that Cleanup doesn't crash
|
|
state.Cleanup()
|
|
}
|