]> git.lizzy.rs Git - dragonfireclient.git/blobdiff - src/test.cpp
Omnicleanup: header cleanup, add ModApiUtil shared between game and mainmenu
[dragonfireclient.git] / src / test.cpp
index fe5a4f232d0819fd857afc0eb01173b881688f69..5e025f2f5fb23164165a1b2ca80f97b871c279b6 100644 (file)
@@ -1,6 +1,6 @@
 /*
-Minetest-c55
-Copyright (C) 2010 celeron55, Perttu Ahola <celeron55@gmail.com>
+Minetest
+Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
 
 This program is free software; you can redistribute it and/or modify
 it under the terms of the GNU Lesser General Public License as published by
@@ -36,11 +36,14 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "settings.h"
 #include "log.h"
 #include "util/string.h"
+#include "filesys.h"
 #include "voxelalgorithms.h"
 #include "inventory.h"
 #include "util/numeric.h"
 #include "util/serialize.h"
 #include "noise.h" // PseudoRandom used for random data for compression
+#include "clientserver.h" // LATEST_PROTOCOL_VERSION
+#include <algorithm>
 
 /*
        Asserts that the exception occurs
@@ -67,20 +70,18 @@ with this program; if not, write to the Free Software Foundation, Inc.,
        A few item and node definitions for those tests that need them
 */
 
-#define CONTENT_STONE 0
-#define CONTENT_GRASS 0x800
-#define CONTENT_TORCH 100
+static content_t CONTENT_STONE;
+static content_t CONTENT_GRASS;
+static content_t CONTENT_TORCH;
 
 void define_some_nodes(IWritableItemDefManager *idef, IWritableNodeDefManager *ndef)
 {
-       content_t i;
        ItemDefinition itemdef;
        ContentFeatures f;
 
        /*
                Stone
        */
-       i = CONTENT_STONE;
        itemdef = ItemDefinition();
        itemdef.type = ITEM_NODE;
        itemdef.name = "default:stone";
@@ -96,12 +97,11 @@ void define_some_nodes(IWritableItemDefManager *idef, IWritableNodeDefManager *n
                f.tiledef[i].name = "default_stone.png";
        f.is_ground_content = true;
        idef->registerItem(itemdef);
-       ndef->set(i, f);
+       CONTENT_STONE = ndef->set(f.name, f);
 
        /*
                Grass
        */
-       i = CONTENT_GRASS;
        itemdef = ItemDefinition();
        itemdef.type = ITEM_NODE;
        itemdef.name = "default:dirt_with_grass";
@@ -119,12 +119,11 @@ void define_some_nodes(IWritableItemDefManager *idef, IWritableNodeDefManager *n
                f.tiledef[i].name = "default_dirt.png^default_grass_side.png";
        f.is_ground_content = true;
        idef->registerItem(itemdef);
-       ndef->set(i, f);
+       CONTENT_GRASS = ndef->set(f.name, f);
 
        /*
                Torch (minimal definition for lighting tests)
        */
-       i = CONTENT_TORCH;
        itemdef = ItemDefinition();
        itemdef.type = ITEM_NODE;
        itemdef.name = "default:torch";
@@ -135,7 +134,7 @@ void define_some_nodes(IWritableItemDefManager *idef, IWritableNodeDefManager *n
        f.sunlight_propagates = true;
        f.light_source = LIGHT_MAX-1;
        idef->registerItem(itemdef);
-       ndef->set(i, f);
+       CONTENT_TORCH = ndef->set(f.name, f);
 }
 
 struct TestBase
@@ -158,9 +157,15 @@ struct TestUtilities: public TestBase
                UASSERT(fabs(wrapDegrees(-0.5) - (-0.5)) < 0.001);
                UASSERT(fabs(wrapDegrees(-365.5) - (-5.5)) < 0.001);
                UASSERT(lowercase("Foo bAR") == "foo bar");
+               UASSERT(trim("\n \t\r  Foo bAR  \r\n\t\t  ") == "Foo bAR");
+               UASSERT(trim("\n \t\r    \r\n\t\t  ") == "");
                UASSERT(is_yes("YeS") == true);
                UASSERT(is_yes("") == false);
                UASSERT(is_yes("FAlse") == false);
+               UASSERT(is_yes("-1") == true);
+               UASSERT(is_yes("0") == false);
+               UASSERT(is_yes("1") == true);
+               UASSERT(is_yes("2") == true);
                const char *ends[] = {"abc", "c", "bc", NULL};
                UASSERT(removeStringEnd("abc", ends) == "");
                UASSERT(removeStringEnd("bc", ends) == "b");
@@ -169,6 +174,212 @@ struct TestUtilities: public TestBase
        }
 };
 
+struct TestPath: public TestBase
+{
+       // adjusts a POSIX path to system-specific conventions
+       // -> changes '/' to DIR_DELIM
+       // -> absolute paths start with "C:\\" on windows
+       std::string p(std::string path)
+       {
+               for(size_t i = 0; i < path.size(); ++i){
+                       if(path[i] == '/'){
+                               path.replace(i, 1, DIR_DELIM);
+                               i += std::string(DIR_DELIM).size() - 1; // generally a no-op
+                       }
+               }
+
+               #ifdef _WIN32
+               if(path[0] == '\\')
+                       path = "C:" + path;
+               #endif
+
+               return path;
+       }
+
+       void Run()
+       {
+               std::string path, result, removed;
+
+               /*
+                       Test fs::IsDirDelimiter
+               */
+               UASSERT(fs::IsDirDelimiter('/') == true);
+               UASSERT(fs::IsDirDelimiter('A') == false);
+               UASSERT(fs::IsDirDelimiter(0) == false);
+               #ifdef _WIN32
+               UASSERT(fs::IsDirDelimiter('\\') == true);
+               #else
+               UASSERT(fs::IsDirDelimiter('\\') == false);
+               #endif
+
+               /*
+                       Test fs::PathStartsWith
+               */
+               {
+                       const int numpaths = 12;
+                       std::string paths[numpaths] = {
+                               "",
+                               p("/"),
+                               p("/home/user/minetest"),
+                               p("/home/user/minetest/bin"),
+                               p("/home/user/.minetest"),
+                               p("/tmp/dir/file"),
+                               p("/tmp/file/"),
+                               p("/tmP/file"),
+                               p("/tmp"),
+                               p("/tmp/dir"),
+                               p("/home/user2/minetest/worlds"),
+                               p("/home/user2/minetest/world"),
+                       };
+                       /*
+                               expected fs::PathStartsWith results
+                               0 = returns false
+                               1 = returns true
+                               2 = returns false on windows, false elsewhere
+                               3 = returns true on windows, true elsewhere
+                               4 = returns true if and only if
+                                   FILESYS_CASE_INSENSITIVE is true
+                       */
+                       int expected_results[numpaths][numpaths] = {
+                               {1,2,0,0,0,0,0,0,0,0,0,0},
+                               {1,1,0,0,0,0,0,0,0,0,0,0},
+                               {1,1,1,0,0,0,0,0,0,0,0,0},
+                               {1,1,1,1,0,0,0,0,0,0,0,0},
+                               {1,1,0,0,1,0,0,0,0,0,0,0},
+                               {1,1,0,0,0,1,0,0,1,1,0,0},
+                               {1,1,0,0,0,0,1,4,1,0,0,0},
+                               {1,1,0,0,0,0,4,1,4,0,0,0},
+                               {1,1,0,0,0,0,0,0,1,0,0,0},
+                               {1,1,0,0,0,0,0,0,1,1,0,0},
+                               {1,1,0,0,0,0,0,0,0,0,1,0},
+                               {1,1,0,0,0,0,0,0,0,0,0,1},
+                       };
+
+                       for (int i = 0; i < numpaths; i++)
+                       for (int j = 0; j < numpaths; j++){
+                               /*verbosestream<<"testing fs::PathStartsWith(\""
+                                       <<paths[i]<<"\", \""
+                                       <<paths[j]<<"\")"<<std::endl;*/
+                               bool starts = fs::PathStartsWith(paths[i], paths[j]);
+                               int expected = expected_results[i][j];
+                               if(expected == 0){
+                                       UASSERT(starts == false);
+                               }
+                               else if(expected == 1){
+                                       UASSERT(starts == true);
+                               }
+                               #ifdef _WIN32
+                               else if(expected == 2){
+                                       UASSERT(starts == false);
+                               }
+                               else if(expected == 3){
+                                       UASSERT(starts == true);
+                               }
+                               #else
+                               else if(expected == 2){
+                                       UASSERT(starts == true);
+                               }
+                               else if(expected == 3){
+                                       UASSERT(starts == false);
+                               }
+                               #endif
+                               else if(expected == 4){
+                                       UASSERT(starts == (bool)FILESYS_CASE_INSENSITIVE);
+                               }
+                       }
+               }
+
+               /*
+                       Test fs::RemoveLastPathComponent
+               */
+               UASSERT(fs::RemoveLastPathComponent("") == "");
+               path = p("/home/user/minetest/bin/..//worlds/world1");
+               result = fs::RemoveLastPathComponent(path, &removed, 0);
+               UASSERT(result == path);
+               UASSERT(removed == "");
+               result = fs::RemoveLastPathComponent(path, &removed, 1);
+               UASSERT(result == p("/home/user/minetest/bin/..//worlds"));
+               UASSERT(removed == p("world1"));
+               result = fs::RemoveLastPathComponent(path, &removed, 2);
+               UASSERT(result == p("/home/user/minetest/bin/.."));
+               UASSERT(removed == p("worlds/world1"));
+               result = fs::RemoveLastPathComponent(path, &removed, 3);
+               UASSERT(result == p("/home/user/minetest/bin"));
+               UASSERT(removed == p("../worlds/world1"));
+               result = fs::RemoveLastPathComponent(path, &removed, 4);
+               UASSERT(result == p("/home/user/minetest"));
+               UASSERT(removed == p("bin/../worlds/world1"));
+               result = fs::RemoveLastPathComponent(path, &removed, 5);
+               UASSERT(result == p("/home/user"));
+               UASSERT(removed == p("minetest/bin/../worlds/world1"));
+               result = fs::RemoveLastPathComponent(path, &removed, 6);
+               UASSERT(result == p("/home"));
+               UASSERT(removed == p("user/minetest/bin/../worlds/world1"));
+               result = fs::RemoveLastPathComponent(path, &removed, 7);
+               #ifdef _WIN32
+               UASSERT(result == "C:");
+               #else
+               UASSERT(result == "");
+               #endif
+               UASSERT(removed == p("home/user/minetest/bin/../worlds/world1"));
+
+               /*
+                       Now repeat the test with a trailing delimiter
+               */
+               path = p("/home/user/minetest/bin/..//worlds/world1/");
+               result = fs::RemoveLastPathComponent(path, &removed, 0);
+               UASSERT(result == path);
+               UASSERT(removed == "");
+               result = fs::RemoveLastPathComponent(path, &removed, 1);
+               UASSERT(result == p("/home/user/minetest/bin/..//worlds"));
+               UASSERT(removed == p("world1"));
+               result = fs::RemoveLastPathComponent(path, &removed, 2);
+               UASSERT(result == p("/home/user/minetest/bin/.."));
+               UASSERT(removed == p("worlds/world1"));
+               result = fs::RemoveLastPathComponent(path, &removed, 3);
+               UASSERT(result == p("/home/user/minetest/bin"));
+               UASSERT(removed == p("../worlds/world1"));
+               result = fs::RemoveLastPathComponent(path, &removed, 4);
+               UASSERT(result == p("/home/user/minetest"));
+               UASSERT(removed == p("bin/../worlds/world1"));
+               result = fs::RemoveLastPathComponent(path, &removed, 5);
+               UASSERT(result == p("/home/user"));
+               UASSERT(removed == p("minetest/bin/../worlds/world1"));
+               result = fs::RemoveLastPathComponent(path, &removed, 6);
+               UASSERT(result == p("/home"));
+               UASSERT(removed == p("user/minetest/bin/../worlds/world1"));
+               result = fs::RemoveLastPathComponent(path, &removed, 7);
+               #ifdef _WIN32
+               UASSERT(result == "C:");
+               #else
+               UASSERT(result == "");
+               #endif
+               UASSERT(removed == p("home/user/minetest/bin/../worlds/world1"));
+
+               /*
+                       Test fs::RemoveRelativePathComponent
+               */
+               path = p("/home/user/minetest/bin");
+               result = fs::RemoveRelativePathComponents(path);
+               UASSERT(result == path);
+               path = p("/home/user/minetest/bin/../worlds/world1");
+               result = fs::RemoveRelativePathComponents(path);
+               UASSERT(result == p("/home/user/minetest/worlds/world1"));
+               path = p("/home/user/minetest/bin/../worlds/world1/");
+               result = fs::RemoveRelativePathComponents(path);
+               UASSERT(result == p("/home/user/minetest/worlds/world1"));
+               path = p(".");
+               result = fs::RemoveRelativePathComponents(path);
+               UASSERT(result == "");
+               path = p("./subdir/../..");
+               result = fs::RemoveRelativePathComponents(path);
+               UASSERT(result == "");
+               path = p("/a/b/c/.././../d/../e/f/g/../h/i/j/../../../..");
+               result = fs::RemoveRelativePathComponents(path);
+               UASSERT(result == p("/a/e"));
+       }
+};
+
 struct TestSettings: public TestBase
 {
        void Run()
@@ -314,6 +525,26 @@ struct TestSerialization: public TestBase
        }
 };
 
+struct TestNodedefSerialization: public TestBase
+{
+       void Run()
+       {
+               ContentFeatures f;
+               f.name = "default:stone";
+               for(int i = 0; i < 6; i++)
+                       f.tiledef[i].name = "default_stone.png";
+               f.is_ground_content = true;
+               std::ostringstream os(std::ios::binary);
+               f.serialize(os, LATEST_PROTOCOL_VERSION);
+               verbosestream<<"Test ContentFeatures size: "<<os.str().size()<<std::endl;
+               std::istringstream is(os.str(), std::ios::binary);
+               ContentFeatures f2;
+               f2.deSerialize(is);
+               UASSERT(f.walkable == f2.walkable);
+               UASSERT(f.node_box.type == f2.node_box.type);
+       }
+};
+
 struct TestCompress: public TestBase
 {
        void Run()
@@ -383,7 +614,7 @@ struct TestCompress: public TestBase
                fromdata[3]=1;
                
                std::ostringstream os(std::ios_base::binary);
-               compress(fromdata, os, SER_FMT_VER_HIGHEST);
+               compress(fromdata, os, SER_FMT_VER_HIGHEST_READ);
 
                std::string str_out = os.str();
                
@@ -398,7 +629,7 @@ struct TestCompress: public TestBase
                std::istringstream is(str_out, std::ios_base::binary);
                std::ostringstream os2(std::ios_base::binary);
 
-               decompress(is, os2, SER_FMT_VER_HIGHEST);
+               decompress(is, os2, SER_FMT_VER_HIGHEST_READ);
                std::string str_out2 = os2.str();
 
                infostream<<"decompress: ";
@@ -441,8 +672,8 @@ struct TestCompress: public TestBase
                                        <<os_decompressed.str().size()<<std::endl;
                        std::string str_decompressed = os_decompressed.str();
                        UTEST(str_decompressed.size() == data_in.size(), "Output size not"
-                                       " equal (output: %i, input: %i)",
-                                       str_decompressed.size(), data_in.size());
+                                       " equal (output: %u, input: %u)",
+                                       (unsigned int)str_decompressed.size(), (unsigned int)data_in.size());
                        for(u32 i=0; i<size && i<str_decompressed.size(); i++){
                                UTEST(str_decompressed[i] == data_in[i],
                                                "index out[%i]=%i differs from in[%i]=%i",
@@ -487,26 +718,26 @@ struct TestVoxelManipulator: public TestBase
                // An area that is 1 bigger in x+ and z-
                VoxelArea d(v3s16(-2,-2,-3), v3s16(3,2,2));
                
-               core::list<VoxelArea> aa;
+               std::list<VoxelArea> aa;
                d.diff(c, aa);
                
                // Correct results
-               core::array<VoxelArea> results;
+               std::vector<VoxelArea> results;
                results.push_back(VoxelArea(v3s16(-2,-2,-3),v3s16(3,2,-3)));
                results.push_back(VoxelArea(v3s16(3,-2,-2),v3s16(3,2,2)));
 
                UASSERT(aa.size() == results.size());
                
                infostream<<"Result of diff:"<<std::endl;
-               for(core::list<VoxelArea>::Iterator
-                               i = aa.begin(); i != aa.end(); i++)
+               for(std::list<VoxelArea>::const_iterator
+                               i = aa.begin(); i != aa.end(); ++i)
                {
                        i->print(infostream);
                        infostream<<std::endl;
                        
-                       s32 j = results.linear_search(*i);
-                       UASSERT(j != -1);
-                       results.erase(j, 1);
+                       std::vector<VoxelArea>::iterator j = std::find(results.begin(), results.end(), *i);
+                       UASSERT(j != results.end());
+                       results.erase(j);
                }
 
 
@@ -561,7 +792,7 @@ struct TestVoxelAlgorithms: public TestBase
                        }
                        VoxelArea a(v3s16(0,0,0), v3s16(2,2,2));
                        {
-                               core::map<v3s16, bool> light_sources;
+                               std::set<v3s16> light_sources;
                                voxalgo::setLight(v, a, 0, ndef);
                                voxalgo::SunlightPropagateResult res = voxalgo::propagateSunlight(
                                                v, a, true, light_sources, ndef);
@@ -572,7 +803,7 @@ struct TestVoxelAlgorithms: public TestBase
                        }
                        v.setNodeNoRef(v3s16(0,0,0), MapNode(CONTENT_STONE));
                        {
-                               core::map<v3s16, bool> light_sources;
+                               std::set<v3s16> light_sources;
                                voxalgo::setLight(v, a, 0, ndef);
                                voxalgo::SunlightPropagateResult res = voxalgo::propagateSunlight(
                                                v, a, true, light_sources, ndef);
@@ -581,7 +812,7 @@ struct TestVoxelAlgorithms: public TestBase
                                                == LIGHT_SUN);
                        }
                        {
-                               core::map<v3s16, bool> light_sources;
+                               std::set<v3s16> light_sources;
                                voxalgo::setLight(v, a, 0, ndef);
                                voxalgo::SunlightPropagateResult res = voxalgo::propagateSunlight(
                                                v, a, false, light_sources, ndef);
@@ -591,7 +822,7 @@ struct TestVoxelAlgorithms: public TestBase
                        }
                        v.setNodeNoRef(v3s16(1,3,2), MapNode(CONTENT_STONE));
                        {
-                               core::map<v3s16, bool> light_sources;
+                               std::set<v3s16> light_sources;
                                voxalgo::setLight(v, a, 0, ndef);
                                voxalgo::SunlightPropagateResult res = voxalgo::propagateSunlight(
                                                v, a, true, light_sources, ndef);
@@ -600,7 +831,7 @@ struct TestVoxelAlgorithms: public TestBase
                                                == 0);
                        }
                        {
-                               core::map<v3s16, bool> light_sources;
+                               std::set<v3s16> light_sources;
                                voxalgo::setLight(v, a, 0, ndef);
                                voxalgo::SunlightPropagateResult res = voxalgo::propagateSunlight(
                                                v, a, false, light_sources, ndef);
@@ -614,14 +845,14 @@ struct TestVoxelAlgorithms: public TestBase
                                v.setNodeNoRef(v3s16(1,-1,2), n);
                        }
                        {
-                               core::map<v3s16, bool> light_sources;
+                               std::set<v3s16> light_sources;
                                voxalgo::setLight(v, a, 0, ndef);
                                voxalgo::SunlightPropagateResult res = voxalgo::propagateSunlight(
                                                v, a, true, light_sources, ndef);
                                UASSERT(res.bottom_sunlight_valid == true);
                        }
                        {
-                               core::map<v3s16, bool> light_sources;
+                               std::set<v3s16> light_sources;
                                voxalgo::setLight(v, a, 0, ndef);
                                voxalgo::SunlightPropagateResult res = voxalgo::propagateSunlight(
                                                v, a, false, light_sources, ndef);
@@ -633,14 +864,14 @@ struct TestVoxelAlgorithms: public TestBase
                                v.setNodeNoRef(v3s16(1,-1,2), n);
                        }
                        {
-                               core::map<v3s16, bool> light_sources;
+                               std::set<v3s16> light_sources;
                                voxalgo::setLight(v, a, 0, ndef);
                                voxalgo::SunlightPropagateResult res = voxalgo::propagateSunlight(
                                                v, a, true, light_sources, ndef);
                                UASSERT(res.bottom_sunlight_valid == false);
                        }
                        {
-                               core::map<v3s16, bool> light_sources;
+                               std::set<v3s16> light_sources;
                                voxalgo::setLight(v, a, 0, ndef);
                                voxalgo::SunlightPropagateResult res = voxalgo::propagateSunlight(
                                                v, a, false, light_sources, ndef);
@@ -648,7 +879,7 @@ struct TestVoxelAlgorithms: public TestBase
                        }
                        v.setNodeNoRef(v3s16(1,3,2), MapNode(CONTENT_IGNORE));
                        {
-                               core::map<v3s16, bool> light_sources;
+                               std::set<v3s16> light_sources;
                                voxalgo::setLight(v, a, 0, ndef);
                                voxalgo::SunlightPropagateResult res = voxalgo::propagateSunlight(
                                                v, a, true, light_sources, ndef);
@@ -676,16 +907,16 @@ struct TestVoxelAlgorithms: public TestBase
                                v.setNode(v3s16(1,1,2), n);
                        }
                        {
-                               core::map<v3s16, bool> light_sources;
-                               core::map<v3s16, u8> unlight_from;
+                               std::set<v3s16> light_sources;
+                               std::map<v3s16, u8> unlight_from;
                                voxalgo::clearLightAndCollectSources(v, a, LIGHTBANK_DAY,
                                                ndef, light_sources, unlight_from);
                                //v.print(dstream, ndef, VOXELPRINT_LIGHT_DAY);
                                UASSERT(v.getNode(v3s16(0,1,1)).getLight(LIGHTBANK_DAY, ndef)
                                                == 0);
-                               UASSERT(light_sources.find(v3s16(1,1,1)) != NULL);
+                               UASSERT(light_sources.find(v3s16(1,1,1)) != light_sources.end());
                                UASSERT(light_sources.size() == 1);
-                               UASSERT(unlight_from.find(v3s16(1,1,2)) != NULL);
+                               UASSERT(unlight_from.find(v3s16(1,1,2)) != unlight_from.end());
                                UASSERT(unlight_from.size() == 1);
                        }
                }
@@ -698,6 +929,7 @@ struct TestInventory: public TestBase
        {
                std::string serialized_inventory =
                "List 0 32\n"
+               "Width 3\n"
                "Empty\n"
                "Empty\n"
                "Empty\n"
@@ -735,6 +967,7 @@ struct TestInventory: public TestBase
                
                std::string serialized_inventory_2 =
                "List main 32\n"
+               "Width 5\n"
                "Empty\n"
                "Empty\n"
                "Empty\n"
@@ -778,6 +1011,8 @@ struct TestInventory: public TestBase
                inv.getList("0")->setName("main");
                UASSERT(!inv.getList("0"));
                UASSERT(inv.getList("main"));
+               UASSERT(inv.getList("main")->getWidth() == 3);
+               inv.getList("main")->setWidth(5);
                std::ostringstream inv_os(std::ios::binary);
                inv.serialize(inv_os);
                UASSERT(inv_os.str() == serialized_inventory_2);
@@ -1267,26 +1502,56 @@ struct TestSocket: public TestBase
        void Run()
        {
                const int port = 30003;
-               UDPSocket socket;
-               socket.Bind(port);
 
-               const char sendbuffer[] = "hello world!";
-               socket.Send(Address(127,0,0,1,port), sendbuffer, sizeof(sendbuffer));
+               // IPv6 socket test
+               {
+                       UDPSocket socket6(true);
+                       socket6.Bind(port);
+
+                       const char sendbuffer[] = "hello world!";
+                       IPv6AddressBytes bytes;
+                       bytes.bytes[15] = 1;
+                       socket6.Send(Address(&bytes, port), sendbuffer, sizeof(sendbuffer));
 
-               sleep_ms(50);
+                       sleep_ms(50);
 
-               char rcvbuffer[256];
-               memset(rcvbuffer, 0, sizeof(rcvbuffer));
-               Address sender;
-               for(;;)
+                       char rcvbuffer[256];
+                       memset(rcvbuffer, 0, sizeof(rcvbuffer));
+                       Address sender;
+                       for(;;)
+                       {
+                               int bytes_read = socket6.Receive(sender, rcvbuffer, sizeof(rcvbuffer));
+                               if(bytes_read < 0)
+                                       break;
+                       }
+                       //FIXME: This fails on some systems
+                       UASSERT(strncmp(sendbuffer, rcvbuffer, sizeof(sendbuffer))==0);
+                       UASSERT(memcmp(sender.getAddress6().sin6_addr.s6_addr, Address(&bytes, 0).getAddress6().sin6_addr.s6_addr, 16) == 0);
+               }
+
+               // IPv4 socket test
                {
-                       int bytes_read = socket.Receive(sender, rcvbuffer, sizeof(rcvbuffer));
-                       if(bytes_read < 0)
-                               break;
+                       UDPSocket socket(false);
+                       socket.Bind(port);
+
+                       const char sendbuffer[] = "hello world!";
+                       socket.Send(Address(127,0,0,1,port), sendbuffer, sizeof(sendbuffer));
+
+                       sleep_ms(50);
+
+                       char rcvbuffer[256];
+                       memset(rcvbuffer, 0, sizeof(rcvbuffer));
+                       Address sender;
+                       for(;;)
+                       {
+                               int bytes_read = socket.Receive(sender, rcvbuffer, sizeof(rcvbuffer));
+                               if(bytes_read < 0)
+                                       break;
+                       }
+                       //FIXME: This fails on some systems
+                       UASSERT(strncmp(sendbuffer, rcvbuffer, sizeof(sendbuffer))==0);
+                       UASSERT(sender.getAddress().sin_addr.s_addr == Address(127,0,0,1, 0).getAddress().sin_addr.s_addr);
                }
-               //FIXME: This fails on some systems
-               UASSERT(strncmp(sendbuffer, rcvbuffer, sizeof(sendbuffer))==0);
-               UASSERT(sender.getAddress() == Address(127,0,0,1, 0).getAddress());
        }
 };
 
@@ -1386,12 +1651,12 @@ struct TestConnection: public TestBase
                Handler hand_client("client");
                
                infostream<<"** Creating server Connection"<<std::endl;
-               con::Connection server(proto_id, 512, 5.0, &hand_server);
+               con::Connection server(proto_id, 512, 5.0, false, &hand_server);
                server.Serve(30001);
                
                infostream<<"** Creating client Connection"<<std::endl;
-               con::Connection client(proto_id, 512, 5.0, &hand_client);
-
+               con::Connection client(proto_id, 512, 5.0, false, &hand_client);
+               
                UASSERT(hand_server.count == 0);
                UASSERT(hand_client.count == 0);
                
@@ -1426,7 +1691,7 @@ struct TestConnection: public TestBase
                // Server should not have added client yet
                UASSERT(hand_server.count == 0);
                
-               sleep_ms(50);
+               sleep_ms(100);
 
                try
                {
@@ -1729,9 +1994,11 @@ void run_tests()
 
        infostream<<"run_tests() started"<<std::endl;
        TEST(TestUtilities);
+       TEST(TestPath);
        TEST(TestSettings);
        TEST(TestCompress);
        TEST(TestSerialization);
+       TEST(TestNodedefSerialization);
        TESTPARAMS(TestMapNode, ndef);
        TESTPARAMS(TestVoxelManipulator, ndef);
        TESTPARAMS(TestVoxelAlgorithms, ndef);
@@ -1745,6 +2012,10 @@ void run_tests()
                TEST(TestConnection);
                dout_con<<"=== END RUNNING UNIT TESTS FOR CONNECTION ==="<<std::endl;
        }
+
+       delete idef;
+       delete ndef;
+
        if(tests_failed == 0){
                infostream<<"run_tests(): "<<tests_failed<<" / "<<tests_run<<" tests failed."<<std::endl;
                infostream<<"run_tests() passed."<<std::endl;