diff --git a/src/BoE.xcodeproj/project.pbxproj b/src/BoE.xcodeproj/project.pbxproj index 8d5ce098..5cd2ca91 100755 --- a/src/BoE.xcodeproj/project.pbxproj +++ b/src/BoE.xcodeproj/project.pbxproj @@ -251,6 +251,9 @@ 91D634560F8FD77800674AB3 /* BoE.icns in Resources */ = {isa = PBXBuildFile; fileRef = 2B8F435C0C0973680012E4A8 /* BoE.icns */; }; 91EF052C1904D099001BEF85 /* bold.ttf in Copy Fonts */ = {isa = PBXBuildFile; fileRef = 91EF05291904D082001BEF85 /* bold.ttf */; }; 91EF052D1904D099001BEF85 /* plain.ttf in Copy Fonts */ = {isa = PBXBuildFile; fileRef = 91EF052A1904D082001BEF85 /* plain.ttf */; }; + 91EF27731B693D3900666469 /* ter_read.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 91EF27721B693D3800666469 /* ter_read.cpp */; }; + 91EF27771B693D5500666469 /* item_read.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 91EF27761B693D5500666469 /* item_read.cpp */; }; + 91EF277B1B693D6E00666469 /* monst_read.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 91EF277A1B693D6E00666469 /* monst_read.cpp */; }; 91F6F8E318F87F3700E3EA15 /* sfml-audio.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 91F6F8DD18F87F3700E3EA15 /* sfml-audio.framework */; }; 91F6F8E418F87F3700E3EA15 /* sfml-audio.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 91F6F8DD18F87F3700E3EA15 /* sfml-audio.framework */; }; 91F6F8E518F87F3700E3EA15 /* sfml-audio.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 91F6F8DD18F87F3700E3EA15 /* sfml-audio.framework */; }; @@ -764,6 +767,9 @@ 91EC481018FBABB100BB1E86 /* prefs.mac.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = prefs.mac.mm; sourceTree = ""; }; 91EF05291904D082001BEF85 /* bold.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = bold.ttf; sourceTree = ""; }; 91EF052A1904D082001BEF85 /* plain.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = plain.ttf; sourceTree = ""; }; + 91EF27721B693D3800666469 /* ter_read.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ter_read.cpp; sourceTree = ""; }; + 91EF27761B693D5500666469 /* item_read.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = item_read.cpp; sourceTree = ""; }; + 91EF277A1B693D6E00666469 /* monst_read.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = monst_read.cpp; sourceTree = ""; }; 91F06E8F1A2EBEE70038E902 /* special_parse.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = special_parse.hpp; sourceTree = ""; }; 91F6F8DD18F87F3700E3EA15 /* sfml-audio.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = "sfml-audio.framework"; path = "/Library/Frameworks/sfml-audio.framework"; sourceTree = ""; }; 91F6F8DE18F87F3700E3EA15 /* sfml-graphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = "sfml-graphics.framework"; path = "/Library/Frameworks/sfml-graphics.framework"; sourceTree = ""; }; @@ -1306,6 +1312,9 @@ 91C763D81B4C4BB30086D879 /* enums.cpp */, 91C763DA1B4EE6E00086D879 /* map_read.cpp */, 91C763DC1B4EE7950086D879 /* map_write.cpp */, + 91EF27721B693D3800666469 /* ter_read.cpp */, + 91EF27761B693D5500666469 /* item_read.cpp */, + 91EF277A1B693D6E00666469 /* monst_read.cpp */, ); name = src; sourceTree = ""; @@ -1799,6 +1808,9 @@ 91C763D91B4C50710086D879 /* enums.cpp in Sources */, 91C763DB1B4EE77F0086D879 /* map_read.cpp in Sources */, 91C763DD1B4EE7950086D879 /* map_write.cpp in Sources */, + 91EF27731B693D3900666469 /* ter_read.cpp in Sources */, + 91EF27771B693D5500666469 /* item_read.cpp in Sources */, + 91EF277B1B693D6E00666469 /* monst_read.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/src/tools/fileio_scen.cpp b/src/tools/fileio_scen.cpp index 530e7956..b46d0df2 100644 --- a/src/tools/fileio_scen.cpp +++ b/src/tools/fileio_scen.cpp @@ -45,6 +45,9 @@ static bool load_scenario_v2(fs::path file_to_load, cScenario& scenario, bool on // Some of these are non-static so that the test cases can access them. ticpp::Document xmlDocFromStream(std::istream& stream, std::string name); void readScenarioFromXml(ticpp::Document&& data, cScenario& scenario); +void readTerrainFromXml(ticpp::Document&& data, cScenario& scenario); +void readItemsFromXml(ticpp::Document&& data, cScenario& scenario); +void readMonstersFromXml(ticpp::Document&& data, cScenario& scenario); void loadOutMapData(map_data&& data, location which, cScenario& scen); void loadTownMapData(map_data&& data, int which, cScenario& scen); @@ -899,7 +902,7 @@ void readScenarioFromXml(ticpp::Document&& data, cScenario& scenario) { throw xMissingElem("scenario", *reqs.begin(), data.FirstChildElement()->Row(), data.FirstChildElement()->Column(), fname); } -static void readTerrainFromXml(ticpp::Document&& data, cScenario& scenario) { +void readTerrainFromXml(ticpp::Document&& data, cScenario& scenario) { using namespace ticpp; int maj, min, rev; std::string fname, type, name, val; @@ -1014,7 +1017,7 @@ static void readTerrainFromXml(ticpp::Document&& data, cScenario& scenario) { } } -static void readItemsFromXml(ticpp::Document&& data, cScenario& scenario) { +void readItemsFromXml(ticpp::Document&& data, cScenario& scenario) { using namespace ticpp; int maj, min, rev; std::string fname, type, name, val; @@ -1090,20 +1093,22 @@ static void readItemsFromXml(ticpp::Document&& data, cScenario& scenario) { Iterator prop; for(prop = prop.begin(item.Get()); prop != prop.end(); prop++) { prop->GetValue(&type); - prop->GetText(&val); - bool state = val == "true"; + auto state = [&prop,&val]() -> bool { + prop->GetText(&val); + return val == "true"; + }; if(type == "identified") { - the_item.ident = state; + the_item.ident = state(); } else if(type == "magic") { - the_item.magic = state; + the_item.magic = state(); } else if(type == "cursed") { - the_item.cursed = state; + the_item.cursed = state(); } else if(type == "concealed") { - the_item.concealed = state; + the_item.concealed = state(); } else if(type == "enchanted") { - the_item.enchanted = state; + the_item.enchanted = state(); } else if(type == "unsellable") { - the_item.unsellable = state; + the_item.unsellable = state(); } else throw xBadNode(type, prop->Row(), prop->Column(), fname); } } else if(type == "description") { @@ -1130,10 +1135,14 @@ static std::pair parseDice(std::string str, std::string elem, std::stri count *= 10; count += c - '0'; } - } else if(!found_d && c == 'd') + } else if(!found_d && c == 'd') { found_d = true; + if(count == 0) count = 1; + } else throw xBadVal(elem, attr, str, row, col, fname); } + if(!found_d) + throw xBadVal(elem, attr, str, row, col, fname); return {count, sides}; } @@ -1291,7 +1300,7 @@ static void readMonstAbilFromXml(ticpp::Element& data, cMonster& monst) { } } -static void readMonstersFromXml(ticpp::Document&& data, cScenario& scenario) { +void readMonstersFromXml(ticpp::Document&& data, cScenario& scenario) { using namespace ticpp; int maj, min, rev; std::string fname, type, name, val; diff --git a/test/files/scenario/bad_root.xml b/test/files/bad_root.xml similarity index 100% rename from test/files/scenario/bad_root.xml rename to test/files/bad_root.xml diff --git a/test/files/items/bad_abil.xml b/test/files/items/bad_abil.xml new file mode 100644 index 00000000..a64471ea --- /dev/null +++ b/test/files/items/bad_abil.xml @@ -0,0 +1,7 @@ + + + + bad + + + \ No newline at end of file diff --git a/test/files/items/bad_abil_tag.xml b/test/files/items/bad_abil_tag.xml new file mode 100644 index 00000000..89bb2231 --- /dev/null +++ b/test/files/items/bad_abil_tag.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/test/files/items/bad_prop.xml b/test/files/items/bad_prop.xml new file mode 100644 index 00000000..3dedf120 --- /dev/null +++ b/test/files/items/bad_prop.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/test/files/items/bad_root_attr.xml b/test/files/items/bad_root_attr.xml new file mode 100644 index 00000000..923bb81c --- /dev/null +++ b/test/files/items/bad_root_attr.xml @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/test/files/items/bad_tag.xml b/test/files/items/bad_tag.xml new file mode 100644 index 00000000..09d9bac2 --- /dev/null +++ b/test/files/items/bad_tag.xml @@ -0,0 +1,5 @@ + + + > + + \ No newline at end of file diff --git a/test/files/items/bad_toplevel.xml b/test/files/items/bad_toplevel.xml new file mode 100644 index 00000000..03c610a9 --- /dev/null +++ b/test/files/items/bad_toplevel.xml @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/test/files/items/bad_type.xml b/test/files/items/bad_type.xml new file mode 100644 index 00000000..35bd4e5f --- /dev/null +++ b/test/files/items/bad_type.xml @@ -0,0 +1,5 @@ + + + bad + + \ No newline at end of file diff --git a/test/files/items/bad_use.xml b/test/files/items/bad_use.xml new file mode 100644 index 00000000..03b18feb --- /dev/null +++ b/test/files/items/bad_use.xml @@ -0,0 +1,7 @@ + + + + bad + + + \ No newline at end of file diff --git a/test/files/items/bad_weapon.xml b/test/files/items/bad_weapon.xml new file mode 100644 index 00000000..baf2b027 --- /dev/null +++ b/test/files/items/bad_weapon.xml @@ -0,0 +1,5 @@ + + + bad + + \ No newline at end of file diff --git a/test/files/items/minimal.xml b/test/files/items/minimal.xml new file mode 100644 index 00000000..758c1da6 --- /dev/null +++ b/test/files/items/minimal.xml @@ -0,0 +1,11 @@ + + + weapon-1hand + 3 + 0 + 100 + 10 + Test Sword + Sword + + \ No newline at end of file diff --git a/test/files/items/missing_abil.xml b/test/files/items/missing_abil.xml new file mode 100644 index 00000000..fcfa555e --- /dev/null +++ b/test/files/items/missing_abil.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/test/files/items/missing_id.xml b/test/files/items/missing_id.xml new file mode 100644 index 00000000..46f25dad --- /dev/null +++ b/test/files/items/missing_id.xml @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/test/files/items/missing_req.xml b/test/files/items/missing_req.xml new file mode 100644 index 00000000..62a38fc3 --- /dev/null +++ b/test/files/items/missing_req.xml @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/test/files/items/no_version.xml b/test/files/items/no_version.xml new file mode 100644 index 00000000..e4c6f6fa --- /dev/null +++ b/test/files/items/no_version.xml @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/test/files/monsters/attacks.xml b/test/files/monsters/attacks.xml new file mode 100644 index 00000000..a03857f0 --- /dev/null +++ b/test/files/monsters/attacks.xml @@ -0,0 +1,19 @@ + + + Test Monster + 1 + 0 + 1 + 10 + 4 + humanoid + + d10 + 2d4 + 1d8 + + 0 + hostile-a + + + \ No newline at end of file diff --git a/test/files/monsters/bad_attack.xml b/test/files/monsters/bad_attack.xml new file mode 100644 index 00000000..8a3d2222 --- /dev/null +++ b/test/files/monsters/bad_attack.xml @@ -0,0 +1,7 @@ + + + + bad + + + \ No newline at end of file diff --git a/test/files/monsters/bad_attack2.xml b/test/files/monsters/bad_attack2.xml new file mode 100644 index 00000000..4af6e105 --- /dev/null +++ b/test/files/monsters/bad_attack2.xml @@ -0,0 +1,7 @@ + + + + 100 + + + \ No newline at end of file diff --git a/test/files/monsters/bad_attack_attr.xml b/test/files/monsters/bad_attack_attr.xml new file mode 100644 index 00000000..3434ce54 --- /dev/null +++ b/test/files/monsters/bad_attack_attr.xml @@ -0,0 +1,7 @@ + + + + 1d4 + + + \ No newline at end of file diff --git a/test/files/monsters/bad_attack_tag.xml b/test/files/monsters/bad_attack_tag.xml new file mode 100644 index 00000000..933e9ceb --- /dev/null +++ b/test/files/monsters/bad_attack_tag.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/test/files/monsters/bad_attack_type.xml b/test/files/monsters/bad_attack_type.xml new file mode 100644 index 00000000..7eba7b4c --- /dev/null +++ b/test/files/monsters/bad_attack_type.xml @@ -0,0 +1,7 @@ + + + + 1d4 + + + \ No newline at end of file diff --git a/test/files/monsters/bad_id.xml b/test/files/monsters/bad_id.xml new file mode 100644 index 00000000..3c578520 --- /dev/null +++ b/test/files/monsters/bad_id.xml @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/test/files/monsters/bad_immune.xml b/test/files/monsters/bad_immune.xml new file mode 100644 index 00000000..31cfffdb --- /dev/null +++ b/test/files/monsters/bad_immune.xml @@ -0,0 +1,7 @@ + + + + 50 + + + \ No newline at end of file diff --git a/test/files/monsters/bad_loot.xml b/test/files/monsters/bad_loot.xml new file mode 100644 index 00000000..a576795a --- /dev/null +++ b/test/files/monsters/bad_loot.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/test/files/monsters/bad_loot2.xml b/test/files/monsters/bad_loot2.xml new file mode 100644 index 00000000..42824b07 --- /dev/null +++ b/test/files/monsters/bad_loot2.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/test/files/monsters/bad_pic.xml b/test/files/monsters/bad_pic.xml new file mode 100644 index 00000000..4c316fcb --- /dev/null +++ b/test/files/monsters/bad_pic.xml @@ -0,0 +1,5 @@ + + + 5 + + \ No newline at end of file diff --git a/test/files/monsters/bad_pic2.xml b/test/files/monsters/bad_pic2.xml new file mode 100644 index 00000000..094a7cf6 --- /dev/null +++ b/test/files/monsters/bad_pic2.xml @@ -0,0 +1,5 @@ + + + 5 + + \ No newline at end of file diff --git a/test/files/monsters/bad_root_attr.xml b/test/files/monsters/bad_root_attr.xml new file mode 100644 index 00000000..4bbb9985 --- /dev/null +++ b/test/files/monsters/bad_root_attr.xml @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/test/files/monsters/bad_tag.xml b/test/files/monsters/bad_tag.xml new file mode 100644 index 00000000..beaa6548 --- /dev/null +++ b/test/files/monsters/bad_tag.xml @@ -0,0 +1,5 @@ + + + > + + \ No newline at end of file diff --git a/test/files/monsters/bad_toplevel.xml b/test/files/monsters/bad_toplevel.xml new file mode 100644 index 00000000..1f8cd710 --- /dev/null +++ b/test/files/monsters/bad_toplevel.xml @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/test/files/monsters/minimal.xml b/test/files/monsters/minimal.xml new file mode 100644 index 00000000..5b98dc11 --- /dev/null +++ b/test/files/monsters/minimal.xml @@ -0,0 +1,15 @@ + + + Test Monster + 1 + 0 + 2 + 10 + 4 + humanoid + + 5 + hostile-a + + + \ No newline at end of file diff --git a/test/files/monsters/missing_attack_type.xml b/test/files/monsters/missing_attack_type.xml new file mode 100644 index 00000000..d75c507c --- /dev/null +++ b/test/files/monsters/missing_attack_type.xml @@ -0,0 +1,7 @@ + + + + 1d4 + + + \ No newline at end of file diff --git a/test/files/monsters/missing_id.xml b/test/files/monsters/missing_id.xml new file mode 100644 index 00000000..b48b81f3 --- /dev/null +++ b/test/files/monsters/missing_id.xml @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/test/files/monsters/missing_req.xml b/test/files/monsters/missing_req.xml new file mode 100644 index 00000000..8e5c4986 --- /dev/null +++ b/test/files/monsters/missing_req.xml @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/test/files/monsters/no_version.xml b/test/files/monsters/no_version.xml new file mode 100644 index 00000000..074f1516 --- /dev/null +++ b/test/files/monsters/no_version.xml @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/test/files/monsters/too_many_attacks.xml b/test/files/monsters/too_many_attacks.xml new file mode 100644 index 00000000..57238b6c --- /dev/null +++ b/test/files/monsters/too_many_attacks.xml @@ -0,0 +1,10 @@ + + + + 1d4 + 1d4 + 1d4 + 1d4 + + + \ No newline at end of file diff --git a/test/files/terrain/bad_abil.xml b/test/files/terrain/bad_abil.xml new file mode 100644 index 00000000..35bf120d --- /dev/null +++ b/test/files/terrain/bad_abil.xml @@ -0,0 +1,7 @@ + + + + bad + + + \ No newline at end of file diff --git a/test/files/terrain/bad_abil_tag.xml b/test/files/terrain/bad_abil_tag.xml new file mode 100644 index 00000000..bca93555 --- /dev/null +++ b/test/files/terrain/bad_abil_tag.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/test/files/terrain/bad_block.xml b/test/files/terrain/bad_block.xml new file mode 100644 index 00000000..cfd6aac2 --- /dev/null +++ b/test/files/terrain/bad_block.xml @@ -0,0 +1,5 @@ + + + bad + + \ No newline at end of file diff --git a/test/files/terrain/bad_root_attr.xml b/test/files/terrain/bad_root_attr.xml new file mode 100644 index 00000000..805fbda4 --- /dev/null +++ b/test/files/terrain/bad_root_attr.xml @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/test/files/terrain/bad_tag.xml b/test/files/terrain/bad_tag.xml new file mode 100644 index 00000000..5e2cbab9 --- /dev/null +++ b/test/files/terrain/bad_tag.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/test/files/terrain/bad_toplevel.xml b/test/files/terrain/bad_toplevel.xml new file mode 100644 index 00000000..91b163f1 --- /dev/null +++ b/test/files/terrain/bad_toplevel.xml @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/test/files/terrain/bad_trim.xml b/test/files/terrain/bad_trim.xml new file mode 100644 index 00000000..ace87172 --- /dev/null +++ b/test/files/terrain/bad_trim.xml @@ -0,0 +1,5 @@ + + + bad + + \ No newline at end of file diff --git a/test/files/terrain/minimal.xml b/test/files/terrain/minimal.xml new file mode 100644 index 00000000..dee9099d --- /dev/null +++ b/test/files/terrain/minimal.xml @@ -0,0 +1,13 @@ + + + Test Terrain + 0 + 0 + move + none + 0 + + none + + + \ No newline at end of file diff --git a/test/files/terrain/missing_abil.xml b/test/files/terrain/missing_abil.xml new file mode 100644 index 00000000..f9082191 --- /dev/null +++ b/test/files/terrain/missing_abil.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/test/files/terrain/missing_id.xml b/test/files/terrain/missing_id.xml new file mode 100644 index 00000000..4c135dcd --- /dev/null +++ b/test/files/terrain/missing_id.xml @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/test/files/terrain/missing_req.xml b/test/files/terrain/missing_req.xml new file mode 100644 index 00000000..769cb9eb --- /dev/null +++ b/test/files/terrain/missing_req.xml @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/test/files/terrain/no_version.xml b/test/files/terrain/no_version.xml new file mode 100644 index 00000000..9c5fc28b --- /dev/null +++ b/test/files/terrain/no_version.xml @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/test/files/terrain/too_many_flags.xml b/test/files/terrain/too_many_flags.xml new file mode 100644 index 00000000..48661dd9 --- /dev/null +++ b/test/files/terrain/too_many_flags.xml @@ -0,0 +1,11 @@ + + + + none + 0 + 0 + 0 + 0 + + + \ No newline at end of file diff --git a/test/item_read.cpp b/test/item_read.cpp new file mode 100644 index 00000000..d6e11510 --- /dev/null +++ b/test/item_read.cpp @@ -0,0 +1,110 @@ +// +// item_read.cpp +// BoE +// +// Created by Celtic Minstrel on 15-07-29. +// +// + +#include +#include "ticpp.h" +#include "catch.hpp" +#include "dialog.hpp" +#include "scenario.hpp" + +using namespace std; +using namespace ticpp; + +extern Document xmlDocFromStream(istream& stream, string name); +extern void readItemsFromXml(Document&& data, cScenario& scenario); + +TEST_CASE("Loading an item type definition") { + ifstream fin; + cScenario scen; + Document doc; + fin.exceptions(ios::badbit); + + SECTION("When the root tag is wrong") { + fin.open("files/bad_root.xml"); + doc = xmlDocFromStream(fin, "bad_root.xml"); + REQUIRE_THROWS_AS(readItemsFromXml(move(doc), scen), xBadNode); + } + SECTION("When the version attribute is missing") { + fin.open("files/items/no_version.xml"); + doc = xmlDocFromStream(fin, "no_version.xml"); + REQUIRE_THROWS_AS(readItemsFromXml(move(doc), scen), xMissingAttr); + } + SECTION("When the root tag has a bad attribute") { + fin.open("files/items/bad_root_attr.xml"); + doc = xmlDocFromStream(fin, "bad_root_attr.xml"); + REQUIRE_THROWS_AS(readItemsFromXml(move(doc), scen), xBadAttr); + } + SECTION("When an unknown toplevel tag appears") { + fin.open("files/items/bad_toplevel.xml"); + doc = xmlDocFromStream(fin, "bad_toplevel.xml"); + REQUIRE_THROWS_AS(readItemsFromXml(move(doc), scen), xBadNode); + } + SECTION("When the ID attribute is missing") { + fin.open("files/items/missing_id.xml"); + doc = xmlDocFromStream(fin, "missing_id.xml"); + REQUIRE_THROWS_AS(readItemsFromXml(move(doc), scen), Exception); + } + SECTION("When a required subtag is missing") { + fin.open("files/items/missing_req.xml"); + doc = xmlDocFromStream(fin, "missing_req.xml"); + REQUIRE_THROWS_AS(readItemsFromXml(move(doc), scen), xMissingElem); + } + SECTION("When a bad subtag is found") { + fin.open("files/items/bad_tag.xml"); + doc = xmlDocFromStream(fin, "bad_tag.xml"); + REQUIRE_THROWS_AS(readItemsFromXml(move(doc), scen), xBadNode); + } + SECTION("When an unknown property is found") { + fin.open("files/items/bad_prop.xml"); + doc = xmlDocFromStream(fin, "bad_prop.xml"); + REQUIRE_THROWS_AS(readItemsFromXml(move(doc), scen), xBadNode); + } + SECTION("When the variety is invalid") { + fin.open("files/items/bad_type.xml"); + doc = xmlDocFromStream(fin, "bad_type.xml"); + REQUIRE_THROWS_AS(readItemsFromXml(move(doc), scen), Exception); + } + SECTION("When the weapon key skill is invalid") { + fin.open("files/items/bad_weapon.xml"); + doc = xmlDocFromStream(fin, "bad_weapon.xml"); + REQUIRE_THROWS_AS(readItemsFromXml(move(doc), scen), Exception); + } + SECTION("When the special ability is missing a required subtag") { + fin.open("files/items/missing_abil.xml"); + doc = xmlDocFromStream(fin, "missing_abil.xml"); + REQUIRE_THROWS_AS(readItemsFromXml(move(doc), scen), xMissingElem); + } + SECTION("When the special ability is invalid") { + fin.open("files/items/bad_abil.xml"); + doc = xmlDocFromStream(fin, "bad_abil.xml"); + REQUIRE_THROWS_AS(readItemsFromXml(move(doc), scen), Exception); + } + SECTION("When the special ability has an invalid subtag") { + fin.open("files/items/bad_abil_tag.xml"); + doc = xmlDocFromStream(fin, "bad_abil_tag.xml"); + REQUIRE_THROWS_AS(readItemsFromXml(move(doc), scen), xBadNode); + } + SECTION("When the special ability has an invalid use flag") { + fin.open("files/items/bad_use.xml"); + doc = xmlDocFromStream(fin, "bad_use.xml"); + REQUIRE_THROWS_AS(readItemsFromXml(move(doc), scen), Exception); + } + SECTION("With the minimal required data") { + fin.open("files/items/minimal.xml"); + doc = xmlDocFromStream(fin, "minimal.xml"); + REQUIRE_NOTHROW(readItemsFromXml(move(doc), scen)); + REQUIRE(scen.scen_items.size() >= 1); + CHECK(scen.scen_items[0].full_name == "Test Sword"); + CHECK(scen.scen_items[0].name == "Sword"); + CHECK(scen.scen_items[0].variety == eItemType::ONE_HANDED); + CHECK(scen.scen_items[0].item_level == 3); + CHECK(scen.scen_items[0].graphic_num == 0); + CHECK(scen.scen_items[0].value == 100); + CHECK(scen.scen_items[0].weight == 10); + } +} diff --git a/test/monst_read.cpp b/test/monst_read.cpp new file mode 100644 index 00000000..ea690a8a --- /dev/null +++ b/test/monst_read.cpp @@ -0,0 +1,154 @@ +// +// monst_read.cpp +// BoE +// +// Created by Celtic Minstrel on 15-07-29. +// +// + +#include +#include "ticpp.h" +#include "catch.hpp" +#include "dialog.hpp" +#include "scenario.hpp" + +using namespace std; +using namespace ticpp; + +extern Document xmlDocFromStream(istream& stream, string name); +extern void readMonstersFromXml(Document&& data, cScenario& scenario); + +TEST_CASE("Loading a monster type definition") { + ifstream fin; + cScenario scen; + Document doc; + fin.exceptions(ios::badbit); + + SECTION("When the root tag is wrong") { + fin.open("files/bad_root.xml"); + doc = xmlDocFromStream(fin, "bad_root.xml"); + REQUIRE_THROWS_AS(readMonstersFromXml(move(doc), scen), xBadNode); + } + SECTION("When the version attribute is missing") { + fin.open("files/monsters/no_version.xml"); + doc = xmlDocFromStream(fin, "no_version.xml"); + REQUIRE_THROWS_AS(readMonstersFromXml(move(doc), scen), xMissingAttr); + } + SECTION("When the root tag has a bad attribute") { + fin.open("files/monsters/bad_root_attr.xml"); + doc = xmlDocFromStream(fin, "bad_root_attr.xml"); + REQUIRE_THROWS_AS(readMonstersFromXml(move(doc), scen), xBadAttr); + } + SECTION("When an unknown toplevel tag appears") { + fin.open("files/monsters/bad_toplevel.xml"); + doc = xmlDocFromStream(fin, "bad_toplevel.xml"); + REQUIRE_THROWS_AS(readMonstersFromXml(move(doc), scen), xBadNode); + } + SECTION("When the ID attribute is missing") { + fin.open("files/monsters/missing_id.xml"); + doc = xmlDocFromStream(fin, "missing_id.xml"); + REQUIRE_THROWS_AS(readMonstersFromXml(move(doc), scen), Exception); + } + SECTION("When the ID attribute is zero") { + fin.open("files/monsters/bad_id.xml"); + doc = xmlDocFromStream(fin, "missing_id.xml"); + REQUIRE_THROWS_AS(readMonstersFromXml(move(doc), scen), xBadVal); + } + SECTION("When a required subtag is missing") { + fin.open("files/monsters/missing_req.xml"); + doc = xmlDocFromStream(fin, "missing_req.xml"); + REQUIRE_THROWS_AS(readMonstersFromXml(move(doc), scen), xMissingElem); + } + SECTION("When a bad subtag is found") { + fin.open("files/monsters/bad_tag.xml"); + doc = xmlDocFromStream(fin, "bad_tag.xml"); + REQUIRE_THROWS_AS(readMonstersFromXml(move(doc), scen), xBadNode); + } + SECTION("When an attack has a bad subtag") { + fin.open("files/monsters/bad_attack_tag.xml"); + doc = xmlDocFromStream(fin, "bad_attack_tag.xml"); + REQUIRE_THROWS_AS(readMonstersFromXml(move(doc), scen), xBadNode); + } + SECTION("When an attack has a bad attribute") { + fin.open("files/monsters/bad_attack_attr.xml"); + doc = xmlDocFromStream(fin, "bad_attack_attr.xml"); + REQUIRE_THROWS_AS(readMonstersFromXml(move(doc), scen), xBadAttr); + } + SECTION("When an attack has a bad type") { + fin.open("files/monsters/bad_attack_type.xml"); + doc = xmlDocFromStream(fin, "bad_attack_type.xml"); + REQUIRE_THROWS_AS(readMonstersFromXml(move(doc), scen), Exception); + } + SECTION("When an attack damage is invalid") { + fin.open("files/monsters/bad_attack.xml"); + doc = xmlDocFromStream(fin, "bad_attack.xml"); + REQUIRE_THROWS_AS(readMonstersFromXml(move(doc), scen), xBadVal); + } + SECTION("When an attack damage is missing 'd'") { + fin.open("files/monsters/bad_attack2.xml"); + doc = xmlDocFromStream(fin, "bad_attack2.xml"); + REQUIRE_THROWS_AS(readMonstersFromXml(move(doc), scen), xBadVal); + } + SECTION("When an attack is missing the type") { + fin.open("files/monsters/missing_attack_type.xml"); + doc = xmlDocFromStream(fin, "missing_attack_type.xml"); + REQUIRE_THROWS_AS(readMonstersFromXml(move(doc), scen), xMissingAttr); + } + SECTION("When the picture is missing the size attributes") { + fin.open("files/monsters/bad_pic.xml"); + doc = xmlDocFromStream(fin, "bad_pic.xml"); + REQUIRE_THROWS_AS(readMonstersFromXml(move(doc), scen), xMissingAttr); + } + SECTION("When the picture has a bad attribute") { + fin.open("files/monsters/bad_pic2.xml"); + doc = xmlDocFromStream(fin, "bad_pic2.xml"); + REQUIRE_THROWS_AS(readMonstersFromXml(move(doc), scen), xBadAttr); + } + SECTION("When there is a bad immunity") { + fin.open("files/monsters/bad_immune.xml"); + doc = xmlDocFromStream(fin, "bad_immune.xml"); + REQUIRE_THROWS_AS(readMonstersFromXml(move(doc), scen), xBadNode); + } + SECTION("When the loot has a bad subtag") { + fin.open("files/monsters/bad_loot.xml"); + doc = xmlDocFromStream(fin, "bad_loot.xml"); + REQUIRE_THROWS_AS(readMonstersFromXml(move(doc), scen), xBadNode); + } + SECTION("When the loot has a missing subtag") { + fin.open("files/monsters/bad_loot2.xml"); + doc = xmlDocFromStream(fin, "bad_loot2.xml"); + REQUIRE_THROWS_AS(readMonstersFromXml(move(doc), scen), xMissingElem); + } + SECTION("With the minimal required data") { + fin.open("files/monsters/minimal.xml"); + doc = xmlDocFromStream(fin, "minimal.xml"); + REQUIRE_NOTHROW(readMonstersFromXml(move(doc), scen)); + REQUIRE(scen.scen_monsters.size() >= 2); + CHECK(scen.scen_monsters[1].m_name == "Test Monster"); + CHECK(scen.scen_monsters[1].level == 1); + CHECK(scen.scen_monsters[1].armor == 0); + CHECK(scen.scen_monsters[1].skill == 2); + CHECK(scen.scen_monsters[1].m_health == 10); + CHECK(scen.scen_monsters[1].speed == 4); + CHECK(scen.scen_monsters[1].m_type == eRace::HUMANOID); + CHECK(scen.scen_monsters[1].picture_num == 5); + CHECK(scen.scen_monsters[1].x_width == 1); + CHECK(scen.scen_monsters[1].y_width == 1); + CHECK(scen.scen_monsters[1].default_attitude == eAttitude::HOSTILE_A); + } + SECTION("With some attacks") { + fin.open("files/monsters/attacks.xml"); + doc = xmlDocFromStream(fin, "attacks.xml"); + REQUIRE_NOTHROW(readMonstersFromXml(move(doc), scen)); + REQUIRE(scen.scen_monsters.size() >= 2); + CHECK(scen.scen_monsters[1].a[0].type == eMonstMelee::SWING); + CHECK(scen.scen_monsters[1].a[0].dice == 1); + CHECK(scen.scen_monsters[1].a[0].sides == 10); + CHECK(scen.scen_monsters[1].a[1].type == eMonstMelee::PUNCH); + CHECK(scen.scen_monsters[1].a[1].dice == 2); + CHECK(scen.scen_monsters[1].a[1].sides == 4); + CHECK(scen.scen_monsters[1].a[2].type == eMonstMelee::BURN); + CHECK(scen.scen_monsters[1].a[2].dice == 1); + CHECK(scen.scen_monsters[1].a[2].sides == 8); + } +} diff --git a/test/scen_read.cpp b/test/scen_read.cpp index 563096f5..edc68793 100644 --- a/test/scen_read.cpp +++ b/test/scen_read.cpp @@ -19,8 +19,8 @@ TEST_CASE("Loading a new-format scenario record") { Document doc; fin.exceptions(ios::badbit); - SECTION("When the version attribute is missing") { - fin.open("files/scenario/bad_root.xml"); + SECTION("When the root tag is wrong") { + fin.open("files/bad_root.xml"); doc = xmlDocFromStream(fin, "bad_root.xml"); REQUIRE_THROWS_AS(readScenarioFromXml(move(doc), scen), xBadNode); } @@ -326,5 +326,6 @@ TEST_CASE("Loading a new-format scenario record") { doc = xmlDocFromStream(fin, "shop-bad_entry.xml"); REQUIRE_THROWS_AS(readScenarioFromXml(move(doc), scen), xBadNode); } + ResMgr::popPath(); } } diff --git a/test/scen_write.cpp b/test/scen_write.cpp index 5689f9fa..b4911ab1 100644 --- a/test/scen_write.cpp +++ b/test/scen_write.cpp @@ -248,6 +248,7 @@ TEST_CASE("Saving a scenario record") { CHECK(scen.shops[2].getItem(11).item.graphic_num == 24); CHECK(scen.shops[2].getItem(11).item.full_name == "Magic!"); CHECK(scen.shops[2].getItem(11).item.desc == "This is magic!"); + ResMgr::popPath(); } SECTION("With some empty strings, only trailing ones are stripped") { scen.spec_strs.resize(12); diff --git a/test/ter_read.cpp b/test/ter_read.cpp new file mode 100644 index 00000000..21803e9d --- /dev/null +++ b/test/ter_read.cpp @@ -0,0 +1,105 @@ +// +// ter_read.cpp +// BoE +// +// Created by Celtic Minstrel on 15-07-29. +// +// + +#include +#include "ticpp.h" +#include "catch.hpp" +#include "dialog.hpp" +#include "scenario.hpp" + +using namespace std; +using namespace ticpp; + +extern Document xmlDocFromStream(istream& stream, string name); +extern void readTerrainFromXml(Document&& data, cScenario& scenario); + +TEST_CASE("Loading a terrain type definition") { + ifstream fin; + cScenario scen; + Document doc; + fin.exceptions(ios::badbit); + + SECTION("When the root tag is wrong") { + fin.open("files/bad_root.xml"); + doc = xmlDocFromStream(fin, "bad_root.xml"); + REQUIRE_THROWS_AS(readTerrainFromXml(move(doc), scen), xBadNode); + } + SECTION("When the version attribute is missing") { + fin.open("files/terrain/no_version.xml"); + doc = xmlDocFromStream(fin, "no_version.xml"); + REQUIRE_THROWS_AS(readTerrainFromXml(move(doc), scen), xMissingAttr); + } + SECTION("When the root tag has a bad attribute") { + fin.open("files/terrain/bad_root_attr.xml"); + doc = xmlDocFromStream(fin, "bad_root_attr.xml"); + REQUIRE_THROWS_AS(readTerrainFromXml(move(doc), scen), xBadAttr); + } + SECTION("When an unknown toplevel tag appears") { + fin.open("files/terrain/bad_toplevel.xml"); + doc = xmlDocFromStream(fin, "bad_toplevel.xml"); + REQUIRE_THROWS_AS(readTerrainFromXml(move(doc), scen), xBadNode); + } + SECTION("When the ID attribute is missing") { + fin.open("files/terrain/missing_id.xml"); + doc = xmlDocFromStream(fin, "missing_id.xml"); + REQUIRE_THROWS_AS(readTerrainFromXml(move(doc), scen), Exception); + } + SECTION("When a required subtag is missing") { + fin.open("files/terrain/missing_req.xml"); + doc = xmlDocFromStream(fin, "missing_req.xml"); + REQUIRE_THROWS_AS(readTerrainFromXml(move(doc), scen), xMissingElem); + } + SECTION("When an invalid subtag is found") { + fin.open("files/terrain/bad_tag.xml"); + doc = xmlDocFromStream(fin, "bad_tag.xml"); + REQUIRE_THROWS_AS(readTerrainFromXml(move(doc), scen), xBadNode); + } + SECTION("When the blockage type is invalid") { + fin.open("files/terrain/bad_block.xml"); + doc = xmlDocFromStream(fin, "bad_block.xml"); + REQUIRE_THROWS_AS(readTerrainFromXml(move(doc), scen), Exception); + } + SECTION("When the trim type is invalid") { + fin.open("files/terrain/bad_trim.xml"); + doc = xmlDocFromStream(fin, "bad_trim.xml"); + REQUIRE_THROWS_AS(readTerrainFromXml(move(doc), scen), Exception); + } + SECTION("When the special ability type is missing") { + fin.open("files/terrain/missing_abil.xml"); + doc = xmlDocFromStream(fin, "missing_abil.xml"); + REQUIRE_THROWS_AS(readTerrainFromXml(move(doc), scen), xMissingElem); + } + SECTION("When the special ability type is invalid") { + fin.open("files/terrain/bad_abil.xml"); + doc = xmlDocFromStream(fin, "bad_abil.xml"); + REQUIRE_THROWS_AS(readTerrainFromXml(move(doc), scen), Exception); + } + SECTION("When there are too many special ability flags") { + fin.open("files/terrain/too_many_flags.xml"); + doc = xmlDocFromStream(fin, "too_many_flags.xml"); + REQUIRE_THROWS_AS(readTerrainFromXml(move(doc), scen), xBadNode); + } + SECTION("When the special ability has an invalid subtag") { + fin.open("files/terrain/bad_abil_tag.xml"); + doc = xmlDocFromStream(fin, "bad_abil_tag.xml"); + REQUIRE_THROWS_AS(readTerrainFromXml(move(doc), scen), xBadNode); + } + SECTION("With the minimal required data") { + fin.open("files/terrain/minimal.xml"); + doc = xmlDocFromStream(fin, "minimal.xml"); + REQUIRE_NOTHROW(readTerrainFromXml(move(doc), scen)); + REQUIRE(scen.ter_types.size() >= 1); + CHECK(scen.ter_types[0].name == "Test Terrain"); + CHECK(scen.ter_types[0].picture == 0); + CHECK(scen.ter_types[0].map_pic == 0); + CHECK(scen.ter_types[0].combat_arena == 0); + CHECK(scen.ter_types[0].blockage == eTerObstruct::BLOCK_MOVE); + CHECK(scen.ter_types[0].trim_type == eTrimType::NONE); + CHECK(scen.ter_types[0].special == eTerSpec::NONE); + } +}