Basic test cases for reading town, dialogue, and outdoor records

This commit is contained in:
2015-08-28 13:38:08 -04:00
parent 18965476e8
commit bbd47088e1
51 changed files with 553 additions and 5 deletions

View File

@@ -40,7 +40,7 @@
<xs:element name="dialogue">
<xs:complexType>
<xs:sequence>
<xs:element ref="personality" maxOccurs="10"/>
<xs:element ref="personality" minOccurs="0" maxOccurs="10"/>
<xs:element ref="node" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
<xs:attribute name="boes" type="xs:string" use="required"/>

View File

@@ -63,6 +63,9 @@
910D9CA41B36439100414B17 /* libboost_thread.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 910D9CA31B36439100414B17 /* libboost_thread.dylib */; };
910D9CA51B36439100414B17 /* libboost_thread.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 910D9CA31B36439100414B17 /* libboost_thread.dylib */; };
910D9CA61B36439100414B17 /* libboost_thread.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 910D9CA31B36439100414B17 /* libboost_thread.dylib */; };
911A14031B8FAFC600900FD9 /* town_read.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 91C2A6EC1B8FA91400346948 /* town_read.cpp */; };
911A14041B8FB00300900FD9 /* talk_read.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 91C2A6EE1B8FAA8E00346948 /* talk_read.cpp */; };
911A14051B8FB00600900FD9 /* out_read.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 91C2A6ED1B8FA9FB00346948 /* out_read.cpp */; };
9127903E0F9B7F49007B0D52 /* boe.actions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2BF04ACF0BF51923006C0831 /* boe.actions.cpp */; };
9127903F0F9B7F50007B0D52 /* boe.graphics.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2BF04AD30BF51923006C0831 /* boe.graphics.cpp */; };
91279BAE0F9CFCBA007B0D52 /* boescenario.icns in Resources */ = {isa = PBXBuildFile; fileRef = 91279BAD0F9CFCBA007B0D52 /* boescenario.icns */; };
@@ -739,6 +742,9 @@
91BFA3DF19033E01001686E4 /* gzstream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = gzstream.h; sourceTree = "<group>"; };
91C2A6E11B823CCD00346948 /* gitrev.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = gitrev.sh; sourceTree = "<group>"; };
91C2A6E21B8244F700346948 /* gitrev.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = gitrev.hpp; sourceTree = "<group>"; };
91C2A6EC1B8FA91400346948 /* town_read.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = town_read.cpp; sourceTree = "<group>"; };
91C2A6ED1B8FA9FB00346948 /* out_read.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = out_read.cpp; sourceTree = "<group>"; };
91C2A6EE1B8FAA8E00346948 /* talk_read.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = talk_read.cpp; sourceTree = "<group>"; };
91C688E60FD702B9000F6D01 /* cursors.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = cursors.hpp; sourceTree = "<group>"; };
91C688E70FD702B9000F6D01 /* cursors.mac.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = cursors.mac.mm; sourceTree = "<group>"; };
91C749B71A2D6432008E0E10 /* strings */ = {isa = PBXFileReference; lastKnownFileType = folder; path = strings; sourceTree = "<group>"; };
@@ -1329,6 +1335,9 @@
91EF27781B693D5F00666469 /* item_write.cpp */,
91EF277A1B693D6E00666469 /* monst_read.cpp */,
91EF277C1B693D7D00666469 /* monst_write.cpp */,
91C2A6EC1B8FA91400346948 /* town_read.cpp */,
91C2A6EE1B8FAA8E00346948 /* talk_read.cpp */,
91C2A6ED1B8FA9FB00346948 /* out_read.cpp */,
);
name = src;
sourceTree = "<group>";
@@ -1843,6 +1852,9 @@
91EF27791B693D5F00666469 /* item_write.cpp in Sources */,
91EF277B1B693D6E00666469 /* monst_read.cpp in Sources */,
91EF277D1B693D7D00666469 /* monst_write.cpp in Sources */,
911A14031B8FAFC600900FD9 /* town_read.cpp in Sources */,
911A14041B8FB00300900FD9 /* talk_read.cpp in Sources */,
911A14051B8FB00600900FD9 /* out_read.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};

View File

@@ -48,6 +48,9 @@ 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 readOutdoorsFromXml(ticpp::Document&& data, cOutdoors& out);
void readTownFromXml(ticpp::Document&& data, cTown*& town, cScenario& scen);
void readDialogueFromXml(ticpp::Document&& data, cSpeech& talk, int town_num);
void loadOutMapData(map_data&& data, location which, cScenario& scen);
void loadTownMapData(map_data&& data, int which, cScenario& scen);
@@ -1439,7 +1442,7 @@ void readMonstersFromXml(ticpp::Document&& data, cScenario& scenario) {
}
}
static void readOutdoorsFromXml(ticpp::Document&& data, cOutdoors& out) {
void readOutdoorsFromXml(ticpp::Document&& data, cOutdoors& out) {
using namespace ticpp;
int maj, min, rev;
std::string fname, type, name, val;
@@ -1533,7 +1536,7 @@ static void readOutdoorsFromXml(ticpp::Document&& data, cOutdoors& out) {
throw xMissingElem("sector", "name", data.FirstChildElement()->Row(), data.FirstChildElement()->Column(), fname);
}
static void readTownFromXml(ticpp::Document&& data, cTown*& town, cScenario& scen) {
void readTownFromXml(ticpp::Document&& data, cTown*& town, cScenario& scen) {
static const std::string dirs = "nwse";
using namespace ticpp;
int maj, min, rev;
@@ -1736,10 +1739,10 @@ static void readTownFromXml(ticpp::Document&& data, cTown*& town, cScenario& sce
} else throw xBadNode(type, elem->Row(), elem->Column(), fname);
}
if(!reqs.empty())
throw xMissingElem("item", *reqs.begin(), data.FirstChildElement()->Row(), data.FirstChildElement()->Column(), fname);
throw xMissingElem("town", *reqs.begin(), data.FirstChildElement()->Row(), data.FirstChildElement()->Column(), fname);
}
static void readDialogueFromXml(ticpp::Document&& data, cSpeech& talk, int town_num) {
void readDialogueFromXml(ticpp::Document&& data, cSpeech& talk, int town_num) {
using namespace ticpp;
int maj, min, rev;
std::string fname, type, name, val;

View File

@@ -0,0 +1 @@
<sector vers="2.0.0"></sector>

View File

@@ -0,0 +1,3 @@
<sector boes="2.0.0">
<bad/>
</sector>

View File

@@ -0,0 +1,5 @@
<sector boes="2.0.0">
<encounter>
<monster human='false'/>
</encounter>
</sector>

View File

@@ -0,0 +1,5 @@
<sector boes="2.0.0">
<encounter>
<bad/>
</encounter>
</sector>

View File

@@ -0,0 +1,3 @@
<sector boes="2.0.0">
<encounter/>
</sector>

View File

@@ -0,0 +1,7 @@
<sector boes="2.0.0">
<encounter><monster>0</monster></encounter>
<encounter><monster>0</monster></encounter>
<encounter><monster>0</monster></encounter>
<encounter><monster>0</monster></encounter>
<encounter><monster>0</monster></encounter>
</sector>

View File

@@ -0,0 +1,8 @@
<sector boes="2.0.0">
<encounter>
<monster friendly='true'>0</monster>
<monster friendly='true'>0</monster>
<monster friendly='true'>0</monster>
<monster friendly='true'>0</monster>
</encounter>
</sector>

View File

@@ -0,0 +1,3 @@
<sector boes="2.0.0">
<name>Test Sector</name>
</sector>

View File

@@ -0,0 +1 @@
<sector boes="2.0.0"></sector>

View File

@@ -0,0 +1 @@
<sector></sector>

View File

@@ -0,0 +1,3 @@
<dialogue boes="2.0.0">
<bad/>
</dialogue>

View File

@@ -0,0 +1 @@
<dialogue vers="2.0.0"></dialogue>

View File

@@ -0,0 +1 @@
<dialogue boes="2.0.0"></dialogue>

View File

@@ -0,0 +1 @@
<dialogue></dialogue>

View File

@@ -0,0 +1,5 @@
<dialogue boes="2.0.0">
<node for='0'>
<bad/>
</node>
</dialogue>

View File

@@ -0,0 +1,3 @@
<dialogue boes="2.0.0">
<node/>
</dialogue>

View File

@@ -0,0 +1,3 @@
<dialogue boes="2.0.0">
<node for='0'/>
</dialogue>

View File

@@ -0,0 +1,6 @@
<dialogue boes="2.0.0">
<node for='0'>
<keyword>what</keyword>
<type>0</type>
</node>
</dialogue>

View File

@@ -0,0 +1,5 @@
<dialogue boes="2.0.0">
<node for='0'>
<keyword/>
</node>
</dialogue>

View File

@@ -0,0 +1,7 @@
<dialogue boes="2.0.0">
<node for='0'>
<keyword/>
<keyword/>
<keyword/>
</node>
</dialogue>

View File

@@ -0,0 +1,9 @@
<dialogue boes="2.0.0">
<node for='0'>
<param>0</param>
<param>0</param>
<param>0</param>
<param>0</param>
<param>0</param>
</node>
</dialogue>

View File

@@ -0,0 +1,7 @@
<dialogue boes="2.0.0">
<node for='0'>
<text/>
<text/>
<text/>
</node>
</dialogue>

View File

@@ -0,0 +1,3 @@
<dialogue boes="2.0.0">
<personality id='10'/>
</dialogue>

View File

@@ -0,0 +1,5 @@
<dialogue boes="2.0.0">
<personality id='0'>
<bad/>
</personality>
</dialogue>

View File

@@ -0,0 +1,3 @@
<dialogue boes="2.0.0">
<personality/>
</dialogue>

View File

@@ -0,0 +1,3 @@
<dialogue boes="2.0.0">
<personality id='0'/>
</dialogue>

View File

@@ -0,0 +1,7 @@
<town boes="2.0.0">
<size>32</size>
<name>Hello World</name>
<creature id='1'>
<level/>
</creature>
</town>

View File

@@ -0,0 +1,5 @@
<town boes="2.0.0">
<size>32</size>
<name>Hello World</name>
<exit dir='up' x='0' y='0'/>
</town>

View File

@@ -0,0 +1,7 @@
<town boes="2.0.0">
<size>32</size>
<name>Hello World</name>
<flags>
<whoops/>
</flags>
</town>

View File

@@ -0,0 +1,7 @@
<town boes="2.0.0">
<size>32</size>
<name>Hello World</name>
<item id='1'>
<level/>
</item>
</town>

View File

@@ -0,0 +1,5 @@
<town boes="2.0.0">
<size>32</size>
<name>Hello World</name>
<onenter condition='kumquat'/>
</town>

View File

@@ -0,0 +1,5 @@
<town boes="2.0.0">
<size>32</size>
<name>Hello World</name>
<onexit dir='up'/>
</town>

View File

@@ -0,0 +1 @@
<town vers="2.0.0"></town>

View File

@@ -0,0 +1,3 @@
<town boes="2.0.0">
<size>1</size>
</town>

View File

@@ -0,0 +1,4 @@
<town boes="2.0.0">
<size>32</size>
<error/>
</town>

View File

@@ -0,0 +1,7 @@
<town boes="2.0.0">
<size>32</size>
<name>Hello World</name>
<wandering>
<creature/>
</wandering>
</town>

View File

@@ -0,0 +1,5 @@
<town boes="2.0.0">
<size>32</size>
<name>Hello World</name>
<creature id='1'/>
</town>

View File

@@ -0,0 +1,5 @@
<town boes="2.0.0">
<size>32</size>
<name>Hello World</name>
<item id='1'/>
</town>

View File

@@ -0,0 +1,5 @@
<town boes="2.0.0">
<size>32</size>
<name>Hello World</name>
<wandering/>
</town>

View File

@@ -0,0 +1,8 @@
<town boes="2.0.0">
<size>32</size>
<name>Test Town</name>
<bounds top='4' left='4' right='28' bottom='28'/>
<difficulty>1</difficulty>
<lighting>lit</lighting>
<flags/>
</town>

View File

@@ -0,0 +1 @@
<town boes="2.0.0"></town>

View File

@@ -0,0 +1 @@
<town></town>

View File

@@ -0,0 +1,4 @@
<town boes="2.0.0">
<name>Hello World</name>
<size>32</size>
</town>

View File

@@ -0,0 +1,8 @@
<town boes="2.0.0">
<size>32</size>
<name>Hello World</name>
<comment>This</comment>
<comment>is</comment>
<comment>a</comment>
<comment>comment</comment>
</town>

View File

@@ -0,0 +1,13 @@
<town boes="2.0.0">
<size>32</size>
<name>Hello World</name>
<timer freq='10'>0</timer>
<timer freq='10'>0</timer>
<timer freq='10'>0</timer>
<timer freq='10'>0</timer>
<timer freq='10'>0</timer>
<timer freq='10'>0</timer>
<timer freq='10'>0</timer>
<timer freq='10'>0</timer>
<timer freq='10'>0</timer>
</town>

85
test/out_read.cpp Normal file
View File

@@ -0,0 +1,85 @@
//
// out_read.cpp
// BoE
//
// Created by Celtic Minstrel on 15-08-27.
//
//
#include <fstream>
#include "ticpp.h"
#include "catch.hpp"
#include "dialog.hpp"
#include "scenario.hpp"
#include "outdoors.hpp"
using namespace std;
using namespace ticpp;
extern Document xmlDocFromStream(istream& stream, string name);
extern void readOutdoorsFromXml(Document&& data, cOutdoors& out);
TEST_CASE("Loading an outdoor section definition") {
ifstream fin;
cScenario scen;
cOutdoors sector(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(readOutdoorsFromXml(move(doc), sector), xBadNode);
}
SECTION("When the version attribute is missing") {
fin.open("files/outdoor/no_version.xml");
doc = xmlDocFromStream(fin, "no_version.xml");
REQUIRE_THROWS_AS(readOutdoorsFromXml(move(doc), sector), xMissingAttr);
}
SECTION("When the root tag has a bad attribute") {
fin.open("files/outdoor/bad_root_attr.xml");
doc = xmlDocFromStream(fin, "bad_root_attr.xml");
REQUIRE_THROWS_AS(readOutdoorsFromXml(move(doc), sector), xBadAttr);
}
SECTION("When an essential toplevel element is missing") {
fin.open("files/outdoor/missing_toplevel.xml");
doc = xmlDocFromStream(fin, "missing_toplevel.xml");
REQUIRE_THROWS_AS(readOutdoorsFromXml(move(doc), sector), xMissingElem);
}
SECTION("When an invalid toplevel element is present") {
fin.open("files/outdoor/bad_toplevel.xml");
doc = xmlDocFromStream(fin, "bad_toplevel.xml");
REQUIRE_THROWS_AS(readOutdoorsFromXml(move(doc), sector), xBadNode);
}
SECTION("When an encounter has an invalid subtag") {
fin.open("files/outdoor/encounter_bad_node.xml");
doc = xmlDocFromStream(fin, "encounter_bad_node.xml");
REQUIRE_THROWS_AS(readOutdoorsFromXml(move(doc), sector), xBadNode);
}
SECTION("When an encounter has no monsters") {
fin.open("files/outdoor/encounter_empty.xml");
doc = xmlDocFromStream(fin, "encounter_empty.xml");
REQUIRE_THROWS_AS(readOutdoorsFromXml(move(doc), sector), xMissingElem);
}
SECTION("When an encounter has too many monsters") {
fin.open("files/outdoor/encounter_too_many_monst.xml");
doc = xmlDocFromStream(fin, "encounter_too_many_monst.xml");
REQUIRE_THROWS_AS(readOutdoorsFromXml(move(doc), sector), xBadNode);
}
SECTION("When an encounter monster has an invalid attribute") {
fin.open("files/outdoor/encounter_bad_attr.xml");
doc = xmlDocFromStream(fin, "encounter_bad_attr.xml");
REQUIRE_THROWS_AS(readOutdoorsFromXml(move(doc), sector), xBadAttr);
}
SECTION("When there are too many encounters") {
fin.open("files/outdoor/encounter_too_many.xml");
doc = xmlDocFromStream(fin, "encounter_too_many.xml");
REQUIRE_THROWS_AS(readOutdoorsFromXml(move(doc), sector), xBadNode);
}
SECTION("With the minimal required data") {
fin.open("files/outdoor/minimal.xml");
doc = xmlDocFromStream(fin, "minimal.xml");
REQUIRE_NOTHROW(readOutdoorsFromXml(move(doc), sector));
CHECK(sector.out_name == "Test Sector");
}
}

114
test/talk_read.cpp Normal file
View File

@@ -0,0 +1,114 @@
//
// talk_read.cpp
// BoE
//
// Created by Celtic Minstrel on 15-08-27.
//
//
#include <fstream>
#include "ticpp.h"
#include "catch.hpp"
#include "dialog.hpp"
#include "talking.hpp"
using namespace std;
using namespace ticpp;
extern Document xmlDocFromStream(istream& stream, string name);
extern void readDialogueFromXml(Document&& data, cSpeech& talk, int town_num);
TEST_CASE("Loading a town dialogue definition") {
ifstream fin;
cSpeech talk;
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(readDialogueFromXml(move(doc), talk, 0), xBadNode);
}
SECTION("When the version attribute is missing") {
fin.open("files/talk/no_version.xml");
doc = xmlDocFromStream(fin, "no_version.xml");
REQUIRE_THROWS_AS(readDialogueFromXml(move(doc), talk, 0), xMissingAttr);
}
SECTION("When the root tag has a bad attribute") {
fin.open("files/talk/bad_root_attr.xml");
doc = xmlDocFromStream(fin, "bad_root_attr.xml");
REQUIRE_THROWS_AS(readDialogueFromXml(move(doc), talk, 0), xBadAttr);
}
SECTION("When an invalid toplevel node is found") {
fin.open("files/talk/bad_node.xml");
doc = xmlDocFromStream(fin, "bad_node.xml");
REQUIRE_THROWS_AS(readDialogueFromXml(move(doc), talk, 0), xBadNode);
}
SECTION("When the root tag is empty") {
fin.open("files/talk/empty.xml");
doc = xmlDocFromStream(fin, "empty.xml");
REQUIRE_NOTHROW(readDialogueFromXml(move(doc), talk, 0));
}
SECTION("When a personality is missing an ID") {
fin.open("files/talk/who_missing_id.xml");
doc = xmlDocFromStream(fin, "who_missing_id.xml");
REQUIRE_THROWS_AS(readDialogueFromXml(move(doc), talk, 0), Exception);
}
SECTION("When a personality has an out-of-bounds ID") {
fin.open("files/talk/who_bad_id.xml");
doc = xmlDocFromStream(fin, "who_bad_id.xml");
REQUIRE_THROWS_AS(readDialogueFromXml(move(doc), talk, 0), xBadVal);
}
SECTION("When a personality is missing a required subtag") {
fin.open("files/talk/who_missing_req.xml");
doc = xmlDocFromStream(fin, "who_missing_req.xml");
REQUIRE_THROWS_AS(readDialogueFromXml(move(doc), talk, 0), xMissingElem);
}
SECTION("When a personality has an invalid subtag") {
fin.open("files/talk/who_bad_node.xml");
doc = xmlDocFromStream(fin, "who_bad_node.xml");
REQUIRE_THROWS_AS(readDialogueFromXml(move(doc), talk, 0), xBadNode);
}
SECTION("When node has an invalid subtag") {
fin.open("files/talk/node_bad_node.xml");
doc = xmlDocFromStream(fin, "node_bad_node.xml");
REQUIRE_THROWS_AS(readDialogueFromXml(move(doc), talk, 0), xBadNode);
}
SECTION("When a node is missing the for attribute") {
fin.open("files/talk/node_missing_for.xml");
doc = xmlDocFromStream(fin, "node_missing_for.xml");
REQUIRE_THROWS_AS(readDialogueFromXml(move(doc), talk, 0), Exception);
}
SECTION("When a node is missing the <key> subtag") {
fin.open("files/talk/node_missing_key.xml");
doc = xmlDocFromStream(fin, "node_missing_key.xml");
REQUIRE_THROWS_AS(readDialogueFromXml(move(doc), talk, 0), xMissingElem);
}
SECTION("When a node is missing the <type> subtag") {
fin.open("files/talk/node_missing_type.xml");
doc = xmlDocFromStream(fin, "node_missing_type.xml");
REQUIRE_THROWS_AS(readDialogueFromXml(move(doc), talk, 0), xMissingElem);
}
SECTION("When a node is missing the <text> subtag") {
fin.open("files/talk/node_missing_string.xml");
doc = xmlDocFromStream(fin, "node_missing_string.xml");
REQUIRE_THROWS_AS(readDialogueFromXml(move(doc), talk, 0), xMissingElem);
}
SECTION("When a node has too many keys") {
fin.open("files/talk/node_too_many_keys.xml");
doc = xmlDocFromStream(fin, "node_too_many_keys.xml");
REQUIRE_THROWS_AS(readDialogueFromXml(move(doc), talk, 0), xBadNode);
}
SECTION("When a node has too many params") {
fin.open("files/talk/node_too_many_params.xml");
doc = xmlDocFromStream(fin, "node_too_many_params.xml");
REQUIRE_THROWS_AS(readDialogueFromXml(move(doc), talk, 0), xBadNode);
}
SECTION("When a node has too many strings") {
fin.open("files/talk/node_too_many_strings.xml");
doc = xmlDocFromStream(fin, "node_too_many_strings.xml");
REQUIRE_THROWS_AS(readDialogueFromXml(move(doc), talk, 0), xBadNode);
}
}

131
test/town_read.cpp Normal file
View File

@@ -0,0 +1,131 @@
//
// town_read.cpp
// BoE
//
// Created by Celtic Minstrel on 15-08-27.
//
//
#include <fstream>
#include "ticpp.h"
#include "catch.hpp"
#include "dialog.hpp"
#include "scenario.hpp"
#include "town.hpp"
using namespace std;
using namespace ticpp;
extern Document xmlDocFromStream(istream& stream, string name);
extern void readTownFromXml(Document&& data, cTown*& town, cScenario& scen);
TEST_CASE("Loading a town definition") {
ifstream fin;
cScenario scen;
cTown* town = nullptr;
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(readTownFromXml(move(doc), town, scen), xBadNode);
}
SECTION("When the version attribute is missing") {
fin.open("files/town/no_version.xml");
doc = xmlDocFromStream(fin, "no_version.xml");
REQUIRE_THROWS_AS(readTownFromXml(move(doc), town, scen), xMissingAttr);
}
SECTION("When the root tag has a bad attribute") {
fin.open("files/town/bad_root_attr.xml");
doc = xmlDocFromStream(fin, "bad_root_attr.xml");
REQUIRE_THROWS_AS(readTownFromXml(move(doc), town, scen), xBadAttr);
}
SECTION("When an essential toplevel element is missing") {
fin.open("files/town/missing_toplevel.xml");
doc = xmlDocFromStream(fin, "missing_toplevel.xml");
REQUIRE_THROWS_AS(readTownFromXml(move(doc), town, scen), xMissingElem);
}
SECTION("When the size is not first") {
fin.open("files/town/size_not_first.xml");
doc = xmlDocFromStream(fin, "size_not_first.xml");
REQUIRE_THROWS_AS(readTownFromXml(move(doc), town, scen), xBadNode);
}
SECTION("When there is an invalid toplevel node") {
fin.open("files/town/bad_toplevel.xml");
doc = xmlDocFromStream(fin, "bad_toplevel.xml");
REQUIRE_THROWS_AS(readTownFromXml(move(doc), town, scen), xBadNode);
}
SECTION("When there are too many comments") {
fin.open("files/town/too_many_comments.xml");
doc = xmlDocFromStream(fin, "too_many_comments.xml");
REQUIRE_THROWS_AS(readTownFromXml(move(doc), town, scen), xBadNode);
}
SECTION("When the onenter condition is invalid") {
fin.open("files/town/bad_onenter_condition.xml");
doc = xmlDocFromStream(fin, "bad_onenter_condition.xml");
REQUIRE_THROWS_AS(readTownFromXml(move(doc), town, scen), xBadVal);
}
SECTION("When the onexit direction is invalid") {
fin.open("files/town/bad_onexit_dir.xml");
doc = xmlDocFromStream(fin, "bad_onexit_dir.xml");
REQUIRE_THROWS_AS(readTownFromXml(move(doc), town, scen), xBadVal);
}
SECTION("When the exit direction is invalid") {
fin.open("files/town/bad_exit_dir.xml");
doc = xmlDocFromStream(fin, "bad_exit_dir.xml");
REQUIRE_THROWS_AS(readTownFromXml(move(doc), town, scen), xBadVal);
}
SECTION("When there are too many timers") {
fin.open("files/town/too_many_timers.xml");
doc = xmlDocFromStream(fin, "too_many_timers.xml");
REQUIRE_THROWS_AS(readTownFromXml(move(doc), town, scen), xBadNode);
}
SECTION("When there is an invalid flag") {
fin.open("files/town/bad_flag.xml");
doc = xmlDocFromStream(fin, "bad_flag.xml");
REQUIRE_THROWS_AS(readTownFromXml(move(doc), town, scen), xBadNode);
}
SECTION("When there is a bad wandering definition") {
fin.open("files/town/bad_wandering.xml");
doc = xmlDocFromStream(fin, "bad_wandering.xml");
REQUIRE_THROWS_AS(readTownFromXml(move(doc), town, scen), xBadNode);
}
SECTION("When there is an empty wandering definition") {
fin.open("files/town/empty_wandering.xml");
doc = xmlDocFromStream(fin, "empty_wandering.xml");
REQUIRE_THROWS_AS(readTownFromXml(move(doc), town, scen), xMissingElem);
}
SECTION("When there is a preset item with an invalid tag") {
fin.open("files/town/bad_item.xml");
doc = xmlDocFromStream(fin, "bad_item.xml");
REQUIRE_THROWS_AS(readTownFromXml(move(doc), town, scen), xBadNode);
}
SECTION("When there is a preset item without a type") {
fin.open("files/town/empty_item.xml");
doc = xmlDocFromStream(fin, "empty_item.xml");
REQUIRE_THROWS_AS(readTownFromXml(move(doc), town, scen), xMissingElem);
}
SECTION("When there is a preset creature with an invalid tag") {
fin.open("files/town/bad_creature.xml");
doc = xmlDocFromStream(fin, "bad_creature.xml");
REQUIRE_THROWS_AS(readTownFromXml(move(doc), town, scen), xBadNode);
}
SECTION("When there is a preset creature without a type") {
fin.open("files/town/empty_creature.xml");
doc = xmlDocFromStream(fin, "empty_creature.xml");
REQUIRE_THROWS_AS(readTownFromXml(move(doc), town, scen), xMissingElem);
}
SECTION("With the minimal required data") {
fin.open("files/town/minimal.xml");
doc = xmlDocFromStream(fin, "minimal.xml");
REQUIRE_NOTHROW(readTownFromXml(move(doc), town, scen));
CHECK(town->max_dim() == 32);
CHECK(town->town_name == "Test Town");
CHECK(town->in_town_rect == rect(4, 4, 28, 28));
CHECK(town->difficulty == 1);
CHECK(town->lighting_type == LIGHT_NORMAL);
}
delete town;
}