diff options
| author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2018-10-17 10:44:42 -0300 |
|---|---|---|
| committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2018-10-17 10:44:42 -0300 |
| commit | bd96330d037660d9a1769c6c0d989f017e5f0278 (patch) | |
| tree | c3f4580c628a71f512b057b7f52987153cb88d74 /testes | |
| parent | 4cd1f4aac01184765818e0cebf02da454ccf6590 (diff) | |
| download | lua-bd96330d037660d9a1769c6c0d989f017e5f0278.tar.gz lua-bd96330d037660d9a1769c6c0d989f017e5f0278.tar.bz2 lua-bd96330d037660d9a1769c6c0d989f017e5f0278.zip | |
First "complete" implementation of to-be-closed variables
Still missing:
- handling of memory errors when creating upvalue (must run closing
method all the same)
- interaction with coroutines
Diffstat (limited to 'testes')
| -rw-r--r-- | testes/api.lua | 14 | ||||
| -rw-r--r-- | testes/locals.lua | 64 |
2 files changed, 72 insertions, 6 deletions
diff --git a/testes/api.lua b/testes/api.lua index bebb6d2d..925a80c1 100644 --- a/testes/api.lua +++ b/testes/api.lua | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | -- $Id: testes/api.lua $ | 1 | -- $Id: testes/api.lua 2018-07-25 15:31:04 -0300 $ |
| 2 | -- See Copyright Notice in file all.lua | 2 | -- See Copyright Notice in file all.lua |
| 3 | 3 | ||
| 4 | if T==nil then | 4 | if T==nil then |
| @@ -1027,6 +1027,18 @@ testamem("coroutine creation", function() | |||
| 1027 | end) | 1027 | end) |
| 1028 | 1028 | ||
| 1029 | 1029 | ||
| 1030 | -- testing to-be-closed variables | ||
| 1031 | testamem("to-be-closed variables", function() | ||
| 1032 | local flag | ||
| 1033 | do | ||
| 1034 | local scoped x = function () flag = true end | ||
| 1035 | flag = false | ||
| 1036 | local x = {} | ||
| 1037 | end | ||
| 1038 | return flag | ||
| 1039 | end) | ||
| 1040 | |||
| 1041 | |||
| 1030 | -- testing threads | 1042 | -- testing threads |
| 1031 | 1043 | ||
| 1032 | -- get main thread from registry (at index LUA_RIDX_MAINTHREAD == 1) | 1044 | -- get main thread from registry (at index LUA_RIDX_MAINTHREAD == 1) |
diff --git a/testes/locals.lua b/testes/locals.lua index 20ecae4b..8d55e9f5 100644 --- a/testes/locals.lua +++ b/testes/locals.lua | |||
| @@ -173,15 +173,69 @@ end | |||
| 173 | assert(x==20) | 173 | assert(x==20) |
| 174 | 174 | ||
| 175 | 175 | ||
| 176 | -- tests for to-be-closed variables | 176 | print"testing to-be-closed variables" |
| 177 | |||
| 178 | do | ||
| 179 | local a = {} | ||
| 180 | do | ||
| 181 | local scoped x = setmetatable({"x"}, {__close = function (self) | ||
| 182 | a[#a + 1] = self[1] end}) | ||
| 183 | local scoped y = function () a[#a + 1] = "y" end | ||
| 184 | a[#a + 1] = "in" | ||
| 185 | end | ||
| 186 | a[#a + 1] = "out" | ||
| 187 | assert(a[1] == "in" and a[2] == "y" and a[3] == "x" and a[4] == "out") | ||
| 188 | end | ||
| 189 | |||
| 190 | |||
| 191 | do -- errors in __close | ||
| 192 | local log = {} | ||
| 193 | local function foo (err) | ||
| 194 | local scoped x = function (msg) log[#log + 1] = msg; error(1) end | ||
| 195 | local scoped x1 = function (msg) log[#log + 1] = msg; end | ||
| 196 | local scoped gc = function () collectgarbage() end | ||
| 197 | local scoped y = function (msg) log[#log + 1] = msg; error(2) end | ||
| 198 | local scoped z = function (msg) log[#log + 1] = msg or 10; error(3) end | ||
| 199 | if err then error(4) end | ||
| 200 | end | ||
| 201 | local stat, msg = pcall(foo, false) | ||
| 202 | assert(msg == 1) | ||
| 203 | assert(log[1] == 10 and log[2] == 3 and log[3] == 2 and log[4] == 2 | ||
| 204 | and #log == 4) | ||
| 205 | |||
| 206 | log = {} | ||
| 207 | local stat, msg = pcall(foo, true) | ||
| 208 | assert(msg == 1) | ||
| 209 | assert(log[1] == 4 and log[2] == 3 and log[3] == 2 and log[4] == 2 | ||
| 210 | and #log == 4) | ||
| 211 | end | ||
| 212 | |||
| 177 | do | 213 | do |
| 178 | local scoped x = 3 | 214 | -- memory error inside closing function |
| 179 | local a | 215 | local function foo () |
| 180 | local scoped y = 5 | 216 | local scoped y = function () io.write(2); T.alloccount() end |
| 181 | assert(x == 3 and y == 5) | 217 | local scoped x = setmetatable({}, {__close = function () |
| 218 | T.alloccount(0); local x = {} -- force a memory error | ||
| 219 | end}) | ||
| 220 | io.write("1\n") | ||
| 221 | error("a") -- common error inside the function's body | ||
| 222 | end | ||
| 223 | |||
| 224 | local _, msg = pcall(foo) | ||
| 225 | T.alloccount() | ||
| 226 | assert(msg == "not enough memory") | ||
| 227 | |||
| 182 | end | 228 | end |
| 183 | 229 | ||
| 184 | 230 | ||
| 231 | -- a suspended coroutine should not close its variables when collected | ||
| 232 | local co = coroutine.wrap(function() | ||
| 233 | local scoped x = function () os.exit(1) end -- should not run | ||
| 234 | coroutine.yield() | ||
| 235 | end) | ||
| 236 | co() | ||
| 237 | co = nil | ||
| 238 | |||
| 185 | print('OK') | 239 | print('OK') |
| 186 | 240 | ||
| 187 | return 5,f | 241 | return 5,f |
