github.com/assemblaj/gopher-lua@v0.0.0-20221116224352-d57295a0d9e8/clone_test.go (about)

     1  package lua
     2  
     3  /*
     4     Broadly speaking, these tests are the regular tests, but instead swapping a clone in after performing
     5     certain functions and seeing if they return the same result
     6  */
     7  
     8  import (
     9  	"fmt"
    10  	"os"
    11  	"strings"
    12  	"testing"
    13  )
    14  
    15  func testScriptDirClone(t *testing.T, tests []string, directory string) {
    16  	if err := os.Chdir(directory); err != nil {
    17  		t.Error(err)
    18  	}
    19  	defer os.Chdir("..")
    20  	for _, script := range tests {
    21  		fmt.Printf("testing %s/%s\n", directory, script)
    22  		testScriptCompile(t, script)
    23  		L := NewState(Options{
    24  			RegistrySize:        1024 * 20,
    25  			CallStackSize:       1024,
    26  			IncludeGoStackTrace: true,
    27  		})
    28  		L.SetMx(maxMemory)
    29  		snapshot := SaveSnapshot(L)
    30  		C := LoadSnapshot(snapshot)
    31  
    32  		fmt.Printf("L %v \n : C: %v\n", L, C)
    33  		if err := C.DoFile(script); err != nil {
    34  			t.Error(err)
    35  		}
    36  		C.Close()
    37  	}
    38  }
    39  
    40  // func TestClonedLStateIsClosed(t *testing.T) {
    41  // 	L := NewState()
    42  // 	L.Close()
    43  // 	C := L.Clone().(*LState)
    44  // 	errorIfNotEqual(t, true, C.IsClosed())
    45  // }
    46  
    47  func TestClonedCallStackOverflowWhenFixed(t *testing.T) {
    48  	L := NewState(Options{
    49  		CallStackSize: 3,
    50  	})
    51  	defer L.Close()
    52  
    53  	C := L.Clone().(*LState)
    54  	defer C.Close()
    55  
    56  	// expect fixed stack implementation by default (for backwards compatibility)
    57  	stack := C.stack
    58  	if _, ok := stack.(*fixedCallFrameStack); !ok {
    59  		t.Errorf("expected fixed callframe stack by default")
    60  	}
    61  
    62  	errorIfScriptNotFail(t, C, `
    63      local function recurse(count)
    64        if count > 0 then
    65          recurse(count - 1)
    66        end
    67      end
    68      local function c()
    69        print(_printregs())
    70        recurse(9)
    71      end
    72      c()
    73      `, "stack overflow")
    74  }
    75  
    76  func TesClonetGetAndReplace(t *testing.T) {
    77  	L := NewState()
    78  	defer L.Close()
    79  	L.Push(LString("a"))
    80  	L.Replace(1, LString("b"))
    81  	L.Replace(0, LString("c"))
    82  	C1 := L.Clone().(*LState)
    83  	defer C1.Close()
    84  
    85  	errorIfNotEqual(t, LNil, C1.Get(0))
    86  	errorIfNotEqual(t, LNil, C1.Get(-10))
    87  	errorIfNotEqual(t, C1.Env, C1.Get(EnvironIndex))
    88  	errorIfNotEqual(t, LString("b"), C1.Get(1))
    89  
    90  	L.Push(LString("c"))
    91  	L.Push(LString("d"))
    92  	L.Replace(-2, LString("e"))
    93  	C2 := L.Clone().(*LState)
    94  	defer C2.Close()
    95  
    96  	errorIfNotEqual(t, LString("e"), C2.Get(-2))
    97  
    98  	registry := L.NewTable()
    99  	L.Replace(RegistryIndex, registry)
   100  	L.G.Registry = registry
   101  	errorIfGFuncNotFail(t, L, func(L *LState) int {
   102  		L.Replace(RegistryIndex, LNil)
   103  		return 0
   104  	}, "registry must be a table")
   105  	errorIfGFuncFail(t, L, func(L *LState) int {
   106  		env := L.NewTable()
   107  		L.Replace(EnvironIndex, env)
   108  		errorIfNotEqual(t, env, L.Get(EnvironIndex))
   109  		return 0
   110  	})
   111  	errorIfGFuncNotFail(t, L, func(L *LState) int {
   112  		L.Replace(EnvironIndex, LNil)
   113  		return 0
   114  	}, "environment must be a table")
   115  	errorIfGFuncFail(t, L, func(L *LState) int {
   116  		gbl := L.NewTable()
   117  		L.Replace(GlobalsIndex, gbl)
   118  		errorIfNotEqual(t, gbl, L.G.Global)
   119  		return 0
   120  	})
   121  	errorIfGFuncNotFail(t, L, func(L *LState) int {
   122  		L.Replace(GlobalsIndex, LNil)
   123  		return 0
   124  	}, "_G must be a table")
   125  
   126  	L2 := NewState()
   127  	defer L2.Close()
   128  	clo := L2.NewClosure(func(L2 *LState) int {
   129  		L2.Replace(UpvalueIndex(1), LNumber(3))
   130  		errorIfNotEqual(t, LNumber(3), L2.Get(UpvalueIndex(1)))
   131  		return 0
   132  	}, LNumber(1), LNumber(2))
   133  	L2.SetGlobal("clo", clo)
   134  	errorIfScriptFail(t, L2, `clo()`)
   135  }
   136  
   137  // func TestCloneRemove(t *testing.T) {
   138  // 	L := NewState()
   139  // 	defer L.Close()
   140  // 	L.Push(LString("a"))
   141  // 	L.Push(LString("b"))
   142  // 	L.Push(LString("c"))
   143  
   144  // 	L.Remove(4)
   145  // 	C1 := L.Clone().(*LState)
   146  // 	defer C1.Close()
   147  
   148  // 	errorIfNotEqual(t, LString("a"), C1.Get(1))
   149  // 	errorIfNotEqual(t, LString("b"), C1.Get(2))
   150  // 	errorIfNotEqual(t, LString("c"), C1.Get(3))
   151  // 	errorIfNotEqual(t, 3, C1.GetTop())
   152  
   153  // 	L.Remove(3)
   154  // 	C2 := L.Clone().(*LState)
   155  // 	defer C2.Close()
   156  
   157  // 	errorIfNotEqual(t, LString("a"), C2.Get(1))
   158  // 	errorIfNotEqual(t, LString("b"), C2.Get(2))
   159  // 	errorIfNotEqual(t, LNil, C2.Get(3))
   160  // 	errorIfNotEqual(t, 2, C2.GetTop())
   161  // 	L.Push(LString("c"))
   162  
   163  // 	L.Remove(-10)
   164  
   165  // 	C3 := L.Clone().(*LState)
   166  // 	defer C3.Close()
   167  
   168  // 	errorIfNotEqual(t, LString("a"), C3.Get(1))
   169  // 	errorIfNotEqual(t, LString("b"), C3.Get(2))
   170  // 	errorIfNotEqual(t, LString("c"), C3.Get(3))
   171  // 	errorIfNotEqual(t, 3, C3.GetTop())
   172  
   173  // 	L.Remove(2)
   174  
   175  // 	C4 := L.Clone().(*LState)
   176  // 	defer C4.Close()
   177  
   178  // 	errorIfNotEqual(t, LString("a"), C4.Get(1))
   179  // 	errorIfNotEqual(t, LString("c"), C4.Get(2))
   180  // 	errorIfNotEqual(t, LNil, C4.Get(3))
   181  // 	errorIfNotEqual(t, 2, C4.GetTop())
   182  // }
   183  
   184  func TestCloneToInt(t *testing.T) {
   185  	L := NewState()
   186  	defer L.Close()
   187  	L.Push(LNumber(10))
   188  	L.Push(LString("99.9"))
   189  	L.Push(L.NewTable())
   190  	C := L.Clone().(*LState)
   191  	defer C.Close()
   192  
   193  	errorIfNotEqual(t, 10, C.ToInt(1))
   194  	errorIfNotEqual(t, 99, C.ToInt(2))
   195  	errorIfNotEqual(t, 0, C.ToInt(3))
   196  }
   197  
   198  func TestCloneToInt64(t *testing.T) {
   199  	L := NewState()
   200  	defer L.Close()
   201  	L.Push(LNumber(10))
   202  	L.Push(LString("99.9"))
   203  	L.Push(L.NewTable())
   204  	C := L.Clone().(*LState)
   205  	defer C.Close()
   206  
   207  	errorIfNotEqual(t, int64(10), C.ToInt64(1))
   208  	errorIfNotEqual(t, int64(99), C.ToInt64(2))
   209  	errorIfNotEqual(t, int64(0), C.ToInt64(3))
   210  }
   211  
   212  func TestCloneoNumber(t *testing.T) {
   213  	L := NewState()
   214  	defer L.Close()
   215  	L.Push(LNumber(10))
   216  	L.Push(LString("99.9"))
   217  	L.Push(L.NewTable())
   218  	C := L.Clone().(*LState)
   219  	defer C.Close()
   220  
   221  	errorIfNotEqual(t, LNumber(10), C.ToNumber(1))
   222  	errorIfNotEqual(t, LNumber(99.9), C.ToNumber(2))
   223  	errorIfNotEqual(t, LNumber(0), C.ToNumber(3))
   224  }
   225  
   226  func TestCloneToString(t *testing.T) {
   227  	L := NewState()
   228  	defer L.Close()
   229  	L.Push(LNumber(10))
   230  	L.Push(LString("99.9"))
   231  	L.Push(L.NewTable())
   232  	C := L.Clone().(*LState)
   233  	defer C.Close()
   234  
   235  	errorIfNotEqual(t, "10", C.ToString(1))
   236  	errorIfNotEqual(t, "99.9", C.ToString(2))
   237  	errorIfNotEqual(t, "", C.ToString(3))
   238  }
   239  
   240  func TestCloneToTable(t *testing.T) {
   241  	L := NewState()
   242  	defer L.Close()
   243  	L.Push(LNumber(10))
   244  	L.Push(LString("99.9"))
   245  	L.Push(L.NewTable())
   246  	C := L.Clone().(*LState)
   247  	defer C.Close()
   248  
   249  	errorIfFalse(t, C.ToTable(1) == nil, "index 1 must be nil")
   250  	errorIfFalse(t, C.ToTable(2) == nil, "index 2 must be nil")
   251  	errorIfNotEqual(t, C.Get(3), C.ToTable(3))
   252  }
   253  
   254  func TestCloneToFunction(t *testing.T) {
   255  	L := NewState()
   256  	defer L.Close()
   257  	L.Push(LNumber(10))
   258  	L.Push(LString("99.9"))
   259  	L.Push(L.NewFunction(func(L *LState) int { return 0 }))
   260  	C := L.Clone().(*LState)
   261  	defer C.Close()
   262  
   263  	errorIfFalse(t, C.ToFunction(1) == nil, "index 1 must be nil")
   264  	errorIfFalse(t, C.ToFunction(2) == nil, "index 2 must be nil")
   265  	errorIfNotEqual(t, C.Get(3), C.ToFunction(3))
   266  }
   267  
   268  func TestCloneToUserData(t *testing.T) {
   269  	L := NewState()
   270  	defer L.Close()
   271  	L.Push(LNumber(10))
   272  	L.Push(LString("99.9"))
   273  	L.Push(L.NewUserData())
   274  	C := L.Clone().(*LState)
   275  	defer C.Close()
   276  
   277  	errorIfFalse(t, C.ToUserData(1) == nil, "index 1 must be nil")
   278  	errorIfFalse(t, C.ToUserData(2) == nil, "index 2 must be nil")
   279  	errorIfNotEqual(t, C.Get(3), C.ToUserData(3))
   280  }
   281  
   282  func TestCloneToChannel(t *testing.T) {
   283  	L := NewState()
   284  	defer L.Close()
   285  	L.Push(LNumber(10))
   286  	L.Push(LString("99.9"))
   287  	var ch chan LValue
   288  	L.Push(LChannel(ch))
   289  	C := L.Clone().(*LState)
   290  	defer C.Close()
   291  
   292  	errorIfFalse(t, C.ToChannel(1) == nil, "index 1 must be nil")
   293  	errorIfFalse(t, C.ToChannel(2) == nil, "index 2 must be nil")
   294  	errorIfNotEqual(t, ch, C.ToChannel(3))
   295  }
   296  
   297  func TestClonePCall(t *testing.T) {
   298  	L := NewState()
   299  	defer L.Close()
   300  	L.Register("f1", func(L *LState) int {
   301  		panic("panic!")
   302  		return 0
   303  	})
   304  	C1 := L.Clone().(*LState)
   305  	defer C1.Close()
   306  
   307  	// Normal
   308  	errorIfScriptNotFail(t, L, `f1()`, "panic!")
   309  	L.Push(L.GetGlobal("f1"))
   310  	err := L.PCall(0, 0, L.NewFunction(func(L *LState) int {
   311  		L.Push(LString("by handler"))
   312  		return 1
   313  	}))
   314  	errorIfFalse(t, strings.Contains(err.Error(), "by handler"), "")
   315  
   316  	// Clone
   317  	errorIfScriptNotFail(t, C1, `f1()`, "panic!")
   318  	C1.Push(C1.GetGlobal("f1"))
   319  	cloneErr := C1.PCall(0, 0, C1.NewFunction(func(L *LState) int {
   320  		C1.Push(LString("by handler"))
   321  		return 1
   322  	}))
   323  	errorIfFalse(t, strings.Contains(cloneErr.Error(), "by handler"), "")
   324  
   325  	C2 := L.Clone().(*LState)
   326  	defer C2.Close()
   327  
   328  	// Normal
   329  	err = L.PCall(0, 0, L.NewFunction(func(L *LState) int {
   330  		L.RaiseError("error!")
   331  		return 1
   332  	}))
   333  	errorIfFalse(t, strings.Contains(err.Error(), "error!"), "")
   334  
   335  	err = L.PCall(0, 0, L.NewFunction(func(L *LState) int {
   336  		panic("panicc!")
   337  		return 1
   338  	}))
   339  	errorIfFalse(t, strings.Contains(err.Error(), "panicc!"), "")
   340  
   341  	// Clone
   342  	cloneErr = C2.PCall(0, 0, C2.NewFunction(func(L *LState) int {
   343  		C2.RaiseError("error!")
   344  		return 1
   345  	}))
   346  	errorIfFalse(t, strings.Contains(cloneErr.Error(), "error!"), "")
   347  
   348  	cloneErr = C2.PCall(0, 0, C2.NewFunction(func(L *LState) int {
   349  		panic("panicc!")
   350  		return 1
   351  	}))
   352  	errorIfFalse(t, strings.Contains(cloneErr.Error(), "panicc!"), "")
   353  
   354  }
   355  func TestGluaClone(t *testing.T) {
   356  	testScriptDirClone(t, gluaTests, "_glua-tests")
   357  }
   358  
   359  func TestLuaClone(t *testing.T) {
   360  	testScriptDirClone(t, luaTests, "_lua5.1-tests")
   361  }