modlib/test.lua

276 lines
7.3 KiB
Lua
Raw Permalink Normal View History

2021-03-24 23:46:17 +01:00
-- TODO make tests minetest-independent
local random, huge = math.random, math.huge
local parent_env = getfenv(1)
setfenv(1, setmetatable({}, {
2021-03-27 20:10:49 +01:00
__index = function(_, key)
local value = modlib[key]
if value ~= nil then
return value
end
return parent_env[key]
end,
__newindex = function(_, key, value)
error(dump{key = key, value = value})
end
2021-03-24 23:46:17 +01:00
}))
2021-03-24 20:27:02 +01:00
2021-01-19 13:24:10 +01:00
-- string
2021-03-24 23:46:17 +01:00
assert(string.escape_magic_chars"%" == "%%")
2021-01-19 13:24:10 +01:00
2021-01-19 13:18:25 +01:00
-- table
2021-01-19 13:24:10 +01:00
do
2021-03-27 20:10:49 +01:00
local tab = {}
tab[tab] = tab
local table_copy = table.deepcopy(tab)
assert(table_copy[table_copy] == table_copy)
assert(table.is_circular(tab))
assert(not table.is_circular{a = 1})
assert(table.equals_noncircular({[{}]={}}, {[{}]={}}))
assert(table.equals_content(tab, table_copy))
local equals_references = table.equals_references
assert(equals_references(tab, table_copy))
assert(equals_references({}, {}))
assert(not equals_references({a = 1, b = 2}, {a = 1, b = 3}))
tab = {}
tab.a, tab.b = tab, tab
table_copy = table.deepcopy(tab)
assert(equals_references(tab, table_copy))
local x, y = {}, {}
assert(not equals_references({[x] = x, [y] = y}, {[x] = y, [y] = x}))
assert(equals_references({[x] = x, [y] = y}, {[x] = x, [y] = y}))
local nilget = table.nilget
assert(nilget({a = {b = {c = 42}}}, "a", "b", "c") == 42)
assert(nilget({a = {}}, "a", "b", "c") == nil)
assert(nilget(nil, "a", "b", "c") == nil)
assert(nilget(nil, "a", nil, "c") == nil)
local rope = table.rope{}
rope:write"hello"
rope:write" "
rope:write"world"
assert(rope:to_text() == "hello world", rope:to_text())
2021-01-19 13:24:10 +01:00
end
-- heap
do
2021-03-27 20:10:49 +01:00
local n = 100
local list = {}
for index = 1, n do
list[index] = index
end
table.shuffle(list)
local heap = heap.new()
for index = 1, #list do
heap:push(list[index])
end
for index = 1, #list do
local popped = heap:pop()
assert(popped == index)
end
2021-01-19 13:24:10 +01:00
end
2021-01-25 21:18:56 +01:00
-- ranked set
do
2021-03-27 20:10:49 +01:00
local n = 100
local ranked_set = ranked_set.new()
local list = {}
for i = 1, n do
ranked_set:insert(i)
list[i] = i
end
2021-01-25 21:18:56 +01:00
2021-03-27 20:10:49 +01:00
assert(table.equals(ranked_set:to_table(), list))
2021-01-25 21:18:56 +01:00
2021-03-27 20:10:49 +01:00
local i = 0
for rank, key in ranked_set:ipairs() do
i = i + 1
assert(i == key and i == rank)
assert(ranked_set:get_by_rank(rank) == key)
local rank, key = ranked_set:get(i)
assert(key == i and i == rank)
end
assert(i == n)
2021-01-25 21:18:56 +01:00
2021-03-27 20:10:49 +01:00
for i = 1, n do
local _, v = ranked_set:delete(i)
assert(v == i, i)
end
assert(not next(ranked_set:to_table()))
2021-01-25 21:18:56 +01:00
2021-03-27 20:10:49 +01:00
local ranked_set = ranked_set.new()
for i = 1, n do
ranked_set:insert(i)
end
2021-01-25 21:18:56 +01:00
2021-03-27 20:10:49 +01:00
for rank, key in ranked_set:ipairs(10, 20) do
assert(rank == key and key >= 10 and key <= 20)
end
2021-01-25 21:18:56 +01:00
2021-03-27 20:10:49 +01:00
for i = n, 1, -1 do
local j = ranked_set:delete_by_rank(i)
assert(j == i)
end
2021-01-25 21:18:56 +01:00
end
2021-01-29 12:32:51 +01:00
-- colorspec
2021-03-27 12:18:27 +01:00
local colorspec = minetest.colorspec
local function test_from_string(string, number)
2021-03-27 20:10:49 +01:00
local spec = colorspec.from_string(string)
local expected = colorspec.from_number(number)
assertdump(table.equals(spec, expected), {expected = expected, actual = spec})
2021-03-27 12:18:27 +01:00
end
local spec = colorspec.from_number(0xDDCCBBAA)
assertdump(table.equals(spec, {a = 0xAA, b = 0xBB, g = 0xCC, r = 0xDD}), spec)
test_from_string("aliceblue", 0xf0f8ffff)
test_from_string("aliceblue#42", 0xf0f8ff42)
test_from_string("#333", 0x333333FF)
test_from_string("#694269", 0x694269FF)
test_from_string("#11223344", 0x11223344)
2021-01-29 12:32:51 +01:00
2021-02-07 14:00:48 +01:00
-- k-d-tree
local vectors = {}
for _ = 1, 1000 do
2021-03-27 20:10:49 +01:00
_G.table.insert(vectors, {random(), random(), random()})
2021-02-07 14:00:48 +01:00
end
2021-03-24 23:46:17 +01:00
local kdtree = kdtree.new(vectors)
for _, v in ipairs(vectors) do
2021-03-27 20:10:49 +01:00
local neighbor, distance = kdtree:get_nearest_neighbor(v)
assert(vector.equals(v, neighbor), distance == 0)
2021-02-07 14:00:48 +01:00
end
for _ = 1, 1000 do
2021-03-27 20:10:49 +01:00
local v = {random(), random(), random()}
local _, distance = kdtree:get_nearest_neighbor(v)
local min_distance = huge
for _, w in ipairs(vectors) do
local other_distance = vector.distance(v, w)
if other_distance < min_distance then
min_distance = other_distance
end
end
assert(distance == min_distance)
2021-02-07 14:00:48 +01:00
end
-- bluon
do
2021-03-27 20:10:49 +01:00
local bluon = bluon
local function assert_preserves(object)
local rope = table.rope{}
local written, read, input
local _, err = pcall(function()
bluon:write(object, rope)
written = rope:to_text()
input = text.inputstream(written)
read = bluon:read(input)
local remaining = input:read(1000)
assert(not remaining)
end)
assertdump(table.equals_references(object, read) and not err, {
object = object,
read = read,
written = written and text.hexdump(written),
err = err
})
end
for _, constant in pairs{true, false, huge, -huge} do
assert_preserves(constant)
end
for i = 1, 1000 do
assert_preserves(_G.table.concat(table.repetition(_G.string.char(i % 256), i)))
end
for _ = 1, 1000 do
local int = random(-2^50, 2^50)
assert(int % 1 == 0)
assert_preserves(int)
assert_preserves((random() - 0.5) * 2^random(-20, 20))
end
assert_preserves{hello = "world", welt = "hallo"}
assert_preserves{"hello", "hello", "hello"}
local a = {}
a[a] = a
a[1] = a
assert_preserves(a)
end
2021-02-01 16:27:21 +01:00
-- in-game tests & b3d testing
2020-12-21 20:26:06 +01:00
local tests = {
2021-03-27 20:10:49 +01:00
-- depends on player_api
b3d = false,
liquid_dir = false,
liquid_raycast = false
2020-12-21 20:26:06 +01:00
}
2021-02-01 16:27:21 +01:00
if tests.b3d then
2021-03-27 20:10:49 +01:00
local stream = io.open(mod.get_resource("player_api", "models", "character.b3d"), "r")
assert(stream)
local b3d = b3d.read(stream)
--! dirty helper method to create truncate tables with 10+ number keys
local function _b3d_truncate(table)
local count = 1
for key, value in pairs(table) do
if type(key) == "table" then
_b3d_truncate(key)
end
if type(value) == "table" then
_b3d_truncate(value)
end
count = count + 1
if type(key) == "number" and count >= 9 and next(table, key) then
if count == 9 then
table[key] = "TRUNCATED"
else
table[key] = nil
end
end
end
return table
end
file.write(mod.get_resource"character.b3d.lua", "return " .. dump(_b3d_truncate(table.copy(b3d))))
stream:close()
2021-02-01 16:27:21 +01:00
end
2021-03-24 23:46:17 +01:00
local vector, minetest, ml_mt = _G.vector, _G.minetest, minetest
2020-12-21 20:26:06 +01:00
if tests.liquid_dir then
2021-03-27 20:10:49 +01:00
minetest.register_abm{
label = "get_liquid_corner_levels & get_liquid_direction test",
nodenames = {"group:liquid"},
interval = 1,
chance = 1,
action = function(pos, node)
assert(type(node) == "table")
for _, corner_level in pairs(ml_mt.get_liquid_corner_levels(pos, node)) do
minetest.add_particle{
pos = vector.add(pos, corner_level),
size = 2,
texture = "logo.png"
}
end
local direction = ml_mt.get_liquid_flow_direction(pos, node)
local start_pos = pos
start_pos.y = start_pos.y + 1
for i = 0, 5 do
minetest.add_particle{
pos = vector.add(start_pos, vector.multiply(direction, i/5)),
size = i/2.5,
texture = "logo.png"
}
end
end
}
2020-12-21 20:26:06 +01:00
end
if tests.liquid_raycast then
2021-03-27 20:10:49 +01:00
minetest.register_globalstep(function()
for _, player in pairs(minetest.get_connected_players()) do
local eye_pos = vector.offset(player:get_pos(), 0, player:get_properties().eye_height, 0)
local raycast = ml_mt.raycast(eye_pos, vector.add(eye_pos, vector.multiply(player:get_look_dir(), 3)), false, true)
for pointed_thing in raycast do
if pointed_thing.type == "node" and minetest.registered_nodes[minetest.get_node(pointed_thing.under).name].liquidtype == "flowing" then
minetest.add_particle{
pos = vector.add(pointed_thing.intersection_point, vector.multiply(pointed_thing.intersection_normal, 0.1)),
size = 0.5,
texture = "object_marker_red.png",
expirationtime = 3
}
end
end
end
end)
2020-12-21 20:26:06 +01:00
end