242 lines
4.3 KiB
Go
242 lines
4.3 KiB
Go
|
package luar
|
||
|
|
||
|
import (
|
||
|
"reflect"
|
||
|
"testing"
|
||
|
|
||
|
"github.com/yuin/gopher-lua"
|
||
|
)
|
||
|
|
||
|
func Test_func_variableargs(t *testing.T) {
|
||
|
L := lua.NewState()
|
||
|
defer L.Close()
|
||
|
|
||
|
fn := func(str string, extra ...int) {
|
||
|
switch str {
|
||
|
case "a":
|
||
|
if len(extra) != 3 || extra[0] != 1 || extra[1] != 2 || extra[2] != 3 {
|
||
|
t.Fatalf("unexpected variable arguments: %v", extra)
|
||
|
}
|
||
|
case "b":
|
||
|
if len(extra) != 0 {
|
||
|
t.Fatalf("unexpected variable arguments: %v", extra)
|
||
|
}
|
||
|
case "c":
|
||
|
if len(extra) != 1 || extra[0] != 4 {
|
||
|
t.Fatalf("unexpected variable arguments: %v", extra)
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
L.SetGlobal("fn", New(L, fn))
|
||
|
|
||
|
testReturn(t, L, `return fn("a", 1, 2, 3)`)
|
||
|
testReturn(t, L, `return fn("b")`)
|
||
|
testReturn(t, L, `return fn("c", 4)`)
|
||
|
}
|
||
|
|
||
|
func Test_func_structarg(t *testing.T) {
|
||
|
L := lua.NewState()
|
||
|
defer L.Close()
|
||
|
|
||
|
tim := &StructTestPerson{
|
||
|
Name: "Tim",
|
||
|
}
|
||
|
|
||
|
fn := func(p *StructTestPerson) string {
|
||
|
return "Hello, " + p.Name
|
||
|
}
|
||
|
|
||
|
L.SetGlobal("person", New(L, tim))
|
||
|
L.SetGlobal("getHello", New(L, fn))
|
||
|
|
||
|
testReturn(t, L, `return getHello(person)`, "Hello, Tim")
|
||
|
}
|
||
|
|
||
|
func Test_func_nilreference(t *testing.T) {
|
||
|
L := lua.NewState()
|
||
|
defer L.Close()
|
||
|
|
||
|
var fn func()
|
||
|
|
||
|
L.SetGlobal("fn", New(L, fn))
|
||
|
|
||
|
testReturn(t, L, `return fn`, "nil")
|
||
|
}
|
||
|
|
||
|
func Test_func_arrayarg(t *testing.T) {
|
||
|
L := lua.NewState()
|
||
|
defer L.Close()
|
||
|
|
||
|
arr := [3]int{1, 2, 3}
|
||
|
fn := func(val [3]int) {
|
||
|
if val != arr {
|
||
|
t.Fatalf("expecting %v, got %v", arr, val)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
L.SetGlobal("fn", New(L, fn))
|
||
|
L.SetGlobal("arr", New(L, arr))
|
||
|
|
||
|
testReturn(t, L, `return fn(arr)`)
|
||
|
}
|
||
|
|
||
|
func Test_func_luareturntype(t *testing.T) {
|
||
|
L := lua.NewState()
|
||
|
defer L.Close()
|
||
|
|
||
|
fn := func(x ...float64) *lua.LTable {
|
||
|
tbl := L.NewTable()
|
||
|
for i := len(x) - 1; i >= 0; i-- {
|
||
|
tbl.Insert(len(x)-i, lua.LNumber(x[i]))
|
||
|
}
|
||
|
return tbl
|
||
|
}
|
||
|
|
||
|
L.SetGlobal("fn", New(L, fn))
|
||
|
|
||
|
testReturn(
|
||
|
t,
|
||
|
L,
|
||
|
`
|
||
|
local t = {}
|
||
|
for _, x in ipairs(fn(1, 2, 3)) do
|
||
|
table.insert(t, x)
|
||
|
end
|
||
|
return t[1], t[2], t[3]`,
|
||
|
"3", "2", "1",
|
||
|
)
|
||
|
|
||
|
testReturn(
|
||
|
t,
|
||
|
L,
|
||
|
`
|
||
|
local t = {}
|
||
|
for _, x in ipairs(fn()) do
|
||
|
table.insert(t, x)
|
||
|
end
|
||
|
return t[1]`,
|
||
|
"nil",
|
||
|
)
|
||
|
}
|
||
|
|
||
|
type TestLuaFuncRef struct {
|
||
|
F1 *lua.LFunction
|
||
|
}
|
||
|
|
||
|
func Test_func_luafuncref(t *testing.T) {
|
||
|
L := lua.NewState()
|
||
|
defer L.Close()
|
||
|
|
||
|
e := &TestLuaFuncRef{}
|
||
|
L.SetGlobal("e", New(L, e))
|
||
|
|
||
|
testReturn(
|
||
|
t,
|
||
|
L,
|
||
|
`
|
||
|
e.F1 = function(str)
|
||
|
return "Hello World", 123
|
||
|
end
|
||
|
`,
|
||
|
)
|
||
|
|
||
|
L.Push(e.F1)
|
||
|
L.Call(0, 2)
|
||
|
|
||
|
if L.GetTop() != 2 || L.Get(1).String() != "Hello World" || L.Get(2).String() != "123" {
|
||
|
t.Fatal("incorrect return values")
|
||
|
}
|
||
|
}
|
||
|
|
||
|
type TestFuncCall struct {
|
||
|
Fn func(a string) (string, int)
|
||
|
Fn2 func(a string, b ...int) string
|
||
|
}
|
||
|
|
||
|
func Test_func_luafunccall(t *testing.T) {
|
||
|
L := lua.NewState()
|
||
|
defer L.Close()
|
||
|
|
||
|
e := &TestFuncCall{}
|
||
|
L.SetGlobal("x", New(L, e))
|
||
|
|
||
|
testReturn(
|
||
|
t,
|
||
|
L,
|
||
|
`
|
||
|
i = 0
|
||
|
x.Fn = function(str)
|
||
|
i = i + 1
|
||
|
return ">" .. str .. "<", i
|
||
|
end
|
||
|
|
||
|
x.Fn2 = function(str, a, b, c)
|
||
|
if type(a) == "number" and type(b) == "number" and type(c) == "number" then
|
||
|
return str
|
||
|
end
|
||
|
return ""
|
||
|
end
|
||
|
`,
|
||
|
)
|
||
|
|
||
|
if str, i := e.Fn("A"); str != ">A<" || i != 1 {
|
||
|
t.Fatal("unexpected return values")
|
||
|
}
|
||
|
|
||
|
if str, i := e.Fn("B"); str != ">B<" || i != 2 {
|
||
|
t.Fatal("unexpected return values")
|
||
|
}
|
||
|
|
||
|
if val := e.Fn2("hello", 1, 2); val != "" {
|
||
|
t.Fatal("unexpected return value")
|
||
|
}
|
||
|
|
||
|
if val := e.Fn2("hello", 1, 2, 3); val != "hello" {
|
||
|
t.Fatal("unexpected return value")
|
||
|
}
|
||
|
|
||
|
if L.GetTop() != 0 {
|
||
|
t.Fatalf("expecting GetTop to return 0, got %d", L.GetTop())
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func Test_func_argerror(t *testing.T) {
|
||
|
L := lua.NewState()
|
||
|
defer L.Close()
|
||
|
|
||
|
fn := func(v uint8) {
|
||
|
}
|
||
|
|
||
|
L.SetGlobal("fn", New(L, fn))
|
||
|
|
||
|
testError(t, L, `fn("hello world")`, "bad argument #1 to fn (cannot use hello world (type lua.LString) as type uint8)")
|
||
|
}
|
||
|
|
||
|
func Test_func_conversionstack(t *testing.T) {
|
||
|
L := lua.NewState()
|
||
|
defer L.Close()
|
||
|
|
||
|
var fn interface{}
|
||
|
L.SetGlobal("fn", New(L, &fn))
|
||
|
if err := L.DoString(`_ = fn ^ function() return "hello", true, 123 end`); err != nil {
|
||
|
t.Fatal(err)
|
||
|
}
|
||
|
|
||
|
callable, ok := fn.(func(...interface{}) []interface{})
|
||
|
if !ok {
|
||
|
t.Fatal("invalid function signature")
|
||
|
}
|
||
|
values := callable()
|
||
|
|
||
|
expected := []interface{}{
|
||
|
string("hello"),
|
||
|
bool(true),
|
||
|
float64(123),
|
||
|
}
|
||
|
|
||
|
if !reflect.DeepEqual(expected, values) {
|
||
|
t.Fatalf("expected return %#v, got %#v", expected, values)
|
||
|
}
|
||
|
}
|