Improvement in warn-mode '@store' (for testing)

When using warn-mode '@store', from the test library, the tests ensure
not only that the expected warnings were issued, but also that there was
no extra warnings.
diff --git a/ltests.c b/ltests.c
index b460d01..95c41fd 100644
--- a/ltests.c
+++ b/ltests.c
@@ -62,8 +62,10 @@
 }
 
 
-static void badexit (const char *fmt, const char *s) {
-  fprintf(stderr, fmt, s);
+static void badexit (const char *fmt, const char *s1, const char *s2) {
+  fprintf(stderr, fmt, s1);
+  if (s2)
+    fprintf(stderr, "extra info: %s\n", s2);
   /* avoid assertion failures when exiting */
   l_memcontrol.numblocks = l_memcontrol.total = 0;
   exit(EXIT_FAILURE);
@@ -72,7 +74,7 @@
 
 static int tpanic (lua_State *L) {
   return (badexit("PANIC: unprotected error in call to Lua API (%s)\n",
-                   lua_tostring(L, -1)),
+                   lua_tostring(L, -1), NULL),
           0);  /* do not return to Lua */
 }
 
@@ -88,13 +90,14 @@
 ** - 2.store: all warnings go to the global '_WARN';
 */
 static void warnf (void *ud, const char *msg, int tocont) {
+  lua_State *L = cast(lua_State *, ud);
   static char buff[200] = "";  /* should be enough for tests... */
   static int onoff = 1;
   static int mode = 0;  /* start in normal mode */
   static int lasttocont = 0;
   if (!lasttocont && !tocont && *msg == '@') {  /* control message? */
     if (buff[0] != '\0')
-      badexit("Control warning during warning: %s\naborting...\n", msg);
+      badexit("Control warning during warning: %s\naborting...\n", msg, buff);
     if (strcmp(msg, "@off") == 0)
       onoff = 0;
     else if (strcmp(msg, "@on") == 0)
@@ -106,18 +109,28 @@
     else if (strcmp(msg, "@store") == 0)
       mode = 2;
     else
-      badexit("Invalid control warning in test mode: %s\naborting...\n", msg);
+      badexit("Invalid control warning in test mode: %s\naborting...\n",
+              msg, NULL);
     return;
   }
   lasttocont = tocont;
   if (strlen(msg) >= sizeof(buff) - strlen(buff))
-    badexit("%s", "warnf-buffer overflow");
+    badexit("warnf-buffer overflow (%s)\n", msg, buff);
   strcat(buff, msg);  /* add new message to current warning */
   if (!tocont) {  /* message finished? */
+    lua_unlock(L);
+    if (lua_getglobal(L, "_WARN") == LUA_TNIL)
+      lua_pop(L, 1);  /* ok, no previous unexpected warning */
+    else {
+      badexit("Unhandled warning in store mode: %s\naborting...\n",
+              lua_tostring(L, -1), buff);
+    }
+    lua_lock(L);
     switch (mode) {
       case 0: {  /* normal */
         if (buff[0] != '#' && onoff)  /* unexpected warning? */
-          badexit("Unexpected warning in test mode: %s\naborting...\n", buff);
+          badexit("Unexpected warning in test mode: %s\naborting...\n",
+                  buff, NULL);
         /* else */ /* FALLTHROUGH */
       }
       case 1: {  /* allow */
@@ -126,7 +139,6 @@
         break;
       }
       case 2: {  /* store */
-        lua_State *L = cast(lua_State *, ud);
         lua_unlock(L);
         lua_pushstring(L, buff);
         lua_setglobal(L, "_WARN");  /* assign message to global '_WARN' */
diff --git a/testes/coroutine.lua b/testes/coroutine.lua
index 79c72a9..4fc2326 100644
--- a/testes/coroutine.lua
+++ b/testes/coroutine.lua
@@ -177,10 +177,15 @@
   end)
   coroutine.resume(co)
   assert(x == 0)
-  _WARN = nil; warn("@off"); warn("@store")
+  -- with test library, use 'store' mode to check warnings
+  warn(not T and "@off" or "@store")
   local st, msg = coroutine.close(co)
-  warn("@on"); warn("@normal")
-  assert(_WARN == nil or string.find(_WARN, "200"))
+  if not T then
+    warn("@on")
+  else   -- test library
+    assert(string.find(_WARN, "200")); _WARN = nil
+    warn("@normal")
+  end
   assert(st == false and coroutine.status(co) == "dead" and msg == 111)
   assert(x == 200)
 
diff --git a/testes/gc.lua b/testes/gc.lua
index 6bdc98c..34854d6 100644
--- a/testes/gc.lua
+++ b/testes/gc.lua
@@ -372,7 +372,7 @@
   warn("@store")
   collectgarbage()
   assert(string.find(_WARN, "error in __gc metamethod"))
-  assert(string.match(_WARN, "@(.-)@") == "expected")
+  assert(string.match(_WARN, "@(.-)@") == "expected"); _WARN = nil
   for i = 8, 10 do assert(s[i]) end
 
   for i = 1, 5 do
@@ -481,6 +481,7 @@
   u = setmetatable({}, {__gc = function () error "@expected error" end})
   u = nil
   collectgarbage()
+  assert(string.find(_WARN, "@expected error")); _WARN = nil
   warn("@normal")
 end
 
@@ -663,9 +664,8 @@
     else
       assert(lastmsg == _WARN)  -- subsequent error messages are equal
     end
-    warn("@store")
+    warn("@store"); _WARN = nil
     error"@expected warning"
-    warn("@normal")
   end}
   for i = 10, 1, -1 do
     -- create object and preserve it until the end
diff --git a/testes/locals.lua b/testes/locals.lua
index 595e107..b4de523 100644
--- a/testes/locals.lua
+++ b/testes/locals.lua
@@ -288,9 +288,8 @@
 
 -- auxiliary functions for testing warnings in '__close'
 local function prepwarn ()
-  warn("@off")      -- do not show (lots of) warnings
-  if not T then
-    _WARN = "OFF"    -- signal that warnings are not being captured
+  if not T then   -- no test library?
+    warn("@off")      -- do not show (lots of) warnings
   else
     warn("@store")    -- to test the warnings
   end
@@ -298,15 +297,20 @@
 
 
 local function endwarn ()
-  assert(T or _WARN == "OFF")
-  warn("@on")          -- back to normal
-  warn("@normal")
-  _WARN = nil
+  if not T then
+    warn("@on")          -- back to normal
+  else
+    assert(_WARN == nil)
+    warn("@normal")
+  end
 end
 
 
 local function checkwarn (msg)
-  assert(_WARN == "OFF" or string.find(_WARN, msg))
+  if T then
+    assert(string.find(_WARN, msg))
+    _WARN = nil    -- reset variable to check next warning
+  end
 end
 
 
@@ -333,7 +337,8 @@
 
     local y <close> =
       func2close(function (self, msg)
-        assert(string.find(msg, "@z"))  -- error in 'z'
+        assert(string.find(msg, "@z"))  -- first error in 'z'
+        checkwarn("@z")   -- second error in 'z' generated a warning
         error("@y")
       end)
 
@@ -377,14 +382,14 @@
 
     local y <close> =
       func2close(function (self, msg)
-         assert(msg == 4)   -- error in body
+        assert(msg == 4)   -- error in body
+        checkwarn("@z")
         error("@y")
       end)
 
     local first = true
     local z <close> =
       func2close(function (self, msg)
-        checkwarn("@z")
         -- 'z' close is called once
         assert(first and msg == 4)
         first = false
@@ -418,16 +423,18 @@
   local st, msg = xpcall(foo, debug.traceback)
   assert(string.match(msg, "^[^ ]* @X"))
   assert(string.find(msg, "in metamethod 'close'"))
+  checkwarn("@Y")
 
   -- error in toclose in vararg function
   local function foo (...)
-    local x123 <close> = func2close(function () error("@X") end)
+    local x123 <close> = func2close(function () error("@x123") end)
   end
 
   local st, msg = xpcall(foo, debug.traceback)
-  assert(string.match(msg, "^[^ ]* @X"))
-
+  assert(string.match(msg, "^[^ ]* @x123"))
   assert(string.find(msg, "in metamethod 'close'"))
+  checkwarn("@x123")   -- from second call to close 'x123'
+
   endwarn()
 end
 
diff --git a/testes/main.lua b/testes/main.lua
index 0ef4822..3622036 100644
--- a/testes/main.lua
+++ b/testes/main.lua
@@ -379,12 +379,12 @@
   -- testing 'warn'
   warn("@store")
   warn("@123", "456", "789")
-  assert(_WARN == "@123456789")
+  assert(_WARN == "@123456789"); _WARN = nil
 
   warn("zip", "", " ", "zap")
-  assert(_WARN == "zip zap")
+  assert(_WARN == "zip zap"); _WARN = nil
   warn("ZIP", "", " ", "ZAP")
-  assert(_WARN == "ZIP ZAP")
+  assert(_WARN == "ZIP ZAP"); _WARN = nil
   warn("@normal")
 end