Supressed errors in '__close' generate warnings

This commit is contained in:
Roberto Ierusalimschy
2019-08-16 09:51:54 -03:00
parent a1d8eb2743
commit ca13be9af7
10 changed files with 166 additions and 45 deletions

View File

@@ -286,57 +286,149 @@ do
end
do -- errors in __close
local log = {}
local function foo (err)
-- auxiliary functions for testing warnings in '__close'
local function prepwarn ()
warn("@off") -- do not show (lots of) warnings
if not T then
_WARN = "OFF" -- signal that warnings are not being captured
else
warn("@store") -- to test the warnings
end
end
local function endwarn ()
assert(T or _WARN == "OFF")
warn("@on") -- back to normal
warn("@normal")
_WARN = nil
end
local function checkwarn (msg)
assert(_WARN == "OFF" or string.find(_WARN, msg))
end
do print("testing errors in __close")
prepwarn()
-- original error is in __close
local function foo ()
local x <close> =
func2close(function (self, msg) log[#log + 1] = msg; error(1) end)
func2close(function (self, msg)
assert(string.find(msg, "@z"))
error("@x")
end)
local x1 <close> =
func2close(function (self, msg) log[#log + 1] = msg; end)
func2close(function (self, msg)
checkwarn("@y")
assert(string.find(msg, "@z"))
end)
local gc <close> = func2close(function () collectgarbage() end)
local y <close> =
func2close(function (self, msg) log[#log + 1] = msg; error(2) end)
func2close(function (self, msg)
assert(string.find(msg, "@z")) -- error in 'z'
error("@y")
end)
local first = true
local z <close> =
-- 'z' close is called twice
func2close(function (self, msg)
if first then
assert(msg == nil)
first = false
else
assert(string.find(msg, "@z")) -- own error
end
error("@z")
end)
return 200
end
local stat, msg = pcall(foo, false)
assert(string.find(msg, "@z"))
checkwarn("@x")
-- original error not in __close
local function foo ()
local x <close> =
func2close(function (self, msg)
assert(msg == 4)
end)
local x1 <close> =
func2close(function (self, msg)
checkwarn("@y")
assert(msg == 4)
error("@x1")
end)
local gc <close> = func2close(function () collectgarbage() end)
local y <close> =
func2close(function (self, msg)
assert(msg == 4) -- error in body
error("@y")
end)
local first = true
local z <close> =
func2close(function (self, msg)
log[#log + 1] = (msg or 10) + 1;
error(3)
checkwarn("@z")
-- 'z' close is called once
assert(first and msg == 4)
first = false
error("@z")
end)
if err then error(4) end
end
local stat, msg = pcall(foo, false)
assert(msg == 3)
-- 'z' close is called twice
assert(log[1] == 11 and log[2] == 4 and log[3] == 3 and log[4] == 3
and log[5] == 3 and #log == 5)
log = {}
error(4) -- original error
end
local stat, msg = pcall(foo, true)
assert(msg == 4)
-- 'z' close is called once
assert(log[1] == 5 and log[2] == 4 and log[3] == 4 and log[4] == 4
and #log == 4)
checkwarn("@x1") -- last error
-- error leaving a block
local function foo (...)
do
local x1 <close> = func2close(function () error("Y") end)
local x123 <close> = func2close(function () error("X") end)
local x1 <close> =
func2close(function ()
checkwarn("@X")
error("@Y")
end)
local x123 <close> =
func2close(function ()
error("@X")
end)
end
os.exit(false) -- should not run
end
local st, msg = xpcall(foo, debug.traceback)
assert(string.match(msg, "^[^ ]* X"))
assert(string.match(msg, "^[^ ]* @X"))
assert(string.find(msg, "in metamethod 'close'"))
-- error in toclose in vararg function
local function foo (...)
local x123 <close> = func2close(function () error("X") end)
local x123 <close> = func2close(function () error("@X") end)
end
local st, msg = xpcall(foo, debug.traceback)
assert(string.match(msg, "^[^ ]* X"))
assert(string.match(msg, "^[^ ]* @X"))
assert(string.find(msg, "in metamethod 'close'"))
endwarn()
end
@@ -361,6 +453,8 @@ end
if rawget(_G, "T") then
warn("@off")
-- memory error inside closing function
local function foo ()
local y <close> = func2close(function () T.alloccount() end)
@@ -437,7 +531,7 @@ if rawget(_G, "T") then
local s = string.rep("a", lim)
-- concat this table needs two buffer resizes (one for each 's')
-- concat this table needs two buffer resizes (one for each 's')
local a = {s, s}
collectgarbage()
@@ -472,6 +566,8 @@ if rawget(_G, "T") then
print'+'
end
warn("@on")
end
@@ -501,17 +597,20 @@ end
do
prepwarn()
-- error in a wrapped coroutine raising errors when closing a variable
local x = 0
local co = coroutine.wrap(function ()
local xx <close> = func2close(function () x = x + 1; error("YYY") end)
local xv <close> = func2close(function () x = x + 1; error("XXX") end)
local xx <close> = func2close(function () x = x + 1; error("@YYY") end)
local xv <close> = func2close(function () x = x + 1; error("@XXX") end)
coroutine.yield(100)
error(200)
end)
assert(co() == 100); assert(x == 0)
local st, msg = pcall(co); assert(x == 2)
assert(not st and msg == 200) -- should get first error raised
checkwarn("@YYY")
local x = 0
local y = 0
@@ -526,6 +625,9 @@ do
assert(x == 2 and y == 1) -- first close is called twice
-- should get first error raised
assert(not st and string.find(msg, "%w+%.%w+:%d+: XXX"))
checkwarn("YYY")
endwarn()
end