xref: /freebsd/sys/contrib/openzfs/tests/zfs-tests/tests/functional/channel_program/lua_core/tst.lib_base.lua (revision 61145dc2b94f12f6a47344fb9aac702321880e43)
1--SPDX-License-Identifier: MIT
2--[[
3--*****************************************************************************
4--* Copyright (C) 1994-2016 Lua.org, PUC-Rio.
5--*
6--* Permission is hereby granted, free of charge, to any person obtaining
7--* a copy of this software and associated documentation files (the
8--* "Software"), to deal in the Software without restriction, including
9--* without limitation the rights to use, copy, modify, merge, publish,
10--* distribute, sublicense, and/or sell copies of the Software, and to
11--* permit persons to whom the Software is furnished to do so, subject to
12--* the following conditions:
13--*
14--* The above copyright notice and this permission notice shall be
15--* included in all copies or substantial portions of the Software.
16--*
17--* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18--* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19--* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20--* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
21--* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
22--* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
23--* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24--*****************************************************************************
25--]]
26
27-- testing metatables
28
29X = 20; B = 30
30
31_ENV = setmetatable({}, {__index=_G})
32
33collectgarbage()
34
35X = X+10
36assert(X == 30 and _G.X == 20)
37B = false
38assert(B == false)
39B = nil
40assert(B == 30)
41
42assert(getmetatable{} == nil)
43assert(getmetatable(4) == nil)
44assert(getmetatable(nil) == nil)
45a={name = "NAME"}; setmetatable(a, {__metatable = "xuxu",
46                    __tostring=function(x) return x.name end})
47assert(getmetatable(a) == "xuxu")
48assert(tostring(a) == "NAME")
49
50local a, t = {10,20,30; x="10", y="20"}, {}
51assert(setmetatable(a,t) == a)
52assert(getmetatable(a) == t)
53assert(setmetatable(a,nil) == a)
54assert(getmetatable(a) == nil)
55assert(setmetatable(a,t) == a)
56
57
58function f (t, i, e)
59  assert(not e)
60  local p = rawget(t, "parent")
61  return (p and p[i]+3), "dummy return"
62end
63
64t.__index = f
65
66a.parent = {z=25, x=12, [4] = 24}
67assert(a[1] == 10 and a.z == 28 and a[4] == 27 and a.x == "10")
68
69collectgarbage()
70
71a = setmetatable({}, t)
72function f(t, i, v) rawset(t, i, v-3) end
73setmetatable(t, t)   -- causes a bug in 5.1 !
74t.__newindex = f
75a[1] = 30; a.x = "101"; a[5] = 200
76assert(a[1] == 27 and a.x == 98 and a[5] == 197)
77
78
79local c = {}
80a = setmetatable({}, t)
81t.__newindex = c
82a[1] = 10; a[2] = 20; a[3] = 90
83assert(c[1] == 10 and c[2] == 20 and c[3] == 90)
84
85
86do
87  local a;
88  a = setmetatable({}, {__index = setmetatable({},
89                     {__index = setmetatable({},
90                     {__index = function (_,n) return a[n-3]+4, "lixo" end})})})
91  a[0] = 20
92  for i=0,10 do
93    assert(a[i*3] == 20 + i*4)
94  end
95end
96
97
98do  -- newindex
99  local foi
100  local a = {}
101  for i=1,10 do a[i] = 0; a['a'..i] = 0; end
102  setmetatable(a, {__newindex = function (t,k,v) foi=true; rawset(t,k,v) end})
103  foi = false; a[1]=0; assert(not foi)
104  foi = false; a['a1']=0; assert(not foi)
105  foi = false; a['a11']=0; assert(foi)
106  foi = false; a[11]=0; assert(foi)
107  foi = false; a[1]=nil; assert(not foi)
108  foi = false; a[1]=nil; assert(foi)
109end
110
111
112setmetatable(t, nil)
113function f (t, ...) return t, {...} end
114t.__call = f
115
116do
117  local x,y = a(table.unpack{'a', 1})
118  assert(x==a and y[1]=='a' and y[2]==1 and y[3]==nil)
119  x,y = a()
120  assert(x==a and y[1]==nil)
121end
122
123
124local b = setmetatable({}, t)
125setmetatable(b,t)
126
127function f(op)
128  return function (...) cap = {[0] = op, ...} ; return (...) end
129end
130t.__add = f("add")
131t.__sub = f("sub")
132t.__mul = f("mul")
133t.__div = f("div")
134t.__mod = f("mod")
135t.__unm = f("unm")
136t.__pow = f("pow")
137t.__len = f("len")
138
139assert(b+5 == b)
140assert(cap[0] == "add" and cap[1] == b and cap[2] == 5 and cap[3]==nil)
141assert(b+'5' == b)
142assert(cap[0] == "add" and cap[1] == b and cap[2] == '5' and cap[3]==nil)
143assert(5+b == 5)
144assert(cap[0] == "add" and cap[1] == 5 and cap[2] == b and cap[3]==nil)
145assert('5'+b == '5')
146assert(cap[0] == "add" and cap[1] == '5' and cap[2] == b and cap[3]==nil)
147b=b-3; assert(getmetatable(b) == t)
148assert(5-a == 5)
149assert(cap[0] == "sub" and cap[1] == 5 and cap[2] == a and cap[3]==nil)
150assert('5'-a == '5')
151assert(cap[0] == "sub" and cap[1] == '5' and cap[2] == a and cap[3]==nil)
152assert(a*a == a)
153assert(cap[0] == "mul" and cap[1] == a and cap[2] == a and cap[3]==nil)
154assert(a/0 == a)
155assert(cap[0] == "div" and cap[1] == a and cap[2] == 0 and cap[3]==nil)
156assert(a%2 == a)
157assert(cap[0] == "mod" and cap[1] == a and cap[2] == 2 and cap[3]==nil)
158assert(-a == a)
159assert(cap[0] == "unm" and cap[1] == a)
160assert(a^4 == a)
161assert(cap[0] == "pow" and cap[1] == a and cap[2] == 4 and cap[3]==nil)
162assert(a^'4' == a)
163assert(cap[0] == "pow" and cap[1] == a and cap[2] == '4' and cap[3]==nil)
164assert(4^a == 4)
165assert(cap[0] == "pow" and cap[1] == 4 and cap[2] == a and cap[3]==nil)
166assert('4'^a == '4')
167assert(cap[0] == "pow" and cap[1] == '4' and cap[2] == a and cap[3]==nil)
168assert(#a == a)
169assert(cap[0] == "len" and cap[1] == a)
170
171
172-- test for rawlen
173t = setmetatable({1,2,3}, {__len = function () return 10 end})
174assert(#t == 10 and rawlen(t) == 3)
175assert(rawlen"abc" == 3)
176assert(rawlen(string.rep('a', 1000)) == 1000)
177
178t = {}
179t.__lt = function (a,b,c)
180  collectgarbage()
181  assert(c == nil)
182  if type(a) == 'table' then a = a.x end
183  if type(b) == 'table' then b = b.x end
184 return a<b, "dummy"
185end
186
187function Op(x) return setmetatable({x=x}, t) end
188
189local function test ()
190  assert(not(Op(1)<Op(1)) and (Op(1)<Op(2)) and not(Op(2)<Op(1)))
191  assert(not(1 < Op(1)) and (Op(1) < 2) and not(2 < Op(1)))
192  assert(not(Op('a')<Op('a')) and (Op('a')<Op('b')) and not(Op('b')<Op('a')))
193  assert(not('a' < Op('a')) and (Op('a') < 'b') and not(Op('b') < Op('a')))
194  assert((Op(1)<=Op(1)) and (Op(1)<=Op(2)) and not(Op(2)<=Op(1)))
195  assert((Op('a')<=Op('a')) and (Op('a')<=Op('b')) and not(Op('b')<=Op('a')))
196  assert(not(Op(1)>Op(1)) and not(Op(1)>Op(2)) and (Op(2)>Op(1)))
197  assert(not(Op('a')>Op('a')) and not(Op('a')>Op('b')) and (Op('b')>Op('a')))
198  assert((Op(1)>=Op(1)) and not(Op(1)>=Op(2)) and (Op(2)>=Op(1)))
199  assert((1 >= Op(1)) and not(1 >= Op(2)) and (Op(2) >= 1))
200  assert((Op('a')>=Op('a')) and not(Op('a')>=Op('b')) and (Op('b')>=Op('a')))
201  assert(('a' >= Op('a')) and not(Op('a') >= 'b') and (Op('b') >= Op('a')))
202end
203
204test()
205
206t.__le = function (a,b,c)
207  assert(c == nil)
208  if type(a) == 'table' then a = a.x end
209  if type(b) == 'table' then b = b.x end
210 return a<=b, "dummy"
211end
212
213test()  -- retest comparisons, now using both `lt' and `le'
214
215
216-- test `partial order'
217
218local function Set(x)
219  local y = {}
220  for _,k in pairs(x) do y[k] = 1 end
221  return setmetatable(y, t)
222end
223
224t.__lt = function (a,b)
225  for k in pairs(a) do
226    if not b[k] then return false end
227    b[k] = nil
228  end
229  return next(b) ~= nil
230end
231
232t.__le = nil
233
234assert(Set{1,2,3} < Set{1,2,3,4})
235assert(not(Set{1,2,3,4} < Set{1,2,3,4}))
236assert((Set{1,2,3,4} <= Set{1,2,3,4}))
237assert((Set{1,2,3,4} >= Set{1,2,3,4}))
238assert((Set{1,3} <= Set{3,5}))   -- wrong!! model needs a `le' method ;-)
239
240t.__le = function (a,b)
241  for k in pairs(a) do
242    if not b[k] then return false end
243  end
244  return true
245end
246
247assert(not (Set{1,3} <= Set{3,5}))   -- now its OK!
248assert(not(Set{1,3} <= Set{3,5}))
249assert(not(Set{1,3} >= Set{3,5}))
250
251t.__eq = function (a,b)
252  for k in pairs(a) do
253    if not b[k] then return false end
254    b[k] = nil
255  end
256  return next(b) == nil
257end
258
259local s = Set{1,3,5}
260assert(s == Set{3,5,1})
261assert(not rawequal(s, Set{3,5,1}))
262assert(rawequal(s, s))
263assert(Set{1,3,5,1} == Set{3,5,1})
264assert(Set{1,3,5} ~= Set{3,5,1,6})
265t[Set{1,3,5}] = 1
266assert(t[Set{1,3,5}] == nil)   -- `__eq' is not valid for table accesses
267
268
269t.__concat = function (a,b,c)
270  assert(c == nil)
271  if type(a) == 'table' then a = a.val end
272  if type(b) == 'table' then b = b.val end
273  if A then return a..b
274  else
275    return setmetatable({val=a..b}, t)
276  end
277end
278
279c = {val="c"}; setmetatable(c, t)
280d = {val="d"}; setmetatable(d, t)
281
282A = true
283assert(c..d == 'cd')
284assert(0 .."a".."b"..c..d.."e".."f"..(5+3).."g" == "0abcdef8g")
285
286A = false
287assert((c..d..c..d).val == 'cdcd')
288x = c..d
289assert(getmetatable(x) == t and x.val == 'cd')
290x = 0 .."a".."b"..c..d.."e".."f".."g"
291assert(x.val == "0abcdefg")
292
293
294-- concat metamethod x numbers (bug in 5.1.1)
295c = {}
296local x
297setmetatable(c, {__concat = function (a,b)
298  assert(type(a) == "number" and b == c or type(b) == "number" and a == c)
299  return c
300end})
301assert(c..5 == c and 5 .. c == c)
302assert(4 .. c .. 5 == c and 4 .. 5 .. 6 .. 7 .. c == c)
303
304
305-- test comparison compatibilities
306local t1, t2, c, d
307t1 = {};  c = {}; setmetatable(c, t1)
308d = {}
309t1.__eq = function () return true end
310t1.__lt = function () return true end
311setmetatable(d, t1)
312assert(c == d and c < d and not(d <= c))
313t2 = {}
314t2.__eq = t1.__eq
315t2.__lt = t1.__lt
316setmetatable(d, t2)
317assert(c == d and c < d and not(d <= c))
318
319
320
321-- test for several levels of calls
322local i
323local tt = {
324  __call = function (t, ...)
325    i = i+1
326    if t.f then return t.f(...)
327    else return {...}
328    end
329  end
330}
331
332local a = setmetatable({}, tt)
333local b = setmetatable({f=a}, tt)
334local c = setmetatable({f=b}, tt)
335
336i = 0
337x = c(3,4,5)
338assert(i == 3 and x[1] == 3 and x[3] == 5)
339
340
341assert(_G.X == 20)
342
343
344local _g = _G
345_ENV = setmetatable({}, {__index=function (_,k) return _g[k] end})
346
347
348a = {}
349rawset(a, "x", 1, 2, 3)
350assert(a.x == 1 and rawget(a, "x", 3) == 1)
351
352
353-- bug in 5.1
354T, K, V = nil
355grandparent = {}
356grandparent.__newindex = function(t,k,v) T=t; K=k; V=v end
357
358parent = {}
359parent.__newindex = parent
360setmetatable(parent, grandparent)
361
362child = setmetatable({}, parent)
363child.foo = 10      --> CRASH (on some machines)
364assert(T == parent and K == "foo" and V == 10)
365
366
367-- testing 'tonumber'
368assert(tonumber{} == nil)
369assert(tonumber('-012') == -010-2)
370assert(tonumber("0xffffffffffff") == 2^(4*12) - 1)
371assert(tonumber("0x"..string.rep("f", 150)) == 2^(4*150) - 1)
372
373-- testing 'tonumber' with base
374assert(tonumber('  001010  ', 2) == 10)
375assert(tonumber('  001010  ', 10) == 1010)
376assert(tonumber('  -1010  ', 2) == -10)
377assert(tonumber('10', 36) == 36)
378assert(tonumber('  -10  ', 36) == -36)
379assert(tonumber('  +1Z  ', 36) == 36 + 35)
380assert(tonumber('  -1z  ', 36) == -36 + -35)
381assert(tonumber('-fFfa', 16) == -(10+(16*(15+(16*(15+(16*15)))))))
382assert(tonumber(string.rep('1', 42), 2) + 1 == 2^42)
383assert(tonumber(string.rep('1', 34), 2) + 1 == 2^34)
384assert(tonumber('ffffFFFF', 16)+1 == 2^32)
385assert(tonumber('0ffffFFFF', 16)+1 == 2^32)
386assert(tonumber('-0ffffffFFFF', 16) - 1 == -2^40)
387for i = 2,36 do
388  assert(tonumber('\t10000000000\t', i) == i^10)
389end
390
391-- testing 'tonumber' for invalid formats
392function f(...)
393  if select('#', ...) == 1 then
394    return (...)
395  else
396    return "***"
397  end
398end
399
400assert(f(tonumber('fFfa', 15)) == nil)
401assert(f(tonumber('099', 8)) == nil)
402assert(f(tonumber('1\0', 2)) == nil)
403assert(f(tonumber('', 8)) == nil)
404assert(f(tonumber('  ', 9)) == nil)
405assert(f(tonumber('0xf', 10)) == nil)
406
407assert(f(tonumber('inf')) == nil)
408assert(f(tonumber(' INF ')) == nil)
409assert(f(tonumber('Nan')) == nil)
410assert(f(tonumber('nan')) == nil)
411
412assert(f(tonumber('')) == nil)
413assert(f(tonumber('1  a')) == nil)
414assert(f(tonumber('1\0')) == nil)
415assert(f(tonumber('1 \0')) == nil)
416assert(f(tonumber('1\0 ')) == nil)
417assert(f(tonumber('e1')) == nil)
418assert(f(tonumber('e  1')) == nil)
419
420
421-- testing 'tonumber' for invalid hexadecimal formats
422assert(tonumber('0x') == nil)
423assert(tonumber('x') == nil)
424assert(tonumber('x3') == nil)
425assert(tonumber('00x2') == nil)
426assert(tonumber('0x 2') == nil)
427assert(tonumber('0 x2') == nil)
428assert(tonumber('23x') == nil)
429assert(tonumber('- 0xaa') == nil)
430
431
432-- testing hexadecimal numerals
433assert(tonumber('+0x2') == 2)
434assert(tonumber('-0xaA') == -170)
435assert(tonumber('-0xffFFFfff') == -2^32 + 1)
436
437
438-- testing 'tostring'
439assert(tostring("alo") == "alo")
440assert(tostring(12) == "12")
441assert(tostring(1234567890123) == '1234567890123')
442assert(type(tostring("hello")) == "string")
443assert(tostring(true) == "true")
444assert(tostring(false) == "false")
445assert(string.find(tostring{}, 'table:'))
446assert(string.find(tostring(select), 'function:'))
447assert(#tostring('\0') == 1)
448
449
450-- testing ipairs
451local x = 0
452for k,v in ipairs{10,20,30;x=12} do
453  x = x + 1
454  assert(k == x and v == x * 10)
455end
456
457for _ in ipairs{x=12, y=24} do assert(nil) end
458
459-- test for 'false' x ipair
460x = false
461local i = 0
462for k,v in ipairs{true,false,true,false} do
463  i = i + 1
464  x = not x
465  assert(x == v)
466end
467assert(i == 4)
468
469
470return "OK"
471