ebefb8e32fbc3f93fc133182d1560da23dfc0e58
[oweals/minetest.git] / src / test.cpp
1 /*
2 Minetest-c55
3 Copyright (C) 2010 celeron55, Perttu Ahola <celeron55@gmail.com>
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 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 General Public License for more details.
14
15 You should have received a copy of the GNU 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 #include "common_irrlicht.h"
22 #include "debug.h"
23 #include "map.h"
24 #include "player.h"
25 #include "main.h"
26 #include "heightmap.h"
27 #include "socket.h"
28 #include "connection.h"
29 #include "utility.h"
30 #include "serialization.h"
31 #include "voxel.h"
32 #include <sstream>
33
34 #ifdef _WIN32
35         #include <windows.h>
36         #define sleep_ms(x) Sleep(x)
37 #else
38         #include <unistd.h>
39         #define sleep_ms(x) usleep(x*1000)
40 #endif
41
42 /*
43         Asserts that the exception occurs
44 */
45 #define EXCEPTION_CHECK(EType, code)\
46 {\
47         bool exception_thrown = false;\
48         try{ code; }\
49         catch(EType &e) { exception_thrown = true; }\
50         assert(exception_thrown);\
51 }
52
53 struct TestUtilities
54 {
55         void Run()
56         {
57                 /*dstream<<"wrapDegrees(100.0) = "<<wrapDegrees(100.0)<<std::endl;
58                 dstream<<"wrapDegrees(720.5) = "<<wrapDegrees(720.5)<<std::endl;
59                 dstream<<"wrapDegrees(-0.5) = "<<wrapDegrees(-0.5)<<std::endl;*/
60                 assert(fabs(wrapDegrees(100.0) - 100.0) < 0.001);
61                 assert(fabs(wrapDegrees(720.5) - 0.5) < 0.001);
62                 assert(fabs(wrapDegrees(-0.5) - (-0.5)) < 0.001);
63                 assert(fabs(wrapDegrees(-365.5) - (-5.5)) < 0.001);
64                 assert(lowercase("Foo bAR") == "foo bar");
65                 assert(is_yes("YeS") == true);
66                 assert(is_yes("") == false);
67                 assert(is_yes("FAlse") == false);
68         }
69 };
70                 
71 struct TestCompress
72 {
73         void Run()
74         {
75                 SharedBuffer<u8> fromdata(4);
76                 fromdata[0]=1;
77                 fromdata[1]=5;
78                 fromdata[2]=5;
79                 fromdata[3]=1;
80                 
81                 std::ostringstream os(std::ios_base::binary);
82                 compress(fromdata, os, 0);
83
84                 std::string str_out = os.str();
85                 
86                 dstream<<"str_out.size()="<<str_out.size()<<std::endl;
87                 dstream<<"TestCompress: 1,5,5,1 -> ";
88                 for(u32 i=0; i<str_out.size(); i++)
89                 {
90                         dstream<<(u32)str_out[i]<<",";
91                 }
92                 dstream<<std::endl;
93
94                 assert(str_out.size() == 10);
95
96                 assert(str_out[0] == 0);
97                 assert(str_out[1] == 0);
98                 assert(str_out[2] == 0);
99                 assert(str_out[3] == 4);
100                 assert(str_out[4] == 0);
101                 assert(str_out[5] == 1);
102                 assert(str_out[6] == 1);
103                 assert(str_out[7] == 5);
104                 assert(str_out[8] == 0);
105                 assert(str_out[9] == 1);
106
107                 std::istringstream is(str_out, std::ios_base::binary);
108                 std::ostringstream os2(std::ios_base::binary);
109
110                 decompress(is, os2, 0);
111                 std::string str_out2 = os2.str();
112
113                 dstream<<"decompress: ";
114                 for(u32 i=0; i<str_out2.size(); i++)
115                 {
116                         dstream<<(u32)str_out2[i]<<",";
117                 }
118                 dstream<<std::endl;
119
120                 assert(str_out2.size() == fromdata.getSize());
121
122                 for(u32 i=0; i<str_out2.size(); i++)
123                 {
124                         assert(str_out2[i] == fromdata[i]);
125                 }
126         }
127 };
128
129 struct TestMapNode
130 {
131         void Run()
132         {
133                 MapNode n;
134
135                 // Default values
136                 assert(n.d == MATERIAL_AIR);
137                 assert(n.getLight() == 0);
138                 
139                 // Transparency
140                 n.d = MATERIAL_AIR;
141                 assert(n.light_propagates() == true);
142                 n.d = 0;
143                 assert(n.light_propagates() == false);
144         }
145 };
146
147 struct TestVoxelManipulator
148 {
149         void Run()
150         {
151                 /*
152                         VoxelArea
153                 */
154
155                 VoxelArea a(v3s16(-1,-1,-1), v3s16(1,1,1));
156                 assert(a.index(0,0,0) == 1*3*3 + 1*3 + 1);
157                 assert(a.index(-1,-1,-1) == 0);
158                 
159                 VoxelArea c(v3s16(-2,-2,-2), v3s16(2,2,2));
160                 // An area that is 1 bigger in x+ and z-
161                 VoxelArea d(v3s16(-2,-2,-3), v3s16(3,2,2));
162                 
163                 core::list<VoxelArea> aa;
164                 d.diff(c, aa);
165                 
166                 // Correct results
167                 core::array<VoxelArea> results;
168                 results.push_back(VoxelArea(v3s16(-2,-2,-3),v3s16(3,2,-3)));
169                 results.push_back(VoxelArea(v3s16(3,-2,-2),v3s16(3,2,2)));
170
171                 assert(aa.size() == results.size());
172                 
173                 dstream<<"Result of diff:"<<std::endl;
174                 for(core::list<VoxelArea>::Iterator
175                                 i = aa.begin(); i != aa.end(); i++)
176                 {
177                         i->print(dstream);
178                         dstream<<std::endl;
179                         
180                         s32 j = results.linear_search(*i);
181                         assert(j != -1);
182                         results.erase(j, 1);
183                 }
184
185
186                 /*
187                         VoxelManipulator
188                 */
189                 
190                 VoxelManipulator v;
191
192                 v.print(dstream);
193
194                 dstream<<"*** Setting (-1,0,-1)=2 ***"<<std::endl;
195                 
196                 v.setNodeNoRef(v3s16(-1,0,-1), MapNode(2));
197
198                 v.print(dstream);
199
200                 assert(v.getNode(v3s16(-1,0,-1)).d == 2);
201
202                 dstream<<"*** Reading from inexistent (0,0,-1) ***"<<std::endl;
203
204                 EXCEPTION_CHECK(InvalidPositionException, v.getNode(v3s16(0,0,-1)));
205
206                 v.print(dstream);
207
208                 dstream<<"*** Adding area ***"<<std::endl;
209
210                 v.addArea(a);
211                 
212                 v.print(dstream);
213
214                 assert(v.getNode(v3s16(-1,0,-1)).d == 2);
215                 EXCEPTION_CHECK(InvalidPositionException, v.getNode(v3s16(0,1,1)));
216
217                 /*
218                         Water stuff
219                 */
220
221                 v.clear();
222
223                 const char *content =
224                         "#...######  "
225                         "#...##..##  "
226                         "#........ .."
227                         "############"
228
229                         "#...######  "
230                         "#...##..##  "
231                         "#........#  "
232                         "############"
233                 ;
234
235                 v3s16 size(12, 4, 2);
236                 VoxelArea area(v3s16(0,0,0), size-v3s16(1,1,1));
237                 
238                 const char *p = content;
239                 for(s16 z=0; z<size.Z; z++)
240                 for(s16 y=size.Y-1; y>=0; y--)
241                 for(s16 x=0; x<size.X; x++)
242                 {
243                         MapNode n;
244                         //n.pressure = size.Y - y;
245                         if(*p == '#')
246                                 n.d = MATERIAL_STONE;
247                         else if(*p == '.')
248                                 n.d = MATERIAL_WATER;
249                         else if(*p == ' ')
250                                 n.d = MATERIAL_AIR;
251                         else
252                                 assert(0);
253                         v.setNode(v3s16(x,y,z), n);
254                         p++;
255                 }
256
257                 v.print(dstream, VOXELPRINT_WATERPRESSURE);
258                 
259                 core::map<v3s16, u8> active_nodes;
260                 v.updateAreaWaterPressure(area, active_nodes);
261
262                 v.print(dstream, VOXELPRINT_WATERPRESSURE);
263                 
264                 s16 highest_y = -32768;
265                 assert(v.getWaterPressure(v3s16(7, 1, 1), highest_y, 0) == -1);
266                 assert(highest_y == 3);
267                 
268                 active_nodes.clear();
269                 active_nodes[v3s16(9,1,0)] = 1;
270                 //v.flowWater(active_nodes, 0, false);
271                 v.flowWater(active_nodes, 0, true);
272                 
273                 dstream<<"Final result of flowWater:"<<std::endl;
274                 v.print(dstream, VOXELPRINT_WATERPRESSURE);
275                 
276                 //assert(0);
277         }
278 };
279
280 struct TestMapBlock
281 {
282         class TC : public NodeContainer
283         {
284         public:
285
286                 MapNode node;
287                 bool position_valid;
288                 core::list<v3s16> validity_exceptions;
289
290                 TC()
291                 {
292                         position_valid = true;
293                 }
294
295                 virtual bool isValidPosition(v3s16 p)
296                 {
297                         //return position_valid ^ (p==position_valid_exception);
298                         bool exception = false;
299                         for(core::list<v3s16>::Iterator i=validity_exceptions.begin();
300                                         i != validity_exceptions.end(); i++)
301                         {
302                                 if(p == *i)
303                                 {
304                                         exception = true;
305                                         break;
306                                 }
307                         }
308                         return exception ? !position_valid : position_valid;
309                 }
310
311                 virtual MapNode getNode(v3s16 p)
312                 {
313                         if(isValidPosition(p) == false)
314                                 throw InvalidPositionException();
315                         return node;
316                 }
317
318                 virtual void setNode(v3s16 p, MapNode & n)
319                 {
320                         if(isValidPosition(p) == false)
321                                 throw InvalidPositionException();
322                 };
323
324                 virtual u16 nodeContainerId() const
325                 {
326                         return 666;
327                 }
328         };
329
330         void Run()
331         {
332                 TC parent;
333                 
334                 MapBlock b(&parent, v3s16(1,1,1));
335                 v3s16 relpos(MAP_BLOCKSIZE, MAP_BLOCKSIZE, MAP_BLOCKSIZE);
336
337                 assert(b.getPosRelative() == relpos);
338
339                 assert(b.getBox().MinEdge.X == MAP_BLOCKSIZE);
340                 assert(b.getBox().MaxEdge.X == MAP_BLOCKSIZE*2-1);
341                 assert(b.getBox().MinEdge.Y == MAP_BLOCKSIZE);
342                 assert(b.getBox().MaxEdge.Y == MAP_BLOCKSIZE*2-1);
343                 assert(b.getBox().MinEdge.Z == MAP_BLOCKSIZE);
344                 assert(b.getBox().MaxEdge.Z == MAP_BLOCKSIZE*2-1);
345                 
346                 assert(b.isValidPosition(v3s16(0,0,0)) == true);
347                 assert(b.isValidPosition(v3s16(-1,0,0)) == false);
348                 assert(b.isValidPosition(v3s16(-1,-142,-2341)) == false);
349                 assert(b.isValidPosition(v3s16(-124,142,2341)) == false);
350                 assert(b.isValidPosition(v3s16(MAP_BLOCKSIZE-1,MAP_BLOCKSIZE-1,MAP_BLOCKSIZE-1)) == true);
351                 assert(b.isValidPosition(v3s16(MAP_BLOCKSIZE-1,MAP_BLOCKSIZE,MAP_BLOCKSIZE-1)) == false);
352
353                 /*
354                         TODO: this method should probably be removed
355                         if the block size isn't going to be set variable
356                 */
357                 /*assert(b.getSizeNodes() == v3s16(MAP_BLOCKSIZE,
358                                 MAP_BLOCKSIZE, MAP_BLOCKSIZE));*/
359                 
360                 // Changed flag should be initially set
361                 assert(b.getChangedFlag() == true);
362                 b.resetChangedFlag();
363                 assert(b.getChangedFlag() == false);
364
365                 // All nodes should have been set to
366                 // .d=MATERIAL_AIR and .getLight() = 0
367                 for(u16 z=0; z<MAP_BLOCKSIZE; z++)
368                         for(u16 y=0; y<MAP_BLOCKSIZE; y++)
369                                 for(u16 x=0; x<MAP_BLOCKSIZE; x++){
370                                         assert(b.getNode(v3s16(x,y,z)).d == MATERIAL_AIR);
371                                         assert(b.getNode(v3s16(x,y,z)).getLight() == 0);
372                                 }
373                 
374                 /*
375                         Parent fetch functions
376                 */
377                 parent.position_valid = false;
378                 parent.node.d = 5;
379
380                 MapNode n;
381                 
382                 // Positions in the block should still be valid
383                 assert(b.isValidPositionParent(v3s16(0,0,0)) == true);
384                 assert(b.isValidPositionParent(v3s16(MAP_BLOCKSIZE-1,MAP_BLOCKSIZE-1,MAP_BLOCKSIZE-1)) == true);
385                 n = b.getNodeParent(v3s16(0,MAP_BLOCKSIZE-1,0));
386                 assert(n.d == MATERIAL_AIR);
387
388                 // ...but outside the block they should be invalid
389                 assert(b.isValidPositionParent(v3s16(-121,2341,0)) == false);
390                 assert(b.isValidPositionParent(v3s16(-1,0,0)) == false);
391                 assert(b.isValidPositionParent(v3s16(MAP_BLOCKSIZE-1,MAP_BLOCKSIZE-1,MAP_BLOCKSIZE)) == false);
392                 
393                 {
394                         bool exception_thrown = false;
395                         try{
396                                 // This should throw an exception
397                                 MapNode n = b.getNodeParent(v3s16(0,0,-1));
398                         }
399                         catch(InvalidPositionException &e)
400                         {
401                                 exception_thrown = true;
402                         }
403                         assert(exception_thrown);
404                 }
405
406                 parent.position_valid = true;
407                 // Now the positions outside should be valid
408                 assert(b.isValidPositionParent(v3s16(-121,2341,0)) == true);
409                 assert(b.isValidPositionParent(v3s16(-1,0,0)) == true);
410                 assert(b.isValidPositionParent(v3s16(MAP_BLOCKSIZE-1,MAP_BLOCKSIZE-1,MAP_BLOCKSIZE)) == true);
411                 n = b.getNodeParent(v3s16(0,0,MAP_BLOCKSIZE));
412                 assert(n.d == 5);
413
414                 /*
415                         Set a node
416                 */
417                 v3s16 p(1,2,0);
418                 n.d = 4;
419                 b.setNode(p, n);
420                 assert(b.getNode(p).d == 4);
421                 assert(b.getNodeMaterial(p) == 4);
422                 assert(b.getNodeMaterial(v3s16(-1,-1,0)) == 5);
423                 
424                 /*
425                         propagateSunlight()
426                 */
427                 // Set lighting of all nodes to 0
428                 for(u16 z=0; z<MAP_BLOCKSIZE; z++){
429                         for(u16 y=0; y<MAP_BLOCKSIZE; y++){
430                                 for(u16 x=0; x<MAP_BLOCKSIZE; x++){
431                                         MapNode n = b.getNode(v3s16(x,y,z));
432                                         n.setLight(0);
433                                         b.setNode(v3s16(x,y,z), n);
434                                 }
435                         }
436                 }
437                 {
438                         /*
439                                 Check how the block handles being a lonely sky block
440                         */
441                         parent.position_valid = true;
442                         b.setIsUnderground(false);
443                         parent.node.d = MATERIAL_AIR;
444                         parent.node.setLight(LIGHT_SUN);
445                         core::map<v3s16, bool> light_sources;
446                         // The bottom block is invalid, because we have a shadowing node
447                         assert(b.propagateSunlight(light_sources) == false);
448                         assert(b.getNode(v3s16(1,4,0)).getLight() == LIGHT_SUN);
449                         assert(b.getNode(v3s16(1,3,0)).getLight() == LIGHT_SUN);
450                         assert(b.getNode(v3s16(1,2,0)).getLight() == 0);
451                         assert(b.getNode(v3s16(1,1,0)).getLight() == 0);
452                         assert(b.getNode(v3s16(1,0,0)).getLight() == 0);
453                         assert(b.getNode(v3s16(1,2,3)).getLight() == LIGHT_SUN);
454                         assert(b.getFaceLight(p, v3s16(0,1,0)) == LIGHT_SUN);
455                         assert(b.getFaceLight(p, v3s16(0,-1,0)) == 0);
456                         // According to MapBlock::getFaceLight,
457                         // The face on the z+ side should have double-diminished light
458                         assert(b.getFaceLight(p, v3s16(0,0,1)) == diminish_light(diminish_light(LIGHT_MAX)));
459                 }
460                 /*
461                         Check how the block handles being in between blocks with some non-sunlight
462                         while being underground
463                 */
464                 {
465                         // Make neighbours to exist and set some non-sunlight to them
466                         parent.position_valid = true;
467                         b.setIsUnderground(true);
468                         parent.node.setLight(LIGHT_MAX/2);
469                         core::map<v3s16, bool> light_sources;
470                         // The block below should be valid because there shouldn't be
471                         // sunlight in there either
472                         assert(b.propagateSunlight(light_sources) == true);
473                         // Should not touch nodes that are not affected (that is, all of them)
474                         //assert(b.getNode(v3s16(1,2,3)).getLight() == LIGHT_SUN);
475                         // Should set light of non-sunlighted blocks to 0.
476                         assert(b.getNode(v3s16(1,2,3)).getLight() == 0);
477                 }
478                 /*
479                         Set up a situation where:
480                         - There is only air in this block
481                         - There is a valid non-sunlighted block at the bottom, and
482                         - Invalid blocks elsewhere.
483                         - the block is not underground.
484
485                         This should result in bottom block invalidity
486                 */
487                 {
488                         b.setIsUnderground(false);
489                         // Clear block
490                         for(u16 z=0; z<MAP_BLOCKSIZE; z++){
491                                 for(u16 y=0; y<MAP_BLOCKSIZE; y++){
492                                         for(u16 x=0; x<MAP_BLOCKSIZE; x++){
493                                                 MapNode n;
494                                                 n.d = MATERIAL_AIR;
495                                                 n.setLight(0);
496                                                 b.setNode(v3s16(x,y,z), n);
497                                         }
498                                 }
499                         }
500                         // Make neighbours invalid
501                         parent.position_valid = false;
502                         // Add exceptions to the top of the bottom block
503                         for(u16 x=0; x<MAP_BLOCKSIZE; x++)
504                         for(u16 z=0; z<MAP_BLOCKSIZE; z++)
505                         {
506                                 parent.validity_exceptions.push_back(v3s16(MAP_BLOCKSIZE+x, MAP_BLOCKSIZE-1, MAP_BLOCKSIZE+z));
507                         }
508                         // Lighting value for the valid nodes
509                         parent.node.setLight(LIGHT_MAX/2);
510                         core::map<v3s16, bool> light_sources;
511                         // Bottom block is not valid
512                         assert(b.propagateSunlight(light_sources) == false);
513                 }
514         }
515 };
516
517 struct TestMapSector
518 {
519         class TC : public NodeContainer
520         {
521         public:
522
523                 MapNode node;
524                 bool position_valid;
525
526                 TC()
527                 {
528                         position_valid = true;
529                 }
530
531                 virtual bool isValidPosition(v3s16 p)
532                 {
533                         return position_valid;
534                 }
535
536                 virtual MapNode getNode(v3s16 p)
537                 {
538                         if(position_valid == false)
539                                 throw InvalidPositionException();
540                         return node;
541                 }
542
543                 virtual void setNode(v3s16 p, MapNode & n)
544                 {
545                         if(position_valid == false)
546                                 throw InvalidPositionException();
547                 };
548                 
549                 virtual u16 nodeContainerId() const
550                 {
551                         return 666;
552                 }
553         };
554         
555         void Run()
556         {
557                 TC parent;
558                 parent.position_valid = false;
559                 
560                 // Create one with no heightmaps
561                 ServerMapSector sector(&parent, v2s16(1,1), 0);
562                 //ConstantGenerator *dummyheightmap = new ConstantGenerator();
563                 //sector->setHeightmap(dummyheightmap);
564                 
565                 EXCEPTION_CHECK(InvalidPositionException, sector.getBlockNoCreate(0));
566                 EXCEPTION_CHECK(InvalidPositionException, sector.getBlockNoCreate(1));
567
568                 MapBlock * bref = sector.createBlankBlock(-2);
569                 
570                 EXCEPTION_CHECK(InvalidPositionException, sector.getBlockNoCreate(0));
571                 assert(sector.getBlockNoCreate(-2) == bref);
572                 
573                 //TODO: Check for AlreadyExistsException
574
575                 /*bool exception_thrown = false;
576                 try{
577                         sector.getBlock(0);
578                 }
579                 catch(InvalidPositionException &e){
580                         exception_thrown = true;
581                 }
582                 assert(exception_thrown);*/
583
584         }
585 };
586
587 struct TestHeightmap
588 {
589         void TestSingleFixed()
590         {
591                 const s16 BS1 = 4;
592                 OneChildHeightmap hm1(BS1);
593                 
594                 // Test that it is filled with < GROUNDHEIGHT_VALID_MINVALUE
595                 for(s16 y=0; y<=BS1; y++){
596                         for(s16 x=0; x<=BS1; x++){
597                                 v2s16 p(x,y);
598                                 assert(hm1.m_child.getGroundHeight(p)
599                                         < GROUNDHEIGHT_VALID_MINVALUE);
600                         }
601                 }
602
603                 hm1.m_child.setGroundHeight(v2s16(1,0), 2.0);
604                 //hm1.m_child.print();
605                 assert(fabs(hm1.getGroundHeight(v2s16(1,0))-2.0)<0.001);
606                 hm1.setGroundHeight(v2s16(0,1), 3.0);
607                 assert(fabs(hm1.m_child.getGroundHeight(v2s16(0,1))-3.0)<0.001);
608                 
609                 // Fill with -1.0
610                 for(s16 y=0; y<=BS1; y++){
611                         for(s16 x=0; x<=BS1; x++){
612                                 v2s16 p(x,y);
613                                 hm1.m_child.setGroundHeight(p, -1.0);
614                         }
615                 }
616
617                 f32 corners[] = {0.0, 0.0, 1.0, 1.0};
618                 hm1.m_child.generateContinued(0.0, 0.0, corners);
619                 
620                 hm1.m_child.print();
621                 assert(fabs(hm1.m_child.getGroundHeight(v2s16(1,0))-0.2)<0.05);
622                 assert(fabs(hm1.m_child.getGroundHeight(v2s16(4,3))-0.7)<0.05);
623                 assert(fabs(hm1.m_child.getGroundHeight(v2s16(4,4))-1.0)<0.05);
624         }
625
626         void TestUnlimited()
627         {
628                 //g_heightmap_debugprint = true;
629                 const s16 BS1 = 4;
630                 UnlimitedHeightmap hm1(BS1,
631                                 new ConstantGenerator(0.0),
632                                 new ConstantGenerator(0.0),
633                                 new ConstantGenerator(5.0));
634                 // Go through it so it generates itself
635                 for(s16 y=0; y<=BS1; y++){
636                         for(s16 x=0; x<=BS1; x++){
637                                 v2s16 p(x,y);
638                                 hm1.getGroundHeight(p);
639                         }
640                 }
641                 // Print it
642                 dstream<<"UnlimitedHeightmap hm1:"<<std::endl;
643                 hm1.print();
644                 
645                 dstream<<"testing UnlimitedHeightmap set/get"<<std::endl;
646                 v2s16 p1(0,3);
647                 f32 v1(234.01);
648                 // Get first heightmap and try setGroundHeight
649                 FixedHeightmap * href = hm1.getHeightmap(v2s16(0,0));
650                 href->setGroundHeight(p1, v1);
651                 // Read from UnlimitedHeightmap
652                 assert(fabs(hm1.getGroundHeight(p1)-v1)<0.001);
653         }
654         
655         void Random()
656         {
657                 dstream<<"Running random code (get a human to check this)"<<std::endl;
658                 dstream<<"rand() values: ";
659                 for(u16 i=0; i<5; i++)
660                         dstream<<(u16)rand()<<" ";
661                 dstream<<std::endl;
662
663                 const s16 BS1 = 8;
664                 UnlimitedHeightmap hm1(BS1,
665                                 new ConstantGenerator(10.0),
666                                 new ConstantGenerator(0.3),
667                                 new ConstantGenerator(0.0));
668
669                 // Force hm1 to generate a some heightmap
670                 hm1.getGroundHeight(v2s16(0,0));
671                 hm1.getGroundHeight(v2s16(0,BS1));
672                 /*hm1.getGroundHeight(v2s16(BS1,-1));
673                 hm1.getGroundHeight(v2s16(BS1-1,-1));*/
674                 hm1.print();
675
676                 // Get the (0,0) and (1,0) heightmaps
677                 /*FixedHeightmap * hr00 = hm1.getHeightmap(v2s16(0,0));
678                 FixedHeightmap * hr01 = hm1.getHeightmap(v2s16(1,0));
679                 f32 corners[] = {1.0, 1.0, 1.0, 1.0};
680                 hr00->generateContinued(0.0, 0.0, corners);
681                 hm1.print();*/
682
683                 //assert(0);
684         }
685
686         void Run()
687         {
688                 //srand(7); // Get constant random
689                 srand(time(0)); // Get better random
690
691                 TestSingleFixed();
692                 TestUnlimited();
693                 Random();
694         }
695 };
696
697 struct TestSocket
698 {
699         void Run()
700         {
701                 const int port = 30003;
702                 UDPSocket socket;
703                 socket.Bind(port);
704
705                 const char sendbuffer[] = "hello world!";
706                 socket.Send(Address(127,0,0,1,port), sendbuffer, sizeof(sendbuffer));
707
708                 sleep_ms(50);
709
710                 char rcvbuffer[256];
711                 memset(rcvbuffer, 0, sizeof(rcvbuffer));
712                 Address sender;
713                 for(;;)
714                 {
715                         int bytes_read = socket.Receive(sender, rcvbuffer, sizeof(rcvbuffer));
716                         if(bytes_read < 0)
717                                 break;
718                 }
719                 //FIXME: This fails on some systems
720                 assert(strncmp(sendbuffer, rcvbuffer, sizeof(sendbuffer))==0);
721                 assert(sender.getAddress() == Address(127,0,0,1, 0).getAddress());
722         }
723 };
724
725 struct TestConnection
726 {
727         void TestHelpers()
728         {
729                 /*
730                         Test helper functions
731                 */
732
733                 // Some constants for testing
734                 u32 proto_id = 0x12345678;
735                 u16 peer_id = 123;
736                 u8 channel = 2;
737                 SharedBuffer<u8> data1(1);
738                 data1[0] = 100;
739                 Address a(127,0,0,1, 10);
740                 u16 seqnum = 34352;
741
742                 con::BufferedPacket p1 = con::makePacket(a, data1,
743                                 proto_id, peer_id, channel);
744                 /*
745                         We should now have a packet with this data:
746                         Header:
747                                 [0] u32 protocol_id
748                                 [4] u16 sender_peer_id
749                                 [6] u8 channel
750                         Data:
751                                 [7] u8 data1[0]
752                 */
753                 assert(readU32(&p1.data[0]) == proto_id);
754                 assert(readU16(&p1.data[4]) == peer_id);
755                 assert(readU8(&p1.data[6]) == channel);
756                 assert(readU8(&p1.data[7]) == data1[0]);
757                 
758                 //dstream<<"initial data1[0]="<<((u32)data1[0]&0xff)<<std::endl;
759
760                 SharedBuffer<u8> p2 = con::makeReliablePacket(data1, seqnum);
761
762                 /*dstream<<"p2.getSize()="<<p2.getSize()<<", data1.getSize()="
763                                 <<data1.getSize()<<std::endl;
764                 dstream<<"readU8(&p2[3])="<<readU8(&p2[3])
765                                 <<" p2[3]="<<((u32)p2[3]&0xff)<<std::endl;
766                 dstream<<"data1[0]="<<((u32)data1[0]&0xff)<<std::endl;*/
767
768                 assert(p2.getSize() == 3 + data1.getSize());
769                 assert(readU8(&p2[0]) == TYPE_RELIABLE);
770                 assert(readU16(&p2[1]) == seqnum);
771                 assert(readU8(&p2[3]) == data1[0]);
772         }
773
774         struct Handler : public con::PeerHandler
775         {
776                 Handler(const char *a_name)
777                 {
778                         count = 0;
779                         last_id = 0;
780                         name = a_name;
781                 }
782                 void peerAdded(con::Peer *peer)
783                 {
784                         dstream<<"Handler("<<name<<")::peerAdded(): "
785                                         "id="<<peer->id<<std::endl;
786                         last_id = peer->id;
787                         count++;
788                 }
789                 void deletingPeer(con::Peer *peer, bool timeout)
790                 {
791                         dstream<<"Handler("<<name<<")::deletingPeer(): "
792                                         "id="<<peer->id
793                                         <<", timeout="<<timeout<<std::endl;
794                         last_id = peer->id;
795                         count--;
796                 }
797
798                 s32 count;
799                 u16 last_id;
800                 const char *name;
801         };
802
803         void Run()
804         {
805                 DSTACK("TestConnection::Run");
806
807                 TestHelpers();
808
809                 /*
810                         Test some real connections
811                 */
812                 u32 proto_id = 0xad26846a;
813
814                 Handler hand_server("server");
815                 Handler hand_client("client");
816                 
817                 dstream<<"** Creating server Connection"<<std::endl;
818                 con::Connection server(proto_id, 512, 5.0, &hand_server);
819                 server.Serve(30001);
820                 
821                 dstream<<"** Creating client Connection"<<std::endl;
822                 con::Connection client(proto_id, 512, 5.0, &hand_client);
823
824                 assert(hand_server.count == 0);
825                 assert(hand_client.count == 0);
826                 
827                 sleep_ms(50);
828                 
829                 Address server_address(127,0,0,1, 30001);
830                 dstream<<"** running client.Connect()"<<std::endl;
831                 client.Connect(server_address);
832
833                 sleep_ms(50);
834                 
835                 // Client should have added server now
836                 assert(hand_client.count == 1);
837                 assert(hand_client.last_id == 1);
838                 // But server should not have added client
839                 assert(hand_server.count == 0);
840
841                 try
842                 {
843                         u16 peer_id;
844                         u8 data[100];
845                         dstream<<"** running server.Receive()"<<std::endl;
846                         u32 size = server.Receive(peer_id, data, 100);
847                         dstream<<"** Server received: peer_id="<<peer_id
848                                         <<", size="<<size
849                                         <<std::endl;
850                 }
851                 catch(con::NoIncomingDataException &e)
852                 {
853                         // No actual data received, but the client has
854                         // probably been connected
855                 }
856                 
857                 // Client should be the same
858                 assert(hand_client.count == 1);
859                 assert(hand_client.last_id == 1);
860                 // Server should have the client
861                 assert(hand_server.count == 1);
862                 assert(hand_server.last_id == 2);
863                 
864                 //sleep_ms(50);
865
866                 while(client.Connected() == false)
867                 {
868                         try
869                         {
870                                 u16 peer_id;
871                                 u8 data[100];
872                                 dstream<<"** running client.Receive()"<<std::endl;
873                                 u32 size = client.Receive(peer_id, data, 100);
874                                 dstream<<"** Client received: peer_id="<<peer_id
875                                                 <<", size="<<size
876                                                 <<std::endl;
877                         }
878                         catch(con::NoIncomingDataException &e)
879                         {
880                         }
881                         sleep_ms(50);
882                 }
883
884                 sleep_ms(50);
885                 
886                 try
887                 {
888                         u16 peer_id;
889                         u8 data[100];
890                         dstream<<"** running server.Receive()"<<std::endl;
891                         u32 size = server.Receive(peer_id, data, 100);
892                         dstream<<"** Server received: peer_id="<<peer_id
893                                         <<", size="<<size
894                                         <<std::endl;
895                 }
896                 catch(con::NoIncomingDataException &e)
897                 {
898                 }
899
900                 {
901                         /*u8 data[] = "Hello World!";
902                         u32 datasize = sizeof(data);*/
903                         SharedBuffer<u8> data = SharedBufferFromString("Hello World!");
904
905                         dstream<<"** running client.Send()"<<std::endl;
906                         client.Send(PEER_ID_SERVER, 0, data, true);
907
908                         sleep_ms(50);
909
910                         u16 peer_id;
911                         u8 recvdata[100];
912                         dstream<<"** running server.Receive()"<<std::endl;
913                         u32 size = server.Receive(peer_id, recvdata, 100);
914                         dstream<<"** Server received: peer_id="<<peer_id
915                                         <<", size="<<size
916                                         <<", data="<<*data
917                                         <<std::endl;
918                         assert(memcmp(*data, recvdata, data.getSize()) == 0);
919                 }
920                 
921                 u16 peer_id_client = 2;
922
923                 {
924                         /*
925                                 Send consequent packets in different order
926                         */
927                         //u8 data1[] = "hello1";
928                         //u8 data2[] = "hello2";
929                         SharedBuffer<u8> data1 = SharedBufferFromString("hello1");
930                         SharedBuffer<u8> data2 = SharedBufferFromString("Hello2");
931
932                         Address client_address =
933                                         server.GetPeer(peer_id_client)->address;
934                         
935                         dstream<<"*** Sending packets in wrong order (2,1,2)"
936                                         <<std::endl;
937                         
938                         u8 chn = 0;
939                         con::Channel *ch = &server.GetPeer(peer_id_client)->channels[chn];
940                         u16 sn = ch->next_outgoing_seqnum;
941                         ch->next_outgoing_seqnum = sn+1;
942                         server.Send(peer_id_client, chn, data2, true);
943                         ch->next_outgoing_seqnum = sn;
944                         server.Send(peer_id_client, chn, data1, true);
945                         ch->next_outgoing_seqnum = sn+1;
946                         server.Send(peer_id_client, chn, data2, true);
947
948                         sleep_ms(50);
949
950                         dstream<<"*** Receiving the packets"<<std::endl;
951
952                         u16 peer_id;
953                         u8 recvdata[20];
954                         u32 size;
955
956                         dstream<<"** running client.Receive()"<<std::endl;
957                         peer_id = 132;
958                         size = client.Receive(peer_id, recvdata, 20);
959                         dstream<<"** Client received: peer_id="<<peer_id
960                                         <<", size="<<size
961                                         <<", data="<<recvdata
962                                         <<std::endl;
963                         assert(size == data1.getSize());
964                         assert(memcmp(*data1, recvdata, data1.getSize()) == 0);
965                         assert(peer_id == PEER_ID_SERVER);
966                         
967                         dstream<<"** running client.Receive()"<<std::endl;
968                         peer_id = 132;
969                         size = client.Receive(peer_id, recvdata, 20);
970                         dstream<<"** Client received: peer_id="<<peer_id
971                                         <<", size="<<size
972                                         <<", data="<<recvdata
973                                         <<std::endl;
974                         assert(size == data2.getSize());
975                         assert(memcmp(*data2, recvdata, data2.getSize()) == 0);
976                         assert(peer_id == PEER_ID_SERVER);
977                         
978                         bool got_exception = false;
979                         try
980                         {
981                                 dstream<<"** running client.Receive()"<<std::endl;
982                                 peer_id = 132;
983                                 size = client.Receive(peer_id, recvdata, 20);
984                                 dstream<<"** Client received: peer_id="<<peer_id
985                                                 <<", size="<<size
986                                                 <<", data="<<recvdata
987                                                 <<std::endl;
988                         }
989                         catch(con::NoIncomingDataException &e)
990                         {
991                                 dstream<<"** No incoming data for client"<<std::endl;
992                                 got_exception = true;
993                         }
994                         assert(got_exception);
995                 }
996                 {
997                         //u8 data1[1100];
998                         SharedBuffer<u8> data1(1100);
999                         for(u16 i=0; i<1100; i++){
1000                                 data1[i] = i/4;
1001                         }
1002
1003                         dstream<<"Sending data (size="<<1100<<"):";
1004                         for(int i=0; i<1100 && i<20; i++){
1005                                 if(i%2==0) printf(" ");
1006                                 printf("%.2X", ((int)((const char*)*data1)[i])&0xff);
1007                         }
1008                         if(1100>20)
1009                                 dstream<<"...";
1010                         dstream<<std::endl;
1011                         
1012                         server.Send(peer_id_client, 0, data1, true);
1013
1014                         sleep_ms(50);
1015                         
1016                         u8 recvdata[2000];
1017                         dstream<<"** running client.Receive()"<<std::endl;
1018                         u16 peer_id = 132;
1019                         u16 size = client.Receive(peer_id, recvdata, 2000);
1020                         dstream<<"** Client received: peer_id="<<peer_id
1021                                         <<", size="<<size
1022                                         <<std::endl;
1023
1024                         dstream<<"Received data (size="<<size<<"):";
1025                         for(int i=0; i<size && i<20; i++){
1026                                 if(i%2==0) printf(" ");
1027                                 printf("%.2X", ((int)((const char*)recvdata)[i])&0xff);
1028                         }
1029                         if(size>20)
1030                                 dstream<<"...";
1031                         dstream<<std::endl;
1032
1033                         assert(memcmp(*data1, recvdata, data1.getSize()) == 0);
1034                         assert(peer_id == PEER_ID_SERVER);
1035                 }
1036                 
1037                 // Check peer handlers
1038                 assert(hand_client.count == 1);
1039                 assert(hand_client.last_id == 1);
1040                 assert(hand_server.count == 1);
1041                 assert(hand_server.last_id == 2);
1042                 
1043                 //assert(0);
1044         }
1045 };
1046
1047 #define TEST(X)\
1048 {\
1049         X x;\
1050         dstream<<"Running " #X <<std::endl;\
1051         x.Run();\
1052 }
1053
1054 void run_tests()
1055 {
1056         DSTACK(__FUNCTION_NAME);
1057         dstream<<"run_tests() started"<<std::endl;
1058         TEST(TestUtilities);
1059         TEST(TestCompress);
1060         TEST(TestMapNode);
1061         TEST(TestVoxelManipulator);
1062         TEST(TestMapBlock);
1063         TEST(TestMapSector);
1064         TEST(TestHeightmap);
1065         if(INTERNET_SIMULATOR == false){
1066                 TEST(TestSocket);
1067                 dout_con<<"=== BEGIN RUNNING UNIT TESTS FOR CONNECTION ==="<<std::endl;
1068                 TEST(TestConnection);
1069                 dout_con<<"=== END RUNNING UNIT TESTS FOR CONNECTION ==="<<std::endl;
1070         }
1071         dstream<<"run_tests() passed"<<std::endl;
1072 }
1073