github.com/hootrhino/gopher-lua@v1.0.3/script_test.go (about) 1 package lua 2 3 import ( 4 "fmt" 5 "os" 6 "runtime" 7 "sync/atomic" 8 "testing" 9 "time" 10 11 "github.com/hootrhino/gopher-lua/parse" 12 ) 13 14 const maxMemory = 40 15 16 var gluaTests []string = []string{ 17 "base.lua", 18 "coroutine.lua", 19 "db.lua", 20 "issues.lua", 21 "os.lua", 22 "table.lua", 23 "vm.lua", 24 "math.lua", 25 "strings.lua", 26 "goto.lua", 27 } 28 29 var luaTests []string = []string{ 30 "attrib.lua", 31 "calls.lua", 32 "closure.lua", 33 "constructs.lua", 34 "events.lua", 35 "literals.lua", 36 "locals.lua", 37 "math.lua", 38 "sort.lua", 39 "strings.lua", 40 "vararg.lua", 41 "pm.lua", 42 "files.lua", 43 } 44 45 func testScriptCompile(t *testing.T, script string) { 46 file, err := os.Open(script) 47 if err != nil { 48 t.Fatal(err) 49 return 50 } 51 chunk, err2 := parse.Parse(file, script) 52 if err2 != nil { 53 t.Fatal(err2) 54 return 55 } 56 parse.Dump(chunk) 57 proto, err3 := Compile(chunk, script) 58 if err3 != nil { 59 t.Fatal(err3) 60 return 61 } 62 nop := func(s string) {} 63 nop(proto.String()) 64 } 65 66 func testScriptDir(t *testing.T, tests []string, directory string) { 67 if err := os.Chdir(directory); err != nil { 68 t.Error(err) 69 } 70 defer os.Chdir("..") 71 for _, script := range tests { 72 fmt.Printf("testing %s/%s\n", directory, script) 73 testScriptCompile(t, script) 74 L := NewState(Options{ 75 RegistrySize: 1024 * 20, 76 CallStackSize: 1024, 77 IncludeGoStackTrace: true, 78 }) 79 L.SetMx(maxMemory) 80 if err := L.DoFile(script); err != nil { 81 t.Error(err) 82 } 83 L.Close() 84 } 85 } 86 87 var numActiveUserDatas int32 = 0 88 89 type finalizerStub struct{ x byte } 90 91 func allocFinalizerUserData(L *LState) int { 92 ud := L.NewUserData() 93 atomic.AddInt32(&numActiveUserDatas, 1) 94 a := finalizerStub{} 95 ud.Value = &a 96 runtime.SetFinalizer(&a, func(aa *finalizerStub) { 97 atomic.AddInt32(&numActiveUserDatas, -1) 98 }) 99 L.Push(ud) 100 return 1 101 } 102 103 func sleep(L *LState) int { 104 time.Sleep(time.Duration(L.CheckInt(1)) * time.Millisecond) 105 return 0 106 } 107 108 func countFinalizers(L *LState) int { 109 L.Push(LNumber(numActiveUserDatas)) 110 return 1 111 } 112 113 // TestLocalVarFree verifies that tables and user user datas which are no longer referenced by the lua script are 114 // correctly gc-ed. There was a bug in gopher lua where local vars were not being gc-ed in all circumstances. 115 func TestLocalVarFree(t *testing.T) { 116 s := ` 117 function Test(a, b, c) 118 local a = { v = allocFinalizer() } 119 local b = { v = allocFinalizer() } 120 return a 121 end 122 Test(1,2,3) 123 for i = 1, 100 do 124 collectgarbage() 125 if countFinalizers() == 0 then 126 return 127 end 128 sleep(100) 129 end 130 error("user datas not finalized after 100 gcs") 131 ` 132 L := NewState() 133 L.SetGlobal("allocFinalizer", L.NewFunction(allocFinalizerUserData)) 134 L.SetGlobal("sleep", L.NewFunction(sleep)) 135 L.SetGlobal("countFinalizers", L.NewFunction(countFinalizers)) 136 defer L.Close() 137 if err := L.DoString(s); err != nil { 138 t.Error(err) 139 } 140 } 141 142 func TestGlua(t *testing.T) { 143 testScriptDir(t, gluaTests, "_glua-tests") 144 } 145 146 func TestLua(t *testing.T) { 147 testScriptDir(t, luaTests, "_lua5.1-tests") 148 }