LCOV - code coverage report
Current view: top level - tests - catch_parser.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 432 432 100.0 %
Date: 2022-11-20 20:56:31 Functions: 4 4 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : // Copyright (c) 2019-2022  Made to Order Software Corp.  All Rights Reserved
       2             : //
       3             : // https://snapwebsites.org/project/basic-xml
       4             : // contact@m2osw.com
       5             : //
       6             : // This program is free software: you can redistribute it and/or modify
       7             : // it under the terms of the GNU General Public License as published by
       8             : // the Free Software Foundation, either version 3 of the License, or
       9             : // (at your option) any later version.
      10             : //
      11             : // This program is distributed in the hope that it will be useful,
      12             : // but WITHOUT ANY WARRANTY; without even the implied warranty of
      13             : // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14             : // GNU General Public License for more details.
      15             : //
      16             : // You should have received a copy of the GNU General Public License
      17             : // along with this program.  If not, see <https://www.gnu.org/licenses/>.
      18             : 
      19             : // self
      20             : //
      21             : #include    "catch_main.h"
      22             : 
      23             : 
      24             : // basic-xml
      25             : //
      26             : #include    <basic-xml/exception.h>
      27             : #include    <basic-xml/parser.h>
      28             : 
      29             : 
      30             : // C++
      31             : //
      32             : #include    <sstream>
      33             : 
      34             : 
      35             : 
      36          10 : CATCH_TEST_CASE("parser", "[parser][valid]")
      37             : {
      38          16 :     CATCH_START_SECTION("empty root")
      39             :     {
      40           2 :         std::string const filename("empty-tag.xml");
      41             : 
      42           2 :         std::stringstream ss;
      43           1 :         ss << "<empty></empty>";
      44             : 
      45           2 :         basic_xml::node::pointer_t root;
      46           2 :         basic_xml::parser p(filename, ss, root);
      47           1 :         CATCH_REQUIRE(root != nullptr);
      48           1 :         CATCH_REQUIRE(root->tag_name() == "empty");
      49           1 :         CATCH_REQUIRE(root->text().empty());
      50           1 :         CATCH_REQUIRE(root->all_attributes().empty());
      51           1 :         CATCH_REQUIRE(root->parent() == nullptr);
      52           1 :         CATCH_REQUIRE(root->first_child() == nullptr);
      53           1 :         CATCH_REQUIRE(root->last_child() == nullptr);
      54           1 :         CATCH_REQUIRE(root->next() == nullptr);
      55           1 :         CATCH_REQUIRE(root->previous() == nullptr);
      56             :     }
      57             :     CATCH_END_SECTION()
      58             : 
      59          16 :     CATCH_START_SECTION("empty root with processor")
      60             :     {
      61           2 :         std::string const filename("empty-tag.xml");
      62             : 
      63           2 :         std::stringstream ss;
      64           1 :         ss << "<?xml version=\"1.0\"?><still-empty></still-empty>";
      65             : 
      66           2 :         basic_xml::node::pointer_t root;
      67           2 :         basic_xml::parser p(filename, ss, root);
      68           1 :         CATCH_REQUIRE(root != nullptr);
      69           1 :         CATCH_REQUIRE(root->tag_name() == "still-empty");
      70           1 :         CATCH_REQUIRE(root->text().empty());
      71           1 :         CATCH_REQUIRE(root->all_attributes().empty());
      72           1 :         CATCH_REQUIRE(root->parent() == nullptr);
      73           1 :         CATCH_REQUIRE(root->first_child() == nullptr);
      74           1 :         CATCH_REQUIRE(root->last_child() == nullptr);
      75           1 :         CATCH_REQUIRE(root->next() == nullptr);
      76           1 :         CATCH_REQUIRE(root->previous() == nullptr);
      77             :     }
      78             :     CATCH_END_SECTION()
      79             : 
      80          16 :     CATCH_START_SECTION("empty root with comment & processor")
      81             :     {
      82           2 :         std::string const filename("quite-empty.xml");
      83             : 
      84           2 :         std::stringstream ss;
      85           1 :         ss << "<!-- name='rotor' --><?xml version=\"1.0\"?><quite-empty></quite-empty>";
      86             : 
      87           2 :         basic_xml::node::pointer_t root;
      88           2 :         basic_xml::parser p(filename, ss, root);
      89           1 :         CATCH_REQUIRE(root != nullptr);
      90           1 :         CATCH_REQUIRE(root->tag_name() == "quite-empty");
      91           1 :         CATCH_REQUIRE(root->text().empty());
      92           1 :         CATCH_REQUIRE(root->all_attributes().empty());
      93           1 :         CATCH_REQUIRE(root->parent() == nullptr);
      94           1 :         CATCH_REQUIRE(root->first_child() == nullptr);
      95           1 :         CATCH_REQUIRE(root->last_child() == nullptr);
      96           1 :         CATCH_REQUIRE(root->next() == nullptr);
      97           1 :         CATCH_REQUIRE(root->previous() == nullptr);
      98             :     }
      99             :     CATCH_END_SECTION()
     100             : 
     101          16 :     CATCH_START_SECTION("empty root with processor & comment")
     102             :     {
     103           2 :         std::string const filename("swapped-empty.xml");
     104             : 
     105           2 :         std::stringstream ss;
     106           1 :         ss << "<?xml version=\"1.0\"?><!-- name='rotor' --><swapped-empty></swapped-empty>";
     107             : 
     108           2 :         basic_xml::node::pointer_t root;
     109           2 :         basic_xml::parser p(filename, ss, root);
     110           1 :         CATCH_REQUIRE(root != nullptr);
     111           1 :         CATCH_REQUIRE(root->tag_name() == "swapped-empty");
     112           1 :         CATCH_REQUIRE(root->text().empty());
     113           1 :         CATCH_REQUIRE(root->all_attributes().empty());
     114           1 :         CATCH_REQUIRE(root->parent() == nullptr);
     115           1 :         CATCH_REQUIRE(root->first_child() == nullptr);
     116           1 :         CATCH_REQUIRE(root->last_child() == nullptr);
     117           1 :         CATCH_REQUIRE(root->next() == nullptr);
     118           1 :         CATCH_REQUIRE(root->previous() == nullptr);
     119             :     }
     120             :     CATCH_END_SECTION()
     121             : 
     122          16 :     CATCH_START_SECTION("empty root with comment & processor & attributes")
     123             :     {
     124           2 :         std::string const filename("root-attributes.xml");
     125             : 
     126           2 :         std::stringstream ss;
     127           1 :         ss << "<!--\n"
     128             :               "name='next level'\n"
     129             :               "-->\n"
     130             :               "\n"
     131             :               "<?xml version=\"1.0\"?>\n"
     132             :               "<root-canal quite=\"quite\" size='123' very=\"true\">"
     133             :               " \t \t \t "
     134             :               "</root-canal>";
     135             : 
     136           2 :         basic_xml::node::pointer_t root;
     137           2 :         basic_xml::parser p(filename, ss, root);
     138           1 :         CATCH_REQUIRE(root != nullptr);
     139           1 :         CATCH_REQUIRE(root->tag_name() == "root-canal");
     140           1 :         CATCH_REQUIRE(root->text() == "");
     141           1 :         CATCH_REQUIRE(root->text(true) == "");
     142           1 :         CATCH_REQUIRE(root->text(false) == " \t \t \t ");
     143           1 :         CATCH_REQUIRE(root->all_attributes().size() == 3);
     144           1 :         CATCH_REQUIRE(root->attribute("quite") == "quite");
     145           1 :         CATCH_REQUIRE(root->attribute("size") == "123");
     146           1 :         CATCH_REQUIRE(root->attribute("very") == "true");
     147           1 :         CATCH_REQUIRE(root->parent() == nullptr);
     148           1 :         CATCH_REQUIRE(root->first_child() == nullptr);
     149           1 :         CATCH_REQUIRE(root->last_child() == nullptr);
     150           1 :         CATCH_REQUIRE(root->next() == nullptr);
     151           1 :         CATCH_REQUIRE(root->previous() == nullptr);
     152             :     }
     153             :     CATCH_END_SECTION()
     154             : 
     155          16 :     CATCH_START_SECTION("entities test")
     156             :     {
     157           2 :         std::string const filename("entities.xml");
     158             : 
     159           2 :         std::stringstream ss;
     160           1 :         ss << "<!--\n"
     161             :               "name='entitie&#x73;'\n"
     162             :               "-->\n"
     163             :               "\n"
     164             :               "<?xml version=\"1.0\"?>\n"
     165             :               "<entity-a-gogo quite=\"&#x71;uit&#101;\" size='1&#x32;3'"
     166             :                   " very=\"&quot;true&quot;\" special-entry=\"&quot;&lt;it&apos;s special &amp; weird&gt;&quot;\">"
     167             :               "</entity-a-gogo><?php echo 'why am I ignoring these here?'; ?????>";
     168             : 
     169           2 :         basic_xml::node::pointer_t root;
     170           2 :         basic_xml::parser p(filename, ss, root);
     171           1 :         CATCH_REQUIRE(root != nullptr);
     172           1 :         CATCH_REQUIRE(root->tag_name() == "entity-a-gogo");
     173           1 :         CATCH_REQUIRE(root->all_attributes().size() == 4);
     174           1 :         CATCH_REQUIRE(root->attribute("quite") == "quite");
     175           1 :         CATCH_REQUIRE(root->attribute("size") == "123");
     176           1 :         CATCH_REQUIRE(root->attribute("very") == "\"true\"");
     177           1 :         CATCH_REQUIRE(root->attribute("special-entry") == "\"<it's special & weird>\"");
     178           1 :         CATCH_REQUIRE(root->parent() == nullptr);
     179           1 :         CATCH_REQUIRE(root->first_child() == nullptr);
     180           1 :         CATCH_REQUIRE(root->last_child() == nullptr);
     181           1 :         CATCH_REQUIRE(root->next() == nullptr);
     182           1 :         CATCH_REQUIRE(root->previous() == nullptr);
     183             :     }
     184             :     CATCH_END_SECTION()
     185             : 
     186          16 :     CATCH_START_SECTION("parse tree")
     187             :     {
     188           2 :         std::string const filename("tree.xml");
     189             : 
     190           2 :         std::stringstream ss;
     191           1 :         ss << "<!--\n"
     192             :               "name='tree'\n"
     193             :               "-->\n"
     194             :               "\n"
     195             :               "<?xml version=\"1.0\"?>\n"
     196             :               "<tree \t \f >"
     197             :                   "<       branch level='1'>"
     198             :                       "<leaf level = '2'>"
     199             :                         "with \f funny \t text \v and \r white \n spaces"
     200             :                       "</  leaf  >"
     201             :                   "</branch  >"
     202             :               "</  tree>\n \t \t \n";
     203             : 
     204           2 :         basic_xml::node::pointer_t root;
     205           2 :         basic_xml::parser p(filename, ss, root);
     206           1 :         CATCH_REQUIRE(root != nullptr);
     207           1 :         CATCH_REQUIRE(root->tag_name() == "tree");
     208           1 :         CATCH_REQUIRE(root->all_attributes().empty());
     209             : 
     210           2 :         basic_xml::node::pointer_t branch(root->first_child());
     211           1 :         CATCH_REQUIRE(branch->parent() == root);
     212           1 :         CATCH_REQUIRE(branch->root() == root);
     213           1 :         CATCH_REQUIRE(branch->all_attributes().size() == 1);
     214           1 :         CATCH_REQUIRE(branch->attribute("level") == "1");
     215             : 
     216           2 :         basic_xml::node::pointer_t leaf(branch->first_child());
     217           1 :         CATCH_REQUIRE(leaf->parent() == branch);
     218           1 :         CATCH_REQUIRE(leaf->root() == root);
     219           1 :         CATCH_REQUIRE(leaf->all_attributes().size() == 1);
     220           1 :         CATCH_REQUIRE(leaf->attribute("level") == "2");
     221           1 :         CATCH_REQUIRE(leaf->text() == "with \f funny \t text \v and \n white \n spaces");
     222             :     }
     223             :     CATCH_END_SECTION()
     224             : 
     225          16 :     CATCH_START_SECTION("parse tree (CDATA)")
     226             :     {
     227           2 :         std::string const filename("tree.xml");
     228             : 
     229           2 :         std::stringstream ss;
     230           1 :         ss << "<tree>"
     231             :                   "<branch level='1'>"
     232             :                       "<leaf level = '2'>"
     233             :                         "with \f funny \t text \v and \r white \n spaces and a > for fun"
     234             :                       "</  leaf  >"
     235             :                       "<leaf level = '2'>"
     236             :                         "<![CDATA[-> with \f funny \t text \v and \r white \n spaces <-]]>"
     237             :                       "</  leaf  >"
     238             :                   "</branch  >"
     239             :                   "<branch level=\"1\">"
     240             :                       "<leaf level=\"2\">"
     241             :                           "This one too has <![CDATA[some <need< for CDATA >and> such]]]]]>"
     242             :                       "</leaf>"
     243             :                       "<leaf level='2' ushes='warning'>=== text starts with equal ===</leaf>"
     244             :                       "<leaf level='2' feature='on'>>>> here it is</leaf>"
     245             :                       "<leaf level='2' message='perfect div'>/// next one ///</leaf>"
     246             :                       "<leaf level='2' hire=\"me\"><![CDATA[we have a case with ]] within the data]]></leaf>"
     247             :                       "<leaf level='2' width=\"250px\"><![CDATA[we have a case with one ] within the data too]]></leaf>"
     248             :                       "<leaf level='2' height=\"350px\">\"string data\"</leaf>"
     249             :                       "<leaf level='2' depth=\"35px\">'string data'</leaf>"
     250             :                       "<leaf level='2' z=\"-9\">bad & but we keep it quiet</leaf>"
     251             :                   "</ branch >"
     252             :                   "<branch level=\"1\" color='orange' />"
     253             :                   "<branch level=\"1\" color='purple'>"
     254             :                       "here is an equal = which I think works"
     255             :                   "</   branch   >"
     256             :               "</  tree>\n \t \t \n";
     257             : 
     258           2 :         basic_xml::node::pointer_t root;
     259           2 :         basic_xml::parser p(filename, ss, root);
     260           1 :         CATCH_REQUIRE(root != nullptr);
     261           1 :         CATCH_REQUIRE(root->tag_name() == "tree");
     262           1 :         CATCH_REQUIRE(root->all_attributes().empty());
     263             : 
     264           2 :         basic_xml::node::pointer_t branch1(root->first_child());
     265           1 :         CATCH_REQUIRE(branch1->parent() == root);
     266           1 :         CATCH_REQUIRE(branch1->root() == root);
     267           1 :         CATCH_REQUIRE(branch1->all_attributes().size() == 1);
     268           1 :         CATCH_REQUIRE(branch1->attribute("level") == "1");
     269             : 
     270           2 :         basic_xml::node::pointer_t leaf1_1(branch1->first_child());
     271           1 :         CATCH_REQUIRE(leaf1_1->parent() == branch1);
     272           1 :         CATCH_REQUIRE(leaf1_1->root() == root);
     273           1 :         CATCH_REQUIRE(leaf1_1->all_attributes().size() == 1);
     274           1 :         CATCH_REQUIRE(leaf1_1->attribute("level") == "2");
     275           1 :         CATCH_REQUIRE(leaf1_1->text() == "with \f funny \t text \v and \n white \n spaces and a > for fun");
     276             : 
     277           2 :         basic_xml::node::pointer_t leaf1_2(leaf1_1->next());
     278           1 :         CATCH_REQUIRE(leaf1_2->parent() == branch1);
     279           1 :         CATCH_REQUIRE(leaf1_2->root() == root);
     280           1 :         CATCH_REQUIRE(leaf1_2->all_attributes().size() == 1);
     281           1 :         CATCH_REQUIRE(leaf1_2->attribute("level") == "2");
     282           1 :         CATCH_REQUIRE(leaf1_2->text() == "-> with \f funny \t text \v and \n white \n spaces <-");
     283             : 
     284           2 :         basic_xml::node::pointer_t branch2(branch1->next());
     285           1 :         CATCH_REQUIRE(branch2->parent() == root);
     286           1 :         CATCH_REQUIRE(branch2->root() == root);
     287           1 :         CATCH_REQUIRE(branch2->all_attributes().size() == 1);
     288           1 :         CATCH_REQUIRE(branch2->attribute("level") == "1");
     289             : 
     290           2 :         basic_xml::node::pointer_t leaf2_1(branch2->first_child());
     291           1 :         CATCH_REQUIRE(leaf2_1->parent() == branch2);
     292           1 :         CATCH_REQUIRE(leaf2_1->root() == root);
     293           1 :         CATCH_REQUIRE(leaf2_1->all_attributes().size() == 1);
     294           1 :         CATCH_REQUIRE(leaf2_1->attribute("level") == "2");
     295           1 :         CATCH_REQUIRE(leaf2_1->text() == "This one too has some <need< for CDATA >and> such]]]");
     296             : 
     297           2 :         basic_xml::node::pointer_t leaf2_2(leaf2_1->next());
     298           1 :         CATCH_REQUIRE(leaf2_2->parent() == branch2);
     299           1 :         CATCH_REQUIRE(leaf2_2->root() == root);
     300           1 :         CATCH_REQUIRE(leaf2_2->all_attributes().size() == 2);
     301           1 :         CATCH_REQUIRE(leaf2_2->attribute("level") == "2");
     302           1 :         CATCH_REQUIRE(leaf2_2->attribute("ushes") == "warning");
     303           1 :         CATCH_REQUIRE(leaf2_2->text() == "=== text starts with equal ===");
     304             : 
     305           2 :         basic_xml::node::pointer_t leaf2_3(leaf2_2->next());
     306           1 :         CATCH_REQUIRE(leaf2_3->parent() == branch2);
     307           1 :         CATCH_REQUIRE(leaf2_3->root() == root);
     308           1 :         CATCH_REQUIRE(leaf2_3->all_attributes().size() == 2);
     309           1 :         CATCH_REQUIRE(leaf2_3->attribute("level") == "2");
     310           1 :         CATCH_REQUIRE(leaf2_3->attribute("feature") == "on");
     311           1 :         CATCH_REQUIRE(leaf2_3->text() == ">>> here it is");
     312             : 
     313           2 :         basic_xml::node::pointer_t leaf2_4(leaf2_3->next());
     314           1 :         CATCH_REQUIRE(leaf2_4->parent() == branch2);
     315           1 :         CATCH_REQUIRE(leaf2_4->root() == root);
     316           1 :         CATCH_REQUIRE(leaf2_4->all_attributes().size() == 2);
     317           1 :         CATCH_REQUIRE(leaf2_4->attribute("level") == "2");
     318           1 :         CATCH_REQUIRE(leaf2_4->attribute("message") == "perfect div");
     319           1 :         CATCH_REQUIRE(leaf2_4->text() == "/// next one ///");
     320             : 
     321           2 :         basic_xml::node::pointer_t leaf2_5(leaf2_4->next());
     322           1 :         CATCH_REQUIRE(leaf2_5->parent() == branch2);
     323           1 :         CATCH_REQUIRE(leaf2_5->root() == root);
     324           1 :         CATCH_REQUIRE(leaf2_5->all_attributes().size() == 2);
     325           1 :         CATCH_REQUIRE(leaf2_5->attribute("level") == "2");
     326           1 :         CATCH_REQUIRE(leaf2_5->attribute("hire") == "me");
     327           1 :         CATCH_REQUIRE(leaf2_5->text() == "we have a case with ]] within the data");
     328             : 
     329           2 :         basic_xml::node::pointer_t leaf2_6(leaf2_5->next());
     330           1 :         CATCH_REQUIRE(leaf2_6->parent() == branch2);
     331           1 :         CATCH_REQUIRE(leaf2_6->root() == root);
     332           1 :         CATCH_REQUIRE(leaf2_6->all_attributes().size() == 2);
     333           1 :         CATCH_REQUIRE(leaf2_6->attribute("level") == "2");
     334           1 :         CATCH_REQUIRE(leaf2_6->attribute("width") == "250px");
     335           1 :         CATCH_REQUIRE(leaf2_6->text() == "we have a case with one ] within the data too");
     336             : 
     337           2 :         basic_xml::node::pointer_t leaf2_7(leaf2_6->next());
     338           1 :         CATCH_REQUIRE(leaf2_7->parent() == branch2);
     339           1 :         CATCH_REQUIRE(leaf2_7->root() == root);
     340           1 :         CATCH_REQUIRE(leaf2_7->all_attributes().size() == 2);
     341           1 :         CATCH_REQUIRE(leaf2_7->attribute("level") == "2");
     342           1 :         CATCH_REQUIRE(leaf2_7->attribute("height") == "350px");
     343           1 :         CATCH_REQUIRE(leaf2_7->text() == "\"string data\"");
     344             : 
     345           2 :         basic_xml::node::pointer_t leaf2_8(leaf2_7->next());
     346           1 :         CATCH_REQUIRE(leaf2_8->parent() == branch2);
     347           1 :         CATCH_REQUIRE(leaf2_8->root() == root);
     348           1 :         CATCH_REQUIRE(leaf2_8->all_attributes().size() == 2);
     349           1 :         CATCH_REQUIRE(leaf2_8->attribute("level") == "2");
     350           1 :         CATCH_REQUIRE(leaf2_8->attribute("depth") == "35px");
     351           1 :         CATCH_REQUIRE(leaf2_8->text() == "'string data'");
     352             : 
     353           2 :         basic_xml::node::pointer_t leaf2_9(leaf2_8->next());
     354           1 :         CATCH_REQUIRE(leaf2_9->parent() == branch2);
     355           1 :         CATCH_REQUIRE(leaf2_9->root() == root);
     356           1 :         CATCH_REQUIRE(leaf2_9->all_attributes().size() == 2);
     357           1 :         CATCH_REQUIRE(leaf2_9->attribute("level") == "2");
     358           1 :         CATCH_REQUIRE(leaf2_9->attribute("z") == "-9");
     359           1 :         CATCH_REQUIRE(leaf2_9->text() == "bad & but we keep it quiet");
     360             : 
     361           2 :         basic_xml::node::pointer_t branch3(branch2->next());
     362           1 :         CATCH_REQUIRE(branch3->parent() == root);
     363           1 :         CATCH_REQUIRE(branch3->root() == root);
     364           1 :         CATCH_REQUIRE(branch3->all_attributes().size() == 2);
     365           1 :         CATCH_REQUIRE(branch3->attribute("level") == "1");
     366           1 :         CATCH_REQUIRE(branch3->attribute("color") == "orange");
     367           1 :         CATCH_REQUIRE(branch3->text().empty());
     368             : 
     369           2 :         basic_xml::node::pointer_t branch4(branch3->next());
     370           1 :         CATCH_REQUIRE(branch4->parent() == root);
     371           1 :         CATCH_REQUIRE(branch4->root() == root);
     372           1 :         CATCH_REQUIRE(branch4->all_attributes().size() == 2);
     373           1 :         CATCH_REQUIRE(branch4->attribute("level") == "1");
     374           1 :         CATCH_REQUIRE(branch4->attribute("color") == "purple");
     375           1 :         CATCH_REQUIRE(branch4->text() == "here is an equal = which I think works");
     376             :     }
     377             :     CATCH_END_SECTION()
     378           8 : }
     379             : 
     380             : 
     381          36 : CATCH_TEST_CASE("parser_errors", "[parser][invalid]")
     382             : {
     383          68 :     CATCH_START_SECTION("parser does not like a completely empty input file")
     384             :     {
     385           2 :         std::stringstream ss;
     386           2 :         std::string const filename("empty.xml");
     387             : 
     388           2 :         basic_xml::node::pointer_t root;
     389           1 :         CATCH_REQUIRE_THROWS_MATCHES(
     390             :                   basic_xml::parser(filename, ss, root)
     391             :                 , basic_xml::unexpected_token
     392             :                 , Catch::Matchers::ExceptionMessage(
     393             :                           "xml_error: "
     394             :                         + filename
     395             :                         + ":1: cannot be empty or include anything other than a processor tag and comments before the root tag.", true));
     396             :     }
     397             :     CATCH_END_SECTION()
     398             : 
     399          68 :     CATCH_START_SECTION("file with only a processor tag")
     400             :     {
     401           2 :         std::stringstream ss;
     402           2 :         std::string const filename("processor.xml");
     403           1 :         ss << "<?xml version=\"1.0\"?>\n";
     404             : 
     405           2 :         basic_xml::node::pointer_t root;
     406           1 :         CATCH_REQUIRE_THROWS_MATCHES(
     407             :                   basic_xml::parser(filename, ss, root)
     408             :                 , basic_xml::unexpected_token
     409             :                 , Catch::Matchers::ExceptionMessage(
     410             :                           "xml_error: "
     411             :                         + filename
     412             :                         + ":2: cannot be empty or include anything other than a processor tag and comments before the root tag.", true));
     413             :     }
     414             :     CATCH_END_SECTION()
     415             : 
     416          68 :     CATCH_START_SECTION("file with only a comment tag")
     417             :     {
     418           2 :         std::stringstream ss;
     419           2 :         std::string const filename("comment.xml");
     420           1 :         ss << "<!-- only a comment... -->\n";
     421             : 
     422           2 :         basic_xml::node::pointer_t root;
     423           1 :         CATCH_REQUIRE_THROWS_MATCHES(
     424             :                   basic_xml::parser(filename, ss, root)
     425             :                 , basic_xml::unexpected_token
     426             :                 , Catch::Matchers::ExceptionMessage(
     427             :                           "xml_error: "
     428             :                         + filename
     429             :                         + ":2: cannot be empty or include anything other than a processor tag and comments before the root tag.", true));
     430             :     }
     431             :     CATCH_END_SECTION()
     432             : 
     433          68 :     CATCH_START_SECTION("file with only comment and preprocessor tags")
     434             :     {
     435           2 :         std::stringstream ss;
     436           2 :         std::string const filename("comment-and-processor.xml");
     437           1 :         ss << "<!-- comment at the start... -->\n"
     438             :               "<?xml version=\"1.0\"?>\n"
     439             :               "<!-- comment further down... -->\n";
     440             : 
     441           2 :         basic_xml::node::pointer_t root;
     442           1 :         CATCH_REQUIRE_THROWS_MATCHES(
     443             :                   basic_xml::parser(filename, ss, root)
     444             :                 , basic_xml::unexpected_token
     445             :                 , Catch::Matchers::ExceptionMessage(
     446             :                           "xml_error: "
     447             :                         + filename
     448             :                         + ":4: cannot be empty or include anything other than a processor tag and comments before the root tag.", true));
     449             :     }
     450             :     CATCH_END_SECTION()
     451             : 
     452          68 :     CATCH_START_SECTION("file with two processor tags and a root")
     453             :     {
     454           2 :         std::stringstream ss;
     455           2 :         std::string const filename("processor-and-root.xml");
     456           1 :         ss << "<?xml version=\"1.0\"?>\n"
     457             :               "<?php\necho 'invalid code';\n?>\n"  // <-- err on this one
     458             :               "<root>too late</root>\n";
     459             : 
     460           2 :         basic_xml::node::pointer_t root;
     461           1 :         CATCH_REQUIRE_THROWS_MATCHES(
     462             :                   basic_xml::parser(filename, ss, root)
     463             :                 , basic_xml::unexpected_token
     464             :                 , Catch::Matchers::ExceptionMessage(
     465             :                           "xml_error: "
     466             :                         + filename
     467             :                         + ":4: cannot be empty or include anything other than a processor tag and comments before the root tag.", true));
     468             :     }
     469             :     CATCH_END_SECTION()
     470             : 
     471          68 :     CATCH_START_SECTION("empty root tag")
     472             :     {
     473           2 :         std::stringstream ss;
     474           2 :         std::string const filename("empty-root.xml");
     475           1 :         ss << "<!-- root can't be empty -->\n"
     476             :               "<root/>\n";
     477             : 
     478           2 :         basic_xml::node::pointer_t root;
     479           1 :         CATCH_REQUIRE_THROWS_MATCHES(
     480             :                   basic_xml::parser(filename, ss, root)
     481             :                 , basic_xml::unexpected_token
     482             :                 , Catch::Matchers::ExceptionMessage(
     483             :                           "xml_error: "
     484             :                         + filename
     485             :                         + ":2: root tag cannot be an empty tag.", true));
     486             :     }
     487             :     CATCH_END_SECTION()
     488             : 
     489          68 :     CATCH_START_SECTION("wrong closing tag")
     490             :     {
     491           2 :         std::stringstream ss;
     492           2 :         std::string const filename("empty-root.xml");
     493           1 :         ss << "<!-- tag mismatch -->\n"
     494             :               "<root><this>incorrect</that></root>\n";
     495             : 
     496           2 :         basic_xml::node::pointer_t root;
     497           1 :         CATCH_REQUIRE_THROWS_MATCHES(
     498             :                   basic_xml::parser(filename, ss, root)
     499             :                 , basic_xml::unexpected_token
     500             :                 , Catch::Matchers::ExceptionMessage(
     501             :                           "xml_error: "
     502             :                         + filename
     503             :                         + ":2: unexpected token \"that\" in this closing tag; expected \"this\" instead."));
     504             :     }
     505             :     CATCH_END_SECTION()
     506             : 
     507          68 :     CATCH_START_SECTION("text after closing root tag")
     508             :     {
     509           2 :         std::stringstream ss;
     510           2 :         std::string const filename("extra-text.xml");
     511           1 :         ss << "<!-- text at the end -->\n"
     512             :               "<root><sub-tag>all good here</sub-tag></root>but no there\n";
     513             : 
     514           2 :         basic_xml::node::pointer_t root;
     515           1 :         CATCH_REQUIRE_THROWS_MATCHES(
     516             :                   basic_xml::parser(filename, ss, root)
     517             :                 , basic_xml::unexpected_token
     518             :                 , Catch::Matchers::ExceptionMessage(
     519             :                           "xml_error: "
     520             :                         + filename
     521             :                         + ":3: cannot include text data before or after the root tag."));
     522             :     }
     523             :     CATCH_END_SECTION()
     524             : 
     525          68 :     CATCH_START_SECTION("tag after closing root tag")
     526             :     {
     527           2 :         std::stringstream ss;
     528           2 :         std::string const filename("extra-text.xml");
     529           1 :         ss << "<!-- text at the end -->\n"
     530             :               "<root><sub-tag>all good here</sub-tag></root><more>invalid</mode>\n";
     531             : 
     532           2 :         basic_xml::node::pointer_t root;
     533           1 :         CATCH_REQUIRE_THROWS_MATCHES(
     534             :                   basic_xml::parser(filename, ss, root)
     535             :                 , basic_xml::unexpected_token
     536             :                 , Catch::Matchers::ExceptionMessage(
     537             :                           "xml_error: "
     538             :                         + filename
     539             :                         + ":2: we reached the end of the XML file, but still"
     540             :                           " found a token of type 6 after the closing root tag"
     541             :                           " instead of the end of the file."));
     542             :     }
     543             :     CATCH_END_SECTION()
     544             : 
     545          68 :     CATCH_START_SECTION("not closing root tag")
     546             :     {
     547           2 :         std::stringstream ss;
     548           2 :         std::string const filename("root-still-open.xml");
     549           1 :         ss << "<!-- text at the end -->\n"
     550             :               "<root><sub-tag>all good here</sub-tag> <!-- invalid end -->\n";
     551             : 
     552           2 :         basic_xml::node::pointer_t root;
     553           1 :         CATCH_REQUIRE_THROWS_MATCHES(
     554             :                   basic_xml::parser(filename, ss, root)
     555             :                 , basic_xml::unexpected_token
     556             :                 , Catch::Matchers::ExceptionMessage(
     557             :                           "xml_error: "
     558             :                         + filename
     559             :                         + ":3: reached the end of the file without first"
     560             :                           " closing the root tag."));
     561             :     }
     562             :     CATCH_END_SECTION()
     563             : 
     564          68 :     CATCH_START_SECTION("attribute expects identifier")
     565             :     {
     566           2 :         std::stringstream ss;
     567           2 :         std::string const filename("attribute-identifier.xml");
     568           1 :         ss << "<root><sub-tag attr=\"good\" =\"bad\">all good here</sub-tag></root>\n";
     569             : 
     570           2 :         basic_xml::node::pointer_t root;
     571           1 :         CATCH_REQUIRE_THROWS_MATCHES(
     572             :                   basic_xml::parser(filename, ss, root)
     573             :                 , basic_xml::invalid_xml
     574             :                 , Catch::Matchers::ExceptionMessage(
     575             :                           "xml_error: "
     576             :                         + filename
     577             :                         + ":1: expected the end of the tag (>) or an attribute name."));
     578             :     }
     579             :     CATCH_END_SECTION()
     580             : 
     581          68 :     CATCH_START_SECTION("attribute missing equal")
     582             :     {
     583           2 :         std::stringstream ss;
     584           2 :         std::string const filename("attribute-identifier.xml");
     585           1 :         ss << "<root><sub-tag attr \"bad\">all good here</sub-tag></root>\n";
     586             : 
     587           2 :         basic_xml::node::pointer_t root;
     588           1 :         CATCH_REQUIRE_THROWS_MATCHES(
     589             :                   basic_xml::parser(filename, ss, root)
     590             :                 , basic_xml::invalid_xml
     591             :                 , Catch::Matchers::ExceptionMessage(
     592             :                           "xml_error: "
     593             :                         + filename
     594             :                         + ":1: expected the '=' character between the attribute name and value."));
     595             :     }
     596             :     CATCH_END_SECTION()
     597             : 
     598          68 :     CATCH_START_SECTION("attribute value must be string")
     599             :     {
     600           2 :         std::stringstream ss;
     601           2 :         std::string const filename("attribute-identifier.xml");
     602           1 :         ss << "<root><sub-tag attr=bad>quotes are missing...</sub-tag></root>\n";
     603             : 
     604           2 :         basic_xml::node::pointer_t root;
     605           1 :         CATCH_REQUIRE_THROWS_MATCHES(
     606             :                   basic_xml::parser(filename, ss, root)
     607             :                 , basic_xml::invalid_xml
     608             :                 , Catch::Matchers::ExceptionMessage(
     609             :                           "xml_error: "
     610             :                         + filename
     611             :                         + ":1: expected a quoted value after the '=' sign."));
     612             :     }
     613             :     CATCH_END_SECTION()
     614             : 
     615          68 :     CATCH_START_SECTION("attribute defined twice")
     616             :     {
     617           2 :         std::stringstream ss;
     618           2 :         std::string const filename("attribute-duplicated.xml");
     619           1 :         ss << "<root><sub-tag attr=\"one\" attr=\"two\">attribute defined twice...</sub-tag></root>\n";
     620             : 
     621           2 :         basic_xml::node::pointer_t root;
     622           1 :         CATCH_REQUIRE_THROWS_MATCHES(
     623             :                   basic_xml::parser(filename, ss, root)
     624             :                 , basic_xml::invalid_xml
     625             :                 , Catch::Matchers::ExceptionMessage(
     626             :                           "xml_error: "
     627             :                         + filename
     628             :                         + ":1: attribute \"attr\" defined twice; we do not allow such."));
     629             :     }
     630             :     CATCH_END_SECTION()
     631             : 
     632          68 :     CATCH_START_SECTION("processor not ended")
     633             :     {
     634           2 :         std::stringstream ss;
     635           2 :         std::string const filename("attribute-duplicated.xml");
     636           1 :         ss << "<root><sub-tag><?php echo 'this is legal in PHP, but not for us...';\n";
     637             : 
     638           2 :         basic_xml::node::pointer_t root;
     639           1 :         CATCH_REQUIRE_THROWS_MATCHES(
     640             :                   basic_xml::parser(filename, ss, root)
     641             :                 , basic_xml::unexpected_eof
     642             :                 , Catch::Matchers::ExceptionMessage(
     643             :                           "xml_error: "
     644             :                         + filename
     645             :                         + ":2: reached the end of the file while reading a processor (\"<?...?>\") tag."));
     646             :     }
     647             :     CATCH_END_SECTION()
     648             : 
     649          68 :     CATCH_START_SECTION("element definitions not supported")
     650             :     {
     651           2 :         std::stringstream ss;
     652           2 :         std::string const filename("element.xml");
     653           1 :         ss << "<root><sub-tag><!ELEMENT abc></sub-tag></root>\n";
     654             : 
     655           2 :         basic_xml::node::pointer_t root;
     656           1 :         CATCH_REQUIRE_THROWS_MATCHES(
     657             :                   basic_xml::parser(filename, ss, root)
     658             :                 , basic_xml::invalid_xml
     659             :                 , Catch::Matchers::ExceptionMessage(
     660             :                           "xml_error: "
     661             :                         + filename
     662             :                         + ":1: found an element definition (such as an \"<!ELEMENT...>\" sequence), which is not supported."));
     663             :     }
     664             :     CATCH_END_SECTION()
     665             : 
     666          68 :     CATCH_START_SECTION("bad CDATA introducer")
     667             :     {
     668           2 :         std::stringstream ss;
     669           2 :         std::string const filename("element.xml");
     670           1 :         ss << "<root><sub-tag><![BAD[abc]]></sub-tag></root>\n";
     671             : 
     672           2 :         basic_xml::node::pointer_t root;
     673           1 :         CATCH_REQUIRE_THROWS_MATCHES(
     674             :                   basic_xml::parser(filename, ss, root)
     675             :                 , basic_xml::invalid_xml
     676             :                 , Catch::Matchers::ExceptionMessage(
     677             :                           "xml_error: "
     678             :                         + filename
     679             :                         + ":1: found an unexpected sequence of character in a \"<![CDATA[...\" sequence."));
     680             :     }
     681             :     CATCH_END_SECTION()
     682             : 
     683          68 :     CATCH_START_SECTION("EOF before closing CDATA tag")
     684             :     {
     685           2 :         std::stringstream ss;
     686           2 :         std::string const filename("element.xml");
     687           1 :         ss << "<root><sub-tag><![CDATA[abc]]\n";
     688             : 
     689           2 :         basic_xml::node::pointer_t root;
     690           1 :         CATCH_REQUIRE_THROWS_MATCHES(
     691             :                   basic_xml::parser(filename, ss, root)
     692             :                 , basic_xml::unexpected_eof
     693             :                 , Catch::Matchers::ExceptionMessage(
     694             :                           "xml_error: "
     695             :                         + filename
     696             :                         + ":2: found EOF while parsing a \"<![CDATA[...]]>\" sequence."));
     697             :     }
     698             :     CATCH_END_SECTION()
     699             : 
     700          68 :     CATCH_START_SECTION("EOF before closing comment tag")
     701             :     {
     702           2 :         std::stringstream ss;
     703           2 :         std::string const filename("element.xml");
     704           1 :         ss << "<root><sub-tag><!-- file\nends\nwith\ncomment\nopen\n...\n";
     705             : 
     706           2 :         basic_xml::node::pointer_t root;
     707           1 :         CATCH_REQUIRE_THROWS_MATCHES(
     708             :                   basic_xml::parser(filename, ss, root)
     709             :                 , basic_xml::unexpected_eof
     710             :                 , Catch::Matchers::ExceptionMessage(
     711             :                           "xml_error: "
     712             :                         + filename
     713             :                         + ":7: found EOF while parsing a comment (\"<!--...-->\") sequence."));
     714             :     }
     715             :     CATCH_END_SECTION()
     716             : 
     717          68 :     CATCH_START_SECTION("unknown <!... sequence")
     718             :     {
     719           2 :         std::stringstream ss;
     720           2 :         std::string const filename("element.xml");
     721           1 :         ss << "<root><sub-tag><!+ unknown +></sub-tag></root>\n";
     722             : 
     723           2 :         basic_xml::node::pointer_t root;
     724           1 :         CATCH_REQUIRE_THROWS_MATCHES(
     725             :                   basic_xml::parser(filename, ss, root)
     726             :                 , basic_xml::invalid_token
     727             :                 , Catch::Matchers::ExceptionMessage(
     728             :                           "xml_error: "
     729             :                         + filename
     730             :                         + ":1: character '+' was not expected after a \"<!\" sequence."));
     731             :     }
     732             :     CATCH_END_SECTION()
     733             : 
     734          68 :     CATCH_START_SECTION("closing tag missing name")
     735             :     {
     736           2 :         std::stringstream ss;
     737           2 :         std::string const filename("element.xml");
     738           1 :         ss << "<root><sub-tag>bad closing tag</\n";
     739             : 
     740           2 :         basic_xml::node::pointer_t root;
     741           1 :         CATCH_REQUIRE_THROWS_MATCHES(
     742             :                   basic_xml::parser(filename, ss, root)
     743             :                 , basic_xml::unexpected_eof
     744             :                 , Catch::Matchers::ExceptionMessage(
     745             :                           "xml_error: "
     746             :                         + filename
     747             :                         + ":2: expected a tag name after \"</\", not EOF."));
     748             :     }
     749             :     CATCH_END_SECTION()
     750             : 
     751          68 :     CATCH_START_SECTION("closing tag not starting with alpha character")
     752             :     {
     753           2 :         std::stringstream ss;
     754           2 :         std::string const filename("element.xml");
     755           1 :         ss << "<root><sub-tag>bad closing tag</-bad-name->\n";
     756             : 
     757           2 :         basic_xml::node::pointer_t root;
     758           1 :         CATCH_REQUIRE_THROWS_MATCHES(
     759             :                   basic_xml::parser(filename, ss, root)
     760             :                 , basic_xml::invalid_token
     761             :                 , Catch::Matchers::ExceptionMessage(
     762             :                           "xml_error: "
     763             :                         + filename
     764             :                         + ":1: character '-' is not valid for a tag name."));
     765             :     }
     766             :     CATCH_END_SECTION()
     767             : 
     768          68 :     CATCH_START_SECTION("closing tag missing >")
     769             :     {
     770           2 :         std::stringstream ss;
     771           2 :         std::string const filename("element.xml");
     772           1 :         ss << "<root><sub-tag>bad closing tag</good-name\n";
     773             : 
     774           2 :         basic_xml::node::pointer_t root;
     775           1 :         CATCH_REQUIRE_THROWS_MATCHES(
     776             :                   basic_xml::parser(filename, ss, root)
     777             :                 , basic_xml::unexpected_eof
     778             :                 , Catch::Matchers::ExceptionMessage(
     779             :                           "xml_error: "
     780             :                         + filename
     781             :                         + ":2: expected '>', not EOF."));
     782             :     }
     783             :     CATCH_END_SECTION()
     784             : 
     785          68 :     CATCH_START_SECTION("closing tag name followed by ';'")
     786             :     {
     787           2 :         std::stringstream ss;
     788           2 :         std::string const filename("element.xml");
     789           1 :         ss << "<root><sub-tag>bad closing tag</good-name;>\n";
     790             : 
     791           2 :         basic_xml::node::pointer_t root;
     792           1 :         CATCH_REQUIRE_THROWS_MATCHES(
     793             :                   basic_xml::parser(filename, ss, root)
     794             :                 , basic_xml::invalid_xml
     795             :                 , Catch::Matchers::ExceptionMessage(
     796             :                           "xml_error: "
     797             :                         + filename
     798             :                         + ":1: found an unexpected ';' in a closing tag, expected '>' instead."));
     799             :     }
     800             :     CATCH_END_SECTION()
     801             : 
     802          68 :     CATCH_START_SECTION("opening tag missing >")
     803             :     {
     804           2 :         std::stringstream ss;
     805           2 :         std::string const filename("element.xml");
     806           1 :         ss << "<root><\n";
     807             : 
     808           2 :         basic_xml::node::pointer_t root;
     809           1 :         CATCH_REQUIRE_THROWS_MATCHES(
     810             :                   basic_xml::parser(filename, ss, root)
     811             :                 , basic_xml::unexpected_eof
     812             :                 , Catch::Matchers::ExceptionMessage(
     813             :                           "xml_error: "
     814             :                         + filename
     815             :                         + ":2: expected a tag name after '<', not EOF."));
     816             :     }
     817             :     CATCH_END_SECTION()
     818             : 
     819          68 :     CATCH_START_SECTION("opening tag bad name")
     820             :     {
     821           2 :         std::stringstream ss;
     822           2 :         std::string const filename("element.xml");
     823           1 :         ss << "<root><{sub-tag>bad opening tag\n";
     824             : 
     825           2 :         basic_xml::node::pointer_t root;
     826           1 :         CATCH_REQUIRE_THROWS_MATCHES(
     827             :                   basic_xml::parser(filename, ss, root)
     828             :                 , basic_xml::invalid_token
     829             :                 , Catch::Matchers::ExceptionMessage(
     830             :                           "xml_error: "
     831             :                         + filename
     832             :                         + ":1: character '{' is not valid for a tag name."));
     833             :     }
     834             :     CATCH_END_SECTION()
     835             : 
     836          68 :     CATCH_START_SECTION("opening tag name followed by ';'")
     837             :     {
     838           2 :         std::stringstream ss;
     839           2 :         std::string const filename("element.xml");
     840           1 :         ss << "<root><sub-tag}>bad closing tag\n";
     841             : 
     842           2 :         basic_xml::node::pointer_t root;
     843           1 :         CATCH_REQUIRE_THROWS_MATCHES(
     844             :                   basic_xml::parser(filename, ss, root)
     845             :                 , basic_xml::invalid_token
     846             :                 , Catch::Matchers::ExceptionMessage(
     847             :                           "xml_error: "
     848             :                         + filename
     849             :                         + ":1: character '}' is not valid right after a tag name."));
     850             :     }
     851             :     CATCH_END_SECTION()
     852             : 
     853          68 :     CATCH_START_SECTION("attribute with '<'")
     854             :     {
     855           2 :         std::stringstream ss;
     856           2 :         std::string const filename("element.xml");
     857           1 :         ss << "<root><sub-tag name='perfect <tag>'>bad closing tag</sub-tag></root>\n";
     858             : 
     859           2 :         basic_xml::node::pointer_t root;
     860           1 :         CATCH_REQUIRE_THROWS_MATCHES(
     861             :                   basic_xml::parser(filename, ss, root)
     862             :                 , basic_xml::invalid_token
     863             :                 , Catch::Matchers::ExceptionMessage(
     864             :                           "xml_error: "
     865             :                         + filename
     866             :                         + ":1: character '>' not expected inside a tag value; please use \"&gt;\" instead."));
     867             :     }
     868             :     CATCH_END_SECTION()
     869             : 
     870          68 :     CATCH_START_SECTION("empty entity (&;)")
     871             :     {
     872           2 :         std::stringstream ss;
     873           2 :         std::string const filename("element.xml");
     874           1 :         ss << "<root><sub-tag name='empty entity: &;'>bad closing tag</sub-tag></root>\n";
     875             : 
     876           2 :         basic_xml::node::pointer_t root;
     877           1 :         CATCH_REQUIRE_THROWS_MATCHES(
     878             :                   basic_xml::parser(filename, ss, root)
     879             :                 , basic_xml::invalid_entity
     880             :                 , Catch::Matchers::ExceptionMessage(
     881             :                           "xml_error: "
     882             :                         + filename
     883             :                         + ":1: the name of an entity cannot be empty (\"&;\" is not valid XML)."));
     884             :     }
     885             :     CATCH_END_SECTION()
     886             : 
     887          68 :     CATCH_START_SECTION("empty numeric entity (&#;)")
     888             :     {
     889           2 :         std::stringstream ss;
     890           2 :         std::string const filename("element.xml");
     891           1 :         ss << "<root><sub-tag name='empty numeric entity: &#;'>bad closing tag</sub-tag></root>\n";
     892             : 
     893           2 :         basic_xml::node::pointer_t root;
     894           1 :         CATCH_REQUIRE_THROWS_MATCHES(
     895             :                   basic_xml::parser(filename, ss, root)
     896             :                 , basic_xml::invalid_entity
     897             :                 , Catch::Matchers::ExceptionMessage(
     898             :                           "xml_error: "
     899             :                         + filename
     900             :                         + ":1: a numeric entity must have a number (\"&#;\" is not valid XML)."));
     901             :     }
     902             :     CATCH_END_SECTION()
     903             : 
     904          68 :     CATCH_START_SECTION("invalid number of numeric entity (not decimal)")
     905             :     {
     906           2 :         std::stringstream ss;
     907           2 :         std::string const filename("element.xml");
     908           1 :         ss << "<root><sub-tag name='empty numeric entity: &#12ab34;'>bad closing tag</sub-tag></root>\n";
     909             : 
     910           2 :         basic_xml::node::pointer_t root;
     911           1 :         CATCH_REQUIRE_THROWS_MATCHES(
     912             :                   basic_xml::parser(filename, ss, root)
     913             :                 , basic_xml::invalid_number
     914             :                 , Catch::Matchers::ExceptionMessage(
     915             :                           "xml_error: "
     916             :                         + filename
     917             :                         + ":1: the number found in numeric entity, \" 12ab34\", is not considered valid."));
     918             :     }
     919             :     CATCH_END_SECTION()
     920             : 
     921          68 :     CATCH_START_SECTION("invalid number of numeric entity (not hexadecimal)")
     922             :     {
     923           2 :         std::stringstream ss;
     924           2 :         std::string const filename("element.xml");
     925           1 :         ss << "<root><sub-tag name='empty numeric entity: &#x10abz4;'>bad closing tag</sub-tag></root>\n";
     926             : 
     927           2 :         basic_xml::node::pointer_t root;
     928           1 :         CATCH_REQUIRE_THROWS_MATCHES(
     929             :                   basic_xml::parser(filename, ss, root)
     930             :                 , basic_xml::invalid_number
     931             :                 , Catch::Matchers::ExceptionMessage(
     932             :                           "xml_error: "
     933             :                         + filename
     934             :                         + ":1: the number found in numeric entity, \"0x10abz4\", is not considered valid."));
     935             :     }
     936             :     CATCH_END_SECTION()
     937             : 
     938          68 :     CATCH_START_SECTION("\"unknown\" entity")
     939             :     {
     940           2 :         std::stringstream ss;
     941           2 :         std::string const filename("element.xml");
     942           1 :         ss << "<root><sub-tag name='empty numeric entity: &unknown;'>bad closing tag</sub-tag></root>\n";
     943             : 
     944           2 :         basic_xml::node::pointer_t root;
     945           1 :         CATCH_REQUIRE_THROWS_MATCHES(
     946             :                   basic_xml::parser(filename, ss, root)
     947             :                 , basic_xml::invalid_entity
     948             :                 , Catch::Matchers::ExceptionMessage(
     949             :                           "xml_error: "
     950             :                         + filename
     951             :                         + ":1: unsupported entity (\"&unknown;\")."));
     952             :     }
     953             :     CATCH_END_SECTION()
     954             : 
     955          68 :     CATCH_START_SECTION("separate attributes with a slash")
     956             :     {
     957           2 :         std::stringstream ss;
     958           2 :         std::string const filename("element.xml");
     959           1 :         ss << "<root><sub-tag name='one' / ignore='two'>bad closing tag</sub-tag></root>\n";
     960             : 
     961           2 :         basic_xml::node::pointer_t root;
     962           1 :         CATCH_REQUIRE_THROWS_MATCHES(
     963             :                   basic_xml::parser(filename, ss, root)
     964             :                 , basic_xml::invalid_xml
     965             :                 , Catch::Matchers::ExceptionMessage(
     966             :                           "xml_error: "
     967             :                         + filename
     968             :                         + ":1: expected the end of the tag (>) or an attribute name."));
     969             :     }
     970             :     CATCH_END_SECTION()
     971          40 : }
     972             : 
     973             : 
     974             : 
     975             : // vim: ts=4 sw=4 et

Generated by: LCOV version 1.13