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