diff --git a/.gitignore b/.gitignore index 5144e46..41fb33f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,5 @@ /.idea /vendor /build -*.lua +/*.lua .phpunit.result.cache diff --git a/tests/lua/closure.lua b/tests/lua/closure.lua new file mode 100644 index 0000000..8b34569 --- /dev/null +++ b/tests/lua/closure.lua @@ -0,0 +1,184 @@ +-- $Id: testes/closure.lua $ +-- See Copyright Notice in file all.lua + +print "testing closures" + +local A,B = 0,{g=10} +function f(x) + local a = {} + for i=1,1000 do + local y = 0 + do + a[i] = function () B.g = B.g+1; y = y+x; return y+A end + end + end + local dummy = function () return a[A] end + collectgarbage() + A = 1; assert(dummy() == a[1]); A = 0; + assert(a[1]() == x) + assert(a[3]() == x) + collectgarbage() + assert(B.g == 12) + return a +end + + +-- testing equality +a = {} + +for i = 1, 5 do a[i] = function (x) return i + a + _ENV end end +assert(a[3] ~= a[4] and a[4] ~= a[5]) + +do + local a = function (x) return math.sin(_ENV[x]) end + local function f() + return a + end + assert(f() == f()) +end + + +-- testing closures with 'for' control variable +a = {} +for i=1,10 do + a[i] = {set = function(x) i=x end, get = function () return i end} + if i == 3 then break end +end +assert(a[4] == undef) +a[1].set(10) +assert(a[2].get() == 2) +a[2].set('a') +assert(a[3].get() == 3) +assert(a[2].get() == 'a') + +a = {} +local t = {"a", "b"} +for i = 1, #t do + local k = t[i] + a[i] = {set = function(x, y) i=x; k=y end, + get = function () return i, k end} + if i == 2 then break end +end +a[1].set(10, 20) +local r,s = a[2].get() +assert(r == 2 and s == 'b') +r,s = a[1].get() +assert(r == 10 and s == 20) +a[2].set('a', 'b') +r,s = a[2].get() +assert(r == "a" and s == "b") + + +-- testing closures with 'for' control variable x break +for i=1,3 do + f = function () return i end + break +end +assert(f() == 1) + +for k = 1, #t do + local v = t[k] + f = function () return k, v end + break +end +assert(({f()})[1] == 1) +assert(({f()})[2] == "a") + + +-- testing closure x break x return x errors + +local b +function f(x) + local first = 1 + while 1 do + if x == 3 and not first then return end + local a = 'xuxu' + b = function (op, y) + if op == 'set' then + a = x+y + else + return a + end + end + if x == 1 then do break end + elseif x == 2 then return + else if x ~= 3 then error() end + end + first = nil + end +end + +for i=1,3 do + f(i) + assert(b('get') == 'xuxu') + b('set', 10); assert(b('get') == 10+i) + b = nil +end + +pcall(f, 4); +assert(b('get') == 'xuxu') +b('set', 10); assert(b('get') == 14) + + +local w +-- testing multi-level closure +function f(x) + return function (y) + return function (z) return w+x+y+z end + end +end + +y = f(10) +w = 1.345 +assert(y(20)(30) == 60+w) + + +print(X,Y) +-- testing closures x break +do + local X, Y + local a = math.sin(0) + + print(a) + while a do + local b = 10 + X = function () return b end -- closure with upvalue + if a then break end + end + + do + local b = 20 + Y = function () return b end -- closure with upvalue + end + + -- upvalues must be different + print(X,Y) + assert(X() == 10 and Y() == 20) +end + + +-- testing closures x repeat-until + +local a = {} +local i = 1 +repeat + local x = i + a[i] = function () i = x+1; return x end +until i > 10 or a[i]() ~= x +assert(i == 11 and a[1]() == 1 and a[3]() == 3 and i == 4) + + +print'+' + + +-- test for correctly closing upvalues in tail calls of vararg functions +local function t () + local function c(a,b) assert(a=="test" and b=="OK") end + local function v(f, ...) c("test", f() ~= 1 and "FAILED" or "OK") end + local x = 1 + return v(function() return x end) +end +t() + + +print'OK' diff --git a/tests/lua/locals.lua b/tests/lua/locals.lua new file mode 100644 index 0000000..211d266 --- /dev/null +++ b/tests/lua/locals.lua @@ -0,0 +1,71 @@ +-- $Id: testes/locals.lua $ +-- See Copyright Notice in file all.lua + +print('testing local variables and environments') + + +-- bug in 5.1: + +local function f(x) x = nil; return x end +assert(f(10) == nil) + +local function f() local x; return x end +assert(f(10) == nil) + +local function f(x) x = nil; local y; return x, y end +assert(f(10) == nil and select(2, f(20)) == nil) + +do + local i = 10 + do local i = 100; assert(i==100) end + do local i = 1000; assert(i==1000) end + assert(i == 10) + if i ~= 10 then + local i = 20 + else + local i = 30 + assert(i == 30) + end +end + + + +f = nil + +local f +x = 1 + +a = nil +load('local a = {}')() +assert(a == nil) + +function f (a) + local _1, _2, _3, _4, _5 + local _6, _7, _8, _9, _10 + local x = 3 + local b = a + local c,d = a,b + if (d == b) then + local x = 'q' + x = b + assert(x == 2) + else + assert(nil) + end + assert(x == 3) + local f = 10 +end + +local b=10 +local a; repeat local b; a,b=1,2; assert(a+1==b); until a+b==3 + + +assert(x == 1) + +f(2) +assert(type(f) == 'function') + + + +print'+' + diff --git a/tests/lua/math.lua b/tests/lua/math.lua new file mode 100644 index 0000000..d34dfcd --- /dev/null +++ b/tests/lua/math.lua @@ -0,0 +1,654 @@ +-- $Id: testes/math.lua $ +-- See Copyright Notice in file all.lua + + +print("testing numbers and math lib") +print(1>0) + +local minint = math.tointeger(math.mininteger) +local maxint = math.tointeger(math.maxinteger) + +print(minint, maxint) + +local intbits= math.floor(math.log(maxint, 2) + 0.5) + 1 +print(maxint) +print(intbits) +assert((1 << intbits) == 0) + +print(1 << (63)) +print(minint) + +print(minint == (1 << 63)) +print(minint == (1 << (intbits - 1))) +print(minint == 1 << (intbits - 1)) +assert(minint == 1 << (intbits - 1)) + +print('+') +-- number of bits in the mantissa of a floating-point number +local floatbits = 24 +do + local p = 2.0^floatbits + while p < p + 1.0 do + p = p * 2.0 + floatbits = floatbits + 1 + end +end + + +do + local x = 2.0^floatbits + assert(x > x - 1.0 and x == x + 1.0) + + print(string.format("%d-bit integers, %d-bit (mantissa) floats", + intbits, floatbits)) +end + +assert(math.type(0) == "integer" and math.type(0.0) == "float" + and not math.type("10")) + + +local function checkerror (msg, f, ...) + local s, err = pcall(f, ...) + print(s) + assert(not s) +end +local function f2i (x) return x | x end +local msgf2i = "number.* has no integer representation" + +-- float equality +function eq (a,b,limit) + if not limit then + if floatbits >= 50 then limit = 1E-11 + else limit = 1E-5 + end + end + + print('.') + print('.') + print(a) + print(b) + print(math.abs(a-b)) + print(limit) + -- a == b needed for +inf/-inf + return a == b or math.abs(a-b) <= limit +end + + +-- equality with types +function eqT (a,b) + return a == b and math.type(a) == math.type(b) +end + + +-- basic float notation +assert(0e12 == 0) +assert(.0 == 0) +assert(0. == 0) +assert(.2e2 == 20) +assert(2.E-1 == 0.2) + +do +local a,b,c = "2", " 3e0 ", " 10 " +assert(a+b == 5 and -b == -3 and b+"2" == 5 and "10"-c == 0) +assert(type(a) == 'string' and type(b) == 'string' and type(c) == 'string') +assert(a == "2" and b == " 3e0 " and c == " 10 " and -c == -" 10 ") +assert(c%a == 0 and a^b == 08) +a = 0 +assert(a == -a and 0 == -0) +end + +do +local x = -1 +local mz = 0/x -- minus zero +t = {[0] = 10, 20, 30, 40, 50} +assert(t[mz] == t[0] and t[-0] == t[0]) +end + +do -- tests for 'modf' +local a,b = math.modf(3.5) +assert(a == 3.0 and b == 0.5) +a,b = math.modf(-2.5) +assert(a == -2.0 and b == -0.5) +a,b = math.modf(-3e23) + +print(a) +print(b) +assert(a == -3e23 and b == 0.0) +a,b = math.modf(3e35) +assert(a == 3e35 and b == 0.0) +a,b = math.modf(3) -- integer argument +assert(eqT(a, 3) and eqT(b, 0.0)) +a,b = math.modf(minint) +assert(eqT(a, minint) and eqT(b, 0.0)) +end + +assert(math.huge > 10e30) +assert(-math.huge < -10e30) + + +-- testing floor division and conversions + +for _, i in pairs ({-16, -15, -3, -2, -1, 0, 1, 2, 3, 15}) do +for _, j in pairs ({-16, -15, -3, -2, -1, 1, 2, 3, 15}) do +for _, ti in pairs({0, 0.0}) do -- try 'i' as integer and as float +for _, tj in pairs({0, 0.0}) do -- try 'j' as integer and as float +local x = i + ti +local y = j + tj +assert(i//j == math.floor(i/j)) +end +end +end +end + +assert(eqT(3.5 // 1.5, 2.0)) +assert(eqT(3.5 // -1.5, -3.0)) + +do -- tests for different kinds of opcodes +local x, y +x = 3.5; assert(eqT(x // 1, 3.0)) +assert(eqT(x // -1, -4.0)) + +x = 3.5; y = 1.5; assert(eqT(x // y, 2.0)) +x = 3.5; y = -1.5; assert(eqT(x // y, -3.0)) +end + + + +-- negative exponents +do +assert(2^-3 == 1 / 2^3) +assert(eq((-3)^-3, 1 / (-3)^3)) +for i = -3, 3 do -- variables avoid constant folding +for j = -3, 3 do +-- domain errors (0^(-n)) are not portable +if i ~= 0 or j > 0 then +assert(eq(i^j, 1 / i^(-j))) +end +end +end +end + + +-- order between floats and integers +assert(1 < 1.1); assert(not (1 < 0.9)) +assert(1 <= 1.1); assert(not (1 <= 0.9)) +assert(-1 < -0.9); assert(not (-1 < -1.1)) +assert(1 <= 1.1); assert(not (-1 <= -1.1)) +assert(-1 < -0.9); assert(not (-1 < -1.1)) +assert(-1 <= -0.9); assert(not (-1 <= -1.1)) + + +if floatbits < intbits then +print("testing order (floats cannot represent all integers)") +local fmax = 2^floatbits +local ifmax = fmax | 0 +assert(fmax < ifmax + 1) +assert(fmax - 1 < ifmax) +assert(-(fmax - 1) > -ifmax) +assert(not (fmax <= ifmax - 1)) +assert(-fmax > -(ifmax + 1)) +assert(not (-fmax >= -(ifmax - 1))) + +assert(fmax/2 - 0.5 < ifmax//2) +assert(-(fmax/2 - 0.5) > -ifmax//2) + +assert(maxint < 2^intbits) +assert(minint > -2^intbits) +assert(maxint <= 2^intbits) +assert(minint >= -2^intbits) +else +print("testing order (floats can represent all integers)") +assert(maxint < maxint + 1.0) +assert(maxint < maxint + 0.5) +assert(maxint - 1.0 < maxint) +assert(maxint - 0.5 < maxint) +assert(not (maxint + 0.0 < maxint)) +assert(maxint + 0.0 <= maxint) +assert(not (maxint < maxint + 0.0)) +assert(maxint + 0.0 <= maxint) +assert(maxint <= maxint + 0.0) +assert(not (maxint + 1.0 <= maxint)) +assert(not (maxint + 0.5 <= maxint)) +assert(not (maxint <= maxint - 1.0)) +assert(not (maxint <= maxint - 0.5)) + +assert(minint < minint + 1.0) +assert(minint < minint + 0.5) +assert(minint <= minint + 0.5) +assert(minint - 1.0 < minint) +assert(minint - 1.0 <= minint) +assert(not (minint + 0.0 < minint)) +assert(not (minint + 0.5 < minint)) +assert(not (minint < minint + 0.0)) +assert(minint + 0.0 <= minint) +assert(minint <= minint + 0.0) +assert(not (minint + 1.0 <= minint)) +assert(not (minint + 0.5 <= minint)) +assert(not (minint <= minint - 1.0)) +end + + +-- testing numeric strings +assert("2" + 1 == 3) +assert("2 " + 1 == 3) +assert(" -2 " + 1 == -1) +--[[ +]] + +-- Literal integer Overflows (new behavior in 5.3.3) +do +-- no overflows +maxint = math.maxinteger +assert(eqT(tonumber(tostring(maxint)), maxint)) +assert(eqT(tonumber(tostring(minint)), minint)) + +-- add 1 to last digit as a string (it cannot be 9...) +local function incd (n) + print(math.type(n)) + local s = string.format("%d", n) + s = string.gsub(s, "%d$", function (d) + assert(d ~= '9') + return string.char(string.byte(d) + 1) + end) + + return s +end + +-- 'tonumber' with overflow by 1 +print(tonumber(incd(maxint))) +assert(eqT(tonumber(incd(maxint)), maxint + 1.0)) +assert(eqT(tonumber(incd(minint)), minint - 1.0)) + +-- large numbers +assert(eqT(tonumber("1"..string.rep("0", 30)), 1e30)) +assert(eqT(tonumber("-1"..string.rep("0", 30)), -1e30)) + +assert(eqT(10000000000000000000000.0, 10000000000000000000000)) +assert(eqT(-10000000000000000000000.0, -10000000000000000000000)) +end + + +-- testing 'tonumber' + +-- 'tonumber' with numbers +assert(tonumber(3.4) == 3.4) +assert(eqT(tonumber(3), 3)) +assert(eqT(tonumber(maxint), maxint) and eqT(tonumber(minint), minint)) + +-- 'tonumber' with strings +assert(tonumber("0") == 0) +assert(not tonumber("")) +assert(not tonumber(" ")) +assert(not tonumber("-")) +assert(not tonumber(" -0x ")) +assert(not tonumber({})) +assert(tonumber('+0.01') == 1/100 and tonumber('+.01') == 0.01 and +tonumber('.01') == 0.01 and tonumber('-1.') == -1 and +tonumber('+1.') == 1) +assert(not tonumber('+ 0.01') and not tonumber('+.e1') and +not tonumber('1e') and not tonumber('1.0e+') and +not tonumber('.')) +assert(tonumber('-012') == -010-2) +assert(tonumber('-1.2e2') == - - -120) + + +-- testing 'tonumber' with base +assert(tonumber(' 001010 ', 2) == 10) +assert(tonumber(' 001010 ', 10) == 001010) +assert(tonumber(' -1010 ', 2) == -10) +assert(tonumber('10', 36) == 36) +assert(tonumber(' -10 ', 36) == -36) +assert(tonumber(' +1Z ', 36) == 36 + 35) +assert(tonumber(' -1z ', 36) == -36 + -35) +assert(tonumber('-fFfa', 16) == -(10+(16*(15+(16*(15+(16*15))))))) +assert(tonumber(string.rep('1', (intbits - 2)), 2) + 1 == 2^(intbits - 2)) +assert(tonumber('ffffFFFF', 16)+1 == (1 << 32)) +assert(tonumber('0ffffFFFF', 16)+1 == (1 << 32)) +assert(tonumber('-0ffffffFFFF', 16) - 1 == -(1 << 40)) +for i = 2,36 do +local i2 = i * i +local i10 = i2 * i2 * i2 * i2 * i2 -- i^10 +assert(tonumber('\t10000000000\t', i) == i10) +end + +if not _soft then +-- tests with very long numerals +assert(tonumber("0x"..string.rep("f", 13)..".0") == 2.0^(4*13) - 1) +assert(tonumber("0x"..string.rep("f", 150)..".0") == 2.0^(4*150) - 1) +assert(tonumber("0x"..string.rep("f", 300)..".0") == 2.0^(4*300) - 1) +assert(tonumber("0x"..string.rep("f", 500)..".0") == 2.0^(4*500) - 1) +assert(tonumber('0x3.' .. string.rep('0', 1000)) == 3) +assert(tonumber('0x' .. string.rep('0', 1000) .. 'a') == 10) +assert(tonumber('0x0.' .. string.rep('0', 13).."1") == 2.0^(-4*14)) +assert(tonumber('0x0.' .. string.rep('0', 150).."1") == 2.0^(-4*151)) +assert(tonumber('0x0.' .. string.rep('0', 300).."1") == 2.0^(-4*301)) +assert(tonumber('0x0.' .. string.rep('0', 500).."1") == 2.0^(-4*501)) + +end + +-- testing 'tonumber' for invalid formats + +local function f (...) +if select('#', ...) == 1 then +return (...) +else +return "***" +end +end + +assert(not f(tonumber('fFfa', 15))) +assert(not f(tonumber('099', 8))) +assert(not f(tonumber('1\0', 2))) +assert(not f(tonumber('', 8))) +assert(not f(tonumber(' ', 9))) +assert(not f(tonumber(' ', 9))) +assert(not f(tonumber('0xf', 10))) + +assert(not f(tonumber('inf'))) +assert(not f(tonumber(' INF '))) +assert(not f(tonumber('Nan'))) +assert(not f(tonumber('nan'))) + +assert(not f(tonumber(' '))) +assert(not f(tonumber(''))) +assert(not f(tonumber('1 a'))) +assert(not f(tonumber('1 a', 2))) +assert(not f(tonumber('1\0'))) +assert(not f(tonumber('1 \0'))) +assert(not f(tonumber('1\0 '))) +assert(not f(tonumber('e1'))) +assert(not f(tonumber('e 1'))) +assert(not f(tonumber(' 3.4.5 '))) + + +-- testing 'tonumber' for invalid hexadecimal formats +print('testing \'tonumber\' for invalid hexadecimal formats') + +assert(not tonumber('0x')) +assert(not tonumber('x')) +assert(not tonumber('x3')) +assert(not tonumber('0x3.3.3')) -- two decimal points +assert(not tonumber('00x2')) +assert(not tonumber('0x 2')) +assert(not tonumber('0 x2')) +assert(not tonumber('23x')) +assert(not tonumber('- 0xaa')) +assert(not tonumber('-0xaaP ')) -- no exponent +assert(not tonumber('0x0.51p')) +assert(not tonumber('0x5p+-2')) + + +-- testing hexadecimal numerals +print('testing hexadecimal numerals') + +assert(0x10 == 16 and 0xfff == 2^12 - 1 and 0XFB == 251) +assert(0x0p12 == 0 and 0x.0p-3 == 0) +assert(0xFFFFFFFF == (1 << 32) - 1) +assert(tonumber('+0x2') == 2) +assert(tonumber('-0xaA') == -170) +assert(tonumber('-0xffFFFfff') == -(1 << 32) + 1) + +-- possible confusion with decimal exponent +assert(0E+1 == 0 and 0xE+1 == 15 and 0xe-1 == 13) + + +-- floating hexas +print('floating hexas') +assert(1.1 == '1.'+'.1') +assert(tonumber('1111111111') - tonumber('1111111110') == +tonumber(" +0.001e+3 \n\t")) + +assert(0.1e-30 > 0.9E-31 and 0.9E30 < 0.1e31) + +assert(0.123456 > 0.123455) + +assert(tonumber('+1.23E18') == 1.23*10.0^18) + +-- testing order operators +print('testing order operators') +assert(not(1<1) and (1<2) and not(2<1)) +assert(not('a'<'a') and ('a'<'b') and not('b'<'a')) +assert((1<=1) and (1<=2) and not(2<=1)) +assert(('a'<='a') and ('a'<='b') and not('b'<='a')) +assert(not(1>1) and not(1>2) and (2>1)) +assert(not('a'>'a') and not('a'>'b') and ('b'>'a')) +assert((1>=1) and not(1>=2) and (2>=1)) +assert(('a'>='a') and not('a'>='b') and ('b'>='a')) +assert(1.3 < 1.4 and 1.3 <= 1.4 and not (1.3 < 1.3) and 1.3 <= 1.3) + +-- testing mod operator +print ('testing mod operator') +assert(eqT(-4 % 3, 2)) +assert(eqT(4 % -3, -2)) +assert(eqT(-4.0 % 3, 2.0)) +assert(eqT(4 % -3.0, -2.0)) +assert(eqT(4 % -5, -1)) +assert(eqT(4 % -5.0, -1.0)) +assert(eqT(4 % 5, 4)) +assert(eqT(4 % 5.0, 4.0)) +assert(eqT(-4 % -5, -4)) +assert(eqT(-4 % -5.0, -4.0)) +assert(eqT(-4 % 5, 1)) +assert(eqT(-4 % 5.0, 1.0)) +assert(eqT(4.25 % 4, 0.25)) +assert(eqT(10.0 % 2, 0.0)) +assert(eqT(-10.0 % 2, 0.0)) +assert(eqT(-10.0 % -2, 0.0)) +assert(math.pi - math.pi % 1 == 3) +assert(math.pi - math.pi % 0.001 == 3.141) + +print('very small numbers') +do -- very small numbers +local i, j = 0, 20000 +while i < j do +local m = (i + j) // 2 +if 10^-m > 0 then +i = m + 1 +else +j = m +end +end + +print ('i is the smallest possible ten-exponent') +-- 'i' is the smallest possible ten-exponent +local b = 10^-(i - (i // 10)) -- a very small number +assert(b > 0 and b * b == 0) +local delta = b / 1000 +assert(eq((2.1 * b) % (2 * b), (0.1 * b), delta)) +assert(eq((-2.1 * b) % (2 * b), (2 * b) - (0.1 * b), delta)) +assert(eq((2.1 * b) % (-2 * b), (0.1 * b) - (2 * b), delta)) +assert(eq((-2.1 * b) % (-2 * b), (-0.1 * b), delta)) +end + + +-- basic consistency between integer modulo and float modulo +for i = -10, 10 do +for j = -10, 10 do +if j ~= 0 then +assert((i + 0.0) % j == i % j) +end +end +end + +for i = 0, 10 do +for j = -10, 10 do +if j ~= 0 then +assert((2^i) % j == (1 << i) % j) +end +end +end + +do -- precision of module for large numbers +local i = 10 +while (1 << i) > 0 do +assert((1 << i) % 3 == i % 2 + 1) +i = i + 1 +end + +i = 10 +while 2^i < math.huge do +assert(2^i % 3 == i % 2 + 1) +i = i + 1 +end +end + + +-- non-portable tests because Windows C library cannot compute +-- fmod(1, huge) correctly +if not _port then +local function anan (x) assert(isNaN(x)) end -- assert Not a Number +anan(0.0 % 0) +anan(1.3 % 0) +anan(math.huge % 1) +anan(math.huge % 1e30) +anan(-math.huge % 1e30) +anan(-math.huge % -1e30) +assert(1 % math.huge == 1) +assert(1e30 % math.huge == 1e30) +assert(1e30 % -math.huge == -math.huge) +assert(-1 % math.huge == math.huge) +assert(-1 % -math.huge == -1) +end + + + + +assert(eq(math.sin(-9.8)^2 + math.cos(-9.8)^2, 1)) +assert(eq(math.tan(math.pi/4), 1)) +assert(eq(math.sin(math.pi/2), 1) and eq(math.cos(math.pi/2), 0)) +assert(eq(math.atan(1), math.pi/4) and eq(math.acos(0), math.pi/2) and +eq(math.asin(1), math.pi/2)) +assert(eq(math.deg(math.pi/2), 90) and eq(math.rad(90), math.pi/2)) +assert(math.abs(-10.43) == 10.43) +assert(eq(math.atan(1,0), math.pi/2)) +assert(math.fmod(10,3) == 1) +assert(eq(math.sqrt(10)^2, 10)) +assert(eq(math.log(2, 10), math.log(2)/math.log(10))) +assert(eq(math.log(2, 2), 1)) +assert(eq(math.log(9, 3), 2)) +assert(eq(math.exp(0), 1)) +assert(eq(math.sin(10), math.sin(10%(2*math.pi)))) + + +assert(tonumber(' 1.3e-2 ') == 1.3e-2) +assert(tonumber(' -1.00000000000001 ') == -1.00000000000001) + +-- testing constant limits +-- 2^23 = 8388608 +assert(8388609 + -8388609 == 0) +assert(8388608 + -8388608 == 0) +assert(8388607 + -8388607 == 0) + + + +do -- testing floor & ceil +assert(eqT(math.floor(3.4), 3)) +assert(eqT(math.ceil(3.4), 4)) +assert(eqT(math.floor(-3.4), -4)) +assert(eqT(math.ceil(-3.4), -3)) +assert(math.floor(1e50) == 1e50) +assert(math.ceil(1e50) == 1e50) +assert(math.floor(-1e50) == -1e50) +assert(math.ceil(-1e50) == -1e50) +for _, p in pairs({31, 32, 63, 64}) do + assert(math.floor(2^p) == 2^p) + assert(math.floor(2^p + 0.5) == 2^p) + assert(math.ceil(2^p) == 2^p) + assert(math.ceil(2^p - 0.5) == 2^p) +end +checkerror("number expected", math.floor, {}) +checkerror("number expected", math.ceil, print) +assert(eqT(math.tointeger(minint), minint)) +assert(eqT(math.tointeger(minint .. ""), minint)) +assert(eqT(math.tointeger(maxint), maxint)) +assert(eqT(math.tointeger(maxint .. ""), maxint)) +assert(eqT(math.tointeger(minint + 0.0), minint)) +assert(not math.tointeger(math.pi)) +assert(not math.tointeger(-math.pi)) +assert(math.floor(math.huge) == math.huge) +assert(math.ceil(math.huge) == math.huge) +assert(not math.tointeger(math.huge)) +assert(math.floor(-math.huge) == -math.huge) +assert(math.ceil(-math.huge) == -math.huge) +assert(not math.tointeger(-math.huge)) +assert(math.tointeger("34.0") == 34) +assert(not math.tointeger("34.3")) +assert(not math.tointeger({})) +end + + + + +do -- testing max/min +checkerror("value expected", math.max) +checkerror("value expected", math.min) +assert(eqT(math.max(3), 3)) +assert(eqT(math.max(3, 5, 9, 1), 9)) +assert(math.max(maxint, 10e60) == 10e60) +assert(eqT(math.max(minint, minint + 1), minint + 1)) +assert(eqT(math.min(3), 3)) +assert(eqT(math.min(3, 5, 9, 1), 1)) +assert(math.min(3.2, 5.9, -9.2, 1.1) == -9.2) +assert(math.min(1.9, 1.7, 1.72) == 1.7) +assert(math.min(-10e60, minint) == -10e60) +assert(eqT(math.min(maxint, maxint - 1), maxint - 1)) +assert(eqT(math.min(maxint - 2, maxint, maxint - 1), maxint - 2)) +end +-- testing implicit conversions + +local a,b = '10', '20' +assert(a*b == 200 and a+b == 30 and a-b == -10 and a/b == 0.5 and -b == -20) +assert(a == '10' and b == '20') + + + +print("testing 'math.random'") + +local random, max, min = math.random, math.max, math.min + +local function testnear (val, ref, tol) +return (math.abs(val - ref) < ref * tol) +end + + + +do +local function aux (x1, x2) -- test random for small intervals + local mark = {}; local count = 0 -- to check that all values appeared + while true do + local t = random(x1, x2) + assert(x1 <= t and t <= x2) + if not mark[t] then -- new value + mark[t] = true + count = count + 1 + if count == x2 - x1 + 1 then -- all values appeared; OK + return + end + end + end +end + +aux(-10,0) +aux(1, 6) +aux(1, 2) +aux(1, 13) +aux(1, 31) +aux(1, 32) +aux(1, 33) +aux(-10, 10) +aux(-10,-10) -- unit set +aux(minint, minint) -- unit set +aux(maxint, maxint) -- unit set +aux(minint, minint + 9) +aux(maxint - 3, maxint) +end + +-- empty interval +print('random empty interval') +assert(not pcall(random, minint + 1, minint)) +assert(not pcall(random, maxint, maxint - 1)) +assert(not pcall(random, maxint, minint)) + + + +print('OK') diff --git a/tests/lua/strings.lua b/tests/lua/strings.lua new file mode 100644 index 0000000..c361f78 --- /dev/null +++ b/tests/lua/strings.lua @@ -0,0 +1,205 @@ +-- $Id: testes/strings.lua $ +-- See Copyright Notice in file all.lua + +print('testing strings and string library') + +local maxi = math.maxinteger-1 +local mini = math.mininteger+1 + + +local function checkerror (msg, f, ...) + local s, err = pcall(f, ...) + + assert(not s) +end + + +-- testing string comparisons +assert('alo' < 'alo1') +assert('' < 'a') +assert('alo\0alo' < 'alo\0b') +assert('alo\0alo\0\0' > 'alo\0alo\0') +assert('alo' < 'alo\0') +assert('alo\0' > 'alo') +assert('\0' < '\1') +assert('\0\0' < '\0\1') +assert('\1\0a\0a' <= '\1\0a\0a') +assert(not ('\1\0a\0b' <= '\1\0a\0a')) +assert('\0\0\0' < '\0\0\0\0') +assert(not('\0\0\0\0' < '\0\0\0')) +assert('\0\0\0' <= '\0\0\0\0') +assert(not('\0\0\0\0' <= '\0\0\0')) +assert('\0\0\0' <= '\0\0\0') +assert('\0\0\0' >= '\0\0\0') +assert(not ('\0\0b' < '\0\0a\0')) + +-- testing string.sub +assert(string.sub("123456789",2,4) == "234") +assert(string.sub("123456789",7) == "789") +assert(string.sub("123456789",7,6) == "") +assert(string.sub("123456789",7,7) == "7") +assert(string.sub("123456789",0,0) == "") +assert(string.sub("123456789",-10,10) == "123456789") +assert(string.sub("123456789",1,9) == "123456789") +assert(string.sub("123456789",-10,-20) == "") +assert(string.sub("123456789",-1) == "9") +assert(string.sub("123456789",-4) == "6789") +assert(string.sub("123456789",-6, -4) == "456") +assert(string.sub("123456789", mini, -4) == "123456") +assert(string.sub("123456789", mini, maxi) == "123456789") +assert(string.sub("123456789", mini, mini) == "") +assert(string.sub("\000123456789",3,5) == "234") +assert(("\000123456789"):sub(8) == "789") + +-- testing string.find +assert(string.find("123456789", "345") == 3) +a,b = string.find("123456789", "345") +assert(string.sub("123456789", a, b) == "345") +assert(string.find("1234567890123456789", "345", 3) == 3) +assert(string.find("1234567890123456789", "345", 4) == 13) +assert(not string.find("1234567890123456789", "346", 4)) +assert(string.find("1234567890123456789", ".45", -9) == 13) +assert(not string.find("abcdefg", "\0", 5, 1)) +assert(string.find("", "") == 1) +assert(string.find("", "", 1) == 1) +assert(not string.find("", "", 2)) +assert(not string.find('', 'aaa', 1)) +assert(('alo(.)alo'):find('(.)', 1, 1) == 4) + +assert(string.len("") == 0) +assert(string.len("\0\0\0") == 3) +assert(string.len("1234567890") == 10) + +assert(#"" == 0) +assert(#"\0\0\0" == 3) +assert(#"1234567890" == 10) + +-- testing string.byte/string.char +assert(string.byte("a") == 97) +assert(string.byte("\xe4") > 127) +assert(string.byte(string.char(255)) == 255) +assert(string.byte(string.char(0)) == 0) +assert(string.byte("\0") == 0) +assert(string.byte("\0\0alo\0x", -1) == string.byte('x')) +assert(string.byte("ba", 2) == 97) +assert(string.byte("\n\n", 2, -1) == 10) +assert(string.byte("\n\n", 2, 2) == 10) +assert(string.byte("") == nil) +assert(string.byte("hi", -3) == nil) +assert(string.byte("hi", 3) == nil) +assert(string.byte("hi", 9, 10) == nil) +assert(string.byte("hi", 2, 1) == nil) +assert(string.char() == "") +assert(string.char(0, 255, 0) == "\0\255\0") +assert(string.char(0, string.byte("\xe4"), 0) == "\0\xe4\0") +assert(string.char(string.byte("\xe4l\0óu", 1, -1)) == "\xe4l\0óu") +assert(string.char(string.byte("\xe4l\0óu", 1, 0)) == "") +assert(string.char(string.byte("\xe4l\0óu", -10, 100)) == "\xe4l\0óu") + +print('check error') +checkerror("out of range", string.char, 256) +checkerror("out of range", string.char, -1) +checkerror("out of range", string.char, math.maxinteger) +checkerror("out of range", string.char, math.mininteger) + +print('upper/lower') +assert(string.upper("ab\0c") == "AB\0C") +assert(string.lower("\0ABCc%$") == "\0abcc%$") + +print('repetitions') +assert(string.rep('teste', 0) == '') +assert(string.rep('tés\00tê', 2) == 'tés\0têtés\000tê') +assert(string.rep('', 10) == '') + + +-- repetitions with separator +print('repetitions with separator') +assert(string.rep('teste', 0, 'xuxu') == '') +assert(string.rep('teste', 1, 'xuxu') == 'teste') +assert(string.rep('\1\0\1', 2, '\0\0') == '\1\0\1\0\0\1\0\1') +assert(string.rep('', 10, '.') == string.rep('.', 9)) +assert(not pcall(string.rep, "aa", maxi // 2 + 10)) +assert(not pcall(string.rep, "", maxi // 2 + 10, "aa")) + +assert(string.reverse"" == "") +assert(string.reverse"\0\1\2\3" == "\3\2\1\0") +assert(string.reverse"\0001234" == "4321\0") + +for i=0,30 do assert(string.len(string.rep('a', i)) == i) end + +assert(type(tostring(nil)) == 'string') +assert(type(tostring(12)) == 'string') +assert(string.find(tostring{}, 'table:')) +assert(string.find(tostring(print), 'function:')) +assert(#tostring('\0') == 1) +assert(tostring(true) == "true") +assert(tostring(false) == "false") +assert(tostring(-1203) == "-1203") +assert(tostring(1203.125) == "1203.125") +assert(tostring(-0.5) == "-0.5") +assert(tostring(-32767) == "-32767") +if math.tointeger(2147483647) then -- no overflow? (32 bits) + assert(tostring(-2147483647) == "-2147483647") +end +if math.tointeger(4611686018427387904) then -- no overflow? (64 bits) + assert(tostring(4611686018427387904) == "4611686018427387904") + assert(tostring(-4611686018427387904) == "-4611686018427387904") +end + +if tostring(0.0) == "0.0" then -- "standard" coercion float->string + assert('' .. 12 == '12' and 12.0 .. '' == '12.0') + assert(tostring(-1203 + 0.0) == "-1203.0") +else -- compatible coercion + assert(tostring(0.0) == "0") + assert('' .. 12 == '12' and 12.0 .. '' == '12') + assert(tostring(-1203 + 0.0) == "-1203") +end + + +assert(string.format("\0%s\0", "\0\0\1") == "\0\0\0\1\0") + +-- format x tostring +assert(string.format("%s %s", nil, true) == "nil true") +assert(string.format("%s %.4s", false, true) == "false true") +assert(string.format("%.3s %.3s", false, true) == "fal tru") + + + + +checkerror("table expected", table.concat, 3) +checkerror("at index " .. maxi, table.concat, {}, " ", maxi, maxi) +-- '%' escapes following minus signal +checkerror("at index %" .. mini, table.concat, {}, " ", mini, mini) + + +print('table.concat') +assert(table.concat{} == "") +assert(table.concat({}, 'x') == "") +assert(table.concat({'\0', '\0\1', '\0\1\2'}, '.\0.') == "\0.\0.\0\1.\0.\0\1\2") +local a = {}; for i=1,300 do a[i] = "xuxu" end +assert(table.concat(a, "123").."123" == string.rep("xuxu123", 300)) +assert(table.concat(a, "b", 20, 20) == "xuxu") +assert(table.concat(a, "", 20, 21) == "xuxuxuxu") +assert(table.concat(a, "x", 22, 21) == "") +assert(table.concat(a, "3", 299) == "xuxu3xuxu") +assert(table.concat({}, "x", maxi, maxi - 1) == "") +assert(table.concat({}, "x", mini + 1, mini) == "") +assert(table.concat({}, "x", maxi, mini) == "") +assert(table.concat({[maxi] = "alo"}, "x", maxi, maxi) == "alo") +assert(table.concat({[maxi] = "alo", [maxi - 1] = "y"}, "-", maxi - 1, maxi) + == "y-alo") + +assert(not pcall(table.concat, {"a", "b", {}})) + +a = {"a","b","c"} +assert(table.concat(a, ",", 1, 0) == "") +assert(table.concat(a, ",", 1, 1) == "a") +assert(table.concat(a, ",", 1, 2) == "a,b") +assert(table.concat(a, ",", 2) == "b,c") +assert(table.concat(a, ",", 3) == "c") +assert(table.concat(a, ",", 4) == "") + + + + +print('OK') diff --git a/tests/lua/vararg.lua b/tests/lua/vararg.lua new file mode 100644 index 0000000..c42419f --- /dev/null +++ b/tests/lua/vararg.lua @@ -0,0 +1,170 @@ +-- $Id: testes/vararg.lua $ +-- See Copyright Notice in file all.lua + +print('testing vararg') + +function f(a, ...) + local x = {n = select('#', ...), ...} + for i = 1, x.n do assert(a[i] == x[i]) end + return x.n +end + +function c12 (...) + assert(arg == _G.arg) -- no local 'arg' + local x = {...}; x.n = #x + local res = (x.n==2 and x[1] == 1 and x[2] == 2) + if res then res = 55 end + return res, 2 +end + +function vararg (...) return {n = select('#', ...), ...} end + +local call = function (f, args) return f(table.unpack(args, 1, args.n)) end + +assert(f() == 0) +assert(f({1,2,3}, 1, 2, 3) == 3) +assert(f({"alo", nil, 45, f, nil}, "alo", nil, 45, f, nil) == 5) + +assert(vararg().n == 0) +assert(vararg(nil, nil).n == 2) + +assert(c12(1,2)==55) +a,b = assert(call(c12, {1,2})) +print(a,b) +assert(a == 55 and b == 2) + + + + + + + + + +a = call(c12, {1,2;n=2}) +assert(a == 55 and b == 2) +a = call(c12, {1,2;n=1}) +assert(not a) +assert(c12(1,2,3) == false) +local a = vararg(call(next, {_G,nil;n=2})) +local b,c = next(_G) +assert(a[1] == b and a[2] == c and a.n == 2) +a = vararg(call(call, {c12, {1,2}})) +assert(a.n == 2 and a[1] == 55 and a[2] == 2) +a = call(print, {'+'}) +assert(a == nil) + +local t = {1, 10} +function t:f (...) local arg = {...}; return self[...]+#arg end +print(t.f) +assert(t:f(1,4) == 3 and t:f(2) == 11) +print('+') + +lim = 20 +local i, a = 1, {} +while i <= lim do a[i] = i+0.3; i=i+1 end + +function f(a, b, c, d, ...) + local more = {...} + assert(a == 1.3 and more[1] == 5.3 and + more[lim-4] == lim+0.3 and not more[lim-3]) +end + +function g(a,b,c) + assert(a == 1.3 and b == 2.3 and c == 3.3) +end + +call(f, a) +call(g, a) + +a = {} +i = 1 +while i <= lim do a[i] = i; i=i+1 end +assert(call(math.max, a) == lim) + +print("+") + + +-- new-style varargs + +function oneless (a, ...) return ... end + +function f (n, a, ...) + local b + assert(arg == _G.arg) -- no local 'arg' + if n == 0 then + local b, c, d = ... + return a, b, c, d, oneless(oneless(oneless(...))) + else + n, b, a = n-1, ..., a + assert(b == ...) + return f(n, a, ...) + end +end + +a,b,c,d,e = assert(f(10,5,4,3,2,1)) +assert(a==5 and b==4 and c==3 and d==2 and e==1) + +a,b,c,d,e = f(4) +assert(a==nil and b==nil and c==nil and d==nil and e==nil) + + +print('f') +-- varargs for main chunks +f = load([[ +print('load f') +print(...) +return {...} +]]) + +print('x') +x = f(2,3) +print(table.unpack(x)) +assert(x[1] == 2 and x[2] == 3 and x[3] == undef) + + +print('ff') +f = load([[ + local x = {...} + for i=1,select('#', ...) do assert(x[i] == select(i, ...)) end + assert(x[select('#', ...)+1] == undef) + return true +]]) + +assert(f("a", "b", nil, {}, assert)) +assert(f()) + +a = {select(3, table.unpack{10,20,30,40})} +assert(#a == 2 and a[1] == 30 and a[2] == 40) +a = {select(1)} +assert(next(a) == nil) +a = {select(-1, 3, 5, 7)} +assert(a[1] == 7 and a[2] == undef) +a = {select(-2, 3, 5, 7)} +assert(a[1] == 5 and a[2] == 7 and a[3] == undef) +pcall(select, 10000) +pcall(select, -10000) + + +-- bug in 5.2.2 + +function f(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, + p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, + p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, + p31, p32, p33, p34, p35, p36, p37, p38, p39, p40, + p41, p42, p43, p44, p45, p46, p48, p49, p50, ...) + local a1,a2,a3,a4,a5,a6,a7 + local a8,a9,a10,a11,a12,a13,a14 +end + +-- assertion fail here +f() + +-- missing arguments in tail call +do + local function f(a,b,c) return c, b end + local function g() return f(1,2) end + local a, b = g() + assert(a == nil and b == 2) +end +print('OK')