aboutsummaryrefslogtreecommitdiff
path: root/testes
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2020-09-23 10:18:01 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2020-10-12 12:29:09 -0300
commit287b302acb8d925178e9edb800f0a8d18c7d35f6 (patch)
treebd662481ea995dc8c050324d553146e870434d93 /testes
parent5d8ce05b3f6fad79e37ed21c1076e47a322472c6 (diff)
downloadlua-287b302acb8d925178e9edb800f0a8d18c7d35f6.tar.gz
lua-287b302acb8d925178e9edb800f0a8d18c7d35f6.tar.bz2
lua-287b302acb8d925178e9edb800f0a8d18c7d35f6.zip
Revision of stackless implementation
- more organized handling of 'nCcalls' - comments - deprecation of 'setcstacklimit'
Diffstat (limited to 'testes')
-rw-r--r--testes/cstack.lua137
-rw-r--r--testes/errors.lua3
2 files changed, 32 insertions, 108 deletions
diff --git a/testes/cstack.lua b/testes/cstack.lua
index c1177f3b..5767adf6 100644
--- a/testes/cstack.lua
+++ b/testes/cstack.lua
@@ -1,75 +1,29 @@
1-- $Id: testes/cstack.lua $ 1-- $Id: testes/cstack.lua $
2-- See Copyright Notice in file all.lua 2-- See Copyright Notice in file all.lua
3 3
4do return end
5
6local debug = require "debug"
7 4
8print"testing C-stack overflow detection" 5print"testing C-stack overflow detection"
9print"If this test crashes, see its file ('cstack.lua')"
10 6
11-- Segmentation faults in these tests probably result from a C-stack 7-- Segmentation faults in these tests probably result from a C-stack
12-- overflow. To avoid these errors, you can use the function 8-- overflow. To avoid these errors, you should set a smaller limit for
13-- 'debug.setcstacklimit' to set a smaller limit for the use of 9-- the use of C stack by Lua, by changing the constant 'LUAI_MAXCCALLS'.
14-- C stack by Lua. After finding a reliable limit, you might want
15-- to recompile Lua with this limit as the value for
16-- the constant 'LUAI_MAXCCALLS', which defines the default limit.
17-- (The default limit is printed by this test.)
18-- Alternatively, you can ensure a larger stack for the program. 10-- Alternatively, you can ensure a larger stack for the program.
19 11
20-- For Linux, a limit up to 30_000 seems Ok. Windows cannot go much
21-- higher than 2_000.
22
23
24-- get and print original limit
25local origlimit <const> = debug.setcstacklimit(400)
26print("default stack limit: " .. origlimit)
27
28
29-- Do the tests using the original limit. Or else you may want to change
30-- 'currentlimit' to lower values to avoid a seg. fault or to higher
31-- values to check whether they are reliable.
32local currentlimit <const> = origlimit
33debug.setcstacklimit(currentlimit)
34print("current stack limit: " .. currentlimit)
35
36 12
37local function checkerror (msg, f, ...) 13local function checkerror (msg, f, ...)
38 local s, err = pcall(f, ...) 14 local s, err = pcall(f, ...)
39 assert(not s and string.find(err, msg)) 15 assert(not s and string.find(err, msg))
40end 16end
41 17
42-- auxiliary function to keep 'count' on the screen even if the program
43-- crashes.
44local count
45local back = string.rep("\b", 8)
46local function progress ()
47 count = count + 1
48 local n = string.format("%-8d", count)
49 io.stderr:write(back, n) -- erase previous value and write new one
50end
51
52
53do print("testing simple recursion:")
54 count = 0
55 local function foo ()
56 progress()
57 foo() -- do recursive calls until a stack error (or crash)
58 end
59 checkerror("stack overflow", foo)
60 print("\tfinal count: ", count)
61end
62
63
64do print("testing stack overflow in message handling") 18do print("testing stack overflow in message handling")
65 count = 0 19 local count = 0
66 local function loop (x, y, z) 20 local function loop (x, y, z)
67 progress() 21 count = count + 1
68 return 1 + loop(x, y, z) 22 return 1 + loop(x, y, z)
69 end 23 end
70 local res, msg = xpcall(loop, loop) 24 local res, msg = xpcall(loop, loop)
71 assert(msg == "error in error handling") 25 assert(msg == "error in error handling")
72 print("\tfinal count: ", count) 26 print("final count: ", count)
73end 27end
74 28
75 29
@@ -82,97 +36,66 @@ do print("testing recursion inside pattern matching")
82 end 36 end
83 local m = f(80) 37 local m = f(80)
84 assert(#m == 80) 38 assert(#m == 80)
85 checkerror("too complex", f, 200000) 39 checkerror("too complex", f, 2000)
86end 40end
87 41
88 42
89do print("testing stack-overflow in recursive 'gsub'") 43do print("testing stack-overflow in recursive 'gsub'")
90 count = 0 44 local count = 0
91 local function foo () 45 local function foo ()
92 progress() 46 count = count + 1
93 string.gsub("a", ".", foo) 47 string.gsub("a", ".", foo)
94 end 48 end
95 checkerror("stack overflow", foo) 49 checkerror("stack overflow", foo)
96 print("\tfinal count: ", count) 50 print("final count: ", count)
97 51
98 print("testing stack-overflow in recursive 'gsub' with metatables") 52 print("testing stack-overflow in recursive 'gsub' with metatables")
99 count = 0 53 local count = 0
100 local t = setmetatable({}, {__index = foo}) 54 local t = setmetatable({}, {__index = foo})
101 foo = function () 55 foo = function ()
102 count = count + 1 56 count = count + 1
103 progress(count)
104 string.gsub("a", ".", t) 57 string.gsub("a", ".", t)
105 end 58 end
106 checkerror("stack overflow", foo) 59 checkerror("stack overflow", foo)
107 print("\tfinal count: ", count) 60 print("final count: ", count)
108end 61end
109 62
63
110do -- bug in 5.4.0 64do -- bug in 5.4.0
111 print("testing limits in coroutines inside deep calls") 65 print("testing limits in coroutines inside deep calls")
112 count = 0 66 local count = 0
113 local lim = 1000 67 local lim = 1000
114 local function stack (n) 68 local function stack (n)
115 progress()
116 if n > 0 then return stack(n - 1) + 1 69 if n > 0 then return stack(n - 1) + 1
117 else coroutine.wrap(function () 70 else coroutine.wrap(function ()
71 count = count + 1
118 stack(lim) 72 stack(lim)
119 end)() 73 end)()
120 end 74 end
121 end 75 end
122 76
123 print(xpcall(stack, function () return "ok" end, lim)) 77 local st, msg = xpcall(stack, function () return "ok" end, lim)
78 assert(not st and msg == "ok")
79 print("final count: ", count)
124end 80end
125 81
126 82
127do print("testing changes in C-stack limit") 83do
84 print("nesting of resuming yielded coroutines")
85 local count = 0
128 86
129 -- Just an alternative limit, different from the current one 87 local function body ()
130 -- (smaller to avoid stack overflows) 88 coroutine.yield()
131 local alterlimit <const> = currentlimit * 8 // 10 89 local f = coroutine.wrap(body)
132 90 f(); -- start new coroutine (will stop in previous yield)
133 assert(not debug.setcstacklimit(0)) -- limit too small 91 count = count + 1
134 assert(not debug.setcstacklimit(50000)) -- limit too large 92 f() -- call it recursively
135 local co = coroutine.wrap (function ()
136 return debug.setcstacklimit(alterlimit)
137 end)
138 assert(not co()) -- cannot change C stack inside coroutine
139
140 local n
141 local function foo () n = n + 1; foo () end
142
143 local function check ()
144 n = 0
145 pcall(foo)
146 return n
147 end 93 end
148 94
149 -- set limit to 'alterlimit' 95 local f = coroutine.wrap(body)
150 assert(debug.setcstacklimit(alterlimit) == currentlimit) 96 f()
151 local limalter <const> = check() 97 assert(not pcall(f))
152 -- set a very low limit (given that there are already several active 98 print("final count: ", count)
153 -- calls to arrive here)
154 local lowlimit <const> = 38
155 assert(debug.setcstacklimit(lowlimit) == alterlimit)
156 -- usable limit is much lower, due to active calls
157 local actuallow = check()
158 assert(actuallow < lowlimit - 30)
159 -- now, add 'lowlimit' extra slots, which should all be available
160 assert(debug.setcstacklimit(lowlimit + lowlimit) == lowlimit)
161 local lim2 <const> = check()
162 assert(lim2 == actuallow + lowlimit)
163
164
165 -- 'setcstacklimit' works inside protected calls. (The new stack
166 -- limit is kept when 'pcall' returns.)
167 assert(pcall(function ()
168 assert(debug.setcstacklimit(alterlimit) == lowlimit * 2)
169 assert(check() <= limalter)
170 end))
171
172 assert(check() == limalter)
173 -- restore original limit
174 assert(debug.setcstacklimit(origlimit) == alterlimit)
175end 99end
176 100
177
178print'OK' 101print'OK'
diff --git a/testes/errors.lua b/testes/errors.lua
index 88918df7..f975b3dd 100644
--- a/testes/errors.lua
+++ b/testes/errors.lua
@@ -532,7 +532,8 @@ local function testrep (init, rep, close, repc, finalresult)
532 end 532 end
533 s = init .. string.rep(rep, 500) 533 s = init .. string.rep(rep, 500)
534 local res, msg = load(s) -- 500 levels not ok 534 local res, msg = load(s) -- 500 levels not ok
535 assert(not res and string.find(msg, "too many")) 535 assert(not res and (string.find(msg, "too many") or
536 string.find(msg, "overflow")))
536end 537end
537 538
538testrep("local a; a", ",a", "= 1", ",1") -- multiple assignment 539testrep("local a; a", ",a", "= 1", ",1") -- multiple assignment