github.com/xyproto/gopher-lua@v1.0.2/_lua5.1-tests/errors.lua (about) 1 print("testing errors") 2 3 function doit (s) 4 local f, msg = loadstring(s) 5 if f == nil then return msg end 6 local cond, msg = pcall(f) 7 return (not cond) and msg 8 end 9 10 11 function checkmessage (prog, msg) 12 assert(string.find(doit(prog), msg, 1, true)) 13 end 14 15 function checksyntax (prog, extra, token, line) 16 local msg = doit(prog) 17 token = string.gsub(token, "(%p)", "%%%1") 18 local pt = string.format([[^%%[string ".*"%%]:%d: .- near '%s'$]], 19 line, token) 20 assert(string.find(msg, pt)) 21 assert(string.find(msg, msg, 1, true)) 22 end 23 24 25 -- test error message with no extra info 26 assert(doit("error('hi', 0)") == 'hi') 27 28 -- test error message with no info 29 assert(doit("error()") == nil) 30 31 32 -- test common errors/errors that crashed in the past 33 assert(doit("unpack({}, 1, n=2^30)")) 34 assert(doit("a=math.sin()")) 35 assert(not doit("tostring(1)") and doit("tostring()")) 36 assert(doit"tonumber()") 37 assert(doit"repeat until 1; a") 38 checksyntax("break label", "", "label", 1) 39 assert(doit";") 40 assert(doit"a=1;;") 41 assert(doit"return;;") 42 assert(doit"assert(false)") 43 assert(doit"assert(nil)") 44 assert(doit"a=math.sin\n(3)") 45 assert(doit("function a (... , ...) end")) 46 assert(doit("function a (, ...) end")) 47 48 checksyntax([[ 49 local a = {4 50 51 ]], "'}' expected (to close '{' at line 1)", "<eof>", 3) 52 53 54 -- tests for better error messages 55 56 checkmessage("a=1; bbbb=2; a=math.sin(3)+bbbb(3)", "global 'bbbb'") 57 checkmessage("a=1; local a,bbbb=2,3; a = math.sin(1) and bbbb(3)", 58 "local 'bbbb'") 59 checkmessage("a={}; do local a=1 end a:bbbb(3)", "method 'bbbb'") 60 checkmessage("local a={}; a.bbbb(3)", "field 'bbbb'") 61 assert(not string.find(doit"a={13}; local bbbb=1; a[bbbb](3)", "'bbbb'")) 62 checkmessage("a={13}; local bbbb=1; a[bbbb](3)", "number") 63 64 aaa = nil 65 checkmessage("aaa.bbb:ddd(9)", "global 'aaa'") 66 checkmessage("local aaa={bbb=1}; aaa.bbb:ddd(9)", "field 'bbb'") 67 checkmessage("local aaa={bbb={}}; aaa.bbb:ddd(9)", "method 'ddd'") 68 checkmessage("local a,b,c; (function () a = b+1 end)()", "upvalue 'b'") 69 assert(not doit"local aaa={bbb={ddd=next}}; aaa.bbb:ddd(nil)") 70 71 checkmessage("b=1; local aaa='a'; x=aaa+b", "local 'aaa'") 72 checkmessage("aaa={}; x=3/aaa", "global 'aaa'") 73 checkmessage("aaa='2'; b=nil;x=aaa*b", "global 'b'") 74 checkmessage("aaa={}; x=-aaa", "global 'aaa'") 75 assert(not string.find(doit"aaa={}; x=(aaa or aaa)+(aaa and aaa)", "'aaa'")) 76 assert(not string.find(doit"aaa={}; (aaa or aaa)()", "'aaa'")) 77 78 checkmessage([[aaa=9 79 repeat until 3==3 80 local x=math.sin(math.cos(3)) 81 if math.sin(1) == x then return math.sin(1) end -- tail call 82 local a,b = 1, { 83 {x='a'..'b'..'c', y='b', z=x}, 84 {1,2,3,4,5} or 3+3<=3+3, 85 3+1>3+1, 86 {d = x and aaa[x or y]}} 87 ]], "global 'aaa'") 88 89 checkmessage([[ 90 local x,y = {},1 91 if math.sin(1) == 0 then return 3 end -- return 92 x.a()]], "field 'a'") 93 94 checkmessage([[ 95 prefix = nil 96 insert = nil 97 while 1 do 98 local a 99 if nil then break end 100 insert(prefix, a) 101 end]], "global 'insert'") 102 103 checkmessage([[ -- tail call 104 return math.sin("a") 105 ]], "'sin'") 106 107 checkmessage([[collectgarbage("nooption")]], "invalid option") 108 109 checkmessage([[x = print .. "a"]], "concatenate") 110 111 checkmessage("getmetatable(io.stdin).__gc()", "no value") 112 113 print'+' 114 115 116 -- testing line error 117 118 function lineerror (s) 119 local err,msg = pcall(loadstring(s)) 120 local line = string.match(msg, ":(%d+):") 121 return line and line+0 122 end 123 124 assert(lineerror"local a\n for i=1,'a' do \n print(i) \n end" == 2) 125 assert(lineerror"\n local a \n for k,v in 3 \n do \n print(k) \n end" == 3) 126 assert(lineerror"\n\n for k,v in \n 3 \n do \n print(k) \n end" == 4) 127 assert(lineerror"function a.x.y ()\na=a+1\nend" == 1) 128 129 local p = [[ 130 function g() f() end 131 function f(x) error('a', X) end 132 g() 133 ]] 134 X=3;assert(lineerror(p) == 3) 135 X=0;assert(lineerror(p) == nil) 136 X=1;assert(lineerror(p) == 2) 137 X=2;assert(lineerror(p) == 1) 138 139 lineerror = nil 140 141 C = 0 142 local l = debug.getinfo(1, "l").currentline; function y () C=C+1; y() end 143 144 local function checkstackmessage (m) 145 return (string.find(m, "^.-:%d+: stack overflow")) 146 end 147 assert(checkstackmessage(doit('y()'))) 148 assert(checkstackmessage(doit('y()'))) 149 assert(checkstackmessage(doit('y()'))) 150 -- teste de linhas em erro 151 C = 0 152 local l1 153 local function g() 154 l1 = debug.getinfo(1, "l").currentline; y() 155 end 156 local _, stackmsg = xpcall(g, debug.traceback) 157 local stack = {} 158 for line in string.gmatch(stackmsg, "[^\n]*") do 159 local curr = string.match(line, ":(%d+):") 160 if curr then table.insert(stack, tonumber(curr)) end 161 end 162 local i=1 163 while stack[i] ~= l1 do 164 assert(stack[i] == l) 165 i = i+1 166 end 167 assert(i > 15) 168 169 170 -- error in error handling 171 local res, msg = xpcall(error, error) 172 assert(not res and type(msg) == 'string') 173 174 local function f (x) 175 if x==0 then error('a\n') 176 else 177 local aux = function () return f(x-1) end 178 local a,b = xpcall(aux, aux) 179 return a,b 180 end 181 end 182 f(3) 183 184 -- non string messages 185 function f() error{msg='x'} end 186 res, msg = xpcall(f, function (r) return {msg=r.msg..'y'} end) 187 assert(msg.msg == 'xy') 188 189 print('+') 190 checksyntax("syntax error", "", "error", 1) 191 checksyntax("1.000", "", "1.000", 1) 192 checksyntax("[[a]]", "", "[[a]]", 1) 193 checksyntax("'aa'", "", "'aa'", 1) 194 195 -- test 255 as first char in a chunk 196 checksyntax("\255a = 1", "", "\255", 1) 197 198 doit('I = loadstring("a=9+"); a=3') 199 assert(a==3 and I == nil) 200 print('+') 201 202 lim = 1000 203 if rawget(_G, "_soft") then lim = 100 end 204 for i=1,lim do 205 doit('a = ') 206 doit('a = 4+nil') 207 end 208 209 210 -- testing syntax limits 211 local function testrep (init, rep) 212 local s = "local a; "..init .. string.rep(rep, 400) 213 local a,b = loadstring(s) 214 assert(not a and string.find(b, "syntax levels")) 215 end 216 testrep("a=", "{") 217 testrep("a=", "(") 218 testrep("", "a(") 219 testrep("", "do ") 220 testrep("", "while a do ") 221 testrep("", "if a then else ") 222 testrep("", "function foo () ") 223 testrep("a=", "a..") 224 testrep("a=", "a^") 225 226 227 -- testing other limits 228 -- upvalues 229 local s = "function foo ()\n local " 230 for j = 1,70 do 231 s = s.."a"..j..", " 232 end 233 s = s.."b\n" 234 for j = 1,70 do 235 s = s.."function foo"..j.." ()\n a"..j.."=3\n" 236 end 237 local a,b = loadstring(s) 238 assert(string.find(b, "line 3")) 239 240 -- local variables 241 s = "\nfunction foo ()\n local " 242 for j = 1,300 do 243 s = s.."a"..j..", " 244 end 245 s = s.."b\n" 246 local a,b = loadstring(s) 247 assert(string.find(b, "line 2")) 248 249 250 print('OK')