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