much more tests; all exceptions in readin tested
This commit is contained in:
@@ -189,13 +189,6 @@ namespace xml {
|
|||||||
stream_error("missing end tag, end of file reached", t, is, tag, c) {
|
stream_error("missing end tag, end of file reached", t, is, tag, c) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
class empty_stream: public stream_error {
|
|
||||||
public:
|
|
||||||
empty_stream(const Node& t, std::istream& is, const Tag& tag, char c=0)
|
|
||||||
throw():
|
|
||||||
stream_error("no xml tag found, stream is empty", t, is, tag, c) {
|
|
||||||
}
|
|
||||||
};
|
|
||||||
class wrong_start_tag: public stream_error {
|
class wrong_start_tag: public stream_error {
|
||||||
public:
|
public:
|
||||||
wrong_start_tag(const Node& t, std::istream& is, const Tag& tag, char c=0)
|
wrong_start_tag(const Node& t, std::istream& is, const Tag& tag, char c=0)
|
||||||
@@ -303,7 +296,8 @@ namespace xml {
|
|||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
//! An xml Node.
|
//! An xml Node.
|
||||||
/*! XML Nodes may contain either text or other nodes, but not both
|
/*! XML Nodes may contain either text or other nodes, but not both
|
||||||
at the same time. */
|
at the same time. This node can hold other nodes. For a Node for
|
||||||
|
text contents, see xml::String. */
|
||||||
class Node {
|
class Node {
|
||||||
private:
|
private:
|
||||||
typedef std::vector<Node*> Contents;
|
typedef std::vector<Node*> Contents;
|
||||||
@@ -398,7 +392,7 @@ namespace xml {
|
|||||||
throw(wrong_end_tag, wrong_start_tag, tag_expected, type_mismatch,
|
throw(wrong_end_tag, wrong_start_tag, tag_expected, type_mismatch,
|
||||||
second_slash_in_tag, character_after_slash,
|
second_slash_in_tag, character_after_slash,
|
||||||
missing_end_tag, attribute_value_not_quoted, access_error,
|
missing_end_tag, attribute_value_not_quoted, access_error,
|
||||||
empty_stream, duplicate_attribute, attributes_in_end_tag);
|
duplicate_attribute, attributes_in_end_tag);
|
||||||
private:
|
private:
|
||||||
friend class stream_error;
|
friend class stream_error;
|
||||||
Factory(); // not implemented
|
Factory(); // not implemented
|
||||||
|
19
src/xml.cxx
19
src/xml.cxx
@@ -426,15 +426,13 @@ namespace xml {
|
|||||||
throw(tag_expected, type_mismatch) {
|
throw(tag_expected, type_mismatch) {
|
||||||
std::string::size_type
|
std::string::size_type
|
||||||
start(txt.find_first_not_of(" \t\n\r")),
|
start(txt.find_first_not_of(" \t\n\r")),
|
||||||
last(txt.find_last_of(" \t\n\r"));
|
last(txt.find_last_not_of(" \t\n\r"));
|
||||||
if (start==std::string::npos) { // empty - set to 0
|
if (start==std::string::npos) { // empty - set to 0
|
||||||
_text = "0";
|
_text = "0";
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
if (txt.find_first_not_of
|
std::string::size_type pos(txt.find_first_not_of("0123456789", start));
|
||||||
("0123456789", start,
|
if (pos<last || pos==last && last==start)
|
||||||
last!=std::string::npos?last-start+1:txt.size()-start)
|
|
||||||
!=std::string::npos)
|
|
||||||
throw type_mismatch(*this, txt,
|
throw type_mismatch(*this, txt,
|
||||||
"unsigned integer may only contain numbers");
|
"unsigned integer may only contain numbers");
|
||||||
unsigned long i(0);
|
unsigned long i(0);
|
||||||
@@ -463,24 +461,25 @@ namespace xml {
|
|||||||
throw(wrong_end_tag, wrong_start_tag, tag_expected, type_mismatch,
|
throw(wrong_end_tag, wrong_start_tag, tag_expected, type_mismatch,
|
||||||
second_slash_in_tag,
|
second_slash_in_tag,
|
||||||
character_after_slash, missing_end_tag, attribute_value_not_quoted,
|
character_after_slash, missing_end_tag, attribute_value_not_quoted,
|
||||||
access_error, empty_stream, duplicate_attribute,
|
access_error, duplicate_attribute,
|
||||||
attributes_in_end_tag) try {
|
attributes_in_end_tag) try {
|
||||||
_line=1;
|
_line=1;
|
||||||
std::auto_ptr<Node> node(_template->clone());
|
std::auto_ptr<Node> node(_template->clone());
|
||||||
node->clear();
|
node->clear();
|
||||||
Tag res;
|
Tag res;
|
||||||
while (true) try {
|
while (true) {
|
||||||
res = tag(is, *node);
|
res = tag(is, *node);
|
||||||
*node<<res.attributes;
|
*node<<res.attributes;
|
||||||
switch (res.type) {
|
switch (res.type) {
|
||||||
case END: throw wrong_end_tag(*node, is, res);
|
case END: throw wrong_end_tag(*node, is, res);
|
||||||
case EMPTY: return node; // empty
|
case EMPTY: return node; // empty
|
||||||
case START: return read(is, *_template);
|
case START:
|
||||||
|
if (!res.name.size()) throw tag_expected(*node, res.text);
|
||||||
|
if (node->name()!=res.name) throw wrong_start_tag(*node, is, res);
|
||||||
|
return read(is, *_template);
|
||||||
//! @todo store instead of ignore
|
//! @todo store instead of ignore
|
||||||
case SPECIAL: break;
|
case SPECIAL: break;
|
||||||
}
|
}
|
||||||
} catch (missing_end_tag&) {
|
|
||||||
throw empty_stream(*node, is, res);
|
|
||||||
}
|
}
|
||||||
} catch (exception& e) {
|
} catch (exception& e) {
|
||||||
e.line(_line);
|
e.line(_line);
|
||||||
|
@@ -161,6 +161,106 @@ class StringTest: public CppUnit::TestFixture {
|
|||||||
};
|
};
|
||||||
CPPUNIT_TEST_SUITE_REGISTRATION(StringTest);
|
CPPUNIT_TEST_SUITE_REGISTRATION(StringTest);
|
||||||
|
|
||||||
|
class ComplexTest: public CppUnit::TestFixture {
|
||||||
|
public:
|
||||||
|
void nodes() {
|
||||||
|
xml::Factory factory(xml::Node("base")
|
||||||
|
<<(xml::Node("child").attr("a", xml::optional)
|
||||||
|
<<xml::String("childofchild")
|
||||||
|
<<xml::UnsignedInteger("number"))
|
||||||
|
<<xml::Node("otherchild"));
|
||||||
|
std::stringstream file1;
|
||||||
|
file1<<"<!DOCTYPE xyz>"<<std::endl
|
||||||
|
<<"<?xml 1.0 encoding=\"utf8\"?>"<<std::endl
|
||||||
|
<<"<base>"<<std::endl
|
||||||
|
<<"<child a=\"b\"><childofchild/><childofchild/><childofchild>"
|
||||||
|
<<"xxx</childofchild><number>13</number><number/><number>"
|
||||||
|
<<" 42 </number><number> </number></child>"
|
||||||
|
<<"<child a=\"b\"/>"
|
||||||
|
<<"< otherchild >< / otherchild >< otherchild / >"<<std::endl
|
||||||
|
<<"</base>";
|
||||||
|
std::auto_ptr<xml::Node> node(factory.read(file1)); // should work
|
||||||
|
CPPUNIT_ASSERT_EQUAL((size_t)2, node->list("child").size());
|
||||||
|
CPPUNIT_ASSERT_EQUAL((size_t)3, (*node)[0].list("childofchild").size());
|
||||||
|
CPPUNIT_ASSERT_EQUAL((size_t)4, (*node)[0].list("number").size());
|
||||||
|
CPPUNIT_ASSERT_EQUAL((size_t)0, (*node)[1].list("childofchild").size());
|
||||||
|
CPPUNIT_ASSERT_EQUAL((size_t)2, node->list("otherchild").size());
|
||||||
|
CPPUNIT_ASSERT_EQUAL(std::string("xxx"), *(*node)["child"][2]);
|
||||||
|
CPPUNIT_ASSERT_EQUAL(std::string("13"), *(*node)["child"][3]);
|
||||||
|
CPPUNIT_ASSERT_EQUAL(std::string("0"), *(*node)["child"][4]);
|
||||||
|
CPPUNIT_ASSERT_EQUAL(std::string("42"), *(*node)["child"][5]);
|
||||||
|
CPPUNIT_ASSERT_EQUAL(std::string("0"), *(*node)["child"][6]);
|
||||||
|
std::stringstream file2;
|
||||||
|
file2<<"<!DOCTYPE xyz>"<<std::endl
|
||||||
|
<<"<?xml 1.0 encoding=\"utf8\"?>"<<std::endl
|
||||||
|
<<"<base>"<<std::endl
|
||||||
|
<<"<child><childofchild/><exception><childofchild/><childofchild>"
|
||||||
|
<<"xxx</childofchild></child>"
|
||||||
|
<<"<child/>"
|
||||||
|
<<"< otherchild >< / otherchild >< otherchild / >"<<std::endl
|
||||||
|
<<"</base>";
|
||||||
|
CPPUNIT_ASSERT_THROW(factory.read(file2), xml::access_error);
|
||||||
|
{
|
||||||
|
std::stringstream file("<base></xyz>");
|
||||||
|
CPPUNIT_ASSERT_THROW(factory.read(file), xml::wrong_end_tag);
|
||||||
|
} {
|
||||||
|
std::stringstream file("<xyz></xyz>");
|
||||||
|
CPPUNIT_ASSERT_THROW(factory.read(file), xml::wrong_start_tag);
|
||||||
|
} {
|
||||||
|
std::stringstream file("base");
|
||||||
|
CPPUNIT_ASSERT_THROW(factory.read(file), xml::tag_expected);
|
||||||
|
} {
|
||||||
|
std::stringstream file("<base>hallo</base>");
|
||||||
|
CPPUNIT_ASSERT_THROW(factory.read(file), xml::tag_expected);
|
||||||
|
} {
|
||||||
|
std::stringstream file
|
||||||
|
("<base><child><number>x</number></child></base>");
|
||||||
|
CPPUNIT_ASSERT_THROW(factory.read(file), xml::type_mismatch);
|
||||||
|
} {
|
||||||
|
std::stringstream file
|
||||||
|
("<base><child><number>xyz</number></child></base>");
|
||||||
|
CPPUNIT_ASSERT_THROW(factory.read(file), xml::type_mismatch);
|
||||||
|
} {
|
||||||
|
std::stringstream file("<base><child></child/></base>");
|
||||||
|
CPPUNIT_ASSERT_THROW(factory.read(file), xml::second_slash_in_tag);
|
||||||
|
} {
|
||||||
|
std::stringstream file("<base><child><child/a></base>");
|
||||||
|
CPPUNIT_ASSERT_THROW(factory.read(file), xml::character_after_slash);
|
||||||
|
} {
|
||||||
|
std::stringstream file("<base>");
|
||||||
|
CPPUNIT_ASSERT_THROW(factory.read(file), xml::missing_end_tag);
|
||||||
|
} {
|
||||||
|
std::stringstream file("<base><child>");
|
||||||
|
CPPUNIT_ASSERT_THROW(factory.read(file), xml::missing_end_tag);
|
||||||
|
} {
|
||||||
|
std::stringstream file;
|
||||||
|
CPPUNIT_ASSERT_THROW(factory.read(file), xml::missing_end_tag);
|
||||||
|
} {
|
||||||
|
std::stringstream file("<base><child a=b></base>");
|
||||||
|
CPPUNIT_ASSERT_THROW(factory.read(file),
|
||||||
|
xml::attribute_value_not_quoted);
|
||||||
|
} {
|
||||||
|
std::stringstream file("<base><child a=\"b\" a=\"b\"></base>");
|
||||||
|
CPPUNIT_ASSERT_THROW(factory.read(file), xml::duplicate_attribute);
|
||||||
|
} {
|
||||||
|
std::stringstream file("<base><child></child a=\"b\"></base>");
|
||||||
|
CPPUNIT_ASSERT_THROW(factory.read(file), xml::attributes_in_end_tag);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void attributes() {
|
||||||
|
xml::Factory factory(xml::Node("base")
|
||||||
|
<<(xml::Node("child")
|
||||||
|
<<xml::String("childofchild")
|
||||||
|
<<xml::UnsignedInteger("number"))
|
||||||
|
<<xml::Node("otherchild"));
|
||||||
|
}
|
||||||
|
CPPUNIT_TEST_SUITE(ComplexTest);
|
||||||
|
CPPUNIT_TEST(nodes);
|
||||||
|
CPPUNIT_TEST(attributes);
|
||||||
|
CPPUNIT_TEST_SUITE_END();
|
||||||
|
};
|
||||||
|
CPPUNIT_TEST_SUITE_REGISTRATION(ComplexTest);
|
||||||
|
|
||||||
class FunTest: public CppUnit::TestFixture {
|
class FunTest: public CppUnit::TestFixture {
|
||||||
public:
|
public:
|
||||||
void playing() {
|
void playing() {
|
||||||
@@ -276,9 +376,9 @@ class FunTest: public CppUnit::TestFixture {
|
|||||||
<<(xml::String("application")
|
<<(xml::String("application")
|
||||||
.attr("id", xml::mandatory)
|
.attr("id", xml::mandatory)
|
||||||
.attr("os", xml::optional))));
|
.attr("os", xml::optional))));
|
||||||
std::cout<<std::endl
|
/*std::cout<<std::endl
|
||||||
<<*applications<<std::endl
|
<<*applications<<std::endl
|
||||||
<<*edition<<std::endl;
|
<<*edition<<std::endl;*/
|
||||||
}
|
}
|
||||||
CPPUNIT_TEST_SUITE(FunTest);
|
CPPUNIT_TEST_SUITE(FunTest);
|
||||||
CPPUNIT_TEST(playing);
|
CPPUNIT_TEST(playing);
|
||||||
|
Reference in New Issue
Block a user