浏览代码

New test file 'memerr.lua'

Tests for memory-allocation errors moved from 'api.lua' to this new
file, as 'api.lua' was already too big. (Besides, these tests have
nothing to do with the API.)
Roberto Ierusalimschy 4 月之前
父节点
当前提交
4398e488e6
共有 4 个文件被更改,包括 268 次插入243 次删除
  1. 1 0
      testes/all.lua
  2. 0 243
      testes/api.lua
  3. 266 0
      testes/memerr.lua
  4. 1 0
      testes/packtests

+ 1 - 0
testes/all.lua

@@ -182,6 +182,7 @@ dofile('nextvar.lua')
 dofile('pm.lua')
 dofile('utf8.lua')
 dofile('api.lua')
+dofile('memerr.lua')
 assert(dofile('events.lua') == 12)
 dofile('vararg.lua')
 dofile('closure.lua')

+ 0 - 243
testes/api.lua

@@ -11,9 +11,6 @@ local debug = require "debug"
 local pack = table.pack
 
 
--- standard error message for memory errors
-local MEMERRMSG = "not enough memory"
-
 local function tcheck (t1, t2)
   assert(t1.n == (t2.n or #t2) + 1)
   for i = 2, t1.n do assert(t1[i] == t2[i - 1]) end
@@ -432,11 +429,6 @@ do
       "bad argument #4 (string expected, got no value)")
 
 
-  -- memory error
-  T.totalmem(T.totalmem()+10000)   -- set low memory limit (+10k)
-  assert(T.checkpanic("newuserdata 20000") == MEMERRMSG)
-  T.totalmem(0)          -- restore high limit
-
   -- memory error + thread status
   local x = T.checkpanic(
     [[ alloccount 0    # force a memory error in next line
@@ -1306,241 +1298,6 @@ do
 end
 
 
---[[
-** {==================================================================
-** Testing memory limits
-** ===================================================================
---]]
-
-print("memory-allocation errors")
-
-checkerr("block too big", T.newuserdata, math.maxinteger)
-collectgarbage()
-local f = load"local a={}; for i=1,100000 do a[i]=i end"
-T.alloccount(10)
-checkerr(MEMERRMSG, f)
-T.alloccount()          -- remove limit
-
-
--- test memory errors; increase limit for maximum memory by steps,
--- o that we get memory errors in all allocations of a given
--- task, until there is enough memory to complete the task without
--- errors.
-local function testbytes (s, f)
-  collectgarbage()
-  local M = T.totalmem()
-  local oldM = M
-  local a,b = nil
-  while true do
-    collectgarbage(); collectgarbage()
-    T.totalmem(M)
-    a, b = T.testC("pcall 0 1 0; pushstatus; return 2", f)
-    T.totalmem(0)  -- remove limit
-    if a and b == "OK" then break end       -- stop when no more errors
-    if b ~= "OK" and b ~= MEMERRMSG then    -- not a memory error?
-      error(a, 0)   -- propagate it
-    end
-    M = M + 7   -- increase memory limit
-  end
-  print(string.format("minimum memory for %s: %d bytes", s, M - oldM))
-  return a
-end
-
--- test memory errors; increase limit for number of allocations one
--- by one, so that we get memory errors in all allocations of a given
--- task, until there is enough allocations to complete the task without
--- errors.
-
-local function testalloc (s, f)
-  collectgarbage()
-  local M = 0
-  local a,b = nil
-  while true do
-    collectgarbage(); collectgarbage()
-    T.alloccount(M)
-    a, b = T.testC("pcall 0 1 0; pushstatus; return 2", f)
-    T.alloccount()  -- remove limit
-    if a and b == "OK" then break end       -- stop when no more errors
-    if b ~= "OK" and b ~= MEMERRMSG then    -- not a memory error?
-      error(a, 0)   -- propagate it
-    end
-    M = M + 1   -- increase allocation limit
-  end
-  print(string.format("minimum allocations for %s: %d allocations", s, M))
-  return a
-end
-
-
-local function testamem (s, f)
-  testalloc(s, f)
-  return testbytes(s, f)
-end
-
-
--- doing nothing
-b = testamem("doing nothing", function () return 10 end)
-assert(b == 10)
-
--- testing memory errors when creating a new state
-
-testamem("state creation", function ()
-  local st = T.newstate()
-  if st then T.closestate(st) end   -- close new state
-  return st
-end)
-
-testamem("empty-table creation", function ()
-  return {}
-end)
-
-testamem("string creation", function ()
-  return "XXX" .. "YYY"
-end)
-
-testamem("coroutine creation", function()
-           return coroutine.create(print)
-end)
-
-
--- testing to-be-closed variables
-testamem("to-be-closed variables", function()
-  local flag
-  do
-    local x <close> =
-              setmetatable({}, {__close = function () flag = true end})
-    flag = false
-    local x = {}
-  end
-  return flag
-end)
-
-
--- testing threads
-
--- get main thread from registry
-local mt = T.testC("rawgeti R !M; return 1")
-assert(type(mt) == "thread" and coroutine.running() == mt)
-
-
-
-local function expand (n,s)
-  if n==0 then return "" end
-  local e = string.rep("=", n)
-  return string.format("T.doonnewstack([%s[ %s;\n collectgarbage(); %s]%s])\n",
-                              e, s, expand(n-1,s), e)
-end
-
-G=0; collectgarbage(); a =collectgarbage("count")
-load(expand(20,"G=G+1"))()
-assert(G==20); collectgarbage();  -- assert(gcinfo() <= a+1)
-G = nil
-
-testamem("running code on new thread", function ()
-  return T.doonnewstack("local x=1") == 0  -- try to create thread
-end)
-
-
--- testing memory x compiler
-
-testamem("loadstring", function ()
-  return load("x=1")  -- try to do load a string
-end)
-
-
-local testprog = [[
-local function foo () return end
-local t = {"x"}
-AA = "aaa"
-for i = 1, #t do AA = AA .. t[i] end
-return true
-]]
-
--- testing memory x dofile
-_G.AA = nil
-local t =os.tmpname()
-local f = assert(io.open(t, "w"))
-f:write(testprog)
-f:close()
-testamem("dofile", function ()
-  local a = loadfile(t)
-  return a and a()
-end)
-assert(os.remove(t))
-assert(_G.AA == "aaax")
-
-
--- other generic tests
-
-testamem("gsub", function ()
-  local a, b = string.gsub("alo alo", "(a)", function (x) return x..'b' end)
-  return (a == 'ablo ablo')
-end)
-
-testamem("dump/undump", function ()
-  local a = load(testprog)
-  local b = a and string.dump(a)
-  a = b and load(b)
-  return a and a()
-end)
-
-_G.AA = nil
-
-local t = os.tmpname()
-testamem("file creation", function ()
-  local f = assert(io.open(t, 'w'))
-  assert (not io.open"nomenaoexistente")
-  io.close(f);
-  return not loadfile'nomenaoexistente'
-end)
-assert(os.remove(t))
-
-testamem("table creation", function ()
-  local a, lim = {}, 10
-  for i=1,lim do a[i] = i; a[i..'a'] = {} end
-  return (type(a[lim..'a']) == 'table' and a[lim] == lim)
-end)
-
-testamem("constructors", function ()
-  local a = {10, 20, 30, 40, 50; a=1, b=2, c=3, d=4, e=5}
-  return (type(a) == 'table' and a.e == 5)
-end)
-
-local a = 1
-local close = nil
-testamem("closure creation", function ()
-  function close (b)
-   return function (x) return b + x end
-  end
-  return (close(2)(4) == 6)
-end)
-
-testamem("using coroutines", function ()
-  local a = coroutine.wrap(function ()
-              coroutine.yield(string.rep("a", 10))
-              return {}
-            end)
-  assert(string.len(a()) == 10)
-  return a()
-end)
-
-do   -- auxiliary buffer
-  local lim = 100
-  local a = {}; for i = 1, lim do a[i] = "01234567890123456789" end
-  testamem("auxiliary buffer", function ()
-    return (#table.concat(a, ",") == 20*lim + lim - 1)
-  end)
-end
-
-testamem("growing stack", function ()
-  local function foo (n)
-    if n == 0 then return 1 else return 1 + foo(n - 1) end
-  end
-  return foo(100)
-end)
-
--- }==================================================================
-
-
 do   -- testing failing in 'lua_checkstack'
   local res = T.testC([[rawcheckstack 500000; return 1]])
   assert(res == false)

+ 266 - 0
testes/memerr.lua

@@ -0,0 +1,266 @@
+-- $Id: testes/memerr.lua $
+-- See Copyright Notice in file all.lua
+
+
+local function checkerr (msg, f, ...)
+  local stat, err = pcall(f, ...)
+  assert(not stat and string.find(err, msg))
+end
+
+if T==nil then
+  (Message or print)
+      ('\n >>> testC not active: skipping memory error tests <<<\n')
+  return
+end
+
+print("testing memory-allocation errors")
+
+local debug = require "debug"
+
+local pack = table.pack
+
+-- standard error message for memory errors
+local MEMERRMSG = "not enough memory"
+
+
+-- memory error in panic function
+T.totalmem(T.totalmem()+10000)   -- set low memory limit (+10k)
+assert(T.checkpanic("newuserdata 20000") == MEMERRMSG)
+T.totalmem(0)          -- restore high limit
+
+
+
+-- {==================================================================
+-- Testing memory limits
+-- ===================================================================
+
+checkerr("block too big", T.newuserdata, math.maxinteger)
+collectgarbage()
+local f = load"local a={}; for i=1,100000 do a[i]=i end"
+T.alloccount(10)
+checkerr(MEMERRMSG, f)
+T.alloccount()          -- remove limit
+
+
+-- test memory errors; increase limit for maximum memory by steps,
+-- o that we get memory errors in all allocations of a given
+-- task, until there is enough memory to complete the task without
+-- errors.
+local function testbytes (s, f)
+  collectgarbage()
+  local M = T.totalmem()
+  local oldM = M
+  local a,b = nil
+  while true do
+    collectgarbage(); collectgarbage()
+    T.totalmem(M)
+    a, b = T.testC("pcall 0 1 0; pushstatus; return 2", f)
+    T.totalmem(0)  -- remove limit
+    if a and b == "OK" then break end       -- stop when no more errors
+    if b ~= "OK" and b ~= MEMERRMSG then    -- not a memory error?
+      error(a, 0)   -- propagate it
+    end
+    M = M + 7   -- increase memory limit
+  end
+  print(string.format("minimum memory for %s: %d bytes", s, M - oldM))
+  return a
+end
+
+-- test memory errors; increase limit for number of allocations one
+-- by one, so that we get memory errors in all allocations of a given
+-- task, until there is enough allocations to complete the task without
+-- errors.
+
+local function testalloc (s, f)
+  collectgarbage()
+  local M = 0
+  local a,b = nil
+  while true do
+    collectgarbage(); collectgarbage()
+    T.alloccount(M)
+    a, b = T.testC("pcall 0 1 0; pushstatus; return 2", f)
+    T.alloccount()  -- remove limit
+    if a and b == "OK" then break end       -- stop when no more errors
+    if b ~= "OK" and b ~= MEMERRMSG then    -- not a memory error?
+      error(a, 0)   -- propagate it
+    end
+    M = M + 1   -- increase allocation limit
+  end
+  print(string.format("minimum allocations for %s: %d allocations", s, M))
+  return a
+end
+
+
+local function testamem (s, f)
+  testalloc(s, f)
+  return testbytes(s, f)
+end
+
+
+-- doing nothing
+b = testamem("doing nothing", function () return 10 end)
+assert(b == 10)
+
+-- testing memory errors when creating a new state
+
+testamem("state creation", function ()
+  local st = T.newstate()
+  if st then T.closestate(st) end   -- close new state
+  return st
+end)
+
+testamem("empty-table creation", function ()
+  return {}
+end)
+
+testamem("string creation", function ()
+  return "XXX" .. "YYY"
+end)
+
+testamem("coroutine creation", function()
+           return coroutine.create(print)
+end)
+
+
+-- testing to-be-closed variables
+testamem("to-be-closed variables", function()
+  local flag
+  do
+    local x <close> =
+              setmetatable({}, {__close = function () flag = true end})
+    flag = false
+    local x = {}
+  end
+  return flag
+end)
+
+
+-- testing threads
+
+-- get main thread from registry
+local mt = T.testC("rawgeti R !M; return 1")
+assert(type(mt) == "thread" and coroutine.running() == mt)
+
+
+
+local function expand (n,s)
+  if n==0 then return "" end
+  local e = string.rep("=", n)
+  return string.format("T.doonnewstack([%s[ %s;\n collectgarbage(); %s]%s])\n",
+                              e, s, expand(n-1,s), e)
+end
+
+G=0; collectgarbage(); a =collectgarbage("count")
+load(expand(20,"G=G+1"))()
+assert(G==20); collectgarbage();  -- assert(gcinfo() <= a+1)
+G = nil
+
+testamem("running code on new thread", function ()
+  return T.doonnewstack("local x=1") == 0  -- try to create thread
+end)
+
+
+-- testing memory x compiler
+
+testamem("loadstring", function ()
+  return load("x=1")  -- try to do load a string
+end)
+
+
+local testprog = [[
+local function foo () return end
+local t = {"x"}
+AA = "aaa"
+for i = 1, #t do AA = AA .. t[i] end
+return true
+]]
+
+-- testing memory x dofile
+_G.AA = nil
+local t =os.tmpname()
+local f = assert(io.open(t, "w"))
+f:write(testprog)
+f:close()
+testamem("dofile", function ()
+  local a = loadfile(t)
+  return a and a()
+end)
+assert(os.remove(t))
+assert(_G.AA == "aaax")
+
+
+-- other generic tests
+
+testamem("gsub", function ()
+  local a, b = string.gsub("alo alo", "(a)", function (x) return x..'b' end)
+  return (a == 'ablo ablo')
+end)
+
+testamem("dump/undump", function ()
+  local a = load(testprog)
+  local b = a and string.dump(a)
+  a = b and load(b)
+  return a and a()
+end)
+
+_G.AA = nil
+
+local t = os.tmpname()
+testamem("file creation", function ()
+  local f = assert(io.open(t, 'w'))
+  assert (not io.open"nomenaoexistente")
+  io.close(f);
+  return not loadfile'nomenaoexistente'
+end)
+assert(os.remove(t))
+
+testamem("table creation", function ()
+  local a, lim = {}, 10
+  for i=1,lim do a[i] = i; a[i..'a'] = {} end
+  return (type(a[lim..'a']) == 'table' and a[lim] == lim)
+end)
+
+testamem("constructors", function ()
+  local a = {10, 20, 30, 40, 50; a=1, b=2, c=3, d=4, e=5}
+  return (type(a) == 'table' and a.e == 5)
+end)
+
+local a = 1
+local close = nil
+testamem("closure creation", function ()
+  function close (b)
+   return function (x) return b + x end
+  end
+  return (close(2)(4) == 6)
+end)
+
+testamem("using coroutines", function ()
+  local a = coroutine.wrap(function ()
+              coroutine.yield(string.rep("a", 10))
+              return {}
+            end)
+  assert(string.len(a()) == 10)
+  return a()
+end)
+
+do   -- auxiliary buffer
+  local lim = 100
+  local a = {}; for i = 1, lim do a[i] = "01234567890123456789" end
+  testamem("auxiliary buffer", function ()
+    return (#table.concat(a, ",") == 20*lim + lim - 1)
+  end)
+end
+
+testamem("growing stack", function ()
+  local function foo (n)
+    if n == 0 then return 1 else return 1 + foo(n - 1) end
+  end
+  return foo(100)
+end)
+
+-- }==================================================================
+
+
+print "Ok"
+
+

+ 1 - 0
testes/packtests

@@ -28,6 +28,7 @@ $NAME/literals.lua  \
 $NAME/locals.lua  \
 $NAME/main.lua  \
 $NAME/math.lua  \
+$NAME/memerr.lua  \
 $NAME/nextvar.lua  \
 $NAME/pm.lua  \
 $NAME/sort.lua  \