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