1-- $Id: testes/attrib.lua $
  2-- See Copyright Notice in file all.lua
  3
  4print "testing require"
  5
  6assert(require"string" == string)
  7assert(require"math" == math)
  8assert(require"table" == table)
  9assert(require"io" == io)
 10assert(require"os" == os)
 11assert(require"coroutine" == coroutine)
 12
 13assert(type(package.path) == "string")
 14assert(type(package.cpath) == "string")
 15assert(type(package.loaded) == "table")
 16assert(type(package.preload) == "table")
 17
 18assert(type(package.config) == "string")
 19print("package config: "..string.gsub(package.config, "\n", "|"))
 20
 21do
 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)))
 40end
 41
 42do
 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
 48end
 49
 50
 51do  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
 71end
 72
 73print('+')
 74
 75
 76-- The next tests for 'require' assume some specific directories and
 77-- libraries.
 78
 79if not _port then --[
 80
 81local dirsep = string.match(package.config, "^([^\n]+)\n")
 82
 83-- auxiliary directory with C modules and temporary files
 84local DIR = "libs" .. dirsep
 85
 86-- prepend DIR to a name and correct directory separators
 87local function D (x)
 88  local x = string.gsub(x, "/", dirsep)
 89  return DIR .. x
 90end
 91
 92-- prepend DIR and pospend proper C lib. extension to a name
 93local function DC (x)
 94  local ext = (dirsep == '\\') and ".dll" or ".so"
 95  return D(x .. ext)
 96end
 97
 98
 99local 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
107end
108
109local function removefiles (files)
110  for n in pairs(files) do
111    os.remove(D(n))
112  end
113end
114
115local 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
128AA = nil
129local extras = [[
130NAME = '%s'
131REQUIRED = ...
132return AA]]
133
134createfiles(files, "", extras)
135
136-- testing explicit "dir" separator in 'searchpath'
137assert(package.searchpath("C.lua", D"?", "", "") == D"C.lua")
138assert(package.searchpath("C.lua", D"?", ".", ".") == D"C.lua")
139assert(package.searchpath("--x-", D"?", "-", "X") == D"XXxX")
140assert(package.searchpath("---xX", D"?", "---", "XX") == D"XXxX")
141assert(package.searchpath(D"C.lua", "?", dirsep) == D"C.lua")
142assert(package.searchpath(".\\C.lua", D"?", "\\") == D"./C.lua")
143
144local oldpath = package.path
145
146package.path = string.gsub("D/?.lua;D/?.lc;D/?;D/??x?;D/L", "D/", DIR)
147
148local 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)
155end
156
157local a = require"names"
158assert(a[1] == "names" and a[2] == D"names.lua")
159
160local st, msg = pcall(require, "err")
161assert(not st and string.find(msg, "arithmetic") and B == 15)
162st, msg = pcall(require, "synerr")
163assert(not st and string.find(msg, "error loading module"))
164
165assert(package.searchpath("C", package.path) == D"C.lua")
166assert(require"C" == 25)
167assert(require"C" == 25)
168AA = nil
169try('B', 'B.lua', true, "libs/B.lua")
170assert(package.loaded.B)
171assert(require"B" == true)
172assert(package.loaded.A)
173assert(require"C" == 25)
174package.loaded.A = nil
175try('B', nil, true, nil)   -- should not reload package
176try('A', 'A.lua', true, "libs/A.lua")
177package.loaded.A = nil
178os.remove(D'A.lua')
179AA = {}
180try('A', 'A.lc', AA, "libs/A.lc")  -- now must find second option
181assert(package.searchpath("A", package.path) == D"A.lc")
182assert(require("A") == AA)
183AA = false
184try('K', 'L', false, "libs/L")     -- default option
185try('K', 'L', false, "libs/L")     -- default option (should reload it)
186assert(rawget(_G, "_REQUIREDNAME") == nil)
187
188AA = "x"
189try("X", "XXxX", AA, "libs/XXxX")
190
191
192removefiles(files)
193NAME, REQUIRED, AA, B = nil
194
195
196-- testing require of sub-packages
197
198local _G = _G
199
200package.path = string.gsub("D/?.lua;D/?/init.lua", "D/", DIR)
201
202files = {
203  ["P1/init.lua"] = "AA = 10",
204  ["P1/xuxu.lua"] = "AA = 20",
205}
206
207createfiles(files, "_ENV = {}\n", "\nreturn _ENV\n")
208AA = 0
209
210local m, ext = assert(require"P1")
211assert(ext == "libs/P1/init.lua")
212assert(AA == 0 and m.AA == 10)
213assert(require"P1" == m)
214assert(require"P1" == m)
215
216assert(package.searchpath("P1.xuxu", package.path) == D"P1/xuxu.lua")
217m.xuxu, ext = assert(require"P1.xuxu")
218assert(AA == 0 and m.xuxu.AA == 20)
219assert(ext == "libs/P1/xuxu.lua")
220assert(require"P1.xuxu" == m.xuxu)
221assert(require"P1.xuxu" == m.xuxu)
222assert(require"P1" == m and m.AA == 10)
223
224
225removefiles(files)
226AA = nil
227
228package.path = ""
229assert(not pcall(require, "file_does_not_exist"))
230package.path = "??\0?"
231assert(not pcall(require, "file_does_not_exist1"))
232
233package.path = oldpath
234
235-- check 'require' error message
236local fname = "file_does_not_exist2"
237local m, err = pcall(require, fname)
238for t in string.gmatch(package.path..";"..package.cpath, "[^;]+") do
239  t = string.gsub(t, "?", fname)
240  assert(string.find(err, t, 1, true))
241end
242
243do  -- 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
249end
250
251local function import(...)
252  local f = {...}
253  return function (m)
254    for i=1, #f do m[f[i]] = _G[f[i]] end
255  end
256end
257
258-- cannot change environment of a C function
259assert(not pcall(module, 'XUXU'))
260
261
262
263-- testing require of C libraries
264
265
266local p = ""   -- On Mac OS X, redefine this to "_"
267
268-- check whether loadlib works in this system
269local st, err, when = package.loadlib(DC"lib1", "*")
270if 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)
275else
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
309end
310
311_ENV = _G
312
313
314-- testing preload
315
316do
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")
332end
333
334print('+')
335
336end  --]
337
338print("testing assignments, logical operators, and constructors")
339
340local res, res2 = 27
341
342local a, b = 1, 2+3
343assert(a==1 and b==5)
344a={}
345local function f() return 10, 11, 12 end
346a.x, b, a[1] = 1, 2, f()
347assert(a.x==1 and b==2 and a[1]==10)
348a[f()], b, a[f()+3] = f(), a, 'x'
349assert(a[10] == 10 and b == a and a[13] == 'x')
350
351do
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)
363end
364
365local a, b, c, d = 1 and nil, 1 or nil, (1 and (nil or 1)), 6
366assert(not a and b and c and d==6)
367
368d = 20
369a, b, c, d = f()
370assert(a==10 and b==11 and c==12 and d==nil)
371a,b = f(), 1, 2, 3, f()
372assert(a==10 and b==1)
373
374assert(a<b == false and a>b == true)
375assert((10 and 2) == 2)
376assert((10 or 2) == 10)
377assert((10 or assert(nil)) == 10)
378assert(not (nil and assert(nil)))
379assert((nil or "alo") == "alo")
380assert((nil and 10) == nil)
381assert((false and 10) == false)
382assert((true or 10) == true)
383assert((false or 10) == 10)
384assert(false ~= nil)
385assert(nil ~= false)
386assert(not nil == true)
387assert(not not nil == false)
388assert(not not 1 == true)
389assert(not not a == true)
390assert(not not (6 or nil) == true)
391assert(not not (nil and 56) == false)
392assert(not not (nil and true) == false)
393assert(not 10 == false)
394assert(not {} == false)
395assert(not 0.5 == false)
396assert(not "x" == false)
397
398assert({} ~= {})
399print('+')
400
401a = {}
402a[true] = 20
403a[false] = 10
404assert(a[1<2] == 20 and a[1>2] == 10)
405
406function f(a) return a end
407
408local a = {}
409for i=3000,-3000,-1 do a[i + 0.0] = i; end
410a[10e30] = "alo"; a[true] = 10; a[false] = 20
411assert(a[10e30] == 'alo' and a[not 1] == 20 and a[10<20] == 10)
412for i=3000,-3000,-1 do assert(a[i] == i); end
413a[print] = assert
414a[f] = print
415a[a] = a
416assert(a[a][a][a][a][print] == assert)
417a[print](a[a[f]] == a[print])
418assert(not pcall(function () local a = {}; a[nil] = 10 end))
419assert(not pcall(function () local a = {[nil] = 10} end))
420assert(a[nil] == undef)
421a = nil
422
423local a, b, c
424a = {10,9,8,7,6,5,4,3,2; [-3]='a', [f]=print, a='a', b='ab'}
425a, a.x, a.y = a, a[-3]
426assert(a[1]==10 and a[-3]==a.a and a[f]==print and a.x=='a' and not a.y)
427a[1], f(a)[2], b, c = {['alo']=assert}, 10, a[1], a[f], 6, 10, 23, f(a), 2
428a[1].alo(a[2]==10 and b==10 and c==print)
429
430a.aVeryLongName012345678901234567890123456789012345678901234567890123456789 = 10
431local function foo ()
432  return a.aVeryLongName012345678901234567890123456789012345678901234567890123456789
433end
434assert(foo() == 10 and
435a.aVeryLongName012345678901234567890123456789012345678901234567890123456789 ==
43610)
437
438
439do
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"))
447end
448
449
450-- test of large float/integer indices 
451
452-- compute maximum integer where all bits fit in a float
453local maxint = math.maxinteger
454
455-- trim (if needed) to fit in a float
456while maxint ~= (maxint + 0.0) or (maxint - 1) ~= (maxint - 1.0) do
457  maxint = maxint // 2
458end
459
460local maxintF = maxint + 0.0   -- float version
461
462assert(maxintF == maxint and math.type(maxintF) == "float" and
463       maxintF >= 2.0^14)
464
465-- floats and integers must index the same places
466a[maxintF] = 10; a[maxintF - 1.0] = 11;
467a[-maxintF] = 12; a[-maxintF + 1.0] = 13;
468
469assert(a[maxint] == 10 and a[maxint - 1] == 11 and
470       a[-maxint] == 12 and a[-maxint + 1] == 13)
471
472a[maxint] = 20
473a[-maxint] = 22
474
475assert(a[maxintF] == 20 and a[maxintF - 1.0] == 11 and
476       a[-maxintF] == 22 and a[-maxintF + 1.0] == 13)
477
478a = nil
479
480
481-- test conflicts in multiple assignment
482do
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)
494end
495
496-- repeat test with upvalues
497do
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)
509end
510
511-- bug in 5.2 beta
512local 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
519end
520
521local a, b = foo()()
522assert(a == 3 and b == 14)
523
524print('OK')
525
526return res
527