summaryrefslogtreecommitdiff
path: root/zig-lua/lua-5.4.7/testes/gengc.lua
diff options
context:
space:
mode:
Diffstat (limited to 'zig-lua/lua-5.4.7/testes/gengc.lua')
-rw-r--r--zig-lua/lua-5.4.7/testes/gengc.lua172
1 files changed, 172 insertions, 0 deletions
diff --git a/zig-lua/lua-5.4.7/testes/gengc.lua b/zig-lua/lua-5.4.7/testes/gengc.lua
new file mode 100644
index 0000000..3d4f67f
--- /dev/null
+++ b/zig-lua/lua-5.4.7/testes/gengc.lua
@@ -0,0 +1,172 @@
+-- $Id: testes/gengc.lua $
+-- See Copyright Notice in file all.lua
+
+print('testing generational garbage collection')
+
+local debug = require"debug"
+
+assert(collectgarbage("isrunning"))
+
+collectgarbage()
+
+local oldmode = collectgarbage("generational")
+
+
+-- ensure that table barrier evolves correctly
+do
+ local U = {}
+ -- full collection makes 'U' old
+ collectgarbage()
+ assert(not T or T.gcage(U) == "old")
+
+ -- U refers to a new table, so it becomes 'touched1'
+ U[1] = {x = {234}}
+ assert(not T or (T.gcage(U) == "touched1" and T.gcage(U[1]) == "new"))
+
+ -- both U and the table survive one more collection
+ collectgarbage("step", 0)
+ assert(not T or (T.gcage(U) == "touched2" and T.gcage(U[1]) == "survival"))
+
+ -- both U and the table survive yet another collection
+ -- now everything is old
+ collectgarbage("step", 0)
+ assert(not T or (T.gcage(U) == "old" and T.gcage(U[1]) == "old1"))
+
+ -- data was not corrupted
+ assert(U[1].x[1] == 234)
+end
+
+
+do
+ -- ensure that 'firstold1' is corrected when object is removed from
+ -- the 'allgc' list
+ local function foo () end
+ local old = {10}
+ collectgarbage() -- make 'old' old
+ assert(not T or T.gcage(old) == "old")
+ setmetatable(old, {}) -- new table becomes OLD0 (barrier)
+ assert(not T or T.gcage(getmetatable(old)) == "old0")
+ collectgarbage("step", 0) -- new table becomes OLD1 and firstold1
+ assert(not T or T.gcage(getmetatable(old)) == "old1")
+ setmetatable(getmetatable(old), {__gc = foo}) -- get it out of allgc list
+ collectgarbage("step", 0) -- should not seg. fault
+end
+
+
+do -- bug in 5.4.0
+-- When an object aged OLD1 is finalized, it is moved from the list
+-- 'finobj' to the *beginning* of the list 'allgc', but that part of the
+-- list was not being visited by 'markold'.
+ local A = {}
+ A[1] = false -- old anchor for object
+
+ -- obj finalizer
+ local function gcf (obj)
+ A[1] = obj -- anchor object
+ assert(not T or T.gcage(obj) == "old1")
+ obj = nil -- remove it from the stack
+ collectgarbage("step", 0) -- do a young collection
+ print(getmetatable(A[1]).x) -- metatable was collected
+ end
+
+ collectgarbage() -- make A old
+ local obj = {} -- create a new object
+ collectgarbage("step", 0) -- make it a survival
+ assert(not T or T.gcage(obj) == "survival")
+ setmetatable(obj, {__gc = gcf, x = "+"}) -- create its metatable
+ assert(not T or T.gcage(getmetatable(obj)) == "new")
+ obj = nil -- clear object
+ collectgarbage("step", 0) -- will call obj's finalizer
+end
+
+
+do -- another bug in 5.4.0
+ local old = {10}
+ collectgarbage() -- make 'old' old
+ local co = coroutine.create(
+ function ()
+ local x = nil
+ local f = function ()
+ return x[1]
+ end
+ x = coroutine.yield(f)
+ coroutine.yield()
+ end
+ )
+ local _, f = coroutine.resume(co) -- create closure over 'x' in coroutine
+ collectgarbage("step", 0) -- make upvalue a survival
+ old[1] = {"hello"} -- 'old' go to grayagain as 'touched1'
+ coroutine.resume(co, {123}) -- its value will be new
+ co = nil
+ collectgarbage("step", 0) -- hit the barrier
+ assert(f() == 123 and old[1][1] == "hello")
+ collectgarbage("step", 0) -- run the collector once more
+ -- make sure old[1] was not collected
+ assert(f() == 123 and old[1][1] == "hello")
+end
+
+
+do -- bug introduced in commit 9cf3299fa
+ local t = setmetatable({}, {__mode = "kv"}) -- all-weak table
+ collectgarbage() -- full collection
+ assert(not T or T.gcage(t) == "old")
+ t[1] = {10}
+ assert(not T or (T.gcage(t) == "touched1" and T.gccolor(t) == "gray"))
+ collectgarbage("step", 0) -- minor collection
+ assert(not T or (T.gcage(t) == "touched2" and T.gccolor(t) == "black"))
+ collectgarbage("step", 0) -- minor collection
+ assert(not T or T.gcage(t) == "old") -- t should be black, but it was gray
+ t[1] = {10} -- no barrier here, so t was still old
+ collectgarbage("step", 0) -- minor collection
+ -- t, being old, is ignored by the collection, so it is not cleared
+ assert(t[1] == nil) -- fails with the bug
+end
+
+
+if T == nil then
+ (Message or print)('\n >>> testC not active: \z
+ skipping some generational tests <<<\n')
+ print 'OK'
+ return
+end
+
+
+-- ensure that userdata barrier evolves correctly
+do
+ local U = T.newuserdata(0, 1)
+ -- full collection makes 'U' old
+ collectgarbage()
+ assert(T.gcage(U) == "old")
+
+ -- U refers to a new table, so it becomes 'touched1'
+ debug.setuservalue(U, {x = {234}})
+ assert(T.gcage(U) == "touched1" and
+ T.gcage(debug.getuservalue(U)) == "new")
+
+ -- both U and the table survive one more collection
+ collectgarbage("step", 0)
+ assert(T.gcage(U) == "touched2" and
+ T.gcage(debug.getuservalue(U)) == "survival")
+
+ -- both U and the table survive yet another collection
+ -- now everything is old
+ collectgarbage("step", 0)
+ assert(T.gcage(U) == "old" and
+ T.gcage(debug.getuservalue(U)) == "old1")
+
+ -- data was not corrupted
+ assert(debug.getuservalue(U).x[1] == 234)
+end
+
+-- just to make sure
+assert(collectgarbage'isrunning')
+
+
+
+-- just to make sure
+assert(collectgarbage'isrunning')
+
+collectgarbage(oldmode)
+
+print('OK')
+