1 /*
2 Minetest
3 Copyright (C) 2010-2014 kwolekr, Ryan Kwolek <kwolekr@minetest.net>
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License as published by
7 the Free Software Foundation; either version 2.1 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20 #include "test.h"
21
22 #include "mapgen/mg_schematic.h"
23 #include "gamedef.h"
24 #include "nodedef.h"
25
26 class TestSchematic : public TestBase {
27 public:
TestSchematic()28 TestSchematic() { TestManager::registerTestModule(this); }
getName()29 const char *getName() { return "TestSchematic"; }
30
31 void runTests(IGameDef *gamedef);
32
33 void testMtsSerializeDeserialize(const NodeDefManager *ndef);
34 void testLuaTableSerialize(const NodeDefManager *ndef);
35 void testFileSerializeDeserialize(const NodeDefManager *ndef);
36
37 static const content_t test_schem1_data[7 * 6 * 4];
38 static const content_t test_schem2_data[3 * 3 * 3];
39 static const u8 test_schem2_prob[3 * 3 * 3];
40 static const char *expected_lua_output;
41 };
42
43 static TestSchematic g_test_instance;
44
runTests(IGameDef * gamedef)45 void TestSchematic::runTests(IGameDef *gamedef)
46 {
47 NodeDefManager *ndef =
48 (NodeDefManager *)gamedef->getNodeDefManager();
49
50 ndef->setNodeRegistrationStatus(true);
51
52 TEST(testMtsSerializeDeserialize, ndef);
53 TEST(testLuaTableSerialize, ndef);
54 TEST(testFileSerializeDeserialize, ndef);
55
56 ndef->resetNodeResolveState();
57 }
58
59 ////////////////////////////////////////////////////////////////////////////////
60
testMtsSerializeDeserialize(const NodeDefManager * ndef)61 void TestSchematic::testMtsSerializeDeserialize(const NodeDefManager *ndef)
62 {
63 static const v3s16 size(7, 6, 4);
64 static const u32 volume = size.X * size.Y * size.Z;
65
66 std::stringstream ss(std::ios_base::binary |
67 std::ios_base::in | std::ios_base::out);
68
69 std::vector<std::string> names;
70 names.emplace_back("foo");
71 names.emplace_back("bar");
72 names.emplace_back("baz");
73 names.emplace_back("qux");
74
75 Schematic schem, schem2;
76
77 schem.flags = 0;
78 schem.size = size;
79 schem.schemdata = new MapNode[volume];
80 schem.slice_probs = new u8[size.Y];
81 for (size_t i = 0; i != volume; i++)
82 schem.schemdata[i] = MapNode(test_schem1_data[i], MTSCHEM_PROB_ALWAYS, 0);
83 for (s16 y = 0; y != size.Y; y++)
84 schem.slice_probs[y] = MTSCHEM_PROB_ALWAYS;
85
86 UASSERT(schem.serializeToMts(&ss, names));
87
88 ss.seekg(0);
89 names.clear();
90
91 UASSERT(schem2.deserializeFromMts(&ss, &names));
92
93 UASSERTEQ(size_t, names.size(), 4);
94 UASSERTEQ(std::string, names[0], "foo");
95 UASSERTEQ(std::string, names[1], "bar");
96 UASSERTEQ(std::string, names[2], "baz");
97 UASSERTEQ(std::string, names[3], "qux");
98
99 UASSERT(schem2.size == size);
100 for (size_t i = 0; i != volume; i++)
101 UASSERT(schem2.schemdata[i] == schem.schemdata[i]);
102 for (s16 y = 0; y != size.Y; y++)
103 UASSERTEQ(u8, schem2.slice_probs[y], schem.slice_probs[y]);
104 }
105
106
testLuaTableSerialize(const NodeDefManager * ndef)107 void TestSchematic::testLuaTableSerialize(const NodeDefManager *ndef)
108 {
109 static const v3s16 size(3, 3, 3);
110 static const u32 volume = size.X * size.Y * size.Z;
111
112 Schematic schem;
113
114 schem.flags = 0;
115 schem.size = size;
116 schem.schemdata = new MapNode[volume];
117 schem.slice_probs = new u8[size.Y];
118 for (size_t i = 0; i != volume; i++)
119 schem.schemdata[i] = MapNode(test_schem2_data[i], test_schem2_prob[i], 0);
120 for (s16 y = 0; y != size.Y; y++)
121 schem.slice_probs[y] = MTSCHEM_PROB_ALWAYS;
122
123 std::vector<std::string> names;
124 names.emplace_back("air");
125 names.emplace_back("default:lava_source");
126 names.emplace_back("default:glass");
127
128 std::ostringstream ss(std::ios_base::binary);
129
130 UASSERT(schem.serializeToLua(&ss, names, false, 0));
131 UASSERTEQ(std::string, ss.str(), expected_lua_output);
132 }
133
134
testFileSerializeDeserialize(const NodeDefManager * ndef)135 void TestSchematic::testFileSerializeDeserialize(const NodeDefManager *ndef)
136 {
137 static const v3s16 size(3, 3, 3);
138 static const u32 volume = size.X * size.Y * size.Z;
139 static const content_t content_map[] = {
140 CONTENT_AIR,
141 t_CONTENT_STONE,
142 t_CONTENT_LAVA,
143 };
144 static const content_t content_map2[] = {
145 CONTENT_AIR,
146 t_CONTENT_STONE,
147 t_CONTENT_WATER,
148 };
149 StringMap replace_names;
150 replace_names["default:lava"] = "default:water";
151
152 Schematic schem1, schem2;
153
154 //// Construct the schematic to save
155 schem1.flags = 0;
156 schem1.size = size;
157 schem1.schemdata = new MapNode[volume];
158 schem1.slice_probs = new u8[size.Y];
159 schem1.slice_probs[0] = 80;
160 schem1.slice_probs[1] = 160;
161 schem1.slice_probs[2] = 240;
162
163 for (size_t i = 0; i != volume; i++) {
164 content_t c = content_map[test_schem2_data[i]];
165 schem1.schemdata[i] = MapNode(c, test_schem2_prob[i], 0);
166 }
167
168 std::string temp_file = getTestTempFile();
169 UASSERT(schem1.saveSchematicToFile(temp_file, ndef));
170 UASSERT(schem2.loadSchematicFromFile(temp_file, ndef, &replace_names));
171
172 UASSERT(schem2.size == size);
173 UASSERT(schem2.slice_probs[0] == 80);
174 UASSERT(schem2.slice_probs[1] == 160);
175 UASSERT(schem2.slice_probs[2] == 240);
176
177 for (size_t i = 0; i != volume; i++) {
178 content_t c = content_map2[test_schem2_data[i]];
179 UASSERT(schem2.schemdata[i] == MapNode(c, test_schem2_prob[i], 0));
180 }
181 }
182
183
184 // Should form a cross-shaped-thing...?
185 const content_t TestSchematic::test_schem1_data[7 * 6 * 4] = {
186 3, 3, 1, 1, 1, 3, 3, // Y=0, Z=0
187 3, 0, 1, 2, 1, 0, 3, // Y=1, Z=0
188 3, 0, 1, 2, 1, 0, 3, // Y=2, Z=0
189 3, 1, 1, 2, 1, 1, 3, // Y=3, Z=0
190 3, 2, 2, 2, 2, 2, 3, // Y=4, Z=0
191 3, 1, 1, 2, 1, 1, 3, // Y=5, Z=0
192
193 0, 0, 1, 1, 1, 0, 0, // Y=0, Z=1
194 0, 0, 1, 2, 1, 0, 0, // Y=1, Z=1
195 0, 0, 1, 2, 1, 0, 0, // Y=2, Z=1
196 1, 1, 1, 2, 1, 1, 1, // Y=3, Z=1
197 1, 2, 2, 2, 2, 2, 1, // Y=4, Z=1
198 1, 1, 1, 2, 1, 1, 1, // Y=5, Z=1
199
200 0, 0, 1, 1, 1, 0, 0, // Y=0, Z=2
201 0, 0, 1, 2, 1, 0, 0, // Y=1, Z=2
202 0, 0, 1, 2, 1, 0, 0, // Y=2, Z=2
203 1, 1, 1, 2, 1, 1, 1, // Y=3, Z=2
204 1, 2, 2, 2, 2, 2, 1, // Y=4, Z=2
205 1, 1, 1, 2, 1, 1, 1, // Y=5, Z=2
206
207 3, 3, 1, 1, 1, 3, 3, // Y=0, Z=3
208 3, 0, 1, 2, 1, 0, 3, // Y=1, Z=3
209 3, 0, 1, 2, 1, 0, 3, // Y=2, Z=3
210 3, 1, 1, 2, 1, 1, 3, // Y=3, Z=3
211 3, 2, 2, 2, 2, 2, 3, // Y=4, Z=3
212 3, 1, 1, 2, 1, 1, 3, // Y=5, Z=3
213 };
214
215 const content_t TestSchematic::test_schem2_data[3 * 3 * 3] = {
216 0, 0, 0,
217 0, 2, 0,
218 0, 0, 0,
219
220 0, 2, 0,
221 2, 1, 2,
222 0, 2, 0,
223
224 0, 0, 0,
225 0, 2, 0,
226 0, 0, 0,
227 };
228
229 const u8 TestSchematic::test_schem2_prob[3 * 3 * 3] = {
230 0x00, 0x00, 0x00,
231 0x00, 0xFF, 0x00,
232 0x00, 0x00, 0x00,
233
234 0x00, 0xFF, 0x00,
235 0xFF, 0xFF, 0xFF,
236 0x00, 0xFF, 0x00,
237
238 0x00, 0x00, 0x00,
239 0x00, 0xFF, 0x00,
240 0x00, 0x00, 0x00,
241 };
242
243 const char *TestSchematic::expected_lua_output =
244 "schematic = {\n"
245 "\tsize = {x=3, y=3, z=3},\n"
246 "\tyslice_prob = {\n"
247 "\t\t{ypos=0, prob=254},\n"
248 "\t\t{ypos=1, prob=254},\n"
249 "\t\t{ypos=2, prob=254},\n"
250 "\t},\n"
251 "\tdata = {\n"
252 "\t\t{name=\"air\", prob=0, param2=0},\n"
253 "\t\t{name=\"air\", prob=0, param2=0},\n"
254 "\t\t{name=\"air\", prob=0, param2=0},\n"
255 "\t\t{name=\"air\", prob=0, param2=0},\n"
256 "\t\t{name=\"default:glass\", prob=254, param2=0, force_place=true},\n"
257 "\t\t{name=\"air\", prob=0, param2=0},\n"
258 "\t\t{name=\"air\", prob=0, param2=0},\n"
259 "\t\t{name=\"air\", prob=0, param2=0},\n"
260 "\t\t{name=\"air\", prob=0, param2=0},\n"
261 "\t\t{name=\"air\", prob=0, param2=0},\n"
262 "\t\t{name=\"default:glass\", prob=254, param2=0, force_place=true},\n"
263 "\t\t{name=\"air\", prob=0, param2=0},\n"
264 "\t\t{name=\"default:glass\", prob=254, param2=0, force_place=true},\n"
265 "\t\t{name=\"default:lava_source\", prob=254, param2=0, force_place=true},\n"
266 "\t\t{name=\"default:glass\", prob=254, param2=0, force_place=true},\n"
267 "\t\t{name=\"air\", prob=0, param2=0},\n"
268 "\t\t{name=\"default:glass\", prob=254, param2=0, force_place=true},\n"
269 "\t\t{name=\"air\", prob=0, param2=0},\n"
270 "\t\t{name=\"air\", prob=0, param2=0},\n"
271 "\t\t{name=\"air\", prob=0, param2=0},\n"
272 "\t\t{name=\"air\", prob=0, param2=0},\n"
273 "\t\t{name=\"air\", prob=0, param2=0},\n"
274 "\t\t{name=\"default:glass\", prob=254, param2=0, force_place=true},\n"
275 "\t\t{name=\"air\", prob=0, param2=0},\n"
276 "\t\t{name=\"air\", prob=0, param2=0},\n"
277 "\t\t{name=\"air\", prob=0, param2=0},\n"
278 "\t\t{name=\"air\", prob=0, param2=0},\n"
279 "\t},\n"
280 "}\n";
281