lua

A copy of the Lua development repository
Log | Files | Refs | README

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"