diff --git a/go.mod b/go.mod index a334e62..4c92e10 100644 --- a/go.mod +++ b/go.mod @@ -36,4 +36,3 @@ require ( ) go 1.13 - diff --git a/plugins/toolkit/toolkit.go b/plugins/toolkit/toolkit.go index 073c642..2c04710 100644 --- a/plugins/toolkit/toolkit.go +++ b/plugins/toolkit/toolkit.go @@ -2,7 +2,7 @@ package toolkit import ( "encoding/hex" - "fmt" + "encoding/json" "reflect" ) @@ -28,16 +28,12 @@ func (t *ToolKit) RandInt(min, max int) int { // String convert to string func (t *ToolKit) String(input interface{}, offsets ...int) string { - v := reflect.ValueOf(input) switch v.Kind() { case reflect.Ptr: return t.String(v.Elem().Interface(), offsets...) case reflect.Slice: - bs, ok := input.([]byte) - if !ok { - return "" - } + bs := transferToBts(input) l := len(bs) start, end := 0, l if len(offsets) > 0 && offsets[0] <= l { @@ -46,9 +42,9 @@ func (t *ToolKit) String(input interface{}, offsets ...int) string { if len(offsets) > 1 && offsets[1] <= l+1 { start = offsets[1] } - fmt.Println(bs, start, end) return string(bs[start:end]) case reflect.Array: + bs := transferToBts(input) l := v.Type().Len() start, end := 0, l if len(offsets) > 0 && offsets[0] <= l { @@ -59,14 +55,26 @@ func (t *ToolKit) String(input interface{}, offsets ...int) string { } ss := make([]byte, 0, end-start) for i := start; i < end; i++ { - ss = append(ss, v.Index(i).Interface().(byte)) + ss = append(ss, bs[i]) } return string(ss) } - fmt.Println("=====") return "" } +func transferToBts(input interface{}) []byte { + bs, ok := input.([]byte) + if !ok { + bs = []byte{} + jsData, _ := json.Marshal(input) + err := json.Unmarshal(jsData, &bs) + if err != nil { + return []byte{} + } + } + return bs +} + // Hex encode string as hex string func (t *ToolKit) Hex(input string) string { return hex.EncodeToString([]byte(input)) diff --git a/vm/lua/glua/glua_convert.go b/vm/lua/glua/glua_convert.go index 2be6bc4..4cc88e7 100644 --- a/vm/lua/glua/glua_convert.go +++ b/vm/lua/glua/glua_convert.go @@ -2,11 +2,14 @@ package glua import ( "encoding/json" + "fmt" fcom "github.com/meshplus/hyperbench-common/common" "github.com/mitchellh/mapstructure" "github.com/pkg/errors" "github.com/yuin/gopher-lua" + "math/big" "reflect" + "strconv" ) //Go2Lua convert go interface val to lua.LValue value and reutrn @@ -100,12 +103,27 @@ func Lua2Go(value lua.LValue) (interface{}, error) { func go2Lua(L *lua.LState, value interface{}) lua.LValue { // check value is struct for Implementation lua.table luaValue, ok := go2luaStruct(L, value) + if ok { return luaValue } + value = parseValueToSupportData(value) switch converted := value.(type) { case bool: return lua.LBool(converted) + case big.Int: + + fret, err := strconv.ParseFloat(converted.String(), 64) + if err != nil { + panic(err) + } + return lua.LNumber(fret) + case uint, uint8, uint16, uint32, uint64, int, int8, int16, int32, int64: + fret, err := strconv.ParseFloat(fmt.Sprint(converted), 64) + if err != nil { + panic(err) + } + return lua.LNumber(fret) case float64: return lua.LNumber(converted) case string: @@ -124,8 +142,32 @@ func go2Lua(L *lua.LState, value interface{}) lua.LValue { return tbl case nil: return lua.LNil + default: + panic("unreachable") + } + +} + +func parseValueToSupportData(value interface{}) interface{} { + + switch reflect.TypeOf(value).Kind() { + case reflect.Slice, reflect.Array: + dataValue := reflect.ValueOf(value) // value + var sliceRet []interface{} + for i := 0; i < dataValue.Len(); i++ { + sliceRet = append(sliceRet, parseValueToSupportData(dataValue.Index(i).Interface())) + } + return sliceRet + case reflect.Struct: + return value + case reflect.Map: + return value + case reflect.Ptr: + dataValue := reflect.ValueOf(value) // value + return parseValueToSupportData(dataValue.Elem().Interface()) + default: + return value } - panic("unreachable") } // go2luaStruct convert struct for Implementation lua.table to lua.Table @@ -138,11 +180,6 @@ func go2luaStruct(L *lua.LState, value interface{}) (lua.LValue, bool) { } } -// function run() -// local i = 0 -// print("----coro-----") -// return i -// end func runLuaRunFunc(state *lua.LState, script string) (lua.LValue, error) { //exec lua run func err := state.DoString(script) diff --git a/vm/lua/glua/index.go b/vm/lua/glua/index.go index 7ed82e0..ebd453a 100644 --- a/vm/lua/glua/index.go +++ b/vm/lua/glua/index.go @@ -1,15 +1,102 @@ package glua import ( + "fmt" idex "github.com/meshplus/hyperbench/plugins/index" lua "github.com/yuin/gopher-lua" + "strings" ) +const ( + Index = "index" + + //field + + Worker = "worker" + VM = "vm" + Engine = "engine" + Tx = "tx" + + index = "__index" + newIndex = "__newindex" + toString = "__tostring" + eq = "__eq" +) + +func registerIndex(L *lua.LState) lua.LValue { + IndexTable := L.NewTypeMetatable(Index) + L.SetGlobal(Index, IndexTable) + L.SetField(IndexTable, index, L.NewFunction(func(L *lua.LState) int { + index := checkIndex(L, 1) + invokeName := L.CheckString(2) + switch strings.ToLower(invokeName) { + case Worker: + L.Push(lua.LNumber(index.Worker)) + return 1 + case VM: + L.Push(lua.LNumber(index.VM)) + return 1 + case Engine: + L.Push(lua.LNumber(index.Engine)) + return 1 + case Tx: + L.Push(lua.LNumber(index.Tx)) + return 1 + } + L.Push(lua.LNil) + return 1 + })) + L.SetField(IndexTable, newIndex, L.NewFunction(func(L *lua.LState) int { + index := checkIndex(L, 1) + switch strings.ToLower(L.CheckString(2)) { + case Worker: + index.Worker = L.CheckInt64(3) + return 0 + case VM: + index.VM = L.CheckInt64(3) + return 0 + case Engine: + index.Engine = L.CheckInt64(3) + return 0 + case Tx: + index.Tx = L.CheckInt64(3) + return 0 + } + return 0 + })) + L.SetField(IndexTable, toString, L.NewFunction(func(L *lua.LState) int { + result := checkIndex(L, 1) + L.Push(lua.LString(fmt.Sprintf("%v", result))) + return 1 + })) + L.SetField(IndexTable, eq, L.NewFunction(func(L *lua.LState) int { + r1 := checkIndex(L, 1) + r2 := checkIndex(L, 2) + L.Push(lua.LBool(fmt.Sprintf("%v", r1) == fmt.Sprintf("%v", r2))) + return 1 + })) + return IndexTable +} + func newIdexIndex(L *lua.LState, idx *idex.Index) lua.LValue { - idxTable := L.NewTable() - idxTable.RawSetString("Worker", lua.LNumber(idx.Worker)) - idxTable.RawSetString("VM", lua.LNumber(idx.VM)) - idxTable.RawSetString("Engine", lua.LNumber(idx.Engine)) - idxTable.RawSetString("Tx", lua.LNumber(idx.Tx)) - return idxTable + + metatable := L.GetTypeMetatable(Index) + if metatable == nil || metatable == lua.LNil { + metatable = registerIndex(L) + } + ud := L.NewUserData() + ud.Value = idx + ud.Metatable = metatable + return ud + +} + +func checkIndex(L *lua.LState, n int) *idex.Index { + ud := L.CheckUserData(n) + if v, ok := ud.Value.(*idex.Index); ok { + return v + } + L.ArgError(1, "Index expected") + return nil + } diff --git a/vm/lua/glua/index_test.go b/vm/lua/glua/index_test.go index 68763ee..ff63aa3 100644 --- a/vm/lua/glua/index_test.go +++ b/vm/lua/glua/index_test.go @@ -1,7 +1,7 @@ package glua import ( - "github.com/meshplus/hyperbench/plugins/index" + idex "github.com/meshplus/hyperbench/plugins/index" "github.com/stretchr/testify/assert" lua "github.com/yuin/gopher-lua" "testing" @@ -12,12 +12,14 @@ func Test_index(t *testing.T) { defer L.Close() mt := L.NewTypeMetatable("case") L.SetGlobal("case", mt) - passIdx := &index.Index{1, 1, 1, 1} + passIdx := &idex.Index{1, 1, 1, 1} cLua := newIdexIndex(L, passIdx) + passIdx.Tx = 2 L.SetField(mt, "index", cLua) scripts := []string{` function run() + print("tx:",case.index.Tx) case.index.Worker=2 case.index.VM=2 case.index.Engine=2 @@ -28,10 +30,12 @@ func Test_index(t *testing.T) { for _, script := range scripts { lvalue, err := runLuaRunFunc(L, script) assert.Nil(t, err) - idx := &index.Index{} - err = TableLua2GoStruct(lvalue.(*lua.LTable), idx) + idx := &idex.Index{} + l1, err := Lua2Go(lvalue) + idx, ok := l1.(*idex.Index) + assert.True(t, ok) assert.Nil(t, err) - assert.Equal(t, idx, &index.Index{Worker: 2, VM: 2, Engine: 2, Tx: 2}) + assert.Equal(t, idx, &idex.Index{Worker: 2, VM: 2, Engine: 2, Tx: 2}) } } diff --git a/vm/lua/glua/toolKit.go b/vm/lua/glua/toolKit.go index 20e97ba..3978c40 100644 --- a/vm/lua/glua/toolKit.go +++ b/vm/lua/glua/toolKit.go @@ -7,7 +7,12 @@ import ( func hexLuaFunction(L *lua.LState, kit *toolkit.ToolKit) *lua.LFunction { return L.NewFunction(func(state *lua.LState) int { - input := state.CheckString(1) + firstArgIdx := 1 + if checkToolKitByIdx(state, 1) { + firstArgIdx++ + } + + input := state.CheckString(firstArgIdx) ret := kit.Hex(input) state.Push(lua.LString(ret)) return 1 @@ -16,7 +21,11 @@ func hexLuaFunction(L *lua.LState, kit *toolkit.ToolKit) *lua.LFunction { func randStrLuaFunction(L *lua.LState, kit *toolkit.ToolKit) *lua.LFunction { return L.NewFunction(func(state *lua.LState) int { - size := state.CheckInt(1) + firstArgIdx := 1 + if checkToolKitByIdx(state, 1) { + firstArgIdx++ + } + size := state.CheckInt(firstArgIdx) ret := kit.RandStr(uint(size)) L.Push(lua.LString(ret)) return 1 @@ -25,8 +34,12 @@ func randStrLuaFunction(L *lua.LState, kit *toolkit.ToolKit) *lua.LFunction { func randIntLuaFunction(L *lua.LState, kit *toolkit.ToolKit) *lua.LFunction { return L.NewFunction(func(state *lua.LState) int { - min := state.CheckInt(1) - max := state.CheckInt(2) + firstArgIdx := 1 + if checkToolKitByIdx(state, 1) { + firstArgIdx++ + } + min := state.CheckInt(firstArgIdx) + max := state.CheckInt(firstArgIdx + 1) ret := kit.RandInt(min, max) L.Push(lua.LNumber(ret)) return 1 @@ -35,22 +48,31 @@ func randIntLuaFunction(L *lua.LState, kit *toolkit.ToolKit) *lua.LFunction { func stringLuaFunction(L *lua.LState, kit *toolkit.ToolKit) *lua.LFunction { return L.NewFunction(func(state *lua.LState) int { + firstArgIdx := 1 + if checkToolKitByIdx(state, 1) { + firstArgIdx++ + } + argLength := state.GetTop() if argLength < 1 { panic("args are less than 1") } - input := state.CheckAny(1) - if argLength == 1 { - ret := kit.String(input) + input := state.CheckAny(firstArgIdx) + inputGo, err := Lua2Go(input) + if err != nil { + panic(err.Error()) + } + if argLength == firstArgIdx { + ret := kit.String(inputGo) L.Push(lua.LString(ret)) return 1 } var offsets []int - for i := 2; i < argLength; i++ { + for i := firstArgIdx + 1; i < argLength; i++ { offset := state.CheckInt(i) offsets = append(offsets, offset) } - ret := kit.String(input, offsets...) + ret := kit.String(inputGo, offsets...) L.Push(lua.LString(ret)) return 1 }) @@ -64,3 +86,15 @@ func newToolKit(L *lua.LState, kit *toolkit.ToolKit) lua.LValue { toolkitTable.RawSetString("String", stringLuaFunction(L, kit)) return toolkitTable } + +func checkToolKitByIdx(state *lua.LState, idx int) bool { + if state.GetTop() < idx { + return false + } + idxValue := state.CheckAny(idx) + _, ok := idxValue.(*lua.LTable) + if !ok { + return false + } + return true +} diff --git a/vm/lua/glua/toolKit_test.go b/vm/lua/glua/toolKit_test.go index 2fad626..2cdfd7a 100644 --- a/vm/lua/glua/toolKit_test.go +++ b/vm/lua/glua/toolKit_test.go @@ -21,6 +21,11 @@ func Test_toolKit(t *testing.T) { function run() return case.toolkit.RandStr(10) end + `, + ` + function run() + return case.toolkit:RandStr(10) + end `, } for _, script := range scripts { @@ -37,6 +42,11 @@ func Test_toolKit(t *testing.T) { function run() return case.toolkit.RandInt(50,51) end + `, + ` + function run() + return case.toolkit:RandInt(50,51) + end `, } for _, script := range scripts { @@ -53,6 +63,11 @@ func Test_toolKit(t *testing.T) { function run() return case.toolkit.Hex("aaaaaa") end + `, + ` + function run() + return case.toolkit:Hex("aaaaaa") + end `, } for _, script := range scripts { @@ -76,6 +91,17 @@ func Test_toolKit(t *testing.T) { function run() return case.toolkit.String("aaaaaa") end + `, + + ` + function run() + return case.toolkit:String("aaaaaa",1,2) + end + `, + ` + function run() + return case.toolkit:String("aaaaaa") + end `, } for _, script := range scripts {