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 }