github.com/awirix/lua@v1.6.0/script_test.go (about)

     1  package lua
     2  
     3  import (
     4  	"fmt"
     5  	"github.com/awirix/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(nil)
    73  		L.SetMx(maxMemory)
    74  		if err := L.DoFile(script); err != nil {
    75  			t.Error(err)
    76  		}
    77  		L.Close()
    78  	}
    79  }
    80  
    81  var numActiveUserDatas int32 = 0
    82  
    83  type finalizerStub struct{ x byte }
    84  
    85  func allocFinalizerUserData(L *LState) int {
    86  	ud := L.NewUserData()
    87  	atomic.AddInt32(&numActiveUserDatas, 1)
    88  	a := finalizerStub{}
    89  	ud.Value = &a
    90  	runtime.SetFinalizer(&a, func(aa *finalizerStub) {
    91  		atomic.AddInt32(&numActiveUserDatas, -1)
    92  	})
    93  	L.Push(ud)
    94  	return 1
    95  }
    96  
    97  func sleep(L *LState) int {
    98  	time.Sleep(time.Duration(L.CheckInt(1)) * time.Millisecond)
    99  	return 0
   100  }
   101  
   102  func countFinalizers(L *LState) int {
   103  	L.Push(LNumber(numActiveUserDatas))
   104  	return 1
   105  }
   106  
   107  // TestLocalVarFree verifies that tables and user user datas which are no longer referenced by the lua script are
   108  // correctly gc-ed. There was a bug in gopher lua where local vars were not being gc-ed in all circumstances.
   109  func TestLocalVarFree(t *testing.T) {
   110  	s := `
   111  		function Test(a, b, c)
   112  			local a = { v = allocFinalizer() }
   113  			local b = { v = allocFinalizer() }
   114  			return a
   115  		end
   116  		Test(1,2,3)
   117  		for i = 1, 100 do
   118  			collectgarbage()
   119  			if countFinalizers() == 0 then
   120  				return
   121  			end
   122  			sleep(100)
   123  		end
   124  		error("user datas not finalized after 100 gcs")
   125  `
   126  	L := NewState(nil)
   127  	L.SetGlobal("allocFinalizer", L.NewFunction(allocFinalizerUserData))
   128  	L.SetGlobal("sleep", L.NewFunction(sleep))
   129  	L.SetGlobal("countFinalizers", L.NewFunction(countFinalizers))
   130  	defer L.Close()
   131  	if err := L.DoString(s); err != nil {
   132  		t.Error(err)
   133  	}
   134  }
   135  
   136  func TestGlua(t *testing.T) {
   137  	testScriptDir(t, gluaTests, "_glua-tests")
   138  }
   139  
   140  func TestLua(t *testing.T) {
   141  	testScriptDir(t, luaTests, "_lua5.1-tests")
   142  }