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