X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=src%2Ftest.cpp;h=350cab127910f8cc6f607d761bedd1453f1ea9ee;hb=3b6480c5b0c968ad9f5a7cfb7ca494989be03629;hp=f988b34f7bb15958ac3cae1e73556a6daf8aca49;hpb=979ca23f1eae1adeb8b0083dffe7203c54d87395;p=dragonfireclient.git diff --git a/src/test.cpp b/src/test.cpp index f988b34f7..350cab127 100644 --- a/src/test.cpp +++ b/src/test.cpp @@ -24,7 +24,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "player.h" #include "main.h" #include "socket.h" -#include "connection.h" +#include "network/connection.h" #include "serialization.h" #include "voxel.h" #include "collision.h" @@ -36,12 +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 "network/networkprotocol.h" // LATEST_PROTOCOL_VERSION +#include /* Asserts that the exception occurs @@ -57,7 +59,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #define UTEST(x, fmt, ...)\ {\ if(!(x)){\ - LOGLINEF(LMT_ERROR, "Test (%s) failed: " fmt, #x, ##__VA_ARGS__);\ + dstream << "Test (" #x ") failed: " fmt << std::endl; \ test_failed = true;\ }\ } @@ -68,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"; @@ -97,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"; @@ -120,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"; @@ -136,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 @@ -149,48 +147,395 @@ struct TestBase struct TestUtilities: public TestBase { + inline float ref_WrapDegrees180(float f) + { + // This is a slower alternative to the wrapDegrees_180() function; + // used as a reference for testing + float value = fmodf(f + 180, 360); + if (value < 0) + value += 360; + return value - 180; + } + + inline float ref_WrapDegrees_0_360(float f) + { + // This is a slower alternative to the wrapDegrees_0_360() function; + // used as a reference for testing + float value = fmodf(f, 360); + if (value < 0) + value += 360; + return value < 0 ? value + 360 : value; + } + + void Run() { - /*infostream<<"wrapDegrees(100.0) = "< 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, true elsewhere + 3 = returns true on windows, false 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(\"" + <getS16("a") == 5); + UASSERT(fabs(group->getFloat("bb") - 2.5) < 0.001); + + Settings *group3 = new Settings; + group3->set("cat", "meow"); + group3->set("dog", "woof"); + + Settings *group2 = new Settings; + group2->setS16("num_apples", 4); + group2->setS16("num_oranges", 53); + group2->setGroup("animals", group3); + group2->set("animals", "cute"); //destroys group 3 + s.setGroup("groupy_thing", group2); + + // Test set failure conditions + UASSERT(s.set("Zoop = Poop\nsome_other_setting", "false") == false); + UASSERT(s.set("sneaky", "\"\"\"\njabberwocky = false") == false); + UASSERT(s.set("hehe", "asdfasdf\n\"\"\"\nsomething = false") == false); + + // Test multiline settings + UASSERT(group->get("ccc") == "testy\n testa "); + + UASSERT(s.get("blarg") == + "some multiline text\n" + " with leading whitespace!"); + + // Test NoiseParams + UASSERT(s.getEntry("np_terrain").is_group == false); + + NoiseParams np; + UASSERT(s.getNoiseParams("np_terrain", np) == true); + UASSERT(fabs(np.offset - 5) < 0.001); + UASSERT(fabs(np.scale - 40) < 0.001); + UASSERT(fabs(np.spread.X - 250) < 0.001); + UASSERT(fabs(np.spread.Y - 250) < 0.001); + UASSERT(fabs(np.spread.Z - 250) < 0.001); + UASSERT(np.seed == 12341); + UASSERT(np.octaves == 5); + UASSERT(fabs(np.persist - 0.7) < 0.001); + + np.offset = 3.5; + np.octaves = 6; + s.setNoiseParams("np_terrain", np); + + UASSERT(s.getEntry("np_terrain").is_group == true); + + // Test writing + std::ostringstream os(std::ios_base::binary); + is.clear(); + is.seekg(0); + + UASSERT(s.updateConfigObject(is, os, "", 0) == true); + //printf(">>>> expected config:\n%s\n", TEST_CONFIG_TEXT_AFTER); + //printf(">>>> actual config:\n%s\n", os.str().c_str()); + UASSERT(os.str() == TEST_CONFIG_TEXT_AFTER); + } catch (SettingNotFoundException &e) { + UASSERT(!"Setting not found!"); + } } }; @@ -220,7 +628,7 @@ struct TestSerialization: public TestBase UASSERT(serializeWideString(L"") == mkstr("\0\0")); UASSERT(serializeLongString("") == mkstr("\0\0\0\0")); UASSERT(serializeJsonString("") == "\"\""); - + std::string teststring = "Hello world!"; UASSERT(serializeString(teststring) == mkstr("\0\14Hello world!")); @@ -346,12 +754,12 @@ struct TestCompress: public TestBase fromdata[1]=5; fromdata[2]=5; fromdata[3]=1; - + std::ostringstream os(std::ios_base::binary); compress(fromdata, os, 0); std::string str_out = os.str(); - + infostream<<"str_out.size()="< "; for(u32 i=0; i "; for(u32 i=0; iget(n).light_propagates == true); @@ -503,44 +910,44 @@ struct TestVoxelManipulator: public TestBase VoxelArea a(v3s16(-1,-1,-1), v3s16(1,1,1)); UASSERT(a.index(0,0,0) == 1*3*3 + 1*3 + 1); UASSERT(a.index(-1,-1,-1) == 0); - + VoxelArea c(v3s16(-2,-2,-2), v3s16(2,2,2)); // An area that is 1 bigger in x+ and z- VoxelArea d(v3s16(-2,-2,-3), v3s16(3,2,2)); - - core::list aa; + + std::list aa; d.diff(c, aa); - + // Correct results - core::array results; + std::vector 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:"<::Iterator - i = aa.begin(); i != aa.end(); i++) + for(std::list::const_iterator + i = aa.begin(); i != aa.end(); ++i) { i->print(infostream); infostream<::iterator j = std::find(results.begin(), results.end(), *i); + UASSERT(j != results.end()); + results.erase(j); } /* VoxelManipulator */ - + VoxelManipulator v; v.print(infostream, nodedef); infostream<<"*** Setting (-1,0,-1)=2 ***"< light_sources; + std::set light_sources; voxalgo::setLight(v, a, 0, ndef); voxalgo::SunlightPropagateResult res = voxalgo::propagateSunlight( v, a, true, light_sources, ndef); @@ -593,7 +1000,7 @@ struct TestVoxelAlgorithms: public TestBase } v.setNodeNoRef(v3s16(0,0,0), MapNode(CONTENT_STONE)); { - core::map light_sources; + std::set light_sources; voxalgo::setLight(v, a, 0, ndef); voxalgo::SunlightPropagateResult res = voxalgo::propagateSunlight( v, a, true, light_sources, ndef); @@ -602,7 +1009,7 @@ struct TestVoxelAlgorithms: public TestBase == LIGHT_SUN); } { - core::map light_sources; + std::set light_sources; voxalgo::setLight(v, a, 0, ndef); voxalgo::SunlightPropagateResult res = voxalgo::propagateSunlight( v, a, false, light_sources, ndef); @@ -612,7 +1019,7 @@ struct TestVoxelAlgorithms: public TestBase } v.setNodeNoRef(v3s16(1,3,2), MapNode(CONTENT_STONE)); { - core::map light_sources; + std::set light_sources; voxalgo::setLight(v, a, 0, ndef); voxalgo::SunlightPropagateResult res = voxalgo::propagateSunlight( v, a, true, light_sources, ndef); @@ -621,7 +1028,7 @@ struct TestVoxelAlgorithms: public TestBase == 0); } { - core::map light_sources; + std::set light_sources; voxalgo::setLight(v, a, 0, ndef); voxalgo::SunlightPropagateResult res = voxalgo::propagateSunlight( v, a, false, light_sources, ndef); @@ -635,14 +1042,14 @@ struct TestVoxelAlgorithms: public TestBase v.setNodeNoRef(v3s16(1,-1,2), n); } { - core::map light_sources; + std::set 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 light_sources; + std::set light_sources; voxalgo::setLight(v, a, 0, ndef); voxalgo::SunlightPropagateResult res = voxalgo::propagateSunlight( v, a, false, light_sources, ndef); @@ -654,14 +1061,14 @@ struct TestVoxelAlgorithms: public TestBase v.setNodeNoRef(v3s16(1,-1,2), n); } { - core::map light_sources; + std::set 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 light_sources; + std::set light_sources; voxalgo::setLight(v, a, 0, ndef); voxalgo::SunlightPropagateResult res = voxalgo::propagateSunlight( v, a, false, light_sources, ndef); @@ -669,7 +1076,7 @@ struct TestVoxelAlgorithms: public TestBase } v.setNodeNoRef(v3s16(1,3,2), MapNode(CONTENT_IGNORE)); { - core::map light_sources; + std::set light_sources; voxalgo::setLight(v, a, 0, ndef); voxalgo::SunlightPropagateResult res = voxalgo::propagateSunlight( v, a, true, light_sources, ndef); @@ -697,16 +1104,16 @@ struct TestVoxelAlgorithms: public TestBase v.setNode(v3s16(1,1,2), n); } { - core::map light_sources; - core::map unlight_from; + std::set light_sources; + std::map 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); } } @@ -754,7 +1161,7 @@ struct TestInventory: public TestBase "Empty\n" "EndInventoryList\n" "EndInventory\n"; - + std::string serialized_inventory_2 = "List main 32\n" "Width 5\n" @@ -792,7 +1199,7 @@ struct TestInventory: public TestBase "Empty\n" "EndInventoryList\n" "EndInventory\n"; - + Inventory inv(idef); std::istringstream is(serialized_inventory, std::ios::binary); inv.deSerialize(is); @@ -868,7 +1275,7 @@ struct TestMapBlock: public TestBase void Run() { TC parent; - + MapBlock b(&parent, v3s16(1,1,1)); v3s16 relpos(MAP_BLOCKSIZE, MAP_BLOCKSIZE, MAP_BLOCKSIZE); @@ -880,7 +1287,7 @@ struct TestMapBlock: public TestBase UASSERT(b.getBox().MaxEdge.Y == MAP_BLOCKSIZE*2-1); UASSERT(b.getBox().MinEdge.Z == MAP_BLOCKSIZE); UASSERT(b.getBox().MaxEdge.Z == MAP_BLOCKSIZE*2-1); - + UASSERT(b.isValidPosition(v3s16(0,0,0)) == true); UASSERT(b.isValidPosition(v3s16(-1,0,0)) == false); UASSERT(b.isValidPosition(v3s16(-1,-142,-2341)) == false); @@ -894,7 +1301,7 @@ struct TestMapBlock: public TestBase */ /*UASSERT(b.getSizeNodes() == v3s16(MAP_BLOCKSIZE, MAP_BLOCKSIZE, MAP_BLOCKSIZE));*/ - + // Changed flag should be initially set UASSERT(b.getModified() == MOD_STATE_WRITE_NEEDED); b.resetModified(); @@ -911,7 +1318,7 @@ struct TestMapBlock: public TestBase UASSERT(b.getNode(v3s16(x,y,z)).getLight(LIGHTBANK_DAY) == 0); UASSERT(b.getNode(v3s16(x,y,z)).getLight(LIGHTBANK_NIGHT) == 0); } - + { MapNode n(CONTENT_AIR); for(u16 z=0; zget("bind_address"); + try { + bind_addr.Resolve(bind_str.c_str()); + + if (!bind_addr.isIPv6()) { + address = bind_addr; + } + } catch (ResolveError &e) { + } - sleep_ms(50); + // IPv6 socket test + if (g_settings->getBool("enable_ipv6")) { + UDPSocket socket6; + + if (!socket6.init(true, true)) { + /* Note: Failing to create an IPv6 socket is not technically an + error because the OS may not support IPv6 or it may + have been disabled. IPv6 is not /required/ by + minetest and therefore this should not cause the unit + test to fail + */ + dstream << "WARNING: IPv6 socket creation failed (unit test)" + << std::endl; + } else { + const char sendbuffer[] = "hello world!"; + IPv6AddressBytes bytes; + bytes.bytes[15] = 1; + + socket6.Bind(address6); + + try { + socket6.Send(Address(&bytes, port), sendbuffer, sizeof(sendbuffer)); + + sleep_ms(50); + + char rcvbuffer[256] = { 0 }; + Address sender; + + for(;;) { + if (socket6.Receive(sender, rcvbuffer, sizeof(rcvbuffer )) < 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); + } + catch (SendFailedException &e) { + errorstream << "IPv6 support enabled but not available!" + << std::endl; + } + } + } - char rcvbuffer[256]; - memset(rcvbuffer, 0, sizeof(rcvbuffer)); - Address sender; - for(;;) + // IPv4 socket test { - int bytes_read = socket.Receive(sender, rcvbuffer, sizeof(rcvbuffer)); - if(bytes_read < 0) - break; + UDPSocket socket(false); + socket.Bind(address); + + const char sendbuffer[] = "hello world!"; + /* + * If there is a bind address, use it. + * It's useful in container environments + */ + if (address != Address(0, 0, 0, 0, port)) { + socket.Send(address, sendbuffer, sizeof(sendbuffer)); + } + else + socket.Send(Address(127, 0, 0 ,1, port), sendbuffer, sizeof(sendbuffer)); + + sleep_ms(50); + + char rcvbuffer[256] = { 0 }; + Address sender; + for(;;) { + if (socket.Receive(sender, rcvbuffer, sizeof(rcvbuffer)) < 0) + break; + } + //FIXME: This fails on some systems + UASSERT(strncmp(sendbuffer, rcvbuffer, sizeof(sendbuffer)) == 0); + + if (address != Address(0, 0, 0, 0, port)) { + UASSERT(sender.getAddress().sin_addr.s_addr == + address.getAddress().sin_addr.s_addr); + } + else { + 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()); } }; @@ -1330,7 +1815,7 @@ struct TestConnection: public TestBase SharedBuffer data1(1); data1[0] = 100; Address a(127,0,0,1, 10); - u16 seqnum = 34352; + const u16 seqnum = 34352; con::BufferedPacket p1 = con::makePacket(a, data1, proto_id, peer_id, channel); @@ -1347,7 +1832,7 @@ struct TestConnection: public TestBase UASSERT(readU16(&p1.data[4]) == peer_id); UASSERT(readU8(&p1.data[6]) == channel); UASSERT(readU8(&p1.data[7]) == data1[0]); - + //infostream<<"initial data1[0]="<<((u32)data1[0]&0xff)< p2 = con::makeReliablePacket(data1, seqnum); @@ -1409,28 +1894,48 @@ struct TestConnection: public TestBase Handler hand_server("server"); Handler hand_client("client"); - + + Address address(0, 0, 0, 0, 30001); + Address bind_addr(0, 0, 0, 0, 30001); + /* + * Try to use the bind_address for servers with no localhost address + * For example: FreeBSD jails + */ + std::string bind_str = g_settings->get("bind_address"); + try { + bind_addr.Resolve(bind_str.c_str()); + + if (!bind_addr.isIPv6()) { + address = bind_addr; + } + } catch (ResolveError &e) { + } + infostream<<"** Creating server Connection"< data = SharedBufferFromString("Hello World!"); + NetworkPacket* pkt = new NetworkPacket((u8*) "Hello World !", 14, 0); + + SharedBuffer sentdata = pkt->oldForgePacket(); infostream<<"** running client.Send()"< recvdata; - infostream<<"** running server.Receive()"< data1 = SharedBufferFromString("hello1"); - SharedBuffer data2 = SharedBufferFromString("Hello2"); - - Address client_address = - server.GetPeerAddress(peer_id_client); - - infostream<<"*** Sending packets in wrong order (2,1,2)" - <channels[chn]; - u16 sn = ch->next_outgoing_seqnum; - ch->next_outgoing_seqnum = sn+1; - server.Send(peer_id_client, chn, data2, true); - ch->next_outgoing_seqnum = sn; - server.Send(peer_id_client, chn, data1, true); - ch->next_outgoing_seqnum = sn+1; - server.Send(peer_id_client, chn, data2, true); - - sleep_ms(50); + infostream << "** Server received: peer_id=" << peer_id + << ", size=" << size + << ", data=" << (const char*)pkt->getU8Ptr(0) + << std::endl; - infostream<<"*** Receiving the packets"< recvdata; - u32 size; + UASSERT(memcmp(*sentdata, *recvdata, recvdata.getSize()) == 0); - infostream<<"** running client.Receive()"<getU8Ptr(0))[i])&0xff); infostream<20) infostream<<"..."; infostream< sentdata = pkt->oldForgePacket(); + + server.Send(peer_id_client, 0, pkt, true); //sleep_ms(3000); - + SharedBuffer recvdata; infostream<<"** running client.Receive()"<