diff options
Diffstat (limited to 'testes')
-rw-r--r-- | testes/api.lua | 19 | ||||
-rw-r--r-- | testes/coroutine.lua | 13 | ||||
-rw-r--r-- | testes/goto.lua | 2 | ||||
-rw-r--r-- | testes/locals.lua | 54 |
4 files changed, 61 insertions, 27 deletions
diff --git a/testes/api.lua b/testes/api.lua index 893a36cb..9904dadf 100644 --- a/testes/api.lua +++ b/testes/api.lua | |||
@@ -396,6 +396,23 @@ do | |||
396 | assert(string.find(msg, "stack overflow")) | 396 | assert(string.find(msg, "stack overflow")) |
397 | end | 397 | end |
398 | 398 | ||
399 | -- exit in panic still close to-be-closed variables | ||
400 | assert(T.checkpanic([[ | ||
401 | pushstring "return {__close = function () Y = 'ho'; end}" | ||
402 | newtable | ||
403 | loadstring -2 | ||
404 | call 0 1 | ||
405 | setmetatable -2 | ||
406 | toclose -1 | ||
407 | pushstring "hi" | ||
408 | error | ||
409 | ]], | ||
410 | [[ | ||
411 | getglobal Y | ||
412 | concat 2 # concat original error with global Y | ||
413 | ]]) == "hiho") | ||
414 | |||
415 | |||
399 | end | 416 | end |
400 | 417 | ||
401 | -- testing deep C stack | 418 | -- testing deep C stack |
@@ -1115,7 +1132,7 @@ end) | |||
1115 | testamem("to-be-closed variables", function() | 1132 | testamem("to-be-closed variables", function() |
1116 | local flag | 1133 | local flag |
1117 | do | 1134 | do |
1118 | local *toclose x = function () flag = true end | 1135 | local *toclose x = setmetatable({}, {__close = function () flag = true end}) |
1119 | flag = false | 1136 | flag = false |
1120 | local x = {} | 1137 | local x = {} |
1121 | end | 1138 | end |
diff --git a/testes/coroutine.lua b/testes/coroutine.lua index ca30011f..a4321bed 100644 --- a/testes/coroutine.lua +++ b/testes/coroutine.lua | |||
@@ -142,8 +142,15 @@ do | |||
142 | 142 | ||
143 | -- to-be-closed variables in coroutines | 143 | -- to-be-closed variables in coroutines |
144 | local X | 144 | local X |
145 | |||
146 | local function func2close (f) | ||
147 | return setmetatable({}, {__close = f}) | ||
148 | end | ||
149 | |||
145 | co = coroutine.create(function () | 150 | co = coroutine.create(function () |
146 | local *toclose x = function (err) assert(err == nil); X = false end | 151 | local *toclose x = func2close(function (self, err) |
152 | assert(err == nil); X = false | ||
153 | end) | ||
147 | X = true | 154 | X = true |
148 | coroutine.yield() | 155 | coroutine.yield() |
149 | end) | 156 | end) |
@@ -154,7 +161,9 @@ do | |||
154 | 161 | ||
155 | -- error killing a coroutine | 162 | -- error killing a coroutine |
156 | co = coroutine.create(function() | 163 | co = coroutine.create(function() |
157 | local *toclose x = function (err) assert(err == nil); error(111) end | 164 | local *toclose x = func2close(function (self, err) |
165 | assert(err == nil); error(111) | ||
166 | end) | ||
158 | coroutine.yield() | 167 | coroutine.yield() |
159 | end) | 168 | end) |
160 | coroutine.resume(co) | 169 | coroutine.resume(co) |
diff --git a/testes/goto.lua b/testes/goto.lua index 5d863a42..f3dcfd4a 100644 --- a/testes/goto.lua +++ b/testes/goto.lua | |||
@@ -258,7 +258,7 @@ do | |||
258 | ::L2:: goto L3 | 258 | ::L2:: goto L3 |
259 | 259 | ||
260 | ::L1:: do | 260 | ::L1:: do |
261 | local *toclose a = function () X = true end | 261 | local *toclose a = setmetatable({}, {__close = function () X = true end}) |
262 | assert(X == nil) | 262 | assert(X == nil) |
263 | if a then goto L2 end -- jumping back out of scope of 'a' | 263 | if a then goto L2 end -- jumping back out of scope of 'a' |
264 | end | 264 | end |
diff --git a/testes/locals.lua b/testes/locals.lua index 340af61c..de47ae31 100644 --- a/testes/locals.lua +++ b/testes/locals.lua | |||
@@ -177,13 +177,19 @@ print"testing to-be-closed variables" | |||
177 | 177 | ||
178 | local function stack(n) n = ((n == 0) or stack(n - 1)) end | 178 | local function stack(n) n = ((n == 0) or stack(n - 1)) end |
179 | 179 | ||
180 | local function func2close (f) | ||
181 | return setmetatable({}, {__close = f}) | ||
182 | end | ||
183 | |||
180 | 184 | ||
181 | do | 185 | do |
182 | local a = {} | 186 | local a = {} |
183 | do | 187 | do |
184 | local *toclose x = setmetatable({"x"}, {__close = function (self) | 188 | local *toclose x = setmetatable({"x"}, {__close = function (self) |
185 | a[#a + 1] = self[1] end}) | 189 | a[#a + 1] = self[1] end}) |
186 | local *toclose y = function (x) assert(x == nil); a[#a + 1] = "y" end | 190 | local *toclose y = func2close(function (self, err) |
191 | assert(err == nil); a[#a + 1] = "y" | ||
192 | end) | ||
187 | a[#a + 1] = "in" | 193 | a[#a + 1] = "in" |
188 | end | 194 | end |
189 | a[#a + 1] = "out" | 195 | a[#a + 1] = "out" |
@@ -193,7 +199,7 @@ end | |||
193 | do | 199 | do |
194 | local X = false | 200 | local X = false |
195 | 201 | ||
196 | local function closescope () stack(10); X = true end | 202 | local closescope = func2close(function () stack(10); X = true end) |
197 | 203 | ||
198 | -- closing functions do not corrupt returning values | 204 | -- closing functions do not corrupt returning values |
199 | local function foo (x) | 205 | local function foo (x) |
@@ -228,13 +234,13 @@ do | |||
228 | -- calls cannot be tail in the scope of to-be-closed variables | 234 | -- calls cannot be tail in the scope of to-be-closed variables |
229 | local X, Y | 235 | local X, Y |
230 | local function foo () | 236 | local function foo () |
231 | local *toclose _ = function () Y = 10 end | 237 | local *toclose _ = func2close(function () Y = 10 end) |
232 | assert(X == true and Y == nil) -- 'X' not closed yet | 238 | assert(X == true and Y == nil) -- 'X' not closed yet |
233 | return 1,2,3 | 239 | return 1,2,3 |
234 | end | 240 | end |
235 | 241 | ||
236 | local function bar () | 242 | local function bar () |
237 | local *toclose _ = function () X = false end | 243 | local *toclose _ = func2close(function () X = false end) |
238 | X = true | 244 | X = true |
239 | do | 245 | do |
240 | return foo() -- not a tail call! | 246 | return foo() -- not a tail call! |
@@ -249,11 +255,15 @@ end | |||
249 | do -- errors in __close | 255 | do -- errors in __close |
250 | local log = {} | 256 | local log = {} |
251 | local function foo (err) | 257 | local function foo (err) |
252 | local *toclose x = function (msg) log[#log + 1] = msg; error(1) end | 258 | local *toclose x = |
253 | local *toclose x1 = function (msg) log[#log + 1] = msg; end | 259 | func2close(function (self, msg) log[#log + 1] = msg; error(1) end) |
254 | local *toclose gc = function () collectgarbage() end | 260 | local *toclose x1 = |
255 | local *toclose y = function (msg) log[#log + 1] = msg; error(2) end | 261 | func2close(function (self, msg) log[#log + 1] = msg; end) |
256 | local *toclose z = function (msg) log[#log + 1] = msg or 10; error(3) end | 262 | local *toclose gc = func2close(function () collectgarbage() end) |
263 | local *toclose y = | ||
264 | func2close(function (self, msg) log[#log + 1] = msg; error(2) end) | ||
265 | local *toclose z = | ||
266 | func2close(function (self, msg) log[#log + 1] = msg or 10; error(3) end) | ||
257 | if err then error(4) end | 267 | if err then error(4) end |
258 | end | 268 | end |
259 | local stat, msg = pcall(foo, false) | 269 | local stat, msg = pcall(foo, false) |
@@ -282,7 +292,7 @@ do | |||
282 | -- with other errors, non-closable values are ignored | 292 | -- with other errors, non-closable values are ignored |
283 | local function foo () | 293 | local function foo () |
284 | local *toclose x = 34 | 294 | local *toclose x = 34 |
285 | local *toclose y = function () error(32) end | 295 | local *toclose y = func2close(function () error(32) end) |
286 | end | 296 | end |
287 | local stat, msg = pcall(foo) | 297 | local stat, msg = pcall(foo) |
288 | assert(not stat and msg == 32) | 298 | assert(not stat and msg == 32) |
@@ -294,7 +304,7 @@ if rawget(_G, "T") then | |||
294 | 304 | ||
295 | -- memory error inside closing function | 305 | -- memory error inside closing function |
296 | local function foo () | 306 | local function foo () |
297 | local *toclose y = function () T.alloccount() end | 307 | local *toclose y = func2close(function () T.alloccount() end) |
298 | local *toclose x = setmetatable({}, {__close = function () | 308 | local *toclose x = setmetatable({}, {__close = function () |
299 | T.alloccount(0); local x = {} -- force a memory error | 309 | T.alloccount(0); local x = {} -- force a memory error |
300 | end}) | 310 | end}) |
@@ -308,12 +318,12 @@ if rawget(_G, "T") then | |||
308 | local _, msg = pcall(foo) | 318 | local _, msg = pcall(foo) |
309 | assert(msg == "not enough memory") | 319 | assert(msg == "not enough memory") |
310 | 320 | ||
311 | local function close (msg) | 321 | local close = func2close(function (self, msg) |
312 | T.alloccount() | 322 | T.alloccount() |
313 | assert(msg == "not enough memory") | 323 | assert(msg == "not enough memory") |
314 | end | 324 | end) |
315 | 325 | ||
316 | -- set a memory limit and return a closing function to remove the limit | 326 | -- set a memory limit and return a closing object to remove the limit |
317 | local function enter (count) | 327 | local function enter (count) |
318 | stack(10) -- reserve some stack space | 328 | stack(10) -- reserve some stack space |
319 | T.alloccount(count) | 329 | T.alloccount(count) |
@@ -336,13 +346,13 @@ if rawget(_G, "T") then | |||
336 | 346 | ||
337 | -- repeat test with extra closing upvalues | 347 | -- repeat test with extra closing upvalues |
338 | local function test () | 348 | local function test () |
339 | local *toclose xxx = function (msg) | 349 | local *toclose xxx = func2close(function (self, msg) |
340 | assert(msg == "not enough memory"); | 350 | assert(msg == "not enough memory"); |
341 | error(1000) -- raise another error | 351 | error(1000) -- raise another error |
342 | end | 352 | end) |
343 | local *toclose xx = function (msg) | 353 | local *toclose xx = func2close(function (self, msg) |
344 | assert(msg == "not enough memory"); | 354 | assert(msg == "not enough memory"); |
345 | end | 355 | end) |
346 | local *toclose x = enter(0) -- set a memory limit | 356 | local *toclose x = enter(0) -- set a memory limit |
347 | -- creation of previous upvalue will raise a memory error | 357 | -- creation of previous upvalue will raise a memory error |
348 | os.exit(false) -- should not run | 358 | os.exit(false) -- should not run |
@@ -413,9 +423,9 @@ do | |||
413 | local x = false | 423 | local x = false |
414 | local y = false | 424 | local y = false |
415 | local co = coroutine.create(function () | 425 | local co = coroutine.create(function () |
416 | local *toclose xv = function () x = true end | 426 | local *toclose xv = func2close(function () x = true end) |
417 | do | 427 | do |
418 | local *toclose yv = function () y = true end | 428 | local *toclose yv = func2close(function () y = true end) |
419 | coroutine.yield(100) -- yield doesn't close variable | 429 | coroutine.yield(100) -- yield doesn't close variable |
420 | end | 430 | end |
421 | coroutine.yield(200) -- yield doesn't close variable | 431 | coroutine.yield(200) -- yield doesn't close variable |
@@ -453,9 +463,7 @@ do | |||
453 | end, | 463 | end, |
454 | nil, -- state | 464 | nil, -- state |
455 | nil, -- control variable | 465 | nil, -- control variable |
456 | function () -- closing function | 466 | func2close(function () numopen = numopen - 1 end) -- closing function |
457 | numopen = numopen - 1 | ||
458 | end | ||
459 | end | 467 | end |
460 | 468 | ||
461 | local s = 0 | 469 | local s = 0 |