misc.lua 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. core.register_mapgen_script(core.get_modpath(core.get_current_modname()) ..
  2. DIR_DELIM .. "inside_mapgen_env.lua")
  3. local function test_pseudo_random()
  4. -- We have comprehensive unit tests in C++, this is just to make sure the API code isn't messing up
  5. local gen1 = PseudoRandom(13)
  6. assert(gen1:next() == 22290)
  7. assert(gen1:next() == 13854)
  8. local gen2 = PseudoRandom(gen1:get_state())
  9. for n = 0, 16 do
  10. assert(gen1:next() == gen2:next())
  11. end
  12. local pr3 = PseudoRandom(-101)
  13. assert(pr3:next(0, 100) == 35)
  14. -- unusual case that is normally disallowed:
  15. assert(pr3:next(10000, 42767) == 12485)
  16. end
  17. unittests.register("test_pseudo_random", test_pseudo_random)
  18. local function test_pcg_random()
  19. -- We have comprehensive unit tests in C++, this is just to make sure the API code isn't messing up
  20. local gen1 = PcgRandom(55)
  21. for n = 0, 16 do
  22. gen1:next()
  23. end
  24. local gen2 = PcgRandom(26)
  25. gen2:set_state(gen1:get_state())
  26. for n = 16, 32 do
  27. assert(gen1:next() == gen2:next())
  28. end
  29. end
  30. unittests.register("test_pcg_random", test_pcg_random)
  31. local function test_dynamic_media(cb, player)
  32. if core.get_player_information(player:get_player_name()).protocol_version < 40 then
  33. core.log("warning", "test_dynamic_media: Client too old, skipping test.")
  34. return cb()
  35. end
  36. -- Check that the client acknowledges media transfers
  37. local path = core.get_worldpath() .. "/test_media.obj"
  38. local f = io.open(path, "w")
  39. f:write("# contents don't matter\n")
  40. f:close()
  41. local call_ok = false
  42. local ok = core.dynamic_add_media({
  43. filepath = path,
  44. to_player = player:get_player_name(),
  45. }, function(name)
  46. if not call_ok then
  47. return cb("impossible condition")
  48. end
  49. cb()
  50. end)
  51. if not ok then
  52. return cb("dynamic_add_media() returned error")
  53. end
  54. call_ok = true
  55. -- if the callback isn't called this test will just hang :shrug:
  56. end
  57. unittests.register("test_dynamic_media", test_dynamic_media, {async=true, player=true})
  58. local function test_v3f_metatable(player)
  59. assert(vector.check(player:get_pos()))
  60. end
  61. unittests.register("test_v3f_metatable", test_v3f_metatable, {player=true})
  62. local function test_v3s16_metatable(player, pos)
  63. local node = minetest.get_node(pos)
  64. local found_pos = minetest.find_node_near(pos, 0, node.name, true)
  65. assert(vector.check(found_pos))
  66. end
  67. unittests.register("test_v3s16_metatable", test_v3s16_metatable, {map=true})
  68. local function test_clear_meta(_, pos)
  69. local ref = core.get_meta(pos)
  70. for way = 1, 3 do
  71. ref:set_string("foo", "bar")
  72. assert(ref:contains("foo"))
  73. if way == 1 then
  74. ref:from_table({})
  75. elseif way == 2 then
  76. ref:from_table(nil)
  77. else
  78. ref:set_string("foo", "")
  79. end
  80. assert(#core.find_nodes_with_meta(pos, pos) == 0, "clearing failed " .. way)
  81. end
  82. end
  83. unittests.register("test_clear_meta", test_clear_meta, {map=true})
  84. local on_punch_called
  85. minetest.register_on_punchnode(function()
  86. on_punch_called = true
  87. end)
  88. unittests.register("test_punch_node", function(_, pos)
  89. minetest.place_node(pos, {name="basenodes:dirt"})
  90. on_punch_called = false
  91. minetest.punch_node(pos)
  92. minetest.remove_node(pos)
  93. -- currently failing: assert(on_punch_called)
  94. end, {map=true})
  95. local function test_compress()
  96. -- This text should be compressible, to make sure the results are... normal
  97. local text = "The\000 icey canoe couldn't move very well on the\128 lake. The\000 ice was too stiff and the icey canoe's paddles simply wouldn't punch through."
  98. local methods = {
  99. "deflate",
  100. "zstd",
  101. -- "noodle", -- for warning alarm test
  102. }
  103. local zstd_magic = string.char(0x28, 0xB5, 0x2F, 0xFD)
  104. for _, method in ipairs(methods) do
  105. local compressed = core.compress(text, method)
  106. assert(core.decompress(compressed, method) == text, "input/output mismatch for compression method " .. method)
  107. local has_zstd_magic = compressed:sub(1, 4) == zstd_magic
  108. if method == "zstd" then
  109. assert(has_zstd_magic, "zstd magic number not in zstd method")
  110. else
  111. assert(not has_zstd_magic, "zstd magic number in method " .. method .. " (which is not zstd)")
  112. end
  113. end
  114. end
  115. unittests.register("test_compress", test_compress)
  116. local function test_urlencode()
  117. -- checks that API code handles null bytes
  118. assert(core.urlencode("foo\000bar!") == "foo%00bar%21")
  119. end
  120. unittests.register("test_urlencode", test_urlencode)
  121. local function test_game_info()
  122. local info = minetest.get_game_info()
  123. local game_conf = Settings(info.path .. "/game.conf")
  124. assert(info.id == "devtest")
  125. assert(info.title == game_conf:get("title"))
  126. end
  127. unittests.register("test_game_info", test_game_info)
  128. local function test_mapgen_edges(cb)
  129. -- Test that the map can extend to the expected edges and no further.
  130. local min_edge, max_edge = minetest.get_mapgen_edges()
  131. local min_finished = {}
  132. local max_finished = {}
  133. local function finish()
  134. if #min_finished ~= 1 then
  135. return cb("Expected 1 block to emerge around mapgen minimum edge")
  136. end
  137. if min_finished[1] ~= (min_edge / minetest.MAP_BLOCKSIZE):floor() then
  138. return cb("Expected block within minimum edge to emerge")
  139. end
  140. if #max_finished ~= 1 then
  141. return cb("Expected 1 block to emerge around mapgen maximum edge")
  142. end
  143. if max_finished[1] ~= (max_edge / minetest.MAP_BLOCKSIZE):floor() then
  144. return cb("Expected block within maximum edge to emerge")
  145. end
  146. return cb()
  147. end
  148. local emerges_left = 2
  149. local function emerge_block(blockpos, action, blocks_left, finished)
  150. if action ~= minetest.EMERGE_CANCELLED then
  151. table.insert(finished, blockpos)
  152. end
  153. if blocks_left == 0 then
  154. emerges_left = emerges_left - 1
  155. if emerges_left == 0 then
  156. return finish()
  157. end
  158. end
  159. end
  160. minetest.emerge_area(min_edge:subtract(1), min_edge, emerge_block, min_finished)
  161. minetest.emerge_area(max_edge, max_edge:add(1), emerge_block, max_finished)
  162. end
  163. unittests.register("test_mapgen_edges", test_mapgen_edges, {map=true, async=true})
  164. local finish_test_on_mapblocks_changed
  165. minetest.register_on_mapblocks_changed(function(modified_blocks, modified_block_count)
  166. if finish_test_on_mapblocks_changed then
  167. finish_test_on_mapblocks_changed(modified_blocks, modified_block_count)
  168. finish_test_on_mapblocks_changed = nil
  169. end
  170. end)
  171. local function test_on_mapblocks_changed(cb, player, pos)
  172. local bp1 = (pos / minetest.MAP_BLOCKSIZE):floor()
  173. local bp2 = bp1:add(1)
  174. for _, bp in ipairs({bp1, bp2}) do
  175. -- Make a modification in the block.
  176. local p = bp * minetest.MAP_BLOCKSIZE
  177. minetest.load_area(p)
  178. local meta = minetest.get_meta(p)
  179. meta:set_int("test_on_mapblocks_changed", meta:get_int("test_on_mapblocks_changed") + 1)
  180. end
  181. finish_test_on_mapblocks_changed = function(modified_blocks, modified_block_count)
  182. if modified_block_count < 2 then
  183. return cb("Expected at least two mapblocks to be recorded as modified")
  184. end
  185. if not modified_blocks[minetest.hash_node_position(bp1)] or
  186. not modified_blocks[minetest.hash_node_position(bp2)] then
  187. return cb("The expected mapblocks were not recorded as modified")
  188. end
  189. cb()
  190. end
  191. end
  192. unittests.register("test_on_mapblocks_changed", test_on_mapblocks_changed, {map=true, async=true})
  193. local function test_gennotify_api()
  194. local DECO_ID = 123
  195. local UD_ID = "unittests:dummy"
  196. -- the engine doesn't check if the id is actually valid, maybe it should
  197. core.set_gen_notify({decoration=true}, {DECO_ID})
  198. core.set_gen_notify({custom=true}, nil, {UD_ID})
  199. local flags, deco, custom = core.get_gen_notify()
  200. local function ff(flag)
  201. return (" " .. flags .. " "):match("[ ,]" .. flag .. "[ ,]") ~= nil
  202. end
  203. assert(ff("decoration"), "'decoration' flag missing")
  204. assert(ff("custom"), "'custom' flag missing")
  205. assert(table.indexof(deco, DECO_ID) > 0)
  206. assert(table.indexof(custom, UD_ID) > 0)
  207. core.set_gen_notify({decoration=false, custom=false})
  208. flags, deco, custom = core.get_gen_notify()
  209. assert(not ff("decoration") and not ff("custom"))
  210. assert(#deco == 0, "deco ids not empty")
  211. assert(#custom == 0, "custom ids not empty")
  212. end
  213. unittests.register("test_gennotify_api", test_gennotify_api)