events.lua (12589B)
1 -- $Id: testes/events.lua $ 2 -- See Copyright Notice in file all.lua 3 4 print('testing metatables') 5 6 local debug = require'debug' 7 8 X = 20; B = 30 9 10 _ENV = setmetatable({}, {__index=_G}) 11 12 collectgarbage() 13 14 X = X+10 15 assert(X == 30 and _G.X == 20) 16 B = false 17 assert(B == false) 18 _ENV["B"] = undef 19 assert(B == 30) 20 21 assert(getmetatable{} == nil) 22 assert(getmetatable(4) == nil) 23 assert(getmetatable(nil) == nil) 24 a={name = "NAME"}; setmetatable(a, {__metatable = "xuxu", 25 __tostring=function(x) return x.name end}) 26 assert(getmetatable(a) == "xuxu") 27 assert(tostring(a) == "NAME") 28 -- cannot change a protected metatable 29 assert(pcall(setmetatable, a, {}) == false) 30 a.name = "gororoba" 31 assert(tostring(a) == "gororoba") 32 33 local a, t = {10,20,30; x="10", y="20"}, {} 34 assert(setmetatable(a,t) == a) 35 assert(getmetatable(a) == t) 36 assert(setmetatable(a,nil) == a) 37 assert(getmetatable(a) == nil) 38 assert(setmetatable(a,t) == a) 39 40 41 function f (t, i, e) 42 assert(not e) 43 local p = rawget(t, "parent") 44 return (p and p[i]+3), "dummy return" 45 end 46 47 t.__index = f 48 49 a.parent = {z=25, x=12, [4] = 24} 50 assert(a[1] == 10 and a.z == 28 and a[4] == 27 and a.x == "10") 51 52 collectgarbage() 53 54 a = setmetatable({}, t) 55 function f(t, i, v) rawset(t, i, v-3) end 56 setmetatable(t, t) -- causes a bug in 5.1 ! 57 t.__newindex = f 58 a[1] = 30; a.x = "101"; a[5] = 200 59 assert(a[1] == 27 and a.x == 98 and a[5] == 197) 60 61 do -- bug in Lua 5.3.2 62 local mt = {} 63 mt.__newindex = mt 64 local t = setmetatable({}, mt) 65 t[1] = 10 -- will segfault on some machines 66 assert(mt[1] == 10) 67 end 68 69 70 local c = {} 71 a = setmetatable({}, t) 72 t.__newindex = c 73 t.__index = c 74 a[1] = 10; a[2] = 20; a[3] = 90; 75 for i = 4, 20 do a[i] = i * 10 end 76 assert(a[1] == 10 and a[2] == 20 and a[3] == 90) 77 for i = 4, 20 do assert(a[i] == i * 10) end 78 assert(next(a) == nil) 79 80 81 do 82 local a; 83 a = setmetatable({}, {__index = setmetatable({}, 84 {__index = setmetatable({}, 85 {__index = function (_,n) return a[n-3]+4, "lixo" end})})}) 86 a[0] = 20 87 for i=0,10 do 88 assert(a[i*3] == 20 + i*4) 89 end 90 end 91 92 93 do -- newindex 94 local foi 95 local a = {} 96 for i=1,10 do a[i] = 0; a['a'..i] = 0; end 97 setmetatable(a, {__newindex = function (t,k,v) foi=true; rawset(t,k,v) end}) 98 foi = false; a[1]=0; assert(not foi) 99 foi = false; a['a1']=0; assert(not foi) 100 foi = false; a['a11']=0; assert(foi) 101 foi = false; a[11]=0; assert(foi) 102 foi = false; a[1]=undef; assert(not foi) 103 a[1] = undef 104 foi = false; a[1]=nil; assert(foi) 105 end 106 107 108 setmetatable(t, nil) 109 function f (t, ...) return t, {...} end 110 t.__call = f 111 112 do 113 local x,y = a(table.unpack{'a', 1}) 114 assert(x==a and y[1]=='a' and y[2]==1 and y[3]==undef) 115 x,y = a() 116 assert(x==a and y[1]==undef) 117 end 118 119 120 local b = setmetatable({}, t) 121 setmetatable(b,t) 122 123 function f(op) 124 return function (...) cap = {[0] = op, ...} ; return (...) end 125 end 126 t.__add = f("add") 127 t.__sub = f("sub") 128 t.__mul = f("mul") 129 t.__div = f("div") 130 t.__idiv = f("idiv") 131 t.__mod = f("mod") 132 t.__unm = f("unm") 133 t.__pow = f("pow") 134 t.__len = f("len") 135 t.__band = f("band") 136 t.__bor = f("bor") 137 t.__bxor = f("bxor") 138 t.__shl = f("shl") 139 t.__shr = f("shr") 140 t.__bnot = f("bnot") 141 t.__lt = f("lt") 142 t.__le = f("le") 143 144 145 local function checkcap (t) 146 assert(#cap + 1 == #t) 147 for i = 1, #t do 148 assert(cap[i - 1] == t[i]) 149 assert(math.type(cap[i - 1]) == math.type(t[i])) 150 end 151 end 152 153 -- Some tests are done inside small anonymous functions to ensure 154 -- that constants go to constant table even in debug compilation, 155 -- when the constant table is very small. 156 assert(b+5 == b); checkcap{"add", b, 5} 157 assert(5.2 + b == 5.2); checkcap{"add", 5.2, b} 158 assert(b+'5' == b); checkcap{"add", b, '5'} 159 assert(5+b == 5); checkcap{"add", 5, b} 160 assert('5'+b == '5'); checkcap{"add", '5', b} 161 b=b-3; assert(getmetatable(b) == t); checkcap{"sub", b, 3} 162 assert(5-a == 5); checkcap{"sub", 5, a} 163 assert('5'-a == '5'); checkcap{"sub", '5', a} 164 assert(a*a == a); checkcap{"mul", a, a} 165 assert(a/0 == a); checkcap{"div", a, 0} 166 assert(a/0.0 == a); checkcap{"div", a, 0.0} 167 assert(a%2 == a); checkcap{"mod", a, 2} 168 assert(a // (1/0) == a); checkcap{"idiv", a, 1/0} 169 ;(function () assert(a & "hi" == a) end)(); checkcap{"band", a, "hi"} 170 ;(function () assert(10 & a == 10) end)(); checkcap{"band", 10, a} 171 ;(function () assert(a | 10 == a) end)(); checkcap{"bor", a, 10} 172 assert(a | "hi" == a); checkcap{"bor", a, "hi"} 173 assert("hi" ~ a == "hi"); checkcap{"bxor", "hi", a} 174 ;(function () assert(10 ~ a == 10) end)(); checkcap{"bxor", 10, a} 175 assert(-a == a); checkcap{"unm", a, a} 176 assert(a^4.0 == a); checkcap{"pow", a, 4.0} 177 assert(a^'4' == a); checkcap{"pow", a, '4'} 178 assert(4^a == 4); checkcap{"pow", 4, a} 179 assert('4'^a == '4'); checkcap{"pow", '4', a} 180 assert(#a == a); checkcap{"len", a, a} 181 assert(~a == a); checkcap{"bnot", a, a} 182 assert(a << 3 == a); checkcap{"shl", a, 3} 183 assert(1.5 >> a == 1.5); checkcap{"shr", 1.5, a} 184 185 -- for comparison operators, all results are true 186 assert(5.0 > a); checkcap{"lt", a, 5.0} 187 assert(a >= 10); checkcap{"le", 10, a} 188 assert(a <= -10.0); checkcap{"le", a, -10.0} 189 assert(a < -10); checkcap{"lt", a, -10} 190 191 192 -- test for rawlen 193 t = setmetatable({1,2,3}, {__len = function () return 10 end}) 194 assert(#t == 10 and rawlen(t) == 3) 195 assert(rawlen"abc" == 3) 196 assert(not pcall(rawlen, io.stdin)) 197 assert(not pcall(rawlen, 34)) 198 assert(not pcall(rawlen)) 199 200 -- rawlen for long strings 201 assert(rawlen(string.rep('a', 1000)) == 1000) 202 203 204 t = {} 205 t.__lt = function (a,b,c) 206 collectgarbage() 207 assert(c == nil) 208 if type(a) == 'table' then a = a.x end 209 if type(b) == 'table' then b = b.x end 210 return a<b, "dummy" 211 end 212 213 t.__le = function (a,b,c) 214 assert(c == nil) 215 if type(a) == 'table' then a = a.x end 216 if type(b) == 'table' then b = b.x end 217 return a<=b, "dummy" 218 end 219 220 t.__eq = function (a,b,c) 221 assert(c == nil) 222 if type(a) == 'table' then a = a.x end 223 if type(b) == 'table' then b = b.x end 224 return a == b, "dummy" 225 end 226 227 function Op(x) return setmetatable({x=x}, t) end 228 229 local function test (a, b, c) 230 assert(not(Op(1)<Op(1)) and (Op(1)<Op(2)) and not(Op(2)<Op(1))) 231 assert(not(1 < Op(1)) and (Op(1) < 2) and not(2 < Op(1))) 232 assert(not(Op('a')<Op('a')) and (Op('a')<Op('b')) and not(Op('b')<Op('a'))) 233 assert(not('a' < Op('a')) and (Op('a') < 'b') and not(Op('b') < Op('a'))) 234 assert((Op(1)<=Op(1)) and (Op(1)<=Op(2)) and not(Op(2)<=Op(1))) 235 assert((Op('a')<=Op('a')) and (Op('a')<=Op('b')) and not(Op('b')<=Op('a'))) 236 assert(not(Op(1)>Op(1)) and not(Op(1)>Op(2)) and (Op(2)>Op(1))) 237 assert(not(Op('a')>Op('a')) and not(Op('a')>Op('b')) and (Op('b')>Op('a'))) 238 assert((Op(1)>=Op(1)) and not(Op(1)>=Op(2)) and (Op(2)>=Op(1))) 239 assert((1 >= Op(1)) and not(1 >= Op(2)) and (Op(2) >= 1)) 240 assert((Op('a')>=Op('a')) and not(Op('a')>=Op('b')) and (Op('b')>=Op('a'))) 241 assert(('a' >= Op('a')) and not(Op('a') >= 'b') and (Op('b') >= Op('a'))) 242 assert(Op(1) == Op(1) and Op(1) ~= Op(2)) 243 assert(Op('a') == Op('a') and Op('a') ~= Op('b')) 244 assert(a == a and a ~= b) 245 assert(Op(3) == c) 246 end 247 248 test(Op(1), Op(2), Op(3)) 249 250 251 do -- test nil as false 252 local x = setmetatable({12}, {__eq= function (a,b) 253 return a[1] == b[1] or nil 254 end}) 255 assert(not (x == {20})) 256 assert(x == {12}) 257 end 258 259 260 -- test `partial order' 261 262 local function rawSet(x) 263 local y = {} 264 for _,k in pairs(x) do y[k] = 1 end 265 return y 266 end 267 268 local function Set(x) 269 return setmetatable(rawSet(x), t) 270 end 271 272 t.__lt = function (a,b) 273 for k in pairs(a) do 274 if not b[k] then return false end 275 b[k] = undef 276 end 277 return next(b) ~= nil 278 end 279 280 t.__le = function (a,b) 281 for k in pairs(a) do 282 if not b[k] then return false end 283 end 284 return true 285 end 286 287 assert(Set{1,2,3} < Set{1,2,3,4}) 288 assert(not(Set{1,2,3,4} < Set{1,2,3,4})) 289 assert((Set{1,2,3,4} <= Set{1,2,3,4})) 290 assert((Set{1,2,3,4} >= Set{1,2,3,4})) 291 assert(not (Set{1,3} <= Set{3,5})) 292 assert(not(Set{1,3} <= Set{3,5})) 293 assert(not(Set{1,3} >= Set{3,5})) 294 295 296 t.__eq = function (a,b) 297 for k in pairs(a) do 298 if not b[k] then return false end 299 b[k] = undef 300 end 301 return next(b) == nil 302 end 303 304 local s = Set{1,3,5} 305 assert(s == Set{3,5,1}) 306 assert(not rawequal(s, Set{3,5,1})) 307 assert(rawequal(s, s)) 308 assert(Set{1,3,5,1} == rawSet{3,5,1}) 309 assert(rawSet{1,3,5,1} == Set{3,5,1}) 310 assert(Set{1,3,5} ~= Set{3,5,1,6}) 311 312 -- '__eq' is not used for table accesses 313 t[Set{1,3,5}] = 1 314 assert(t[Set{1,3,5}] == undef) 315 316 317 do -- test invalidating flags 318 local mt = {__eq = true} 319 local a = setmetatable({10}, mt) 320 local b = setmetatable({10}, mt) 321 mt.__eq = nil 322 assert(a ~= b) -- no metamethod 323 mt.__eq = function (x,y) return x[1] == y[1] end 324 assert(a == b) -- must use metamethod now 325 end 326 327 328 if not T then 329 (Message or print)('\n >>> testC not active: skipping tests for \z 330 userdata <<<\n') 331 else 332 local u1 = T.newuserdata(0, 1) 333 local u2 = T.newuserdata(0, 1) 334 local u3 = T.newuserdata(0, 1) 335 assert(u1 ~= u2 and u1 ~= u3) 336 debug.setuservalue(u1, 1); 337 debug.setuservalue(u2, 2); 338 debug.setuservalue(u3, 1); 339 debug.setmetatable(u1, {__eq = function (a, b) 340 return debug.getuservalue(a) == debug.getuservalue(b) 341 end}) 342 debug.setmetatable(u2, {__eq = function (a, b) 343 return true 344 end}) 345 assert(u1 == u3 and u3 == u1 and u1 ~= u2) 346 assert(u2 == u1 and u2 == u3 and u3 == u2) 347 assert(u2 ~= {}) -- different types cannot be equal 348 assert(rawequal(u1, u1) and not rawequal(u1, u3)) 349 350 local mirror = {} 351 debug.setmetatable(u3, {__index = mirror, __newindex = mirror}) 352 for i = 1, 10 do u3[i] = i end 353 for i = 1, 10 do assert(u3[i] == i) end 354 end 355 356 357 t.__concat = function (a,b,c) 358 assert(c == nil) 359 if type(a) == 'table' then a = a.val end 360 if type(b) == 'table' then b = b.val end 361 if A then return a..b 362 else 363 return setmetatable({val=a..b}, t) 364 end 365 end 366 367 c = {val="c"}; setmetatable(c, t) 368 d = {val="d"}; setmetatable(d, t) 369 370 A = true 371 assert(c..d == 'cd') 372 assert(0 .."a".."b"..c..d.."e".."f"..(5+3).."g" == "0abcdef8g") 373 374 A = false 375 assert((c..d..c..d).val == 'cdcd') 376 x = c..d 377 assert(getmetatable(x) == t and x.val == 'cd') 378 x = 0 .."a".."b"..c..d.."e".."f".."g" 379 assert(x.val == "0abcdefg") 380 381 382 -- concat metamethod x numbers (bug in 5.1.1) 383 c = {} 384 local x 385 setmetatable(c, {__concat = function (a,b) 386 assert(type(a) == "number" and b == c or type(b) == "number" and a == c) 387 return c 388 end}) 389 assert(c..5 == c and 5 .. c == c) 390 assert(4 .. c .. 5 == c and 4 .. 5 .. 6 .. 7 .. c == c) 391 392 393 -- test comparison compatibilities 394 local t1, t2, c, d 395 t1 = {}; c = {}; setmetatable(c, t1) 396 d = {} 397 t1.__eq = function () return true end 398 t1.__lt = function () return true end 399 t1.__le = function () return false end 400 setmetatable(d, t1) 401 assert(c == d and c < d and not(d <= c)) 402 t2 = {} 403 t2.__eq = t1.__eq 404 t2.__lt = t1.__lt 405 setmetatable(d, t2) 406 assert(c == d and c < d and not(d <= c)) 407 408 409 410 -- test for several levels of calls 411 local i 412 local tt = { 413 __call = function (t, ...) 414 i = i+1 415 if t.f then return t.f(...) 416 else return {...} 417 end 418 end 419 } 420 421 local a = setmetatable({}, tt) 422 local b = setmetatable({f=a}, tt) 423 local c = setmetatable({f=b}, tt) 424 425 i = 0 426 x = c(3,4,5) 427 assert(i == 3 and x[1] == 3 and x[3] == 5) 428 429 430 assert(_G.X == 20) 431 432 _G.X, _G.B = nil 433 434 435 print'+' 436 437 local _g = _G 438 _ENV = setmetatable({}, {__index=function (_,k) return _g[k] end}) 439 440 441 a = {} 442 rawset(a, "x", 1, 2, 3) 443 assert(a.x == 1 and rawget(a, "x", 3) == 1) 444 445 print '+' 446 447 -- testing metatables for basic types 448 mt = {__index = function (a,b) return a+b end, 449 __len = function (x) return math.floor(x) end} 450 debug.setmetatable(10, mt) 451 assert(getmetatable(-2) == mt) 452 assert((10)[3] == 13) 453 assert((10)["3"] == 13) 454 assert(#3.45 == 3) 455 debug.setmetatable(23, nil) 456 assert(getmetatable(-2) == nil) 457 458 debug.setmetatable(true, mt) 459 assert(getmetatable(false) == mt) 460 mt.__index = function (a,b) return a or b end 461 assert((true)[false] == true) 462 assert((false)[false] == false) 463 debug.setmetatable(false, nil) 464 assert(getmetatable(true) == nil) 465 466 debug.setmetatable(nil, mt) 467 assert(getmetatable(nil) == mt) 468 mt.__add = function (a,b) return (a or 1) + (b or 2) end 469 assert(10 + nil == 12) 470 assert(nil + 23 == 24) 471 assert(nil + nil == 3) 472 debug.setmetatable(nil, nil) 473 assert(getmetatable(nil) == nil) 474 475 debug.setmetatable(nil, {}) 476 477 478 -- loops in delegation 479 a = {}; setmetatable(a, a); a.__index = a; a.__newindex = a 480 assert(not pcall(function (a,b) return a[b] end, a, 10)) 481 assert(not pcall(function (a,b,c) a[b] = c end, a, 10, true)) 482 483 -- bug in 5.1 484 T, K, V = nil 485 grandparent = {} 486 grandparent.__newindex = function(t,k,v) T=t; K=k; V=v end 487 488 parent = {} 489 parent.__newindex = parent 490 setmetatable(parent, grandparent) 491 492 child = setmetatable({}, parent) 493 child.foo = 10 --> CRASH (on some machines) 494 assert(T == parent and K == "foo" and V == 10) 495 496 print 'OK' 497 498 return 12 499 500