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