1--[[ 2--***************************************************************************** 3--* Copyright (C) 1994-2016 Lua.org, PUC-Rio. 4--* 5--* Permission is hereby granted, free of charge, to any person obtaining 6--* a copy of this software and associated documentation files (the 7--* "Software"), to deal in the Software without restriction, including 8--* without limitation the rights to use, copy, modify, merge, publish, 9--* distribute, sublicense, and/or sell copies of the Software, and to 10--* permit persons to whom the Software is furnished to do so, subject to 11--* the following conditions: 12--* 13--* The above copyright notice and this permission notice shall be 14--* included in all copies or substantial portions of the Software. 15--* 16--* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17--* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18--* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19--* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 20--* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 21--* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 22--* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23--***************************************************************************** 24--]] 25 26-- testing metatables 27 28X = 20; B = 30 29 30_ENV = setmetatable({}, {__index=_G}) 31 32collectgarbage() 33 34X = X+10 35assert(X == 30 and _G.X == 20) 36B = false 37assert(B == false) 38B = nil 39assert(B == 30) 40 41assert(getmetatable{} == nil) 42assert(getmetatable(4) == nil) 43assert(getmetatable(nil) == nil) 44a={name = "NAME"}; setmetatable(a, {__metatable = "xuxu", 45 __tostring=function(x) return x.name end}) 46assert(getmetatable(a) == "xuxu") 47assert(tostring(a) == "NAME") 48 49local a, t = {10,20,30; x="10", y="20"}, {} 50assert(setmetatable(a,t) == a) 51assert(getmetatable(a) == t) 52assert(setmetatable(a,nil) == a) 53assert(getmetatable(a) == nil) 54assert(setmetatable(a,t) == a) 55 56 57function f (t, i, e) 58 assert(not e) 59 local p = rawget(t, "parent") 60 return (p and p[i]+3), "dummy return" 61end 62 63t.__index = f 64 65a.parent = {z=25, x=12, [4] = 24} 66assert(a[1] == 10 and a.z == 28 and a[4] == 27 and a.x == "10") 67 68collectgarbage() 69 70a = setmetatable({}, t) 71function f(t, i, v) rawset(t, i, v-3) end 72setmetatable(t, t) -- causes a bug in 5.1 ! 73t.__newindex = f 74a[1] = 30; a.x = "101"; a[5] = 200 75assert(a[1] == 27 and a.x == 98 and a[5] == 197) 76 77 78local c = {} 79a = setmetatable({}, t) 80t.__newindex = c 81a[1] = 10; a[2] = 20; a[3] = 90 82assert(c[1] == 10 and c[2] == 20 and c[3] == 90) 83 84 85do 86 local a; 87 a = setmetatable({}, {__index = setmetatable({}, 88 {__index = setmetatable({}, 89 {__index = function (_,n) return a[n-3]+4, "lixo" end})})}) 90 a[0] = 20 91 for i=0,10 do 92 assert(a[i*3] == 20 + i*4) 93 end 94end 95 96 97do -- newindex 98 local foi 99 local a = {} 100 for i=1,10 do a[i] = 0; a['a'..i] = 0; end 101 setmetatable(a, {__newindex = function (t,k,v) foi=true; rawset(t,k,v) end}) 102 foi = false; a[1]=0; assert(not foi) 103 foi = false; a['a1']=0; assert(not foi) 104 foi = false; a['a11']=0; assert(foi) 105 foi = false; a[11]=0; assert(foi) 106 foi = false; a[1]=nil; assert(not foi) 107 foi = false; a[1]=nil; assert(foi) 108end 109 110 111setmetatable(t, nil) 112function f (t, ...) return t, {...} end 113t.__call = f 114 115do 116 local x,y = a(table.unpack{'a', 1}) 117 assert(x==a and y[1]=='a' and y[2]==1 and y[3]==nil) 118 x,y = a() 119 assert(x==a and y[1]==nil) 120end 121 122 123local b = setmetatable({}, t) 124setmetatable(b,t) 125 126function f(op) 127 return function (...) cap = {[0] = op, ...} ; return (...) end 128end 129t.__add = f("add") 130t.__sub = f("sub") 131t.__mul = f("mul") 132t.__div = f("div") 133t.__mod = f("mod") 134t.__unm = f("unm") 135t.__pow = f("pow") 136t.__len = f("len") 137 138assert(b+5 == b) 139assert(cap[0] == "add" and cap[1] == b and cap[2] == 5 and cap[3]==nil) 140assert(b+'5' == b) 141assert(cap[0] == "add" and cap[1] == b and cap[2] == '5' and cap[3]==nil) 142assert(5+b == 5) 143assert(cap[0] == "add" and cap[1] == 5 and cap[2] == b and cap[3]==nil) 144assert('5'+b == '5') 145assert(cap[0] == "add" and cap[1] == '5' and cap[2] == b and cap[3]==nil) 146b=b-3; assert(getmetatable(b) == t) 147assert(5-a == 5) 148assert(cap[0] == "sub" and cap[1] == 5 and cap[2] == a and cap[3]==nil) 149assert('5'-a == '5') 150assert(cap[0] == "sub" and cap[1] == '5' and cap[2] == a and cap[3]==nil) 151assert(a*a == a) 152assert(cap[0] == "mul" and cap[1] == a and cap[2] == a and cap[3]==nil) 153assert(a/0 == a) 154assert(cap[0] == "div" and cap[1] == a and cap[2] == 0 and cap[3]==nil) 155assert(a%2 == a) 156assert(cap[0] == "mod" and cap[1] == a and cap[2] == 2 and cap[3]==nil) 157assert(-a == a) 158assert(cap[0] == "unm" and cap[1] == a) 159assert(a^4 == a) 160assert(cap[0] == "pow" and cap[1] == a and cap[2] == 4 and cap[3]==nil) 161assert(a^'4' == a) 162assert(cap[0] == "pow" and cap[1] == a and cap[2] == '4' and cap[3]==nil) 163assert(4^a == 4) 164assert(cap[0] == "pow" and cap[1] == 4 and cap[2] == a and cap[3]==nil) 165assert('4'^a == '4') 166assert(cap[0] == "pow" and cap[1] == '4' and cap[2] == a and cap[3]==nil) 167assert(#a == a) 168assert(cap[0] == "len" and cap[1] == a) 169 170 171-- test for rawlen 172t = setmetatable({1,2,3}, {__len = function () return 10 end}) 173assert(#t == 10 and rawlen(t) == 3) 174assert(rawlen"abc" == 3) 175assert(rawlen(string.rep('a', 1000)) == 1000) 176 177t = {} 178t.__lt = function (a,b,c) 179 collectgarbage() 180 assert(c == nil) 181 if type(a) == 'table' then a = a.x end 182 if type(b) == 'table' then b = b.x end 183 return a<b, "dummy" 184end 185 186function Op(x) return setmetatable({x=x}, t) end 187 188local function test () 189 assert(not(Op(1)<Op(1)) and (Op(1)<Op(2)) and not(Op(2)<Op(1))) 190 assert(not(1 < Op(1)) and (Op(1) < 2) and not(2 < Op(1))) 191 assert(not(Op('a')<Op('a')) and (Op('a')<Op('b')) and not(Op('b')<Op('a'))) 192 assert(not('a' < Op('a')) and (Op('a') < 'b') and not(Op('b') < Op('a'))) 193 assert((Op(1)<=Op(1)) and (Op(1)<=Op(2)) and not(Op(2)<=Op(1))) 194 assert((Op('a')<=Op('a')) and (Op('a')<=Op('b')) and not(Op('b')<=Op('a'))) 195 assert(not(Op(1)>Op(1)) and not(Op(1)>Op(2)) and (Op(2)>Op(1))) 196 assert(not(Op('a')>Op('a')) and not(Op('a')>Op('b')) and (Op('b')>Op('a'))) 197 assert((Op(1)>=Op(1)) and not(Op(1)>=Op(2)) and (Op(2)>=Op(1))) 198 assert((1 >= Op(1)) and not(1 >= Op(2)) and (Op(2) >= 1)) 199 assert((Op('a')>=Op('a')) and not(Op('a')>=Op('b')) and (Op('b')>=Op('a'))) 200 assert(('a' >= Op('a')) and not(Op('a') >= 'b') and (Op('b') >= Op('a'))) 201end 202 203test() 204 205t.__le = function (a,b,c) 206 assert(c == nil) 207 if type(a) == 'table' then a = a.x end 208 if type(b) == 'table' then b = b.x end 209 return a<=b, "dummy" 210end 211 212test() -- retest comparisons, now using both `lt' and `le' 213 214 215-- test `partial order' 216 217local function Set(x) 218 local y = {} 219 for _,k in pairs(x) do y[k] = 1 end 220 return setmetatable(y, t) 221end 222 223t.__lt = function (a,b) 224 for k in pairs(a) do 225 if not b[k] then return false end 226 b[k] = nil 227 end 228 return next(b) ~= nil 229end 230 231t.__le = nil 232 233assert(Set{1,2,3} < Set{1,2,3,4}) 234assert(not(Set{1,2,3,4} < Set{1,2,3,4})) 235assert((Set{1,2,3,4} <= Set{1,2,3,4})) 236assert((Set{1,2,3,4} >= Set{1,2,3,4})) 237assert((Set{1,3} <= Set{3,5})) -- wrong!! model needs a `le' method ;-) 238 239t.__le = function (a,b) 240 for k in pairs(a) do 241 if not b[k] then return false end 242 end 243 return true 244end 245 246assert(not (Set{1,3} <= Set{3,5})) -- now its OK! 247assert(not(Set{1,3} <= Set{3,5})) 248assert(not(Set{1,3} >= Set{3,5})) 249 250t.__eq = function (a,b) 251 for k in pairs(a) do 252 if not b[k] then return false end 253 b[k] = nil 254 end 255 return next(b) == nil 256end 257 258local s = Set{1,3,5} 259assert(s == Set{3,5,1}) 260assert(not rawequal(s, Set{3,5,1})) 261assert(rawequal(s, s)) 262assert(Set{1,3,5,1} == Set{3,5,1}) 263assert(Set{1,3,5} ~= Set{3,5,1,6}) 264t[Set{1,3,5}] = 1 265assert(t[Set{1,3,5}] == nil) -- `__eq' is not valid for table accesses 266 267 268t.__concat = function (a,b,c) 269 assert(c == nil) 270 if type(a) == 'table' then a = a.val end 271 if type(b) == 'table' then b = b.val end 272 if A then return a..b 273 else 274 return setmetatable({val=a..b}, t) 275 end 276end 277 278c = {val="c"}; setmetatable(c, t) 279d = {val="d"}; setmetatable(d, t) 280 281A = true 282assert(c..d == 'cd') 283assert(0 .."a".."b"..c..d.."e".."f"..(5+3).."g" == "0abcdef8g") 284 285A = false 286assert((c..d..c..d).val == 'cdcd') 287x = c..d 288assert(getmetatable(x) == t and x.val == 'cd') 289x = 0 .."a".."b"..c..d.."e".."f".."g" 290assert(x.val == "0abcdefg") 291 292 293-- concat metamethod x numbers (bug in 5.1.1) 294c = {} 295local x 296setmetatable(c, {__concat = function (a,b) 297 assert(type(a) == "number" and b == c or type(b) == "number" and a == c) 298 return c 299end}) 300assert(c..5 == c and 5 .. c == c) 301assert(4 .. c .. 5 == c and 4 .. 5 .. 6 .. 7 .. c == c) 302 303 304-- test comparison compatibilities 305local t1, t2, c, d 306t1 = {}; c = {}; setmetatable(c, t1) 307d = {} 308t1.__eq = function () return true end 309t1.__lt = function () return true end 310setmetatable(d, t1) 311assert(c == d and c < d and not(d <= c)) 312t2 = {} 313t2.__eq = t1.__eq 314t2.__lt = t1.__lt 315setmetatable(d, t2) 316assert(c == d and c < d and not(d <= c)) 317 318 319 320-- test for several levels of calls 321local i 322local tt = { 323 __call = function (t, ...) 324 i = i+1 325 if t.f then return t.f(...) 326 else return {...} 327 end 328 end 329} 330 331local a = setmetatable({}, tt) 332local b = setmetatable({f=a}, tt) 333local c = setmetatable({f=b}, tt) 334 335i = 0 336x = c(3,4,5) 337assert(i == 3 and x[1] == 3 and x[3] == 5) 338 339 340assert(_G.X == 20) 341 342 343local _g = _G 344_ENV = setmetatable({}, {__index=function (_,k) return _g[k] end}) 345 346 347a = {} 348rawset(a, "x", 1, 2, 3) 349assert(a.x == 1 and rawget(a, "x", 3) == 1) 350 351 352-- bug in 5.1 353T, K, V = nil 354grandparent = {} 355grandparent.__newindex = function(t,k,v) T=t; K=k; V=v end 356 357parent = {} 358parent.__newindex = parent 359setmetatable(parent, grandparent) 360 361child = setmetatable({}, parent) 362child.foo = 10 --> CRASH (on some machines) 363assert(T == parent and K == "foo" and V == 10) 364 365 366-- testing 'tonumber' 367assert(tonumber{} == nil) 368assert(tonumber('-012') == -010-2) 369assert(tonumber("0xffffffffffff") == 2^(4*12) - 1) 370assert(tonumber("0x"..string.rep("f", 150)) == 2^(4*150) - 1) 371 372-- testing 'tonumber' with base 373assert(tonumber(' 001010 ', 2) == 10) 374assert(tonumber(' 001010 ', 10) == 1010) 375assert(tonumber(' -1010 ', 2) == -10) 376assert(tonumber('10', 36) == 36) 377assert(tonumber(' -10 ', 36) == -36) 378assert(tonumber(' +1Z ', 36) == 36 + 35) 379assert(tonumber(' -1z ', 36) == -36 + -35) 380assert(tonumber('-fFfa', 16) == -(10+(16*(15+(16*(15+(16*15))))))) 381assert(tonumber(string.rep('1', 42), 2) + 1 == 2^42) 382assert(tonumber(string.rep('1', 34), 2) + 1 == 2^34) 383assert(tonumber('ffffFFFF', 16)+1 == 2^32) 384assert(tonumber('0ffffFFFF', 16)+1 == 2^32) 385assert(tonumber('-0ffffffFFFF', 16) - 1 == -2^40) 386for i = 2,36 do 387 assert(tonumber('\t10000000000\t', i) == i^10) 388end 389 390-- testing 'tonumber' for invalid formats 391function f(...) 392 if select('#', ...) == 1 then 393 return (...) 394 else 395 return "***" 396 end 397end 398 399assert(f(tonumber('fFfa', 15)) == nil) 400assert(f(tonumber('099', 8)) == nil) 401assert(f(tonumber('1\0', 2)) == nil) 402assert(f(tonumber('', 8)) == nil) 403assert(f(tonumber(' ', 9)) == nil) 404assert(f(tonumber('0xf', 10)) == nil) 405 406assert(f(tonumber('inf')) == nil) 407assert(f(tonumber(' INF ')) == nil) 408assert(f(tonumber('Nan')) == nil) 409assert(f(tonumber('nan')) == nil) 410 411assert(f(tonumber('')) == nil) 412assert(f(tonumber('1 a')) == nil) 413assert(f(tonumber('1\0')) == nil) 414assert(f(tonumber('1 \0')) == nil) 415assert(f(tonumber('1\0 ')) == nil) 416assert(f(tonumber('e1')) == nil) 417assert(f(tonumber('e 1')) == nil) 418 419 420-- testing 'tonumber' for invalid hexadecimal formats 421assert(tonumber('0x') == nil) 422assert(tonumber('x') == nil) 423assert(tonumber('x3') == nil) 424assert(tonumber('00x2') == nil) 425assert(tonumber('0x 2') == nil) 426assert(tonumber('0 x2') == nil) 427assert(tonumber('23x') == nil) 428assert(tonumber('- 0xaa') == nil) 429 430 431-- testing hexadecimal numerals 432assert(tonumber('+0x2') == 2) 433assert(tonumber('-0xaA') == -170) 434assert(tonumber('-0xffFFFfff') == -2^32 + 1) 435 436 437-- testing 'tostring' 438assert(tostring("alo") == "alo") 439assert(tostring(12) == "12") 440assert(tostring(1234567890123) == '1234567890123') 441assert(type(tostring("hello")) == "string") 442assert(tostring(true) == "true") 443assert(tostring(false) == "false") 444assert(string.find(tostring{}, 'table:')) 445assert(string.find(tostring(select), 'function:')) 446assert(#tostring('\0') == 1) 447 448 449-- testing ipairs 450local x = 0 451for k,v in ipairs{10,20,30;x=12} do 452 x = x + 1 453 assert(k == x and v == x * 10) 454end 455 456for _ in ipairs{x=12, y=24} do assert(nil) end 457 458-- test for 'false' x ipair 459x = false 460local i = 0 461for k,v in ipairs{true,false,true,false} do 462 i = i + 1 463 x = not x 464 assert(x == v) 465end 466assert(i == 4) 467 468 469return "OK" 470