aboutsummaryrefslogtreecommitdiff
path: root/testes
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2020-12-22 10:54:25 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2020-12-22 10:54:25 -0300
commit0ceada8da92135717d31a3954b5b89a954f9e71a (patch)
tree99655e44791a11bf805d9f059da7391310618eec /testes
parentf9d29b0c442447ebe429bcaad1e2b4bf13c5dc93 (diff)
downloadlua-0ceada8da92135717d31a3954b5b89a954f9e71a.tar.gz
lua-0ceada8da92135717d31a3954b5b89a954f9e71a.tar.bz2
lua-0ceada8da92135717d31a3954b5b89a954f9e71a.zip
Report last error in closing methods
When there are multiple errors around closing methods, report the last error instead of the original.
Diffstat (limited to 'testes')
-rw-r--r--testes/coroutine.lua15
-rw-r--r--testes/locals.lua99
2 files changed, 27 insertions, 87 deletions
diff --git a/testes/coroutine.lua b/testes/coroutine.lua
index aaf565fb..0a970e98 100644
--- a/testes/coroutine.lua
+++ b/testes/coroutine.lua
@@ -172,13 +172,12 @@ do
172 assert(not X and coroutine.status(co) == "dead") 172 assert(not X and coroutine.status(co) == "dead")
173 173
174 -- error closing a coroutine 174 -- error closing a coroutine
175 warn("@on")
176 local x = 0 175 local x = 0
177 co = coroutine.create(function() 176 co = coroutine.create(function()
178 local y <close> = func2close(function (self,err) 177 local y <close> = func2close(function (self,err)
179 if (err ~= 111) then os.exit(false) end -- should not happen 178 assert(err == 111)
180 x = 200 179 x = 200
181 error("200") 180 error(200)
182 end) 181 end)
183 local x <close> = func2close(function (self, err) 182 local x <close> = func2close(function (self, err)
184 assert(err == nil); error(111) 183 assert(err == nil); error(111)
@@ -187,16 +186,8 @@ do
187 end) 186 end)
188 coroutine.resume(co) 187 coroutine.resume(co)
189 assert(x == 0) 188 assert(x == 0)
190 -- with test library, use 'store' mode to check warnings
191 warn(not T and "@off" or "@store")
192 local st, msg = coroutine.close(co) 189 local st, msg = coroutine.close(co)
193 if not T then 190 assert(st == false and coroutine.status(co) == "dead" and msg == 200)
194 warn("@on")
195 else -- test library
196 assert(string.find(_WARN, "200")); _WARN = false
197 warn("@normal")
198 end
199 assert(st == false and coroutine.status(co) == "dead" and msg == 111)
200 assert(x == 200) 191 assert(x == 200)
201 192
202end 193end
diff --git a/testes/locals.lua b/testes/locals.lua
index d32a9a3e..84e0b03a 100644
--- a/testes/locals.lua
+++ b/testes/locals.lua
@@ -232,7 +232,11 @@ end
232do 232do
233 local X = false 233 local X = false
234 234
235 local x, closescope = func2close(function () stack(10); X = true end, 100) 235 local x, closescope = func2close(function (_, msg)
236 stack(10);
237 assert(msg == nil)
238 X = true
239 end, 100)
236 assert(x == 100); x = 101; -- 'x' is not read-only 240 assert(x == 100); x = 101; -- 'x' is not read-only
237 241
238 -- closing functions do not corrupt returning values 242 -- closing functions do not corrupt returning values
@@ -246,10 +250,11 @@ do
246 250
247 X = false 251 X = false
248 foo = function (x) 252 foo = function (x)
249 local _<close> = func2close(function () 253 local _<close> = func2close(function (_, msg)
250 -- without errors, enclosing function should be still active when 254 -- without errors, enclosing function should be still active when
251 -- __close is called 255 -- __close is called
252 assert(debug.getinfo(2).name == "foo") 256 assert(debug.getinfo(2).name == "foo")
257 assert(msg == nil)
253 end) 258 end)
254 local _<close> = closescope 259 local _<close> = closescope
255 local y = 15 260 local y = 15
@@ -328,64 +333,20 @@ do
328end 333end
329 334
330 335
331-- auxiliary functions for testing warnings in '__close'
332local function prepwarn ()
333 if not T then -- no test library?
334 warn("@off") -- do not show (lots of) warnings
335 else
336 warn("@store") -- to test the warnings
337 end
338end
339
340
341local function endwarn ()
342 if not T then
343 warn("@on") -- back to normal
344 else
345 assert(_WARN == false)
346 warn("@normal")
347 end
348end
349
350
351-- errors inside __close can generate a warning instead of an
352-- error. This new 'assert' force them to appear.
353local function assert(cond, msg)
354 if not cond then
355 local line = debug.getinfo(2).currentline or "?"
356 msg = string.format("assertion failed! line %d (%s)\n", line, msg or "")
357 io.stderr:write(msg)
358 os.exit(1)
359 end
360end
361
362
363local function checkwarn (msg)
364 if T then
365 assert(_WARN and string.find(_WARN, msg))
366 _WARN = false -- reset variable to check next warning
367 end
368end
369
370warn("@on")
371
372do print("testing errors in __close") 336do print("testing errors in __close")
373 337
374 prepwarn()
375
376 -- original error is in __close 338 -- original error is in __close
377 local function foo () 339 local function foo ()
378 340
379 local x <close> = 341 local x <close> =
380 func2close(function (self, msg) 342 func2close(function (self, msg)
381 assert(string.find(msg, "@z")) 343 assert(string.find(msg, "@y"))
382 error("@x") 344 error("@x")
383 end) 345 end)
384 346
385 local x1 <close> = 347 local x1 <close> =
386 func2close(function (self, msg) 348 func2close(function (self, msg)
387 checkwarn("@y") 349 assert(string.find(msg, "@y"))
388 assert(string.find(msg, "@z"))
389 end) 350 end)
390 351
391 local gc <close> = func2close(function () collectgarbage() end) 352 local gc <close> = func2close(function () collectgarbage() end)
@@ -406,8 +367,7 @@ do print("testing errors in __close")
406 end 367 end
407 368
408 local stat, msg = pcall(foo, false) 369 local stat, msg = pcall(foo, false)
409 assert(string.find(msg, "@z")) 370 assert(string.find(msg, "@x"))
410 checkwarn("@x")
411 371
412 372
413 -- original error not in __close 373 -- original error not in __close
@@ -418,14 +378,13 @@ do print("testing errors in __close")
418 -- after error, 'foo' was discarded, so caller now 378 -- after error, 'foo' was discarded, so caller now
419 -- must be 'pcall' 379 -- must be 'pcall'
420 assert(debug.getinfo(2).name == "pcall") 380 assert(debug.getinfo(2).name == "pcall")
421 assert(msg == 4) 381 assert(string.find(msg, "@x1"))
422 end) 382 end)
423 383
424 local x1 <close> = 384 local x1 <close> =
425 func2close(function (self, msg) 385 func2close(function (self, msg)
426 assert(debug.getinfo(2).name == "pcall") 386 assert(debug.getinfo(2).name == "pcall")
427 checkwarn("@y") 387 assert(string.find(msg, "@y"))
428 assert(msg == 4)
429 error("@x1") 388 error("@x1")
430 end) 389 end)
431 390
@@ -434,8 +393,7 @@ do print("testing errors in __close")
434 local y <close> = 393 local y <close> =
435 func2close(function (self, msg) 394 func2close(function (self, msg)
436 assert(debug.getinfo(2).name == "pcall") 395 assert(debug.getinfo(2).name == "pcall")
437 assert(msg == 4) -- error in body 396 assert(string.find(msg, "@z"))
438 checkwarn("@z")
439 error("@y") 397 error("@y")
440 end) 398 end)
441 399
@@ -453,8 +411,7 @@ do print("testing errors in __close")
453 end 411 end
454 412
455 local stat, msg = pcall(foo, true) 413 local stat, msg = pcall(foo, true)
456 assert(msg == 4) 414 assert(string.find(msg, "@x1"))
457 checkwarn("@x1") -- last error
458 415
459 -- error leaving a block 416 -- error leaving a block
460 local function foo (...) 417 local function foo (...)
@@ -466,7 +423,8 @@ do print("testing errors in __close")
466 end) 423 end)
467 424
468 local x123 <close> = 425 local x123 <close> =
469 func2close(function () 426 func2close(function (_, msg)
427 assert(msg == nil)
470 error("@X") 428 error("@X")
471 end) 429 end)
472 end 430 end
@@ -474,9 +432,7 @@ do print("testing errors in __close")
474 end 432 end
475 433
476 local st, msg = xpcall(foo, debug.traceback) 434 local st, msg = xpcall(foo, debug.traceback)
477 assert(string.match(msg, "^[^ ]* @X")) 435 assert(string.match(msg, "^[^ ]* @Y"))
478 assert(string.find(msg, "in metamethod 'close'"))
479 checkwarn("@Y")
480 436
481 -- error in toclose in vararg function 437 -- error in toclose in vararg function
482 local function foo (...) 438 local function foo (...)
@@ -486,7 +442,6 @@ do print("testing errors in __close")
486 local st, msg = xpcall(foo, debug.traceback) 442 local st, msg = xpcall(foo, debug.traceback)
487 assert(string.match(msg, "^[^ ]* @x123")) 443 assert(string.match(msg, "^[^ ]* @x123"))
488 assert(string.find(msg, "in metamethod 'close'")) 444 assert(string.find(msg, "in metamethod 'close'"))
489 endwarn()
490end 445end
491 446
492 447
@@ -511,8 +466,6 @@ end
511 466
512if rawget(_G, "T") then 467if rawget(_G, "T") then
513 468
514 warn("@off")
515
516 -- memory error inside closing function 469 -- memory error inside closing function
517 local function foo () 470 local function foo ()
518 local y <close> = func2close(function () T.alloccount() end) 471 local y <close> = func2close(function () T.alloccount() end)
@@ -527,7 +480,7 @@ if rawget(_G, "T") then
527 -- despite memory error, 'y' will be executed and 480 -- despite memory error, 'y' will be executed and
528 -- memory limit will be lifted 481 -- memory limit will be lifted
529 local _, msg = pcall(foo) 482 local _, msg = pcall(foo)
530 assert(msg == 1000) 483 assert(msg == "not enough memory")
531 484
532 local close = func2close(function (self, msg) 485 local close = func2close(function (self, msg)
533 T.alloccount() 486 T.alloccount()
@@ -570,7 +523,7 @@ if rawget(_G, "T") then
570 end 523 end
571 524
572 local _, msg = pcall(test) 525 local _, msg = pcall(test)
573 assert(msg == "not enough memory") -- reported error is the first one 526 assert(msg == 1000)
574 527
575 do -- testing 'toclose' in C string buffer 528 do -- testing 'toclose' in C string buffer
576 collectgarbage() 529 collectgarbage()
@@ -625,7 +578,6 @@ if rawget(_G, "T") then
625 print'+' 578 print'+'
626 end 579 end
627 580
628 warn("@on")
629end 581end
630 582
631 583
@@ -655,14 +607,14 @@ end
655 607
656 608
657do 609do
658 prepwarn()
659 610
660 -- error in a wrapped coroutine raising errors when closing a variable 611 -- error in a wrapped coroutine raising errors when closing a variable
661 local x = 0 612 local x = 0
662 local co = coroutine.wrap(function () 613 local co = coroutine.wrap(function ()
663 local xx <close> = func2close(function () 614 local xx <close> = func2close(function (_, msg)
664 x = x + 1; 615 x = x + 1;
665 checkwarn("@XXX"); error("@YYY") 616 assert(string.find(msg, "@XXX"))
617 error("@YYY")
666 end) 618 end)
667 local xv <close> = func2close(function () x = x + 1; error("@XXX") end) 619 local xv <close> = func2close(function () x = x + 1; error("@XXX") end)
668 coroutine.yield(100) 620 coroutine.yield(100)
@@ -670,8 +622,7 @@ do
670 end) 622 end)
671 assert(co() == 100); assert(x == 0) 623 assert(co() == 100); assert(x == 0)
672 local st, msg = pcall(co); assert(x == 2) 624 local st, msg = pcall(co); assert(x == 2)
673 assert(not st and msg == 200) -- should get first error raised 625 assert(not st and string.find(msg, "@YYY")) -- should get error raised
674 checkwarn("@YYY")
675 626
676 local x = 0 627 local x = 0
677 local y = 0 628 local y = 0
@@ -691,10 +642,8 @@ do
691 local st, msg = pcall(co) 642 local st, msg = pcall(co)
692 assert(x == 1 and y == 1) 643 assert(x == 1 and y == 1)
693 -- should get first error raised 644 -- should get first error raised
694 assert(not st and string.find(msg, "%w+%.%w+:%d+: XXX")) 645 assert(not st and string.find(msg, "%w+%.%w+:%d+: YYY"))
695 checkwarn("YYY")
696 646
697 endwarn()
698end 647end
699 648
700 649