2014-09-02 13:55:12 +04:00
|
|
|
package server
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
2015-05-04 17:42:28 +03:00
|
|
|
|
2014-09-02 13:55:12 +04:00
|
|
|
"github.com/siddontang/ledisdb/config"
|
2017-04-15 16:51:03 +03:00
|
|
|
"github.com/yuin/gopher-lua"
|
2014-09-02 13:55:12 +04:00
|
|
|
|
|
|
|
"testing"
|
|
|
|
)
|
|
|
|
|
|
|
|
var testLuaWriter = &luaWriter{}
|
|
|
|
|
2017-04-15 16:51:03 +03:00
|
|
|
func testLuaWriteError(l *lua.LState) int {
|
2014-09-02 13:55:12 +04:00
|
|
|
testLuaWriter.writeError(fmt.Errorf("test error"))
|
|
|
|
return 1
|
|
|
|
}
|
|
|
|
|
2017-04-15 16:51:03 +03:00
|
|
|
func testLuaWriteArray(l *lua.LState) int {
|
2014-09-02 13:55:12 +04:00
|
|
|
ay := make([]interface{}, 2)
|
|
|
|
ay[0] = []byte("1")
|
|
|
|
b := make([]interface{}, 2)
|
|
|
|
b[0] = int64(10)
|
|
|
|
b[1] = []byte("11")
|
|
|
|
|
|
|
|
ay[1] = b
|
|
|
|
|
|
|
|
testLuaWriter.writeArray(ay)
|
|
|
|
|
|
|
|
return 1
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestLuaWriter(t *testing.T) {
|
2017-04-15 16:51:03 +03:00
|
|
|
l := lua.NewState(lua.Options{SkipOpenLibs: true})
|
|
|
|
defer l.Close()
|
|
|
|
for _, pair := range []struct {
|
|
|
|
n string
|
|
|
|
f lua.LGFunction
|
|
|
|
}{
|
|
|
|
{lua.LoadLibName, lua.OpenPackage}, // Must be first
|
|
|
|
{lua.BaseLibName, lua.OpenBase},
|
|
|
|
} {
|
|
|
|
if err := l.CallByParam(lua.P{
|
|
|
|
Fn: l.NewFunction(pair.f),
|
|
|
|
NRet: 0,
|
|
|
|
Protect: true,
|
|
|
|
}, lua.LString(pair.n)); err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
}
|
2014-09-02 13:55:12 +04:00
|
|
|
|
|
|
|
testLuaWriter.l = l
|
|
|
|
|
|
|
|
l.Register("WriteError", testLuaWriteError)
|
|
|
|
|
|
|
|
str := `
|
|
|
|
WriteError()
|
|
|
|
`
|
|
|
|
|
|
|
|
err := l.DoString(str)
|
|
|
|
|
|
|
|
if err == nil {
|
|
|
|
t.Fatal("must error")
|
|
|
|
}
|
|
|
|
|
|
|
|
l.Register("WriteArray", testLuaWriteArray)
|
|
|
|
|
|
|
|
str = `
|
|
|
|
local a = WriteArray()
|
|
|
|
|
|
|
|
if #a ~= 2 then
|
|
|
|
error("len a must 2")
|
|
|
|
elseif a[1] ~= "1" then
|
|
|
|
error("a[1] must 1")
|
|
|
|
elseif #a[2] ~= 2 then
|
|
|
|
error("len a[2] must 2")
|
|
|
|
elseif a[2][1] ~= 10 then
|
|
|
|
error("a[2][1] must 10")
|
|
|
|
elseif a[2][2] ~= "11" then
|
|
|
|
error("a[2][2] must 11")
|
|
|
|
end
|
|
|
|
`
|
|
|
|
|
|
|
|
err = l.DoString(str)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
l.Close()
|
|
|
|
}
|
|
|
|
|
|
|
|
var testScript1 = `
|
|
|
|
return {1,2,3}
|
|
|
|
`
|
|
|
|
|
|
|
|
var testScript2 = `
|
|
|
|
return ledis.call("ping")
|
|
|
|
`
|
|
|
|
|
|
|
|
var testScript3 = `
|
|
|
|
ledis.call("set", 1, "a")
|
|
|
|
|
|
|
|
local a = ledis.call("get", 1)
|
|
|
|
if type(a) ~= "string" then
|
|
|
|
error("must string")
|
|
|
|
elseif a ~= "a" then
|
|
|
|
error("must a")
|
|
|
|
end
|
|
|
|
`
|
|
|
|
|
|
|
|
var testScript4 = `
|
|
|
|
ledis.call("select", 2)
|
|
|
|
ledis.call("set", 2, "b")
|
|
|
|
`
|
|
|
|
|
2016-01-21 14:46:44 +03:00
|
|
|
var testScript5 = `
|
|
|
|
return ledis.call("PING")
|
|
|
|
`
|
|
|
|
|
2016-01-21 20:48:19 +03:00
|
|
|
var testScript6 = `
|
|
|
|
ledis.call('hmset', 'zzz', 1, 2, 5, 42)
|
|
|
|
local a = ledis.call('hmget', 'zzz', 1, 2, 5, 42)
|
|
|
|
for i = 1, 5 do
|
|
|
|
a[i] = type(a[i])
|
|
|
|
end
|
|
|
|
return a
|
|
|
|
`
|
|
|
|
|
2017-04-15 16:51:03 +03:00
|
|
|
var testScript7 = `
|
|
|
|
redis.call('HSET', 'carlos', 1, 1)
|
|
|
|
redis.call('HSET', 'carlos', 2, 2)
|
|
|
|
redis.call('HSET', 'carlos', 3, 3)
|
|
|
|
redis.call('HSET', 'carlos', 9, 36)
|
|
|
|
|
|
|
|
local sum = 0
|
|
|
|
local matches = redis.call('HKEYS', 'carlos')
|
|
|
|
|
|
|
|
for _,key in ipairs(matches) do
|
|
|
|
local val = redis.call('HGET', 'carlos', key)
|
|
|
|
sum = sum + tonumber(val)
|
|
|
|
end
|
|
|
|
|
|
|
|
return sum
|
|
|
|
`
|
|
|
|
|
|
|
|
var testScript8 = `
|
|
|
|
local raw = cjson.encode({a=9, b=11, c=20, d=2})
|
|
|
|
local obj = cjson.decode(raw)
|
|
|
|
local sum = 0
|
|
|
|
|
|
|
|
for _,val in pairs(obj) do
|
|
|
|
sum = sum + val
|
|
|
|
end
|
|
|
|
|
|
|
|
if cjson.decode("True") then
|
|
|
|
sum = sum / 2
|
|
|
|
end
|
|
|
|
|
|
|
|
if cjson.encode(cjson.encode("foo")) == "foo" then
|
|
|
|
sum = sum - 2
|
|
|
|
end
|
|
|
|
|
|
|
|
local arr = cjson.decode("[1,2,5,5,10]")
|
|
|
|
for _,val in ipairs(obj) do
|
|
|
|
sum = sum + val
|
|
|
|
end
|
|
|
|
|
|
|
|
return sum
|
|
|
|
`
|
|
|
|
|
2014-09-02 13:55:12 +04:00
|
|
|
func TestLuaCall(t *testing.T) {
|
2014-10-11 12:00:59 +04:00
|
|
|
cfg := config.NewConfigDefault()
|
2014-09-02 13:55:12 +04:00
|
|
|
cfg.Addr = ":11188"
|
|
|
|
cfg.DataDir = "/tmp/testscript"
|
|
|
|
cfg.DBName = "memory"
|
|
|
|
|
|
|
|
app, e := NewApp(cfg)
|
|
|
|
if e != nil {
|
|
|
|
t.Fatal(e)
|
|
|
|
}
|
|
|
|
go app.Run()
|
|
|
|
|
|
|
|
defer app.Close()
|
|
|
|
|
|
|
|
db, _ := app.ldb.Select(0)
|
|
|
|
|
2015-03-14 04:10:00 +03:00
|
|
|
luaClient := app.script.c
|
|
|
|
luaClient.db = db
|
2014-09-02 13:55:12 +04:00
|
|
|
|
2015-03-14 04:10:00 +03:00
|
|
|
l := app.script.l
|
2014-09-02 13:55:12 +04:00
|
|
|
|
2015-03-14 04:10:00 +03:00
|
|
|
err := app.script.l.DoString(testScript1)
|
2014-09-02 13:55:12 +04:00
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
v := luaReplyToLedisReply(l)
|
|
|
|
if vv, ok := v.([]interface{}); ok {
|
|
|
|
if len(vv) != 3 {
|
|
|
|
t.Fatal(len(vv))
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
t.Fatal(fmt.Sprintf("%v %T", v, v))
|
|
|
|
}
|
|
|
|
|
2015-03-14 04:10:00 +03:00
|
|
|
err = app.script.l.DoString(testScript2)
|
2014-09-02 13:55:12 +04:00
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
v = luaReplyToLedisReply(l)
|
2017-04-15 16:51:03 +03:00
|
|
|
if vv, ok := v.(string); !ok || vv != "PONG" {
|
2014-09-02 13:55:12 +04:00
|
|
|
t.Fatal(fmt.Sprintf("%v %T", v, v))
|
|
|
|
}
|
|
|
|
|
2015-03-14 04:10:00 +03:00
|
|
|
err = app.script.l.DoString(testScript3)
|
2014-09-02 13:55:12 +04:00
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if v, err := db.Get([]byte("1")); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
} else if string(v) != "a" {
|
|
|
|
t.Fatal(string(v))
|
|
|
|
}
|
|
|
|
|
2015-03-14 04:10:00 +03:00
|
|
|
err = app.script.l.DoString(testScript4)
|
2014-09-02 13:55:12 +04:00
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if luaClient.db.Index() != 2 {
|
|
|
|
t.Fatal(luaClient.db.Index())
|
|
|
|
}
|
|
|
|
|
|
|
|
db2, _ := app.ldb.Select(2)
|
|
|
|
if v, err := db2.Get([]byte("2")); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
} else if string(v) != "b" {
|
|
|
|
t.Fatal(string(v))
|
|
|
|
}
|
|
|
|
|
2016-01-21 14:46:44 +03:00
|
|
|
err = app.script.l.DoString(testScript5)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
v = luaReplyToLedisReply(l)
|
|
|
|
if vv := v.(string); vv != "PONG" {
|
|
|
|
t.Fatal(fmt.Sprintf("%v %T", v, v))
|
|
|
|
}
|
|
|
|
|
2016-01-21 20:48:19 +03:00
|
|
|
err = app.script.l.DoString(testScript6)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
v = luaReplyToLedisReply(l)
|
|
|
|
vv := v.([]interface{})
|
|
|
|
expected := []string{
|
|
|
|
"string",
|
|
|
|
"boolean",
|
|
|
|
"string",
|
|
|
|
"boolean",
|
|
|
|
"nil",
|
|
|
|
}
|
|
|
|
if len(expected) != len(vv) {
|
|
|
|
t.Fatalf("length different: %d, %d", len(expected), len(vv))
|
|
|
|
}
|
|
|
|
for i, r := range vv {
|
2017-04-15 16:51:03 +03:00
|
|
|
s, ok := r.([]byte)
|
|
|
|
if !ok {
|
|
|
|
t.Errorf("reply[%d] expected: %s (%T), actual: %v (%T)",
|
|
|
|
i, expected[i], expected[i], r, r)
|
|
|
|
} else if string(s) != expected[i] {
|
|
|
|
t.Errorf("reply[%d] expected: %s, actual: %v", i, expected[i], string(s))
|
2016-01-21 20:48:19 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-04-15 16:51:03 +03:00
|
|
|
err = app.script.l.DoString(testScript7)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
v = luaReplyToLedisReply(l)
|
|
|
|
if vv := v.(int64); vv != 42 {
|
|
|
|
t.Fatal(fmt.Sprintf("%v %T", v, v))
|
|
|
|
}
|
|
|
|
|
|
|
|
err = app.script.l.DoString(testScript8)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
v = luaReplyToLedisReply(l)
|
|
|
|
if vv := v.(int64); vv != 42 {
|
|
|
|
t.Fatal(fmt.Sprintf("%v %T", v, v))
|
|
|
|
}
|
|
|
|
|
2014-09-02 13:55:12 +04:00
|
|
|
luaClient.db = nil
|
|
|
|
}
|