summaryrefslogtreecommitdiff
path: root/testes
diff options
context:
space:
mode:
Diffstat (limited to 'testes')
-rwxr-xr-xtestes/all.lua294
-rw-r--r--testes/api.lua1264
-rw-r--r--testes/attrib.lua487
-rw-r--r--testes/big.lua82
-rwxr-xr-xtestes/bitwise.lua346
-rw-r--r--testes/bwcoercion.lua78
-rw-r--r--testes/calls.lua435
-rw-r--r--testes/closure.lua271
-rw-r--r--testes/code.lua347
-rw-r--r--testes/constructs.lua302
-rw-r--r--testes/coroutine.lua918
-rw-r--r--testes/db.lua948
-rw-r--r--testes/errors.lua554
-rw-r--r--testes/events.lua476
-rw-r--r--testes/files.lua832
-rw-r--r--testes/gc.lua661
-rw-r--r--testes/goto.lua256
-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.lua181
-rw-r--r--testes/main.lua381
-rw-r--r--testes/math.lua931
-rw-r--r--testes/nextvar.lua669
-rw-r--r--testes/pm.lua374
-rw-r--r--testes/sort.lua310
-rw-r--r--testes/strings.lua382
-rw-r--r--testes/tpack.lua324
-rw-r--r--testes/utf8.lua210
-rw-r--r--testes/vararg.lua151
-rw-r--r--testes/verybig.lua152
34 files changed, 13031 insertions, 0 deletions
diff --git a/testes/all.lua b/testes/all.lua
new file mode 100755
index 00000000..cfe21603
--- /dev/null
+++ b/testes/all.lua
@@ -0,0 +1,294 @@
1#!../lua
2-- $Id: all.lua,v 1.100 2018/03/09 14:23:48 roberto Exp $
3-- See Copyright Notice at the end of this file
4
5
6local version = "Lua 5.4"
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
40require"bwcoercion"
41
42
43if usertests then
44 T = nil -- no "internal" tests for user tests
45else
46 T = rawget(_G, "T") -- avoid problems with 'strict' module
47end
48
49math.randomseed(0)
50
51--[=[
52 example of a long [comment],
53 [[spanning several [lines]]]
54
55]=]
56
57print("current path:\n****" .. package.path .. "****\n")
58
59
60local initclock = os.clock()
61local lastclock = initclock
62local walltime = os.time()
63
64local collectgarbage = collectgarbage
65
66do -- (
67
68-- track messages for tests not performed
69local msgs = {}
70function Message (m)
71 if not _nomsg then
72 print(m)
73 msgs[#msgs+1] = string.sub(m, 3, -3)
74 end
75end
76
77assert(os.setlocale"C")
78
79local T,print,format,write,assert,type,unpack,floor =
80 T,print,string.format,io.write,assert,type,table.unpack,math.floor
81
82-- use K for 1000 and M for 1000000 (not 2^10 -- 2^20)
83local function F (m)
84 local function round (m)
85 m = m + 0.04999
86 return format("%.1f", m) -- keep one decimal digit
87 end
88 if m < 1000 then return m
89 else
90 m = m / 1000
91 if m < 1000 then return round(m).."K"
92 else
93 return round(m/1000).."M"
94 end
95 end
96end
97
98local showmem
99if not T then
100 local max = 0
101 showmem = function ()
102 local m = collectgarbage("count") * 1024
103 max = (m > max) and m or max
104 print(format(" ---- total memory: %s, max memory: %s ----\n",
105 F(m), F(max)))
106 end
107else
108 showmem = function ()
109 T.checkmemory()
110 local total, numblocks, maxmem = T.totalmem()
111 local count = collectgarbage("count")
112 print(format(
113 "\n ---- total memory: %s (%.0fK), max use: %s, blocks: %d\n",
114 F(total), count, F(maxmem), numblocks))
115 print(format("\t(strings: %d, tables: %d, functions: %d, "..
116 "\n\tudata: %d, threads: %d)",
117 T.totalmem"string", T.totalmem"table", T.totalmem"function",
118 T.totalmem"userdata", T.totalmem"thread"))
119 end
120end
121
122
123--
124-- redefine dofile to run files through dump/undump
125--
126local function report (n) print("\n***** FILE '"..n.."'*****") end
127local olddofile = dofile
128local dofile = function (n, strip)
129 showmem()
130 local c = os.clock()
131 print(string.format("time: %g (+%g)", c - initclock, c - lastclock))
132 lastclock = c
133 report(n)
134 local f = assert(loadfile(n))
135 local b = string.dump(f, strip)
136 f = assert(load(b))
137 return f()
138end
139
140dofile('main.lua')
141
142do
143 local next, setmetatable, stderr = next, setmetatable, io.stderr
144 -- track collections
145 local mt = {}
146 -- each time a table is collected, remark it for finalization
147 -- on next cycle
148 mt.__gc = function (o)
149 stderr:write'.' -- mark progress
150 local n = setmetatable(o, mt) -- remark it
151 end
152 local n = setmetatable({}, mt) -- create object
153end
154
155report"gc.lua"
156local f = assert(loadfile('gc.lua'))
157f()
158
159dofile('db.lua')
160assert(dofile('calls.lua') == deep and deep)
161olddofile('strings.lua')
162olddofile('literals.lua')
163dofile('tpack.lua')
164assert(dofile('attrib.lua') == 27)
165
166assert(dofile('locals.lua') == 5)
167dofile('constructs.lua')
168dofile('code.lua', true)
169if not _G._soft then
170 report('big.lua')
171 local f = coroutine.wrap(assert(loadfile('big.lua')))
172 assert(f() == 'b')
173 assert(f() == 'a')
174end
175dofile('nextvar.lua')
176dofile('pm.lua')
177dofile('utf8.lua')
178dofile('api.lua')
179assert(dofile('events.lua') == 12)
180dofile('vararg.lua')
181dofile('closure.lua')
182dofile('coroutine.lua')
183dofile('goto.lua', true)
184dofile('errors.lua')
185dofile('math.lua')
186dofile('sort.lua', true)
187dofile('bitwise.lua')
188assert(dofile('verybig.lua', true) == 10); collectgarbage()
189dofile('files.lua')
190
191if #msgs > 0 then
192 print("\ntests not performed:")
193 for i=1,#msgs do
194 print(msgs[i])
195 end
196 print()
197end
198
199-- no test module should define 'debug'
200assert(debug == nil)
201
202local debug = require "debug"
203
204print(string.format("%d-bit integers, %d-bit floats",
205 string.packsize("j") * 8, string.packsize("n") * 8))
206
207debug.sethook(function (a) assert(type(a) == 'string') end, "cr")
208
209-- to survive outside block
210_G.showmem = showmem
211
212end --)
213
214local _G, showmem, print, format, clock, time, difftime, assert, open =
215 _G, showmem, print, string.format, os.clock, os.time, os.difftime,
216 assert, io.open
217
218-- file with time of last performed test
219local fname = T and "time-debug.txt" or "time.txt"
220local lasttime
221
222if not usertests then
223 -- open file with time of last performed test
224 local f = io.open(fname)
225 if f then
226 lasttime = assert(tonumber(f:read'a'))
227 f:close();
228 else -- no such file; assume it is recording time for first time
229 lasttime = nil
230 end
231end
232
233-- erase (almost) all globals
234print('cleaning all!!!!')
235for n in pairs(_G) do
236 if not ({___Glob = 1, tostring = 1})[n] then
237 _G[n] = undef
238 end
239end
240
241
242collectgarbage()
243collectgarbage()
244collectgarbage()
245collectgarbage()
246collectgarbage()
247collectgarbage();showmem()
248
249local clocktime = clock() - initclock
250walltime = difftime(time(), walltime)
251
252print(format("\n\ntotal time: %.2fs (wall time: %gs)\n", clocktime, walltime))
253
254if not usertests then
255 lasttime = lasttime or clocktime -- if no last time, ignore difference
256 -- check whether current test time differs more than 5% from last time
257 local diff = (clocktime - lasttime) / lasttime
258 local tolerance = 0.05 -- 5%
259 if (diff >= tolerance or diff <= -tolerance) then
260 print(format("WARNING: time difference from previous test: %+.1f%%",
261 diff * 100))
262 end
263 assert(open(fname, "w")):write(clocktime):close()
264end
265
266print("final OK !!!")
267
268
269
270--[[
271*****************************************************************************
272* Copyright (C) 1994-2016 Lua.org, PUC-Rio.
273*
274* Permission is hereby granted, free of charge, to any person obtaining
275* a copy of this software and associated documentation files (the
276* "Software"), to deal in the Software without restriction, including
277* without limitation the rights to use, copy, modify, merge, publish,
278* distribute, sublicense, and/or sell copies of the Software, and to
279* permit persons to whom the Software is furnished to do so, subject to
280* the following conditions:
281*
282* The above copyright notice and this permission notice shall be
283* included in all copies or substantial portions of the Software.
284*
285* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
286* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
287* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
288* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
289* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
290* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
291* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
292*****************************************************************************
293]]
294
diff --git a/testes/api.lua b/testes/api.lua
new file mode 100644
index 00000000..836a6070
--- /dev/null
+++ b/testes/api.lua
@@ -0,0 +1,1264 @@
1-- $Id: api.lua,v 1.155 2018/03/09 14:23:48 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 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(string.upper) -- function handler
125 assert(st == "ERRRUN" and msg == "BOLA")
126 local msg, st = f(string.len) -- function handler
127 assert(st == "ERRRUN" and msg == 4)
128
129end
130
131t = pack(T.testC("insert 3; pushvalue 3; remove 3; pushvalue 2; remove 2; \
132 insert 2; pushvalue 1; remove 1; insert 1; \
133 insert -2; pushvalue -2; remove -3; return *",
134 2, 3, 4, 5, 10, 40, 90))
135tcheck(t, {n=7,2,3,4,5,10,40,90})
136
137t = pack(T.testC("concat 5; return *", "alo", 2, 3, "joao", 12))
138tcheck(t, {n=1,"alo23joao12"})
139
140-- testing MULTRET
141t = pack(T.testC("call 2,-1; return *",
142 function (a,b) return 1,2,3,4,a,b end, "alo", "joao"))
143tcheck(t, {n=6,1,2,3,4,"alo", "joao"})
144
145do -- test returning more results than fit in the caller stack
146 local a = {}
147 for i=1,1000 do a[i] = true end; a[999] = 10
148 local b = T.testC([[pcall 1 -1 0; pop 1; tostring -1; return 1]],
149 table.unpack, a)
150 assert(b == "10")
151end
152
153
154-- testing globals
155_G.a = 14; _G.b = "a31"
156local a = {T.testC[[
157 getglobal a;
158 getglobal b;
159 getglobal b;
160 setglobal a;
161 return *
162]]}
163assert(a[2] == 14 and a[3] == "a31" and a[4] == nil and _G.a == "a31")
164
165
166-- testing arith
167assert(T.testC("pushnum 10; pushnum 20; arith /; return 1") == 0.5)
168assert(T.testC("pushnum 10; pushnum 20; arith -; return 1") == -10)
169assert(T.testC("pushnum 10; pushnum -20; arith *; return 1") == -200)
170assert(T.testC("pushnum 10; pushnum 3; arith ^; return 1") == 1000)
171assert(T.testC("pushnum 10; pushstring 20; arith /; return 1") == 0.5)
172assert(T.testC("pushstring 10; pushnum 20; arith -; return 1") == -10)
173assert(T.testC("pushstring 10; pushstring -20; arith *; return 1") == -200)
174assert(T.testC("pushstring 10; pushstring 3; arith ^; return 1") == 1000)
175assert(T.testC("arith /; return 1", 2, 0) == 10.0/0)
176a = T.testC("pushnum 10; pushint 3; arith \\; return 1")
177assert(a == 3.0 and math.type(a) == "float")
178a = T.testC("pushint 10; pushint 3; arith \\; return 1")
179assert(a == 3 and math.type(a) == "integer")
180a = assert(T.testC("pushint 10; pushint 3; arith +; return 1"))
181assert(a == 13 and math.type(a) == "integer")
182a = assert(T.testC("pushnum 10; pushint 3; arith +; return 1"))
183assert(a == 13 and math.type(a) == "float")
184a,b,c = T.testC([[pushnum 1;
185 pushstring 10; arith _;
186 pushstring 5; return 3]])
187assert(a == 1 and b == -10 and c == "5")
188mt = {__add = function (a,b) return setmetatable({a[1] + b[1]}, mt) end,
189 __mod = function (a,b) return setmetatable({a[1] % b[1]}, mt) end,
190 __unm = function (a) return setmetatable({a[1]* 2}, mt) end}
191a,b,c = setmetatable({4}, mt),
192 setmetatable({8}, mt),
193 setmetatable({-3}, mt)
194x,y,z = T.testC("arith +; return 2", 10, a, b)
195assert(x == 10 and y[1] == 12 and z == nil)
196assert(T.testC("arith %; return 1", a, c)[1] == 4%-3)
197assert(T.testC("arith _; arith +; arith %; return 1", b, a, c)[1] ==
198 8 % (4 + (-3)*2))
199
200-- errors in arithmetic
201checkerr("divide by zero", T.testC, "arith \\", 10, 0)
202checkerr("%%0", T.testC, "arith %", 10, 0)
203
204
205-- testing lessthan and lessequal
206assert(T.testC("compare LT 2 5, return 1", 3, 2, 2, 4, 2, 2))
207assert(T.testC("compare LE 2 5, return 1", 3, 2, 2, 4, 2, 2))
208assert(not T.testC("compare LT 3 4, return 1", 3, 2, 2, 4, 2, 2))
209assert(T.testC("compare LE 3 4, return 1", 3, 2, 2, 4, 2, 2))
210assert(T.testC("compare LT 5 2, return 1", 4, 2, 2, 3, 2, 2))
211assert(not T.testC("compare LT 2 -3, return 1", "4", "2", "2", "3", "2", "2"))
212assert(not T.testC("compare LT -3 2, return 1", "3", "2", "2", "4", "2", "2"))
213
214-- non-valid indices produce false
215assert(not T.testC("compare LT 1 4, return 1"))
216assert(not T.testC("compare LE 9 1, return 1"))
217assert(not T.testC("compare EQ 9 9, return 1"))
218
219local b = {__lt = function (a,b) return a[1] < b[1] end}
220local a1,a3,a4 = setmetatable({1}, b),
221 setmetatable({3}, b),
222 setmetatable({4}, b)
223assert(T.testC("compare LT 2 5, return 1", a3, 2, 2, a4, 2, 2))
224assert(T.testC("compare LE 2 5, return 1", a3, 2, 2, a4, 2, 2))
225assert(T.testC("compare LT 5 -6, return 1", a4, 2, 2, a3, 2, 2))
226a,b = T.testC("compare LT 5 -6, return 2", a1, 2, 2, a3, 2, 20)
227assert(a == 20 and b == false)
228a,b = T.testC("compare LE 5 -6, return 2", a1, 2, 2, a3, 2, 20)
229assert(a == 20 and b == false)
230a,b = T.testC("compare LE 5 -6, return 2", a1, 2, 2, a1, 2, 20)
231assert(a == 20 and b == true)
232
233-- testing length
234local t = setmetatable({x = 20}, {__len = function (t) return t.x end})
235a,b,c = T.testC([[
236 len 2;
237 Llen 2;
238 objsize 2;
239 return 3
240]], t)
241assert(a == 20 and b == 20 and c == 0)
242
243t.x = "234"; t[1] = 20
244a,b,c = T.testC([[
245 len 2;
246 Llen 2;
247 objsize 2;
248 return 3
249]], t)
250assert(a == "234" and b == 234 and c == 1)
251
252t.x = print; t[1] = 20
253a,c = T.testC([[
254 len 2;
255 objsize 2;
256 return 2
257]], t)
258assert(a == print and c == 1)
259
260
261-- testing __concat
262
263a = setmetatable({x="u"}, {__concat = function (a,b) return a.x..'.'..b.x end})
264x,y = T.testC([[
265 pushnum 5
266 pushvalue 2;
267 pushvalue 2;
268 concat 2;
269 pushvalue -2;
270 return 2;
271]], a, a)
272assert(x == a..a and y == 5)
273
274-- concat with 0 elements
275assert(T.testC("concat 0; return 1") == "")
276
277-- concat with 1 element
278assert(T.testC("concat 1; return 1", "xuxu") == "xuxu")
279
280
281
282-- testing lua_is
283
284function B(x) return x and 1 or 0 end
285
286function count (x, n)
287 n = n or 2
288 local prog = [[
289 isnumber %d;
290 isstring %d;
291 isfunction %d;
292 iscfunction %d;
293 istable %d;
294 isuserdata %d;
295 isnil %d;
296 isnull %d;
297 return 8
298 ]]
299 prog = string.format(prog, n, n, n, n, n, n, n, n)
300 local a,b,c,d,e,f,g,h = T.testC(prog, x)
301 return B(a)+B(b)+B(c)+B(d)+B(e)+B(f)+B(g)+(100*B(h))
302end
303
304assert(count(3) == 2)
305assert(count('alo') == 1)
306assert(count('32') == 2)
307assert(count({}) == 1)
308assert(count(print) == 2)
309assert(count(function () end) == 1)
310assert(count(nil) == 1)
311assert(count(io.stdin) == 1)
312assert(count(nil, 15) == 100)
313
314
315-- testing lua_to...
316
317function to (s, x, n)
318 n = n or 2
319 return T.testC(string.format("%s %d; return 1", s, n), x)
320end
321
322local hfunc = string.gmatch("", "") -- a "heavy C function" (with upvalues)
323assert(debug.getupvalue(hfunc, 1))
324assert(to("tostring", {}) == nil)
325assert(to("tostring", "alo") == "alo")
326assert(to("tostring", 12) == "12")
327assert(to("tostring", 12, 3) == nil)
328assert(to("objsize", {}) == 0)
329assert(to("objsize", {1,2,3}) == 3)
330assert(to("objsize", "alo\0\0a") == 6)
331assert(to("objsize", T.newuserdata(0)) == 0)
332assert(to("objsize", T.newuserdata(101)) == 101)
333assert(to("objsize", 124) == 0)
334assert(to("objsize", true) == 0)
335assert(to("tonumber", {}) == 0)
336assert(to("tonumber", "12") == 12)
337assert(to("tonumber", "s2") == 0)
338assert(to("tonumber", 1, 20) == 0)
339assert(to("topointer", 10) == 0)
340assert(to("topointer", true) == 0)
341assert(to("topointer", T.pushuserdata(20)) == 20)
342assert(to("topointer", io.read) ~= 0) -- light C function
343assert(to("topointer", hfunc) ~= 0) -- "heavy" C function
344assert(to("topointer", function () end) ~= 0) -- Lua function
345assert(to("topointer", io.stdin) ~= 0) -- full userdata
346assert(to("func2num", 20) == 0)
347assert(to("func2num", T.pushuserdata(10)) == 0)
348assert(to("func2num", io.read) ~= 0) -- light C function
349assert(to("func2num", hfunc) ~= 0) -- "heavy" C function (with upvalue)
350a = to("tocfunction", math.deg)
351assert(a(3) == math.deg(3) and a == math.deg)
352
353
354print("testing panic function")
355do
356 -- trivial error
357 assert(T.checkpanic("pushstring hi; error") == "hi")
358
359 -- using the stack inside panic
360 assert(T.checkpanic("pushstring hi; error;",
361 [[checkstack 5 XX
362 pushstring ' alo'
363 pushstring ' mundo'
364 concat 3]]) == "hi alo mundo")
365
366 -- "argerror" without frames
367 assert(T.checkpanic("loadstring 4") ==
368 "bad argument #4 (string expected, got no value)")
369
370
371 -- memory error
372 T.totalmem(T.totalmem()+10000) -- set low memory limit (+10k)
373 assert(T.checkpanic("newuserdata 20000") == "not enough memory")
374 T.totalmem(0) -- restore high limit
375
376 -- stack error
377 if not _soft then
378 local msg = T.checkpanic[[
379 pushstring "function f() f() end"
380 loadstring -1; call 0 0
381 getglobal f; call 0 0
382 ]]
383 assert(string.find(msg, "stack overflow"))
384 end
385
386end
387
388-- testing deep C stack
389if not _soft then
390 print("testing stack overflow")
391 collectgarbage("stop")
392 checkerr("XXXX", T.testC, "checkstack 1000023 XXXX") -- too deep
393 -- too deep (with no message)
394 checkerr("^stack overflow$", T.testC, "checkstack 1000023 ''")
395 local s = string.rep("pushnil;checkstack 1 XX;", 1000000)
396 checkerr("overflow", T.testC, s)
397 collectgarbage("restart")
398 print'+'
399end
400
401local lim = _soft and 500 or 12000
402local prog = {"checkstack " .. (lim * 2 + 100) .. "msg", "newtable"}
403for i = 1,lim do
404 prog[#prog + 1] = "pushnum " .. i
405 prog[#prog + 1] = "pushnum " .. i * 10
406end
407
408prog[#prog + 1] = "rawgeti R 2" -- get global table in registry
409prog[#prog + 1] = "insert " .. -(2*lim + 2)
410
411for i = 1,lim do
412 prog[#prog + 1] = "settable " .. -(2*(lim - i + 1) + 1)
413end
414
415prog[#prog + 1] = "return 2"
416
417prog = table.concat(prog, ";")
418local g, t = T.testC(prog)
419assert(g == _G)
420for i = 1,lim do assert(t[i] == i*10); t[i] = undef end
421assert(next(t) == nil)
422prog, g, t = nil
423
424-- testing errors
425
426a = T.testC([[
427 loadstring 2; pcall 0 1 0;
428 pushvalue 3; insert -2; pcall 1 1 0;
429 pcall 0 0 0;
430 return 1
431]], "x=150", function (a) assert(a==nil); return 3 end)
432
433assert(type(a) == 'string' and x == 150)
434
435function check3(p, ...)
436 local arg = {...}
437 assert(#arg == 3)
438 assert(string.find(arg[3], p))
439end
440check3(":1:", T.testC("loadstring 2; return *", "x="))
441check3("%.", T.testC("loadfile 2; return *", "."))
442check3("xxxx", T.testC("loadfile 2; return *", "xxxx"))
443
444-- test errors in non protected threads
445function checkerrnopro (code, msg)
446 local th = coroutine.create(function () end) -- create new thread
447 local stt, err = pcall(T.testC, th, code) -- run code there
448 assert(not stt and string.find(err, msg))
449end
450
451if not _soft then
452 checkerrnopro("pushnum 3; call 0 0", "attempt to call")
453 print"testing stack overflow in unprotected thread"
454 function f () f() end
455 checkerrnopro("getglobal 'f'; call 0 0;", "stack overflow")
456end
457print"+"
458
459
460-- testing table access
461
462do -- getp/setp
463 local a = {}
464 T.testC("rawsetp 2 1", a, 20)
465 assert(a[T.pushuserdata(1)] == 20)
466 assert(T.testC("rawgetp 2 1; return 1", a) == 20)
467end
468
469a = {x=0, y=12}
470x, y = T.testC("gettable 2; pushvalue 4; gettable 2; return 2",
471 a, 3, "y", 4, "x")
472assert(x == 0 and y == 12)
473T.testC("settable -5", a, 3, 4, "x", 15)
474assert(a.x == 15)
475a[a] = print
476x = T.testC("gettable 2; return 1", a) -- table and key are the same object!
477assert(x == print)
478T.testC("settable 2", a, "x") -- table and key are the same object!
479assert(a[a] == "x")
480
481b = setmetatable({p = a}, {})
482getmetatable(b).__index = function (t, i) return t.p[i] end
483k, x = T.testC("gettable 3, return 2", 4, b, 20, 35, "x")
484assert(x == 15 and k == 35)
485k = T.testC("getfield 2 y, return 1", b)
486assert(k == 12)
487getmetatable(b).__index = function (t, i) return a[i] end
488getmetatable(b).__newindex = function (t, i,v ) a[i] = v end
489y = T.testC("insert 2; gettable -5; return 1", 2, 3, 4, "y", b)
490assert(y == 12)
491k = T.testC("settable -5, return 1", b, 3, 4, "x", 16)
492assert(a.x == 16 and k == 4)
493a[b] = 'xuxu'
494y = T.testC("gettable 2, return 1", b)
495assert(y == 'xuxu')
496T.testC("settable 2", b, 19)
497assert(a[b] == 19)
498
499--
500do -- testing getfield/setfield with long keys
501 local t = {_012345678901234567890123456789012345678901234567890123456789 = 32}
502 local a = T.testC([[
503 getfield 2 _012345678901234567890123456789012345678901234567890123456789
504 return 1
505 ]], t)
506 assert(a == 32)
507 local a = T.testC([[
508 pushnum 33
509 setglobal _012345678901234567890123456789012345678901234567890123456789
510 ]])
511 assert(_012345678901234567890123456789012345678901234567890123456789 == 33)
512 _012345678901234567890123456789012345678901234567890123456789 = nil
513end
514
515-- testing next
516a = {}
517t = pack(T.testC("next; return *", a, nil))
518tcheck(t, {n=1,a})
519a = {a=3}
520t = pack(T.testC("next; return *", a, nil))
521tcheck(t, {n=3,a,'a',3})
522t = pack(T.testC("next; pop 1; next; return *", a, nil))
523tcheck(t, {n=1,a})
524
525
526
527-- testing upvalues
528
529do
530 local A = T.testC[[ pushnum 10; pushnum 20; pushcclosure 2; return 1]]
531 t, b, c = A([[pushvalue U0; pushvalue U1; pushvalue U2; return 3]])
532 assert(b == 10 and c == 20 and type(t) == 'table')
533 a, b = A([[tostring U3; tonumber U4; return 2]])
534 assert(a == nil and b == 0)
535 A([[pushnum 100; pushnum 200; replace U2; replace U1]])
536 b, c = A([[pushvalue U1; pushvalue U2; return 2]])
537 assert(b == 100 and c == 200)
538 A([[replace U2; replace U1]], {x=1}, {x=2})
539 b, c = A([[pushvalue U1; pushvalue U2; return 2]])
540 assert(b.x == 1 and c.x == 2)
541 T.checkmemory()
542end
543
544
545-- testing absent upvalues from C-function pointers
546assert(T.testC[[isnull U1; return 1]] == true)
547assert(T.testC[[isnull U100; return 1]] == true)
548assert(T.testC[[pushvalue U1; return 1]] == nil)
549
550local f = T.testC[[ pushnum 10; pushnum 20; pushcclosure 2; return 1]]
551assert(T.upvalue(f, 1) == 10 and
552 T.upvalue(f, 2) == 20 and
553 T.upvalue(f, 3) == nil)
554T.upvalue(f, 2, "xuxu")
555assert(T.upvalue(f, 2) == "xuxu")
556
557
558-- large closures
559do
560 local A = "checkstack 300 msg;" ..
561 string.rep("pushnum 10;", 255) ..
562 "pushcclosure 255; return 1"
563 A = T.testC(A)
564 for i=1,255 do
565 assert(A(("pushvalue U%d; return 1"):format(i)) == 10)
566 end
567 assert(A("isnull U256; return 1"))
568 assert(not A("isnil U256; return 1"))
569end
570
571
572
573-- testing get/setuservalue
574-- bug in 5.1.2
575checkerr("got number", debug.setuservalue, 3, {})
576checkerr("got nil", debug.setuservalue, nil, {})
577checkerr("got light userdata", debug.setuservalue, T.pushuserdata(1), {})
578
579-- testing multiple user values
580local b = T.newuserdata(0, 10)
581for i = 1, 10 do
582 local v, p = debug.getuservalue(b, i)
583 assert(v == nil and p)
584end
585do -- indices out of range
586 local v, p = debug.getuservalue(b, -2)
587 assert(v == nil and not p)
588 local v, p = debug.getuservalue(b, 11)
589 assert(v == nil and not p)
590end
591local t = {true, false, 4.56, print, {}, b, "XYZ"}
592for k, v in ipairs(t) do
593 debug.setuservalue(b, v, k)
594end
595for k, v in ipairs(t) do
596 local v1, p = debug.getuservalue(b, k)
597 assert(v1 == v and p)
598end
599
600assert(debug.getuservalue(4) == nil)
601
602debug.setuservalue(b, function () return 10 end, 10)
603collectgarbage() -- function should not be collected
604assert(debug.getuservalue(b, 10)() == 10)
605
606debug.setuservalue(b, 134)
607collectgarbage() -- number should not be a problem for collector
608assert(debug.getuservalue(b) == 134)
609
610
611-- test barrier for uservalues
612do
613 local oldmode = collectgarbage("incremental")
614 T.gcstate("atomic")
615 assert(T.gccolor(b) == "black")
616 debug.setuservalue(b, {x = 100})
617 T.gcstate("pause") -- complete collection
618 assert(debug.getuservalue(b).x == 100) -- uvalue should be there
619 collectgarbage(oldmode)
620end
621
622-- long chain of userdata
623for i = 1, 1000 do
624 local bb = T.newuserdata(0, 1)
625 debug.setuservalue(bb, b)
626 b = bb
627end
628collectgarbage() -- nothing should not be collected
629for i = 1, 1000 do
630 b = debug.getuservalue(b)
631end
632assert(debug.getuservalue(b).x == 100)
633b = nil
634
635
636-- testing locks (refs)
637
638-- reuse of references
639local i = T.ref{}
640T.unref(i)
641assert(T.ref{} == i)
642
643Arr = {}
644Lim = 100
645for i=1,Lim do -- lock many objects
646 Arr[i] = T.ref({})
647end
648
649assert(T.ref(nil) == -1 and T.getref(-1) == nil)
650T.unref(-1); T.unref(-1)
651
652for i=1,Lim do -- unlock all them
653 T.unref(Arr[i])
654end
655
656function printlocks ()
657 local f = T.makeCfunc("gettable R; return 1")
658 local n = f("n")
659 print("n", n)
660 for i=0,n do
661 print(i, f(i))
662 end
663end
664
665
666for i=1,Lim do -- lock many objects
667 Arr[i] = T.ref({})
668end
669
670for i=1,Lim,2 do -- unlock half of them
671 T.unref(Arr[i])
672end
673
674assert(type(T.getref(Arr[2])) == 'table')
675
676
677assert(T.getref(-1) == nil)
678
679
680a = T.ref({})
681
682collectgarbage()
683
684assert(type(T.getref(a)) == 'table')
685
686
687-- colect in cl the `val' of all collected userdata
688tt = {}
689cl = {n=0}
690A = nil; B = nil
691local F
692F = function (x)
693 local udval = T.udataval(x)
694 table.insert(cl, udval)
695 local d = T.newuserdata(100) -- create garbage
696 d = nil
697 assert(debug.getmetatable(x).__gc == F)
698 assert(load("table.insert({}, {})"))() -- create more garbage
699 collectgarbage() -- force a GC during GC
700 assert(debug.getmetatable(x).__gc == F) -- previous GC did not mess this?
701 local dummy = {} -- create more garbage during GC
702 if A ~= nil then
703 assert(type(A) == "userdata")
704 assert(T.udataval(A) == B)
705 debug.getmetatable(A) -- just acess it
706 end
707 A = x -- ressucita userdata
708 B = udval
709 return 1,2,3
710end
711tt.__gc = F
712
713-- test whether udate collection frees memory in the right time
714do
715 collectgarbage();
716 collectgarbage();
717 local x = collectgarbage("count");
718 local a = T.newuserdata(5001)
719 assert(T.testC("objsize 2; return 1", a) == 5001)
720 assert(collectgarbage("count") >= x+4)
721 a = nil
722 collectgarbage();
723 assert(collectgarbage("count") <= x+1)
724 -- udata without finalizer
725 x = collectgarbage("count")
726 collectgarbage("stop")
727 for i=1,1000 do T.newuserdata(0) end
728 assert(collectgarbage("count") > x+10)
729 collectgarbage()
730 assert(collectgarbage("count") <= x+1)
731 -- udata with finalizer
732 collectgarbage()
733 x = collectgarbage("count")
734 collectgarbage("stop")
735 a = {__gc = function () end}
736 for i=1,1000 do debug.setmetatable(T.newuserdata(0), a) end
737 assert(collectgarbage("count") >= x+10)
738 collectgarbage() -- this collection only calls TM, without freeing memory
739 assert(collectgarbage("count") >= x+10)
740 collectgarbage() -- now frees memory
741 assert(collectgarbage("count") <= x+1)
742 collectgarbage("restart")
743end
744
745
746collectgarbage("stop")
747
748-- create 3 userdatas with tag `tt'
749a = T.newuserdata(0); debug.setmetatable(a, tt); na = T.udataval(a)
750b = T.newuserdata(0); debug.setmetatable(b, tt); nb = T.udataval(b)
751c = T.newuserdata(0); debug.setmetatable(c, tt); nc = T.udataval(c)
752
753-- create userdata without meta table
754x = T.newuserdata(4)
755y = T.newuserdata(0)
756
757checkerr("FILE%* expected, got userdata", io.input, a)
758checkerr("FILE%* expected, got userdata", io.input, x)
759
760assert(debug.getmetatable(x) == nil and debug.getmetatable(y) == nil)
761
762d=T.ref(a);
763e=T.ref(b);
764f=T.ref(c);
765t = {T.getref(d), T.getref(e), T.getref(f)}
766assert(t[1] == a and t[2] == b and t[3] == c)
767
768t=nil; a=nil; c=nil;
769T.unref(e); T.unref(f)
770
771collectgarbage()
772
773-- check that unref objects have been collected
774assert(#cl == 1 and cl[1] == nc)
775
776x = T.getref(d)
777assert(type(x) == 'userdata' and debug.getmetatable(x) == tt)
778x =nil
779tt.b = b -- create cycle
780tt=nil -- frees tt for GC
781A = nil
782b = nil
783T.unref(d);
784n5 = T.newuserdata(0)
785debug.setmetatable(n5, {__gc=F})
786n5 = T.udataval(n5)
787collectgarbage()
788assert(#cl == 4)
789-- check order of collection
790assert(cl[2] == n5 and cl[3] == nb and cl[4] == na)
791
792collectgarbage"restart"
793
794
795a, na = {}, {}
796for i=30,1,-1 do
797 a[i] = T.newuserdata(0)
798 debug.setmetatable(a[i], {__gc=F})
799 na[i] = T.udataval(a[i])
800end
801cl = {}
802a = nil; collectgarbage()
803assert(#cl == 30)
804for i=1,30 do assert(cl[i] == na[i]) end
805na = nil
806
807
808for i=2,Lim,2 do -- unlock the other half
809 T.unref(Arr[i])
810end
811
812x = T.newuserdata(41); debug.setmetatable(x, {__gc=F})
813assert(T.testC("objsize 2; return 1", x) == 41)
814cl = {}
815a = {[x] = 1}
816x = T.udataval(x)
817collectgarbage()
818-- old `x' cannot be collected (`a' still uses it)
819assert(#cl == 0)
820for n in pairs(a) do a[n] = undef end
821collectgarbage()
822assert(#cl == 1 and cl[1] == x) -- old `x' must be collected
823
824-- testing lua_equal
825assert(T.testC("compare EQ 2 4; return 1", print, 1, print, 20))
826assert(T.testC("compare EQ 3 2; return 1", 'alo', "alo"))
827assert(T.testC("compare EQ 2 3; return 1", nil, nil))
828assert(not T.testC("compare EQ 2 3; return 1", {}, {}))
829assert(not T.testC("compare EQ 2 3; return 1"))
830assert(not T.testC("compare EQ 2 3; return 1", 3))
831
832-- testing lua_equal with fallbacks
833do
834 local map = {}
835 local t = {__eq = function (a,b) return map[a] == map[b] end}
836 local function f(x)
837 local u = T.newuserdata(0)
838 debug.setmetatable(u, t)
839 map[u] = x
840 return u
841 end
842 assert(f(10) == f(10))
843 assert(f(10) ~= f(11))
844 assert(T.testC("compare EQ 2 3; return 1", f(10), f(10)))
845 assert(not T.testC("compare EQ 2 3; return 1", f(10), f(20)))
846 t.__eq = nil
847 assert(f(10) ~= f(10))
848end
849
850print'+'
851
852
853
854-- testing changing hooks during hooks
855_G.t = {}
856T.sethook([[
857 # set a line hook after 3 count hooks
858 sethook 4 0 '
859 getglobal t;
860 pushvalue -3; append -2
861 pushvalue -2; append -2
862 ']], "c", 3)
863local a = 1 -- counting
864a = 1 -- counting
865a = 1 -- count hook (set line hook)
866a = 1 -- line hook
867a = 1 -- line hook
868debug.sethook()
869t = _G.t
870assert(t[1] == "line")
871line = t[2]
872assert(t[3] == "line" and t[4] == line + 1)
873assert(t[5] == "line" and t[6] == line + 2)
874assert(t[7] == nil)
875
876
877-------------------------------------------------------------------------
878do -- testing errors during GC
879 collectgarbage("stop")
880 local a = {}
881 for i=1,20 do
882 a[i] = T.newuserdata(i) -- creates several udata
883 end
884 for i=1,20,2 do -- mark half of them to raise errors during GC
885 debug.setmetatable(a[i], {__gc = function (x) error("error inside gc") end})
886 end
887 for i=2,20,2 do -- mark the other half to count and to create more garbage
888 debug.setmetatable(a[i], {__gc = function (x) load("A=A+1")() end})
889 end
890 _G.A = 0
891 a = 0
892 while 1 do
893 local stat, msg = pcall(collectgarbage)
894 if stat then
895 break -- stop when no more errors
896 else
897 a = a + 1
898 assert(string.find(msg, "__gc"))
899 end
900 end
901 assert(a == 10) -- number of errors
902
903 assert(A == 10) -- number of normal collections
904 collectgarbage("restart")
905end
906-------------------------------------------------------------------------
907-- test for userdata vals
908do
909 local a = {}; local lim = 30
910 for i=0,lim do a[i] = T.pushuserdata(i) end
911 for i=0,lim do assert(T.udataval(a[i]) == i) end
912 for i=0,lim do assert(T.pushuserdata(i) == a[i]) end
913 for i=0,lim do a[a[i]] = i end
914 for i=0,lim do a[T.pushuserdata(i)] = i end
915 assert(type(tostring(a[1])) == "string")
916end
917
918
919-------------------------------------------------------------------------
920-- testing multiple states
921T.closestate(T.newstate());
922L1 = T.newstate()
923assert(L1)
924
925assert(T.doremote(L1, "X='a'; return 'a'") == 'a')
926
927
928assert(#pack(T.doremote(L1, "function f () return 'alo', 3 end; f()")) == 0)
929
930a, b = T.doremote(L1, "return f()")
931assert(a == 'alo' and b == '3')
932
933T.doremote(L1, "_ERRORMESSAGE = nil")
934-- error: `sin' is not defined
935a, _, b = T.doremote(L1, "return sin(1)")
936assert(a == nil and b == 2) -- 2 == run-time error
937
938-- error: syntax error
939a, b, c = T.doremote(L1, "return a+")
940assert(a == nil and c == 3 and type(b) == "string") -- 3 == syntax error
941
942T.loadlib(L1)
943a, b, c = T.doremote(L1, [[
944 string = require'string'
945 a = require'_G'; assert(a == _G and require("_G") == a)
946 io = require'io'; assert(type(io.read) == "function")
947 assert(require("io") == io)
948 a = require'table'; assert(type(a.insert) == "function")
949 a = require'debug'; assert(type(a.getlocal) == "function")
950 a = require'math'; assert(type(a.sin) == "function")
951 return string.sub('okinama', 1, 2)
952]])
953assert(a == "ok")
954
955T.closestate(L1);
956
957
958L1 = T.newstate()
959T.loadlib(L1)
960T.doremote(L1, "a = {}")
961T.testC(L1, [[getglobal "a"; pushstring "x"; pushint 1;
962 settable -3]])
963assert(T.doremote(L1, "return a.x") == "1")
964
965T.closestate(L1)
966
967L1 = nil
968
969print('+')
970
971-------------------------------------------------------------------------
972-- testing memory limits
973-------------------------------------------------------------------------
974print("memory-allocation errors")
975
976checkerr("block too big", T.newuserdata, math.maxinteger)
977collectgarbage()
978local f = load"local a={}; for i=1,100000 do a[i]=i end"
979T.alloccount(10)
980checkerr("not enough memory", f)
981T.alloccount() -- remove limit
982
983-- test memory errors; increase limit for number of allocations one
984-- by one, so that we get memory errors in all allocations of a given
985-- task, until there is enough allocations to complete the task without
986-- errors.
987
988function testamem (s, f)
989 collectgarbage(); collectgarbage()
990 local M = 0
991 local a,b = nil
992 while true do
993 T.alloccount(M)
994 a, b = pcall(f)
995 T.alloccount() -- remove limit
996 if a and b then break end -- stop when no more errors
997 if not a and not -- `real' error?
998 (string.find(b, "memory") or string.find(b, "overflow")) then
999 error(b, 0) -- propagate it
1000 end
1001 M = M + 1 -- increase allocation limit
1002 end
1003 print(string.format("limit for %s: %d allocations", s, M))
1004 return b
1005end
1006
1007
1008-- doing nothing
1009b = testamem("doing nothing", function () return 10 end)
1010assert(b == 10)
1011
1012-- testing memory errors when creating a new state
1013
1014b = testamem("state creation", T.newstate)
1015T.closestate(b); -- close new state
1016
1017testamem("empty-table creation", function ()
1018 return {}
1019end)
1020
1021testamem("string creation", function ()
1022 return "XXX" .. "YYY"
1023end)
1024
1025testamem("coroutine creation", function()
1026 return coroutine.create(print)
1027end)
1028
1029
1030-- testing threads
1031
1032-- get main thread from registry (at index LUA_RIDX_MAINTHREAD == 1)
1033mt = T.testC("rawgeti R 1; return 1")
1034assert(type(mt) == "thread" and coroutine.running() == mt)
1035
1036
1037
1038function expand (n,s)
1039 if n==0 then return "" end
1040 local e = string.rep("=", n)
1041 return string.format("T.doonnewstack([%s[ %s;\n collectgarbage(); %s]%s])\n",
1042 e, s, expand(n-1,s), e)
1043end
1044
1045G=0; collectgarbage(); a =collectgarbage("count")
1046load(expand(20,"G=G+1"))()
1047assert(G==20); collectgarbage(); -- assert(gcinfo() <= a+1)
1048
1049testamem("running code on new thread", function ()
1050 return T.doonnewstack("x=1") == 0 -- try to create thread
1051end)
1052
1053
1054-- testing memory x compiler
1055
1056testamem("loadstring", function ()
1057 return load("x=1") -- try to do load a string
1058end)
1059
1060
1061local testprog = [[
1062local function foo () return end
1063local t = {"x"}
1064a = "aaa"
1065for i = 1, #t do a=a..t[i] end
1066return true
1067]]
1068
1069-- testing memory x dofile
1070_G.a = nil
1071local t =os.tmpname()
1072local f = assert(io.open(t, "w"))
1073f:write(testprog)
1074f:close()
1075testamem("dofile", function ()
1076 local a = loadfile(t)
1077 return a and a()
1078end)
1079assert(os.remove(t))
1080assert(_G.a == "aaax")
1081
1082
1083-- other generic tests
1084
1085testamem("gsub", function ()
1086 local a, b = string.gsub("alo alo", "(a)", function (x) return x..'b' end)
1087 return (a == 'ablo ablo')
1088end)
1089
1090testamem("dump/undump", function ()
1091 local a = load(testprog)
1092 local b = a and string.dump(a)
1093 a = b and load(b)
1094 return a and a()
1095end)
1096
1097local t = os.tmpname()
1098testamem("file creation", function ()
1099 local f = assert(io.open(t, 'w'))
1100 assert (not io.open"nomenaoexistente")
1101 io.close(f);
1102 return not loadfile'nomenaoexistente'
1103end)
1104assert(os.remove(t))
1105
1106testamem("table creation", function ()
1107 local a, lim = {}, 10
1108 for i=1,lim do a[i] = i; a[i..'a'] = {} end
1109 return (type(a[lim..'a']) == 'table' and a[lim] == lim)
1110end)
1111
1112testamem("constructors", function ()
1113 local a = {10, 20, 30, 40, 50; a=1, b=2, c=3, d=4, e=5}
1114 return (type(a) == 'table' and a.e == 5)
1115end)
1116
1117local a = 1
1118close = nil
1119testamem("closure creation", function ()
1120 function close (b)
1121 return function (x) return b + x end
1122 end
1123 return (close(2)(4) == 6)
1124end)
1125
1126testamem("using coroutines", function ()
1127 local a = coroutine.wrap(function ()
1128 coroutine.yield(string.rep("a", 10))
1129 return {}
1130 end)
1131 assert(string.len(a()) == 10)
1132 return a()
1133end)
1134
1135do -- auxiliary buffer
1136 local lim = 100
1137 local a = {}; for i = 1, lim do a[i] = "01234567890123456789" end
1138 testamem("auxiliary buffer", function ()
1139 return (#table.concat(a, ",") == 20*lim + lim - 1)
1140 end)
1141end
1142
1143testamem("growing stack", function ()
1144 local function foo (n)
1145 if n == 0 then return 1 else return 1 + foo(n - 1) end
1146 end
1147 return foo(100)
1148end)
1149
1150do -- testing failing in 'lua_checkstack'
1151 local res = T.testC([[rawcheckstack 500000; return 1]])
1152 assert(res == false)
1153 local L = T.newstate()
1154 T.alloccount(0) -- will be unable to reallocate the stack
1155 res = T.testC(L, [[rawcheckstack 5000; return 1]])
1156 T.alloccount()
1157 T.closestate(L)
1158 assert(res == false)
1159end
1160
1161do -- closing state with no extra memory
1162 local L = T.newstate()
1163 T.alloccount(0)
1164 T.closestate(L)
1165 T.alloccount()
1166end
1167
1168do -- garbage collection with no extra memory
1169 local L = T.newstate()
1170 T.loadlib(L)
1171 local res = (T.doremote(L, [[
1172 _ENV = require"_G"
1173 local T = require"T"
1174 local a = {}
1175 for i = 1, 1000 do a[i] = 'i' .. i end -- grow string table
1176 local stsize, stuse = T.querystr()
1177 assert(stuse > 1000)
1178 local function foo (n)
1179 if n > 0 then foo(n - 1) end
1180 end
1181 foo(180) -- grow stack
1182 local _, stksize = T.stacklevel()
1183 assert(stksize > 180)
1184 a = nil
1185 T.alloccount(0)
1186 collectgarbage()
1187 T.alloccount()
1188 -- stack and string table could not be reallocated,
1189 -- so they kept their sizes (without errors)
1190 assert(select(2, T.stacklevel()) == stksize)
1191 assert(T.querystr() == stsize)
1192 return 'ok'
1193 ]]))
1194 assert(res == 'ok')
1195 T.closestate(L)
1196end
1197
1198print'+'
1199
1200-- testing some auxlib functions
1201local function gsub (a, b, c)
1202 a, b = T.testC("gsub 2 3 4; gettop; return 2", a, b, c)
1203 assert(b == 5)
1204 return a
1205end
1206
1207assert(gsub("alo.alo.uhuh.", ".", "//") == "alo//alo//uhuh//")
1208assert(gsub("alo.alo.uhuh.", "alo", "//") == "//.//.uhuh.")
1209assert(gsub("", "alo", "//") == "")
1210assert(gsub("...", ".", "/.") == "/././.")
1211assert(gsub("...", "...", "") == "")
1212
1213
1214-- testing luaL_newmetatable
1215local mt_xuxu, res, top = T.testC("newmetatable xuxu; gettop; return 3")
1216assert(type(mt_xuxu) == "table" and res and top == 3)
1217local d, res, top = T.testC("newmetatable xuxu; gettop; return 3")
1218assert(mt_xuxu == d and not res and top == 3)
1219d, res, top = T.testC("newmetatable xuxu1; gettop; return 3")
1220assert(mt_xuxu ~= d and res and top == 3)
1221
1222x = T.newuserdata(0);
1223y = T.newuserdata(0);
1224T.testC("pushstring xuxu; gettable R; setmetatable 2", x)
1225assert(getmetatable(x) == mt_xuxu)
1226
1227-- testing luaL_testudata
1228-- correct metatable
1229local res1, res2, top = T.testC([[testudata -1 xuxu
1230 testudata 2 xuxu
1231 gettop
1232 return 3]], x)
1233assert(res1 and res2 and top == 4)
1234
1235-- wrong metatable
1236res1, res2, top = T.testC([[testudata -1 xuxu1
1237 testudata 2 xuxu1
1238 gettop
1239 return 3]], x)
1240assert(not res1 and not res2 and top == 4)
1241
1242-- non-existent type
1243res1, res2, top = T.testC([[testudata -1 xuxu2
1244 testudata 2 xuxu2
1245 gettop
1246 return 3]], x)
1247assert(not res1 and not res2 and top == 4)
1248
1249-- userdata has no metatable
1250res1, res2, top = T.testC([[testudata -1 xuxu
1251 testudata 2 xuxu
1252 gettop
1253 return 3]], y)
1254assert(not res1 and not res2 and top == 4)
1255
1256-- erase metatables
1257do
1258 local r = debug.getregistry()
1259 assert(r.xuxu == mt_xuxu and r.xuxu1 == d)
1260 r.xuxu = nil; r.xuxu1 = nil
1261end
1262
1263print'OK'
1264
diff --git a/testes/attrib.lua b/testes/attrib.lua
new file mode 100644
index 00000000..79a08a4f
--- /dev/null
+++ b/testes/attrib.lua
@@ -0,0 +1,487 @@
1-- $Id: attrib.lua,v 1.69 2018/03/12 13:51:02 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] == undef)
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
400a.aVeryLongName012345678901234567890123456789012345678901234567890123456789 = 10
401local function foo ()
402 return a.aVeryLongName012345678901234567890123456789012345678901234567890123456789
403end
404assert(foo() == 10 and
405a.aVeryLongName012345678901234567890123456789012345678901234567890123456789 ==
40610)
407
408
409
410-- test of large float/integer indices
411
412-- compute maximum integer where all bits fit in a float
413local maxint = math.maxinteger
414
415-- trim (if needed) to fit in a float
416while maxint ~= (maxint + 0.0) or (maxint - 1) ~= (maxint - 1.0) do
417 maxint = maxint // 2
418end
419
420maxintF = maxint + 0.0 -- float version
421
422assert(maxintF == maxint and math.type(maxintF) == "float" and
423 maxintF >= 2.0^14)
424
425-- floats and integers must index the same places
426a[maxintF] = 10; a[maxintF - 1.0] = 11;
427a[-maxintF] = 12; a[-maxintF + 1.0] = 13;
428
429assert(a[maxint] == 10 and a[maxint - 1] == 11 and
430 a[-maxint] == 12 and a[-maxint + 1] == 13)
431
432a[maxint] = 20
433a[-maxint] = 22
434
435assert(a[maxintF] == 20 and a[maxintF - 1.0] == 11 and
436 a[-maxintF] == 22 and a[-maxintF + 1.0] == 13)
437
438a = nil
439
440
441-- test conflicts in multiple assignment
442do
443 local a,i,j,b
444 a = {'a', 'b'}; i=1; j=2; b=a
445 i, a[i], a, j, a[j], a[i+j] = j, i, i, b, j, i
446 assert(i == 2 and b[1] == 1 and a == 1 and j == b and b[2] == 2 and
447 b[3] == 1)
448 a = {}
449 local function foo () -- assigining to upvalues
450 b, a.x, a = a, 10, 20
451 end
452 foo()
453 assert(a == 20 and b.x == 10)
454end
455
456-- repeat test with upvalues
457do
458 local a,i,j,b
459 a = {'a', 'b'}; i=1; j=2; b=a
460 local function foo ()
461 i, a[i], a, j, a[j], a[i+j] = j, i, i, b, j, i
462 end
463 foo()
464 assert(i == 2 and b[1] == 1 and a == 1 and j == b and b[2] == 2 and
465 b[3] == 1)
466 local t = {}
467 (function (a) t[a], a = 10, 20 end)(1);
468 assert(t[1] == 10)
469end
470
471-- bug in 5.2 beta
472local function foo ()
473 local a
474 return function ()
475 local b
476 a, b = 3, 14 -- local and upvalue have same index
477 return a, b
478 end
479end
480
481local a, b = foo()()
482assert(a == 3 and b == 14)
483
484print('OK')
485
486return res
487
diff --git a/testes/big.lua b/testes/big.lua
new file mode 100644
index 00000000..ebee1ec0
--- /dev/null
+++ b/testes/big.lua
@@ -0,0 +1,82 @@
1-- $Id: big.lua,v 1.35 2018/03/09 14:23:48 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] = undef 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..3e7079d3
--- /dev/null
+++ b/testes/bitwise.lua
@@ -0,0 +1,346 @@
1-- $Id: bitwise.lua,v 1.27 2018/02/21 17:49:39 roberto Exp $
2-- See Copyright Notice in file all.lua
3
4print("testing bitwise operations")
5
6require "bwcoercion"
7
8local numbits = string.packsize('j') * 8
9
10assert(~0 == -1)
11
12assert((1 << (numbits - 1)) == math.mininteger)
13
14-- basic tests for bitwise operators;
15-- use variables to avoid constant folding
16local a, b, c, d
17a = 0xFFFFFFFFFFFFFFFF
18assert(a == -1 and a & -1 == a and a & 35 == 35)
19a = 0xF0F0F0F0F0F0F0F0
20assert(a | -1 == -1)
21assert(a ~ a == 0 and a ~ 0 == a and a ~ ~a == -1)
22assert(a >> 4 == ~a)
23a = 0xF0; b = 0xCC; c = 0xAA; d = 0xFD
24assert(a | b ~ c & d == 0xF4)
25
26a = 0xF0.0; b = 0xCC.0; c = "0xAA.0"; d = "0xFD.0"
27assert(a | b ~ c & d == 0xF4)
28
29a = 0xF0000000; b = 0xCC000000;
30c = 0xAA000000; d = 0xFD000000
31assert(a | b ~ c & d == 0xF4000000)
32assert(~~a == a and ~a == -1 ~ a and -d == ~d + 1)
33
34a = a << 32
35b = b << 32
36c = c << 32
37d = d << 32
38assert(a | b ~ c & d == 0xF4000000 << 32)
39assert(~~a == a and ~a == -1 ~ a and -d == ~d + 1)
40
41assert(-1 >> 1 == (1 << (numbits - 1)) - 1 and 1 << 31 == 0x80000000)
42assert(-1 >> (numbits - 1) == 1)
43assert(-1 >> numbits == 0 and
44 -1 >> -numbits == 0 and
45 -1 << numbits == 0 and
46 -1 << -numbits == 0)
47
48assert((2^30 - 1) << 2^30 == 0)
49assert((2^30 - 1) >> 2^30 == 0)
50
51assert(1 >> -3 == 1 << 3 and 1000 >> 5 == 1000 << -5)
52
53
54-- coercion from strings to integers
55assert("0xffffffffffffffff" | 0 == -1)
56assert("0xfffffffffffffffe" & "-1" == -2)
57assert(" \t-0xfffffffffffffffe\n\t" & "-1" == 2)
58assert(" \n -45 \t " >> " -2 " == -45 * 4)
59assert("1234.0" << "5.0" == 1234 * 32)
60assert("0xffff.0" ~ "0xAAAA" == 0x5555)
61assert(~"0x0.000p4" == -1)
62
63assert("7" .. 3 << 1 == 146)
64assert(10 >> 1 .. "9" == 0)
65assert(10 | 1 .. "9" == 27)
66
67do
68 local st, msg = pcall(function () return 4 & "a" end)
69 assert(string.find(msg, "'band'"))
70
71 local st, msg = pcall(function () return ~"a" end)
72 assert(string.find(msg, "'bnot'"))
73end
74
75
76-- out of range number
77assert(not pcall(function () return "0xffffffffffffffff.0" | 0 end))
78
79-- embedded zeros
80assert(not pcall(function () return "0xffffffffffffffff\0" | 0 end))
81
82print'+'
83
84
85package.preload.bit32 = function () --{
86
87-- no built-in 'bit32' library: implement it using bitwise operators
88
89local bit = {}
90
91function bit.bnot (a)
92 return ~a & 0xFFFFFFFF
93end
94
95
96--
97-- in all vararg functions, avoid creating 'arg' table when there are
98-- only 2 (or less) parameters, as 2 parameters is the common case
99--
100
101function bit.band (x, y, z, ...)
102 if not z then
103 return ((x or -1) & (y or -1)) & 0xFFFFFFFF
104 else
105 local arg = {...}
106 local res = x & y & z
107 for i = 1, #arg do res = res & arg[i] end
108 return res & 0xFFFFFFFF
109 end
110end
111
112function bit.bor (x, y, z, ...)
113 if not z then
114 return ((x or 0) | (y or 0)) & 0xFFFFFFFF
115 else
116 local arg = {...}
117 local res = x | y | z
118 for i = 1, #arg do res = res | arg[i] end
119 return res & 0xFFFFFFFF
120 end
121end
122
123function bit.bxor (x, y, z, ...)
124 if not z then
125 return ((x or 0) ~ (y or 0)) & 0xFFFFFFFF
126 else
127 local arg = {...}
128 local res = x ~ y ~ z
129 for i = 1, #arg do res = res ~ arg[i] end
130 return res & 0xFFFFFFFF
131 end
132end
133
134function bit.btest (...)
135 return bit.band(...) ~= 0
136end
137
138function bit.lshift (a, b)
139 return ((a & 0xFFFFFFFF) << b) & 0xFFFFFFFF
140end
141
142function bit.rshift (a, b)
143 return ((a & 0xFFFFFFFF) >> b) & 0xFFFFFFFF
144end
145
146function bit.arshift (a, b)
147 a = a & 0xFFFFFFFF
148 if b <= 0 or (a & 0x80000000) == 0 then
149 return (a >> b) & 0xFFFFFFFF
150 else
151 return ((a >> b) | ~(0xFFFFFFFF >> b)) & 0xFFFFFFFF
152 end
153end
154
155function bit.lrotate (a ,b)
156 b = b & 31
157 a = a & 0xFFFFFFFF
158 a = (a << b) | (a >> (32 - b))
159 return a & 0xFFFFFFFF
160end
161
162function bit.rrotate (a, b)
163 return bit.lrotate(a, -b)
164end
165
166local function checkfield (f, w)
167 w = w or 1
168 assert(f >= 0, "field cannot be negative")
169 assert(w > 0, "width must be positive")
170 assert(f + w <= 32, "trying to access non-existent bits")
171 return f, ~(-1 << w)
172end
173
174function bit.extract (a, f, w)
175 local f, mask = checkfield(f, w)
176 return (a >> f) & mask
177end
178
179function bit.replace (a, v, f, w)
180 local f, mask = checkfield(f, w)
181 v = v & mask
182 a = (a & ~(mask << f)) | (v << f)
183 return a & 0xFFFFFFFF
184end
185
186return bit
187
188end --}
189
190
191print("testing bitwise library")
192
193local bit32 = require'bit32'
194
195assert(bit32.band() == bit32.bnot(0))
196assert(bit32.btest() == true)
197assert(bit32.bor() == 0)
198assert(bit32.bxor() == 0)
199
200assert(bit32.band() == bit32.band(0xffffffff))
201assert(bit32.band(1,2) == 0)
202
203
204-- out-of-range numbers
205assert(bit32.band(-1) == 0xffffffff)
206assert(bit32.band((1 << 33) - 1) == 0xffffffff)
207assert(bit32.band(-(1 << 33) - 1) == 0xffffffff)
208assert(bit32.band((1 << 33) + 1) == 1)
209assert(bit32.band(-(1 << 33) + 1) == 1)
210assert(bit32.band(-(1 << 40)) == 0)
211assert(bit32.band(1 << 40) == 0)
212assert(bit32.band(-(1 << 40) - 2) == 0xfffffffe)
213assert(bit32.band((1 << 40) - 4) == 0xfffffffc)
214
215assert(bit32.lrotate(0, -1) == 0)
216assert(bit32.lrotate(0, 7) == 0)
217assert(bit32.lrotate(0x12345678, 0) == 0x12345678)
218assert(bit32.lrotate(0x12345678, 32) == 0x12345678)
219assert(bit32.lrotate(0x12345678, 4) == 0x23456781)
220assert(bit32.rrotate(0x12345678, -4) == 0x23456781)
221assert(bit32.lrotate(0x12345678, -8) == 0x78123456)
222assert(bit32.rrotate(0x12345678, 8) == 0x78123456)
223assert(bit32.lrotate(0xaaaaaaaa, 2) == 0xaaaaaaaa)
224assert(bit32.lrotate(0xaaaaaaaa, -2) == 0xaaaaaaaa)
225for i = -50, 50 do
226 assert(bit32.lrotate(0x89abcdef, i) == bit32.lrotate(0x89abcdef, i%32))
227end
228
229assert(bit32.lshift(0x12345678, 4) == 0x23456780)
230assert(bit32.lshift(0x12345678, 8) == 0x34567800)
231assert(bit32.lshift(0x12345678, -4) == 0x01234567)
232assert(bit32.lshift(0x12345678, -8) == 0x00123456)
233assert(bit32.lshift(0x12345678, 32) == 0)
234assert(bit32.lshift(0x12345678, -32) == 0)
235assert(bit32.rshift(0x12345678, 4) == 0x01234567)
236assert(bit32.rshift(0x12345678, 8) == 0x00123456)
237assert(bit32.rshift(0x12345678, 32) == 0)
238assert(bit32.rshift(0x12345678, -32) == 0)
239assert(bit32.arshift(0x12345678, 0) == 0x12345678)
240assert(bit32.arshift(0x12345678, 1) == 0x12345678 // 2)
241assert(bit32.arshift(0x12345678, -1) == 0x12345678 * 2)
242assert(bit32.arshift(-1, 1) == 0xffffffff)
243assert(bit32.arshift(-1, 24) == 0xffffffff)
244assert(bit32.arshift(-1, 32) == 0xffffffff)
245assert(bit32.arshift(-1, -1) == bit32.band(-1 * 2, 0xffffffff))
246
247assert(0x12345678 << 4 == 0x123456780)
248assert(0x12345678 << 8 == 0x1234567800)
249assert(0x12345678 << -4 == 0x01234567)
250assert(0x12345678 << -8 == 0x00123456)
251assert(0x12345678 << 32 == 0x1234567800000000)
252assert(0x12345678 << -32 == 0)
253assert(0x12345678 >> 4 == 0x01234567)
254assert(0x12345678 >> 8 == 0x00123456)
255assert(0x12345678 >> 32 == 0)
256assert(0x12345678 >> -32 == 0x1234567800000000)
257
258print("+")
259-- some special cases
260local c = {0, 1, 2, 3, 10, 0x80000000, 0xaaaaaaaa, 0x55555555,
261 0xffffffff, 0x7fffffff}
262
263for _, b in pairs(c) do
264 assert(bit32.band(b) == b)
265 assert(bit32.band(b, b) == b)
266 assert(bit32.band(b, b, b, b) == b)
267 assert(bit32.btest(b, b) == (b ~= 0))
268 assert(bit32.band(b, b, b) == b)
269 assert(bit32.band(b, b, b, ~b) == 0)
270 assert(bit32.btest(b, b, b) == (b ~= 0))
271 assert(bit32.band(b, bit32.bnot(b)) == 0)
272 assert(bit32.bor(b, bit32.bnot(b)) == bit32.bnot(0))
273 assert(bit32.bor(b) == b)
274 assert(bit32.bor(b, b) == b)
275 assert(bit32.bor(b, b, b) == b)
276 assert(bit32.bor(b, b, 0, ~b) == 0xffffffff)
277 assert(bit32.bxor(b) == b)
278 assert(bit32.bxor(b, b) == 0)
279 assert(bit32.bxor(b, b, b) == b)
280 assert(bit32.bxor(b, b, b, b) == 0)
281 assert(bit32.bxor(b, 0) == b)
282 assert(bit32.bnot(b) ~= b)
283 assert(bit32.bnot(bit32.bnot(b)) == b)
284 assert(bit32.bnot(b) == (1 << 32) - 1 - b)
285 assert(bit32.lrotate(b, 32) == b)
286 assert(bit32.rrotate(b, 32) == b)
287 assert(bit32.lshift(bit32.lshift(b, -4), 4) == bit32.band(b, bit32.bnot(0xf)))
288 assert(bit32.rshift(bit32.rshift(b, 4), -4) == bit32.band(b, bit32.bnot(0xf)))
289end
290
291-- for this test, use at most 24 bits (mantissa of a single float)
292c = {0, 1, 2, 3, 10, 0x800000, 0xaaaaaa, 0x555555, 0xffffff, 0x7fffff}
293for _, b in pairs(c) do
294 for i = -40, 40 do
295 local x = bit32.lshift(b, i)
296 local y = math.floor(math.fmod(b * 2.0^i, 2.0^32))
297 assert(math.fmod(x - y, 2.0^32) == 0)
298 end
299end
300
301assert(not pcall(bit32.band, {}))
302assert(not pcall(bit32.bnot, "a"))
303assert(not pcall(bit32.lshift, 45))
304assert(not pcall(bit32.lshift, 45, print))
305assert(not pcall(bit32.rshift, 45, print))
306
307print("+")
308
309
310-- testing extract/replace
311
312assert(bit32.extract(0x12345678, 0, 4) == 8)
313assert(bit32.extract(0x12345678, 4, 4) == 7)
314assert(bit32.extract(0xa0001111, 28, 4) == 0xa)
315assert(bit32.extract(0xa0001111, 31, 1) == 1)
316assert(bit32.extract(0x50000111, 31, 1) == 0)
317assert(bit32.extract(0xf2345679, 0, 32) == 0xf2345679)
318
319assert(not pcall(bit32.extract, 0, -1))
320assert(not pcall(bit32.extract, 0, 32))
321assert(not pcall(bit32.extract, 0, 0, 33))
322assert(not pcall(bit32.extract, 0, 31, 2))
323
324assert(bit32.replace(0x12345678, 5, 28, 4) == 0x52345678)
325assert(bit32.replace(0x12345678, 0x87654321, 0, 32) == 0x87654321)
326assert(bit32.replace(0, 1, 2) == 2^2)
327assert(bit32.replace(0, -1, 4) == 2^4)
328assert(bit32.replace(-1, 0, 31) == (1 << 31) - 1)
329assert(bit32.replace(-1, 0, 1, 2) == (1 << 32) - 7)
330
331
332-- testing conversion of floats
333
334assert(bit32.bor(3.0) == 3)
335assert(bit32.bor(-4.0) == 0xfffffffc)
336
337-- large floats and large-enough integers?
338if 2.0^50 < 2.0^50 + 1.0 and 2.0^50 < (-1 >> 1) then
339 assert(bit32.bor(2.0^32 - 5.0) == 0xfffffffb)
340 assert(bit32.bor(-2.0^32 - 6.0) == 0xfffffffa)
341 assert(bit32.bor(2.0^48 - 5.0) == 0xfffffffb)
342 assert(bit32.bor(-2.0^48 - 6.0) == 0xfffffffa)
343end
344
345print'OK'
346
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..95d9d6d6
--- /dev/null
+++ b/testes/calls.lua
@@ -0,0 +1,435 @@
1-- $Id: calls.lua,v 1.66 2018/02/09 16:35:21 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(180)
124
125-- testing tail calls
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
132do -- tail calls x varargs
133 local function foo (x, ...) local a = {...}; return x, a[1], a[2] end
134
135 local function foo1 (x) return foo(10, x, x + 1) end
136
137 local a, b, c = foo1(-2)
138 assert(a == 10 and b == -2 and c == -1)
139
140 -- tail calls x metamethods
141 local t = setmetatable({}, {__call = foo})
142 local function foo2 (x) return t(10, x) end
143 a, b, c = foo2(100)
144 assert(a == t and b == 10 and c == 100)
145
146 a, b = (function () return foo() end)()
147 assert(a == nil and b == nil)
148
149 local X, Y, A
150 local function foo (x, y, ...) X = x; Y = y; A = {...} end
151 local function foo1 (...) return foo(...) end
152
153 local a, b, c = foo1()
154 assert(X == nil and Y == nil and #A == 0)
155
156 a, b, c = foo1(10)
157 assert(X == 10 and Y == nil and #A == 0)
158
159 a, b, c = foo1(10, 20)
160 assert(X == 10 and Y == 20 and #A == 0)
161
162 a, b, c = foo1(10, 20, 30)
163 assert(X == 10 and Y == 20 and #A == 1 and A[1] == 30)
164end
165
166print('+')
167
168
169a = nil
170(function (x) a=x end)(23)
171assert(a == 23 and (function (x) return x*2 end)(20) == 40)
172
173
174-- testing closures
175
176-- fixed-point operator
177Z = function (le)
178 local function a (f)
179 return le(function (x) return f(f)(x) end)
180 end
181 return a(a)
182 end
183
184
185-- non-recursive factorial
186
187F = function (f)
188 return function (n)
189 if n == 0 then return 1
190 else return n*f(n-1) end
191 end
192 end
193
194fat = Z(F)
195
196assert(fat(0) == 1 and fat(4) == 24 and Z(F)(5)==5*Z(F)(4))
197
198local function g (z)
199 local function f (a,b,c,d)
200 return function (x,y) return a+b+c+d+a+x+y+z end
201 end
202 return f(z,z+1,z+2,z+3)
203end
204
205f = g(10)
206assert(f(9, 16) == 10+11+12+13+10+9+16+10)
207
208Z, F, f = nil
209print('+')
210
211-- testing multiple returns
212
213function unlpack (t, i)
214 i = i or 1
215 if (i <= #t) then
216 return t[i], unlpack(t, i+1)
217 end
218end
219
220function equaltab (t1, t2)
221 assert(#t1 == #t2)
222 for i = 1, #t1 do
223 assert(t1[i] == t2[i])
224 end
225end
226
227local pack = function (...) return (table.pack(...)) end
228
229function f() return 1,2,30,4 end
230function ret2 (a,b) return a,b end
231
232local a,b,c,d = unlpack{1,2,3}
233assert(a==1 and b==2 and c==3 and d==nil)
234a = {1,2,3,4,false,10,'alo',false,assert}
235equaltab(pack(unlpack(a)), a)
236equaltab(pack(unlpack(a), -1), {1,-1})
237a,b,c,d = ret2(f()), ret2(f())
238assert(a==1 and b==1 and c==2 and d==nil)
239a,b,c,d = unlpack(pack(ret2(f()), ret2(f())))
240assert(a==1 and b==1 and c==2 and d==nil)
241a,b,c,d = unlpack(pack(ret2(f()), (ret2(f()))))
242assert(a==1 and b==1 and c==nil and d==nil)
243
244a = ret2{ unlpack{1,2,3}, unlpack{3,2,1}, unlpack{"a", "b"}}
245assert(a[1] == 1 and a[2] == 3 and a[3] == "a" and a[4] == "b")
246
247
248-- testing calls with 'incorrect' arguments
249rawget({}, "x", 1)
250rawset({}, "x", 1, 2)
251assert(math.sin(1,2) == math.sin(1))
252table.sort({10,9,8,4,19,23,0,0}, function (a,b) return a<b end, "extra arg")
253
254
255-- test for generic load
256local x = "-- a comment\0\0\0\n x = 10 + \n23; \
257 local a = function () x = 'hi' end; \
258 return '\0'"
259function read1 (x)
260 local i = 0
261 return function ()
262 collectgarbage()
263 i=i+1
264 return string.sub(x, i, i)
265 end
266end
267
268function cannotload (msg, a,b)
269 assert(not a and string.find(b, msg))
270end
271
272a = assert(load(read1(x), "modname", "t", _G))
273assert(a() == "\0" and _G.x == 33)
274assert(debug.getinfo(a).source == "modname")
275-- cannot read text in binary mode
276cannotload("attempt to load a text chunk", load(read1(x), "modname", "b", {}))
277cannotload("attempt to load a text chunk", load(x, "modname", "b"))
278
279a = assert(load(function () return nil end))
280a() -- empty chunk
281
282assert(not load(function () return true end))
283
284
285-- small bug
286local t = {nil, "return ", "3"}
287f, msg = load(function () return table.remove(t, 1) end)
288assert(f() == nil) -- should read the empty chunk
289
290-- another small bug (in 5.2.1)
291f = load(string.dump(function () return 1 end), nil, "b", {})
292assert(type(f) == "function" and f() == 1)
293
294
295x = string.dump(load("x = 1; return x"))
296a = assert(load(read1(x), nil, "b"))
297assert(a() == 1 and _G.x == 1)
298cannotload("attempt to load a binary chunk", load(read1(x), nil, "t"))
299cannotload("attempt to load a binary chunk", load(x, nil, "t"))
300
301assert(not pcall(string.dump, print)) -- no dump of C functions
302
303cannotload("unexpected symbol", load(read1("*a = 123")))
304cannotload("unexpected symbol", load("*a = 123"))
305cannotload("hhi", load(function () error("hhi") end))
306
307-- any value is valid for _ENV
308assert(load("return _ENV", nil, nil, 123)() == 123)
309
310
311-- load when _ENV is not first upvalue
312local x; XX = 123
313local function h ()
314 local y=x -- use 'x', so that it becomes 1st upvalue
315 return XX -- global name
316end
317local d = string.dump(h)
318x = load(d, "", "b")
319assert(debug.getupvalue(x, 2) == '_ENV')
320debug.setupvalue(x, 2, _G)
321assert(x() == 123)
322
323assert(assert(load("return XX + ...", nil, nil, {XX = 13}))(4) == 17)
324
325
326-- test generic load with nested functions
327x = [[
328 return function (x)
329 return function (y)
330 return function (z)
331 return x+y+z
332 end
333 end
334 end
335]]
336
337a = assert(load(read1(x)))
338assert(a()(2)(3)(10) == 15)
339
340
341-- test for dump/undump with upvalues
342local a, b = 20, 30
343x = load(string.dump(function (x)
344 if x == "set" then a = 10+b; b = b+1 else
345 return a
346 end
347end), "", "b", nil)
348assert(x() == nil)
349assert(debug.setupvalue(x, 1, "hi") == "a")
350assert(x() == "hi")
351assert(debug.setupvalue(x, 2, 13) == "b")
352assert(not debug.setupvalue(x, 3, 10)) -- only 2 upvalues
353x("set")
354assert(x() == 23)
355x("set")
356assert(x() == 24)
357
358-- test for dump/undump with many upvalues
359do
360 local nup = 200 -- maximum number of local variables
361 local prog = {"local a1"}
362 for i = 2, nup do prog[#prog + 1] = ", a" .. i end
363 prog[#prog + 1] = " = 1"
364 for i = 2, nup do prog[#prog + 1] = ", " .. i end
365 local sum = 1
366 prog[#prog + 1] = "; return function () return a1"
367 for i = 2, nup do prog[#prog + 1] = " + a" .. i; sum = sum + i end
368 prog[#prog + 1] = " end"
369 prog = table.concat(prog)
370 local f = assert(load(prog))()
371 assert(f() == sum)
372
373 f = load(string.dump(f)) -- main chunk now has many upvalues
374 local a = 10
375 local h = function () return a end
376 for i = 1, nup do
377 debug.upvaluejoin(f, i, h, 1)
378 end
379 assert(f() == 10 * nup)
380end
381
382-- test for long method names
383do
384 local t = {x = 1}
385 function t:_012345678901234567890123456789012345678901234567890123456789 ()
386 return self.x
387 end
388 assert(t:_012345678901234567890123456789012345678901234567890123456789() == 1)
389end
390
391
392-- test for bug in parameter adjustment
393assert((function () return nil end)(4) == nil)
394assert((function () local a; return a end)(4) == nil)
395assert((function (a) return a end)() == nil)
396
397
398print("testing binary chunks")
399do
400 local header = string.pack("c4BBc6BBBBBj",
401 "\27Lua", -- signature
402 5*16 + 4, -- version 5.4
403 0, -- format
404 "\x19\x93\r\n\x1a\n", -- data
405 string.packsize("i"), -- sizeof(int)
406 string.packsize("T"), -- sizeof(size_t)
407 4, -- size of instruction
408 string.packsize("j"), -- sizeof(lua integer)
409 string.packsize("n"), -- sizeof(lua number)
410 0x5678 -- LUAC_INT
411 -- LUAC_NUM may not have a unique binary representation (padding...)
412 )
413 local c = string.dump(function () local a = 1; local b = 3; return a+b*3 end)
414
415 assert(string.sub(c, 1, #header) == header)
416
417 -- corrupted header
418 for i = 1, #header do
419 local s = string.sub(c, 1, i - 1) ..
420 string.char(string.byte(string.sub(c, i, i)) + 1) ..
421 string.sub(c, i + 1, -1)
422 assert(#s == #c)
423 assert(not load(s))
424 end
425
426 -- loading truncated binary chunks
427 for i = 1, #c - 1 do
428 local st, msg = load(string.sub(c, 1, i))
429 assert(not st and string.find(msg, "truncated"))
430 end
431 assert(assert(load(c))() == 10)
432end
433
434print('OK')
435return deep
diff --git a/testes/closure.lua b/testes/closure.lua
new file mode 100644
index 00000000..79da3cc0
--- /dev/null
+++ b/testes/closure.lua
@@ -0,0 +1,271 @@
1-- $Id: closure.lua,v 1.62 2018/03/12 14:19:36 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 = {}
47collectgarbage"stop"
48for i = 1, 5 do a[i] = function (x) return x + a + _ENV end end
49collectgarbage"restart"
50assert(a[3] == a[4] and a[4] == a[5])
51
52for i = 1, 5 do a[i] = function (x) return i + a + _ENV end end
53assert(a[3] ~= a[4] and a[4] ~= a[5])
54
55local function f()
56 return function (x) return math.sin(_ENV[x]) end
57end
58assert(f() == f())
59
60
61-- testing closures with 'for' control variable
62a = {}
63for i=1,10 do
64 a[i] = {set = function(x) i=x end, get = function () return i end}
65 if i == 3 then break end
66end
67assert(a[4] == undef)
68a[1].set(10)
69assert(a[2].get() == 2)
70a[2].set('a')
71assert(a[3].get() == 3)
72assert(a[2].get() == 'a')
73
74a = {}
75local t = {"a", "b"}
76for i = 1, #t do
77 local k = t[i]
78 a[i] = {set = function(x, y) i=x; k=y end,
79 get = function () return i, k end}
80 if i == 2 then break end
81end
82a[1].set(10, 20)
83local r,s = a[2].get()
84assert(r == 2 and s == 'b')
85r,s = a[1].get()
86assert(r == 10 and s == 20)
87a[2].set('a', 'b')
88r,s = a[2].get()
89assert(r == "a" and s == "b")
90
91
92-- testing closures with 'for' control variable x break
93for i=1,3 do
94 f = function () return i end
95 break
96end
97assert(f() == 1)
98
99for k = 1, #t do
100 local v = t[k]
101 f = function () return k, v end
102 break
103end
104assert(({f()})[1] == 1)
105assert(({f()})[2] == "a")
106
107
108-- testing closure x break x return x errors
109
110local b
111function f(x)
112 local first = 1
113 while 1 do
114 if x == 3 and not first then return end
115 local a = 'xuxu'
116 b = function (op, y)
117 if op == 'set' then
118 a = x+y
119 else
120 return a
121 end
122 end
123 if x == 1 then do break end
124 elseif x == 2 then return
125 else if x ~= 3 then error() end
126 end
127 first = nil
128 end
129end
130
131for i=1,3 do
132 f(i)
133 assert(b('get') == 'xuxu')
134 b('set', 10); assert(b('get') == 10+i)
135 b = nil
136end
137
138pcall(f, 4);
139assert(b('get') == 'xuxu')
140b('set', 10); assert(b('get') == 14)
141
142
143local w
144-- testing multi-level closure
145function f(x)
146 return function (y)
147 return function (z) return w+x+y+z end
148 end
149end
150
151y = f(10)
152w = 1.345
153assert(y(20)(30) == 60+w)
154
155
156-- testing closures x break
157do
158 local X, Y
159 local a = math.sin(0)
160
161 while a do
162 local b = 10
163 X = function () return b end -- closure with upvalue
164 if a then break end
165 end
166
167 do
168 local b = 20
169 Y = function () return b end -- closure with upvalue
170 end
171
172 -- upvalues must be different
173 assert(X() == 10 and Y() == 20)
174end
175
176
177-- testing closures x repeat-until
178
179local a = {}
180local i = 1
181repeat
182 local x = i
183 a[i] = function () i = x+1; return x end
184until i > 10 or a[i]() ~= x
185assert(i == 11 and a[1]() == 1 and a[3]() == 3 and i == 4)
186
187
188-- testing closures created in 'then' and 'else' parts of 'if's
189a = {}
190for i = 1, 10 do
191 if i % 3 == 0 then
192 local y = 0
193 a[i] = function (x) local t = y; y = x; return t end
194 elseif i % 3 == 1 then
195 goto L1
196 error'not here'
197 ::L1::
198 local y = 1
199 a[i] = function (x) local t = y; y = x; return t end
200 elseif i % 3 == 2 then
201 local t
202 goto l4
203 ::l4a:: a[i] = t; goto l4b
204 error("should never be here!")
205 ::l4::
206 local y = 2
207 t = function (x) local t = y; y = x; return t end
208 goto l4a
209 error("should never be here!")
210 ::l4b::
211 end
212end
213
214for i = 1, 10 do
215 assert(a[i](i * 10) == i % 3 and a[i]() == i * 10)
216end
217
218print'+'
219
220
221-- test for correctly closing upvalues in tail calls of vararg functions
222local function t ()
223 local function c(a,b) assert(a=="test" and b=="OK") end
224 local function v(f, ...) c("test", f() ~= 1 and "FAILED" or "OK") end
225 local x = 1
226 return v(function() return x end)
227end
228t()
229
230
231-- test for debug manipulation of upvalues
232local debug = require'debug'
233
234do
235 local a , b, c = 3, 5, 7
236 foo1 = function () return a+b end;
237 foo2 = function () return b+a end;
238 do
239 local a = 10
240 foo3 = function () return a+b end;
241 end
242end
243
244assert(debug.upvalueid(foo1, 1))
245assert(debug.upvalueid(foo1, 2))
246assert(not pcall(debug.upvalueid, foo1, 3))
247assert(debug.upvalueid(foo1, 1) == debug.upvalueid(foo2, 2))
248assert(debug.upvalueid(foo1, 2) == debug.upvalueid(foo2, 1))
249assert(debug.upvalueid(foo3, 1))
250assert(debug.upvalueid(foo1, 1) ~= debug.upvalueid(foo3, 1))
251assert(debug.upvalueid(foo1, 2) == debug.upvalueid(foo3, 2))
252
253assert(debug.upvalueid(string.gmatch("x", "x"), 1) ~= nil)
254
255assert(foo1() == 3 + 5 and foo2() == 5 + 3)
256debug.upvaluejoin(foo1, 2, foo2, 2)
257assert(foo1() == 3 + 3 and foo2() == 5 + 3)
258assert(foo3() == 10 + 5)
259debug.upvaluejoin(foo3, 2, foo2, 1)
260assert(foo3() == 10 + 5)
261debug.upvaluejoin(foo3, 2, foo2, 2)
262assert(foo3() == 10 + 3)
263
264assert(not pcall(debug.upvaluejoin, foo1, 3, foo2, 1))
265assert(not pcall(debug.upvaluejoin, foo1, 1, foo2, 3))
266assert(not pcall(debug.upvaluejoin, foo1, 0, foo2, 1))
267assert(not pcall(debug.upvaluejoin, print, 1, foo2, 1))
268assert(not pcall(debug.upvaluejoin, {}, 1, foo2, 1))
269assert(not pcall(debug.upvaluejoin, foo1, 1, print, 1))
270
271print'OK'
diff --git a/testes/code.lua b/testes/code.lua
new file mode 100644
index 00000000..e39c62ad
--- /dev/null
+++ b/testes/code.lua
@@ -0,0 +1,347 @@
1-- $Id: code.lua,v 1.55 2018/03/12 14:19:36 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.78/4, -3.78/4, -3.79/4})
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 local opcode = string.match(c[i], "%u%w+")
48 -- print(arg[i], opcode)
49 assert(arg[i] == opcode)
50 end
51 assert(c[#arg+2] == undef)
52end
53
54
55function checkequal (a, b)
56 a = T.listcode(a)
57 b = T.listcode(b)
58 for i = 1, #a do
59 a[i] = string.gsub(a[i], '%b()', '') -- remove line number
60 b[i] = string.gsub(b[i], '%b()', '') -- remove line number
61 assert(a[i] == b[i])
62 end
63end
64
65
66-- some basic instructions
67check(function ()
68 (function () end){f()}
69end, 'CLOSURE', 'NEWTABLE', 'GETTABUP', 'CALL', 'SETLIST', 'CALL', 'RETURN')
70
71
72-- sequence of LOADNILs
73check(function ()
74 local a,b,c
75 local d; local e;
76 local f,g,h;
77 d = nil; d=nil; b=nil; a=nil; c=nil;
78end, 'LOADNIL', 'RETURN0')
79
80check(function ()
81 local a,b,c,d = 1,1,1,1
82 d=nil;c=nil;b=nil;a=nil
83end, 'LOADI', 'LOADI', 'LOADI', 'LOADI', 'LOADNIL', 'RETURN0')
84
85do
86 local a,b,c,d = 1,1,1,1
87 d=nil;c=nil;b=nil;a=nil
88 assert(a == nil and b == nil and c == nil and d == nil)
89end
90
91
92-- single return
93check (function (a,b,c) return a end, 'RETURN1')
94
95
96-- infinite loops
97check(function () while true do local a = -1 end end,
98'LOADI', 'JMP', 'RETURN0')
99
100check(function () while 1 do local a = -1 end end,
101'LOADI', 'JMP', 'RETURN0')
102
103check(function () repeat local x = 1 until true end,
104'LOADI', 'RETURN0')
105
106
107-- concat optimization
108check(function (a,b,c,d) return a..b..c..d end,
109 'MOVE', 'MOVE', 'MOVE', 'MOVE', 'CONCAT', 'RETURN1')
110
111-- not
112check(function () return not not nil end, 'LOADBOOL', 'RETURN1')
113check(function () return not not false end, 'LOADBOOL', 'RETURN1')
114check(function () return not not true end, 'LOADBOOL', 'RETURN1')
115check(function () return not not 1 end, 'LOADBOOL', 'RETURN1')
116
117-- direct access to locals
118check(function ()
119 local a,b,c,d
120 a = b*a
121 c.x, a[b] = -((a + d/b - a[b]) ^ a.x), b
122end,
123 'LOADNIL',
124 'MUL',
125 'DIV', 'ADD', 'GETTABLE', 'SUB', 'GETFIELD', 'POW',
126 'UNM', 'SETTABLE', 'SETFIELD', 'RETURN0')
127
128
129-- direct access to constants
130check(function ()
131 local a,b
132 a.x = 3.2
133 a.x = b
134 a[b] = 'x'
135end,
136 'LOADNIL', 'SETFIELD', 'SETFIELD', 'SETTABLE', 'RETURN0')
137
138-- "get/set table" with numeric indices
139check(function (a)
140 a[1] = a[100]
141 a[255] = a[256]
142 a[256] = 5
143end,
144 'GETI', 'SETI',
145 'LOADI', 'GETTABLE', 'SETI',
146 'LOADI', 'SETTABLE', 'RETURN0')
147
148check(function ()
149 local a,b
150 a = a - a
151 b = a/a
152 b = 5-4
153end,
154 'LOADNIL', 'SUB', 'DIV', 'LOADI', 'RETURN0')
155
156check(function ()
157 local a,b
158 a[true] = false
159end,
160 'LOADNIL', 'LOADBOOL', 'SETTABLE', 'RETURN0')
161
162
163-- equalities
164check(function (a) if a == 1 then return 2 end end,
165 'EQI', 'JMP', 'LOADI', 'RETURN1')
166
167check(function (a) if -4.0 == a then return 2 end end,
168 'EQI', 'JMP', 'LOADI', 'RETURN1')
169
170check(function (a) if a == "hi" then return 2 end end,
171 'EQK', 'JMP', 'LOADI', 'RETURN1')
172
173check(function (a) if a == 10000 then return 2 end end,
174 'EQK', 'JMP', 'LOADI', 'RETURN1') -- number too large
175
176check(function (a) if -10000 == a then return 2 end end,
177 'EQK', 'JMP', 'LOADI', 'RETURN1') -- number too large
178
179-- comparisons
180
181check(function (a) if -10 <= a then return 2 end end,
182 'GEI', 'JMP', 'LOADI', 'RETURN1')
183
184check(function (a) if 128.0 > a then return 2 end end,
185 'LTI', 'JMP', 'LOADI', 'RETURN1')
186
187check(function (a) if -127.0 < a then return 2 end end,
188 'GTI', 'JMP', 'LOADI', 'RETURN1')
189
190check(function (a) if 10 < a then return 2 end end,
191 'GTI', 'JMP', 'LOADI', 'RETURN1')
192
193check(function (a) if 129 < a then return 2 end end,
194 'LOADI', 'LT', 'JMP', 'LOADI', 'RETURN1')
195
196check(function (a) if a >= 23.0 then return 2 end end,
197 'GEI', 'JMP', 'LOADI', 'RETURN1')
198
199check(function (a) if a >= 23.1 then return 2 end end,
200 'LOADK', 'LE', 'JMP', 'LOADI', 'RETURN1')
201
202check(function (a) if a > 2300.0 then return 2 end end,
203 'LOADF', 'LT', 'JMP', 'LOADI', 'RETURN1')
204
205
206-- constant folding
207local function checkK (func, val)
208 check(func, 'LOADK', 'RETURN1')
209 local k = T.listk(func)
210 assert(#k == 1 and k[1] == val and math.type(k[1]) == math.type(val))
211 assert(func() == val)
212end
213
214local function checkI (func, val)
215 check(func, 'LOADI', 'RETURN1')
216 assert(#T.listk(func) == 0)
217 assert(func() == val)
218end
219
220local function checkF (func, val)
221 check(func, 'LOADF', 'RETURN1')
222 assert(#T.listk(func) == 0)
223 assert(func() == val)
224end
225
226checkF(function () return 0.0 end, 0.0)
227checkI(function () return 0 end, 0)
228checkI(function () return -0//1 end, 0)
229checkK(function () return 3^-1 end, 1/3)
230checkK(function () return (1 + 1)^(50 + 50) end, 2^100)
231checkK(function () return (-2)^(31 - 2) end, -0x20000000 + 0.0)
232checkF(function () return (-3^0 + 5) // 3.0 end, 1.0)
233checkI(function () return -3 % 5 end, 2)
234checkF(function () return -((2.0^8 + -(-1)) % 8)/2 * 4 - 3 end, -5.0)
235checkF(function () return -((2^8 + -(-1)) % 8)//2 * 4 - 3 end, -7.0)
236checkI(function () return 0xF0.0 | 0xCC.0 ~ 0xAA & 0xFD end, 0xF4)
237checkI(function () return ~(~0xFF0 | 0xFF0) end, 0)
238checkI(function () return ~~-1024.0 end, -1024)
239checkI(function () return ((100 << 6) << -4) >> 2 end, 100)
240
241-- borders around MAXARG_sBx ((((1 << 17) - 1) >> 1) == 65535)
242local sbx = ((1 << "17") - 1) >> 1 -- avoid folding
243checkI(function () return 65535 end, sbx)
244checkI(function () return -65535 end, -sbx)
245checkI(function () return 65536 end, sbx + 1)
246checkK(function () return 65537 end, sbx + 2)
247checkK(function () return -65536 end, -(sbx + 1))
248
249checkF(function () return 65535.0 end, sbx + 0.0)
250checkF(function () return -65535.0 end, -sbx + 0.0)
251checkF(function () return 65536.0 end, (sbx + 1.0))
252checkK(function () return 65537.0 end, (sbx + 2.0))
253checkK(function () return -65536.0 end, -(sbx + 1.0))
254
255
256-- immediate operands
257check(function (x) return x + 1 end, 'ADDI', 'RETURN1')
258check(function (x) return 128 + x end, 'ADDI', 'RETURN1')
259check(function (x) return x * -127 end, 'MULI', 'RETURN1')
260check(function (x) return 20 * x end, 'MULI', 'RETURN1')
261check(function (x) return x ^ -2 end, 'POWI', 'RETURN1')
262check(function (x) return x / 40 end, 'DIVI', 'RETURN1')
263check(function (x) return x // 1 end, 'IDIVI', 'RETURN1')
264check(function (x) return x % (100 - 10) end, 'MODI', 'RETURN1')
265check(function (x) return 1 << x end, 'SHLI', 'RETURN1')
266check(function (x) return x << 2 end, 'SHRI', 'RETURN1')
267check(function (x) return x >> 2 end, 'SHRI', 'RETURN1')
268check(function (x) return x & 1 end, 'BANDK', 'RETURN1')
269check(function (x) return 10 | x end, 'BORK', 'RETURN1')
270check(function (x) return -10 ~ x end, 'BXORK', 'RETURN1')
271
272-- no foldings (and immediate operands)
273check(function () return -0.0 end, 'LOADF', 'UNM', 'RETURN1')
274check(function () return 3/0 end, 'LOADI', 'DIVI', 'RETURN1')
275check(function () return 0%0 end, 'LOADI', 'MODI', 'RETURN1')
276check(function () return -4//0 end, 'LOADI', 'IDIVI', 'RETURN1')
277check(function (x) return x >> 2.0 end, 'LOADF', 'SHR', 'RETURN1')
278check(function (x) return x & 2.0 end, 'LOADF', 'BAND', 'RETURN1')
279
280-- basic 'for' loops
281check(function () for i = -10, 10.5 do end end,
282'LOADI', 'LOADK', 'LOADI', 'FORPREP1', 'FORLOOP1', 'RETURN0')
283check(function () for i = 0xfffffff, 10.0, 1 do end end,
284'LOADK', 'LOADF', 'LOADI', 'FORPREP1', 'FORLOOP1', 'RETURN0')
285
286-- bug in constant folding for 5.1
287check(function () return -nil end, 'LOADNIL', 'UNM', 'RETURN1')
288
289
290check(function ()
291 local a,b,c
292 b[c], a = c, b
293 b[a], a = c, b
294 a, b = c, a
295 a = a
296end,
297 'LOADNIL',
298 'MOVE', 'MOVE', 'SETTABLE',
299 'MOVE', 'MOVE', 'MOVE', 'SETTABLE',
300 'MOVE', 'MOVE', 'MOVE',
301 -- no code for a = a
302 'RETURN0')
303
304
305-- x == nil , x ~= nil
306-- checkequal(function (b) if (a==nil) then a=1 end; if a~=nil then a=1 end end,
307-- function () if (a==9) then a=1 end; if a~=9 then a=1 end end)
308
309-- check(function () if a==nil then a='a' end end,
310-- 'GETTABUP', 'EQ', 'JMP', 'SETTABUP', 'RETURN')
311
312do -- tests for table access in upvalues
313 local t
314 check(function () t.x = t.y end, 'GETTABUP', 'SETTABUP')
315 check(function (a) t[a()] = t[a()] end,
316 'MOVE', 'CALL', 'GETUPVAL', 'MOVE', 'CALL',
317 'GETUPVAL', 'GETTABLE', 'SETTABLE')
318end
319
320-- de morgan
321checkequal(function () local a; if not (a or b) then b=a end end,
322 function () local a; if (not a and not b) then b=a end end)
323
324checkequal(function (l) local a; return 0 <= a and a <= l end,
325 function (l) local a; return not (not(a >= 0) or not(a <= l)) end)
326
327
328-- if-goto optimizations
329check(function (a, b, c, d, e)
330 if a == b then goto l1;
331 elseif a == c then goto l2;
332 elseif a == d then goto l2;
333 else if a == e then goto l3;
334 else goto l3
335 end
336 end
337 ::l1:: ::l2:: ::l3:: ::l4::
338end, 'EQ', 'JMP', 'EQ', 'JMP', 'EQ', 'JMP', 'EQ', 'JMP', 'JMP',
339'CLOSE', 'CLOSE', 'CLOSE', 'CLOSE', 'RETURN0')
340
341checkequal(
342function (a) while a < 10 do a = a + 1 end end,
343function (a) while true do if not(a < 10) then break end; a = a + 1; end end
344)
345
346print 'OK'
347
diff --git a/testes/constructs.lua b/testes/constructs.lua
new file mode 100644
index 00000000..7796c46f
--- /dev/null
+++ b/testes/constructs.lua
@@ -0,0 +1,302 @@
1-- $Id: constructs.lua,v 1.43 2018/02/21 17:41:07 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(0xF0 | 0xCC ~ 0xAA & 0xFD == 0xF4)
36assert(0xFD & 0xAA ~ 0xCC | 0xF0 == 0xF4)
37assert(0xF0 & 0x0F + 1 == 0x10)
38
39assert(3^4//2^3//5 == 2)
40
41assert(-3+4*5//2^3^2//9+4%10/3 == (-3)+(((4*5)//(2^(3^2)))//9)+((4%10)/3))
42
43assert(not ((true or false) and nil))
44assert( true or false and nil)
45
46-- old bug
47assert((((1 or false) and true) or false) == true)
48assert((((nil and true) or false) and true) == false)
49
50local a,b = 1,nil;
51assert(-(1 or 2) == -1 and (1 and 2)+(-1.25 or -4) == 0.75);
52x = ((b or a)+1 == 2 and (10 or a)+1 == 11); assert(x);
53x = (((2<3) or 1) == true and (2<3 and 4) == 4); assert(x);
54
55x,y=1,2;
56assert((x>y) and x or y == 2);
57x,y=2,1;
58assert((x>y) and x or y == 2);
59
60assert(1234567890 == tonumber('1234567890') and 1234567890+1 == 1234567891)
61
62
63-- silly loops
64repeat until 1; repeat until true;
65while false do end; while nil do end;
66
67do -- test old bug (first name could not be an `upvalue')
68 local a; function f(x) x={a=1}; x={x=1}; x={G=1} end
69end
70
71function f (i)
72 if type(i) ~= 'number' then return i,'jojo'; end;
73 if i > 0 then return i, f(i-1); end;
74end
75
76x = {f(3), f(5), f(10);};
77assert(x[1] == 3 and x[2] == 5 and x[3] == 10 and x[4] == 9 and x[12] == 1);
78assert(x[nil] == nil)
79x = {f'alo', f'xixi', nil};
80assert(x[1] == 'alo' and x[2] == 'xixi' and x[3] == nil);
81x = {f'alo'..'xixi'};
82assert(x[1] == 'aloxixi')
83x = {f{}}
84assert(x[2] == 'jojo' and type(x[1]) == 'table')
85
86
87local f = function (i)
88 if i < 10 then return 'a';
89 elseif i < 20 then return 'b';
90 elseif i < 30 then return 'c';
91 end;
92end
93
94assert(f(3) == 'a' and f(12) == 'b' and f(26) == 'c' and f(100) == nil)
95
96for i=1,1000 do break; end;
97n=100;
98i=3;
99t = {};
100a=nil
101while not a do
102 a=0; for i=1,n do for i=i,1,-1 do a=a+1; t[i]=1; end; end;
103end
104assert(a == n*(n+1)/2 and i==3);
105assert(t[1] and t[n] and not t[0] and not t[n+1])
106
107function f(b)
108 local x = 1;
109 repeat
110 local a;
111 if b==1 then local b=1; x=10; break
112 elseif b==2 then x=20; break;
113 elseif b==3 then x=30;
114 else local a,b,c,d=math.sin(1); x=x+1;
115 end
116 until x>=12;
117 return x;
118end;
119
120assert(f(1) == 10 and f(2) == 20 and f(3) == 30 and f(4)==12)
121
122
123local f = function (i)
124 if i < 10 then return 'a'
125 elseif i < 20 then return 'b'
126 elseif i < 30 then return 'c'
127 else return 8
128 end
129end
130
131assert(f(3) == 'a' and f(12) == 'b' and f(26) == 'c' and f(100) == 8)
132
133local a, b = nil, 23
134x = {f(100)*2+3 or a, a or b+2}
135assert(x[1] == 19 and x[2] == 25)
136x = {f=2+3 or a, a = b+2}
137assert(x.f == 5 and x.a == 25)
138
139a={y=1}
140x = {a.y}
141assert(x[1] == 1)
142
143function f(i)
144 while 1 do
145 if i>0 then i=i-1;
146 else return; end;
147 end;
148end;
149
150function g(i)
151 while 1 do
152 if i>0 then i=i-1
153 else return end
154 end
155end
156
157f(10); g(10);
158
159do
160 function f () return 1,2,3; end
161 local a, b, c = f();
162 assert(a==1 and b==2 and c==3)
163 a, b, c = (f());
164 assert(a==1 and b==nil and c==nil)
165end
166
167local a,b = 3 and f();
168assert(a==1 and b==nil)
169
170function g() f(); return; end;
171assert(g() == nil)
172function g() return nil or f() end
173a,b = g()
174assert(a==1 and b==nil)
175
176print'+';
177
178
179f = [[
180return function ( a , b , c , d , e )
181 local x = a >= b or c or ( d and e ) or nil
182 return x
183end , { a = 1 , b = 2 >= 1 , } or { 1 };
184]]
185f = string.gsub(f, "%s+", "\n"); -- force a SETLINE between opcodes
186f,a = load(f)();
187assert(a.a == 1 and a.b)
188
189function g (a,b,c,d,e)
190 if not (a>=b or c or d and e or nil) then return 0; else return 1; end;
191end
192
193function h (a,b,c,d,e)
194 while (a>=b or c or (d and e) or nil) do return 1; end;
195 return 0;
196end;
197
198assert(f(2,1) == true and g(2,1) == 1 and h(2,1) == 1)
199assert(f(1,2,'a') == 'a' and g(1,2,'a') == 1 and h(1,2,'a') == 1)
200assert(f(1,2,'a')
201~= -- force SETLINE before nil
202nil, "")
203assert(f(1,2,'a') == 'a' and g(1,2,'a') == 1 and h(1,2,'a') == 1)
204assert(f(1,2,nil,1,'x') == 'x' and g(1,2,nil,1,'x') == 1 and
205 h(1,2,nil,1,'x') == 1)
206assert(f(1,2,nil,nil,'x') == nil and g(1,2,nil,nil,'x') == 0 and
207 h(1,2,nil,nil,'x') == 0)
208assert(f(1,2,nil,1,nil) == nil and g(1,2,nil,1,nil) == 0 and
209 h(1,2,nil,1,nil) == 0)
210
211assert(1 and 2<3 == true and 2<3 and 'a'<'b' == true)
212x = 2<3 and not 3; assert(x==false)
213x = 2<1 or (2>1 and 'a'); assert(x=='a')
214
215
216do
217 local a; if nil then a=1; else a=2; end; -- this nil comes as PUSHNIL 2
218 assert(a==2)
219end
220
221function F(a)
222 assert(debug.getinfo(1, "n").name == 'F')
223 return a,2,3
224end
225
226a,b = F(1)~=nil; assert(a == true and b == nil);
227a,b = F(nil)==nil; assert(a == true and b == nil)
228
229----------------------------------------------------------------
230------------------------------------------------------------------
231
232-- sometimes will be 0, sometimes will not...
233_ENV.GLOB1 = math.floor(os.time()) % 2
234
235-- basic expressions with their respective values
236local basiccases = {
237 {"nil", nil},
238 {"false", false},
239 {"true", true},
240 {"10", 10},
241 {"(0==_ENV.GLOB1)", 0 == _ENV.GLOB1},
242}
243
244print('testing short-circuit optimizations (' .. _ENV.GLOB1 .. ')')
245
246
247-- operators with their respective values
248local binops = {
249 {" and ", function (a,b) if not a then return a else return b end end},
250 {" or ", function (a,b) if a then return a else return b end end},
251}
252
253local cases = {}
254
255-- creates all combinations of '(cases[i] op cases[n-i])' plus
256-- 'not(cases[i] op cases[n-i])' (syntax + value)
257local function createcases (n)
258 local res = {}
259 for i = 1, n - 1 do
260 for _, v1 in ipairs(cases[i]) do
261 for _, v2 in ipairs(cases[n - i]) do
262 for _, op in ipairs(binops) do
263 local t = {
264 "(" .. v1[1] .. op[1] .. v2[1] .. ")",
265 op[2](v1[2], v2[2])
266 }
267 res[#res + 1] = t
268 res[#res + 1] = {"not" .. t[1], not t[2]}
269 end
270 end
271 end
272 end
273 return res
274end
275
276-- do not do too many combinations for soft tests
277local level = _soft and 3 or 4
278
279cases[1] = basiccases
280for i = 2, level do cases[i] = createcases(i) end
281print("+")
282
283local prog = [[if %s then IX = true end; return %s]]
284
285local i = 0
286for n = 1, level do
287 for _, v in pairs(cases[n]) do
288 local s = v[1]
289 local p = load(string.format(prog, s, s), "")
290 IX = false
291 assert(p() == v[2] and IX == not not v[2])
292 i = i + 1
293 if i % 60000 == 0 then print('+') end
294 end
295end
296------------------------------------------------------------------
297
298-- testing some syntax errors (chosen through 'gcov')
299checkload("for x do", "expected")
300checkload("x:call", "expected")
301
302print'OK'
diff --git a/testes/coroutine.lua b/testes/coroutine.lua
new file mode 100644
index 00000000..22087320
--- /dev/null
+++ b/testes/coroutine.lua
@@ -0,0 +1,918 @@
1-- $Id: coroutine.lua,v 1.48 2018/03/12 14:19:36 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
181do -- testing single trace of coroutines
182 local X
183 local co = coroutine.create(function ()
184 coroutine.yield(10)
185 return 20;
186 end)
187 local trace = {}
188 local function dotrace (event)
189 trace[#trace + 1] = event
190 end
191 debug.sethook(co, dotrace, "clr")
192 repeat until not coroutine.resume(co)
193 local correcttrace = {"call", "line", "call", "return", "line", "return"}
194 assert(#trace == #correcttrace)
195 for k, v in pairs(trace) do
196 assert(v == correcttrace[k])
197 end
198end
199
200-- errors in coroutines
201function foo ()
202 assert(debug.getinfo(1).currentline == debug.getinfo(foo).linedefined + 1)
203 assert(debug.getinfo(2).currentline == debug.getinfo(goo).linedefined)
204 coroutine.yield(3)
205 error(foo)
206end
207
208function goo() foo() end
209x = coroutine.wrap(goo)
210assert(x() == 3)
211local a,b = pcall(x)
212assert(not a and b == foo)
213
214x = coroutine.create(goo)
215a,b = coroutine.resume(x)
216assert(a and b == 3)
217a,b = coroutine.resume(x)
218assert(not a and b == foo and coroutine.status(x) == "dead")
219a,b = coroutine.resume(x)
220assert(not a and string.find(b, "dead") and coroutine.status(x) == "dead")
221
222
223-- co-routines x for loop
224function all (a, n, k)
225 if k == 0 then coroutine.yield(a)
226 else
227 for i=1,n do
228 a[k] = i
229 all(a, n, k-1)
230 end
231 end
232end
233
234local a = 0
235for t in coroutine.wrap(function () all({}, 5, 4) end) do
236 a = a+1
237end
238assert(a == 5^4)
239
240
241-- access to locals of collected corroutines
242local C = {}; setmetatable(C, {__mode = "kv"})
243local x = coroutine.wrap (function ()
244 local a = 10
245 local function f () a = a+10; return a end
246 while true do
247 a = a+1
248 coroutine.yield(f)
249 end
250 end)
251
252C[1] = x;
253
254local f = x()
255assert(f() == 21 and x()() == 32 and x() == f)
256x = nil
257collectgarbage()
258assert(C[1] == undef)
259assert(f() == 43 and f() == 53)
260
261
262-- old bug: attempt to resume itself
263
264function co_func (current_co)
265 assert(coroutine.running() == current_co)
266 assert(coroutine.resume(current_co) == false)
267 coroutine.yield(10, 20)
268 assert(coroutine.resume(current_co) == false)
269 coroutine.yield(23)
270 return 10
271end
272
273local co = coroutine.create(co_func)
274local a,b,c = coroutine.resume(co, co)
275assert(a == true and b == 10 and c == 20)
276a,b = coroutine.resume(co, co)
277assert(a == true and b == 23)
278a,b = coroutine.resume(co, co)
279assert(a == true and b == 10)
280assert(coroutine.resume(co, co) == false)
281assert(coroutine.resume(co, co) == false)
282
283
284-- other old bug when attempting to resume itself
285-- (trigger C-code assertions)
286do
287 local A = coroutine.running()
288 local B = coroutine.create(function() return coroutine.resume(A) end)
289 local st, res = coroutine.resume(B)
290 assert(st == true and res == false)
291
292 A = coroutine.wrap(function() return pcall(A, 1) end)
293 st, res = A()
294 assert(not st and string.find(res, "non%-suspended"))
295end
296
297
298-- attempt to resume 'normal' coroutine
299local co1, co2
300co1 = coroutine.create(function () return co2() end)
301co2 = coroutine.wrap(function ()
302 assert(coroutine.status(co1) == 'normal')
303 assert(not coroutine.resume(co1))
304 coroutine.yield(3)
305 end)
306
307a,b = coroutine.resume(co1)
308assert(a and b == 3)
309assert(coroutine.status(co1) == 'dead')
310
311-- infinite recursion of coroutines
312a = function(a) coroutine.wrap(a)(a) end
313assert(not pcall(a, a))
314a = nil
315
316
317-- access to locals of erroneous coroutines
318local x = coroutine.create (function ()
319 local a = 10
320 _G.f = function () a=a+1; return a end
321 error('x')
322 end)
323
324assert(not coroutine.resume(x))
325-- overwrite previous position of local `a'
326assert(not coroutine.resume(x, 1, 1, 1, 1, 1, 1, 1))
327assert(_G.f() == 11)
328assert(_G.f() == 12)
329
330
331if not T then
332 (Message or print)('\n >>> testC not active: skipping yield/hook tests <<<\n')
333else
334 print "testing yields inside hooks"
335
336 local turn
337
338 function fact (t, x)
339 assert(turn == t)
340 if x == 0 then return 1
341 else return x*fact(t, x-1)
342 end
343 end
344
345 local A, B = 0, 0
346
347 local x = coroutine.create(function ()
348 T.sethook("yield 0", "", 2)
349 A = fact("A", 6)
350 end)
351
352 local y = coroutine.create(function ()
353 T.sethook("yield 0", "", 3)
354 B = fact("B", 7)
355 end)
356
357 while A==0 or B==0 do -- A ~= 0 when 'x' finishes (similar for 'B','y')
358 if A==0 then turn = "A"; assert(T.resume(x)) end
359 if B==0 then turn = "B"; assert(T.resume(y)) end
360 end
361
362 assert(B // A == 7) -- fact(7) // fact(6)
363
364 local line = debug.getinfo(1, "l").currentline + 2 -- get line number
365 local function foo ()
366 local x = 10 --<< this line is 'line'
367 x = x + 10
368 _G.XX = x
369 end
370
371 -- testing yields in line hook
372 local co = coroutine.wrap(function ()
373 T.sethook("setglobal X; yield 0", "l", 0); foo(); return 10 end)
374
375 _G.XX = nil;
376 _G.X = nil; co(); assert(_G.X == line)
377 _G.X = nil; co(); assert(_G.X == line + 1)
378 _G.X = nil; co(); assert(_G.X == line + 2 and _G.XX == nil)
379 _G.X = nil; co(); assert(_G.X == line + 3 and _G.XX == 20)
380 assert(co() == 10)
381
382 -- testing yields in count hook
383 co = coroutine.wrap(function ()
384 T.sethook("yield 0", "", 1); foo(); return 10 end)
385
386 _G.XX = nil;
387 local c = 0
388 repeat c = c + 1; local a = co() until a == 10
389 assert(_G.XX == 20 and c >= 5)
390
391 co = coroutine.wrap(function ()
392 T.sethook("yield 0", "", 2); foo(); return 10 end)
393
394 _G.XX = nil;
395 local c = 0
396 repeat c = c + 1; local a = co() until a == 10
397 assert(_G.XX == 20 and c >= 5)
398 _G.X = nil; _G.XX = nil
399
400 do
401 -- testing debug library on a coroutine suspended inside a hook
402 -- (bug in 5.2/5.3)
403 c = coroutine.create(function (a, ...)
404 T.sethook("yield 0", "l") -- will yield on next two lines
405 assert(a == 10)
406 return ...
407 end)
408
409 assert(coroutine.resume(c, 1, 2, 3)) -- start coroutine
410 local n,v = debug.getlocal(c, 0, 1) -- check its local
411 assert(n == "a" and v == 1)
412 assert(debug.setlocal(c, 0, 1, 10)) -- test 'setlocal'
413 local t = debug.getinfo(c, 0) -- test 'getinfo'
414 assert(t.currentline == t.linedefined + 1)
415 assert(not debug.getinfo(c, 1)) -- no other level
416 assert(coroutine.resume(c)) -- run next line
417 v = {coroutine.resume(c)} -- finish coroutine
418 assert(v[1] == true and v[2] == 2 and v[3] == 3 and v[4] == undef)
419 assert(not coroutine.resume(c))
420 end
421
422 do
423 -- testing debug library on last function in a suspended coroutine
424 -- (bug in 5.2/5.3)
425 local c = coroutine.create(function () T.testC("yield 1", 10, 20) end)
426 local a, b = coroutine.resume(c)
427 assert(a and b == 20)
428 assert(debug.getinfo(c, 0).linedefined == -1)
429 a, b = debug.getlocal(c, 0, 2)
430 assert(b == 10)
431 end
432
433
434 print "testing coroutine API"
435
436 -- reusing a thread
437 assert(T.testC([[
438 newthread # create thread
439 pushvalue 2 # push body
440 pushstring 'a a a' # push argument
441 xmove 0 3 2 # move values to new thread
442 resume -1, 1 # call it first time
443 pushstatus
444 xmove 3 0 0 # move results back to stack
445 setglobal X # result
446 setglobal Y # status
447 pushvalue 2 # push body (to call it again)
448 pushstring 'b b b'
449 xmove 0 3 2
450 resume -1, 1 # call it again
451 pushstatus
452 xmove 3 0 0
453 return 1 # return result
454 ]], function (...) return ... end) == 'b b b')
455
456 assert(X == 'a a a' and Y == 'OK')
457
458
459 -- resuming running coroutine
460 C = coroutine.create(function ()
461 return T.testC([[
462 pushnum 10;
463 pushnum 20;
464 resume -3 2;
465 pushstatus
466 gettop;
467 return 3]], C)
468 end)
469 local a, b, c, d = coroutine.resume(C)
470 assert(a == true and string.find(b, "non%-suspended") and
471 c == "ERRRUN" and d == 4)
472
473 a, b, c, d = T.testC([[
474 rawgeti R 1 # get main thread
475 pushnum 10;
476 pushnum 20;
477 resume -3 2;
478 pushstatus
479 gettop;
480 return 4]])
481 assert(a == coroutine.running() and string.find(b, "non%-suspended") and
482 c == "ERRRUN" and d == 4)
483
484
485 -- using a main thread as a coroutine
486 local state = T.newstate()
487 T.loadlib(state)
488
489 assert(T.doremote(state, [[
490 coroutine = require'coroutine';
491 X = function (x) coroutine.yield(x, 'BB'); return 'CC' end;
492 return 'ok']]))
493
494 t = table.pack(T.testC(state, [[
495 rawgeti R 1 # get main thread
496 pushstring 'XX'
497 getglobal X # get function for body
498 pushstring AA # arg
499 resume 1 1 # 'resume' shadows previous stack!
500 gettop
501 setglobal T # top
502 setglobal B # second yielded value
503 setglobal A # fist yielded value
504 rawgeti R 1 # get main thread
505 pushnum 5 # arg (noise)
506 resume 1 1 # after coroutine ends, previous stack is back
507 pushstatus
508 return *
509 ]]))
510 assert(t.n == 4 and t[2] == 'XX' and t[3] == 'CC' and t[4] == 'OK')
511 assert(T.doremote(state, "return T") == '2')
512 assert(T.doremote(state, "return A") == 'AA')
513 assert(T.doremote(state, "return B") == 'BB')
514
515 T.closestate(state)
516
517 print'+'
518
519end
520
521
522-- leaving a pending coroutine open
523_X = coroutine.wrap(function ()
524 local a = 10
525 local x = function () a = a+1 end
526 coroutine.yield()
527 end)
528
529_X()
530
531
532if not _soft then
533 -- bug (stack overflow)
534 local j = 2^9
535 local lim = 1000000 -- (C stack limit; assume 32-bit machine)
536 local t = {lim - 10, lim - 5, lim - 1, lim, lim + 1}
537 for i = 1, #t do
538 local j = t[i]
539 co = coroutine.create(function()
540 local t = {}
541 for i = 1, j do t[i] = i end
542 return table.unpack(t)
543 end)
544 local r, msg = coroutine.resume(co)
545 assert(not r)
546 end
547 co = nil
548end
549
550
551assert(coroutine.running() == main)
552
553print"+"
554
555
556print"testing yields inside metamethods"
557
558local function val(x)
559 if type(x) == "table" then return x.x else return x end
560end
561
562local mt = {
563 __eq = function(a,b) coroutine.yield(nil, "eq"); return val(a) == val(b) end,
564 __lt = function(a,b) coroutine.yield(nil, "lt"); return val(a) < val(b) end,
565 __le = function(a,b) coroutine.yield(nil, "le"); return a - b <= 0 end,
566 __add = function(a,b) coroutine.yield(nil, "add");
567 return val(a) + val(b) end,
568 __sub = function(a,b) coroutine.yield(nil, "sub"); return val(a) - val(b) end,
569 __mul = function(a,b) coroutine.yield(nil, "mul"); return val(a) * val(b) end,
570 __div = function(a,b) coroutine.yield(nil, "div"); return val(a) / val(b) end,
571 __idiv = function(a,b) coroutine.yield(nil, "idiv");
572 return val(a) // val(b) end,
573 __pow = function(a,b) coroutine.yield(nil, "pow"); return val(a) ^ val(b) end,
574 __mod = function(a,b) coroutine.yield(nil, "mod"); return val(a) % val(b) end,
575 __unm = function(a,b) coroutine.yield(nil, "unm"); return -val(a) end,
576 __bnot = function(a,b) coroutine.yield(nil, "bnot"); return ~val(a) end,
577 __shl = function(a,b) coroutine.yield(nil, "shl");
578 return val(a) << val(b) end,
579 __shr = function(a,b) coroutine.yield(nil, "shr");
580 return val(a) >> val(b) end,
581 __band = function(a,b)
582 coroutine.yield(nil, "band")
583 return val(a) & val(b)
584 end,
585 __bor = function(a,b) coroutine.yield(nil, "bor");
586 return val(a) | val(b) end,
587 __bxor = function(a,b) coroutine.yield(nil, "bxor");
588 return val(a) ~ val(b) end,
589
590 __concat = function(a,b)
591 coroutine.yield(nil, "concat");
592 return val(a) .. val(b)
593 end,
594 __index = function (t,k) coroutine.yield(nil, "idx"); return t.k[k] end,
595 __newindex = function (t,k,v) coroutine.yield(nil, "nidx"); t.k[k] = v end,
596}
597
598
599local function new (x)
600 return setmetatable({x = x, k = {}}, mt)
601end
602
603
604local a = new(10)
605local b = new(12)
606local c = new"hello"
607
608local function run (f, t)
609 local i = 1
610 local c = coroutine.wrap(f)
611 while true do
612 local res, stat = c()
613 if res then assert(t[i] == undef); return res, t end
614 assert(stat == t[i])
615 i = i + 1
616 end
617end
618
619
620assert(run(function () if (a>=b) then return '>=' else return '<' end end,
621 {"le", "sub"}) == "<")
622-- '<=' using '<'
623mt.__le = nil
624assert(run(function () if (a<=b) then return '<=' else return '>' end end,
625 {"lt"}) == "<=")
626assert(run(function () if (a==b) then return '==' else return '~=' end end,
627 {"eq"}) == "~=")
628
629assert(run(function () return a & b + a end, {"add", "band"}) == 2)
630
631assert(run(function () return 1 + a end, {"add"}) == 11)
632assert(run(function () return a - 25 end, {"sub"}) == -15)
633assert(run(function () return 2 * a end, {"mul"}) == 20)
634assert(run(function () return a ^ 2 end, {"pow"}) == 100)
635assert(run(function () return a / 2 end, {"div"}) == 5)
636assert(run(function () return a % 6 end, {"mod"}) == 4)
637assert(run(function () return a // 3 end, {"idiv"}) == 3)
638
639assert(run(function () return a + b end, {"add"}) == 22)
640assert(run(function () return a - b end, {"sub"}) == -2)
641assert(run(function () return a * b end, {"mul"}) == 120)
642assert(run(function () return a ^ b end, {"pow"}) == 10^12)
643assert(run(function () return a / b end, {"div"}) == 10/12)
644assert(run(function () return a % b end, {"mod"}) == 10)
645assert(run(function () return a // b end, {"idiv"}) == 0)
646
647
648assert(run(function () return a % b end, {"mod"}) == 10)
649
650assert(run(function () return ~a & b end, {"bnot", "band"}) == ~10 & 12)
651assert(run(function () return a | b end, {"bor"}) == 10 | 12)
652assert(run(function () return a ~ b end, {"bxor"}) == 10 ~ 12)
653assert(run(function () return a << b end, {"shl"}) == 10 << 12)
654assert(run(function () return a >> b end, {"shr"}) == 10 >> 12)
655
656assert(run(function () return 10 & b end, {"band"}) == 10 & 12)
657assert(run(function () return a | 2 end, {"bor"}) == 10 | 2)
658assert(run(function () return a ~ 2 end, {"bxor"}) == 10 ~ 2)
659
660assert(run(function () return a..b end, {"concat"}) == "1012")
661
662assert(run(function() return a .. b .. c .. a end,
663 {"concat", "concat", "concat"}) == "1012hello10")
664
665assert(run(function() return "a" .. "b" .. a .. "c" .. c .. b .. "x" end,
666 {"concat", "concat", "concat"}) == "ab10chello12x")
667
668
669do -- a few more tests for comparsion operators
670 local mt1 = {
671 __le = function (a,b)
672 coroutine.yield(10)
673 return (val(a) <= val(b))
674 end,
675 __lt = function (a,b)
676 coroutine.yield(10)
677 return val(a) < val(b)
678 end,
679 }
680 local mt2 = { __lt = mt1.__lt } -- no __le
681
682 local function run (f)
683 local co = coroutine.wrap(f)
684 local res
685 repeat
686 res = co()
687 until res ~= 10
688 return res
689 end
690
691 local function test ()
692 local a1 = setmetatable({x=1}, mt1)
693 local a2 = setmetatable({x=2}, mt2)
694 assert(a1 < a2)
695 assert(a1 <= a2)
696 assert(1 < a2)
697 assert(1 <= a2)
698 assert(2 > a1)
699 assert(2 >= a2)
700 return true
701 end
702
703 run(test)
704
705end
706
707assert(run(function ()
708 a.BB = print
709 return a.BB
710 end, {"nidx", "idx"}) == print)
711
712-- getuptable & setuptable
713do local _ENV = _ENV
714 f = function () AAA = BBB + 1; return AAA end
715end
716g = new(10); g.k.BBB = 10;
717debug.setupvalue(f, 1, g)
718assert(run(f, {"idx", "nidx", "idx"}) == 11)
719assert(g.k.AAA == 11)
720
721print"+"
722
723print"testing yields inside 'for' iterators"
724
725local f = function (s, i)
726 if i%2 == 0 then coroutine.yield(nil, "for") end
727 if i < s then return i + 1 end
728 end
729
730assert(run(function ()
731 local s = 0
732 for i in f, 4, 0 do s = s + i end
733 return s
734 end, {"for", "for", "for"}) == 10)
735
736
737
738-- tests for coroutine API
739if T==nil then
740 (Message or print)('\n >>> testC not active: skipping coroutine API tests <<<\n')
741 return
742end
743
744print('testing coroutine API')
745
746local function apico (...)
747 local x = {...}
748 return coroutine.wrap(function ()
749 return T.testC(table.unpack(x))
750 end)
751end
752
753local a = {apico(
754[[
755 pushstring errorcode
756 pcallk 1 0 2;
757 invalid command (should not arrive here)
758]],
759[[return *]],
760"stackmark",
761error
762)()}
763assert(#a == 4 and
764 a[3] == "stackmark" and
765 a[4] == "errorcode" and
766 _G.status == "ERRRUN" and
767 _G.ctx == 2) -- 'ctx' to pcallk
768
769local co = apico(
770 "pushvalue 2; pushnum 10; pcallk 1 2 3; invalid command;",
771 coroutine.yield,
772 "getglobal status; getglobal ctx; pushvalue 2; pushstring a; pcallk 1 0 4; invalid command",
773 "getglobal status; getglobal ctx; return *")
774
775assert(co() == 10)
776assert(co(20, 30) == 'a')
777a = {co()}
778assert(#a == 10 and
779 a[2] == coroutine.yield and
780 a[5] == 20 and a[6] == 30 and
781 a[7] == "YIELD" and a[8] == 3 and
782 a[9] == "YIELD" and a[10] == 4)
783assert(not pcall(co)) -- coroutine is dead now
784
785
786f = T.makeCfunc("pushnum 3; pushnum 5; yield 1;")
787co = coroutine.wrap(function ()
788 assert(f() == 23); assert(f() == 23); return 10
789end)
790assert(co(23,16) == 5)
791assert(co(23,16) == 5)
792assert(co(23,16) == 10)
793
794
795-- testing coroutines with C bodies
796f = T.makeCfunc([[
797 pushnum 102
798 yieldk 1 U2
799 cannot be here!
800]],
801[[ # continuation
802 pushvalue U3 # accessing upvalues inside a continuation
803 pushvalue U4
804 return *
805]], 23, "huu")
806
807x = coroutine.wrap(f)
808assert(x() == 102)
809eqtab({x()}, {23, "huu"})
810
811
812f = T.makeCfunc[[pushstring 'a'; pushnum 102; yield 2; ]]
813
814a, b, c, d = T.testC([[newthread; pushvalue 2; xmove 0 3 1; resume 3 0;
815 pushstatus; xmove 3 0 0; resume 3 0; pushstatus;
816 return 4; ]], f)
817
818assert(a == 'YIELD' and b == 'a' and c == 102 and d == 'OK')
819
820
821-- testing chain of suspendable C calls
822
823local count = 3 -- number of levels
824
825f = T.makeCfunc([[
826 remove 1; # remove argument
827 pushvalue U3; # get selection function
828 call 0 1; # call it (result is 'f' or 'yield')
829 pushstring hello # single argument for selected function
830 pushupvalueindex 2; # index of continuation program
831 callk 1 -1 .; # call selected function
832 errorerror # should never arrive here
833]],
834[[
835 # continuation program
836 pushnum 34 # return value
837 return * # return all results
838]],
839function () -- selection function
840 count = count - 1
841 if count == 0 then return coroutine.yield
842 else return f
843 end
844end
845)
846
847co = coroutine.wrap(function () return f(nil) end)
848assert(co() == "hello") -- argument to 'yield'
849a = {co()}
850-- three '34's (one from each pending C call)
851assert(#a == 3 and a[1] == a[2] and a[2] == a[3] and a[3] == 34)
852
853
854-- testing yields with continuations
855
856co = coroutine.wrap(function (...) return
857 T.testC([[ # initial function
858 yieldk 1 2
859 cannot be here!
860 ]],
861 [[ # 1st continuation
862 yieldk 0 3
863 cannot be here!
864 ]],
865 [[ # 2nd continuation
866 yieldk 0 4
867 cannot be here!
868 ]],
869 [[ # 3th continuation
870 pushvalue 6 # function which is last arg. to 'testC' here
871 pushnum 10; pushnum 20;
872 pcall 2 0 0 # call should throw an error and return to next line
873 pop 1 # remove error message
874 pushvalue 6
875 getglobal status; getglobal ctx
876 pcallk 2 2 5 # call should throw an error and jump to continuation
877 cannot be here!
878 ]],
879 [[ # 4th (and last) continuation
880 return *
881 ]],
882 -- function called by 3th continuation
883 function (a,b) x=a; y=b; error("errmsg") end,
884 ...
885)
886end)
887
888local a = {co(3,4,6)}
889assert(a[1] == 6 and a[2] == undef)
890a = {co()}; assert(a[1] == undef and _G.status == "YIELD" and _G.ctx == 2)
891a = {co()}; assert(a[1] == undef and _G.status == "YIELD" and _G.ctx == 3)
892a = {co(7,8)};
893-- original arguments
894assert(type(a[1]) == 'string' and type(a[2]) == 'string' and
895 type(a[3]) == 'string' and type(a[4]) == 'string' and
896 type(a[5]) == 'string' and type(a[6]) == 'function')
897-- arguments left from fist resume
898assert(a[7] == 3 and a[8] == 4)
899-- arguments to last resume
900assert(a[9] == 7 and a[10] == 8)
901-- error message and nothing more
902assert(a[11]:find("errmsg") and #a == 11)
903-- check arguments to pcallk
904assert(x == "YIELD" and y == 4)
905
906assert(not pcall(co)) -- coroutine should be dead
907
908
909-- bug in nCcalls
910local co = coroutine.wrap(function ()
911 local a = {pcall(pcall,pcall,pcall,pcall,pcall,pcall,pcall,error,"hi")}
912 return pcall(assert, table.unpack(a))
913end)
914
915local a = {co()}
916assert(a[10] == "hi")
917
918print'OK'
diff --git a/testes/db.lua b/testes/db.lua
new file mode 100644
index 00000000..36d1cdaa
--- /dev/null
+++ b/testes/db.lua
@@ -0,0 +1,948 @@
1-- $Id: db.lua,v 1.90 2018/04/02 17:55:58 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
168do -- testing line info/trace with large gaps in source
169
170 local a = {1, 2, 3, 10, 124, 125, 126, 127, 128, 129, 130,
171 255, 256, 257, 500, 1000}
172 local s = [[
173 local b = {10}
174 a = b[1] X + Y b[1]
175 b = 4
176 ]]
177 for _, i in ipairs(a) do
178 local subs = {X = string.rep("\n", i)}
179 for _, j in ipairs(a) do
180 subs.Y = string.rep("\n", j)
181 local s = string.gsub(s, "[XY]", subs)
182 test(s, {1, 2 + i, 2 + i + j, 2 + i, 2 + i + j, 3 + i + j})
183 end
184 end
185end
186
187print'+'
188
189-- invalid levels in [gs]etlocal
190assert(not pcall(debug.getlocal, 20, 1))
191assert(not pcall(debug.setlocal, -1, 1, 10))
192
193
194-- parameter names
195local function foo (a,b,...) local d, e end
196local co = coroutine.create(foo)
197
198assert(debug.getlocal(foo, 1) == 'a')
199assert(debug.getlocal(foo, 2) == 'b')
200assert(not debug.getlocal(foo, 3))
201assert(debug.getlocal(co, foo, 1) == 'a')
202assert(debug.getlocal(co, foo, 2) == 'b')
203assert(not debug.getlocal(co, foo, 3))
204
205assert(not debug.getlocal(print, 1))
206
207
208local function foo () return (debug.getlocal(1, -1)) end
209assert(not foo(10))
210
211
212-- varargs
213local function foo (a, ...)
214 local t = table.pack(...)
215 for i = 1, t.n do
216 local n, v = debug.getlocal(1, -i)
217 assert(n == "(*vararg)" and v == t[i])
218 end
219 assert(not debug.getlocal(1, -(t.n + 1)))
220 assert(not debug.setlocal(1, -(t.n + 1), 30))
221 if t.n > 0 then
222 (function (x)
223 assert(debug.setlocal(2, -1, x) == "(*vararg)")
224 assert(debug.setlocal(2, -t.n, x) == "(*vararg)")
225 end)(430)
226 assert(... == 430)
227 end
228end
229
230foo()
231foo(print)
232foo(200, 3, 4)
233local a = {}
234for i = 1, (_soft and 100 or 1000) do a[i] = i end
235foo(table.unpack(a))
236a = nil
237
238
239
240do -- test hook presence in debug info
241 assert(not debug.gethook())
242 local count = 0
243 local function f ()
244 assert(debug.getinfo(1).namewhat == "hook")
245 local sndline = string.match(debug.traceback(), "\n(.-)\n")
246 assert(string.find(sndline, "hook"))
247 count = count + 1
248 end
249 debug.sethook(f, "l")
250 local a = 0
251 _ENV.a = a
252 a = 1
253 debug.sethook()
254 assert(count == 4)
255end
256
257
258a = {}; L = nil
259local glob = 1
260local oldglob = glob
261debug.sethook(function (e,l)
262 collectgarbage() -- force GC during a hook
263 local f, m, c = debug.gethook()
264 assert(m == 'crl' and c == 0)
265 if e == "line" then
266 if glob ~= oldglob then
267 L = l-1 -- get the first line where "glob" has changed
268 oldglob = glob
269 end
270 elseif e == "call" then
271 local f = debug.getinfo(2, "f").func
272 a[f] = 1
273 else assert(e == "return")
274 end
275end, "crl")
276
277
278function f(a,b)
279 collectgarbage()
280 local _, x = debug.getlocal(1, 1)
281 local _, y = debug.getlocal(1, 2)
282 assert(x == a and y == b)
283 assert(debug.setlocal(2, 3, "pera") == "AA".."AA")
284 assert(debug.setlocal(2, 4, "maçã") == "B")
285 x = debug.getinfo(2)
286 assert(x.func == g and x.what == "Lua" and x.name == 'g' and
287 x.nups == 2 and string.find(x.source, "^@.*db%.lua$"))
288 glob = glob+1
289 assert(debug.getinfo(1, "l").currentline == L+1)
290 assert(debug.getinfo(1, "l").currentline == L+2)
291end
292
293function foo()
294 glob = glob+1
295 assert(debug.getinfo(1, "l").currentline == L+1)
296end; foo() -- set L
297-- check line counting inside strings and empty lines
298
299_ = 'alo\
300alo' .. [[
301
302]]
303--[[
304]]
305assert(debug.getinfo(1, "l").currentline == L+11) -- check count of lines
306
307
308function g (...)
309 local arg = {...}
310 do local a,b,c; a=math.sin(40); end
311 local feijao
312 local AAAA,B = "xuxu", "mamão"
313 f(AAAA,B)
314 assert(AAAA == "pera" and B == "maçã")
315 do
316 local B = 13
317 local x,y = debug.getlocal(1,5)
318 assert(x == 'B' and y == 13)
319 end
320end
321
322g()
323
324
325assert(a[f] and a[g] and a[assert] and a[debug.getlocal] and not a[print])
326
327
328-- tests for manipulating non-registered locals (C and Lua temporaries)
329
330local n, v = debug.getlocal(0, 1)
331assert(v == 0 and n == "(*temporary)")
332local n, v = debug.getlocal(0, 2)
333assert(v == 2 and n == "(*temporary)")
334assert(not debug.getlocal(0, 3))
335assert(not debug.getlocal(0, 0))
336
337function f()
338 assert(select(2, debug.getlocal(2,3)) == 1)
339 assert(not debug.getlocal(2,4))
340 debug.setlocal(2, 3, 10)
341 return 20
342end
343
344function g(a,b) return (a+1) + f() end
345
346assert(g(0,0) == 30)
347
348
349debug.sethook(nil);
350assert(debug.gethook() == nil)
351
352
353-- minimal tests for setuservalue/getuservalue
354do
355 assert(debug.setuservalue(io.stdin, 10) == nil)
356 local a, b = debug.getuservalue(io.stdin, 10)
357 assert(a == nil and not b)
358end
359
360-- testing iteraction between multiple values x hooks
361do
362 local function f(...) return 3, ... end
363 local count = 0
364 local a = {}
365 for i = 1, 100 do a[i] = i end
366 debug.sethook(function () count = count + 1 end, "", 1)
367 local t = {table.unpack(a)}
368 assert(#t == 100)
369 t = {table.unpack(a, 1, 3)}
370 assert(#t == 3)
371 t = {f(table.unpack(a, 1, 30))}
372 assert(#t == 31)
373end
374
375
376-- testing access to function arguments
377
378local function collectlocals (level)
379 local tab = {}
380 for i = 1, math.huge do
381 local n, v = debug.getlocal(level + 1, i)
382 if not (n and string.find(n, "^[a-zA-Z0-9_]+$")) then
383 break -- consider only real variables
384 end
385 tab[n] = v
386 end
387 return tab
388end
389
390
391X = nil
392a = {}
393function a:f (a, b, ...) local arg = {...}; local c = 13 end
394debug.sethook(function (e)
395 assert(e == "call")
396 dostring("XX = 12") -- test dostring inside hooks
397 -- testing errors inside hooks
398 assert(not pcall(load("a='joao'+1")))
399 debug.sethook(function (e, l)
400 assert(debug.getinfo(2, "l").currentline == l)
401 local f,m,c = debug.gethook()
402 assert(e == "line")
403 assert(m == 'l' and c == 0)
404 debug.sethook(nil) -- hook is called only once
405 assert(not X) -- check that
406 X = collectlocals(2)
407 end, "l")
408end, "c")
409
410a:f(1,2,3,4,5)
411assert(X.self == a and X.a == 1 and X.b == 2 and X.c == nil)
412assert(XX == 12)
413assert(debug.gethook() == nil)
414
415
416-- testing access to local variables in return hook (bug in 5.2)
417do
418 local X = false
419
420 local function foo (a, b, ...)
421 do local x,y,z end
422 local c, d = 10, 20
423 return
424 end
425
426 local function aux ()
427 if debug.getinfo(2).name == "foo" then
428 X = true -- to signal that it found 'foo'
429 local tab = {a = 100, b = 200, c = 10, d = 20}
430 for n, v in pairs(collectlocals(2)) do
431 assert(tab[n] == v)
432 tab[n] = undef
433 end
434 assert(next(tab) == nil) -- 'tab' must be empty
435 end
436 end
437
438 debug.sethook(aux, "r"); foo(100, 200); debug.sethook()
439 assert(X)
440
441end
442
443
444local function eqseq (t1, t2)
445 assert(#t1 == #t2)
446 for i = 1, #t1 do
447 assert(t1[i] == t2[i])
448 end
449end
450
451
452do print("testing inspection of parameters/returned values")
453 local on = false
454 local inp, out
455
456 local function hook (event)
457 if not on then return end
458 local ar = debug.getinfo(2, "ruS")
459 local t = {}
460 for i = ar.ftransfer, ar.ftransfer + ar.ntransfer - 1 do
461 local _, v = debug.getlocal(2, i)
462 t[#t + 1] = v
463 end
464 if event == "return" then
465 out = t
466 else
467 inp = t
468 end
469 end
470
471 debug.sethook(hook, "cr")
472
473 on = true; math.sin(3); on = false
474 eqseq(inp, {3}); eqseq(out, {math.sin(3)})
475
476 on = true; select(2, 10, 20, 30, 40); on = false
477 eqseq(inp, {2, 10, 20, 30, 40}); eqseq(out, {20, 30, 40})
478
479 local function foo (a, ...) return ... end
480 local function foo1 () on = not on; return foo(20, 10, 0) end
481 foo1(); on = false
482 eqseq(inp, {20}); eqseq(out, {10, 0})
483
484 debug.sethook()
485end
486
487
488
489-- testing upvalue access
490local function getupvalues (f)
491 local t = {}
492 local i = 1
493 while true do
494 local name, value = debug.getupvalue(f, i)
495 if not name then break end
496 assert(not t[name])
497 t[name] = value
498 i = i + 1
499 end
500 return t
501end
502
503local a,b,c = 1,2,3
504local function foo1 (a) b = a; return c end
505local function foo2 (x) a = x; return c+b end
506assert(not debug.getupvalue(foo1, 3))
507assert(not debug.getupvalue(foo1, 0))
508assert(not debug.setupvalue(foo1, 3, "xuxu"))
509local t = getupvalues(foo1)
510assert(t.a == nil and t.b == 2 and t.c == 3)
511t = getupvalues(foo2)
512assert(t.a == 1 and t.b == 2 and t.c == 3)
513assert(debug.setupvalue(foo1, 1, "xuxu") == "b")
514assert(({debug.getupvalue(foo2, 3)})[2] == "xuxu")
515-- upvalues of C functions are allways "called" "" (the empty string)
516assert(debug.getupvalue(string.gmatch("x", "x"), 1) == "")
517
518
519-- testing count hooks
520local a=0
521debug.sethook(function (e) a=a+1 end, "", 1)
522a=0; for i=1,1000 do end; assert(1000 < a and a < 1012)
523debug.sethook(function (e) a=a+1 end, "", 4)
524a=0; for i=1,1000 do end; assert(250 < a and a < 255)
525local f,m,c = debug.gethook()
526assert(m == "" and c == 4)
527debug.sethook(function (e) a=a+1 end, "", 4000)
528a=0; for i=1,1000 do end; assert(a == 0)
529
530do
531 debug.sethook(print, "", 2^24 - 1) -- count upperbound
532 local f,m,c = debug.gethook()
533 assert(({debug.gethook()})[3] == 2^24 - 1)
534end
535
536debug.sethook()
537
538
539-- tests for tail calls
540local function f (x)
541 if x then
542 assert(debug.getinfo(1, "S").what == "Lua")
543 assert(debug.getinfo(1, "t").istailcall == true)
544 local tail = debug.getinfo(2)
545 assert(tail.func == g1 and tail.istailcall == true)
546 assert(debug.getinfo(3, "S").what == "main")
547 print"+"
548 end
549end
550
551function g(x) return f(x) end
552
553function g1(x) g(x) end
554
555local function h (x) local f=g1; return f(x) end
556
557h(true)
558
559local b = {}
560debug.sethook(function (e) table.insert(b, e) end, "cr")
561h(false)
562debug.sethook()
563local res = {"return", -- first return (from sethook)
564 "call", "tail call", "call", "tail call",
565 "return", "return",
566 "call", -- last call (to sethook)
567}
568for i = 1, #res do assert(res[i] == table.remove(b, 1)) end
569
570b = 0
571debug.sethook(function (e)
572 if e == "tail call" then
573 b = b + 1
574 assert(debug.getinfo(2, "t").istailcall == true)
575 else
576 assert(debug.getinfo(2, "t").istailcall == false)
577 end
578 end, "c")
579h(false)
580debug.sethook()
581assert(b == 2) -- two tail calls
582
583lim = _soft and 3000 or 30000
584local function foo (x)
585 if x==0 then
586 assert(debug.getinfo(2).what == "main")
587 local info = debug.getinfo(1)
588 assert(info.istailcall == true and info.func == foo)
589 else return foo(x-1)
590 end
591end
592
593foo(lim)
594
595
596print"+"
597
598
599-- testing local function information
600co = load[[
601 local A = function ()
602 return x
603 end
604 return
605]]
606
607local a = 0
608-- 'A' should be visible to debugger only after its complete definition
609debug.sethook(function (e, l)
610 if l == 3 then a = a + 1; assert(debug.getlocal(2, 1) == "(*temporary)")
611 elseif l == 4 then a = a + 1; assert(debug.getlocal(2, 1) == "A")
612 end
613end, "l")
614co() -- run local function definition
615debug.sethook() -- turn off hook
616assert(a == 2) -- ensure all two lines where hooked
617
618-- testing traceback
619
620assert(debug.traceback(print) == print)
621assert(debug.traceback(print, 4) == print)
622assert(string.find(debug.traceback("hi", 4), "^hi\n"))
623assert(string.find(debug.traceback("hi"), "^hi\n"))
624assert(not string.find(debug.traceback("hi"), "'debug.traceback'"))
625assert(string.find(debug.traceback("hi", 0), "'debug.traceback'"))
626assert(string.find(debug.traceback(), "^stack traceback:\n"))
627
628do -- C-function names in traceback
629 local st, msg = (function () return pcall end)()(debug.traceback)
630 assert(st == true and string.find(msg, "pcall"))
631end
632
633
634-- testing nparams, nups e isvararg
635local t = debug.getinfo(print, "u")
636assert(t.isvararg == true and t.nparams == 0 and t.nups == 0)
637
638t = debug.getinfo(function (a,b,c) end, "u")
639assert(t.isvararg == false and t.nparams == 3 and t.nups == 0)
640
641t = debug.getinfo(function (a,b,...) return t[a] end, "u")
642assert(t.isvararg == true and t.nparams == 2 and t.nups == 1)
643
644t = debug.getinfo(1) -- main
645assert(t.isvararg == true and t.nparams == 0 and t.nups == 1 and
646 debug.getupvalue(t.func, 1) == "_ENV")
647
648
649
650
651-- testing debugging of coroutines
652
653local function checktraceback (co, p, level)
654 local tb = debug.traceback(co, nil, level)
655 local i = 0
656 for l in string.gmatch(tb, "[^\n]+\n?") do
657 assert(i == 0 or string.find(l, p[i]))
658 i = i+1
659 end
660 assert(p[i] == undef)
661end
662
663
664local function f (n)
665 if n > 0 then f(n-1)
666 else coroutine.yield() end
667end
668
669local co = coroutine.create(f)
670coroutine.resume(co, 3)
671checktraceback(co, {"yield", "db.lua", "db.lua", "db.lua", "db.lua"})
672checktraceback(co, {"db.lua", "db.lua", "db.lua", "db.lua"}, 1)
673checktraceback(co, {"db.lua", "db.lua", "db.lua"}, 2)
674checktraceback(co, {"db.lua"}, 4)
675checktraceback(co, {}, 40)
676
677
678co = coroutine.create(function (x)
679 local a = 1
680 coroutine.yield(debug.getinfo(1, "l"))
681 coroutine.yield(debug.getinfo(1, "l").currentline)
682 return a
683 end)
684
685local tr = {}
686local foo = function (e, l) if l then table.insert(tr, l) end end
687debug.sethook(co, foo, "lcr")
688
689local _, l = coroutine.resume(co, 10)
690local x = debug.getinfo(co, 1, "lfLS")
691assert(x.currentline == l.currentline and x.activelines[x.currentline])
692assert(type(x.func) == "function")
693for i=x.linedefined + 1, x.lastlinedefined do
694 assert(x.activelines[i])
695 x.activelines[i] = undef
696end
697assert(next(x.activelines) == nil) -- no 'extra' elements
698assert(not debug.getinfo(co, 2))
699local a,b = debug.getlocal(co, 1, 1)
700assert(a == "x" and b == 10)
701a,b = debug.getlocal(co, 1, 2)
702assert(a == "a" and b == 1)
703debug.setlocal(co, 1, 2, "hi")
704assert(debug.gethook(co) == foo)
705assert(#tr == 2 and
706 tr[1] == l.currentline-1 and tr[2] == l.currentline)
707
708a,b,c = pcall(coroutine.resume, co)
709assert(a and b and c == l.currentline+1)
710checktraceback(co, {"yield", "in function <"})
711
712a,b = coroutine.resume(co)
713assert(a and b == "hi")
714assert(#tr == 4 and tr[4] == l.currentline+2)
715assert(debug.gethook(co) == foo)
716assert(not debug.gethook())
717checktraceback(co, {})
718
719
720-- check get/setlocal in coroutines
721co = coroutine.create(function (x)
722 local a, b = coroutine.yield(x)
723 assert(a == 100 and b == nil)
724 return x
725end)
726a, b = coroutine.resume(co, 10)
727assert(a and b == 10)
728a, b = debug.getlocal(co, 1, 1)
729assert(a == "x" and b == 10)
730assert(not debug.getlocal(co, 1, 5))
731assert(debug.setlocal(co, 1, 1, 30) == "x")
732assert(not debug.setlocal(co, 1, 5, 40))
733a, b = coroutine.resume(co, 100)
734assert(a and b == 30)
735
736
737-- check traceback of suspended (or dead with error) coroutines
738
739function f(i) if i==0 then error(i) else coroutine.yield(); f(i-1) end end
740
741co = coroutine.create(function (x) f(x) end)
742a, b = coroutine.resume(co, 3)
743t = {"'coroutine.yield'", "'f'", "in function <"}
744while coroutine.status(co) == "suspended" do
745 checktraceback(co, t)
746 a, b = coroutine.resume(co)
747 table.insert(t, 2, "'f'") -- one more recursive call to 'f'
748end
749t[1] = "'error'"
750checktraceback(co, t)
751
752
753-- test acessing line numbers of a coroutine from a resume inside
754-- a C function (this is a known bug in Lua 5.0)
755
756local function g(x)
757 coroutine.yield(x)
758end
759
760local function f (i)
761 debug.sethook(function () end, "l")
762 for j=1,1000 do
763 g(i+j)
764 end
765end
766
767local co = coroutine.wrap(f)
768co(10)
769pcall(co)
770pcall(co)
771
772
773assert(type(debug.getregistry()) == "table")
774
775
776-- test tagmethod information
777local a = {}
778local function f (t)
779 local info = debug.getinfo(1);
780 assert(info.namewhat == "metamethod")
781 a.op = info.name
782 return info.name
783end
784setmetatable(a, {
785 __index = f; __add = f; __div = f; __mod = f; __concat = f; __pow = f;
786 __mul = f; __idiv = f; __unm = f; __len = f; __sub = f;
787 __shl = f; __shr = f; __bor = f; __bxor = f;
788 __eq = f; __le = f; __lt = f; __unm = f; __len = f; __band = f;
789 __bnot = f;
790})
791
792local b = setmetatable({}, getmetatable(a))
793
794assert(a[3] == "index" and a^3 == "pow" and a..a == "concat")
795assert(a/3 == "div" and 3%a == "mod")
796assert(a+3 == "add" and 3-a == "sub" and a*3 == "mul" and
797 -a == "unm" and #a == "len" and a&3 == "band")
798assert(a|3 == "bor" and 3~a == "bxor" and a<<3 == "shift" and
799 a>>1 == "shift")
800assert (a==b and a.op == "eq")
801assert (a>=b and a.op == "order")
802assert (a>b and a.op == "order")
803assert(~a == "bnot")
804
805do -- testing for-iterator name
806 local function f()
807 assert(debug.getinfo(1).name == "for iterator")
808 end
809
810 for i in f do end
811end
812
813
814do -- testing debug info for finalizers
815 local name = nil
816
817 -- create a piece of garbage with a finalizer
818 setmetatable({}, {__gc = function ()
819 local t = debug.getinfo(2) -- get callee information
820 assert(t.namewhat == "metamethod")
821 name = t.name
822 end})
823
824 -- repeat until previous finalizer runs (setting 'name')
825 repeat local a = {} until name
826 assert(name == "__gc")
827end
828
829
830do
831 print("testing traceback sizes")
832
833 local function countlines (s)
834 return select(2, string.gsub(s, "\n", ""))
835 end
836
837 local function deep (lvl, n)
838 if lvl == 0 then
839 return (debug.traceback("message", n))
840 else
841 return (deep(lvl-1, n))
842 end
843 end
844
845 local function checkdeep (total, start)
846 local s = deep(total, start)
847 local rest = string.match(s, "^message\nstack traceback:\n(.*)$")
848 local cl = countlines(rest)
849 -- at most 10 lines in first part, 11 in second, plus '...'
850 assert(cl <= 10 + 11 + 1)
851 local brk = string.find(rest, "%.%.%.")
852 if brk then -- does message have '...'?
853 local rest1 = string.sub(rest, 1, brk)
854 local rest2 = string.sub(rest, brk, #rest)
855 assert(countlines(rest1) == 10 and countlines(rest2) == 11)
856 else
857 assert(cl == total - start + 2)
858 end
859 end
860
861 for d = 1, 51, 10 do
862 for l = 1, d do
863 -- use coroutines to ensure complete control of the stack
864 coroutine.wrap(checkdeep)(d, l)
865 end
866 end
867
868end
869
870
871print("testing debug functions on chunk without debug info")
872prog = [[-- program to be loaded without debug information
873local debug = require'debug'
874local a = 12 -- a local variable
875
876local n, v = debug.getlocal(1, 1)
877assert(n == "(*temporary)" and v == debug) -- unkown name but known value
878n, v = debug.getlocal(1, 2)
879assert(n == "(*temporary)" and v == 12) -- unkown name but known value
880
881-- a function with an upvalue
882local f = function () local x; return a end
883n, v = debug.getupvalue(f, 1)
884assert(n == "(*no name)" and v == 12)
885assert(debug.setupvalue(f, 1, 13) == "(*no name)")
886assert(a == 13)
887
888local t = debug.getinfo(f)
889assert(t.name == nil and t.linedefined > 0 and
890 t.lastlinedefined == t.linedefined and
891 t.short_src == "?")
892assert(debug.getinfo(1).currentline == -1)
893
894t = debug.getinfo(f, "L").activelines
895assert(next(t) == nil) -- active lines are empty
896
897-- dump/load a function without debug info
898f = load(string.dump(f))
899
900t = debug.getinfo(f)
901assert(t.name == nil and t.linedefined > 0 and
902 t.lastlinedefined == t.linedefined and
903 t.short_src == "?")
904assert(debug.getinfo(1).currentline == -1)
905
906return a
907]]
908
909
910-- load 'prog' without debug info
911local f = assert(load(string.dump(load(prog), true)))
912
913assert(f() == 13)
914
915do -- tests for 'source' in binary dumps
916 local prog = [[
917 return function (x)
918 return function (y)
919 return x + y
920 end
921 end
922 ]]
923 local name = string.rep("x", 1000)
924 local p = assert(load(prog, name))
925 -- load 'p' as a binary chunk with debug information
926 local c = string.dump(p)
927 assert(#c > 1000 and #c < 2000) -- no repetition of 'source' in dump
928 local f = assert(load(c))
929 local g = f()
930 local h = g(3)
931 assert(h(5) == 8)
932 assert(debug.getinfo(f).source == name and -- all functions have 'source'
933 debug.getinfo(g).source == name and
934 debug.getinfo(h).source == name)
935 -- again, without debug info
936 local c = string.dump(p, true)
937 assert(#c < 500) -- no 'source' in dump
938 local f = assert(load(c))
939 local g = f()
940 local h = g(30)
941 assert(h(50) == 80)
942 assert(debug.getinfo(f).source == '=?' and -- no function has 'source'
943 debug.getinfo(g).source == '=?' and
944 debug.getinfo(h).source == '=?')
945end
946
947print"OK"
948
diff --git a/testes/errors.lua b/testes/errors.lua
new file mode 100644
index 00000000..63a7b740
--- /dev/null
+++ b/testes/errors.lua
@@ -0,0 +1,554 @@
1-- $Id: errors.lua,v 1.97 2017/11/28 15:31:56 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
70if not T then
71 (Message or print)
72 ('\n >>> testC not active: skipping memory message test <<<\n')
73else
74 print "testing memory error message"
75 local a = {}
76 for i = 1, 10000 do a[i] = true end -- preallocate array
77 collectgarbage()
78 T.totalmem(T.totalmem() + 10000)
79 -- force a memory error (by a small margin)
80 local st, msg = pcall(function()
81 for i = 1, 100000 do a[i] = tostring(i) end
82 end)
83 T.totalmem(0)
84 assert(not st and msg == "not enough" .. " memory")
85end
86
87
88-- tests for better error messages
89
90checkmessage("a = {} + 1", "arithmetic")
91checkmessage("a = {} | 1", "bitwise operation")
92checkmessage("a = {} < 1", "attempt to compare")
93checkmessage("a = {} <= 1", "attempt to compare")
94
95checkmessage("a=1; bbbb=2; a=math.sin(3)+bbbb(3)", "global 'bbbb'")
96checkmessage("a={}; do local a=1 end a:bbbb(3)", "method 'bbbb'")
97checkmessage("local a={}; a.bbbb(3)", "field 'bbbb'")
98assert(not string.find(doit"a={13}; local bbbb=1; a[bbbb](3)", "'bbbb'"))
99checkmessage("a={13}; local bbbb=1; a[bbbb](3)", "number")
100checkmessage("a=(1)..{}", "a table value")
101
102checkmessage("a = #print", "length of a function value")
103checkmessage("a = #3", "length of a number value")
104
105aaa = nil
106checkmessage("aaa.bbb:ddd(9)", "global 'aaa'")
107checkmessage("local aaa={bbb=1}; aaa.bbb:ddd(9)", "field 'bbb'")
108checkmessage("local aaa={bbb={}}; aaa.bbb:ddd(9)", "method 'ddd'")
109checkmessage("local a,b,c; (function () a = b+1.1 end)()", "upvalue 'b'")
110assert(not doit"local aaa={bbb={ddd=next}}; aaa.bbb:ddd(nil)")
111
112-- upvalues being indexed do not go to the stack
113checkmessage("local a,b,cc; (function () a = cc[1] end)()", "upvalue 'cc'")
114checkmessage("local a,b,cc; (function () a.x = 1 end)()", "upvalue 'a'")
115
116checkmessage("local _ENV = {x={}}; a = a + 1", "global 'a'")
117
118checkmessage("b=1; local aaa={}; x=aaa+b", "local 'aaa'")
119checkmessage("aaa={}; x=3.3/aaa", "global 'aaa'")
120checkmessage("aaa=2; b=nil;x=aaa*b", "global 'b'")
121checkmessage("aaa={}; x=-aaa", "global 'aaa'")
122
123-- short circuit
124checkmessage("a=1; local a,bbbb=2,3; a = math.sin(1) and bbbb(3)",
125 "local 'bbbb'")
126checkmessage("a=1; local a,bbbb=2,3; a = bbbb(1) or a(3)", "local 'bbbb'")
127checkmessage("local a,b,c,f = 1,1,1; f((a and b) or c)", "local 'f'")
128checkmessage("local a,b,c = 1,1,1; ((a and b) or c)()", "call a number value")
129assert(not string.find(doit"aaa={}; x=(aaa or aaa)+(aaa and aaa)", "'aaa'"))
130assert(not string.find(doit"aaa={}; (aaa or aaa)()", "'aaa'"))
131
132checkmessage("print(print < 10)", "function with number")
133checkmessage("print(print < print)", "two function values")
134checkmessage("print('10' < 10)", "string with number")
135checkmessage("print(10 < '23')", "number with string")
136
137-- float->integer conversions
138checkmessage("local a = 2.0^100; x = a << 2", "local a")
139checkmessage("local a = 1 >> 2.0^100", "has no integer representation")
140checkmessage("local a = 10.1 << 2.0^100", "has no integer representation")
141checkmessage("local a = 2.0^100 & 1", "has no integer representation")
142checkmessage("local a = 2.0^100 & 1e100", "has no integer representation")
143checkmessage("local a = 2.0 | 1e40", "has no integer representation")
144checkmessage("local a = 2e100 ~ 1", "has no integer representation")
145checkmessage("string.sub('a', 2.0^100)", "has no integer representation")
146checkmessage("string.rep('a', 3.3)", "has no integer representation")
147checkmessage("return 6e40 & 7", "has no integer representation")
148checkmessage("return 34 << 7e30", "has no integer representation")
149checkmessage("return ~-3e40", "has no integer representation")
150checkmessage("return ~-3.009", "has no integer representation")
151checkmessage("return 3.009 & 1", "has no integer representation")
152checkmessage("return 34 >> {}", "table value")
153checkmessage("a = 24 // 0", "divide by zero")
154checkmessage("a = 1 % 0", "'n%0'")
155
156
157-- passing light userdata instead of full userdata
158_G.D = debug
159checkmessage([[
160 -- create light udata
161 local x = D.upvalueid(function () return debug end, 1)
162 D.setuservalue(x, {})
163]], "light userdata")
164_G.D = nil
165
166do -- named objects (field '__name')
167 checkmessage("math.sin(io.input())", "(number expected, got FILE*)")
168 _G.XX = setmetatable({}, {__name = "My Type"})
169 assert(string.find(tostring(XX), "^My Type"))
170 checkmessage("io.input(XX)", "(FILE* expected, got My Type)")
171 checkmessage("return XX + 1", "on a My Type value")
172 checkmessage("return ~io.stdin", "on a FILE* value")
173 checkmessage("return XX < XX", "two My Type values")
174 checkmessage("return {} < XX", "table with My Type")
175 checkmessage("return XX < io.stdin", "My Type with FILE*")
176 _G.XX = nil
177end
178
179-- global functions
180checkmessage("(io.write or print){}", "io.write")
181checkmessage("(collectgarbage or print){}", "collectgarbage")
182
183-- errors in functions without debug info
184do
185 local f = function (a) return a + 1 end
186 f = assert(load(string.dump(f, true)))
187 assert(f(3) == 4)
188 checkerr("^%?:%-1:", f, {})
189
190 -- code with a move to a local var ('OP_MOV A B' with A<B)
191 f = function () local a; a = {}; return a + 2 end
192 -- no debug info (so that 'a' is unknown)
193 f = assert(load(string.dump(f, true)))
194 -- symbolic execution should not get lost
195 checkerr("^%?:%-1:.*table value", f)
196end
197
198
199-- tests for field accesses after RK limit
200local t = {}
201for i = 1, 1000 do
202 t[i] = "a = x" .. i
203end
204local s = table.concat(t, "; ")
205t = nil
206checkmessage(s.."; a = bbb + 1", "global 'bbb'")
207checkmessage("local _ENV=_ENV;"..s.."; a = bbb + 1", "global 'bbb'")
208checkmessage(s.."; local t = {}; a = t.bbb + 1", "field 'bbb'")
209checkmessage(s.."; local t = {}; t:bbb()", "method 'bbb'")
210
211checkmessage([[aaa=9
212repeat until 3==3
213local x=math.sin(math.cos(3))
214if math.sin(1) == x then return math.sin(1) end -- tail call
215local a,b = 1, {
216 {x='a'..'b'..'c', y='b', z=x},
217 {1,2,3,4,5} or 3+3<=3+3,
218 3+1>3+1,
219 {d = x and aaa[x or y]}}
220]], "global 'aaa'")
221
222checkmessage([[
223local x,y = {},1
224if math.sin(1) == 0 then return 3 end -- return
225x.a()]], "field 'a'")
226
227checkmessage([[
228prefix = nil
229insert = nil
230while 1 do
231 local a
232 if nil then break end
233 insert(prefix, a)
234end]], "global 'insert'")
235
236checkmessage([[ -- tail call
237 return math.sin("a")
238]], "'sin'")
239
240checkmessage([[collectgarbage("nooption")]], "invalid option")
241
242checkmessage([[x = print .. "a"]], "concatenate")
243checkmessage([[x = "a" .. false]], "concatenate")
244checkmessage([[x = {} .. 2]], "concatenate")
245
246checkmessage("getmetatable(io.stdin).__gc()", "no value")
247
248checkmessage([[
249local Var
250local function main()
251 NoSuchName (function() Var=0 end)
252end
253main()
254]], "global 'NoSuchName'")
255print'+'
256
257a = {}; setmetatable(a, {__index = string})
258checkmessage("a:sub()", "bad self")
259checkmessage("string.sub('a', {})", "#2")
260checkmessage("('a'):sub{}", "#1")
261
262checkmessage("table.sort({1,2,3}, table.sort)", "'table.sort'")
263checkmessage("string.gsub('s', 's', setmetatable)", "'setmetatable'")
264
265-- tests for errors in coroutines
266
267local function f (n)
268 local c = coroutine.create(f)
269 local a,b = coroutine.resume(c)
270 return b
271end
272assert(string.find(f(), "C stack overflow"))
273
274checkmessage("coroutine.yield()", "outside a coroutine")
275
276f = coroutine.wrap(function () table.sort({1,2,3}, coroutine.yield) end)
277checkerr("yield across", f)
278
279
280-- testing size of 'source' info; size of buffer for that info is
281-- LUA_IDSIZE, declared as 60 in luaconf. Get one position for '\0'.
282idsize = 60 - 1
283local function checksize (source)
284 -- syntax error
285 local _, msg = load("x", source)
286 msg = string.match(msg, "^([^:]*):") -- get source (1st part before ':')
287 assert(msg:len() <= idsize)
288end
289
290for i = 60 - 10, 60 + 10 do -- check border cases around 60
291 checksize("@" .. string.rep("x", i)) -- file names
292 checksize(string.rep("x", i - 10)) -- string sources
293 checksize("=" .. string.rep("x", i)) -- exact sources
294end
295
296
297-- testing line error
298
299local function lineerror (s, l)
300 local err,msg = pcall(load(s))
301 local line = string.match(msg, ":(%d+):")
302 assert((line and line+0) == l)
303end
304
305lineerror("local a\n for i=1,'a' do \n print(i) \n end", 2)
306lineerror("\n local a \n for k,v in 3 \n do \n print(k) \n end", 3)
307lineerror("\n\n for k,v in \n 3 \n do \n print(k) \n end", 4)
308lineerror("function a.x.y ()\na=a+1\nend", 1)
309
310lineerror("a = \na\n+\n{}", 3)
311lineerror("a = \n3\n+\n(\n4\n/\nprint)", 6)
312lineerror("a = \nprint\n+\n(\n4\n/\n7)", 3)
313
314lineerror("a\n=\n-\n\nprint\n;", 3)
315
316lineerror([[
317a
318(
31923)
320]], 1)
321
322lineerror([[
323local a = {x = 13}
324a
325.
326x
327(
32823
329)
330]], 2)
331
332lineerror([[
333local a = {x = 13}
334a
335.
336x
337(
33823 + a
339)
340]], 6)
341
342local p = [[
343 function g() f() end
344 function f(x) error('a', X) end
345g()
346]]
347X=3;lineerror((p), 3)
348X=0;lineerror((p), nil)
349X=1;lineerror((p), 2)
350X=2;lineerror((p), 1)
351
352
353if not _soft then
354 -- several tests that exaust the Lua stack
355 collectgarbage()
356 print"testing stack overflow"
357 C = 0
358 local l = debug.getinfo(1, "l").currentline; function y () C=C+1; y() end
359
360 local function checkstackmessage (m)
361 return (string.find(m, "stack overflow"))
362 end
363 -- repeated stack overflows (to check stack recovery)
364 assert(checkstackmessage(doit('y()')))
365 print('+')
366 assert(checkstackmessage(doit('y()')))
367 print('+')
368 assert(checkstackmessage(doit('y()')))
369 print('+')
370
371
372 -- error lines in stack overflow
373 C = 0
374 local l1
375 local function g(x)
376 l1 = debug.getinfo(x, "l").currentline; y()
377 end
378 local _, stackmsg = xpcall(g, debug.traceback, 1)
379 print('+')
380 local stack = {}
381 for line in string.gmatch(stackmsg, "[^\n]*") do
382 local curr = string.match(line, ":(%d+):")
383 if curr then table.insert(stack, tonumber(curr)) end
384 end
385 local i=1
386 while stack[i] ~= l1 do
387 assert(stack[i] == l)
388 i = i+1
389 end
390 assert(i > 15)
391
392
393 -- error in error handling
394 local res, msg = xpcall(error, error)
395 assert(not res and type(msg) == 'string')
396 print('+')
397
398 local function f (x)
399 if x==0 then error('a\n')
400 else
401 local aux = function () return f(x-1) end
402 local a,b = xpcall(aux, aux)
403 return a,b
404 end
405 end
406 f(3)
407
408 local function loop (x,y,z) return 1 + loop(x, y, z) end
409
410 local res, msg = xpcall(loop, function (m)
411 assert(string.find(m, "stack overflow"))
412 checkerr("error handling", loop)
413 assert(math.sin(0) == 0)
414 return 15
415 end)
416 assert(msg == 15)
417
418 local f = function ()
419 for i = 999900, 1000000, 1 do table.unpack({}, 1, i) end
420 end
421 checkerr("too many results", f)
422
423end
424
425
426do
427 -- non string messages
428 local t = {}
429 local res, msg = pcall(function () error(t) end)
430 assert(not res and msg == t)
431
432 res, msg = pcall(function () error(nil) end)
433 assert(not res and msg == nil)
434
435 local function f() error{msg='x'} end
436 res, msg = xpcall(f, function (r) return {msg=r.msg..'y'} end)
437 assert(msg.msg == 'xy')
438
439 -- 'assert' with extra arguments
440 res, msg = pcall(assert, false, "X", t)
441 assert(not res and msg == "X")
442
443 -- 'assert' with no message
444 res, msg = pcall(function () assert(false) end)
445 local line = string.match(msg, "%w+%.lua:(%d+): assertion failed!$")
446 assert(tonumber(line) == debug.getinfo(1, "l").currentline - 2)
447
448 -- 'assert' with non-string messages
449 res, msg = pcall(assert, false, t)
450 assert(not res and msg == t)
451
452 res, msg = pcall(assert, nil, nil)
453 assert(not res and msg == nil)
454
455 -- 'assert' without arguments
456 res, msg = pcall(assert)
457 assert(not res and string.find(msg, "value expected"))
458end
459
460-- xpcall with arguments
461a, b, c = xpcall(string.find, error, "alo", "al")
462assert(a and b == 1 and c == 2)
463a, b, c = xpcall(string.find, function (x) return {} end, true, "al")
464assert(not a and type(b) == "table" and c == nil)
465
466
467print("testing tokens in error messages")
468checksyntax("syntax error", "", "error", 1)
469checksyntax("1.000", "", "1.000", 1)
470checksyntax("[[a]]", "", "[[a]]", 1)
471checksyntax("'aa'", "", "'aa'", 1)
472checksyntax("while << do end", "", "<<", 1)
473checksyntax("for >> do end", "", ">>", 1)
474
475-- test invalid non-printable char in a chunk
476checksyntax("a\1a = 1", "", "<\\1>", 1)
477
478-- test 255 as first char in a chunk
479checksyntax("\255a = 1", "", "<\\255>", 1)
480
481doit('I = load("a=9+"); a=3')
482assert(a==3 and I == nil)
483print('+')
484
485lim = 1000
486if _soft then lim = 100 end
487for i=1,lim do
488 doit('a = ')
489 doit('a = 4+nil')
490end
491
492
493-- testing syntax limits
494
495local function testrep (init, rep, close, repc)
496 local s = init .. string.rep(rep, 100) .. close .. string.rep(repc, 100)
497 assert(load(s)) -- 100 levels is OK
498 s = init .. string.rep(rep, 10000)
499 local res, msg = load(s) -- 10000 levels not ok
500 assert(not res and (string.find(msg, "too many registers") or
501 string.find(msg, "stack overflow")))
502end
503
504testrep("local a; a", ",a", "= 1", ",1") -- multiple assignment
505testrep("local a; a=", "{", "0", "}")
506testrep("local a; a=", "(", "2", ")")
507testrep("local a; ", "a(", "2", ")")
508testrep("", "do ", "", " end")
509testrep("", "while a do ", "", " end")
510testrep("local a; ", "if a then else ", "", " end")
511testrep("", "function foo () ", "", " end")
512testrep("local a; a=", "a..", "a", "")
513testrep("local a; a=", "a^", "a", "")
514
515checkmessage("a = f(x" .. string.rep(",x", 260) .. ")", "too many registers")
516
517
518-- testing other limits
519
520-- upvalues
521local lim = 127
522local s = "local function fooA ()\n local "
523for j = 1,lim do
524 s = s.."a"..j..", "
525end
526s = s.."b,c\n"
527s = s.."local function fooB ()\n local "
528for j = 1,lim do
529 s = s.."b"..j..", "
530end
531s = s.."b\n"
532s = s.."function fooC () return b+c"
533local c = 1+2
534for j = 1,lim do
535 s = s.."+a"..j.."+b"..j
536 c = c + 2
537end
538s = s.."\nend end end"
539local a,b = load(s)
540assert(c > 255 and string.find(b, "too many upvalues") and
541 string.find(b, "line 5"))
542
543-- local variables
544s = "\nfunction foo ()\n local "
545for j = 1,300 do
546 s = s.."a"..j..", "
547end
548s = s.."b\n"
549local a,b = load(s)
550assert(string.find(b, "line 2") and string.find(b, "too many local variables"))
551
552mt.__index = oldmm
553
554print('OK')
diff --git a/testes/events.lua b/testes/events.lua
new file mode 100644
index 00000000..cf064d3d
--- /dev/null
+++ b/testes/events.lua
@@ -0,0 +1,476 @@
1-- $Id: events.lua,v 1.52 2018/03/12 13:51: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)
18_ENV["B"] = undef
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
73t.__index = c
74a[1] = 10; a[2] = 20; a[3] = 90;
75for i = 4, 20 do a[i] = i * 10 end
76assert(a[1] == 10 and a[2] == 20 and a[3] == 90)
77for i = 4, 20 do assert(a[i] == i * 10) end
78assert(next(a) == nil)
79
80
81do
82 local a;
83 a = setmetatable({}, {__index = setmetatable({},
84 {__index = setmetatable({},
85 {__index = function (_,n) return a[n-3]+4, "lixo" end})})})
86 a[0] = 20
87 for i=0,10 do
88 assert(a[i*3] == 20 + i*4)
89 end
90end
91
92
93do -- newindex
94 local foi
95 local a = {}
96 for i=1,10 do a[i] = 0; a['a'..i] = 0; end
97 setmetatable(a, {__newindex = function (t,k,v) foi=true; rawset(t,k,v) end})
98 foi = false; a[1]=0; assert(not foi)
99 foi = false; a['a1']=0; assert(not foi)
100 foi = false; a['a11']=0; assert(foi)
101 foi = false; a[11]=0; assert(foi)
102 foi = false; a[1]=undef; assert(not foi)
103 a[1] = undef
104 foi = false; a[1]=nil; assert(foi)
105end
106
107
108setmetatable(t, nil)
109function f (t, ...) return t, {...} end
110t.__call = f
111
112do
113 local x,y = a(table.unpack{'a', 1})
114 assert(x==a and y[1]=='a' and y[2]==1 and y[3]==undef)
115 x,y = a()
116 assert(x==a and y[1]==undef)
117end
118
119
120local b = setmetatable({}, t)
121setmetatable(b,t)
122
123function f(op)
124 return function (...) cap = {[0] = op, ...} ; return (...) end
125end
126t.__add = f("add")
127t.__sub = f("sub")
128t.__mul = f("mul")
129t.__div = f("div")
130t.__idiv = f("idiv")
131t.__mod = f("mod")
132t.__unm = f("unm")
133t.__pow = f("pow")
134t.__len = f("len")
135t.__band = f("band")
136t.__bor = f("bor")
137t.__bxor = f("bxor")
138t.__shl = f("shl")
139t.__shr = f("shr")
140t.__bnot = f("bnot")
141
142-- Some tests are done inside small anonymous functions to ensure
143-- that constants go to constant table even in debug compilation,
144-- when the constant table is very small.
145assert(b+5 == b)
146assert(cap[0] == "add" and cap[1] == b and cap[2] == 5 and cap[3]==undef)
147assert(b+'5' == b)
148assert(cap[0] == "add" and cap[1] == b and cap[2] == '5' and cap[3]==undef)
149assert(5+b == 5)
150assert(cap[0] == "add" and cap[1] == 5 and cap[2] == b and cap[3]==undef)
151assert('5'+b == '5')
152assert(cap[0] == "add" and cap[1] == '5' and cap[2] == b and cap[3]==undef)
153b=b-3; assert(getmetatable(b) == t)
154assert(cap[0] == "sub" and cap[1] == b and cap[2] == 3 and cap[3]==undef)
155assert(5-a == 5)
156assert(cap[0] == "sub" and cap[1] == 5 and cap[2] == a and cap[3]==undef)
157assert('5'-a == '5')
158assert(cap[0] == "sub" and cap[1] == '5' and cap[2] == a and cap[3]==undef)
159assert(a*a == a)
160assert(cap[0] == "mul" and cap[1] == a and cap[2] == a and cap[3]==undef)
161assert(a/0 == a)
162assert(cap[0] == "div" and cap[1] == a and cap[2] == 0 and cap[3]==undef)
163assert(a%2 == a)
164assert(cap[0] == "mod" and cap[1] == a and cap[2] == 2 and cap[3]==undef)
165assert(a // (1/0) == a)
166assert(cap[0] == "idiv" and cap[1] == a and cap[2] == 1/0 and cap[3]==undef)
167;(function () assert(a & "hi" == a) end)()
168assert(cap[0] == "band" and cap[1] == a and cap[2] == "hi" and cap[3]==undef)
169;(function () assert(10 & a == 10) end)()
170assert(cap[0] == "band" and cap[1] == 10 and cap[2] == a and cap[3]==undef)
171;(function () assert(a | 10 == a) end)()
172assert(cap[0] == "bor" and cap[1] == a and cap[2] == 10 and cap[3]==undef)
173assert(a | "hi" == a)
174assert(cap[0] == "bor" and cap[1] == a and cap[2] == "hi" and cap[3]==undef)
175assert("hi" ~ a == "hi")
176assert(cap[0] == "bxor" and cap[1] == "hi" and cap[2] == a and cap[3]==undef)
177;(function () assert(10 ~ a == 10) end)()
178assert(cap[0] == "bxor" and cap[1] == 10 and cap[2] == a and cap[3]==undef)
179assert(-a == a)
180assert(cap[0] == "unm" and cap[1] == a)
181assert(a^4 == a)
182assert(cap[0] == "pow" and cap[1] == a and cap[2] == 4 and cap[3]==undef)
183assert(a^'4' == a)
184assert(cap[0] == "pow" and cap[1] == a and cap[2] == '4' and cap[3]==undef)
185assert(4^a == 4)
186assert(cap[0] == "pow" and cap[1] == 4 and cap[2] == a and cap[3]==undef)
187assert('4'^a == '4')
188assert(cap[0] == "pow" and cap[1] == '4' and cap[2] == a and cap[3]==undef)
189assert(#a == a)
190assert(cap[0] == "len" and cap[1] == a)
191assert(~a == a)
192assert(cap[0] == "bnot" and cap[1] == a)
193assert(a << 3 == a)
194assert(cap[0] == "shl" and cap[1] == a and cap[2] == 3)
195assert(1.5 >> a == 1.5)
196assert(cap[0] == "shr" and cap[1] == 1.5 and cap[2] == a)
197
198
199-- test for rawlen
200t = setmetatable({1,2,3}, {__len = function () return 10 end})
201assert(#t == 10 and rawlen(t) == 3)
202assert(rawlen"abc" == 3)
203assert(not pcall(rawlen, io.stdin))
204assert(not pcall(rawlen, 34))
205assert(not pcall(rawlen))
206
207-- rawlen for long strings
208assert(rawlen(string.rep('a', 1000)) == 1000)
209
210
211t = {}
212t.__lt = function (a,b,c)
213 collectgarbage()
214 assert(c == nil)
215 if type(a) == 'table' then a = a.x end
216 if type(b) == 'table' then b = b.x end
217 return a<b, "dummy"
218end
219
220function Op(x) return setmetatable({x=x}, t) end
221
222local function test ()
223 assert(not(Op(1)<Op(1)) and (Op(1)<Op(2)) and not(Op(2)<Op(1)))
224 assert(not(1 < Op(1)) and (Op(1) < 2) and not(2 < Op(1)))
225 assert(not(Op('a')<Op('a')) and (Op('a')<Op('b')) and not(Op('b')<Op('a')))
226 assert(not('a' < Op('a')) and (Op('a') < 'b') and not(Op('b') < Op('a')))
227 assert((Op(1)<=Op(1)) and (Op(1)<=Op(2)) and not(Op(2)<=Op(1)))
228 assert((Op('a')<=Op('a')) and (Op('a')<=Op('b')) and not(Op('b')<=Op('a')))
229 assert(not(Op(1)>Op(1)) and not(Op(1)>Op(2)) and (Op(2)>Op(1)))
230 assert(not(Op('a')>Op('a')) and not(Op('a')>Op('b')) and (Op('b')>Op('a')))
231 assert((Op(1)>=Op(1)) and not(Op(1)>=Op(2)) and (Op(2)>=Op(1)))
232 assert((1 >= Op(1)) and not(1 >= Op(2)) and (Op(2) >= 1))
233 assert((Op('a')>=Op('a')) and not(Op('a')>=Op('b')) and (Op('b')>=Op('a')))
234 assert(('a' >= Op('a')) and not(Op('a') >= 'b') and (Op('b') >= Op('a')))
235end
236
237test()
238
239t.__le = function (a,b,c)
240 assert(c == nil)
241 if type(a) == 'table' then a = a.x end
242 if type(b) == 'table' then b = b.x end
243 return a<=b, "dummy"
244end
245
246test() -- retest comparisons, now using both `lt' and `le'
247
248
249-- test `partial order'
250
251local function rawSet(x)
252 local y = {}
253 for _,k in pairs(x) do y[k] = 1 end
254 return y
255end
256
257local function Set(x)
258 return setmetatable(rawSet(x), t)
259end
260
261t.__lt = function (a,b)
262 for k in pairs(a) do
263 if not b[k] then return false end
264 b[k] = undef
265 end
266 return next(b) ~= nil
267end
268
269t.__le = nil
270
271assert(Set{1,2,3} < Set{1,2,3,4})
272assert(not(Set{1,2,3,4} < Set{1,2,3,4}))
273assert((Set{1,2,3,4} <= Set{1,2,3,4}))
274assert((Set{1,2,3,4} >= Set{1,2,3,4}))
275assert((Set{1,3} <= Set{3,5})) -- wrong!! model needs a `le' method ;-)
276
277t.__le = function (a,b)
278 for k in pairs(a) do
279 if not b[k] then return false end
280 end
281 return true
282end
283
284assert(not (Set{1,3} <= Set{3,5})) -- now its OK!
285assert(not(Set{1,3} <= Set{3,5}))
286assert(not(Set{1,3} >= Set{3,5}))
287
288t.__eq = function (a,b)
289 for k in pairs(a) do
290 if not b[k] then return false end
291 b[k] = undef
292 end
293 return next(b) == nil
294end
295
296local s = Set{1,3,5}
297assert(s == Set{3,5,1})
298assert(not rawequal(s, Set{3,5,1}))
299assert(rawequal(s, s))
300assert(Set{1,3,5,1} == rawSet{3,5,1})
301assert(rawSet{1,3,5,1} == Set{3,5,1})
302assert(Set{1,3,5} ~= Set{3,5,1,6})
303
304-- '__eq' is not used for table accesses
305t[Set{1,3,5}] = 1
306assert(t[Set{1,3,5}] == undef)
307
308
309if not T then
310 (Message or print)('\n >>> testC not active: skipping tests for \z
311userdata <<<\n')
312else
313 local u1 = T.newuserdata(0, 1)
314 local u2 = T.newuserdata(0, 1)
315 local u3 = T.newuserdata(0, 1)
316 assert(u1 ~= u2 and u1 ~= u3)
317 debug.setuservalue(u1, 1);
318 debug.setuservalue(u2, 2);
319 debug.setuservalue(u3, 1);
320 debug.setmetatable(u1, {__eq = function (a, b)
321 return debug.getuservalue(a) == debug.getuservalue(b)
322 end})
323 debug.setmetatable(u2, {__eq = function (a, b)
324 return true
325 end})
326 assert(u1 == u3 and u3 == u1 and u1 ~= u2)
327 assert(u2 == u1 and u2 == u3 and u3 == u2)
328 assert(u2 ~= {}) -- different types cannot be equal
329
330 local mirror = {}
331 debug.setmetatable(u3, {__index = mirror, __newindex = mirror})
332 for i = 1, 10 do u3[i] = i end
333 for i = 1, 10 do assert(u3[i] == i) end
334end
335
336
337t.__concat = function (a,b,c)
338 assert(c == nil)
339 if type(a) == 'table' then a = a.val end
340 if type(b) == 'table' then b = b.val end
341 if A then return a..b
342 else
343 return setmetatable({val=a..b}, t)
344 end
345end
346
347c = {val="c"}; setmetatable(c, t)
348d = {val="d"}; setmetatable(d, t)
349
350A = true
351assert(c..d == 'cd')
352assert(0 .."a".."b"..c..d.."e".."f"..(5+3).."g" == "0abcdef8g")
353
354A = false
355assert((c..d..c..d).val == 'cdcd')
356x = c..d
357assert(getmetatable(x) == t and x.val == 'cd')
358x = 0 .."a".."b"..c..d.."e".."f".."g"
359assert(x.val == "0abcdefg")
360
361
362-- concat metamethod x numbers (bug in 5.1.1)
363c = {}
364local x
365setmetatable(c, {__concat = function (a,b)
366 assert(type(a) == "number" and b == c or type(b) == "number" and a == c)
367 return c
368end})
369assert(c..5 == c and 5 .. c == c)
370assert(4 .. c .. 5 == c and 4 .. 5 .. 6 .. 7 .. c == c)
371
372
373-- test comparison compatibilities
374local t1, t2, c, d
375t1 = {}; c = {}; setmetatable(c, t1)
376d = {}
377t1.__eq = function () return true end
378t1.__lt = function () return true end
379setmetatable(d, t1)
380assert(c == d and c < d and not(d <= c))
381t2 = {}
382t2.__eq = t1.__eq
383t2.__lt = t1.__lt
384setmetatable(d, t2)
385assert(c == d and c < d and not(d <= c))
386
387
388
389-- test for several levels of calls
390local i
391local tt = {
392 __call = function (t, ...)
393 i = i+1
394 if t.f then return t.f(...)
395 else return {...}
396 end
397 end
398}
399
400local a = setmetatable({}, tt)
401local b = setmetatable({f=a}, tt)
402local c = setmetatable({f=b}, tt)
403
404i = 0
405x = c(3,4,5)
406assert(i == 3 and x[1] == 3 and x[3] == 5)
407
408
409assert(_G.X == 20)
410
411print'+'
412
413local _g = _G
414_ENV = setmetatable({}, {__index=function (_,k) return _g[k] end})
415
416
417a = {}
418rawset(a, "x", 1, 2, 3)
419assert(a.x == 1 and rawget(a, "x", 3) == 1)
420
421print '+'
422
423-- testing metatables for basic types
424mt = {__index = function (a,b) return a+b end,
425 __len = function (x) return math.floor(x) end}
426debug.setmetatable(10, mt)
427assert(getmetatable(-2) == mt)
428assert((10)[3] == 13)
429assert((10)["3"] == 13)
430assert(#3.45 == 3)
431debug.setmetatable(23, nil)
432assert(getmetatable(-2) == nil)
433
434debug.setmetatable(true, mt)
435assert(getmetatable(false) == mt)
436mt.__index = function (a,b) return a or b end
437assert((true)[false] == true)
438assert((false)[false] == false)
439debug.setmetatable(false, nil)
440assert(getmetatable(true) == nil)
441
442debug.setmetatable(nil, mt)
443assert(getmetatable(nil) == mt)
444mt.__add = function (a,b) return (a or 1) + (b or 2) end
445assert(10 + nil == 12)
446assert(nil + 23 == 24)
447assert(nil + nil == 3)
448debug.setmetatable(nil, nil)
449assert(getmetatable(nil) == nil)
450
451debug.setmetatable(nil, {})
452
453
454-- loops in delegation
455a = {}; setmetatable(a, a); a.__index = a; a.__newindex = a
456assert(not pcall(function (a,b) return a[b] end, a, 10))
457assert(not pcall(function (a,b,c) a[b] = c end, a, 10, true))
458
459-- bug in 5.1
460T, K, V = nil
461grandparent = {}
462grandparent.__newindex = function(t,k,v) T=t; K=k; V=v end
463
464parent = {}
465parent.__newindex = parent
466setmetatable(parent, grandparent)
467
468child = setmetatable({}, parent)
469child.foo = 10 --> CRASH (on some machines)
470assert(T == parent and K == "foo" and V == 10)
471
472print 'OK'
473
474return 12
475
476
diff --git a/testes/files.lua b/testes/files.lua
new file mode 100644
index 00000000..b2c7c202
--- /dev/null
+++ b/testes/files.lua
@@ -0,0 +1,832 @@
1-- $Id: files.lua,v 1.101 2018/03/12 13:51:02 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-- cannot call close method without an argument (new in 5.3.5)
32checkerr("got no value", io.stdin.close)
33
34
35assert(type(io.input()) == "userdata" and io.type(io.output()) == "file")
36assert(type(io.stdin) == "userdata" and io.type(io.stderr) == "file")
37assert(not io.type(8))
38local a = {}; setmetatable(a, {})
39assert(not io.type(a))
40
41assert(getmetatable(io.input()).__name == "FILE*")
42
43local a,b,c = io.open('xuxu_nao_existe')
44assert(not a and type(b) == "string" and type(c) == "number")
45
46a,b,c = io.open('/a/b/c/d', 'w')
47assert(not a and type(b) == "string" and type(c) == "number")
48
49local file = os.tmpname()
50local f, msg = io.open(file, "w")
51if not f then
52 (Message or print)("'os.tmpname' file cannot be open; skipping file tests")
53
54else --{ most tests here need tmpname
55f:close()
56
57print('testing i/o')
58
59local otherfile = os.tmpname()
60
61checkerr("invalid mode", io.open, file, "rw")
62checkerr("invalid mode", io.open, file, "rb+")
63checkerr("invalid mode", io.open, file, "r+bk")
64checkerr("invalid mode", io.open, file, "")
65checkerr("invalid mode", io.open, file, "+")
66checkerr("invalid mode", io.open, file, "b")
67assert(io.open(file, "r+b")):close()
68assert(io.open(file, "r+")):close()
69assert(io.open(file, "rb")):close()
70
71assert(os.setlocale('C', 'all'))
72
73io.input(io.stdin); io.output(io.stdout);
74
75os.remove(file)
76assert(not loadfile(file))
77checkerr("", dofile, file)
78assert(not io.open(file))
79io.output(file)
80assert(io.output() ~= io.stdout)
81
82if not _port then -- invalid seek
83 local status, msg, code = io.stdin:seek("set", 1000)
84 assert(not status and type(msg) == "string" and type(code) == "number")
85end
86
87assert(io.output():seek() == 0)
88assert(io.write("alo alo"):seek() == string.len("alo alo"))
89assert(io.output():seek("cur", -3) == string.len("alo alo")-3)
90assert(io.write("joao"))
91assert(io.output():seek("end") == string.len("alo joao"))
92
93assert(io.output():seek("set") == 0)
94
95assert(io.write('"álo"', "{a}\n", "second line\n", "third line \n"))
96assert(io.write('çfourth_line'))
97io.output(io.stdout)
98collectgarbage() -- file should be closed by GC
99assert(io.input() == io.stdin and rawequal(io.output(), io.stdout))
100print('+')
101
102-- test GC for files
103collectgarbage()
104for i=1,120 do
105 for i=1,5 do
106 io.input(file)
107 assert(io.open(file, 'r'))
108 io.lines(file)
109 end
110 collectgarbage()
111end
112
113io.input():close()
114io.close()
115
116assert(os.rename(file, otherfile))
117assert(not os.rename(file, otherfile))
118
119io.output(io.open(otherfile, "ab"))
120assert(io.write("\n\n\t\t ", 3450, "\n"));
121io.close()
122
123-- test writing/reading numbers
124f = assert(io.open(file, "w"))
125f:write(maxint, '\n')
126f:write(string.format("0X%x\n", maxint))
127f:write("0xABCp-3", '\n')
128f:write(0, '\n')
129f:write(-maxint, '\n')
130f:write(string.format("0x%X\n", -maxint))
131f:write("-0xABCp-3", '\n')
132assert(f:close())
133f = assert(io.open(file, "r"))
134assert(f:read("n") == maxint)
135assert(f:read("n") == maxint)
136assert(f:read("n") == 0xABCp-3)
137assert(f:read("n") == 0)
138assert(f:read("*n") == -maxint) -- test old format (with '*')
139assert(f:read("n") == -maxint)
140assert(f:read("*n") == -0xABCp-3) -- test old format (with '*')
141assert(f:close())
142assert(os.remove(file))
143
144
145-- testing multiple arguments to io.read
146do
147 local f = assert(io.open(file, "w"))
148 f:write[[
149a line
150another line
1511234
1523.45
153one
154two
155three
156]]
157 local l1, l2, l3, l4, n1, n2, c, dummy
158 assert(f:close())
159 f = assert(io.open(file, "r"))
160 l1, l2, n1, n2, dummy = f:read("l", "L", "n", "n")
161 assert(l1 == "a line" and l2 == "another line\n" and
162 n1 == 1234 and n2 == 3.45 and dummy == nil)
163 assert(f:close())
164 f = assert(io.open(file, "r"))
165 l1, l2, n1, n2, c, l3, l4, dummy = f:read(7, "l", "n", "n", 1, "l", "l")
166 assert(l1 == "a line\n" and l2 == "another line" and c == '\n' and
167 n1 == 1234 and n2 == 3.45 and l3 == "one" and l4 == "two"
168 and dummy == nil)
169 assert(f:close())
170 f = assert(io.open(file, "r"))
171 -- second item failing
172 l1, n1, n2, dummy = f:read("l", "n", "n", "l")
173 assert(l1 == "a line" and n1 == nil)
174 assert(f:close())
175 assert(os.remove(file))
176end
177
178
179
180-- test yielding during 'dofile'
181f = assert(io.open(file, "w"))
182f:write[[
183local x, z = coroutine.yield(10)
184local y = coroutine.yield(20)
185return x + y * z
186]]
187assert(f:close())
188f = coroutine.wrap(dofile)
189assert(f(file) == 10)
190print(f(100, 101) == 20)
191assert(f(200) == 100 + 200 * 101)
192assert(os.remove(file))
193
194
195f = assert(io.open(file, "w"))
196-- test number termination
197f:write[[
198-12.3- -0xffff+ .3|5.E-3X +234e+13E 0xDEADBEEFDEADBEEFx
1990x1.13Ap+3e
200]]
201-- very long number
202f:write("1234"); for i = 1, 1000 do f:write("0") end; f:write("\n")
203-- invalid sequences (must read and discard valid prefixes)
204f:write[[
205.e+ 0.e; --; 0xX;
206]]
207assert(f:close())
208f = assert(io.open(file, "r"))
209assert(f:read("n") == -12.3); assert(f:read(1) == "-")
210assert(f:read("n") == -0xffff); assert(f:read(2) == "+ ")
211assert(f:read("n") == 0.3); assert(f:read(1) == "|")
212assert(f:read("n") == 5e-3); assert(f:read(1) == "X")
213assert(f:read("n") == 234e13); assert(f:read(1) == "E")
214assert(f:read("n") == 0Xdeadbeefdeadbeef); assert(f:read(2) == "x\n")
215assert(f:read("n") == 0x1.13aP3); assert(f:read(1) == "e")
216
217do -- attempt to read too long number
218 assert(f:read("n") == nil) -- fails
219 local s = f:read("L") -- read rest of line
220 assert(string.find(s, "^00*\n$")) -- lots of 0's left
221end
222
223assert(not f:read("n")); assert(f:read(2) == "e+")
224assert(not f:read("n")); assert(f:read(1) == ";")
225assert(not f:read("n")); assert(f:read(2) == "-;")
226assert(not f:read("n")); assert(f:read(1) == "X")
227assert(not f:read("n")); assert(f:read(1) == ";")
228assert(not f:read("n")); assert(not f:read(0)) -- end of file
229assert(f:close())
230assert(os.remove(file))
231
232
233-- test line generators
234assert(not pcall(io.lines, "non-existent-file"))
235assert(os.rename(otherfile, file))
236io.output(otherfile)
237local n = 0
238local f = io.lines(file)
239while f() do n = n + 1 end;
240assert(n == 6) -- number of lines in the file
241checkerr("file is already closed", f)
242checkerr("file is already closed", f)
243-- copy from file to otherfile
244n = 0
245for l in io.lines(file) do io.write(l, "\n"); n = n + 1 end
246io.close()
247assert(n == 6)
248-- copy from otherfile back to file
249local f = assert(io.open(otherfile))
250assert(io.type(f) == "file")
251io.output(file)
252assert(not io.output():read())
253n = 0
254for l in f:lines() do io.write(l, "\n"); n = n + 1 end
255assert(tostring(f):sub(1, 5) == "file ")
256assert(f:close()); io.close()
257assert(n == 6)
258checkerr("closed file", io.close, f)
259assert(tostring(f) == "file (closed)")
260assert(io.type(f) == "closed file")
261io.input(file)
262f = io.open(otherfile):lines()
263n = 0
264for l in io.lines() do assert(l == f()); n = n + 1 end
265f = nil; collectgarbage()
266assert(n == 6)
267assert(os.remove(otherfile))
268
269do -- bug in 5.3.1
270 io.output(otherfile)
271 io.write(string.rep("a", 300), "\n")
272 io.close()
273 local t ={}; for i = 1, 250 do t[i] = 1 end
274 t = {io.lines(otherfile, table.unpack(t))()}
275 -- everything ok here
276 assert(#t == 250 and t[1] == 'a' and t[#t] == 'a')
277 t[#t + 1] = 1 -- one too many
278 checkerr("too many arguments", io.lines, otherfile, table.unpack(t))
279 collectgarbage() -- ensure 'otherfile' is closed
280 assert(os.remove(otherfile))
281end
282
283io.input(file)
284do -- test error returns
285 local a,b,c = io.input():write("xuxu")
286 assert(not a and type(b) == "string" and type(c) == "number")
287end
288checkerr("invalid format", io.read, "x")
289assert(io.read(0) == "") -- not eof
290assert(io.read(5, 'l') == '"álo"')
291assert(io.read(0) == "")
292assert(io.read() == "second line")
293local x = io.input():seek()
294assert(io.read() == "third line ")
295assert(io.input():seek("set", x))
296assert(io.read('L') == "third line \n")
297assert(io.read(1) == "ç")
298assert(io.read(string.len"fourth_line") == "fourth_line")
299assert(io.input():seek("cur", -string.len"fourth_line"))
300assert(io.read() == "fourth_line")
301assert(io.read() == "") -- empty line
302assert(io.read('n') == 3450)
303assert(io.read(1) == '\n')
304assert(io.read(0) == nil) -- end of file
305assert(io.read(1) == nil) -- end of file
306assert(io.read(30000) == nil) -- end of file
307assert(({io.read(1)})[2] == undef)
308assert(io.read() == nil) -- end of file
309assert(({io.read()})[2] == undef)
310assert(io.read('n') == nil) -- end of file
311assert(({io.read('n')})[2] == undef)
312assert(io.read('a') == '') -- end of file (OK for 'a')
313assert(io.read('a') == '') -- end of file (OK for 'a')
314collectgarbage()
315print('+')
316io.close(io.input())
317checkerr(" input file is closed", io.read)
318
319assert(os.remove(file))
320
321local t = '0123456789'
322for i=1,10 do t = t..t; end
323assert(string.len(t) == 10*2^10)
324
325io.output(file)
326io.write("alo"):write("\n")
327io.close()
328checkerr(" output file is closed", io.write)
329local f = io.open(file, "a+b")
330io.output(f)
331collectgarbage()
332
333assert(io.write(' ' .. t .. ' '))
334assert(io.write(';', 'end of file\n'))
335f:flush(); io.flush()
336f:close()
337print('+')
338
339io.input(file)
340assert(io.read() == "alo")
341assert(io.read(1) == ' ')
342assert(io.read(string.len(t)) == t)
343assert(io.read(1) == ' ')
344assert(io.read(0))
345assert(io.read('a') == ';end of file\n')
346assert(io.read(0) == nil)
347assert(io.close(io.input()))
348
349
350-- test errors in read/write
351do
352 local function ismsg (m)
353 -- error message is not a code number
354 return (type(m) == "string" and tonumber(m) == nil)
355 end
356
357 -- read
358 local f = io.open(file, "w")
359 local r, m, c = f:read()
360 assert(not r and ismsg(m) and type(c) == "number")
361 assert(f:close())
362 -- write
363 f = io.open(file, "r")
364 r, m, c = f:write("whatever")
365 assert(not r and ismsg(m) and type(c) == "number")
366 assert(f:close())
367 -- lines
368 f = io.open(file, "w")
369 r, m = pcall(f:lines())
370 assert(r == false and ismsg(m))
371 assert(f:close())
372end
373
374assert(os.remove(file))
375
376-- test for L format
377io.output(file); io.write"\n\nline\nother":close()
378io.input(file)
379assert(io.read"L" == "\n")
380assert(io.read"L" == "\n")
381assert(io.read"L" == "line\n")
382assert(io.read"L" == "other")
383assert(io.read"L" == nil)
384io.input():close()
385
386local f = assert(io.open(file))
387local s = ""
388for l in f:lines("L") do s = s .. l end
389assert(s == "\n\nline\nother")
390f:close()
391
392io.input(file)
393s = ""
394for l in io.lines(nil, "L") do s = s .. l end
395assert(s == "\n\nline\nother")
396io.input():close()
397
398s = ""
399for l in io.lines(file, "L") do s = s .. l end
400assert(s == "\n\nline\nother")
401
402s = ""
403for l in io.lines(file, "l") do s = s .. l end
404assert(s == "lineother")
405
406io.output(file); io.write"a = 10 + 34\na = 2*a\na = -a\n":close()
407local t = {}
408assert(load(io.lines(file, "L"), nil, nil, t))()
409assert(t.a == -((10 + 34) * 2))
410
411
412-- test for multipe arguments in 'lines'
413io.output(file); io.write"0123456789\n":close()
414for a,b in io.lines(file, 1, 1) do
415 if a == "\n" then assert(b == nil)
416 else assert(tonumber(a) == tonumber(b) - 1)
417 end
418end
419
420for a,b,c in io.lines(file, 1, 2, "a") do
421 assert(a == "0" and b == "12" and c == "3456789\n")
422end
423
424for a,b,c in io.lines(file, "a", 0, 1) do
425 if a == "" then break end
426 assert(a == "0123456789\n" and b == nil and c == nil)
427end
428collectgarbage() -- to close file in previous iteration
429
430io.output(file); io.write"00\n10\n20\n30\n40\n":close()
431for a, b in io.lines(file, "n", "n") do
432 if a == 40 then assert(b == nil)
433 else assert(a == b - 10)
434 end
435end
436
437
438-- test load x lines
439io.output(file);
440io.write[[
441local y
442= X
443X =
444X *
4452 +
446X;
447X =
448X
449- y;
450]]:close()
451_G.X = 1
452assert(not load(io.lines(file)))
453collectgarbage() -- to close file in previous iteration
454load(io.lines(file, "L"))()
455assert(_G.X == 2)
456load(io.lines(file, 1))()
457assert(_G.X == 4)
458load(io.lines(file, 3))()
459assert(_G.X == 8)
460
461print('+')
462
463local x1 = "string\n\n\\com \"\"''coisas [[estranhas]] ]]'"
464io.output(file)
465assert(io.write(string.format("x2 = %q\n-- comment without ending EOS", x1)))
466io.close()
467assert(loadfile(file))()
468assert(x1 == x2)
469print('+')
470assert(os.remove(file))
471assert(not os.remove(file))
472assert(not os.remove(otherfile))
473
474-- testing loadfile
475local function testloadfile (s, expres)
476 io.output(file)
477 if s then io.write(s) end
478 io.close()
479 local res = assert(loadfile(file))()
480 assert(os.remove(file))
481 assert(res == expres)
482end
483
484-- loading empty file
485testloadfile(nil, nil)
486
487-- loading file with initial comment without end of line
488testloadfile("# a non-ending comment", nil)
489
490
491-- checking Unicode BOM in files
492testloadfile("\xEF\xBB\xBF# some comment\nreturn 234", 234)
493testloadfile("\xEF\xBB\xBFreturn 239", 239)
494testloadfile("\xEF\xBB\xBF", nil) -- empty file with a BOM
495
496
497-- checking line numbers in files with initial comments
498testloadfile("# a comment\nreturn require'debug'.getinfo(1).currentline", 2)
499
500
501-- loading binary file
502io.output(io.open(file, "wb"))
503assert(io.write(string.dump(function () return 10, '\0alo\255', 'hi' end)))
504io.close()
505a, b, c = assert(loadfile(file))()
506assert(a == 10 and b == "\0alo\255" and c == "hi")
507assert(os.remove(file))
508
509-- bug in 5.2.1
510do
511 io.output(io.open(file, "wb"))
512 -- save function with no upvalues
513 assert(io.write(string.dump(function () return 1 end)))
514 io.close()
515 f = assert(loadfile(file, "b", {}))
516 assert(type(f) == "function" and f() == 1)
517 assert(os.remove(file))
518end
519
520-- loading binary file with initial comment
521io.output(io.open(file, "wb"))
522assert(io.write("#this is a comment for a binary file\0\n",
523 string.dump(function () return 20, '\0\0\0' end)))
524io.close()
525a, b, c = assert(loadfile(file))()
526assert(a == 20 and b == "\0\0\0" and c == nil)
527assert(os.remove(file))
528
529
530-- 'loadfile' with 'env'
531do
532 local f = io.open(file, 'w')
533 f:write[[
534 if (...) then a = 15; return b, c, d
535 else return _ENV
536 end
537 ]]
538 f:close()
539 local t = {b = 12, c = "xuxu", d = print}
540 local f = assert(loadfile(file, 't', t))
541 local b, c, d = f(1)
542 assert(t.a == 15 and b == 12 and c == t.c and d == print)
543 assert(f() == t)
544 f = assert(loadfile(file, 't', nil))
545 assert(f() == nil)
546 f = assert(loadfile(file))
547 assert(f() == _G)
548 assert(os.remove(file))
549end
550
551
552-- 'loadfile' x modes
553do
554 io.open(file, 'w'):write("return 10"):close()
555 local s, m = loadfile(file, 'b')
556 assert(not s and string.find(m, "a text chunk"))
557 io.open(file, 'w'):write("\27 return 10"):close()
558 local s, m = loadfile(file, 't')
559 assert(not s and string.find(m, "a binary chunk"))
560 assert(os.remove(file))
561end
562
563
564io.output(file)
565assert(io.write("qualquer coisa\n"))
566assert(io.write("mais qualquer coisa"))
567io.close()
568assert(io.output(assert(io.open(otherfile, 'wb')))
569 :write("outra coisa\0\1\3\0\0\0\0\255\0")
570 :close())
571
572local filehandle = assert(io.open(file, 'r+'))
573local otherfilehandle = assert(io.open(otherfile, 'rb'))
574assert(filehandle ~= otherfilehandle)
575assert(type(filehandle) == "userdata")
576assert(filehandle:read('l') == "qualquer coisa")
577io.input(otherfilehandle)
578assert(io.read(string.len"outra coisa") == "outra coisa")
579assert(filehandle:read('l') == "mais qualquer coisa")
580filehandle:close();
581assert(type(filehandle) == "userdata")
582io.input(otherfilehandle)
583assert(io.read(4) == "\0\1\3\0")
584assert(io.read(3) == "\0\0\0")
585assert(io.read(0) == "") -- 255 is not eof
586assert(io.read(1) == "\255")
587assert(io.read('a') == "\0")
588assert(not io.read(0))
589assert(otherfilehandle == io.input())
590otherfilehandle:close()
591assert(os.remove(file))
592assert(os.remove(otherfile))
593collectgarbage()
594
595io.output(file)
596 :write[[
597 123.4 -56e-2 not a number
598second line
599third line
600
601and the rest of the file
602]]
603 :close()
604io.input(file)
605local _,a,b,c,d,e,h,__ = io.read(1, 'n', 'n', 'l', 'l', 'l', 'a', 10)
606assert(io.close(io.input()))
607assert(_ == ' ' and __ == nil)
608assert(type(a) == 'number' and a==123.4 and b==-56e-2)
609assert(d=='second line' and e=='third line')
610assert(h==[[
611
612and the rest of the file
613]])
614assert(os.remove(file))
615collectgarbage()
616
617-- testing buffers
618do
619 local f = assert(io.open(file, "w"))
620 local fr = assert(io.open(file, "r"))
621 assert(f:setvbuf("full", 2000))
622 f:write("x")
623 assert(fr:read("all") == "") -- full buffer; output not written yet
624 f:close()
625 fr:seek("set")
626 assert(fr:read("all") == "x") -- `close' flushes it
627 f = assert(io.open(file), "w")
628 assert(f:setvbuf("no"))
629 f:write("x")
630 fr:seek("set")
631 assert(fr:read("all") == "x") -- no buffer; output is ready
632 f:close()
633 f = assert(io.open(file, "a"))
634 assert(f:setvbuf("line"))
635 f:write("x")
636 fr:seek("set", 1)
637 assert(fr:read("all") == "") -- line buffer; no output without `\n'
638 f:write("a\n"):seek("set", 1)
639 assert(fr:read("all") == "xa\n") -- now we have a whole line
640 f:close(); fr:close()
641 assert(os.remove(file))
642end
643
644
645if not _soft then
646 print("testing large files (> BUFSIZ)")
647 io.output(file)
648 for i=1,5001 do io.write('0123456789123') end
649 io.write('\n12346'):close()
650 io.input(file)
651 local x = io.read('a')
652 io.input():seek('set', 0)
653 local y = io.read(30001)..io.read(1005)..io.read(0)..
654 io.read(1)..io.read(100003)
655 assert(x == y and string.len(x) == 5001*13 + 6)
656 io.input():seek('set', 0)
657 y = io.read() -- huge line
658 assert(x == y..'\n'..io.read())
659 assert(io.read() == nil)
660 io.close(io.input())
661 assert(os.remove(file))
662 x = nil; y = nil
663end
664
665if not _port then
666 local progname
667 do -- get name of running executable
668 local arg = arg or ARG
669 local i = 0
670 while arg[i] do i = i - 1 end
671 progname = '"' .. arg[i + 1] .. '"'
672 end
673 print("testing popen/pclose and execute")
674 local tests = {
675 -- command, what, code
676 {"ls > /dev/null", "ok"},
677 {"not-to-be-found-command", "exit"},
678 {"exit 3", "exit", 3},
679 {"exit 129", "exit", 129},
680 {"kill -s HUP $$", "signal", 1},
681 {"kill -s KILL $$", "signal", 9},
682 {"sh -c 'kill -s HUP $$'", "exit"},
683 {progname .. ' -e " "', "ok"},
684 {progname .. ' -e "os.exit(0, true)"', "ok"},
685 {progname .. ' -e "os.exit(20, true)"', "exit", 20},
686 }
687 print("\n(some error messages are expected now)")
688 for _, v in ipairs(tests) do
689 local x, y, z = io.popen(v[1]):close()
690 local x1, y1, z1 = os.execute(v[1])
691 assert(x == x1 and y == y1 and z == z1)
692 if v[2] == "ok" then
693 assert(x and y == 'exit' and z == 0)
694 else
695 assert(not x and y == v[2]) -- correct status and 'what'
696 -- correct code if known (but always different from 0)
697 assert((v[3] == nil and z > 0) or v[3] == z)
698 end
699 end
700end
701
702
703-- testing tmpfile
704f = io.tmpfile()
705assert(io.type(f) == "file")
706f:write("alo")
707f:seek("set")
708assert(f:read"a" == "alo")
709
710end --}
711
712print'+'
713
714print("testing date/time")
715
716assert(os.date("") == "")
717assert(os.date("!") == "")
718assert(os.date("\0\0") == "\0\0")
719assert(os.date("!\0\0") == "\0\0")
720local x = string.rep("a", 10000)
721assert(os.date(x) == x)
722local t = os.time()
723D = os.date("*t", t)
724assert(os.date(string.rep("%d", 1000), t) ==
725 string.rep(os.date("%d", t), 1000))
726assert(os.date(string.rep("%", 200)) == string.rep("%", 100))
727
728local t = os.time()
729D = os.date("*t", t)
730load(os.date([[assert(D.year==%Y and D.month==%m and D.day==%d and
731 D.hour==%H and D.min==%M and D.sec==%S and
732 D.wday==%w+1 and D.yday==%j and type(D.isdst) == 'boolean')]], t))()
733
734checkerr("invalid conversion specifier", os.date, "%")
735checkerr("invalid conversion specifier", os.date, "%9")
736checkerr("invalid conversion specifier", os.date, "%")
737checkerr("invalid conversion specifier", os.date, "%O")
738checkerr("invalid conversion specifier", os.date, "%E")
739checkerr("invalid conversion specifier", os.date, "%Ea")
740
741checkerr("not an integer", os.time, {year=1000, month=1, day=1, hour='x'})
742checkerr("not an integer", os.time, {year=1000, month=1, day=1, hour=1.5})
743
744checkerr("missing", os.time, {hour = 12}) -- missing date
745
746if not _port then
747 -- test Posix-specific modifiers
748 assert(type(os.date("%Ex")) == 'string')
749 assert(type(os.date("%Oy")) == 'string')
750
751
752 -- test out-of-range dates (at least for Unix)
753 if maxint >= 2^62 then -- cannot do these tests in Small Lua
754 -- no arith overflows
755 checkerr("out-of-bound", os.time, {year = -maxint, month = 1, day = 1})
756 if string.packsize("i") == 4 then -- 4-byte ints
757 if testerr("out-of-bound", os.date, "%Y", 2^40) then
758 -- time_t has 4 bytes and therefore cannot represent year 4000
759 print(" 4-byte time_t")
760 checkerr("cannot be represented", os.time, {year=4000, month=1, day=1})
761 else
762 -- time_t has 8 bytes; an int year cannot represent a huge time
763 print(" 8-byte time_t")
764 checkerr("cannot be represented", os.date, "%Y", 2^60)
765 -- it should have no problems with year 4000
766 assert(tonumber(os.time{year=4000, month=1, day=1}))
767 end
768 else -- 8-byte ints
769 -- assume time_t has 8 bytes too
770 print(" 8-byte time_t")
771 assert(tonumber(os.date("%Y", 2^60)))
772 -- but still cannot represent a huge year
773 checkerr("cannot be represented", os.time, {year=2^60, month=1, day=1})
774 end
775 end
776end
777
778
779D = os.date("!*t", t)
780load(os.date([[!assert(D.year==%Y and D.month==%m and D.day==%d and
781 D.hour==%H and D.min==%M and D.sec==%S and
782 D.wday==%w+1 and D.yday==%j and type(D.isdst) == 'boolean')]], t))()
783
784do
785 local D = os.date("*t")
786 local t = os.time(D)
787 assert(type(D.isdst) == 'boolean')
788 D.isdst = nil
789 local t1 = os.time(D)
790 assert(t == t1) -- if isdst is absent uses correct default
791end
792
793t = os.time(D)
794D.year = D.year-1;
795local t1 = os.time(D)
796-- allow for leap years
797assert(math.abs(os.difftime(t,t1)/(24*3600) - 365) < 2)
798
799-- should not take more than 1 second to execute these two lines
800t = os.time()
801t1 = os.time(os.date("*t"))
802local diff = os.difftime(t1,t)
803assert(0 <= diff and diff <= 1)
804diff = os.difftime(t,t1)
805assert(-1 <= diff and diff <= 0)
806
807local t1 = os.time{year=2000, month=10, day=1, hour=23, min=12}
808local t2 = os.time{year=2000, month=10, day=1, hour=23, min=10, sec=19}
809assert(os.difftime(t1,t2) == 60*2-19)
810
811-- since 5.3.3, 'os.time' normalizes table fields
812t1 = {year = 2005, month = 1, day = 1, hour = 1, min = 0, sec = -3602}
813os.time(t1)
814assert(t1.day == 31 and t1.month == 12 and t1.year == 2004 and
815 t1.hour == 23 and t1.min == 59 and t1.sec == 58 and
816 t1.yday == 366)
817
818io.output(io.stdout)
819local t = os.date('%d %m %Y %H %M %S')
820local d, m, a, h, min, s = string.match(t,
821 "(%d+) (%d+) (%d+) (%d+) (%d+) (%d+)")
822d = tonumber(d)
823m = tonumber(m)
824a = tonumber(a)
825h = tonumber(h)
826min = tonumber(min)
827s = tonumber(s)
828io.write(string.format('test done on %2.2d/%2.2d/%d', d, m, a))
829io.write(string.format(', at %2.2d:%2.2d:%2.2d\n', h, min, s))
830io.write(string.format('%s\n', _VERSION))
831
832
diff --git a/testes/gc.lua b/testes/gc.lua
new file mode 100644
index 00000000..9647cd54
--- /dev/null
+++ b/testes/gc.lua
@@ -0,0 +1,661 @@
1-- $Id: gc.lua,v 1.82 2018/03/12 14:19:36 roberto Exp $
2-- See Copyright Notice in file all.lua
3
4print('testing garbage collection')
5
6local debug = require"debug"
7
8assert(collectgarbage("isrunning"))
9
10collectgarbage()
11
12local oldmode = collectgarbage("incremental")
13
14
15local function gcinfo ()
16 return collectgarbage"count" * 1024
17end
18
19
20-- test weird parameters to 'collectgarbage'
21do
22 -- save original parameters
23 local a = collectgarbage("setpause", 200)
24 local b = collectgarbage("setstepmul", 200)
25 local t = {0, 2, 10, 90, 500, 5000, 30000, 0x7ffffffe}
26 for i = 1, #t do
27 local p = t[i]
28 for j = 1, #t do
29 local m = t[j]
30 collectgarbage("setpause", p)
31 collectgarbage("setstepmul", m)
32 collectgarbage("step", 0)
33 collectgarbage("step", 10000)
34 end
35 end
36 -- restore original parameters
37 collectgarbage("setpause", a)
38 collectgarbage("setstepmul", b)
39 collectgarbage()
40end
41
42
43_G["while"] = 234
44
45
46--
47-- tests for GC activation when creating different kinds of objects
48--
49local function GC1 ()
50 local u
51 local b -- (above 'u' it in the stack)
52 local finish = false
53 u = setmetatable({}, {__gc = function () finish = true end})
54 b = {34}
55 repeat u = {} until finish
56 assert(b[1] == 34) -- 'u' was collected, but 'b' was not
57
58 finish = false; local i = 1
59 u = setmetatable({}, {__gc = function () finish = true end})
60 repeat i = i + 1; u = tostring(i) .. tostring(i) until finish
61 assert(b[1] == 34) -- 'u' was collected, but 'b' was not
62
63 finish = false
64 u = setmetatable({}, {__gc = function () finish = true end})
65 repeat local i; u = function () return i end until finish
66 assert(b[1] == 34) -- 'u' was collected, but 'b' was not
67end
68
69local function GC2 ()
70 local u
71 local finish = false
72 u = {setmetatable({}, {__gc = function () finish = true end})}
73 local b = {34}
74 repeat u = {{}} until finish
75 assert(b[1] == 34) -- 'u' was collected, but 'b' was not
76
77 finish = false; local i = 1
78 u = {setmetatable({}, {__gc = function () finish = true end})}
79 repeat i = i + 1; u = {tostring(i) .. tostring(i)} until finish
80 assert(b[1] == 34) -- 'u' was collected, but 'b' was not
81
82 finish = false
83 u = {setmetatable({}, {__gc = function () finish = true end})}
84 repeat local i; u = {function () return i end} until finish
85 assert(b[1] == 34) -- 'u' was collected, but 'b' was not
86end
87
88local function GC() GC1(); GC2() end
89
90
91do
92 print("creating many objects")
93
94 local contCreate = 0
95
96 local limit = 5000
97
98 while contCreate <= limit do
99 local a = {}; a = nil
100 contCreate = contCreate+1
101 end
102
103 local a = "a"
104
105 contCreate = 0
106 while contCreate <= limit do
107 a = contCreate .. "b";
108 a = string.gsub(a, '(%d%d*)', string.upper)
109 a = "a"
110 contCreate = contCreate+1
111 end
112
113
114 contCreate = 0
115
116 a = {}
117
118 function a:test ()
119 while contCreate <= limit do
120 load(string.format("function temp(a) return 'a%d' end", contCreate), "")()
121 assert(temp() == string.format('a%d', contCreate))
122 contCreate = contCreate+1
123 end
124 end
125
126 a:test()
127
128end
129
130
131-- collection of functions without locals, globals, etc.
132do local f = function () end end
133
134
135print("functions with errors")
136prog = [[
137do
138 a = 10;
139 function foo(x,y)
140 a = sin(a+0.456-0.23e-12);
141 return function (z) return sin(%x+z) end
142 end
143 local x = function (w) a=a+w; end
144end
145]]
146do
147 local step = 1
148 if _soft then step = 13 end
149 for i=1, string.len(prog), step do
150 for j=i, string.len(prog), step do
151 pcall(load(string.sub(prog, i, j), ""))
152 end
153 end
154end
155
156foo = nil
157print('long strings')
158x = "01234567890123456789012345678901234567890123456789012345678901234567890123456789"
159assert(string.len(x)==80)
160s = ''
161n = 0
162k = math.min(300, (math.maxinteger // 80) // 2)
163while n < k do s = s..x; n=n+1; j=tostring(n) end
164assert(string.len(s) == k*80)
165s = string.sub(s, 1, 10000)
166s, i = string.gsub(s, '(%d%d%d%d)', '')
167assert(i==10000 // 4)
168s = nil
169x = nil
170
171assert(_G["while"] == 234)
172
173
174--
175-- test the "size" of basic GC steps (whatever they mean...)
176--
177do
178print("steps")
179
180 print("steps (2)")
181
182 local function dosteps (siz)
183 collectgarbage()
184 local a = {}
185 for i=1,100 do a[i] = {{}}; local b = {} end
186 local x = gcinfo()
187 local i = 0
188 repeat -- do steps until it completes a collection cycle
189 i = i+1
190 until collectgarbage("step", siz)
191 assert(gcinfo() < x)
192 return i -- number of steps
193 end
194
195 collectgarbage"stop"
196
197 if not _port then
198 assert(dosteps(10) < dosteps(2))
199 end
200
201 -- collector should do a full collection with so many steps
202 assert(dosteps(20000) == 1)
203 assert(collectgarbage("step", 20000) == true)
204 assert(collectgarbage("step", 20000) == true)
205
206 assert(not collectgarbage("isrunning"))
207 collectgarbage"restart"
208 assert(collectgarbage("isrunning"))
209
210end
211
212
213if not _port then
214 -- test the pace of the collector
215 collectgarbage(); collectgarbage()
216 local x = gcinfo()
217 collectgarbage"stop"
218 repeat
219 local a = {}
220 until gcinfo() > 3 * x
221 collectgarbage"restart"
222 assert(collectgarbage("isrunning"))
223 repeat
224 local a = {}
225 until gcinfo() <= x * 2
226end
227
228
229print("clearing tables")
230lim = 15
231a = {}
232-- fill a with `collectable' indices
233for i=1,lim do a[{}] = i end
234b = {}
235for k,v in pairs(a) do b[k]=v end
236-- remove all indices and collect them
237for n in pairs(b) do
238 a[n] = undef
239 assert(type(n) == 'table' and next(n) == nil)
240 collectgarbage()
241end
242b = nil
243collectgarbage()
244for n in pairs(a) do error'cannot be here' end
245for i=1,lim do a[i] = i end
246for i=1,lim do assert(a[i] == i) end
247
248
249print('weak tables')
250a = {}; setmetatable(a, {__mode = 'k'});
251-- fill a with some `collectable' indices
252for i=1,lim do a[{}] = i end
253-- and some non-collectable ones
254for i=1,lim do a[i] = i end
255for i=1,lim do local s=string.rep('@', i); a[s] = s..'#' end
256collectgarbage()
257local i = 0
258for k,v in pairs(a) do assert(k==v or k..'#'==v); i=i+1 end
259assert(i == 2*lim)
260
261a = {}; setmetatable(a, {__mode = 'v'});
262a[1] = string.rep('b', 21)
263collectgarbage()
264assert(a[1]) -- strings are *values*
265a[1] = undef
266-- fill a with some `collectable' values (in both parts of the table)
267for i=1,lim do a[i] = {} end
268for i=1,lim do a[i..'x'] = {} end
269-- and some non-collectable ones
270for i=1,lim do local t={}; a[t]=t end
271for i=1,lim do a[i+lim]=i..'x' end
272collectgarbage()
273local i = 0
274for k,v in pairs(a) do assert(k==v or k-lim..'x' == v); i=i+1 end
275assert(i == 2*lim)
276
277a = {}; setmetatable(a, {__mode = 'kv'});
278local x, y, z = {}, {}, {}
279-- keep only some items
280a[1], a[2], a[3] = x, y, z
281a[string.rep('$', 11)] = string.rep('$', 11)
282-- fill a with some `collectable' values
283for i=4,lim do a[i] = {} end
284for i=1,lim do a[{}] = i end
285for i=1,lim do local t={}; a[t]=t end
286collectgarbage()
287assert(next(a) ~= nil)
288local i = 0
289for k,v in pairs(a) do
290 assert((k == 1 and v == x) or
291 (k == 2 and v == y) or
292 (k == 3 and v == z) or k==v);
293 i = i+1
294end
295assert(i == 4)
296x,y,z=nil
297collectgarbage()
298assert(next(a) == string.rep('$', 11))
299
300
301-- 'bug' in 5.1
302a = {}
303local t = {x = 10}
304local C = setmetatable({key = t}, {__mode = 'v'})
305local C1 = setmetatable({[t] = 1}, {__mode = 'k'})
306a.x = t -- this should not prevent 't' from being removed from
307 -- weak table 'C' by the time 'a' is finalized
308
309setmetatable(a, {__gc = function (u)
310 assert(C.key == nil)
311 assert(type(next(C1)) == 'table')
312 end})
313
314a, t = nil
315collectgarbage()
316collectgarbage()
317assert(next(C) == nil and next(C1) == nil)
318C, C1 = nil
319
320
321-- ephemerons
322local mt = {__mode = 'k'}
323a = {{10},{20},{30},{40}}; setmetatable(a, mt)
324x = nil
325for i = 1, 100 do local n = {}; a[n] = {k = {x}}; x = n end
326GC()
327local n = x
328local i = 0
329while n do n = a[n].k[1]; i = i + 1 end
330assert(i == 100)
331x = nil
332GC()
333for i = 1, 4 do assert(a[i][1] == i * 10); a[i] = undef end
334assert(next(a) == nil)
335
336local K = {}
337a[K] = {}
338for i=1,10 do a[K][i] = {}; a[a[K][i]] = setmetatable({}, mt) end
339x = nil
340local k = 1
341for j = 1,100 do
342 local n = {}; local nk = k%10 + 1
343 a[a[K][nk]][n] = {x, k = k}; x = n; k = nk
344end
345GC()
346local n = x
347local i = 0
348while n do local t = a[a[K][k]][n]; n = t[1]; k = t.k; i = i + 1 end
349assert(i == 100)
350K = nil
351GC()
352-- assert(next(a) == nil)
353
354
355-- testing errors during GC
356do
357collectgarbage("stop") -- stop collection
358local u = {}
359local s = {}; setmetatable(s, {__mode = 'k'})
360setmetatable(u, {__gc = function (o)
361 local i = s[o]
362 s[i] = true
363 assert(not s[i - 1]) -- check proper finalization order
364 if i == 8 then error("here") end -- error during GC
365end})
366
367for i = 6, 10 do
368 local n = setmetatable({}, getmetatable(u))
369 s[n] = i
370end
371
372assert(not pcall(collectgarbage))
373for i = 8, 10 do assert(s[i]) end
374
375for i = 1, 5 do
376 local n = setmetatable({}, getmetatable(u))
377 s[n] = i
378end
379
380collectgarbage()
381for i = 1, 10 do assert(s[i]) end
382
383getmetatable(u).__gc = false
384
385
386-- __gc errors with non-string messages
387setmetatable({}, {__gc = function () error{} end})
388local a, b = pcall(collectgarbage)
389assert(not a and type(b) == "string" and string.find(b, "error in __gc"))
390
391end
392print '+'
393
394
395-- testing userdata
396if T==nil then
397 (Message or print)('\n >>> testC not active: skipping userdata GC tests <<<\n')
398
399else
400
401 local function newproxy(u)
402 return debug.setmetatable(T.newuserdata(0), debug.getmetatable(u))
403 end
404
405 collectgarbage("stop") -- stop collection
406 local u = newproxy(nil)
407 debug.setmetatable(u, {__gc = true})
408 local s = 0
409 local a = {[u] = 0}; setmetatable(a, {__mode = 'vk'})
410 for i=1,10 do a[newproxy(u)] = i end
411 for k in pairs(a) do assert(getmetatable(k) == getmetatable(u)) end
412 local a1 = {}; for k,v in pairs(a) do a1[k] = v end
413 for k,v in pairs(a1) do a[v] = k end
414 for i =1,10 do assert(a[i]) end
415 getmetatable(u).a = a1
416 getmetatable(u).u = u
417 do
418 local u = u
419 getmetatable(u).__gc = function (o)
420 assert(a[o] == 10-s)
421 assert(a[10-s] == undef) -- udata already removed from weak table
422 assert(getmetatable(o) == getmetatable(u))
423 assert(getmetatable(o).a[o] == 10-s)
424 s=s+1
425 end
426 end
427 a1, u = nil
428 assert(next(a) ~= nil)
429 collectgarbage()
430 assert(s==11)
431 collectgarbage()
432 assert(next(a) == nil) -- finalized keys are removed in two cycles
433end
434
435
436-- __gc x weak tables
437local u = setmetatable({}, {__gc = true})
438-- __gc metamethod should be collected before running
439setmetatable(getmetatable(u), {__mode = "v"})
440getmetatable(u).__gc = function (o) os.exit(1) end -- cannot happen
441u = nil
442collectgarbage()
443
444local u = setmetatable({}, {__gc = true})
445local m = getmetatable(u)
446m.x = {[{0}] = 1; [0] = {1}}; setmetatable(m.x, {__mode = "kv"});
447m.__gc = function (o)
448 assert(next(getmetatable(o).x) == nil)
449 m = 10
450end
451u, m = nil
452collectgarbage()
453assert(m==10)
454
455do -- tests for string keys in weak tables
456 collectgarbage(); collectgarbage()
457 local m = collectgarbage("count") -- current memory
458 local a = setmetatable({}, {__mode = "kv"})
459 a[string.rep("a", 2^22)] = 25 -- long string key -> number value
460 a[string.rep("b", 2^22)] = {} -- long string key -> colectable value
461 a[{}] = 14 -- colectable key
462 assert(collectgarbage("count") > m + 2^13) -- 2^13 == 2 * 2^22 in KB
463 collectgarbage()
464 assert(collectgarbage("count") >= m + 2^12 and
465 collectgarbage("count") < m + 2^13) -- one key was collected
466 local k, v = next(a) -- string key with number value preserved
467 assert(k == string.rep("a", 2^22) and v == 25)
468 assert(next(a, k) == nil) -- everything else cleared
469 assert(a[string.rep("b", 2^22)] == undef)
470 a[k] = undef -- erase this last entry
471 k = nil
472 collectgarbage()
473 assert(next(a) == nil)
474 -- make sure will not try to compare with dead key
475 assert(a[string.rep("b", 100)] == undef)
476 assert(collectgarbage("count") <= m + 1) -- eveything collected
477end
478
479
480-- errors during collection
481u = setmetatable({}, {__gc = function () error "!!!" end})
482u = nil
483assert(not pcall(collectgarbage))
484
485
486if not _soft then
487 print("long list")
488 local a = {}
489 for i = 1,200000 do
490 a = {next = a}
491 end
492 a = nil
493 collectgarbage()
494end
495
496-- create many threads with self-references and open upvalues
497print("self-referenced threads")
498local thread_id = 0
499local threads = {}
500
501local function fn (thread)
502 local x = {}
503 threads[thread_id] = function()
504 thread = x
505 end
506 coroutine.yield()
507end
508
509while thread_id < 1000 do
510 local thread = coroutine.create(fn)
511 coroutine.resume(thread, thread)
512 thread_id = thread_id + 1
513end
514
515
516-- Create a closure (function inside 'f') with an upvalue ('param') that
517-- points (through a table) to the closure itself and to the thread
518-- ('co' and the initial value of 'param') where closure is running.
519-- Then, assert that table (and therefore everything else) will be
520-- collected.
521do
522 local collected = false -- to detect collection
523 collectgarbage(); collectgarbage("stop")
524 do
525 local function f (param)
526 ;(function ()
527 assert(type(f) == 'function' and type(param) == 'thread')
528 param = {param, f}
529 setmetatable(param, {__gc = function () collected = true end})
530 coroutine.yield(100)
531 end)()
532 end
533 local co = coroutine.create(f)
534 assert(coroutine.resume(co, co))
535 end
536 -- Now, thread and closure are not reacheable any more.
537 collectgarbage()
538 assert(collected)
539 collectgarbage("restart")
540end
541
542
543do
544 collectgarbage()
545 collectgarbage"stop"
546 collectgarbage("step", 0) -- steps should not unblock the collector
547 local x = gcinfo()
548 repeat
549 for i=1,1000 do _ENV.a = {} end -- no collection during the loop
550 until gcinfo() > 2 * x
551 collectgarbage"restart"
552end
553
554
555if T then -- tests for weird cases collecting upvalues
556
557 local function foo ()
558 local a = {x = 20}
559 coroutine.yield(function () return a.x end) -- will run collector
560 assert(a.x == 20) -- 'a' is 'ok'
561 a = {x = 30} -- create a new object
562 assert(T.gccolor(a) == "white") -- of course it is new...
563 coroutine.yield(100) -- 'a' is still local to this thread
564 end
565
566 local t = setmetatable({}, {__mode = "kv"})
567 collectgarbage(); collectgarbage('stop')
568 -- create coroutine in a weak table, so it will never be marked
569 t.co = coroutine.wrap(foo)
570 local f = t.co() -- create function to access local 'a'
571 T.gcstate("atomic") -- ensure all objects are traversed
572 assert(T.gcstate() == "atomic")
573 assert(t.co() == 100) -- resume coroutine, creating new table for 'a'
574 assert(T.gccolor(t.co) == "white") -- thread was not traversed
575 T.gcstate("pause") -- collect thread, but should mark 'a' before that
576 assert(t.co == nil and f() == 30) -- ensure correct access to 'a'
577
578 collectgarbage("restart")
579
580 -- test barrier in sweep phase (backing userdata to gray)
581 local u = T.newuserdata(0, 1) -- create a userdata
582 collectgarbage()
583 collectgarbage"stop"
584 local a = {} -- avoid 'u' as first element in 'allgc'
585 T.gcstate"atomic"
586 T.gcstate"sweepallgc"
587 local x = {}
588 assert(T.gccolor(u) == "black") -- userdata is "old" (black)
589 assert(T.gccolor(x) == "white") -- table is "new" (white)
590 debug.setuservalue(u, x) -- trigger barrier
591 assert(T.gccolor(u) == "gray") -- userdata changed back to gray
592 collectgarbage"restart"
593
594 print"+"
595end
596
597
598if T then
599 local debug = require "debug"
600 collectgarbage("stop")
601 local x = T.newuserdata(0)
602 local y = T.newuserdata(0)
603 debug.setmetatable(y, {__gc = true}) -- bless the new udata before...
604 debug.setmetatable(x, {__gc = true}) -- ...the old one
605 assert(T.gccolor(y) == "white")
606 T.checkmemory()
607 collectgarbage("restart")
608end
609
610
611if T then
612 print("emergency collections")
613 collectgarbage()
614 collectgarbage()
615 T.totalmem(T.totalmem() + 200)
616 for i=1,200 do local a = {} end
617 T.totalmem(0)
618 collectgarbage()
619 local t = T.totalmem("table")
620 local a = {{}, {}, {}} -- create 4 new tables
621 assert(T.totalmem("table") == t + 4)
622 t = T.totalmem("function")
623 a = function () end -- create 1 new closure
624 assert(T.totalmem("function") == t + 1)
625 t = T.totalmem("thread")
626 a = coroutine.create(function () end) -- create 1 new coroutine
627 assert(T.totalmem("thread") == t + 1)
628end
629
630-- create an object to be collected when state is closed
631do
632 local setmetatable,assert,type,print,getmetatable =
633 setmetatable,assert,type,print,getmetatable
634 local tt = {}
635 tt.__gc = function (o)
636 assert(getmetatable(o) == tt)
637 -- create new objects during GC
638 local a = 'xuxu'..(10+3)..'joao', {}
639 ___Glob = o -- ressurect object!
640 setmetatable({}, tt) -- creates a new one with same metatable
641 print(">>> closing state " .. "<<<\n")
642 end
643 local u = setmetatable({}, tt)
644 ___Glob = {u} -- avoid object being collected before program end
645end
646
647-- create several objects to raise errors when collected while closing state
648do
649 local mt = {__gc = function (o) return o + 1 end}
650 for i = 1,10 do
651 -- create object and preserve it until the end
652 table.insert(___Glob, setmetatable({}, mt))
653 end
654end
655
656-- just to make sure
657assert(collectgarbage'isrunning')
658
659collectgarbage(oldmode)
660
661print('OK')
diff --git a/testes/goto.lua b/testes/goto.lua
new file mode 100644
index 00000000..d22601f9
--- /dev/null
+++ b/testes/goto.lua
@@ -0,0 +1,256 @@
1-- $Id: goto.lua,v 1.15 2017/11/30 13:31:07 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-- bug in 5.3
132do
133 local first = true
134 local a = false
135 if true then
136 goto LBL
137 ::loop::
138 a = true
139 ::LBL::
140 if first then
141 first = false
142 goto loop
143 end
144 end
145 assert(a)
146end
147
148do -- compiling infinite loops
149 goto escape -- do not run the infinite loops
150 ::a:: goto a
151 ::b:: goto c
152 ::c:: goto b
153end
154::escape::
155--------------------------------------------------------------------------------
156-- testing closing of upvalues
157
158local debug = require 'debug'
159
160local function foo ()
161 local t = {}
162 do
163 local i = 1
164 local a, b, c, d
165 t[1] = function () return a, b, c, d end
166 ::l1::
167 local b
168 do
169 local c
170 t[#t + 1] = function () return a, b, c, d end -- t[2], t[4], t[6]
171 if i > 2 then goto l2 end
172 do
173 local d
174 t[#t + 1] = function () return a, b, c, d end -- t[3], t[5]
175 i = i + 1
176 local a
177 goto l1
178 end
179 end
180 end
181 ::l2:: return t
182end
183
184local a = foo()
185assert(#a == 6)
186
187-- all functions share same 'a'
188for i = 2, 6 do
189 assert(debug.upvalueid(a[1], 1) == debug.upvalueid(a[i], 1))
190end
191
192-- 'b' and 'c' are shared among some of them
193for i = 2, 6 do
194 -- only a[1] uses external 'b'/'b'
195 assert(debug.upvalueid(a[1], 2) ~= debug.upvalueid(a[i], 2))
196 assert(debug.upvalueid(a[1], 3) ~= debug.upvalueid(a[i], 3))
197end
198
199for i = 3, 5, 2 do
200 -- inner functions share 'b'/'c' with previous ones
201 assert(debug.upvalueid(a[i], 2) == debug.upvalueid(a[i - 1], 2))
202 assert(debug.upvalueid(a[i], 3) == debug.upvalueid(a[i - 1], 3))
203 -- but not with next ones
204 assert(debug.upvalueid(a[i], 2) ~= debug.upvalueid(a[i + 1], 2))
205 assert(debug.upvalueid(a[i], 3) ~= debug.upvalueid(a[i + 1], 3))
206end
207
208-- only external 'd' is shared
209for i = 2, 6, 2 do
210 assert(debug.upvalueid(a[1], 4) == debug.upvalueid(a[i], 4))
211end
212
213-- internal 'd's are all different
214for i = 3, 5, 2 do
215 for j = 1, 6 do
216 assert((debug.upvalueid(a[i], 4) == debug.upvalueid(a[j], 4))
217 == (i == j))
218 end
219end
220
221--------------------------------------------------------------------------------
222-- testing if x goto optimizations
223
224local function testG (a)
225 if a == 1 then
226 goto l1
227 error("should never be here!")
228 elseif a == 2 then goto l2
229 elseif a == 3 then goto l3
230 elseif a == 4 then
231 goto l1 -- go to inside the block
232 error("should never be here!")
233 ::l1:: a = a + 1 -- must go to 'if' end
234 else
235 goto l4
236 ::l4a:: a = a * 2; goto l4b
237 error("should never be here!")
238 ::l4:: goto l4a
239 error("should never be here!")
240 ::l4b::
241 end
242 do return a end
243 ::l2:: do return "2" end
244 ::l3:: do return "3" end
245 ::l1:: return "1"
246end
247
248assert(testG(1) == "1")
249assert(testG(2) == "2")
250assert(testG(3) == "3")
251assert(testG(4) == 5)
252assert(testG(5) == 10)
253--------------------------------------------------------------------------------
254
255
256print'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..f0780a03
--- /dev/null
+++ b/testes/locals.lua
@@ -0,0 +1,181 @@
1-- $Id: locals.lua,v 1.41 2018/06/19 12:25:39 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, "T") 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 = T.querytab(a)
115
116 for k,_ in pairs(a) do a[k] = undef 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
122
123 -- testing allocation errors during table insertions
124 local a = {}
125 local function additems ()
126 a.x = true; a.y = true; a.z = true
127 a[1] = true
128 a[2] = true
129 end
130 for i = 1, math.huge do
131 T.alloccount(i)
132 local st, msg = pcall(additems)
133 T.alloccount()
134 local count = 0
135 for k, v in pairs(a) do
136 assert(a[k] == v)
137 count = count + 1
138 end
139 if st then assert(count == 5); break end
140 end
141end
142
143
144-- testing lexical environments
145
146assert(_ENV == _G)
147
148do
149local dummy
150local _ENV = (function (...) return ... end)(_G, dummy) -- {
151
152do local _ENV = {assert=assert}; assert(true) end
153mt = {_G = _G}
154local foo,x
155A = false -- "declare" A
156do local _ENV = mt
157 function foo (x)
158 A = x
159 do local _ENV = _G; A = 1000 end
160 return function (x) return A .. x end
161 end
162end
163assert(getenv(foo) == mt)
164x = foo('hi'); assert(mt.A == 'hi' and A == 1000)
165assert(x('*') == mt.A .. '*')
166
167do local _ENV = {assert=assert, A=10};
168 do local _ENV = {assert=assert, A=20};
169 assert(A==20);x=A
170 end
171 assert(A==10 and x==20)
172end
173assert(x==20)
174
175
176print('OK')
177
178return 5,f
179
180end -- }
181
diff --git a/testes/main.lua b/testes/main.lua
new file mode 100644
index 00000000..582b39c0
--- /dev/null
+++ b/testes/main.lua
@@ -0,0 +1,381 @@
1# testing special comment on first line
2-- $Id: main.lua,v 1.69 2018/06/19 12:23:50 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_4=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_4=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_4="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] == undef and arg[-4] == undef)
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 %s 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..66998460
--- /dev/null
+++ b/testes/math.lua
@@ -0,0 +1,931 @@
1-- $Id: math.lua,v 1.86 2018/05/09 14:55:52 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))
270 assert(not (4 <= NaN))
271 assert(not (4 < NaN))
272end
273
274
275-- avoiding errors at compile time
276local function checkcompt (msg, code)
277 checkerror(msg, assert(load(code)))
278end
279checkcompt("divide by zero", "return 2 // 0")
280checkcompt(msgf2i, "return 2.3 >> 0")
281checkcompt(msgf2i, ("return 2.0^%d & 1"):format(intbits - 1))
282checkcompt("field 'huge'", "return math.huge << 1")
283checkcompt(msgf2i, ("return 1 | 2.0^%d"):format(intbits - 1))
284checkcompt(msgf2i, "return 2.3 ~ 0.0")
285
286
287-- testing overflow errors when converting from float to integer (runtime)
288local function f2i (x) return x | x end
289checkerror(msgf2i, f2i, math.huge) -- +inf
290checkerror(msgf2i, f2i, -math.huge) -- -inf
291checkerror(msgf2i, f2i, 0/0) -- NaN
292
293if floatbits < intbits then
294 -- conversion tests when float cannot represent all integers
295 assert(maxint + 1.0 == maxint + 0.0)
296 assert(minint - 1.0 == minint + 0.0)
297 checkerror(msgf2i, f2i, maxint + 0.0)
298 assert(f2i(2.0^(intbits - 2)) == 1 << (intbits - 2))
299 assert(f2i(-2.0^(intbits - 2)) == -(1 << (intbits - 2)))
300 assert((2.0^(floatbits - 1) + 1.0) // 1 == (1 << (floatbits - 1)) + 1)
301 -- maximum integer representable as a float
302 local mf = maxint - (1 << (floatbits - intbits)) + 1
303 assert(f2i(mf + 0.0) == mf) -- OK up to here
304 mf = mf + 1
305 assert(f2i(mf + 0.0) ~= mf) -- no more representable
306else
307 -- conversion tests when float can represent all integers
308 assert(maxint + 1.0 > maxint)
309 assert(minint - 1.0 < minint)
310 assert(f2i(maxint + 0.0) == maxint)
311 checkerror("no integer rep", f2i, maxint + 1.0)
312 checkerror("no integer rep", f2i, minint - 1.0)
313end
314
315-- 'minint' should be representable as a float no matter the precision
316assert(f2i(minint + 0.0) == minint)
317
318
319-- testing numeric strings
320
321assert("2" + 1 == 3)
322assert("2 " + 1 == 3)
323assert(" -2 " + 1 == -1)
324assert(" -0xa " + 1 == -9)
325
326
327-- Literal integer Overflows (new behavior in 5.3.3)
328do
329 -- no overflows
330 assert(eqT(tonumber(tostring(maxint)), maxint))
331 assert(eqT(tonumber(tostring(minint)), minint))
332
333 -- add 1 to last digit as a string (it cannot be 9...)
334 local function incd (n)
335 local s = string.format("%d", n)
336 s = string.gsub(s, "%d$", function (d)
337 assert(d ~= '9')
338 return string.char(string.byte(d) + 1)
339 end)
340 return s
341 end
342
343 -- 'tonumber' with overflow by 1
344 assert(eqT(tonumber(incd(maxint)), maxint + 1.0))
345 assert(eqT(tonumber(incd(minint)), minint - 1.0))
346
347 -- large numbers
348 assert(eqT(tonumber("1"..string.rep("0", 30)), 1e30))
349 assert(eqT(tonumber("-1"..string.rep("0", 30)), -1e30))
350
351 -- hexa format still wraps around
352 assert(eqT(tonumber("0x1"..string.rep("0", 30)), 0))
353
354 -- lexer in the limits
355 assert(minint == load("return " .. minint)())
356 assert(eqT(maxint, load("return " .. maxint)()))
357
358 assert(eqT(10000000000000000000000.0, 10000000000000000000000))
359 assert(eqT(-10000000000000000000000.0, -10000000000000000000000))
360end
361
362
363-- testing 'tonumber'
364
365-- 'tonumber' with numbers
366assert(tonumber(3.4) == 3.4)
367assert(eqT(tonumber(3), 3))
368assert(eqT(tonumber(maxint), maxint) and eqT(tonumber(minint), minint))
369assert(tonumber(1/0) == 1/0)
370
371-- 'tonumber' with strings
372assert(tonumber("0") == 0)
373assert(tonumber("") == nil)
374assert(tonumber(" ") == nil)
375assert(tonumber("-") == nil)
376assert(tonumber(" -0x ") == nil)
377assert(tonumber{} == nil)
378assert(tonumber'+0.01' == 1/100 and tonumber'+.01' == 0.01 and
379 tonumber'.01' == 0.01 and tonumber'-1.' == -1 and
380 tonumber'+1.' == 1)
381assert(tonumber'+ 0.01' == nil and tonumber'+.e1' == nil and
382 tonumber'1e' == nil and tonumber'1.0e+' == nil and
383 tonumber'.' == nil)
384assert(tonumber('-012') == -010-2)
385assert(tonumber('-1.2e2') == - - -120)
386
387assert(tonumber("0xffffffffffff") == (1 << (4*12)) - 1)
388assert(tonumber("0x"..string.rep("f", (intbits//4))) == -1)
389assert(tonumber("-0x"..string.rep("f", (intbits//4))) == 1)
390
391-- testing 'tonumber' with base
392assert(tonumber(' 001010 ', 2) == 10)
393assert(tonumber(' 001010 ', 10) == 001010)
394assert(tonumber(' -1010 ', 2) == -10)
395assert(tonumber('10', 36) == 36)
396assert(tonumber(' -10 ', 36) == -36)
397assert(tonumber(' +1Z ', 36) == 36 + 35)
398assert(tonumber(' -1z ', 36) == -36 + -35)
399assert(tonumber('-fFfa', 16) == -(10+(16*(15+(16*(15+(16*15)))))))
400assert(tonumber(string.rep('1', (intbits - 2)), 2) + 1 == 2^(intbits - 2))
401assert(tonumber('ffffFFFF', 16)+1 == (1 << 32))
402assert(tonumber('0ffffFFFF', 16)+1 == (1 << 32))
403assert(tonumber('-0ffffffFFFF', 16) - 1 == -(1 << 40))
404for i = 2,36 do
405 local i2 = i * i
406 local i10 = i2 * i2 * i2 * i2 * i2 -- i^10
407 assert(tonumber('\t10000000000\t', i) == i10)
408end
409
410if not _soft then
411 -- tests with very long numerals
412 assert(tonumber("0x"..string.rep("f", 13)..".0") == 2.0^(4*13) - 1)
413 assert(tonumber("0x"..string.rep("f", 150)..".0") == 2.0^(4*150) - 1)
414 assert(tonumber("0x"..string.rep("f", 300)..".0") == 2.0^(4*300) - 1)
415 assert(tonumber("0x"..string.rep("f", 500)..".0") == 2.0^(4*500) - 1)
416 assert(tonumber('0x3.' .. string.rep('0', 1000)) == 3)
417 assert(tonumber('0x' .. string.rep('0', 1000) .. 'a') == 10)
418 assert(tonumber('0x0.' .. string.rep('0', 13).."1") == 2.0^(-4*14))
419 assert(tonumber('0x0.' .. string.rep('0', 150).."1") == 2.0^(-4*151))
420 assert(tonumber('0x0.' .. string.rep('0', 300).."1") == 2.0^(-4*301))
421 assert(tonumber('0x0.' .. string.rep('0', 500).."1") == 2.0^(-4*501))
422
423 assert(tonumber('0xe03' .. string.rep('0', 1000) .. 'p-4000') == 3587.0)
424 assert(tonumber('0x.' .. string.rep('0', 1000) .. '74p4004') == 0x7.4)
425end
426
427-- testing 'tonumber' for invalid formats
428
429local function f (...)
430 if select('#', ...) == 1 then
431 return (...)
432 else
433 return "***"
434 end
435end
436
437assert(f(tonumber('fFfa', 15)) == nil)
438assert(f(tonumber('099', 8)) == nil)
439assert(f(tonumber('1\0', 2)) == nil)
440assert(f(tonumber('', 8)) == nil)
441assert(f(tonumber(' ', 9)) == nil)
442assert(f(tonumber(' ', 9)) == nil)
443assert(f(tonumber('0xf', 10)) == nil)
444
445assert(f(tonumber('inf')) == nil)
446assert(f(tonumber(' INF ')) == nil)
447assert(f(tonumber('Nan')) == nil)
448assert(f(tonumber('nan')) == nil)
449
450assert(f(tonumber(' ')) == nil)
451assert(f(tonumber('')) == nil)
452assert(f(tonumber('1 a')) == nil)
453assert(f(tonumber('1 a', 2)) == nil)
454assert(f(tonumber('1\0')) == nil)
455assert(f(tonumber('1 \0')) == nil)
456assert(f(tonumber('1\0 ')) == nil)
457assert(f(tonumber('e1')) == nil)
458assert(f(tonumber('e 1')) == nil)
459assert(f(tonumber(' 3.4.5 ')) == nil)
460
461
462-- testing 'tonumber' for invalid hexadecimal formats
463
464assert(tonumber('0x') == nil)
465assert(tonumber('x') == nil)
466assert(tonumber('x3') == nil)
467assert(tonumber('0x3.3.3') == nil) -- two decimal points
468assert(tonumber('00x2') == nil)
469assert(tonumber('0x 2') == nil)
470assert(tonumber('0 x2') == nil)
471assert(tonumber('23x') == nil)
472assert(tonumber('- 0xaa') == nil)
473assert(tonumber('-0xaaP ') == nil) -- no exponent
474assert(tonumber('0x0.51p') == nil)
475assert(tonumber('0x5p+-2') == nil)
476
477
478-- testing hexadecimal numerals
479
480assert(0x10 == 16 and 0xfff == 2^12 - 1 and 0XFB == 251)
481assert(0x0p12 == 0 and 0x.0p-3 == 0)
482assert(0xFFFFFFFF == (1 << 32) - 1)
483assert(tonumber('+0x2') == 2)
484assert(tonumber('-0xaA') == -170)
485assert(tonumber('-0xffFFFfff') == -(1 << 32) + 1)
486
487-- possible confusion with decimal exponent
488assert(0E+1 == 0 and 0xE+1 == 15 and 0xe-1 == 13)
489
490
491-- floating hexas
492
493assert(tonumber(' 0x2.5 ') == 0x25/16)
494assert(tonumber(' -0x2.5 ') == -0x25/16)
495assert(tonumber(' +0x0.51p+8 ') == 0x51)
496assert(0x.FfffFFFF == 1 - '0x.00000001')
497assert('0xA.a' + 0 == 10 + 10/16)
498assert(0xa.aP4 == 0XAA)
499assert(0x4P-2 == 1)
500assert(0x1.1 == '0x1.' + '+0x.1')
501assert(0Xabcdef.0 == 0x.ABCDEFp+24)
502
503
504assert(1.1 == 1.+.1)
505assert(100.0 == 1E2 and .01 == 1e-2)
506assert(1111111111 - 1111111110 == 1000.00e-03)
507assert(1.1 == '1.'+'.1')
508assert(tonumber'1111111111' - tonumber'1111111110' ==
509 tonumber" +0.001e+3 \n\t")
510
511assert(0.1e-30 > 0.9E-31 and 0.9E30 < 0.1e31)
512
513assert(0.123456 > 0.123455)
514
515assert(tonumber('+1.23E18') == 1.23*10.0^18)
516
517-- testing order operators
518assert(not(1<1) and (1<2) and not(2<1))
519assert(not('a'<'a') and ('a'<'b') and not('b'<'a'))
520assert((1<=1) and (1<=2) and not(2<=1))
521assert(('a'<='a') and ('a'<='b') and not('b'<='a'))
522assert(not(1>1) and not(1>2) and (2>1))
523assert(not('a'>'a') and not('a'>'b') and ('b'>'a'))
524assert((1>=1) and not(1>=2) and (2>=1))
525assert(('a'>='a') and not('a'>='b') and ('b'>='a'))
526assert(1.3 < 1.4 and 1.3 <= 1.4 and not (1.3 < 1.3) and 1.3 <= 1.3)
527
528-- testing mod operator
529assert(eqT(-4 % 3, 2))
530assert(eqT(4 % -3, -2))
531assert(eqT(-4.0 % 3, 2.0))
532assert(eqT(4 % -3.0, -2.0))
533assert(math.pi - math.pi % 1 == 3)
534assert(math.pi - math.pi % 0.001 == 3.141)
535
536assert(eqT(minint % minint, 0))
537assert(eqT(maxint % maxint, 0))
538assert((minint + 1) % minint == minint + 1)
539assert((maxint - 1) % maxint == maxint - 1)
540assert(minint % maxint == maxint - 1)
541
542assert(minint % -1 == 0)
543assert(minint % -2 == 0)
544assert(maxint % -2 == -1)
545
546-- non-portable tests because Windows C library cannot compute
547-- fmod(1, huge) correctly
548if not _port then
549 local function anan (x) assert(isNaN(x)) end -- assert Not a Number
550 anan(0.0 % 0)
551 anan(1.3 % 0)
552 anan(math.huge % 1)
553 anan(math.huge % 1e30)
554 anan(-math.huge % 1e30)
555 anan(-math.huge % -1e30)
556 assert(1 % math.huge == 1)
557 assert(1e30 % math.huge == 1e30)
558 assert(1e30 % -math.huge == -math.huge)
559 assert(-1 % math.huge == math.huge)
560 assert(-1 % -math.huge == -1)
561end
562
563
564-- testing unsigned comparisons
565assert(math.ult(3, 4))
566assert(not math.ult(4, 4))
567assert(math.ult(-2, -1))
568assert(math.ult(2, -1))
569assert(not math.ult(-2, -2))
570assert(math.ult(maxint, minint))
571assert(not math.ult(minint, maxint))
572
573
574assert(eq(math.sin(-9.8)^2 + math.cos(-9.8)^2, 1))
575assert(eq(math.tan(math.pi/4), 1))
576assert(eq(math.sin(math.pi/2), 1) and eq(math.cos(math.pi/2), 0))
577assert(eq(math.atan(1), math.pi/4) and eq(math.acos(0), math.pi/2) and
578 eq(math.asin(1), math.pi/2))
579assert(eq(math.deg(math.pi/2), 90) and eq(math.rad(90), math.pi/2))
580assert(math.abs(-10.43) == 10.43)
581assert(eqT(math.abs(minint), minint))
582assert(eqT(math.abs(maxint), maxint))
583assert(eqT(math.abs(-maxint), maxint))
584assert(eq(math.atan(1,0), math.pi/2))
585assert(math.fmod(10,3) == 1)
586assert(eq(math.sqrt(10)^2, 10))
587assert(eq(math.log(2, 10), math.log(2)/math.log(10)))
588assert(eq(math.log(2, 2), 1))
589assert(eq(math.log(9, 3), 2))
590assert(eq(math.exp(0), 1))
591assert(eq(math.sin(10), math.sin(10%(2*math.pi))))
592
593
594assert(tonumber(' 1.3e-2 ') == 1.3e-2)
595assert(tonumber(' -1.00000000000001 ') == -1.00000000000001)
596
597-- testing constant limits
598-- 2^23 = 8388608
599assert(8388609 + -8388609 == 0)
600assert(8388608 + -8388608 == 0)
601assert(8388607 + -8388607 == 0)
602
603
604
605do -- testing floor & ceil
606 assert(eqT(math.floor(3.4), 3))
607 assert(eqT(math.ceil(3.4), 4))
608 assert(eqT(math.floor(-3.4), -4))
609 assert(eqT(math.ceil(-3.4), -3))
610 assert(eqT(math.floor(maxint), maxint))
611 assert(eqT(math.ceil(maxint), maxint))
612 assert(eqT(math.floor(minint), minint))
613 assert(eqT(math.floor(minint + 0.0), minint))
614 assert(eqT(math.ceil(minint), minint))
615 assert(eqT(math.ceil(minint + 0.0), minint))
616 assert(math.floor(1e50) == 1e50)
617 assert(math.ceil(1e50) == 1e50)
618 assert(math.floor(-1e50) == -1e50)
619 assert(math.ceil(-1e50) == -1e50)
620 for _, p in pairs{31,32,63,64} do
621 assert(math.floor(2^p) == 2^p)
622 assert(math.floor(2^p + 0.5) == 2^p)
623 assert(math.ceil(2^p) == 2^p)
624 assert(math.ceil(2^p - 0.5) == 2^p)
625 end
626 checkerror("number expected", math.floor, {})
627 checkerror("number expected", math.ceil, print)
628 assert(eqT(math.tointeger(minint), minint))
629 assert(eqT(math.tointeger(minint .. ""), minint))
630 assert(eqT(math.tointeger(maxint), maxint))
631 assert(eqT(math.tointeger(maxint .. ""), maxint))
632 assert(eqT(math.tointeger(minint + 0.0), minint))
633 assert(math.tointeger(0.0 - minint) == nil)
634 assert(math.tointeger(math.pi) == nil)
635 assert(math.tointeger(-math.pi) == nil)
636 assert(math.floor(math.huge) == math.huge)
637 assert(math.ceil(math.huge) == math.huge)
638 assert(math.tointeger(math.huge) == nil)
639 assert(math.floor(-math.huge) == -math.huge)
640 assert(math.ceil(-math.huge) == -math.huge)
641 assert(math.tointeger(-math.huge) == nil)
642 assert(math.tointeger("34.0") == 34)
643 assert(math.tointeger("34.3") == nil)
644 assert(math.tointeger({}) == nil)
645 assert(math.tointeger(0/0) == nil) -- NaN
646end
647
648
649-- testing fmod for integers
650for i = -6, 6 do
651 for j = -6, 6 do
652 if j ~= 0 then
653 local mi = math.fmod(i, j)
654 local mf = math.fmod(i + 0.0, j)
655 assert(mi == mf)
656 assert(math.type(mi) == 'integer' and math.type(mf) == 'float')
657 if (i >= 0 and j >= 0) or (i <= 0 and j <= 0) or mi == 0 then
658 assert(eqT(mi, i % j))
659 end
660 end
661 end
662end
663assert(eqT(math.fmod(minint, minint), 0))
664assert(eqT(math.fmod(maxint, maxint), 0))
665assert(eqT(math.fmod(minint + 1, minint), minint + 1))
666assert(eqT(math.fmod(maxint - 1, maxint), maxint - 1))
667
668checkerror("zero", math.fmod, 3, 0)
669
670
671do -- testing max/min
672 checkerror("value expected", math.max)
673 checkerror("value expected", math.min)
674 assert(eqT(math.max(3), 3))
675 assert(eqT(math.max(3, 5, 9, 1), 9))
676 assert(math.max(maxint, 10e60) == 10e60)
677 assert(eqT(math.max(minint, minint + 1), minint + 1))
678 assert(eqT(math.min(3), 3))
679 assert(eqT(math.min(3, 5, 9, 1), 1))
680 assert(math.min(3.2, 5.9, -9.2, 1.1) == -9.2)
681 assert(math.min(1.9, 1.7, 1.72) == 1.7)
682 assert(math.min(-10e60, minint) == -10e60)
683 assert(eqT(math.min(maxint, maxint - 1), maxint - 1))
684 assert(eqT(math.min(maxint - 2, maxint, maxint - 1), maxint - 2))
685end
686-- testing implicit convertions
687
688local a,b = '10', '20'
689assert(a*b == 200 and a+b == 30 and a-b == -10 and a/b == 0.5 and -b == -20)
690assert(a == '10' and b == '20')
691
692
693do
694 print("testing -0 and NaN")
695 local mz, z = -0.0, 0.0
696 assert(mz == z)
697 assert(1/mz < 0 and 0 < 1/z)
698 local a = {[mz] = 1}
699 assert(a[z] == 1 and a[mz] == 1)
700 a[z] = 2
701 assert(a[z] == 2 and a[mz] == 2)
702 local inf = math.huge * 2 + 1
703 mz, z = -1/inf, 1/inf
704 assert(mz == z)
705 assert(1/mz < 0 and 0 < 1/z)
706 local NaN = inf - inf
707 assert(NaN ~= NaN)
708 assert(not (NaN < NaN))
709 assert(not (NaN <= NaN))
710 assert(not (NaN > NaN))
711 assert(not (NaN >= NaN))
712 assert(not (0 < NaN) and not (NaN < 0))
713 local NaN1 = 0/0
714 assert(NaN ~= NaN1 and not (NaN <= NaN1) and not (NaN1 <= NaN))
715 local a = {}
716 assert(not pcall(rawset, a, NaN, 1))
717 assert(a[NaN] == undef)
718 a[1] = 1
719 assert(not pcall(rawset, a, NaN, 1))
720 assert(a[NaN] == undef)
721 -- strings with same binary representation as 0.0 (might create problems
722 -- for constant manipulation in the pre-compiler)
723 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"
724 assert(a1 == a2 and a2 == a4 and a1 ~= a3)
725 assert(a3 == a5)
726end
727
728
729print("testing 'math.random'")
730
731local random, max, min = math.random, math.max, math.min
732
733local function testnear (val, ref, tol)
734 return (math.abs(val - ref) < ref * tol)
735end
736
737
738-- low-level!! For the current implementation of random in Lua,
739-- the first call after seed 1007 should return 0x7a7040a5a323c9d6
740do
741 -- all computations assume at most 32-bit integers
742 local h = 0x7a7040a5 -- higher half
743 local l = 0xa323c9d6 -- lower half
744
745 math.randomseed(1007)
746 -- get the low 'intbits' of the 64-bit expected result
747 local res = (h << 32 | l) & ~(~0 << intbits)
748 assert(random(0) == res)
749
750 math.randomseed(1007, 0)
751 -- using lower bits to generate random floats; (the '% 2^32' converts
752 -- 32-bit integers to floats as unsigned)
753 local res
754 if floatbits <= 32 then
755 -- get all bits from the lower half
756 res = (l & ~(~0 << floatbits)) % 2^32
757 else
758 -- get 32 bits from the lower half and the rest from the higher half
759 res = ((h & ~(~0 << (floatbits - 32))) % 2^32) * 2^32 + (l % 2^32)
760 end
761 assert(random() * 2^floatbits == res)
762end
763
764math.randomseed(0, os.time())
765
766do -- test random for floats
767 local randbits = math.min(floatbits, 64) -- at most 64 random bits
768 local mult = 2^randbits -- to make random float into an integral
769 local counts = {} -- counts for bits
770 for i = 1, randbits do counts[i] = 0 end
771 local up = -math.huge
772 local low = math.huge
773 local rounds = 100 * randbits -- 100 times for each bit
774 local totalrounds = 0
775 ::doagain:: -- will repeat test until we get good statistics
776 for i = 0, rounds do
777 local t = random()
778 assert(0 <= t and t < 1)
779 up = max(up, t)
780 low = min(low, t)
781 assert(t * mult % 1 == 0) -- no extra bits
782 local bit = i % randbits -- bit to be tested
783 if (t * 2^bit) % 1 >= 0.5 then -- is bit set?
784 counts[bit + 1] = counts[bit + 1] + 1 -- increment its count
785 end
786 end
787 totalrounds = totalrounds + rounds
788 if not (eq(up, 1, 0.001) and eq(low, 0, 0.001)) then
789 goto doagain
790 end
791 -- all bit counts should be near 50%
792 local expected = (totalrounds / randbits / 2)
793 for i = 1, randbits do
794 if not testnear(counts[i], expected, 0.10) then
795 goto doagain
796 end
797 end
798 print(string.format("float random range in %d calls: [%f, %f]",
799 totalrounds, low, up))
800end
801
802
803do -- test random for full integers
804 local up = 0
805 local low = 0
806 local counts = {} -- counts for bits
807 for i = 1, intbits do counts[i] = 0 end
808 local rounds = 100 * intbits -- 100 times for each bit
809 local totalrounds = 0
810 ::doagain:: -- will repeat test until we get good statistics
811 for i = 0, rounds do
812 local t = random(0)
813 up = max(up, t)
814 low = min(low, t)
815 local bit = i % intbits -- bit to be tested
816 -- increment its count if it is set
817 counts[bit + 1] = counts[bit + 1] + ((t >> bit) & 1)
818 end
819 totalrounds = totalrounds + rounds
820 local lim = maxint >> 10
821 if not (maxint - up < lim and low - minint < lim) then
822 goto doagain
823 end
824 -- all bit counts should be near 50%
825 local expected = (totalrounds / intbits / 2)
826 for i = 1, intbits do
827 if not testnear(counts[i], expected, 0.10) then
828 goto doagain
829 end
830 end
831 print(string.format(
832 "integer random range in %d calls: [minint + %.0fppm, maxint - %.0fppm]",
833 totalrounds, (minint - low) / minint * 1e6,
834 (maxint - up) / maxint * 1e6))
835end
836
837do
838 -- test distribution for a dice
839 local count = {0, 0, 0, 0, 0, 0}
840 local rep = 200
841 local totalrep = 0
842 ::doagain::
843 for i = 1, rep * 6 do
844 local r = random(6)
845 count[r] = count[r] + 1
846 end
847 totalrep = totalrep + rep
848 for i = 1, 6 do
849 if not testnear(count[i], totalrep, 0.05) then
850 goto doagain
851 end
852 end
853end
854
855do
856 local function aux (x1, x2) -- test random for small intervals
857 local mark = {}; local count = 0 -- to check that all values appeared
858 while true do
859 local t = random(x1, x2)
860 assert(x1 <= t and t <= x2)
861 if not mark[t] then -- new value
862 mark[t] = true
863 count = count + 1
864 if count == x2 - x1 + 1 then -- all values appeared; OK
865 goto ok
866 end
867 end
868 end
869 ::ok::
870 end
871
872 aux(-10,0)
873 aux(1, 6)
874 aux(1, 2)
875 aux(1, 32)
876 aux(-10, 10)
877 aux(-10,-10) -- unit set
878 aux(minint, minint) -- unit set
879 aux(maxint, maxint) -- unit set
880 aux(minint, minint + 9)
881 aux(maxint - 3, maxint)
882end
883
884do
885 local function aux(p1, p2) -- test random for large intervals
886 local max = minint
887 local min = maxint
888 local n = 100
889 local mark = {}; local count = 0 -- to count how many different values
890 ::doagain::
891 for _ = 1, n do
892 local t = random(p1, p2)
893 if not mark[t] then -- new value
894 assert(p1 <= t and t <= p2)
895 max = math.max(max, t)
896 min = math.min(min, t)
897 mark[t] = true
898 count = count + 1
899 end
900 end
901 -- at least 80% of values are different
902 if not (count >= n * 0.8) then
903 goto doagain
904 end
905 -- min and max not too far from formal min and max
906 local diff = (p2 - p1) >> 4
907 if not (min < p1 + diff and max > p2 - diff) then
908 goto doagain
909 end
910 end
911 aux(0, maxint)
912 aux(1, maxint)
913 aux(minint, -1)
914 aux(minint // 2, maxint // 2)
915 aux(minint, maxint)
916 aux(minint + 1, maxint)
917 aux(minint, maxint - 1)
918 aux(0, 1 << (intbits - 5))
919end
920
921
922assert(not pcall(random, 1, 2, 3)) -- too many arguments
923
924-- empty interval
925assert(not pcall(random, minint + 1, minint))
926assert(not pcall(random, maxint, maxint - 1))
927assert(not pcall(random, maxint, minint))
928
929
930
931print('OK')
diff --git a/testes/nextvar.lua b/testes/nextvar.lua
new file mode 100644
index 00000000..3ac3acd9
--- /dev/null
+++ b/testes/nextvar.lua
@@ -0,0 +1,669 @@
1-- $Id: nextvar.lua,v 1.85 2018/06/19 12:24:19 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.."+"] = undef 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] = undef end
149 for i=30,50 do a[i] = true; a[i] = undef end -- force a rehash (?)
150 check(a, 0, 8) -- 5 elements in the table
151 a[10] = 1
152 for i=30,50 do a[i] = true; a[i] = undef end -- force a rehash (?)
153 check(a, 0, 8) -- only 6 elements in the table
154 for i=1,14 do a[i] = true; a[i] = undef end
155 for i=18,50 do a[i] = true; a[i] = undef 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
180
181-- Table length with limit smaller than maximum value at array
182local a = {}
183for i = 1,64 do a[i] = true end -- make its array size 64
184for i = 1,64 do a[i] = nil end -- erase all elements
185assert(T.querytab(a) == 64) -- array part has 64 elements
186a[32] = true; a[48] = true; -- binary search will find these ones
187a[51] = true -- binary search will miss this one
188assert(#a == 48) -- this will set the limit
189assert(select(4, T.querytab(a)) == 48) -- this is the limit now
190a[50] = true -- this will set a new limit
191assert(select(4, T.querytab(a)) == 50) -- this is the limit now
192-- but the size is larger (and still inside the array part)
193assert(#a == 51)
194
195end --]
196
197
198-- test size operation on tables with nils
199assert(#{} == 0)
200assert(#{nil} == 0)
201assert(#{nil, nil} == 0)
202assert(#{nil, nil, nil} == 0)
203assert(#{nil, nil, nil, nil} == 0)
204assert(#{1, 2, 3, nil, nil} == 3)
205print'+'
206
207
208local nofind = {}
209
210a,b,c = 1,2,3
211a,b,c = nil
212
213
214-- next uses always the same iteraction function
215assert(next{} == next{})
216
217local function find (name)
218 local n,v
219 while 1 do
220 n,v = next(_G, n)
221 if not n then return nofind end
222 assert(_G[n] ~= undef)
223 if n == name then return v end
224 end
225end
226
227local function find1 (name)
228 for n,v in pairs(_G) do
229 if n==name then return v end
230 end
231 return nil -- not found
232end
233
234
235assert(print==find("print") and print == find1("print"))
236assert(_G["print"]==find("print"))
237assert(assert==find1("assert"))
238assert(nofind==find("return"))
239assert(not find1("return"))
240_G["ret" .. "urn"] = undef
241assert(nofind==find("return"))
242_G["xxx"] = 1
243assert(xxx==find("xxx"))
244
245-- invalid key to 'next'
246checkerror("invalid key", next, {10,20}, 3)
247
248-- both 'pairs' and 'ipairs' need an argument
249checkerror("bad argument", pairs)
250checkerror("bad argument", ipairs)
251
252print('+')
253
254a = {}
255for i=0,10000 do
256 if math.fmod(i,10) ~= 0 then
257 a['x'..i] = i
258 end
259end
260
261n = {n=0}
262for i,v in pairs(a) do
263 n.n = n.n+1
264 assert(i and v and a[i] == v)
265end
266assert(n.n == 9000)
267a = nil
268
269do -- clear global table
270 local a = {}
271 for n,v in pairs(_G) do a[n]=v end
272 for n,v in pairs(a) do
273 if not package.loaded[n] and type(v) ~= "function" and
274 not string.find(n, "^[%u_]") then
275 _G[n] = undef
276 end
277 collectgarbage()
278 end
279end
280
281
282--
283
284local function checknext (a)
285 local b = {}
286 do local k,v = next(a); while k do b[k] = v; k,v = next(a,k) end end
287 for k,v in pairs(b) do assert(a[k] == v) end
288 for k,v in pairs(a) do assert(b[k] == v) end
289end
290
291checknext{1,x=1,y=2,z=3}
292checknext{1,2,x=1,y=2,z=3}
293checknext{1,2,3,x=1,y=2,z=3}
294checknext{1,2,3,4,x=1,y=2,z=3}
295checknext{1,2,3,4,5,x=1,y=2,z=3}
296
297assert(#{} == 0)
298assert(#{[-1] = 2} == 0)
299for i=0,40 do
300 local a = {}
301 for j=1,i do a[j]=j end
302 assert(#a == i)
303end
304
305-- 'maxn' is now deprecated, but it is easily defined in Lua
306function table.maxn (t)
307 local max = 0
308 for k in pairs(t) do
309 max = (type(k) == 'number') and math.max(max, k) or max
310 end
311 return max
312end
313
314assert(table.maxn{} == 0)
315assert(table.maxn{["1000"] = true} == 0)
316assert(table.maxn{["1000"] = true, [24.5] = 3} == 24.5)
317assert(table.maxn{[1000] = true} == 1000)
318assert(table.maxn{[10] = true, [100*math.pi] = print} == 100*math.pi)
319
320table.maxn = nil
321
322-- int overflow
323a = {}
324for i=0,50 do a[2^i] = true end
325assert(a[#a])
326
327print('+')
328
329
330do -- testing 'next' with all kinds of keys
331 local a = {
332 [1] = 1, -- integer
333 [1.1] = 2, -- float
334 ['x'] = 3, -- short string
335 [string.rep('x', 1000)] = 4, -- long string
336 [print] = 5, -- C function
337 [checkerror] = 6, -- Lua function
338 [coroutine.running()] = 7, -- thread
339 [true] = 8, -- boolean
340 [io.stdin] = 9, -- userdata
341 [{}] = 10, -- table
342 }
343 local b = {}; for i = 1, 10 do b[i] = true end
344 for k, v in pairs(a) do
345 assert(b[v]); b[v] = undef
346 end
347 assert(next(b) == nil) -- 'b' now is empty
348end
349
350
351-- erasing values
352local t = {[{1}] = 1, [{2}] = 2, [string.rep("x ", 4)] = 3,
353 [100.3] = 4, [4] = 5}
354
355local n = 0
356for k, v in pairs( t ) do
357 n = n+1
358 assert(t[k] == v)
359 t[k] = undef
360 collectgarbage()
361 assert(t[k] == undef)
362end
363assert(n == 5)
364
365
366local function test (a)
367 assert(not pcall(table.insert, a, 2, 20));
368 table.insert(a, 10); table.insert(a, 2, 20);
369 table.insert(a, 1, -1); table.insert(a, 40);
370 table.insert(a, #a+1, 50)
371 table.insert(a, 2, -2)
372 assert(a[2] ~= undef)
373 assert(a["2"] == undef)
374 assert(not pcall(table.insert, a, 0, 20));
375 assert(not pcall(table.insert, a, #a + 2, 20));
376 assert(table.remove(a,1) == -1)
377 assert(table.remove(a,1) == -2)
378 assert(table.remove(a,1) == 10)
379 assert(table.remove(a,1) == 20)
380 assert(table.remove(a,1) == 40)
381 assert(table.remove(a,1) == 50)
382 assert(table.remove(a,1) == nil)
383 assert(table.remove(a) == nil)
384 assert(table.remove(a, #a) == nil)
385end
386
387a = {n=0, [-7] = "ban"}
388test(a)
389assert(a.n == 0 and a[-7] == "ban")
390
391a = {[-7] = "ban"};
392test(a)
393assert(a.n == nil and #a == 0 and a[-7] == "ban")
394
395a = {[-1] = "ban"}
396test(a)
397assert(#a == 0 and table.remove(a) == nil and a[-1] == "ban")
398
399a = {[0] = "ban"}
400assert(#a == 0 and table.remove(a) == "ban" and a[0] == undef)
401
402table.insert(a, 1, 10); table.insert(a, 1, 20); table.insert(a, 1, -1)
403assert(table.remove(a) == 10)
404assert(table.remove(a) == 20)
405assert(table.remove(a) == -1)
406assert(table.remove(a) == nil)
407
408a = {'c', 'd'}
409table.insert(a, 3, 'a')
410table.insert(a, 'b')
411assert(table.remove(a, 1) == 'c')
412assert(table.remove(a, 1) == 'd')
413assert(table.remove(a, 1) == 'a')
414assert(table.remove(a, 1) == 'b')
415assert(table.remove(a, 1) == nil)
416assert(#a == 0 and a.n == nil)
417
418a = {10,20,30,40}
419assert(table.remove(a, #a + 1) == nil)
420assert(not pcall(table.remove, a, 0))
421assert(a[#a] == 40)
422assert(table.remove(a, #a) == 40)
423assert(a[#a] == 30)
424assert(table.remove(a, 2) == 20)
425assert(a[#a] == 30 and #a == 2)
426
427do -- testing table library with metamethods
428 local function test (proxy, t)
429 for i = 1, 10 do
430 table.insert(proxy, 1, i)
431 end
432 assert(#proxy == 10 and #t == 10 and proxy[1] ~= undef)
433 for i = 1, 10 do
434 assert(t[i] == 11 - i)
435 end
436 table.sort(proxy)
437 for i = 1, 10 do
438 assert(t[i] == i and proxy[i] == i)
439 end
440 assert(table.concat(proxy, ",") == "1,2,3,4,5,6,7,8,9,10")
441 for i = 1, 8 do
442 assert(table.remove(proxy, 1) == i)
443 end
444 assert(#proxy == 2 and #t == 2)
445 local a, b, c = table.unpack(proxy)
446 assert(a == 9 and b == 10 and c == nil)
447 end
448
449 -- all virtual
450 local t = {}
451 local proxy = setmetatable({}, {
452 __len = function () return #t end,
453 __index = t,
454 __newindex = t,
455 })
456 test(proxy, t)
457
458 -- only __newindex
459 local count = 0
460 t = setmetatable({}, {
461 __newindex = function (t,k,v) count = count + 1; rawset(t,k,v) end})
462 test(t, t)
463 assert(count == 10) -- after first 10, all other sets are not new
464
465 -- no __newindex
466 t = setmetatable({}, {
467 __index = function (_,k) return k + 1 end,
468 __len = function (_) return 5 end})
469 assert(table.concat(t, ";") == "2;3;4;5;6")
470
471end
472
473
474if not T then
475 (Message or print)
476 ('\n >>> testC not active: skipping tests for table library on non-tables <<<\n')
477else --[
478 local debug = require'debug'
479 local tab = {10, 20, 30}
480 local mt = {}
481 local u = T.newuserdata(0)
482 checkerror("table expected", table.insert, u, 40)
483 checkerror("table expected", table.remove, u)
484 debug.setmetatable(u, mt)
485 checkerror("table expected", table.insert, u, 40)
486 checkerror("table expected", table.remove, u)
487 mt.__index = tab
488 checkerror("table expected", table.insert, u, 40)
489 checkerror("table expected", table.remove, u)
490 mt.__newindex = tab
491 checkerror("table expected", table.insert, u, 40)
492 checkerror("table expected", table.remove, u)
493 mt.__len = function () return #tab end
494 table.insert(u, 40)
495 assert(#u == 4 and #tab == 4 and u[4] == 40 and tab[4] == 40)
496 assert(table.remove(u) == 40)
497 table.insert(u, 1, 50)
498 assert(#u == 4 and #tab == 4 and u[4] == 30 and tab[1] == 50)
499
500 mt.__newindex = nil
501 mt.__len = nil
502 local tab2 = {}
503 local u2 = T.newuserdata(0)
504 debug.setmetatable(u2, {__newindex = function (_, k, v) tab2[k] = v end})
505 table.move(u, 1, 4, 1, u2)
506 assert(#tab2 == 4 and tab2[1] == tab[1] and tab2[4] == tab[4])
507
508end -- ]
509
510print('+')
511
512a = {}
513for i=1,1000 do
514 a[i] = i; a[i - 1] = undef
515end
516assert(next(a,nil) == 1000 and next(a,1000) == nil)
517
518assert(next({}) == nil)
519assert(next({}, nil) == nil)
520
521for a,b in pairs{} do error"not here" end
522for i=1,0 do error'not here' end
523for i=0,1,-1 do error'not here' end
524a = nil; for i=1,1 do assert(not a); a=1 end; assert(a)
525a = nil; for i=1,1,-1 do assert(not a); a=1 end; assert(a)
526
527do
528 print("testing floats in numeric for")
529 local a
530 -- integer count
531 a = 0; for i=1, 1, 1 do a=a+1 end; assert(a==1)
532 a = 0; for i=10000, 1e4, -1 do a=a+1 end; assert(a==1)
533 a = 0; for i=1, 0.99999, 1 do a=a+1 end; assert(a==0)
534 a = 0; for i=9999, 1e4, -1 do a=a+1 end; assert(a==0)
535 a = 0; for i=1, 0.99999, -1 do a=a+1 end; assert(a==1)
536
537 -- float count
538 a = 0; for i=0, 0.999999999, 0.1 do a=a+1 end; assert(a==10)
539 a = 0; for i=1.0, 1, 1 do a=a+1 end; assert(a==1)
540 a = 0; for i=-1.5, -1.5, 1 do a=a+1 end; assert(a==1)
541 a = 0; for i=1e6, 1e6, -1 do a=a+1 end; assert(a==1)
542 a = 0; for i=1.0, 0.99999, 1 do a=a+1 end; assert(a==0)
543 a = 0; for i=99999, 1e5, -1.0 do a=a+1 end; assert(a==0)
544 a = 0; for i=1.0, 0.99999, -1 do a=a+1 end; assert(a==1)
545end
546
547-- conversion
548a = 0; for i="10","1","-2" do a=a+1 end; assert(a==5)
549
550do -- checking types
551 local c
552 local function checkfloat (i)
553 assert(math.type(i) == "float")
554 c = c + 1
555 end
556
557 c = 0; for i = 1.0, 10 do checkfloat(i) end
558 assert(c == 10)
559
560 c = 0; for i = -1, -10, -1.0 do checkfloat(i) end
561 assert(c == 10)
562
563 local function checkint (i)
564 assert(math.type(i) == "integer")
565 c = c + 1
566 end
567
568 local m = math.maxinteger
569 c = 0; for i = m, m - 10, -1 do checkint(i) end
570 assert(c == 11)
571
572 c = 0; for i = 1, 10.9 do checkint(i) end
573 assert(c == 10)
574
575 c = 0; for i = 10, 0.001, -1 do checkint(i) end
576 assert(c == 10)
577
578 c = 0; for i = 1, "10.8" do checkint(i) end
579 assert(c == 10)
580
581 c = 0; for i = 9, "3.4", -1 do checkint(i) end
582 assert(c == 6)
583
584 c = 0; for i = 0, " -3.4 ", -1 do checkint(i) end
585 assert(c == 4)
586
587 c = 0; for i = 100, "96.3", -2 do checkint(i) end
588 assert(c == 2)
589
590 c = 0; for i = 1, math.huge do if i > 10 then break end; checkint(i) end
591 assert(c == 10)
592
593 c = 0; for i = -1, -math.huge, -1 do
594 if i < -10 then break end; checkint(i)
595 end
596 assert(c == 10)
597
598
599 for i = math.mininteger, -10e100 do assert(false) end
600 for i = math.maxinteger, 10e100, -1 do assert(false) end
601
602end
603
604collectgarbage()
605
606
607-- testing generic 'for'
608
609local function f (n, p)
610 local t = {}; for i=1,p do t[i] = i*10 end
611 return function (_,n)
612 if n > 0 then
613 n = n-1
614 return n, table.unpack(t)
615 end
616 end, nil, n
617end
618
619local x = 0
620for n,a,b,c,d in f(5,3) do
621 x = x+1
622 assert(a == 10 and b == 20 and c == 30 and d == nil)
623end
624assert(x == 5)
625
626
627
628-- testing __pairs and __ipairs metamethod
629a = {}
630do
631 local x,y,z = pairs(a)
632 assert(type(x) == 'function' and y == a and z == nil)
633end
634
635local function foo (e,i)
636 assert(e == a)
637 if i <= 10 then return i+1, i+2 end
638end
639
640local function foo1 (e,i)
641 i = i + 1
642 assert(e == a)
643 if i <= e.n then return i,a[i] end
644end
645
646setmetatable(a, {__pairs = function (x) return foo, x, 0 end})
647
648local i = 0
649for k,v in pairs(a) do
650 i = i + 1
651 assert(k == i and v == k+1)
652end
653
654a.n = 5
655a[3] = 30
656
657-- testing ipairs with metamethods
658a = {n=10}
659setmetatable(a, { __index = function (t,k)
660 if k <= t.n then return k * 10 end
661 end})
662i = 0
663for k,v in ipairs(a) do
664 i = i + 1
665 assert(k == i and v == i * 10)
666end
667assert(i == a.n)
668
669print"OK"
diff --git a/testes/pm.lua b/testes/pm.lua
new file mode 100644
index 00000000..e517c8b6
--- /dev/null
+++ b/testes/pm.lua
@@ -0,0 +1,374 @@
1-- $Id: pm.lua,v 1.50 2018/03/12 14:19:36 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, 127)) .. string.char(range(128, 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] == undef)
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..6eb9b706
--- /dev/null
+++ b/testes/sort.lua
@@ -0,0 +1,310 @@
1-- $Id: sort.lua,v 1.39 2018/03/12 13:51:02 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] == undef 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..dd720b65
--- /dev/null
+++ b/testes/strings.lua
@@ -0,0 +1,382 @@
1-- $Id: strings.lua,v 1.89 2018/06/19 12:25:15 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 checkQ(math.huge)
190 checkQ(-math.huge)
191 assert(string.format("%q", 0/0) == "(0/0)") -- NaN
192 checkerror("no literal", string.format, "%q", {})
193end
194
195assert(string.format("\0%s\0", "\0\0\1") == "\0\0\0\1\0")
196checkerror("contains zeros", string.format, "%10s", "\0")
197
198-- format x tostring
199assert(string.format("%s %s", nil, true) == "nil true")
200assert(string.format("%s %.4s", false, true) == "false true")
201assert(string.format("%.3s %.3s", false, true) == "fal tru")
202local m = setmetatable({}, {__tostring = function () return "hello" end,
203 __name = "hi"})
204assert(string.format("%s %.10s", m, m) == "hello hello")
205getmetatable(m).__tostring = nil -- will use '__name' from now on
206assert(string.format("%.4s", m) == "hi: ")
207
208getmetatable(m).__tostring = function () return {} end
209checkerror("'__tostring' must return a string", tostring, m)
210
211
212assert(string.format("%x", 0.0) == "0")
213assert(string.format("%02x", 0.0) == "00")
214assert(string.format("%08X", 0xFFFFFFFF) == "FFFFFFFF")
215assert(string.format("%+08d", 31501) == "+0031501")
216assert(string.format("%+08d", -30927) == "-0030927")
217
218
219do -- longest number that can be formatted
220 local i = 1
221 local j = 10000
222 while i + 1 < j do -- binary search for maximum finite float
223 local m = (i + j) // 2
224 if 10^m < math.huge then i = m else j = m end
225 end
226 assert(10^i < math.huge and 10^j == math.huge)
227 local s = string.format('%.99f', -(10^i))
228 assert(string.len(s) >= i + 101)
229 assert(tonumber(s) == -(10^i))
230end
231
232
233-- testing large numbers for format
234do -- assume at least 32 bits
235 local max, min = 0x7fffffff, -0x80000000 -- "large" for 32 bits
236 assert(string.sub(string.format("%8x", -1), -8) == "ffffffff")
237 assert(string.format("%x", max) == "7fffffff")
238 assert(string.sub(string.format("%x", min), -8) == "80000000")
239 assert(string.format("%d", max) == "2147483647")
240 assert(string.format("%d", min) == "-2147483648")
241 assert(string.format("%u", 0xffffffff) == "4294967295")
242 assert(string.format("%o", 0xABCD) == "125715")
243
244 max, min = 0x7fffffffffffffff, -0x8000000000000000
245 if max > 2.0^53 then -- only for 64 bits
246 assert(string.format("%x", (2^52 | 0) - 1) == "fffffffffffff")
247 assert(string.format("0x%8X", 0x8f000003) == "0x8F000003")
248 assert(string.format("%d", 2^53) == "9007199254740992")
249 assert(string.format("%i", -2^53) == "-9007199254740992")
250 assert(string.format("%x", max) == "7fffffffffffffff")
251 assert(string.format("%x", min) == "8000000000000000")
252 assert(string.format("%d", max) == "9223372036854775807")
253 assert(string.format("%d", min) == "-9223372036854775808")
254 assert(string.format("%u", ~(-1 << 64)) == "18446744073709551615")
255 assert(tostring(1234567890123) == '1234567890123')
256 end
257end
258
259
260do print("testing 'format %a %A'")
261 local function matchhexa (n)
262 local s = string.format("%a", n)
263 -- result matches ISO C requirements
264 assert(string.find(s, "^%-?0x[1-9a-f]%.?[0-9a-f]*p[-+]?%d+$"))
265 assert(tonumber(s) == n) -- and has full precision
266 s = string.format("%A", n)
267 assert(string.find(s, "^%-?0X[1-9A-F]%.?[0-9A-F]*P[-+]?%d+$"))
268 assert(tonumber(s) == n)
269 end
270 for _, n in ipairs{0.1, -0.1, 1/3, -1/3, 1e30, -1e30,
271 -45/247, 1, -1, 2, -2, 3e-20, -3e-20} do
272 matchhexa(n)
273 end
274
275 assert(string.find(string.format("%A", 0.0), "^0X0%.?0?P%+?0$"))
276 assert(string.find(string.format("%a", -0.0), "^%-0x0%.?0?p%+?0$"))
277
278 if not _port then -- test inf, -inf, NaN, and -0.0
279 assert(string.find(string.format("%a", 1/0), "^inf"))
280 assert(string.find(string.format("%A", -1/0), "^%-INF"))
281 assert(string.find(string.format("%a", 0/0), "^%-?nan"))
282 assert(string.find(string.format("%a", -0.0), "^%-0x0"))
283 end
284
285 if not pcall(string.format, "%.3a", 0) then
286 (Message or print)("\n >>> modifiers for format '%a' not available <<<\n")
287 else
288 assert(string.find(string.format("%+.2A", 12), "^%+0X%x%.%x0P%+?%d$"))
289 assert(string.find(string.format("%.4A", -12), "^%-0X%x%.%x000P%+?%d$"))
290 end
291end
292
293
294-- errors in format
295
296local function check (fmt, msg)
297 checkerror(msg, string.format, fmt, 10)
298end
299
300local aux = string.rep('0', 600)
301check("%100.3d", "too long")
302check("%1"..aux..".3d", "too long")
303check("%1.100d", "too long")
304check("%10.1"..aux.."004d", "too long")
305check("%t", "invalid option")
306check("%"..aux.."d", "repeated flags")
307check("%d %d", "no value")
308
309
310assert(load("return 1\n--comment without ending EOL")() == 1)
311
312
313checkerror("table expected", table.concat, 3)
314assert(table.concat{} == "")
315assert(table.concat({}, 'x') == "")
316assert(table.concat({'\0', '\0\1', '\0\1\2'}, '.\0.') == "\0.\0.\0\1.\0.\0\1\2")
317local a = {}; for i=1,300 do a[i] = "xuxu" end
318assert(table.concat(a, "123").."123" == string.rep("xuxu123", 300))
319assert(table.concat(a, "b", 20, 20) == "xuxu")
320assert(table.concat(a, "", 20, 21) == "xuxuxuxu")
321assert(table.concat(a, "x", 22, 21) == "")
322assert(table.concat(a, "3", 299) == "xuxu3xuxu")
323assert(table.concat({}, "x", maxi, maxi - 1) == "")
324assert(table.concat({}, "x", mini + 1, mini) == "")
325assert(table.concat({}, "x", maxi, mini) == "")
326assert(table.concat({[maxi] = "alo"}, "x", maxi, maxi) == "alo")
327assert(table.concat({[maxi] = "alo", [maxi - 1] = "y"}, "-", maxi - 1, maxi)
328 == "y-alo")
329
330assert(not pcall(table.concat, {"a", "b", {}}))
331
332a = {"a","b","c"}
333assert(table.concat(a, ",", 1, 0) == "")
334assert(table.concat(a, ",", 1, 1) == "a")
335assert(table.concat(a, ",", 1, 2) == "a,b")
336assert(table.concat(a, ",", 2) == "b,c")
337assert(table.concat(a, ",", 3) == "c")
338assert(table.concat(a, ",", 4) == "")
339
340if not _port then
341
342 local locales = { "ptb", "pt_BR.iso88591", "ISO-8859-1" }
343 local function trylocale (w)
344 for i = 1, #locales do
345 if os.setlocale(locales[i], w) then
346 print(string.format("'%s' locale set to '%s'", w, locales[i]))
347 return locales[i]
348 end
349 end
350 print(string.format("'%s' locale not found", w))
351 return false
352 end
353
354 if trylocale("collate") then
355 assert("alo" < "álo" and "álo" < "amo")
356 end
357
358 if trylocale("ctype") then
359 assert(string.gsub("áéíóú", "%a", "x") == "xxxxx")
360 assert(string.gsub("áÁéÉ", "%l", "x") == "xÁxÉ")
361 assert(string.gsub("áÁéÉ", "%u", "x") == "áxéx")
362 assert(string.upper"áÁé{xuxu}ção" == "ÁÁÉ{XUXU}ÇÃO")
363 end
364
365 os.setlocale("C")
366 assert(os.setlocale() == 'C')
367 assert(os.setlocale(nil, "numeric") == 'C')
368
369end
370
371
372-- bug in Lua 5.3.2
373-- 'gmatch' iterator does not work across coroutines
374do
375 local f = string.gmatch("1 2 3 4 5", "%d+")
376 assert(f() == "1")
377 co = coroutine.wrap(f)
378 assert(co() == "2")
379end
380
381print('OK')
382
diff --git a/testes/tpack.lua b/testes/tpack.lua
new file mode 100644
index 00000000..0e639cc5
--- /dev/null
+++ b/testes/tpack.lua
@@ -0,0 +1,324 @@
1-- $Id: tpack.lua,v 1.14 2018/06/04 14:26:32 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 checkerror("unfinished string", unpack, "zc10000000", "alo")
208
209 for i = 2, NB do
210 local s1 = pack("s" .. i, s)
211 assert(unpack("s" .. i, s1) == s and #s1 == #s + i)
212 end
213end
214
215do
216 local x = pack("s", "alo")
217 checkerror("too short", unpack, "s", x:sub(1, -2))
218 checkerror("too short", unpack, "c5", "abcd")
219 checkerror("out of limits", pack, "s100", "alo")
220end
221
222do
223 assert(pack("c0", "") == "")
224 assert(packsize("c0") == 0)
225 assert(unpack("c0", "") == "")
226 assert(pack("<! c3", "abc") == "abc")
227 assert(packsize("<! c3") == 3)
228 assert(pack(">!4 c6", "abcdef") == "abcdef")
229 assert(pack("c3", "123") == "123")
230 assert(pack("c0", "") == "")
231 assert(pack("c8", "123456") == "123456\0\0")
232 assert(pack("c88", "") == string.rep("\0", 88))
233 assert(pack("c188", "ab") == "ab" .. string.rep("\0", 188 - 2))
234 local a, b, c = unpack("!4 z c3", "abcdefghi\0xyz")
235 assert(a == "abcdefghi" and b == "xyz" and c == 14)
236 checkerror("longer than", pack, "c3", "1234")
237end
238
239
240-- testing multiple types and sequence
241do
242 local x = pack("<b h b f d f n i", 1, 2, 3, 4, 5, 6, 7, 8)
243 assert(#x == packsize("<b h b f d f n i"))
244 local a, b, c, d, e, f, g, h = unpack("<b h b f d f n i", x)
245 assert(a == 1 and b == 2 and c == 3 and d == 4 and e == 5 and f == 6 and
246 g == 7 and h == 8)
247end
248
249print "testing alignment"
250do
251 assert(pack(" < i1 i2 ", 2, 3) == "\2\3\0") -- no alignment by default
252 local x = pack(">!8 b Xh i4 i8 c1 Xi8", -12, 100, 200, "\xEC")
253 assert(#x == packsize(">!8 b Xh i4 i8 c1 Xi8"))
254 assert(x == "\xf4" .. "\0\0\0" ..
255 "\0\0\0\100" ..
256 "\0\0\0\0\0\0\0\xC8" ..
257 "\xEC" .. "\0\0\0\0\0\0\0")
258 local a, b, c, d, pos = unpack(">!8 c1 Xh i4 i8 b Xi8 XI XH", x)
259 assert(a == "\xF4" and b == 100 and c == 200 and d == -20 and (pos - 1) == #x)
260
261 x = pack(">!4 c3 c4 c2 z i4 c5 c2 Xi4",
262 "abc", "abcd", "xz", "hello", 5, "world", "xy")
263 assert(x == "abcabcdxzhello\0\0\0\0\0\5worldxy\0")
264 local a, b, c, d, e, f, g, pos = unpack(">!4 c3 c4 c2 z i4 c5 c2 Xh Xi4", x)
265 assert(a == "abc" and b == "abcd" and c == "xz" and d == "hello" and
266 e == 5 and f == "world" and g == "xy" and (pos - 1) % 4 == 0)
267
268 x = pack(" b b Xd b Xb x", 1, 2, 3)
269 assert(packsize(" b b Xd b Xb x") == 4)
270 assert(x == "\1\2\3\0")
271 a, b, c, pos = unpack("bbXdb", x)
272 assert(a == 1 and b == 2 and c == 3 and pos == #x)
273
274 -- only alignment
275 assert(packsize("!8 xXi8") == 8)
276 local pos = unpack("!8 xXi8", "0123456701234567"); assert(pos == 9)
277 assert(packsize("!8 xXi2") == 2)
278 local pos = unpack("!8 xXi2", "0123456701234567"); assert(pos == 3)
279 assert(packsize("!2 xXi2") == 2)
280 local pos = unpack("!2 xXi2", "0123456701234567"); assert(pos == 3)
281 assert(packsize("!2 xXi8") == 2)
282 local pos = unpack("!2 xXi8", "0123456701234567"); assert(pos == 3)
283 assert(packsize("!16 xXi16") == 16)
284 local pos = unpack("!16 xXi16", "0123456701234567"); assert(pos == 17)
285
286 checkerror("invalid next option", pack, "X")
287 checkerror("invalid next option", unpack, "XXi", "")
288 checkerror("invalid next option", unpack, "X i", "")
289 checkerror("invalid next option", pack, "Xc1")
290end
291
292do -- testing initial position
293 local x = pack("i4i4i4i4", 1, 2, 3, 4)
294 for pos = 1, 16, 4 do
295 local i, p = unpack("i4", x, pos)
296 assert(i == pos//4 + 1 and p == pos + 4)
297 end
298
299 -- with alignment
300 for pos = 0, 12 do -- will always round position to power of 2
301 local i, p = unpack("!4 i4", x, pos + 1)
302 assert(i == (pos + 3)//4 + 1 and p == i*4 + 1)
303 end
304
305 -- negative indices
306 local i, p = unpack("!4 i4", x, -4)
307 assert(i == 4 and p == 17)
308 local i, p = unpack("!4 i4", x, -7)
309 assert(i == 4 and p == 17)
310 local i, p = unpack("!4 i4", x, -#x)
311 assert(i == 1 and p == 5)
312
313 -- limits
314 for i = 1, #x + 1 do
315 assert(unpack("c0", x, i) == "")
316 end
317 checkerror("out of string", unpack, "c0", x, 0)
318 checkerror("out of string", unpack, "c0", x, #x + 2)
319 checkerror("out of string", unpack, "c0", x, -(#x + 1))
320
321end
322
323print "OK"
324
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..4d5ce4ab
--- /dev/null
+++ b/testes/vararg.lua
@@ -0,0 +1,151 @@
1-- $Id: vararg.lua,v 1.29 2018/03/12 14:19:36 roberto Exp $
2-- See Copyright Notice in file all.lua
3
4print('testing vararg')
5
6function f(a, ...)
7 local x = {n = select('#', ...), ...}
8 for i = 1, x.n do assert(a[i] == x[i]) end
9 return x.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(vararg().n == 0)
29assert(vararg(nil, nil).n == 2)
30
31assert(c12(1,2)==55)
32a,b = assert(call(c12, {1,2}))
33assert(a == 55 and b == 2)
34a = call(c12, {1,2;n=2})
35assert(a == 55 and b == 2)
36a = call(c12, {1,2;n=1})
37assert(not a)
38assert(c12(1,2,3) == false)
39local a = vararg(call(next, {_G,nil;n=2}))
40local b,c = next(_G)
41assert(a[1] == b and a[2] == c and a.n == 2)
42a = vararg(call(call, {c12, {1,2}}))
43assert(a.n == 2 and a[1] == 55 and a[2] == 2)
44a = call(print, {'+'})
45assert(a == nil)
46
47local t = {1, 10}
48function t:f (...) local arg = {...}; return self[...]+#arg end
49assert(t:f(1,4) == 3 and t:f(2) == 11)
50print('+')
51
52lim = 20
53local i, a = 1, {}
54while i <= lim do a[i] = i+0.3; i=i+1 end
55
56function f(a, b, c, d, ...)
57 local more = {...}
58 assert(a == 1.3 and more[1] == 5.3 and
59 more[lim-4] == lim+0.3 and not more[lim-3])
60end
61
62function g(a,b,c)
63 assert(a == 1.3 and b == 2.3 and c == 3.3)
64end
65
66call(f, a)
67call(g, a)
68
69a = {}
70i = 1
71while i <= lim do a[i] = i; i=i+1 end
72assert(call(math.max, a) == lim)
73
74print("+")
75
76
77-- new-style varargs
78
79function oneless (a, ...) return ... end
80
81function f (n, a, ...)
82 local b
83 assert(arg == _G.arg) -- no local 'arg'
84 if n == 0 then
85 local b, c, d = ...
86 return a, b, c, d, oneless(oneless(oneless(...)))
87 else
88 n, b, a = n-1, ..., a
89 assert(b == ...)
90 return f(n, a, ...)
91 end
92end
93
94a,b,c,d,e = assert(f(10,5,4,3,2,1))
95assert(a==5 and b==4 and c==3 and d==2 and e==1)
96
97a,b,c,d,e = f(4)
98assert(a==nil and b==nil and c==nil and d==nil and e==nil)
99
100
101-- varargs for main chunks
102f = load[[ return {...} ]]
103x = f(2,3)
104assert(x[1] == 2 and x[2] == 3 and x[3] == undef)
105
106
107f = load[[
108 local x = {...}
109 for i=1,select('#', ...) do assert(x[i] == select(i, ...)) end
110 assert(x[select('#', ...)+1] == undef)
111 return true
112]]
113
114assert(f("a", "b", nil, {}, assert))
115assert(f())
116
117a = {select(3, table.unpack{10,20,30,40})}
118assert(#a == 2 and a[1] == 30 and a[2] == 40)
119a = {select(1)}
120assert(next(a) == nil)
121a = {select(-1, 3, 5, 7)}
122assert(a[1] == 7 and a[2] == undef)
123a = {select(-2, 3, 5, 7)}
124assert(a[1] == 5 and a[2] == 7 and a[3] == undef)
125pcall(select, 10000)
126pcall(select, -10000)
127
128
129-- bug in 5.2.2
130
131function f(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10,
132p11, p12, p13, p14, p15, p16, p17, p18, p19, p20,
133p21, p22, p23, p24, p25, p26, p27, p28, p29, p30,
134p31, p32, p33, p34, p35, p36, p37, p38, p39, p40,
135p41, p42, p43, p44, p45, p46, p48, p49, p50, ...)
136 local a1,a2,a3,a4,a5,a6,a7
137 local a8,a9,a10,a11,a12,a13,a14
138end
139
140-- assertion fail here
141f()
142
143-- missing arguments in tail call
144do
145 local function f(a,b,c) return c, b end
146 local function g() return f(1,2) end
147 local a, b = g()
148 assert(a == nil and b == 2)
149end
150print('OK')
151
diff --git a/testes/verybig.lua b/testes/verybig.lua
new file mode 100644
index 00000000..5b29dea7
--- /dev/null
+++ b/testes/verybig.lua
@@ -0,0 +1,152 @@
1-- $Id: verybig.lua,v 1.27 2018/03/09 14:23:48 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"] = undef
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