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