aboutsummaryrefslogtreecommitdiff
path: root/games
diff options
context:
space:
mode:
authorsfan5 <sfan5@live.de>2022-05-02 20:55:04 +0200
committersfan5 <sfan5@live.de>2022-05-02 20:56:06 +0200
commite7659883cc6fca343785da2a1af3890ae273abbf (patch)
treeb8d2e3bdbe10ed0e99074207113e24ccca3fb5df /games
parent663c9364289dae45aeb86a87cba826f577d84a9c (diff)
downloadminetest-e7659883cc6fca343785da2a1af3890ae273abbf.tar.gz
minetest-e7659883cc6fca343785da2a1af3890ae273abbf.tar.bz2
minetest-e7659883cc6fca343785da2a1af3890ae273abbf.zip
Async environment for mods to do concurrent tasks (#11131)
Diffstat (limited to 'games')
-rw-r--r--games/devtest/mods/unittests/async_env.lua149
-rw-r--r--games/devtest/mods/unittests/init.lua1
-rw-r--r--games/devtest/mods/unittests/inside_async_env.lua15
3 files changed, 165 insertions, 0 deletions
diff --git a/games/devtest/mods/unittests/async_env.lua b/games/devtest/mods/unittests/async_env.lua
new file mode 100644
index 000000000..aff1fc4d9
--- /dev/null
+++ b/games/devtest/mods/unittests/async_env.lua
@@ -0,0 +1,149 @@
+-- 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,
+ light_source = 0,
+}
+
+local function test_object_passing()
+ local tmp = core.serialize_roundtrip(test_object)
+ assert(deepequal(test_object, tmp))
+
+ -- Circular key, should error
+ tmp = {"foo", "bar"}
+ tmp[tmp] = true
+ assert(not pcall(core.serialize_roundtrip, tmp))
+
+ -- Circular value, should error
+ tmp = {"foo"}
+ tmp[2] = tmp
+ assert(not pcall(core.serialize_roundtrip, tmp))
+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
+ cb("Values did not equal")
+ end
+ if core.get_last_run_mod() ~= expect[1] then
+ 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
+ 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
+ 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
+ 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})
diff --git a/games/devtest/mods/unittests/init.lua b/games/devtest/mods/unittests/init.lua
index 0754d507f..0608f2dd2 100644
--- a/games/devtest/mods/unittests/init.lua
+++ b/games/devtest/mods/unittests/init.lua
@@ -175,6 +175,7 @@ dofile(modpath .. "/misc.lua")
dofile(modpath .. "/player.lua")
dofile(modpath .. "/crafting.lua")
dofile(modpath .. "/itemdescription.lua")
+dofile(modpath .. "/async_env.lua")
--------------
diff --git a/games/devtest/mods/unittests/inside_async_env.lua b/games/devtest/mods/unittests/inside_async_env.lua
new file mode 100644
index 000000000..9774771f9
--- /dev/null
+++ b/games/devtest/mods/unittests/inside_async_env.lua
@@ -0,0 +1,15 @@
+unittests = {}
+
+core.log("info", "Hello World")
+
+function unittests.async_test()
+ assert(core == minetest)
+ -- stuff that should not be here
+ assert(not core.get_player_by_name)
+ assert(not core.set_node)
+ assert(not core.object_refs)
+ -- stuff that should be here
+ assert(ItemStack)
+ assert(core.registered_items[""])
+ return true
+end