summaryrefslogtreecommitdiff
path: root/testes
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2018-12-17 14:46:37 -0200
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2018-12-17 14:46:37 -0200
commit063d4e4543088e7a21965bda8ee5a0f952a9029e (patch)
tree6c3f2f8e98c26f071a94a32f9f2754396a66a9de /testes
parente354c6355e7f48e087678ec49e340ca0696725b1 (diff)
downloadlua-5.3.5.tar.gz
lua-5.3.5.tar.bz2
lua-5.3.5.zip
Lua 5.3.5 ported to gitv5.3.5
This is the first commit for the branch Lua 5.3. All source files were copied from the official distribution of 5.3.5 in the Lua site. The test files are the same of 5.3.4. The manual came from the previous RCS repository, revision 1.167.1.2.
Diffstat (limited to '')
-rwxr-xr-xtestes/all.lua291
-rw-r--r--testes/api.lua1172
-rw-r--r--testes/attrib.lua470
-rw-r--r--testes/big.lua82
-rwxr-xr-xtestes/bitwise.lua328
-rw-r--r--testes/bwcoercion.lua78
-rw-r--r--testes/calls.lua401
-rw-r--r--testes/closure.lua247
-rw-r--r--testes/code.lua239
-rw-r--r--testes/constructs.lua313
-rw-r--r--testes/coroutine.lua874
-rw-r--r--testes/db.lua857
-rw-r--r--testes/errors.lua537
-rw-r--r--testes/events.lua456
-rw-r--r--testes/files.lua793
-rw-r--r--testes/gc.lua624
-rw-r--r--testes/goto.lua232
-rw-r--r--testes/heavy.lua72
-rw-r--r--testes/libs/lib1.c44
-rw-r--r--testes/libs/lib11.c10
-rw-r--r--testes/libs/lib2.c23
-rw-r--r--testes/libs/lib21.c10
-rw-r--r--testes/libs/makefile26
-rw-r--r--testes/literals.lua302
-rw-r--r--testes/locals.lua162
-rw-r--r--testes/main.lua381
-rw-r--r--testes/math.lua824
-rw-r--r--testes/nextvar.lua631
-rw-r--r--testes/pm.lua374
-rw-r--r--testes/sort.lua310
-rw-r--r--testes/strings.lua379
-rw-r--r--testes/tpack.lua322
-rw-r--r--testes/utf8.lua210
-rw-r--r--testes/vararg.lua142
-rw-r--r--testes/verybig.lua152
35 files changed, 12368 insertions, 0 deletions
diff --git a/testes/all.lua b/testes/all.lua
new file mode 100755
index 00000000..017533ca
--- /dev/null
+++ b/testes/all.lua
@@ -0,0 +1,291 @@
1#!../lua
2-- $Id: all.lua,v 1.95 2016/11/07 13:11:28 roberto Exp $
3-- See Copyright Notice at the end of this file
4
5
6local version = "Lua 5.3"
7if _VERSION ~= version then
8 io.stderr:write("\nThis test suite is for ", version, ", not for ", _VERSION,
9 "\nExiting tests\n")
10 return
11end
12
13
14_G._ARG = arg -- save arg for other tests
15
16
17-- next variables control the execution of some tests
18-- true means no test (so an undefined variable does not skip a test)
19-- defaults are for Linux; test everything.
20-- Make true to avoid long or memory consuming tests
21_soft = rawget(_G, "_soft") or false
22-- Make true to avoid non-portable tests
23_port = rawget(_G, "_port") or false
24-- Make true to avoid messages about tests not performed
25_nomsg = rawget(_G, "_nomsg") or false
26
27
28local usertests = rawget(_G, "_U")
29
30if usertests then
31 -- tests for sissies ;) Avoid problems
32 _soft = true
33 _port = true
34 _nomsg = true
35end
36
37-- tests should require debug when needed
38debug = nil
39
40if usertests then
41 T = nil -- no "internal" tests for user tests
42else
43 T = rawget(_G, "T") -- avoid problems with 'strict' module
44end
45
46math.randomseed(0)
47
48--[=[
49 example of a long [comment],
50 [[spanning several [lines]]]
51
52]=]
53
54print("current path:\n****" .. package.path .. "****\n")
55
56
57local initclock = os.clock()
58local lastclock = initclock
59local walltime = os.time()
60
61local collectgarbage = collectgarbage
62
63do -- (
64
65-- track messages for tests not performed
66local msgs = {}
67function Message (m)
68 if not _nomsg then
69 print(m)
70 msgs[#msgs+1] = string.sub(m, 3, -3)
71 end
72end
73
74assert(os.setlocale"C")
75
76local T,print,format,write,assert,type,unpack,floor =
77 T,print,string.format,io.write,assert,type,table.unpack,math.floor
78
79-- use K for 1000 and M for 1000000 (not 2^10 -- 2^20)
80local function F (m)
81 local function round (m)
82 m = m + 0.04999
83 return format("%.1f", m) -- keep one decimal digit
84 end
85 if m < 1000 then return m
86 else
87 m = m / 1000
88 if m < 1000 then return round(m).."K"
89 else
90 return round(m/1000).."M"
91 end
92 end
93end
94
95local showmem
96if not T then
97 local max = 0
98 showmem = function ()
99 local m = collectgarbage("count") * 1024
100 max = (m > max) and m or max
101 print(format(" ---- total memory: %s, max memory: %s ----\n",
102 F(m), F(max)))
103 end
104else
105 showmem = function ()
106 T.checkmemory()
107 local total, numblocks, maxmem = T.totalmem()
108 local count = collectgarbage("count")
109 print(format(
110 "\n ---- total memory: %s (%.0fK), max use: %s, blocks: %d\n",
111 F(total), count, F(maxmem), numblocks))
112 print(format("\t(strings: %d, tables: %d, functions: %d, "..
113 "\n\tudata: %d, threads: %d)",
114 T.totalmem"string", T.totalmem"table", T.totalmem"function",
115 T.totalmem"userdata", T.totalmem"thread"))
116 end
117end
118
119
120--
121-- redefine dofile to run files through dump/undump
122--
123local function report (n) print("\n***** FILE '"..n.."'*****") end
124local olddofile = dofile
125local dofile = function (n, strip)
126 showmem()
127 local c = os.clock()
128 print(string.format("time: %g (+%g)", c - initclock, c - lastclock))
129 lastclock = c
130 report(n)
131 local f = assert(loadfile(n))
132 local b = string.dump(f, strip)
133 f = assert(load(b))
134 return f()
135end
136
137dofile('main.lua')
138
139do
140 local next, setmetatable, stderr = next, setmetatable, io.stderr
141 -- track collections
142 local mt = {}
143 -- each time a table is collected, remark it for finalization
144 -- on next cycle
145 mt.__gc = function (o)
146 stderr:write'.' -- mark progress
147 local n = setmetatable(o, mt) -- remark it
148 end
149 local n = setmetatable({}, mt) -- create object
150end
151
152report"gc.lua"
153local f = assert(loadfile('gc.lua'))
154f()
155
156dofile('db.lua')
157assert(dofile('calls.lua') == deep and deep)
158olddofile('strings.lua')
159olddofile('literals.lua')
160dofile('tpack.lua')
161assert(dofile('attrib.lua') == 27)
162
163assert(dofile('locals.lua') == 5)
164dofile('constructs.lua')
165dofile('code.lua', true)
166if not _G._soft then
167 report('big.lua')
168 local f = coroutine.wrap(assert(loadfile('big.lua')))
169 assert(f() == 'b')
170 assert(f() == 'a')
171end
172dofile('nextvar.lua')
173dofile('pm.lua')
174dofile('utf8.lua')
175dofile('api.lua')
176assert(dofile('events.lua') == 12)
177dofile('vararg.lua')
178dofile('closure.lua')
179dofile('coroutine.lua')
180dofile('goto.lua', true)
181dofile('errors.lua')
182dofile('math.lua')
183dofile('sort.lua', true)
184dofile('bitwise.lua')
185assert(dofile('verybig.lua', true) == 10); collectgarbage()
186dofile('files.lua')
187
188if #msgs > 0 then
189 print("\ntests not performed:")
190 for i=1,#msgs do
191 print(msgs[i])
192 end
193 print()
194end
195
196-- no test module should define 'debug'
197assert(debug == nil)
198
199local debug = require "debug"
200
201print(string.format("%d-bit integers, %d-bit floats",
202 string.packsize("j") * 8, string.packsize("n") * 8))
203
204debug.sethook(function (a) assert(type(a) == 'string') end, "cr")
205
206-- to survive outside block
207_G.showmem = showmem
208
209end --)
210
211local _G, showmem, print, format, clock, time, difftime, assert, open =
212 _G, showmem, print, string.format, os.clock, os.time, os.difftime,
213 assert, io.open
214
215-- file with time of last performed test
216local fname = T and "time-debug.txt" or "time.txt"
217local lasttime
218
219if not usertests then
220 -- open file with time of last performed test
221 local f = io.open(fname)
222 if f then
223 lasttime = assert(tonumber(f:read'a'))
224 f:close();
225 else -- no such file; assume it is recording time for first time
226 lasttime = nil
227 end
228end
229
230-- erase (almost) all globals
231print('cleaning all!!!!')
232for n in pairs(_G) do
233 if not ({___Glob = 1, tostring = 1})[n] then
234 _G[n] = nil
235 end
236end
237
238
239collectgarbage()
240collectgarbage()
241collectgarbage()
242collectgarbage()
243collectgarbage()
244collectgarbage();showmem()
245
246local clocktime = clock() - initclock
247walltime = difftime(time(), walltime)
248
249print(format("\n\ntotal time: %.2fs (wall time: %gs)\n", clocktime, walltime))
250
251if not usertests then
252 lasttime = lasttime or clocktime -- if no last time, ignore difference
253 -- check whether current test time differs more than 5% from last time
254 local diff = (clocktime - lasttime) / lasttime
255 local tolerance = 0.05 -- 5%
256 if (diff >= tolerance or diff <= -tolerance) then
257 print(format("WARNING: time difference from previous test: %+.1f%%",
258 diff * 100))
259 end
260 assert(open(fname, "w")):write(clocktime):close()
261end
262
263print("final OK !!!")
264
265
266
267--[[
268*****************************************************************************
269* Copyright (C) 1994-2016 Lua.org, PUC-Rio.
270*
271* Permission is hereby granted, free of charge, to any person obtaining
272* a copy of this software and associated documentation files (the
273* "Software"), to deal in the Software without restriction, including
274* without limitation the rights to use, copy, modify, merge, publish,
275* distribute, sublicense, and/or sell copies of the Software, and to
276* permit persons to whom the Software is furnished to do so, subject to
277* the following conditions:
278*
279* The above copyright notice and this permission notice shall be
280* included in all copies or substantial portions of the Software.
281*
282* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
283* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
284* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
285* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
286* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
287* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
288* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
289*****************************************************************************
290]]
291
diff --git a/testes/api.lua b/testes/api.lua
new file mode 100644
index 00000000..c27ee97f
--- /dev/null
+++ b/testes/api.lua
@@ -0,0 +1,1172 @@
1-- $Id: api.lua,v 1.147 2016/11/07 13:06:25 roberto Exp $
2-- See Copyright Notice in file all.lua
3
4if T==nil then
5 (Message or print)('\n >>> testC not active: skipping API tests <<<\n')
6 return
7end
8
9local debug = require "debug"
10
11local pack = table.pack
12
13
14function tcheck (t1, t2)
15 assert(t1.n == (t2.n or #t2) + 1)
16 for i = 2, t1.n do assert(t1[i] == t2[i - 1]) end
17end
18
19
20local function checkerr (msg, f, ...)
21 local stat, err = pcall(f, ...)
22 assert(not stat and string.find(err, msg))
23end
24
25
26print('testing C API')
27
28a = T.testC("pushvalue R; return 1")
29assert(a == debug.getregistry())
30
31
32-- absindex
33assert(T.testC("settop 10; absindex -1; return 1") == 10)
34assert(T.testC("settop 5; absindex -5; return 1") == 1)
35assert(T.testC("settop 10; absindex 1; return 1") == 1)
36assert(T.testC("settop 10; absindex R; return 1") < -10)
37
38-- testing alignment
39a = T.d2s(12458954321123.0)
40assert(a == string.pack("d", 12458954321123.0))
41assert(T.s2d(a) == 12458954321123.0)
42
43a,b,c = T.testC("pushnum 1; pushnum 2; pushnum 3; return 2")
44assert(a == 2 and b == 3 and not c)
45
46f = T.makeCfunc("pushnum 1; pushnum 2; pushnum 3; return 2")
47a,b,c = f()
48assert(a == 2 and b == 3 and not c)
49
50-- test that all trues are equal
51a,b,c = T.testC("pushbool 1; pushbool 2; pushbool 0; return 3")
52assert(a == b and a == true and c == false)
53a,b,c = T.testC"pushbool 0; pushbool 10; pushnil;\
54 tobool -3; tobool -3; tobool -3; return 3"
55assert(a==false and b==true and c==false)
56
57
58a,b,c = T.testC("gettop; return 2", 10, 20, 30, 40)
59assert(a == 40 and b == 5 and not c)
60
61t = pack(T.testC("settop 5; return *", 2, 3))
62tcheck(t, {n=4,2,3})
63
64t = pack(T.testC("settop 0; settop 15; return 10", 3, 1, 23))
65assert(t.n == 10 and t[1] == nil and t[10] == nil)
66
67t = pack(T.testC("remove -2; return *", 2, 3, 4))
68tcheck(t, {n=2,2,4})
69
70t = pack(T.testC("insert -1; return *", 2, 3))
71tcheck(t, {n=2,2,3})
72
73t = pack(T.testC("insert 3; return *", 2, 3, 4, 5))
74tcheck(t, {n=4,2,5,3,4})
75
76t = pack(T.testC("replace 2; return *", 2, 3, 4, 5))
77tcheck(t, {n=3,5,3,4})
78
79t = pack(T.testC("replace -2; return *", 2, 3, 4, 5))
80tcheck(t, {n=3,2,3,5})
81
82t = pack(T.testC("remove 3; return *", 2, 3, 4, 5))
83tcheck(t, {n=3,2,4,5})
84
85t = pack(T.testC("copy 3 4; return *", 2, 3, 4, 5))
86tcheck(t, {n=4,2,3,3,5})
87
88t = pack(T.testC("copy -3 -1; return *", 2, 3, 4, 5))
89tcheck(t, {n=4,2,3,4,3})
90
91do -- testing 'rotate'
92 local t = {10, 20, 30, 40, 50, 60}
93 for i = -6, 6 do
94 local s = string.format("rotate 2 %d; return 7", i)
95 local t1 = pack(T.testC(s, 10, 20, 30, 40, 50, 60))
96 tcheck(t1, t)
97 table.insert(t, 1, table.remove(t))
98 end
99
100 t = pack(T.testC("rotate -2 1; return *", 10, 20, 30, 40))
101 tcheck(t, {10, 20, 40, 30})
102 t = pack(T.testC("rotate -2 -1; return *", 10, 20, 30, 40))
103 tcheck(t, {10, 20, 40, 30})
104
105 -- some corner cases
106 t = pack(T.testC("rotate -1 0; return *", 10, 20, 30, 40))
107 tcheck(t, {10, 20, 30, 40})
108 t = pack(T.testC("rotate -1 1; return *", 10, 20, 30, 40))
109 tcheck(t, {10, 20, 30, 40})
110 t = pack(T.testC("rotate 5 -1; return *", 10, 20, 30, 40))
111 tcheck(t, {10, 20, 30, 40})
112end
113
114-- testing non-function message handlers
115do
116 local f = T.makeCfunc[[
117 getglobal error
118 pushstring bola
119 pcall 1 1 1 # call 'error' with given handler
120 pushstatus
121 return 2 # return error message and status
122 ]]
123
124 local msg, st = f({}) -- invalid handler
125 assert(st == "ERRERR" and string.find(msg, "error handling"))
126 local msg, st = f(nil) -- invalid handler
127 assert(st == "ERRERR" and string.find(msg, "error handling"))
128
129 local a = setmetatable({}, {__call = function (_, x) return x:upper() end})
130 local msg, st = f(a) -- callable handler
131 assert(st == "ERRRUN" and msg == "BOLA")
132end
133
134t = pack(T.testC("insert 3; pushvalue 3; remove 3; pushvalue 2; remove 2; \
135 insert 2; pushvalue 1; remove 1; insert 1; \
136 insert -2; pushvalue -2; remove -3; return *",
137 2, 3, 4, 5, 10, 40, 90))
138tcheck(t, {n=7,2,3,4,5,10,40,90})
139
140t = pack(T.testC("concat 5; return *", "alo", 2, 3, "joao", 12))
141tcheck(t, {n=1,"alo23joao12"})
142
143-- testing MULTRET
144t = pack(T.testC("call 2,-1; return *",
145 function (a,b) return 1,2,3,4,a,b end, "alo", "joao"))
146tcheck(t, {n=6,1,2,3,4,"alo", "joao"})
147
148do -- test returning more results than fit in the caller stack
149 local a = {}
150 for i=1,1000 do a[i] = true end; a[999] = 10
151 local b = T.testC([[pcall 1 -1 0; pop 1; tostring -1; return 1]],
152 table.unpack, a)
153 assert(b == "10")
154end
155
156
157-- testing globals
158_G.a = 14; _G.b = "a31"
159local a = {T.testC[[
160 getglobal a;
161 getglobal b;
162 getglobal b;
163 setglobal a;
164 return *
165]]}
166assert(a[2] == 14 and a[3] == "a31" and a[4] == nil and _G.a == "a31")
167
168
169-- testing arith
170assert(T.testC("pushnum 10; pushnum 20; arith /; return 1") == 0.5)
171assert(T.testC("pushnum 10; pushnum 20; arith -; return 1") == -10)
172assert(T.testC("pushnum 10; pushnum -20; arith *; return 1") == -200)
173assert(T.testC("pushnum 10; pushnum 3; arith ^; return 1") == 1000)
174assert(T.testC("pushnum 10; pushstring 20; arith /; return 1") == 0.5)
175assert(T.testC("pushstring 10; pushnum 20; arith -; return 1") == -10)
176assert(T.testC("pushstring 10; pushstring -20; arith *; return 1") == -200)
177assert(T.testC("pushstring 10; pushstring 3; arith ^; return 1") == 1000)
178assert(T.testC("arith /; return 1", 2, 0) == 10.0/0)
179a = T.testC("pushnum 10; pushint 3; arith \\; return 1")
180assert(a == 3.0 and math.type(a) == "float")
181a = T.testC("pushint 10; pushint 3; arith \\; return 1")
182assert(a == 3 and math.type(a) == "integer")
183a = assert(T.testC("pushint 10; pushint 3; arith +; return 1"))
184assert(a == 13 and math.type(a) == "integer")
185a = assert(T.testC("pushnum 10; pushint 3; arith +; return 1"))
186assert(a == 13 and math.type(a) == "float")
187a,b,c = T.testC([[pushnum 1;
188 pushstring 10; arith _;
189 pushstring 5; return 3]])
190assert(a == 1 and b == -10 and c == "5")
191mt = {__add = function (a,b) return setmetatable({a[1] + b[1]}, mt) end,
192 __mod = function (a,b) return setmetatable({a[1] % b[1]}, mt) end,
193 __unm = function (a) return setmetatable({a[1]* 2}, mt) end}
194a,b,c = setmetatable({4}, mt),
195 setmetatable({8}, mt),
196 setmetatable({-3}, mt)
197x,y,z = T.testC("arith +; return 2", 10, a, b)
198assert(x == 10 and y[1] == 12 and z == nil)
199assert(T.testC("arith %; return 1", a, c)[1] == 4%-3)
200assert(T.testC("arith _; arith +; arith %; return 1", b, a, c)[1] ==
201 8 % (4 + (-3)*2))
202
203-- errors in arithmetic
204checkerr("divide by zero", T.testC, "arith \\", 10, 0)
205checkerr("%%0", T.testC, "arith %", 10, 0)
206
207
208-- testing lessthan and lessequal
209assert(T.testC("compare LT 2 5, return 1", 3, 2, 2, 4, 2, 2))
210assert(T.testC("compare LE 2 5, return 1", 3, 2, 2, 4, 2, 2))
211assert(not T.testC("compare LT 3 4, return 1", 3, 2, 2, 4, 2, 2))
212assert(T.testC("compare LE 3 4, return 1", 3, 2, 2, 4, 2, 2))
213assert(T.testC("compare LT 5 2, return 1", 4, 2, 2, 3, 2, 2))
214assert(not T.testC("compare LT 2 -3, return 1", "4", "2", "2", "3", "2", "2"))
215assert(not T.testC("compare LT -3 2, return 1", "3", "2", "2", "4", "2", "2"))
216
217-- non-valid indices produce false
218assert(not T.testC("compare LT 1 4, return 1"))
219assert(not T.testC("compare LE 9 1, return 1"))
220assert(not T.testC("compare EQ 9 9, return 1"))
221
222local b = {__lt = function (a,b) return a[1] < b[1] end}
223local a1,a3,a4 = setmetatable({1}, b),
224 setmetatable({3}, b),
225 setmetatable({4}, b)
226assert(T.testC("compare LT 2 5, return 1", a3, 2, 2, a4, 2, 2))
227assert(T.testC("compare LE 2 5, return 1", a3, 2, 2, a4, 2, 2))
228assert(T.testC("compare LT 5 -6, return 1", a4, 2, 2, a3, 2, 2))
229a,b = T.testC("compare LT 5 -6, return 2", a1, 2, 2, a3, 2, 20)
230assert(a == 20 and b == false)
231a,b = T.testC("compare LE 5 -6, return 2", a1, 2, 2, a3, 2, 20)
232assert(a == 20 and b == false)
233a,b = T.testC("compare LE 5 -6, return 2", a1, 2, 2, a1, 2, 20)
234assert(a == 20 and b == true)
235
236-- testing length
237local t = setmetatable({x = 20}, {__len = function (t) return t.x end})
238a,b,c = T.testC([[
239 len 2;
240 Llen 2;
241 objsize 2;
242 return 3
243]], t)
244assert(a == 20 and b == 20 and c == 0)
245
246t.x = "234"; t[1] = 20
247a,b,c = T.testC([[
248 len 2;
249 Llen 2;
250 objsize 2;
251 return 3
252]], t)
253assert(a == "234" and b == 234 and c == 1)
254
255t.x = print; t[1] = 20
256a,c = T.testC([[
257 len 2;
258 objsize 2;
259 return 2
260]], t)
261assert(a == print and c == 1)
262
263
264-- testing __concat
265
266a = setmetatable({x="u"}, {__concat = function (a,b) return a.x..'.'..b.x end})
267x,y = T.testC([[
268 pushnum 5
269 pushvalue 2;
270 pushvalue 2;
271 concat 2;
272 pushvalue -2;
273 return 2;
274]], a, a)
275assert(x == a..a and y == 5)
276
277-- concat with 0 elements
278assert(T.testC("concat 0; return 1") == "")
279
280-- concat with 1 element
281assert(T.testC("concat 1; return 1", "xuxu") == "xuxu")
282
283
284
285-- testing lua_is
286
287function B(x) return x and 1 or 0 end
288
289function count (x, n)
290 n = n or 2
291 local prog = [[
292 isnumber %d;
293 isstring %d;
294 isfunction %d;
295 iscfunction %d;
296 istable %d;
297 isuserdata %d;
298 isnil %d;
299 isnull %d;
300 return 8
301 ]]
302 prog = string.format(prog, n, n, n, n, n, n, n, n)
303 local a,b,c,d,e,f,g,h = T.testC(prog, x)
304 return B(a)+B(b)+B(c)+B(d)+B(e)+B(f)+B(g)+(100*B(h))
305end
306
307assert(count(3) == 2)
308assert(count('alo') == 1)
309assert(count('32') == 2)
310assert(count({}) == 1)
311assert(count(print) == 2)
312assert(count(function () end) == 1)
313assert(count(nil) == 1)
314assert(count(io.stdin) == 1)
315assert(count(nil, 15) == 100)
316
317
318-- testing lua_to...
319
320function to (s, x, n)
321 n = n or 2
322 return T.testC(string.format("%s %d; return 1", s, n), x)
323end
324
325local hfunc = string.gmatch("", "") -- a "heavy C function" (with upvalues)
326assert(debug.getupvalue(hfunc, 1))
327assert(to("tostring", {}) == nil)
328assert(to("tostring", "alo") == "alo")
329assert(to("tostring", 12) == "12")
330assert(to("tostring", 12, 3) == nil)
331assert(to("objsize", {}) == 0)
332assert(to("objsize", {1,2,3}) == 3)
333assert(to("objsize", "alo\0\0a") == 6)
334assert(to("objsize", T.newuserdata(0)) == 0)
335assert(to("objsize", T.newuserdata(101)) == 101)
336assert(to("objsize", 124) == 0)
337assert(to("objsize", true) == 0)
338assert(to("tonumber", {}) == 0)
339assert(to("tonumber", "12") == 12)
340assert(to("tonumber", "s2") == 0)
341assert(to("tonumber", 1, 20) == 0)
342assert(to("topointer", 10) == 0)
343assert(to("topointer", true) == 0)
344assert(to("topointer", T.pushuserdata(20)) == 20)
345assert(to("topointer", io.read) ~= 0) -- light C function
346assert(to("topointer", hfunc) ~= 0) -- "heavy" C function
347assert(to("topointer", function () end) ~= 0) -- Lua function
348assert(to("topointer", io.stdin) ~= 0) -- full userdata
349assert(to("func2num", 20) == 0)
350assert(to("func2num", T.pushuserdata(10)) == 0)
351assert(to("func2num", io.read) ~= 0) -- light C function
352assert(to("func2num", hfunc) ~= 0) -- "heavy" C function (with upvalue)
353a = to("tocfunction", math.deg)
354assert(a(3) == math.deg(3) and a == math.deg)
355
356
357print("testing panic function")
358do
359 -- trivial error
360 assert(T.checkpanic("pushstring hi; error") == "hi")
361
362 -- using the stack inside panic
363 assert(T.checkpanic("pushstring hi; error;",
364 [[checkstack 5 XX
365 pushstring ' alo'
366 pushstring ' mundo'
367 concat 3]]) == "hi alo mundo")
368
369 -- "argerror" without frames
370 assert(T.checkpanic("loadstring 4") ==
371 "bad argument #4 (string expected, got no value)")
372
373
374 -- memory error
375 T.totalmem(T.totalmem()+10000) -- set low memory limit (+10k)
376 assert(T.checkpanic("newuserdata 20000") == "not enough memory")
377 T.totalmem(0) -- restore high limit
378
379 -- stack error
380 if not _soft then
381 local msg = T.checkpanic[[
382 pushstring "function f() f() end"
383 loadstring -1; call 0 0
384 getglobal f; call 0 0
385 ]]
386 assert(string.find(msg, "stack overflow"))
387 end
388
389end
390
391-- testing deep C stack
392if not _soft then
393 print("testing stack overflow")
394 collectgarbage("stop")
395 checkerr("XXXX", T.testC, "checkstack 1000023 XXXX") -- too deep
396 -- too deep (with no message)
397 checkerr("^stack overflow$", T.testC, "checkstack 1000023 ''")
398 local s = string.rep("pushnil;checkstack 1 XX;", 1000000)
399 checkerr("overflow", T.testC, s)
400 collectgarbage("restart")
401 print'+'
402end
403
404local lim = _soft and 500 or 12000
405local prog = {"checkstack " .. (lim * 2 + 100) .. "msg", "newtable"}
406for i = 1,lim do
407 prog[#prog + 1] = "pushnum " .. i
408 prog[#prog + 1] = "pushnum " .. i * 10
409end
410
411prog[#prog + 1] = "rawgeti R 2" -- get global table in registry
412prog[#prog + 1] = "insert " .. -(2*lim + 2)
413
414for i = 1,lim do
415 prog[#prog + 1] = "settable " .. -(2*(lim - i + 1) + 1)
416end
417
418prog[#prog + 1] = "return 2"
419
420prog = table.concat(prog, ";")
421local g, t = T.testC(prog)
422assert(g == _G)
423for i = 1,lim do assert(t[i] == i*10); t[i] = nil end
424assert(next(t) == nil)
425prog, g, t = nil
426
427-- testing errors
428
429a = T.testC([[
430 loadstring 2; pcall 0 1 0;
431 pushvalue 3; insert -2; pcall 1 1 0;
432 pcall 0 0 0;
433 return 1
434]], "x=150", function (a) assert(a==nil); return 3 end)
435
436assert(type(a) == 'string' and x == 150)
437
438function check3(p, ...)
439 local arg = {...}
440 assert(#arg == 3)
441 assert(string.find(arg[3], p))
442end
443check3(":1:", T.testC("loadstring 2; return *", "x="))
444check3("%.", T.testC("loadfile 2; return *", "."))
445check3("xxxx", T.testC("loadfile 2; return *", "xxxx"))
446
447-- test errors in non protected threads
448function checkerrnopro (code, msg)
449 local th = coroutine.create(function () end) -- create new thread
450 local stt, err = pcall(T.testC, th, code) -- run code there
451 assert(not stt and string.find(err, msg))
452end
453
454if not _soft then
455 checkerrnopro("pushnum 3; call 0 0", "attempt to call")
456 print"testing stack overflow in unprotected thread"
457 function f () f() end
458 checkerrnopro("getglobal 'f'; call 0 0;", "stack overflow")
459end
460print"+"
461
462
463-- testing table access
464
465do -- getp/setp
466 local a = {}
467 T.testC("rawsetp 2 1", a, 20)
468 assert(a[T.pushuserdata(1)] == 20)
469 assert(T.testC("rawgetp 2 1; return 1", a) == 20)
470end
471
472a = {x=0, y=12}
473x, y = T.testC("gettable 2; pushvalue 4; gettable 2; return 2",
474 a, 3, "y", 4, "x")
475assert(x == 0 and y == 12)
476T.testC("settable -5", a, 3, 4, "x", 15)
477assert(a.x == 15)
478a[a] = print
479x = T.testC("gettable 2; return 1", a) -- table and key are the same object!
480assert(x == print)
481T.testC("settable 2", a, "x") -- table and key are the same object!
482assert(a[a] == "x")
483
484b = setmetatable({p = a}, {})
485getmetatable(b).__index = function (t, i) return t.p[i] end
486k, x = T.testC("gettable 3, return 2", 4, b, 20, 35, "x")
487assert(x == 15 and k == 35)
488k = T.testC("getfield 2 y, return 1", b)
489assert(k == 12)
490getmetatable(b).__index = function (t, i) return a[i] end
491getmetatable(b).__newindex = function (t, i,v ) a[i] = v end
492y = T.testC("insert 2; gettable -5; return 1", 2, 3, 4, "y", b)
493assert(y == 12)
494k = T.testC("settable -5, return 1", b, 3, 4, "x", 16)
495assert(a.x == 16 and k == 4)
496a[b] = 'xuxu'
497y = T.testC("gettable 2, return 1", b)
498assert(y == 'xuxu')
499T.testC("settable 2", b, 19)
500assert(a[b] == 19)
501
502--
503do -- testing getfield/setfield with long keys
504 local t = {_012345678901234567890123456789012345678901234567890123456789 = 32}
505 local a = T.testC([[
506 getfield 2 _012345678901234567890123456789012345678901234567890123456789
507 return 1
508 ]], t)
509 assert(a == 32)
510 local a = T.testC([[
511 pushnum 33
512 setglobal _012345678901234567890123456789012345678901234567890123456789
513 ]])
514 assert(_012345678901234567890123456789012345678901234567890123456789 == 33)
515 _012345678901234567890123456789012345678901234567890123456789 = nil
516end
517
518-- testing next
519a = {}
520t = pack(T.testC("next; return *", a, nil))
521tcheck(t, {n=1,a})
522a = {a=3}
523t = pack(T.testC("next; return *", a, nil))
524tcheck(t, {n=3,a,'a',3})
525t = pack(T.testC("next; pop 1; next; return *", a, nil))
526tcheck(t, {n=1,a})
527
528
529
530-- testing upvalues
531
532do
533 local A = T.testC[[ pushnum 10; pushnum 20; pushcclosure 2; return 1]]
534 t, b, c = A([[pushvalue U0; pushvalue U1; pushvalue U2; return 3]])
535 assert(b == 10 and c == 20 and type(t) == 'table')
536 a, b = A([[tostring U3; tonumber U4; return 2]])
537 assert(a == nil and b == 0)
538 A([[pushnum 100; pushnum 200; replace U2; replace U1]])
539 b, c = A([[pushvalue U1; pushvalue U2; return 2]])
540 assert(b == 100 and c == 200)
541 A([[replace U2; replace U1]], {x=1}, {x=2})
542 b, c = A([[pushvalue U1; pushvalue U2; return 2]])
543 assert(b.x == 1 and c.x == 2)
544 T.checkmemory()
545end
546
547
548-- testing absent upvalues from C-function pointers
549assert(T.testC[[isnull U1; return 1]] == true)
550assert(T.testC[[isnull U100; return 1]] == true)
551assert(T.testC[[pushvalue U1; return 1]] == nil)
552
553local f = T.testC[[ pushnum 10; pushnum 20; pushcclosure 2; return 1]]
554assert(T.upvalue(f, 1) == 10 and
555 T.upvalue(f, 2) == 20 and
556 T.upvalue(f, 3) == nil)
557T.upvalue(f, 2, "xuxu")
558assert(T.upvalue(f, 2) == "xuxu")
559
560
561-- large closures
562do
563 local A = "checkstack 300 msg;" ..
564 string.rep("pushnum 10;", 255) ..
565 "pushcclosure 255; return 1"
566 A = T.testC(A)
567 for i=1,255 do
568 assert(A(("pushvalue U%d; return 1"):format(i)) == 10)
569 end
570 assert(A("isnull U256; return 1"))
571 assert(not A("isnil U256; return 1"))
572end
573
574
575
576-- testing get/setuservalue
577-- bug in 5.1.2
578checkerr("got number", debug.setuservalue, 3, {})
579checkerr("got nil", debug.setuservalue, nil, {})
580checkerr("got light userdata", debug.setuservalue, T.pushuserdata(1), {})
581
582local b = T.newuserdata(0)
583assert(debug.getuservalue(b) == nil)
584for _, v in pairs{true, false, 4.56, print, {}, b, "XYZ"} do
585 assert(debug.setuservalue(b, v) == b)
586 assert(debug.getuservalue(b) == v)
587end
588
589assert(debug.getuservalue(4) == nil)
590
591debug.setuservalue(b, function () return 10 end)
592collectgarbage() -- function should not be collected
593assert(debug.getuservalue(b)() == 10)
594
595debug.setuservalue(b, 134)
596collectgarbage() -- number should not be a problem for collector
597assert(debug.getuservalue(b) == 134)
598
599-- test barrier for uservalues
600T.gcstate("atomic")
601assert(T.gccolor(b) == "black")
602debug.setuservalue(b, {x = 100})
603T.gcstate("pause") -- complete collection
604assert(debug.getuservalue(b).x == 100) -- uvalue should be there
605
606-- long chain of userdata
607for i = 1, 1000 do
608 local bb = T.newuserdata(0)
609 debug.setuservalue(bb, b)
610 b = bb
611end
612collectgarbage() -- nothing should not be collected
613for i = 1, 1000 do
614 b = debug.getuservalue(b)
615end
616assert(debug.getuservalue(b).x == 100)
617b = nil
618
619
620-- testing locks (refs)
621
622-- reuse of references
623local i = T.ref{}
624T.unref(i)
625assert(T.ref{} == i)
626
627Arr = {}
628Lim = 100
629for i=1,Lim do -- lock many objects
630 Arr[i] = T.ref({})
631end
632
633assert(T.ref(nil) == -1 and T.getref(-1) == nil)
634T.unref(-1); T.unref(-1)
635
636for i=1,Lim do -- unlock all them
637 T.unref(Arr[i])
638end
639
640function printlocks ()
641 local f = T.makeCfunc("gettable R; return 1")
642 local n = f("n")
643 print("n", n)
644 for i=0,n do
645 print(i, f(i))
646 end
647end
648
649
650for i=1,Lim do -- lock many objects
651 Arr[i] = T.ref({})
652end
653
654for i=1,Lim,2 do -- unlock half of them
655 T.unref(Arr[i])
656end
657
658assert(type(T.getref(Arr[2])) == 'table')
659
660
661assert(T.getref(-1) == nil)
662
663
664a = T.ref({})
665
666collectgarbage()
667
668assert(type(T.getref(a)) == 'table')
669
670
671-- colect in cl the `val' of all collected userdata
672tt = {}
673cl = {n=0}
674A = nil; B = nil
675local F
676F = function (x)
677 local udval = T.udataval(x)
678 table.insert(cl, udval)
679 local d = T.newuserdata(100) -- cria lixo
680 d = nil
681 assert(debug.getmetatable(x).__gc == F)
682 assert(load("table.insert({}, {})"))() -- cria mais lixo
683 collectgarbage() -- forca coleta de lixo durante coleta!
684 assert(debug.getmetatable(x).__gc == F) -- coleta anterior nao melou isso?
685 local dummy = {} -- cria lixo durante coleta
686 if A ~= nil then
687 assert(type(A) == "userdata")
688 assert(T.udataval(A) == B)
689 debug.getmetatable(A) -- just acess it
690 end
691 A = x -- ressucita userdata
692 B = udval
693 return 1,2,3
694end
695tt.__gc = F
696
697-- test whether udate collection frees memory in the right time
698do
699 collectgarbage();
700 collectgarbage();
701 local x = collectgarbage("count");
702 local a = T.newuserdata(5001)
703 assert(T.testC("objsize 2; return 1", a) == 5001)
704 assert(collectgarbage("count") >= x+4)
705 a = nil
706 collectgarbage();
707 assert(collectgarbage("count") <= x+1)
708 -- udata without finalizer
709 x = collectgarbage("count")
710 collectgarbage("stop")
711 for i=1,1000 do T.newuserdata(0) end
712 assert(collectgarbage("count") > x+10)
713 collectgarbage()
714 assert(collectgarbage("count") <= x+1)
715 -- udata with finalizer
716 collectgarbage()
717 x = collectgarbage("count")
718 collectgarbage("stop")
719 a = {__gc = function () end}
720 for i=1,1000 do debug.setmetatable(T.newuserdata(0), a) end
721 assert(collectgarbage("count") >= x+10)
722 collectgarbage() -- this collection only calls TM, without freeing memory
723 assert(collectgarbage("count") >= x+10)
724 collectgarbage() -- now frees memory
725 assert(collectgarbage("count") <= x+1)
726 collectgarbage("restart")
727end
728
729
730collectgarbage("stop")
731
732-- create 3 userdatas with tag `tt'
733a = T.newuserdata(0); debug.setmetatable(a, tt); na = T.udataval(a)
734b = T.newuserdata(0); debug.setmetatable(b, tt); nb = T.udataval(b)
735c = T.newuserdata(0); debug.setmetatable(c, tt); nc = T.udataval(c)
736
737-- create userdata without meta table
738x = T.newuserdata(4)
739y = T.newuserdata(0)
740
741checkerr("FILE%* expected, got userdata", io.input, a)
742checkerr("FILE%* expected, got userdata", io.input, x)
743
744assert(debug.getmetatable(x) == nil and debug.getmetatable(y) == nil)
745
746d=T.ref(a);
747e=T.ref(b);
748f=T.ref(c);
749t = {T.getref(d), T.getref(e), T.getref(f)}
750assert(t[1] == a and t[2] == b and t[3] == c)
751
752t=nil; a=nil; c=nil;
753T.unref(e); T.unref(f)
754
755collectgarbage()
756
757-- check that unref objects have been collected
758assert(#cl == 1 and cl[1] == nc)
759
760x = T.getref(d)
761assert(type(x) == 'userdata' and debug.getmetatable(x) == tt)
762x =nil
763tt.b = b -- create cycle
764tt=nil -- frees tt for GC
765A = nil
766b = nil
767T.unref(d);
768n5 = T.newuserdata(0)
769debug.setmetatable(n5, {__gc=F})
770n5 = T.udataval(n5)
771collectgarbage()
772assert(#cl == 4)
773-- check order of collection
774assert(cl[2] == n5 and cl[3] == nb and cl[4] == na)
775
776collectgarbage"restart"
777
778
779a, na = {}, {}
780for i=30,1,-1 do
781 a[i] = T.newuserdata(0)
782 debug.setmetatable(a[i], {__gc=F})
783 na[i] = T.udataval(a[i])
784end
785cl = {}
786a = nil; collectgarbage()
787assert(#cl == 30)
788for i=1,30 do assert(cl[i] == na[i]) end
789na = nil
790
791
792for i=2,Lim,2 do -- unlock the other half
793 T.unref(Arr[i])
794end
795
796x = T.newuserdata(41); debug.setmetatable(x, {__gc=F})
797assert(T.testC("objsize 2; return 1", x) == 41)
798cl = {}
799a = {[x] = 1}
800x = T.udataval(x)
801collectgarbage()
802-- old `x' cannot be collected (`a' still uses it)
803assert(#cl == 0)
804for n in pairs(a) do a[n] = nil end
805collectgarbage()
806assert(#cl == 1 and cl[1] == x) -- old `x' must be collected
807
808-- testing lua_equal
809assert(T.testC("compare EQ 2 4; return 1", print, 1, print, 20))
810assert(T.testC("compare EQ 3 2; return 1", 'alo', "alo"))
811assert(T.testC("compare EQ 2 3; return 1", nil, nil))
812assert(not T.testC("compare EQ 2 3; return 1", {}, {}))
813assert(not T.testC("compare EQ 2 3; return 1"))
814assert(not T.testC("compare EQ 2 3; return 1", 3))
815
816-- testing lua_equal with fallbacks
817do
818 local map = {}
819 local t = {__eq = function (a,b) return map[a] == map[b] end}
820 local function f(x)
821 local u = T.newuserdata(0)
822 debug.setmetatable(u, t)
823 map[u] = x
824 return u
825 end
826 assert(f(10) == f(10))
827 assert(f(10) ~= f(11))
828 assert(T.testC("compare EQ 2 3; return 1", f(10), f(10)))
829 assert(not T.testC("compare EQ 2 3; return 1", f(10), f(20)))
830 t.__eq = nil
831 assert(f(10) ~= f(10))
832end
833
834print'+'
835
836
837
838-- testing changing hooks during hooks
839_G.t = {}
840T.sethook([[
841 # set a line hook after 3 count hooks
842 sethook 4 0 '
843 getglobal t;
844 pushvalue -3; append -2
845 pushvalue -2; append -2
846 ']], "c", 3)
847local a = 1 -- counting
848a = 1 -- counting
849a = 1 -- count hook (set line hook)
850a = 1 -- line hook
851a = 1 -- line hook
852debug.sethook()
853t = _G.t
854assert(t[1] == "line")
855line = t[2]
856assert(t[3] == "line" and t[4] == line + 1)
857assert(t[5] == "line" and t[6] == line + 2)
858assert(t[7] == nil)
859
860
861-------------------------------------------------------------------------
862do -- testing errors during GC
863 local a = {}
864 for i=1,20 do
865 a[i] = T.newuserdata(i) -- creates several udata
866 end
867 for i=1,20,2 do -- mark half of them to raise errors during GC
868 debug.setmetatable(a[i], {__gc = function (x) error("error inside gc") end})
869 end
870 for i=2,20,2 do -- mark the other half to count and to create more garbage
871 debug.setmetatable(a[i], {__gc = function (x) load("A=A+1")() end})
872 end
873 _G.A = 0
874 a = 0
875 while 1 do
876 local stat, msg = pcall(collectgarbage)
877 if stat then
878 break -- stop when no more errors
879 else
880 a = a + 1
881 assert(string.find(msg, "__gc"))
882 end
883 end
884 assert(a == 10) -- number of errors
885
886 assert(A == 10) -- number of normal collections
887end
888-------------------------------------------------------------------------
889-- test for userdata vals
890do
891 local a = {}; local lim = 30
892 for i=0,lim do a[i] = T.pushuserdata(i) end
893 for i=0,lim do assert(T.udataval(a[i]) == i) end
894 for i=0,lim do assert(T.pushuserdata(i) == a[i]) end
895 for i=0,lim do a[a[i]] = i end
896 for i=0,lim do a[T.pushuserdata(i)] = i end
897 assert(type(tostring(a[1])) == "string")
898end
899
900
901-------------------------------------------------------------------------
902-- testing multiple states
903T.closestate(T.newstate());
904L1 = T.newstate()
905assert(L1)
906
907assert(T.doremote(L1, "X='a'; return 'a'") == 'a')
908
909
910assert(#pack(T.doremote(L1, "function f () return 'alo', 3 end; f()")) == 0)
911
912a, b = T.doremote(L1, "return f()")
913assert(a == 'alo' and b == '3')
914
915T.doremote(L1, "_ERRORMESSAGE = nil")
916-- error: `sin' is not defined
917a, _, b = T.doremote(L1, "return sin(1)")
918assert(a == nil and b == 2) -- 2 == run-time error
919
920-- error: syntax error
921a, b, c = T.doremote(L1, "return a+")
922assert(a == nil and c == 3 and type(b) == "string") -- 3 == syntax error
923
924T.loadlib(L1)
925a, b, c = T.doremote(L1, [[
926 string = require'string'
927 a = require'_G'; assert(a == _G and require("_G") == a)
928 io = require'io'; assert(type(io.read) == "function")
929 assert(require("io") == io)
930 a = require'table'; assert(type(a.insert) == "function")
931 a = require'debug'; assert(type(a.getlocal) == "function")
932 a = require'math'; assert(type(a.sin) == "function")
933 return string.sub('okinama', 1, 2)
934]])
935assert(a == "ok")
936
937T.closestate(L1);
938
939
940L1 = T.newstate()
941T.loadlib(L1)
942T.doremote(L1, "a = {}")
943T.testC(L1, [[getglobal "a"; pushstring "x"; pushint 1;
944 settable -3]])
945assert(T.doremote(L1, "return a.x") == "1")
946
947T.closestate(L1)
948
949L1 = nil
950
951print('+')
952
953-------------------------------------------------------------------------
954-- testing memory limits
955-------------------------------------------------------------------------
956checkerr("block too big", T.newuserdata, math.maxinteger)
957collectgarbage()
958T.totalmem(T.totalmem()+5000) -- set low memory limit (+5k)
959checkerr("not enough memory", load"local a={}; for i=1,100000 do a[i]=i end")
960T.totalmem(0) -- restore high limit
961
962-- test memory errors; increase memory limit in small steps, so that
963-- we get memory errors in different parts of a given task, up to there
964-- is enough memory to complete the task without errors
965function testamem (s, f)
966 collectgarbage(); collectgarbage()
967 local M = T.totalmem()
968 local oldM = M
969 local a,b = nil
970 while 1 do
971 M = M+7 -- increase memory limit in small steps
972 T.totalmem(M)
973 a, b = pcall(f)
974 T.totalmem(0) -- restore high limit
975 if a and b then break end -- stop when no more errors
976 collectgarbage()
977 if not a and not -- `real' error?
978 (string.find(b, "memory") or string.find(b, "overflow")) then
979 error(b, 0) -- propagate it
980 end
981 end
982 print("\nlimit for " .. s .. ": " .. M-oldM)
983 return b
984end
985
986
987-- testing memory errors when creating a new state
988
989b = testamem("state creation", T.newstate)
990T.closestate(b); -- close new state
991
992
993-- testing threads
994
995-- get main thread from registry (at index LUA_RIDX_MAINTHREAD == 1)
996mt = T.testC("rawgeti R 1; return 1")
997assert(type(mt) == "thread" and coroutine.running() == mt)
998
999
1000
1001function expand (n,s)
1002 if n==0 then return "" end
1003 local e = string.rep("=", n)
1004 return string.format("T.doonnewstack([%s[ %s;\n collectgarbage(); %s]%s])\n",
1005 e, s, expand(n-1,s), e)
1006end
1007
1008G=0; collectgarbage(); a =collectgarbage("count")
1009load(expand(20,"G=G+1"))()
1010assert(G==20); collectgarbage(); -- assert(gcinfo() <= a+1)
1011
1012testamem("thread creation", function ()
1013 return T.doonnewstack("x=1") == 0 -- try to create thread
1014end)
1015
1016
1017-- testing memory x compiler
1018
1019testamem("loadstring", function ()
1020 return load("x=1") -- try to do load a string
1021end)
1022
1023
1024local testprog = [[
1025local function foo () return end
1026local t = {"x"}
1027a = "aaa"
1028for i = 1, #t do a=a..t[i] end
1029return true
1030]]
1031
1032-- testing memory x dofile
1033_G.a = nil
1034local t =os.tmpname()
1035local f = assert(io.open(t, "w"))
1036f:write(testprog)
1037f:close()
1038testamem("dofile", function ()
1039 local a = loadfile(t)
1040 return a and a()
1041end)
1042assert(os.remove(t))
1043assert(_G.a == "aaax")
1044
1045
1046-- other generic tests
1047
1048testamem("string creation", function ()
1049 local a, b = string.gsub("alo alo", "(a)", function (x) return x..'b' end)
1050 return (a == 'ablo ablo')
1051end)
1052
1053testamem("dump/undump", function ()
1054 local a = load(testprog)
1055 local b = a and string.dump(a)
1056 a = b and load(b)
1057 return a and a()
1058end)
1059
1060local t = os.tmpname()
1061testamem("file creation", function ()
1062 local f = assert(io.open(t, 'w'))
1063 assert (not io.open"nomenaoexistente")
1064 io.close(f);
1065 return not loadfile'nomenaoexistente'
1066end)
1067assert(os.remove(t))
1068
1069testamem("table creation", function ()
1070 local a, lim = {}, 10
1071 for i=1,lim do a[i] = i; a[i..'a'] = {} end
1072 return (type(a[lim..'a']) == 'table' and a[lim] == lim)
1073end)
1074
1075testamem("constructors", function ()
1076 local a = {10, 20, 30, 40, 50; a=1, b=2, c=3, d=4, e=5}
1077 return (type(a) == 'table' and a.e == 5)
1078end)
1079
1080local a = 1
1081close = nil
1082testamem("closure creation", function ()
1083 function close (b,c)
1084 return function (x) return a+b+c+x end
1085 end
1086 return (close(2,3)(4) == 10)
1087end)
1088
1089testamem("coroutines", function ()
1090 local a = coroutine.wrap(function ()
1091 coroutine.yield(string.rep("a", 10))
1092 return {}
1093 end)
1094 assert(string.len(a()) == 10)
1095 return a()
1096end)
1097
1098do -- auxiliary buffer
1099 local lim = 100
1100 local a = {}; for i = 1, lim do a[i] = "01234567890123456789" end
1101 testamem("auxiliary buffer", function ()
1102 return (#table.concat(a, ",") == 20*lim + lim - 1)
1103 end)
1104end
1105
1106print'+'
1107
1108-- testing some auxlib functions
1109local function gsub (a, b, c)
1110 a, b = T.testC("gsub 2 3 4; gettop; return 2", a, b, c)
1111 assert(b == 5)
1112 return a
1113end
1114
1115assert(gsub("alo.alo.uhuh.", ".", "//") == "alo//alo//uhuh//")
1116assert(gsub("alo.alo.uhuh.", "alo", "//") == "//.//.uhuh.")
1117assert(gsub("", "alo", "//") == "")
1118assert(gsub("...", ".", "/.") == "/././.")
1119assert(gsub("...", "...", "") == "")
1120
1121
1122-- testing luaL_newmetatable
1123local mt_xuxu, res, top = T.testC("newmetatable xuxu; gettop; return 3")
1124assert(type(mt_xuxu) == "table" and res and top == 3)
1125local d, res, top = T.testC("newmetatable xuxu; gettop; return 3")
1126assert(mt_xuxu == d and not res and top == 3)
1127d, res, top = T.testC("newmetatable xuxu1; gettop; return 3")
1128assert(mt_xuxu ~= d and res and top == 3)
1129
1130x = T.newuserdata(0);
1131y = T.newuserdata(0);
1132T.testC("pushstring xuxu; gettable R; setmetatable 2", x)
1133assert(getmetatable(x) == mt_xuxu)
1134
1135-- testing luaL_testudata
1136-- correct metatable
1137local res1, res2, top = T.testC([[testudata -1 xuxu
1138 testudata 2 xuxu
1139 gettop
1140 return 3]], x)
1141assert(res1 and res2 and top == 4)
1142
1143-- wrong metatable
1144res1, res2, top = T.testC([[testudata -1 xuxu1
1145 testudata 2 xuxu1
1146 gettop
1147 return 3]], x)
1148assert(not res1 and not res2 and top == 4)
1149
1150-- non-existent type
1151res1, res2, top = T.testC([[testudata -1 xuxu2
1152 testudata 2 xuxu2
1153 gettop
1154 return 3]], x)
1155assert(not res1 and not res2 and top == 4)
1156
1157-- userdata has no metatable
1158res1, res2, top = T.testC([[testudata -1 xuxu
1159 testudata 2 xuxu
1160 gettop
1161 return 3]], y)
1162assert(not res1 and not res2 and top == 4)
1163
1164-- erase metatables
1165do
1166 local r = debug.getregistry()
1167 assert(r.xuxu == mt_xuxu and r.xuxu1 == d)
1168 r.xuxu = nil; r.xuxu1 = nil
1169end
1170
1171print'OK'
1172
diff --git a/testes/attrib.lua b/testes/attrib.lua
new file mode 100644
index 00000000..993a96cc
--- /dev/null
+++ b/testes/attrib.lua
@@ -0,0 +1,470 @@
1-- $Id: attrib.lua,v 1.65 2016/11/07 13:11:28 roberto Exp $
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 occurence 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
50print('+')
51
52
53-- The next tests for 'require' assume some specific directories and
54-- libraries.
55
56if not _port then --[
57
58local dirsep = string.match(package.config, "^([^\n]+)\n")
59
60-- auxiliary directory with C modules and temporary files
61local DIR = "libs" .. dirsep
62
63-- prepend DIR to a name and correct directory separators
64local function D (x)
65 x = string.gsub(x, "/", dirsep)
66 return DIR .. x
67end
68
69-- prepend DIR and pospend proper C lib. extension to a name
70local function DC (x)
71 local ext = (dirsep == '\\') and ".dll" or ".so"
72 return D(x .. ext)
73end
74
75
76local function createfiles (files, preextras, posextras)
77 for n,c in pairs(files) do
78 io.output(D(n))
79 io.write(string.format(preextras, n))
80 io.write(c)
81 io.write(string.format(posextras, n))
82 io.close(io.output())
83 end
84end
85
86function removefiles (files)
87 for n in pairs(files) do
88 os.remove(D(n))
89 end
90end
91
92local files = {
93 ["names.lua"] = "do return {...} end\n",
94 ["err.lua"] = "B = 15; a = a + 1;",
95 ["synerr.lua"] = "B =",
96 ["A.lua"] = "",
97 ["B.lua"] = "assert(...=='B');require 'A'",
98 ["A.lc"] = "",
99 ["A"] = "",
100 ["L"] = "",
101 ["XXxX"] = "",
102 ["C.lua"] = "package.loaded[...] = 25; require'C'",
103}
104
105AA = nil
106local extras = [[
107NAME = '%s'
108REQUIRED = ...
109return AA]]
110
111createfiles(files, "", extras)
112
113-- testing explicit "dir" separator in 'searchpath'
114assert(package.searchpath("C.lua", D"?", "", "") == D"C.lua")
115assert(package.searchpath("C.lua", D"?", ".", ".") == D"C.lua")
116assert(package.searchpath("--x-", D"?", "-", "X") == D"XXxX")
117assert(package.searchpath("---xX", D"?", "---", "XX") == D"XXxX")
118assert(package.searchpath(D"C.lua", "?", dirsep) == D"C.lua")
119assert(package.searchpath(".\\C.lua", D"?", "\\") == D"./C.lua")
120
121local oldpath = package.path
122
123package.path = string.gsub("D/?.lua;D/?.lc;D/?;D/??x?;D/L", "D/", DIR)
124
125local try = function (p, n, r)
126 NAME = nil
127 local rr = require(p)
128 assert(NAME == n)
129 assert(REQUIRED == p)
130 assert(rr == r)
131end
132
133a = require"names"
134assert(a[1] == "names" and a[2] == D"names.lua")
135
136_G.a = nil
137local st, msg = pcall(require, "err")
138assert(not st and string.find(msg, "arithmetic") and B == 15)
139st, msg = pcall(require, "synerr")
140assert(not st and string.find(msg, "error loading module"))
141
142assert(package.searchpath("C", package.path) == D"C.lua")
143assert(require"C" == 25)
144assert(require"C" == 25)
145AA = nil
146try('B', 'B.lua', true)
147assert(package.loaded.B)
148assert(require"B" == true)
149assert(package.loaded.A)
150assert(require"C" == 25)
151package.loaded.A = nil
152try('B', nil, true) -- should not reload package
153try('A', 'A.lua', true)
154package.loaded.A = nil
155os.remove(D'A.lua')
156AA = {}
157try('A', 'A.lc', AA) -- now must find second option
158assert(package.searchpath("A", package.path) == D"A.lc")
159assert(require("A") == AA)
160AA = false
161try('K', 'L', false) -- default option
162try('K', 'L', false) -- default option (should reload it)
163assert(rawget(_G, "_REQUIREDNAME") == nil)
164
165AA = "x"
166try("X", "XXxX", AA)
167
168
169removefiles(files)
170
171
172-- testing require of sub-packages
173
174local _G = _G
175
176package.path = string.gsub("D/?.lua;D/?/init.lua", "D/", DIR)
177
178files = {
179 ["P1/init.lua"] = "AA = 10",
180 ["P1/xuxu.lua"] = "AA = 20",
181}
182
183createfiles(files, "_ENV = {}\n", "\nreturn _ENV\n")
184AA = 0
185
186local m = assert(require"P1")
187assert(AA == 0 and m.AA == 10)
188assert(require"P1" == m)
189assert(require"P1" == m)
190
191assert(package.searchpath("P1.xuxu", package.path) == D"P1/xuxu.lua")
192m.xuxu = assert(require"P1.xuxu")
193assert(AA == 0 and m.xuxu.AA == 20)
194assert(require"P1.xuxu" == m.xuxu)
195assert(require"P1.xuxu" == m.xuxu)
196assert(require"P1" == m and m.AA == 10)
197
198
199removefiles(files)
200
201
202package.path = ""
203assert(not pcall(require, "file_does_not_exist"))
204package.path = "??\0?"
205assert(not pcall(require, "file_does_not_exist1"))
206
207package.path = oldpath
208
209-- check 'require' error message
210local fname = "file_does_not_exist2"
211local m, err = pcall(require, fname)
212for t in string.gmatch(package.path..";"..package.cpath, "[^;]+") do
213 t = string.gsub(t, "?", fname)
214 assert(string.find(err, t, 1, true))
215end
216
217do -- testing 'package.searchers' not being a table
218 local searchers = package.searchers
219 package.searchers = 3
220 local st, msg = pcall(require, 'a')
221 assert(not st and string.find(msg, "must be a table"))
222 package.searchers = searchers
223end
224
225local function import(...)
226 local f = {...}
227 return function (m)
228 for i=1, #f do m[f[i]] = _G[f[i]] end
229 end
230end
231
232-- cannot change environment of a C function
233assert(not pcall(module, 'XUXU'))
234
235
236
237-- testing require of C libraries
238
239
240local p = "" -- On Mac OS X, redefine this to "_"
241
242-- check whether loadlib works in this system
243local st, err, when = package.loadlib(DC"lib1", "*")
244if not st then
245 local f, err, when = package.loadlib("donotexist", p.."xuxu")
246 assert(not f and type(err) == "string" and when == "absent")
247 ;(Message or print)('\n >>> cannot load dynamic library <<<\n')
248 print(err, when)
249else
250 -- tests for loadlib
251 local f = assert(package.loadlib(DC"lib1", p.."onefunction"))
252 local a, b = f(15, 25)
253 assert(a == 25 and b == 15)
254
255 f = assert(package.loadlib(DC"lib1", p.."anotherfunc"))
256 assert(f(10, 20) == "10%20\n")
257
258 -- check error messages
259 local f, err, when = package.loadlib(DC"lib1", p.."xuxu")
260 assert(not f and type(err) == "string" and when == "init")
261 f, err, when = package.loadlib("donotexist", p.."xuxu")
262 assert(not f and type(err) == "string" and when == "open")
263
264 -- symbols from 'lib1' must be visible to other libraries
265 f = assert(package.loadlib(DC"lib11", p.."luaopen_lib11"))
266 assert(f() == "exported")
267
268 -- test C modules with prefixes in names
269 package.cpath = DC"?"
270 local lib2 = require"lib2-v2"
271 -- check correct access to global environment and correct
272 -- parameters
273 assert(_ENV.x == "lib2-v2" and _ENV.y == DC"lib2-v2")
274 assert(lib2.id("x") == "x")
275
276 -- test C submodules
277 local fs = require"lib1.sub"
278 assert(_ENV.x == "lib1.sub" and _ENV.y == DC"lib1")
279 assert(fs.id(45) == 45)
280end
281
282_ENV = _G
283
284
285-- testing preload
286
287do
288 local p = package
289 package = {}
290 p.preload.pl = function (...)
291 local _ENV = {...}
292 function xuxu (x) return x+20 end
293 return _ENV
294 end
295
296 local pl = require"pl"
297 assert(require"pl" == pl)
298 assert(pl.xuxu(10) == 30)
299 assert(pl[1] == "pl" and pl[2] == nil)
300
301 package = p
302 assert(type(package.path) == "string")
303end
304
305print('+')
306
307end --]
308
309print("testing assignments, logical operators, and constructors")
310
311local res, res2 = 27
312
313a, b = 1, 2+3
314assert(a==1 and b==5)
315a={}
316function f() return 10, 11, 12 end
317a.x, b, a[1] = 1, 2, f()
318assert(a.x==1 and b==2 and a[1]==10)
319a[f()], b, a[f()+3] = f(), a, 'x'
320assert(a[10] == 10 and b == a and a[13] == 'x')
321
322do
323 local f = function (n) local x = {}; for i=1,n do x[i]=i end;
324 return table.unpack(x) end;
325 local a,b,c
326 a,b = 0, f(1)
327 assert(a == 0 and b == 1)
328 A,b = 0, f(1)
329 assert(A == 0 and b == 1)
330 a,b,c = 0,5,f(4)
331 assert(a==0 and b==5 and c==1)
332 a,b,c = 0,5,f(0)
333 assert(a==0 and b==5 and c==nil)
334end
335
336a, b, c, d = 1 and nil, 1 or nil, (1 and (nil or 1)), 6
337assert(not a and b and c and d==6)
338
339d = 20
340a, b, c, d = f()
341assert(a==10 and b==11 and c==12 and d==nil)
342a,b = f(), 1, 2, 3, f()
343assert(a==10 and b==1)
344
345assert(a<b == false and a>b == true)
346assert((10 and 2) == 2)
347assert((10 or 2) == 10)
348assert((10 or assert(nil)) == 10)
349assert(not (nil and assert(nil)))
350assert((nil or "alo") == "alo")
351assert((nil and 10) == nil)
352assert((false and 10) == false)
353assert((true or 10) == true)
354assert((false or 10) == 10)
355assert(false ~= nil)
356assert(nil ~= false)
357assert(not nil == true)
358assert(not not nil == false)
359assert(not not 1 == true)
360assert(not not a == true)
361assert(not not (6 or nil) == true)
362assert(not not (nil and 56) == false)
363assert(not not (nil and true) == false)
364assert(not 10 == false)
365assert(not {} == false)
366assert(not 0.5 == false)
367assert(not "x" == false)
368
369assert({} ~= {})
370print('+')
371
372a = {}
373a[true] = 20
374a[false] = 10
375assert(a[1<2] == 20 and a[1>2] == 10)
376
377function f(a) return a end
378
379local a = {}
380for i=3000,-3000,-1 do a[i + 0.0] = i; end
381a[10e30] = "alo"; a[true] = 10; a[false] = 20
382assert(a[10e30] == 'alo' and a[not 1] == 20 and a[10<20] == 10)
383for i=3000,-3000,-1 do assert(a[i] == i); end
384a[print] = assert
385a[f] = print
386a[a] = a
387assert(a[a][a][a][a][print] == assert)
388a[print](a[a[f]] == a[print])
389assert(not pcall(function () local a = {}; a[nil] = 10 end))
390assert(not pcall(function () local a = {[nil] = 10} end))
391assert(a[nil] == nil)
392a = nil
393
394a = {10,9,8,7,6,5,4,3,2; [-3]='a', [f]=print, a='a', b='ab'}
395a, a.x, a.y = a, a[-3]
396assert(a[1]==10 and a[-3]==a.a and a[f]==print and a.x=='a' and not a.y)
397a[1], f(a)[2], b, c = {['alo']=assert}, 10, a[1], a[f], 6, 10, 23, f(a), 2
398a[1].alo(a[2]==10 and b==10 and c==print)
399
400
401-- test of large float/integer indices
402
403-- compute maximum integer where all bits fit in a float
404local maxint = math.maxinteger
405
406while maxint - 1.0 == maxint - 0.0 do -- trim (if needed) to fit in a float
407 maxint = maxint // 2
408end
409
410maxintF = maxint + 0.0 -- float version
411
412assert(math.type(maxintF) == "float" and maxintF >= 2.0^14)
413
414-- floats and integers must index the same places
415a[maxintF] = 10; a[maxintF - 1.0] = 11;
416a[-maxintF] = 12; a[-maxintF + 1.0] = 13;
417
418assert(a[maxint] == 10 and a[maxint - 1] == 11 and
419 a[-maxint] == 12 and a[-maxint + 1] == 13)
420
421a[maxint] = 20
422a[-maxint] = 22
423
424assert(a[maxintF] == 20 and a[maxintF - 1.0] == 11 and
425 a[-maxintF] == 22 and a[-maxintF + 1.0] == 13)
426
427a = nil
428
429
430-- test conflicts in multiple assignment
431do
432 local a,i,j,b
433 a = {'a', 'b'}; i=1; j=2; b=a
434 i, a[i], a, j, a[j], a[i+j] = j, i, i, b, j, i
435 assert(i == 2 and b[1] == 1 and a == 1 and j == b and b[2] == 2 and
436 b[3] == 1)
437end
438
439-- repeat test with upvalues
440do
441 local a,i,j,b
442 a = {'a', 'b'}; i=1; j=2; b=a
443 local function foo ()
444 i, a[i], a, j, a[j], a[i+j] = j, i, i, b, j, i
445 end
446 foo()
447 assert(i == 2 and b[1] == 1 and a == 1 and j == b and b[2] == 2 and
448 b[3] == 1)
449 local t = {}
450 (function (a) t[a], a = 10, 20 end)(1);
451 assert(t[1] == 10)
452end
453
454-- bug in 5.2 beta
455local function foo ()
456 local a
457 return function ()
458 local b
459 a, b = 3, 14 -- local and upvalue have same index
460 return a, b
461 end
462end
463
464local a, b = foo()()
465assert(a == 3 and b == 14)
466
467print('OK')
468
469return res
470
diff --git a/testes/big.lua b/testes/big.lua
new file mode 100644
index 00000000..1a1fa788
--- /dev/null
+++ b/testes/big.lua
@@ -0,0 +1,82 @@
1-- $Id: big.lua,v 1.32 2016/11/07 13:11:28 roberto Exp $
2-- See Copyright Notice in file all.lua
3
4if _soft then
5 return 'a'
6end
7
8print "testing large tables"
9
10local debug = require"debug"
11
12local lim = 2^18 + 1000
13local prog = { "local y = {0" }
14for i = 1, lim do prog[#prog + 1] = i end
15prog[#prog + 1] = "}\n"
16prog[#prog + 1] = "X = y\n"
17prog[#prog + 1] = ("assert(X[%d] == %d)"):format(lim - 1, lim - 2)
18prog[#prog + 1] = "return 0"
19prog = table.concat(prog, ";")
20
21local env = {string = string, assert = assert}
22local f = assert(load(prog, nil, nil, env))
23
24f()
25assert(env.X[lim] == lim - 1 and env.X[lim + 1] == lim)
26for k in pairs(env) do env[k] = nil end
27
28-- yields during accesses larger than K (in RK)
29setmetatable(env, {
30 __index = function (t, n) coroutine.yield('g'); return _G[n] end,
31 __newindex = function (t, n, v) coroutine.yield('s'); _G[n] = v end,
32})
33
34X = nil
35co = coroutine.wrap(f)
36assert(co() == 's')
37assert(co() == 'g')
38assert(co() == 'g')
39assert(co() == 0)
40
41assert(X[lim] == lim - 1 and X[lim + 1] == lim)
42
43-- errors in accesses larger than K (in RK)
44getmetatable(env).__index = function () end
45getmetatable(env).__newindex = function () end
46local e, m = pcall(f)
47assert(not e and m:find("global 'X'"))
48
49-- errors in metamethods
50getmetatable(env).__newindex = function () error("hi") end
51local e, m = xpcall(f, debug.traceback)
52assert(not e and m:find("'__newindex'"))
53
54f, X = nil
55
56coroutine.yield'b'
57
58if 2^32 == 0 then -- (small integers) {
59
60print "testing string length overflow"
61
62local repstrings = 192 -- number of strings to be concatenated
63local ssize = math.ceil(2.0^32 / repstrings) + 1 -- size of each string
64
65assert(repstrings * ssize > 2.0^32) -- it should be larger than maximum size
66
67local longs = string.rep("\0", ssize) -- create one long string
68
69-- create function to concatentate 'repstrings' copies of its argument
70local rep = assert(load(
71 "local a = ...; return " .. string.rep("a", repstrings, "..")))
72
73local a, b = pcall(rep, longs) -- call that function
74
75-- it should fail without creating string (result would be too large)
76assert(not a and string.find(b, "overflow"))
77
78end -- }
79
80print'OK'
81
82return 'a'
diff --git a/testes/bitwise.lua b/testes/bitwise.lua
new file mode 100755
index 00000000..786679f4
--- /dev/null
+++ b/testes/bitwise.lua
@@ -0,0 +1,328 @@
1-- $Id: bitwise.lua,v 1.26 2016/11/07 13:11:28 roberto Exp $
2-- See Copyright Notice in file all.lua
3
4print("testing bitwise operations")
5
6local numbits = string.packsize('j') * 8
7
8assert(~0 == -1)
9
10assert((1 << (numbits - 1)) == math.mininteger)
11
12-- basic tests for bitwise operators;
13-- use variables to avoid constant folding
14local a, b, c, d
15a = 0xFFFFFFFFFFFFFFFF
16assert(a == -1 and a & -1 == a and a & 35 == 35)
17a = 0xF0F0F0F0F0F0F0F0
18assert(a | -1 == -1)
19assert(a ~ a == 0 and a ~ 0 == a and a ~ ~a == -1)
20assert(a >> 4 == ~a)
21a = 0xF0; b = 0xCC; c = 0xAA; d = 0xFD
22assert(a | b ~ c & d == 0xF4)
23
24a = 0xF0.0; b = 0xCC.0; c = "0xAA.0"; d = "0xFD.0"
25assert(a | b ~ c & d == 0xF4)
26
27a = 0xF0000000; b = 0xCC000000;
28c = 0xAA000000; d = 0xFD000000
29assert(a | b ~ c & d == 0xF4000000)
30assert(~~a == a and ~a == -1 ~ a and -d == ~d + 1)
31
32a = a << 32
33b = b << 32
34c = c << 32
35d = d << 32
36assert(a | b ~ c & d == 0xF4000000 << 32)
37assert(~~a == a and ~a == -1 ~ a and -d == ~d + 1)
38
39assert(-1 >> 1 == (1 << (numbits - 1)) - 1 and 1 << 31 == 0x80000000)
40assert(-1 >> (numbits - 1) == 1)
41assert(-1 >> numbits == 0 and
42 -1 >> -numbits == 0 and
43 -1 << numbits == 0 and
44 -1 << -numbits == 0)
45
46assert((2^30 - 1) << 2^30 == 0)
47assert((2^30 - 1) >> 2^30 == 0)
48
49assert(1 >> -3 == 1 << 3 and 1000 >> 5 == 1000 << -5)
50
51
52-- coercion from strings to integers
53assert("0xffffffffffffffff" | 0 == -1)
54assert("0xfffffffffffffffe" & "-1" == -2)
55assert(" \t-0xfffffffffffffffe\n\t" & "-1" == 2)
56assert(" \n -45 \t " >> " -2 " == -45 * 4)
57
58-- out of range number
59assert(not pcall(function () return "0xffffffffffffffff.0" | 0 end))
60
61-- embedded zeros
62assert(not pcall(function () return "0xffffffffffffffff\0" | 0 end))
63
64print'+'
65
66
67package.preload.bit32 = function () --{
68
69-- no built-in 'bit32' library: implement it using bitwise operators
70
71local bit = {}
72
73function bit.bnot (a)
74 return ~a & 0xFFFFFFFF
75end
76
77
78--
79-- in all vararg functions, avoid creating 'arg' table when there are
80-- only 2 (or less) parameters, as 2 parameters is the common case
81--
82
83function bit.band (x, y, z, ...)
84 if not z then
85 return ((x or -1) & (y or -1)) & 0xFFFFFFFF
86 else
87 local arg = {...}
88 local res = x & y & z
89 for i = 1, #arg do res = res & arg[i] end
90 return res & 0xFFFFFFFF
91 end
92end
93
94function bit.bor (x, y, z, ...)
95 if not z then
96 return ((x or 0) | (y or 0)) & 0xFFFFFFFF
97 else
98 local arg = {...}
99 local res = x | y | z
100 for i = 1, #arg do res = res | arg[i] end
101 return res & 0xFFFFFFFF
102 end
103end
104
105function bit.bxor (x, y, z, ...)
106 if not z then
107 return ((x or 0) ~ (y or 0)) & 0xFFFFFFFF
108 else
109 local arg = {...}
110 local res = x ~ y ~ z
111 for i = 1, #arg do res = res ~ arg[i] end
112 return res & 0xFFFFFFFF
113 end
114end
115
116function bit.btest (...)
117 return bit.band(...) ~= 0
118end
119
120function bit.lshift (a, b)
121 return ((a & 0xFFFFFFFF) << b) & 0xFFFFFFFF
122end
123
124function bit.rshift (a, b)
125 return ((a & 0xFFFFFFFF) >> b) & 0xFFFFFFFF
126end
127
128function bit.arshift (a, b)
129 a = a & 0xFFFFFFFF
130 if b <= 0 or (a & 0x80000000) == 0 then
131 return (a >> b) & 0xFFFFFFFF
132 else
133 return ((a >> b) | ~(0xFFFFFFFF >> b)) & 0xFFFFFFFF
134 end
135end
136
137function bit.lrotate (a ,b)
138 b = b & 31
139 a = a & 0xFFFFFFFF
140 a = (a << b) | (a >> (32 - b))
141 return a & 0xFFFFFFFF
142end
143
144function bit.rrotate (a, b)
145 return bit.lrotate(a, -b)
146end
147
148local function checkfield (f, w)
149 w = w or 1
150 assert(f >= 0, "field cannot be negative")
151 assert(w > 0, "width must be positive")
152 assert(f + w <= 32, "trying to access non-existent bits")
153 return f, ~(-1 << w)
154end
155
156function bit.extract (a, f, w)
157 local f, mask = checkfield(f, w)
158 return (a >> f) & mask
159end
160
161function bit.replace (a, v, f, w)
162 local f, mask = checkfield(f, w)
163 v = v & mask
164 a = (a & ~(mask << f)) | (v << f)
165 return a & 0xFFFFFFFF
166end
167
168return bit
169
170end --}
171
172
173print("testing bitwise library")
174
175local bit32 = require'bit32'
176
177assert(bit32.band() == bit32.bnot(0))
178assert(bit32.btest() == true)
179assert(bit32.bor() == 0)
180assert(bit32.bxor() == 0)
181
182assert(bit32.band() == bit32.band(0xffffffff))
183assert(bit32.band(1,2) == 0)
184
185
186-- out-of-range numbers
187assert(bit32.band(-1) == 0xffffffff)
188assert(bit32.band((1 << 33) - 1) == 0xffffffff)
189assert(bit32.band(-(1 << 33) - 1) == 0xffffffff)
190assert(bit32.band((1 << 33) + 1) == 1)
191assert(bit32.band(-(1 << 33) + 1) == 1)
192assert(bit32.band(-(1 << 40)) == 0)
193assert(bit32.band(1 << 40) == 0)
194assert(bit32.band(-(1 << 40) - 2) == 0xfffffffe)
195assert(bit32.band((1 << 40) - 4) == 0xfffffffc)
196
197assert(bit32.lrotate(0, -1) == 0)
198assert(bit32.lrotate(0, 7) == 0)
199assert(bit32.lrotate(0x12345678, 0) == 0x12345678)
200assert(bit32.lrotate(0x12345678, 32) == 0x12345678)
201assert(bit32.lrotate(0x12345678, 4) == 0x23456781)
202assert(bit32.rrotate(0x12345678, -4) == 0x23456781)
203assert(bit32.lrotate(0x12345678, -8) == 0x78123456)
204assert(bit32.rrotate(0x12345678, 8) == 0x78123456)
205assert(bit32.lrotate(0xaaaaaaaa, 2) == 0xaaaaaaaa)
206assert(bit32.lrotate(0xaaaaaaaa, -2) == 0xaaaaaaaa)
207for i = -50, 50 do
208 assert(bit32.lrotate(0x89abcdef, i) == bit32.lrotate(0x89abcdef, i%32))
209end
210
211assert(bit32.lshift(0x12345678, 4) == 0x23456780)
212assert(bit32.lshift(0x12345678, 8) == 0x34567800)
213assert(bit32.lshift(0x12345678, -4) == 0x01234567)
214assert(bit32.lshift(0x12345678, -8) == 0x00123456)
215assert(bit32.lshift(0x12345678, 32) == 0)
216assert(bit32.lshift(0x12345678, -32) == 0)
217assert(bit32.rshift(0x12345678, 4) == 0x01234567)
218assert(bit32.rshift(0x12345678, 8) == 0x00123456)
219assert(bit32.rshift(0x12345678, 32) == 0)
220assert(bit32.rshift(0x12345678, -32) == 0)
221assert(bit32.arshift(0x12345678, 0) == 0x12345678)
222assert(bit32.arshift(0x12345678, 1) == 0x12345678 // 2)
223assert(bit32.arshift(0x12345678, -1) == 0x12345678 * 2)
224assert(bit32.arshift(-1, 1) == 0xffffffff)
225assert(bit32.arshift(-1, 24) == 0xffffffff)
226assert(bit32.arshift(-1, 32) == 0xffffffff)
227assert(bit32.arshift(-1, -1) == bit32.band(-1 * 2, 0xffffffff))
228
229assert(0x12345678 << 4 == 0x123456780)
230assert(0x12345678 << 8 == 0x1234567800)
231assert(0x12345678 << -4 == 0x01234567)
232assert(0x12345678 << -8 == 0x00123456)
233assert(0x12345678 << 32 == 0x1234567800000000)
234assert(0x12345678 << -32 == 0)
235assert(0x12345678 >> 4 == 0x01234567)
236assert(0x12345678 >> 8 == 0x00123456)
237assert(0x12345678 >> 32 == 0)
238assert(0x12345678 >> -32 == 0x1234567800000000)
239
240print("+")
241-- some special cases
242local c = {0, 1, 2, 3, 10, 0x80000000, 0xaaaaaaaa, 0x55555555,
243 0xffffffff, 0x7fffffff}
244
245for _, b in pairs(c) do
246 assert(bit32.band(b) == b)
247 assert(bit32.band(b, b) == b)
248 assert(bit32.band(b, b, b, b) == b)
249 assert(bit32.btest(b, b) == (b ~= 0))
250 assert(bit32.band(b, b, b) == b)
251 assert(bit32.band(b, b, b, ~b) == 0)
252 assert(bit32.btest(b, b, b) == (b ~= 0))
253 assert(bit32.band(b, bit32.bnot(b)) == 0)
254 assert(bit32.bor(b, bit32.bnot(b)) == bit32.bnot(0))
255 assert(bit32.bor(b) == b)
256 assert(bit32.bor(b, b) == b)
257 assert(bit32.bor(b, b, b) == b)
258 assert(bit32.bor(b, b, 0, ~b) == 0xffffffff)
259 assert(bit32.bxor(b) == b)
260 assert(bit32.bxor(b, b) == 0)
261 assert(bit32.bxor(b, b, b) == b)
262 assert(bit32.bxor(b, b, b, b) == 0)
263 assert(bit32.bxor(b, 0) == b)
264 assert(bit32.bnot(b) ~= b)
265 assert(bit32.bnot(bit32.bnot(b)) == b)
266 assert(bit32.bnot(b) == (1 << 32) - 1 - b)
267 assert(bit32.lrotate(b, 32) == b)
268 assert(bit32.rrotate(b, 32) == b)
269 assert(bit32.lshift(bit32.lshift(b, -4), 4) == bit32.band(b, bit32.bnot(0xf)))
270 assert(bit32.rshift(bit32.rshift(b, 4), -4) == bit32.band(b, bit32.bnot(0xf)))
271end
272
273-- for this test, use at most 24 bits (mantissa of a single float)
274c = {0, 1, 2, 3, 10, 0x800000, 0xaaaaaa, 0x555555, 0xffffff, 0x7fffff}
275for _, b in pairs(c) do
276 for i = -40, 40 do
277 local x = bit32.lshift(b, i)
278 local y = math.floor(math.fmod(b * 2.0^i, 2.0^32))
279 assert(math.fmod(x - y, 2.0^32) == 0)
280 end
281end
282
283assert(not pcall(bit32.band, {}))
284assert(not pcall(bit32.bnot, "a"))
285assert(not pcall(bit32.lshift, 45))
286assert(not pcall(bit32.lshift, 45, print))
287assert(not pcall(bit32.rshift, 45, print))
288
289print("+")
290
291
292-- testing extract/replace
293
294assert(bit32.extract(0x12345678, 0, 4) == 8)
295assert(bit32.extract(0x12345678, 4, 4) == 7)
296assert(bit32.extract(0xa0001111, 28, 4) == 0xa)
297assert(bit32.extract(0xa0001111, 31, 1) == 1)
298assert(bit32.extract(0x50000111, 31, 1) == 0)
299assert(bit32.extract(0xf2345679, 0, 32) == 0xf2345679)
300
301assert(not pcall(bit32.extract, 0, -1))
302assert(not pcall(bit32.extract, 0, 32))
303assert(not pcall(bit32.extract, 0, 0, 33))
304assert(not pcall(bit32.extract, 0, 31, 2))
305
306assert(bit32.replace(0x12345678, 5, 28, 4) == 0x52345678)
307assert(bit32.replace(0x12345678, 0x87654321, 0, 32) == 0x87654321)
308assert(bit32.replace(0, 1, 2) == 2^2)
309assert(bit32.replace(0, -1, 4) == 2^4)
310assert(bit32.replace(-1, 0, 31) == (1 << 31) - 1)
311assert(bit32.replace(-1, 0, 1, 2) == (1 << 32) - 7)
312
313
314-- testing conversion of floats
315
316assert(bit32.bor(3.0) == 3)
317assert(bit32.bor(-4.0) == 0xfffffffc)
318
319-- large floats and large-enough integers?
320if 2.0^50 < 2.0^50 + 1.0 and 2.0^50 < (-1 >> 1) then
321 assert(bit32.bor(2.0^32 - 5.0) == 0xfffffffb)
322 assert(bit32.bor(-2.0^32 - 6.0) == 0xfffffffa)
323 assert(bit32.bor(2.0^48 - 5.0) == 0xfffffffb)
324 assert(bit32.bor(-2.0^48 - 6.0) == 0xfffffffa)
325end
326
327print'OK'
328
diff --git a/testes/bwcoercion.lua b/testes/bwcoercion.lua
new file mode 100644
index 00000000..cd735ab0
--- /dev/null
+++ b/testes/bwcoercion.lua
@@ -0,0 +1,78 @@
1local tonumber, tointeger = tonumber, math.tointeger
2local type, getmetatable, rawget, error = type, getmetatable, rawget, error
3local strsub = string.sub
4
5local print = print
6
7_ENV = nil
8
9-- Try to convert a value to an integer, without assuming any coercion.
10local function toint (x)
11 x = tonumber(x) -- handle numerical strings
12 if not x then
13 return false -- not coercible to a number
14 end
15 return tointeger(x)
16end
17
18
19-- If operation fails, maybe second operand has a metamethod that should
20-- have been called if not for this string metamethod, so try to
21-- call it.
22local function trymt (x, y, mtname)
23 if type(y) ~= "string" then -- avoid recalling original metamethod
24 local mt = getmetatable(y)
25 local mm = mt and rawget(mt, mtname)
26 if mm then
27 return mm(x, y)
28 end
29 end
30 -- if any test fails, there is no other metamethod to be called
31 error("attempt to '" .. strsub(mtname, 3) ..
32 "' a " .. type(x) .. " with a " .. type(y), 4)
33end
34
35
36local function checkargs (x, y, mtname)
37 local xi = toint(x)
38 local yi = toint(y)
39 if xi and yi then
40 return xi, yi
41 else
42 return trymt(x, y, mtname), nil
43 end
44end
45
46
47local smt = getmetatable("")
48
49smt.__band = function (x, y)
50 local x, y = checkargs(x, y, "__band")
51 return y and x & y or x
52end
53
54smt.__bor = function (x, y)
55 local x, y = checkargs(x, y, "__bor")
56 return y and x | y or x
57end
58
59smt.__bxor = function (x, y)
60 local x, y = checkargs(x, y, "__bxor")
61 return y and x ~ y or x
62end
63
64smt.__shl = function (x, y)
65 local x, y = checkargs(x, y, "__shl")
66 return y and x << y or x
67end
68
69smt.__shr = function (x, y)
70 local x, y = checkargs(x, y, "__shr")
71 return y and x >> y or x
72end
73
74smt.__bnot = function (x)
75 local x, y = checkargs(x, x, "__bnot")
76 return y and ~x or x
77end
78
diff --git a/testes/calls.lua b/testes/calls.lua
new file mode 100644
index 00000000..6d6fb7b2
--- /dev/null
+++ b/testes/calls.lua
@@ -0,0 +1,401 @@
1-- $Id: calls.lua,v 1.60 2016/11/07 13:11:28 roberto Exp $
2-- See Copyright Notice in file all.lua
3
4print("testing functions and calls")
5
6local debug = require "debug"
7
8-- get the opportunity to test 'type' too ;)
9
10assert(type(1<2) == 'boolean')
11assert(type(true) == 'boolean' and type(false) == 'boolean')
12assert(type(nil) == 'nil'
13 and type(-3) == 'number'
14 and type'x' == 'string'
15 and type{} == 'table'
16 and type(type) == 'function')
17
18assert(type(assert) == type(print))
19function f (x) return a:x (x) end
20assert(type(f) == 'function')
21assert(not pcall(type))
22
23
24do -- test error in 'print' too...
25 local tostring = _ENV.tostring
26
27 _ENV.tostring = nil
28 local st, msg = pcall(print, 1)
29 assert(st == false and string.find(msg, "attempt to call a nil value"))
30
31 _ENV.tostring = function () return {} end
32 local st, msg = pcall(print, 1)
33 assert(st == false and string.find(msg, "must return a string"))
34
35 _ENV.tostring = tostring
36end
37
38
39-- testing local-function recursion
40fact = false
41do
42 local res = 1
43 local function fact (n)
44 if n==0 then return res
45 else return n*fact(n-1)
46 end
47 end
48 assert(fact(5) == 120)
49end
50assert(fact == false)
51
52-- testing declarations
53a = {i = 10}
54self = 20
55function a:x (x) return x+self.i end
56function a.y (x) return x+self end
57
58assert(a:x(1)+10 == a.y(1))
59
60a.t = {i=-100}
61a["t"].x = function (self, a,b) return self.i+a+b end
62
63assert(a.t:x(2,3) == -95)
64
65do
66 local a = {x=0}
67 function a:add (x) self.x, a.y = self.x+x, 20; return self end
68 assert(a:add(10):add(20):add(30).x == 60 and a.y == 20)
69end
70
71local a = {b={c={}}}
72
73function a.b.c.f1 (x) return x+1 end
74function a.b.c:f2 (x,y) self[x] = y end
75assert(a.b.c.f1(4) == 5)
76a.b.c:f2('k', 12); assert(a.b.c.k == 12)
77
78print('+')
79
80t = nil -- 'declare' t
81function f(a,b,c) local d = 'a'; t={a,b,c,d} end
82
83f( -- this line change must be valid
84 1,2)
85assert(t[1] == 1 and t[2] == 2 and t[3] == nil and t[4] == 'a')
86f(1,2, -- this one too
87 3,4)
88assert(t[1] == 1 and t[2] == 2 and t[3] == 3 and t[4] == 'a')
89
90function fat(x)
91 if x <= 1 then return 1
92 else return x*load("return fat(" .. x-1 .. ")", "")()
93 end
94end
95
96assert(load "load 'assert(fat(6)==720)' () ")()
97a = load('return fat(5), 3')
98a,b = a()
99assert(a == 120 and b == 3)
100print('+')
101
102function err_on_n (n)
103 if n==0 then error(); exit(1);
104 else err_on_n (n-1); exit(1);
105 end
106end
107
108do
109 function dummy (n)
110 if n > 0 then
111 assert(not pcall(err_on_n, n))
112 dummy(n-1)
113 end
114 end
115end
116
117dummy(10)
118
119function deep (n)
120 if n>0 then deep(n-1) end
121end
122deep(10)
123deep(200)
124
125-- testing tail call
126function deep (n) if n>0 then return deep(n-1) else return 101 end end
127assert(deep(30000) == 101)
128a = {}
129function a:deep (n) if n>0 then return self:deep(n-1) else return 101 end end
130assert(a:deep(30000) == 101)
131
132print('+')
133
134
135a = nil
136(function (x) a=x end)(23)
137assert(a == 23 and (function (x) return x*2 end)(20) == 40)
138
139
140-- testing closures
141
142-- fixed-point operator
143Z = function (le)
144 local function a (f)
145 return le(function (x) return f(f)(x) end)
146 end
147 return a(a)
148 end
149
150
151-- non-recursive factorial
152
153F = function (f)
154 return function (n)
155 if n == 0 then return 1
156 else return n*f(n-1) end
157 end
158 end
159
160fat = Z(F)
161
162assert(fat(0) == 1 and fat(4) == 24 and Z(F)(5)==5*Z(F)(4))
163
164local function g (z)
165 local function f (a,b,c,d)
166 return function (x,y) return a+b+c+d+a+x+y+z end
167 end
168 return f(z,z+1,z+2,z+3)
169end
170
171f = g(10)
172assert(f(9, 16) == 10+11+12+13+10+9+16+10)
173
174Z, F, f = nil
175print('+')
176
177-- testing multiple returns
178
179function unlpack (t, i)
180 i = i or 1
181 if (i <= #t) then
182 return t[i], unlpack(t, i+1)
183 end
184end
185
186function equaltab (t1, t2)
187 assert(#t1 == #t2)
188 for i = 1, #t1 do
189 assert(t1[i] == t2[i])
190 end
191end
192
193local pack = function (...) return (table.pack(...)) end
194
195function f() return 1,2,30,4 end
196function ret2 (a,b) return a,b end
197
198local a,b,c,d = unlpack{1,2,3}
199assert(a==1 and b==2 and c==3 and d==nil)
200a = {1,2,3,4,false,10,'alo',false,assert}
201equaltab(pack(unlpack(a)), a)
202equaltab(pack(unlpack(a), -1), {1,-1})
203a,b,c,d = ret2(f()), ret2(f())
204assert(a==1 and b==1 and c==2 and d==nil)
205a,b,c,d = unlpack(pack(ret2(f()), ret2(f())))
206assert(a==1 and b==1 and c==2 and d==nil)
207a,b,c,d = unlpack(pack(ret2(f()), (ret2(f()))))
208assert(a==1 and b==1 and c==nil and d==nil)
209
210a = ret2{ unlpack{1,2,3}, unlpack{3,2,1}, unlpack{"a", "b"}}
211assert(a[1] == 1 and a[2] == 3 and a[3] == "a" and a[4] == "b")
212
213
214-- testing calls with 'incorrect' arguments
215rawget({}, "x", 1)
216rawset({}, "x", 1, 2)
217assert(math.sin(1,2) == math.sin(1))
218table.sort({10,9,8,4,19,23,0,0}, function (a,b) return a<b end, "extra arg")
219
220
221-- test for generic load
222local x = "-- a comment\0\0\0\n x = 10 + \n23; \
223 local a = function () x = 'hi' end; \
224 return '\0'"
225function read1 (x)
226 local i = 0
227 return function ()
228 collectgarbage()
229 i=i+1
230 return string.sub(x, i, i)
231 end
232end
233
234function cannotload (msg, a,b)
235 assert(not a and string.find(b, msg))
236end
237
238a = assert(load(read1(x), "modname", "t", _G))
239assert(a() == "\0" and _G.x == 33)
240assert(debug.getinfo(a).source == "modname")
241-- cannot read text in binary mode
242cannotload("attempt to load a text chunk", load(read1(x), "modname", "b", {}))
243cannotload("attempt to load a text chunk", load(x, "modname", "b"))
244
245a = assert(load(function () return nil end))
246a() -- empty chunk
247
248assert(not load(function () return true end))
249
250
251-- small bug
252local t = {nil, "return ", "3"}
253f, msg = load(function () return table.remove(t, 1) end)
254assert(f() == nil) -- should read the empty chunk
255
256-- another small bug (in 5.2.1)
257f = load(string.dump(function () return 1 end), nil, "b", {})
258assert(type(f) == "function" and f() == 1)
259
260
261x = string.dump(load("x = 1; return x"))
262a = assert(load(read1(x), nil, "b"))
263assert(a() == 1 and _G.x == 1)
264cannotload("attempt to load a binary chunk", load(read1(x), nil, "t"))
265cannotload("attempt to load a binary chunk", load(x, nil, "t"))
266
267assert(not pcall(string.dump, print)) -- no dump of C functions
268
269cannotload("unexpected symbol", load(read1("*a = 123")))
270cannotload("unexpected symbol", load("*a = 123"))
271cannotload("hhi", load(function () error("hhi") end))
272
273-- any value is valid for _ENV
274assert(load("return _ENV", nil, nil, 123)() == 123)
275
276
277-- load when _ENV is not first upvalue
278local x; XX = 123
279local function h ()
280 local y=x -- use 'x', so that it becomes 1st upvalue
281 return XX -- global name
282end
283local d = string.dump(h)
284x = load(d, "", "b")
285assert(debug.getupvalue(x, 2) == '_ENV')
286debug.setupvalue(x, 2, _G)
287assert(x() == 123)
288
289assert(assert(load("return XX + ...", nil, nil, {XX = 13}))(4) == 17)
290
291
292-- test generic load with nested functions
293x = [[
294 return function (x)
295 return function (y)
296 return function (z)
297 return x+y+z
298 end
299 end
300 end
301]]
302
303a = assert(load(read1(x)))
304assert(a()(2)(3)(10) == 15)
305
306
307-- test for dump/undump with upvalues
308local a, b = 20, 30
309x = load(string.dump(function (x)
310 if x == "set" then a = 10+b; b = b+1 else
311 return a
312 end
313end), "", "b", nil)
314assert(x() == nil)
315assert(debug.setupvalue(x, 1, "hi") == "a")
316assert(x() == "hi")
317assert(debug.setupvalue(x, 2, 13) == "b")
318assert(not debug.setupvalue(x, 3, 10)) -- only 2 upvalues
319x("set")
320assert(x() == 23)
321x("set")
322assert(x() == 24)
323
324-- test for dump/undump with many upvalues
325do
326 local nup = 200 -- maximum number of local variables
327 local prog = {"local a1"}
328 for i = 2, nup do prog[#prog + 1] = ", a" .. i end
329 prog[#prog + 1] = " = 1"
330 for i = 2, nup do prog[#prog + 1] = ", " .. i end
331 local sum = 1
332 prog[#prog + 1] = "; return function () return a1"
333 for i = 2, nup do prog[#prog + 1] = " + a" .. i; sum = sum + i end
334 prog[#prog + 1] = " end"
335 prog = table.concat(prog)
336 local f = assert(load(prog))()
337 assert(f() == sum)
338
339 f = load(string.dump(f)) -- main chunk now has many upvalues
340 local a = 10
341 local h = function () return a end
342 for i = 1, nup do
343 debug.upvaluejoin(f, i, h, 1)
344 end
345 assert(f() == 10 * nup)
346end
347
348-- test for long method names
349do
350 local t = {x = 1}
351 function t:_012345678901234567890123456789012345678901234567890123456789 ()
352 return self.x
353 end
354 assert(t:_012345678901234567890123456789012345678901234567890123456789() == 1)
355end
356
357
358-- test for bug in parameter adjustment
359assert((function () return nil end)(4) == nil)
360assert((function () local a; return a end)(4) == nil)
361assert((function (a) return a end)() == nil)
362
363
364print("testing binary chunks")
365do
366 local header = string.pack("c4BBc6BBBBBj",
367 "\27Lua", -- signature
368 5*16 + 3, -- version 5.3
369 0, -- format
370 "\x19\x93\r\n\x1a\n", -- data
371 string.packsize("i"), -- sizeof(int)
372 string.packsize("T"), -- sizeof(size_t)
373 4, -- size of instruction
374 string.packsize("j"), -- sizeof(lua integer)
375 string.packsize("n"), -- sizeof(lua number)
376 0x5678 -- LUAC_INT
377 -- LUAC_NUM may not have a unique binary representation (padding...)
378 )
379 local c = string.dump(function () local a = 1; local b = 3; return a+b*3 end)
380
381 assert(string.sub(c, 1, #header) == header)
382
383 -- corrupted header
384 for i = 1, #header do
385 local s = string.sub(c, 1, i - 1) ..
386 string.char(string.byte(string.sub(c, i, i)) + 1) ..
387 string.sub(c, i + 1, -1)
388 assert(#s == #c)
389 assert(not load(s))
390 end
391
392 -- loading truncated binary chunks
393 for i = 1, #c - 1 do
394 local st, msg = load(string.sub(c, 1, i))
395 assert(not st and string.find(msg, "truncated"))
396 end
397 assert(assert(load(c))() == 10)
398end
399
400print('OK')
401return deep
diff --git a/testes/closure.lua b/testes/closure.lua
new file mode 100644
index 00000000..15897ae6
--- /dev/null
+++ b/testes/closure.lua
@@ -0,0 +1,247 @@
1-- $Id: closure.lua,v 1.59 2016/11/07 13:11:28 roberto Exp $
2-- See Copyright Notice in file all.lua
3
4print "testing closures"
5
6local A,B = 0,{g=10}
7function f(x)
8 local a = {}
9 for i=1,1000 do
10 local y = 0
11 do
12 a[i] = function () B.g = B.g+1; y = y+x; return y+A end
13 end
14 end
15 local dummy = function () return a[A] end
16 collectgarbage()
17 A = 1; assert(dummy() == a[1]); A = 0;
18 assert(a[1]() == x)
19 assert(a[3]() == x)
20 collectgarbage()
21 assert(B.g == 12)
22 return a
23end
24
25local a = f(10)
26-- force a GC in this level
27local x = {[1] = {}} -- to detect a GC
28setmetatable(x, {__mode = 'kv'})
29while x[1] do -- repeat until GC
30 local a = A..A..A..A -- create garbage
31 A = A+1
32end
33assert(a[1]() == 20+A)
34assert(a[1]() == 30+A)
35assert(a[2]() == 10+A)
36collectgarbage()
37assert(a[2]() == 20+A)
38assert(a[2]() == 30+A)
39assert(a[3]() == 20+A)
40assert(a[8]() == 10+A)
41assert(getmetatable(x).__mode == 'kv')
42assert(B.g == 19)
43
44
45-- testing equality
46a = {}
47for i = 1, 5 do a[i] = function (x) return x + a + _ENV end end
48assert(a[3] == a[4] and a[4] == a[5])
49
50for i = 1, 5 do a[i] = function (x) return i + a + _ENV end end
51assert(a[3] ~= a[4] and a[4] ~= a[5])
52
53local function f()
54 return function (x) return math.sin(_ENV[x]) end
55end
56assert(f() == f())
57
58
59-- testing closures with 'for' control variable
60a = {}
61for i=1,10 do
62 a[i] = {set = function(x) i=x end, get = function () return i end}
63 if i == 3 then break end
64end
65assert(a[4] == nil)
66a[1].set(10)
67assert(a[2].get() == 2)
68a[2].set('a')
69assert(a[3].get() == 3)
70assert(a[2].get() == 'a')
71
72a = {}
73local t = {"a", "b"}
74for i = 1, #t do
75 local k = t[i]
76 a[i] = {set = function(x, y) i=x; k=y end,
77 get = function () return i, k end}
78 if i == 2 then break end
79end
80a[1].set(10, 20)
81local r,s = a[2].get()
82assert(r == 2 and s == 'b')
83r,s = a[1].get()
84assert(r == 10 and s == 20)
85a[2].set('a', 'b')
86r,s = a[2].get()
87assert(r == "a" and s == "b")
88
89
90-- testing closures with 'for' control variable x break
91for i=1,3 do
92 f = function () return i end
93 break
94end
95assert(f() == 1)
96
97for k = 1, #t do
98 local v = t[k]
99 f = function () return k, v end
100 break
101end
102assert(({f()})[1] == 1)
103assert(({f()})[2] == "a")
104
105
106-- testing closure x break x return x errors
107
108local b
109function f(x)
110 local first = 1
111 while 1 do
112 if x == 3 and not first then return end
113 local a = 'xuxu'
114 b = function (op, y)
115 if op == 'set' then
116 a = x+y
117 else
118 return a
119 end
120 end
121 if x == 1 then do break end
122 elseif x == 2 then return
123 else if x ~= 3 then error() end
124 end
125 first = nil
126 end
127end
128
129for i=1,3 do
130 f(i)
131 assert(b('get') == 'xuxu')
132 b('set', 10); assert(b('get') == 10+i)
133 b = nil
134end
135
136pcall(f, 4);
137assert(b('get') == 'xuxu')
138b('set', 10); assert(b('get') == 14)
139
140
141local w
142-- testing multi-level closure
143function f(x)
144 return function (y)
145 return function (z) return w+x+y+z end
146 end
147end
148
149y = f(10)
150w = 1.345
151assert(y(20)(30) == 60+w)
152
153-- testing closures x repeat-until
154
155local a = {}
156local i = 1
157repeat
158 local x = i
159 a[i] = function () i = x+1; return x end
160until i > 10 or a[i]() ~= x
161assert(i == 11 and a[1]() == 1 and a[3]() == 3 and i == 4)
162
163
164-- testing closures created in 'then' and 'else' parts of 'if's
165a = {}
166for i = 1, 10 do
167 if i % 3 == 0 then
168 local y = 0
169 a[i] = function (x) local t = y; y = x; return t end
170 elseif i % 3 == 1 then
171 goto L1
172 error'not here'
173 ::L1::
174 local y = 1
175 a[i] = function (x) local t = y; y = x; return t end
176 elseif i % 3 == 2 then
177 local t
178 goto l4
179 ::l4a:: a[i] = t; goto l4b
180 error("should never be here!")
181 ::l4::
182 local y = 2
183 t = function (x) local t = y; y = x; return t end
184 goto l4a
185 error("should never be here!")
186 ::l4b::
187 end
188end
189
190for i = 1, 10 do
191 assert(a[i](i * 10) == i % 3 and a[i]() == i * 10)
192end
193
194print'+'
195
196
197-- test for correctly closing upvalues in tail calls of vararg functions
198local function t ()
199 local function c(a,b) assert(a=="test" and b=="OK") end
200 local function v(f, ...) c("test", f() ~= 1 and "FAILED" or "OK") end
201 local x = 1
202 return v(function() return x end)
203end
204t()
205
206
207-- test for debug manipulation of upvalues
208local debug = require'debug'
209
210do
211 local a , b, c = 3, 5, 7
212 foo1 = function () return a+b end;
213 foo2 = function () return b+a end;
214 do
215 local a = 10
216 foo3 = function () return a+b end;
217 end
218end
219
220assert(debug.upvalueid(foo1, 1))
221assert(debug.upvalueid(foo1, 2))
222assert(not pcall(debug.upvalueid, foo1, 3))
223assert(debug.upvalueid(foo1, 1) == debug.upvalueid(foo2, 2))
224assert(debug.upvalueid(foo1, 2) == debug.upvalueid(foo2, 1))
225assert(debug.upvalueid(foo3, 1))
226assert(debug.upvalueid(foo1, 1) ~= debug.upvalueid(foo3, 1))
227assert(debug.upvalueid(foo1, 2) == debug.upvalueid(foo3, 2))
228
229assert(debug.upvalueid(string.gmatch("x", "x"), 1) ~= nil)
230
231assert(foo1() == 3 + 5 and foo2() == 5 + 3)
232debug.upvaluejoin(foo1, 2, foo2, 2)
233assert(foo1() == 3 + 3 and foo2() == 5 + 3)
234assert(foo3() == 10 + 5)
235debug.upvaluejoin(foo3, 2, foo2, 1)
236assert(foo3() == 10 + 5)
237debug.upvaluejoin(foo3, 2, foo2, 2)
238assert(foo3() == 10 + 3)
239
240assert(not pcall(debug.upvaluejoin, foo1, 3, foo2, 1))
241assert(not pcall(debug.upvaluejoin, foo1, 1, foo2, 3))
242assert(not pcall(debug.upvaluejoin, foo1, 0, foo2, 1))
243assert(not pcall(debug.upvaluejoin, print, 1, foo2, 1))
244assert(not pcall(debug.upvaluejoin, {}, 1, foo2, 1))
245assert(not pcall(debug.upvaluejoin, foo1, 1, print, 1))
246
247print'OK'
diff --git a/testes/code.lua b/testes/code.lua
new file mode 100644
index 00000000..0b9d142d
--- /dev/null
+++ b/testes/code.lua
@@ -0,0 +1,239 @@
1-- $Id: code.lua,v 1.42 2016/11/07 13:04:32 roberto Exp $
2-- See Copyright Notice in file all.lua
3
4if T==nil then
5 (Message or print)('\n >>> testC not active: skipping opcode tests <<<\n')
6 return
7end
8print "testing code generation and optimizations"
9
10
11-- this code gave an error for the code checker
12do
13 local function f (a)
14 for k,v,w in a do end
15 end
16end
17
18
19-- testing reuse in constant table
20local function checkKlist (func, list)
21 local k = T.listk(func)
22 assert(#k == #list)
23 for i = 1, #k do
24 assert(k[i] == list[i] and math.type(k[i]) == math.type(list[i]))
25 end
26end
27
28local function foo ()
29 local a
30 a = 3;
31 a = 0; a = 0.0; a = -7 + 7
32 a = 3.78/4; a = 3.78/4
33 a = -3.78/4; a = 3.78/4; a = -3.78/4
34 a = -3.79/4; a = 0.0; a = -0;
35 a = 3; a = 3.0; a = 3; a = 3.0
36end
37
38checkKlist(foo, {3, 0, 0.0, 3.78/4, -3.78/4, -3.79/4, 3.0})
39
40
41-- testing opcodes
42
43function check (f, ...)
44 local arg = {...}
45 local c = T.listcode(f)
46 for i=1, #arg do
47 -- print(arg[i], c[i])
48 assert(string.find(c[i], '- '..arg[i]..' *%d'))
49 end
50 assert(c[#arg+2] == nil)
51end
52
53
54function checkequal (a, b)
55 a = T.listcode(a)
56 b = T.listcode(b)
57 for i = 1, #a do
58 a[i] = string.gsub(a[i], '%b()', '') -- remove line number
59 b[i] = string.gsub(b[i], '%b()', '') -- remove line number
60 assert(a[i] == b[i])
61 end
62end
63
64
65-- some basic instructions
66check(function ()
67 (function () end){f()}
68end, 'CLOSURE', 'NEWTABLE', 'GETTABUP', 'CALL', 'SETLIST', 'CALL', 'RETURN')
69
70
71-- sequence of LOADNILs
72check(function ()
73 local a,b,c
74 local d; local e;
75 local f,g,h;
76 d = nil; d=nil; b=nil; a=nil; c=nil;
77end, 'LOADNIL', 'RETURN')
78
79check(function ()
80 local a,b,c,d = 1,1,1,1
81 d=nil;c=nil;b=nil;a=nil
82end, 'LOADK', 'LOADK', 'LOADK', 'LOADK', 'LOADNIL', 'RETURN')
83
84do
85 local a,b,c,d = 1,1,1,1
86 d=nil;c=nil;b=nil;a=nil
87 assert(a == nil and b == nil and c == nil and d == nil)
88end
89
90
91-- single return
92check (function (a,b,c) return a end, 'RETURN')
93
94
95-- infinite loops
96check(function () while true do local a = -1 end end,
97'LOADK', 'JMP', 'RETURN')
98
99check(function () while 1 do local a = -1 end end,
100'LOADK', 'JMP', 'RETURN')
101
102check(function () repeat local x = 1 until true end,
103'LOADK', 'RETURN')
104
105
106-- concat optimization
107check(function (a,b,c,d) return a..b..c..d end,
108 'MOVE', 'MOVE', 'MOVE', 'MOVE', 'CONCAT', 'RETURN')
109
110-- not
111check(function () return not not nil end, 'LOADBOOL', 'RETURN')
112check(function () return not not false end, 'LOADBOOL', 'RETURN')
113check(function () return not not true end, 'LOADBOOL', 'RETURN')
114check(function () return not not 1 end, 'LOADBOOL', 'RETURN')
115
116-- direct access to locals
117check(function ()
118 local a,b,c,d
119 a = b*2
120 c[2], a[b] = -((a + d/2 - a[b]) ^ a.x), b
121end,
122 'LOADNIL',
123 'MUL',
124 'DIV', 'ADD', 'GETTABLE', 'SUB', 'GETTABLE', 'POW',
125 'UNM', 'SETTABLE', 'SETTABLE', 'RETURN')
126
127
128-- direct access to constants
129check(function ()
130 local a,b
131 a.x = 3.2
132 a.x = b
133 a[b] = 'x'
134end,
135 'LOADNIL', 'SETTABLE', 'SETTABLE', 'SETTABLE', 'RETURN')
136
137check(function ()
138 local a,b
139 a = 1 - a
140 b = 1/a
141 b = 5-4
142end,
143 'LOADNIL', 'SUB', 'DIV', 'LOADK', 'RETURN')
144
145check(function ()
146 local a,b
147 a[true] = false
148end,
149 'LOADNIL', 'SETTABLE', 'RETURN')
150
151
152-- constant folding
153local function checkK (func, val)
154 check(func, 'LOADK', 'RETURN')
155 local k = T.listk(func)
156 assert(#k == 1 and k[1] == val and math.type(k[1]) == math.type(val))
157 assert(func() == val)
158end
159checkK(function () return 0.0 end, 0.0)
160checkK(function () return 0 end, 0)
161checkK(function () return -0//1 end, 0)
162checkK(function () return 3^-1 end, 1/3)
163checkK(function () return (1 + 1)^(50 + 50) end, 2^100)
164checkK(function () return (-2)^(31 - 2) end, -0x20000000 + 0.0)
165checkK(function () return (-3^0 + 5) // 3.0 end, 1.0)
166checkK(function () return -3 % 5 end, 2)
167checkK(function () return -((2.0^8 + -(-1)) % 8)/2 * 4 - 3 end, -5.0)
168checkK(function () return -((2^8 + -(-1)) % 8)//2 * 4 - 3 end, -7.0)
169checkK(function () return 0xF0.0 | 0xCC.0 ~ 0xAA & 0xFD end, 0xF4)
170checkK(function () return ~(~0xFF0 | 0xFF0) end, 0)
171checkK(function () return ~~-100024.0 end, -100024)
172checkK(function () return ((100 << 6) << -4) >> 2 end, 100)
173
174
175-- no foldings
176check(function () return -0.0 end, 'LOADK', 'UNM', 'RETURN')
177check(function () return 3/0 end, 'DIV', 'RETURN')
178check(function () return 0%0 end, 'MOD', 'RETURN')
179check(function () return -4//0 end, 'IDIV', 'RETURN')
180
181-- bug in constant folding for 5.1
182check(function () return -nil end, 'LOADNIL', 'UNM', 'RETURN')
183
184
185check(function ()
186 local a,b,c
187 b[c], a = c, b
188 b[a], a = c, b
189 a, b = c, a
190 a = a
191end,
192 'LOADNIL',
193 'MOVE', 'MOVE', 'SETTABLE',
194 'MOVE', 'MOVE', 'MOVE', 'SETTABLE',
195 'MOVE', 'MOVE', 'MOVE',
196 -- no code for a = a
197 'RETURN')
198
199
200-- x == nil , x ~= nil
201checkequal(function () if (a==nil) then a=1 end; if a~=nil then a=1 end end,
202 function () if (a==9) then a=1 end; if a~=9 then a=1 end end)
203
204check(function () if a==nil then a='a' end end,
205'GETTABUP', 'EQ', 'JMP', 'SETTABUP', 'RETURN')
206
207-- de morgan
208checkequal(function () local a; if not (a or b) then b=a end end,
209 function () local a; if (not a and not b) then b=a end end)
210
211checkequal(function (l) local a; return 0 <= a and a <= l end,
212 function (l) local a; return not (not(a >= 0) or not(a <= l)) end)
213
214
215-- if-goto optimizations
216check(function (a, b, c, d, e)
217 if a == b then goto l1
218 elseif a == c then goto l2
219 elseif a == d then goto l2
220 else if a == e then goto l3
221 else goto l3
222 end
223 end
224 ::l1:: ::l2:: ::l3:: ::l4::
225end, 'EQ', 'JMP', 'EQ', 'JMP', 'EQ', 'JMP', 'EQ', 'JMP', 'JMP', 'RETURN')
226
227checkequal(
228function (a) while a < 10 do a = a + 1 end end,
229function (a) ::L2:: if not(a < 10) then goto L1 end; a = a + 1;
230 goto L2; ::L1:: end
231)
232
233checkequal(
234function (a) while a < 10 do a = a + 1 end end,
235function (a) while true do if not(a < 10) then break end; a = a + 1; end end
236)
237
238print 'OK'
239
diff --git a/testes/constructs.lua b/testes/constructs.lua
new file mode 100644
index 00000000..cebd2572
--- /dev/null
+++ b/testes/constructs.lua
@@ -0,0 +1,313 @@
1-- $Id: constructs.lua,v 1.41 2016/11/07 13:11:28 roberto Exp $
2-- See Copyright Notice in file all.lua
3
4;;print "testing syntax";;
5
6local debug = require "debug"
7
8
9local function checkload (s, msg)
10 assert(string.find(select(2, load(s)), msg))
11end
12
13-- testing semicollons
14do ;;; end
15; do ; a = 3; assert(a == 3) end;
16;
17
18
19-- invalid operations should not raise errors when not executed
20if false then a = 3 // 0; a = 0 % 0 end
21
22
23-- testing priorities
24
25assert(2^3^2 == 2^(3^2));
26assert(2^3*4 == (2^3)*4);
27assert(2.0^-2 == 1/4 and -2^- -2 == - - -4);
28assert(not nil and 2 and not(2>3 or 3<2));
29assert(-3-1-5 == 0+0-9);
30assert(-2^2 == -4 and (-2)^2 == 4 and 2*2-3-1 == 0);
31assert(-3%5 == 2 and -3+5 == 2)
32assert(2*1+3/3 == 3 and 1+2 .. 3*1 == "33");
33assert(not(2+1 > 3*1) and "a".."b" > "a");
34
35assert("7" .. 3 << 1 == 146)
36assert(10 >> 1 .. "9" == 0)
37assert(10 | 1 .. "9" == 27)
38
39assert(0xF0 | 0xCC ~ 0xAA & 0xFD == 0xF4)
40assert(0xFD & 0xAA ~ 0xCC | 0xF0 == 0xF4)
41assert(0xF0 & 0x0F + 1 == 0x10)
42
43assert(3^4//2^3//5 == 2)
44
45assert(-3+4*5//2^3^2//9+4%10/3 == (-3)+(((4*5)//(2^(3^2)))//9)+((4%10)/3))
46
47assert(not ((true or false) and nil))
48assert( true or false and nil)
49
50-- old bug
51assert((((1 or false) and true) or false) == true)
52assert((((nil and true) or false) and true) == false)
53
54local a,b = 1,nil;
55assert(-(1 or 2) == -1 and (1 and 2)+(-1.25 or -4) == 0.75);
56x = ((b or a)+1 == 2 and (10 or a)+1 == 11); assert(x);
57x = (((2<3) or 1) == true and (2<3 and 4) == 4); assert(x);
58
59x,y=1,2;
60assert((x>y) and x or y == 2);
61x,y=2,1;
62assert((x>y) and x or y == 2);
63
64assert(1234567890 == tonumber('1234567890') and 1234567890+1 == 1234567891)
65
66
67-- silly loops
68repeat until 1; repeat until true;
69while false do end; while nil do end;
70
71do -- test old bug (first name could not be an `upvalue')
72 local a; function f(x) x={a=1}; x={x=1}; x={G=1} end
73end
74
75function f (i)
76 if type(i) ~= 'number' then return i,'jojo'; end;
77 if i > 0 then return i, f(i-1); end;
78end
79
80x = {f(3), f(5), f(10);};
81assert(x[1] == 3 and x[2] == 5 and x[3] == 10 and x[4] == 9 and x[12] == 1);
82assert(x[nil] == nil)
83x = {f'alo', f'xixi', nil};
84assert(x[1] == 'alo' and x[2] == 'xixi' and x[3] == nil);
85x = {f'alo'..'xixi'};
86assert(x[1] == 'aloxixi')
87x = {f{}}
88assert(x[2] == 'jojo' and type(x[1]) == 'table')
89
90
91local f = function (i)
92 if i < 10 then return 'a';
93 elseif i < 20 then return 'b';
94 elseif i < 30 then return 'c';
95 end;
96end
97
98assert(f(3) == 'a' and f(12) == 'b' and f(26) == 'c' and f(100) == nil)
99
100for i=1,1000 do break; end;
101n=100;
102i=3;
103t = {};
104a=nil
105while not a do
106 a=0; for i=1,n do for i=i,1,-1 do a=a+1; t[i]=1; end; end;
107end
108assert(a == n*(n+1)/2 and i==3);
109assert(t[1] and t[n] and not t[0] and not t[n+1])
110
111function f(b)
112 local x = 1;
113 repeat
114 local a;
115 if b==1 then local b=1; x=10; break
116 elseif b==2 then x=20; break;
117 elseif b==3 then x=30;
118 else local a,b,c,d=math.sin(1); x=x+1;
119 end
120 until x>=12;
121 return x;
122end;
123
124assert(f(1) == 10 and f(2) == 20 and f(3) == 30 and f(4)==12)
125
126
127local f = function (i)
128 if i < 10 then return 'a'
129 elseif i < 20 then return 'b'
130 elseif i < 30 then return 'c'
131 else return 8
132 end
133end
134
135assert(f(3) == 'a' and f(12) == 'b' and f(26) == 'c' and f(100) == 8)
136
137local a, b = nil, 23
138x = {f(100)*2+3 or a, a or b+2}
139assert(x[1] == 19 and x[2] == 25)
140x = {f=2+3 or a, a = b+2}
141assert(x.f == 5 and x.a == 25)
142
143a={y=1}
144x = {a.y}
145assert(x[1] == 1)
146
147function f(i)
148 while 1 do
149 if i>0 then i=i-1;
150 else return; end;
151 end;
152end;
153
154function g(i)
155 while 1 do
156 if i>0 then i=i-1
157 else return end
158 end
159end
160
161f(10); g(10);
162
163do
164 function f () return 1,2,3; end
165 local a, b, c = f();
166 assert(a==1 and b==2 and c==3)
167 a, b, c = (f());
168 assert(a==1 and b==nil and c==nil)
169end
170
171local a,b = 3 and f();
172assert(a==1 and b==nil)
173
174function g() f(); return; end;
175assert(g() == nil)
176function g() return nil or f() end
177a,b = g()
178assert(a==1 and b==nil)
179
180print'+';
181
182
183f = [[
184return function ( a , b , c , d , e )
185 local x = a >= b or c or ( d and e ) or nil
186 return x
187end , { a = 1 , b = 2 >= 1 , } or { 1 };
188]]
189f = string.gsub(f, "%s+", "\n"); -- force a SETLINE between opcodes
190f,a = load(f)();
191assert(a.a == 1 and a.b)
192
193function g (a,b,c,d,e)
194 if not (a>=b or c or d and e or nil) then return 0; else return 1; end;
195end
196
197function h (a,b,c,d,e)
198 while (a>=b or c or (d and e) or nil) do return 1; end;
199 return 0;
200end;
201
202assert(f(2,1) == true and g(2,1) == 1 and h(2,1) == 1)
203assert(f(1,2,'a') == 'a' and g(1,2,'a') == 1 and h(1,2,'a') == 1)
204assert(f(1,2,'a')
205~= -- force SETLINE before nil
206nil, "")
207assert(f(1,2,'a') == 'a' and g(1,2,'a') == 1 and h(1,2,'a') == 1)
208assert(f(1,2,nil,1,'x') == 'x' and g(1,2,nil,1,'x') == 1 and
209 h(1,2,nil,1,'x') == 1)
210assert(f(1,2,nil,nil,'x') == nil and g(1,2,nil,nil,'x') == 0 and
211 h(1,2,nil,nil,'x') == 0)
212assert(f(1,2,nil,1,nil) == nil and g(1,2,nil,1,nil) == 0 and
213 h(1,2,nil,1,nil) == 0)
214
215assert(1 and 2<3 == true and 2<3 and 'a'<'b' == true)
216x = 2<3 and not 3; assert(x==false)
217x = 2<1 or (2>1 and 'a'); assert(x=='a')
218
219
220do
221 local a; if nil then a=1; else a=2; end; -- this nil comes as PUSHNIL 2
222 assert(a==2)
223end
224
225function F(a)
226 assert(debug.getinfo(1, "n").name == 'F')
227 return a,2,3
228end
229
230a,b = F(1)~=nil; assert(a == true and b == nil);
231a,b = F(nil)==nil; assert(a == true and b == nil)
232
233----------------------------------------------------------------
234------------------------------------------------------------------
235
236-- sometimes will be 0, sometimes will not...
237_ENV.GLOB1 = math.floor(os.time()) % 2
238
239-- basic expressions with their respective values
240local basiccases = {
241 {"nil", nil},
242 {"false", false},
243 {"true", true},
244 {"10", 10},
245 {"(0==_ENV.GLOB1)", 0 == _ENV.GLOB1},
246}
247
248print('testing short-circuit optimizations (' .. _ENV.GLOB1 .. ')')
249
250
251-- operators with their respective values
252local binops = {
253 {" and ", function (a,b) if not a then return a else return b end end},
254 {" or ", function (a,b) if a then return a else return b end end},
255}
256
257local cases = {}
258
259-- creates all combinations of '(cases[i] op cases[n-i])' plus
260-- 'not(cases[i] op cases[n-i])' (syntax + value)
261local function createcases (n)
262 local res = {}
263 for i = 1, n - 1 do
264 for _, v1 in ipairs(cases[i]) do
265 for _, v2 in ipairs(cases[n - i]) do
266 for _, op in ipairs(binops) do
267 local t = {
268 "(" .. v1[1] .. op[1] .. v2[1] .. ")",
269 op[2](v1[2], v2[2])
270 }
271 res[#res + 1] = t
272 res[#res + 1] = {"not" .. t[1], not t[2]}
273 end
274 end
275 end
276 end
277 return res
278end
279
280-- do not do too many combinations for soft tests
281local level = _soft and 3 or 4
282
283cases[1] = basiccases
284for i = 2, level do cases[i] = createcases(i) end
285print("+")
286
287local prog = [[if %s then IX = true end; return %s]]
288
289local i = 0
290for n = 1, level do
291 for _, v in pairs(cases[n]) do
292 local s = v[1]
293 local p = load(string.format(prog, s, s), "")
294 IX = false
295 assert(p() == v[2] and IX == not not v[2])
296 i = i + 1
297 if i % 60000 == 0 then print('+') end
298 end
299end
300------------------------------------------------------------------
301
302-- testing some syntax errors (chosen through 'gcov')
303checkload("for x do", "expected")
304checkload("x:call", "expected")
305
306if not _soft then
307 -- control structure too long
308 local s = string.rep("a = a + 1\n", 2^18)
309 s = "while true do " .. s .. "end"
310 checkload(s, "too long")
311end
312
313print'OK'
diff --git a/testes/coroutine.lua b/testes/coroutine.lua
new file mode 100644
index 00000000..c8fc8572
--- /dev/null
+++ b/testes/coroutine.lua
@@ -0,0 +1,874 @@
1-- $Id: coroutine.lua,v 1.42 2016/11/07 13:03:20 roberto Exp $
2-- See Copyright Notice in file all.lua
3
4print "testing coroutines"
5
6local debug = require'debug'
7
8local f
9
10local main, ismain = coroutine.running()
11assert(type(main) == "thread" and ismain)
12assert(not coroutine.resume(main))
13assert(not coroutine.isyieldable())
14assert(not pcall(coroutine.yield))
15
16
17-- trivial errors
18assert(not pcall(coroutine.resume, 0))
19assert(not pcall(coroutine.status, 0))
20
21
22-- tests for multiple yield/resume arguments
23
24local function eqtab (t1, t2)
25 assert(#t1 == #t2)
26 for i = 1, #t1 do
27 local v = t1[i]
28 assert(t2[i] == v)
29 end
30end
31
32_G.x = nil -- declare x
33function foo (a, ...)
34 local x, y = coroutine.running()
35 assert(x == f and y == false)
36 -- next call should not corrupt coroutine (but must fail,
37 -- as it attempts to resume the running coroutine)
38 assert(coroutine.resume(f) == false)
39 assert(coroutine.status(f) == "running")
40 local arg = {...}
41 assert(coroutine.isyieldable())
42 for i=1,#arg do
43 _G.x = {coroutine.yield(table.unpack(arg[i]))}
44 end
45 return table.unpack(a)
46end
47
48f = coroutine.create(foo)
49assert(type(f) == "thread" and coroutine.status(f) == "suspended")
50assert(string.find(tostring(f), "thread"))
51local s,a,b,c,d
52s,a,b,c,d = coroutine.resume(f, {1,2,3}, {}, {1}, {'a', 'b', 'c'})
53assert(s and a == nil and coroutine.status(f) == "suspended")
54s,a,b,c,d = coroutine.resume(f)
55eqtab(_G.x, {})
56assert(s and a == 1 and b == nil)
57s,a,b,c,d = coroutine.resume(f, 1, 2, 3)
58eqtab(_G.x, {1, 2, 3})
59assert(s and a == 'a' and b == 'b' and c == 'c' and d == nil)
60s,a,b,c,d = coroutine.resume(f, "xuxu")
61eqtab(_G.x, {"xuxu"})
62assert(s and a == 1 and b == 2 and c == 3 and d == nil)
63assert(coroutine.status(f) == "dead")
64s, a = coroutine.resume(f, "xuxu")
65assert(not s and string.find(a, "dead") and coroutine.status(f) == "dead")
66
67
68-- yields in tail calls
69local function foo (i) return coroutine.yield(i) end
70f = coroutine.wrap(function ()
71 for i=1,10 do
72 assert(foo(i) == _G.x)
73 end
74 return 'a'
75end)
76for i=1,10 do _G.x = i; assert(f(i) == i) end
77_G.x = 'xuxu'; assert(f('xuxu') == 'a')
78
79-- recursive
80function pf (n, i)
81 coroutine.yield(n)
82 pf(n*i, i+1)
83end
84
85f = coroutine.wrap(pf)
86local s=1
87for i=1,10 do
88 assert(f(1, 1) == s)
89 s = s*i
90end
91
92-- sieve
93function gen (n)
94 return coroutine.wrap(function ()
95 for i=2,n do coroutine.yield(i) end
96 end)
97end
98
99
100function filter (p, g)
101 return coroutine.wrap(function ()
102 while 1 do
103 local n = g()
104 if n == nil then return end
105 if math.fmod(n, p) ~= 0 then coroutine.yield(n) end
106 end
107 end)
108end
109
110local x = gen(100)
111local a = {}
112while 1 do
113 local n = x()
114 if n == nil then break end
115 table.insert(a, n)
116 x = filter(n, x)
117end
118
119assert(#a == 25 and a[#a] == 97)
120x, a = nil
121
122-- yielding across C boundaries
123
124co = coroutine.wrap(function()
125 assert(not pcall(table.sort,{1,2,3}, coroutine.yield))
126 assert(coroutine.isyieldable())
127 coroutine.yield(20)
128 return 30
129 end)
130
131assert(co() == 20)
132assert(co() == 30)
133
134
135local f = function (s, i) return coroutine.yield(i) end
136
137local f1 = coroutine.wrap(function ()
138 return xpcall(pcall, function (...) return ... end,
139 function ()
140 local s = 0
141 for i in f, nil, 1 do pcall(function () s = s + i end) end
142 error({s})
143 end)
144 end)
145
146f1()
147for i = 1, 10 do assert(f1(i) == i) end
148local r1, r2, v = f1(nil)
149assert(r1 and not r2 and v[1] == (10 + 1)*10/2)
150
151
152function f (a, b) a = coroutine.yield(a); error{a + b} end
153function g(x) return x[1]*2 end
154
155co = coroutine.wrap(function ()
156 coroutine.yield(xpcall(f, g, 10, 20))
157 end)
158
159assert(co() == 10)
160r, msg = co(100)
161assert(not r and msg == 240)
162
163
164-- unyieldable C call
165do
166 local function f (c)
167 assert(not coroutine.isyieldable())
168 return c .. c
169 end
170
171 local co = coroutine.wrap(function (c)
172 assert(coroutine.isyieldable())
173 local s = string.gsub("a", ".", f)
174 return s
175 end)
176 assert(co() == "aa")
177end
178
179
180-- errors in coroutines
181function foo ()
182 assert(debug.getinfo(1).currentline == debug.getinfo(foo).linedefined + 1)
183 assert(debug.getinfo(2).currentline == debug.getinfo(goo).linedefined)
184 coroutine.yield(3)
185 error(foo)
186end
187
188function goo() foo() end
189x = coroutine.wrap(goo)
190assert(x() == 3)
191local a,b = pcall(x)
192assert(not a and b == foo)
193
194x = coroutine.create(goo)
195a,b = coroutine.resume(x)
196assert(a and b == 3)
197a,b = coroutine.resume(x)
198assert(not a and b == foo and coroutine.status(x) == "dead")
199a,b = coroutine.resume(x)
200assert(not a and string.find(b, "dead") and coroutine.status(x) == "dead")
201
202
203-- co-routines x for loop
204function all (a, n, k)
205 if k == 0 then coroutine.yield(a)
206 else
207 for i=1,n do
208 a[k] = i
209 all(a, n, k-1)
210 end
211 end
212end
213
214local a = 0
215for t in coroutine.wrap(function () all({}, 5, 4) end) do
216 a = a+1
217end
218assert(a == 5^4)
219
220
221-- access to locals of collected corroutines
222local C = {}; setmetatable(C, {__mode = "kv"})
223local x = coroutine.wrap (function ()
224 local a = 10
225 local function f () a = a+10; return a end
226 while true do
227 a = a+1
228 coroutine.yield(f)
229 end
230 end)
231
232C[1] = x;
233
234local f = x()
235assert(f() == 21 and x()() == 32 and x() == f)
236x = nil
237collectgarbage()
238assert(C[1] == nil)
239assert(f() == 43 and f() == 53)
240
241
242-- old bug: attempt to resume itself
243
244function co_func (current_co)
245 assert(coroutine.running() == current_co)
246 assert(coroutine.resume(current_co) == false)
247 coroutine.yield(10, 20)
248 assert(coroutine.resume(current_co) == false)
249 coroutine.yield(23)
250 return 10
251end
252
253local co = coroutine.create(co_func)
254local a,b,c = coroutine.resume(co, co)
255assert(a == true and b == 10 and c == 20)
256a,b = coroutine.resume(co, co)
257assert(a == true and b == 23)
258a,b = coroutine.resume(co, co)
259assert(a == true and b == 10)
260assert(coroutine.resume(co, co) == false)
261assert(coroutine.resume(co, co) == false)
262
263
264-- other old bug when attempting to resume itself
265-- (trigger C-code assertions)
266do
267 local A = coroutine.running()
268 local B = coroutine.create(function() return coroutine.resume(A) end)
269 local st, res = coroutine.resume(B)
270 assert(st == true and res == false)
271
272 A = coroutine.wrap(function() return pcall(A, 1) end)
273 st, res = A()
274 assert(not st and string.find(res, "non%-suspended"))
275end
276
277
278-- attempt to resume 'normal' coroutine
279local co1, co2
280co1 = coroutine.create(function () return co2() end)
281co2 = coroutine.wrap(function ()
282 assert(coroutine.status(co1) == 'normal')
283 assert(not coroutine.resume(co1))
284 coroutine.yield(3)
285 end)
286
287a,b = coroutine.resume(co1)
288assert(a and b == 3)
289assert(coroutine.status(co1) == 'dead')
290
291-- infinite recursion of coroutines
292a = function(a) coroutine.wrap(a)(a) end
293assert(not pcall(a, a))
294a = nil
295
296
297-- access to locals of erroneous coroutines
298local x = coroutine.create (function ()
299 local a = 10
300 _G.f = function () a=a+1; return a end
301 error('x')
302 end)
303
304assert(not coroutine.resume(x))
305-- overwrite previous position of local `a'
306assert(not coroutine.resume(x, 1, 1, 1, 1, 1, 1, 1))
307assert(_G.f() == 11)
308assert(_G.f() == 12)
309
310
311if not T then
312 (Message or print)('\n >>> testC not active: skipping yield/hook tests <<<\n')
313else
314 print "testing yields inside hooks"
315
316 local turn
317
318 function fact (t, x)
319 assert(turn == t)
320 if x == 0 then return 1
321 else return x*fact(t, x-1)
322 end
323 end
324
325 local A, B = 0, 0
326
327 local x = coroutine.create(function ()
328 T.sethook("yield 0", "", 2)
329 A = fact("A", 6)
330 end)
331
332 local y = coroutine.create(function ()
333 T.sethook("yield 0", "", 3)
334 B = fact("B", 7)
335 end)
336
337 while A==0 or B==0 do -- A ~= 0 when 'x' finishes (similar for 'B','y')
338 if A==0 then turn = "A"; assert(T.resume(x)) end
339 if B==0 then turn = "B"; assert(T.resume(y)) end
340 end
341
342 assert(B // A == 7) -- fact(7) // fact(6)
343
344 local line = debug.getinfo(1, "l").currentline + 2 -- get line number
345 local function foo ()
346 local x = 10 --<< this line is 'line'
347 x = x + 10
348 _G.XX = x
349 end
350
351 -- testing yields in line hook
352 local co = coroutine.wrap(function ()
353 T.sethook("setglobal X; yield 0", "l", 0); foo(); return 10 end)
354
355 _G.XX = nil;
356 _G.X = nil; co(); assert(_G.X == line)
357 _G.X = nil; co(); assert(_G.X == line + 1)
358 _G.X = nil; co(); assert(_G.X == line + 2 and _G.XX == nil)
359 _G.X = nil; co(); assert(_G.X == line + 3 and _G.XX == 20)
360 assert(co() == 10)
361
362 -- testing yields in count hook
363 co = coroutine.wrap(function ()
364 T.sethook("yield 0", "", 1); foo(); return 10 end)
365
366 _G.XX = nil;
367 local c = 0
368 repeat c = c + 1; local a = co() until a == 10
369 assert(_G.XX == 20 and c >= 5)
370
371 co = coroutine.wrap(function ()
372 T.sethook("yield 0", "", 2); foo(); return 10 end)
373
374 _G.XX = nil;
375 local c = 0
376 repeat c = c + 1; local a = co() until a == 10
377 assert(_G.XX == 20 and c >= 5)
378 _G.X = nil; _G.XX = nil
379
380 do
381 -- testing debug library on a coroutine suspended inside a hook
382 -- (bug in 5.2/5.3)
383 c = coroutine.create(function (a, ...)
384 T.sethook("yield 0", "l") -- will yield on next two lines
385 assert(a == 10)
386 return ...
387 end)
388
389 assert(coroutine.resume(c, 1, 2, 3)) -- start coroutine
390 local n,v = debug.getlocal(c, 0, 1) -- check its local
391 assert(n == "a" and v == 1)
392 n,v = debug.getlocal(c, 0, -1) -- check varargs
393 assert(v == 2)
394 n,v = debug.getlocal(c, 0, -2)
395 assert(v == 3)
396 assert(debug.setlocal(c, 0, 1, 10)) -- test 'setlocal'
397 assert(debug.setlocal(c, 0, -2, 20))
398 local t = debug.getinfo(c, 0) -- test 'getinfo'
399 assert(t.currentline == t.linedefined + 1)
400 assert(not debug.getinfo(c, 1)) -- no other level
401 assert(coroutine.resume(c)) -- run next line
402 v = {coroutine.resume(c)} -- finish coroutine
403 assert(v[1] == true and v[2] == 2 and v[3] == 20 and v[4] == nil)
404 assert(not coroutine.resume(c))
405 end
406
407 do
408 -- testing debug library on last function in a suspended coroutine
409 -- (bug in 5.2/5.3)
410 local c = coroutine.create(function () T.testC("yield 1", 10, 20) end)
411 local a, b = coroutine.resume(c)
412 assert(a and b == 20)
413 assert(debug.getinfo(c, 0).linedefined == -1)
414 a, b = debug.getlocal(c, 0, 2)
415 assert(b == 10)
416 end
417
418
419 print "testing coroutine API"
420
421 -- reusing a thread
422 assert(T.testC([[
423 newthread # create thread
424 pushvalue 2 # push body
425 pushstring 'a a a' # push argument
426 xmove 0 3 2 # move values to new thread
427 resume -1, 1 # call it first time
428 pushstatus
429 xmove 3 0 0 # move results back to stack
430 setglobal X # result
431 setglobal Y # status
432 pushvalue 2 # push body (to call it again)
433 pushstring 'b b b'
434 xmove 0 3 2
435 resume -1, 1 # call it again
436 pushstatus
437 xmove 3 0 0
438 return 1 # return result
439 ]], function (...) return ... end) == 'b b b')
440
441 assert(X == 'a a a' and Y == 'OK')
442
443
444 -- resuming running coroutine
445 C = coroutine.create(function ()
446 return T.testC([[
447 pushnum 10;
448 pushnum 20;
449 resume -3 2;
450 pushstatus
451 gettop;
452 return 3]], C)
453 end)
454 local a, b, c, d = coroutine.resume(C)
455 assert(a == true and string.find(b, "non%-suspended") and
456 c == "ERRRUN" and d == 4)
457
458 a, b, c, d = T.testC([[
459 rawgeti R 1 # get main thread
460 pushnum 10;
461 pushnum 20;
462 resume -3 2;
463 pushstatus
464 gettop;
465 return 4]])
466 assert(a == coroutine.running() and string.find(b, "non%-suspended") and
467 c == "ERRRUN" and d == 4)
468
469
470 -- using a main thread as a coroutine
471 local state = T.newstate()
472 T.loadlib(state)
473
474 assert(T.doremote(state, [[
475 coroutine = require'coroutine';
476 X = function (x) coroutine.yield(x, 'BB'); return 'CC' end;
477 return 'ok']]))
478
479 t = table.pack(T.testC(state, [[
480 rawgeti R 1 # get main thread
481 pushstring 'XX'
482 getglobal X # get function for body
483 pushstring AA # arg
484 resume 1 1 # 'resume' shadows previous stack!
485 gettop
486 setglobal T # top
487 setglobal B # second yielded value
488 setglobal A # fist yielded value
489 rawgeti R 1 # get main thread
490 pushnum 5 # arg (noise)
491 resume 1 1 # after coroutine ends, previous stack is back
492 pushstatus
493 return *
494 ]]))
495 assert(t.n == 4 and t[2] == 'XX' and t[3] == 'CC' and t[4] == 'OK')
496 assert(T.doremote(state, "return T") == '2')
497 assert(T.doremote(state, "return A") == 'AA')
498 assert(T.doremote(state, "return B") == 'BB')
499
500 T.closestate(state)
501
502 print'+'
503
504end
505
506
507-- leaving a pending coroutine open
508_X = coroutine.wrap(function ()
509 local a = 10
510 local x = function () a = a+1 end
511 coroutine.yield()
512 end)
513
514_X()
515
516
517if not _soft then
518 -- bug (stack overflow)
519 local j = 2^9
520 local lim = 1000000 -- (C stack limit; assume 32-bit machine)
521 local t = {lim - 10, lim - 5, lim - 1, lim, lim + 1}
522 for i = 1, #t do
523 local j = t[i]
524 co = coroutine.create(function()
525 local t = {}
526 for i = 1, j do t[i] = i end
527 return table.unpack(t)
528 end)
529 local r, msg = coroutine.resume(co)
530 assert(not r)
531 end
532 co = nil
533end
534
535
536assert(coroutine.running() == main)
537
538print"+"
539
540
541print"testing yields inside metamethods"
542
543local mt = {
544 __eq = function(a,b) coroutine.yield(nil, "eq"); return a.x == b.x end,
545 __lt = function(a,b) coroutine.yield(nil, "lt"); return a.x < b.x end,
546 __le = function(a,b) coroutine.yield(nil, "le"); return a - b <= 0 end,
547 __add = function(a,b) coroutine.yield(nil, "add"); return a.x + b.x end,
548 __sub = function(a,b) coroutine.yield(nil, "sub"); return a.x - b.x end,
549 __mod = function(a,b) coroutine.yield(nil, "mod"); return a.x % b.x end,
550 __unm = function(a,b) coroutine.yield(nil, "unm"); return -a.x end,
551 __bnot = function(a,b) coroutine.yield(nil, "bnot"); return ~a.x end,
552 __shl = function(a,b) coroutine.yield(nil, "shl"); return a.x << b.x end,
553 __shr = function(a,b) coroutine.yield(nil, "shr"); return a.x >> b.x end,
554 __band = function(a,b)
555 a = type(a) == "table" and a.x or a
556 b = type(b) == "table" and b.x or b
557 coroutine.yield(nil, "band")
558 return a & b
559 end,
560 __bor = function(a,b) coroutine.yield(nil, "bor"); return a.x | b.x end,
561 __bxor = function(a,b) coroutine.yield(nil, "bxor"); return a.x ~ b.x end,
562
563 __concat = function(a,b)
564 coroutine.yield(nil, "concat");
565 a = type(a) == "table" and a.x or a
566 b = type(b) == "table" and b.x or b
567 return a .. b
568 end,
569 __index = function (t,k) coroutine.yield(nil, "idx"); return t.k[k] end,
570 __newindex = function (t,k,v) coroutine.yield(nil, "nidx"); t.k[k] = v end,
571}
572
573
574local function new (x)
575 return setmetatable({x = x, k = {}}, mt)
576end
577
578
579local a = new(10)
580local b = new(12)
581local c = new"hello"
582
583local function run (f, t)
584 local i = 1
585 local c = coroutine.wrap(f)
586 while true do
587 local res, stat = c()
588 if res then assert(t[i] == nil); return res, t end
589 assert(stat == t[i])
590 i = i + 1
591 end
592end
593
594
595assert(run(function () if (a>=b) then return '>=' else return '<' end end,
596 {"le", "sub"}) == "<")
597-- '<=' using '<'
598mt.__le = nil
599assert(run(function () if (a<=b) then return '<=' else return '>' end end,
600 {"lt"}) == "<=")
601assert(run(function () if (a==b) then return '==' else return '~=' end end,
602 {"eq"}) == "~=")
603
604assert(run(function () return a & b + a end, {"add", "band"}) == 2)
605
606assert(run(function () return a % b end, {"mod"}) == 10)
607
608assert(run(function () return ~a & b end, {"bnot", "band"}) == ~10 & 12)
609assert(run(function () return a | b end, {"bor"}) == 10 | 12)
610assert(run(function () return a ~ b end, {"bxor"}) == 10 ~ 12)
611assert(run(function () return a << b end, {"shl"}) == 10 << 12)
612assert(run(function () return a >> b end, {"shr"}) == 10 >> 12)
613
614assert(run(function () return a..b end, {"concat"}) == "1012")
615
616assert(run(function() return a .. b .. c .. a end,
617 {"concat", "concat", "concat"}) == "1012hello10")
618
619assert(run(function() return "a" .. "b" .. a .. "c" .. c .. b .. "x" end,
620 {"concat", "concat", "concat"}) == "ab10chello12x")
621
622
623do -- a few more tests for comparsion operators
624 local mt1 = {
625 __le = function (a,b)
626 coroutine.yield(10)
627 return
628 (type(a) == "table" and a.x or a) <= (type(b) == "table" and b.x or b)
629 end,
630 __lt = function (a,b)
631 coroutine.yield(10)
632 return
633 (type(a) == "table" and a.x or a) < (type(b) == "table" and b.x or b)
634 end,
635 }
636 local mt2 = { __lt = mt1.__lt } -- no __le
637
638 local function run (f)
639 local co = coroutine.wrap(f)
640 local res
641 repeat
642 res = co()
643 until res ~= 10
644 return res
645 end
646
647 local function test ()
648 local a1 = setmetatable({x=1}, mt1)
649 local a2 = setmetatable({x=2}, mt2)
650 assert(a1 < a2)
651 assert(a1 <= a2)
652 assert(1 < a2)
653 assert(1 <= a2)
654 assert(2 > a1)
655 assert(2 >= a2)
656 return true
657 end
658
659 run(test)
660
661end
662
663assert(run(function ()
664 a.BB = print
665 return a.BB
666 end, {"nidx", "idx"}) == print)
667
668-- getuptable & setuptable
669do local _ENV = _ENV
670 f = function () AAA = BBB + 1; return AAA end
671end
672g = new(10); g.k.BBB = 10;
673debug.setupvalue(f, 1, g)
674assert(run(f, {"idx", "nidx", "idx"}) == 11)
675assert(g.k.AAA == 11)
676
677print"+"
678
679print"testing yields inside 'for' iterators"
680
681local f = function (s, i)
682 if i%2 == 0 then coroutine.yield(nil, "for") end
683 if i < s then return i + 1 end
684 end
685
686assert(run(function ()
687 local s = 0
688 for i in f, 4, 0 do s = s + i end
689 return s
690 end, {"for", "for", "for"}) == 10)
691
692
693
694-- tests for coroutine API
695if T==nil then
696 (Message or print)('\n >>> testC not active: skipping coroutine API tests <<<\n')
697 return
698end
699
700print('testing coroutine API')
701
702local function apico (...)
703 local x = {...}
704 return coroutine.wrap(function ()
705 return T.testC(table.unpack(x))
706 end)
707end
708
709local a = {apico(
710[[
711 pushstring errorcode
712 pcallk 1 0 2;
713 invalid command (should not arrive here)
714]],
715[[return *]],
716"stackmark",
717error
718)()}
719assert(#a == 4 and
720 a[3] == "stackmark" and
721 a[4] == "errorcode" and
722 _G.status == "ERRRUN" and
723 _G.ctx == 2) -- 'ctx' to pcallk
724
725local co = apico(
726 "pushvalue 2; pushnum 10; pcallk 1 2 3; invalid command;",
727 coroutine.yield,
728 "getglobal status; getglobal ctx; pushvalue 2; pushstring a; pcallk 1 0 4; invalid command",
729 "getglobal status; getglobal ctx; return *")
730
731assert(co() == 10)
732assert(co(20, 30) == 'a')
733a = {co()}
734assert(#a == 10 and
735 a[2] == coroutine.yield and
736 a[5] == 20 and a[6] == 30 and
737 a[7] == "YIELD" and a[8] == 3 and
738 a[9] == "YIELD" and a[10] == 4)
739assert(not pcall(co)) -- coroutine is dead now
740
741
742f = T.makeCfunc("pushnum 3; pushnum 5; yield 1;")
743co = coroutine.wrap(function ()
744 assert(f() == 23); assert(f() == 23); return 10
745end)
746assert(co(23,16) == 5)
747assert(co(23,16) == 5)
748assert(co(23,16) == 10)
749
750
751-- testing coroutines with C bodies
752f = T.makeCfunc([[
753 pushnum 102
754 yieldk 1 U2
755 cannot be here!
756]],
757[[ # continuation
758 pushvalue U3 # accessing upvalues inside a continuation
759 pushvalue U4
760 return *
761]], 23, "huu")
762
763x = coroutine.wrap(f)
764assert(x() == 102)
765eqtab({x()}, {23, "huu"})
766
767
768f = T.makeCfunc[[pushstring 'a'; pushnum 102; yield 2; ]]
769
770a, b, c, d = T.testC([[newthread; pushvalue 2; xmove 0 3 1; resume 3 0;
771 pushstatus; xmove 3 0 0; resume 3 0; pushstatus;
772 return 4; ]], f)
773
774assert(a == 'YIELD' and b == 'a' and c == 102 and d == 'OK')
775
776
777-- testing chain of suspendable C calls
778
779local count = 3 -- number of levels
780
781f = T.makeCfunc([[
782 remove 1; # remove argument
783 pushvalue U3; # get selection function
784 call 0 1; # call it (result is 'f' or 'yield')
785 pushstring hello # single argument for selected function
786 pushupvalueindex 2; # index of continuation program
787 callk 1 -1 .; # call selected function
788 errorerror # should never arrive here
789]],
790[[
791 # continuation program
792 pushnum 34 # return value
793 return * # return all results
794]],
795function () -- selection function
796 count = count - 1
797 if count == 0 then return coroutine.yield
798 else return f
799 end
800end
801)
802
803co = coroutine.wrap(function () return f(nil) end)
804assert(co() == "hello") -- argument to 'yield'
805a = {co()}
806-- three '34's (one from each pending C call)
807assert(#a == 3 and a[1] == a[2] and a[2] == a[3] and a[3] == 34)
808
809
810-- testing yields with continuations
811
812co = coroutine.wrap(function (...) return
813 T.testC([[ # initial function
814 yieldk 1 2
815 cannot be here!
816 ]],
817 [[ # 1st continuation
818 yieldk 0 3
819 cannot be here!
820 ]],
821 [[ # 2nd continuation
822 yieldk 0 4
823 cannot be here!
824 ]],
825 [[ # 3th continuation
826 pushvalue 6 # function which is last arg. to 'testC' here
827 pushnum 10; pushnum 20;
828 pcall 2 0 0 # call should throw an error and return to next line
829 pop 1 # remove error message
830 pushvalue 6
831 getglobal status; getglobal ctx
832 pcallk 2 2 5 # call should throw an error and jump to continuation
833 cannot be here!
834 ]],
835 [[ # 4th (and last) continuation
836 return *
837 ]],
838 -- function called by 3th continuation
839 function (a,b) x=a; y=b; error("errmsg") end,
840 ...
841)
842end)
843
844local a = {co(3,4,6)}
845assert(a[1] == 6 and a[2] == nil)
846a = {co()}; assert(a[1] == nil and _G.status == "YIELD" and _G.ctx == 2)
847a = {co()}; assert(a[1] == nil and _G.status == "YIELD" and _G.ctx == 3)
848a = {co(7,8)};
849-- original arguments
850assert(type(a[1]) == 'string' and type(a[2]) == 'string' and
851 type(a[3]) == 'string' and type(a[4]) == 'string' and
852 type(a[5]) == 'string' and type(a[6]) == 'function')
853-- arguments left from fist resume
854assert(a[7] == 3 and a[8] == 4)
855-- arguments to last resume
856assert(a[9] == 7 and a[10] == 8)
857-- error message and nothing more
858assert(a[11]:find("errmsg") and #a == 11)
859-- check arguments to pcallk
860assert(x == "YIELD" and y == 4)
861
862assert(not pcall(co)) -- coroutine should be dead
863
864
865-- bug in nCcalls
866local co = coroutine.wrap(function ()
867 local a = {pcall(pcall,pcall,pcall,pcall,pcall,pcall,pcall,error,"hi")}
868 return pcall(assert, table.unpack(a))
869end)
870
871local a = {co()}
872assert(a[10] == "hi")
873
874print'OK'
diff --git a/testes/db.lua b/testes/db.lua
new file mode 100644
index 00000000..004f57a7
--- /dev/null
+++ b/testes/db.lua
@@ -0,0 +1,857 @@
1-- $Id: db.lua,v 1.79 2016/11/07 13:02:34 roberto Exp $
2-- See Copyright Notice in file all.lua
3
4-- testing debug library
5
6local debug = require "debug"
7
8local function dostring(s) return assert(load(s))() end
9
10print"testing debug library and debug information"
11
12do
13local a=1
14end
15
16assert(not debug.gethook())
17
18local testline = 19 -- line where 'test' is defined
19function test (s, l, p) -- this must be line 19
20 collectgarbage() -- avoid gc during trace
21 local function f (event, line)
22 assert(event == 'line')
23 local l = table.remove(l, 1)
24 if p then print(l, line) end
25 assert(l == line, "wrong trace!!")
26 end
27 debug.sethook(f,"l"); load(s)(); debug.sethook()
28 assert(#l == 0)
29end
30
31
32do
33 assert(not pcall(debug.getinfo, print, "X")) -- invalid option
34 assert(not debug.getinfo(1000)) -- out of range level
35 assert(not debug.getinfo(-1)) -- out of range level
36 local a = debug.getinfo(print)
37 assert(a.what == "C" and a.short_src == "[C]")
38 a = debug.getinfo(print, "L")
39 assert(a.activelines == nil)
40 local b = debug.getinfo(test, "SfL")
41 assert(b.name == nil and b.what == "Lua" and b.linedefined == testline and
42 b.lastlinedefined == b.linedefined + 10 and
43 b.func == test and not string.find(b.short_src, "%["))
44 assert(b.activelines[b.linedefined + 1] and
45 b.activelines[b.lastlinedefined])
46 assert(not b.activelines[b.linedefined] and
47 not b.activelines[b.lastlinedefined + 1])
48end
49
50
51-- test file and string names truncation
52a = "function f () end"
53local function dostring (s, x) return load(s, x)() end
54dostring(a)
55assert(debug.getinfo(f).short_src == string.format('[string "%s"]', a))
56dostring(a..string.format("; %s\n=1", string.rep('p', 400)))
57assert(string.find(debug.getinfo(f).short_src, '^%[string [^\n]*%.%.%."%]$'))
58dostring(a..string.format("; %s=1", string.rep('p', 400)))
59assert(string.find(debug.getinfo(f).short_src, '^%[string [^\n]*%.%.%."%]$'))
60dostring("\n"..a)
61assert(debug.getinfo(f).short_src == '[string "..."]')
62dostring(a, "")
63assert(debug.getinfo(f).short_src == '[string ""]')
64dostring(a, "@xuxu")
65assert(debug.getinfo(f).short_src == "xuxu")
66dostring(a, "@"..string.rep('p', 1000)..'t')
67assert(string.find(debug.getinfo(f).short_src, "^%.%.%.p*t$"))
68dostring(a, "=xuxu")
69assert(debug.getinfo(f).short_src == "xuxu")
70dostring(a, string.format("=%s", string.rep('x', 500)))
71assert(string.find(debug.getinfo(f).short_src, "^x*$"))
72dostring(a, "=")
73assert(debug.getinfo(f).short_src == "")
74a = nil; f = nil;
75
76
77repeat
78 local g = {x = function ()
79 local a = debug.getinfo(2)
80 assert(a.name == 'f' and a.namewhat == 'local')
81 a = debug.getinfo(1)
82 assert(a.name == 'x' and a.namewhat == 'field')
83 return 'xixi'
84 end}
85 local f = function () return 1+1 and (not 1 or g.x()) end
86 assert(f() == 'xixi')
87 g = debug.getinfo(f)
88 assert(g.what == "Lua" and g.func == f and g.namewhat == "" and not g.name)
89
90 function f (x, name) -- local!
91 name = name or 'f'
92 local a = debug.getinfo(1)
93 assert(a.name == name and a.namewhat == 'local')
94 return x
95 end
96
97 -- breaks in different conditions
98 if 3>4 then break end; f()
99 if 3<4 then a=1 else break end; f()
100 while 1 do local x=10; break end; f()
101 local b = 1
102 if 3>4 then return math.sin(1) end; f()
103 a = 3<4; f()
104 a = 3<4 or 1; f()
105 repeat local x=20; if 4>3 then f() else break end; f() until 1
106 g = {}
107 f(g).x = f(2) and f(10)+f(9)
108 assert(g.x == f(19))
109 function g(x) if not x then return 3 end return (x('a', 'x')) end
110 assert(g(f) == 'a')
111until 1
112
113test([[if
114math.sin(1)
115then
116 a=1
117else
118 a=2
119end
120]], {2,3,4,7})
121
122test([[--
123if nil then
124 a=1
125else
126 a=2
127end
128]], {2,5,6})
129
130test([[a=1
131repeat
132 a=a+1
133until a==3
134]], {1,3,4,3,4})
135
136test([[ do
137 return
138end
139]], {2})
140
141test([[local a
142a=1
143while a<=3 do
144 a=a+1
145end
146]], {1,2,3,4,3,4,3,4,3,5})
147
148test([[while math.sin(1) do
149 if math.sin(1)
150 then break
151 end
152end
153a=1]], {1,2,3,6})
154
155test([[for i=1,3 do
156 a=i
157end
158]], {1,2,1,2,1,2,1,3})
159
160test([[for i,v in pairs{'a','b'} do
161 a=tostring(i) .. v
162end
163]], {1,2,1,2,1,3})
164
165test([[for i=1,4 do a=1 end]], {1,1,1,1,1})
166
167
168
169print'+'
170
171-- invalid levels in [gs]etlocal
172assert(not pcall(debug.getlocal, 20, 1))
173assert(not pcall(debug.setlocal, -1, 1, 10))
174
175
176-- parameter names
177local function foo (a,b,...) local d, e end
178local co = coroutine.create(foo)
179
180assert(debug.getlocal(foo, 1) == 'a')
181assert(debug.getlocal(foo, 2) == 'b')
182assert(not debug.getlocal(foo, 3))
183assert(debug.getlocal(co, foo, 1) == 'a')
184assert(debug.getlocal(co, foo, 2) == 'b')
185assert(not debug.getlocal(co, foo, 3))
186
187assert(not debug.getlocal(print, 1))
188
189
190-- varargs
191local function foo (a, ...)
192 local t = table.pack(...)
193 for i = 1, t.n do
194 local n, v = debug.getlocal(1, -i)
195 assert(n == "(*vararg)" and v == t[i])
196 end
197 assert(not debug.getlocal(1, -(t.n + 1)))
198 assert(not debug.setlocal(1, -(t.n + 1), 30))
199 if t.n > 0 then
200 (function (x)
201 assert(debug.setlocal(2, -1, x) == "(*vararg)")
202 assert(debug.setlocal(2, -t.n, x) == "(*vararg)")
203 end)(430)
204 assert(... == 430)
205 end
206end
207
208foo()
209foo(print)
210foo(200, 3, 4)
211local a = {}
212for i = 1, (_soft and 100 or 1000) do a[i] = i end
213foo(table.unpack(a))
214a = nil
215
216-- access to vararg in non-vararg function
217local function foo () return debug.getlocal(1, -1) end
218assert(not foo(10))
219
220
221do -- test hook presence in debug info
222 assert(not debug.gethook())
223 local count = 0
224 local function f ()
225 assert(debug.getinfo(1).namewhat == "hook")
226 local sndline = string.match(debug.traceback(), "\n(.-)\n")
227 assert(string.find(sndline, "hook"))
228 count = count + 1
229 end
230 debug.sethook(f, "l")
231 local a = 0
232 _ENV.a = a
233 a = 1
234 debug.sethook()
235 assert(count == 4)
236end
237
238
239a = {}; L = nil
240local glob = 1
241local oldglob = glob
242debug.sethook(function (e,l)
243 collectgarbage() -- force GC during a hook
244 local f, m, c = debug.gethook()
245 assert(m == 'crl' and c == 0)
246 if e == "line" then
247 if glob ~= oldglob then
248 L = l-1 -- get the first line where "glob" has changed
249 oldglob = glob
250 end
251 elseif e == "call" then
252 local f = debug.getinfo(2, "f").func
253 a[f] = 1
254 else assert(e == "return")
255 end
256end, "crl")
257
258
259function f(a,b)
260 collectgarbage()
261 local _, x = debug.getlocal(1, 1)
262 local _, y = debug.getlocal(1, 2)
263 assert(x == a and y == b)
264 assert(debug.setlocal(2, 3, "pera") == "AA".."AA")
265 assert(debug.setlocal(2, 4, "maçã") == "B")
266 x = debug.getinfo(2)
267 assert(x.func == g and x.what == "Lua" and x.name == 'g' and
268 x.nups == 2 and string.find(x.source, "^@.*db%.lua$"))
269 glob = glob+1
270 assert(debug.getinfo(1, "l").currentline == L+1)
271 assert(debug.getinfo(1, "l").currentline == L+2)
272end
273
274function foo()
275 glob = glob+1
276 assert(debug.getinfo(1, "l").currentline == L+1)
277end; foo() -- set L
278-- check line counting inside strings and empty lines
279
280_ = 'alo\
281alo' .. [[
282
283]]
284--[[
285]]
286assert(debug.getinfo(1, "l").currentline == L+11) -- check count of lines
287
288
289function g(...)
290 local arg = {...}
291 do local a,b,c; a=math.sin(40); end
292 local feijao
293 local AAAA,B = "xuxu", "mamão"
294 f(AAAA,B)
295 assert(AAAA == "pera" and B == "maçã")
296 do
297 local B = 13
298 local x,y = debug.getlocal(1,5)
299 assert(x == 'B' and y == 13)
300 end
301end
302
303g()
304
305
306assert(a[f] and a[g] and a[assert] and a[debug.getlocal] and not a[print])
307
308
309-- tests for manipulating non-registered locals (C and Lua temporaries)
310
311local n, v = debug.getlocal(0, 1)
312assert(v == 0 and n == "(*temporary)")
313local n, v = debug.getlocal(0, 2)
314assert(v == 2 and n == "(*temporary)")
315assert(not debug.getlocal(0, 3))
316assert(not debug.getlocal(0, 0))
317
318function f()
319 assert(select(2, debug.getlocal(2,3)) == 1)
320 assert(not debug.getlocal(2,4))
321 debug.setlocal(2, 3, 10)
322 return 20
323end
324
325function g(a,b) return (a+1) + f() end
326
327assert(g(0,0) == 30)
328
329
330debug.sethook(nil);
331assert(debug.gethook() == nil)
332
333
334-- testing access to function arguments
335
336local function collectlocals (level)
337 local tab = {}
338 for i = 1, math.huge do
339 local n, v = debug.getlocal(level + 1, i)
340 if not (n and string.find(n, "^[a-zA-Z0-9_]+$")) then
341 break -- consider only real variables
342 end
343 tab[n] = v
344 end
345 return tab
346end
347
348
349X = nil
350a = {}
351function a:f (a, b, ...) local arg = {...}; local c = 13 end
352debug.sethook(function (e)
353 assert(e == "call")
354 dostring("XX = 12") -- test dostring inside hooks
355 -- testing errors inside hooks
356 assert(not pcall(load("a='joao'+1")))
357 debug.sethook(function (e, l)
358 assert(debug.getinfo(2, "l").currentline == l)
359 local f,m,c = debug.gethook()
360 assert(e == "line")
361 assert(m == 'l' and c == 0)
362 debug.sethook(nil) -- hook is called only once
363 assert(not X) -- check that
364 X = collectlocals(2)
365 end, "l")
366end, "c")
367
368a:f(1,2,3,4,5)
369assert(X.self == a and X.a == 1 and X.b == 2 and X.c == nil)
370assert(XX == 12)
371assert(debug.gethook() == nil)
372
373
374-- testing access to local variables in return hook (bug in 5.2)
375do
376 local function foo (a, b)
377 do local x,y,z end
378 local c, d = 10, 20
379 return
380 end
381
382 local function aux ()
383 if debug.getinfo(2).name == "foo" then
384 foo = nil -- to signal that it found 'foo'
385 local tab = {a = 100, b = 200, c = 10, d = 20}
386 for n, v in pairs(collectlocals(2)) do
387 assert(tab[n] == v)
388 tab[n] = nil
389 end
390 assert(next(tab) == nil) -- 'tab' must be empty
391 end
392 end
393
394 debug.sethook(aux, "r"); foo(100, 200); debug.sethook()
395 assert(foo == nil)
396end
397
398-- testing upvalue access
399local function getupvalues (f)
400 local t = {}
401 local i = 1
402 while true do
403 local name, value = debug.getupvalue(f, i)
404 if not name then break end
405 assert(not t[name])
406 t[name] = value
407 i = i + 1
408 end
409 return t
410end
411
412local a,b,c = 1,2,3
413local function foo1 (a) b = a; return c end
414local function foo2 (x) a = x; return c+b end
415assert(not debug.getupvalue(foo1, 3))
416assert(not debug.getupvalue(foo1, 0))
417assert(not debug.setupvalue(foo1, 3, "xuxu"))
418local t = getupvalues(foo1)
419assert(t.a == nil and t.b == 2 and t.c == 3)
420t = getupvalues(foo2)
421assert(t.a == 1 and t.b == 2 and t.c == 3)
422assert(debug.setupvalue(foo1, 1, "xuxu") == "b")
423assert(({debug.getupvalue(foo2, 3)})[2] == "xuxu")
424-- upvalues of C functions are allways "called" "" (the empty string)
425assert(debug.getupvalue(string.gmatch("x", "x"), 1) == "")
426
427
428-- testing count hooks
429local a=0
430debug.sethook(function (e) a=a+1 end, "", 1)
431a=0; for i=1,1000 do end; assert(1000 < a and a < 1012)
432debug.sethook(function (e) a=a+1 end, "", 4)
433a=0; for i=1,1000 do end; assert(250 < a and a < 255)
434local f,m,c = debug.gethook()
435assert(m == "" and c == 4)
436debug.sethook(function (e) a=a+1 end, "", 4000)
437a=0; for i=1,1000 do end; assert(a == 0)
438
439do
440 debug.sethook(print, "", 2^24 - 1) -- count upperbound
441 local f,m,c = debug.gethook()
442 assert(({debug.gethook()})[3] == 2^24 - 1)
443end
444
445debug.sethook()
446
447
448-- tests for tail calls
449local function f (x)
450 if x then
451 assert(debug.getinfo(1, "S").what == "Lua")
452 assert(debug.getinfo(1, "t").istailcall == true)
453 local tail = debug.getinfo(2)
454 assert(tail.func == g1 and tail.istailcall == true)
455 assert(debug.getinfo(3, "S").what == "main")
456 print"+"
457 end
458end
459
460function g(x) return f(x) end
461
462function g1(x) g(x) end
463
464local function h (x) local f=g1; return f(x) end
465
466h(true)
467
468local b = {}
469debug.sethook(function (e) table.insert(b, e) end, "cr")
470h(false)
471debug.sethook()
472local res = {"return", -- first return (from sethook)
473 "call", "tail call", "call", "tail call",
474 "return", "return",
475 "call", -- last call (to sethook)
476}
477for i = 1, #res do assert(res[i] == table.remove(b, 1)) end
478
479b = 0
480debug.sethook(function (e)
481 if e == "tail call" then
482 b = b + 1
483 assert(debug.getinfo(2, "t").istailcall == true)
484 else
485 assert(debug.getinfo(2, "t").istailcall == false)
486 end
487 end, "c")
488h(false)
489debug.sethook()
490assert(b == 2) -- two tail calls
491
492lim = _soft and 3000 or 30000
493local function foo (x)
494 if x==0 then
495 assert(debug.getinfo(2).what == "main")
496 local info = debug.getinfo(1)
497 assert(info.istailcall == true and info.func == foo)
498 else return foo(x-1)
499 end
500end
501
502foo(lim)
503
504
505print"+"
506
507
508-- testing local function information
509co = load[[
510 local A = function ()
511 return x
512 end
513 return
514]]
515
516local a = 0
517-- 'A' should be visible to debugger only after its complete definition
518debug.sethook(function (e, l)
519 if l == 3 then a = a + 1; assert(debug.getlocal(2, 1) == "(*temporary)")
520 elseif l == 4 then a = a + 1; assert(debug.getlocal(2, 1) == "A")
521 end
522end, "l")
523co() -- run local function definition
524debug.sethook() -- turn off hook
525assert(a == 2) -- ensure all two lines where hooked
526
527-- testing traceback
528
529assert(debug.traceback(print) == print)
530assert(debug.traceback(print, 4) == print)
531assert(string.find(debug.traceback("hi", 4), "^hi\n"))
532assert(string.find(debug.traceback("hi"), "^hi\n"))
533assert(not string.find(debug.traceback("hi"), "'debug.traceback'"))
534assert(string.find(debug.traceback("hi", 0), "'debug.traceback'"))
535assert(string.find(debug.traceback(), "^stack traceback:\n"))
536
537do -- C-function names in traceback
538 local st, msg = (function () return pcall end)()(debug.traceback)
539 assert(st == true and string.find(msg, "pcall"))
540end
541
542
543-- testing nparams, nups e isvararg
544local t = debug.getinfo(print, "u")
545assert(t.isvararg == true and t.nparams == 0 and t.nups == 0)
546
547t = debug.getinfo(function (a,b,c) end, "u")
548assert(t.isvararg == false and t.nparams == 3 and t.nups == 0)
549
550t = debug.getinfo(function (a,b,...) return t[a] end, "u")
551assert(t.isvararg == true and t.nparams == 2 and t.nups == 1)
552
553t = debug.getinfo(1) -- main
554assert(t.isvararg == true and t.nparams == 0 and t.nups == 1 and
555 debug.getupvalue(t.func, 1) == "_ENV")
556
557
558
559
560-- testing debugging of coroutines
561
562local function checktraceback (co, p, level)
563 local tb = debug.traceback(co, nil, level)
564 local i = 0
565 for l in string.gmatch(tb, "[^\n]+\n?") do
566 assert(i == 0 or string.find(l, p[i]))
567 i = i+1
568 end
569 assert(p[i] == nil)
570end
571
572
573local function f (n)
574 if n > 0 then f(n-1)
575 else coroutine.yield() end
576end
577
578local co = coroutine.create(f)
579coroutine.resume(co, 3)
580checktraceback(co, {"yield", "db.lua", "db.lua", "db.lua", "db.lua"})
581checktraceback(co, {"db.lua", "db.lua", "db.lua", "db.lua"}, 1)
582checktraceback(co, {"db.lua", "db.lua", "db.lua"}, 2)
583checktraceback(co, {"db.lua"}, 4)
584checktraceback(co, {}, 40)
585
586
587co = coroutine.create(function (x)
588 local a = 1
589 coroutine.yield(debug.getinfo(1, "l"))
590 coroutine.yield(debug.getinfo(1, "l").currentline)
591 return a
592 end)
593
594local tr = {}
595local foo = function (e, l) if l then table.insert(tr, l) end end
596debug.sethook(co, foo, "lcr")
597
598local _, l = coroutine.resume(co, 10)
599local x = debug.getinfo(co, 1, "lfLS")
600assert(x.currentline == l.currentline and x.activelines[x.currentline])
601assert(type(x.func) == "function")
602for i=x.linedefined + 1, x.lastlinedefined do
603 assert(x.activelines[i])
604 x.activelines[i] = nil
605end
606assert(next(x.activelines) == nil) -- no 'extra' elements
607assert(not debug.getinfo(co, 2))
608local a,b = debug.getlocal(co, 1, 1)
609assert(a == "x" and b == 10)
610a,b = debug.getlocal(co, 1, 2)
611assert(a == "a" and b == 1)
612debug.setlocal(co, 1, 2, "hi")
613assert(debug.gethook(co) == foo)
614assert(#tr == 2 and
615 tr[1] == l.currentline-1 and tr[2] == l.currentline)
616
617a,b,c = pcall(coroutine.resume, co)
618assert(a and b and c == l.currentline+1)
619checktraceback(co, {"yield", "in function <"})
620
621a,b = coroutine.resume(co)
622assert(a and b == "hi")
623assert(#tr == 4 and tr[4] == l.currentline+2)
624assert(debug.gethook(co) == foo)
625assert(not debug.gethook())
626checktraceback(co, {})
627
628
629-- check get/setlocal in coroutines
630co = coroutine.create(function (x)
631 local a, b = coroutine.yield(x)
632 assert(a == 100 and b == nil)
633 return x
634end)
635a, b = coroutine.resume(co, 10)
636assert(a and b == 10)
637a, b = debug.getlocal(co, 1, 1)
638assert(a == "x" and b == 10)
639assert(not debug.getlocal(co, 1, 5))
640assert(debug.setlocal(co, 1, 1, 30) == "x")
641assert(not debug.setlocal(co, 1, 5, 40))
642a, b = coroutine.resume(co, 100)
643assert(a and b == 30)
644
645
646-- check traceback of suspended (or dead with error) coroutines
647
648function f(i) if i==0 then error(i) else coroutine.yield(); f(i-1) end end
649
650co = coroutine.create(function (x) f(x) end)
651a, b = coroutine.resume(co, 3)
652t = {"'coroutine.yield'", "'f'", "in function <"}
653while coroutine.status(co) == "suspended" do
654 checktraceback(co, t)
655 a, b = coroutine.resume(co)
656 table.insert(t, 2, "'f'") -- one more recursive call to 'f'
657end
658t[1] = "'error'"
659checktraceback(co, t)
660
661
662-- test acessing line numbers of a coroutine from a resume inside
663-- a C function (this is a known bug in Lua 5.0)
664
665local function g(x)
666 coroutine.yield(x)
667end
668
669local function f (i)
670 debug.sethook(function () end, "l")
671 for j=1,1000 do
672 g(i+j)
673 end
674end
675
676local co = coroutine.wrap(f)
677co(10)
678pcall(co)
679pcall(co)
680
681
682assert(type(debug.getregistry()) == "table")
683
684
685-- test tagmethod information
686local a = {}
687local function f (t)
688 local info = debug.getinfo(1);
689 assert(info.namewhat == "metamethod")
690 a.op = info.name
691 return info.name
692end
693setmetatable(a, {
694 __index = f; __add = f; __div = f; __mod = f; __concat = f; __pow = f;
695 __mul = f; __idiv = f; __unm = f; __len = f; __sub = f;
696 __shl = f; __shr = f; __bor = f; __bxor = f;
697 __eq = f; __le = f; __lt = f; __unm = f; __len = f; __band = f;
698 __bnot = f;
699})
700
701local b = setmetatable({}, getmetatable(a))
702
703assert(a[3] == "__index" and a^3 == "__pow" and a..a == "__concat")
704assert(a/3 == "__div" and 3%a == "__mod")
705assert(a+3 == "__add" and 3-a == "__sub" and a*3 == "__mul" and
706 -a == "__unm" and #a == "__len" and a&3 == "__band")
707assert(a|3 == "__bor" and 3~a == "__bxor" and a<<3 == "__shl" and
708 a>>1 == "__shr")
709assert (a==b and a.op == "__eq")
710assert (a>=b and a.op == "__le")
711assert (a>b and a.op == "__lt")
712assert(~a == "__bnot")
713
714do -- testing for-iterator name
715 local function f()
716 assert(debug.getinfo(1).name == "for iterator")
717 end
718
719 for i in f do end
720end
721
722
723do -- testing debug info for finalizers
724 local name = nil
725
726 -- create a piece of garbage with a finalizer
727 setmetatable({}, {__gc = function ()
728 local t = debug.getinfo(2) -- get callee information
729 assert(t.namewhat == "metamethod")
730 name = t.name
731 end})
732
733 -- repeat until previous finalizer runs (setting 'name')
734 repeat local a = {} until name
735 assert(name == "__gc")
736end
737
738
739do
740 print("testing traceback sizes")
741
742 local function countlines (s)
743 return select(2, string.gsub(s, "\n", ""))
744 end
745
746 local function deep (lvl, n)
747 if lvl == 0 then
748 return (debug.traceback("message", n))
749 else
750 return (deep(lvl-1, n))
751 end
752 end
753
754 local function checkdeep (total, start)
755 local s = deep(total, start)
756 local rest = string.match(s, "^message\nstack traceback:\n(.*)$")
757 local cl = countlines(rest)
758 -- at most 10 lines in first part, 11 in second, plus '...'
759 assert(cl <= 10 + 11 + 1)
760 local brk = string.find(rest, "%.%.%.")
761 if brk then -- does message have '...'?
762 local rest1 = string.sub(rest, 1, brk)
763 local rest2 = string.sub(rest, brk, #rest)
764 assert(countlines(rest1) == 10 and countlines(rest2) == 11)
765 else
766 assert(cl == total - start + 2)
767 end
768 end
769
770 for d = 1, 51, 10 do
771 for l = 1, d do
772 -- use coroutines to ensure complete control of the stack
773 coroutine.wrap(checkdeep)(d, l)
774 end
775 end
776
777end
778
779
780print("testing debug functions on chunk without debug info")
781prog = [[-- program to be loaded without debug information
782local debug = require'debug'
783local a = 12 -- a local variable
784
785local n, v = debug.getlocal(1, 1)
786assert(n == "(*temporary)" and v == debug) -- unkown name but known value
787n, v = debug.getlocal(1, 2)
788assert(n == "(*temporary)" and v == 12) -- unkown name but known value
789
790-- a function with an upvalue
791local f = function () local x; return a end
792n, v = debug.getupvalue(f, 1)
793assert(n == "(*no name)" and v == 12)
794assert(debug.setupvalue(f, 1, 13) == "(*no name)")
795assert(a == 13)
796
797local t = debug.getinfo(f)
798assert(t.name == nil and t.linedefined > 0 and
799 t.lastlinedefined == t.linedefined and
800 t.short_src == "?")
801assert(debug.getinfo(1).currentline == -1)
802
803t = debug.getinfo(f, "L").activelines
804assert(next(t) == nil) -- active lines are empty
805
806-- dump/load a function without debug info
807f = load(string.dump(f))
808
809t = debug.getinfo(f)
810assert(t.name == nil and t.linedefined > 0 and
811 t.lastlinedefined == t.linedefined and
812 t.short_src == "?")
813assert(debug.getinfo(1).currentline == -1)
814
815return a
816]]
817
818
819-- load 'prog' without debug info
820local f = assert(load(string.dump(load(prog), true)))
821
822assert(f() == 13)
823
824do -- tests for 'source' in binary dumps
825 local prog = [[
826 return function (x)
827 return function (y)
828 return x + y
829 end
830 end
831 ]]
832 local name = string.rep("x", 1000)
833 local p = assert(load(prog, name))
834 -- load 'p' as a binary chunk with debug information
835 local c = string.dump(p)
836 assert(#c > 1000 and #c < 2000) -- no repetition of 'source' in dump
837 local f = assert(load(c))
838 local g = f()
839 local h = g(3)
840 assert(h(5) == 8)
841 assert(debug.getinfo(f).source == name and -- all functions have 'source'
842 debug.getinfo(g).source == name and
843 debug.getinfo(h).source == name)
844 -- again, without debug info
845 local c = string.dump(p, true)
846 assert(#c < 500) -- no 'source' in dump
847 local f = assert(load(c))
848 local g = f()
849 local h = g(30)
850 assert(h(50) == 80)
851 assert(debug.getinfo(f).source == '=?' and -- no function has 'source'
852 debug.getinfo(g).source == '=?' and
853 debug.getinfo(h).source == '=?')
854end
855
856print"OK"
857
diff --git a/testes/errors.lua b/testes/errors.lua
new file mode 100644
index 00000000..79d746c7
--- /dev/null
+++ b/testes/errors.lua
@@ -0,0 +1,537 @@
1-- $Id: errors.lua,v 1.94 2016/12/21 19:23:02 roberto Exp $
2-- See Copyright Notice in file all.lua
3
4print("testing errors")
5
6local debug = require"debug"
7
8-- avoid problems with 'strict' module (which may generate other error messages)
9local mt = getmetatable(_G) or {}
10local oldmm = mt.__index
11mt.__index = nil
12
13local function checkerr (msg, f, ...)
14 local st, err = pcall(f, ...)
15 assert(not st and string.find(err, msg))
16end
17
18
19local function doit (s)
20 local f, msg = load(s)
21 if f == nil then return msg end
22 local cond, msg = pcall(f)
23 return (not cond) and msg
24end
25
26
27local function checkmessage (prog, msg)
28 local m = doit(prog)
29 assert(string.find(m, msg, 1, true))
30end
31
32local function checksyntax (prog, extra, token, line)
33 local msg = doit(prog)
34 if not string.find(token, "^<%a") and not string.find(token, "^char%(")
35 then token = "'"..token.."'" end
36 token = string.gsub(token, "(%p)", "%%%1")
37 local pt = string.format([[^%%[string ".*"%%]:%d: .- near %s$]],
38 line, token)
39 assert(string.find(msg, pt))
40 assert(string.find(msg, msg, 1, true))
41end
42
43
44-- test error message with no extra info
45assert(doit("error('hi', 0)") == 'hi')
46
47-- test error message with no info
48assert(doit("error()") == nil)
49
50
51-- test common errors/errors that crashed in the past
52assert(doit("table.unpack({}, 1, n=2^30)"))
53assert(doit("a=math.sin()"))
54assert(not doit("tostring(1)") and doit("tostring()"))
55assert(doit"tonumber()")
56assert(doit"repeat until 1; a")
57assert(doit"return;;")
58assert(doit"assert(false)")
59assert(doit"assert(nil)")
60assert(doit("function a (... , ...) end"))
61assert(doit("function a (, ...) end"))
62assert(doit("local t={}; t = t[#t] + 1"))
63
64checksyntax([[
65 local a = {4
66
67]], "'}' expected (to close '{' at line 1)", "<eof>", 3)
68
69
70-- tests for better error messages
71
72checkmessage("a = {} + 1", "arithmetic")
73checkmessage("a = {} | 1", "bitwise operation")
74checkmessage("a = {} < 1", "attempt to compare")
75checkmessage("a = {} <= 1", "attempt to compare")
76
77checkmessage("a=1; bbbb=2; a=math.sin(3)+bbbb(3)", "global 'bbbb'")
78checkmessage("a={}; do local a=1 end a:bbbb(3)", "method 'bbbb'")
79checkmessage("local a={}; a.bbbb(3)", "field 'bbbb'")
80assert(not string.find(doit"a={13}; local bbbb=1; a[bbbb](3)", "'bbbb'"))
81checkmessage("a={13}; local bbbb=1; a[bbbb](3)", "number")
82checkmessage("a=(1)..{}", "a table value")
83
84checkmessage("a = #print", "length of a function value")
85checkmessage("a = #3", "length of a number value")
86
87aaa = nil
88checkmessage("aaa.bbb:ddd(9)", "global 'aaa'")
89checkmessage("local aaa={bbb=1}; aaa.bbb:ddd(9)", "field 'bbb'")
90checkmessage("local aaa={bbb={}}; aaa.bbb:ddd(9)", "method 'ddd'")
91checkmessage("local a,b,c; (function () a = b+1 end)()", "upvalue 'b'")
92assert(not doit"local aaa={bbb={ddd=next}}; aaa.bbb:ddd(nil)")
93
94-- upvalues being indexed do not go to the stack
95checkmessage("local a,b,cc; (function () a = cc[1] end)()", "upvalue 'cc'")
96checkmessage("local a,b,cc; (function () a.x = 1 end)()", "upvalue 'a'")
97
98checkmessage("local _ENV = {x={}}; a = a + 1", "global 'a'")
99
100checkmessage("b=1; local aaa='a'; x=aaa+b", "local 'aaa'")
101checkmessage("aaa={}; x=3/aaa", "global 'aaa'")
102checkmessage("aaa='2'; b=nil;x=aaa*b", "global 'b'")
103checkmessage("aaa={}; x=-aaa", "global 'aaa'")
104
105-- short circuit
106checkmessage("a=1; local a,bbbb=2,3; a = math.sin(1) and bbbb(3)",
107 "local 'bbbb'")
108checkmessage("a=1; local a,bbbb=2,3; a = bbbb(1) or a(3)", "local 'bbbb'")
109checkmessage("local a,b,c,f = 1,1,1; f((a and b) or c)", "local 'f'")
110checkmessage("local a,b,c = 1,1,1; ((a and b) or c)()", "call a number value")
111assert(not string.find(doit"aaa={}; x=(aaa or aaa)+(aaa and aaa)", "'aaa'"))
112assert(not string.find(doit"aaa={}; (aaa or aaa)()", "'aaa'"))
113
114checkmessage("print(print < 10)", "function with number")
115checkmessage("print(print < print)", "two function values")
116checkmessage("print('10' < 10)", "string with number")
117checkmessage("print(10 < '23')", "number with string")
118
119-- float->integer conversions
120checkmessage("local a = 2.0^100; x = a << 2", "local a")
121checkmessage("local a = 1 >> 2.0^100", "has no integer representation")
122checkmessage("local a = '10' << 2.0^100", "has no integer representation")
123checkmessage("local a = 2.0^100 & 1", "has no integer representation")
124checkmessage("local a = 2.0^100 & '1'", "has no integer representation")
125checkmessage("local a = 2.0 | 1e40", "has no integer representation")
126checkmessage("local a = 2e100 ~ 1", "has no integer representation")
127checkmessage("string.sub('a', 2.0^100)", "has no integer representation")
128checkmessage("string.rep('a', 3.3)", "has no integer representation")
129checkmessage("return 6e40 & 7", "has no integer representation")
130checkmessage("return 34 << 7e30", "has no integer representation")
131checkmessage("return ~-3e40", "has no integer representation")
132checkmessage("return ~-3.009", "has no integer representation")
133checkmessage("return 3.009 & 1", "has no integer representation")
134checkmessage("return 34 >> {}", "table value")
135checkmessage("a = 24 // 0", "divide by zero")
136checkmessage("a = 1 % 0", "'n%0'")
137
138
139-- passing light userdata instead of full userdata
140_G.D = debug
141checkmessage([[
142 -- create light udata
143 local x = D.upvalueid(function () return debug end, 1)
144 D.setuservalue(x, {})
145]], "light userdata")
146_G.D = nil
147
148do -- named objects (field '__name')
149 checkmessage("math.sin(io.input())", "(number expected, got FILE*)")
150 _G.XX = setmetatable({}, {__name = "My Type"})
151 assert(string.find(tostring(XX), "^My Type"))
152 checkmessage("io.input(XX)", "(FILE* expected, got My Type)")
153 checkmessage("return XX + 1", "on a My Type value")
154 checkmessage("return ~io.stdin", "on a FILE* value")
155 checkmessage("return XX < XX", "two My Type values")
156 checkmessage("return {} < XX", "table with My Type")
157 checkmessage("return XX < io.stdin", "My Type with FILE*")
158 _G.XX = nil
159end
160
161-- global functions
162checkmessage("(io.write or print){}", "io.write")
163checkmessage("(collectgarbage or print){}", "collectgarbage")
164
165-- errors in functions without debug info
166do
167 local f = function (a) return a + 1 end
168 f = assert(load(string.dump(f, true)))
169 assert(f(3) == 4)
170 checkerr("^%?:%-1:", f, {})
171
172 -- code with a move to a local var ('OP_MOV A B' with A<B)
173 f = function () local a; a = {}; return a + 2 end
174 -- no debug info (so that 'a' is unknown)
175 f = assert(load(string.dump(f, true)))
176 -- symbolic execution should not get lost
177 checkerr("^%?:%-1:.*table value", f)
178end
179
180
181-- tests for field accesses after RK limit
182local t = {}
183for i = 1, 1000 do
184 t[i] = "a = x" .. i
185end
186local s = table.concat(t, "; ")
187t = nil
188checkmessage(s.."; a = bbb + 1", "global 'bbb'")
189checkmessage("local _ENV=_ENV;"..s.."; a = bbb + 1", "global 'bbb'")
190checkmessage(s.."; local t = {}; a = t.bbb + 1", "field 'bbb'")
191checkmessage(s.."; local t = {}; t:bbb()", "method 'bbb'")
192
193checkmessage([[aaa=9
194repeat until 3==3
195local x=math.sin(math.cos(3))
196if math.sin(1) == x then return math.sin(1) end -- tail call
197local a,b = 1, {
198 {x='a'..'b'..'c', y='b', z=x},
199 {1,2,3,4,5} or 3+3<=3+3,
200 3+1>3+1,
201 {d = x and aaa[x or y]}}
202]], "global 'aaa'")
203
204checkmessage([[
205local x,y = {},1
206if math.sin(1) == 0 then return 3 end -- return
207x.a()]], "field 'a'")
208
209checkmessage([[
210prefix = nil
211insert = nil
212while 1 do
213 local a
214 if nil then break end
215 insert(prefix, a)
216end]], "global 'insert'")
217
218checkmessage([[ -- tail call
219 return math.sin("a")
220]], "'sin'")
221
222checkmessage([[collectgarbage("nooption")]], "invalid option")
223
224checkmessage([[x = print .. "a"]], "concatenate")
225checkmessage([[x = "a" .. false]], "concatenate")
226checkmessage([[x = {} .. 2]], "concatenate")
227
228checkmessage("getmetatable(io.stdin).__gc()", "no value")
229
230checkmessage([[
231local Var
232local function main()
233 NoSuchName (function() Var=0 end)
234end
235main()
236]], "global 'NoSuchName'")
237print'+'
238
239a = {}; setmetatable(a, {__index = string})
240checkmessage("a:sub()", "bad self")
241checkmessage("string.sub('a', {})", "#2")
242checkmessage("('a'):sub{}", "#1")
243
244checkmessage("table.sort({1,2,3}, table.sort)", "'table.sort'")
245checkmessage("string.gsub('s', 's', setmetatable)", "'setmetatable'")
246
247-- tests for errors in coroutines
248
249local function f (n)
250 local c = coroutine.create(f)
251 local a,b = coroutine.resume(c)
252 return b
253end
254assert(string.find(f(), "C stack overflow"))
255
256checkmessage("coroutine.yield()", "outside a coroutine")
257
258f = coroutine.wrap(function () table.sort({1,2,3}, coroutine.yield) end)
259checkerr("yield across", f)
260
261
262-- testing size of 'source' info; size of buffer for that info is
263-- LUA_IDSIZE, declared as 60 in luaconf. Get one position for '\0'.
264idsize = 60 - 1
265local function checksize (source)
266 -- syntax error
267 local _, msg = load("x", source)
268 msg = string.match(msg, "^([^:]*):") -- get source (1st part before ':')
269 assert(msg:len() <= idsize)
270end
271
272for i = 60 - 10, 60 + 10 do -- check border cases around 60
273 checksize("@" .. string.rep("x", i)) -- file names
274 checksize(string.rep("x", i - 10)) -- string sources
275 checksize("=" .. string.rep("x", i)) -- exact sources
276end
277
278
279-- testing line error
280
281local function lineerror (s, l)
282 local err,msg = pcall(load(s))
283 local line = string.match(msg, ":(%d+):")
284 assert((line and line+0) == l)
285end
286
287lineerror("local a\n for i=1,'a' do \n print(i) \n end", 2)
288lineerror("\n local a \n for k,v in 3 \n do \n print(k) \n end", 3)
289lineerror("\n\n for k,v in \n 3 \n do \n print(k) \n end", 4)
290lineerror("function a.x.y ()\na=a+1\nend", 1)
291
292lineerror("a = \na\n+\n{}", 3)
293lineerror("a = \n3\n+\n(\n4\n/\nprint)", 6)
294lineerror("a = \nprint\n+\n(\n4\n/\n7)", 3)
295
296lineerror("a\n=\n-\n\nprint\n;", 3)
297
298lineerror([[
299a
300(
30123)
302]], 1)
303
304lineerror([[
305local a = {x = 13}
306a
307.
308x
309(
31023
311)
312]], 2)
313
314lineerror([[
315local a = {x = 13}
316a
317.
318x
319(
32023 + a
321)
322]], 6)
323
324local p = [[
325 function g() f() end
326 function f(x) error('a', X) end
327g()
328]]
329X=3;lineerror((p), 3)
330X=0;lineerror((p), nil)
331X=1;lineerror((p), 2)
332X=2;lineerror((p), 1)
333
334
335if not _soft then
336 -- several tests that exaust the Lua stack
337 collectgarbage()
338 print"testing stack overflow"
339 C = 0
340 local l = debug.getinfo(1, "l").currentline; function y () C=C+1; y() end
341
342 local function checkstackmessage (m)
343 return (string.find(m, "^.-:%d+: stack overflow"))
344 end
345 -- repeated stack overflows (to check stack recovery)
346 assert(checkstackmessage(doit('y()')))
347 print('+')
348 assert(checkstackmessage(doit('y()')))
349 print('+')
350 assert(checkstackmessage(doit('y()')))
351 print('+')
352
353
354 -- error lines in stack overflow
355 C = 0
356 local l1
357 local function g(x)
358 l1 = debug.getinfo(x, "l").currentline; y()
359 end
360 local _, stackmsg = xpcall(g, debug.traceback, 1)
361 print('+')
362 local stack = {}
363 for line in string.gmatch(stackmsg, "[^\n]*") do
364 local curr = string.match(line, ":(%d+):")
365 if curr then table.insert(stack, tonumber(curr)) end
366 end
367 local i=1
368 while stack[i] ~= l1 do
369 assert(stack[i] == l)
370 i = i+1
371 end
372 assert(i > 15)
373
374
375 -- error in error handling
376 local res, msg = xpcall(error, error)
377 assert(not res and type(msg) == 'string')
378 print('+')
379
380 local function f (x)
381 if x==0 then error('a\n')
382 else
383 local aux = function () return f(x-1) end
384 local a,b = xpcall(aux, aux)
385 return a,b
386 end
387 end
388 f(3)
389
390 local function loop (x,y,z) return 1 + loop(x, y, z) end
391
392 local res, msg = xpcall(loop, function (m)
393 assert(string.find(m, "stack overflow"))
394 checkerr("error handling", loop)
395 assert(math.sin(0) == 0)
396 return 15
397 end)
398 assert(msg == 15)
399
400 local f = function ()
401 for i = 999900, 1000000, 1 do table.unpack({}, 1, i) end
402 end
403 checkerr("too many results", f)
404
405end
406
407
408do
409 -- non string messages
410 local t = {}
411 local res, msg = pcall(function () error(t) end)
412 assert(not res and msg == t)
413
414 res, msg = pcall(function () error(nil) end)
415 assert(not res and msg == nil)
416
417 local function f() error{msg='x'} end
418 res, msg = xpcall(f, function (r) return {msg=r.msg..'y'} end)
419 assert(msg.msg == 'xy')
420
421 -- 'assert' with extra arguments
422 res, msg = pcall(assert, false, "X", t)
423 assert(not res and msg == "X")
424
425 -- 'assert' with no message
426 res, msg = pcall(function () assert(false) end)
427 local line = string.match(msg, "%w+%.lua:(%d+): assertion failed!$")
428 assert(tonumber(line) == debug.getinfo(1, "l").currentline - 2)
429
430 -- 'assert' with non-string messages
431 res, msg = pcall(assert, false, t)
432 assert(not res and msg == t)
433
434 res, msg = pcall(assert, nil, nil)
435 assert(not res and msg == nil)
436
437 -- 'assert' without arguments
438 res, msg = pcall(assert)
439 assert(not res and string.find(msg, "value expected"))
440end
441
442-- xpcall with arguments
443a, b, c = xpcall(string.find, error, "alo", "al")
444assert(a and b == 1 and c == 2)
445a, b, c = xpcall(string.find, function (x) return {} end, true, "al")
446assert(not a and type(b) == "table" and c == nil)
447
448
449print("testing tokens in error messages")
450checksyntax("syntax error", "", "error", 1)
451checksyntax("1.000", "", "1.000", 1)
452checksyntax("[[a]]", "", "[[a]]", 1)
453checksyntax("'aa'", "", "'aa'", 1)
454checksyntax("while << do end", "", "<<", 1)
455checksyntax("for >> do end", "", ">>", 1)
456
457-- test invalid non-printable char in a chunk
458checksyntax("a\1a = 1", "", "<\\1>", 1)
459
460-- test 255 as first char in a chunk
461checksyntax("\255a = 1", "", "<\\255>", 1)
462
463doit('I = load("a=9+"); a=3')
464assert(a==3 and I == nil)
465print('+')
466
467lim = 1000
468if _soft then lim = 100 end
469for i=1,lim do
470 doit('a = ')
471 doit('a = 4+nil')
472end
473
474
475-- testing syntax limits
476
477local maxClevel = 200 -- LUAI_MAXCCALLS (in llimits.h)
478
479local function testrep (init, rep, close, repc)
480 local s = init .. string.rep(rep, maxClevel - 10) .. close ..
481 string.rep(repc, maxClevel - 10)
482 assert(load(s)) -- 190 levels is OK
483 s = init .. string.rep(rep, maxClevel + 1)
484 checkmessage(s, "too many C levels")
485end
486
487testrep("local a; a", ",a", "= 1", ",1") -- multiple assignment
488testrep("local a; a=", "{", "0", "}")
489testrep("local a; a=", "(", "2", ")")
490testrep("local a; ", "a(", "2", ")")
491testrep("", "do ", "", " end")
492testrep("", "while a do ", "", " end")
493testrep("local a; ", "if a then else ", "", " end")
494testrep("", "function foo () ", "", " end")
495testrep("local a; a=", "a..", "a", "")
496testrep("local a; a=", "a^", "a", "")
497
498checkmessage("a = f(x" .. string.rep(",x", 260) .. ")", "too many registers")
499
500
501-- testing other limits
502
503-- upvalues
504local lim = 127
505local s = "local function fooA ()\n local "
506for j = 1,lim do
507 s = s.."a"..j..", "
508end
509s = s.."b,c\n"
510s = s.."local function fooB ()\n local "
511for j = 1,lim do
512 s = s.."b"..j..", "
513end
514s = s.."b\n"
515s = s.."function fooC () return b+c"
516local c = 1+2
517for j = 1,lim do
518 s = s.."+a"..j.."+b"..j
519 c = c + 2
520end
521s = s.."\nend end end"
522local a,b = load(s)
523assert(c > 255 and string.find(b, "too many upvalues") and
524 string.find(b, "line 5"))
525
526-- local variables
527s = "\nfunction foo ()\n local "
528for j = 1,300 do
529 s = s.."a"..j..", "
530end
531s = s.."b\n"
532local a,b = load(s)
533assert(string.find(b, "line 2") and string.find(b, "too many local variables"))
534
535mt.__index = oldmm
536
537print('OK')
diff --git a/testes/events.lua b/testes/events.lua
new file mode 100644
index 00000000..9136f99c
--- /dev/null
+++ b/testes/events.lua
@@ -0,0 +1,456 @@
1-- $Id: events.lua,v 1.45 2016/12/21 19:23:02 roberto Exp $
2-- See Copyright Notice in file all.lua
3
4print('testing metatables')
5
6local debug = require'debug'
7
8X = 20; B = 30
9
10_ENV = setmetatable({}, {__index=_G})
11
12collectgarbage()
13
14X = X+10
15assert(X == 30 and _G.X == 20)
16B = false
17assert(B == false)
18B = nil
19assert(B == 30)
20
21assert(getmetatable{} == nil)
22assert(getmetatable(4) == nil)
23assert(getmetatable(nil) == nil)
24a={name = "NAME"}; setmetatable(a, {__metatable = "xuxu",
25 __tostring=function(x) return x.name end})
26assert(getmetatable(a) == "xuxu")
27assert(tostring(a) == "NAME")
28-- cannot change a protected metatable
29assert(pcall(setmetatable, a, {}) == false)
30a.name = "gororoba"
31assert(tostring(a) == "gororoba")
32
33local a, t = {10,20,30; x="10", y="20"}, {}
34assert(setmetatable(a,t) == a)
35assert(getmetatable(a) == t)
36assert(setmetatable(a,nil) == a)
37assert(getmetatable(a) == nil)
38assert(setmetatable(a,t) == a)
39
40
41function f (t, i, e)
42 assert(not e)
43 local p = rawget(t, "parent")
44 return (p and p[i]+3), "dummy return"
45end
46
47t.__index = f
48
49a.parent = {z=25, x=12, [4] = 24}
50assert(a[1] == 10 and a.z == 28 and a[4] == 27 and a.x == "10")
51
52collectgarbage()
53
54a = setmetatable({}, t)
55function f(t, i, v) rawset(t, i, v-3) end
56setmetatable(t, t) -- causes a bug in 5.1 !
57t.__newindex = f
58a[1] = 30; a.x = "101"; a[5] = 200
59assert(a[1] == 27 and a.x == 98 and a[5] == 197)
60
61do -- bug in Lua 5.3.2
62 local mt = {}
63 mt.__newindex = mt
64 local t = setmetatable({}, mt)
65 t[1] = 10 -- will segfault on some machines
66 assert(mt[1] == 10)
67end
68
69
70local c = {}
71a = setmetatable({}, t)
72t.__newindex = c
73a[1] = 10; a[2] = 20; a[3] = 90
74assert(c[1] == 10 and c[2] == 20 and c[3] == 90)
75
76
77do
78 local a;
79 a = setmetatable({}, {__index = setmetatable({},
80 {__index = setmetatable({},
81 {__index = function (_,n) return a[n-3]+4, "lixo" end})})})
82 a[0] = 20
83 for i=0,10 do
84 assert(a[i*3] == 20 + i*4)
85 end
86end
87
88
89do -- newindex
90 local foi
91 local a = {}
92 for i=1,10 do a[i] = 0; a['a'..i] = 0; end
93 setmetatable(a, {__newindex = function (t,k,v) foi=true; rawset(t,k,v) end})
94 foi = false; a[1]=0; assert(not foi)
95 foi = false; a['a1']=0; assert(not foi)
96 foi = false; a['a11']=0; assert(foi)
97 foi = false; a[11]=0; assert(foi)
98 foi = false; a[1]=nil; assert(not foi)
99 foi = false; a[1]=nil; assert(foi)
100end
101
102
103setmetatable(t, nil)
104function f (t, ...) return t, {...} end
105t.__call = f
106
107do
108 local x,y = a(table.unpack{'a', 1})
109 assert(x==a and y[1]=='a' and y[2]==1 and y[3]==nil)
110 x,y = a()
111 assert(x==a and y[1]==nil)
112end
113
114
115local b = setmetatable({}, t)
116setmetatable(b,t)
117
118function f(op)
119 return function (...) cap = {[0] = op, ...} ; return (...) end
120end
121t.__add = f("add")
122t.__sub = f("sub")
123t.__mul = f("mul")
124t.__div = f("div")
125t.__idiv = f("idiv")
126t.__mod = f("mod")
127t.__unm = f("unm")
128t.__pow = f("pow")
129t.__len = f("len")
130t.__band = f("band")
131t.__bor = f("bor")
132t.__bxor = f("bxor")
133t.__shl = f("shl")
134t.__shr = f("shr")
135t.__bnot = f("bnot")
136
137assert(b+5 == b)
138assert(cap[0] == "add" and cap[1] == b and cap[2] == 5 and cap[3]==nil)
139assert(b+'5' == b)
140assert(cap[0] == "add" and cap[1] == b and cap[2] == '5' and cap[3]==nil)
141assert(5+b == 5)
142assert(cap[0] == "add" and cap[1] == 5 and cap[2] == b and cap[3]==nil)
143assert('5'+b == '5')
144assert(cap[0] == "add" and cap[1] == '5' and cap[2] == b and cap[3]==nil)
145b=b-3; assert(getmetatable(b) == t)
146assert(5-a == 5)
147assert(cap[0] == "sub" and cap[1] == 5 and cap[2] == a and cap[3]==nil)
148assert('5'-a == '5')
149assert(cap[0] == "sub" and cap[1] == '5' and cap[2] == a and cap[3]==nil)
150assert(a*a == a)
151assert(cap[0] == "mul" and cap[1] == a and cap[2] == a and cap[3]==nil)
152assert(a/0 == a)
153assert(cap[0] == "div" and cap[1] == a and cap[2] == 0 and cap[3]==nil)
154assert(a%2 == a)
155assert(cap[0] == "mod" and cap[1] == a and cap[2] == 2 and cap[3]==nil)
156assert(a // (1/0) == a)
157assert(cap[0] == "idiv" and cap[1] == a and cap[2] == 1/0 and cap[3]==nil)
158assert(a & "hi" == a)
159assert(cap[0] == "band" and cap[1] == a and cap[2] == "hi" and cap[3]==nil)
160assert(a | "hi" == a)
161assert(cap[0] == "bor" and cap[1] == a and cap[2] == "hi" and cap[3]==nil)
162assert("hi" ~ a == "hi")
163assert(cap[0] == "bxor" and cap[1] == "hi" and cap[2] == a and cap[3]==nil)
164assert(-a == a)
165assert(cap[0] == "unm" and cap[1] == a)
166assert(a^4 == a)
167assert(cap[0] == "pow" and cap[1] == a and cap[2] == 4 and cap[3]==nil)
168assert(a^'4' == a)
169assert(cap[0] == "pow" and cap[1] == a and cap[2] == '4' and cap[3]==nil)
170assert(4^a == 4)
171assert(cap[0] == "pow" and cap[1] == 4 and cap[2] == a and cap[3]==nil)
172assert('4'^a == '4')
173assert(cap[0] == "pow" and cap[1] == '4' and cap[2] == a and cap[3]==nil)
174assert(#a == a)
175assert(cap[0] == "len" and cap[1] == a)
176assert(~a == a)
177assert(cap[0] == "bnot" and cap[1] == a)
178assert(a << 3 == a)
179assert(cap[0] == "shl" and cap[1] == a and cap[2] == 3)
180assert(1.5 >> a == 1.5)
181assert(cap[0] == "shr" and cap[1] == 1.5 and cap[2] == a)
182
183
184-- test for rawlen
185t = setmetatable({1,2,3}, {__len = function () return 10 end})
186assert(#t == 10 and rawlen(t) == 3)
187assert(rawlen"abc" == 3)
188assert(not pcall(rawlen, io.stdin))
189assert(not pcall(rawlen, 34))
190assert(not pcall(rawlen))
191
192-- rawlen for long strings
193assert(rawlen(string.rep('a', 1000)) == 1000)
194
195
196t = {}
197t.__lt = function (a,b,c)
198 collectgarbage()
199 assert(c == nil)
200 if type(a) == 'table' then a = a.x end
201 if type(b) == 'table' then b = b.x end
202 return a<b, "dummy"
203end
204
205function Op(x) return setmetatable({x=x}, t) end
206
207local function test ()
208 assert(not(Op(1)<Op(1)) and (Op(1)<Op(2)) and not(Op(2)<Op(1)))
209 assert(not(1 < Op(1)) and (Op(1) < 2) and not(2 < Op(1)))
210 assert(not(Op('a')<Op('a')) and (Op('a')<Op('b')) and not(Op('b')<Op('a')))
211 assert(not('a' < Op('a')) and (Op('a') < 'b') and not(Op('b') < Op('a')))
212 assert((Op(1)<=Op(1)) and (Op(1)<=Op(2)) and not(Op(2)<=Op(1)))
213 assert((Op('a')<=Op('a')) and (Op('a')<=Op('b')) and not(Op('b')<=Op('a')))
214 assert(not(Op(1)>Op(1)) and not(Op(1)>Op(2)) and (Op(2)>Op(1)))
215 assert(not(Op('a')>Op('a')) and not(Op('a')>Op('b')) and (Op('b')>Op('a')))
216 assert((Op(1)>=Op(1)) and not(Op(1)>=Op(2)) and (Op(2)>=Op(1)))
217 assert((1 >= Op(1)) and not(1 >= Op(2)) and (Op(2) >= 1))
218 assert((Op('a')>=Op('a')) and not(Op('a')>=Op('b')) and (Op('b')>=Op('a')))
219 assert(('a' >= Op('a')) and not(Op('a') >= 'b') and (Op('b') >= Op('a')))
220end
221
222test()
223
224t.__le = function (a,b,c)
225 assert(c == nil)
226 if type(a) == 'table' then a = a.x end
227 if type(b) == 'table' then b = b.x end
228 return a<=b, "dummy"
229end
230
231test() -- retest comparisons, now using both `lt' and `le'
232
233
234-- test `partial order'
235
236local function rawSet(x)
237 local y = {}
238 for _,k in pairs(x) do y[k] = 1 end
239 return y
240end
241
242local function Set(x)
243 return setmetatable(rawSet(x), t)
244end
245
246t.__lt = function (a,b)
247 for k in pairs(a) do
248 if not b[k] then return false end
249 b[k] = nil
250 end
251 return next(b) ~= nil
252end
253
254t.__le = nil
255
256assert(Set{1,2,3} < Set{1,2,3,4})
257assert(not(Set{1,2,3,4} < Set{1,2,3,4}))
258assert((Set{1,2,3,4} <= Set{1,2,3,4}))
259assert((Set{1,2,3,4} >= Set{1,2,3,4}))
260assert((Set{1,3} <= Set{3,5})) -- wrong!! model needs a `le' method ;-)
261
262t.__le = function (a,b)
263 for k in pairs(a) do
264 if not b[k] then return false end
265 end
266 return true
267end
268
269assert(not (Set{1,3} <= Set{3,5})) -- now its OK!
270assert(not(Set{1,3} <= Set{3,5}))
271assert(not(Set{1,3} >= Set{3,5}))
272
273t.__eq = function (a,b)
274 for k in pairs(a) do
275 if not b[k] then return false end
276 b[k] = nil
277 end
278 return next(b) == nil
279end
280
281local s = Set{1,3,5}
282assert(s == Set{3,5,1})
283assert(not rawequal(s, Set{3,5,1}))
284assert(rawequal(s, s))
285assert(Set{1,3,5,1} == rawSet{3,5,1})
286assert(rawSet{1,3,5,1} == Set{3,5,1})
287assert(Set{1,3,5} ~= Set{3,5,1,6})
288
289-- '__eq' is not used for table accesses
290t[Set{1,3,5}] = 1
291assert(t[Set{1,3,5}] == nil)
292
293
294if not T then
295 (Message or print)('\n >>> testC not active: skipping tests for \z
296userdata equality <<<\n')
297else
298 local u1 = T.newuserdata(0)
299 local u2 = T.newuserdata(0)
300 local u3 = T.newuserdata(0)
301 assert(u1 ~= u2 and u1 ~= u3)
302 debug.setuservalue(u1, 1);
303 debug.setuservalue(u2, 2);
304 debug.setuservalue(u3, 1);
305 debug.setmetatable(u1, {__eq = function (a, b)
306 return debug.getuservalue(a) == debug.getuservalue(b)
307 end})
308 debug.setmetatable(u2, {__eq = function (a, b)
309 return true
310 end})
311 assert(u1 == u3 and u3 == u1 and u1 ~= u2)
312 assert(u2 == u1 and u2 == u3 and u3 == u2)
313 assert(u2 ~= {}) -- different types cannot be equal
314end
315
316
317t.__concat = function (a,b,c)
318 assert(c == nil)
319 if type(a) == 'table' then a = a.val end
320 if type(b) == 'table' then b = b.val end
321 if A then return a..b
322 else
323 return setmetatable({val=a..b}, t)
324 end
325end
326
327c = {val="c"}; setmetatable(c, t)
328d = {val="d"}; setmetatable(d, t)
329
330A = true
331assert(c..d == 'cd')
332assert(0 .."a".."b"..c..d.."e".."f"..(5+3).."g" == "0abcdef8g")
333
334A = false
335assert((c..d..c..d).val == 'cdcd')
336x = c..d
337assert(getmetatable(x) == t and x.val == 'cd')
338x = 0 .."a".."b"..c..d.."e".."f".."g"
339assert(x.val == "0abcdefg")
340
341
342-- concat metamethod x numbers (bug in 5.1.1)
343c = {}
344local x
345setmetatable(c, {__concat = function (a,b)
346 assert(type(a) == "number" and b == c or type(b) == "number" and a == c)
347 return c
348end})
349assert(c..5 == c and 5 .. c == c)
350assert(4 .. c .. 5 == c and 4 .. 5 .. 6 .. 7 .. c == c)
351
352
353-- test comparison compatibilities
354local t1, t2, c, d
355t1 = {}; c = {}; setmetatable(c, t1)
356d = {}
357t1.__eq = function () return true end
358t1.__lt = function () return true end
359setmetatable(d, t1)
360assert(c == d and c < d and not(d <= c))
361t2 = {}
362t2.__eq = t1.__eq
363t2.__lt = t1.__lt
364setmetatable(d, t2)
365assert(c == d and c < d and not(d <= c))
366
367
368
369-- test for several levels of calls
370local i
371local tt = {
372 __call = function (t, ...)
373 i = i+1
374 if t.f then return t.f(...)
375 else return {...}
376 end
377 end
378}
379
380local a = setmetatable({}, tt)
381local b = setmetatable({f=a}, tt)
382local c = setmetatable({f=b}, tt)
383
384i = 0
385x = c(3,4,5)
386assert(i == 3 and x[1] == 3 and x[3] == 5)
387
388
389assert(_G.X == 20)
390
391print'+'
392
393local _g = _G
394_ENV = setmetatable({}, {__index=function (_,k) return _g[k] end})
395
396
397a = {}
398rawset(a, "x", 1, 2, 3)
399assert(a.x == 1 and rawget(a, "x", 3) == 1)
400
401print '+'
402
403-- testing metatables for basic types
404mt = {__index = function (a,b) return a+b end,
405 __len = function (x) return math.floor(x) end}
406debug.setmetatable(10, mt)
407assert(getmetatable(-2) == mt)
408assert((10)[3] == 13)
409assert((10)["3"] == 13)
410assert(#3.45 == 3)
411debug.setmetatable(23, nil)
412assert(getmetatable(-2) == nil)
413
414debug.setmetatable(true, mt)
415assert(getmetatable(false) == mt)
416mt.__index = function (a,b) return a or b end
417assert((true)[false] == true)
418assert((false)[false] == false)
419debug.setmetatable(false, nil)
420assert(getmetatable(true) == nil)
421
422debug.setmetatable(nil, mt)
423assert(getmetatable(nil) == mt)
424mt.__add = function (a,b) return (a or 0) + (b or 0) end
425assert(10 + nil == 10)
426assert(nil + 23 == 23)
427assert(nil + nil == 0)
428debug.setmetatable(nil, nil)
429assert(getmetatable(nil) == nil)
430
431debug.setmetatable(nil, {})
432
433
434-- loops in delegation
435a = {}; setmetatable(a, a); a.__index = a; a.__newindex = a
436assert(not pcall(function (a,b) return a[b] end, a, 10))
437assert(not pcall(function (a,b,c) a[b] = c end, a, 10, true))
438
439-- bug in 5.1
440T, K, V = nil
441grandparent = {}
442grandparent.__newindex = function(t,k,v) T=t; K=k; V=v end
443
444parent = {}
445parent.__newindex = parent
446setmetatable(parent, grandparent)
447
448child = setmetatable({}, parent)
449child.foo = 10 --> CRASH (on some machines)
450assert(T == parent and K == "foo" and V == 10)
451
452print 'OK'
453
454return 12
455
456
diff --git a/testes/files.lua b/testes/files.lua
new file mode 100644
index 00000000..3cfe12d2
--- /dev/null
+++ b/testes/files.lua
@@ -0,0 +1,793 @@
1-- $Id: files.lua,v 1.95 2016/11/07 13:11:28 roberto Exp $
2-- See Copyright Notice in file all.lua
3
4local debug = require "debug"
5
6local maxint = math.maxinteger
7
8assert(type(os.getenv"PATH") == "string")
9
10assert(io.input(io.stdin) == io.stdin)
11assert(not pcall(io.input, "non-existent-file"))
12assert(io.output(io.stdout) == io.stdout)
13
14
15local function testerr (msg, f, ...)
16 local stat, err = pcall(f, ...)
17 return (not stat and string.find(err, msg, 1, true))
18end
19
20
21local function checkerr (msg, f, ...)
22 assert(testerr(msg, f, ...))
23end
24
25
26-- cannot close standard files
27assert(not io.close(io.stdin) and
28 not io.stdout:close() and
29 not io.stderr:close())
30
31
32assert(type(io.input()) == "userdata" and io.type(io.output()) == "file")
33assert(type(io.stdin) == "userdata" and io.type(io.stderr) == "file")
34assert(not io.type(8))
35local a = {}; setmetatable(a, {})
36assert(not io.type(a))
37
38assert(getmetatable(io.input()).__name == "FILE*")
39
40local a,b,c = io.open('xuxu_nao_existe')
41assert(not a and type(b) == "string" and type(c) == "number")
42
43a,b,c = io.open('/a/b/c/d', 'w')
44assert(not a and type(b) == "string" and type(c) == "number")
45
46local file = os.tmpname()
47local f, msg = io.open(file, "w")
48if not f then
49 (Message or print)("'os.tmpname' file cannot be open; skipping file tests")
50
51else --{ most tests here need tmpname
52f:close()
53
54print('testing i/o')
55
56local otherfile = os.tmpname()
57
58checkerr("invalid mode", io.open, file, "rw")
59checkerr("invalid mode", io.open, file, "rb+")
60checkerr("invalid mode", io.open, file, "r+bk")
61checkerr("invalid mode", io.open, file, "")
62checkerr("invalid mode", io.open, file, "+")
63checkerr("invalid mode", io.open, file, "b")
64assert(io.open(file, "r+b")):close()
65assert(io.open(file, "r+")):close()
66assert(io.open(file, "rb")):close()
67
68assert(os.setlocale('C', 'all'))
69
70io.input(io.stdin); io.output(io.stdout);
71
72os.remove(file)
73assert(not loadfile(file))
74checkerr("", dofile, file)
75assert(not io.open(file))
76io.output(file)
77assert(io.output() ~= io.stdout)
78
79if not _port then -- invalid seek
80 local status, msg, code = io.stdin:seek("set", 1000)
81 assert(not status and type(msg) == "string" and type(code) == "number")
82end
83
84assert(io.output():seek() == 0)
85assert(io.write("alo alo"):seek() == string.len("alo alo"))
86assert(io.output():seek("cur", -3) == string.len("alo alo")-3)
87assert(io.write("joao"))
88assert(io.output():seek("end") == string.len("alo joao"))
89
90assert(io.output():seek("set") == 0)
91
92assert(io.write('"álo"', "{a}\n", "second line\n", "third line \n"))
93assert(io.write('çfourth_line'))
94io.output(io.stdout)
95collectgarbage() -- file should be closed by GC
96assert(io.input() == io.stdin and rawequal(io.output(), io.stdout))
97print('+')
98
99-- test GC for files
100collectgarbage()
101for i=1,120 do
102 for i=1,5 do
103 io.input(file)
104 assert(io.open(file, 'r'))
105 io.lines(file)
106 end
107 collectgarbage()
108end
109
110io.input():close()
111io.close()
112
113assert(os.rename(file, otherfile))
114assert(not os.rename(file, otherfile))
115
116io.output(io.open(otherfile, "ab"))
117assert(io.write("\n\n\t\t ", 3450, "\n"));
118io.close()
119
120-- test writing/reading numbers
121f = assert(io.open(file, "w"))
122f:write(maxint, '\n')
123f:write(string.format("0X%x\n", maxint))
124f:write("0xABCp-3", '\n')
125f:write(0, '\n')
126f:write(-maxint, '\n')
127f:write(string.format("0x%X\n", -maxint))
128f:write("-0xABCp-3", '\n')
129assert(f:close())
130f = assert(io.open(file, "r"))
131assert(f:read("n") == maxint)
132assert(f:read("n") == maxint)
133assert(f:read("n") == 0xABCp-3)
134assert(f:read("n") == 0)
135assert(f:read("*n") == -maxint) -- test old format (with '*')
136assert(f:read("n") == -maxint)
137assert(f:read("*n") == -0xABCp-3) -- test old format (with '*')
138assert(f:close())
139assert(os.remove(file))
140
141-- test yielding during 'dofile'
142f = assert(io.open(file, "w"))
143f:write[[
144local x, z = coroutine.yield(10)
145local y = coroutine.yield(20)
146return x + y * z
147]]
148assert(f:close())
149f = coroutine.wrap(dofile)
150assert(f(file) == 10)
151print(f(100, 101) == 20)
152assert(f(200) == 100 + 200 * 101)
153assert(os.remove(file))
154
155
156f = assert(io.open(file, "w"))
157-- test number termination
158f:write[[
159-12.3- -0xffff+ .3|5.E-3X +234e+13E 0xDEADBEEFDEADBEEFx
1600x1.13Ap+3e
161]]
162-- very long number
163f:write("1234"); for i = 1, 1000 do f:write("0") end; f:write("\n")
164-- invalid sequences (must read and discard valid prefixes)
165f:write[[
166.e+ 0.e; --; 0xX;
167]]
168assert(f:close())
169f = assert(io.open(file, "r"))
170assert(f:read("n") == -12.3); assert(f:read(1) == "-")
171assert(f:read("n") == -0xffff); assert(f:read(2) == "+ ")
172assert(f:read("n") == 0.3); assert(f:read(1) == "|")
173assert(f:read("n") == 5e-3); assert(f:read(1) == "X")
174assert(f:read("n") == 234e13); assert(f:read(1) == "E")
175assert(f:read("n") == 0Xdeadbeefdeadbeef); assert(f:read(2) == "x\n")
176assert(f:read("n") == 0x1.13aP3); assert(f:read(1) == "e")
177
178do -- attempt to read too long number
179 assert(f:read("n") == nil) -- fails
180 local s = f:read("L") -- read rest of line
181 assert(string.find(s, "^00*\n$")) -- lots of 0's left
182end
183
184assert(not f:read("n")); assert(f:read(2) == "e+")
185assert(not f:read("n")); assert(f:read(1) == ";")
186assert(not f:read("n")); assert(f:read(2) == "-;")
187assert(not f:read("n")); assert(f:read(1) == "X")
188assert(not f:read("n")); assert(f:read(1) == ";")
189assert(not f:read("n")); assert(not f:read(0)) -- end of file
190assert(f:close())
191assert(os.remove(file))
192
193
194-- test line generators
195assert(not pcall(io.lines, "non-existent-file"))
196assert(os.rename(otherfile, file))
197io.output(otherfile)
198local n = 0
199local f = io.lines(file)
200while f() do n = n + 1 end;
201assert(n == 6) -- number of lines in the file
202checkerr("file is already closed", f)
203checkerr("file is already closed", f)
204-- copy from file to otherfile
205n = 0
206for l in io.lines(file) do io.write(l, "\n"); n = n + 1 end
207io.close()
208assert(n == 6)
209-- copy from otherfile back to file
210local f = assert(io.open(otherfile))
211assert(io.type(f) == "file")
212io.output(file)
213assert(not io.output():read())
214n = 0
215for l in f:lines() do io.write(l, "\n"); n = n + 1 end
216assert(tostring(f):sub(1, 5) == "file ")
217assert(f:close()); io.close()
218assert(n == 6)
219checkerr("closed file", io.close, f)
220assert(tostring(f) == "file (closed)")
221assert(io.type(f) == "closed file")
222io.input(file)
223f = io.open(otherfile):lines()
224n = 0
225for l in io.lines() do assert(l == f()); n = n + 1 end
226f = nil; collectgarbage()
227assert(n == 6)
228assert(os.remove(otherfile))
229
230do -- bug in 5.3.1
231 io.output(otherfile)
232 io.write(string.rep("a", 300), "\n")
233 io.close()
234 local t ={}; for i = 1, 250 do t[i] = 1 end
235 t = {io.lines(otherfile, table.unpack(t))()}
236 -- everything ok here
237 assert(#t == 250 and t[1] == 'a' and t[#t] == 'a')
238 t[#t + 1] = 1 -- one too many
239 checkerr("too many arguments", io.lines, otherfile, table.unpack(t))
240 collectgarbage() -- ensure 'otherfile' is closed
241 assert(os.remove(otherfile))
242end
243
244io.input(file)
245do -- test error returns
246 local a,b,c = io.input():write("xuxu")
247 assert(not a and type(b) == "string" and type(c) == "number")
248end
249checkerr("invalid format", io.read, "x")
250assert(io.read(0) == "") -- not eof
251assert(io.read(5, 'l') == '"álo"')
252assert(io.read(0) == "")
253assert(io.read() == "second line")
254local x = io.input():seek()
255assert(io.read() == "third line ")
256assert(io.input():seek("set", x))
257assert(io.read('L') == "third line \n")
258assert(io.read(1) == "ç")
259assert(io.read(string.len"fourth_line") == "fourth_line")
260assert(io.input():seek("cur", -string.len"fourth_line"))
261assert(io.read() == "fourth_line")
262assert(io.read() == "") -- empty line
263assert(io.read('n') == 3450)
264assert(io.read(1) == '\n')
265assert(io.read(0) == nil) -- end of file
266assert(io.read(1) == nil) -- end of file
267assert(io.read(30000) == nil) -- end of file
268assert(({io.read(1)})[2] == nil)
269assert(io.read() == nil) -- end of file
270assert(({io.read()})[2] == nil)
271assert(io.read('n') == nil) -- end of file
272assert(({io.read('n')})[2] == nil)
273assert(io.read('a') == '') -- end of file (OK for 'a')
274assert(io.read('a') == '') -- end of file (OK for 'a')
275collectgarbage()
276print('+')
277io.close(io.input())
278checkerr(" input file is closed", io.read)
279
280assert(os.remove(file))
281
282local t = '0123456789'
283for i=1,10 do t = t..t; end
284assert(string.len(t) == 10*2^10)
285
286io.output(file)
287io.write("alo"):write("\n")
288io.close()
289checkerr(" output file is closed", io.write)
290local f = io.open(file, "a+b")
291io.output(f)
292collectgarbage()
293
294assert(io.write(' ' .. t .. ' '))
295assert(io.write(';', 'end of file\n'))
296f:flush(); io.flush()
297f:close()
298print('+')
299
300io.input(file)
301assert(io.read() == "alo")
302assert(io.read(1) == ' ')
303assert(io.read(string.len(t)) == t)
304assert(io.read(1) == ' ')
305assert(io.read(0))
306assert(io.read('a') == ';end of file\n')
307assert(io.read(0) == nil)
308assert(io.close(io.input()))
309
310
311-- test errors in read/write
312do
313 local function ismsg (m)
314 -- error message is not a code number
315 return (type(m) == "string" and tonumber(m) == nil)
316 end
317
318 -- read
319 local f = io.open(file, "w")
320 local r, m, c = f:read()
321 assert(not r and ismsg(m) and type(c) == "number")
322 assert(f:close())
323 -- write
324 f = io.open(file, "r")
325 r, m, c = f:write("whatever")
326 assert(not r and ismsg(m) and type(c) == "number")
327 assert(f:close())
328 -- lines
329 f = io.open(file, "w")
330 r, m = pcall(f:lines())
331 assert(r == false and ismsg(m))
332 assert(f:close())
333end
334
335assert(os.remove(file))
336
337-- test for L format
338io.output(file); io.write"\n\nline\nother":close()
339io.input(file)
340assert(io.read"L" == "\n")
341assert(io.read"L" == "\n")
342assert(io.read"L" == "line\n")
343assert(io.read"L" == "other")
344assert(io.read"L" == nil)
345io.input():close()
346
347local f = assert(io.open(file))
348local s = ""
349for l in f:lines("L") do s = s .. l end
350assert(s == "\n\nline\nother")
351f:close()
352
353io.input(file)
354s = ""
355for l in io.lines(nil, "L") do s = s .. l end
356assert(s == "\n\nline\nother")
357io.input():close()
358
359s = ""
360for l in io.lines(file, "L") do s = s .. l end
361assert(s == "\n\nline\nother")
362
363s = ""
364for l in io.lines(file, "l") do s = s .. l end
365assert(s == "lineother")
366
367io.output(file); io.write"a = 10 + 34\na = 2*a\na = -a\n":close()
368local t = {}
369load(io.lines(file, "L"), nil, nil, t)()
370assert(t.a == -((10 + 34) * 2))
371
372
373-- test for multipe arguments in 'lines'
374io.output(file); io.write"0123456789\n":close()
375for a,b in io.lines(file, 1, 1) do
376 if a == "\n" then assert(b == nil)
377 else assert(tonumber(a) == tonumber(b) - 1)
378 end
379end
380
381for a,b,c in io.lines(file, 1, 2, "a") do
382 assert(a == "0" and b == "12" and c == "3456789\n")
383end
384
385for a,b,c in io.lines(file, "a", 0, 1) do
386 if a == "" then break end
387 assert(a == "0123456789\n" and b == nil and c == nil)
388end
389collectgarbage() -- to close file in previous iteration
390
391io.output(file); io.write"00\n10\n20\n30\n40\n":close()
392for a, b in io.lines(file, "n", "n") do
393 if a == 40 then assert(b == nil)
394 else assert(a == b - 10)
395 end
396end
397
398
399-- test load x lines
400io.output(file);
401io.write[[
402local y
403= X
404X =
405X *
4062 +
407X;
408X =
409X
410- y;
411]]:close()
412_G.X = 1
413assert(not load(io.lines(file)))
414collectgarbage() -- to close file in previous iteration
415load(io.lines(file, "L"))()
416assert(_G.X == 2)
417load(io.lines(file, 1))()
418assert(_G.X == 4)
419load(io.lines(file, 3))()
420assert(_G.X == 8)
421
422print('+')
423
424local x1 = "string\n\n\\com \"\"''coisas [[estranhas]] ]]'"
425io.output(file)
426assert(io.write(string.format("x2 = %q\n-- comment without ending EOS", x1)))
427io.close()
428assert(loadfile(file))()
429assert(x1 == x2)
430print('+')
431assert(os.remove(file))
432assert(not os.remove(file))
433assert(not os.remove(otherfile))
434
435-- testing loadfile
436local function testloadfile (s, expres)
437 io.output(file)
438 if s then io.write(s) end
439 io.close()
440 local res = assert(loadfile(file))()
441 assert(os.remove(file))
442 assert(res == expres)
443end
444
445-- loading empty file
446testloadfile(nil, nil)
447
448-- loading file with initial comment without end of line
449testloadfile("# a non-ending comment", nil)
450
451
452-- checking Unicode BOM in files
453testloadfile("\xEF\xBB\xBF# some comment\nreturn 234", 234)
454testloadfile("\xEF\xBB\xBFreturn 239", 239)
455testloadfile("\xEF\xBB\xBF", nil) -- empty file with a BOM
456
457
458-- checking line numbers in files with initial comments
459testloadfile("# a comment\nreturn require'debug'.getinfo(1).currentline", 2)
460
461
462-- loading binary file
463io.output(io.open(file, "wb"))
464assert(io.write(string.dump(function () return 10, '\0alo\255', 'hi' end)))
465io.close()
466a, b, c = assert(loadfile(file))()
467assert(a == 10 and b == "\0alo\255" and c == "hi")
468assert(os.remove(file))
469
470-- bug in 5.2.1
471do
472 io.output(io.open(file, "wb"))
473 -- save function with no upvalues
474 assert(io.write(string.dump(function () return 1 end)))
475 io.close()
476 f = assert(loadfile(file, "b", {}))
477 assert(type(f) == "function" and f() == 1)
478 assert(os.remove(file))
479end
480
481-- loading binary file with initial comment
482io.output(io.open(file, "wb"))
483assert(io.write("#this is a comment for a binary file\0\n",
484 string.dump(function () return 20, '\0\0\0' end)))
485io.close()
486a, b, c = assert(loadfile(file))()
487assert(a == 20 and b == "\0\0\0" and c == nil)
488assert(os.remove(file))
489
490
491-- 'loadfile' with 'env'
492do
493 local f = io.open(file, 'w')
494 f:write[[
495 if (...) then a = 15; return b, c, d
496 else return _ENV
497 end
498 ]]
499 f:close()
500 local t = {b = 12, c = "xuxu", d = print}
501 local f = assert(loadfile(file, 't', t))
502 local b, c, d = f(1)
503 assert(t.a == 15 and b == 12 and c == t.c and d == print)
504 assert(f() == t)
505 f = assert(loadfile(file, 't', nil))
506 assert(f() == nil)
507 f = assert(loadfile(file))
508 assert(f() == _G)
509 assert(os.remove(file))
510end
511
512
513-- 'loadfile' x modes
514do
515 io.open(file, 'w'):write("return 10"):close()
516 local s, m = loadfile(file, 'b')
517 assert(not s and string.find(m, "a text chunk"))
518 io.open(file, 'w'):write("\27 return 10"):close()
519 local s, m = loadfile(file, 't')
520 assert(not s and string.find(m, "a binary chunk"))
521 assert(os.remove(file))
522end
523
524
525io.output(file)
526assert(io.write("qualquer coisa\n"))
527assert(io.write("mais qualquer coisa"))
528io.close()
529assert(io.output(assert(io.open(otherfile, 'wb')))
530 :write("outra coisa\0\1\3\0\0\0\0\255\0")
531 :close())
532
533local filehandle = assert(io.open(file, 'r+'))
534local otherfilehandle = assert(io.open(otherfile, 'rb'))
535assert(filehandle ~= otherfilehandle)
536assert(type(filehandle) == "userdata")
537assert(filehandle:read('l') == "qualquer coisa")
538io.input(otherfilehandle)
539assert(io.read(string.len"outra coisa") == "outra coisa")
540assert(filehandle:read('l') == "mais qualquer coisa")
541filehandle:close();
542assert(type(filehandle) == "userdata")
543io.input(otherfilehandle)
544assert(io.read(4) == "\0\1\3\0")
545assert(io.read(3) == "\0\0\0")
546assert(io.read(0) == "") -- 255 is not eof
547assert(io.read(1) == "\255")
548assert(io.read('a') == "\0")
549assert(not io.read(0))
550assert(otherfilehandle == io.input())
551otherfilehandle:close()
552assert(os.remove(file))
553assert(os.remove(otherfile))
554collectgarbage()
555
556io.output(file)
557 :write[[
558 123.4 -56e-2 not a number
559second line
560third line
561
562and the rest of the file
563]]
564 :close()
565io.input(file)
566local _,a,b,c,d,e,h,__ = io.read(1, 'n', 'n', 'l', 'l', 'l', 'a', 10)
567assert(io.close(io.input()))
568assert(_ == ' ' and __ == nil)
569assert(type(a) == 'number' and a==123.4 and b==-56e-2)
570assert(d=='second line' and e=='third line')
571assert(h==[[
572
573and the rest of the file
574]])
575assert(os.remove(file))
576collectgarbage()
577
578-- testing buffers
579do
580 local f = assert(io.open(file, "w"))
581 local fr = assert(io.open(file, "r"))
582 assert(f:setvbuf("full", 2000))
583 f:write("x")
584 assert(fr:read("all") == "") -- full buffer; output not written yet
585 f:close()
586 fr:seek("set")
587 assert(fr:read("all") == "x") -- `close' flushes it
588 f = assert(io.open(file), "w")
589 assert(f:setvbuf("no"))
590 f:write("x")
591 fr:seek("set")
592 assert(fr:read("all") == "x") -- no buffer; output is ready
593 f:close()
594 f = assert(io.open(file, "a"))
595 assert(f:setvbuf("line"))
596 f:write("x")
597 fr:seek("set", 1)
598 assert(fr:read("all") == "") -- line buffer; no output without `\n'
599 f:write("a\n"):seek("set", 1)
600 assert(fr:read("all") == "xa\n") -- now we have a whole line
601 f:close(); fr:close()
602 assert(os.remove(file))
603end
604
605
606if not _soft then
607 print("testing large files (> BUFSIZ)")
608 io.output(file)
609 for i=1,5001 do io.write('0123456789123') end
610 io.write('\n12346'):close()
611 io.input(file)
612 local x = io.read('a')
613 io.input():seek('set', 0)
614 local y = io.read(30001)..io.read(1005)..io.read(0)..
615 io.read(1)..io.read(100003)
616 assert(x == y and string.len(x) == 5001*13 + 6)
617 io.input():seek('set', 0)
618 y = io.read() -- huge line
619 assert(x == y..'\n'..io.read())
620 assert(io.read() == nil)
621 io.close(io.input())
622 assert(os.remove(file))
623 x = nil; y = nil
624end
625
626if not _port then
627 local progname
628 do -- get name of running executable
629 local arg = arg or _ARG
630 local i = 0
631 while arg[i] do i = i - 1 end
632 progname = '"' .. arg[i + 1] .. '"'
633 end
634 print("testing popen/pclose and execute")
635 local tests = {
636 -- command, what, code
637 {"ls > /dev/null", "ok"},
638 {"not-to-be-found-command", "exit"},
639 {"exit 3", "exit", 3},
640 {"exit 129", "exit", 129},
641 {"kill -s HUP $$", "signal", 1},
642 {"kill -s KILL $$", "signal", 9},
643 {"sh -c 'kill -s HUP $$'", "exit"},
644 {progname .. ' -e " "', "ok"},
645 {progname .. ' -e "os.exit(0, true)"', "ok"},
646 {progname .. ' -e "os.exit(20, true)"', "exit", 20},
647 }
648 print("\n(some error messages are expected now)")
649 for _, v in ipairs(tests) do
650 local x, y, z = io.popen(v[1]):close()
651 local x1, y1, z1 = os.execute(v[1])
652 assert(x == x1 and y == y1 and z == z1)
653 if v[2] == "ok" then
654 assert(x and y == 'exit' and z == 0)
655 else
656 assert(not x and y == v[2]) -- correct status and 'what'
657 -- correct code if known (but always different from 0)
658 assert((v[3] == nil and z > 0) or v[3] == z)
659 end
660 end
661end
662
663
664-- testing tmpfile
665f = io.tmpfile()
666assert(io.type(f) == "file")
667f:write("alo")
668f:seek("set")
669assert(f:read"a" == "alo")
670
671end --}
672
673print'+'
674
675print("testing date/time")
676
677assert(os.date("") == "")
678assert(os.date("!") == "")
679assert(os.date("\0\0") == "\0\0")
680assert(os.date("!\0\0") == "\0\0")
681local x = string.rep("a", 10000)
682assert(os.date(x) == x)
683local t = os.time()
684D = os.date("*t", t)
685assert(os.date(string.rep("%d", 1000), t) ==
686 string.rep(os.date("%d", t), 1000))
687assert(os.date(string.rep("%", 200)) == string.rep("%", 100))
688
689local t = os.time()
690D = os.date("*t", t)
691load(os.date([[assert(D.year==%Y and D.month==%m and D.day==%d and
692 D.hour==%H and D.min==%M and D.sec==%S and
693 D.wday==%w+1 and D.yday==%j and type(D.isdst) == 'boolean')]], t))()
694
695checkerr("invalid conversion specifier", os.date, "%")
696checkerr("invalid conversion specifier", os.date, "%9")
697checkerr("invalid conversion specifier", os.date, "%")
698checkerr("invalid conversion specifier", os.date, "%O")
699checkerr("invalid conversion specifier", os.date, "%E")
700checkerr("invalid conversion specifier", os.date, "%Ea")
701
702checkerr("not an integer", os.time, {year=1000, month=1, day=1, hour='x'})
703checkerr("not an integer", os.time, {year=1000, month=1, day=1, hour=1.5})
704
705checkerr("missing", os.time, {hour = 12}) -- missing date
706
707if not _port then
708 -- test Posix-specific modifiers
709 assert(type(os.date("%Ex")) == 'string')
710 assert(type(os.date("%Oy")) == 'string')
711
712
713 -- test out-of-range dates (at least for Unix)
714 if maxint >= 2^62 then -- cannot do these tests in Small Lua
715 -- no arith overflows
716 checkerr("out-of-bound", os.time, {year = -maxint, month = 1, day = 1})
717 if string.packsize("i") == 4 then -- 4-byte ints
718 if testerr("out-of-bound", os.date, "%Y", 2^40) then
719 -- time_t has 4 bytes and therefore cannot represent year 4000
720 print(" 4-byte time_t")
721 checkerr("cannot be represented", os.time, {year=4000, month=1, day=1})
722 else
723 -- time_t has 8 bytes; an int year cannot represent a huge time
724 print(" 8-byte time_t")
725 checkerr("cannot be represented", os.date, "%Y", 2^60)
726 -- it should have no problems with year 4000
727 assert(tonumber(os.time{year=4000, month=1, day=1}))
728 end
729 else -- 8-byte ints
730 -- assume time_t has 8 bytes too
731 print(" 8-byte time_t")
732 assert(tonumber(os.date("%Y", 2^60)))
733 -- but still cannot represent a huge year
734 checkerr("cannot be represented", os.time, {year=2^60, month=1, day=1})
735 end
736 end
737end
738
739
740D = os.date("!*t", t)
741load(os.date([[!assert(D.year==%Y and D.month==%m and D.day==%d and
742 D.hour==%H and D.min==%M and D.sec==%S and
743 D.wday==%w+1 and D.yday==%j and type(D.isdst) == 'boolean')]], t))()
744
745do
746 local D = os.date("*t")
747 local t = os.time(D)
748 assert(type(D.isdst) == 'boolean')
749 D.isdst = nil
750 local t1 = os.time(D)
751 assert(t == t1) -- if isdst is absent uses correct default
752end
753
754t = os.time(D)
755D.year = D.year-1;
756local t1 = os.time(D)
757-- allow for leap years
758assert(math.abs(os.difftime(t,t1)/(24*3600) - 365) < 2)
759
760-- should not take more than 1 second to execute these two lines
761t = os.time()
762t1 = os.time(os.date("*t"))
763local diff = os.difftime(t1,t)
764assert(0 <= diff and diff <= 1)
765diff = os.difftime(t,t1)
766assert(-1 <= diff and diff <= 0)
767
768local t1 = os.time{year=2000, month=10, day=1, hour=23, min=12}
769local t2 = os.time{year=2000, month=10, day=1, hour=23, min=10, sec=19}
770assert(os.difftime(t1,t2) == 60*2-19)
771
772-- since 5.3.3, 'os.time' normalizes table fields
773t1 = {year = 2005, month = 1, day = 1, hour = 1, min = 0, sec = -3602}
774os.time(t1)
775assert(t1.day == 31 and t1.month == 12 and t1.year == 2004 and
776 t1.hour == 23 and t1.min == 59 and t1.sec == 58 and
777 t1.yday == 366)
778
779io.output(io.stdout)
780local t = os.date('%d %m %Y %H %M %S')
781local d, m, a, h, min, s = string.match(t,
782 "(%d+) (%d+) (%d+) (%d+) (%d+) (%d+)")
783d = tonumber(d)
784m = tonumber(m)
785a = tonumber(a)
786h = tonumber(h)
787min = tonumber(min)
788s = tonumber(s)
789io.write(string.format('test done on %2.2d/%2.2d/%d', d, m, a))
790io.write(string.format(', at %2.2d:%2.2d:%2.2d\n', h, min, s))
791io.write(string.format('%s\n', _VERSION))
792
793
diff --git a/testes/gc.lua b/testes/gc.lua
new file mode 100644
index 00000000..93fd6d69
--- /dev/null
+++ b/testes/gc.lua
@@ -0,0 +1,624 @@
1-- $Id: gc.lua,v 1.72 2016/11/07 13:11:28 roberto Exp $
2-- See Copyright Notice in file all.lua
3
4print('testing garbage collection')
5
6local debug = require"debug"
7
8collectgarbage()
9
10assert(collectgarbage("isrunning"))
11
12local function gcinfo () return collectgarbage"count" * 1024 end
13
14
15-- test weird parameters
16do
17 -- save original parameters
18 local a = collectgarbage("setpause", 200)
19 local b = collectgarbage("setstepmul", 200)
20 local t = {0, 2, 10, 90, 500, 5000, 30000, 0x7ffffffe}
21 for i = 1, #t do
22 local p = t[i]
23 for j = 1, #t do
24 local m = t[j]
25 collectgarbage("setpause", p)
26 collectgarbage("setstepmul", m)
27 collectgarbage("step", 0)
28 collectgarbage("step", 10000)
29 end
30 end
31 -- restore original parameters
32 collectgarbage("setpause", a)
33 collectgarbage("setstepmul", b)
34 collectgarbage()
35end
36
37
38_G["while"] = 234
39
40limit = 5000
41
42
43local function GC1 ()
44 local u
45 local b -- must be declared after 'u' (to be above it in the stack)
46 local finish = false
47 u = setmetatable({}, {__gc = function () finish = true end})
48 b = {34}
49 repeat u = {} until finish
50 assert(b[1] == 34) -- 'u' was collected, but 'b' was not
51
52 finish = false; local i = 1
53 u = setmetatable({}, {__gc = function () finish = true end})
54 repeat i = i + 1; u = tostring(i) .. tostring(i) until finish
55 assert(b[1] == 34) -- 'u' was collected, but 'b' was not
56
57 finish = false
58 u = setmetatable({}, {__gc = function () finish = true end})
59 repeat local i; u = function () return i end until finish
60 assert(b[1] == 34) -- 'u' was collected, but 'b' was not
61end
62
63local function GC2 ()
64 local u
65 local finish = false
66 u = {setmetatable({}, {__gc = function () finish = true end})}
67 b = {34}
68 repeat u = {{}} until finish
69 assert(b[1] == 34) -- 'u' was collected, but 'b' was not
70
71 finish = false; local i = 1
72 u = {setmetatable({}, {__gc = function () finish = true end})}
73 repeat i = i + 1; u = {tostring(i) .. tostring(i)} until finish
74 assert(b[1] == 34) -- 'u' was collected, but 'b' was not
75
76 finish = false
77 u = {setmetatable({}, {__gc = function () finish = true end})}
78 repeat local i; u = {function () return i end} until finish
79 assert(b[1] == 34) -- 'u' was collected, but 'b' was not
80end
81
82local function GC() GC1(); GC2() end
83
84
85contCreate = 0
86
87print('tables')
88while contCreate <= limit do
89 local a = {}; a = nil
90 contCreate = contCreate+1
91end
92
93a = "a"
94
95contCreate = 0
96print('strings')
97while contCreate <= limit do
98 a = contCreate .. "b";
99 a = string.gsub(a, '(%d%d*)', string.upper)
100 a = "a"
101 contCreate = contCreate+1
102end
103
104
105contCreate = 0
106
107a = {}
108
109print('functions')
110function a:test ()
111 while contCreate <= limit do
112 load(string.format("function temp(a) return 'a%d' end", contCreate), "")()
113 assert(temp() == string.format('a%d', contCreate))
114 contCreate = contCreate+1
115 end
116end
117
118a:test()
119
120-- collection of functions without locals, globals, etc.
121do local f = function () end end
122
123
124print("functions with errors")
125prog = [[
126do
127 a = 10;
128 function foo(x,y)
129 a = sin(a+0.456-0.23e-12);
130 return function (z) return sin(%x+z) end
131 end
132 local x = function (w) a=a+w; end
133end
134]]
135do
136 local step = 1
137 if _soft then step = 13 end
138 for i=1, string.len(prog), step do
139 for j=i, string.len(prog), step do
140 pcall(load(string.sub(prog, i, j), ""))
141 end
142 end
143end
144
145foo = nil
146print('long strings')
147x = "01234567890123456789012345678901234567890123456789012345678901234567890123456789"
148assert(string.len(x)==80)
149s = ''
150n = 0
151k = math.min(300, (math.maxinteger // 80) // 2)
152while n < k do s = s..x; n=n+1; j=tostring(n) end
153assert(string.len(s) == k*80)
154s = string.sub(s, 1, 10000)
155s, i = string.gsub(s, '(%d%d%d%d)', '')
156assert(i==10000 // 4)
157s = nil
158x = nil
159
160assert(_G["while"] == 234)
161
162
163print("steps")
164
165print("steps (2)")
166
167local function dosteps (siz)
168 assert(not collectgarbage("isrunning"))
169 collectgarbage()
170 assert(not collectgarbage("isrunning"))
171 local a = {}
172 for i=1,100 do a[i] = {{}}; local b = {} end
173 local x = gcinfo()
174 local i = 0
175 repeat -- do steps until it completes a collection cycle
176 i = i+1
177 until collectgarbage("step", siz)
178 assert(gcinfo() < x)
179 return i
180end
181
182collectgarbage"stop"
183
184if not _port then
185 -- test the "size" of basic GC steps (whatever they mean...)
186 assert(dosteps(0) > 10)
187 assert(dosteps(10) < dosteps(2))
188end
189
190-- collector should do a full collection with so many steps
191assert(dosteps(20000) == 1)
192assert(collectgarbage("step", 20000) == true)
193assert(collectgarbage("step", 20000) == true)
194
195assert(not collectgarbage("isrunning"))
196collectgarbage"restart"
197assert(collectgarbage("isrunning"))
198
199
200if not _port then
201 -- test the pace of the collector
202 collectgarbage(); collectgarbage()
203 local x = gcinfo()
204 collectgarbage"stop"
205 assert(not collectgarbage("isrunning"))
206 repeat
207 local a = {}
208 until gcinfo() > 3 * x
209 collectgarbage"restart"
210 assert(collectgarbage("isrunning"))
211 repeat
212 local a = {}
213 until gcinfo() <= x * 2
214end
215
216
217print("clearing tables")
218lim = 15
219a = {}
220-- fill a with `collectable' indices
221for i=1,lim do a[{}] = i end
222b = {}
223for k,v in pairs(a) do b[k]=v end
224-- remove all indices and collect them
225for n in pairs(b) do
226 a[n] = nil
227 assert(type(n) == 'table' and next(n) == nil)
228 collectgarbage()
229end
230b = nil
231collectgarbage()
232for n in pairs(a) do error'cannot be here' end
233for i=1,lim do a[i] = i end
234for i=1,lim do assert(a[i] == i) end
235
236
237print('weak tables')
238a = {}; setmetatable(a, {__mode = 'k'});
239-- fill a with some `collectable' indices
240for i=1,lim do a[{}] = i end
241-- and some non-collectable ones
242for i=1,lim do a[i] = i end
243for i=1,lim do local s=string.rep('@', i); a[s] = s..'#' end
244collectgarbage()
245local i = 0
246for k,v in pairs(a) do assert(k==v or k..'#'==v); i=i+1 end
247assert(i == 2*lim)
248
249a = {}; setmetatable(a, {__mode = 'v'});
250a[1] = string.rep('b', 21)
251collectgarbage()
252assert(a[1]) -- strings are *values*
253a[1] = nil
254-- fill a with some `collectable' values (in both parts of the table)
255for i=1,lim do a[i] = {} end
256for i=1,lim do a[i..'x'] = {} end
257-- and some non-collectable ones
258for i=1,lim do local t={}; a[t]=t end
259for i=1,lim do a[i+lim]=i..'x' end
260collectgarbage()
261local i = 0
262for k,v in pairs(a) do assert(k==v or k-lim..'x' == v); i=i+1 end
263assert(i == 2*lim)
264
265a = {}; setmetatable(a, {__mode = 'vk'});
266local x, y, z = {}, {}, {}
267-- keep only some items
268a[1], a[2], a[3] = x, y, z
269a[string.rep('$', 11)] = string.rep('$', 11)
270-- fill a with some `collectable' values
271for i=4,lim do a[i] = {} end
272for i=1,lim do a[{}] = i end
273for i=1,lim do local t={}; a[t]=t end
274collectgarbage()
275assert(next(a) ~= nil)
276local i = 0
277for k,v in pairs(a) do
278 assert((k == 1 and v == x) or
279 (k == 2 and v == y) or
280 (k == 3 and v == z) or k==v);
281 i = i+1
282end
283assert(i == 4)
284x,y,z=nil
285collectgarbage()
286assert(next(a) == string.rep('$', 11))
287
288
289-- 'bug' in 5.1
290a = {}
291local t = {x = 10}
292local C = setmetatable({key = t}, {__mode = 'v'})
293local C1 = setmetatable({[t] = 1}, {__mode = 'k'})
294a.x = t -- this should not prevent 't' from being removed from
295 -- weak table 'C' by the time 'a' is finalized
296
297setmetatable(a, {__gc = function (u)
298 assert(C.key == nil)
299 assert(type(next(C1)) == 'table')
300 end})
301
302a, t = nil
303collectgarbage()
304collectgarbage()
305assert(next(C) == nil and next(C1) == nil)
306C, C1 = nil
307
308
309-- ephemerons
310local mt = {__mode = 'k'}
311a = {{10},{20},{30},{40}}; setmetatable(a, mt)
312x = nil
313for i = 1, 100 do local n = {}; a[n] = {k = {x}}; x = n end
314GC()
315local n = x
316local i = 0
317while n do n = a[n].k[1]; i = i + 1 end
318assert(i == 100)
319x = nil
320GC()
321for i = 1, 4 do assert(a[i][1] == i * 10); a[i] = nil end
322assert(next(a) == nil)
323
324local K = {}
325a[K] = {}
326for i=1,10 do a[K][i] = {}; a[a[K][i]] = setmetatable({}, mt) end
327x = nil
328local k = 1
329for j = 1,100 do
330 local n = {}; local nk = k%10 + 1
331 a[a[K][nk]][n] = {x, k = k}; x = n; k = nk
332end
333GC()
334local n = x
335local i = 0
336while n do local t = a[a[K][k]][n]; n = t[1]; k = t.k; i = i + 1 end
337assert(i == 100)
338K = nil
339GC()
340-- assert(next(a) == nil)
341
342
343-- testing errors during GC
344do
345collectgarbage("stop") -- stop collection
346local u = {}
347local s = {}; setmetatable(s, {__mode = 'k'})
348setmetatable(u, {__gc = function (o)
349 local i = s[o]
350 s[i] = true
351 assert(not s[i - 1]) -- check proper finalization order
352 if i == 8 then error("here") end -- error during GC
353end})
354
355for i = 6, 10 do
356 local n = setmetatable({}, getmetatable(u))
357 s[n] = i
358end
359
360assert(not pcall(collectgarbage))
361for i = 8, 10 do assert(s[i]) end
362
363for i = 1, 5 do
364 local n = setmetatable({}, getmetatable(u))
365 s[n] = i
366end
367
368collectgarbage()
369for i = 1, 10 do assert(s[i]) end
370
371getmetatable(u).__gc = false
372
373
374-- __gc errors with non-string messages
375setmetatable({}, {__gc = function () error{} end})
376local a, b = pcall(collectgarbage)
377assert(not a and type(b) == "string" and string.find(b, "error in __gc"))
378
379end
380print '+'
381
382
383-- testing userdata
384if T==nil then
385 (Message or print)('\n >>> testC not active: skipping userdata GC tests <<<\n')
386
387else
388
389 local function newproxy(u)
390 return debug.setmetatable(T.newuserdata(0), debug.getmetatable(u))
391 end
392
393 collectgarbage("stop") -- stop collection
394 local u = newproxy(nil)
395 debug.setmetatable(u, {__gc = true})
396 local s = 0
397 local a = {[u] = 0}; setmetatable(a, {__mode = 'vk'})
398 for i=1,10 do a[newproxy(u)] = i end
399 for k in pairs(a) do assert(getmetatable(k) == getmetatable(u)) end
400 local a1 = {}; for k,v in pairs(a) do a1[k] = v end
401 for k,v in pairs(a1) do a[v] = k end
402 for i =1,10 do assert(a[i]) end
403 getmetatable(u).a = a1
404 getmetatable(u).u = u
405 do
406 local u = u
407 getmetatable(u).__gc = function (o)
408 assert(a[o] == 10-s)
409 assert(a[10-s] == nil) -- udata already removed from weak table
410 assert(getmetatable(o) == getmetatable(u))
411 assert(getmetatable(o).a[o] == 10-s)
412 s=s+1
413 end
414 end
415 a1, u = nil
416 assert(next(a) ~= nil)
417 collectgarbage()
418 assert(s==11)
419 collectgarbage()
420 assert(next(a) == nil) -- finalized keys are removed in two cycles
421end
422
423
424-- __gc x weak tables
425local u = setmetatable({}, {__gc = true})
426-- __gc metamethod should be collected before running
427setmetatable(getmetatable(u), {__mode = "v"})
428getmetatable(u).__gc = function (o) os.exit(1) end -- cannot happen
429u = nil
430collectgarbage()
431
432local u = setmetatable({}, {__gc = true})
433local m = getmetatable(u)
434m.x = {[{0}] = 1; [0] = {1}}; setmetatable(m.x, {__mode = "kv"});
435m.__gc = function (o)
436 assert(next(getmetatable(o).x) == nil)
437 m = 10
438end
439u, m = nil
440collectgarbage()
441assert(m==10)
442
443
444-- errors during collection
445u = setmetatable({}, {__gc = function () error "!!!" end})
446u = nil
447assert(not pcall(collectgarbage))
448
449
450if not _soft then
451 print("deep structures")
452 local a = {}
453 for i = 1,200000 do
454 a = {next = a}
455 end
456 collectgarbage()
457end
458
459-- create many threads with self-references and open upvalues
460print("self-referenced threads")
461local thread_id = 0
462local threads = {}
463
464local function fn (thread)
465 local x = {}
466 threads[thread_id] = function()
467 thread = x
468 end
469 coroutine.yield()
470end
471
472while thread_id < 1000 do
473 local thread = coroutine.create(fn)
474 coroutine.resume(thread, thread)
475 thread_id = thread_id + 1
476end
477
478
479-- Create a closure (function inside 'f') with an upvalue ('param') that
480-- points (through a table) to the closure itself and to the thread
481-- ('co' and the initial value of 'param') where closure is running.
482-- Then, assert that table (and therefore everything else) will be
483-- collected.
484do
485 local collected = false -- to detect collection
486 collectgarbage(); collectgarbage("stop")
487 do
488 local function f (param)
489 ;(function ()
490 assert(type(f) == 'function' and type(param) == 'thread')
491 param = {param, f}
492 setmetatable(param, {__gc = function () collected = true end})
493 coroutine.yield(100)
494 end)()
495 end
496 local co = coroutine.create(f)
497 assert(coroutine.resume(co, co))
498 end
499 -- Now, thread and closure are not reacheable any more;
500 -- two collections are needed to break cycle
501 collectgarbage()
502 assert(not collected)
503 collectgarbage()
504 assert(collected)
505 collectgarbage("restart")
506end
507
508
509do
510 collectgarbage()
511 collectgarbage"stop"
512 local x = gcinfo()
513 repeat
514 for i=1,1000 do _ENV.a = {} end
515 collectgarbage("step", 0) -- steps should not unblock the collector
516 until gcinfo() > 2 * x
517 collectgarbage"restart"
518end
519
520
521if T then -- tests for weird cases collecting upvalues
522
523 local function foo ()
524 local a = {x = 20}
525 coroutine.yield(function () return a.x end) -- will run collector
526 assert(a.x == 20) -- 'a' is 'ok'
527 a = {x = 30} -- create a new object
528 assert(T.gccolor(a) == "white") -- of course it is new...
529 coroutine.yield(100) -- 'a' is still local to this thread
530 end
531
532 local t = setmetatable({}, {__mode = "kv"})
533 collectgarbage(); collectgarbage('stop')
534 -- create coroutine in a weak table, so it will never be marked
535 t.co = coroutine.wrap(foo)
536 local f = t.co() -- create function to access local 'a'
537 T.gcstate("atomic") -- ensure all objects are traversed
538 assert(T.gcstate() == "atomic")
539 assert(t.co() == 100) -- resume coroutine, creating new table for 'a'
540 assert(T.gccolor(t.co) == "white") -- thread was not traversed
541 T.gcstate("pause") -- collect thread, but should mark 'a' before that
542 assert(t.co == nil and f() == 30) -- ensure correct access to 'a'
543
544 collectgarbage("restart")
545
546 -- test barrier in sweep phase (advance cleaning of upvalue to white)
547 local u = T.newuserdata(0) -- create a userdata
548 collectgarbage()
549 collectgarbage"stop"
550 T.gcstate"atomic"
551 T.gcstate"sweepallgc"
552 local x = {}
553 assert(T.gccolor(u) == "black") -- upvalue is "old" (black)
554 assert(T.gccolor(x) == "white") -- table is "new" (white)
555 debug.setuservalue(u, x) -- trigger barrier
556 assert(T.gccolor(u) == "white") -- upvalue changed to white
557 collectgarbage"restart"
558
559 print"+"
560end
561
562
563if T then
564 local debug = require "debug"
565 collectgarbage("stop")
566 local x = T.newuserdata(0)
567 local y = T.newuserdata(0)
568 debug.setmetatable(y, {__gc = true}) -- bless the new udata before...
569 debug.setmetatable(x, {__gc = true}) -- ...the old one
570 assert(T.gccolor(y) == "white")
571 T.checkmemory()
572 collectgarbage("restart")
573end
574
575
576if T then
577 print("emergency collections")
578 collectgarbage()
579 collectgarbage()
580 T.totalmem(T.totalmem() + 200)
581 for i=1,200 do local a = {} end
582 T.totalmem(0)
583 collectgarbage()
584 local t = T.totalmem("table")
585 local a = {{}, {}, {}} -- create 4 new tables
586 assert(T.totalmem("table") == t + 4)
587 t = T.totalmem("function")
588 a = function () end -- create 1 new closure
589 assert(T.totalmem("function") == t + 1)
590 t = T.totalmem("thread")
591 a = coroutine.create(function () end) -- create 1 new coroutine
592 assert(T.totalmem("thread") == t + 1)
593end
594
595-- create an object to be collected when state is closed
596do
597 local setmetatable,assert,type,print,getmetatable =
598 setmetatable,assert,type,print,getmetatable
599 local tt = {}
600 tt.__gc = function (o)
601 assert(getmetatable(o) == tt)
602 -- create new objects during GC
603 local a = 'xuxu'..(10+3)..'joao', {}
604 ___Glob = o -- ressurect object!
605 setmetatable({}, tt) -- creates a new one with same metatable
606 print(">>> closing state " .. "<<<\n")
607 end
608 local u = setmetatable({}, tt)
609 ___Glob = {u} -- avoid object being collected before program end
610end
611
612-- create several objects to raise errors when collected while closing state
613do
614 local mt = {__gc = function (o) return o + 1 end}
615 for i = 1,10 do
616 -- create object and preserve it until the end
617 table.insert(___Glob, setmetatable({}, mt))
618 end
619end
620
621-- just to make sure
622assert(collectgarbage'isrunning')
623
624print('OK')
diff --git a/testes/goto.lua b/testes/goto.lua
new file mode 100644
index 00000000..0372aa9d
--- /dev/null
+++ b/testes/goto.lua
@@ -0,0 +1,232 @@
1-- $Id: goto.lua,v 1.13 2016/11/07 13:11:28 roberto Exp $
2-- See Copyright Notice in file all.lua
3
4collectgarbage()
5
6local function errmsg (code, m)
7 local st, msg = load(code)
8 assert(not st and string.find(msg, m))
9end
10
11-- cannot see label inside block
12errmsg([[ goto l1; do ::l1:: end ]], "label 'l1'")
13errmsg([[ do ::l1:: end goto l1; ]], "label 'l1'")
14
15-- repeated label
16errmsg([[ ::l1:: ::l1:: ]], "label 'l1'")
17
18
19-- undefined label
20errmsg([[ goto l1; local aa ::l1:: ::l2:: print(3) ]], "local 'aa'")
21
22-- jumping over variable definition
23errmsg([[
24do local bb, cc; goto l1; end
25local aa
26::l1:: print(3)
27]], "local 'aa'")
28
29-- jumping into a block
30errmsg([[ do ::l1:: end goto l1 ]], "label 'l1'")
31errmsg([[ goto l1 do ::l1:: end ]], "label 'l1'")
32
33-- cannot continue a repeat-until with variables
34errmsg([[
35 repeat
36 if x then goto cont end
37 local xuxu = 10
38 ::cont::
39 until xuxu < x
40]], "local 'xuxu'")
41
42-- simple gotos
43local x
44do
45 local y = 12
46 goto l1
47 ::l2:: x = x + 1; goto l3
48 ::l1:: x = y; goto l2
49end
50::l3:: ::l3_1:: assert(x == 13)
51
52
53-- long labels
54do
55 local prog = [[
56 do
57 local a = 1
58 goto l%sa; a = a + 1
59 ::l%sa:: a = a + 10
60 goto l%sb; a = a + 2
61 ::l%sb:: a = a + 20
62 return a
63 end
64 ]]
65 local label = string.rep("0123456789", 40)
66 prog = string.format(prog, label, label, label, label)
67 assert(assert(load(prog))() == 31)
68end
69
70-- goto to correct label when nested
71do goto l3; ::l3:: end -- does not loop jumping to previous label 'l3'
72
73-- ok to jump over local dec. to end of block
74do
75 goto l1
76 local a = 23
77 x = a
78 ::l1::;
79end
80
81while true do
82 goto l4
83 goto l1 -- ok to jump over local dec. to end of block
84 goto l1 -- multiple uses of same label
85 local x = 45
86 ::l1:: ;;;
87end
88::l4:: assert(x == 13)
89
90if print then
91 goto l1 -- ok to jump over local dec. to end of block
92 error("should not be here")
93 goto l2 -- ok to jump over local dec. to end of block
94 local x
95 ::l1:: ; ::l2:: ;;
96else end
97
98-- to repeat a label in a different function is OK
99local function foo ()
100 local a = {}
101 goto l3
102 ::l1:: a[#a + 1] = 1; goto l2;
103 ::l2:: a[#a + 1] = 2; goto l5;
104 ::l3::
105 ::l3a:: a[#a + 1] = 3; goto l1;
106 ::l4:: a[#a + 1] = 4; goto l6;
107 ::l5:: a[#a + 1] = 5; goto l4;
108 ::l6:: assert(a[1] == 3 and a[2] == 1 and a[3] == 2 and
109 a[4] == 5 and a[5] == 4)
110 if not a[6] then a[6] = true; goto l3a end -- do it twice
111end
112
113::l6:: foo()
114
115
116do -- bug in 5.2 -> 5.3.2
117 local x
118 ::L1::
119 local y -- cannot join this SETNIL with previous one
120 assert(y == nil)
121 y = true
122 if x == nil then
123 x = 1
124 goto L1
125 else
126 x = x + 1
127 end
128 assert(x == 2 and y == true)
129end
130
131--------------------------------------------------------------------------------
132-- testing closing of upvalues
133
134local debug = require 'debug'
135
136local function foo ()
137 local t = {}
138 do
139 local i = 1
140 local a, b, c, d
141 t[1] = function () return a, b, c, d end
142 ::l1::
143 local b
144 do
145 local c
146 t[#t + 1] = function () return a, b, c, d end -- t[2], t[4], t[6]
147 if i > 2 then goto l2 end
148 do
149 local d
150 t[#t + 1] = function () return a, b, c, d end -- t[3], t[5]
151 i = i + 1
152 local a
153 goto l1
154 end
155 end
156 end
157 ::l2:: return t
158end
159
160local a = foo()
161assert(#a == 6)
162
163-- all functions share same 'a'
164for i = 2, 6 do
165 assert(debug.upvalueid(a[1], 1) == debug.upvalueid(a[i], 1))
166end
167
168-- 'b' and 'c' are shared among some of them
169for i = 2, 6 do
170 -- only a[1] uses external 'b'/'b'
171 assert(debug.upvalueid(a[1], 2) ~= debug.upvalueid(a[i], 2))
172 assert(debug.upvalueid(a[1], 3) ~= debug.upvalueid(a[i], 3))
173end
174
175for i = 3, 5, 2 do
176 -- inner functions share 'b'/'c' with previous ones
177 assert(debug.upvalueid(a[i], 2) == debug.upvalueid(a[i - 1], 2))
178 assert(debug.upvalueid(a[i], 3) == debug.upvalueid(a[i - 1], 3))
179 -- but not with next ones
180 assert(debug.upvalueid(a[i], 2) ~= debug.upvalueid(a[i + 1], 2))
181 assert(debug.upvalueid(a[i], 3) ~= debug.upvalueid(a[i + 1], 3))
182end
183
184-- only external 'd' is shared
185for i = 2, 6, 2 do
186 assert(debug.upvalueid(a[1], 4) == debug.upvalueid(a[i], 4))
187end
188
189-- internal 'd's are all different
190for i = 3, 5, 2 do
191 for j = 1, 6 do
192 assert((debug.upvalueid(a[i], 4) == debug.upvalueid(a[j], 4))
193 == (i == j))
194 end
195end
196
197--------------------------------------------------------------------------------
198-- testing if x goto optimizations
199
200local function testG (a)
201 if a == 1 then
202 goto l1
203 error("should never be here!")
204 elseif a == 2 then goto l2
205 elseif a == 3 then goto l3
206 elseif a == 4 then
207 goto l1 -- go to inside the block
208 error("should never be here!")
209 ::l1:: a = a + 1 -- must go to 'if' end
210 else
211 goto l4
212 ::l4a:: a = a * 2; goto l4b
213 error("should never be here!")
214 ::l4:: goto l4a
215 error("should never be here!")
216 ::l4b::
217 end
218 do return a end
219 ::l2:: do return "2" end
220 ::l3:: do return "3" end
221 ::l1:: return "1"
222end
223
224assert(testG(1) == "1")
225assert(testG(2) == "2")
226assert(testG(3) == "3")
227assert(testG(4) == 5)
228assert(testG(5) == 10)
229--------------------------------------------------------------------------------
230
231
232print'OK'
diff --git a/testes/heavy.lua b/testes/heavy.lua
new file mode 100644
index 00000000..889d9f49
--- /dev/null
+++ b/testes/heavy.lua
@@ -0,0 +1,72 @@
1-- $Id: heavy.lua,v 1.4 2016/11/07 13:11:28 roberto Exp $
2-- See Copyright Notice in file all.lua
3
4print("creating a string too long")
5do
6 local st, msg = pcall(function ()
7 local a = "x"
8 while true do
9 a = a .. a.. a.. a.. a.. a.. a.. a.. a.. a
10 .. a .. a.. a.. a.. a.. a.. a.. a.. a.. a
11 .. a .. a.. a.. a.. a.. a.. a.. a.. a.. a
12 .. a .. a.. a.. a.. a.. a.. a.. a.. a.. a
13 .. a .. a.. a.. a.. a.. a.. a.. a.. a.. a
14 .. a .. a.. a.. a.. a.. a.. a.. a.. a.. a
15 .. a .. a.. a.. a.. a.. a.. a.. a.. a.. a
16 .. a .. a.. a.. a.. a.. a.. a.. a.. a.. a
17 .. a .. a.. a.. a.. a.. a.. a.. a.. a.. a
18 .. a .. a.. a.. a.. a.. a.. a.. a.. a.. a
19 print(string.format("string with %d bytes", #a))
20 end
21 end)
22 assert(not st and
23 (string.find(msg, "string length overflow") or
24 string.find(msg, "not enough memory")))
25end
26print('+')
27
28
29local function loadrep (x, what)
30 local p = 1<<20
31 local s = string.rep(x, p)
32 local count = 0
33 local function f()
34 count = count + p
35 if count % (0x80*p) == 0 then
36 io.stderr:write("(", string.format("0x%x", count), ")")
37 end
38 return s
39 end
40 local st, msg = load(f, "=big")
41 print(string.format("\ntotal: 0x%x %s", count, what))
42 return st, msg
43end
44
45
46print("loading chunk with too many lines")
47do
48 local st, msg = loadrep("\n", "lines")
49 assert(not st and string.find(msg, "too many lines"))
50end
51print('+')
52
53
54print("loading chunk with huge identifier")
55do
56 local st, msg = loadrep("a", "chars")
57 assert(not st and
58 (string.find(msg, "lexical element too long") or
59 string.find(msg, "not enough memory")))
60end
61print('+')
62
63
64print("loading chunk with too many instructions")
65do
66 local st, msg = loadrep("a = 10; ", "instructions")
67 print(st, msg)
68end
69print('+')
70
71
72print "OK"
diff --git a/testes/libs/lib1.c b/testes/libs/lib1.c
new file mode 100644
index 00000000..56b6ef41
--- /dev/null
+++ b/testes/libs/lib1.c
@@ -0,0 +1,44 @@
1#include "lua.h"
2#include "lauxlib.h"
3
4static int id (lua_State *L) {
5 return lua_gettop(L);
6}
7
8
9static const struct luaL_Reg funcs[] = {
10 {"id", id},
11 {NULL, NULL}
12};
13
14
15/* function used by lib11.c */
16LUAMOD_API int lib1_export (lua_State *L) {
17 lua_pushstring(L, "exported");
18 return 1;
19}
20
21
22LUAMOD_API int onefunction (lua_State *L) {
23 luaL_checkversion(L);
24 lua_settop(L, 2);
25 lua_pushvalue(L, 1);
26 return 2;
27}
28
29
30LUAMOD_API int anotherfunc (lua_State *L) {
31 luaL_checkversion(L);
32 lua_pushfstring(L, "%d%%%d\n", (int)lua_tointeger(L, 1),
33 (int)lua_tointeger(L, 2));
34 return 1;
35}
36
37
38LUAMOD_API int luaopen_lib1_sub (lua_State *L) {
39 lua_setglobal(L, "y"); /* 2nd arg: extra value (file name) */
40 lua_setglobal(L, "x"); /* 1st arg: module name */
41 luaL_newlib(L, funcs);
42 return 1;
43}
44
diff --git a/testes/libs/lib11.c b/testes/libs/lib11.c
new file mode 100644
index 00000000..377d0c48
--- /dev/null
+++ b/testes/libs/lib11.c
@@ -0,0 +1,10 @@
1#include "lua.h"
2
3/* function from lib1.c */
4int lib1_export (lua_State *L);
5
6LUAMOD_API int luaopen_lib11 (lua_State *L) {
7 return lib1_export(L);
8}
9
10
diff --git a/testes/libs/lib2.c b/testes/libs/lib2.c
new file mode 100644
index 00000000..bc9651ee
--- /dev/null
+++ b/testes/libs/lib2.c
@@ -0,0 +1,23 @@
1#include "lua.h"
2#include "lauxlib.h"
3
4static int id (lua_State *L) {
5 return lua_gettop(L);
6}
7
8
9static const struct luaL_Reg funcs[] = {
10 {"id", id},
11 {NULL, NULL}
12};
13
14
15LUAMOD_API int luaopen_lib2 (lua_State *L) {
16 lua_settop(L, 2);
17 lua_setglobal(L, "y"); /* y gets 2nd parameter */
18 lua_setglobal(L, "x"); /* x gets 1st parameter */
19 luaL_newlib(L, funcs);
20 return 1;
21}
22
23
diff --git a/testes/libs/lib21.c b/testes/libs/lib21.c
new file mode 100644
index 00000000..a39b683d
--- /dev/null
+++ b/testes/libs/lib21.c
@@ -0,0 +1,10 @@
1#include "lua.h"
2
3
4int luaopen_lib2 (lua_State *L);
5
6LUAMOD_API int luaopen_lib21 (lua_State *L) {
7 return luaopen_lib2(L);
8}
9
10
diff --git a/testes/libs/makefile b/testes/libs/makefile
new file mode 100644
index 00000000..9925fb00
--- /dev/null
+++ b/testes/libs/makefile
@@ -0,0 +1,26 @@
1# change this variable to point to the directory with Lua headers
2# of the version being tested
3LUA_DIR = ../../
4
5CC = gcc
6
7# compilation should generate Dynamic-Link Libraries
8CFLAGS = -Wall -std=gnu99 -O2 -I$(LUA_DIR) -fPIC -shared
9
10# libraries used by the tests
11all: lib1.so lib11.so lib2.so lib21.so lib2-v2.so
12
13lib1.so: lib1.c
14 $(CC) $(CFLAGS) -o lib1.so lib1.c
15
16lib11.so: lib11.c
17 $(CC) $(CFLAGS) -o lib11.so lib11.c
18
19lib2.so: lib2.c
20 $(CC) $(CFLAGS) -o lib2.so lib2.c
21
22lib21.so: lib21.c
23 $(CC) $(CFLAGS) -o lib21.so lib21.c
24
25lib2-v2.so: lib2.so
26 mv lib2.so ./lib2-v2.so
diff --git a/testes/literals.lua b/testes/literals.lua
new file mode 100644
index 00000000..3922b3f5
--- /dev/null
+++ b/testes/literals.lua
@@ -0,0 +1,302 @@
1-- $Id: literals.lua,v 1.36 2016/11/07 13:11:28 roberto Exp $
2-- See Copyright Notice in file all.lua
3
4print('testing scanner')
5
6local debug = require "debug"
7
8
9local function dostring (x) return assert(load(x), "")() end
10
11dostring("x \v\f = \t\r 'a\0a' \v\f\f")
12assert(x == 'a\0a' and string.len(x) == 3)
13
14-- escape sequences
15assert('\n\"\'\\' == [[
16
17"'\]])
18
19assert(string.find("\a\b\f\n\r\t\v", "^%c%c%c%c%c%c%c$"))
20
21-- assume ASCII just for tests:
22assert("\09912" == 'c12')
23assert("\99ab" == 'cab')
24assert("\099" == '\99')
25assert("\099\n" == 'c\10')
26assert('\0\0\0alo' == '\0' .. '\0\0' .. 'alo')
27
28assert(010 .. 020 .. -030 == "1020-30")
29
30-- hexadecimal escapes
31assert("\x00\x05\x10\x1f\x3C\xfF\xe8" == "\0\5\16\31\60\255\232")
32
33local function lexstring (x, y, n)
34 local f = assert(load('return ' .. x ..
35 ', require"debug".getinfo(1).currentline', ''))
36 local s, l = f()
37 assert(s == y and l == n)
38end
39
40lexstring("'abc\\z \n efg'", "abcefg", 2)
41lexstring("'abc\\z \n\n\n'", "abc", 4)
42lexstring("'\\z \n\t\f\v\n'", "", 3)
43lexstring("[[\nalo\nalo\n\n]]", "alo\nalo\n\n", 5)
44lexstring("[[\nalo\ralo\n\n]]", "alo\nalo\n\n", 5)
45lexstring("[[\nalo\ralo\r\n]]", "alo\nalo\n", 4)
46lexstring("[[\ralo\n\ralo\r\n]]", "alo\nalo\n", 4)
47lexstring("[[alo]\n]alo]]", "alo]\n]alo", 2)
48
49assert("abc\z
50 def\z
51 ghi\z
52 " == 'abcdefghi')
53
54
55-- UTF-8 sequences
56assert("\u{0}\u{00000000}\x00\0" == string.char(0, 0, 0, 0))
57
58-- limits for 1-byte sequences
59assert("\u{0}\u{7F}" == "\x00\z\x7F")
60
61-- limits for 2-byte sequences
62assert("\u{80}\u{7FF}" == "\xC2\x80\z\xDF\xBF")
63
64-- limits for 3-byte sequences
65assert("\u{800}\u{FFFF}" == "\xE0\xA0\x80\z\xEF\xBF\xBF")
66
67-- limits for 4-byte sequences
68assert("\u{10000}\u{10FFFF}" == "\xF0\x90\x80\x80\z\xF4\x8F\xBF\xBF")
69
70
71-- Error in escape sequences
72local function lexerror (s, err)
73 local st, msg = load('return ' .. s, '')
74 if err ~= '<eof>' then err = err .. "'" end
75 assert(not st and string.find(msg, "near .-" .. err))
76end
77
78lexerror([["abc\x"]], [[\x"]])
79lexerror([["abc\x]], [[\x]])
80lexerror([["\x]], [[\x]])
81lexerror([["\x5"]], [[\x5"]])
82lexerror([["\x5]], [[\x5]])
83lexerror([["\xr"]], [[\xr]])
84lexerror([["\xr]], [[\xr]])
85lexerror([["\x.]], [[\x.]])
86lexerror([["\x8%"]], [[\x8%%]])
87lexerror([["\xAG]], [[\xAG]])
88lexerror([["\g"]], [[\g]])
89lexerror([["\g]], [[\g]])
90lexerror([["\."]], [[\%.]])
91
92lexerror([["\999"]], [[\999"]])
93lexerror([["xyz\300"]], [[\300"]])
94lexerror([[" \256"]], [[\256"]])
95
96-- errors in UTF-8 sequences
97lexerror([["abc\u{110000}"]], [[abc\u{110000]]) -- too large
98lexerror([["abc\u11r"]], [[abc\u1]]) -- missing '{'
99lexerror([["abc\u"]], [[abc\u"]]) -- missing '{'
100lexerror([["abc\u{11r"]], [[abc\u{11r]]) -- missing '}'
101lexerror([["abc\u{11"]], [[abc\u{11"]]) -- missing '}'
102lexerror([["abc\u{11]], [[abc\u{11]]) -- missing '}'
103lexerror([["abc\u{r"]], [[abc\u{r]]) -- no digits
104
105-- unfinished strings
106lexerror("[=[alo]]", "<eof>")
107lexerror("[=[alo]=", "<eof>")
108lexerror("[=[alo]", "<eof>")
109lexerror("'alo", "<eof>")
110lexerror("'alo \\z \n\n", "<eof>")
111lexerror("'alo \\z", "<eof>")
112lexerror([['alo \98]], "<eof>")
113
114-- valid characters in variable names
115for i = 0, 255 do
116 local s = string.char(i)
117 assert(not string.find(s, "[a-zA-Z_]") == not load(s .. "=1", ""))
118 assert(not string.find(s, "[a-zA-Z_0-9]") ==
119 not load("a" .. s .. "1 = 1", ""))
120end
121
122
123-- long variable names
124
125var1 = string.rep('a', 15000) .. '1'
126var2 = string.rep('a', 15000) .. '2'
127prog = string.format([[
128 %s = 5
129 %s = %s + 1
130 return function () return %s - %s end
131]], var1, var2, var1, var1, var2)
132local f = dostring(prog)
133assert(_G[var1] == 5 and _G[var2] == 6 and f() == -1)
134var1, var2, f = nil
135print('+')
136
137-- escapes --
138assert("\n\t" == [[
139
140 ]])
141assert([[
142
143 $debug]] == "\n $debug")
144assert([[ [ ]] ~= [[ ] ]])
145-- long strings --
146b = "001234567890123456789012345678901234567891234567890123456789012345678901234567890012345678901234567890123456789012345678912345678901234567890123456789012345678900123456789012345678901234567890123456789123456789012345678901234567890123456789001234567890123456789012345678901234567891234567890123456789012345678901234567890012345678901234567890123456789012345678912345678901234567890123456789012345678900123456789012345678901234567890123456789123456789012345678901234567890123456789001234567890123456789012345678901234567891234567890123456789012345678901234567890012345678901234567890123456789012345678912345678901234567890123456789012345678900123456789012345678901234567890123456789123456789012345678901234567890123456789001234567890123456789012345678901234567891234567890123456789012345678901234567890012345678901234567890123456789012345678912345678901234567890123456789012345678900123456789012345678901234567890123456789123456789012345678901234567890123456789"
147assert(string.len(b) == 960)
148prog = [=[
149print('+')
150
151a1 = [["this is a 'string' with several 'quotes'"]]
152a2 = "'quotes'"
153
154assert(string.find(a1, a2) == 34)
155print('+')
156
157a1 = [==[temp = [[an arbitrary value]]; ]==]
158assert(load(a1))()
159assert(temp == 'an arbitrary value')
160-- long strings --
161b = "001234567890123456789012345678901234567891234567890123456789012345678901234567890012345678901234567890123456789012345678912345678901234567890123456789012345678900123456789012345678901234567890123456789123456789012345678901234567890123456789001234567890123456789012345678901234567891234567890123456789012345678901234567890012345678901234567890123456789012345678912345678901234567890123456789012345678900123456789012345678901234567890123456789123456789012345678901234567890123456789001234567890123456789012345678901234567891234567890123456789012345678901234567890012345678901234567890123456789012345678912345678901234567890123456789012345678900123456789012345678901234567890123456789123456789012345678901234567890123456789001234567890123456789012345678901234567891234567890123456789012345678901234567890012345678901234567890123456789012345678912345678901234567890123456789012345678900123456789012345678901234567890123456789123456789012345678901234567890123456789"
162assert(string.len(b) == 960)
163print('+')
164
165a = [[00123456789012345678901234567890123456789123456789012345678901234567890123456789
16600123456789012345678901234567890123456789123456789012345678901234567890123456789
16700123456789012345678901234567890123456789123456789012345678901234567890123456789
16800123456789012345678901234567890123456789123456789012345678901234567890123456789
16900123456789012345678901234567890123456789123456789012345678901234567890123456789
17000123456789012345678901234567890123456789123456789012345678901234567890123456789
17100123456789012345678901234567890123456789123456789012345678901234567890123456789
17200123456789012345678901234567890123456789123456789012345678901234567890123456789
17300123456789012345678901234567890123456789123456789012345678901234567890123456789
17400123456789012345678901234567890123456789123456789012345678901234567890123456789
17500123456789012345678901234567890123456789123456789012345678901234567890123456789
17600123456789012345678901234567890123456789123456789012345678901234567890123456789
17700123456789012345678901234567890123456789123456789012345678901234567890123456789
17800123456789012345678901234567890123456789123456789012345678901234567890123456789
17900123456789012345678901234567890123456789123456789012345678901234567890123456789
18000123456789012345678901234567890123456789123456789012345678901234567890123456789
18100123456789012345678901234567890123456789123456789012345678901234567890123456789
18200123456789012345678901234567890123456789123456789012345678901234567890123456789
18300123456789012345678901234567890123456789123456789012345678901234567890123456789
18400123456789012345678901234567890123456789123456789012345678901234567890123456789
18500123456789012345678901234567890123456789123456789012345678901234567890123456789
18600123456789012345678901234567890123456789123456789012345678901234567890123456789
18700123456789012345678901234567890123456789123456789012345678901234567890123456789
188]]
189assert(string.len(a) == 1863)
190assert(string.sub(a, 1, 40) == string.sub(b, 1, 40))
191x = 1
192]=]
193
194print('+')
195x = nil
196dostring(prog)
197assert(x)
198
199prog = nil
200a = nil
201b = nil
202
203
204-- testing line ends
205prog = [[
206a = 1 -- a comment
207b = 2
208
209
210x = [=[
211hi
212]=]
213y = "\
214hello\r\n\
215"
216return require"debug".getinfo(1).currentline
217]]
218
219for _, n in pairs{"\n", "\r", "\n\r", "\r\n"} do
220 local prog, nn = string.gsub(prog, "\n", n)
221 assert(dostring(prog) == nn)
222 assert(_G.x == "hi\n" and _G.y == "\nhello\r\n\n")
223end
224
225
226-- testing comments and strings with long brackets
227a = [==[]=]==]
228assert(a == "]=")
229
230a = [==[[===[[=[]]=][====[]]===]===]==]
231assert(a == "[===[[=[]]=][====[]]===]===")
232
233a = [====[[===[[=[]]=][====[]]===]===]====]
234assert(a == "[===[[=[]]=][====[]]===]===")
235
236a = [=[]]]]]]]]]=]
237assert(a == "]]]]]]]]")
238
239
240--[===[
241x y z [==[ blu foo
242]==
243]
244]=]==]
245error error]=]===]
246
247-- generate all strings of four of these chars
248local x = {"=", "[", "]", "\n"}
249local len = 4
250local function gen (c, n)
251 if n==0 then coroutine.yield(c)
252 else
253 for _, a in pairs(x) do
254 gen(c..a, n-1)
255 end
256 end
257end
258
259for s in coroutine.wrap(function () gen("", len) end) do
260 assert(s == load("return [====[\n"..s.."]====]", "")())
261end
262
263
264-- testing decimal point locale
265if os.setlocale("pt_BR") or os.setlocale("ptb") then
266 assert(tonumber("3,4") == 3.4 and tonumber"3.4" == 3.4)
267 assert(tonumber(" -.4 ") == -0.4)
268 assert(tonumber(" +0x.41 ") == 0X0.41)
269 assert(not load("a = (3,4)"))
270 assert(assert(load("return 3.4"))() == 3.4)
271 assert(assert(load("return .4,3"))() == .4)
272 assert(assert(load("return 4."))() == 4.)
273 assert(assert(load("return 4.+.5"))() == 4.5)
274
275 assert(" 0x.1 " + " 0x,1" + "-0X.1\t" == 0x0.1)
276
277 assert(tonumber"inf" == nil and tonumber"NAN" == nil)
278
279 assert(assert(load(string.format("return %q", 4.51)))() == 4.51)
280
281 local a,b = load("return 4.5.")
282 assert(string.find(b, "'4%.5%.'"))
283
284 assert(os.setlocale("C"))
285else
286 (Message or print)(
287 '\n >>> pt_BR locale not available: skipping decimal point tests <<<\n')
288end
289
290
291-- testing %q x line ends
292local s = "a string with \r and \n and \r\n and \n\r"
293local c = string.format("return %q", s)
294assert(assert(load(c))() == s)
295
296-- testing errors
297assert(not load"a = 'non-ending string")
298assert(not load"a = 'non-ending string\n'")
299assert(not load"a = '\\345'")
300assert(not load"a = [=x]")
301
302print('OK')
diff --git a/testes/locals.lua b/testes/locals.lua
new file mode 100644
index 00000000..f66f6f7a
--- /dev/null
+++ b/testes/locals.lua
@@ -0,0 +1,162 @@
1-- $Id: locals.lua,v 1.37 2016/11/07 13:11:28 roberto Exp $
2-- See Copyright Notice in file all.lua
3
4print('testing local variables and environments')
5
6local debug = require"debug"
7
8
9-- bug in 5.1:
10
11local function f(x) x = nil; return x end
12assert(f(10) == nil)
13
14local function f() local x; return x end
15assert(f(10) == nil)
16
17local function f(x) x = nil; local y; return x, y end
18assert(f(10) == nil and select(2, f(20)) == nil)
19
20do
21 local i = 10
22 do local i = 100; assert(i==100) end
23 do local i = 1000; assert(i==1000) end
24 assert(i == 10)
25 if i ~= 10 then
26 local i = 20
27 else
28 local i = 30
29 assert(i == 30)
30 end
31end
32
33
34
35f = nil
36
37local f
38x = 1
39
40a = nil
41load('local a = {}')()
42assert(a == nil)
43
44function f (a)
45 local _1, _2, _3, _4, _5
46 local _6, _7, _8, _9, _10
47 local x = 3
48 local b = a
49 local c,d = a,b
50 if (d == b) then
51 local x = 'q'
52 x = b
53 assert(x == 2)
54 else
55 assert(nil)
56 end
57 assert(x == 3)
58 local f = 10
59end
60
61local b=10
62local a; repeat local b; a,b=1,2; assert(a+1==b); until a+b==3
63
64
65assert(x == 1)
66
67f(2)
68assert(type(f) == 'function')
69
70
71local function getenv (f)
72 local a,b = debug.getupvalue(f, 1)
73 assert(a == '_ENV')
74 return b
75end
76
77-- test for global table of loaded chunks
78assert(getenv(load"a=3") == _G)
79local c = {}; local f = load("a = 3", nil, nil, c)
80assert(getenv(f) == c)
81assert(c.a == nil)
82f()
83assert(c.a == 3)
84
85-- old test for limits for special instructions (now just a generic test)
86do
87 local i = 2
88 local p = 4 -- p == 2^i
89 repeat
90 for j=-3,3 do
91 assert(load(string.format([[local a=%s;
92 a=a+%s;
93 assert(a ==2^%s)]], j, p-j, i), '')) ()
94 assert(load(string.format([[local a=%s;
95 a=a-%s;
96 assert(a==-2^%s)]], -j, p-j, i), '')) ()
97 assert(load(string.format([[local a,b=0,%s;
98 a=b-%s;
99 assert(a==-2^%s)]], -j, p-j, i), '')) ()
100 end
101 p = 2 * p; i = i + 1
102 until p <= 0
103end
104
105print'+'
106
107
108if rawget(_G, "querytab") then
109 -- testing clearing of dead elements from tables
110 collectgarbage("stop") -- stop GC
111 local a = {[{}] = 4, [3] = 0, alo = 1,
112 a1234567890123456789012345678901234567890 = 10}
113
114 local t = querytab(a)
115
116 for k,_ in pairs(a) do a[k] = nil end
117 collectgarbage() -- restore GC and collect dead fiels in `a'
118 for i=0,t-1 do
119 local k = querytab(a, i)
120 assert(k == nil or type(k) == 'number' or k == 'alo')
121 end
122end
123
124
125-- testing lexical environments
126
127assert(_ENV == _G)
128
129do
130local dummy
131local _ENV = (function (...) return ... end)(_G, dummy) -- {
132
133do local _ENV = {assert=assert}; assert(true) end
134mt = {_G = _G}
135local foo,x
136A = false -- "declare" A
137do local _ENV = mt
138 function foo (x)
139 A = x
140 do local _ENV = _G; A = 1000 end
141 return function (x) return A .. x end
142 end
143end
144assert(getenv(foo) == mt)
145x = foo('hi'); assert(mt.A == 'hi' and A == 1000)
146assert(x('*') == mt.A .. '*')
147
148do local _ENV = {assert=assert, A=10};
149 do local _ENV = {assert=assert, A=20};
150 assert(A==20);x=A
151 end
152 assert(A==10 and x==20)
153end
154assert(x==20)
155
156
157print('OK')
158
159return 5,f
160
161end -- }
162
diff --git a/testes/main.lua b/testes/main.lua
new file mode 100644
index 00000000..9fc20c1d
--- /dev/null
+++ b/testes/main.lua
@@ -0,0 +1,381 @@
1# testing special comment on first line
2-- $Id: main.lua,v 1.65 2016/11/07 13:11:28 roberto Exp $
3-- See Copyright Notice in file all.lua
4
5-- most (all?) tests here assume a reasonable "Unix-like" shell
6if _port then return end
7
8-- use only "double quotes" inside shell scripts (better change to
9-- run on Windows)
10
11
12print ("testing stand-alone interpreter")
13
14assert(os.execute()) -- machine has a system command
15
16local arg = arg or _ARG
17
18local prog = os.tmpname()
19local otherprog = os.tmpname()
20local out = os.tmpname()
21
22local progname
23do
24 local i = 0
25 while arg[i] do i=i-1 end
26 progname = arg[i+1]
27end
28print("progname: "..progname)
29
30local prepfile = function (s, p)
31 p = p or prog
32 io.output(p)
33 io.write(s)
34 assert(io.close())
35end
36
37local function getoutput ()
38 io.input(out)
39 local t = io.read("a")
40 io.input():close()
41 assert(os.remove(out))
42 return t
43end
44
45local function checkprogout (s)
46 local t = getoutput()
47 for line in string.gmatch(s, ".-\n") do
48 assert(string.find(t, line, 1, true))
49 end
50end
51
52local function checkout (s)
53 local t = getoutput()
54 if s ~= t then print(string.format("'%s' - '%s'\n", s, t)) end
55 assert(s == t)
56 return t
57end
58
59
60local function RUN (p, ...)
61 p = string.gsub(p, "lua", '"'..progname..'"', 1)
62 local s = string.format(p, ...)
63 assert(os.execute(s))
64end
65
66local function NoRun (msg, p, ...)
67 p = string.gsub(p, "lua", '"'..progname..'"', 1)
68 local s = string.format(p, ...)
69 s = string.format("%s 2> %s", s, out) -- will send error to 'out'
70 assert(not os.execute(s))
71 assert(string.find(getoutput(), msg, 1, true)) -- check error message
72end
73
74RUN('lua -v')
75
76print(string.format("(temporary program file used in these tests: %s)", prog))
77
78-- running stdin as a file
79prepfile""
80RUN('lua - < %s > %s', prog, out)
81checkout("")
82
83prepfile[[
84 print(
851, a
86)
87]]
88RUN('lua - < %s > %s', prog, out)
89checkout("1\tnil\n")
90
91RUN('echo "print(10)\nprint(2)\n" | lua > %s', out)
92checkout("10\n2\n")
93
94
95-- test option '-'
96RUN('echo "print(arg[1])" | lua - -h > %s', out)
97checkout("-h\n")
98
99-- test environment variables used by Lua
100
101prepfile("print(package.path)")
102
103-- test LUA_PATH
104RUN('env LUA_INIT= LUA_PATH=x lua %s > %s', prog, out)
105checkout("x\n")
106
107-- test LUA_PATH_version
108RUN('env LUA_INIT= LUA_PATH_5_3=y LUA_PATH=x lua %s > %s', prog, out)
109checkout("y\n")
110
111-- test LUA_CPATH
112prepfile("print(package.cpath)")
113RUN('env LUA_INIT= LUA_CPATH=xuxu lua %s > %s', prog, out)
114checkout("xuxu\n")
115
116-- test LUA_CPATH_version
117RUN('env LUA_INIT= LUA_CPATH_5_3=yacc LUA_CPATH=x lua %s > %s', prog, out)
118checkout("yacc\n")
119
120-- test LUA_INIT (and its access to 'arg' table)
121prepfile("print(X)")
122RUN('env LUA_INIT="X=tonumber(arg[1])" lua %s 3.2 > %s', prog, out)
123checkout("3.2\n")
124
125-- test LUA_INIT_version
126prepfile("print(X)")
127RUN('env LUA_INIT_5_3="X=10" LUA_INIT="X=3" lua %s > %s', prog, out)
128checkout("10\n")
129
130-- test LUA_INIT for files
131prepfile("x = x or 10; print(x); x = x + 1")
132RUN('env LUA_INIT="@%s" lua %s > %s', prog, prog, out)
133checkout("10\n11\n")
134
135-- test errors in LUA_INIT
136NoRun('LUA_INIT:1: msg', 'env LUA_INIT="error(\'msg\')" lua')
137
138-- test option '-E'
139local defaultpath, defaultCpath
140
141do
142 prepfile("print(package.path, package.cpath)")
143 RUN('env LUA_INIT="error(10)" LUA_PATH=xxx LUA_CPATH=xxx lua -E %s > %s',
144 prog, out)
145 local out = getoutput()
146 defaultpath = string.match(out, "^(.-)\t")
147 defaultCpath = string.match(out, "\t(.-)$")
148end
149
150-- paths did not changed
151assert(not string.find(defaultpath, "xxx") and
152 string.find(defaultpath, "lua") and
153 not string.find(defaultCpath, "xxx") and
154 string.find(defaultCpath, "lua"))
155
156
157-- test replacement of ';;' to default path
158local function convert (p)
159 prepfile("print(package.path)")
160 RUN('env LUA_PATH="%s" lua %s > %s', p, prog, out)
161 local expected = getoutput()
162 expected = string.sub(expected, 1, -2) -- cut final end of line
163 assert(string.gsub(p, ";;", ";"..defaultpath..";") == expected)
164end
165
166convert(";")
167convert(";;")
168convert(";;;")
169convert(";;;;")
170convert(";;;;;")
171convert(";;a;;;bc")
172
173
174-- test -l over multiple libraries
175prepfile("print(1); a=2; return {x=15}")
176prepfile(("print(a); print(_G['%s'].x)"):format(prog), otherprog)
177RUN('env LUA_PATH="?;;" lua -l %s -l%s -lstring -l io %s > %s', prog, otherprog, otherprog, out)
178checkout("1\n2\n15\n2\n15\n")
179
180-- test 'arg' table
181local a = [[
182 assert(#arg == 3 and arg[1] == 'a' and
183 arg[2] == 'b' and arg[3] == 'c')
184 assert(arg[-1] == '--' and arg[-2] == "-e " and arg[-3] == '%s')
185 assert(arg[4] == nil and arg[-4] == nil)
186 local a, b, c = ...
187 assert(... == 'a' and a == 'a' and b == 'b' and c == 'c')
188]]
189a = string.format(a, progname)
190prepfile(a)
191RUN('lua "-e " -- %s a b c', prog) -- "-e " runs an empty command
192
193-- test 'arg' availability in libraries
194prepfile"assert(arg)"
195prepfile("assert(arg)", otherprog)
196RUN('env LUA_PATH="?;;" lua -l%s - < %s', prog, otherprog)
197
198-- test messing up the 'arg' table
199RUN('echo "print(...)" | lua -e "arg[1] = 100" - > %s', out)
200checkout("100\n")
201NoRun("'arg' is not a table", 'echo "" | lua -e "arg = 1" -')
202
203-- test error in 'print'
204RUN('echo 10 | lua -e "print=nil" -i > /dev/null 2> %s', out)
205assert(string.find(getoutput(), "error calling 'print'"))
206
207-- test 'debug.debug'
208RUN('echo "io.stderr:write(1000)\ncont" | lua -e "require\'debug\'.debug()" 2> %s', out)
209checkout("lua_debug> 1000lua_debug> ")
210
211-- test many arguments
212prepfile[[print(({...})[30])]]
213RUN('lua %s %s > %s', prog, string.rep(" a", 30), out)
214checkout("a\n")
215
216RUN([[lua "-eprint(1)" -ea=3 -e "print(a)" > %s]], out)
217checkout("1\n3\n")
218
219-- test iteractive mode
220prepfile[[
221(6*2-6) -- ===
222a =
22310
224print(a)
225a]]
226RUN([[lua -e"_PROMPT='' _PROMPT2=''" -i < %s > %s]], prog, out)
227checkprogout("6\n10\n10\n\n")
228
229prepfile("a = [[b\nc\nd\ne]]\n=a")
230RUN([[lua -e"_PROMPT='' _PROMPT2=''" -i < %s > %s]], prog, out)
231checkprogout("b\nc\nd\ne\n\n")
232
233prompt = "alo"
234prepfile[[ --
235a = 2
236]]
237RUN([[lua "-e_PROMPT='%s'" -i < %s > %s]], prompt, prog, out)
238local t = getoutput()
239assert(string.find(t, prompt .. ".*" .. prompt .. ".*" .. prompt))
240
241-- test for error objects
242prepfile[[
243debug = require "debug"
244m = {x=0}
245setmetatable(m, {__tostring = function(x)
246 return tostring(debug.getinfo(4).currentline + x.x)
247end})
248error(m)
249]]
250NoRun(progname .. ": 6\n", [[lua %s]], prog)
251
252prepfile("error{}")
253NoRun("error object is a table value", [[lua %s]], prog)
254
255
256-- chunk broken in many lines
257s = [=[ --
258function f ( x )
259 local a = [[
260xuxu
261]]
262 local b = "\
263xuxu\n"
264 if x == 11 then return 1 + 12 , 2 + 20 end --[[ test multiple returns ]]
265 return x + 1
266 --\\
267end
268return( f( 100 ) )
269assert( a == b )
270do return f( 11 ) end ]=]
271s = string.gsub(s, ' ', '\n\n') -- change all spaces for newlines
272prepfile(s)
273RUN([[lua -e"_PROMPT='' _PROMPT2=''" -i < %s > %s]], prog, out)
274checkprogout("101\n13\t22\n\n")
275
276prepfile[[#comment in 1st line without \n at the end]]
277RUN('lua %s', prog)
278
279prepfile[[#test line number when file starts with comment line
280debug = require"debug"
281print(debug.getinfo(1).currentline)
282]]
283RUN('lua %s > %s', prog, out)
284checkprogout('3')
285
286-- close Lua with an open file
287prepfile(string.format([[io.output(%q); io.write('alo')]], out))
288RUN('lua %s', prog)
289checkout('alo')
290
291-- bug in 5.2 beta (extra \0 after version line)
292RUN([[lua -v -e"print'hello'" > %s]], out)
293t = getoutput()
294assert(string.find(t, "PUC%-Rio\nhello"))
295
296
297-- testing os.exit
298prepfile("os.exit(nil, true)")
299RUN('lua %s', prog)
300prepfile("os.exit(0, true)")
301RUN('lua %s', prog)
302prepfile("os.exit(true, true)")
303RUN('lua %s', prog)
304prepfile("os.exit(1, true)")
305NoRun("", "lua %s", prog) -- no message
306prepfile("os.exit(false, true)")
307NoRun("", "lua %s", prog) -- no message
308
309-- remove temporary files
310assert(os.remove(prog))
311assert(os.remove(otherprog))
312assert(not os.remove(out))
313
314-- invalid options
315NoRun("unrecognized option '-h'", "lua -h")
316NoRun("unrecognized option '---'", "lua ---")
317NoRun("unrecognized option '-Ex'", "lua -Ex")
318NoRun("unrecognized option '-vv'", "lua -vv")
319NoRun("unrecognized option '-iv'", "lua -iv")
320NoRun("'-e' needs argument", "lua -e")
321NoRun("syntax error", "lua -e a")
322NoRun("'-l' needs argument", "lua -l")
323
324
325if T then -- auxiliary library?
326 print("testing 'not enough memory' to create a state")
327 NoRun("not enough memory", "env MEMLIMIT=100 lua")
328end
329print('+')
330
331print('testing Ctrl C')
332do
333 -- interrupt a script
334 local function kill (pid)
335 return os.execute(string.format('kill -INT %d 2> /dev/null', pid))
336 end
337
338 -- function to run a script in background, returning its output file
339 -- descriptor and its pid
340 local function runback (luaprg)
341 -- shell script to run 'luaprg' in background and echo its pid
342 local shellprg = string.format('%s -e "%s" & echo $!', progname, luaprg)
343 local f = io.popen(shellprg, "r") -- run shell script
344 local pid = f:read() -- get pid for Lua script
345 print("(if test fails now, it may leave a Lua script running in \z
346 background, pid " .. pid .. ")")
347 return f, pid
348 end
349
350 -- Lua script that runs protected infinite loop and then prints '42'
351 local f, pid = runback[[
352 pcall(function () print(12); while true do end end); print(42)]]
353 -- wait until script is inside 'pcall'
354 assert(f:read() == "12")
355 kill(pid) -- send INT signal to Lua script
356 -- check that 'pcall' captured the exception and script continued running
357 assert(f:read() == "42") -- expected output
358 assert(f:close())
359 print("done")
360
361 -- Lua script in a long unbreakable search
362 local f, pid = runback[[
363 print(15); string.find(string.rep('a', 100000), '.*b')]]
364 -- wait (so script can reach the loop)
365 assert(f:read() == "15")
366 assert(os.execute("sleep 1"))
367 -- must send at least two INT signals to stop this Lua script
368 local n = 100
369 for i = 0, 100 do -- keep sending signals
370 if not kill(pid) then -- until it fails
371 n = i -- number of non-failed kills
372 break
373 end
374 end
375 assert(f:close())
376 assert(n >= 2)
377 print(string.format("done (with %d kills)", n))
378
379end
380
381print("OK")
diff --git a/testes/math.lua b/testes/math.lua
new file mode 100644
index 00000000..53ce9b5a
--- /dev/null
+++ b/testes/math.lua
@@ -0,0 +1,824 @@
1-- $Id: math.lua,v 1.78 2016/11/07 13:11:28 roberto Exp $
2-- See Copyright Notice in file all.lua
3
4print("testing numbers and math lib")
5
6local minint = math.mininteger
7local maxint = math.maxinteger
8
9local intbits = math.floor(math.log(maxint, 2) + 0.5) + 1
10assert((1 << intbits) == 0)
11
12assert(minint == 1 << (intbits - 1))
13assert(maxint == minint - 1)
14
15-- number of bits in the mantissa of a floating-point number
16local floatbits = 24
17do
18 local p = 2.0^floatbits
19 while p < p + 1.0 do
20 p = p * 2.0
21 floatbits = floatbits + 1
22 end
23end
24
25local function isNaN (x)
26 return (x ~= x)
27end
28
29assert(isNaN(0/0))
30assert(not isNaN(1/0))
31
32
33do
34 local x = 2.0^floatbits
35 assert(x > x - 1.0 and x == x + 1.0)
36
37 print(string.format("%d-bit integers, %d-bit (mantissa) floats",
38 intbits, floatbits))
39end
40
41assert(math.type(0) == "integer" and math.type(0.0) == "float"
42 and math.type("10") == nil)
43
44
45local function checkerror (msg, f, ...)
46 local s, err = pcall(f, ...)
47 assert(not s and string.find(err, msg))
48end
49
50local msgf2i = "number.* has no integer representation"
51
52-- float equality
53function eq (a,b,limit)
54 if not limit then
55 if floatbits >= 50 then limit = 1E-11
56 else limit = 1E-5
57 end
58 end
59 -- a == b needed for +inf/-inf
60 return a == b or math.abs(a-b) <= limit
61end
62
63
64-- equality with types
65function eqT (a,b)
66 return a == b and math.type(a) == math.type(b)
67end
68
69
70-- basic float notation
71assert(0e12 == 0 and .0 == 0 and 0. == 0 and .2e2 == 20 and 2.E-1 == 0.2)
72
73do
74 local a,b,c = "2", " 3e0 ", " 10 "
75 assert(a+b == 5 and -b == -3 and b+"2" == 5 and "10"-c == 0)
76 assert(type(a) == 'string' and type(b) == 'string' and type(c) == 'string')
77 assert(a == "2" and b == " 3e0 " and c == " 10 " and -c == -" 10 ")
78 assert(c%a == 0 and a^b == 08)
79 a = 0
80 assert(a == -a and 0 == -0)
81end
82
83do
84 local x = -1
85 local mz = 0/x -- minus zero
86 t = {[0] = 10, 20, 30, 40, 50}
87 assert(t[mz] == t[0] and t[-0] == t[0])
88end
89
90do -- tests for 'modf'
91 local a,b = math.modf(3.5)
92 assert(a == 3.0 and b == 0.5)
93 a,b = math.modf(-2.5)
94 assert(a == -2.0 and b == -0.5)
95 a,b = math.modf(-3e23)
96 assert(a == -3e23 and b == 0.0)
97 a,b = math.modf(3e35)
98 assert(a == 3e35 and b == 0.0)
99 a,b = math.modf(-1/0) -- -inf
100 assert(a == -1/0 and b == 0.0)
101 a,b = math.modf(1/0) -- inf
102 assert(a == 1/0 and b == 0.0)
103 a,b = math.modf(0/0) -- NaN
104 assert(isNaN(a) and isNaN(b))
105 a,b = math.modf(3) -- integer argument
106 assert(eqT(a, 3) and eqT(b, 0.0))
107 a,b = math.modf(minint)
108 assert(eqT(a, minint) and eqT(b, 0.0))
109end
110
111assert(math.huge > 10e30)
112assert(-math.huge < -10e30)
113
114
115-- integer arithmetic
116assert(minint < minint + 1)
117assert(maxint - 1 < maxint)
118assert(0 - minint == minint)
119assert(minint * minint == 0)
120assert(maxint * maxint * maxint == maxint)
121
122
123-- testing floor division and conversions
124
125for _, i in pairs{-16, -15, -3, -2, -1, 0, 1, 2, 3, 15} do
126 for _, j in pairs{-16, -15, -3, -2, -1, 1, 2, 3, 15} do
127 for _, ti in pairs{0, 0.0} do -- try 'i' as integer and as float
128 for _, tj in pairs{0, 0.0} do -- try 'j' as integer and as float
129 local x = i + ti
130 local y = j + tj
131 assert(i//j == math.floor(i/j))
132 end
133 end
134 end
135end
136
137assert(1//0.0 == 1/0)
138assert(-1 // 0.0 == -1/0)
139assert(eqT(3.5 // 1.5, 2.0))
140assert(eqT(3.5 // -1.5, -3.0))
141
142assert(maxint // maxint == 1)
143assert(maxint // 1 == maxint)
144assert((maxint - 1) // maxint == 0)
145assert(maxint // (maxint - 1) == 1)
146assert(minint // minint == 1)
147assert(minint // minint == 1)
148assert((minint + 1) // minint == 0)
149assert(minint // (minint + 1) == 1)
150assert(minint // 1 == minint)
151
152assert(minint // -1 == -minint)
153assert(minint // -2 == 2^(intbits - 2))
154assert(maxint // -1 == -maxint)
155
156
157-- negative exponents
158do
159 assert(2^-3 == 1 / 2^3)
160 assert(eq((-3)^-3, 1 / (-3)^3))
161 for i = -3, 3 do -- variables avoid constant folding
162 for j = -3, 3 do
163 -- domain errors (0^(-n)) are not portable
164 if not _port or i ~= 0 or j > 0 then
165 assert(eq(i^j, 1 / i^(-j)))
166 end
167 end
168 end
169end
170
171-- comparison between floats and integers (border cases)
172if floatbits < intbits then
173 assert(2.0^floatbits == (1 << floatbits))
174 assert(2.0^floatbits - 1.0 == (1 << floatbits) - 1.0)
175 assert(2.0^floatbits - 1.0 ~= (1 << floatbits))
176 -- float is rounded, int is not
177 assert(2.0^floatbits + 1.0 ~= (1 << floatbits) + 1)
178else -- floats can express all integers with full accuracy
179 assert(maxint == maxint + 0.0)
180 assert(maxint - 1 == maxint - 1.0)
181 assert(minint + 1 == minint + 1.0)
182 assert(maxint ~= maxint - 1.0)
183end
184assert(maxint + 0.0 == 2.0^(intbits - 1) - 1.0)
185assert(minint + 0.0 == minint)
186assert(minint + 0.0 == -2.0^(intbits - 1))
187
188
189-- order between floats and integers
190assert(1 < 1.1); assert(not (1 < 0.9))
191assert(1 <= 1.1); assert(not (1 <= 0.9))
192assert(-1 < -0.9); assert(not (-1 < -1.1))
193assert(1 <= 1.1); assert(not (-1 <= -1.1))
194assert(-1 < -0.9); assert(not (-1 < -1.1))
195assert(-1 <= -0.9); assert(not (-1 <= -1.1))
196assert(minint <= minint + 0.0)
197assert(minint + 0.0 <= minint)
198assert(not (minint < minint + 0.0))
199assert(not (minint + 0.0 < minint))
200assert(maxint < minint * -1.0)
201assert(maxint <= minint * -1.0)
202
203do
204 local fmaxi1 = 2^(intbits - 1)
205 assert(maxint < fmaxi1)
206 assert(maxint <= fmaxi1)
207 assert(not (fmaxi1 <= maxint))
208 assert(minint <= -2^(intbits - 1))
209 assert(-2^(intbits - 1) <= minint)
210end
211
212if floatbits < intbits then
213 print("testing order (floats cannot represent all integers)")
214 local fmax = 2^floatbits
215 local ifmax = fmax | 0
216 assert(fmax < ifmax + 1)
217 assert(fmax - 1 < ifmax)
218 assert(-(fmax - 1) > -ifmax)
219 assert(not (fmax <= ifmax - 1))
220 assert(-fmax > -(ifmax + 1))
221 assert(not (-fmax >= -(ifmax - 1)))
222
223 assert(fmax/2 - 0.5 < ifmax//2)
224 assert(-(fmax/2 - 0.5) > -ifmax//2)
225
226 assert(maxint < 2^intbits)
227 assert(minint > -2^intbits)
228 assert(maxint <= 2^intbits)
229 assert(minint >= -2^intbits)
230else
231 print("testing order (floats can represent all integers)")
232 assert(maxint < maxint + 1.0)
233 assert(maxint < maxint + 0.5)
234 assert(maxint - 1.0 < maxint)
235 assert(maxint - 0.5 < maxint)
236 assert(not (maxint + 0.0 < maxint))
237 assert(maxint + 0.0 <= maxint)
238 assert(not (maxint < maxint + 0.0))
239 assert(maxint + 0.0 <= maxint)
240 assert(maxint <= maxint + 0.0)
241 assert(not (maxint + 1.0 <= maxint))
242 assert(not (maxint + 0.5 <= maxint))
243 assert(not (maxint <= maxint - 1.0))
244 assert(not (maxint <= maxint - 0.5))
245
246 assert(minint < minint + 1.0)
247 assert(minint < minint + 0.5)
248 assert(minint <= minint + 0.5)
249 assert(minint - 1.0 < minint)
250 assert(minint - 1.0 <= minint)
251 assert(not (minint + 0.0 < minint))
252 assert(not (minint + 0.5 < minint))
253 assert(not (minint < minint + 0.0))
254 assert(minint + 0.0 <= minint)
255 assert(minint <= minint + 0.0)
256 assert(not (minint + 1.0 <= minint))
257 assert(not (minint + 0.5 <= minint))
258 assert(not (minint <= minint - 1.0))
259end
260
261do
262 local NaN = 0/0
263 assert(not (NaN < 0))
264 assert(not (NaN > minint))
265 assert(not (NaN <= -9))
266 assert(not (NaN <= maxint))
267 assert(not (NaN < maxint))
268 assert(not (minint <= NaN))
269 assert(not (minint < NaN))
270end
271
272
273-- avoiding errors at compile time
274local function checkcompt (msg, code)
275 checkerror(msg, assert(load(code)))
276end
277checkcompt("divide by zero", "return 2 // 0")
278checkcompt(msgf2i, "return 2.3 >> 0")
279checkcompt(msgf2i, ("return 2.0^%d & 1"):format(intbits - 1))
280checkcompt("field 'huge'", "return math.huge << 1")
281checkcompt(msgf2i, ("return 1 | 2.0^%d"):format(intbits - 1))
282checkcompt(msgf2i, "return 2.3 ~ '0.0'")
283
284
285-- testing overflow errors when converting from float to integer (runtime)
286local function f2i (x) return x | x end
287checkerror(msgf2i, f2i, math.huge) -- +inf
288checkerror(msgf2i, f2i, -math.huge) -- -inf
289checkerror(msgf2i, f2i, 0/0) -- NaN
290
291if floatbits < intbits then
292 -- conversion tests when float cannot represent all integers
293 assert(maxint + 1.0 == maxint + 0.0)
294 assert(minint - 1.0 == minint + 0.0)
295 checkerror(msgf2i, f2i, maxint + 0.0)
296 assert(f2i(2.0^(intbits - 2)) == 1 << (intbits - 2))
297 assert(f2i(-2.0^(intbits - 2)) == -(1 << (intbits - 2)))
298 assert((2.0^(floatbits - 1) + 1.0) // 1 == (1 << (floatbits - 1)) + 1)
299 -- maximum integer representable as a float
300 local mf = maxint - (1 << (floatbits - intbits)) + 1
301 assert(f2i(mf + 0.0) == mf) -- OK up to here
302 mf = mf + 1
303 assert(f2i(mf + 0.0) ~= mf) -- no more representable
304else
305 -- conversion tests when float can represent all integers
306 assert(maxint + 1.0 > maxint)
307 assert(minint - 1.0 < minint)
308 assert(f2i(maxint + 0.0) == maxint)
309 checkerror("no integer rep", f2i, maxint + 1.0)
310 checkerror("no integer rep", f2i, minint - 1.0)
311end
312
313-- 'minint' should be representable as a float no matter the precision
314assert(f2i(minint + 0.0) == minint)
315
316
317-- testing numeric strings
318
319assert("2" + 1 == 3)
320assert("2 " + 1 == 3)
321assert(" -2 " + 1 == -1)
322assert(" -0xa " + 1 == -9)
323
324
325-- Literal integer Overflows (new behavior in 5.3.3)
326do
327 -- no overflows
328 assert(eqT(tonumber(tostring(maxint)), maxint))
329 assert(eqT(tonumber(tostring(minint)), minint))
330
331 -- add 1 to last digit as a string (it cannot be 9...)
332 local function incd (n)
333 local s = string.format("%d", n)
334 s = string.gsub(s, "%d$", function (d)
335 assert(d ~= '9')
336 return string.char(string.byte(d) + 1)
337 end)
338 return s
339 end
340
341 -- 'tonumber' with overflow by 1
342 assert(eqT(tonumber(incd(maxint)), maxint + 1.0))
343 assert(eqT(tonumber(incd(minint)), minint - 1.0))
344
345 -- large numbers
346 assert(eqT(tonumber("1"..string.rep("0", 30)), 1e30))
347 assert(eqT(tonumber("-1"..string.rep("0", 30)), -1e30))
348
349 -- hexa format still wraps around
350 assert(eqT(tonumber("0x1"..string.rep("0", 30)), 0))
351
352 -- lexer in the limits
353 assert(minint == load("return " .. minint)())
354 assert(eqT(maxint, load("return " .. maxint)()))
355
356 assert(eqT(10000000000000000000000.0, 10000000000000000000000))
357 assert(eqT(-10000000000000000000000.0, -10000000000000000000000))
358end
359
360
361-- testing 'tonumber'
362
363-- 'tonumber' with numbers
364assert(tonumber(3.4) == 3.4)
365assert(eqT(tonumber(3), 3))
366assert(eqT(tonumber(maxint), maxint) and eqT(tonumber(minint), minint))
367assert(tonumber(1/0) == 1/0)
368
369-- 'tonumber' with strings
370assert(tonumber("0") == 0)
371assert(tonumber("") == nil)
372assert(tonumber(" ") == nil)
373assert(tonumber("-") == nil)
374assert(tonumber(" -0x ") == nil)
375assert(tonumber{} == nil)
376assert(tonumber'+0.01' == 1/100 and tonumber'+.01' == 0.01 and
377 tonumber'.01' == 0.01 and tonumber'-1.' == -1 and
378 tonumber'+1.' == 1)
379assert(tonumber'+ 0.01' == nil and tonumber'+.e1' == nil and
380 tonumber'1e' == nil and tonumber'1.0e+' == nil and
381 tonumber'.' == nil)
382assert(tonumber('-012') == -010-2)
383assert(tonumber('-1.2e2') == - - -120)
384
385assert(tonumber("0xffffffffffff") == (1 << (4*12)) - 1)
386assert(tonumber("0x"..string.rep("f", (intbits//4))) == -1)
387assert(tonumber("-0x"..string.rep("f", (intbits//4))) == 1)
388
389-- testing 'tonumber' with base
390assert(tonumber(' 001010 ', 2) == 10)
391assert(tonumber(' 001010 ', 10) == 001010)
392assert(tonumber(' -1010 ', 2) == -10)
393assert(tonumber('10', 36) == 36)
394assert(tonumber(' -10 ', 36) == -36)
395assert(tonumber(' +1Z ', 36) == 36 + 35)
396assert(tonumber(' -1z ', 36) == -36 + -35)
397assert(tonumber('-fFfa', 16) == -(10+(16*(15+(16*(15+(16*15)))))))
398assert(tonumber(string.rep('1', (intbits - 2)), 2) + 1 == 2^(intbits - 2))
399assert(tonumber('ffffFFFF', 16)+1 == (1 << 32))
400assert(tonumber('0ffffFFFF', 16)+1 == (1 << 32))
401assert(tonumber('-0ffffffFFFF', 16) - 1 == -(1 << 40))
402for i = 2,36 do
403 local i2 = i * i
404 local i10 = i2 * i2 * i2 * i2 * i2 -- i^10
405 assert(tonumber('\t10000000000\t', i) == i10)
406end
407
408if not _soft then
409 -- tests with very long numerals
410 assert(tonumber("0x"..string.rep("f", 13)..".0") == 2.0^(4*13) - 1)
411 assert(tonumber("0x"..string.rep("f", 150)..".0") == 2.0^(4*150) - 1)
412 assert(tonumber("0x"..string.rep("f", 300)..".0") == 2.0^(4*300) - 1)
413 assert(tonumber("0x"..string.rep("f", 500)..".0") == 2.0^(4*500) - 1)
414 assert(tonumber('0x3.' .. string.rep('0', 1000)) == 3)
415 assert(tonumber('0x' .. string.rep('0', 1000) .. 'a') == 10)
416 assert(tonumber('0x0.' .. string.rep('0', 13).."1") == 2.0^(-4*14))
417 assert(tonumber('0x0.' .. string.rep('0', 150).."1") == 2.0^(-4*151))
418 assert(tonumber('0x0.' .. string.rep('0', 300).."1") == 2.0^(-4*301))
419 assert(tonumber('0x0.' .. string.rep('0', 500).."1") == 2.0^(-4*501))
420
421 assert(tonumber('0xe03' .. string.rep('0', 1000) .. 'p-4000') == 3587.0)
422 assert(tonumber('0x.' .. string.rep('0', 1000) .. '74p4004') == 0x7.4)
423end
424
425-- testing 'tonumber' for invalid formats
426
427local function f (...)
428 if select('#', ...) == 1 then
429 return (...)
430 else
431 return "***"
432 end
433end
434
435assert(f(tonumber('fFfa', 15)) == nil)
436assert(f(tonumber('099', 8)) == nil)
437assert(f(tonumber('1\0', 2)) == nil)
438assert(f(tonumber('', 8)) == nil)
439assert(f(tonumber(' ', 9)) == nil)
440assert(f(tonumber(' ', 9)) == nil)
441assert(f(tonumber('0xf', 10)) == nil)
442
443assert(f(tonumber('inf')) == nil)
444assert(f(tonumber(' INF ')) == nil)
445assert(f(tonumber('Nan')) == nil)
446assert(f(tonumber('nan')) == nil)
447
448assert(f(tonumber(' ')) == nil)
449assert(f(tonumber('')) == nil)
450assert(f(tonumber('1 a')) == nil)
451assert(f(tonumber('1 a', 2)) == nil)
452assert(f(tonumber('1\0')) == nil)
453assert(f(tonumber('1 \0')) == nil)
454assert(f(tonumber('1\0 ')) == nil)
455assert(f(tonumber('e1')) == nil)
456assert(f(tonumber('e 1')) == nil)
457assert(f(tonumber(' 3.4.5 ')) == nil)
458
459
460-- testing 'tonumber' for invalid hexadecimal formats
461
462assert(tonumber('0x') == nil)
463assert(tonumber('x') == nil)
464assert(tonumber('x3') == nil)
465assert(tonumber('0x3.3.3') == nil) -- two decimal points
466assert(tonumber('00x2') == nil)
467assert(tonumber('0x 2') == nil)
468assert(tonumber('0 x2') == nil)
469assert(tonumber('23x') == nil)
470assert(tonumber('- 0xaa') == nil)
471assert(tonumber('-0xaaP ') == nil) -- no exponent
472assert(tonumber('0x0.51p') == nil)
473assert(tonumber('0x5p+-2') == nil)
474
475
476-- testing hexadecimal numerals
477
478assert(0x10 == 16 and 0xfff == 2^12 - 1 and 0XFB == 251)
479assert(0x0p12 == 0 and 0x.0p-3 == 0)
480assert(0xFFFFFFFF == (1 << 32) - 1)
481assert(tonumber('+0x2') == 2)
482assert(tonumber('-0xaA') == -170)
483assert(tonumber('-0xffFFFfff') == -(1 << 32) + 1)
484
485-- possible confusion with decimal exponent
486assert(0E+1 == 0 and 0xE+1 == 15 and 0xe-1 == 13)
487
488
489-- floating hexas
490
491assert(tonumber(' 0x2.5 ') == 0x25/16)
492assert(tonumber(' -0x2.5 ') == -0x25/16)
493assert(tonumber(' +0x0.51p+8 ') == 0x51)
494assert(0x.FfffFFFF == 1 - '0x.00000001')
495assert('0xA.a' + 0 == 10 + 10/16)
496assert(0xa.aP4 == 0XAA)
497assert(0x4P-2 == 1)
498assert(0x1.1 == '0x1.' + '+0x.1')
499assert(0Xabcdef.0 == 0x.ABCDEFp+24)
500
501
502assert(1.1 == 1.+.1)
503assert(100.0 == 1E2 and .01 == 1e-2)
504assert(1111111111 - 1111111110 == 1000.00e-03)
505assert(1.1 == '1.'+'.1')
506assert(tonumber'1111111111' - tonumber'1111111110' ==
507 tonumber" +0.001e+3 \n\t")
508
509assert(0.1e-30 > 0.9E-31 and 0.9E30 < 0.1e31)
510
511assert(0.123456 > 0.123455)
512
513assert(tonumber('+1.23E18') == 1.23*10.0^18)
514
515-- testing order operators
516assert(not(1<1) and (1<2) and not(2<1))
517assert(not('a'<'a') and ('a'<'b') and not('b'<'a'))
518assert((1<=1) and (1<=2) and not(2<=1))
519assert(('a'<='a') and ('a'<='b') and not('b'<='a'))
520assert(not(1>1) and not(1>2) and (2>1))
521assert(not('a'>'a') and not('a'>'b') and ('b'>'a'))
522assert((1>=1) and not(1>=2) and (2>=1))
523assert(('a'>='a') and not('a'>='b') and ('b'>='a'))
524assert(1.3 < 1.4 and 1.3 <= 1.4 and not (1.3 < 1.3) and 1.3 <= 1.3)
525
526-- testing mod operator
527assert(eqT(-4 % 3, 2))
528assert(eqT(4 % -3, -2))
529assert(eqT(-4.0 % 3, 2.0))
530assert(eqT(4 % -3.0, -2.0))
531assert(math.pi - math.pi % 1 == 3)
532assert(math.pi - math.pi % 0.001 == 3.141)
533
534assert(eqT(minint % minint, 0))
535assert(eqT(maxint % maxint, 0))
536assert((minint + 1) % minint == minint + 1)
537assert((maxint - 1) % maxint == maxint - 1)
538assert(minint % maxint == maxint - 1)
539
540assert(minint % -1 == 0)
541assert(minint % -2 == 0)
542assert(maxint % -2 == -1)
543
544-- non-portable tests because Windows C library cannot compute
545-- fmod(1, huge) correctly
546if not _port then
547 local function anan (x) assert(isNaN(x)) end -- assert Not a Number
548 anan(0.0 % 0)
549 anan(1.3 % 0)
550 anan(math.huge % 1)
551 anan(math.huge % 1e30)
552 anan(-math.huge % 1e30)
553 anan(-math.huge % -1e30)
554 assert(1 % math.huge == 1)
555 assert(1e30 % math.huge == 1e30)
556 assert(1e30 % -math.huge == -math.huge)
557 assert(-1 % math.huge == math.huge)
558 assert(-1 % -math.huge == -1)
559end
560
561
562-- testing unsigned comparisons
563assert(math.ult(3, 4))
564assert(not math.ult(4, 4))
565assert(math.ult(-2, -1))
566assert(math.ult(2, -1))
567assert(not math.ult(-2, -2))
568assert(math.ult(maxint, minint))
569assert(not math.ult(minint, maxint))
570
571
572assert(eq(math.sin(-9.8)^2 + math.cos(-9.8)^2, 1))
573assert(eq(math.tan(math.pi/4), 1))
574assert(eq(math.sin(math.pi/2), 1) and eq(math.cos(math.pi/2), 0))
575assert(eq(math.atan(1), math.pi/4) and eq(math.acos(0), math.pi/2) and
576 eq(math.asin(1), math.pi/2))
577assert(eq(math.deg(math.pi/2), 90) and eq(math.rad(90), math.pi/2))
578assert(math.abs(-10.43) == 10.43)
579assert(eqT(math.abs(minint), minint))
580assert(eqT(math.abs(maxint), maxint))
581assert(eqT(math.abs(-maxint), maxint))
582assert(eq(math.atan(1,0), math.pi/2))
583assert(math.fmod(10,3) == 1)
584assert(eq(math.sqrt(10)^2, 10))
585assert(eq(math.log(2, 10), math.log(2)/math.log(10)))
586assert(eq(math.log(2, 2), 1))
587assert(eq(math.log(9, 3), 2))
588assert(eq(math.exp(0), 1))
589assert(eq(math.sin(10), math.sin(10%(2*math.pi))))
590
591
592assert(tonumber(' 1.3e-2 ') == 1.3e-2)
593assert(tonumber(' -1.00000000000001 ') == -1.00000000000001)
594
595-- testing constant limits
596-- 2^23 = 8388608
597assert(8388609 + -8388609 == 0)
598assert(8388608 + -8388608 == 0)
599assert(8388607 + -8388607 == 0)
600
601
602
603do -- testing floor & ceil
604 assert(eqT(math.floor(3.4), 3))
605 assert(eqT(math.ceil(3.4), 4))
606 assert(eqT(math.floor(-3.4), -4))
607 assert(eqT(math.ceil(-3.4), -3))
608 assert(eqT(math.floor(maxint), maxint))
609 assert(eqT(math.ceil(maxint), maxint))
610 assert(eqT(math.floor(minint), minint))
611 assert(eqT(math.floor(minint + 0.0), minint))
612 assert(eqT(math.ceil(minint), minint))
613 assert(eqT(math.ceil(minint + 0.0), minint))
614 assert(math.floor(1e50) == 1e50)
615 assert(math.ceil(1e50) == 1e50)
616 assert(math.floor(-1e50) == -1e50)
617 assert(math.ceil(-1e50) == -1e50)
618 for _, p in pairs{31,32,63,64} do
619 assert(math.floor(2^p) == 2^p)
620 assert(math.floor(2^p + 0.5) == 2^p)
621 assert(math.ceil(2^p) == 2^p)
622 assert(math.ceil(2^p - 0.5) == 2^p)
623 end
624 checkerror("number expected", math.floor, {})
625 checkerror("number expected", math.ceil, print)
626 assert(eqT(math.tointeger(minint), minint))
627 assert(eqT(math.tointeger(minint .. ""), minint))
628 assert(eqT(math.tointeger(maxint), maxint))
629 assert(eqT(math.tointeger(maxint .. ""), maxint))
630 assert(eqT(math.tointeger(minint + 0.0), minint))
631 assert(math.tointeger(0.0 - minint) == nil)
632 assert(math.tointeger(math.pi) == nil)
633 assert(math.tointeger(-math.pi) == nil)
634 assert(math.floor(math.huge) == math.huge)
635 assert(math.ceil(math.huge) == math.huge)
636 assert(math.tointeger(math.huge) == nil)
637 assert(math.floor(-math.huge) == -math.huge)
638 assert(math.ceil(-math.huge) == -math.huge)
639 assert(math.tointeger(-math.huge) == nil)
640 assert(math.tointeger("34.0") == 34)
641 assert(math.tointeger("34.3") == nil)
642 assert(math.tointeger({}) == nil)
643 assert(math.tointeger(0/0) == nil) -- NaN
644end
645
646
647-- testing fmod for integers
648for i = -6, 6 do
649 for j = -6, 6 do
650 if j ~= 0 then
651 local mi = math.fmod(i, j)
652 local mf = math.fmod(i + 0.0, j)
653 assert(mi == mf)
654 assert(math.type(mi) == 'integer' and math.type(mf) == 'float')
655 if (i >= 0 and j >= 0) or (i <= 0 and j <= 0) or mi == 0 then
656 assert(eqT(mi, i % j))
657 end
658 end
659 end
660end
661assert(eqT(math.fmod(minint, minint), 0))
662assert(eqT(math.fmod(maxint, maxint), 0))
663assert(eqT(math.fmod(minint + 1, minint), minint + 1))
664assert(eqT(math.fmod(maxint - 1, maxint), maxint - 1))
665
666checkerror("zero", math.fmod, 3, 0)
667
668
669do -- testing max/min
670 checkerror("value expected", math.max)
671 checkerror("value expected", math.min)
672 assert(eqT(math.max(3), 3))
673 assert(eqT(math.max(3, 5, 9, 1), 9))
674 assert(math.max(maxint, 10e60) == 10e60)
675 assert(eqT(math.max(minint, minint + 1), minint + 1))
676 assert(eqT(math.min(3), 3))
677 assert(eqT(math.min(3, 5, 9, 1), 1))
678 assert(math.min(3.2, 5.9, -9.2, 1.1) == -9.2)
679 assert(math.min(1.9, 1.7, 1.72) == 1.7)
680 assert(math.min(-10e60, minint) == -10e60)
681 assert(eqT(math.min(maxint, maxint - 1), maxint - 1))
682 assert(eqT(math.min(maxint - 2, maxint, maxint - 1), maxint - 2))
683end
684-- testing implicit convertions
685
686local a,b = '10', '20'
687assert(a*b == 200 and a+b == 30 and a-b == -10 and a/b == 0.5 and -b == -20)
688assert(a == '10' and b == '20')
689
690
691do
692 print("testing -0 and NaN")
693 local mz, z = -0.0, 0.0
694 assert(mz == z)
695 assert(1/mz < 0 and 0 < 1/z)
696 local a = {[mz] = 1}
697 assert(a[z] == 1 and a[mz] == 1)
698 a[z] = 2
699 assert(a[z] == 2 and a[mz] == 2)
700 local inf = math.huge * 2 + 1
701 mz, z = -1/inf, 1/inf
702 assert(mz == z)
703 assert(1/mz < 0 and 0 < 1/z)
704 local NaN = inf - inf
705 assert(NaN ~= NaN)
706 assert(not (NaN < NaN))
707 assert(not (NaN <= NaN))
708 assert(not (NaN > NaN))
709 assert(not (NaN >= NaN))
710 assert(not (0 < NaN) and not (NaN < 0))
711 local NaN1 = 0/0
712 assert(NaN ~= NaN1 and not (NaN <= NaN1) and not (NaN1 <= NaN))
713 local a = {}
714 assert(not pcall(rawset, a, NaN, 1))
715 assert(a[NaN] == nil)
716 a[1] = 1
717 assert(not pcall(rawset, a, NaN, 1))
718 assert(a[NaN] == nil)
719 -- strings with same binary representation as 0.0 (might create problems
720 -- for constant manipulation in the pre-compiler)
721 local a1, a2, a3, a4, a5 = 0, 0, "\0\0\0\0\0\0\0\0", 0, "\0\0\0\0\0\0\0\0"
722 assert(a1 == a2 and a2 == a4 and a1 ~= a3)
723 assert(a3 == a5)
724end
725
726
727print("testing 'math.random'")
728math.randomseed(0)
729
730do -- test random for floats
731 local max = -math.huge
732 local min = math.huge
733 for i = 0, 20000 do
734 local t = math.random()
735 assert(0 <= t and t < 1)
736 max = math.max(max, t)
737 min = math.min(min, t)
738 if eq(max, 1, 0.001) and eq(min, 0, 0.001) then
739 goto ok
740 end
741 end
742 -- loop ended without satisfing condition
743 assert(false)
744 ::ok::
745end
746
747do
748 local function aux (p, lim) -- test random for small intervals
749 local x1, x2
750 if #p == 1 then x1 = 1; x2 = p[1]
751 else x1 = p[1]; x2 = p[2]
752 end
753 local mark = {}; local count = 0 -- to check that all values appeared
754 for i = 0, lim or 2000 do
755 local t = math.random(table.unpack(p))
756 assert(x1 <= t and t <= x2)
757 if not mark[t] then -- new value
758 mark[t] = true
759 count = count + 1
760 end
761 if count == x2 - x1 + 1 then -- all values appeared; OK
762 goto ok
763 end
764 end
765 -- loop ended without satisfing condition
766 assert(false)
767 ::ok::
768 end
769
770 aux({-10,0})
771 aux({6})
772 aux({-10, 10})
773 aux({minint, minint})
774 aux({maxint, maxint})
775 aux({minint, minint + 9})
776 aux({maxint - 3, maxint})
777end
778
779do
780 local function aux(p1, p2) -- test random for large intervals
781 local max = minint
782 local min = maxint
783 local n = 200
784 local mark = {}; local count = 0 -- to count how many different values
785 for _ = 1, n do
786 local t = math.random(p1, p2)
787 max = math.max(max, t)
788 min = math.min(min, t)
789 if not mark[t] then -- new value
790 mark[t] = true
791 count = count + 1
792 end
793 end
794 -- at least 80% of values are different
795 assert(count >= n * 0.8)
796 -- min and max not too far from formal min and max
797 local diff = (p2 - p1) // 8
798 assert(min < p1 + diff and max > p2 - diff)
799 end
800 aux(0, maxint)
801 aux(1, maxint)
802 aux(minint, -1)
803 aux(minint // 2, maxint // 2)
804end
805
806for i=1,100 do
807 assert(math.random(maxint) > 0)
808 assert(math.random(minint, -1) < 0)
809end
810
811assert(not pcall(math.random, 1, 2, 3)) -- too many arguments
812
813-- empty interval
814assert(not pcall(math.random, minint + 1, minint))
815assert(not pcall(math.random, maxint, maxint - 1))
816assert(not pcall(math.random, maxint, minint))
817
818-- interval too large
819assert(not pcall(math.random, minint, 0))
820assert(not pcall(math.random, -1, maxint))
821assert(not pcall(math.random, minint // 2, maxint // 2 + 1))
822
823
824print('OK')
diff --git a/testes/nextvar.lua b/testes/nextvar.lua
new file mode 100644
index 00000000..ce7312e3
--- /dev/null
+++ b/testes/nextvar.lua
@@ -0,0 +1,631 @@
1-- $Id: nextvar.lua,v 1.79 2016/11/07 13:11:28 roberto Exp $
2-- See Copyright Notice in file all.lua
3
4print('testing tables, next, and for')
5
6local function checkerror (msg, f, ...)
7 local s, err = pcall(f, ...)
8 assert(not s and string.find(err, msg))
9end
10
11
12local a = {}
13
14-- make sure table has lots of space in hash part
15for i=1,100 do a[i.."+"] = true end
16for i=1,100 do a[i.."+"] = nil end
17-- fill hash part with numeric indices testing size operator
18for i=1,100 do
19 a[i] = true
20 assert(#a == i)
21end
22
23-- testing ipairs
24local x = 0
25for k,v in ipairs{10,20,30;x=12} do
26 x = x + 1
27 assert(k == x and v == x * 10)
28end
29
30for _ in ipairs{x=12, y=24} do assert(nil) end
31
32-- test for 'false' x ipair
33x = false
34local i = 0
35for k,v in ipairs{true,false,true,false} do
36 i = i + 1
37 x = not x
38 assert(x == v)
39end
40assert(i == 4)
41
42-- iterator function is always the same
43assert(type(ipairs{}) == 'function' and ipairs{} == ipairs{})
44
45
46if not T then
47 (Message or print)
48 ('\n >>> testC not active: skipping tests for table sizes <<<\n')
49else --[
50-- testing table sizes
51
52local function log2 (x) return math.log(x, 2) end
53
54local function mp2 (n) -- minimum power of 2 >= n
55 local mp = 2^math.ceil(log2(n))
56 assert(n == 0 or (mp/2 < n and n <= mp))
57 return mp
58end
59
60local function fb (n)
61 local r, nn = T.int2fb(n)
62 assert(r < 256)
63 return nn
64end
65
66-- test fb function
67for a = 1, 10000 do -- all numbers up to 10^4
68 local n = fb(a)
69 assert(a <= n and n <= a*1.125)
70end
71local a = 1024 -- plus a few up to 2 ^30
72local lim = 2^30
73while a < lim do
74 local n = fb(a)
75 assert(a <= n and n <= a*1.125)
76 a = math.ceil(a*1.3)
77end
78
79
80local function check (t, na, nh)
81 local a, h = T.querytab(t)
82 if a ~= na or h ~= nh then
83 print(na, nh, a, h)
84 assert(nil)
85 end
86end
87
88
89-- testing C library sizes
90do
91 local s = 0
92 for _ in pairs(math) do s = s + 1 end
93 check(math, 0, mp2(s))
94end
95
96
97-- testing constructor sizes
98local lim = 40
99local s = 'return {'
100for i=1,lim do
101 s = s..i..','
102 local s = s
103 for k=0,lim do
104 local t = load(s..'}', '')()
105 assert(#t == i)
106 check(t, fb(i), mp2(k))
107 s = string.format('%sa%d=%d,', s, k, k)
108 end
109end
110
111
112-- tests with unknown number of elements
113local a = {}
114for i=1,lim do a[i] = i end -- build auxiliary table
115for k=0,lim do
116 local a = {table.unpack(a,1,k)}
117 assert(#a == k)
118 check(a, k, 0)
119 a = {1,2,3,table.unpack(a,1,k)}
120 check(a, k+3, 0)
121 assert(#a == k + 3)
122end
123
124
125-- testing tables dynamically built
126local lim = 130
127local a = {}; a[2] = 1; check(a, 0, 1)
128a = {}; a[0] = 1; check(a, 0, 1); a[2] = 1; check(a, 0, 2)
129a = {}; a[0] = 1; a[1] = 1; check(a, 1, 1)
130a = {}
131for i = 1,lim do
132 a[i] = 1
133 assert(#a == i)
134 check(a, mp2(i), 0)
135end
136
137a = {}
138for i = 1,lim do
139 a['a'..i] = 1
140 assert(#a == 0)
141 check(a, 0, mp2(i))
142end
143
144a = {}
145for i=1,16 do a[i] = i end
146check(a, 16, 0)
147do
148 for i=1,11 do a[i] = nil end
149 for i=30,50 do a[i] = nil end -- force a rehash (?)
150 check(a, 0, 8) -- only 5 elements in the table
151 a[10] = 1
152 for i=30,50 do a[i] = nil end -- force a rehash (?)
153 check(a, 0, 8) -- only 6 elements in the table
154 for i=1,14 do a[i] = nil end
155 for i=18,50 do a[i] = nil end -- force a rehash (?)
156 check(a, 0, 4) -- only 2 elements ([15] and [16])
157end
158
159-- reverse filling
160for i=1,lim do
161 local a = {}
162 for i=i,1,-1 do a[i] = i end -- fill in reverse
163 check(a, mp2(i), 0)
164end
165
166-- size tests for vararg
167lim = 35
168function foo (n, ...)
169 local arg = {...}
170 check(arg, n, 0)
171 assert(select('#', ...) == n)
172 arg[n+1] = true
173 check(arg, mp2(n+1), 0)
174 arg.x = true
175 check(arg, mp2(n+1), 1)
176end
177local a = {}
178for i=1,lim do a[i] = true; foo(i, table.unpack(a)) end
179
180end --]
181
182
183-- test size operation on empty tables
184assert(#{} == 0)
185assert(#{nil} == 0)
186assert(#{nil, nil} == 0)
187assert(#{nil, nil, nil} == 0)
188assert(#{nil, nil, nil, nil} == 0)
189print'+'
190
191
192local nofind = {}
193
194a,b,c = 1,2,3
195a,b,c = nil
196
197
198-- next uses always the same iteraction function
199assert(next{} == next{})
200
201local function find (name)
202 local n,v
203 while 1 do
204 n,v = next(_G, n)
205 if not n then return nofind end
206 assert(v ~= nil)
207 if n == name then return v end
208 end
209end
210
211local function find1 (name)
212 for n,v in pairs(_G) do
213 if n==name then return v end
214 end
215 return nil -- not found
216end
217
218
219assert(print==find("print") and print == find1("print"))
220assert(_G["print"]==find("print"))
221assert(assert==find1("assert"))
222assert(nofind==find("return"))
223assert(not find1("return"))
224_G["ret" .. "urn"] = nil
225assert(nofind==find("return"))
226_G["xxx"] = 1
227assert(xxx==find("xxx"))
228
229-- invalid key to 'next'
230checkerror("invalid key", next, {10,20}, 3)
231
232-- both 'pairs' and 'ipairs' need an argument
233checkerror("bad argument", pairs)
234checkerror("bad argument", ipairs)
235
236print('+')
237
238a = {}
239for i=0,10000 do
240 if math.fmod(i,10) ~= 0 then
241 a['x'..i] = i
242 end
243end
244
245n = {n=0}
246for i,v in pairs(a) do
247 n.n = n.n+1
248 assert(i and v and a[i] == v)
249end
250assert(n.n == 9000)
251a = nil
252
253do -- clear global table
254 local a = {}
255 for n,v in pairs(_G) do a[n]=v end
256 for n,v in pairs(a) do
257 if not package.loaded[n] and type(v) ~= "function" and
258 not string.find(n, "^[%u_]") then
259 _G[n] = nil
260 end
261 collectgarbage()
262 end
263end
264
265
266--
267
268local function checknext (a)
269 local b = {}
270 do local k,v = next(a); while k do b[k] = v; k,v = next(a,k) end end
271 for k,v in pairs(b) do assert(a[k] == v) end
272 for k,v in pairs(a) do assert(b[k] == v) end
273end
274
275checknext{1,x=1,y=2,z=3}
276checknext{1,2,x=1,y=2,z=3}
277checknext{1,2,3,x=1,y=2,z=3}
278checknext{1,2,3,4,x=1,y=2,z=3}
279checknext{1,2,3,4,5,x=1,y=2,z=3}
280
281assert(#{} == 0)
282assert(#{[-1] = 2} == 0)
283assert(#{1,2,3,nil,nil} == 3)
284for i=0,40 do
285 local a = {}
286 for j=1,i do a[j]=j end
287 assert(#a == i)
288end
289
290-- 'maxn' is now deprecated, but it is easily defined in Lua
291function table.maxn (t)
292 local max = 0
293 for k in pairs(t) do
294 max = (type(k) == 'number') and math.max(max, k) or max
295 end
296 return max
297end
298
299assert(table.maxn{} == 0)
300assert(table.maxn{["1000"] = true} == 0)
301assert(table.maxn{["1000"] = true, [24.5] = 3} == 24.5)
302assert(table.maxn{[1000] = true} == 1000)
303assert(table.maxn{[10] = true, [100*math.pi] = print} == 100*math.pi)
304
305table.maxn = nil
306
307-- int overflow
308a = {}
309for i=0,50 do a[2^i] = true end
310assert(a[#a])
311
312print('+')
313
314
315-- erasing values
316local t = {[{1}] = 1, [{2}] = 2, [string.rep("x ", 4)] = 3,
317 [100.3] = 4, [4] = 5}
318
319local n = 0
320for k, v in pairs( t ) do
321 n = n+1
322 assert(t[k] == v)
323 t[k] = nil
324 collectgarbage()
325 assert(t[k] == nil)
326end
327assert(n == 5)
328
329
330local function test (a)
331 assert(not pcall(table.insert, a, 2, 20));
332 table.insert(a, 10); table.insert(a, 2, 20);
333 table.insert(a, 1, -1); table.insert(a, 40);
334 table.insert(a, #a+1, 50)
335 table.insert(a, 2, -2)
336 assert(not pcall(table.insert, a, 0, 20));
337 assert(not pcall(table.insert, a, #a + 2, 20));
338 assert(table.remove(a,1) == -1)
339 assert(table.remove(a,1) == -2)
340 assert(table.remove(a,1) == 10)
341 assert(table.remove(a,1) == 20)
342 assert(table.remove(a,1) == 40)
343 assert(table.remove(a,1) == 50)
344 assert(table.remove(a,1) == nil)
345 assert(table.remove(a) == nil)
346 assert(table.remove(a, #a) == nil)
347end
348
349a = {n=0, [-7] = "ban"}
350test(a)
351assert(a.n == 0 and a[-7] == "ban")
352
353a = {[-7] = "ban"};
354test(a)
355assert(a.n == nil and #a == 0 and a[-7] == "ban")
356
357a = {[-1] = "ban"}
358test(a)
359assert(#a == 0 and table.remove(a) == nil and a[-1] == "ban")
360
361a = {[0] = "ban"}
362assert(#a == 0 and table.remove(a) == "ban" and a[0] == nil)
363
364table.insert(a, 1, 10); table.insert(a, 1, 20); table.insert(a, 1, -1)
365assert(table.remove(a) == 10)
366assert(table.remove(a) == 20)
367assert(table.remove(a) == -1)
368assert(table.remove(a) == nil)
369
370a = {'c', 'd'}
371table.insert(a, 3, 'a')
372table.insert(a, 'b')
373assert(table.remove(a, 1) == 'c')
374assert(table.remove(a, 1) == 'd')
375assert(table.remove(a, 1) == 'a')
376assert(table.remove(a, 1) == 'b')
377assert(table.remove(a, 1) == nil)
378assert(#a == 0 and a.n == nil)
379
380a = {10,20,30,40}
381assert(table.remove(a, #a + 1) == nil)
382assert(not pcall(table.remove, a, 0))
383assert(a[#a] == 40)
384assert(table.remove(a, #a) == 40)
385assert(a[#a] == 30)
386assert(table.remove(a, 2) == 20)
387assert(a[#a] == 30 and #a == 2)
388
389do -- testing table library with metamethods
390 local function test (proxy, t)
391 for i = 1, 10 do
392 table.insert(proxy, 1, i)
393 end
394 assert(#proxy == 10 and #t == 10)
395 for i = 1, 10 do
396 assert(t[i] == 11 - i)
397 end
398 table.sort(proxy)
399 for i = 1, 10 do
400 assert(t[i] == i and proxy[i] == i)
401 end
402 assert(table.concat(proxy, ",") == "1,2,3,4,5,6,7,8,9,10")
403 for i = 1, 8 do
404 assert(table.remove(proxy, 1) == i)
405 end
406 assert(#proxy == 2 and #t == 2)
407 local a, b, c = table.unpack(proxy)
408 assert(a == 9 and b == 10 and c == nil)
409 end
410
411 -- all virtual
412 local t = {}
413 local proxy = setmetatable({}, {
414 __len = function () return #t end,
415 __index = t,
416 __newindex = t,
417 })
418 test(proxy, t)
419
420 -- only __newindex
421 local count = 0
422 t = setmetatable({}, {
423 __newindex = function (t,k,v) count = count + 1; rawset(t,k,v) end})
424 test(t, t)
425 assert(count == 10) -- after first 10, all other sets are not new
426
427 -- no __newindex
428 t = setmetatable({}, {
429 __index = function (_,k) return k + 1 end,
430 __len = function (_) return 5 end})
431 assert(table.concat(t, ";") == "2;3;4;5;6")
432
433end
434
435
436if not T then
437 (Message or print)
438 ('\n >>> testC not active: skipping tests for table library on non-tables <<<\n')
439else --[
440 local debug = require'debug'
441 local tab = {10, 20, 30}
442 local mt = {}
443 local u = T.newuserdata(0)
444 checkerror("table expected", table.insert, u, 40)
445 checkerror("table expected", table.remove, u)
446 debug.setmetatable(u, mt)
447 checkerror("table expected", table.insert, u, 40)
448 checkerror("table expected", table.remove, u)
449 mt.__index = tab
450 checkerror("table expected", table.insert, u, 40)
451 checkerror("table expected", table.remove, u)
452 mt.__newindex = tab
453 checkerror("table expected", table.insert, u, 40)
454 checkerror("table expected", table.remove, u)
455 mt.__len = function () return #tab end
456 table.insert(u, 40)
457 assert(#u == 4 and #tab == 4 and u[4] == 40 and tab[4] == 40)
458 assert(table.remove(u) == 40)
459 table.insert(u, 1, 50)
460 assert(#u == 4 and #tab == 4 and u[4] == 30 and tab[1] == 50)
461
462 mt.__newindex = nil
463 mt.__len = nil
464 local tab2 = {}
465 local u2 = T.newuserdata(0)
466 debug.setmetatable(u2, {__newindex = function (_, k, v) tab2[k] = v end})
467 table.move(u, 1, 4, 1, u2)
468 assert(#tab2 == 4 and tab2[1] == tab[1] and tab2[4] == tab[4])
469
470end -- ]
471
472print('+')
473
474a = {}
475for i=1,1000 do
476 a[i] = i; a[i-1] = nil
477end
478assert(next(a,nil) == 1000 and next(a,1000) == nil)
479
480assert(next({}) == nil)
481assert(next({}, nil) == nil)
482
483for a,b in pairs{} do error"not here" end
484for i=1,0 do error'not here' end
485for i=0,1,-1 do error'not here' end
486a = nil; for i=1,1 do assert(not a); a=1 end; assert(a)
487a = nil; for i=1,1,-1 do assert(not a); a=1 end; assert(a)
488
489do
490 print("testing floats in numeric for")
491 local a
492 -- integer count
493 a = 0; for i=1, 1, 1 do a=a+1 end; assert(a==1)
494 a = 0; for i=10000, 1e4, -1 do a=a+1 end; assert(a==1)
495 a = 0; for i=1, 0.99999, 1 do a=a+1 end; assert(a==0)
496 a = 0; for i=9999, 1e4, -1 do a=a+1 end; assert(a==0)
497 a = 0; for i=1, 0.99999, -1 do a=a+1 end; assert(a==1)
498
499 -- float count
500 a = 0; for i=0, 0.999999999, 0.1 do a=a+1 end; assert(a==10)
501 a = 0; for i=1.0, 1, 1 do a=a+1 end; assert(a==1)
502 a = 0; for i=-1.5, -1.5, 1 do a=a+1 end; assert(a==1)
503 a = 0; for i=1e6, 1e6, -1 do a=a+1 end; assert(a==1)
504 a = 0; for i=1.0, 0.99999, 1 do a=a+1 end; assert(a==0)
505 a = 0; for i=99999, 1e5, -1.0 do a=a+1 end; assert(a==0)
506 a = 0; for i=1.0, 0.99999, -1 do a=a+1 end; assert(a==1)
507end
508
509-- conversion
510a = 0; for i="10","1","-2" do a=a+1 end; assert(a==5)
511
512do -- checking types
513 local c
514 local function checkfloat (i)
515 assert(math.type(i) == "float")
516 c = c + 1
517 end
518
519 c = 0; for i = 1.0, 10 do checkfloat(i) end
520 assert(c == 10)
521
522 c = 0; for i = -1, -10, -1.0 do checkfloat(i) end
523 assert(c == 10)
524
525 local function checkint (i)
526 assert(math.type(i) == "integer")
527 c = c + 1
528 end
529
530 local m = math.maxinteger
531 c = 0; for i = m, m - 10, -1 do checkint(i) end
532 assert(c == 11)
533
534 c = 0; for i = 1, 10.9 do checkint(i) end
535 assert(c == 10)
536
537 c = 0; for i = 10, 0.001, -1 do checkint(i) end
538 assert(c == 10)
539
540 c = 0; for i = 1, "10.8" do checkint(i) end
541 assert(c == 10)
542
543 c = 0; for i = 9, "3.4", -1 do checkint(i) end
544 assert(c == 6)
545
546 c = 0; for i = 0, " -3.4 ", -1 do checkint(i) end
547 assert(c == 4)
548
549 c = 0; for i = 100, "96.3", -2 do checkint(i) end
550 assert(c == 2)
551
552 c = 0; for i = 1, math.huge do if i > 10 then break end; checkint(i) end
553 assert(c == 10)
554
555 c = 0; for i = -1, -math.huge, -1 do
556 if i < -10 then break end; checkint(i)
557 end
558 assert(c == 10)
559
560
561 for i = math.mininteger, -10e100 do assert(false) end
562 for i = math.maxinteger, 10e100, -1 do assert(false) end
563
564end
565
566collectgarbage()
567
568
569-- testing generic 'for'
570
571local function f (n, p)
572 local t = {}; for i=1,p do t[i] = i*10 end
573 return function (_,n)
574 if n > 0 then
575 n = n-1
576 return n, table.unpack(t)
577 end
578 end, nil, n
579end
580
581local x = 0
582for n,a,b,c,d in f(5,3) do
583 x = x+1
584 assert(a == 10 and b == 20 and c == 30 and d == nil)
585end
586assert(x == 5)
587
588
589
590-- testing __pairs and __ipairs metamethod
591a = {}
592do
593 local x,y,z = pairs(a)
594 assert(type(x) == 'function' and y == a and z == nil)
595end
596
597local function foo (e,i)
598 assert(e == a)
599 if i <= 10 then return i+1, i+2 end
600end
601
602local function foo1 (e,i)
603 i = i + 1
604 assert(e == a)
605 if i <= e.n then return i,a[i] end
606end
607
608setmetatable(a, {__pairs = function (x) return foo, x, 0 end})
609
610local i = 0
611for k,v in pairs(a) do
612 i = i + 1
613 assert(k == i and v == k+1)
614end
615
616a.n = 5
617a[3] = 30
618
619-- testing ipairs with metamethods
620a = {n=10}
621setmetatable(a, { __index = function (t,k)
622 if k <= t.n then return k * 10 end
623 end})
624i = 0
625for k,v in ipairs(a) do
626 i = i + 1
627 assert(k == i and v == i * 10)
628end
629assert(i == a.n)
630
631print"OK"
diff --git a/testes/pm.lua b/testes/pm.lua
new file mode 100644
index 00000000..fde39ff0
--- /dev/null
+++ b/testes/pm.lua
@@ -0,0 +1,374 @@
1-- $Id: pm.lua,v 1.48 2016/11/07 13:11:28 roberto Exp $
2-- See Copyright Notice in file all.lua
3
4print('testing pattern matching')
5
6local function checkerror (msg, f, ...)
7 local s, err = pcall(f, ...)
8 assert(not s and string.find(err, msg))
9end
10
11
12function f(s, p)
13 local i,e = string.find(s, p)
14 if i then return string.sub(s, i, e) end
15end
16
17a,b = string.find('', '') -- empty patterns are tricky
18assert(a == 1 and b == 0);
19a,b = string.find('alo', '')
20assert(a == 1 and b == 0)
21a,b = string.find('a\0o a\0o a\0o', 'a', 1) -- first position
22assert(a == 1 and b == 1)
23a,b = string.find('a\0o a\0o a\0o', 'a\0o', 2) -- starts in the midle
24assert(a == 5 and b == 7)
25a,b = string.find('a\0o a\0o a\0o', 'a\0o', 9) -- starts in the midle
26assert(a == 9 and b == 11)
27a,b = string.find('a\0a\0a\0a\0\0ab', '\0ab', 2); -- finds at the end
28assert(a == 9 and b == 11);
29a,b = string.find('a\0a\0a\0a\0\0ab', 'b') -- last position
30assert(a == 11 and b == 11)
31assert(string.find('a\0a\0a\0a\0\0ab', 'b\0') == nil) -- check ending
32assert(string.find('', '\0') == nil)
33assert(string.find('alo123alo', '12') == 4)
34assert(string.find('alo123alo', '^12') == nil)
35
36assert(string.match("aaab", ".*b") == "aaab")
37assert(string.match("aaa", ".*a") == "aaa")
38assert(string.match("b", ".*b") == "b")
39
40assert(string.match("aaab", ".+b") == "aaab")
41assert(string.match("aaa", ".+a") == "aaa")
42assert(not string.match("b", ".+b"))
43
44assert(string.match("aaab", ".?b") == "ab")
45assert(string.match("aaa", ".?a") == "aa")
46assert(string.match("b", ".?b") == "b")
47
48assert(f('aloALO', '%l*') == 'alo')
49assert(f('aLo_ALO', '%a*') == 'aLo')
50
51assert(f(" \n\r*&\n\r xuxu \n\n", "%g%g%g+") == "xuxu")
52
53assert(f('aaab', 'a*') == 'aaa');
54assert(f('aaa', '^.*$') == 'aaa');
55assert(f('aaa', 'b*') == '');
56assert(f('aaa', 'ab*a') == 'aa')
57assert(f('aba', 'ab*a') == 'aba')
58assert(f('aaab', 'a+') == 'aaa')
59assert(f('aaa', '^.+$') == 'aaa')
60assert(f('aaa', 'b+') == nil)
61assert(f('aaa', 'ab+a') == nil)
62assert(f('aba', 'ab+a') == 'aba')
63assert(f('a$a', '.$') == 'a')
64assert(f('a$a', '.%$') == 'a$')
65assert(f('a$a', '.$.') == 'a$a')
66assert(f('a$a', '$$') == nil)
67assert(f('a$b', 'a$') == nil)
68assert(f('a$a', '$') == '')
69assert(f('', 'b*') == '')
70assert(f('aaa', 'bb*') == nil)
71assert(f('aaab', 'a-') == '')
72assert(f('aaa', '^.-$') == 'aaa')
73assert(f('aabaaabaaabaaaba', 'b.*b') == 'baaabaaabaaab')
74assert(f('aabaaabaaabaaaba', 'b.-b') == 'baaab')
75assert(f('alo xo', '.o$') == 'xo')
76assert(f(' \n isto é assim', '%S%S*') == 'isto')
77assert(f(' \n isto é assim', '%S*$') == 'assim')
78assert(f(' \n isto é assim', '[a-z]*$') == 'assim')
79assert(f('um caracter ? extra', '[^%sa-z]') == '?')
80assert(f('', 'a?') == '')
81assert(f('á', 'á?') == 'á')
82assert(f('ábl', 'á?b?l?') == 'ábl')
83assert(f(' ábl', 'á?b?l?') == '')
84assert(f('aa', '^aa?a?a') == 'aa')
85assert(f(']]]áb', '[^]]') == 'á')
86assert(f("0alo alo", "%x*") == "0a")
87assert(f("alo alo", "%C+") == "alo alo")
88print('+')
89
90
91function f1(s, p)
92 p = string.gsub(p, "%%([0-9])", function (s)
93 return "%" .. (tonumber(s)+1)
94 end)
95 p = string.gsub(p, "^(^?)", "%1()", 1)
96 p = string.gsub(p, "($?)$", "()%1", 1)
97 local t = {string.match(s, p)}
98 return string.sub(s, t[1], t[#t] - 1)
99end
100
101assert(f1('alo alx 123 b\0o b\0o', '(..*) %1') == "b\0o b\0o")
102assert(f1('axz123= 4= 4 34', '(.+)=(.*)=%2 %1') == '3= 4= 4 3')
103assert(f1('=======', '^(=*)=%1$') == '=======')
104assert(string.match('==========', '^([=]*)=%1$') == nil)
105
106local function range (i, j)
107 if i <= j then
108 return i, range(i+1, j)
109 end
110end
111
112local abc = string.char(range(0, 255));
113
114assert(string.len(abc) == 256)
115
116function strset (p)
117 local res = {s=''}
118 string.gsub(abc, p, function (c) res.s = res.s .. c end)
119 return res.s
120end;
121
122assert(string.len(strset('[\200-\210]')) == 11)
123
124assert(strset('[a-z]') == "abcdefghijklmnopqrstuvwxyz")
125assert(strset('[a-z%d]') == strset('[%da-uu-z]'))
126assert(strset('[a-]') == "-a")
127assert(strset('[^%W]') == strset('[%w]'))
128assert(strset('[]%%]') == '%]')
129assert(strset('[a%-z]') == '-az')
130assert(strset('[%^%[%-a%]%-b]') == '-[]^ab')
131assert(strset('%Z') == strset('[\1-\255]'))
132assert(strset('.') == strset('[\1-\255%z]'))
133print('+');
134
135assert(string.match("alo xyzK", "(%w+)K") == "xyz")
136assert(string.match("254 K", "(%d*)K") == "")
137assert(string.match("alo ", "(%w*)$") == "")
138assert(string.match("alo ", "(%w+)$") == nil)
139assert(string.find("(álo)", "%(á") == 1)
140local a, b, c, d, e = string.match("âlo alo", "^(((.).).* (%w*))$")
141assert(a == 'âlo alo' and b == 'âl' and c == 'â' and d == 'alo' and e == nil)
142a, b, c, d = string.match('0123456789', '(.+(.?)())')
143assert(a == '0123456789' and b == '' and c == 11 and d == nil)
144print('+')
145
146assert(string.gsub('ülo ülo', 'ü', 'x') == 'xlo xlo')
147assert(string.gsub('alo úlo ', ' +$', '') == 'alo úlo') -- trim
148assert(string.gsub(' alo alo ', '^%s*(.-)%s*$', '%1') == 'alo alo') -- double trim
149assert(string.gsub('alo alo \n 123\n ', '%s+', ' ') == 'alo alo 123 ')
150t = "abç d"
151a, b = string.gsub(t, '(.)', '%1@')
152assert('@'..a == string.gsub(t, '', '@') and b == 5)
153a, b = string.gsub('abçd', '(.)', '%0@', 2)
154assert(a == 'a@b@çd' and b == 2)
155assert(string.gsub('alo alo', '()[al]', '%1') == '12o 56o')
156assert(string.gsub("abc=xyz", "(%w*)(%p)(%w+)", "%3%2%1-%0") ==
157 "xyz=abc-abc=xyz")
158assert(string.gsub("abc", "%w", "%1%0") == "aabbcc")
159assert(string.gsub("abc", "%w+", "%0%1") == "abcabc")
160assert(string.gsub('áéí', '$', '\0óú') == 'áéí\0óú')
161assert(string.gsub('', '^', 'r') == 'r')
162assert(string.gsub('', '$', 'r') == 'r')
163print('+')
164
165
166do -- new (5.3.3) semantics for empty matches
167 assert(string.gsub("a b cd", " *", "-") == "-a-b-c-d-")
168
169 local res = ""
170 local sub = "a \nbc\t\td"
171 local i = 1
172 for p, e in string.gmatch(sub, "()%s*()") do
173 res = res .. string.sub(sub, i, p - 1) .. "-"
174 i = e
175 end
176 assert(res == "-a-b-c-d-")
177end
178
179
180assert(string.gsub("um (dois) tres (quatro)", "(%(%w+%))", string.upper) ==
181 "um (DOIS) tres (QUATRO)")
182
183do
184 local function setglobal (n,v) rawset(_G, n, v) end
185 string.gsub("a=roberto,roberto=a", "(%w+)=(%w%w*)", setglobal)
186 assert(_G.a=="roberto" and _G.roberto=="a")
187end
188
189function f(a,b) return string.gsub(a,'.',b) end
190assert(string.gsub("trocar tudo em |teste|b| é |beleza|al|", "|([^|]*)|([^|]*)|", f) ==
191 "trocar tudo em bbbbb é alalalalalal")
192
193local function dostring (s) return load(s, "")() or "" end
194assert(string.gsub("alo $a='x'$ novamente $return a$",
195 "$([^$]*)%$",
196 dostring) == "alo novamente x")
197
198x = string.gsub("$x=string.gsub('alo', '.', string.upper)$ assim vai para $return x$",
199 "$([^$]*)%$", dostring)
200assert(x == ' assim vai para ALO')
201
202t = {}
203s = 'a alo jose joao'
204r = string.gsub(s, '()(%w+)()', function (a,w,b)
205 assert(string.len(w) == b-a);
206 t[a] = b-a;
207 end)
208assert(s == r and t[1] == 1 and t[3] == 3 and t[7] == 4 and t[13] == 4)
209
210
211function isbalanced (s)
212 return string.find(string.gsub(s, "%b()", ""), "[()]") == nil
213end
214
215assert(isbalanced("(9 ((8))(\0) 7) \0\0 a b ()(c)() a"))
216assert(not isbalanced("(9 ((8) 7) a b (\0 c) a"))
217assert(string.gsub("alo 'oi' alo", "%b''", '"') == 'alo " alo')
218
219
220local t = {"apple", "orange", "lime"; n=0}
221assert(string.gsub("x and x and x", "x", function () t.n=t.n+1; return t[t.n] end)
222 == "apple and orange and lime")
223
224t = {n=0}
225string.gsub("first second word", "%w%w*", function (w) t.n=t.n+1; t[t.n] = w end)
226assert(t[1] == "first" and t[2] == "second" and t[3] == "word" and t.n == 3)
227
228t = {n=0}
229assert(string.gsub("first second word", "%w+",
230 function (w) t.n=t.n+1; t[t.n] = w end, 2) == "first second word")
231assert(t[1] == "first" and t[2] == "second" and t[3] == nil)
232
233checkerror("invalid replacement value %(a table%)",
234 string.gsub, "alo", ".", {a = {}})
235checkerror("invalid capture index %%2", string.gsub, "alo", ".", "%2")
236checkerror("invalid capture index %%0", string.gsub, "alo", "(%0)", "a")
237checkerror("invalid capture index %%1", string.gsub, "alo", "(%1)", "a")
238checkerror("invalid use of '%%'", string.gsub, "alo", ".", "%x")
239
240-- bug since 2.5 (C-stack overflow)
241do
242 local function f (size)
243 local s = string.rep("a", size)
244 local p = string.rep(".?", size)
245 return pcall(string.match, s, p)
246 end
247 local r, m = f(80)
248 assert(r and #m == 80)
249 r, m = f(200000)
250 assert(not r and string.find(m, "too complex"))
251end
252
253if not _soft then
254 print("big strings")
255 local a = string.rep('a', 300000)
256 assert(string.find(a, '^a*.?$'))
257 assert(not string.find(a, '^a*.?b$'))
258 assert(string.find(a, '^a-.?$'))
259
260 -- bug in 5.1.2
261 a = string.rep('a', 10000) .. string.rep('b', 10000)
262 assert(not pcall(string.gsub, a, 'b'))
263end
264
265-- recursive nest of gsubs
266function rev (s)
267 return string.gsub(s, "(.)(.+)", function (c,s1) return rev(s1)..c end)
268end
269
270local x = "abcdef"
271assert(rev(rev(x)) == x)
272
273
274-- gsub with tables
275assert(string.gsub("alo alo", ".", {}) == "alo alo")
276assert(string.gsub("alo alo", "(.)", {a="AA", l=""}) == "AAo AAo")
277assert(string.gsub("alo alo", "(.).", {a="AA", l="K"}) == "AAo AAo")
278assert(string.gsub("alo alo", "((.)(.?))", {al="AA", o=false}) == "AAo AAo")
279
280assert(string.gsub("alo alo", "().", {'x','yy','zzz'}) == "xyyzzz alo")
281
282t = {}; setmetatable(t, {__index = function (t,s) return string.upper(s) end})
283assert(string.gsub("a alo b hi", "%w%w+", t) == "a ALO b HI")
284
285
286-- tests for gmatch
287local a = 0
288for i in string.gmatch('abcde', '()') do assert(i == a+1); a=i end
289assert(a==6)
290
291t = {n=0}
292for w in string.gmatch("first second word", "%w+") do
293 t.n=t.n+1; t[t.n] = w
294end
295assert(t[1] == "first" and t[2] == "second" and t[3] == "word")
296
297t = {3, 6, 9}
298for i in string.gmatch ("xuxx uu ppar r", "()(.)%2") do
299 assert(i == table.remove(t, 1))
300end
301assert(#t == 0)
302
303t = {}
304for i,j in string.gmatch("13 14 10 = 11, 15= 16, 22=23", "(%d+)%s*=%s*(%d+)") do
305 t[tonumber(i)] = tonumber(j)
306end
307a = 0
308for k,v in pairs(t) do assert(k+1 == v+0); a=a+1 end
309assert(a == 3)
310
311
312-- tests for `%f' (`frontiers')
313
314assert(string.gsub("aaa aa a aaa a", "%f[%w]a", "x") == "xaa xa x xaa x")
315assert(string.gsub("[[]] [][] [[[[", "%f[[].", "x") == "x[]] x]x] x[[[")
316assert(string.gsub("01abc45de3", "%f[%d]", ".") == ".01abc.45de.3")
317assert(string.gsub("01abc45 de3x", "%f[%D]%w", ".") == "01.bc45 de3.")
318assert(string.gsub("function", "%f[\1-\255]%w", ".") == ".unction")
319assert(string.gsub("function", "%f[^\1-\255]", ".") == "function.")
320
321assert(string.find("a", "%f[a]") == 1)
322assert(string.find("a", "%f[^%z]") == 1)
323assert(string.find("a", "%f[^%l]") == 2)
324assert(string.find("aba", "%f[a%z]") == 3)
325assert(string.find("aba", "%f[%z]") == 4)
326assert(not string.find("aba", "%f[%l%z]"))
327assert(not string.find("aba", "%f[^%l%z]"))
328
329local i, e = string.find(" alo aalo allo", "%f[%S].-%f[%s].-%f[%S]")
330assert(i == 2 and e == 5)
331local k = string.match(" alo aalo allo", "%f[%S](.-%f[%s].-%f[%S])")
332assert(k == 'alo ')
333
334local a = {1, 5, 9, 14, 17,}
335for k in string.gmatch("alo alo th02 is 1hat", "()%f[%w%d]") do
336 assert(table.remove(a, 1) == k)
337end
338assert(#a == 0)
339
340
341-- malformed patterns
342local function malform (p, m)
343 m = m or "malformed"
344 local r, msg = pcall(string.find, "a", p)
345 assert(not r and string.find(msg, m))
346end
347
348malform("(.", "unfinished capture")
349malform(".)", "invalid pattern capture")
350malform("[a")
351malform("[]")
352malform("[^]")
353malform("[a%]")
354malform("[a%")
355malform("%b")
356malform("%ba")
357malform("%")
358malform("%f", "missing")
359
360-- \0 in patterns
361assert(string.match("ab\0\1\2c", "[\0-\2]+") == "\0\1\2")
362assert(string.match("ab\0\1\2c", "[\0-\0]+") == "\0")
363assert(string.find("b$a", "$\0?") == 2)
364assert(string.find("abc\0efg", "%\0") == 4)
365assert(string.match("abc\0efg\0\1e\1g", "%b\0\1") == "\0efg\0\1e\1")
366assert(string.match("abc\0\0\0", "%\0+") == "\0\0\0")
367assert(string.match("abc\0\0\0", "%\0%\0?") == "\0\0")
368
369-- magic char after \0
370assert(string.find("abc\0\0","\0.") == 4)
371assert(string.find("abcx\0\0abc\0abc","x\0\0abc\0a.") == 4)
372
373print('OK')
374
diff --git a/testes/sort.lua b/testes/sort.lua
new file mode 100644
index 00000000..d52feee8
--- /dev/null
+++ b/testes/sort.lua
@@ -0,0 +1,310 @@
1-- $Id: sort.lua,v 1.38 2016/11/07 13:11:28 roberto Exp $
2-- See Copyright Notice in file all.lua
3
4print "testing (parts of) table library"
5
6print "testing unpack"
7
8local unpack = table.unpack
9
10local maxI = math.maxinteger
11local minI = math.mininteger
12
13
14local function checkerror (msg, f, ...)
15 local s, err = pcall(f, ...)
16 assert(not s and string.find(err, msg))
17end
18
19
20checkerror("wrong number of arguments", table.insert, {}, 2, 3, 4)
21
22local x,y,z,a,n
23a = {}; lim = _soft and 200 or 2000
24for i=1, lim do a[i]=i end
25assert(select(lim, unpack(a)) == lim and select('#', unpack(a)) == lim)
26x = unpack(a)
27assert(x == 1)
28x = {unpack(a)}
29assert(#x == lim and x[1] == 1 and x[lim] == lim)
30x = {unpack(a, lim-2)}
31assert(#x == 3 and x[1] == lim-2 and x[3] == lim)
32x = {unpack(a, 10, 6)}
33assert(next(x) == nil) -- no elements
34x = {unpack(a, 11, 10)}
35assert(next(x) == nil) -- no elements
36x,y = unpack(a, 10, 10)
37assert(x == 10 and y == nil)
38x,y,z = unpack(a, 10, 11)
39assert(x == 10 and y == 11 and z == nil)
40a,x = unpack{1}
41assert(a==1 and x==nil)
42a,x = unpack({1,2}, 1, 1)
43assert(a==1 and x==nil)
44
45do
46 local maxi = (1 << 31) - 1 -- maximum value for an int (usually)
47 local mini = -(1 << 31) -- minimum value for an int (usually)
48 checkerror("too many results", unpack, {}, 0, maxi)
49 checkerror("too many results", unpack, {}, 1, maxi)
50 checkerror("too many results", unpack, {}, 0, maxI)
51 checkerror("too many results", unpack, {}, 1, maxI)
52 checkerror("too many results", unpack, {}, mini, maxi)
53 checkerror("too many results", unpack, {}, -maxi, maxi)
54 checkerror("too many results", unpack, {}, minI, maxI)
55 unpack({}, maxi, 0)
56 unpack({}, maxi, 1)
57 unpack({}, maxI, minI)
58 pcall(unpack, {}, 1, maxi + 1)
59 local a, b = unpack({[maxi] = 20}, maxi, maxi)
60 assert(a == 20 and b == nil)
61 a, b = unpack({[maxi] = 20}, maxi - 1, maxi)
62 assert(a == nil and b == 20)
63 local t = {[maxI - 1] = 12, [maxI] = 23}
64 a, b = unpack(t, maxI - 1, maxI); assert(a == 12 and b == 23)
65 a, b = unpack(t, maxI, maxI); assert(a == 23 and b == nil)
66 a, b = unpack(t, maxI, maxI - 1); assert(a == nil and b == nil)
67 t = {[minI] = 12.3, [minI + 1] = 23.5}
68 a, b = unpack(t, minI, minI + 1); assert(a == 12.3 and b == 23.5)
69 a, b = unpack(t, minI, minI); assert(a == 12.3 and b == nil)
70 a, b = unpack(t, minI + 1, minI); assert(a == nil and b == nil)
71end
72
73do -- length is not an integer
74 local t = setmetatable({}, {__len = function () return 'abc' end})
75 assert(#t == 'abc')
76 checkerror("object length is not an integer", table.insert, t, 1)
77end
78
79print "testing pack"
80
81a = table.pack()
82assert(a[1] == nil and a.n == 0)
83
84a = table.pack(table)
85assert(a[1] == table and a.n == 1)
86
87a = table.pack(nil, nil, nil, nil)
88assert(a[1] == nil and a.n == 4)
89
90
91-- testing move
92do
93
94 checkerror("table expected", table.move, 1, 2, 3, 4)
95
96 local function eqT (a, b)
97 for k, v in pairs(a) do assert(b[k] == v) end
98 for k, v in pairs(b) do assert(a[k] == v) end
99 end
100
101 local a = table.move({10,20,30}, 1, 3, 2) -- move forward
102 eqT(a, {10,10,20,30})
103
104 -- move forward with overlap of 1
105 a = table.move({10, 20, 30}, 1, 3, 3)
106 eqT(a, {10, 20, 10, 20, 30})
107
108 -- moving to the same table (not being explicit about it)
109 a = {10, 20, 30, 40}
110 table.move(a, 1, 4, 2, a)
111 eqT(a, {10, 10, 20, 30, 40})
112
113 a = table.move({10,20,30}, 2, 3, 1) -- move backward
114 eqT(a, {20,30,30})
115
116 a = {} -- move to new table
117 assert(table.move({10,20,30}, 1, 3, 1, a) == a)
118 eqT(a, {10,20,30})
119
120 a = {}
121 assert(table.move({10,20,30}, 1, 0, 3, a) == a) -- empty move (no move)
122 eqT(a, {})
123
124 a = table.move({10,20,30}, 1, 10, 1) -- move to the same place
125 eqT(a, {10,20,30})
126
127 -- moving on the fringes
128 a = table.move({[maxI - 2] = 1, [maxI - 1] = 2, [maxI] = 3},
129 maxI - 2, maxI, -10, {})
130 eqT(a, {[-10] = 1, [-9] = 2, [-8] = 3})
131
132 a = table.move({[minI] = 1, [minI + 1] = 2, [minI + 2] = 3},
133 minI, minI + 2, -10, {})
134 eqT(a, {[-10] = 1, [-9] = 2, [-8] = 3})
135
136 a = table.move({45}, 1, 1, maxI)
137 eqT(a, {45, [maxI] = 45})
138
139 a = table.move({[maxI] = 100}, maxI, maxI, minI)
140 eqT(a, {[minI] = 100, [maxI] = 100})
141
142 a = table.move({[minI] = 100}, minI, minI, maxI)
143 eqT(a, {[minI] = 100, [maxI] = 100})
144
145 a = setmetatable({}, {
146 __index = function (_,k) return k * 10 end,
147 __newindex = error})
148 local b = table.move(a, 1, 10, 3, {})
149 eqT(a, {})
150 eqT(b, {nil,nil,10,20,30,40,50,60,70,80,90,100})
151
152 b = setmetatable({""}, {
153 __index = error,
154 __newindex = function (t,k,v)
155 t[1] = string.format("%s(%d,%d)", t[1], k, v)
156 end})
157 table.move(a, 10, 13, 3, b)
158 assert(b[1] == "(3,100)(4,110)(5,120)(6,130)")
159 local stat, msg = pcall(table.move, b, 10, 13, 3, b)
160 assert(not stat and msg == b)
161end
162
163do
164 -- for very long moves, just check initial accesses and interrupt
165 -- move with an error
166 local function checkmove (f, e, t, x, y)
167 local pos1, pos2
168 local a = setmetatable({}, {
169 __index = function (_,k) pos1 = k end,
170 __newindex = function (_,k) pos2 = k; error() end, })
171 local st, msg = pcall(table.move, a, f, e, t)
172 assert(not st and not msg and pos1 == x and pos2 == y)
173 end
174 checkmove(1, maxI, 0, 1, 0)
175 checkmove(0, maxI - 1, 1, maxI - 1, maxI)
176 checkmove(minI, -2, -5, -2, maxI - 6)
177 checkmove(minI + 1, -1, -2, -1, maxI - 3)
178 checkmove(minI, -2, 0, minI, 0) -- non overlapping
179 checkmove(minI + 1, -1, 1, minI + 1, 1) -- non overlapping
180end
181
182checkerror("too many", table.move, {}, 0, maxI, 1)
183checkerror("too many", table.move, {}, -1, maxI - 1, 1)
184checkerror("too many", table.move, {}, minI, -1, 1)
185checkerror("too many", table.move, {}, minI, maxI, 1)
186checkerror("wrap around", table.move, {}, 1, maxI, 2)
187checkerror("wrap around", table.move, {}, 1, 2, maxI)
188checkerror("wrap around", table.move, {}, minI, -2, 2)
189
190
191print"testing sort"
192
193
194-- strange lengths
195local a = setmetatable({}, {__len = function () return -1 end})
196assert(#a == -1)
197table.sort(a, error) -- should not compare anything
198a = setmetatable({}, {__len = function () return maxI end})
199checkerror("too big", table.sort, a)
200
201-- test checks for invalid order functions
202local function check (t)
203 local function f(a, b) assert(a and b); return true end
204 checkerror("invalid order function", table.sort, t, f)
205end
206
207check{1,2,3,4}
208check{1,2,3,4,5}
209check{1,2,3,4,5,6}
210
211
212function check (a, f)
213 f = f or function (x,y) return x<y end;
214 for n = #a, 2, -1 do
215 assert(not f(a[n], a[n-1]))
216 end
217end
218
219a = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep",
220 "Oct", "Nov", "Dec"}
221
222table.sort(a)
223check(a)
224
225function perm (s, n)
226 n = n or #s
227 if n == 1 then
228 local t = {unpack(s)}
229 table.sort(t)
230 check(t)
231 else
232 for i = 1, n do
233 s[i], s[n] = s[n], s[i]
234 perm(s, n - 1)
235 s[i], s[n] = s[n], s[i]
236 end
237 end
238end
239
240perm{}
241perm{1}
242perm{1,2}
243perm{1,2,3}
244perm{1,2,3,4}
245perm{2,2,3,4}
246perm{1,2,3,4,5}
247perm{1,2,3,3,5}
248perm{1,2,3,4,5,6}
249perm{2,2,3,3,5,6}
250
251function timesort (a, n, func, msg, pre)
252 local x = os.clock()
253 table.sort(a, func)
254 x = (os.clock() - x) * 1000
255 pre = pre or ""
256 print(string.format("%ssorting %d %s elements in %.2f msec.", pre, n, msg, x))
257 check(a, func)
258end
259
260limit = 50000
261if _soft then limit = 5000 end
262
263a = {}
264for i=1,limit do
265 a[i] = math.random()
266end
267
268timesort(a, limit, nil, "random")
269
270timesort(a, limit, nil, "sorted", "re-")
271
272a = {}
273for i=1,limit do
274 a[i] = math.random()
275end
276
277x = os.clock(); i=0
278table.sort(a, function(x,y) i=i+1; return y<x end)
279x = (os.clock() - x) * 1000
280print(string.format("Invert-sorting other %d elements in %.2f msec., with %i comparisons",
281 limit, x, i))
282check(a, function(x,y) return y<x end)
283
284
285table.sort{} -- empty array
286
287for i=1,limit do a[i] = false end
288timesort(a, limit, function(x,y) return nil end, "equal")
289
290for i,v in pairs(a) do assert(v == false) end
291
292A = {"álo", "\0first :-)", "alo", "then this one", "45", "and a new"}
293table.sort(A)
294check(A)
295
296table.sort(A, function (x, y)
297 load(string.format("A[%q] = ''", x), "")()
298 collectgarbage()
299 return x<y
300 end)
301
302
303tt = {__lt = function (a,b) return a.val < b.val end}
304a = {}
305for i=1,10 do a[i] = {val=math.random(100)}; setmetatable(a[i], tt); end
306table.sort(a)
307check(a, tt.__lt)
308check(a)
309
310print"OK"
diff --git a/testes/strings.lua b/testes/strings.lua
new file mode 100644
index 00000000..c37a8e75
--- /dev/null
+++ b/testes/strings.lua
@@ -0,0 +1,379 @@
1-- $Id: strings.lua,v 1.87 2016/12/21 19:23:02 roberto Exp $
2-- See Copyright Notice in file all.lua
3
4print('testing strings and string library')
5
6local maxi, mini = math.maxinteger, math.mininteger
7
8
9local function checkerror (msg, f, ...)
10 local s, err = pcall(f, ...)
11 assert(not s and string.find(err, msg))
12end
13
14
15-- testing string comparisons
16assert('alo' < 'alo1')
17assert('' < 'a')
18assert('alo\0alo' < 'alo\0b')
19assert('alo\0alo\0\0' > 'alo\0alo\0')
20assert('alo' < 'alo\0')
21assert('alo\0' > 'alo')
22assert('\0' < '\1')
23assert('\0\0' < '\0\1')
24assert('\1\0a\0a' <= '\1\0a\0a')
25assert(not ('\1\0a\0b' <= '\1\0a\0a'))
26assert('\0\0\0' < '\0\0\0\0')
27assert(not('\0\0\0\0' < '\0\0\0'))
28assert('\0\0\0' <= '\0\0\0\0')
29assert(not('\0\0\0\0' <= '\0\0\0'))
30assert('\0\0\0' <= '\0\0\0')
31assert('\0\0\0' >= '\0\0\0')
32assert(not ('\0\0b' < '\0\0a\0'))
33
34-- testing string.sub
35assert(string.sub("123456789",2,4) == "234")
36assert(string.sub("123456789",7) == "789")
37assert(string.sub("123456789",7,6) == "")
38assert(string.sub("123456789",7,7) == "7")
39assert(string.sub("123456789",0,0) == "")
40assert(string.sub("123456789",-10,10) == "123456789")
41assert(string.sub("123456789",1,9) == "123456789")
42assert(string.sub("123456789",-10,-20) == "")
43assert(string.sub("123456789",-1) == "9")
44assert(string.sub("123456789",-4) == "6789")
45assert(string.sub("123456789",-6, -4) == "456")
46assert(string.sub("123456789", mini, -4) == "123456")
47assert(string.sub("123456789", mini, maxi) == "123456789")
48assert(string.sub("123456789", mini, mini) == "")
49assert(string.sub("\000123456789",3,5) == "234")
50assert(("\000123456789"):sub(8) == "789")
51
52-- testing string.find
53assert(string.find("123456789", "345") == 3)
54a,b = string.find("123456789", "345")
55assert(string.sub("123456789", a, b) == "345")
56assert(string.find("1234567890123456789", "345", 3) == 3)
57assert(string.find("1234567890123456789", "345", 4) == 13)
58assert(string.find("1234567890123456789", "346", 4) == nil)
59assert(string.find("1234567890123456789", ".45", -9) == 13)
60assert(string.find("abcdefg", "\0", 5, 1) == nil)
61assert(string.find("", "") == 1)
62assert(string.find("", "", 1) == 1)
63assert(not string.find("", "", 2))
64assert(string.find('', 'aaa', 1) == nil)
65assert(('alo(.)alo'):find('(.)', 1, 1) == 4)
66
67assert(string.len("") == 0)
68assert(string.len("\0\0\0") == 3)
69assert(string.len("1234567890") == 10)
70
71assert(#"" == 0)
72assert(#"\0\0\0" == 3)
73assert(#"1234567890" == 10)
74
75-- testing string.byte/string.char
76assert(string.byte("a") == 97)
77assert(string.byte("\xe4") > 127)
78assert(string.byte(string.char(255)) == 255)
79assert(string.byte(string.char(0)) == 0)
80assert(string.byte("\0") == 0)
81assert(string.byte("\0\0alo\0x", -1) == string.byte('x'))
82assert(string.byte("ba", 2) == 97)
83assert(string.byte("\n\n", 2, -1) == 10)
84assert(string.byte("\n\n", 2, 2) == 10)
85assert(string.byte("") == nil)
86assert(string.byte("hi", -3) == nil)
87assert(string.byte("hi", 3) == nil)
88assert(string.byte("hi", 9, 10) == nil)
89assert(string.byte("hi", 2, 1) == nil)
90assert(string.char() == "")
91assert(string.char(0, 255, 0) == "\0\255\0")
92assert(string.char(0, string.byte("\xe4"), 0) == "\0\xe4\0")
93assert(string.char(string.byte("\xe4l\0óu", 1, -1)) == "\xe4l\0óu")
94assert(string.char(string.byte("\xe4l\0óu", 1, 0)) == "")
95assert(string.char(string.byte("\xe4l\0óu", -10, 100)) == "\xe4l\0óu")
96
97assert(string.upper("ab\0c") == "AB\0C")
98assert(string.lower("\0ABCc%$") == "\0abcc%$")
99assert(string.rep('teste', 0) == '')
100assert(string.rep('tés\00tê', 2) == 'tés\0têtés\000tê')
101assert(string.rep('', 10) == '')
102
103if string.packsize("i") == 4 then
104 -- result length would be 2^31 (int overflow)
105 checkerror("too large", string.rep, 'aa', (1 << 30))
106 checkerror("too large", string.rep, 'a', (1 << 30), ',')
107end
108
109-- repetitions with separator
110assert(string.rep('teste', 0, 'xuxu') == '')
111assert(string.rep('teste', 1, 'xuxu') == 'teste')
112assert(string.rep('\1\0\1', 2, '\0\0') == '\1\0\1\0\0\1\0\1')
113assert(string.rep('', 10, '.') == string.rep('.', 9))
114assert(not pcall(string.rep, "aa", maxi // 2 + 10))
115assert(not pcall(string.rep, "", maxi // 2 + 10, "aa"))
116
117assert(string.reverse"" == "")
118assert(string.reverse"\0\1\2\3" == "\3\2\1\0")
119assert(string.reverse"\0001234" == "4321\0")
120
121for i=0,30 do assert(string.len(string.rep('a', i)) == i) end
122
123assert(type(tostring(nil)) == 'string')
124assert(type(tostring(12)) == 'string')
125assert(string.find(tostring{}, 'table:'))
126assert(string.find(tostring(print), 'function:'))
127assert(#tostring('\0') == 1)
128assert(tostring(true) == "true")
129assert(tostring(false) == "false")
130assert(tostring(-1203) == "-1203")
131assert(tostring(1203.125) == "1203.125")
132assert(tostring(-0.5) == "-0.5")
133assert(tostring(-32767) == "-32767")
134if math.tointeger(2147483647) then -- no overflow? (32 bits)
135 assert(tostring(-2147483647) == "-2147483647")
136end
137if math.tointeger(4611686018427387904) then -- no overflow? (64 bits)
138 assert(tostring(4611686018427387904) == "4611686018427387904")
139 assert(tostring(-4611686018427387904) == "-4611686018427387904")
140end
141
142if tostring(0.0) == "0.0" then -- "standard" coercion float->string
143 assert('' .. 12 == '12' and 12.0 .. '' == '12.0')
144 assert(tostring(-1203 + 0.0) == "-1203.0")
145else -- compatible coercion
146 assert(tostring(0.0) == "0")
147 assert('' .. 12 == '12' and 12.0 .. '' == '12')
148 assert(tostring(-1203 + 0.0) == "-1203")
149end
150
151
152x = '"ílo"\n\\'
153assert(string.format('%q%s', x, x) == '"\\"ílo\\"\\\n\\\\""ílo"\n\\')
154assert(string.format('%q', "\0") == [["\0"]])
155assert(load(string.format('return %q', x))() == x)
156x = "\0\1\0023\5\0009"
157assert(load(string.format('return %q', x))() == x)
158assert(string.format("\0%c\0%c%x\0", string.byte("\xe4"), string.byte("b"), 140) ==
159 "\0\xe4\0b8c\0")
160assert(string.format('') == "")
161assert(string.format("%c",34)..string.format("%c",48)..string.format("%c",90)..string.format("%c",100) ==
162 string.format("%c%c%c%c", 34, 48, 90, 100))
163assert(string.format("%s\0 is not \0%s", 'not be', 'be') == 'not be\0 is not \0be')
164assert(string.format("%%%d %010d", 10, 23) == "%10 0000000023")
165assert(tonumber(string.format("%f", 10.3)) == 10.3)
166x = string.format('"%-50s"', 'a')
167assert(#x == 52)
168assert(string.sub(x, 1, 4) == '"a ')
169
170assert(string.format("-%.20s.20s", string.rep("%", 2000)) ==
171 "-"..string.rep("%", 20)..".20s")
172assert(string.format('"-%20s.20s"', string.rep("%", 2000)) ==
173 string.format("%q", "-"..string.rep("%", 2000)..".20s"))
174
175do
176 local function checkQ (v)
177 local s = string.format("%q", v)
178 local nv = load("return " .. s)()
179 assert(v == nv and math.type(v) == math.type(nv))
180 end
181 checkQ("\0\0\1\255\u{234}")
182 checkQ(math.maxinteger)
183 checkQ(math.mininteger)
184 checkQ(math.pi)
185 checkQ(0.1)
186 checkQ(true)
187 checkQ(nil)
188 checkQ(false)
189 checkerror("no literal", string.format, "%q", {})
190end
191
192assert(string.format("\0%s\0", "\0\0\1") == "\0\0\0\1\0")
193checkerror("contains zeros", string.format, "%10s", "\0")
194
195-- format x tostring
196assert(string.format("%s %s", nil, true) == "nil true")
197assert(string.format("%s %.4s", false, true) == "false true")
198assert(string.format("%.3s %.3s", false, true) == "fal tru")
199local m = setmetatable({}, {__tostring = function () return "hello" end,
200 __name = "hi"})
201assert(string.format("%s %.10s", m, m) == "hello hello")
202getmetatable(m).__tostring = nil -- will use '__name' from now on
203assert(string.format("%.4s", m) == "hi: ")
204
205getmetatable(m).__tostring = function () return {} end
206checkerror("'__tostring' must return a string", tostring, m)
207
208
209assert(string.format("%x", 0.0) == "0")
210assert(string.format("%02x", 0.0) == "00")
211assert(string.format("%08X", 0xFFFFFFFF) == "FFFFFFFF")
212assert(string.format("%+08d", 31501) == "+0031501")
213assert(string.format("%+08d", -30927) == "-0030927")
214
215
216do -- longest number that can be formatted
217 local i = 1
218 local j = 10000
219 while i + 1 < j do -- binary search for maximum finite float
220 local m = (i + j) // 2
221 if 10^m < math.huge then i = m else j = m end
222 end
223 assert(10^i < math.huge and 10^j == math.huge)
224 local s = string.format('%.99f', -(10^i))
225 assert(string.len(s) >= i + 101)
226 assert(tonumber(s) == -(10^i))
227end
228
229
230-- testing large numbers for format
231do -- assume at least 32 bits
232 local max, min = 0x7fffffff, -0x80000000 -- "large" for 32 bits
233 assert(string.sub(string.format("%8x", -1), -8) == "ffffffff")
234 assert(string.format("%x", max) == "7fffffff")
235 assert(string.sub(string.format("%x", min), -8) == "80000000")
236 assert(string.format("%d", max) == "2147483647")
237 assert(string.format("%d", min) == "-2147483648")
238 assert(string.format("%u", 0xffffffff) == "4294967295")
239 assert(string.format("%o", 0xABCD) == "125715")
240
241 max, min = 0x7fffffffffffffff, -0x8000000000000000
242 if max > 2.0^53 then -- only for 64 bits
243 assert(string.format("%x", (2^52 | 0) - 1) == "fffffffffffff")
244 assert(string.format("0x%8X", 0x8f000003) == "0x8F000003")
245 assert(string.format("%d", 2^53) == "9007199254740992")
246 assert(string.format("%i", -2^53) == "-9007199254740992")
247 assert(string.format("%x", max) == "7fffffffffffffff")
248 assert(string.format("%x", min) == "8000000000000000")
249 assert(string.format("%d", max) == "9223372036854775807")
250 assert(string.format("%d", min) == "-9223372036854775808")
251 assert(string.format("%u", ~(-1 << 64)) == "18446744073709551615")
252 assert(tostring(1234567890123) == '1234567890123')
253 end
254end
255
256
257do print("testing 'format %a %A'")
258 local function matchhexa (n)
259 local s = string.format("%a", n)
260 -- result matches ISO C requirements
261 assert(string.find(s, "^%-?0x[1-9a-f]%.?[0-9a-f]*p[-+]?%d+$"))
262 assert(tonumber(s) == n) -- and has full precision
263 s = string.format("%A", n)
264 assert(string.find(s, "^%-?0X[1-9A-F]%.?[0-9A-F]*P[-+]?%d+$"))
265 assert(tonumber(s) == n)
266 end
267 for _, n in ipairs{0.1, -0.1, 1/3, -1/3, 1e30, -1e30,
268 -45/247, 1, -1, 2, -2, 3e-20, -3e-20} do
269 matchhexa(n)
270 end
271
272 assert(string.find(string.format("%A", 0.0), "^0X0%.?0?P%+?0$"))
273 assert(string.find(string.format("%a", -0.0), "^%-0x0%.?0?p%+?0$"))
274
275 if not _port then -- test inf, -inf, NaN, and -0.0
276 assert(string.find(string.format("%a", 1/0), "^inf"))
277 assert(string.find(string.format("%A", -1/0), "^%-INF"))
278 assert(string.find(string.format("%a", 0/0), "^%-?nan"))
279 assert(string.find(string.format("%a", -0.0), "^%-0x0"))
280 end
281
282 if not pcall(string.format, "%.3a", 0) then
283 (Message or print)("\n >>> modifiers for format '%a' not available <<<\n")
284 else
285 assert(string.find(string.format("%+.2A", 12), "^%+0X%x%.%x0P%+?%d$"))
286 assert(string.find(string.format("%.4A", -12), "^%-0X%x%.%x000P%+?%d$"))
287 end
288end
289
290
291-- errors in format
292
293local function check (fmt, msg)
294 checkerror(msg, string.format, fmt, 10)
295end
296
297local aux = string.rep('0', 600)
298check("%100.3d", "too long")
299check("%1"..aux..".3d", "too long")
300check("%1.100d", "too long")
301check("%10.1"..aux.."004d", "too long")
302check("%t", "invalid option")
303check("%"..aux.."d", "repeated flags")
304check("%d %d", "no value")
305
306
307assert(load("return 1\n--comment without ending EOL")() == 1)
308
309
310checkerror("table expected", table.concat, 3)
311assert(table.concat{} == "")
312assert(table.concat({}, 'x') == "")
313assert(table.concat({'\0', '\0\1', '\0\1\2'}, '.\0.') == "\0.\0.\0\1.\0.\0\1\2")
314local a = {}; for i=1,300 do a[i] = "xuxu" end
315assert(table.concat(a, "123").."123" == string.rep("xuxu123", 300))
316assert(table.concat(a, "b", 20, 20) == "xuxu")
317assert(table.concat(a, "", 20, 21) == "xuxuxuxu")
318assert(table.concat(a, "x", 22, 21) == "")
319assert(table.concat(a, "3", 299) == "xuxu3xuxu")
320assert(table.concat({}, "x", maxi, maxi - 1) == "")
321assert(table.concat({}, "x", mini + 1, mini) == "")
322assert(table.concat({}, "x", maxi, mini) == "")
323assert(table.concat({[maxi] = "alo"}, "x", maxi, maxi) == "alo")
324assert(table.concat({[maxi] = "alo", [maxi - 1] = "y"}, "-", maxi - 1, maxi)
325 == "y-alo")
326
327assert(not pcall(table.concat, {"a", "b", {}}))
328
329a = {"a","b","c"}
330assert(table.concat(a, ",", 1, 0) == "")
331assert(table.concat(a, ",", 1, 1) == "a")
332assert(table.concat(a, ",", 1, 2) == "a,b")
333assert(table.concat(a, ",", 2) == "b,c")
334assert(table.concat(a, ",", 3) == "c")
335assert(table.concat(a, ",", 4) == "")
336
337if not _port then
338
339 local locales = { "ptb", "pt_BR.iso88591", "ISO-8859-1" }
340 local function trylocale (w)
341 for i = 1, #locales do
342 if os.setlocale(locales[i], w) then
343 print(string.format("'%s' locale set to '%s'", w, locales[i]))
344 return locales[i]
345 end
346 end
347 print(string.format("'%s' locale not found", w))
348 return false
349 end
350
351 if trylocale("collate") then
352 assert("alo" < "álo" and "álo" < "amo")
353 end
354
355 if trylocale("ctype") then
356 assert(string.gsub("áéíóú", "%a", "x") == "xxxxx")
357 assert(string.gsub("áÁéÉ", "%l", "x") == "xÁxÉ")
358 assert(string.gsub("áÁéÉ", "%u", "x") == "áxéx")
359 assert(string.upper"áÁé{xuxu}ção" == "ÁÁÉ{XUXU}ÇÃO")
360 end
361
362 os.setlocale("C")
363 assert(os.setlocale() == 'C')
364 assert(os.setlocale(nil, "numeric") == 'C')
365
366end
367
368
369-- bug in Lua 5.3.2
370-- 'gmatch' iterator does not work across coroutines
371do
372 local f = string.gmatch("1 2 3 4 5", "%d+")
373 assert(f() == "1")
374 co = coroutine.wrap(f)
375 assert(co() == "2")
376end
377
378print('OK')
379
diff --git a/testes/tpack.lua b/testes/tpack.lua
new file mode 100644
index 00000000..96bb4da4
--- /dev/null
+++ b/testes/tpack.lua
@@ -0,0 +1,322 @@
1-- $Id: tpack.lua,v 1.13 2016/11/07 13:11:28 roberto Exp $
2-- See Copyright Notice in file all.lua
3
4local pack = string.pack
5local packsize = string.packsize
6local unpack = string.unpack
7
8print "testing pack/unpack"
9
10-- maximum size for integers
11local NB = 16
12
13local sizeshort = packsize("h")
14local sizeint = packsize("i")
15local sizelong = packsize("l")
16local sizesize_t = packsize("T")
17local sizeLI = packsize("j")
18local sizefloat = packsize("f")
19local sizedouble = packsize("d")
20local sizenumber = packsize("n")
21local little = (pack("i2", 1) == "\1\0")
22local align = packsize("!xXi16")
23
24assert(1 <= sizeshort and sizeshort <= sizeint and sizeint <= sizelong and
25 sizefloat <= sizedouble)
26
27print("platform:")
28print(string.format(
29 "\tshort %d, int %d, long %d, size_t %d, float %d, double %d,\n\z
30 \tlua Integer %d, lua Number %d",
31 sizeshort, sizeint, sizelong, sizesize_t, sizefloat, sizedouble,
32 sizeLI, sizenumber))
33print("\t" .. (little and "little" or "big") .. " endian")
34print("\talignment: " .. align)
35
36
37-- check errors in arguments
38function checkerror (msg, f, ...)
39 local status, err = pcall(f, ...)
40 -- print(status, err, msg)
41 assert(not status and string.find(err, msg))
42end
43
44-- minimum behavior for integer formats
45assert(unpack("B", pack("B", 0xff)) == 0xff)
46assert(unpack("b", pack("b", 0x7f)) == 0x7f)
47assert(unpack("b", pack("b", -0x80)) == -0x80)
48
49assert(unpack("H", pack("H", 0xffff)) == 0xffff)
50assert(unpack("h", pack("h", 0x7fff)) == 0x7fff)
51assert(unpack("h", pack("h", -0x8000)) == -0x8000)
52
53assert(unpack("L", pack("L", 0xffffffff)) == 0xffffffff)
54assert(unpack("l", pack("l", 0x7fffffff)) == 0x7fffffff)
55assert(unpack("l", pack("l", -0x80000000)) == -0x80000000)
56
57
58for i = 1, NB do
59 -- small numbers with signal extension ("\xFF...")
60 local s = string.rep("\xff", i)
61 assert(pack("i" .. i, -1) == s)
62 assert(packsize("i" .. i) == #s)
63 assert(unpack("i" .. i, s) == -1)
64
65 -- small unsigned number ("\0...\xAA")
66 s = "\xAA" .. string.rep("\0", i - 1)
67 assert(pack("<I" .. i, 0xAA) == s)
68 assert(unpack("<I" .. i, s) == 0xAA)
69 assert(pack(">I" .. i, 0xAA) == s:reverse())
70 assert(unpack(">I" .. i, s:reverse()) == 0xAA)
71end
72
73do
74 local lnum = 0x13121110090807060504030201
75 local s = pack("<j", lnum)
76 assert(unpack("<j", s) == lnum)
77 assert(unpack("<i" .. sizeLI + 1, s .. "\0") == lnum)
78 assert(unpack("<i" .. sizeLI + 1, s .. "\0") == lnum)
79
80 for i = sizeLI + 1, NB do
81 local s = pack("<j", -lnum)
82 assert(unpack("<j", s) == -lnum)
83 -- strings with (correct) extra bytes
84 assert(unpack("<i" .. i, s .. ("\xFF"):rep(i - sizeLI)) == -lnum)
85 assert(unpack(">i" .. i, ("\xFF"):rep(i - sizeLI) .. s:reverse()) == -lnum)
86 assert(unpack("<I" .. i, s .. ("\0"):rep(i - sizeLI)) == -lnum)
87
88 -- overflows
89 checkerror("does not fit", unpack, "<I" .. i, ("\x00"):rep(i - 1) .. "\1")
90 checkerror("does not fit", unpack, ">i" .. i, "\1" .. ("\x00"):rep(i - 1))
91 end
92end
93
94for i = 1, sizeLI do
95 local lstr = "\1\2\3\4\5\6\7\8\9\10\11\12\13"
96 local lnum = 0x13121110090807060504030201
97 local n = lnum & (~(-1 << (i * 8)))
98 local s = string.sub(lstr, 1, i)
99 assert(pack("<i" .. i, n) == s)
100 assert(pack(">i" .. i, n) == s:reverse())
101 assert(unpack(">i" .. i, s:reverse()) == n)
102end
103
104-- sign extension
105do
106 local u = 0xf0
107 for i = 1, sizeLI - 1 do
108 assert(unpack("<i"..i, "\xf0"..("\xff"):rep(i - 1)) == -16)
109 assert(unpack(">I"..i, "\xf0"..("\xff"):rep(i - 1)) == u)
110 u = u * 256 + 0xff
111 end
112end
113
114-- mixed endianness
115do
116 assert(pack(">i2 <i2", 10, 20) == "\0\10\20\0")
117 local a, b = unpack("<i2 >i2", "\10\0\0\20")
118 assert(a == 10 and b == 20)
119 assert(pack("=i4", 2001) == pack("i4", 2001))
120end
121
122print("testing invalid formats")
123
124checkerror("out of limits", pack, "i0", 0)
125checkerror("out of limits", pack, "i" .. NB + 1, 0)
126checkerror("out of limits", pack, "!" .. NB + 1, 0)
127checkerror("%(17%) out of limits %[1,16%]", pack, "Xi" .. NB + 1)
128checkerror("invalid format option 'r'", pack, "i3r", 0)
129checkerror("16%-byte integer", unpack, "i16", string.rep('\3', 16))
130checkerror("not power of 2", pack, "!4i3", 0);
131checkerror("missing size", pack, "c", "")
132checkerror("variable%-length format", packsize, "s")
133checkerror("variable%-length format", packsize, "z")
134
135-- overflow in option size (error will be in digit after limit)
136checkerror("invalid format", packsize, "c1" .. string.rep("0", 40))
137
138if packsize("i") == 4 then
139 -- result would be 2^31 (2^3 repetitions of 2^28 strings)
140 local s = string.rep("c268435456", 2^3)
141 checkerror("too large", packsize, s)
142 -- one less is OK
143 s = string.rep("c268435456", 2^3 - 1) .. "c268435455"
144 assert(packsize(s) == 0x7fffffff)
145end
146
147-- overflow in packing
148for i = 1, sizeLI - 1 do
149 local umax = (1 << (i * 8)) - 1
150 local max = umax >> 1
151 local min = ~max
152 checkerror("overflow", pack, "<I" .. i, -1)
153 checkerror("overflow", pack, "<I" .. i, min)
154 checkerror("overflow", pack, ">I" .. i, umax + 1)
155
156 checkerror("overflow", pack, ">i" .. i, umax)
157 checkerror("overflow", pack, ">i" .. i, max + 1)
158 checkerror("overflow", pack, "<i" .. i, min - 1)
159
160 assert(unpack(">i" .. i, pack(">i" .. i, max)) == max)
161 assert(unpack("<i" .. i, pack("<i" .. i, min)) == min)
162 assert(unpack(">I" .. i, pack(">I" .. i, umax)) == umax)
163end
164
165-- Lua integer size
166assert(unpack(">j", pack(">j", math.maxinteger)) == math.maxinteger)
167assert(unpack("<j", pack("<j", math.mininteger)) == math.mininteger)
168assert(unpack("<J", pack("<j", -1)) == -1) -- maximum unsigned integer
169
170if little then
171 assert(pack("f", 24) == pack("<f", 24))
172else
173 assert(pack("f", 24) == pack(">f", 24))
174end
175
176print "testing pack/unpack of floating-point numbers"
177
178for _, n in ipairs{0, -1.1, 1.9, 1/0, -1/0, 1e20, -1e20, 0.1, 2000.7} do
179 assert(unpack("n", pack("n", n)) == n)
180 assert(unpack("<n", pack("<n", n)) == n)
181 assert(unpack(">n", pack(">n", n)) == n)
182 assert(pack("<f", n) == pack(">f", n):reverse())
183 assert(pack(">d", n) == pack("<d", n):reverse())
184end
185
186-- for non-native precisions, test only with "round" numbers
187for _, n in ipairs{0, -1.5, 1/0, -1/0, 1e10, -1e9, 0.5, 2000.25} do
188 assert(unpack("<f", pack("<f", n)) == n)
189 assert(unpack(">f", pack(">f", n)) == n)
190 assert(unpack("<d", pack("<d", n)) == n)
191 assert(unpack(">d", pack(">d", n)) == n)
192end
193
194print "testing pack/unpack of strings"
195do
196 local s = string.rep("abc", 1000)
197 assert(pack("zB", s, 247) == s .. "\0\xF7")
198 local s1, b = unpack("zB", s .. "\0\xF9")
199 assert(b == 249 and s1 == s)
200 s1 = pack("s", s)
201 assert(unpack("s", s1) == s)
202
203 checkerror("does not fit", pack, "s1", s)
204
205 checkerror("contains zeros", pack, "z", "alo\0");
206
207 for i = 2, NB do
208 local s1 = pack("s" .. i, s)
209 assert(unpack("s" .. i, s1) == s and #s1 == #s + i)
210 end
211end
212
213do
214 local x = pack("s", "alo")
215 checkerror("too short", unpack, "s", x:sub(1, -2))
216 checkerror("too short", unpack, "c5", "abcd")
217 checkerror("out of limits", pack, "s100", "alo")
218end
219
220do
221 assert(pack("c0", "") == "")
222 assert(packsize("c0") == 0)
223 assert(unpack("c0", "") == "")
224 assert(pack("<! c3", "abc") == "abc")
225 assert(packsize("<! c3") == 3)
226 assert(pack(">!4 c6", "abcdef") == "abcdef")
227 assert(pack("c3", "123") == "123")
228 assert(pack("c0", "") == "")
229 assert(pack("c8", "123456") == "123456\0\0")
230 assert(pack("c88", "") == string.rep("\0", 88))
231 assert(pack("c188", "ab") == "ab" .. string.rep("\0", 188 - 2))
232 local a, b, c = unpack("!4 z c3", "abcdefghi\0xyz")
233 assert(a == "abcdefghi" and b == "xyz" and c == 14)
234 checkerror("longer than", pack, "c3", "1234")
235end
236
237
238-- testing multiple types and sequence
239do
240 local x = pack("<b h b f d f n i", 1, 2, 3, 4, 5, 6, 7, 8)
241 assert(#x == packsize("<b h b f d f n i"))
242 local a, b, c, d, e, f, g, h = unpack("<b h b f d f n i", x)
243 assert(a == 1 and b == 2 and c == 3 and d == 4 and e == 5 and f == 6 and
244 g == 7 and h == 8)
245end
246
247print "testing alignment"
248do
249 assert(pack(" < i1 i2 ", 2, 3) == "\2\3\0") -- no alignment by default
250 local x = pack(">!8 b Xh i4 i8 c1 Xi8", -12, 100, 200, "\xEC")
251 assert(#x == packsize(">!8 b Xh i4 i8 c1 Xi8"))
252 assert(x == "\xf4" .. "\0\0\0" ..
253 "\0\0\0\100" ..
254 "\0\0\0\0\0\0\0\xC8" ..
255 "\xEC" .. "\0\0\0\0\0\0\0")
256 local a, b, c, d, pos = unpack(">!8 c1 Xh i4 i8 b Xi8 XI XH", x)
257 assert(a == "\xF4" and b == 100 and c == 200 and d == -20 and (pos - 1) == #x)
258
259 x = pack(">!4 c3 c4 c2 z i4 c5 c2 Xi4",
260 "abc", "abcd", "xz", "hello", 5, "world", "xy")
261 assert(x == "abcabcdxzhello\0\0\0\0\0\5worldxy\0")
262 local a, b, c, d, e, f, g, pos = unpack(">!4 c3 c4 c2 z i4 c5 c2 Xh Xi4", x)
263 assert(a == "abc" and b == "abcd" and c == "xz" and d == "hello" and
264 e == 5 and f == "world" and g == "xy" and (pos - 1) % 4 == 0)
265
266 x = pack(" b b Xd b Xb x", 1, 2, 3)
267 assert(packsize(" b b Xd b Xb x") == 4)
268 assert(x == "\1\2\3\0")
269 a, b, c, pos = unpack("bbXdb", x)
270 assert(a == 1 and b == 2 and c == 3 and pos == #x)
271
272 -- only alignment
273 assert(packsize("!8 xXi8") == 8)
274 local pos = unpack("!8 xXi8", "0123456701234567"); assert(pos == 9)
275 assert(packsize("!8 xXi2") == 2)
276 local pos = unpack("!8 xXi2", "0123456701234567"); assert(pos == 3)
277 assert(packsize("!2 xXi2") == 2)
278 local pos = unpack("!2 xXi2", "0123456701234567"); assert(pos == 3)
279 assert(packsize("!2 xXi8") == 2)
280 local pos = unpack("!2 xXi8", "0123456701234567"); assert(pos == 3)
281 assert(packsize("!16 xXi16") == 16)
282 local pos = unpack("!16 xXi16", "0123456701234567"); assert(pos == 17)
283
284 checkerror("invalid next option", pack, "X")
285 checkerror("invalid next option", unpack, "XXi", "")
286 checkerror("invalid next option", unpack, "X i", "")
287 checkerror("invalid next option", pack, "Xc1")
288end
289
290do -- testing initial position
291 local x = pack("i4i4i4i4", 1, 2, 3, 4)
292 for pos = 1, 16, 4 do
293 local i, p = unpack("i4", x, pos)
294 assert(i == pos//4 + 1 and p == pos + 4)
295 end
296
297 -- with alignment
298 for pos = 0, 12 do -- will always round position to power of 2
299 local i, p = unpack("!4 i4", x, pos + 1)
300 assert(i == (pos + 3)//4 + 1 and p == i*4 + 1)
301 end
302
303 -- negative indices
304 local i, p = unpack("!4 i4", x, -4)
305 assert(i == 4 and p == 17)
306 local i, p = unpack("!4 i4", x, -7)
307 assert(i == 4 and p == 17)
308 local i, p = unpack("!4 i4", x, -#x)
309 assert(i == 1 and p == 5)
310
311 -- limits
312 for i = 1, #x + 1 do
313 assert(unpack("c0", x, i) == "")
314 end
315 checkerror("out of string", unpack, "c0", x, 0)
316 checkerror("out of string", unpack, "c0", x, #x + 2)
317 checkerror("out of string", unpack, "c0", x, -(#x + 1))
318
319end
320
321print "OK"
322
diff --git a/testes/utf8.lua b/testes/utf8.lua
new file mode 100644
index 00000000..ebc190b7
--- /dev/null
+++ b/testes/utf8.lua
@@ -0,0 +1,210 @@
1-- $Id: utf8.lua,v 1.12 2016/11/07 13:11:28 roberto Exp $
2-- See Copyright Notice in file all.lua
3
4print "testing UTF-8 library"
5
6local utf8 = require'utf8'
7
8
9local function checkerror (msg, f, ...)
10 local s, err = pcall(f, ...)
11 assert(not s and string.find(err, msg))
12end
13
14
15local function len (s)
16 return #string.gsub(s, "[\x80-\xBF]", "")
17end
18
19
20local justone = "^" .. utf8.charpattern .. "$"
21
22-- 't' is the list of codepoints of 's'
23local function checksyntax (s, t)
24 local ts = {"return '"}
25 for i = 1, #t do ts[i + 1] = string.format("\\u{%x}", t[i]) end
26 ts[#t + 2] = "'"
27 ts = table.concat(ts)
28 assert(assert(load(ts))() == s)
29end
30
31assert(utf8.offset("alo", 5) == nil)
32assert(utf8.offset("alo", -4) == nil)
33
34-- 't' is the list of codepoints of 's'
35local function check (s, t)
36 local l = utf8.len(s)
37 assert(#t == l and len(s) == l)
38 assert(utf8.char(table.unpack(t)) == s)
39
40 assert(utf8.offset(s, 0) == 1)
41
42 checksyntax(s, t)
43
44 local t1 = {utf8.codepoint(s, 1, -1)}
45 assert(#t == #t1)
46 for i = 1, #t do assert(t[i] == t1[i]) end
47
48 for i = 1, l do
49 local pi = utf8.offset(s, i) -- position of i-th char
50 local pi1 = utf8.offset(s, 2, pi) -- position of next char
51 assert(string.find(string.sub(s, pi, pi1 - 1), justone))
52 assert(utf8.offset(s, -1, pi1) == pi)
53 assert(utf8.offset(s, i - l - 1) == pi)
54 assert(pi1 - pi == #utf8.char(utf8.codepoint(s, pi)))
55 for j = pi, pi1 - 1 do
56 assert(utf8.offset(s, 0, j) == pi)
57 end
58 for j = pi + 1, pi1 - 1 do
59 assert(not utf8.len(s, j))
60 end
61 assert(utf8.len(s, pi, pi) == 1)
62 assert(utf8.len(s, pi, pi1 - 1) == 1)
63 assert(utf8.len(s, pi) == l - i + 1)
64 assert(utf8.len(s, pi1) == l - i)
65 assert(utf8.len(s, 1, pi) == i)
66 end
67
68 local i = 0
69 for p, c in utf8.codes(s) do
70 i = i + 1
71 assert(c == t[i] and p == utf8.offset(s, i))
72 assert(utf8.codepoint(s, p) == c)
73 end
74 assert(i == #t)
75
76 i = 0
77 for p, c in utf8.codes(s) do
78 i = i + 1
79 assert(c == t[i] and p == utf8.offset(s, i))
80 end
81 assert(i == #t)
82
83 i = 0
84 for c in string.gmatch(s, utf8.charpattern) do
85 i = i + 1
86 assert(c == utf8.char(t[i]))
87 end
88 assert(i == #t)
89
90 for i = 1, l do
91 assert(utf8.offset(s, i) == utf8.offset(s, i - l - 1, #s + 1))
92 end
93
94end
95
96
97do -- error indication in utf8.len
98 local function check (s, p)
99 local a, b = utf8.len(s)
100 assert(not a and b == p)
101 end
102 check("abc\xE3def", 4)
103 check("汉字\x80", #("汉字") + 1)
104 check("\xF4\x9F\xBF", 1)
105 check("\xF4\x9F\xBF\xBF", 1)
106end
107
108-- error in utf8.codes
109checkerror("invalid UTF%-8 code",
110 function ()
111 local s = "ab\xff"
112 for c in utf8.codes(s) do assert(c) end
113 end)
114
115
116-- error in initial position for offset
117checkerror("position out of range", utf8.offset, "abc", 1, 5)
118checkerror("position out of range", utf8.offset, "abc", 1, -4)
119checkerror("position out of range", utf8.offset, "", 1, 2)
120checkerror("position out of range", utf8.offset, "", 1, -1)
121checkerror("continuation byte", utf8.offset, "𦧺", 1, 2)
122checkerror("continuation byte", utf8.offset, "𦧺", 1, 2)
123checkerror("continuation byte", utf8.offset, "\x80", 1)
124
125
126
127local s = "hello World"
128local t = {string.byte(s, 1, -1)}
129for i = 1, utf8.len(s) do assert(t[i] == string.byte(s, i)) end
130check(s, t)
131
132check("汉字/漢字", {27721, 23383, 47, 28450, 23383,})
133
134do
135 local s = "áéí\128"
136 local t = {utf8.codepoint(s,1,#s - 1)}
137 assert(#t == 3 and t[1] == 225 and t[2] == 233 and t[3] == 237)
138 checkerror("invalid UTF%-8 code", utf8.codepoint, s, 1, #s)
139 checkerror("out of range", utf8.codepoint, s, #s + 1)
140 t = {utf8.codepoint(s, 4, 3)}
141 assert(#t == 0)
142 checkerror("out of range", utf8.codepoint, s, -(#s + 1), 1)
143 checkerror("out of range", utf8.codepoint, s, 1, #s + 1)
144end
145
146assert(utf8.char() == "")
147assert(utf8.char(97, 98, 99) == "abc")
148
149assert(utf8.codepoint(utf8.char(0x10FFFF)) == 0x10FFFF)
150
151checkerror("value out of range", utf8.char, 0x10FFFF + 1)
152
153local function invalid (s)
154 checkerror("invalid UTF%-8 code", utf8.codepoint, s)
155 assert(not utf8.len(s))
156end
157
158-- UTF-8 representation for 0x11ffff (value out of valid range)
159invalid("\xF4\x9F\xBF\xBF")
160
161-- overlong sequences
162invalid("\xC0\x80") -- zero
163invalid("\xC1\xBF") -- 0x7F (should be coded in 1 byte)
164invalid("\xE0\x9F\xBF") -- 0x7FF (should be coded in 2 bytes)
165invalid("\xF0\x8F\xBF\xBF") -- 0xFFFF (should be coded in 3 bytes)
166
167
168-- invalid bytes
169invalid("\x80") -- continuation byte
170invalid("\xBF") -- continuation byte
171invalid("\xFE") -- invalid byte
172invalid("\xFF") -- invalid byte
173
174
175-- empty string
176check("", {})
177
178-- minimum and maximum values for each sequence size
179s = "\0 \x7F\z
180 \xC2\x80 \xDF\xBF\z
181 \xE0\xA0\x80 \xEF\xBF\xBF\z
182 \xF0\x90\x80\x80 \xF4\x8F\xBF\xBF"
183s = string.gsub(s, " ", "")
184check(s, {0,0x7F, 0x80,0x7FF, 0x800,0xFFFF, 0x10000,0x10FFFF})
185
186x = "日本語a-4\0éó"
187check(x, {26085, 26412, 35486, 97, 45, 52, 0, 233, 243})
188
189
190-- Supplementary Characters
191check("𣲷𠜎𠱓ð¡»ð µ¼ab𠺢",
192 {0x23CB7, 0x2070E, 0x20C53, 0x2107B, 0x20D7C, 0x61, 0x62, 0x20EA2,})
193
194check("𨳊𩶘𦧺𨳒𥄫𤓓\xF4\x8F\xBF\xBF",
195 {0x28CCA, 0x29D98, 0x269FA, 0x28CD2, 0x2512B, 0x244D3, 0x10ffff})
196
197
198local i = 0
199for p, c in string.gmatch(x, "()(" .. utf8.charpattern .. ")") do
200 i = i + 1
201 assert(utf8.offset(x, i) == p)
202 assert(utf8.len(x, p) == utf8.len(x) - i + 1)
203 assert(utf8.len(c) == 1)
204 for j = 1, #c - 1 do
205 assert(utf8.offset(x, 0, p + j - 1) == p)
206 end
207end
208
209print'ok'
210
diff --git a/testes/vararg.lua b/testes/vararg.lua
new file mode 100644
index 00000000..d617a98b
--- /dev/null
+++ b/testes/vararg.lua
@@ -0,0 +1,142 @@
1-- $Id: vararg.lua,v 1.25 2016/11/07 13:11:28 roberto Exp $
2-- See Copyright Notice in file all.lua
3
4print('testing vararg')
5
6function f(a, ...)
7 local arg = {n = select('#', ...), ...}
8 for i=1,arg.n do assert(a[i]==arg[i]) end
9 return arg.n
10end
11
12function c12 (...)
13 assert(arg == _G.arg) -- no local 'arg'
14 local x = {...}; x.n = #x
15 local res = (x.n==2 and x[1] == 1 and x[2] == 2)
16 if res then res = 55 end
17 return res, 2
18end
19
20function vararg (...) return {n = select('#', ...), ...} end
21
22local call = function (f, args) return f(table.unpack(args, 1, args.n)) end
23
24assert(f() == 0)
25assert(f({1,2,3}, 1, 2, 3) == 3)
26assert(f({"alo", nil, 45, f, nil}, "alo", nil, 45, f, nil) == 5)
27
28assert(c12(1,2)==55)
29a,b = assert(call(c12, {1,2}))
30assert(a == 55 and b == 2)
31a = call(c12, {1,2;n=2})
32assert(a == 55 and b == 2)
33a = call(c12, {1,2;n=1})
34assert(not a)
35assert(c12(1,2,3) == false)
36local a = vararg(call(next, {_G,nil;n=2}))
37local b,c = next(_G)
38assert(a[1] == b and a[2] == c and a.n == 2)
39a = vararg(call(call, {c12, {1,2}}))
40assert(a.n == 2 and a[1] == 55 and a[2] == 2)
41a = call(print, {'+'})
42assert(a == nil)
43
44local t = {1, 10}
45function t:f (...) local arg = {...}; return self[...]+#arg end
46assert(t:f(1,4) == 3 and t:f(2) == 11)
47print('+')
48
49lim = 20
50local i, a = 1, {}
51while i <= lim do a[i] = i+0.3; i=i+1 end
52
53function f(a, b, c, d, ...)
54 local more = {...}
55 assert(a == 1.3 and more[1] == 5.3 and
56 more[lim-4] == lim+0.3 and not more[lim-3])
57end
58
59function g(a,b,c)
60 assert(a == 1.3 and b == 2.3 and c == 3.3)
61end
62
63call(f, a)
64call(g, a)
65
66a = {}
67i = 1
68while i <= lim do a[i] = i; i=i+1 end
69assert(call(math.max, a) == lim)
70
71print("+")
72
73
74-- new-style varargs
75
76function oneless (a, ...) return ... end
77
78function f (n, a, ...)
79 local b
80 assert(arg == _G.arg) -- no local 'arg'
81 if n == 0 then
82 local b, c, d = ...
83 return a, b, c, d, oneless(oneless(oneless(...)))
84 else
85 n, b, a = n-1, ..., a
86 assert(b == ...)
87 return f(n, a, ...)
88 end
89end
90
91a,b,c,d,e = assert(f(10,5,4,3,2,1))
92assert(a==5 and b==4 and c==3 and d==2 and e==1)
93
94a,b,c,d,e = f(4)
95assert(a==nil and b==nil and c==nil and d==nil and e==nil)
96
97
98-- varargs for main chunks
99f = load[[ return {...} ]]
100x = f(2,3)
101assert(x[1] == 2 and x[2] == 3 and x[3] == nil)
102
103
104f = load[[
105 local x = {...}
106 for i=1,select('#', ...) do assert(x[i] == select(i, ...)) end
107 assert(x[select('#', ...)+1] == nil)
108 return true
109]]
110
111assert(f("a", "b", nil, {}, assert))
112assert(f())
113
114a = {select(3, table.unpack{10,20,30,40})}
115assert(#a == 2 and a[1] == 30 and a[2] == 40)
116a = {select(1)}
117assert(next(a) == nil)
118a = {select(-1, 3, 5, 7)}
119assert(a[1] == 7 and a[2] == nil)
120a = {select(-2, 3, 5, 7)}
121assert(a[1] == 5 and a[2] == 7 and a[3] == nil)
122pcall(select, 10000)
123pcall(select, -10000)
124
125
126-- bug in 5.2.2
127
128function f(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10,
129p11, p12, p13, p14, p15, p16, p17, p18, p19, p20,
130p21, p22, p23, p24, p25, p26, p27, p28, p29, p30,
131p31, p32, p33, p34, p35, p36, p37, p38, p39, p40,
132p41, p42, p43, p44, p45, p46, p48, p49, p50, ...)
133 local a1,a2,a3,a4,a5,a6,a7
134 local a8,a9,a10,a11,a12,a13,a14
135end
136
137-- assertion fail here
138f()
139
140
141print('OK')
142
diff --git a/testes/verybig.lua b/testes/verybig.lua
new file mode 100644
index 00000000..1cfd10be
--- /dev/null
+++ b/testes/verybig.lua
@@ -0,0 +1,152 @@
1-- $Id: verybig.lua,v 1.25 2016/11/07 13:11:28 roberto Exp $
2-- See Copyright Notice in file all.lua
3
4print "testing RK"
5
6-- testing opcodes with RK arguments larger than K limit
7local function foo ()
8 local dummy = {
9 -- fill first 256 entries in table of constants
10 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
11 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32,
12 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
13 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64,
14 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80,
15 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96,
16 97, 98, 99, 100, 101, 102, 103, 104,
17 105, 106, 107, 108, 109, 110, 111, 112,
18 113, 114, 115, 116, 117, 118, 119, 120,
19 121, 122, 123, 124, 125, 126, 127, 128,
20 129, 130, 131, 132, 133, 134, 135, 136,
21 137, 138, 139, 140, 141, 142, 143, 144,
22 145, 146, 147, 148, 149, 150, 151, 152,
23 153, 154, 155, 156, 157, 158, 159, 160,
24 161, 162, 163, 164, 165, 166, 167, 168,
25 169, 170, 171, 172, 173, 174, 175, 176,
26 177, 178, 179, 180, 181, 182, 183, 184,
27 185, 186, 187, 188, 189, 190, 191, 192,
28 193, 194, 195, 196, 197, 198, 199, 200,
29 201, 202, 203, 204, 205, 206, 207, 208,
30 209, 210, 211, 212, 213, 214, 215, 216,
31 217, 218, 219, 220, 221, 222, 223, 224,
32 225, 226, 227, 228, 229, 230, 231, 232,
33 233, 234, 235, 236, 237, 238, 239, 240,
34 241, 242, 243, 244, 245, 246, 247, 248,
35 249, 250, 251, 252, 253, 254, 255, 256,
36 }
37 assert(24.5 + 0.6 == 25.1)
38 local t = {foo = function (self, x) return x + self.x end, x = 10}
39 t.t = t
40 assert(t:foo(1.5) == 11.5)
41 assert(t.t:foo(0.5) == 10.5) -- bug in 5.2 alpha
42 assert(24.3 == 24.3)
43 assert((function () return t.x end)() == 10)
44end
45
46
47foo()
48foo = nil
49
50if _soft then return 10 end
51
52print "testing large programs (>64k)"
53
54-- template to create a very big test file
55prog = [[$
56
57local a,b
58
59b = {$1$
60 b30009 = 65534,
61 b30010 = 65535,
62 b30011 = 65536,
63 b30012 = 65537,
64 b30013 = 16777214,
65 b30014 = 16777215,
66 b30015 = 16777216,
67 b30016 = 16777217,
68 b30017 = 0x7fffff,
69 b30018 = -0x7fffff,
70 b30019 = 0x1ffffff,
71 b30020 = -0x1ffffd,
72 b30021 = -65534,
73 b30022 = -65535,
74 b30023 = -65536,
75 b30024 = -0xffffff,
76 b30025 = 15012.5,
77 $2$
78};
79
80assert(b.a50008 == 25004 and b["a11"] == -5.5)
81assert(b.a33007 == -16503.5 and b.a50009 == -25004.5)
82assert(b["b"..30024] == -0xffffff)
83
84function b:xxx (a,b) return a+b end
85assert(b:xxx(10, 12) == 22) -- pushself with non-constant index
86b.xxx = nil
87
88s = 0; n=0
89for a,b in pairs(b) do s=s+b; n=n+1 end
90-- with 32-bit floats, exact value of 's' depends on summation order
91assert(81800000.0 < s and s < 81860000 and n == 70001)
92
93a = nil; b = nil
94print'+'
95
96function f(x) b=x end
97
98a = f{$3$} or 10
99
100assert(a==10)
101assert(b[1] == "a10" and b[2] == 5 and b[#b-1] == "a50009")
102
103
104function xxxx (x) return b[x] end
105
106assert(xxxx(3) == "a11")
107
108a = nil; b=nil
109xxxx = nil
110
111return 10
112
113]]
114
115-- functions to fill in the $n$
116
117local function sig (x)
118 return (x % 2 == 0) and '' or '-'
119end
120
121F = {
122function () -- $1$
123 for i=10,50009 do
124 io.write('a', i, ' = ', sig(i), 5+((i-10)/2), ',\n')
125 end
126end,
127
128function () -- $2$
129 for i=30026,50009 do
130 io.write('b', i, ' = ', sig(i), 15013+((i-30026)/2), ',\n')
131 end
132end,
133
134function () -- $3$
135 for i=10,50009 do
136 io.write('"a', i, '", ', sig(i), 5+((i-10)/2), ',\n')
137 end
138end,
139}
140
141file = os.tmpname()
142io.output(file)
143for s in string.gmatch(prog, "$([^$]+)") do
144 local n = tonumber(s)
145 if not n then io.write(s) else F[n]() end
146end
147io.close()
148result = dofile(file)
149assert(os.remove(file))
150print'OK'
151return result
152