constructs.lua (9946B)
1 -- $Id: testes/constructs.lua $ 2 -- See Copyright Notice in file all.lua 3 4 ;;print "testing syntax";; 5 6 local debug = require "debug" 7 8 9 local function checkload (s, msg) 10 assert(string.find(select(2, load(s)), msg)) 11 end 12 13 -- testing semicollons 14 local a 15 do ;;; end 16 ; do ; a = 3; assert(a == 3) end; 17 ; 18 19 20 -- invalid operations should not raise errors when not executed 21 if false then a = 3 // 0; a = 0 % 0 end 22 23 24 -- testing priorities 25 26 assert(2^3^2 == 2^(3^2)); 27 assert(2^3*4 == (2^3)*4); 28 assert(2.0^-2 == 1/4 and -2^- -2 == - - -4); 29 assert(not nil and 2 and not(2>3 or 3<2)); 30 assert(-3-1-5 == 0+0-9); 31 assert(-2^2 == -4 and (-2)^2 == 4 and 2*2-3-1 == 0); 32 assert(-3%5 == 2 and -3+5 == 2) 33 assert(2*1+3/3 == 3 and 1+2 .. 3*1 == "33"); 34 assert(not(2+1 > 3*1) and "a".."b" > "a"); 35 36 assert(0xF0 | 0xCC ~ 0xAA & 0xFD == 0xF4) 37 assert(0xFD & 0xAA ~ 0xCC | 0xF0 == 0xF4) 38 assert(0xF0 & 0x0F + 1 == 0x10) 39 40 assert(3^4//2^3//5 == 2) 41 42 assert(-3+4*5//2^3^2//9+4%10/3 == (-3)+(((4*5)//(2^(3^2)))//9)+((4%10)/3)) 43 44 assert(not ((true or false) and nil)) 45 assert( true or false and nil) 46 47 -- old bug 48 assert((((1 or false) and true) or false) == true) 49 assert((((nil and true) or false) and true) == false) 50 51 local a,b = 1,nil; 52 assert(-(1 or 2) == -1 and (1 and 2)+(-1.25 or -4) == 0.75); 53 local x = ((b or a)+1 == 2 and (10 or a)+1 == 11); assert(x); 54 x = (((2<3) or 1) == true and (2<3 and 4) == 4); assert(x); 55 56 local x, y = 1, 2; 57 assert((x>y) and x or y == 2); 58 x,y=2,1; 59 assert((x>y) and x or y == 2); 60 61 assert(1234567890 == tonumber('1234567890') and 1234567890+1 == 1234567891) 62 63 do -- testing operators with diffent kinds of constants 64 -- operands to consider: 65 -- * fit in register 66 -- * constant doesn't fit in register 67 -- * floats with integral values 68 local operand = {3, 100, 5.0, -10, -5.0, 10000, -10000} 69 local operator = {"+", "-", "*", "/", "//", "%", "^", 70 "&", "|", "^", "<<", ">>", 71 "==", "~=", "<", ">", "<=", ">=",} 72 for _, op in ipairs(operator) do 73 local f = assert(load(string.format([[return function (x,y) 74 return x %s y 75 end]], op)))(); 76 for _, o1 in ipairs(operand) do 77 for _, o2 in ipairs(operand) do 78 local gab = f(o1, o2) 79 80 _ENV.XX = o1 81 local code = string.format("return XX %s %s", op, o2) 82 local res = assert(load(code))() 83 assert(res == gab) 84 85 _ENV.XX = o2 86 code = string.format("return (%s) %s XX", o1, op) 87 res = assert(load(code))() 88 assert(res == gab) 89 90 code = string.format("return (%s) %s %s", o1, op, o2) 91 res = assert(load(code))() 92 assert(res == gab) 93 end 94 end 95 end 96 _ENV.XX = nil 97 end 98 99 100 -- silly loops 101 repeat until 1; repeat until true; 102 while false do end; while nil do end; 103 104 do -- test old bug (first name could not be an `upvalue') 105 local a; local function f(x) x={a=1}; x={x=1}; x={G=1} end 106 end 107 108 109 do -- bug since 5.4.0 110 -- create code with a table using more than 256 constants 111 local code = {"local x = {"} 112 for i = 1, 257 do 113 code[#code + 1] = i .. ".1," 114 end 115 code[#code + 1] = "};" 116 code = table.concat(code) 117 118 -- add "ret" to the end of that code and checks that 119 -- it produces the expected value "val" 120 local function check (ret, val) 121 local code = code .. ret 122 code = load(code) 123 assert(code() == val) 124 end 125 126 check("return (1 ~ (2 or 3))", 1 ~ 2) 127 check("return (1 | (2 or 3))", 1 | 2) 128 check("return (1 + (2 or 3))", 1 + 2) 129 check("return (1 << (2 or 3))", 1 << 2) 130 end 131 132 133 local function f (i) 134 if type(i) ~= 'number' then return i,'jojo'; end; 135 if i > 0 then return i, f(i-1); end; 136 end 137 138 x = {f(3), f(5), f(10);}; 139 assert(x[1] == 3 and x[2] == 5 and x[3] == 10 and x[4] == 9 and x[12] == 1); 140 assert(x[nil] == nil) 141 x = {f'alo', f'xixi', nil}; 142 assert(x[1] == 'alo' and x[2] == 'xixi' and x[3] == nil); 143 x = {f'alo'..'xixi'}; 144 assert(x[1] == 'aloxixi') 145 x = {f{}} 146 assert(x[2] == 'jojo' and type(x[1]) == 'table') 147 148 149 local f = function (i) 150 if i < 10 then return 'a'; 151 elseif i < 20 then return 'b'; 152 elseif i < 30 then return 'c'; 153 end; 154 end 155 156 assert(f(3) == 'a' and f(12) == 'b' and f(26) == 'c' and f(100) == nil) 157 158 for i=1,1000 do break; end; 159 local n=100; 160 local i=3; 161 local t = {}; 162 local a=nil 163 while not a do 164 a=0; for i=1,n do for i=i,1,-1 do a=a+1; t[i]=1; end; end; 165 end 166 assert(a == n*(n+1)/2 and i==3); 167 assert(t[1] and t[n] and not t[0] and not t[n+1]) 168 169 function f(b) 170 local x = 1; 171 repeat 172 local a; 173 if b==1 then local b=1; x=10; break 174 elseif b==2 then x=20; break; 175 elseif b==3 then x=30; 176 else local a,b,c,d=math.sin(1); x=x+1; 177 end 178 until x>=12; 179 return x; 180 end; 181 182 assert(f(1) == 10 and f(2) == 20 and f(3) == 30 and f(4)==12) 183 184 185 local f = function (i) 186 if i < 10 then return 'a' 187 elseif i < 20 then return 'b' 188 elseif i < 30 then return 'c' 189 else return 8 190 end 191 end 192 193 assert(f(3) == 'a' and f(12) == 'b' and f(26) == 'c' and f(100) == 8) 194 195 local a, b = nil, 23 196 x = {f(100)*2+3 or a, a or b+2} 197 assert(x[1] == 19 and x[2] == 25) 198 x = {f=2+3 or a, a = b+2} 199 assert(x.f == 5 and x.a == 25) 200 201 a={y=1} 202 x = {a.y} 203 assert(x[1] == 1) 204 205 local function f (i) 206 while 1 do 207 if i>0 then i=i-1; 208 else return; end; 209 end; 210 end; 211 212 local function g(i) 213 while 1 do 214 if i>0 then i=i-1 215 else return end 216 end 217 end 218 219 f(10); g(10); 220 221 do 222 function f () return 1,2,3; end 223 local a, b, c = f(); 224 assert(a==1 and b==2 and c==3) 225 a, b, c = (f()); 226 assert(a==1 and b==nil and c==nil) 227 end 228 229 local a,b = 3 and f(); 230 assert(a==1 and b==nil) 231 232 function g() f(); return; end; 233 assert(g() == nil) 234 function g() return nil or f() end 235 a,b = g() 236 assert(a==1 and b==nil) 237 238 print'+'; 239 240 do -- testing constants 241 local prog <const> = [[local x <XXX> = 10]] 242 checkload(prog, "unknown attribute 'XXX'") 243 244 checkload([[local xxx <const> = 20; xxx = 10]], 245 ":1: attempt to assign to const variable 'xxx'") 246 247 checkload([[ 248 local xx; 249 local xxx <const> = 20; 250 local yyy; 251 local function foo () 252 local abc = xx + yyy + xxx; 253 return function () return function () xxx = yyy end end 254 end 255 ]], ":6: attempt to assign to const variable 'xxx'") 256 257 checkload([[ 258 local x <close> = nil 259 x = io.open() 260 ]], ":2: attempt to assign to const variable 'x'") 261 end 262 263 f = [[ 264 return function ( a , b , c , d , e ) 265 local x = a >= b or c or ( d and e ) or nil 266 return x 267 end , { a = 1 , b = 2 >= 1 , } or { 1 }; 268 ]] 269 f = string.gsub(f, "%s+", "\n"); -- force a SETLINE between opcodes 270 f,a = load(f)(); 271 assert(a.a == 1 and a.b) 272 273 function g (a,b,c,d,e) 274 if not (a>=b or c or d and e or nil) then return 0; else return 1; end; 275 end 276 277 local function h (a,b,c,d,e) 278 while (a>=b or c or (d and e) or nil) do return 1; end; 279 return 0; 280 end; 281 282 assert(f(2,1) == true and g(2,1) == 1 and h(2,1) == 1) 283 assert(f(1,2,'a') == 'a' and g(1,2,'a') == 1 and h(1,2,'a') == 1) 284 assert(f(1,2,'a') 285 ~= -- force SETLINE before nil 286 nil, "") 287 assert(f(1,2,'a') == 'a' and g(1,2,'a') == 1 and h(1,2,'a') == 1) 288 assert(f(1,2,nil,1,'x') == 'x' and g(1,2,nil,1,'x') == 1 and 289 h(1,2,nil,1,'x') == 1) 290 assert(f(1,2,nil,nil,'x') == nil and g(1,2,nil,nil,'x') == 0 and 291 h(1,2,nil,nil,'x') == 0) 292 assert(f(1,2,nil,1,nil) == nil and g(1,2,nil,1,nil) == 0 and 293 h(1,2,nil,1,nil) == 0) 294 295 assert(1 and 2<3 == true and 2<3 and 'a'<'b' == true) 296 x = 2<3 and not 3; assert(x==false) 297 x = 2<1 or (2>1 and 'a'); assert(x=='a') 298 299 300 do 301 local a; if nil then a=1; else a=2; end; -- this nil comes as PUSHNIL 2 302 assert(a==2) 303 end 304 305 local function F (a) 306 assert(debug.getinfo(1, "n").name == 'F') 307 return a,2,3 308 end 309 310 a,b = F(1)~=nil; assert(a == true and b == nil); 311 a,b = F(nil)==nil; assert(a == true and b == nil) 312 313 ---------------------------------------------------------------- 314 ------------------------------------------------------------------ 315 316 -- sometimes will be 0, sometimes will not... 317 _ENV.GLOB1 = math.random(0, 1) 318 319 -- basic expressions with their respective values 320 local basiccases = { 321 {"nil", nil}, 322 {"false", false}, 323 {"true", true}, 324 {"10", 10}, 325 {"(0==_ENV.GLOB1)", 0 == _ENV.GLOB1}, 326 } 327 328 local prog 329 330 if _ENV.GLOB1 == 0 then 331 basiccases[2][1] = "F" -- constant false 332 333 prog = [[ 334 local F <const> = false 335 if %s then IX = true end 336 return %s 337 ]] 338 else 339 basiccases[4][1] = "k10" -- constant 10 340 341 prog = [[ 342 local k10 <const> = 10 343 if %s then IX = true end 344 return %s 345 ]] 346 end 347 348 print('testing short-circuit optimizations (' .. _ENV.GLOB1 .. ')') 349 350 351 -- operators with their respective values 352 local binops <const> = { 353 {" and ", function (a,b) if not a then return a else return b end end}, 354 {" or ", function (a,b) if a then return a else return b end end}, 355 } 356 357 local cases <const> = {} 358 359 -- creates all combinations of '(cases[i] op cases[n-i])' plus 360 -- 'not(cases[i] op cases[n-i])' (syntax + value) 361 local function createcases (n) 362 local res = {} 363 for i = 1, n - 1 do 364 for _, v1 in ipairs(cases[i]) do 365 for _, v2 in ipairs(cases[n - i]) do 366 for _, op in ipairs(binops) do 367 local t = { 368 "(" .. v1[1] .. op[1] .. v2[1] .. ")", 369 op[2](v1[2], v2[2]) 370 } 371 res[#res + 1] = t 372 res[#res + 1] = {"not" .. t[1], not t[2]} 373 end 374 end 375 end 376 end 377 return res 378 end 379 380 -- do not do too many combinations for soft tests 381 local level = _soft and 3 or 4 382 383 cases[1] = basiccases 384 for i = 2, level do cases[i] = createcases(i) end 385 print("+") 386 387 local i = 0 388 for n = 1, level do 389 for _, v in pairs(cases[n]) do 390 local s = v[1] 391 local p = load(string.format(prog, s, s), "") 392 IX = false 393 assert(p() == v[2] and IX == not not v[2]) 394 i = i + 1 395 if i % 60000 == 0 then print('+') end 396 end 397 end 398 IX = nil 399 _G.GLOB1 = nil 400 ------------------------------------------------------------------ 401 402 -- testing some syntax errors (chosen through 'gcov') 403 checkload("for x do", "expected") 404 checkload("x:call", "expected") 405 406 print'OK'