lua

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

attrib.lua (13410B)


      1 -- $Id: testes/attrib.lua $
      2 -- See Copyright Notice in file all.lua
      3 
      4 print "testing require"
      5 
      6 assert(require"string" == string)
      7 assert(require"math" == math)
      8 assert(require"table" == table)
      9 assert(require"io" == io)
     10 assert(require"os" == os)
     11 assert(require"coroutine" == coroutine)
     12 
     13 assert(type(package.path) == "string")
     14 assert(type(package.cpath) == "string")
     15 assert(type(package.loaded) == "table")
     16 assert(type(package.preload) == "table")
     17 
     18 assert(type(package.config) == "string")
     19 print("package config: "..string.gsub(package.config, "\n", "|"))
     20 
     21 do
     22   -- create a path with 'max' templates,
     23   -- each with 1-10 repetitions of '?'
     24   local max = _soft and 100 or 2000
     25   local t = {}
     26   for i = 1,max do t[i] = string.rep("?", i%10 + 1) end
     27   t[#t + 1] = ";"    -- empty template
     28   local path = table.concat(t, ";")
     29   -- use that path in a search
     30   local s, err = package.searchpath("xuxu", path)
     31   -- search fails; check that message has an occurrence of
     32   -- '??????????' with ? replaced by xuxu and at least 'max' lines
     33   assert(not s and
     34          string.find(err, string.rep("xuxu", 10)) and
     35          #string.gsub(err, "[^\n]", "") >= max)
     36   -- path with one very long template
     37   local path = string.rep("?", max)
     38   local s, err = package.searchpath("xuxu", path)
     39   assert(not s and string.find(err, string.rep('xuxu', max)))
     40 end
     41 
     42 do
     43   local oldpath = package.path
     44   package.path = {}
     45   local s, err = pcall(require, "no-such-file")
     46   assert(not s and string.find(err, "package.path"))
     47   package.path = oldpath
     48 end
     49 
     50 
     51 do  print"testing 'require' message"
     52   local oldpath = package.path
     53   local oldcpath = package.cpath
     54 
     55   package.path = "?.lua;?/?"
     56   package.cpath = "?.so;?/init"
     57 
     58   local st, msg = pcall(require, 'XXX')
     59 
     60   local expected = [[module 'XXX' not found:
     61 	no field package.preload['XXX']
     62 	no file 'XXX.lua'
     63 	no file 'XXX/XXX'
     64 	no file 'XXX.so'
     65 	no file 'XXX/init']]
     66 
     67   assert(msg == expected)
     68 
     69   package.path = oldpath
     70   package.cpath = oldcpath
     71 end
     72 
     73 print('+')
     74 
     75 
     76 -- The next tests for 'require' assume some specific directories and
     77 -- libraries.
     78 
     79 if not _port then --[
     80 
     81 local dirsep = string.match(package.config, "^([^\n]+)\n")
     82 
     83 -- auxiliary directory with C modules and temporary files
     84 local DIR = "libs" .. dirsep
     85 
     86 -- prepend DIR to a name and correct directory separators
     87 local function D (x)
     88   local x = string.gsub(x, "/", dirsep)
     89   return DIR .. x
     90 end
     91 
     92 -- prepend DIR and pospend proper C lib. extension to a name
     93 local function DC (x)
     94   local ext = (dirsep == '\\') and ".dll" or ".so"
     95   return D(x .. ext)
     96 end
     97 
     98 
     99 local function createfiles (files, preextras, posextras)
    100   for n,c in pairs(files) do
    101     io.output(D(n))
    102     io.write(string.format(preextras, n))
    103     io.write(c)
    104     io.write(string.format(posextras, n))
    105     io.close(io.output())
    106   end
    107 end
    108 
    109 local function removefiles (files)
    110   for n in pairs(files) do
    111     os.remove(D(n))
    112   end
    113 end
    114 
    115 local files = {
    116   ["names.lua"] = "do return {...} end\n",
    117   ["err.lua"] = "B = 15; a = a + 1;",
    118   ["synerr.lua"] = "B =",
    119   ["A.lua"] = "",
    120   ["B.lua"] = "assert(...=='B');require 'A'",
    121   ["A.lc"] = "",
    122   ["A"] = "",
    123   ["L"] = "",
    124   ["XXxX"] = "",
    125   ["C.lua"] = "package.loaded[...] = 25; require'C'",
    126 }
    127 
    128 AA = nil
    129 local extras = [[
    130 NAME = '%s'
    131 REQUIRED = ...
    132 return AA]]
    133 
    134 createfiles(files, "", extras)
    135 
    136 -- testing explicit "dir" separator in 'searchpath'
    137 assert(package.searchpath("C.lua", D"?", "", "") == D"C.lua")
    138 assert(package.searchpath("C.lua", D"?", ".", ".") == D"C.lua")
    139 assert(package.searchpath("--x-", D"?", "-", "X") == D"XXxX")
    140 assert(package.searchpath("---xX", D"?", "---", "XX") == D"XXxX")
    141 assert(package.searchpath(D"C.lua", "?", dirsep) == D"C.lua")
    142 assert(package.searchpath(".\\C.lua", D"?", "\\") == D"./C.lua")
    143 
    144 local oldpath = package.path
    145 
    146 package.path = string.gsub("D/?.lua;D/?.lc;D/?;D/??x?;D/L", "D/", DIR)
    147 
    148 local try = function (p, n, r, ext)
    149   NAME = nil
    150   local rr, x = require(p)
    151   assert(NAME == n)
    152   assert(REQUIRED == p)
    153   assert(rr == r)
    154   assert(ext == x)
    155 end
    156 
    157 local a = require"names"
    158 assert(a[1] == "names" and a[2] == D"names.lua")
    159 
    160 local st, msg = pcall(require, "err")
    161 assert(not st and string.find(msg, "arithmetic") and B == 15)
    162 st, msg = pcall(require, "synerr")
    163 assert(not st and string.find(msg, "error loading module"))
    164 
    165 assert(package.searchpath("C", package.path) == D"C.lua")
    166 assert(require"C" == 25)
    167 assert(require"C" == 25)
    168 AA = nil
    169 try('B', 'B.lua', true, "libs/B.lua")
    170 assert(package.loaded.B)
    171 assert(require"B" == true)
    172 assert(package.loaded.A)
    173 assert(require"C" == 25)
    174 package.loaded.A = nil
    175 try('B', nil, true, nil)   -- should not reload package
    176 try('A', 'A.lua', true, "libs/A.lua")
    177 package.loaded.A = nil
    178 os.remove(D'A.lua')
    179 AA = {}
    180 try('A', 'A.lc', AA, "libs/A.lc")  -- now must find second option
    181 assert(package.searchpath("A", package.path) == D"A.lc")
    182 assert(require("A") == AA)
    183 AA = false
    184 try('K', 'L', false, "libs/L")     -- default option
    185 try('K', 'L', false, "libs/L")     -- default option (should reload it)
    186 assert(rawget(_G, "_REQUIREDNAME") == nil)
    187 
    188 AA = "x"
    189 try("X", "XXxX", AA, "libs/XXxX")
    190 
    191 
    192 removefiles(files)
    193 NAME, REQUIRED, AA, B = nil
    194 
    195 
    196 -- testing require of sub-packages
    197 
    198 local _G = _G
    199 
    200 package.path = string.gsub("D/?.lua;D/?/init.lua", "D/", DIR)
    201 
    202 files = {
    203   ["P1/init.lua"] = "AA = 10",
    204   ["P1/xuxu.lua"] = "AA = 20",
    205 }
    206 
    207 createfiles(files, "_ENV = {}\n", "\nreturn _ENV\n")
    208 AA = 0
    209 
    210 local m, ext = assert(require"P1")
    211 assert(ext == "libs/P1/init.lua")
    212 assert(AA == 0 and m.AA == 10)
    213 assert(require"P1" == m)
    214 assert(require"P1" == m)
    215 
    216 assert(package.searchpath("P1.xuxu", package.path) == D"P1/xuxu.lua")
    217 m.xuxu, ext = assert(require"P1.xuxu")
    218 assert(AA == 0 and m.xuxu.AA == 20)
    219 assert(ext == "libs/P1/xuxu.lua")
    220 assert(require"P1.xuxu" == m.xuxu)
    221 assert(require"P1.xuxu" == m.xuxu)
    222 assert(require"P1" == m and m.AA == 10)
    223 
    224 
    225 removefiles(files)
    226 AA = nil
    227 
    228 package.path = ""
    229 assert(not pcall(require, "file_does_not_exist"))
    230 package.path = "??\0?"
    231 assert(not pcall(require, "file_does_not_exist1"))
    232 
    233 package.path = oldpath
    234 
    235 -- check 'require' error message
    236 local fname = "file_does_not_exist2"
    237 local m, err = pcall(require, fname)
    238 for t in string.gmatch(package.path..";"..package.cpath, "[^;]+") do
    239   local t = string.gsub(t, "?", fname)
    240   assert(string.find(err, t, 1, true))
    241 end
    242 
    243 do  -- testing 'package.searchers' not being a table
    244   local searchers = package.searchers
    245   package.searchers = 3
    246   local st, msg = pcall(require, 'a')
    247   assert(not st and string.find(msg, "must be a table"))
    248   package.searchers = searchers
    249 end
    250 
    251 local function import(...)
    252   local f = {...}
    253   return function (m)
    254     for i=1, #f do m[f[i]] = _G[f[i]] end
    255   end
    256 end
    257 
    258 -- cannot change environment of a C function
    259 assert(not pcall(module, 'XUXU'))
    260 
    261 
    262 
    263 -- testing require of C libraries
    264 
    265 
    266 local p = ""   -- On Mac OS X, redefine this to "_"
    267 
    268 -- check whether loadlib works in this system
    269 local st, err, when = package.loadlib(DC"lib1", "*")
    270 if not st then
    271   local f, err, when = package.loadlib("donotexist", p.."xuxu")
    272   assert(not f and type(err) == "string" and when == "absent")
    273   ;(Message or print)('\n >>> cannot load dynamic library <<<\n')
    274   print(err, when)
    275 else
    276   -- tests for loadlib
    277   local f = assert(package.loadlib(DC"lib1", p.."onefunction"))
    278   local a, b = f(15, 25)
    279   assert(a == 25 and b == 15)
    280 
    281   f = assert(package.loadlib(DC"lib1", p.."anotherfunc"))
    282   assert(f(10, 20) == "10%20\n")
    283 
    284   -- check error messages
    285   local f, err, when = package.loadlib(DC"lib1", p.."xuxu")
    286   assert(not f and type(err) == "string" and when == "init")
    287   f, err, when = package.loadlib("donotexist", p.."xuxu")
    288   assert(not f and type(err) == "string" and when == "open")
    289 
    290   -- symbols from 'lib1' must be visible to other libraries
    291   f = assert(package.loadlib(DC"lib11", p.."luaopen_lib11"))
    292   assert(f() == "exported")
    293 
    294   -- test C modules with prefixes in names
    295   package.cpath = DC"?"
    296   local lib2, ext = require"lib2-v2"
    297   assert(string.find(ext, "libs/lib2-v2", 1, true))
    298   -- check correct access to global environment and correct
    299   -- parameters
    300   assert(_ENV.x == "lib2-v2" and _ENV.y == DC"lib2-v2")
    301   assert(lib2.id("x") == true)   -- a different "id" implementation
    302 
    303   -- test C submodules
    304   local fs, ext = require"lib1.sub"
    305   assert(_ENV.x == "lib1.sub" and _ENV.y == DC"lib1")
    306   assert(string.find(ext, "libs/lib1", 1, true))
    307   assert(fs.id(45) == 45)
    308   _ENV.x, _ENV.y = nil
    309 end
    310 
    311 _ENV = _G
    312 
    313 
    314 -- testing preload
    315 
    316 do
    317   local p = package
    318   package = {}
    319   p.preload.pl = function (...)
    320     local _ENV = {...}
    321     function xuxu (x) return x+20 end
    322     return _ENV
    323   end
    324 
    325   local pl, ext = require"pl"
    326   assert(require"pl" == pl)
    327   assert(pl.xuxu(10) == 30)
    328   assert(pl[1] == "pl" and pl[2] == ":preload:" and ext == ":preload:")
    329 
    330   package = p
    331   assert(type(package.path) == "string")
    332 end
    333 
    334 print('+')
    335 
    336 end  --]
    337 
    338 print("testing assignments, logical operators, and constructors")
    339 
    340 local res, res2 = 27
    341 
    342 local a, b = 1, 2+3
    343 assert(a==1 and b==5)
    344 a={}
    345 local function f() return 10, 11, 12 end
    346 a.x, b, a[1] = 1, 2, f()
    347 assert(a.x==1 and b==2 and a[1]==10)
    348 a[f()], b, a[f()+3] = f(), a, 'x'
    349 assert(a[10] == 10 and b == a and a[13] == 'x')
    350 
    351 do
    352   local f = function (n) local x = {}; for i=1,n do x[i]=i end;
    353                          return table.unpack(x) end;
    354   local a,b,c
    355   a,b = 0, f(1)
    356   assert(a == 0 and b == 1)
    357   a,b = 0, f(1)
    358   assert(a == 0 and b == 1)
    359   a,b,c = 0,5,f(4)
    360   assert(a==0 and b==5 and c==1)
    361   a,b,c = 0,5,f(0)
    362   assert(a==0 and b==5 and c==nil)
    363 end
    364 
    365 local a, b, c, d = 1 and nil, 1 or nil, (1 and (nil or 1)), 6
    366 assert(not a and b and c and d==6)
    367 
    368 d = 20
    369 a, b, c, d = f()
    370 assert(a==10 and b==11 and c==12 and d==nil)
    371 a,b = f(), 1, 2, 3, f()
    372 assert(a==10 and b==1)
    373 
    374 assert(a<b == false and a>b == true)
    375 assert((10 and 2) == 2)
    376 assert((10 or 2) == 10)
    377 assert((10 or assert(nil)) == 10)
    378 assert(not (nil and assert(nil)))
    379 assert((nil or "alo") == "alo")
    380 assert((nil and 10) == nil)
    381 assert((false and 10) == false)
    382 assert((true or 10) == true)
    383 assert((false or 10) == 10)
    384 assert(false ~= nil)
    385 assert(nil ~= false)
    386 assert(not nil == true)
    387 assert(not not nil == false)
    388 assert(not not 1 == true)
    389 assert(not not a == true)
    390 assert(not not (6 or nil) == true)
    391 assert(not not (nil and 56) == false)
    392 assert(not not (nil and true) == false)
    393 assert(not 10 == false)
    394 assert(not {} == false)
    395 assert(not 0.5 == false)
    396 assert(not "x" == false)
    397 
    398 assert({} ~= {})
    399 print('+')
    400 
    401 a = {}
    402 a[true] = 20
    403 a[false] = 10
    404 assert(a[1<2] == 20 and a[1>2] == 10)
    405 
    406 function f(a) return a end
    407 
    408 local a = {}
    409 for i=3000,-3000,-1 do a[i + 0.0] = i; end
    410 a[10e30] = "alo"; a[true] = 10; a[false] = 20
    411 assert(a[10e30] == 'alo' and a[not 1] == 20 and a[10<20] == 10)
    412 for i=3000,-3000,-1 do assert(a[i] == i); end
    413 a[print] = assert
    414 a[f] = print
    415 a[a] = a
    416 assert(a[a][a][a][a][print] == assert)
    417 a[print](a[a[f]] == a[print])
    418 assert(not pcall(function () local a = {}; a[nil] = 10 end))
    419 assert(not pcall(function () local a = {[nil] = 10} end))
    420 assert(a[nil] == undef)
    421 a = nil
    422 
    423 local a, b, c
    424 a = {10,9,8,7,6,5,4,3,2; [-3]='a', [f]=print, a='a', b='ab'}
    425 a, a.x, a.y = a, a[-3]
    426 assert(a[1]==10 and a[-3]==a.a and a[f]==print and a.x=='a' and not a.y)
    427 a[1], f(a)[2], b, c = {['alo']=assert}, 10, a[1], a[f], 6, 10, 23, f(a), 2
    428 a[1].alo(a[2]==10 and b==10 and c==print)
    429 
    430 a.aVeryLongName012345678901234567890123456789012345678901234567890123456789 = 10
    431 local function foo ()
    432   return a.aVeryLongName012345678901234567890123456789012345678901234567890123456789
    433 end
    434 assert(foo() == 10 and
    435 a.aVeryLongName012345678901234567890123456789012345678901234567890123456789 ==
    436 10)
    437 
    438 
    439 do
    440   -- _ENV constant
    441   local function foo ()
    442     local _ENV <const> = 11
    443     X = "hi"
    444   end
    445   local st, msg = pcall(foo)
    446   assert(not st and string.find(msg, "number"))
    447 end
    448 
    449 
    450 -- test of large float/integer indices 
    451 
    452 -- compute maximum integer where all bits fit in a float
    453 local maxint = math.maxinteger
    454 
    455 -- trim (if needed) to fit in a float
    456 while maxint ~= (maxint + 0.0) or (maxint - 1) ~= (maxint - 1.0) do
    457   maxint = maxint // 2
    458 end
    459 
    460 local maxintF = maxint + 0.0   -- float version
    461 
    462 assert(maxintF == maxint and math.type(maxintF) == "float" and
    463        maxintF >= 2.0^14)
    464 
    465 -- floats and integers must index the same places
    466 a[maxintF] = 10; a[maxintF - 1.0] = 11;
    467 a[-maxintF] = 12; a[-maxintF + 1.0] = 13;
    468 
    469 assert(a[maxint] == 10 and a[maxint - 1] == 11 and
    470        a[-maxint] == 12 and a[-maxint + 1] == 13)
    471 
    472 a[maxint] = 20
    473 a[-maxint] = 22
    474 
    475 assert(a[maxintF] == 20 and a[maxintF - 1.0] == 11 and
    476        a[-maxintF] == 22 and a[-maxintF + 1.0] == 13)
    477 
    478 a = nil
    479 
    480 
    481 -- test conflicts in multiple assignment
    482 do
    483   local a,i,j,b
    484   a = {'a', 'b'}; i=1; j=2; b=a
    485   i, a[i], a, j, a[j], a[i+j] = j, i, i, b, j, i
    486   assert(i == 2 and b[1] == 1 and a == 1 and j == b and b[2] == 2 and
    487          b[3] == 1)
    488   a = {}
    489   local function foo ()    -- assigining to upvalues
    490     b, a.x, a = a, 10, 20
    491   end
    492   foo()
    493   assert(a == 20 and b.x == 10)
    494 end
    495 
    496 -- repeat test with upvalues
    497 do
    498   local a,i,j,b
    499   a = {'a', 'b'}; i=1; j=2; b=a
    500   local function foo ()
    501     i, a[i], a, j, a[j], a[i+j] = j, i, i, b, j, i
    502   end
    503   foo()
    504   assert(i == 2 and b[1] == 1 and a == 1 and j == b and b[2] == 2 and
    505          b[3] == 1)
    506   local t = {}
    507   (function (a) t[a], a = 10, 20  end)(1);
    508   assert(t[1] == 10)
    509 end
    510 
    511 -- bug in 5.2 beta
    512 local function foo ()
    513   local a
    514   return function ()
    515     local b
    516     a, b = 3, 14    -- local and upvalue have same index
    517     return a, b
    518   end
    519 end
    520 
    521 local a, b = foo()()
    522 assert(a == 3 and b == 14)
    523 
    524 print('OK')
    525 
    526 return res
    527