LCOV - code coverage report
Current view: top level - tests - catch_xml.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 118 118 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/xml.h>
      28             : 
      29             : 
      30             : // C++
      31             : //
      32             : #include    <fstream>
      33             : 
      34             : 
      35             : 
      36           7 : CATCH_TEST_CASE("xml", "[xml][valid]")
      37             : {
      38          10 :     CATCH_START_SECTION("empty root")
      39             :     {
      40           2 :         std::string const xml_path(SNAP_CATCH2_NAMESPACE::get_folder_name());
      41           2 :         std::string const filename(xml_path + "/empty-tag.xml");
      42             : 
      43             :         // create file with one empty tag
      44             :         {
      45           2 :             std::ofstream f;
      46           1 :             f.open(filename);
      47           1 :             CATCH_REQUIRE(f.is_open());
      48           1 :             f << "<empty></empty>";
      49             :         }
      50             : 
      51           2 :         basic_xml::xml x(filename);
      52           2 :         basic_xml::node::pointer_t root(x.root());
      53           1 :         CATCH_REQUIRE(root != nullptr);
      54           1 :         CATCH_REQUIRE(root->tag_name() == "empty");
      55           1 :         CATCH_REQUIRE(root->text().empty());
      56           1 :         CATCH_REQUIRE(root->all_attributes().empty());
      57           1 :         CATCH_REQUIRE(root->parent() == nullptr);
      58           1 :         CATCH_REQUIRE(root->first_child() == nullptr);
      59           1 :         CATCH_REQUIRE(root->last_child() == nullptr);
      60           1 :         CATCH_REQUIRE(root->next() == nullptr);
      61           1 :         CATCH_REQUIRE(root->previous() == nullptr);
      62             :     }
      63             :     CATCH_END_SECTION()
      64             : 
      65          10 :     CATCH_START_SECTION("empty root with preprocessor")
      66             :     {
      67           2 :         std::string const filename("empty-tag.xml");
      68             : 
      69             :         // create file with one empty tag
      70           2 :         std::stringstream ss;
      71           1 :         ss << "<?xml version=\"1.0\"?><still-empty></still-empty>";
      72             : 
      73           2 :         basic_xml::xml x(filename, ss);
      74           2 :         basic_xml::node::pointer_t root(x.root());
      75           1 :         CATCH_REQUIRE(root != nullptr);
      76           1 :         CATCH_REQUIRE(root->tag_name() == "still-empty");
      77           1 :         CATCH_REQUIRE(root->text().empty());
      78           1 :         CATCH_REQUIRE(root->all_attributes().empty());
      79           1 :         CATCH_REQUIRE(root->parent() == nullptr);
      80           1 :         CATCH_REQUIRE(root->first_child() == nullptr);
      81           1 :         CATCH_REQUIRE(root->last_child() == nullptr);
      82           1 :         CATCH_REQUIRE(root->next() == nullptr);
      83           1 :         CATCH_REQUIRE(root->previous() == nullptr);
      84             :     }
      85             :     CATCH_END_SECTION()
      86             : 
      87          10 :     CATCH_START_SECTION("empty root with comment & preprocessor")
      88             :     {
      89           2 :         std::string const xml_path(SNAP_CATCH2_NAMESPACE::get_folder_name());
      90           2 :         std::string const filename(xml_path + "/quite-empty.xml");
      91             : 
      92             :         // create file with one empty tag
      93             :         {
      94           2 :             std::ofstream f;
      95           1 :             f.open(filename);
      96           1 :             CATCH_REQUIRE(f.is_open());
      97           1 :             f << "<!-- name='rotor' --><?xml version=\"1.0\"?><quite-empty></quite-empty>";
      98             :         }
      99             : 
     100           2 :         basic_xml::xml x(filename);
     101           2 :         basic_xml::node::pointer_t root(x.root());
     102           1 :         CATCH_REQUIRE(root != nullptr);
     103           1 :         CATCH_REQUIRE(root->tag_name() == "quite-empty");
     104           1 :         CATCH_REQUIRE(root->text().empty());
     105           1 :         CATCH_REQUIRE(root->all_attributes().empty());
     106           1 :         CATCH_REQUIRE(root->parent() == nullptr);
     107           1 :         CATCH_REQUIRE(root->first_child() == nullptr);
     108           1 :         CATCH_REQUIRE(root->last_child() == nullptr);
     109           1 :         CATCH_REQUIRE(root->next() == nullptr);
     110           1 :         CATCH_REQUIRE(root->previous() == nullptr);
     111             :     }
     112             :     CATCH_END_SECTION()
     113             : 
     114          10 :     CATCH_START_SECTION("empty root with comment & preprocessor & attributes")
     115             :     {
     116           2 :         std::string const xml_path(SNAP_CATCH2_NAMESPACE::get_folder_name());
     117           2 :         std::string const filename(xml_path + "/root-attributes.xml");
     118             : 
     119             :         // create file with one empty tag
     120             :         {
     121           2 :             std::ofstream f;
     122           1 :             f.open(filename);
     123           1 :             CATCH_REQUIRE(f.is_open());
     124           1 :             f << "<!--\n"
     125             :                  "name='next level'\n"
     126             :                  "-->\n"
     127             :                  "\n"
     128             :                  "<?xml version=\"1.0\"?>\n"
     129             :                  "<root-canal quite=\"quite\" size='123' very=\"true\">"
     130             :                  " \t \t \t "
     131             :                  "</root-canal>";
     132             :         }
     133             : 
     134           2 :         basic_xml::xml x(filename);
     135           2 :         basic_xml::node::pointer_t root(x.root());
     136           1 :         CATCH_REQUIRE(root != nullptr);
     137           1 :         CATCH_REQUIRE(root->tag_name() == "root-canal");
     138           1 :         CATCH_REQUIRE(root->text() == "");
     139           1 :         CATCH_REQUIRE(root->text(true) == "");
     140           1 :         CATCH_REQUIRE(root->text(false) == " \t \t \t ");
     141           1 :         CATCH_REQUIRE(root->all_attributes().size() == 3);
     142           1 :         CATCH_REQUIRE(root->attribute("quite") == "quite");
     143           1 :         CATCH_REQUIRE(root->attribute("size") == "123");
     144           1 :         CATCH_REQUIRE(root->attribute("very") == "true");
     145           1 :         CATCH_REQUIRE(root->parent() == nullptr);
     146           1 :         CATCH_REQUIRE(root->first_child() == nullptr);
     147           1 :         CATCH_REQUIRE(root->last_child() == nullptr);
     148           1 :         CATCH_REQUIRE(root->next() == nullptr);
     149           1 :         CATCH_REQUIRE(root->previous() == nullptr);
     150             :     }
     151             :     CATCH_END_SECTION()
     152             : 
     153          10 :     CATCH_START_SECTION("entities test")
     154             :     {
     155           2 :         std::string const xml_path(SNAP_CATCH2_NAMESPACE::get_folder_name());
     156           2 :         std::string const filename(xml_path + "/entities.xml");
     157             : 
     158             :         // create file with one empty tag
     159             :         {
     160           2 :             std::ofstream f;
     161           1 :             f.open(filename);
     162           1 :             CATCH_REQUIRE(f.is_open());
     163           1 :             f << "<!--\n"
     164             :                  "name='entitie&#x73;'\n"
     165             :                  "-->\n"
     166             :                  "\n"
     167             :                  "<?xml version=\"1.0\"?>\n"
     168             :                  "<entity-a-gogo quite=\"&#x71;uit&#101;\" size='1&#x32;3'"
     169             :                         " very=\"&quot;true&quot;\" special-entry=\"&quot;&lt;it&apos;s special &amp; weird&gt;&quot;\">"
     170             :                  "</entity-a-gogo>";
     171             :         }
     172             : 
     173           2 :         basic_xml::xml x(filename);
     174           2 :         basic_xml::node::pointer_t root(x.root());
     175           1 :         CATCH_REQUIRE(root != nullptr);
     176           1 :         CATCH_REQUIRE(root->tag_name() == "entity-a-gogo");
     177           1 :         CATCH_REQUIRE(root->all_attributes().size() == 4);
     178           1 :         CATCH_REQUIRE(root->attribute("quite") == "quite");
     179           1 :         CATCH_REQUIRE(root->attribute("size") == "123");
     180           1 :         CATCH_REQUIRE(root->attribute("very") == "\"true\"");
     181           1 :         CATCH_REQUIRE(root->attribute("special-entry") == "\"<it's special & weird>\"");
     182           1 :         CATCH_REQUIRE(root->parent() == nullptr);
     183           1 :         CATCH_REQUIRE(root->first_child() == nullptr);
     184           1 :         CATCH_REQUIRE(root->last_child() == nullptr);
     185           1 :         CATCH_REQUIRE(root->next() == nullptr);
     186           1 :         CATCH_REQUIRE(root->previous() == nullptr);
     187             :     }
     188             :     CATCH_END_SECTION()
     189           5 : }
     190             : 
     191             : 
     192           6 : CATCH_TEST_CASE("xml", "[xml][invalid]")
     193             : {
     194           8 :     CATCH_START_SECTION("file missing")
     195             :     {
     196           2 :         std::string const xml_path(SNAP_CATCH2_NAMESPACE::get_folder_name());
     197           2 :         std::string const filename(xml_path + "/file-does-not-exist.xml");
     198             : 
     199           1 :         CATCH_REQUIRE_THROWS_MATCHES(
     200             :                   basic_xml::xml(filename)
     201             :                 , basic_xml::file_not_found
     202             :                 , Catch::Matchers::ExceptionMessage(
     203             :                           "xml_error: could not open XML file \""
     204             :                         + filename
     205             :                         + "\": "
     206             :                         + strerror(ENOENT)
     207             :                         + ".", true));
     208             :     }
     209             :     CATCH_END_SECTION()
     210             : 
     211           8 :     CATCH_START_SECTION("file no permission")
     212             :     {
     213           2 :         std::string const filename("/root/.bashrc");
     214             : 
     215           1 :         CATCH_REQUIRE_THROWS_MATCHES(
     216             :                   basic_xml::xml(filename)
     217             :                 , basic_xml::file_not_found
     218             :                 , Catch::Matchers::ExceptionMessage(
     219             :                           "xml_error: could not open XML file \""
     220             :                         + filename
     221             :                         + "\": "
     222             :                         + strerror(EACCES)
     223             :                         + ".", true));
     224             :     }
     225             :     CATCH_END_SECTION()
     226             : 
     227           8 :     CATCH_START_SECTION("parse empty xml file")
     228             :     {
     229           2 :         std::string const xml_path(SNAP_CATCH2_NAMESPACE::get_folder_name());
     230           2 :         std::string const filename(xml_path + "/empty.xml");
     231             : 
     232             :         // create empty file
     233             :         {
     234           2 :             std::ofstream f;
     235           1 :             f.open(filename);
     236           1 :             CATCH_REQUIRE(f.is_open());
     237             :         }
     238             : 
     239           1 :         CATCH_REQUIRE_THROWS_MATCHES(
     240             :                   basic_xml::xml(filename)
     241             :                 , basic_xml::unexpected_token
     242             :                 , Catch::Matchers::ExceptionMessage(
     243             :                           "xml_error: "
     244             :                         + filename
     245             :                         + ":1: cannot be empty or include anything other than a processor tag and comments before the root tag.", true));
     246             :     }
     247             :     CATCH_END_SECTION()
     248             : 
     249           8 :     CATCH_START_SECTION("empty root tag")
     250             :     {
     251           2 :         std::string const filename("empty-tag.xml");
     252             : 
     253             :         // create file with one empty tag
     254           2 :         std::stringstream ss;
     255           1 :         ss << "<empty/>";
     256             : 
     257           1 :         CATCH_REQUIRE_THROWS_MATCHES(
     258             :                   basic_xml::xml(filename, ss)
     259             :                 , basic_xml::unexpected_token
     260             :                 , Catch::Matchers::ExceptionMessage(
     261             :                           "xml_error: "
     262             :                         + filename
     263             :                         + ":1: root tag cannot be an empty tag.", true));
     264             :     }
     265             :     CATCH_END_SECTION()
     266          10 : }
     267             : 
     268             : 
     269             : 
     270             : // vim: ts=4 sw=4 et

Generated by: LCOV version 1.13