436 lines
9.9 KiB
JavaScript
436 lines
9.9 KiB
JavaScript
"use strict";
|
|
|
|
const lua = require('../src/lua.js');
|
|
const lauxlib = require('../src/lauxlib.js');
|
|
const lualib = require('../src/lualib.js');
|
|
const {to_luastring} = require("../src/fengaricore.js");
|
|
|
|
|
|
test('print', () => {
|
|
let L = lauxlib.luaL_newstate();
|
|
if (!L) throw Error("failed to create lua state");
|
|
|
|
let luaCode = `
|
|
print("hello", "world", 123)
|
|
`;
|
|
{
|
|
lualib.luaL_openlibs(L);
|
|
expect(lauxlib.luaL_loadstring(L, to_luastring(luaCode))).toBe(lua.LUA_OK);
|
|
lua.lua_call(L, 0, -1);
|
|
}
|
|
});
|
|
|
|
|
|
test('setmetatable, getmetatable', () => {
|
|
let L = lauxlib.luaL_newstate();
|
|
if (!L) throw Error("failed to create lua state");
|
|
|
|
let luaCode = `
|
|
local mt = {
|
|
__index = function ()
|
|
return "hello"
|
|
end
|
|
}
|
|
|
|
local t = {}
|
|
|
|
setmetatable(t, mt);
|
|
|
|
return t[1], getmetatable(t)
|
|
`;
|
|
{
|
|
lualib.luaL_openlibs(L);
|
|
expect(lauxlib.luaL_loadstring(L, to_luastring(luaCode))).toBe(lua.LUA_OK);
|
|
lua.lua_call(L, 0, -1);
|
|
}
|
|
|
|
expect(lua.lua_tojsstring(L, -2))
|
|
.toBe("hello");
|
|
|
|
expect(lua.lua_istable(L, -1)).toBe(true);
|
|
});
|
|
|
|
|
|
test('rawequal', () => {
|
|
let L = lauxlib.luaL_newstate();
|
|
if (!L) throw Error("failed to create lua state");
|
|
|
|
let luaCode = `
|
|
local mt = {
|
|
__eq = function ()
|
|
return true
|
|
end
|
|
}
|
|
|
|
local t1 = {}
|
|
local t2 = {}
|
|
|
|
setmetatable(t1, mt);
|
|
|
|
return rawequal(t1, t2), t1 == t2
|
|
`;
|
|
{
|
|
lualib.luaL_openlibs(L);
|
|
expect(lauxlib.luaL_loadstring(L, to_luastring(luaCode))).toBe(lua.LUA_OK);
|
|
lua.lua_call(L, 0, -1);
|
|
}
|
|
|
|
expect(lua.lua_toboolean(L, -2)).toBe(false);
|
|
|
|
expect(lua.lua_toboolean(L, -1)).toBe(true);
|
|
});
|
|
|
|
|
|
test('rawset, rawget', () => {
|
|
let L = lauxlib.luaL_newstate();
|
|
if (!L) throw Error("failed to create lua state");
|
|
|
|
let luaCode = `
|
|
local mt = {
|
|
__newindex = function (table, key, value)
|
|
rawset(table, key, "hello")
|
|
end
|
|
}
|
|
|
|
local t = {}
|
|
|
|
setmetatable(t, mt);
|
|
|
|
t["yo"] = "bye"
|
|
rawset(t, "yoyo", "bye")
|
|
|
|
return rawget(t, "yo"), t["yo"], rawget(t, "yoyo"), t["yoyo"]
|
|
`;
|
|
{
|
|
lualib.luaL_openlibs(L);
|
|
expect(lauxlib.luaL_loadstring(L, to_luastring(luaCode))).toBe(lua.LUA_OK);
|
|
lua.lua_call(L, 0, -1);
|
|
}
|
|
|
|
expect(lua.lua_tojsstring(L, -4))
|
|
.toBe("hello");
|
|
|
|
expect(lua.lua_tojsstring(L, -3))
|
|
.toBe("hello");
|
|
|
|
expect(lua.lua_tojsstring(L, -2))
|
|
.toBe("bye");
|
|
|
|
expect(lua.lua_tojsstring(L, -1))
|
|
.toBe("bye");
|
|
});
|
|
|
|
|
|
test('type', () => {
|
|
let L = lauxlib.luaL_newstate();
|
|
if (!L) throw Error("failed to create lua state");
|
|
|
|
let luaCode = `
|
|
return type(1), type(true), type("hello"), type({}), type(nil)
|
|
`;
|
|
{
|
|
lualib.luaL_openlibs(L);
|
|
expect(lauxlib.luaL_loadstring(L, to_luastring(luaCode))).toBe(lua.LUA_OK);
|
|
lua.lua_call(L, 0, -1);
|
|
}
|
|
|
|
expect(lua.lua_tojsstring(L, -5))
|
|
.toBe("number");
|
|
|
|
expect(lua.lua_tojsstring(L, -4))
|
|
.toBe("boolean");
|
|
|
|
expect(lua.lua_tojsstring(L, -3))
|
|
.toBe("string");
|
|
|
|
expect(lua.lua_tojsstring(L, -2))
|
|
.toBe("table");
|
|
|
|
expect(lua.lua_tojsstring(L, -1))
|
|
.toBe("nil");
|
|
});
|
|
|
|
|
|
test('error', () => {
|
|
let L = lauxlib.luaL_newstate();
|
|
if (!L) throw Error("failed to create lua state");
|
|
|
|
let luaCode = `
|
|
error("you fucked up")
|
|
`;
|
|
{
|
|
lualib.luaL_openlibs(L);
|
|
expect(lauxlib.luaL_loadstring(L, to_luastring(luaCode))).toBe(lua.LUA_OK);
|
|
expect(() => {
|
|
lua.lua_call(L, 0, -1);
|
|
}).toThrow(/you fucked up/);
|
|
}
|
|
});
|
|
|
|
|
|
test('error, protected', () => {
|
|
let L = lauxlib.luaL_newstate();
|
|
if (!L) throw Error("failed to create lua state");
|
|
|
|
let luaCode = `
|
|
error("you fucked up")
|
|
`;
|
|
{
|
|
lualib.luaL_openlibs(L);
|
|
expect(lauxlib.luaL_loadstring(L, to_luastring(luaCode))).toBe(lua.LUA_OK);
|
|
lua.lua_pcall(L, 0, -1, 0);
|
|
}
|
|
|
|
expect(lua.lua_tojsstring(L, -1)).toMatch(/you fucked up/);
|
|
});
|
|
|
|
|
|
test('pcall', () => {
|
|
let L = lauxlib.luaL_newstate();
|
|
if (!L) throw Error("failed to create lua state");
|
|
|
|
let luaCode = `
|
|
local willFail = function ()
|
|
error("you fucked up")
|
|
end
|
|
|
|
return pcall(willFail)
|
|
`;
|
|
{
|
|
lualib.luaL_openlibs(L);
|
|
expect(lauxlib.luaL_loadstring(L, to_luastring(luaCode))).toBe(lua.LUA_OK);
|
|
lua.lua_call(L, 0, -1);
|
|
}
|
|
|
|
expect(lua.lua_tojsstring(L, -1)).toMatch(/you fucked up/);
|
|
});
|
|
|
|
|
|
test('xpcall', () => {
|
|
let L = lauxlib.luaL_newstate();
|
|
if (!L) throw Error("failed to create lua state");
|
|
|
|
let luaCode = `
|
|
local willFail = function ()
|
|
error("you fucked up")
|
|
end
|
|
|
|
local msgh = function (err)
|
|
return "Something's wrong: " .. err
|
|
end
|
|
|
|
return xpcall(willFail, msgh)
|
|
`;
|
|
{
|
|
lualib.luaL_openlibs(L);
|
|
expect(lauxlib.luaL_loadstring(L, to_luastring(luaCode))).toBe(lua.LUA_OK);
|
|
lua.lua_call(L, 0, -1);
|
|
}
|
|
|
|
expect(lua.lua_tojsstring(L, -1)).toMatch(/Something's wrong: .*you fucked up/);
|
|
});
|
|
|
|
|
|
test('ipairs', () => {
|
|
let L = lauxlib.luaL_newstate();
|
|
if (!L) throw Error("failed to create lua state");
|
|
|
|
let luaCode = `
|
|
local t = {1, 2, 3, 4, 5, ['yo'] = 'lo'}
|
|
|
|
local sum = 0
|
|
for i, v in ipairs(t) do
|
|
sum = sum + v
|
|
end
|
|
|
|
return sum
|
|
`;
|
|
{
|
|
lualib.luaL_openlibs(L);
|
|
expect(lauxlib.luaL_loadstring(L, to_luastring(luaCode))).toBe(lua.LUA_OK);
|
|
lua.lua_call(L, 0, -1);
|
|
}
|
|
|
|
expect(lua.lua_tointeger(L, -1)).toBe(15);
|
|
});
|
|
|
|
|
|
test('select', () => {
|
|
let L = lauxlib.luaL_newstate();
|
|
if (!L) throw Error("failed to create lua state");
|
|
|
|
let luaCode = `
|
|
return {select('#', 1, 2, 3)}, {select(2, 1, 2, 3)}, {select(-2, 1, 2, 3)}
|
|
`;
|
|
{
|
|
lualib.luaL_openlibs(L);
|
|
expect(lauxlib.luaL_loadstring(L, to_luastring(luaCode))).toBe(lua.LUA_OK);
|
|
lua.lua_call(L, 0, -1);
|
|
}
|
|
|
|
expect([...lua.lua_topointer(L, -3).strong.entries()].map(e => e[1].value.value))
|
|
.toEqual([3]);
|
|
|
|
expect([...lua.lua_topointer(L, -2).strong.entries()].map(e => e[1].value.value).sort())
|
|
.toEqual([2, 3]);
|
|
|
|
expect([...lua.lua_topointer(L, -1).strong.entries()].map(e => e[1].value.value).sort())
|
|
.toEqual([2, 3]);
|
|
});
|
|
|
|
|
|
test('tonumber', () => {
|
|
let L = lauxlib.luaL_newstate();
|
|
if (!L) throw Error("failed to create lua state");
|
|
|
|
let luaCode = `
|
|
return tonumber('foo'),
|
|
tonumber('123'),
|
|
tonumber('12.3'),
|
|
tonumber('az', 36),
|
|
tonumber('10', 2)
|
|
`;
|
|
{
|
|
lualib.luaL_openlibs(L);
|
|
expect(lauxlib.luaL_loadstring(L, to_luastring(luaCode))).toBe(lua.LUA_OK);
|
|
lua.lua_call(L, 0, -1);
|
|
}
|
|
|
|
expect(lua.lua_isnil(L, -5)).toBe(true);
|
|
expect(lua.lua_tonumber(L, -4)).toBe(123);
|
|
expect(lua.lua_tonumber(L, -3)).toBe(12.3);
|
|
expect(lua.lua_tonumber(L, -2)).toBe(395);
|
|
expect(lua.lua_tonumber(L, -1)).toBe(2);
|
|
});
|
|
|
|
|
|
test('assert', () => {
|
|
let L = lauxlib.luaL_newstate();
|
|
if (!L) throw Error("failed to create lua state");
|
|
|
|
let luaCode = `
|
|
assert(1 < 0, "this doesn't makes sense")
|
|
`;
|
|
{
|
|
lualib.luaL_openlibs(L);
|
|
expect(lauxlib.luaL_loadstring(L, to_luastring(luaCode))).toBe(lua.LUA_OK);
|
|
lua.lua_pcall(L, 0, -1, 0);
|
|
}
|
|
|
|
expect(lua.lua_tojsstring(L, -1)).toMatch(/this doesn't makes sense/);
|
|
});
|
|
|
|
|
|
test('rawlen', () => {
|
|
let L = lauxlib.luaL_newstate();
|
|
if (!L) throw Error("failed to create lua state");
|
|
|
|
let luaCode = `
|
|
return rawlen({1, 2, 3}), rawlen('hello')
|
|
`;
|
|
{
|
|
lualib.luaL_openlibs(L);
|
|
expect(lauxlib.luaL_loadstring(L, to_luastring(luaCode))).toBe(lua.LUA_OK);
|
|
lua.lua_call(L, 0, -1);
|
|
}
|
|
|
|
expect(lua.lua_tonumber(L, -2)).toBe(3);
|
|
expect(lua.lua_tonumber(L, -1)).toBe(5);
|
|
});
|
|
|
|
|
|
test('next', () => {
|
|
let L = lauxlib.luaL_newstate();
|
|
if (!L) throw Error("failed to create lua state");
|
|
|
|
let luaCode = `
|
|
local total = 0
|
|
local t = {
|
|
1,
|
|
two = 2,
|
|
3,
|
|
four = 4
|
|
}
|
|
|
|
for k,v in next, t, nil do
|
|
total = total + v
|
|
end
|
|
|
|
return total
|
|
`;
|
|
{
|
|
lualib.luaL_openlibs(L);
|
|
expect(lauxlib.luaL_loadstring(L, to_luastring(luaCode))).toBe(lua.LUA_OK);
|
|
lua.lua_call(L, 0, -1);
|
|
}
|
|
|
|
expect(lua.lua_tonumber(L, -1)).toBe(10);
|
|
});
|
|
|
|
|
|
test('pairs', () => {
|
|
let L = lauxlib.luaL_newstate();
|
|
if (!L) throw Error("failed to create lua state");
|
|
|
|
let luaCode = `
|
|
local total = 0
|
|
local t = {
|
|
1,
|
|
two = 2,
|
|
3,
|
|
four = 4
|
|
}
|
|
|
|
for k,v in pairs(t) do
|
|
total = total + v
|
|
end
|
|
|
|
return total
|
|
`;
|
|
{
|
|
lualib.luaL_openlibs(L);
|
|
expect(lauxlib.luaL_loadstring(L, to_luastring(luaCode))).toBe(lua.LUA_OK);
|
|
lua.lua_call(L, 0, -1);
|
|
}
|
|
|
|
expect(lua.lua_tonumber(L, -1)).toBe(10);
|
|
});
|
|
|
|
|
|
test('pairs with __pairs', () => {
|
|
let L = lauxlib.luaL_newstate();
|
|
if (!L) throw Error("failed to create lua state");
|
|
|
|
let luaCode = `
|
|
local total = 0
|
|
|
|
local mt = {
|
|
__pairs = function(t)
|
|
return next, {5, 6, 7, 8}, nil
|
|
end
|
|
}
|
|
|
|
local t = {
|
|
1,
|
|
two = 2,
|
|
3,
|
|
four = 4
|
|
}
|
|
|
|
setmetatable(t, mt)
|
|
|
|
for k,v in pairs(t) do
|
|
total = total + v
|
|
end
|
|
|
|
return total
|
|
`;
|
|
{
|
|
lualib.luaL_openlibs(L);
|
|
expect(lauxlib.luaL_loadstring(L, to_luastring(luaCode))).toBe(lua.LUA_OK);
|
|
lua.lua_call(L, 0, -1);
|
|
}
|
|
|
|
expect(lua.lua_tonumber(L, -1)).toBe(26);
|
|
});
|