test.cpp 55 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043
  1. /*
  2. Minetest
  3. Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU Lesser General Public License as published by
  6. the Free Software Foundation; either version 2.1 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU Lesser General Public License for more details.
  12. You should have received a copy of the GNU Lesser General Public License along
  13. with this program; if not, write to the Free Software Foundation, Inc.,
  14. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  15. */
  16. #include "test.h"
  17. #include "irrlichttypes_extrabloated.h"
  18. #include "debug.h"
  19. #include "map.h"
  20. #include "player.h"
  21. #include "main.h"
  22. #include "socket.h"
  23. #include "connection.h"
  24. #include "serialization.h"
  25. #include "voxel.h"
  26. #include "collision.h"
  27. #include <sstream>
  28. #include "porting.h"
  29. #include "content_mapnode.h"
  30. #include "nodedef.h"
  31. #include "mapsector.h"
  32. #include "settings.h"
  33. #include "log.h"
  34. #include "util/string.h"
  35. #include "filesys.h"
  36. #include "voxelalgorithms.h"
  37. #include "inventory.h"
  38. #include "util/numeric.h"
  39. #include "util/serialize.h"
  40. #include "noise.h" // PseudoRandom used for random data for compression
  41. #include "clientserver.h" // LATEST_PROTOCOL_VERSION
  42. #include <algorithm>
  43. /*
  44. Asserts that the exception occurs
  45. */
  46. #define EXCEPTION_CHECK(EType, code)\
  47. {\
  48. bool exception_thrown = false;\
  49. try{ code; }\
  50. catch(EType &e) { exception_thrown = true; }\
  51. UASSERT(exception_thrown);\
  52. }
  53. #define UTEST(x, fmt, ...)\
  54. {\
  55. if(!(x)){\
  56. LOGLINEF(LMT_ERROR, "Test (%s) failed: " fmt, #x, ##__VA_ARGS__);\
  57. test_failed = true;\
  58. }\
  59. }
  60. #define UASSERT(x) UTEST(x, "UASSERT")
  61. /*
  62. A few item and node definitions for those tests that need them
  63. */
  64. static content_t CONTENT_STONE;
  65. static content_t CONTENT_GRASS;
  66. static content_t CONTENT_TORCH;
  67. void define_some_nodes(IWritableItemDefManager *idef, IWritableNodeDefManager *ndef)
  68. {
  69. ItemDefinition itemdef;
  70. ContentFeatures f;
  71. /*
  72. Stone
  73. */
  74. itemdef = ItemDefinition();
  75. itemdef.type = ITEM_NODE;
  76. itemdef.name = "default:stone";
  77. itemdef.description = "Stone";
  78. itemdef.groups["cracky"] = 3;
  79. itemdef.inventory_image = "[inventorycube"
  80. "{default_stone.png"
  81. "{default_stone.png"
  82. "{default_stone.png";
  83. f = ContentFeatures();
  84. f.name = itemdef.name;
  85. for(int i = 0; i < 6; i++)
  86. f.tiledef[i].name = "default_stone.png";
  87. f.is_ground_content = true;
  88. idef->registerItem(itemdef);
  89. CONTENT_STONE = ndef->set(f.name, f);
  90. /*
  91. Grass
  92. */
  93. itemdef = ItemDefinition();
  94. itemdef.type = ITEM_NODE;
  95. itemdef.name = "default:dirt_with_grass";
  96. itemdef.description = "Dirt with grass";
  97. itemdef.groups["crumbly"] = 3;
  98. itemdef.inventory_image = "[inventorycube"
  99. "{default_grass.png"
  100. "{default_dirt.png&default_grass_side.png"
  101. "{default_dirt.png&default_grass_side.png";
  102. f = ContentFeatures();
  103. f.name = itemdef.name;
  104. f.tiledef[0].name = "default_grass.png";
  105. f.tiledef[1].name = "default_dirt.png";
  106. for(int i = 2; i < 6; i++)
  107. f.tiledef[i].name = "default_dirt.png^default_grass_side.png";
  108. f.is_ground_content = true;
  109. idef->registerItem(itemdef);
  110. CONTENT_GRASS = ndef->set(f.name, f);
  111. /*
  112. Torch (minimal definition for lighting tests)
  113. */
  114. itemdef = ItemDefinition();
  115. itemdef.type = ITEM_NODE;
  116. itemdef.name = "default:torch";
  117. f = ContentFeatures();
  118. f.name = itemdef.name;
  119. f.param_type = CPT_LIGHT;
  120. f.light_propagates = true;
  121. f.sunlight_propagates = true;
  122. f.light_source = LIGHT_MAX-1;
  123. idef->registerItem(itemdef);
  124. CONTENT_TORCH = ndef->set(f.name, f);
  125. }
  126. struct TestBase
  127. {
  128. bool test_failed;
  129. TestBase():
  130. test_failed(false)
  131. {}
  132. };
  133. struct TestUtilities: public TestBase
  134. {
  135. void Run()
  136. {
  137. /*infostream<<"wrapDegrees(100.0) = "<<wrapDegrees(100.0)<<std::endl;
  138. infostream<<"wrapDegrees(720.5) = "<<wrapDegrees(720.5)<<std::endl;
  139. infostream<<"wrapDegrees(-0.5) = "<<wrapDegrees(-0.5)<<std::endl;*/
  140. UASSERT(fabs(wrapDegrees(100.0) - 100.0) < 0.001);
  141. UASSERT(fabs(wrapDegrees(720.5) - 0.5) < 0.001);
  142. UASSERT(fabs(wrapDegrees(-0.5) - (-0.5)) < 0.001);
  143. UASSERT(fabs(wrapDegrees(-365.5) - (-5.5)) < 0.001);
  144. UASSERT(lowercase("Foo bAR") == "foo bar");
  145. UASSERT(trim("\n \t\r Foo bAR \r\n\t\t ") == "Foo bAR");
  146. UASSERT(trim("\n \t\r \r\n\t\t ") == "");
  147. UASSERT(is_yes("YeS") == true);
  148. UASSERT(is_yes("") == false);
  149. UASSERT(is_yes("FAlse") == false);
  150. UASSERT(is_yes("-1") == true);
  151. UASSERT(is_yes("0") == false);
  152. UASSERT(is_yes("1") == true);
  153. UASSERT(is_yes("2") == true);
  154. const char *ends[] = {"abc", "c", "bc", NULL};
  155. UASSERT(removeStringEnd("abc", ends) == "");
  156. UASSERT(removeStringEnd("bc", ends) == "b");
  157. UASSERT(removeStringEnd("12c", ends) == "12");
  158. UASSERT(removeStringEnd("foo", ends) == "");
  159. UASSERT(urlencode("\"Aardvarks lurk, OK?\"")
  160. == "%22Aardvarks%20lurk%2C%20OK%3F%22");
  161. UASSERT(urldecode("%22Aardvarks%20lurk%2C%20OK%3F%22")
  162. == "\"Aardvarks lurk, OK?\"");
  163. }
  164. };
  165. struct TestPath: public TestBase
  166. {
  167. // adjusts a POSIX path to system-specific conventions
  168. // -> changes '/' to DIR_DELIM
  169. // -> absolute paths start with "C:\\" on windows
  170. std::string p(std::string path)
  171. {
  172. for(size_t i = 0; i < path.size(); ++i){
  173. if(path[i] == '/'){
  174. path.replace(i, 1, DIR_DELIM);
  175. i += std::string(DIR_DELIM).size() - 1; // generally a no-op
  176. }
  177. }
  178. #ifdef _WIN32
  179. if(path[0] == '\\')
  180. path = "C:" + path;
  181. #endif
  182. return path;
  183. }
  184. void Run()
  185. {
  186. std::string path, result, removed;
  187. /*
  188. Test fs::IsDirDelimiter
  189. */
  190. UASSERT(fs::IsDirDelimiter('/') == true);
  191. UASSERT(fs::IsDirDelimiter('A') == false);
  192. UASSERT(fs::IsDirDelimiter(0) == false);
  193. #ifdef _WIN32
  194. UASSERT(fs::IsDirDelimiter('\\') == true);
  195. #else
  196. UASSERT(fs::IsDirDelimiter('\\') == false);
  197. #endif
  198. /*
  199. Test fs::PathStartsWith
  200. */
  201. {
  202. const int numpaths = 12;
  203. std::string paths[numpaths] = {
  204. "",
  205. p("/"),
  206. p("/home/user/minetest"),
  207. p("/home/user/minetest/bin"),
  208. p("/home/user/.minetest"),
  209. p("/tmp/dir/file"),
  210. p("/tmp/file/"),
  211. p("/tmP/file"),
  212. p("/tmp"),
  213. p("/tmp/dir"),
  214. p("/home/user2/minetest/worlds"),
  215. p("/home/user2/minetest/world"),
  216. };
  217. /*
  218. expected fs::PathStartsWith results
  219. 0 = returns false
  220. 1 = returns true
  221. 2 = returns false on windows, false elsewhere
  222. 3 = returns true on windows, true elsewhere
  223. 4 = returns true if and only if
  224. FILESYS_CASE_INSENSITIVE is true
  225. */
  226. int expected_results[numpaths][numpaths] = {
  227. {1,2,0,0,0,0,0,0,0,0,0,0},
  228. {1,1,0,0,0,0,0,0,0,0,0,0},
  229. {1,1,1,0,0,0,0,0,0,0,0,0},
  230. {1,1,1,1,0,0,0,0,0,0,0,0},
  231. {1,1,0,0,1,0,0,0,0,0,0,0},
  232. {1,1,0,0,0,1,0,0,1,1,0,0},
  233. {1,1,0,0,0,0,1,4,1,0,0,0},
  234. {1,1,0,0,0,0,4,1,4,0,0,0},
  235. {1,1,0,0,0,0,0,0,1,0,0,0},
  236. {1,1,0,0,0,0,0,0,1,1,0,0},
  237. {1,1,0,0,0,0,0,0,0,0,1,0},
  238. {1,1,0,0,0,0,0,0,0,0,0,1},
  239. };
  240. for (int i = 0; i < numpaths; i++)
  241. for (int j = 0; j < numpaths; j++){
  242. /*verbosestream<<"testing fs::PathStartsWith(\""
  243. <<paths[i]<<"\", \""
  244. <<paths[j]<<"\")"<<std::endl;*/
  245. bool starts = fs::PathStartsWith(paths[i], paths[j]);
  246. int expected = expected_results[i][j];
  247. if(expected == 0){
  248. UASSERT(starts == false);
  249. }
  250. else if(expected == 1){
  251. UASSERT(starts == true);
  252. }
  253. #ifdef _WIN32
  254. else if(expected == 2){
  255. UASSERT(starts == false);
  256. }
  257. else if(expected == 3){
  258. UASSERT(starts == true);
  259. }
  260. #else
  261. else if(expected == 2){
  262. UASSERT(starts == true);
  263. }
  264. else if(expected == 3){
  265. UASSERT(starts == false);
  266. }
  267. #endif
  268. else if(expected == 4){
  269. UASSERT(starts == (bool)FILESYS_CASE_INSENSITIVE);
  270. }
  271. }
  272. }
  273. /*
  274. Test fs::RemoveLastPathComponent
  275. */
  276. UASSERT(fs::RemoveLastPathComponent("") == "");
  277. path = p("/home/user/minetest/bin/..//worlds/world1");
  278. result = fs::RemoveLastPathComponent(path, &removed, 0);
  279. UASSERT(result == path);
  280. UASSERT(removed == "");
  281. result = fs::RemoveLastPathComponent(path, &removed, 1);
  282. UASSERT(result == p("/home/user/minetest/bin/..//worlds"));
  283. UASSERT(removed == p("world1"));
  284. result = fs::RemoveLastPathComponent(path, &removed, 2);
  285. UASSERT(result == p("/home/user/minetest/bin/.."));
  286. UASSERT(removed == p("worlds/world1"));
  287. result = fs::RemoveLastPathComponent(path, &removed, 3);
  288. UASSERT(result == p("/home/user/minetest/bin"));
  289. UASSERT(removed == p("../worlds/world1"));
  290. result = fs::RemoveLastPathComponent(path, &removed, 4);
  291. UASSERT(result == p("/home/user/minetest"));
  292. UASSERT(removed == p("bin/../worlds/world1"));
  293. result = fs::RemoveLastPathComponent(path, &removed, 5);
  294. UASSERT(result == p("/home/user"));
  295. UASSERT(removed == p("minetest/bin/../worlds/world1"));
  296. result = fs::RemoveLastPathComponent(path, &removed, 6);
  297. UASSERT(result == p("/home"));
  298. UASSERT(removed == p("user/minetest/bin/../worlds/world1"));
  299. result = fs::RemoveLastPathComponent(path, &removed, 7);
  300. #ifdef _WIN32
  301. UASSERT(result == "C:");
  302. #else
  303. UASSERT(result == "");
  304. #endif
  305. UASSERT(removed == p("home/user/minetest/bin/../worlds/world1"));
  306. /*
  307. Now repeat the test with a trailing delimiter
  308. */
  309. path = p("/home/user/minetest/bin/..//worlds/world1/");
  310. result = fs::RemoveLastPathComponent(path, &removed, 0);
  311. UASSERT(result == path);
  312. UASSERT(removed == "");
  313. result = fs::RemoveLastPathComponent(path, &removed, 1);
  314. UASSERT(result == p("/home/user/minetest/bin/..//worlds"));
  315. UASSERT(removed == p("world1"));
  316. result = fs::RemoveLastPathComponent(path, &removed, 2);
  317. UASSERT(result == p("/home/user/minetest/bin/.."));
  318. UASSERT(removed == p("worlds/world1"));
  319. result = fs::RemoveLastPathComponent(path, &removed, 3);
  320. UASSERT(result == p("/home/user/minetest/bin"));
  321. UASSERT(removed == p("../worlds/world1"));
  322. result = fs::RemoveLastPathComponent(path, &removed, 4);
  323. UASSERT(result == p("/home/user/minetest"));
  324. UASSERT(removed == p("bin/../worlds/world1"));
  325. result = fs::RemoveLastPathComponent(path, &removed, 5);
  326. UASSERT(result == p("/home/user"));
  327. UASSERT(removed == p("minetest/bin/../worlds/world1"));
  328. result = fs::RemoveLastPathComponent(path, &removed, 6);
  329. UASSERT(result == p("/home"));
  330. UASSERT(removed == p("user/minetest/bin/../worlds/world1"));
  331. result = fs::RemoveLastPathComponent(path, &removed, 7);
  332. #ifdef _WIN32
  333. UASSERT(result == "C:");
  334. #else
  335. UASSERT(result == "");
  336. #endif
  337. UASSERT(removed == p("home/user/minetest/bin/../worlds/world1"));
  338. /*
  339. Test fs::RemoveRelativePathComponent
  340. */
  341. path = p("/home/user/minetest/bin");
  342. result = fs::RemoveRelativePathComponents(path);
  343. UASSERT(result == path);
  344. path = p("/home/user/minetest/bin/../worlds/world1");
  345. result = fs::RemoveRelativePathComponents(path);
  346. UASSERT(result == p("/home/user/minetest/worlds/world1"));
  347. path = p("/home/user/minetest/bin/../worlds/world1/");
  348. result = fs::RemoveRelativePathComponents(path);
  349. UASSERT(result == p("/home/user/minetest/worlds/world1"));
  350. path = p(".");
  351. result = fs::RemoveRelativePathComponents(path);
  352. UASSERT(result == "");
  353. path = p("./subdir/../..");
  354. result = fs::RemoveRelativePathComponents(path);
  355. UASSERT(result == "");
  356. path = p("/a/b/c/.././../d/../e/f/g/../h/i/j/../../../..");
  357. result = fs::RemoveRelativePathComponents(path);
  358. UASSERT(result == p("/a/e"));
  359. }
  360. };
  361. struct TestSettings: public TestBase
  362. {
  363. void Run()
  364. {
  365. Settings s;
  366. // Test reading of settings
  367. s.parseConfigLine("leet = 1337");
  368. s.parseConfigLine("leetleet = 13371337");
  369. s.parseConfigLine("leetleet_neg = -13371337");
  370. s.parseConfigLine("floaty_thing = 1.1");
  371. s.parseConfigLine("stringy_thing = asd /( ¤%&(/\" BLÖÄRP");
  372. s.parseConfigLine("coord = (1, 2, 4.5)");
  373. UASSERT(s.getS32("leet") == 1337);
  374. UASSERT(s.getS16("leetleet") == 32767);
  375. UASSERT(s.getS16("leetleet_neg") == -32768);
  376. // Not sure if 1.1 is an exact value as a float, but doesn't matter
  377. UASSERT(fabs(s.getFloat("floaty_thing") - 1.1) < 0.001);
  378. UASSERT(s.get("stringy_thing") == "asd /( ¤%&(/\" BLÖÄRP");
  379. UASSERT(fabs(s.getV3F("coord").X - 1.0) < 0.001);
  380. UASSERT(fabs(s.getV3F("coord").Y - 2.0) < 0.001);
  381. UASSERT(fabs(s.getV3F("coord").Z - 4.5) < 0.001);
  382. // Test the setting of settings too
  383. s.setFloat("floaty_thing_2", 1.2);
  384. s.setV3F("coord2", v3f(1, 2, 3.3));
  385. UASSERT(s.get("floaty_thing_2").substr(0,3) == "1.2");
  386. UASSERT(fabs(s.getFloat("floaty_thing_2") - 1.2) < 0.001);
  387. UASSERT(fabs(s.getV3F("coord2").X - 1.0) < 0.001);
  388. UASSERT(fabs(s.getV3F("coord2").Y - 2.0) < 0.001);
  389. UASSERT(fabs(s.getV3F("coord2").Z - 3.3) < 0.001);
  390. }
  391. };
  392. struct TestSerialization: public TestBase
  393. {
  394. // To be used like this:
  395. // mkstr("Some\0string\0with\0embedded\0nuls")
  396. // since std::string("...") doesn't work as expected in that case.
  397. template<size_t N> std::string mkstr(const char (&s)[N])
  398. {
  399. return std::string(s, N - 1);
  400. }
  401. void Run()
  402. {
  403. // Tests some serialization primitives
  404. UASSERT(serializeString("") == mkstr("\0\0"));
  405. UASSERT(serializeWideString(L"") == mkstr("\0\0"));
  406. UASSERT(serializeLongString("") == mkstr("\0\0\0\0"));
  407. UASSERT(serializeJsonString("") == "\"\"");
  408. std::string teststring = "Hello world!";
  409. UASSERT(serializeString(teststring) ==
  410. mkstr("\0\14Hello world!"));
  411. UASSERT(serializeWideString(narrow_to_wide(teststring)) ==
  412. mkstr("\0\14\0H\0e\0l\0l\0o\0 \0w\0o\0r\0l\0d\0!"));
  413. UASSERT(serializeLongString(teststring) ==
  414. mkstr("\0\0\0\14Hello world!"));
  415. UASSERT(serializeJsonString(teststring) ==
  416. "\"Hello world!\"");
  417. std::string teststring2;
  418. std::wstring teststring2_w;
  419. std::string teststring2_w_encoded;
  420. {
  421. std::ostringstream tmp_os;
  422. std::wostringstream tmp_os_w;
  423. std::ostringstream tmp_os_w_encoded;
  424. for(int i = 0; i < 256; i++)
  425. {
  426. tmp_os<<(char)i;
  427. tmp_os_w<<(wchar_t)i;
  428. tmp_os_w_encoded<<(char)0<<(char)i;
  429. }
  430. teststring2 = tmp_os.str();
  431. teststring2_w = tmp_os_w.str();
  432. teststring2_w_encoded = tmp_os_w_encoded.str();
  433. }
  434. UASSERT(serializeString(teststring2) ==
  435. mkstr("\1\0") + teststring2);
  436. UASSERT(serializeWideString(teststring2_w) ==
  437. mkstr("\1\0") + teststring2_w_encoded);
  438. UASSERT(serializeLongString(teststring2) ==
  439. mkstr("\0\0\1\0") + teststring2);
  440. // MSVC fails when directly using "\\\\"
  441. std::string backslash = "\\";
  442. UASSERT(serializeJsonString(teststring2) ==
  443. mkstr("\"") +
  444. "\\u0000\\u0001\\u0002\\u0003\\u0004\\u0005\\u0006\\u0007" +
  445. "\\b\\t\\n\\u000b\\f\\r\\u000e\\u000f" +
  446. "\\u0010\\u0011\\u0012\\u0013\\u0014\\u0015\\u0016\\u0017" +
  447. "\\u0018\\u0019\\u001a\\u001b\\u001c\\u001d\\u001e\\u001f" +
  448. " !\\\"" + teststring2.substr(0x23, 0x2f-0x23) +
  449. "\\/" + teststring2.substr(0x30, 0x5c-0x30) +
  450. backslash + backslash + teststring2.substr(0x5d, 0x7f-0x5d) + "\\u007f" +
  451. "\\u0080\\u0081\\u0082\\u0083\\u0084\\u0085\\u0086\\u0087" +
  452. "\\u0088\\u0089\\u008a\\u008b\\u008c\\u008d\\u008e\\u008f" +
  453. "\\u0090\\u0091\\u0092\\u0093\\u0094\\u0095\\u0096\\u0097" +
  454. "\\u0098\\u0099\\u009a\\u009b\\u009c\\u009d\\u009e\\u009f" +
  455. "\\u00a0\\u00a1\\u00a2\\u00a3\\u00a4\\u00a5\\u00a6\\u00a7" +
  456. "\\u00a8\\u00a9\\u00aa\\u00ab\\u00ac\\u00ad\\u00ae\\u00af" +
  457. "\\u00b0\\u00b1\\u00b2\\u00b3\\u00b4\\u00b5\\u00b6\\u00b7" +
  458. "\\u00b8\\u00b9\\u00ba\\u00bb\\u00bc\\u00bd\\u00be\\u00bf" +
  459. "\\u00c0\\u00c1\\u00c2\\u00c3\\u00c4\\u00c5\\u00c6\\u00c7" +
  460. "\\u00c8\\u00c9\\u00ca\\u00cb\\u00cc\\u00cd\\u00ce\\u00cf" +
  461. "\\u00d0\\u00d1\\u00d2\\u00d3\\u00d4\\u00d5\\u00d6\\u00d7" +
  462. "\\u00d8\\u00d9\\u00da\\u00db\\u00dc\\u00dd\\u00de\\u00df" +
  463. "\\u00e0\\u00e1\\u00e2\\u00e3\\u00e4\\u00e5\\u00e6\\u00e7" +
  464. "\\u00e8\\u00e9\\u00ea\\u00eb\\u00ec\\u00ed\\u00ee\\u00ef" +
  465. "\\u00f0\\u00f1\\u00f2\\u00f3\\u00f4\\u00f5\\u00f6\\u00f7" +
  466. "\\u00f8\\u00f9\\u00fa\\u00fb\\u00fc\\u00fd\\u00fe\\u00ff" +
  467. "\"");
  468. {
  469. std::istringstream is(serializeString(teststring2), std::ios::binary);
  470. UASSERT(deSerializeString(is) == teststring2);
  471. UASSERT(!is.eof());
  472. is.get();
  473. UASSERT(is.eof());
  474. }
  475. {
  476. std::istringstream is(serializeWideString(teststring2_w), std::ios::binary);
  477. UASSERT(deSerializeWideString(is) == teststring2_w);
  478. UASSERT(!is.eof());
  479. is.get();
  480. UASSERT(is.eof());
  481. }
  482. {
  483. std::istringstream is(serializeLongString(teststring2), std::ios::binary);
  484. UASSERT(deSerializeLongString(is) == teststring2);
  485. UASSERT(!is.eof());
  486. is.get();
  487. UASSERT(is.eof());
  488. }
  489. {
  490. std::istringstream is(serializeJsonString(teststring2), std::ios::binary);
  491. //dstream<<serializeJsonString(deSerializeJsonString(is));
  492. UASSERT(deSerializeJsonString(is) == teststring2);
  493. UASSERT(!is.eof());
  494. is.get();
  495. UASSERT(is.eof());
  496. }
  497. }
  498. };
  499. struct TestNodedefSerialization: public TestBase
  500. {
  501. void Run()
  502. {
  503. ContentFeatures f;
  504. f.name = "default:stone";
  505. for(int i = 0; i < 6; i++)
  506. f.tiledef[i].name = "default_stone.png";
  507. f.is_ground_content = true;
  508. std::ostringstream os(std::ios::binary);
  509. f.serialize(os, LATEST_PROTOCOL_VERSION);
  510. verbosestream<<"Test ContentFeatures size: "<<os.str().size()<<std::endl;
  511. std::istringstream is(os.str(), std::ios::binary);
  512. ContentFeatures f2;
  513. f2.deSerialize(is);
  514. UASSERT(f.walkable == f2.walkable);
  515. UASSERT(f.node_box.type == f2.node_box.type);
  516. }
  517. };
  518. struct TestCompress: public TestBase
  519. {
  520. void Run()
  521. {
  522. { // ver 0
  523. SharedBuffer<u8> fromdata(4);
  524. fromdata[0]=1;
  525. fromdata[1]=5;
  526. fromdata[2]=5;
  527. fromdata[3]=1;
  528. std::ostringstream os(std::ios_base::binary);
  529. compress(fromdata, os, 0);
  530. std::string str_out = os.str();
  531. infostream<<"str_out.size()="<<str_out.size()<<std::endl;
  532. infostream<<"TestCompress: 1,5,5,1 -> ";
  533. for(u32 i=0; i<str_out.size(); i++)
  534. {
  535. infostream<<(u32)str_out[i]<<",";
  536. }
  537. infostream<<std::endl;
  538. UASSERT(str_out.size() == 10);
  539. UASSERT(str_out[0] == 0);
  540. UASSERT(str_out[1] == 0);
  541. UASSERT(str_out[2] == 0);
  542. UASSERT(str_out[3] == 4);
  543. UASSERT(str_out[4] == 0);
  544. UASSERT(str_out[5] == 1);
  545. UASSERT(str_out[6] == 1);
  546. UASSERT(str_out[7] == 5);
  547. UASSERT(str_out[8] == 0);
  548. UASSERT(str_out[9] == 1);
  549. std::istringstream is(str_out, std::ios_base::binary);
  550. std::ostringstream os2(std::ios_base::binary);
  551. decompress(is, os2, 0);
  552. std::string str_out2 = os2.str();
  553. infostream<<"decompress: ";
  554. for(u32 i=0; i<str_out2.size(); i++)
  555. {
  556. infostream<<(u32)str_out2[i]<<",";
  557. }
  558. infostream<<std::endl;
  559. UASSERT(str_out2.size() == fromdata.getSize());
  560. for(u32 i=0; i<str_out2.size(); i++)
  561. {
  562. UASSERT(str_out2[i] == fromdata[i]);
  563. }
  564. }
  565. { // ver HIGHEST
  566. SharedBuffer<u8> fromdata(4);
  567. fromdata[0]=1;
  568. fromdata[1]=5;
  569. fromdata[2]=5;
  570. fromdata[3]=1;
  571. std::ostringstream os(std::ios_base::binary);
  572. compress(fromdata, os, SER_FMT_VER_HIGHEST_READ);
  573. std::string str_out = os.str();
  574. infostream<<"str_out.size()="<<str_out.size()<<std::endl;
  575. infostream<<"TestCompress: 1,5,5,1 -> ";
  576. for(u32 i=0; i<str_out.size(); i++)
  577. {
  578. infostream<<(u32)str_out[i]<<",";
  579. }
  580. infostream<<std::endl;
  581. std::istringstream is(str_out, std::ios_base::binary);
  582. std::ostringstream os2(std::ios_base::binary);
  583. decompress(is, os2, SER_FMT_VER_HIGHEST_READ);
  584. std::string str_out2 = os2.str();
  585. infostream<<"decompress: ";
  586. for(u32 i=0; i<str_out2.size(); i++)
  587. {
  588. infostream<<(u32)str_out2[i]<<",";
  589. }
  590. infostream<<std::endl;
  591. UASSERT(str_out2.size() == fromdata.getSize());
  592. for(u32 i=0; i<str_out2.size(); i++)
  593. {
  594. UASSERT(str_out2[i] == fromdata[i]);
  595. }
  596. }
  597. // Test zlib wrapper with large amounts of data (larger than its
  598. // internal buffers)
  599. {
  600. infostream<<"Test: Testing zlib wrappers with a large amount "
  601. <<"of pseudorandom data"<<std::endl;
  602. u32 size = 50000;
  603. infostream<<"Test: Input size of large compressZlib is "
  604. <<size<<std::endl;
  605. std::string data_in;
  606. data_in.resize(size);
  607. PseudoRandom pseudorandom(9420);
  608. for(u32 i=0; i<size; i++)
  609. data_in[i] = pseudorandom.range(0,255);
  610. std::ostringstream os_compressed(std::ios::binary);
  611. compressZlib(data_in, os_compressed);
  612. infostream<<"Test: Output size of large compressZlib is "
  613. <<os_compressed.str().size()<<std::endl;
  614. std::istringstream is_compressed(os_compressed.str(), std::ios::binary);
  615. std::ostringstream os_decompressed(std::ios::binary);
  616. decompressZlib(is_compressed, os_decompressed);
  617. infostream<<"Test: Output size of large decompressZlib is "
  618. <<os_decompressed.str().size()<<std::endl;
  619. std::string str_decompressed = os_decompressed.str();
  620. UTEST(str_decompressed.size() == data_in.size(), "Output size not"
  621. " equal (output: %u, input: %u)",
  622. (unsigned int)str_decompressed.size(), (unsigned int)data_in.size());
  623. for(u32 i=0; i<size && i<str_decompressed.size(); i++){
  624. UTEST(str_decompressed[i] == data_in[i],
  625. "index out[%i]=%i differs from in[%i]=%i",
  626. i, str_decompressed[i], i, data_in[i]);
  627. }
  628. }
  629. }
  630. };
  631. struct TestMapNode: public TestBase
  632. {
  633. void Run(INodeDefManager *nodedef)
  634. {
  635. MapNode n;
  636. // Default values
  637. UASSERT(n.getContent() == CONTENT_AIR);
  638. UASSERT(n.getLight(LIGHTBANK_DAY, nodedef) == 0);
  639. UASSERT(n.getLight(LIGHTBANK_NIGHT, nodedef) == 0);
  640. // Transparency
  641. n.setContent(CONTENT_AIR);
  642. UASSERT(nodedef->get(n).light_propagates == true);
  643. n.setContent(LEGN(nodedef, "CONTENT_STONE"));
  644. UASSERT(nodedef->get(n).light_propagates == false);
  645. }
  646. };
  647. struct TestVoxelManipulator: public TestBase
  648. {
  649. void Run(INodeDefManager *nodedef)
  650. {
  651. /*
  652. VoxelArea
  653. */
  654. VoxelArea a(v3s16(-1,-1,-1), v3s16(1,1,1));
  655. UASSERT(a.index(0,0,0) == 1*3*3 + 1*3 + 1);
  656. UASSERT(a.index(-1,-1,-1) == 0);
  657. VoxelArea c(v3s16(-2,-2,-2), v3s16(2,2,2));
  658. // An area that is 1 bigger in x+ and z-
  659. VoxelArea d(v3s16(-2,-2,-3), v3s16(3,2,2));
  660. std::list<VoxelArea> aa;
  661. d.diff(c, aa);
  662. // Correct results
  663. std::vector<VoxelArea> results;
  664. results.push_back(VoxelArea(v3s16(-2,-2,-3),v3s16(3,2,-3)));
  665. results.push_back(VoxelArea(v3s16(3,-2,-2),v3s16(3,2,2)));
  666. UASSERT(aa.size() == results.size());
  667. infostream<<"Result of diff:"<<std::endl;
  668. for(std::list<VoxelArea>::const_iterator
  669. i = aa.begin(); i != aa.end(); ++i)
  670. {
  671. i->print(infostream);
  672. infostream<<std::endl;
  673. std::vector<VoxelArea>::iterator j = std::find(results.begin(), results.end(), *i);
  674. UASSERT(j != results.end());
  675. results.erase(j);
  676. }
  677. /*
  678. VoxelManipulator
  679. */
  680. VoxelManipulator v;
  681. v.print(infostream, nodedef);
  682. infostream<<"*** Setting (-1,0,-1)=2 ***"<<std::endl;
  683. v.setNodeNoRef(v3s16(-1,0,-1), MapNode(CONTENT_GRASS));
  684. v.print(infostream, nodedef);
  685. UASSERT(v.getNode(v3s16(-1,0,-1)).getContent() == CONTENT_GRASS);
  686. infostream<<"*** Reading from inexistent (0,0,-1) ***"<<std::endl;
  687. EXCEPTION_CHECK(InvalidPositionException, v.getNode(v3s16(0,0,-1)));
  688. v.print(infostream, nodedef);
  689. infostream<<"*** Adding area ***"<<std::endl;
  690. v.addArea(a);
  691. v.print(infostream, nodedef);
  692. UASSERT(v.getNode(v3s16(-1,0,-1)).getContent() == CONTENT_GRASS);
  693. EXCEPTION_CHECK(InvalidPositionException, v.getNode(v3s16(0,1,1)));
  694. }
  695. };
  696. struct TestVoxelAlgorithms: public TestBase
  697. {
  698. void Run(INodeDefManager *ndef)
  699. {
  700. /*
  701. voxalgo::propagateSunlight
  702. */
  703. {
  704. VoxelManipulator v;
  705. for(u16 z=0; z<3; z++)
  706. for(u16 y=0; y<3; y++)
  707. for(u16 x=0; x<3; x++)
  708. {
  709. v3s16 p(x,y,z);
  710. v.setNodeNoRef(p, MapNode(CONTENT_AIR));
  711. }
  712. VoxelArea a(v3s16(0,0,0), v3s16(2,2,2));
  713. {
  714. std::set<v3s16> light_sources;
  715. voxalgo::setLight(v, a, 0, ndef);
  716. voxalgo::SunlightPropagateResult res = voxalgo::propagateSunlight(
  717. v, a, true, light_sources, ndef);
  718. //v.print(dstream, ndef, VOXELPRINT_LIGHT_DAY);
  719. UASSERT(res.bottom_sunlight_valid == true);
  720. UASSERT(v.getNode(v3s16(1,1,1)).getLight(LIGHTBANK_DAY, ndef)
  721. == LIGHT_SUN);
  722. }
  723. v.setNodeNoRef(v3s16(0,0,0), MapNode(CONTENT_STONE));
  724. {
  725. std::set<v3s16> light_sources;
  726. voxalgo::setLight(v, a, 0, ndef);
  727. voxalgo::SunlightPropagateResult res = voxalgo::propagateSunlight(
  728. v, a, true, light_sources, ndef);
  729. UASSERT(res.bottom_sunlight_valid == true);
  730. UASSERT(v.getNode(v3s16(1,1,1)).getLight(LIGHTBANK_DAY, ndef)
  731. == LIGHT_SUN);
  732. }
  733. {
  734. std::set<v3s16> light_sources;
  735. voxalgo::setLight(v, a, 0, ndef);
  736. voxalgo::SunlightPropagateResult res = voxalgo::propagateSunlight(
  737. v, a, false, light_sources, ndef);
  738. UASSERT(res.bottom_sunlight_valid == true);
  739. UASSERT(v.getNode(v3s16(2,0,2)).getLight(LIGHTBANK_DAY, ndef)
  740. == 0);
  741. }
  742. v.setNodeNoRef(v3s16(1,3,2), MapNode(CONTENT_STONE));
  743. {
  744. std::set<v3s16> light_sources;
  745. voxalgo::setLight(v, a, 0, ndef);
  746. voxalgo::SunlightPropagateResult res = voxalgo::propagateSunlight(
  747. v, a, true, light_sources, ndef);
  748. UASSERT(res.bottom_sunlight_valid == true);
  749. UASSERT(v.getNode(v3s16(1,1,2)).getLight(LIGHTBANK_DAY, ndef)
  750. == 0);
  751. }
  752. {
  753. std::set<v3s16> light_sources;
  754. voxalgo::setLight(v, a, 0, ndef);
  755. voxalgo::SunlightPropagateResult res = voxalgo::propagateSunlight(
  756. v, a, false, light_sources, ndef);
  757. UASSERT(res.bottom_sunlight_valid == true);
  758. UASSERT(v.getNode(v3s16(1,0,2)).getLight(LIGHTBANK_DAY, ndef)
  759. == 0);
  760. }
  761. {
  762. MapNode n(CONTENT_AIR);
  763. n.setLight(LIGHTBANK_DAY, 10, ndef);
  764. v.setNodeNoRef(v3s16(1,-1,2), n);
  765. }
  766. {
  767. std::set<v3s16> light_sources;
  768. voxalgo::setLight(v, a, 0, ndef);
  769. voxalgo::SunlightPropagateResult res = voxalgo::propagateSunlight(
  770. v, a, true, light_sources, ndef);
  771. UASSERT(res.bottom_sunlight_valid == true);
  772. }
  773. {
  774. std::set<v3s16> light_sources;
  775. voxalgo::setLight(v, a, 0, ndef);
  776. voxalgo::SunlightPropagateResult res = voxalgo::propagateSunlight(
  777. v, a, false, light_sources, ndef);
  778. UASSERT(res.bottom_sunlight_valid == true);
  779. }
  780. {
  781. MapNode n(CONTENT_AIR);
  782. n.setLight(LIGHTBANK_DAY, LIGHT_SUN, ndef);
  783. v.setNodeNoRef(v3s16(1,-1,2), n);
  784. }
  785. {
  786. std::set<v3s16> light_sources;
  787. voxalgo::setLight(v, a, 0, ndef);
  788. voxalgo::SunlightPropagateResult res = voxalgo::propagateSunlight(
  789. v, a, true, light_sources, ndef);
  790. UASSERT(res.bottom_sunlight_valid == false);
  791. }
  792. {
  793. std::set<v3s16> light_sources;
  794. voxalgo::setLight(v, a, 0, ndef);
  795. voxalgo::SunlightPropagateResult res = voxalgo::propagateSunlight(
  796. v, a, false, light_sources, ndef);
  797. UASSERT(res.bottom_sunlight_valid == false);
  798. }
  799. v.setNodeNoRef(v3s16(1,3,2), MapNode(CONTENT_IGNORE));
  800. {
  801. std::set<v3s16> light_sources;
  802. voxalgo::setLight(v, a, 0, ndef);
  803. voxalgo::SunlightPropagateResult res = voxalgo::propagateSunlight(
  804. v, a, true, light_sources, ndef);
  805. UASSERT(res.bottom_sunlight_valid == true);
  806. }
  807. }
  808. /*
  809. voxalgo::clearLightAndCollectSources
  810. */
  811. {
  812. VoxelManipulator v;
  813. for(u16 z=0; z<3; z++)
  814. for(u16 y=0; y<3; y++)
  815. for(u16 x=0; x<3; x++)
  816. {
  817. v3s16 p(x,y,z);
  818. v.setNode(p, MapNode(CONTENT_AIR));
  819. }
  820. VoxelArea a(v3s16(0,0,0), v3s16(2,2,2));
  821. v.setNodeNoRef(v3s16(0,0,0), MapNode(CONTENT_STONE));
  822. v.setNodeNoRef(v3s16(1,1,1), MapNode(CONTENT_TORCH));
  823. {
  824. MapNode n(CONTENT_AIR);
  825. n.setLight(LIGHTBANK_DAY, 1, ndef);
  826. v.setNode(v3s16(1,1,2), n);
  827. }
  828. {
  829. std::set<v3s16> light_sources;
  830. std::map<v3s16, u8> unlight_from;
  831. voxalgo::clearLightAndCollectSources(v, a, LIGHTBANK_DAY,
  832. ndef, light_sources, unlight_from);
  833. //v.print(dstream, ndef, VOXELPRINT_LIGHT_DAY);
  834. UASSERT(v.getNode(v3s16(0,1,1)).getLight(LIGHTBANK_DAY, ndef)
  835. == 0);
  836. UASSERT(light_sources.find(v3s16(1,1,1)) != light_sources.end());
  837. UASSERT(light_sources.size() == 1);
  838. UASSERT(unlight_from.find(v3s16(1,1,2)) != unlight_from.end());
  839. UASSERT(unlight_from.size() == 1);
  840. }
  841. }
  842. }
  843. };
  844. struct TestInventory: public TestBase
  845. {
  846. void Run(IItemDefManager *idef)
  847. {
  848. std::string serialized_inventory =
  849. "List 0 32\n"
  850. "Width 3\n"
  851. "Empty\n"
  852. "Empty\n"
  853. "Empty\n"
  854. "Empty\n"
  855. "Empty\n"
  856. "Empty\n"
  857. "Empty\n"
  858. "Empty\n"
  859. "Empty\n"
  860. "Item default:cobble 61\n"
  861. "Empty\n"
  862. "Empty\n"
  863. "Empty\n"
  864. "Empty\n"
  865. "Empty\n"
  866. "Empty\n"
  867. "Item default:dirt 71\n"
  868. "Empty\n"
  869. "Empty\n"
  870. "Empty\n"
  871. "Empty\n"
  872. "Empty\n"
  873. "Empty\n"
  874. "Empty\n"
  875. "Item default:dirt 99\n"
  876. "Item default:cobble 38\n"
  877. "Empty\n"
  878. "Empty\n"
  879. "Empty\n"
  880. "Empty\n"
  881. "Empty\n"
  882. "Empty\n"
  883. "EndInventoryList\n"
  884. "EndInventory\n";
  885. std::string serialized_inventory_2 =
  886. "List main 32\n"
  887. "Width 5\n"
  888. "Empty\n"
  889. "Empty\n"
  890. "Empty\n"
  891. "Empty\n"
  892. "Empty\n"
  893. "Empty\n"
  894. "Empty\n"
  895. "Empty\n"
  896. "Empty\n"
  897. "Item default:cobble 61\n"
  898. "Empty\n"
  899. "Empty\n"
  900. "Empty\n"
  901. "Empty\n"
  902. "Empty\n"
  903. "Empty\n"
  904. "Item default:dirt 71\n"
  905. "Empty\n"
  906. "Empty\n"
  907. "Empty\n"
  908. "Empty\n"
  909. "Empty\n"
  910. "Empty\n"
  911. "Empty\n"
  912. "Item default:dirt 99\n"
  913. "Item default:cobble 38\n"
  914. "Empty\n"
  915. "Empty\n"
  916. "Empty\n"
  917. "Empty\n"
  918. "Empty\n"
  919. "Empty\n"
  920. "EndInventoryList\n"
  921. "EndInventory\n";
  922. Inventory inv(idef);
  923. std::istringstream is(serialized_inventory, std::ios::binary);
  924. inv.deSerialize(is);
  925. UASSERT(inv.getList("0"));
  926. UASSERT(!inv.getList("main"));
  927. inv.getList("0")->setName("main");
  928. UASSERT(!inv.getList("0"));
  929. UASSERT(inv.getList("main"));
  930. UASSERT(inv.getList("main")->getWidth() == 3);
  931. inv.getList("main")->setWidth(5);
  932. std::ostringstream inv_os(std::ios::binary);
  933. inv.serialize(inv_os);
  934. UASSERT(inv_os.str() == serialized_inventory_2);
  935. }
  936. };
  937. /*
  938. NOTE: These tests became non-working then NodeContainer was removed.
  939. These should be redone, utilizing some kind of a virtual
  940. interface for Map (IMap would be fine).
  941. */
  942. #if 0
  943. struct TestMapBlock: public TestBase
  944. {
  945. class TC : public NodeContainer
  946. {
  947. public:
  948. MapNode node;
  949. bool position_valid;
  950. core::list<v3s16> validity_exceptions;
  951. TC()
  952. {
  953. position_valid = true;
  954. }
  955. virtual bool isValidPosition(v3s16 p)
  956. {
  957. //return position_valid ^ (p==position_valid_exception);
  958. bool exception = false;
  959. for(core::list<v3s16>::Iterator i=validity_exceptions.begin();
  960. i != validity_exceptions.end(); i++)
  961. {
  962. if(p == *i)
  963. {
  964. exception = true;
  965. break;
  966. }
  967. }
  968. return exception ? !position_valid : position_valid;
  969. }
  970. virtual MapNode getNode(v3s16 p)
  971. {
  972. if(isValidPosition(p) == false)
  973. throw InvalidPositionException();
  974. return node;
  975. }
  976. virtual void setNode(v3s16 p, MapNode & n)
  977. {
  978. if(isValidPosition(p) == false)
  979. throw InvalidPositionException();
  980. };
  981. virtual u16 nodeContainerId() const
  982. {
  983. return 666;
  984. }
  985. };
  986. void Run()
  987. {
  988. TC parent;
  989. MapBlock b(&parent, v3s16(1,1,1));
  990. v3s16 relpos(MAP_BLOCKSIZE, MAP_BLOCKSIZE, MAP_BLOCKSIZE);
  991. UASSERT(b.getPosRelative() == relpos);
  992. UASSERT(b.getBox().MinEdge.X == MAP_BLOCKSIZE);
  993. UASSERT(b.getBox().MaxEdge.X == MAP_BLOCKSIZE*2-1);
  994. UASSERT(b.getBox().MinEdge.Y == MAP_BLOCKSIZE);
  995. UASSERT(b.getBox().MaxEdge.Y == MAP_BLOCKSIZE*2-1);
  996. UASSERT(b.getBox().MinEdge.Z == MAP_BLOCKSIZE);
  997. UASSERT(b.getBox().MaxEdge.Z == MAP_BLOCKSIZE*2-1);
  998. UASSERT(b.isValidPosition(v3s16(0,0,0)) == true);
  999. UASSERT(b.isValidPosition(v3s16(-1,0,0)) == false);
  1000. UASSERT(b.isValidPosition(v3s16(-1,-142,-2341)) == false);
  1001. UASSERT(b.isValidPosition(v3s16(-124,142,2341)) == false);
  1002. UASSERT(b.isValidPosition(v3s16(MAP_BLOCKSIZE-1,MAP_BLOCKSIZE-1,MAP_BLOCKSIZE-1)) == true);
  1003. UASSERT(b.isValidPosition(v3s16(MAP_BLOCKSIZE-1,MAP_BLOCKSIZE,MAP_BLOCKSIZE-1)) == false);
  1004. /*
  1005. TODO: this method should probably be removed
  1006. if the block size isn't going to be set variable
  1007. */
  1008. /*UASSERT(b.getSizeNodes() == v3s16(MAP_BLOCKSIZE,
  1009. MAP_BLOCKSIZE, MAP_BLOCKSIZE));*/
  1010. // Changed flag should be initially set
  1011. UASSERT(b.getModified() == MOD_STATE_WRITE_NEEDED);
  1012. b.resetModified();
  1013. UASSERT(b.getModified() == MOD_STATE_CLEAN);
  1014. // All nodes should have been set to
  1015. // .d=CONTENT_IGNORE and .getLight() = 0
  1016. for(u16 z=0; z<MAP_BLOCKSIZE; z++)
  1017. for(u16 y=0; y<MAP_BLOCKSIZE; y++)
  1018. for(u16 x=0; x<MAP_BLOCKSIZE; x++)
  1019. {
  1020. //UASSERT(b.getNode(v3s16(x,y,z)).getContent() == CONTENT_AIR);
  1021. UASSERT(b.getNode(v3s16(x,y,z)).getContent() == CONTENT_IGNORE);
  1022. UASSERT(b.getNode(v3s16(x,y,z)).getLight(LIGHTBANK_DAY) == 0);
  1023. UASSERT(b.getNode(v3s16(x,y,z)).getLight(LIGHTBANK_NIGHT) == 0);
  1024. }
  1025. {
  1026. MapNode n(CONTENT_AIR);
  1027. for(u16 z=0; z<MAP_BLOCKSIZE; z++)
  1028. for(u16 y=0; y<MAP_BLOCKSIZE; y++)
  1029. for(u16 x=0; x<MAP_BLOCKSIZE; x++)
  1030. {
  1031. b.setNode(v3s16(x,y,z), n);
  1032. }
  1033. }
  1034. /*
  1035. Parent fetch functions
  1036. */
  1037. parent.position_valid = false;
  1038. parent.node.setContent(5);
  1039. MapNode n;
  1040. // Positions in the block should still be valid
  1041. UASSERT(b.isValidPositionParent(v3s16(0,0,0)) == true);
  1042. UASSERT(b.isValidPositionParent(v3s16(MAP_BLOCKSIZE-1,MAP_BLOCKSIZE-1,MAP_BLOCKSIZE-1)) == true);
  1043. n = b.getNodeParent(v3s16(0,MAP_BLOCKSIZE-1,0));
  1044. UASSERT(n.getContent() == CONTENT_AIR);
  1045. // ...but outside the block they should be invalid
  1046. UASSERT(b.isValidPositionParent(v3s16(-121,2341,0)) == false);
  1047. UASSERT(b.isValidPositionParent(v3s16(-1,0,0)) == false);
  1048. UASSERT(b.isValidPositionParent(v3s16(MAP_BLOCKSIZE-1,MAP_BLOCKSIZE-1,MAP_BLOCKSIZE)) == false);
  1049. {
  1050. bool exception_thrown = false;
  1051. try{
  1052. // This should throw an exception
  1053. MapNode n = b.getNodeParent(v3s16(0,0,-1));
  1054. }
  1055. catch(InvalidPositionException &e)
  1056. {
  1057. exception_thrown = true;
  1058. }
  1059. UASSERT(exception_thrown);
  1060. }
  1061. parent.position_valid = true;
  1062. // Now the positions outside should be valid
  1063. UASSERT(b.isValidPositionParent(v3s16(-121,2341,0)) == true);
  1064. UASSERT(b.isValidPositionParent(v3s16(-1,0,0)) == true);
  1065. UASSERT(b.isValidPositionParent(v3s16(MAP_BLOCKSIZE-1,MAP_BLOCKSIZE-1,MAP_BLOCKSIZE)) == true);
  1066. n = b.getNodeParent(v3s16(0,0,MAP_BLOCKSIZE));
  1067. UASSERT(n.getContent() == 5);
  1068. /*
  1069. Set a node
  1070. */
  1071. v3s16 p(1,2,0);
  1072. n.setContent(4);
  1073. b.setNode(p, n);
  1074. UASSERT(b.getNode(p).getContent() == 4);
  1075. //TODO: Update to new system
  1076. /*UASSERT(b.getNodeTile(p) == 4);
  1077. UASSERT(b.getNodeTile(v3s16(-1,-1,0)) == 5);*/
  1078. /*
  1079. propagateSunlight()
  1080. */
  1081. // Set lighting of all nodes to 0
  1082. for(u16 z=0; z<MAP_BLOCKSIZE; z++){
  1083. for(u16 y=0; y<MAP_BLOCKSIZE; y++){
  1084. for(u16 x=0; x<MAP_BLOCKSIZE; x++){
  1085. MapNode n = b.getNode(v3s16(x,y,z));
  1086. n.setLight(LIGHTBANK_DAY, 0);
  1087. n.setLight(LIGHTBANK_NIGHT, 0);
  1088. b.setNode(v3s16(x,y,z), n);
  1089. }
  1090. }
  1091. }
  1092. {
  1093. /*
  1094. Check how the block handles being a lonely sky block
  1095. */
  1096. parent.position_valid = true;
  1097. b.setIsUnderground(false);
  1098. parent.node.setContent(CONTENT_AIR);
  1099. parent.node.setLight(LIGHTBANK_DAY, LIGHT_SUN);
  1100. parent.node.setLight(LIGHTBANK_NIGHT, 0);
  1101. core::map<v3s16, bool> light_sources;
  1102. // The bottom block is invalid, because we have a shadowing node
  1103. UASSERT(b.propagateSunlight(light_sources) == false);
  1104. UASSERT(b.getNode(v3s16(1,4,0)).getLight(LIGHTBANK_DAY) == LIGHT_SUN);
  1105. UASSERT(b.getNode(v3s16(1,3,0)).getLight(LIGHTBANK_DAY) == LIGHT_SUN);
  1106. UASSERT(b.getNode(v3s16(1,2,0)).getLight(LIGHTBANK_DAY) == 0);
  1107. UASSERT(b.getNode(v3s16(1,1,0)).getLight(LIGHTBANK_DAY) == 0);
  1108. UASSERT(b.getNode(v3s16(1,0,0)).getLight(LIGHTBANK_DAY) == 0);
  1109. UASSERT(b.getNode(v3s16(1,2,3)).getLight(LIGHTBANK_DAY) == LIGHT_SUN);
  1110. UASSERT(b.getFaceLight2(1000, p, v3s16(0,1,0)) == LIGHT_SUN);
  1111. UASSERT(b.getFaceLight2(1000, p, v3s16(0,-1,0)) == 0);
  1112. UASSERT(b.getFaceLight2(0, p, v3s16(0,-1,0)) == 0);
  1113. // According to MapBlock::getFaceLight,
  1114. // The face on the z+ side should have double-diminished light
  1115. //UASSERT(b.getFaceLight(p, v3s16(0,0,1)) == diminish_light(diminish_light(LIGHT_MAX)));
  1116. // The face on the z+ side should have diminished light
  1117. UASSERT(b.getFaceLight2(1000, p, v3s16(0,0,1)) == diminish_light(LIGHT_MAX));
  1118. }
  1119. /*
  1120. Check how the block handles being in between blocks with some non-sunlight
  1121. while being underground
  1122. */
  1123. {
  1124. // Make neighbours to exist and set some non-sunlight to them
  1125. parent.position_valid = true;
  1126. b.setIsUnderground(true);
  1127. parent.node.setLight(LIGHTBANK_DAY, LIGHT_MAX/2);
  1128. core::map<v3s16, bool> light_sources;
  1129. // The block below should be valid because there shouldn't be
  1130. // sunlight in there either
  1131. UASSERT(b.propagateSunlight(light_sources, true) == true);
  1132. // Should not touch nodes that are not affected (that is, all of them)
  1133. //UASSERT(b.getNode(v3s16(1,2,3)).getLight() == LIGHT_SUN);
  1134. // Should set light of non-sunlighted blocks to 0.
  1135. UASSERT(b.getNode(v3s16(1,2,3)).getLight(LIGHTBANK_DAY) == 0);
  1136. }
  1137. /*
  1138. Set up a situation where:
  1139. - There is only air in this block
  1140. - There is a valid non-sunlighted block at the bottom, and
  1141. - Invalid blocks elsewhere.
  1142. - the block is not underground.
  1143. This should result in bottom block invalidity
  1144. */
  1145. {
  1146. b.setIsUnderground(false);
  1147. // Clear block
  1148. for(u16 z=0; z<MAP_BLOCKSIZE; z++){
  1149. for(u16 y=0; y<MAP_BLOCKSIZE; y++){
  1150. for(u16 x=0; x<MAP_BLOCKSIZE; x++){
  1151. MapNode n;
  1152. n.setContent(CONTENT_AIR);
  1153. n.setLight(LIGHTBANK_DAY, 0);
  1154. b.setNode(v3s16(x,y,z), n);
  1155. }
  1156. }
  1157. }
  1158. // Make neighbours invalid
  1159. parent.position_valid = false;
  1160. // Add exceptions to the top of the bottom block
  1161. for(u16 x=0; x<MAP_BLOCKSIZE; x++)
  1162. for(u16 z=0; z<MAP_BLOCKSIZE; z++)
  1163. {
  1164. parent.validity_exceptions.push_back(v3s16(MAP_BLOCKSIZE+x, MAP_BLOCKSIZE-1, MAP_BLOCKSIZE+z));
  1165. }
  1166. // Lighting value for the valid nodes
  1167. parent.node.setLight(LIGHTBANK_DAY, LIGHT_MAX/2);
  1168. core::map<v3s16, bool> light_sources;
  1169. // Bottom block is not valid
  1170. UASSERT(b.propagateSunlight(light_sources) == false);
  1171. }
  1172. }
  1173. };
  1174. struct TestMapSector: public TestBase
  1175. {
  1176. class TC : public NodeContainer
  1177. {
  1178. public:
  1179. MapNode node;
  1180. bool position_valid;
  1181. TC()
  1182. {
  1183. position_valid = true;
  1184. }
  1185. virtual bool isValidPosition(v3s16 p)
  1186. {
  1187. return position_valid;
  1188. }
  1189. virtual MapNode getNode(v3s16 p)
  1190. {
  1191. if(position_valid == false)
  1192. throw InvalidPositionException();
  1193. return node;
  1194. }
  1195. virtual void setNode(v3s16 p, MapNode & n)
  1196. {
  1197. if(position_valid == false)
  1198. throw InvalidPositionException();
  1199. };
  1200. virtual u16 nodeContainerId() const
  1201. {
  1202. return 666;
  1203. }
  1204. };
  1205. void Run()
  1206. {
  1207. TC parent;
  1208. parent.position_valid = false;
  1209. // Create one with no heightmaps
  1210. ServerMapSector sector(&parent, v2s16(1,1));
  1211. UASSERT(sector.getBlockNoCreateNoEx(0) == 0);
  1212. UASSERT(sector.getBlockNoCreateNoEx(1) == 0);
  1213. MapBlock * bref = sector.createBlankBlock(-2);
  1214. UASSERT(sector.getBlockNoCreateNoEx(0) == 0);
  1215. UASSERT(sector.getBlockNoCreateNoEx(-2) == bref);
  1216. //TODO: Check for AlreadyExistsException
  1217. /*bool exception_thrown = false;
  1218. try{
  1219. sector.getBlock(0);
  1220. }
  1221. catch(InvalidPositionException &e){
  1222. exception_thrown = true;
  1223. }
  1224. UASSERT(exception_thrown);*/
  1225. }
  1226. };
  1227. #endif
  1228. struct TestCollision: public TestBase
  1229. {
  1230. void Run()
  1231. {
  1232. /*
  1233. axisAlignedCollision
  1234. */
  1235. for(s16 bx = -3; bx <= 3; bx++)
  1236. for(s16 by = -3; by <= 3; by++)
  1237. for(s16 bz = -3; bz <= 3; bz++)
  1238. {
  1239. // X-
  1240. {
  1241. aabb3f s(bx, by, bz, bx+1, by+1, bz+1);
  1242. aabb3f m(bx-2, by, bz, bx-1, by+1, bz+1);
  1243. v3f v(1, 0, 0);
  1244. f32 dtime = 0;
  1245. UASSERT(axisAlignedCollision(s, m, v, 0, dtime) == 0);
  1246. UASSERT(fabs(dtime - 1.000) < 0.001);
  1247. }
  1248. {
  1249. aabb3f s(bx, by, bz, bx+1, by+1, bz+1);
  1250. aabb3f m(bx-2, by, bz, bx-1, by+1, bz+1);
  1251. v3f v(-1, 0, 0);
  1252. f32 dtime = 0;
  1253. UASSERT(axisAlignedCollision(s, m, v, 0, dtime) == -1);
  1254. }
  1255. {
  1256. aabb3f s(bx, by, bz, bx+1, by+1, bz+1);
  1257. aabb3f m(bx-2, by+1.5, bz, bx-1, by+2.5, bz-1);
  1258. v3f v(1, 0, 0);
  1259. f32 dtime;
  1260. UASSERT(axisAlignedCollision(s, m, v, 0, dtime) == -1);
  1261. }
  1262. {
  1263. aabb3f s(bx, by, bz, bx+1, by+1, bz+1);
  1264. aabb3f m(bx-2, by-1.5, bz, bx-1.5, by+0.5, bz+1);
  1265. v3f v(0.5, 0.1, 0);
  1266. f32 dtime;
  1267. UASSERT(axisAlignedCollision(s, m, v, 0, dtime) == 0);
  1268. UASSERT(fabs(dtime - 3.000) < 0.001);
  1269. }
  1270. {
  1271. aabb3f s(bx, by, bz, bx+1, by+1, bz+1);
  1272. aabb3f m(bx-2, by-1.5, bz, bx-1.5, by+0.5, bz+1);
  1273. v3f v(0.5, 0.1, 0);
  1274. f32 dtime;
  1275. UASSERT(axisAlignedCollision(s, m, v, 0, dtime) == 0);
  1276. UASSERT(fabs(dtime - 3.000) < 0.001);
  1277. }
  1278. // X+
  1279. {
  1280. aabb3f s(bx, by, bz, bx+1, by+1, bz+1);
  1281. aabb3f m(bx+2, by, bz, bx+3, by+1, bz+1);
  1282. v3f v(-1, 0, 0);
  1283. f32 dtime;
  1284. UASSERT(axisAlignedCollision(s, m, v, 0, dtime) == 0);
  1285. UASSERT(fabs(dtime - 1.000) < 0.001);
  1286. }
  1287. {
  1288. aabb3f s(bx, by, bz, bx+1, by+1, bz+1);
  1289. aabb3f m(bx+2, by, bz, bx+3, by+1, bz+1);
  1290. v3f v(1, 0, 0);
  1291. f32 dtime;
  1292. UASSERT(axisAlignedCollision(s, m, v, 0, dtime) == -1);
  1293. }
  1294. {
  1295. aabb3f s(bx, by, bz, bx+1, by+1, bz+1);
  1296. aabb3f m(bx+2, by, bz+1.5, bx+3, by+1, bz+3.5);
  1297. v3f v(-1, 0, 0);
  1298. f32 dtime;
  1299. UASSERT(axisAlignedCollision(s, m, v, 0, dtime) == -1);
  1300. }
  1301. {
  1302. aabb3f s(bx, by, bz, bx+1, by+1, bz+1);
  1303. aabb3f m(bx+2, by-1.5, bz, bx+2.5, by-0.5, bz+1);
  1304. v3f v(-0.5, 0.2, 0);
  1305. f32 dtime;
  1306. UASSERT(axisAlignedCollision(s, m, v, 0, dtime) == 1); // Y, not X!
  1307. UASSERT(fabs(dtime - 2.500) < 0.001);
  1308. }
  1309. {
  1310. aabb3f s(bx, by, bz, bx+1, by+1, bz+1);
  1311. aabb3f m(bx+2, by-1.5, bz, bx+2.5, by-0.5, bz+1);
  1312. v3f v(-0.5, 0.3, 0);
  1313. f32 dtime;
  1314. UASSERT(axisAlignedCollision(s, m, v, 0, dtime) == 0);
  1315. UASSERT(fabs(dtime - 2.000) < 0.001);
  1316. }
  1317. // TODO: Y-, Y+, Z-, Z+
  1318. // misc
  1319. {
  1320. aabb3f s(bx, by, bz, bx+2, by+2, bz+2);
  1321. aabb3f m(bx+2.3, by+2.29, bz+2.29, bx+4.2, by+4.2, bz+4.2);
  1322. v3f v(-1./3, -1./3, -1./3);
  1323. f32 dtime;
  1324. UASSERT(axisAlignedCollision(s, m, v, 0, dtime) == 0);
  1325. UASSERT(fabs(dtime - 0.9) < 0.001);
  1326. }
  1327. {
  1328. aabb3f s(bx, by, bz, bx+2, by+2, bz+2);
  1329. aabb3f m(bx+2.29, by+2.3, bz+2.29, bx+4.2, by+4.2, bz+4.2);
  1330. v3f v(-1./3, -1./3, -1./3);
  1331. f32 dtime;
  1332. UASSERT(axisAlignedCollision(s, m, v, 0, dtime) == 1);
  1333. UASSERT(fabs(dtime - 0.9) < 0.001);
  1334. }
  1335. {
  1336. aabb3f s(bx, by, bz, bx+2, by+2, bz+2);
  1337. aabb3f m(bx+2.29, by+2.29, bz+2.3, bx+4.2, by+4.2, bz+4.2);
  1338. v3f v(-1./3, -1./3, -1./3);
  1339. f32 dtime;
  1340. UASSERT(axisAlignedCollision(s, m, v, 0, dtime) == 2);
  1341. UASSERT(fabs(dtime - 0.9) < 0.001);
  1342. }
  1343. {
  1344. aabb3f s(bx, by, bz, bx+2, by+2, bz+2);
  1345. aabb3f m(bx-4.2, by-4.2, bz-4.2, bx-2.3, by-2.29, bz-2.29);
  1346. v3f v(1./7, 1./7, 1./7);
  1347. f32 dtime;
  1348. UASSERT(axisAlignedCollision(s, m, v, 0, dtime) == 0);
  1349. UASSERT(fabs(dtime - 16.1) < 0.001);
  1350. }
  1351. {
  1352. aabb3f s(bx, by, bz, bx+2, by+2, bz+2);
  1353. aabb3f m(bx-4.2, by-4.2, bz-4.2, bx-2.29, by-2.3, bz-2.29);
  1354. v3f v(1./7, 1./7, 1./7);
  1355. f32 dtime;
  1356. UASSERT(axisAlignedCollision(s, m, v, 0, dtime) == 1);
  1357. UASSERT(fabs(dtime - 16.1) < 0.001);
  1358. }
  1359. {
  1360. aabb3f s(bx, by, bz, bx+2, by+2, bz+2);
  1361. aabb3f m(bx-4.2, by-4.2, bz-4.2, bx-2.29, by-2.29, bz-2.3);
  1362. v3f v(1./7, 1./7, 1./7);
  1363. f32 dtime;
  1364. UASSERT(axisAlignedCollision(s, m, v, 0, dtime) == 2);
  1365. UASSERT(fabs(dtime - 16.1) < 0.001);
  1366. }
  1367. }
  1368. }
  1369. };
  1370. struct TestSocket: public TestBase
  1371. {
  1372. void Run()
  1373. {
  1374. const int port = 30003;
  1375. Address address(0,0,0,0, port);
  1376. Address address6((IPv6AddressBytes*) NULL, port);
  1377. // IPv6 socket test
  1378. {
  1379. UDPSocket socket6(true);
  1380. socket6.Bind(address6);
  1381. const char sendbuffer[] = "hello world!";
  1382. IPv6AddressBytes bytes;
  1383. bytes.bytes[15] = 1;
  1384. try {
  1385. socket6.Send(Address(&bytes, port), sendbuffer, sizeof(sendbuffer));
  1386. sleep_ms(50);
  1387. char rcvbuffer[256];
  1388. memset(rcvbuffer, 0, sizeof(rcvbuffer));
  1389. Address sender;
  1390. for(;;)
  1391. {
  1392. int bytes_read = socket6.Receive(sender, rcvbuffer, sizeof(rcvbuffer));
  1393. if(bytes_read < 0)
  1394. break;
  1395. }
  1396. //FIXME: This fails on some systems
  1397. UASSERT(strncmp(sendbuffer, rcvbuffer, sizeof(sendbuffer))==0);
  1398. UASSERT(memcmp(sender.getAddress6().sin6_addr.s6_addr, Address(&bytes, 0).getAddress6().sin6_addr.s6_addr, 16) == 0);
  1399. }
  1400. catch (SendFailedException e) {
  1401. errorstream << "IPv6 support enabled but not available!" << std::endl;
  1402. }
  1403. }
  1404. // IPv4 socket test
  1405. {
  1406. UDPSocket socket(false);
  1407. socket.Bind(address);
  1408. const char sendbuffer[] = "hello world!";
  1409. socket.Send(Address(127,0,0,1,port), sendbuffer, sizeof(sendbuffer));
  1410. sleep_ms(50);
  1411. char rcvbuffer[256];
  1412. memset(rcvbuffer, 0, sizeof(rcvbuffer));
  1413. Address sender;
  1414. for(;;)
  1415. {
  1416. int bytes_read = socket.Receive(sender, rcvbuffer, sizeof(rcvbuffer));
  1417. if(bytes_read < 0)
  1418. break;
  1419. }
  1420. //FIXME: This fails on some systems
  1421. UASSERT(strncmp(sendbuffer, rcvbuffer, sizeof(sendbuffer))==0);
  1422. UASSERT(sender.getAddress().sin_addr.s_addr == Address(127,0,0,1, 0).getAddress().sin_addr.s_addr);
  1423. }
  1424. }
  1425. };
  1426. struct TestConnection: public TestBase
  1427. {
  1428. void TestHelpers()
  1429. {
  1430. /*
  1431. Test helper functions
  1432. */
  1433. // Some constants for testing
  1434. u32 proto_id = 0x12345678;
  1435. u16 peer_id = 123;
  1436. u8 channel = 2;
  1437. SharedBuffer<u8> data1(1);
  1438. data1[0] = 100;
  1439. Address a(127,0,0,1, 10);
  1440. u16 seqnum = 34352;
  1441. con::BufferedPacket p1 = con::makePacket(a, data1,
  1442. proto_id, peer_id, channel);
  1443. /*
  1444. We should now have a packet with this data:
  1445. Header:
  1446. [0] u32 protocol_id
  1447. [4] u16 sender_peer_id
  1448. [6] u8 channel
  1449. Data:
  1450. [7] u8 data1[0]
  1451. */
  1452. UASSERT(readU32(&p1.data[0]) == proto_id);
  1453. UASSERT(readU16(&p1.data[4]) == peer_id);
  1454. UASSERT(readU8(&p1.data[6]) == channel);
  1455. UASSERT(readU8(&p1.data[7]) == data1[0]);
  1456. //infostream<<"initial data1[0]="<<((u32)data1[0]&0xff)<<std::endl;
  1457. SharedBuffer<u8> p2 = con::makeReliablePacket(data1, seqnum);
  1458. /*infostream<<"p2.getSize()="<<p2.getSize()<<", data1.getSize()="
  1459. <<data1.getSize()<<std::endl;
  1460. infostream<<"readU8(&p2[3])="<<readU8(&p2[3])
  1461. <<" p2[3]="<<((u32)p2[3]&0xff)<<std::endl;
  1462. infostream<<"data1[0]="<<((u32)data1[0]&0xff)<<std::endl;*/
  1463. UASSERT(p2.getSize() == 3 + data1.getSize());
  1464. UASSERT(readU8(&p2[0]) == TYPE_RELIABLE);
  1465. UASSERT(readU16(&p2[1]) == seqnum);
  1466. UASSERT(readU8(&p2[3]) == data1[0]);
  1467. }
  1468. struct Handler : public con::PeerHandler
  1469. {
  1470. Handler(const char *a_name)
  1471. {
  1472. count = 0;
  1473. last_id = 0;
  1474. name = a_name;
  1475. }
  1476. void peerAdded(con::Peer *peer)
  1477. {
  1478. infostream<<"Handler("<<name<<")::peerAdded(): "
  1479. "id="<<peer->id<<std::endl;
  1480. last_id = peer->id;
  1481. count++;
  1482. }
  1483. void deletingPeer(con::Peer *peer, bool timeout)
  1484. {
  1485. infostream<<"Handler("<<name<<")::deletingPeer(): "
  1486. "id="<<peer->id
  1487. <<", timeout="<<timeout<<std::endl;
  1488. last_id = peer->id;
  1489. count--;
  1490. }
  1491. s32 count;
  1492. u16 last_id;
  1493. const char *name;
  1494. };
  1495. void Run()
  1496. {
  1497. DSTACK("TestConnection::Run");
  1498. TestHelpers();
  1499. /*
  1500. Test some real connections
  1501. NOTE: This mostly tests the legacy interface.
  1502. */
  1503. u32 proto_id = 0xad26846a;
  1504. Handler hand_server("server");
  1505. Handler hand_client("client");
  1506. infostream<<"** Creating server Connection"<<std::endl;
  1507. con::Connection server(proto_id, 512, 5.0, false, &hand_server);
  1508. Address address(0,0,0,0, 30001);
  1509. server.Serve(address);
  1510. infostream<<"** Creating client Connection"<<std::endl;
  1511. con::Connection client(proto_id, 512, 5.0, false, &hand_client);
  1512. UASSERT(hand_server.count == 0);
  1513. UASSERT(hand_client.count == 0);
  1514. sleep_ms(50);
  1515. Address server_address(127,0,0,1, 30001);
  1516. infostream<<"** running client.Connect()"<<std::endl;
  1517. client.Connect(server_address);
  1518. sleep_ms(50);
  1519. // Client should not have added client yet
  1520. UASSERT(hand_client.count == 0);
  1521. try
  1522. {
  1523. u16 peer_id;
  1524. SharedBuffer<u8> data;
  1525. infostream<<"** running client.Receive()"<<std::endl;
  1526. u32 size = client.Receive(peer_id, data);
  1527. infostream<<"** Client received: peer_id="<<peer_id
  1528. <<", size="<<size
  1529. <<std::endl;
  1530. }
  1531. catch(con::NoIncomingDataException &e)
  1532. {
  1533. }
  1534. // Client should have added server now
  1535. UASSERT(hand_client.count == 1);
  1536. UASSERT(hand_client.last_id == 1);
  1537. // Server should not have added client yet
  1538. UASSERT(hand_server.count == 0);
  1539. sleep_ms(100);
  1540. try
  1541. {
  1542. u16 peer_id;
  1543. SharedBuffer<u8> data;
  1544. infostream<<"** running server.Receive()"<<std::endl;
  1545. u32 size = server.Receive(peer_id, data);
  1546. infostream<<"** Server received: peer_id="<<peer_id
  1547. <<", size="<<size
  1548. <<std::endl;
  1549. }
  1550. catch(con::NoIncomingDataException &e)
  1551. {
  1552. // No actual data received, but the client has
  1553. // probably been connected
  1554. }
  1555. // Client should be the same
  1556. UASSERT(hand_client.count == 1);
  1557. UASSERT(hand_client.last_id == 1);
  1558. // Server should have the client
  1559. UASSERT(hand_server.count == 1);
  1560. UASSERT(hand_server.last_id == 2);
  1561. //sleep_ms(50);
  1562. while(client.Connected() == false)
  1563. {
  1564. try
  1565. {
  1566. u16 peer_id;
  1567. SharedBuffer<u8> data;
  1568. infostream<<"** running client.Receive()"<<std::endl;
  1569. u32 size = client.Receive(peer_id, data);
  1570. infostream<<"** Client received: peer_id="<<peer_id
  1571. <<", size="<<size
  1572. <<std::endl;
  1573. }
  1574. catch(con::NoIncomingDataException &e)
  1575. {
  1576. }
  1577. sleep_ms(50);
  1578. }
  1579. sleep_ms(50);
  1580. try
  1581. {
  1582. u16 peer_id;
  1583. SharedBuffer<u8> data;
  1584. infostream<<"** running server.Receive()"<<std::endl;
  1585. u32 size = server.Receive(peer_id, data);
  1586. infostream<<"** Server received: peer_id="<<peer_id
  1587. <<", size="<<size
  1588. <<std::endl;
  1589. }
  1590. catch(con::NoIncomingDataException &e)
  1591. {
  1592. }
  1593. #if 1
  1594. /*
  1595. Simple send-receive test
  1596. */
  1597. {
  1598. /*u8 data[] = "Hello World!";
  1599. u32 datasize = sizeof(data);*/
  1600. SharedBuffer<u8> data = SharedBufferFromString("Hello World!");
  1601. infostream<<"** running client.Send()"<<std::endl;
  1602. client.Send(PEER_ID_SERVER, 0, data, true);
  1603. sleep_ms(50);
  1604. u16 peer_id;
  1605. SharedBuffer<u8> recvdata;
  1606. infostream<<"** running server.Receive()"<<std::endl;
  1607. u32 size = server.Receive(peer_id, recvdata);
  1608. infostream<<"** Server received: peer_id="<<peer_id
  1609. <<", size="<<size
  1610. <<", data="<<*data
  1611. <<std::endl;
  1612. UASSERT(memcmp(*data, *recvdata, data.getSize()) == 0);
  1613. }
  1614. #endif
  1615. u16 peer_id_client = 2;
  1616. #if 0
  1617. /*
  1618. Send consequent packets in different order
  1619. Not compatible with new Connection, thus commented out.
  1620. */
  1621. {
  1622. //u8 data1[] = "hello1";
  1623. //u8 data2[] = "hello2";
  1624. SharedBuffer<u8> data1 = SharedBufferFromString("hello1");
  1625. SharedBuffer<u8> data2 = SharedBufferFromString("Hello2");
  1626. Address client_address =
  1627. server.GetPeerAddress(peer_id_client);
  1628. infostream<<"*** Sending packets in wrong order (2,1,2)"
  1629. <<std::endl;
  1630. u8 chn = 0;
  1631. con::Channel *ch = &server.getPeer(peer_id_client)->channels[chn];
  1632. u16 sn = ch->next_outgoing_seqnum;
  1633. ch->next_outgoing_seqnum = sn+1;
  1634. server.Send(peer_id_client, chn, data2, true);
  1635. ch->next_outgoing_seqnum = sn;
  1636. server.Send(peer_id_client, chn, data1, true);
  1637. ch->next_outgoing_seqnum = sn+1;
  1638. server.Send(peer_id_client, chn, data2, true);
  1639. sleep_ms(50);
  1640. infostream<<"*** Receiving the packets"<<std::endl;
  1641. u16 peer_id;
  1642. SharedBuffer<u8> recvdata;
  1643. u32 size;
  1644. infostream<<"** running client.Receive()"<<std::endl;
  1645. peer_id = 132;
  1646. size = client.Receive(peer_id, recvdata);
  1647. infostream<<"** Client received: peer_id="<<peer_id
  1648. <<", size="<<size
  1649. <<", data="<<*recvdata
  1650. <<std::endl;
  1651. UASSERT(size == data1.getSize());
  1652. UASSERT(memcmp(*data1, *recvdata, data1.getSize()) == 0);
  1653. UASSERT(peer_id == PEER_ID_SERVER);
  1654. infostream<<"** running client.Receive()"<<std::endl;
  1655. peer_id = 132;
  1656. size = client.Receive(peer_id, recvdata);
  1657. infostream<<"** Client received: peer_id="<<peer_id
  1658. <<", size="<<size
  1659. <<", data="<<*recvdata
  1660. <<std::endl;
  1661. UASSERT(size == data2.getSize());
  1662. UASSERT(memcmp(*data2, *recvdata, data2.getSize()) == 0);
  1663. UASSERT(peer_id == PEER_ID_SERVER);
  1664. bool got_exception = false;
  1665. try
  1666. {
  1667. infostream<<"** running client.Receive()"<<std::endl;
  1668. peer_id = 132;
  1669. size = client.Receive(peer_id, recvdata);
  1670. infostream<<"** Client received: peer_id="<<peer_id
  1671. <<", size="<<size
  1672. <<", data="<<*recvdata
  1673. <<std::endl;
  1674. }
  1675. catch(con::NoIncomingDataException &e)
  1676. {
  1677. infostream<<"** No incoming data for client"<<std::endl;
  1678. got_exception = true;
  1679. }
  1680. UASSERT(got_exception);
  1681. }
  1682. #endif
  1683. #if 0
  1684. /*
  1685. Send large amounts of packets (infinite test)
  1686. Commented out because of infinity.
  1687. */
  1688. {
  1689. infostream<<"Sending large amounts of packets (infinite test)"<<std::endl;
  1690. int sendcount = 0;
  1691. for(;;){
  1692. int datasize = myrand_range(0,5)==0?myrand_range(100,10000):myrand_range(0,100);
  1693. infostream<<"datasize="<<datasize<<std::endl;
  1694. SharedBuffer<u8> data1(datasize);
  1695. for(u16 i=0; i<datasize; i++)
  1696. data1[i] = i/4;
  1697. int sendtimes = myrand_range(1,10);
  1698. for(int i=0; i<sendtimes; i++){
  1699. server.Send(peer_id_client, 0, data1, true);
  1700. sendcount++;
  1701. }
  1702. infostream<<"sendcount="<<sendcount<<std::endl;
  1703. //int receivetimes = myrand_range(1,20);
  1704. int receivetimes = 20;
  1705. for(int i=0; i<receivetimes; i++){
  1706. SharedBuffer<u8> recvdata;
  1707. u16 peer_id = 132;
  1708. u16 size = 0;
  1709. bool received = false;
  1710. try{
  1711. size = client.Receive(peer_id, recvdata);
  1712. received = true;
  1713. }catch(con::NoIncomingDataException &e){
  1714. }
  1715. }
  1716. }
  1717. }
  1718. #endif
  1719. /*
  1720. Send a large packet
  1721. */
  1722. {
  1723. const int datasize = 30000;
  1724. SharedBuffer<u8> data1(datasize);
  1725. for(u16 i=0; i<datasize; i++){
  1726. data1[i] = i/4;
  1727. }
  1728. infostream<<"Sending data (size="<<datasize<<"):";
  1729. for(int i=0; i<datasize && i<20; i++){
  1730. if(i%2==0) infostream<<" ";
  1731. char buf[10];
  1732. snprintf(buf, 10, "%.2X", ((int)((const char*)*data1)[i])&0xff);
  1733. infostream<<buf;
  1734. }
  1735. if(datasize>20)
  1736. infostream<<"...";
  1737. infostream<<std::endl;
  1738. server.Send(peer_id_client, 0, data1, true);
  1739. //sleep_ms(3000);
  1740. SharedBuffer<u8> recvdata;
  1741. infostream<<"** running client.Receive()"<<std::endl;
  1742. u16 peer_id = 132;
  1743. u16 size = 0;
  1744. bool received = false;
  1745. u32 timems0 = porting::getTimeMs();
  1746. for(;;){
  1747. if(porting::getTimeMs() - timems0 > 5000 || received)
  1748. break;
  1749. try{
  1750. size = client.Receive(peer_id, recvdata);
  1751. received = true;
  1752. }catch(con::NoIncomingDataException &e){
  1753. }
  1754. sleep_ms(10);
  1755. }
  1756. UASSERT(received);
  1757. infostream<<"** Client received: peer_id="<<peer_id
  1758. <<", size="<<size
  1759. <<std::endl;
  1760. infostream<<"Received data (size="<<size<<"): ";
  1761. for(int i=0; i<size && i<20; i++){
  1762. if(i%2==0) infostream<<" ";
  1763. char buf[10];
  1764. snprintf(buf, 10, "%.2X", ((int)(recvdata[i]))&0xff);
  1765. infostream<<buf;
  1766. }
  1767. if(size>20)
  1768. infostream<<"...";
  1769. infostream<<std::endl;
  1770. UASSERT(memcmp(*data1, *recvdata, data1.getSize()) == 0);
  1771. UASSERT(peer_id == PEER_ID_SERVER);
  1772. }
  1773. // Check peer handlers
  1774. UASSERT(hand_client.count == 1);
  1775. UASSERT(hand_client.last_id == 1);
  1776. UASSERT(hand_server.count == 1);
  1777. UASSERT(hand_server.last_id == 2);
  1778. //assert(0);
  1779. }
  1780. };
  1781. #define TEST(X)\
  1782. {\
  1783. X x;\
  1784. infostream<<"Running " #X <<std::endl;\
  1785. x.Run();\
  1786. tests_run++;\
  1787. tests_failed += x.test_failed ? 1 : 0;\
  1788. }
  1789. #define TESTPARAMS(X, ...)\
  1790. {\
  1791. X x;\
  1792. infostream<<"Running " #X <<std::endl;\
  1793. x.Run(__VA_ARGS__);\
  1794. tests_run++;\
  1795. tests_failed += x.test_failed ? 1 : 0;\
  1796. }
  1797. void run_tests()
  1798. {
  1799. DSTACK(__FUNCTION_NAME);
  1800. int tests_run = 0;
  1801. int tests_failed = 0;
  1802. // Create item and node definitions
  1803. IWritableItemDefManager *idef = createItemDefManager();
  1804. IWritableNodeDefManager *ndef = createNodeDefManager();
  1805. define_some_nodes(idef, ndef);
  1806. infostream<<"run_tests() started"<<std::endl;
  1807. TEST(TestUtilities);
  1808. TEST(TestPath);
  1809. TEST(TestSettings);
  1810. TEST(TestCompress);
  1811. TEST(TestSerialization);
  1812. TEST(TestNodedefSerialization);
  1813. TESTPARAMS(TestMapNode, ndef);
  1814. TESTPARAMS(TestVoxelManipulator, ndef);
  1815. TESTPARAMS(TestVoxelAlgorithms, ndef);
  1816. TESTPARAMS(TestInventory, idef);
  1817. //TEST(TestMapBlock);
  1818. //TEST(TestMapSector);
  1819. TEST(TestCollision);
  1820. if(INTERNET_SIMULATOR == false){
  1821. TEST(TestSocket);
  1822. dout_con<<"=== BEGIN RUNNING UNIT TESTS FOR CONNECTION ==="<<std::endl;
  1823. TEST(TestConnection);
  1824. dout_con<<"=== END RUNNING UNIT TESTS FOR CONNECTION ==="<<std::endl;
  1825. }
  1826. delete idef;
  1827. delete ndef;
  1828. if(tests_failed == 0){
  1829. infostream<<"run_tests(): "<<tests_failed<<" / "<<tests_run<<" tests failed."<<std::endl;
  1830. infostream<<"run_tests() passed."<<std::endl;
  1831. return;
  1832. } else {
  1833. errorstream<<"run_tests(): "<<tests_failed<<" / "<<tests_run<<" tests failed."<<std::endl;
  1834. errorstream<<"run_tests() aborting."<<std::endl;
  1835. abort();
  1836. }
  1837. }