much more tests; all exceptions in readin tested

master
Marc Wäckerlin 16 years ago
parent 0965b21e27
commit e48b91683e
  1. 12
      src/xml-cxx/xml.hxx
  2. 19
      src/xml.cxx
  3. 104
      test/xml_test.cxx

@ -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

@ -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);

Loading…
Cancel
Save