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  }