aboutsummaryrefslogtreecommitdiff
path: root/testes/memerr.lua
diff options
context:
space:
mode:
Diffstat (limited to 'testes/memerr.lua')
-rw-r--r--testes/memerr.lua266
1 files changed, 266 insertions, 0 deletions
diff --git a/testes/memerr.lua b/testes/memerr.lua
new file mode 100644
index 00000000..cb236eb9
--- /dev/null
+++ b/testes/memerr.lua
@@ -0,0 +1,266 @@
1-- $Id: testes/memerr.lua $
2-- See Copyright Notice in file all.lua
3
4
5local function checkerr (msg, f, ...)
6 local stat, err = pcall(f, ...)
7 assert(not stat and string.find(err, msg))
8end
9
10if T==nil then
11 (Message or print)
12 ('\n >>> testC not active: skipping memory error tests <<<\n')
13 return
14end
15
16print("testing memory-allocation errors")
17
18local debug = require "debug"
19
20local pack = table.pack
21
22-- standard error message for memory errors
23local MEMERRMSG = "not enough memory"
24
25
26-- memory error in panic function
27T.totalmem(T.totalmem()+10000) -- set low memory limit (+10k)
28assert(T.checkpanic("newuserdata 20000") == MEMERRMSG)
29T.totalmem(0) -- restore high limit
30
31
32
33-- {==================================================================
34-- Testing memory limits
35-- ===================================================================
36
37checkerr("block too big", T.newuserdata, math.maxinteger)
38collectgarbage()
39local f = load"local a={}; for i=1,100000 do a[i]=i end"
40T.alloccount(10)
41checkerr(MEMERRMSG, f)
42T.alloccount() -- remove limit
43
44
45-- test memory errors; increase limit for maximum memory by steps,
46-- o that we get memory errors in all allocations of a given
47-- task, until there is enough memory to complete the task without
48-- errors.
49local function testbytes (s, f)
50 collectgarbage()
51 local M = T.totalmem()
52 local oldM = M
53 local a,b = nil
54 while true do
55 collectgarbage(); collectgarbage()
56 T.totalmem(M)
57 a, b = T.testC("pcall 0 1 0; pushstatus; return 2", f)
58 T.totalmem(0) -- remove limit
59 if a and b == "OK" then break end -- stop when no more errors
60 if b ~= "OK" and b ~= MEMERRMSG then -- not a memory error?
61 error(a, 0) -- propagate it
62 end
63 M = M + 7 -- increase memory limit
64 end
65 print(string.format("minimum memory for %s: %d bytes", s, M - oldM))
66 return a
67end
68
69-- test memory errors; increase limit for number of allocations one
70-- by one, so that we get memory errors in all allocations of a given
71-- task, until there is enough allocations to complete the task without
72-- errors.
73
74local function testalloc (s, f)
75 collectgarbage()
76 local M = 0
77 local a,b = nil
78 while true do
79 collectgarbage(); collectgarbage()
80 T.alloccount(M)
81 a, b = T.testC("pcall 0 1 0; pushstatus; return 2", f)
82 T.alloccount() -- remove limit
83 if a and b == "OK" then break end -- stop when no more errors
84 if b ~= "OK" and b ~= MEMERRMSG then -- not a memory error?
85 error(a, 0) -- propagate it
86 end
87 M = M + 1 -- increase allocation limit
88 end
89 print(string.format("minimum allocations for %s: %d allocations", s, M))
90 return a
91end
92
93
94local function testamem (s, f)
95 testalloc(s, f)
96 return testbytes(s, f)
97end
98
99
100-- doing nothing
101b = testamem("doing nothing", function () return 10 end)
102assert(b == 10)
103
104-- testing memory errors when creating a new state
105
106testamem("state creation", function ()
107 local st = T.newstate()
108 if st then T.closestate(st) end -- close new state
109 return st
110end)
111
112testamem("empty-table creation", function ()
113 return {}
114end)
115
116testamem("string creation", function ()
117 return "XXX" .. "YYY"
118end)
119
120testamem("coroutine creation", function()
121 return coroutine.create(print)
122end)
123
124
125-- testing to-be-closed variables
126testamem("to-be-closed variables", function()
127 local flag
128 do
129 local x <close> =
130 setmetatable({}, {__close = function () flag = true end})
131 flag = false
132 local x = {}
133 end
134 return flag
135end)
136
137
138-- testing threads
139
140-- get main thread from registry
141local mt = T.testC("rawgeti R !M; return 1")
142assert(type(mt) == "thread" and coroutine.running() == mt)
143
144
145
146local function expand (n,s)
147 if n==0 then return "" end
148 local e = string.rep("=", n)
149 return string.format("T.doonnewstack([%s[ %s;\n collectgarbage(); %s]%s])\n",
150 e, s, expand(n-1,s), e)
151end
152
153G=0; collectgarbage(); a =collectgarbage("count")
154load(expand(20,"G=G+1"))()
155assert(G==20); collectgarbage(); -- assert(gcinfo() <= a+1)
156G = nil
157
158testamem("running code on new thread", function ()
159 return T.doonnewstack("local x=1") == 0 -- try to create thread
160end)
161
162
163-- testing memory x compiler
164
165testamem("loadstring", function ()
166 return load("x=1") -- try to do load a string
167end)
168
169
170local testprog = [[
171local function foo () return end
172local t = {"x"}
173AA = "aaa"
174for i = 1, #t do AA = AA .. t[i] end
175return true
176]]
177
178-- testing memory x dofile
179_G.AA = nil
180local t =os.tmpname()
181local f = assert(io.open(t, "w"))
182f:write(testprog)
183f:close()
184testamem("dofile", function ()
185 local a = loadfile(t)
186 return a and a()
187end)
188assert(os.remove(t))
189assert(_G.AA == "aaax")
190
191
192-- other generic tests
193
194testamem("gsub", function ()
195 local a, b = string.gsub("alo alo", "(a)", function (x) return x..'b' end)
196 return (a == 'ablo ablo')
197end)
198
199testamem("dump/undump", function ()
200 local a = load(testprog)
201 local b = a and string.dump(a)
202 a = b and load(b)
203 return a and a()
204end)
205
206_G.AA = nil
207
208local t = os.tmpname()
209testamem("file creation", function ()
210 local f = assert(io.open(t, 'w'))
211 assert (not io.open"nomenaoexistente")
212 io.close(f);
213 return not loadfile'nomenaoexistente'
214end)
215assert(os.remove(t))
216
217testamem("table creation", function ()
218 local a, lim = {}, 10
219 for i=1,lim do a[i] = i; a[i..'a'] = {} end
220 return (type(a[lim..'a']) == 'table' and a[lim] == lim)
221end)
222
223testamem("constructors", function ()
224 local a = {10, 20, 30, 40, 50; a=1, b=2, c=3, d=4, e=5}
225 return (type(a) == 'table' and a.e == 5)
226end)
227
228local a = 1
229local close = nil
230testamem("closure creation", function ()
231 function close (b)
232 return function (x) return b + x end
233 end
234 return (close(2)(4) == 6)
235end)
236
237testamem("using coroutines", function ()
238 local a = coroutine.wrap(function ()
239 coroutine.yield(string.rep("a", 10))
240 return {}
241 end)
242 assert(string.len(a()) == 10)
243 return a()
244end)
245
246do -- auxiliary buffer
247 local lim = 100
248 local a = {}; for i = 1, lim do a[i] = "01234567890123456789" end
249 testamem("auxiliary buffer", function ()
250 return (#table.concat(a, ",") == 20*lim + lim - 1)
251 end)
252end
253
254testamem("growing stack", function ()
255 local function foo (n)
256 if n == 0 then return 1 else return 1 + foo(n - 1) end
257 end
258 return foo(100)
259end)
260
261-- }==================================================================
262
263
264print "Ok"
265
266