route/vendor/layeh.com/gopher-luar/func_test.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)
}
}