diff options
Diffstat (limited to 'tests/test-suite/code.js')
| -rw-r--r-- | tests/test-suite/code.js | 554 | 
1 files changed, 554 insertions, 0 deletions
| diff --git a/tests/test-suite/code.js b/tests/test-suite/code.js new file mode 100644 index 0000000..4438cd2 --- /dev/null +++ b/tests/test-suite/code.js @@ -0,0 +1,554 @@ +"use strict"; + +const test     = require('tape'); + +global.WEB = false; + +const lua     = require('../../src/lua.js'); +const lauxlib = require('../../src/lauxlib.js'); +const lualib  = require('../../src/lualib.js'); + +const ltests  = require('./ltests.js'); + + +test("[test-suite] code: testing reuse in constant table", function (t) { +    let luaCode = ` +        local function checkKlist (func, list) +          local k = T.listk(func) +          assert(#k == #list) +          for i = 1, #k do +            assert(k[i] == list[i] and math.type(k[i]) == math.type(list[i])) +          end +        end + +        local function foo () +          local a +          a = 3; +          a = 0; a = 0.0; a = -7 + 7 +          a = 3.78/4; a = 3.78/4 +          a = -3.78/4; a = 3.78/4; a = -3.78/4 +          a = -3.79/4; a = 0.0; a = -0; +          a = 3; a = 3.0; a = 3; a = 3.0 +        end + +        checkKlist(foo, {3, 0, 0.0, 3.78/4, -3.78/4, -3.79/4, 3.0}) +    `, L; +     +    t.plan(2); + +    t.doesNotThrow(function () { + +        L = lauxlib.luaL_newstate(); + +        lualib.luaL_openlibs(L); + +        ltests.luaopen_tests(L); + +        lauxlib.luaL_loadstring(L, lua.to_luastring(luaCode)); + +    }, "Lua program loaded without error"); + +    t.doesNotThrow(function () { + +        lua.lua_call(L, 0, -1); + +    }, "Lua program ran without error"); +}); + + +const prefix = ` +    function check (f, ...) +      local arg = {...} +      local c = T.listcode(f) +      for i=1, #arg do +        print(arg[i], c[i]) +        assert(string.find(c[i], '- '..arg[i]..' *%d')) +      end +      assert(c[#arg+2] == nil) +    end + + +    function checkequal (a, b) +      a = T.listcode(a) +      b = T.listcode(b) +      for i = 1, #a do +        a[i] = string.gsub(a[i], '%b()', '')   -- remove line number +        b[i] = string.gsub(b[i], '%b()', '')   -- remove line number +        assert(a[i] == b[i]) +      end +    end +`; + +test("[test-suite] code: some basic instructions", function (t) { +    let luaCode = ` +        check(function () +          (function () end){f()} +        end, 'CLOSURE', 'NEWTABLE', 'GETTABUP', 'CALL', 'SETLIST', 'CALL', 'RETURN') +    `, L; +     +    t.plan(2); + +    t.doesNotThrow(function () { + +        L = lauxlib.luaL_newstate(); + +        lualib.luaL_openlibs(L); + +        ltests.luaopen_tests(L); + +        lauxlib.luaL_loadstring(L, lua.to_luastring(prefix + luaCode)); + +    }, "Lua program loaded without error"); + +    t.doesNotThrow(function () { + +        lua.lua_call(L, 0, -1); + +    }, "Lua program ran without error"); +}); + + +test("[test-suite] code: sequence of LOADNILs", function (t) { +    let luaCode = ` +        check(function () +          local a,b,c +          local d; local e; +          local f,g,h; +          d = nil; d=nil; b=nil; a=nil; c=nil; +        end, 'LOADNIL', 'RETURN') + +        check(function () +          local a,b,c,d = 1,1,1,1 +          d=nil;c=nil;b=nil;a=nil +        end, 'LOADK', 'LOADK', 'LOADK', 'LOADK', 'LOADNIL', 'RETURN') + +        do +          local a,b,c,d = 1,1,1,1 +          d=nil;c=nil;b=nil;a=nil +          assert(a == nil and b == nil and c == nil and d == nil) +        end +    `, L; +     +    t.plan(2); + +    t.doesNotThrow(function () { + +        L = lauxlib.luaL_newstate(); + +        lualib.luaL_openlibs(L); + +        ltests.luaopen_tests(L); + +        lauxlib.luaL_loadstring(L, lua.to_luastring(prefix + luaCode)); + +    }, "Lua program loaded without error"); + +    t.doesNotThrow(function () { + +        lua.lua_call(L, 0, -1); + +    }, "Lua program ran without error"); +}); + + +test("[test-suite] code: single return", function (t) { +    let luaCode = ` +        check (function (a,b,c) return a end, 'RETURN') +    `, L; +     +    t.plan(2); + +    t.doesNotThrow(function () { + +        L = lauxlib.luaL_newstate(); + +        lualib.luaL_openlibs(L); + +        ltests.luaopen_tests(L); + +        lauxlib.luaL_loadstring(L, lua.to_luastring(prefix + luaCode)); + +    }, "Lua program loaded without error"); + +    t.doesNotThrow(function () { + +        lua.lua_call(L, 0, -1); + +    }, "Lua program ran without error"); +}); + + +test("[test-suite] code: infinite loops", function (t) { +    let luaCode = ` +        check(function () while true do local a = -1 end end, +        'LOADK', 'JMP', 'RETURN') + +        check(function () while 1 do local a = -1 end end, +        'LOADK', 'JMP', 'RETURN') + +        check(function () repeat local x = 1 until true end, +        'LOADK', 'RETURN') +    `, L; +     +    t.plan(2); + +    t.doesNotThrow(function () { + +        L = lauxlib.luaL_newstate(); + +        lualib.luaL_openlibs(L); + +        ltests.luaopen_tests(L); + +        lauxlib.luaL_loadstring(L, lua.to_luastring(prefix + luaCode)); + +    }, "Lua program loaded without error"); + +    t.doesNotThrow(function () { + +        lua.lua_call(L, 0, -1); + +    }, "Lua program ran without error"); +}); + + +test("[test-suite] code: concat optimization", function (t) { +    let luaCode = ` +        check(function (a,b,c,d) return a..b..c..d end, +          'MOVE', 'MOVE', 'MOVE', 'MOVE', 'CONCAT', 'RETURN') +    `, L; +     +    t.plan(2); + +    t.doesNotThrow(function () { + +        L = lauxlib.luaL_newstate(); + +        lualib.luaL_openlibs(L); + +        ltests.luaopen_tests(L); + +        lauxlib.luaL_loadstring(L, lua.to_luastring(prefix + luaCode)); + +    }, "Lua program loaded without error"); + +    t.doesNotThrow(function () { + +        lua.lua_call(L, 0, -1); + +    }, "Lua program ran without error"); +}); + + +test("[test-suite] code: not", function (t) { +    let luaCode = ` +        check(function () return not not nil end, 'LOADBOOL', 'RETURN') +        check(function () return not not false end, 'LOADBOOL', 'RETURN') +        check(function () return not not true end, 'LOADBOOL', 'RETURN') +        check(function () return not not 1 end, 'LOADBOOL', 'RETURN') +    `, L; +     +    t.plan(2); + +    t.doesNotThrow(function () { + +        L = lauxlib.luaL_newstate(); + +        lualib.luaL_openlibs(L); + +        ltests.luaopen_tests(L); + +        lauxlib.luaL_loadstring(L, lua.to_luastring(prefix + luaCode)); + +    }, "Lua program loaded without error"); + +    t.doesNotThrow(function () { + +        lua.lua_call(L, 0, -1); + +    }, "Lua program ran without error"); +}); + + +test("[test-suite] code: direct access to locals", function (t) { +    let luaCode = ` +        check(function () +          local a,b,c,d +          a = b*2 +          c[2], a[b] = -((a + d/2 - a[b]) ^ a.x), b +        end, +          'LOADNIL', +          'MUL', +          'DIV', 'ADD', 'GETTABLE', 'SUB', 'GETTABLE', 'POW', +            'UNM', 'SETTABLE', 'SETTABLE', 'RETURN') +    `, L; +     +    t.plan(2); + +    t.doesNotThrow(function () { + +        L = lauxlib.luaL_newstate(); + +        lualib.luaL_openlibs(L); + +        ltests.luaopen_tests(L); + +        lauxlib.luaL_loadstring(L, lua.to_luastring(prefix + luaCode)); + +    }, "Lua program loaded without error"); + +    t.doesNotThrow(function () { + +        lua.lua_call(L, 0, -1); + +    }, "Lua program ran without error"); +}); + + +test("[test-suite] code: direct access to constants", function (t) { +    let luaCode = ` +        check(function () +          local a,b +          a.x = 3.2 +          a.x = b +          a[b] = 'x' +        end, +          'LOADNIL', 'SETTABLE', 'SETTABLE', 'SETTABLE', 'RETURN') + +        check(function () +          local a,b +          a = 1 - a +          b = 1/a +          b = 5-4 +        end, +          'LOADNIL', 'SUB', 'DIV', 'LOADK', 'RETURN') + +        check(function () +          local a,b +          a[true] = false +        end, +          'LOADNIL', 'SETTABLE', 'RETURN') +    `, L; +     +    t.plan(2); + +    t.doesNotThrow(function () { + +        L = lauxlib.luaL_newstate(); + +        lualib.luaL_openlibs(L); + +        ltests.luaopen_tests(L); + +        lauxlib.luaL_loadstring(L, lua.to_luastring(prefix + luaCode)); + +    }, "Lua program loaded without error"); + +    t.doesNotThrow(function () { + +        lua.lua_call(L, 0, -1); + +    }, "Lua program ran without error"); +}); + + +test("[test-suite] code: constant folding", function (t) { +    let luaCode = ` +        local function checkK (func, val) +          check(func, 'LOADK', 'RETURN') +          local k = T.listk(func) +          assert(#k == 1 and k[1] == val and math.type(k[1]) == math.type(val)) +          assert(func() == val) +        end +        checkK(function () return 0.0 end, 0.0) +        checkK(function () return 0 end, 0) +        checkK(function () return -0//1 end, 0) +        checkK(function () return 3^-1 end, 1/3) +        checkK(function () return (1 + 1)^(50 + 50) end, 2^100) +        checkK(function () return (-2)^(31 - 2) end, -0x20000000 + 0.0) +        checkK(function () return (-3^0 + 5) // 3.0 end, 1.0) +        checkK(function () return -3 % 5 end, 2) +        checkK(function () return -((2.0^8 + -(-1)) % 8)/2 * 4 - 3 end, -5.0) +        checkK(function () return -((2^8 + -(-1)) % 8)//2 * 4 - 3 end, -7.0) +        checkK(function () return 0xF0.0 | 0xCC.0 ~ 0xAA & 0xFD end, 0xF4) +        checkK(function () return ~(~0xFF0 | 0xFF0) end, 0) +        checkK(function () return ~~-100024.0 end, -100024) +        checkK(function () return ((100 << 6) << -4) >> 2 end, 100) +    `, L; +     +    t.plan(2); + +    t.doesNotThrow(function () { + +        L = lauxlib.luaL_newstate(); + +        lualib.luaL_openlibs(L); + +        ltests.luaopen_tests(L); + +        lauxlib.luaL_loadstring(L, lua.to_luastring(prefix + luaCode)); + +    }, "Lua program loaded without error"); + +    t.doesNotThrow(function () { + +        lua.lua_call(L, 0, -1); + +    }, "Lua program ran without error"); +}); + + +test("[test-suite] code: no folding", function (t) { +    let luaCode = ` +        check(function () return -0.0 end, 'LOADK', 'UNM', 'RETURN') +        check(function () return 3/0 end, 'DIV', 'RETURN') +        check(function () return 0%0 end, 'MOD', 'RETURN') +        check(function () return -4//0 end, 'IDIV', 'RETURN') +    `, L; +     +    t.plan(2); + +    t.doesNotThrow(function () { + +        L = lauxlib.luaL_newstate(); + +        lualib.luaL_openlibs(L); + +        ltests.luaopen_tests(L); + +        lauxlib.luaL_loadstring(L, lua.to_luastring(prefix + luaCode)); + +    }, "Lua program loaded without error"); + +    t.doesNotThrow(function () { + +        lua.lua_call(L, 0, -1); + +    }, "Lua program ran without error"); +}); + + +test("[test-suite] code: bug in constant folding for 5.1", function (t) { +    let luaCode = ` +        check(function () return -nil end, 'LOADNIL', 'UNM', 'RETURN') + + +        check(function () +          local a,b,c +          b[c], a = c, b +          b[a], a = c, b +          a, b = c, a +          a = a +        end,  +          'LOADNIL', +          'MOVE', 'MOVE', 'SETTABLE', +          'MOVE', 'MOVE', 'MOVE', 'SETTABLE', +          'MOVE', 'MOVE', 'MOVE', +          -- no code for a = a +          'RETURN') +    `, L; +     +    t.plan(2); + +    t.doesNotThrow(function () { + +        L = lauxlib.luaL_newstate(); + +        lualib.luaL_openlibs(L); + +        ltests.luaopen_tests(L); + +        lauxlib.luaL_loadstring(L, lua.to_luastring(prefix + luaCode)); + +    }, "Lua program loaded without error"); + +    t.doesNotThrow(function () { + +        lua.lua_call(L, 0, -1); + +    }, "Lua program ran without error"); +}); + + +test("[test-suite] code: x == nil , x ~= nil", function (t) { +    let luaCode = ` +        checkequal(function () if (a==nil) then a=1 end; if a~=nil then a=1 end end, +                   function () if (a==9) then a=1 end; if a~=9 then a=1 end end) + +        check(function () if a==nil then a='a' end end, +            'GETTABUP', 'EQ', 'JMP', 'SETTABUP', 'RETURN') + +        checkequal(function () local a; if not (a or b) then b=a end end, +           function () local a; if (not a and not b) then b=a end end) + +        checkequal(function (l) local a; return 0 <= a and a <= l end, +                   function (l) local a; return not (not(a >= 0) or not(a <= l)) end) +    `, L; +     +    t.plan(2); + +    t.doesNotThrow(function () { + +        L = lauxlib.luaL_newstate(); + +        lualib.luaL_openlibs(L); + +        ltests.luaopen_tests(L); + +        lauxlib.luaL_loadstring(L, lua.to_luastring(prefix + luaCode)); + +    }, "Lua program loaded without error"); + +    t.doesNotThrow(function () { + +        lua.lua_call(L, 0, -1); + +    }, "Lua program ran without error"); +}); + + +test("[test-suite] code: if-goto optimizations", function (t) { +    let luaCode = ` +        check(function (a, b, c, d, e) +                if a == b then goto l1 +                elseif a == c then goto l2 +                elseif a == d then goto l2 +                else if a == e then goto l3 +                     else goto l3 +                     end +                end +                ::l1:: ::l2:: ::l3:: ::l4::  +        end, 'EQ', 'JMP', 'EQ', 'JMP', 'EQ', 'JMP', 'EQ', 'JMP', 'JMP', 'RETURN') + +        checkequal( +        function (a) while a < 10 do a = a + 1 end end, +        function (a) ::L2:: if not(a < 10) then goto L1 end; a = a + 1; +                        goto L2; ::L1:: end +        ) + +        checkequal( +        function (a) while a < 10 do a = a + 1 end end, +        function (a) while true do if not(a < 10) then break end; a = a + 1; end end +        ) +    `, L; +     +    t.plan(2); + +    t.doesNotThrow(function () { + +        L = lauxlib.luaL_newstate(); + +        lualib.luaL_openlibs(L); + +        ltests.luaopen_tests(L); + +        lauxlib.luaL_loadstring(L, lua.to_luastring(prefix + luaCode)); + +    }, "Lua program loaded without error"); + +    t.doesNotThrow(function () { + +        lua.lua_call(L, 0, -1); + +    }, "Lua program ran without error"); +}); | 
