diff options
| author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2018-11-29 16:02:44 -0200 |
|---|---|---|
| committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2018-11-29 16:02:44 -0200 |
| commit | 6d04537ea660fd12fc16c328366b701fabaf4919 (patch) | |
| tree | 41eab6e4d87552e29731db552f7d58d679c56973 /testes | |
| parent | 7696c6474fe51ed59fee324e78c1233af74febdd (diff) | |
| download | lua-6d04537ea660fd12fc16c328366b701fabaf4919.tar.gz lua-6d04537ea660fd12fc16c328366b701fabaf4919.tar.bz2 lua-6d04537ea660fd12fc16c328366b701fabaf4919.zip | |
A to-be-closed variable must have a closable value (or be nil)
It is an error for a to-be-closed variable to have a non-closable
non-nil value when it is being closed. This situation does not seem to
be useful and often hints to an error. (Particularly in the C API, it is
easy to change a to-be-closed index by mistake.)
Diffstat (limited to 'testes')
| -rw-r--r-- | testes/api.lua | 21 | ||||
| -rw-r--r-- | testes/db.lua | 20 | ||||
| -rw-r--r-- | testes/locals.lua | 21 |
3 files changed, 45 insertions, 17 deletions
diff --git a/testes/api.lua b/testes/api.lua index ed857fd0..6f35e132 100644 --- a/testes/api.lua +++ b/testes/api.lua | |||
| @@ -366,7 +366,7 @@ do | |||
| 366 | -- "argerror" without frames | 366 | -- "argerror" without frames |
| 367 | assert(T.checkpanic("loadstring 4") == | 367 | assert(T.checkpanic("loadstring 4") == |
| 368 | "bad argument #4 (string expected, got no value)") | 368 | "bad argument #4 (string expected, got no value)") |
| 369 | 369 | ||
| 370 | 370 | ||
| 371 | -- memory error | 371 | -- memory error |
| 372 | T.totalmem(T.totalmem()+10000) -- set low memory limit (+10k) | 372 | T.totalmem(T.totalmem()+10000) -- set low memory limit (+10k) |
| @@ -987,12 +987,12 @@ do | |||
| 987 | 987 | ||
| 988 | local a, b = T.testC([[ | 988 | local a, b = T.testC([[ |
| 989 | call 0 1 # create resource | 989 | call 0 1 # create resource |
| 990 | pushint 34 | 990 | pushnil |
| 991 | toclose -2 # mark call result to be closed | 991 | toclose -2 # mark call result to be closed |
| 992 | toclose -1 # mark number to be closed (will be ignored) | 992 | toclose -1 # mark nil to be closed (will be ignored) |
| 993 | return 2 | 993 | return 2 |
| 994 | ]], newresource) | 994 | ]], newresource) |
| 995 | assert(a[1] == 11 and b == 34) | 995 | assert(a[1] == 11 and b == nil) |
| 996 | assert(#openresource == 0) -- was closed | 996 | assert(#openresource == 0) -- was closed |
| 997 | 997 | ||
| 998 | -- repeat the test, but calling function in a 'multret' context | 998 | -- repeat the test, but calling function in a 'multret' context |
| @@ -1005,7 +1005,7 @@ do | |||
| 1005 | assert(#openresource == 0) -- was closed | 1005 | assert(#openresource == 0) -- was closed |
| 1006 | 1006 | ||
| 1007 | -- error | 1007 | -- error |
| 1008 | local a, b = pcall(T.testC, [[ | 1008 | local a, b = pcall(T.makeCfunc[[ |
| 1009 | call 0 1 # create resource | 1009 | call 0 1 # create resource |
| 1010 | toclose -1 # mark it to be closed | 1010 | toclose -1 # mark it to be closed |
| 1011 | error # resource is the error object | 1011 | error # resource is the error object |
| @@ -1038,6 +1038,13 @@ do | |||
| 1038 | ]], newresource, check) | 1038 | ]], newresource, check) |
| 1039 | assert(a == 3) -- no extra items left in the stack | 1039 | assert(a == 3) -- no extra items left in the stack |
| 1040 | 1040 | ||
| 1041 | -- non-closable value | ||
| 1042 | local a, b = pcall(T.makeCfunc[[ | ||
| 1043 | pushint 32 | ||
| 1044 | toclose -1 | ||
| 1045 | ]]) | ||
| 1046 | assert(not a and string.find(b, "(C temporary)")) | ||
| 1047 | |||
| 1041 | end | 1048 | end |
| 1042 | 1049 | ||
| 1043 | 1050 | ||
| @@ -1249,9 +1256,9 @@ do -- closing state with no extra memory | |||
| 1249 | T.closestate(L) | 1256 | T.closestate(L) |
| 1250 | T.alloccount() | 1257 | T.alloccount() |
| 1251 | end | 1258 | end |
| 1252 | 1259 | ||
| 1253 | do -- garbage collection with no extra memory | 1260 | do -- garbage collection with no extra memory |
| 1254 | local L = T.newstate() | 1261 | local L = T.newstate() |
| 1255 | T.loadlib(L) | 1262 | T.loadlib(L) |
| 1256 | local res = (T.doremote(L, [[ | 1263 | local res = (T.doremote(L, [[ |
| 1257 | _ENV = require"_G" | 1264 | _ENV = require"_G" |
diff --git a/testes/db.lua b/testes/db.lua index 5b243c39..976962b0 100644 --- a/testes/db.lua +++ b/testes/db.lua | |||
| @@ -214,14 +214,14 @@ local function foo (a, ...) | |||
| 214 | local t = table.pack(...) | 214 | local t = table.pack(...) |
| 215 | for i = 1, t.n do | 215 | for i = 1, t.n do |
| 216 | local n, v = debug.getlocal(1, -i) | 216 | local n, v = debug.getlocal(1, -i) |
| 217 | assert(n == "(*vararg)" and v == t[i]) | 217 | assert(n == "(vararg)" and v == t[i]) |
| 218 | end | 218 | end |
| 219 | assert(not debug.getlocal(1, -(t.n + 1))) | 219 | assert(not debug.getlocal(1, -(t.n + 1))) |
| 220 | assert(not debug.setlocal(1, -(t.n + 1), 30)) | 220 | assert(not debug.setlocal(1, -(t.n + 1), 30)) |
| 221 | if t.n > 0 then | 221 | if t.n > 0 then |
| 222 | (function (x) | 222 | (function (x) |
| 223 | assert(debug.setlocal(2, -1, x) == "(*vararg)") | 223 | assert(debug.setlocal(2, -1, x) == "(vararg)") |
| 224 | assert(debug.setlocal(2, -t.n, x) == "(*vararg)") | 224 | assert(debug.setlocal(2, -t.n, x) == "(vararg)") |
| 225 | end)(430) | 225 | end)(430) |
| 226 | assert(... == 430) | 226 | assert(... == 430) |
| 227 | end | 227 | end |
| @@ -328,9 +328,9 @@ assert(a[f] and a[g] and a[assert] and a[debug.getlocal] and not a[print]) | |||
| 328 | -- tests for manipulating non-registered locals (C and Lua temporaries) | 328 | -- tests for manipulating non-registered locals (C and Lua temporaries) |
| 329 | 329 | ||
| 330 | local n, v = debug.getlocal(0, 1) | 330 | local n, v = debug.getlocal(0, 1) |
| 331 | assert(v == 0 and n == "(*temporary)") | 331 | assert(v == 0 and n == "(C temporary)") |
| 332 | local n, v = debug.getlocal(0, 2) | 332 | local n, v = debug.getlocal(0, 2) |
| 333 | assert(v == 2 and n == "(*temporary)") | 333 | assert(v == 2 and n == "(C temporary)") |
| 334 | assert(not debug.getlocal(0, 3)) | 334 | assert(not debug.getlocal(0, 3)) |
| 335 | assert(not debug.getlocal(0, 0)) | 335 | assert(not debug.getlocal(0, 0)) |
| 336 | 336 | ||
| @@ -607,7 +607,7 @@ co = load[[ | |||
| 607 | local a = 0 | 607 | local a = 0 |
| 608 | -- 'A' should be visible to debugger only after its complete definition | 608 | -- 'A' should be visible to debugger only after its complete definition |
| 609 | debug.sethook(function (e, l) | 609 | debug.sethook(function (e, l) |
| 610 | if l == 3 then a = a + 1; assert(debug.getlocal(2, 1) == "(*temporary)") | 610 | if l == 3 then a = a + 1; assert(debug.getlocal(2, 1) == "(temporary)") |
| 611 | elseif l == 4 then a = a + 1; assert(debug.getlocal(2, 1) == "A") | 611 | elseif l == 4 then a = a + 1; assert(debug.getlocal(2, 1) == "A") |
| 612 | end | 612 | end |
| 613 | end, "l") | 613 | end, "l") |
| @@ -875,15 +875,15 @@ local debug = require'debug' | |||
| 875 | local a = 12 -- a local variable | 875 | local a = 12 -- a local variable |
| 876 | 876 | ||
| 877 | local n, v = debug.getlocal(1, 1) | 877 | local n, v = debug.getlocal(1, 1) |
| 878 | assert(n == "(*temporary)" and v == debug) -- unkown name but known value | 878 | assert(n == "(temporary)" and v == debug) -- unkown name but known value |
| 879 | n, v = debug.getlocal(1, 2) | 879 | n, v = debug.getlocal(1, 2) |
| 880 | assert(n == "(*temporary)" and v == 12) -- unkown name but known value | 880 | assert(n == "(temporary)" and v == 12) -- unkown name but known value |
| 881 | 881 | ||
| 882 | -- a function with an upvalue | 882 | -- a function with an upvalue |
| 883 | local f = function () local x; return a end | 883 | local f = function () local x; return a end |
| 884 | n, v = debug.getupvalue(f, 1) | 884 | n, v = debug.getupvalue(f, 1) |
| 885 | assert(n == "(*no name)" and v == 12) | 885 | assert(n == "(no name)" and v == 12) |
| 886 | assert(debug.setupvalue(f, 1, 13) == "(*no name)") | 886 | assert(debug.setupvalue(f, 1, 13) == "(no name)") |
| 887 | assert(a == 13) | 887 | assert(a == 13) |
| 888 | 888 | ||
| 889 | local t = debug.getinfo(f) | 889 | local t = debug.getinfo(f) |
diff --git a/testes/locals.lua b/testes/locals.lua index 90a8b845..24681dd9 100644 --- a/testes/locals.lua +++ b/testes/locals.lua | |||
| @@ -266,6 +266,27 @@ do -- errors in __close | |||
| 266 | end | 266 | end |
| 267 | 267 | ||
| 268 | 268 | ||
| 269 | do | ||
| 270 | |||
| 271 | -- errors due to non-closable values | ||
| 272 | local function foo () | ||
| 273 | local *toclose x = 34 | ||
| 274 | end | ||
| 275 | local stat, msg = pcall(foo) | ||
| 276 | assert(not stat and string.find(msg, "variable 'x'")) | ||
| 277 | |||
| 278 | |||
| 279 | -- with other errors, non-closable values are ignored | ||
| 280 | local function foo () | ||
| 281 | local *toclose x = 34 | ||
| 282 | local *toclose y = function () error(32) end | ||
| 283 | end | ||
| 284 | local stat, msg = pcall(foo) | ||
| 285 | assert(not stat and msg == 32) | ||
| 286 | |||
| 287 | end | ||
| 288 | |||
| 289 | |||
| 269 | if rawget(_G, "T") then | 290 | if rawget(_G, "T") then |
| 270 | 291 | ||
| 271 | -- memory error inside closing function | 292 | -- memory error inside closing function |
