nextvar.lua (22356B)
1 -- $Id: testes/nextvar.lua $ 2 -- See Copyright Notice in file all.lua 3 4 print('testing tables, next, and for') 5 6 local function checkerror (msg, f, ...) 7 local s, err = pcall(f, ...) 8 assert(not s and string.find(err, msg)) 9 end 10 11 12 13 ---------------------------------------------------------------- 14 local function printTable (t) 15 local a, h = T.querytab(t) 16 print("array:") 17 for i = 1, a do 18 print("", T.querytab(t, i - 1)) 19 end 20 print("hash:") 21 for i = 1, h do 22 print("", T.querytab(t, a + i - 1)) 23 end 24 end 25 ---------------------------------------------------------------- 26 local function countentries (t) 27 local e = 0 28 for _ in pairs(t) do e = e + 1 end 29 return e 30 end 31 ---------------------------------------------------------------- 32 33 34 local function check (t, na, nh) 35 if not T then return end 36 local a, h = T.querytab(t) 37 if a ~= na or h ~= nh then 38 print(na, nh, a, h) 39 assert(nil) 40 end 41 end 42 43 44 local a = {} 45 46 -- make sure table has lots of space in hash part 47 for i=1,100 do a[i.."+"] = true end 48 for i=1,100 do a[i.."+"] = undef end 49 -- fill hash part with numeric indices testing size operator 50 for i=1,100 do 51 a[i] = true 52 assert(#a == i) 53 end 54 55 56 do -- rehash moving elements from array to hash 57 local a = {} 58 for i = 1, 100 do a[i] = i end 59 check(a, 128, 0) 60 61 for i = 5, 95 do a[i] = nil end 62 check(a, 128, 0) 63 64 a[129] = 1 -- force a re-hash 65 check(a, 4, 8) -- keys larger than 4 go to the hash part 66 67 for i = 1, 4 do assert(a[i] == i) end 68 for i = 5, 95 do assert(a[i] == nil) end 69 for i = 96, 100 do assert(a[i] == i) end 70 assert(a[129] == 1) 71 end 72 73 74 do -- growing hash part keeping array part 75 local a = table.create(1000) 76 check(a, 1000, 0) 77 a.x = 10 78 check(a, 1000, 1) -- array part keeps its elements 79 end 80 81 82 do -- "growing" length of a prebuilt table 83 local N = 100 84 local a = table.create(N) 85 for i = 1, N do 86 a[#a + 1] = true 87 assert(#a == i) 88 end 89 check(a, N, 0) 90 end 91 92 93 -- testing ipairs 94 local x = 0 95 for k,v in ipairs{10,20,30;x=12} do 96 x = x + 1 97 assert(k == x and v == x * 10) 98 end 99 100 for _ in ipairs{x=12, y=24} do assert(nil) end 101 102 -- test for 'false' x ipair 103 x = false 104 local i = 0 105 for k,v in ipairs{true,false,true,false} do 106 i = i + 1 107 x = not x 108 assert(x == v) 109 end 110 assert(i == 4) 111 112 -- iterator function is always the same 113 assert(type(ipairs{}) == 'function' and ipairs{} == ipairs{}) 114 115 116 do -- overflow (must wrap-around) 117 local f = ipairs{} 118 local k, v = f({[math.mininteger] = 10}, math.maxinteger) 119 assert(k == math.mininteger and v == 10) 120 k, v = f({[math.mininteger] = 10}, k) 121 assert(k == nil) 122 end 123 124 125 do 126 -- alternate insertions and deletions in an almost full hash. 127 -- In versions pre-5.5, that causes constant rehashings and 128 -- takes a long time to complete. 129 local a = {} 130 for i = 1, 2^11 - 1 do 131 a[i .. ""] = true 132 end 133 134 for i = 1, 1e5 do 135 local key = i .. "." 136 a[key] = true 137 a[key] = nil 138 end 139 assert(countentries(a) == 2^11 - 1) 140 end 141 142 if not T then 143 (Message or print) 144 ('\n >>> testC not active: skipping tests for table sizes <<<\n') 145 else --[ 146 -- testing table sizes 147 148 149 -- minimum power of 2 (or zero) >= n 150 local function mp2 (n) 151 local mp = 2^math.ceil(math.log(n, 2)) 152 assert((mp == 0 or mp/2 < n) and n <= mp) 153 return mp 154 end 155 156 157 -- testing C library sizes 158 do 159 local s = 0 160 for _ in pairs(math) do s = s + 1 end 161 check(math, 0, mp2(s)) 162 end 163 164 165 -- testing constructor sizes 166 local sizes = {0, 1, 2, 3, 4, 5, 7, 8, 9, 15, 16, 17, 167 30, 31, 32, 33, 34, 254, 255, 256, 257, 500, 1001} 168 169 for _, sa in ipairs(sizes) do -- 'sa' is size of the array part 170 local arr = {"return {"} 171 for i = 1, sa do arr[1 + i] = "1," end -- build array part 172 for _, sh in ipairs(sizes) do -- 'sh' is size of the hash part 173 for j = 1, sh do -- build hash part 174 arr[1 + sa + j] = string.format('k%x=%d,', j, j) 175 end 176 arr[1 + sa + sh + 1] = "}" 177 local prog = table.concat(arr) 178 local f = assert(load(prog)) 179 collectgarbage("stop") 180 f() -- call once to ensure stack space 181 -- make sure table is not resized after being created 182 if sa == 0 or sh == 0 then 183 T.alloccount(2); -- header + array or hash part 184 else 185 T.alloccount(3); -- header + array part + hash part 186 end 187 local t = f() 188 T.alloccount(); 189 collectgarbage("restart") 190 assert(#t == sa) 191 check(t, sa, mp2(sh)) 192 end 193 end 194 195 196 -- tests with unknown number of elements 197 local a = {} 198 for i=1,sizes[#sizes] do a[i] = i end -- build auxiliary table 199 for k in ipairs(sizes) do 200 local t = {table.unpack(a,1,k)} 201 assert(#t == k) 202 check(t, k, 0) 203 t = {1,2,3,table.unpack(a,1,k)} 204 check(t, k+3, 0) 205 assert(#t == k + 3) 206 end 207 208 209 -- testing tables dynamically built 210 local lim = 130 211 local a = {}; a[2] = 1; check(a, 2, 0) 212 a = {}; a[0] = 1; check(a, 0, 1); 213 a[2] = 1; check(a, 2, 1) 214 a = {}; a[0] = 1; a[1] = 1; check(a, 1, 1) 215 a = {} 216 for i = 1,lim do 217 a[i] = 1 218 assert(#a == i) 219 check(a, mp2(i), 0) 220 end 221 222 a = {} 223 for i = 1,lim do 224 a['a'..i] = 1 225 assert(#a == 0) 226 check(a, 0, mp2(i)) 227 end 228 229 230 -- insert and delete elements until a rehash occurr. Caller must ensure 231 -- that a rehash will change the shape of the table. Must repeat because 232 -- the insertion may collide with the deleted element, and then there is 233 -- no rehash. 234 local function forcerehash (t) 235 local na, nh = T.querytab(t) 236 local i = 10000 237 repeat 238 i = i + 1 239 t[i] = true 240 t[i] = undef 241 local nna, nnh = T.querytab(t) 242 until nna ~= na or nnh ~= nh 243 end 244 245 246 do 247 local a = {} 248 for i=1,16 do a[i] = i end 249 check(a, 16, 0) 250 for i=1,11 do a[i] = undef end 251 check(a, 16, 0) 252 a[30] = true -- force a rehash 253 a[30] = undef 254 check(a, 0, 8) -- 5 elements in the hash part: [12]-[16] 255 a[10] = 1 256 forcerehash(a) 257 check(a, 16, 1) 258 for i=1,14 do a[i] = true; a[i] = undef end 259 check(a, 16, 1) -- no rehash... 260 a[31] = true; a[32] = true -- force a rehash 261 check(a, 0, 4) -- [15], [16], [31], [32] 262 end 263 264 -- reverse filling 265 do 266 local N = 2^10 267 local a = {} 268 for i = N, 1, -1 do a[i] = i end -- fill in reverse 269 check(a, mp2(N), 0) 270 end 271 272 273 do -- "almost sparse" arrays 274 -- create table with holes in 1/3 of its entries; all its 275 -- elements are always in the array part 276 local a = {} 277 for i = 1, 257 do 278 if i % 3 ~= 1 then 279 a[i] = true 280 check(a, mp2(i), 0) 281 end 282 end 283 end 284 285 286 do 287 -- alternate insertions and deletions should give some extra 288 -- space for the hash part. Otherwise, a mix of insertions/deletions 289 -- could cause too many rehashes. (See the other test for "alternate 290 -- insertions and deletions" in this file.) 291 local a = {} 292 for i = 1, 256 do 293 a[i .. ""] = true 294 end 295 check(a, 0, 256) -- hash part is full 296 a["256"] = nil -- delete a key 297 forcerehash(a) 298 -- table has only 255 elements, but it got some extra space; 299 -- otherwise, almost each delete-insert would rehash the table again. 300 assert(countentries(a) == 255) 301 check(a, 0, 512) 302 end 303 304 305 -- size tests for vararg 306 lim = 35 307 local function foo (n, ...) 308 local arg = {...} 309 check(arg, n, 0) 310 assert(select('#', ...) == n) 311 arg[n+1] = true 312 check(arg, mp2(n+1), 0) 313 arg.x = true 314 check(arg, mp2(n+1), 1) 315 end 316 local a = {} 317 for i=1,lim do a[i] = true; foo(i, table.unpack(a)) end 318 319 end --] 320 321 322 -- test size operation on tables with nils 323 assert(#{} == 0) 324 assert(#{nil} == 0) 325 assert(#{nil, nil} == 0) 326 assert(#{nil, nil, nil} == 0) 327 assert(#{nil, nil, nil, nil} == 0) 328 assert(#{1, 2, 3, nil, nil} == 3) 329 print'+' 330 331 332 do 333 local s1, s2 = math.randomseed() 334 print(string.format( 335 "testing length for some random tables (seeds 0X%x:%x)", s1, s2)) 336 local N = 130 337 for i = 1, 1e3 do -- create that many random tables 338 local a = table.create(math.random(N)) -- initiate with random size 339 for j = 1, math.random(N) do -- add random number of random entries 340 a[math.random(N)] = true 341 end 342 assert(#a == 0 or a[#a] and not a[#a + 1]) 343 end 344 end 345 346 local nofind = {} 347 348 a,b,c = 1,2,3 349 a,b,c = nil 350 351 352 -- next uses always the same iteraction function 353 assert(next{} == next{}) 354 355 local function find (name) 356 local n,v 357 while 1 do 358 n,v = next(_G, n) 359 if not n then return nofind end 360 assert(_G[n] ~= undef) 361 if n == name then return v end 362 end 363 end 364 365 local function find1 (name) 366 for n,v in pairs(_G) do 367 if n==name then return v end 368 end 369 return nil -- not found 370 end 371 372 373 assert(print==find("print") and print == find1("print")) 374 assert(_G["print"]==find("print")) 375 assert(assert==find1("assert")) 376 assert(nofind==find("return")) 377 assert(not find1("return")) 378 _G["ret" .. "urn"] = undef 379 assert(nofind==find("return")) 380 _G["xxx"] = 1 381 assert(xxx==find("xxx")) 382 383 -- invalid key to 'next' 384 checkerror("invalid key", next, {10,20}, 3) 385 386 -- both 'pairs' and 'ipairs' need an argument 387 checkerror("bad argument", pairs) 388 checkerror("bad argument", ipairs) 389 390 print('+') 391 392 a = {} 393 for i=0,10000 do 394 if math.fmod(i,10) ~= 0 then 395 a['x'..i] = i 396 end 397 end 398 399 n = {n=0} 400 for i,v in pairs(a) do 401 n.n = n.n+1 402 assert(i and v and a[i] == v) 403 end 404 assert(n.n == 9000) 405 a = nil 406 407 do -- clear global table 408 local a = {} 409 for n,v in pairs(_G) do a[n]=v end 410 for n,v in pairs(a) do 411 if not package.loaded[n] and type(v) ~= "function" and 412 not string.find(n, "^[%u_]") then 413 _G[n] = undef 414 end 415 collectgarbage() 416 end 417 end 418 419 420 -- 421 422 local function checknext (a) 423 local b = {} 424 do local k,v = next(a); while k do b[k] = v; k,v = next(a,k) end end 425 for k,v in pairs(b) do assert(a[k] == v) end 426 for k,v in pairs(a) do assert(b[k] == v) end 427 end 428 429 checknext{1,x=1,y=2,z=3} 430 checknext{1,2,x=1,y=2,z=3} 431 checknext{1,2,3,x=1,y=2,z=3} 432 checknext{1,2,3,4,x=1,y=2,z=3} 433 checknext{1,2,3,4,5,x=1,y=2,z=3} 434 435 assert(#{} == 0) 436 assert(#{[-1] = 2} == 0) 437 for i=0,40 do 438 local a = {} 439 for j=1,i do a[j]=j end 440 assert(#a == i) 441 end 442 443 -- 'maxn' is now deprecated, but it is easily defined in Lua 444 function table.maxn (t) 445 local max = 0 446 for k in pairs(t) do 447 max = (type(k) == 'number') and math.max(max, k) or max 448 end 449 return max 450 end 451 452 assert(table.maxn{} == 0) 453 assert(table.maxn{["1000"] = true} == 0) 454 assert(table.maxn{["1000"] = true, [24.5] = 3} == 24.5) 455 assert(table.maxn{[1000] = true} == 1000) 456 assert(table.maxn{[10] = true, [100*math.pi] = print} == 100*math.pi) 457 458 table.maxn = nil 459 460 -- int overflow 461 a = {} 462 for i=0,50 do a[2^i] = true end 463 assert(a[#a]) 464 465 print('+') 466 467 468 do -- testing 'next' with all kinds of keys 469 local a = { 470 [1] = 1, -- integer 471 [1.1] = 2, -- float 472 ['x'] = 3, -- short string 473 [string.rep('x', 1000)] = 4, -- long string 474 [print] = 5, -- C function 475 [checkerror] = 6, -- Lua function 476 [coroutine.running()] = 7, -- thread 477 [true] = 8, -- boolean 478 [io.stdin] = 9, -- userdata 479 [{}] = 10, -- table 480 } 481 local b = {}; for i = 1, 10 do b[i] = true end 482 for k, v in pairs(a) do 483 assert(b[v]); b[v] = undef 484 end 485 assert(next(b) == nil) -- 'b' now is empty 486 end 487 488 489 -- erasing values 490 local t = {[{1}] = 1, [{2}] = 2, [string.rep("x ", 4)] = 3, 491 [100.3] = 4, [4] = 5} 492 493 local n = 0 494 for k, v in pairs( t ) do 495 n = n+1 496 assert(t[k] == v) 497 t[k] = undef 498 collectgarbage() 499 assert(t[k] == undef) 500 end 501 assert(n == 5) 502 503 504 do 505 print("testing next x GC of deleted keys") 506 -- bug in 5.4.1 507 local co = coroutine.wrap(function (t) 508 for k, v in pairs(t) do 509 local k1 = next(t) -- all previous keys were deleted 510 assert(k == k1) -- current key is the first in the table 511 t[k] = nil 512 local expected = (type(k) == "table" and k[1] or 513 type(k) == "function" and k() or 514 string.sub(k, 1, 1)) 515 assert(expected == v) 516 coroutine.yield(v) 517 end 518 end) 519 local t = {} 520 t[{1}] = 1 -- add several unanchored, collectable keys 521 t[{2}] = 2 522 t[string.rep("a", 50)] = "a" -- long string 523 t[string.rep("b", 50)] = "b" 524 t[{3}] = 3 525 t[string.rep("c", 10)] = "c" -- short string 526 t[function () return 10 end] = 10 527 local count = 7 528 while co(t) do 529 collectgarbage("collect") -- collect dead keys 530 count = count - 1 531 end 532 assert(count == 0 and next(t) == nil) -- traversed the whole table 533 end 534 535 536 local function test (a) 537 assert(not pcall(table.insert, a, 2, 20)); 538 table.insert(a, 10); table.insert(a, 2, 20); 539 table.insert(a, 1, -1); table.insert(a, 40); 540 table.insert(a, #a+1, 50) 541 table.insert(a, 2, -2) 542 assert(a[2] ~= undef) 543 assert(a["2"] == undef) 544 assert(not pcall(table.insert, a, 0, 20)); 545 assert(not pcall(table.insert, a, #a + 2, 20)); 546 assert(table.remove(a,1) == -1) 547 assert(table.remove(a,1) == -2) 548 assert(table.remove(a,1) == 10) 549 assert(table.remove(a,1) == 20) 550 assert(table.remove(a,1) == 40) 551 assert(table.remove(a,1) == 50) 552 assert(table.remove(a,1) == nil) 553 assert(table.remove(a) == nil) 554 assert(table.remove(a, #a) == nil) 555 end 556 557 a = {n=0, [-7] = "ban"} 558 test(a) 559 assert(a.n == 0 and a[-7] == "ban") 560 561 a = {[-7] = "ban"}; 562 test(a) 563 assert(a.n == nil and #a == 0 and a[-7] == "ban") 564 565 a = {[-1] = "ban"} 566 test(a) 567 assert(#a == 0 and table.remove(a) == nil and a[-1] == "ban") 568 569 a = {[0] = "ban"} 570 assert(#a == 0 and table.remove(a) == "ban" and a[0] == undef) 571 572 table.insert(a, 1, 10); table.insert(a, 1, 20); table.insert(a, 1, -1) 573 assert(table.remove(a) == 10) 574 assert(table.remove(a) == 20) 575 assert(table.remove(a) == -1) 576 assert(table.remove(a) == nil) 577 578 a = {'c', 'd'} 579 table.insert(a, 3, 'a') 580 table.insert(a, 'b') 581 assert(table.remove(a, 1) == 'c') 582 assert(table.remove(a, 1) == 'd') 583 assert(table.remove(a, 1) == 'a') 584 assert(table.remove(a, 1) == 'b') 585 assert(table.remove(a, 1) == nil) 586 assert(#a == 0 and a.n == nil) 587 588 a = {10,20,30,40} 589 assert(table.remove(a, #a + 1) == nil) 590 assert(not pcall(table.remove, a, 0)) 591 assert(a[#a] == 40) 592 assert(table.remove(a, #a) == 40) 593 assert(a[#a] == 30) 594 assert(table.remove(a, 2) == 20) 595 assert(a[#a] == 30 and #a == 2) 596 597 do -- testing table library with metamethods 598 local function test (proxy, t) 599 for i = 1, 10 do 600 table.insert(proxy, 1, i) 601 end 602 assert(#proxy == 10 and #t == 10 and proxy[1] ~= undef) 603 for i = 1, 10 do 604 assert(t[i] == 11 - i) 605 end 606 table.sort(proxy) 607 for i = 1, 10 do 608 assert(t[i] == i and proxy[i] == i) 609 end 610 assert(table.concat(proxy, ",") == "1,2,3,4,5,6,7,8,9,10") 611 for i = 1, 8 do 612 assert(table.remove(proxy, 1) == i) 613 end 614 assert(#proxy == 2 and #t == 2) 615 local a, b, c = table.unpack(proxy) 616 assert(a == 9 and b == 10 and c == nil) 617 end 618 619 -- all virtual 620 local t = {} 621 local proxy = setmetatable({}, { 622 __len = function () return #t end, 623 __index = t, 624 __newindex = t, 625 }) 626 test(proxy, t) 627 628 -- only __newindex 629 local count = 0 630 t = setmetatable({}, { 631 __newindex = function (t,k,v) count = count + 1; rawset(t,k,v) end}) 632 test(t, t) 633 assert(count == 10) -- after first 10, all other sets are not new 634 635 -- no __newindex 636 t = setmetatable({}, { 637 __index = function (_,k) return k + 1 end, 638 __len = function (_) return 5 end}) 639 assert(table.concat(t, ";") == "2;3;4;5;6") 640 641 end 642 643 644 do -- testing overflow in table.insert (must wrap-around) 645 646 local t = setmetatable({}, 647 {__len = function () return math.maxinteger end}) 648 table.insert(t, 20) 649 local k, v = next(t) 650 assert(k == math.mininteger and v == 20) 651 end 652 653 if not T then 654 (Message or print) 655 ('\n >>> testC not active: skipping tests for table library on non-tables <<<\n') 656 else --[ 657 local debug = require'debug' 658 local tab = {10, 20, 30} 659 local mt = {} 660 local u = T.newuserdata(0) 661 checkerror("table expected", table.insert, u, 40) 662 checkerror("table expected", table.remove, u) 663 debug.setmetatable(u, mt) 664 checkerror("table expected", table.insert, u, 40) 665 checkerror("table expected", table.remove, u) 666 mt.__index = tab 667 checkerror("table expected", table.insert, u, 40) 668 checkerror("table expected", table.remove, u) 669 mt.__newindex = tab 670 checkerror("table expected", table.insert, u, 40) 671 checkerror("table expected", table.remove, u) 672 mt.__len = function () return #tab end 673 table.insert(u, 40) 674 assert(#u == 4 and #tab == 4 and u[4] == 40 and tab[4] == 40) 675 assert(table.remove(u) == 40) 676 table.insert(u, 1, 50) 677 assert(#u == 4 and #tab == 4 and u[4] == 30 and tab[1] == 50) 678 679 mt.__newindex = nil 680 mt.__len = nil 681 local tab2 = {} 682 local u2 = T.newuserdata(0) 683 debug.setmetatable(u2, {__newindex = function (_, k, v) tab2[k] = v end}) 684 table.move(u, 1, 4, 1, u2) 685 assert(#tab2 == 4 and tab2[1] == tab[1] and tab2[4] == tab[4]) 686 687 end -- ] 688 689 print('+') 690 691 a = {} 692 for i=1,1000 do 693 a[i] = i; a[i - 1] = undef 694 end 695 assert(next(a,nil) == 1000 and next(a,1000) == nil) 696 697 assert(next({}) == nil) 698 assert(next({}, nil) == nil) 699 700 for a,b in pairs{} do error"not here" end 701 for i=1,0 do error'not here' end 702 for i=0,1,-1 do error'not here' end 703 a = nil; for i=1,1 do assert(not a); a=1 end; assert(a) 704 a = nil; for i=1,1,-1 do assert(not a); a=1 end; assert(a) 705 706 do 707 print("testing floats in numeric for") 708 local a 709 -- integer count 710 a = 0; for i=1, 1, 1 do a=a+1 end; assert(a==1) 711 a = 0; for i=10000, 1e4, -1 do a=a+1 end; assert(a==1) 712 a = 0; for i=1, 0.99999, 1 do a=a+1 end; assert(a==0) 713 a = 0; for i=9999, 1e4, -1 do a=a+1 end; assert(a==0) 714 a = 0; for i=1, 0.99999, -1 do a=a+1 end; assert(a==1) 715 716 -- float count 717 a = 0; for i=0, 0.999999999, 0.1 do a=a+1 end; assert(a==10) 718 a = 0; for i=1.0, 1, 1 do a=a+1 end; assert(a==1) 719 a = 0; for i=-1.5, -1.5, 1 do a=a+1 end; assert(a==1) 720 a = 0; for i=1e6, 1e6, -1 do a=a+1 end; assert(a==1) 721 a = 0; for i=1.0, 0.99999, 1 do a=a+1 end; assert(a==0) 722 a = 0; for i=99999, 1e5, -1.0 do a=a+1 end; assert(a==0) 723 a = 0; for i=1.0, 0.99999, -1 do a=a+1 end; assert(a==1) 724 end 725 726 do -- attempt to change the control variable 727 local st, msg = load "for i = 1, 10 do i = 10 end" 728 assert(not st and string.find(msg, "assign to const variable 'i'")) 729 730 local st, msg = load "for v, k in pairs{} do v = 10 end" 731 assert(not st and string.find(msg, "assign to const variable 'v'")) 732 end 733 734 -- conversion 735 a = 0; for i="10","1","-2" do a=a+1 end; assert(a==5) 736 737 do -- checking types 738 local c 739 local function checkfloat (i) 740 assert(math.type(i) == "float") 741 c = c + 1 742 end 743 744 c = 0; for i = 1.0, 10 do checkfloat(i) end 745 assert(c == 10) 746 747 c = 0; for i = -1, -10, -1.0 do checkfloat(i) end 748 assert(c == 10) 749 750 local function checkint (i) 751 assert(math.type(i) == "integer") 752 c = c + 1 753 end 754 755 local m = math.maxinteger 756 c = 0; for i = m, m - 10, -1 do checkint(i) end 757 assert(c == 11) 758 759 c = 0; for i = 1, 10.9 do checkint(i) end 760 assert(c == 10) 761 762 c = 0; for i = 10, 0.001, -1 do checkint(i) end 763 assert(c == 10) 764 765 c = 0; for i = 1, "10.8" do checkint(i) end 766 assert(c == 10) 767 768 c = 0; for i = 9, "3.4", -1 do checkint(i) end 769 assert(c == 6) 770 771 c = 0; for i = 0, " -3.4 ", -1 do checkint(i) end 772 assert(c == 4) 773 774 c = 0; for i = 100, "96.3", -2 do checkint(i) end 775 assert(c == 2) 776 777 c = 0; for i = 1, math.huge do if i > 10 then break end; checkint(i) end 778 assert(c == 10) 779 780 c = 0; for i = -1, -math.huge, -1 do 781 if i < -10 then break end; checkint(i) 782 end 783 assert(c == 10) 784 785 786 for i = math.mininteger, -10e100 do assert(false) end 787 for i = math.maxinteger, 10e100, -1 do assert(false) end 788 789 end 790 791 792 do -- testing other strange cases for numeric 'for' 793 794 local function checkfor (from, to, step, t) 795 local c = 0 796 for i = from, to, step do 797 c = c + 1 798 assert(i == t[c]) 799 end 800 assert(c == #t) 801 end 802 803 local maxi = math.maxinteger 804 local mini = math.mininteger 805 806 checkfor(mini, maxi, maxi, {mini, -1, maxi - 1}) 807 808 checkfor(mini, math.huge, maxi, {mini, -1, maxi - 1}) 809 810 checkfor(maxi, mini, mini, {maxi, -1}) 811 812 checkfor(maxi, mini, -maxi, {maxi, 0, -maxi}) 813 814 checkfor(maxi, -math.huge, mini, {maxi, -1}) 815 816 checkfor(maxi, mini, 1, {}) 817 checkfor(mini, maxi, -1, {}) 818 819 checkfor(maxi - 6, maxi, 3, {maxi - 6, maxi - 3, maxi}) 820 checkfor(mini + 4, mini, -2, {mini + 4, mini + 2, mini}) 821 822 local step = maxi // 10 823 local c = mini 824 for i = mini, maxi, step do 825 assert(i == c) 826 c = c + step 827 end 828 829 c = maxi 830 for i = maxi, mini, -step do 831 assert(i == c) 832 c = c - step 833 end 834 835 checkfor(maxi, maxi, maxi, {maxi}) 836 checkfor(maxi, maxi, mini, {maxi}) 837 checkfor(mini, mini, maxi, {mini}) 838 checkfor(mini, mini, mini, {mini}) 839 end 840 841 842 checkerror("'for' step is zero", function () 843 for i = 1, 10, 0 do end 844 end) 845 846 checkerror("'for' step is zero", function () 847 for i = 1, -10, 0 do end 848 end) 849 850 checkerror("'for' step is zero", function () 851 for i = 1.0, -10, 0.0 do end 852 end) 853 854 collectgarbage() 855 856 857 -- testing generic 'for' 858 859 local function f (n, p) 860 local t = {}; for i=1,p do t[i] = i*10 end 861 return function (_, n, ...) 862 assert(select("#", ...) == 0) -- no extra arguments 863 if n > 0 then 864 n = n-1 865 return n, table.unpack(t) 866 end 867 end, nil, n 868 end 869 870 local x = 0 871 for n,a,b,c,d in f(5,3) do 872 x = x+1 873 assert(a == 10 and b == 20 and c == 30 and d == nil) 874 end 875 assert(x == 5) 876 877 878 879 -- testing __pairs and __ipairs metamethod 880 a = {} 881 do 882 local x,y,z = pairs(a) 883 assert(type(x) == 'function' and y == a and z == nil) 884 end 885 886 local function foo (e,i) 887 assert(e == a) 888 if i <= 10 then return i+1, i+2 end 889 end 890 891 local function foo1 (e,i) 892 i = i + 1 893 assert(e == a) 894 if i <= e.n then return i,a[i] end 895 end 896 897 setmetatable(a, {__pairs = function (x) return foo, x, 0 end}) 898 899 local i = 0 900 for k,v in pairs(a) do 901 i = i + 1 902 assert(k == i and v == k+1) 903 end 904 905 a.n = 5 906 a[3] = 30 907 908 -- testing ipairs with metamethods 909 a = {n=10} 910 setmetatable(a, { __index = function (t,k) 911 if k <= t.n then return k * 10 end 912 end}) 913 i = 0 914 for k,v in ipairs(a) do 915 i = i + 1 916 assert(k == i and v == i * 10) 917 end 918 assert(i == a.n) 919 920 921 -- testing yield inside __pairs 922 do 923 local t = setmetatable({10, 20, 30}, {__pairs = function (t) 924 local inc = coroutine.yield() 925 return function (t, i) 926 if i > 1 then return i - inc, t[i - inc] else return nil end 927 end, t, #t + 1 928 end}) 929 930 local res = {} 931 local co = coroutine.wrap(function () 932 for i,p in pairs(t) do res[#res + 1] = p end 933 end) 934 935 co() -- start coroutine 936 co(1) -- continue after yield 937 assert(res[1] == 30 and res[2] == 20 and res[3] == 10 and #res == 3) 938 939 end 940 941 print"OK"