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