2024-02-13 22:47:30 +01:00
core.register_mapgen_script ( core.get_modpath ( core.get_current_modname ( ) ) ..
DIR_DELIM .. " inside_mapgen_env.lua " )
2024-01-16 23:20:52 +01:00
local function test_pseudo_random ( )
2024-01-10 20:00:14 +01:00
-- We have comprehensive unit tests in C++, this is just to make sure the API code isn't messing up
2024-01-16 23:20:52 +01:00
local gen1 = PseudoRandom ( 13 )
assert ( gen1 : next ( ) == 22290 )
assert ( gen1 : next ( ) == 13854 )
2024-01-10 20:00:14 +01:00
2024-01-16 23:20:52 +01:00
local gen2 = PseudoRandom ( gen1 : get_state ( ) )
for n = 0 , 16 do
assert ( gen1 : next ( ) == gen2 : next ( ) )
end
local pr3 = PseudoRandom ( - 101 )
assert ( pr3 : next ( 0 , 100 ) == 35 )
2024-01-10 20:08:00 +01:00
-- unusual case that is normally disallowed:
2024-01-16 23:20:52 +01:00
assert ( pr3 : next ( 10000 , 42767 ) == 12485 )
end
unittests.register ( " test_pseudo_random " , test_pseudo_random )
local function test_pcg_random ( )
-- We have comprehensive unit tests in C++, this is just to make sure the API code isn't messing up
local gen1 = PcgRandom ( 55 )
for n = 0 , 16 do
gen1 : next ( )
end
local gen2 = PcgRandom ( 26 )
gen2 : set_state ( gen1 : get_state ( ) )
for n = 16 , 32 do
assert ( gen1 : next ( ) == gen2 : next ( ) )
end
2021-12-18 20:36:43 +01:00
end
2024-01-16 23:20:52 +01:00
unittests.register ( " test_pcg_random " , test_pcg_random )
2021-12-18 20:36:43 +01:00
local function test_dynamic_media ( cb , player )
if core.get_player_information ( player : get_player_name ( ) ) . protocol_version < 40 then
core.log ( " warning " , " test_dynamic_media: Client too old, skipping test. " )
return cb ( )
end
-- Check that the client acknowledges media transfers
local path = core.get_worldpath ( ) .. " /test_media.obj "
local f = io.open ( path , " w " )
f : write ( " # contents don't matter \n " )
f : close ( )
local call_ok = false
local ok = core.dynamic_add_media ( {
filepath = path ,
to_player = player : get_player_name ( ) ,
} , function ( name )
if not call_ok then
2022-07-04 01:06:42 +02:00
return cb ( " impossible condition " )
2021-12-18 20:36:43 +01:00
end
cb ( )
end )
if not ok then
return cb ( " dynamic_add_media() returned error " )
end
call_ok = true
-- if the callback isn't called this test will just hang :shrug:
end
unittests.register ( " test_dynamic_media " , test_dynamic_media , { async = true , player = true } )
2022-03-29 18:07:00 +02:00
local function test_v3f_metatable ( player )
assert ( vector.check ( player : get_pos ( ) ) )
end
unittests.register ( " test_v3f_metatable " , test_v3f_metatable , { player = true } )
local function test_v3s16_metatable ( player , pos )
2024-10-28 15:57:54 +01:00
local node = core.get_node ( pos )
local found_pos = core.find_node_near ( pos , 0 , node.name , true )
2022-03-29 18:07:00 +02:00
assert ( vector.check ( found_pos ) )
end
unittests.register ( " test_v3s16_metatable " , test_v3s16_metatable , { map = true } )
2022-05-26 15:45:34 +02:00
local function test_clear_meta ( _ , pos )
local ref = core.get_meta ( pos )
for way = 1 , 3 do
ref : set_string ( " foo " , " bar " )
assert ( ref : contains ( " foo " ) )
if way == 1 then
ref : from_table ( { } )
elseif way == 2 then
ref : from_table ( nil )
else
ref : set_string ( " foo " , " " )
end
assert ( # core.find_nodes_with_meta ( pos , pos ) == 0 , " clearing failed " .. way )
end
end
unittests.register ( " test_clear_meta " , test_clear_meta , { map = true } )
2022-07-14 20:51:42 +02:00
2024-02-24 00:53:22 +01:00
local on_punch_called , on_place_called
core.register_on_placenode ( function ( )
on_place_called = true
end )
core.register_on_punchnode ( function ( )
2022-07-14 20:51:42 +02:00
on_punch_called = true
end )
2024-02-24 00:53:22 +01:00
local function test_node_callbacks ( _ , pos )
on_place_called = false
2022-07-14 20:51:42 +02:00
on_punch_called = false
2024-02-24 00:53:22 +01:00
core.place_node ( pos , { name = " basenodes:dirt " } )
assert ( on_place_called , " on_place not called " )
core.punch_node ( pos )
assert ( on_punch_called , " on_punch not called " )
core.remove_node ( pos )
end
unittests.register ( " test_node_callbacks " , test_node_callbacks , { map = true } )
2022-09-28 15:06:14 +02:00
2024-02-25 18:12:23 +01:00
local function test_hashing ( )
local input = " hello \000 world "
assert ( core.sha1 ( input ) == " f85b420f1e43ebf88649dfcab302b898d889606c " )
assert ( core.sha256 ( input ) == " b206899bc103669c8e7b36de29d73f95b46795b508aa87d612b2ce84bfb29df2 " )
end
unittests.register ( " test_hashing " , test_hashing )
2022-09-28 15:06:14 +02:00
local function test_compress ( )
-- This text should be compressible, to make sure the results are... normal
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. "
local methods = {
" deflate " ,
" zstd " ,
-- "noodle", -- for warning alarm test
}
local zstd_magic = string.char ( 0x28 , 0xB5 , 0x2F , 0xFD )
for _ , method in ipairs ( methods ) do
local compressed = core.compress ( text , method )
assert ( core.decompress ( compressed , method ) == text , " input/output mismatch for compression method " .. method )
local has_zstd_magic = compressed : sub ( 1 , 4 ) == zstd_magic
if method == " zstd " then
assert ( has_zstd_magic , " zstd magic number not in zstd method " )
else
assert ( not has_zstd_magic , " zstd magic number in method " .. method .. " (which is not zstd) " )
end
end
end
unittests.register ( " test_compress " , test_compress )
2024-02-17 15:35:33 +01:00
local function test_urlencode ( )
-- checks that API code handles null bytes
assert ( core.urlencode ( " foo \000 bar! " ) == " foo%00bar%21 " )
end
unittests.register ( " test_urlencode " , test_urlencode )
2024-10-12 22:26:17 +02:00
local function test_parse_json ( )
local raw = " { \" how \\ u0000weird \" : \n \" yes \\ u0000really \" , \" n \" :-1234567891011, \" z \" :null} "
2024-10-12 23:24:47 +02:00
do
local data = core.parse_json ( raw )
assert ( data [ " how \000 weird " ] == " yes \000 really " )
assert ( data.n == - 1234567891011 )
assert ( data.z == nil )
end
do
local null = { }
local data = core.parse_json ( raw , null )
assert ( data.z == null )
end
do
local data , err = core.parse_json ( ' "ceci n \' est pas un json ' , nil , true )
assert ( data == nil )
assert ( type ( err ) == " string " )
end
2024-10-12 22:26:17 +02:00
end
unittests.register ( " test_parse_json " , test_parse_json )
2024-10-14 15:46:25 +02:00
local function test_write_json ( )
-- deeply nested structures should be preserved
local leaf = 42
local data = leaf
for i = 1 , 1000 do
data = { data }
end
2024-10-28 15:57:54 +01:00
local roundtripped = core.parse_json ( core.write_json ( data ) )
2024-10-14 15:46:25 +02:00
for i = 1 , 1000 do
roundtripped = roundtripped [ 1 ]
end
assert ( roundtripped == 42 )
end
unittests.register ( " test_write_json " , test_write_json )
2022-11-28 13:21:43 +01:00
local function test_game_info ( )
2024-10-28 15:57:54 +01:00
local info = core.get_game_info ( )
2022-11-28 13:21:43 +01:00
local game_conf = Settings ( info.path .. " /game.conf " )
assert ( info.id == " devtest " )
assert ( info.title == game_conf : get ( " title " ) )
end
unittests.register ( " test_game_info " , test_game_info )
2022-12-03 16:40:46 +01:00
local function test_mapgen_edges ( cb )
-- Test that the map can extend to the expected edges and no further.
2024-10-28 15:57:54 +01:00
local min_edge , max_edge = core.get_mapgen_edges ( )
2022-12-03 16:40:46 +01:00
local min_finished = { }
local max_finished = { }
local function finish ( )
if # min_finished ~= 1 then
return cb ( " Expected 1 block to emerge around mapgen minimum edge " )
end
2024-10-28 15:57:54 +01:00
if min_finished [ 1 ] ~= ( min_edge / core.MAP_BLOCKSIZE ) : floor ( ) then
2022-12-03 16:40:46 +01:00
return cb ( " Expected block within minimum edge to emerge " )
end
if # max_finished ~= 1 then
return cb ( " Expected 1 block to emerge around mapgen maximum edge " )
end
2024-10-28 15:57:54 +01:00
if max_finished [ 1 ] ~= ( max_edge / core.MAP_BLOCKSIZE ) : floor ( ) then
2022-12-03 16:40:46 +01:00
return cb ( " Expected block within maximum edge to emerge " )
end
return cb ( )
end
local emerges_left = 2
local function emerge_block ( blockpos , action , blocks_left , finished )
2024-10-28 15:57:54 +01:00
if action ~= core.EMERGE_CANCELLED then
2022-12-03 16:40:46 +01:00
table.insert ( finished , blockpos )
end
if blocks_left == 0 then
emerges_left = emerges_left - 1
if emerges_left == 0 then
return finish ( )
end
end
end
2024-10-28 15:57:54 +01:00
core.emerge_area ( min_edge : subtract ( 1 ) , min_edge , emerge_block , min_finished )
core.emerge_area ( max_edge , max_edge : add ( 1 ) , emerge_block , max_finished )
2022-12-03 16:40:46 +01:00
end
unittests.register ( " test_mapgen_edges " , test_mapgen_edges , { map = true , async = true } )
2022-09-04 04:05:07 +02:00
local finish_test_on_mapblocks_changed
2024-10-28 15:57:54 +01:00
core.register_on_mapblocks_changed ( function ( modified_blocks , modified_block_count )
2022-09-04 04:05:07 +02:00
if finish_test_on_mapblocks_changed then
finish_test_on_mapblocks_changed ( modified_blocks , modified_block_count )
finish_test_on_mapblocks_changed = nil
end
end )
local function test_on_mapblocks_changed ( cb , player , pos )
2024-10-28 15:57:54 +01:00
local bp1 = ( pos / core.MAP_BLOCKSIZE ) : floor ( )
2022-09-04 04:05:07 +02:00
local bp2 = bp1 : add ( 1 )
for _ , bp in ipairs ( { bp1 , bp2 } ) do
-- Make a modification in the block.
2024-10-28 15:57:54 +01:00
local p = bp * core.MAP_BLOCKSIZE
core.load_area ( p )
local meta = core.get_meta ( p )
2022-09-04 04:05:07 +02:00
meta : set_int ( " test_on_mapblocks_changed " , meta : get_int ( " test_on_mapblocks_changed " ) + 1 )
end
finish_test_on_mapblocks_changed = function ( modified_blocks , modified_block_count )
if modified_block_count < 2 then
return cb ( " Expected at least two mapblocks to be recorded as modified " )
end
2024-10-28 15:57:54 +01:00
if not modified_blocks [ core.hash_node_position ( bp1 ) ] or
not modified_blocks [ core.hash_node_position ( bp2 ) ] then
2022-09-04 04:05:07 +02:00
return cb ( " The expected mapblocks were not recorded as modified " )
end
cb ( )
end
end
unittests.register ( " test_on_mapblocks_changed " , test_on_mapblocks_changed , { map = true , async = true } )
2024-02-13 22:47:30 +01:00
local function test_gennotify_api ( )
local DECO_ID = 123
local UD_ID = " unittests:dummy "
-- the engine doesn't check if the id is actually valid, maybe it should
core.set_gen_notify ( { decoration = true } , { DECO_ID } )
core.set_gen_notify ( { custom = true } , nil , { UD_ID } )
local flags , deco , custom = core.get_gen_notify ( )
local function ff ( flag )
return ( " " .. flags .. " " ) : match ( " [ ,] " .. flag .. " [ ,] " ) ~= nil
end
assert ( ff ( " decoration " ) , " 'decoration' flag missing " )
assert ( ff ( " custom " ) , " 'custom' flag missing " )
assert ( table.indexof ( deco , DECO_ID ) > 0 )
assert ( table.indexof ( custom , UD_ID ) > 0 )
core.set_gen_notify ( { decoration = false , custom = false } )
flags , deco , custom = core.get_gen_notify ( )
assert ( not ff ( " decoration " ) and not ff ( " custom " ) )
assert ( # deco == 0 , " deco ids not empty " )
assert ( # custom == 0 , " custom ids not empty " )
end
unittests.register ( " test_gennotify_api " , test_gennotify_api )
2024-05-14 22:24:05 +02:00
-- <=> inside_mapgen_env.lua
local function test_mapgen_env ( cb )
-- emerge threads start delayed so this can take a second
local res = core.ipc_get ( " unittests:mg " )
if res == nil then
return core.after ( 0 , test_mapgen_env , cb )
end
-- handle error status
if res [ 1 ] then
cb ( )
else
cb ( res [ 2 ] )
end
end
unittests.register ( " test_mapgen_env " , test_mapgen_env , { async = true } )
local function test_ipc_vector_preserve ( cb )
-- the IPC also uses register_portable_metatable
core.ipc_set ( " unittests:v " , vector.new ( 4 , 0 , 4 ) )
local v = core.ipc_get ( " unittests:v " )
assert ( type ( v ) == " table " )
assert ( vector.check ( v ) )
end
unittests.register ( " test_ipc_vector_preserve " , test_ipc_vector_preserve )
2024-05-28 23:04:08 +02:00
local function test_ipc_poll ( cb )
core.ipc_set ( " unittests:flag " , nil )
assert ( core.ipc_poll ( " unittests:flag " , 1 ) == false )
-- Note that unlike the async result callback - which has to wait for the
-- next server step - the IPC is instant
local t0 = core.get_us_time ( )
core.handle_async ( function ( )
core.ipc_set ( " unittests:flag " , true )
end , function ( ) end )
assert ( core.ipc_poll ( " unittests:flag " , 1000 ) == true , " Wait failed (or slow machine?) " )
print ( " delta: " .. ( core.get_us_time ( ) - t0 ) .. " us " )
end
unittests.register ( " test_ipc_poll " , test_ipc_poll )