mirror of
https://github.com/minetest/minetest.git
synced 2024-11-19 22:23:46 +01:00
fc80f65a6d
Co-authored-by: sfan5 <sfan5@live.de> Co-authored-by: Lars Mueller <appgurulars@gmx.de>
210 lines
6.0 KiB
Lua
210 lines
6.0 KiB
Lua
-- helper
|
|
|
|
core.register_async_dofile(core.get_modpath(core.get_current_modname()) ..
|
|
DIR_DELIM .. "inside_async_env.lua")
|
|
|
|
local function deepequal(a, b)
|
|
if type(a) == "function" then
|
|
return type(b) == "function"
|
|
elseif type(a) ~= "table" then
|
|
return a == b
|
|
elseif type(b) ~= "table" then
|
|
return false
|
|
end
|
|
for k, v in pairs(a) do
|
|
if not deepequal(v, b[k]) then
|
|
return false
|
|
end
|
|
end
|
|
for k, v in pairs(b) do
|
|
if not deepequal(a[k], v) then
|
|
return false
|
|
end
|
|
end
|
|
return true
|
|
end
|
|
|
|
-- Object Passing / Serialization
|
|
|
|
local test_object = {
|
|
name = "stairs:stair_glass",
|
|
type = "node",
|
|
groups = {oddly_breakable_by_hand = 3, cracky = 3, stair = 1},
|
|
description = "Glass Stair",
|
|
sounds = {
|
|
dig = {name = "default_glass_footstep", gain = 0.5},
|
|
footstep = {name = "default_glass_footstep", gain = 0.3},
|
|
dug = {name = "default_break_glass", gain = 1}
|
|
},
|
|
node_box = {
|
|
fixed = {
|
|
{-0.5, -0.5, -0.5, 0.5, 0, 0.5},
|
|
{-0.5, 0, 0, 0.5, 0.5, 0.5}
|
|
},
|
|
type = "fixed"
|
|
},
|
|
tiles = {
|
|
{name = "stairs_glass_split.png", backface_culling = true},
|
|
{name = "default_glass.png", backface_culling = true},
|
|
{name = "stairs_glass_stairside.png^[transformFX", backface_culling = true}
|
|
},
|
|
on_place = function(itemstack, placer)
|
|
return core.is_player(placer)
|
|
end,
|
|
sunlight_propagates = true,
|
|
is_ground_content = false,
|
|
pos = vector.new(-1, -2, -3),
|
|
}
|
|
|
|
local function test_object_passing()
|
|
local tmp = core.serialize_roundtrip(test_object)
|
|
assert(deepequal(test_object, tmp))
|
|
|
|
local circular_key = {"foo", "bar"}
|
|
circular_key[circular_key] = true
|
|
tmp = core.serialize_roundtrip(circular_key)
|
|
assert(tmp[1] == "foo")
|
|
assert(tmp[2] == "bar")
|
|
assert(tmp[tmp] == true)
|
|
|
|
local circular_value = {"foo"}
|
|
circular_value[2] = circular_value
|
|
tmp = core.serialize_roundtrip(circular_value)
|
|
assert(tmp[1] == "foo")
|
|
assert(tmp[2] == tmp)
|
|
|
|
-- Two-segment cycle
|
|
local cycle_seg_1, cycle_seg_2 = {}, {}
|
|
cycle_seg_1[1] = cycle_seg_2
|
|
cycle_seg_2[1] = cycle_seg_1
|
|
tmp = core.serialize_roundtrip(cycle_seg_1)
|
|
assert(tmp[1][1] == tmp)
|
|
|
|
-- Duplicated value without a cycle
|
|
local acyclic_dup_holder = {}
|
|
tmp = ItemStack("")
|
|
acyclic_dup_holder[tmp] = tmp
|
|
tmp = core.serialize_roundtrip(acyclic_dup_holder)
|
|
for k, v in pairs(tmp) do
|
|
assert(rawequal(k, v))
|
|
end
|
|
end
|
|
unittests.register("test_object_passing", test_object_passing)
|
|
|
|
local function test_userdata_passing(_, pos)
|
|
-- basic userdata passing
|
|
local obj = table.copy(test_object.tiles[1])
|
|
obj.test = ItemStack("default:cobble 99")
|
|
local tmp = core.serialize_roundtrip(obj)
|
|
assert(type(tmp.test) == "userdata")
|
|
assert(obj.test:to_string() == tmp.test:to_string())
|
|
|
|
-- object can't be passed, should error
|
|
obj = core.raycast(pos, pos)
|
|
assert(not pcall(core.serialize_roundtrip, obj))
|
|
|
|
-- VManip
|
|
local vm = core.get_voxel_manip(pos, pos)
|
|
local expect = vm:get_node_at(pos)
|
|
local vm2 = core.serialize_roundtrip(vm)
|
|
assert(deepequal(vm2:get_node_at(pos), expect))
|
|
end
|
|
unittests.register("test_userdata_passing", test_userdata_passing, {map=true})
|
|
|
|
-- Asynchronous jobs
|
|
|
|
local function test_handle_async(cb)
|
|
-- Basic test including mod name tracking and unittests.async_test()
|
|
-- which is defined inside_async_env.lua
|
|
local func = function(x)
|
|
return core.get_last_run_mod(), _VERSION, unittests[x]()
|
|
end
|
|
local expect = {core.get_last_run_mod(), _VERSION, true}
|
|
|
|
core.handle_async(func, function(...)
|
|
if not deepequal(expect, {...}) then
|
|
return cb("Values did not equal")
|
|
end
|
|
if core.get_last_run_mod() ~= expect[1] then
|
|
return cb("Mod name not tracked correctly")
|
|
end
|
|
|
|
-- Test passing of nil arguments and return values
|
|
core.handle_async(function(a, b)
|
|
return a, b
|
|
end, function(a, b)
|
|
if b ~= 123 then
|
|
return cb("Argument went missing")
|
|
end
|
|
cb()
|
|
end, nil, 123)
|
|
end, "async_test")
|
|
end
|
|
unittests.register("test_handle_async", test_handle_async, {async=true})
|
|
|
|
local function test_userdata_passing2(cb, _, pos)
|
|
-- VManip: check transfer into other env
|
|
local vm = core.get_voxel_manip(pos, pos)
|
|
local expect = vm:get_node_at(pos)
|
|
|
|
core.handle_async(function(vm_, pos_)
|
|
return vm_:get_node_at(pos_)
|
|
end, function(ret)
|
|
if not deepequal(expect, ret) then
|
|
return cb("Node data mismatch (one-way)")
|
|
end
|
|
|
|
-- VManip: test a roundtrip
|
|
core.handle_async(function(vm_)
|
|
return vm_
|
|
end, function(vm2)
|
|
if not deepequal(expect, vm2:get_node_at(pos)) then
|
|
return cb("Node data mismatch (roundtrip)")
|
|
end
|
|
cb()
|
|
end, vm)
|
|
end, vm, pos)
|
|
end
|
|
unittests.register("test_userdata_passing2", test_userdata_passing2, {map=true, async=true})
|
|
|
|
local function test_async_metatable_override()
|
|
assert(pcall(core.register_async_metatable, "__builtin:vector", vector.metatable),
|
|
"Metatable name aliasing throws an error when it should be allowed")
|
|
|
|
assert(not pcall(core.register_async_metatable, "__builtin:vector", {}),
|
|
"Illegal metatable overriding allowed")
|
|
end
|
|
unittests.register("test_async_metatable_override", test_async_metatable_override)
|
|
|
|
local function test_async_metatable_registration(cb)
|
|
local custom_metatable = {}
|
|
core.register_async_metatable("unittests:custom_metatable", custom_metatable)
|
|
|
|
core.handle_async(function(x)
|
|
-- unittests.custom_metatable is registered in inside_async_env.lua
|
|
return getmetatable(x) == unittests.custom_metatable, x
|
|
end, function(metatable_preserved_async, table_after_roundtrip)
|
|
if not metatable_preserved_async then
|
|
return cb("Custom metatable not preserved (main -> async)")
|
|
end
|
|
if getmetatable(table_after_roundtrip) ~= custom_metatable then
|
|
return cb("Custom metable not preserved (after roundtrip)")
|
|
end
|
|
cb()
|
|
end, setmetatable({}, custom_metatable))
|
|
end
|
|
unittests.register("test_async_metatable_registration", test_async_metatable_registration, {async=true})
|
|
|
|
local function test_vector_preserve(cb)
|
|
local vec = vector.new(1, 2, 3)
|
|
core.handle_async(function(x)
|
|
return x[1]
|
|
end, function(ret)
|
|
if ret ~= vec then -- fails if metatable was not preserved
|
|
return cb("Vector value mismatch")
|
|
end
|
|
cb()
|
|
end, {vec})
|
|
end
|
|
unittests.register("test_async_vector", test_vector_preserve, {async=true})
|