aboutsummaryrefslogtreecommitdiff
path: root/testes
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2019-07-31 10:43:51 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2019-07-31 10:43:51 -0300
commitf645d3157372c73573dff221c5b26691cb0e7d56 (patch)
tree61adb1f332bbd8c0c0365b81cef8de47fa2ea06a /testes
parent35b4efc270db2418bc2cac6671575a45028061c3 (diff)
downloadlua-f645d3157372c73573dff221c5b26691cb0e7d56.tar.gz
lua-f645d3157372c73573dff221c5b26691cb0e7d56.tar.bz2
lua-f645d3157372c73573dff221c5b26691cb0e7d56.zip
To-be-closed variables must be closed on initialization
When initializing a to-be-closed variable, check whether it has a '__close' metamethod (or is a false value) and raise an error if if it hasn't. This produces more accurate error messages. (The check before closing still need to be done: in the C API, the value is not constant; and the object may lose its '__close' metamethod during the block.)
Diffstat (limited to 'testes')
-rw-r--r--testes/api.lua11
-rw-r--r--testes/locals.lua23
2 files changed, 22 insertions, 12 deletions
diff --git a/testes/api.lua b/testes/api.lua
index 3f7f7596..f6915c3e 100644
--- a/testes/api.lua
+++ b/testes/api.lua
@@ -1096,7 +1096,7 @@ do
1096 assert(type(a[1]) == "string" and a[2][1] == 11) 1096 assert(type(a[1]) == "string" and a[2][1] == 11)
1097 assert(#openresource == 0) -- was closed 1097 assert(#openresource == 0) -- was closed
1098 1098
1099 -- error 1099 -- closing by error
1100 local a, b = pcall(T.makeCfunc[[ 1100 local a, b = pcall(T.makeCfunc[[
1101 call 0 1 # create resource 1101 call 0 1 # create resource
1102 toclose -1 # mark it to be closed 1102 toclose -1 # mark it to be closed
@@ -1105,6 +1105,15 @@ do
1105 assert(a == false and b[1] == 11) 1105 assert(a == false and b[1] == 11)
1106 assert(#openresource == 0) -- was closed 1106 assert(#openresource == 0) -- was closed
1107 1107
1108 -- non-closable value
1109 local a, b = pcall(T.makeCfunc[[
1110 newtable # create non-closable object
1111 toclose -1 # mark it to be closed (shoud raise an error)
1112 abort # will not be executed
1113 ]])
1114 assert(a == false and
1115 string.find(b, "non%-closable value"))
1116
1108 local function check (n) 1117 local function check (n)
1109 assert(#openresource == n) 1118 assert(#openresource == n)
1110 end 1119 end
diff --git a/testes/locals.lua b/testes/locals.lua
index 3b145ca3..6eb1ba0e 100644
--- a/testes/locals.lua
+++ b/testes/locals.lua
@@ -215,11 +215,13 @@ end
215do 215do
216 local a = {} 216 local a = {}
217 do 217 do
218 local b <close> = false -- not to be closed
218 local x <close> = setmetatable({"x"}, {__close = function (self) 219 local x <close> = setmetatable({"x"}, {__close = function (self)
219 a[#a + 1] = self[1] end}) 220 a[#a + 1] = self[1] end})
220 local w, y <close>, z = func2close(function (self, err) 221 local w, y <close>, z = func2close(function (self, err)
221 assert(err == nil); a[#a + 1] = "y" 222 assert(err == nil); a[#a + 1] = "y"
222 end, 10, 20) 223 end, 10, 20)
224 local c <close> = nil -- not to be closed
223 a[#a + 1] = "in" 225 a[#a + 1] = "in"
224 assert(w == 10 and z == 20) 226 assert(w == 10 and z == 20)
225 end 227 end
@@ -325,24 +327,22 @@ do -- errors in __close
325end 327end
326 328
327 329
328do 330do -- errors due to non-closable values
329
330 -- errors due to non-closable values
331 local function foo () 331 local function foo ()
332 local x <close> = {} 332 local x <close> = {}
333 os.exit(false) -- should not run
333 end 334 end
334 local stat, msg = pcall(foo) 335 local stat, msg = pcall(foo)
335 assert(not stat and string.find(msg, "variable 'x'")) 336 assert(not stat and
337 string.find(msg, "variable 'x' got a non%-closable value"))
336 338
337
338 -- with other errors, non-closable values are ignored
339 local function foo () 339 local function foo ()
340 local x <close> = 34 340 local xyz <close> = setmetatable({}, {__close = print})
341 local y <close> = func2close(function () error(32) end) 341 getmetatable(xyz).__close = nil -- remove metamethod
342 end 342 end
343 local stat, msg = pcall(foo) 343 local stat, msg = pcall(foo)
344 assert(not stat and msg == 32) 344 assert(not stat and
345 345 string.find(msg, "attempt to close non%-closable variable 'xyz'"))
346end 346end
347 347
348 348
@@ -519,7 +519,8 @@ end
519-- a suspended coroutine should not close its variables when collected 519-- a suspended coroutine should not close its variables when collected
520local co 520local co
521co = coroutine.wrap(function() 521co = coroutine.wrap(function()
522 local x <close> = function () os.exit(false) end -- should not run 522 -- should not run
523 local x <close> = func2close(function () os.exit(false) end)
523 co = nil 524 co = nil
524 coroutine.yield() 525 coroutine.yield()
525end) 526end)