1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
|
-- 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))
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})
|