LCOV - code coverage report
Current view: top level - tests - catch_assembler.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 1626 1639 99.2 %
Date: 2023-11-01 21:56:19 Functions: 17 17 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : // Copyright (c) 2015-2022  Made to Order Software Corp.  All Rights Reserved
       2             : //
       3             : // https://snapwebsites.org/project/csspp
       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 2 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 along
      17             : // with this program; if not, write to the Free Software Foundation, Inc.,
      18             : // 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
      19             : 
      20             : /** \file
      21             :  * \brief Test the assembler.cpp file.
      22             :  *
      23             :  * This test runs a battery of tests agains the assembler.cpp file to ensure
      24             :  * full coverage and many edge cases of CSS encoding.
      25             :  */
      26             : 
      27             : // csspp
      28             : //
      29             : #include    <csspp/assembler.h>
      30             : 
      31             : #include    <csspp/compiler.h>
      32             : #include    <csspp/exception.h>
      33             : #include    <csspp/parser.h>
      34             : 
      35             : 
      36             : // self
      37             : //
      38             : #include    "catch_main.h"
      39             : 
      40             : 
      41             : // C++
      42             : //
      43             : #include    <fstream>
      44             : #include    <iostream>
      45             : #include    <sstream>
      46             : 
      47             : 
      48             : // C
      49             : //
      50             : #include    <string.h>
      51             : #include    <string.h>
      52             : #include    <unistd.h>
      53             : #include    <sys/stat.h>
      54             : 
      55             : 
      56             : // last include
      57             : //
      58             : #include    <snapdev/poison.h>
      59             : 
      60             : 
      61             : 
      62             : namespace
      63             : {
      64             : 
      65         100 : bool is_valid_mode(csspp::output_mode_t const mode)
      66             : {
      67         100 :     switch(mode)
      68             :     {
      69           0 :     case csspp::output_mode_t::COMPACT:
      70             :     case csspp::output_mode_t::COMPRESSED:
      71             :     case csspp::output_mode_t::EXPANDED:
      72             :     case csspp::output_mode_t::TIDY:
      73           0 :         return true;
      74             : 
      75         100 :     default:
      76         100 :         return false;
      77             : 
      78             :     }
      79             : }
      80             : 
      81          64 : bool is_valid_char(csspp::wide_char_t c)
      82             : {
      83          64 :     switch(c)
      84             :     {
      85           0 :     case 0:
      86             :     case 0xFFFD:
      87           0 :         return false;
      88             : 
      89          64 :     default:
      90          64 :         if(c >= 0xD800 && c <= 0xDFFF)
      91             :         {
      92             :             // UTF-16 surrogates are not valid wide characters
      93           0 :             return false;
      94             :         }
      95          64 :         return true;
      96             : 
      97             :     }
      98             : }
      99             : 
     100             : } // no name namespace
     101             : 
     102          10 : CATCH_TEST_CASE("Assemble rules", "[assembler]")
     103             : {
     104          10 :     CATCH_START_SECTION("with many spaces")
     105             :     {
     106           5 :         for(int i(static_cast<int>(csspp::output_mode_t::COMPACT));
     107           5 :             i <= static_cast<int>(csspp::output_mode_t::TIDY);
     108             :             ++i)
     109             :         {
     110           4 :             std::stringstream ss;
     111             :             ss << "div { color: black; }"
     112             :                << "span { border: 3px solid complement(#f7d0cf); }"
     113             :                << "p { font: 13px/135% sans-serif; }"
     114           4 :                << "section { width: calc(30px - 5%); }";
     115          12 :             csspp::position pos("test.css");
     116           4 :             csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
     117             : 
     118           8 :             csspp::parser p(l);
     119             : 
     120           4 :             csspp::node::pointer_t n(p.stylesheet());
     121             : 
     122           4 :             csspp::compiler c;
     123           4 :             c.set_root(n);
     124           4 :             c.set_date_time_variables(csspp_test::get_now());
     125           4 :             c.add_path(csspp_test::get_script_path());
     126           4 :             c.add_path(csspp_test::get_version_script_path());
     127             : 
     128           4 :             c.compile(false);
     129             : 
     130             : //std::cerr << "Compiler result is: [" << *c.get_root() << "]\n";
     131             : 
     132           4 :             std::stringstream out;
     133           4 :             csspp::assembler a(out);
     134           4 :             a.output(n, static_cast<csspp::output_mode_t>(i));
     135             : 
     136             : //std::cerr << "----------------- Result is " << static_cast<csspp::output_mode_t>(i) << "\n[" << out.str() << "]\n";
     137             : 
     138           4 :             switch(static_cast<csspp::output_mode_t>(i))
     139             :             {
     140           1 :             case csspp::output_mode_t::COMPACT:
     141           1 :                 CATCH_REQUIRE(out.str() ==
     142             : "div { color: #000 }\n"
     143             : "span { border: 3px solid #cff6f7 }\n"
     144             : "p { font: 13px/135% sans-serif }\n"
     145             : "section { width: calc(30px - 5%) }\n"
     146             : + csspp_test::get_close_comment()
     147             :                     );
     148           1 :                 break;
     149             : 
     150           1 :             case csspp::output_mode_t::COMPRESSED:
     151           1 :                 CATCH_REQUIRE(out.str() ==
     152             : "div{color:#000}span{border:3px solid #cff6f7}p{font:13px/135% sans-serif}section{width:calc(30px - 5%)}\n"
     153             : + csspp_test::get_close_comment()
     154             :                     );
     155           1 :                 break;
     156             : 
     157           1 :             case csspp::output_mode_t::EXPANDED:
     158           1 :                 CATCH_REQUIRE(out.str() ==
     159             : "div\n"
     160             : "{\n"
     161             : "  color: #000;\n"
     162             : "}\n"
     163             : "span\n"
     164             : "{\n"
     165             : "  border: 3px solid #cff6f7;\n"
     166             : "}\n"
     167             : "p\n"
     168             : "{\n"
     169             : "  font: 13px/135% sans-serif;\n"
     170             : "}\n"
     171             : "section\n"
     172             : "{\n"
     173             : "  width: calc(30px - 5%);\n"
     174             : "}\n"
     175             : + csspp_test::get_close_comment()
     176             :                     );
     177           1 :                 break;
     178             : 
     179           1 :             case csspp::output_mode_t::TIDY:
     180           1 :                 CATCH_REQUIRE(out.str() ==
     181             : "div{color:#000}\n"
     182             : "span{border:3px solid #cff6f7}\n"
     183             : "p{font:13px/135% sans-serif}\n"
     184             : "section{width:calc(30px - 5%)}\n"
     185             : + csspp_test::get_close_comment()
     186             :                     );
     187           1 :                 break;
     188             : 
     189             :             }
     190             : 
     191           4 :             CATCH_REQUIRE(c.get_root() == n);
     192           4 :         }
     193             :     }
     194          10 :     CATCH_END_SECTION()
     195             : 
     196          10 :     CATCH_START_SECTION("with a calc including a divide after parenthesis")
     197             :     {
     198           5 :         for(int i(static_cast<int>(csspp::output_mode_t::COMPACT));
     199           5 :             i <= static_cast<int>(csspp::output_mode_t::TIDY);
     200             :             ++i)
     201             :         {
     202           4 :             std::stringstream ss;
     203           4 :             ss << "#left-margin { width: calc((100% - 300px) / 2); }";
     204          12 :             csspp::position pos("test.css");
     205           4 :             csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
     206             : 
     207           8 :             csspp::parser p(l);
     208             : 
     209           4 :             csspp::node::pointer_t n(p.stylesheet());
     210             : 
     211           4 :             csspp::compiler c;
     212           4 :             c.set_root(n);
     213           4 :             c.set_date_time_variables(csspp_test::get_now());
     214           4 :             c.add_path(csspp_test::get_script_path());
     215           4 :             c.add_path(csspp_test::get_version_script_path());
     216             : 
     217           4 :             c.compile(false);
     218             : 
     219             : //std::cerr << "Compiler result is: [" << *c.get_root() << "]\n";
     220             : 
     221           4 :             std::stringstream out;
     222           4 :             csspp::assembler a(out);
     223           4 :             a.output(n, static_cast<csspp::output_mode_t>(i));
     224             : 
     225             : //std::cerr << "----------------- Result is " << static_cast<csspp::output_mode_t>(i) << "\n[" << out.str() << "]\n";
     226             : 
     227           4 :             switch(static_cast<csspp::output_mode_t>(i))
     228             :             {
     229           1 :             case csspp::output_mode_t::COMPACT:
     230           1 :                 CATCH_REQUIRE(out.str() ==
     231             : "#left-margin { width: calc( (100% - 300px)  / 2) }\n"
     232             : + csspp_test::get_close_comment()
     233             :                     );
     234           1 :                 break;
     235             : 
     236           1 :             case csspp::output_mode_t::COMPRESSED:
     237           1 :                 CATCH_REQUIRE(out.str() ==
     238             : "#left-margin{width:calc( (100% - 300px) / 2)}\n"
     239             : + csspp_test::get_close_comment()
     240             :                     );
     241           1 :                 break;
     242             : 
     243           1 :             case csspp::output_mode_t::EXPANDED:
     244           1 :                 CATCH_REQUIRE(out.str() ==
     245             : "#left-margin\n"
     246             : "{\n"
     247             : "  width: calc( (100% - 300px)  / 2);\n"
     248             : "}\n"
     249             : + csspp_test::get_close_comment()
     250             :                     );
     251           1 :                 break;
     252             : 
     253           1 :             case csspp::output_mode_t::TIDY:
     254           1 :                 CATCH_REQUIRE(out.str() ==
     255             : "#left-margin{width:calc( (100% - 300px) / 2)}\n"
     256             : + csspp_test::get_close_comment()
     257             :                     );
     258           1 :                 break;
     259             : 
     260             :             }
     261             : 
     262           4 :             CATCH_REQUIRE(c.get_root() == n);
     263           4 :         }
     264             :     }
     265          10 :     CATCH_END_SECTION()
     266             : 
     267          10 :     CATCH_START_SECTION("test multiple declarations in one rule")
     268             :     {
     269           5 :         for(int i(static_cast<int>(csspp::output_mode_t::COMPACT));
     270           5 :             i <= static_cast<int>(csspp::output_mode_t::TIDY);
     271             :             ++i)
     272             :         {
     273           4 :             std::stringstream ss;
     274             :             ss << "div\n"
     275             :                << "{\n"
     276             :                << "  color: invert(black);\n"
     277             :                << "  font-size: 1.3rem;\n"
     278             :                << "}\n"
     279             :                << "\n"
     280             :                << "span\n"
     281             :                << "{\n"
     282             :                << "  border: 3px solid darken(#f7d0cf, 3%);\n"
     283             :                << "\tborder-bottom-width: 1px;\n"
     284             :                << "\tbox-shadow: 1px 0px 7px #88aa11, 0px 3px 1px #aa8833;\n"
     285             :                << "  font: 17.2px/1.35em\tArial;\n"
     286             :                << "}\n"
     287           4 :                << "\n";
     288          12 :             csspp::position pos("test.css");
     289           4 :             csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
     290             : 
     291           8 :             csspp::parser p(l);
     292             : 
     293           4 :             csspp::node::pointer_t n(p.stylesheet());
     294             : 
     295           4 :             csspp::compiler c;
     296           4 :             c.set_root(n);
     297           4 :             c.set_date_time_variables(csspp_test::get_now());
     298           4 :             c.add_path(csspp_test::get_script_path());
     299           4 :             c.add_path(csspp_test::get_version_script_path());
     300             : 
     301           4 :             c.compile(false);
     302             : 
     303             : //std::cerr << "Compiler result is: [" << *n << "]\n";
     304             : 
     305           4 :             std::stringstream out;
     306           4 :             csspp::assembler a(out);
     307           4 :             a.output(n, static_cast<csspp::output_mode_t>(i));
     308             : 
     309             : //std::cerr << "----------------- Result is " << static_cast<csspp::output_mode_t>(i) << "\n[" << out.str() << "]\n";
     310             : 
     311           4 :             switch(static_cast<csspp::output_mode_t>(i))
     312             :             {
     313           1 :             case csspp::output_mode_t::COMPACT:
     314           1 :                 CATCH_REQUIRE(out.str() ==
     315             : "div { color: #fff; font-size: 1.3rem }\n"
     316             : "span { border: 3px solid #f5c3c2; border-bottom-width: 1px; box-shadow: 1px 0px 7px #8a1, 0px 3px 1px #a83; font: 17.2px/1.35em Arial }\n"
     317             : + csspp_test::get_close_comment()
     318             :                     );
     319           1 :                 break;
     320             : 
     321           1 :             case csspp::output_mode_t::COMPRESSED:
     322           1 :                 CATCH_REQUIRE(out.str() ==
     323             : "div{color:#fff;font-size:1.3rem}span{border:3px solid #f5c3c2;border-bottom-width:1px;box-shadow:1px 0px 7px #8a1,0px 3px 1px #a83;font:17.2px/1.35em Arial}\n"
     324             : + csspp_test::get_close_comment()
     325             :                     );
     326           1 :                 break;
     327             : 
     328           1 :             case csspp::output_mode_t::EXPANDED:
     329           1 :                 CATCH_REQUIRE(out.str() ==
     330             : "div\n"
     331             : "{\n"
     332             : "  color: #fff;\n"
     333             : "  font-size: 1.3rem;\n"
     334             : "}\n"
     335             : "span\n"
     336             : "{\n"
     337             : "  border: 3px solid #f5c3c2;\n"
     338             : "  border-bottom-width: 1px;\n"
     339             : "  box-shadow: 1px 0px 7px #8a1, 0px 3px 1px #a83;\n"
     340             : "  font: 17.2px/1.35em Arial;\n"
     341             : "}\n"
     342             : + csspp_test::get_close_comment()
     343             :                     );
     344           1 :                 break;
     345             : 
     346           1 :             case csspp::output_mode_t::TIDY:
     347           1 :                 CATCH_REQUIRE(out.str() ==
     348             : "div{color:#fff;font-size:1.3rem}\n"
     349             : "span{border:3px solid #f5c3c2;border-bottom-width:1px;box-shadow:1px 0px 7px #8a1,0px 3px 1px #a83;font:17.2px/1.35em Arial}\n"
     350             : + csspp_test::get_close_comment()
     351             :                     );
     352           1 :                 break;
     353             : 
     354             :             }
     355             : 
     356           4 :             CATCH_REQUIRE(c.get_root() == n);
     357           4 :         }
     358             :     }
     359          10 :     CATCH_END_SECTION()
     360             : 
     361          10 :     CATCH_START_SECTION("test multiple selector lists")
     362             :     {
     363           5 :         for(int i(static_cast<int>(csspp::output_mode_t::COMPACT));
     364           5 :             i <= static_cast<int>(csspp::output_mode_t::TIDY);
     365             :             ++i)
     366             :         {
     367           4 :             std::stringstream ss;
     368             :             ss << "div a b,\n"
     369             :                << "p span i\n"
     370             :                << "{\n"
     371             :                << "  color: mix(black, white);\n"
     372             :                << "\t  font-size: 1.3em;\n"
     373             :                << " \n"
     374             :                << "  border: 3px solid desaturate(#f7d0cf, 5%);\n"
     375             :                << "  \tbox-shadow: 1px 0px 7px #88aa11, 0px 3px 1px #aa8833, 1px 2px 3px #92af54;\n"
     376             :                << "\tborder-bottom-width: 1px;\n"
     377             :                << "}\n"
     378           4 :                << "\n";
     379          12 :             csspp::position pos("test.css");
     380           4 :             csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
     381             : 
     382           8 :             csspp::parser p(l);
     383             : 
     384           4 :             csspp::node::pointer_t n(p.stylesheet());
     385             : 
     386           4 :             csspp::compiler c;
     387           4 :             c.set_root(n);
     388           4 :             c.set_date_time_variables(csspp_test::get_now());
     389           4 :             c.add_path(csspp_test::get_script_path());
     390           4 :             c.add_path(csspp_test::get_version_script_path());
     391             : 
     392           4 :             c.compile(false);
     393             : 
     394             : //std::cerr << "Compiler result is: [" << *n << "]\n";
     395             : 
     396           4 :             std::stringstream out;
     397           4 :             csspp::assembler a(out);
     398           4 :             a.output(n, static_cast<csspp::output_mode_t>(i));
     399             : 
     400             : //std::cerr << "----------------- Result is " << static_cast<csspp::output_mode_t>(i) << "\n[" << out.str() << "]\n";
     401             : 
     402           4 :             switch(static_cast<csspp::output_mode_t>(i))
     403             :             {
     404           1 :             case csspp::output_mode_t::COMPACT:
     405           1 :                 CATCH_REQUIRE(out.str() ==
     406             : "div a b, p span i { color: gray; font-size: 1.3em; border: 3px solid #f6d1d0; box-shadow: 1px 0px 7px #8a1, 0px 3px 1px #a83, 1px 2px 3px #92af54; border-bottom-width: 1px }\n"
     407             : + csspp_test::get_close_comment()
     408             :                     );
     409           1 :                 break;
     410             : 
     411           1 :             case csspp::output_mode_t::COMPRESSED:
     412           1 :                 CATCH_REQUIRE(out.str() ==
     413             : "div a b,p span i{color:gray;font-size:1.3em;border:3px solid #f6d1d0;box-shadow:1px 0px 7px #8a1,0px 3px 1px #a83,1px 2px 3px #92af54;border-bottom-width:1px}\n"
     414             : + csspp_test::get_close_comment()
     415             :                     );
     416           1 :                 break;
     417             : 
     418           1 :             case csspp::output_mode_t::EXPANDED:
     419           1 :                 CATCH_REQUIRE(out.str() ==
     420             : "div a b, p span i\n"
     421             : "{\n"
     422             : "  color: gray;\n"
     423             : "  font-size: 1.3em;\n"
     424             : "  border: 3px solid #f6d1d0;\n"
     425             : "  box-shadow: 1px 0px 7px #8a1, 0px 3px 1px #a83, 1px 2px 3px #92af54;\n"
     426             : "  border-bottom-width: 1px;\n"
     427             : "}\n"
     428             : + csspp_test::get_close_comment()
     429             :                     );
     430           1 :                 break;
     431             : 
     432           1 :             case csspp::output_mode_t::TIDY:
     433           1 :                 CATCH_REQUIRE(out.str() ==
     434             : "div a b,p span i{color:gray;font-size:1.3em;border:3px solid #f6d1d0;box-shadow:1px 0px 7px #8a1,0px 3px 1px #a83,1px 2px 3px #92af54;border-bottom-width:1px}\n"
     435             : + csspp_test::get_close_comment()
     436             :                     );
     437           1 :                 break;
     438             : 
     439             :             }
     440             : 
     441           4 :             CATCH_REQUIRE(c.get_root() == n);
     442           4 :         }
     443             :     }
     444          10 :     CATCH_END_SECTION()
     445             : 
     446          10 :     CATCH_START_SECTION("test set_unit() to various numbers")
     447             :     {
     448           5 :         for(int i(static_cast<int>(csspp::output_mode_t::COMPACT));
     449           5 :             i <= static_cast<int>(csspp::output_mode_t::TIDY);
     450             :             ++i)
     451             :         {
     452           4 :             std::stringstream ss;
     453             :             ss << "div \n"
     454             :                << "{\n"
     455             :                << "  width: set_unit(33, px);\n"
     456             :                << "  height: set_unit(3.3, em);\n"
     457             :                << "  margin-left: set_unit(33px, 'cm');\n"
     458             :                << "  margin-right: set_unit(3.3em, mm);\n"
     459             :                //<< "  content: unit(123%);\n"
     460             :                //<< "  z-index: remove_unit(12.3%);\n"
     461             :                << "  margin-top: set_unit(123%, \"px\");\n"
     462             :                << "  margin-bottom: set_unit(45, \"%\");\n"
     463             :                << "  border-bottom-width: set_unit(4.5, \"%\");\n"
     464             :                << "  border-top-width: set_unit(45cm, \"%\");\n"
     465             :                << "  border-left-width: set_unit(.45vm, \"%\");\n"
     466             :                << "  border-right-width: set_unit(68, \"\");\n"
     467             :                << "  background-x: set_unit(68vm, \"\");\n"
     468             :                << "  background-y: set_unit(6.8cm, \"\");\n"
     469             :                << "  padding-left: set_unit(63.81%, \"\");\n"
     470             :                << "}\n"
     471           4 :                << "\n";
     472          12 :             csspp::position pos("test.css");
     473           4 :             csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
     474             : 
     475           8 :             csspp::parser p(l);
     476             : 
     477           4 :             csspp::node::pointer_t n(p.stylesheet());
     478             : 
     479           4 :             csspp::compiler c;
     480           4 :             c.set_root(n);
     481           4 :             c.set_date_time_variables(csspp_test::get_now());
     482           4 :             c.add_path(csspp_test::get_script_path());
     483           4 :             c.add_path(csspp_test::get_version_script_path());
     484             : 
     485           4 :             c.compile(false);
     486             : 
     487             : //std::cerr << "Compiler result is: [" << *n << "]\n";
     488             : 
     489           4 :             std::stringstream out;
     490           4 :             csspp::assembler a(out);
     491           4 :             a.output(n, static_cast<csspp::output_mode_t>(i));
     492             : 
     493             : //std::cerr << "----------------- Result is " << static_cast<csspp::output_mode_t>(i) << "\n[" << out.str() << "]\n";
     494             : 
     495           4 :             switch(static_cast<csspp::output_mode_t>(i))
     496             :             {
     497           1 :             case csspp::output_mode_t::COMPACT:
     498           1 :                 CATCH_REQUIRE(out.str() ==
     499             : "div { width: 33px; height: 3.3em; margin-left: 33cm; margin-right: 3.3mm; margin-top: 1.23px; margin-bottom: 4500%; border-bottom-width: 450%; border-top-width: 4500%; border-left-width: 45%; border-right-width: 68; background-x: 68; background-y: 6.8; padding-left: .638 }\n"
     500             : + csspp_test::get_close_comment()
     501             :                     );
     502           1 :                 break;
     503             : 
     504           1 :             case csspp::output_mode_t::COMPRESSED:
     505           1 :                 CATCH_REQUIRE(out.str() ==
     506             : "div{width:33px;height:3.3em;margin-left:33cm;margin-right:3.3mm;margin-top:1.23px;margin-bottom:4500%;border-bottom-width:450%;border-top-width:4500%;border-left-width:45%;border-right-width:68;background-x:68;background-y:6.8;padding-left:.638}\n"
     507             : + csspp_test::get_close_comment()
     508             :                     );
     509           1 :                 break;
     510             : 
     511           1 :             case csspp::output_mode_t::EXPANDED:
     512           1 :                 CATCH_REQUIRE(out.str() ==
     513             : "div\n"
     514             : "{\n"
     515             : "  width: 33px;\n"
     516             : "  height: 3.3em;\n"
     517             : "  margin-left: 33cm;\n"
     518             : "  margin-right: 3.3mm;\n"
     519             : "  margin-top: 1.23px;\n"
     520             : "  margin-bottom: 4500%;\n"
     521             : "  border-bottom-width: 450%;\n"
     522             : "  border-top-width: 4500%;\n"
     523             : "  border-left-width: 45%;\n"
     524             : "  border-right-width: 68;\n"
     525             : "  background-x: 68;\n"
     526             : "  background-y: 6.8;\n"
     527             : "  padding-left: .638;\n"
     528             : "}\n"
     529             : + csspp_test::get_close_comment()
     530             :                     );
     531           1 :                 break;
     532             : 
     533           1 :             case csspp::output_mode_t::TIDY:
     534           1 :                 CATCH_REQUIRE(out.str() ==
     535             : "div{width:33px;height:3.3em;margin-left:33cm;margin-right:3.3mm;margin-top:1.23px;margin-bottom:4500%;border-bottom-width:450%;border-top-width:4500%;border-left-width:45%;border-right-width:68;background-x:68;background-y:6.8;padding-left:.638}\n"
     536             : + csspp_test::get_close_comment()
     537             :                     );
     538           1 :                 break;
     539             : 
     540             :             }
     541             : 
     542           4 :             CATCH_REQUIRE(c.get_root() == n);
     543           4 :         }
     544             :     }
     545          10 :     CATCH_END_SECTION()
     546             : 
     547          10 :     CATCH_START_SECTION("test unitless() to various numbers")
     548             :     {
     549           5 :         for(int i(static_cast<int>(csspp::output_mode_t::COMPACT));
     550           5 :             i <= static_cast<int>(csspp::output_mode_t::TIDY);
     551             :             ++i)
     552             :         {
     553           4 :             std::stringstream ss;
     554             :             ss << "div \n"
     555             :                << "{\n"
     556             :                << "  width: unitless(33px) ? 15px : 3em;\n"
     557             :                << "  height: unitless(3.3em) ? 5cm : 3mm;\n"
     558             :                << "  content: unitless(123%) ? 'incorrect' : 'correct';\n"
     559             :                << "  border-bottom-width: unitless(4.5) ? 30vm : 45%;\n"
     560             :                << "  border-left-width: unitless(45) ? 131px : 4.15cm;\n"
     561             :                << "}\n"
     562           4 :                << "\n";
     563          12 :             csspp::position pos("test.css");
     564           4 :             csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
     565             : 
     566           8 :             csspp::parser p(l);
     567             : 
     568           4 :             csspp::node::pointer_t n(p.stylesheet());
     569             : 
     570           4 :             csspp::compiler c;
     571           4 :             c.set_root(n);
     572           4 :             c.set_date_time_variables(csspp_test::get_now());
     573           4 :             c.add_path(csspp_test::get_script_path());
     574           4 :             c.add_path(csspp_test::get_version_script_path());
     575             : 
     576           4 :             c.compile(false);
     577             : 
     578             : //std::cerr << "Compiler result is: [" << *n << "]\n";
     579             : 
     580           4 :             std::stringstream out;
     581           4 :             csspp::assembler a(out);
     582           4 :             a.output(n, static_cast<csspp::output_mode_t>(i));
     583             : 
     584             : //std::cerr << "----------------- Result is " << static_cast<csspp::output_mode_t>(i) << "\n[" << out.str() << "]\n";
     585             : 
     586           4 :             switch(static_cast<csspp::output_mode_t>(i))
     587             :             {
     588           1 :             case csspp::output_mode_t::COMPACT:
     589           1 :                 CATCH_REQUIRE(out.str() ==
     590             : "div { width: 3em; height: 3mm; content: \"correct\"; border-bottom-width: 30vm; border-left-width: 131px }\n"
     591             : + csspp_test::get_close_comment()
     592             :                     );
     593           1 :                 break;
     594             : 
     595           1 :             case csspp::output_mode_t::COMPRESSED:
     596           1 :                 CATCH_REQUIRE(out.str() ==
     597             : "div{width:3em;height:3mm;content:\"correct\";border-bottom-width:30vm;border-left-width:131px}\n"
     598             : + csspp_test::get_close_comment()
     599             :                     );
     600           1 :                 break;
     601             : 
     602           1 :             case csspp::output_mode_t::EXPANDED:
     603           1 :                 CATCH_REQUIRE(out.str() ==
     604             : "div\n"
     605             : "{\n"
     606             : "  width: 3em;\n"
     607             : "  height: 3mm;\n"
     608             : "  content: \"correct\";\n"
     609             : "  border-bottom-width: 30vm;\n"
     610             : "  border-left-width: 131px;\n"
     611             : "}\n"
     612             : + csspp_test::get_close_comment()
     613             :                     );
     614           1 :                 break;
     615             : 
     616           1 :             case csspp::output_mode_t::TIDY:
     617           1 :                 CATCH_REQUIRE(out.str() ==
     618             : "div{width:3em;height:3mm;content:\"correct\";border-bottom-width:30vm;border-left-width:131px}\n"
     619             : + csspp_test::get_close_comment()
     620             :                     );
     621           1 :                 break;
     622             : 
     623             :             }
     624             : 
     625           4 :             CATCH_REQUIRE(c.get_root() == n);
     626           4 :         }
     627             :     }
     628          10 :     CATCH_END_SECTION()
     629             : 
     630          10 :     CATCH_START_SECTION("test unique_id()")
     631             :     {
     632           5 :         for(int i(static_cast<int>(csspp::output_mode_t::COMPACT));
     633           5 :             i <= static_cast<int>(csspp::output_mode_t::TIDY);
     634             :             ++i)
     635             :         {
     636           4 :             std::stringstream ss;
     637             :             ss << "div\n"
     638             :                << "{\n"
     639             :                << "  content: string(unique_id());\n"
     640             :                << "  border: 3px unique_id() lightsteelblue;\n"
     641             :                << "}\n"
     642             :                << "a.withColor\n"
     643             :                << "{\n"
     644             :                << "  padding: unique_id();\n"
     645             :                << "}\n"
     646           4 :                << "\n";
     647          12 :             csspp::position pos("test.css");
     648           4 :             csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
     649             : 
     650           8 :             csspp::parser p(l);
     651             : 
     652           4 :             csspp::node::pointer_t n(p.stylesheet());
     653             : 
     654             :             // reset counter so we can compare with 1, 2, 3 each time
     655           4 :             csspp::expression::set_unique_id_counter(0);
     656             : 
     657           4 :             csspp::compiler c;
     658           4 :             c.set_root(n);
     659           4 :             c.set_date_time_variables(csspp_test::get_now());
     660           4 :             c.add_path(csspp_test::get_script_path());
     661           4 :             c.add_path(csspp_test::get_version_script_path());
     662             : 
     663           4 :             c.compile(false);
     664             : 
     665             : //std::cerr << "Compiler result is: [" << *n << "]\n";
     666             : 
     667           4 :             std::stringstream out;
     668           4 :             csspp::assembler a(out);
     669           4 :             a.output(n, static_cast<csspp::output_mode_t>(i));
     670             : 
     671             : //std::cerr << "----------------- Result is " << static_cast<csspp::output_mode_t>(i) << "\n[" << out.str() << "]\n";
     672             : 
     673           4 :             switch(static_cast<csspp::output_mode_t>(i))
     674             :             {
     675           1 :             case csspp::output_mode_t::COMPACT:
     676           1 :                 CATCH_REQUIRE(out.str() ==
     677             : "div { content: \"_csspp_unique1\"; border: 3px _csspp_unique2 #b0c4de }\n"
     678             : "a.withColor { padding: _csspp_unique3 }\n"
     679             : + csspp_test::get_close_comment()
     680             :                     );
     681           1 :                 break;
     682             : 
     683           1 :             case csspp::output_mode_t::COMPRESSED:
     684           1 :                 CATCH_REQUIRE(out.str() ==
     685             : "div{content:\"_csspp_unique1\";border:3px _csspp_unique2 #b0c4de}a.withColor{padding:_csspp_unique3}\n"
     686             : + csspp_test::get_close_comment()
     687             :                     );
     688           1 :                 break;
     689             : 
     690           1 :             case csspp::output_mode_t::EXPANDED:
     691           1 :                 CATCH_REQUIRE(out.str() ==
     692             : "div\n"
     693             : "{\n"
     694             : "  content: \"_csspp_unique1\";\n"
     695             : "  border: 3px _csspp_unique2 #b0c4de;\n"
     696             : "}\n"
     697             : "a.withColor\n"
     698             : "{\n"
     699             : "  padding: _csspp_unique3;\n"
     700             : "}\n"
     701             : + csspp_test::get_close_comment()
     702             :                     );
     703           1 :                 break;
     704             : 
     705           1 :             case csspp::output_mode_t::TIDY:
     706           1 :                 CATCH_REQUIRE(out.str() ==
     707             : "div{content:\"_csspp_unique1\";border:3px _csspp_unique2 #b0c4de}\n"
     708             : "a.withColor{padding:_csspp_unique3}\n"
     709             : + csspp_test::get_close_comment()
     710             :                     );
     711           1 :                 break;
     712             : 
     713             :             }
     714             : 
     715           4 :             CATCH_REQUIRE(c.get_root() == n);
     716           4 :         }
     717             :     }
     718          10 :     CATCH_END_SECTION()
     719             : 
     720          10 :     CATCH_START_SECTION("identifier with unicode characters and starting with a digit and including a period")
     721             :     {
     722           5 :         for(int i(static_cast<int>(csspp::output_mode_t::COMPACT));
     723           5 :             i <= static_cast<int>(csspp::output_mode_t::TIDY);
     724             :             ++i)
     725             :         {
     726           4 :             std::stringstream ss;
     727             :             // word "e'te'" (summer in French)
     728             :             ss << "\xc3\xa9t\xc3\xa9 { color: fade_in(gold, 0.2); }\n"
     729             :                << "\\33 21 { color: fade_out(tan, 0.2); }\n"
     730             :                << "\\36 face { color: orchid; }\n"
     731             :                << "\\30 BLUR { color: thistle; }\n"
     732             :                << "this\\.and\\.that { color: honeydew; }\n"
     733             :                << "\xe4\x96\x82 { color: dimgray; }\n"
     734             :                << "\xf0\x90\x90\x94\xf0\x90\x90\xa9\xf0\x90\x91\x85\xf0\x90\x90\xaf\xf0\x90\x91\x89\xf0\x90\x90\xaf\xf0\x90\x90\xbb { color: darkred; }\n"
     735           4 :                << "normal { color: mix(darkseagreen, lavender, 0.3); }\n";
     736          12 :             csspp::position pos("test.css");
     737           4 :             csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
     738             : 
     739           8 :             csspp::parser p(l);
     740             : 
     741           4 :             csspp::node::pointer_t n(p.stylesheet());
     742             : 
     743           4 :             csspp::compiler c;
     744           4 :             c.set_root(n);
     745           4 :             c.set_date_time_variables(csspp_test::get_now());
     746           4 :             c.add_path(csspp_test::get_script_path());
     747           4 :             c.add_path(csspp_test::get_version_script_path());
     748             : 
     749           4 :             c.compile(false);
     750             : 
     751             : //std::cerr << "Compiler result is: [" << *c.get_root() << "]\n";
     752             : 
     753           4 :             std::stringstream out;
     754           4 :             csspp::assembler a(out);
     755           4 :             a.output(n, static_cast<csspp::output_mode_t>(i));
     756             : 
     757             : //std::cerr << "----------------- Result is " << static_cast<csspp::output_mode_t>(i) << "\n[" << out.str() << "]\n";
     758             : 
     759           4 :             switch(static_cast<csspp::output_mode_t>(i))
     760             :             {
     761           1 :             case csspp::output_mode_t::COMPACT:
     762           1 :                 CATCH_REQUIRE(out.str() ==
     763             : "\xc3\xa9t\xc3\xa9 { color: #ffd700 }\n"
     764             : "\\33 21 { color: rgba(210,180,140,.8) }\n"
     765             : "\\36 face { color: #da70d6 }\n"
     766             : "\\30 BLUR { color: #d8bfd8 }\n"
     767             : "this\\.and\\.that { color: #f0fff0 }\n"
     768             : "\xe4\x96\x82 { color: #696969 }\n"
     769             : "\xf0\x90\x90\x94\xf0\x90\x90\xa9\xf0\x90\x91\x85\xf0\x90\x90\xaf\xf0\x90\x91\x89\xf0\x90\x90\xaf\xf0\x90\x90\xbb { color: #8b0000 }\n"
     770             : "normal { color: #ccd9da }\n"
     771             : + csspp_test::get_close_comment()
     772             :                     );
     773           1 :                 break;
     774             : 
     775           1 :             case csspp::output_mode_t::COMPRESSED:
     776           1 :                 CATCH_REQUIRE(out.str() ==
     777             : "\xc3\xa9t\xc3\xa9{color:#ffd700}"
     778             : "\\33 21{color:rgba(210,180,140,.8)}"
     779             : "\\36 face{color:#da70d6}"
     780             : "\\30 BLUR{color:#d8bfd8}"
     781             : "this\\.and\\.that{color:#f0fff0}"
     782             : "\xe4\x96\x82{color:#696969}"
     783             : "\xf0\x90\x90\x94\xf0\x90\x90\xa9\xf0\x90\x91\x85\xf0\x90\x90\xaf\xf0\x90\x91\x89\xf0\x90\x90\xaf\xf0\x90\x90\xbb{color:#8b0000}"
     784             : "normal{color:#ccd9da}"
     785             : "\n"
     786             : + csspp_test::get_close_comment()
     787             :                     );
     788           1 :                 break;
     789             : 
     790           1 :             case csspp::output_mode_t::EXPANDED:
     791           1 :                 CATCH_REQUIRE(out.str() ==
     792             : "\xc3\xa9t\xc3\xa9\n"
     793             : "{\n"
     794             : "  color: #ffd700;\n"
     795             : "}\n"
     796             : "\\33 21\n"
     797             : "{\n"
     798             : "  color: rgba(210,180,140,.8);\n"
     799             : "}\n"
     800             : "\\36 face\n"
     801             : "{\n"
     802             : "  color: #da70d6;\n"
     803             : "}\n"
     804             : "\\30 BLUR\n"
     805             : "{\n"
     806             : "  color: #d8bfd8;\n"
     807             : "}\n"
     808             : "this\\.and\\.that\n"
     809             : "{\n"
     810             : "  color: #f0fff0;\n"
     811             : "}\n"
     812             : "\xe4\x96\x82\n"
     813             : "{\n"
     814             : "  color: #696969;\n"
     815             : "}\n"
     816             : "\xf0\x90\x90\x94\xf0\x90\x90\xa9\xf0\x90\x91\x85\xf0\x90\x90\xaf\xf0\x90\x91\x89\xf0\x90\x90\xaf\xf0\x90\x90\xbb\n"
     817             : "{\n"
     818             : "  color: #8b0000;\n"
     819             : "}\n"
     820             : "normal\n"
     821             : "{\n"
     822             : "  color: #ccd9da;\n"
     823             : "}\n"
     824             : + csspp_test::get_close_comment()
     825             :                     );
     826           1 :                 break;
     827             : 
     828           1 :             case csspp::output_mode_t::TIDY:
     829           1 :                 CATCH_REQUIRE(out.str() ==
     830             : "\xc3\xa9t\xc3\xa9{color:#ffd700}\n"
     831             : "\\33 21{color:rgba(210,180,140,.8)}\n"
     832             : "\\36 face{color:#da70d6}\n"
     833             : "\\30 BLUR{color:#d8bfd8}\n"
     834             : "this\\.and\\.that{color:#f0fff0}\n"
     835             : "\xe4\x96\x82{color:#696969}\n"
     836             : "\xf0\x90\x90\x94\xf0\x90\x90\xa9\xf0\x90\x91\x85\xf0\x90\x90\xaf\xf0\x90\x91\x89\xf0\x90\x90\xaf\xf0\x90\x90\xbb{color:#8b0000}\n"
     837             : "normal{color:#ccd9da}\n"
     838             : + csspp_test::get_close_comment()
     839             :                     );
     840           1 :                 break;
     841             : 
     842             :             }
     843             : 
     844           4 :             CATCH_REQUIRE(c.get_root() == n);
     845           4 :         }
     846             :     }
     847          10 :     CATCH_END_SECTION()
     848             : 
     849          10 :     CATCH_START_SECTION("whitespace at the beginning of a rule")
     850             :     {
     851           5 :         for(int i(static_cast<int>(csspp::output_mode_t::COMPACT));
     852           5 :             i <= static_cast<int>(csspp::output_mode_t::TIDY);
     853             :             ++i)
     854             :         {
     855           4 :             std::stringstream ss;
     856             :             ss << "  // spaces before a comment will produce problems\n"
     857             :                << "  // and such comments are not preserved as expected\n"
     858             :                << "  // @preserve this comment\n"
     859             :                << "\n"
     860             :                << ".face { content: quote(\xe4\x96\x82); }\n"
     861             :                << ".hair { color: fade_in(rgba(50, 100, 150, 0.14), 0.46); }\n"
     862           4 :                << ".plan { opacity: opacity(fade_in(rgba(50, 100, 150, 0.14), 0.46)); }\n";
     863          12 :             csspp::position pos("test.css");
     864           4 :             csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
     865             : 
     866           8 :             csspp::parser p(l);
     867             : 
     868           4 :             csspp::node::pointer_t n(p.stylesheet());
     869             : 
     870           4 :             csspp::compiler c;
     871           4 :             c.set_root(n);
     872           4 :             c.set_date_time_variables(csspp_test::get_now());
     873           4 :             c.add_path(csspp_test::get_script_path());
     874           4 :             c.add_path(csspp_test::get_version_script_path());
     875             : 
     876           4 :             c.compile(false);
     877             : 
     878             : //std::cerr << "Compiler result is: [" << *c.get_root() << "]\n";
     879             : 
     880           4 :             std::stringstream out;
     881           4 :             csspp::assembler a(out);
     882           4 :             a.output(n, static_cast<csspp::output_mode_t>(i));
     883             : 
     884             : //std::cerr << "----------------- Result is " << static_cast<csspp::output_mode_t>(i) << "\n[" << out.str() << "]\n";
     885             : 
     886           4 :             VERIFY_ERRORS("test.css(3): warning: C++ comments should not be preserved as they are not supported by most CSS parsers.\n");
     887             : 
     888           4 :             switch(static_cast<csspp::output_mode_t>(i))
     889             :             {
     890           1 :             case csspp::output_mode_t::COMPACT:
     891           1 :                 CATCH_REQUIRE(out.str() ==
     892             : "/* @preserve this comment */\n"
     893             : ".face { content: \"\xe4\x96\x82\" }\n"
     894             : ".hair { color: rgba(50,100,150,.6) }\n"
     895             : ".plan { opacity: .6 }\n"
     896             : + csspp_test::get_close_comment()
     897             :                     );
     898           1 :                 break;
     899             : 
     900           1 :             case csspp::output_mode_t::COMPRESSED:
     901           1 :                 CATCH_REQUIRE(out.str() ==
     902             : "/* @preserve this comment */\n"
     903             : ".face{content:\"\xe4\x96\x82\"}"
     904             : ".hair{color:rgba(50,100,150,.6)}"
     905             : ".plan{opacity:.6}"
     906             : "\n"
     907             : + csspp_test::get_close_comment()
     908             :                     );
     909           1 :                 break;
     910             : 
     911           1 :             case csspp::output_mode_t::EXPANDED:
     912           1 :                 CATCH_REQUIRE(out.str() ==
     913             : "/* @preserve this comment */\n"
     914             : ".face\n"
     915             : "{\n"
     916             : "  content: \"\xe4\x96\x82\";\n"
     917             : "}\n"
     918             : ".hair\n"
     919             : "{\n"
     920             : "  color: rgba(50,100,150,.6);\n"
     921             : "}\n"
     922             : ".plan\n"
     923             : "{\n"
     924             : "  opacity: .6;\n"
     925             : "}\n"
     926             : + csspp_test::get_close_comment()
     927             :                     );
     928           1 :                 break;
     929             : 
     930           1 :             case csspp::output_mode_t::TIDY:
     931           1 :                 CATCH_REQUIRE(out.str() ==
     932             : "/* @preserve this comment */\n"
     933             : ".face{content:\"\xe4\x96\x82\"}\n"
     934             : ".hair{color:rgba(50,100,150,.6)}\n"
     935             : ".plan{opacity:.6}\n"
     936             : + csspp_test::get_close_comment()
     937             :                     );
     938           1 :                 break;
     939             : 
     940             :             }
     941             : 
     942           4 :             CATCH_REQUIRE(c.get_root() == n);
     943           4 :         }
     944             :     }
     945          10 :     CATCH_END_SECTION()
     946             : 
     947          10 :     CATCH_START_SECTION("whitespace at the beginning of a variable")
     948             :     {
     949           5 :         for(int i(static_cast<int>(csspp::output_mode_t::COMPACT));
     950           5 :             i <= static_cast<int>(csspp::output_mode_t::TIDY);
     951             :             ++i)
     952             :         {
     953           4 :             std::stringstream ss;
     954             :             ss << "  // an empty comment was creating trouble!\n"
     955             :                << "  //\n"
     956             :                << "\n"
     957             :                << "$color: #329182;\n"
     958             :                << "$image: url(\"images/ladybug.jpeg\");\n"
     959             :                << "$width: 300px;\n"
     960             :                << "\n"
     961             :                << "  p\n"
     962             :                << "  {\n"
     963             :                << "    // background color defined in variable\n"
     964             :                << "    background-color: grayscale($color);\n"
     965             :                << "\n"
     966             :                << "    // this is like \"body div.flowers\"\n"
     967             :                << "    div.flowers\n"
     968             :                << "    {\n"
     969             :                << "      background-image: $image;\n"
     970             :                << "      z-index: remove_unit($width);\n"
     971             :                << "    }\n"
     972             :                << "  }\n"
     973           4 :                << "\n";
     974          12 :             csspp::position pos("test.css");
     975           4 :             csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
     976             : 
     977           8 :             csspp::parser p(l);
     978             : 
     979           4 :             csspp::node::pointer_t n(p.stylesheet());
     980             : 
     981             : //std::cerr << "Parser result is: [" << *n << "]\n";
     982             : 
     983           4 :             csspp::compiler c;
     984           4 :             c.set_root(n);
     985           4 :             c.set_date_time_variables(csspp_test::get_now());
     986           4 :             c.add_path(csspp_test::get_script_path());
     987           4 :             c.add_path(csspp_test::get_version_script_path());
     988             : 
     989           4 :             c.compile(false);
     990             : 
     991             : //std::cerr << "Compiler result is: [" << *c.get_root() << "]\n";
     992             : 
     993           4 :             std::stringstream out;
     994           4 :             csspp::assembler a(out);
     995           4 :             a.output(n, static_cast<csspp::output_mode_t>(i));
     996             : 
     997             : //std::cerr << "----------------- Result is " << static_cast<csspp::output_mode_t>(i) << "\n[" << out.str() << "]\n";
     998             : 
     999           4 :             VERIFY_ERRORS("");
    1000             : 
    1001           4 :             switch(static_cast<csspp::output_mode_t>(i))
    1002             :             {
    1003           1 :             case csspp::output_mode_t::COMPACT:
    1004           1 :                 CATCH_REQUIRE(out.str() ==
    1005             : "p { background-color: #626262 }\n"
    1006             : "p div.flowers { background-image: url( images/ladybug.jpeg ); z-index: 300 }\n"
    1007             : + csspp_test::get_close_comment()
    1008             :                     );
    1009           1 :                 break;
    1010             : 
    1011           1 :             case csspp::output_mode_t::COMPRESSED:
    1012           1 :                 CATCH_REQUIRE(out.str() ==
    1013             : "p{background-color:#626262}"
    1014             : "p div.flowers{background-image:url(images/ladybug.jpeg);z-index:300}"
    1015             : "\n"
    1016             : + csspp_test::get_close_comment()
    1017             :                     );
    1018           1 :                 break;
    1019             : 
    1020           1 :             case csspp::output_mode_t::EXPANDED:
    1021           1 :                 CATCH_REQUIRE(out.str() ==
    1022             : "p\n"
    1023             : "{\n"
    1024             : "  background-color: #626262;\n"
    1025             : "}\n"
    1026             : "p div.flowers\n"
    1027             : "{\n"
    1028             : "  background-image: url( images/ladybug.jpeg );\n"
    1029             : "  z-index: 300;\n"
    1030             : "}\n"
    1031             : + csspp_test::get_close_comment()
    1032             :                     );
    1033           1 :                 break;
    1034             : 
    1035           1 :             case csspp::output_mode_t::TIDY:
    1036           1 :                 CATCH_REQUIRE(out.str() ==
    1037             : "p{background-color:#626262}\n"
    1038             : "p div.flowers{background-image:url(images/ladybug.jpeg);z-index:300}\n"
    1039             : + csspp_test::get_close_comment()
    1040             :                     );
    1041           1 :                 break;
    1042             : 
    1043             :             }
    1044             : 
    1045           4 :             CATCH_REQUIRE(c.get_root() == n);
    1046           4 :         }
    1047             :     }
    1048          10 :     CATCH_END_SECTION()
    1049             : 
    1050             :     // no error left over
    1051          10 :     VERIFY_ERRORS("");
    1052          10 : }
    1053             : 
    1054           1 : CATCH_TEST_CASE("Assemble selectors", "[assembler] [selectors]")
    1055             : {
    1056             :     // check various selectors without the operators
    1057             : 
    1058             :     // simple identifiers
    1059           5 :     for(int i(static_cast<int>(csspp::output_mode_t::COMPACT));
    1060           5 :         i <= static_cast<int>(csspp::output_mode_t::TIDY);
    1061             :         ++i)
    1062             :     {
    1063           4 :         std::stringstream ss;
    1064           4 :         ss << "div span a { color: black; }";
    1065          12 :         csspp::position pos("test.css");
    1066           4 :         csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
    1067             : 
    1068           8 :         csspp::parser p(l);
    1069             : 
    1070           4 :         csspp::node::pointer_t n(p.stylesheet());
    1071             : 
    1072           4 :         csspp::compiler c;
    1073           4 :         c.set_root(n);
    1074           4 :         c.set_date_time_variables(csspp_test::get_now());
    1075           4 :         c.add_path(csspp_test::get_script_path());
    1076           4 :         c.add_path(csspp_test::get_version_script_path());
    1077             : 
    1078           4 :         c.compile(false);
    1079             : 
    1080             : //std::cerr << "Compiler result is: [" << *c.get_root() << "]\n";
    1081             : 
    1082           4 :         std::stringstream out;
    1083           4 :         csspp::assembler a(out);
    1084           4 :         a.output(n, static_cast<csspp::output_mode_t>(i));
    1085             : 
    1086             : //std::cerr << "----------------- Result is " << static_cast<csspp::output_mode_t>(i) << "\n[" << out.str() << "]\n";
    1087             : 
    1088           4 :         switch(static_cast<csspp::output_mode_t>(i))
    1089             :         {
    1090           1 :         case csspp::output_mode_t::COMPACT:
    1091           1 :             CATCH_REQUIRE(out.str() ==
    1092             : "div span a { color: #000 }\n"
    1093             : + csspp_test::get_close_comment()
    1094             :                 );
    1095           1 :             break;
    1096             : 
    1097           1 :         case csspp::output_mode_t::COMPRESSED:
    1098           1 :             CATCH_REQUIRE(out.str() ==
    1099             : "div span a{color:#000}\n"
    1100             : + csspp_test::get_close_comment()
    1101             :                 );
    1102           1 :             break;
    1103             : 
    1104           1 :         case csspp::output_mode_t::EXPANDED:
    1105           1 :             CATCH_REQUIRE(out.str() ==
    1106             : "div span a\n"
    1107             : "{\n"
    1108             : "  color: #000;\n"
    1109             : "}\n"
    1110             : + csspp_test::get_close_comment()
    1111             :                 );
    1112           1 :             break;
    1113             : 
    1114           1 :         case csspp::output_mode_t::TIDY:
    1115           1 :             CATCH_REQUIRE(out.str() ==
    1116             : "div span a{color:#000}\n"
    1117             : + csspp_test::get_close_comment()
    1118             :                 );
    1119           1 :             break;
    1120             : 
    1121             :         }
    1122             : 
    1123           4 :         CATCH_REQUIRE(c.get_root() == n);
    1124           4 :     }
    1125             : 
    1126             :     // test a simple attribute
    1127           5 :     for(int i(static_cast<int>(csspp::output_mode_t::COMPACT));
    1128           5 :         i <= static_cast<int>(csspp::output_mode_t::TIDY);
    1129             :         ++i)
    1130             :     {
    1131           4 :         std::stringstream ss;
    1132           4 :         ss << "div[foo] {color: black}\n";
    1133          12 :         csspp::position pos("test.css");
    1134           4 :         csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
    1135             : 
    1136           8 :         csspp::parser p(l);
    1137             : 
    1138           4 :         csspp::node::pointer_t n(p.stylesheet());
    1139             : 
    1140           4 :         csspp::compiler c;
    1141           4 :         c.set_root(n);
    1142           4 :         c.set_date_time_variables(csspp_test::get_now());
    1143           4 :         c.add_path(csspp_test::get_script_path());
    1144           4 :         c.add_path(csspp_test::get_version_script_path());
    1145             : 
    1146           4 :         c.compile(false);
    1147             : 
    1148             : //std::cerr << "Compiler result is: [" << *n << "]\n";
    1149             : 
    1150           4 :         std::stringstream out;
    1151           4 :         csspp::assembler a(out);
    1152           4 :         a.output(n, static_cast<csspp::output_mode_t>(i));
    1153             : 
    1154             : //std::cerr << "----------------- Result is " << static_cast<csspp::output_mode_t>(i) << "\n[" << out.str() << "]\n";
    1155             : 
    1156           4 :         switch(static_cast<csspp::output_mode_t>(i))
    1157             :         {
    1158           1 :         case csspp::output_mode_t::COMPACT:
    1159           1 :             CATCH_REQUIRE(out.str() ==
    1160             : "div[foo] { color: #000 }\n"
    1161             : + csspp_test::get_close_comment()
    1162             :                 );
    1163           1 :             break;
    1164             : 
    1165           1 :         case csspp::output_mode_t::COMPRESSED:
    1166           1 :             CATCH_REQUIRE(out.str() ==
    1167             : "div[foo]{color:#000}\n"
    1168             : + csspp_test::get_close_comment()
    1169             :                 );
    1170           1 :             break;
    1171             : 
    1172           1 :         case csspp::output_mode_t::EXPANDED:
    1173           1 :             CATCH_REQUIRE(out.str() ==
    1174             : "div[foo]\n"
    1175             : "{\n"
    1176             : "  color: #000;\n"
    1177             : "}\n"
    1178             : + csspp_test::get_close_comment()
    1179             :                 );
    1180           1 :             break;
    1181             : 
    1182           1 :         case csspp::output_mode_t::TIDY:
    1183           1 :             CATCH_REQUIRE(out.str() ==
    1184             : "div[foo]{color:#000}\n"
    1185             : + csspp_test::get_close_comment()
    1186             :                 );
    1187           1 :             break;
    1188             : 
    1189             :         }
    1190             : 
    1191           4 :         CATCH_REQUIRE(c.get_root() == n);
    1192           4 :     }
    1193             : 
    1194             :     // Test with a class
    1195           5 :     for(int i(static_cast<int>(csspp::output_mode_t::COMPACT));
    1196           5 :         i <= static_cast<int>(csspp::output_mode_t::TIDY);
    1197             :         ++i)
    1198             :     {
    1199           4 :         std::stringstream ss;
    1200           4 :         ss << "div.foo{color:black}\n";
    1201          12 :         csspp::position pos("test.css");
    1202           4 :         csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
    1203             : 
    1204           8 :         csspp::parser p(l);
    1205             : 
    1206           4 :         csspp::node::pointer_t n(p.stylesheet());
    1207             : 
    1208           4 :         csspp::compiler c;
    1209           4 :         c.set_root(n);
    1210           4 :         c.set_date_time_variables(csspp_test::get_now());
    1211           4 :         c.add_path(csspp_test::get_script_path());
    1212           4 :         c.add_path(csspp_test::get_version_script_path());
    1213             : 
    1214           4 :         c.compile(false);
    1215             : 
    1216             : //std::cerr << "Compiler result is: [" << *n << "]\n";
    1217             : 
    1218           4 :         std::stringstream out;
    1219           4 :         csspp::assembler a(out);
    1220           4 :         a.output(n, static_cast<csspp::output_mode_t>(i));
    1221             : 
    1222             : //std::cerr << "----------------- Result is " << static_cast<csspp::output_mode_t>(i) << "\n[" << out.str() << "]\n";
    1223             : 
    1224           4 :         switch(static_cast<csspp::output_mode_t>(i))
    1225             :         {
    1226           1 :         case csspp::output_mode_t::COMPACT:
    1227           1 :             CATCH_REQUIRE(out.str() ==
    1228             : "div.foo { color: #000 }\n"
    1229             : + csspp_test::get_close_comment()
    1230             :                 );
    1231           1 :             break;
    1232             : 
    1233           1 :         case csspp::output_mode_t::COMPRESSED:
    1234           1 :             CATCH_REQUIRE(out.str() ==
    1235             : "div.foo{color:#000}\n"
    1236             : + csspp_test::get_close_comment()
    1237             :                 );
    1238           1 :             break;
    1239             : 
    1240           1 :         case csspp::output_mode_t::EXPANDED:
    1241           1 :             CATCH_REQUIRE(out.str() ==
    1242             : "div.foo\n"
    1243             : "{\n"
    1244             : "  color: #000;\n"
    1245             : "}\n"
    1246             : + csspp_test::get_close_comment()
    1247             :                 );
    1248           1 :             break;
    1249             : 
    1250           1 :         case csspp::output_mode_t::TIDY:
    1251           1 :             CATCH_REQUIRE(out.str() ==
    1252             : "div.foo{color:#000}\n"
    1253             : + csspp_test::get_close_comment()
    1254             :                 );
    1255           1 :             break;
    1256             : 
    1257             :         }
    1258             : 
    1259           4 :         CATCH_REQUIRE(c.get_root() == n);
    1260           4 :     }
    1261             : 
    1262             :     // Test with an identifier
    1263           5 :     for(int i(static_cast<int>(csspp::output_mode_t::COMPACT));
    1264           5 :         i <= static_cast<int>(csspp::output_mode_t::TIDY);
    1265             :         ++i)
    1266             :     {
    1267           4 :         std::stringstream ss;
    1268           4 :         ss << "#foo div{color:black}\n";
    1269          12 :         csspp::position pos("test.css");
    1270           4 :         csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
    1271             : 
    1272           8 :         csspp::parser p(l);
    1273             : 
    1274           4 :         csspp::node::pointer_t n(p.stylesheet());
    1275             : 
    1276           4 :         csspp::compiler c;
    1277           4 :         c.set_root(n);
    1278           4 :         c.set_date_time_variables(csspp_test::get_now());
    1279           4 :         c.add_path(csspp_test::get_script_path());
    1280           4 :         c.add_path(csspp_test::get_version_script_path());
    1281             : 
    1282           4 :         c.compile(false);
    1283             : 
    1284             : //std::cerr << "Compiler result is: [" << *n << "]\n";
    1285             : 
    1286           4 :         std::stringstream out;
    1287           4 :         csspp::assembler a(out);
    1288           4 :         a.output(n, static_cast<csspp::output_mode_t>(i));
    1289             : 
    1290             : //std::cerr << "----------------- Result is " << static_cast<csspp::output_mode_t>(i) << "\n[" << out.str() << "]\n";
    1291             : 
    1292           4 :         switch(static_cast<csspp::output_mode_t>(i))
    1293             :         {
    1294           1 :         case csspp::output_mode_t::COMPACT:
    1295           1 :             CATCH_REQUIRE(out.str() ==
    1296             : "#foo div { color: #000 }\n"
    1297             : + csspp_test::get_close_comment()
    1298             :                 );
    1299           1 :             break;
    1300             : 
    1301           1 :         case csspp::output_mode_t::COMPRESSED:
    1302           1 :             CATCH_REQUIRE(out.str() ==
    1303             : "#foo div{color:#000}\n"
    1304             : + csspp_test::get_close_comment()
    1305             :                 );
    1306           1 :             break;
    1307             : 
    1308           1 :         case csspp::output_mode_t::EXPANDED:
    1309           1 :             CATCH_REQUIRE(out.str() ==
    1310             : "#foo div\n"
    1311             : "{\n"
    1312             : "  color: #000;\n"
    1313             : "}\n"
    1314             : + csspp_test::get_close_comment()
    1315             :                 );
    1316           1 :             break;
    1317             : 
    1318           1 :         case csspp::output_mode_t::TIDY:
    1319           1 :             CATCH_REQUIRE(out.str() ==
    1320             : "#foo div{color:#000}\n"
    1321             : + csspp_test::get_close_comment()
    1322             :                 );
    1323           1 :             break;
    1324             : 
    1325             :         }
    1326             : 
    1327           4 :         CATCH_REQUIRE(c.get_root() == n);
    1328           4 :     }
    1329             : 
    1330             :     // test an attribute with a test
    1331           5 :     for(int i(static_cast<int>(csspp::output_mode_t::COMPACT));
    1332           5 :         i <= static_cast<int>(csspp::output_mode_t::TIDY);
    1333             :         ++i)
    1334             :     {
    1335           4 :         std::stringstream ss;
    1336           4 :         ss << "div[foo=\"a b c\"] {color: black}\n";
    1337          12 :         csspp::position pos("test.css");
    1338           4 :         csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
    1339             : 
    1340           8 :         csspp::parser p(l);
    1341             : 
    1342           4 :         csspp::node::pointer_t n(p.stylesheet());
    1343             : 
    1344           4 :         csspp::compiler c;
    1345           4 :         c.set_root(n);
    1346           4 :         c.set_date_time_variables(csspp_test::get_now());
    1347           4 :         c.add_path(csspp_test::get_script_path());
    1348           4 :         c.add_path(csspp_test::get_version_script_path());
    1349             : 
    1350           4 :         c.compile(false);
    1351             : 
    1352             : //std::cerr << "Compiler result is: [" << *n << "]\n";
    1353             : 
    1354           4 :         std::stringstream out;
    1355           4 :         csspp::assembler a(out);
    1356           4 :         a.output(n, static_cast<csspp::output_mode_t>(i));
    1357             : 
    1358             : //std::cerr << "----------------- Result is " << static_cast<csspp::output_mode_t>(i) << "\n[" << out.str() << "]\n";
    1359             : 
    1360           4 :         switch(static_cast<csspp::output_mode_t>(i))
    1361             :         {
    1362           1 :         case csspp::output_mode_t::COMPACT:
    1363           1 :             CATCH_REQUIRE(out.str() ==
    1364             : "div[foo = \"a b c\"] { color: #000 }\n"
    1365             : + csspp_test::get_close_comment()
    1366             :                 );
    1367           1 :             break;
    1368             : 
    1369           1 :         case csspp::output_mode_t::COMPRESSED:
    1370           1 :             CATCH_REQUIRE(out.str() ==
    1371             : "div[foo=\"a b c\"]{color:#000}\n"
    1372             : + csspp_test::get_close_comment()
    1373             :                 );
    1374           1 :             break;
    1375             : 
    1376           1 :         case csspp::output_mode_t::EXPANDED:
    1377           1 :             CATCH_REQUIRE(out.str() ==
    1378             : "div[foo = \"a b c\"]\n"
    1379             : "{\n"
    1380             : "  color: #000;\n"
    1381             : "}\n"
    1382             : + csspp_test::get_close_comment()
    1383             :                 );
    1384           1 :             break;
    1385             : 
    1386           1 :         case csspp::output_mode_t::TIDY:
    1387           1 :             CATCH_REQUIRE(out.str() ==
    1388             : "div[foo=\"a b c\"]{color:#000}\n"
    1389             : + csspp_test::get_close_comment()
    1390             :                 );
    1391           1 :             break;
    1392             : 
    1393             :         }
    1394             : 
    1395           4 :         CATCH_REQUIRE(c.get_root() == n);
    1396           4 :     }
    1397             : 
    1398             :     // test an :lang() pseudo function
    1399           5 :     for(int i(static_cast<int>(csspp::output_mode_t::COMPACT));
    1400           5 :         i <= static_cast<int>(csspp::output_mode_t::TIDY);
    1401             :         ++i)
    1402             :     {
    1403           4 :         std::stringstream ss;
    1404           4 :         ss << "div:lang(fr) {color: black}\n";
    1405          12 :         csspp::position pos("test.css");
    1406           4 :         csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
    1407             : 
    1408           8 :         csspp::parser p(l);
    1409             : 
    1410           4 :         csspp::node::pointer_t n(p.stylesheet());
    1411             : 
    1412           4 :         csspp::compiler c;
    1413           4 :         c.set_root(n);
    1414           4 :         c.set_date_time_variables(csspp_test::get_now());
    1415           4 :         c.add_path(csspp_test::get_script_path());
    1416           4 :         c.add_path(csspp_test::get_version_script_path());
    1417             : 
    1418           4 :         c.compile(false);
    1419             : 
    1420             : //std::cerr << "Compiler result is: [" << *n << "]\n";
    1421             : 
    1422           4 :         std::stringstream out;
    1423           4 :         csspp::assembler a(out);
    1424           4 :         a.output(n, static_cast<csspp::output_mode_t>(i));
    1425             : 
    1426             : //std::cerr << "----------------- Result is " << static_cast<csspp::output_mode_t>(i) << "\n[" << out.str() << "]\n";
    1427             : 
    1428           4 :         switch(static_cast<csspp::output_mode_t>(i))
    1429             :         {
    1430           1 :         case csspp::output_mode_t::COMPACT:
    1431           1 :             CATCH_REQUIRE(out.str() ==
    1432             : "div:lang(fr) { color: #000 }\n"
    1433             : + csspp_test::get_close_comment()
    1434             :                 );
    1435           1 :             break;
    1436             : 
    1437           1 :         case csspp::output_mode_t::COMPRESSED:
    1438           1 :             CATCH_REQUIRE(out.str() ==
    1439             : "div:lang(fr){color:#000}\n"
    1440             : + csspp_test::get_close_comment()
    1441             :                 );
    1442           1 :             break;
    1443             : 
    1444           1 :         case csspp::output_mode_t::EXPANDED:
    1445           1 :             CATCH_REQUIRE(out.str() ==
    1446             : "div:lang(fr)\n"
    1447             : "{\n"
    1448             : "  color: #000;\n"
    1449             : "}\n"
    1450             : + csspp_test::get_close_comment()
    1451             :                 );
    1452           1 :             break;
    1453             : 
    1454           1 :         case csspp::output_mode_t::TIDY:
    1455           1 :             CATCH_REQUIRE(out.str() ==
    1456             : "div:lang(fr){color:#000}\n"
    1457             : + csspp_test::get_close_comment()
    1458             :                 );
    1459           1 :             break;
    1460             : 
    1461             :         }
    1462             : 
    1463           4 :         CATCH_REQUIRE(c.get_root() == n);
    1464           4 :     }
    1465             : 
    1466             :     // test an :not() pseudo function
    1467           5 :     for(int i(static_cast<int>(csspp::output_mode_t::COMPACT));
    1468           5 :         i <= static_cast<int>(csspp::output_mode_t::TIDY);
    1469             :         ++i)
    1470             :     {
    1471           4 :         std::stringstream ss;
    1472           4 :         ss << "div:not(:lang(fr)):not(:nth-child(2n+1)) {color: black}\n";
    1473          12 :         csspp::position pos("test.css");
    1474           4 :         csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
    1475             : 
    1476           8 :         csspp::parser p(l);
    1477             : 
    1478           4 :         csspp::node::pointer_t n(p.stylesheet());
    1479             : 
    1480           4 :         csspp::compiler c;
    1481           4 :         c.set_root(n);
    1482           4 :         c.set_date_time_variables(csspp_test::get_now());
    1483           4 :         c.add_path(csspp_test::get_script_path());
    1484           4 :         c.add_path(csspp_test::get_version_script_path());
    1485             : 
    1486           4 :         c.compile(false);
    1487             : 
    1488             : //std::cerr << "Compiler result is: [" << *n << "]\n";
    1489             : 
    1490           4 :         std::stringstream out;
    1491           4 :         csspp::assembler a(out);
    1492           4 :         a.output(n, static_cast<csspp::output_mode_t>(i));
    1493             : 
    1494             : //std::cerr << "----------------- Result is " << static_cast<csspp::output_mode_t>(i) << "\n[" << out.str() << "]\n";
    1495             : 
    1496           4 :         switch(static_cast<csspp::output_mode_t>(i))
    1497             :         {
    1498           1 :         case csspp::output_mode_t::COMPACT:
    1499           1 :             CATCH_REQUIRE(out.str() ==
    1500             : "div:not(:lang(fr)):not(:nth-child(odd)) { color: #000 }\n"
    1501             : + csspp_test::get_close_comment()
    1502             :                 );
    1503           1 :             break;
    1504             : 
    1505           1 :         case csspp::output_mode_t::COMPRESSED:
    1506           1 :             CATCH_REQUIRE(out.str() ==
    1507             : "div:not(:lang(fr)):not(:nth-child(odd)){color:#000}\n"
    1508             : + csspp_test::get_close_comment()
    1509             :                 );
    1510           1 :             break;
    1511             : 
    1512           1 :         case csspp::output_mode_t::EXPANDED:
    1513           1 :             CATCH_REQUIRE(out.str() ==
    1514             : "div:not(:lang(fr)):not(:nth-child(odd))\n"
    1515             : "{\n"
    1516             : "  color: #000;\n"
    1517             : "}\n"
    1518             : + csspp_test::get_close_comment()
    1519             :                 );
    1520           1 :             break;
    1521             : 
    1522           1 :         case csspp::output_mode_t::TIDY:
    1523           1 :             CATCH_REQUIRE(out.str() ==
    1524             : "div:not(:lang(fr)):not(:nth-child(odd)){color:#000}\n"
    1525             : + csspp_test::get_close_comment()
    1526             :                 );
    1527           1 :             break;
    1528             : 
    1529             :         }
    1530             : 
    1531           4 :         CATCH_REQUIRE(c.get_root() == n);
    1532           4 :     }
    1533             : 
    1534             :     // test the pseudo classes
    1535           1 :     char const * pseudo_classes[] =
    1536             :     {
    1537             :         "root",
    1538             :         "first-child",
    1539             :         "last-child",
    1540             :         "first-of-type",
    1541             :         "last-of-type",
    1542             :         "only-child",
    1543             :         "only-of-type",
    1544             :         "empty",
    1545             :         "link",
    1546             :         "visited",
    1547             :         "active",
    1548             :         "hover",
    1549             :         "focus",
    1550             :         "target",
    1551             :         "enabled",
    1552             :         "disabled",
    1553             :         "checked"
    1554             :     };
    1555           5 :     for(int i(static_cast<int>(csspp::output_mode_t::COMPACT));
    1556           5 :         i <= static_cast<int>(csspp::output_mode_t::TIDY);
    1557             :         ++i)
    1558             :     {
    1559          72 :         for(size_t j(0); j < sizeof(pseudo_classes) / sizeof(pseudo_classes[0]); ++j)
    1560             :         {
    1561          68 :             std::stringstream ss;
    1562          68 :             ss << "div:" << pseudo_classes[j] << " {color: black}\n";
    1563         204 :             csspp::position pos("test.css");
    1564          68 :             csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
    1565             : 
    1566         136 :             csspp::parser p(l);
    1567             : 
    1568          68 :             csspp::node::pointer_t n(p.stylesheet());
    1569             : 
    1570          68 :             csspp::compiler c;
    1571          68 :             c.set_root(n);
    1572          68 :             c.set_date_time_variables(csspp_test::get_now());
    1573          68 :             c.add_path(csspp_test::get_script_path());
    1574          68 :             c.add_path(csspp_test::get_version_script_path());
    1575             : 
    1576          68 :             c.compile(false);
    1577             : 
    1578             : //std::cerr << "Compiler result is: [" << *n << "]\n";
    1579             : 
    1580          68 :             std::stringstream out;
    1581          68 :             csspp::assembler a(out);
    1582          68 :             a.output(n, static_cast<csspp::output_mode_t>(i));
    1583             : 
    1584             : //std::cerr << "----------------- Result is " << static_cast<csspp::output_mode_t>(i) << "\n[" << out.str() << "]\n";
    1585             : 
    1586          68 :             std::stringstream expected;
    1587          68 :             switch(static_cast<csspp::output_mode_t>(i))
    1588             :             {
    1589          17 :             case csspp::output_mode_t::COMPACT:
    1590             : expected << "div:" << pseudo_classes[j] << " { color: #000 }\n"
    1591          17 :          << csspp_test::get_close_comment();
    1592          17 :                 break;
    1593             : 
    1594          17 :             case csspp::output_mode_t::COMPRESSED:
    1595             : expected << "div:" << pseudo_classes[j] << "{color:#000}\n"
    1596          17 :          << csspp_test::get_close_comment();
    1597          17 :                 break;
    1598             : 
    1599          17 :             case csspp::output_mode_t::EXPANDED:
    1600             : expected << "div:" << pseudo_classes[j] << "\n"
    1601             :             "{\n"
    1602             :             "  color: #000;\n"
    1603             :             "}\n"
    1604          17 :          << csspp_test::get_close_comment();
    1605          17 :                 break;
    1606             : 
    1607          17 :             case csspp::output_mode_t::TIDY:
    1608             : expected << "div:" << pseudo_classes[j] << "{color:#000}\n"
    1609          17 :          << csspp_test::get_close_comment();
    1610          17 :                 break;
    1611             : 
    1612             :             }
    1613             : 
    1614          68 :             CATCH_REQUIRE(out.str() == expected.str());
    1615          68 :             CATCH_REQUIRE(c.get_root() == n);
    1616          68 :         }
    1617             :     }
    1618             : 
    1619             :     // test the pseudo classes
    1620           1 :     char const * pseudo_elements[] =
    1621             :     {
    1622             :         "first-line",
    1623             :         "first-letter",
    1624             :         "before",
    1625             :         "after"
    1626             :     };
    1627           5 :     for(int i(static_cast<int>(csspp::output_mode_t::COMPACT));
    1628           5 :         i <= static_cast<int>(csspp::output_mode_t::TIDY);
    1629             :         ++i)
    1630             :     {
    1631          20 :         for(size_t j(0); j < sizeof(pseudo_elements) / sizeof(pseudo_elements[0]); ++j)
    1632             :         {
    1633          16 :             std::stringstream ss;
    1634          16 :             ss << "div::" << pseudo_elements[j] << " {color: black}\n";
    1635          48 :             csspp::position pos("test.css");
    1636          16 :             csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
    1637             : 
    1638          32 :             csspp::parser p(l);
    1639             : 
    1640          16 :             csspp::node::pointer_t n(p.stylesheet());
    1641             : 
    1642          16 :             csspp::compiler c;
    1643          16 :             c.set_root(n);
    1644          16 :             c.set_date_time_variables(csspp_test::get_now());
    1645          16 :             c.add_path(csspp_test::get_script_path());
    1646          16 :             c.add_path(csspp_test::get_version_script_path());
    1647             : 
    1648          16 :             c.compile(false);
    1649             : 
    1650             : //std::cerr << "Compiler result is: [" << *n << "]\n";
    1651             : 
    1652          16 :             std::stringstream out;
    1653          16 :             csspp::assembler a(out);
    1654          16 :             a.output(n, static_cast<csspp::output_mode_t>(i));
    1655             : 
    1656             : //std::cerr << "----------------- Result is " << static_cast<csspp::output_mode_t>(i) << "\n[" << out.str() << "]\n";
    1657             : 
    1658          16 :             std::stringstream expected;
    1659          16 :             switch(static_cast<csspp::output_mode_t>(i))
    1660             :             {
    1661           4 :             case csspp::output_mode_t::COMPACT:
    1662             : expected << "div::" << pseudo_elements[j] << " { color: #000 }\n"
    1663           4 :          << csspp_test::get_close_comment();
    1664           4 :                 break;
    1665             : 
    1666           4 :             case csspp::output_mode_t::COMPRESSED:
    1667             : expected << "div::" << pseudo_elements[j] << "{color:#000}\n"
    1668           4 :          << csspp_test::get_close_comment();
    1669           4 :                 break;
    1670             : 
    1671           4 :             case csspp::output_mode_t::EXPANDED:
    1672             : expected << "div::" << pseudo_elements[j] << "\n"
    1673             :             "{\n"
    1674             :             "  color: #000;\n"
    1675             :             "}\n"
    1676           4 :          << csspp_test::get_close_comment();
    1677           4 :                 break;
    1678             : 
    1679           4 :             case csspp::output_mode_t::TIDY:
    1680             : expected << "div::" << pseudo_elements[j] << "{color:#000}\n"
    1681           4 :          << csspp_test::get_close_comment();
    1682           4 :                 break;
    1683             : 
    1684             :             }
    1685             : 
    1686          16 :             CATCH_REQUIRE(out.str() == expected.str());
    1687          16 :             CATCH_REQUIRE(c.get_root() == n);
    1688          16 :         }
    1689             :     }
    1690             : 
    1691             :     // test the An+B pseudo classes
    1692           1 :     char const * pseudo_functions[] =
    1693             :     {
    1694             :         "nth-child",
    1695             :         "nth-last-child",
    1696             :         "nth-of-type",
    1697             :         "nth-last-of-type"
    1698             :     };
    1699           5 :     for(int i(static_cast<int>(csspp::output_mode_t::COMPACT));
    1700           5 :         i <= static_cast<int>(csspp::output_mode_t::TIDY);
    1701             :         ++i)
    1702             :     {
    1703          20 :         for(size_t j(0); j < sizeof(pseudo_functions) / sizeof(pseudo_functions[0]); ++j)
    1704             :         {
    1705          16 :             std::stringstream ss;
    1706          16 :             ss << "div:" << pseudo_functions[j] << "(5n+2) {color: black}\n";
    1707          48 :             csspp::position pos("test.css");
    1708          16 :             csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
    1709             : 
    1710          32 :             csspp::parser p(l);
    1711             : 
    1712          16 :             csspp::node::pointer_t n(p.stylesheet());
    1713             : 
    1714          16 :             csspp::compiler c;
    1715          16 :             c.set_root(n);
    1716          16 :             c.set_date_time_variables(csspp_test::get_now());
    1717          16 :             c.add_path(csspp_test::get_script_path());
    1718          16 :             c.add_path(csspp_test::get_version_script_path());
    1719             : 
    1720          16 :             c.compile(false);
    1721             : 
    1722             : //std::cerr << "Compiler result is: [" << *n << "]\n";
    1723             : 
    1724          16 :             std::stringstream out;
    1725          16 :             csspp::assembler a(out);
    1726          16 :             a.output(n, static_cast<csspp::output_mode_t>(i));
    1727             : 
    1728             : //std::cerr << "----------------- Result is " << static_cast<csspp::output_mode_t>(i) << "\n[" << out.str() << "]\n";
    1729             : 
    1730          16 :             std::stringstream expected;
    1731          16 :             switch(static_cast<csspp::output_mode_t>(i))
    1732             :             {
    1733           4 :             case csspp::output_mode_t::COMPACT:
    1734             : expected << "div:" << pseudo_functions[j] << "(5n+2) { color: #000 }\n"
    1735           4 :          << csspp_test::get_close_comment();
    1736           4 :                 break;
    1737             : 
    1738           4 :             case csspp::output_mode_t::COMPRESSED:
    1739             : expected << "div:" << pseudo_functions[j] << "(5n+2){color:#000}\n"
    1740           4 :          << csspp_test::get_close_comment();
    1741           4 :                 break;
    1742             : 
    1743           4 :             case csspp::output_mode_t::EXPANDED:
    1744             : expected << "div:" << pseudo_functions[j] << "(5n+2)\n"
    1745             :             "{\n"
    1746             :             "  color: #000;\n"
    1747             :             "}\n"
    1748           4 :          << csspp_test::get_close_comment();
    1749           4 :                 break;
    1750             : 
    1751           4 :             case csspp::output_mode_t::TIDY:
    1752             : expected << "div:" << pseudo_functions[j] << "(5n+2){color:#000}\n"
    1753           4 :          << csspp_test::get_close_comment();
    1754           4 :                 break;
    1755             : 
    1756             :             }
    1757             : 
    1758          16 :             CATCH_REQUIRE(out.str() == expected.str());
    1759          16 :             CATCH_REQUIRE(c.get_root() == n);
    1760          16 :         }
    1761             :     }
    1762             : 
    1763             :     // test the scope operator
    1764           1 :     char const * scope[] =
    1765             :     {
    1766             :         "*|div",
    1767             :         "*|*",
    1768             :         "div|*",
    1769             :         "|div",
    1770             :         "|*"
    1771             :     };
    1772           5 :     for(int i(static_cast<int>(csspp::output_mode_t::COMPACT));
    1773           5 :         i <= static_cast<int>(csspp::output_mode_t::TIDY);
    1774             :         ++i)
    1775             :     {
    1776          24 :         for(size_t j(0); j < sizeof(scope) / sizeof(scope[0]); ++j)
    1777             :         {
    1778          20 :             std::stringstream ss;
    1779          20 :             ss << "with " << scope[j] << " scope {color: black}\n";
    1780          60 :             csspp::position pos("test.css");
    1781          20 :             csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
    1782             : 
    1783          40 :             csspp::parser p(l);
    1784             : 
    1785          20 :             csspp::node::pointer_t n(p.stylesheet());
    1786             : 
    1787          20 :             csspp::compiler c;
    1788          20 :             c.set_root(n);
    1789          20 :             c.set_date_time_variables(csspp_test::get_now());
    1790          20 :             c.add_path(csspp_test::get_script_path());
    1791          20 :             c.add_path(csspp_test::get_version_script_path());
    1792             : 
    1793          20 :             c.compile(false);
    1794             : 
    1795             : //std::cerr << "Compiler result is: [" << *n << "]\n";
    1796             : 
    1797          20 :             std::stringstream out;
    1798          20 :             csspp::assembler a(out);
    1799          20 :             a.output(n, static_cast<csspp::output_mode_t>(i));
    1800             : 
    1801             : //std::cerr << "----------------- Result is " << static_cast<csspp::output_mode_t>(i) << "\n[" << out.str() << "]\n";
    1802             : 
    1803          20 :             std::stringstream expected;
    1804          20 :             switch(static_cast<csspp::output_mode_t>(i))
    1805             :             {
    1806           5 :             case csspp::output_mode_t::COMPACT:
    1807             : expected << "with " << scope[j] << " scope { color: #000 }\n"
    1808           5 :          << csspp_test::get_close_comment();
    1809           5 :                 break;
    1810             : 
    1811           5 :             case csspp::output_mode_t::COMPRESSED:
    1812             : expected << "with " << scope[j] << " scope{color:#000}\n"
    1813           5 :          << csspp_test::get_close_comment();
    1814           5 :                 break;
    1815             : 
    1816           5 :             case csspp::output_mode_t::EXPANDED:
    1817             : expected << "with " << scope[j] << " scope\n"
    1818             :             "{\n"
    1819             :             "  color: #000;\n"
    1820             :             "}\n"
    1821           5 :          << csspp_test::get_close_comment();
    1822           5 :                 break;
    1823             : 
    1824           5 :             case csspp::output_mode_t::TIDY:
    1825             : expected << "with " << scope[j] << " scope{color:#000}\n"
    1826           5 :          << csspp_test::get_close_comment();
    1827           5 :                 break;
    1828             : 
    1829             :             }
    1830             : 
    1831          20 :             CATCH_REQUIRE(out.str() == expected.str());
    1832          20 :             CATCH_REQUIRE(c.get_root() == n);
    1833          20 :         }
    1834             :     }
    1835             : 
    1836             :     // no error left over
    1837           1 :     VERIFY_ERRORS("");
    1838           1 : }
    1839             : 
    1840           1 : CATCH_TEST_CASE("Assemble numbers", "[assembler] [numbers]")
    1841             : {
    1842             :     // create strings with more single quotes (')
    1843           5 :     for(int i(static_cast<int>(csspp::output_mode_t::COMPACT));
    1844           5 :         i <= static_cast<int>(csspp::output_mode_t::TIDY);
    1845             :         ++i)
    1846             :     {
    1847           4 :         std::stringstream ss;
    1848          12 :         csspp::position pos("test.css");
    1849           4 :         csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
    1850             : 
    1851           4 :         csspp::integer_t integer(rand() % 10000);
    1852           4 :         csspp::decimal_number_t decimal_number(static_cast<csspp::decimal_number_t>(rand() % 10000) / 100.0);
    1853           4 :         csspp::decimal_number_t percent(static_cast<csspp::decimal_number_t>(rand() % 10000) / 100.0);
    1854             : 
    1855             :         ss << "#wrapper div * span a:hover {\n"
    1856           4 :            << "  width: " << integer << ";\n"
    1857           4 :            << "  height: " << decimal_number << ";\n"
    1858           4 :            << "  font-size: " << percent << "%;\n"
    1859           4 :            << "}\n";
    1860             : 
    1861           8 :         csspp::parser p(l);
    1862             : 
    1863           4 :         csspp::node::pointer_t n(p.stylesheet());
    1864             : 
    1865           4 :         csspp::compiler c;
    1866           4 :         c.set_root(n);
    1867           4 :         c.set_date_time_variables(csspp_test::get_now());
    1868           4 :         c.add_path(csspp_test::get_script_path());
    1869           4 :         c.add_path(csspp_test::get_version_script_path());
    1870             : 
    1871           4 :         c.compile(false);
    1872             : 
    1873             : //std::cerr << "Compiler result is: [" << *c.get_root() << "]\n";
    1874             : 
    1875           4 :         std::stringstream out;
    1876           4 :         csspp::assembler a(out);
    1877           4 :         a.output(n, static_cast<csspp::output_mode_t>(i));
    1878             : 
    1879             : //std::cerr << "----------------- Result is " << static_cast<csspp::output_mode_t>(i) << "\n[" << out.str() << "]\n";
    1880             : 
    1881           4 :         std::stringstream percent_stream;
    1882           4 :         percent_stream << percent;
    1883           4 :         std::string percent_str(percent_stream.str());
    1884           4 :         if(percent_str.length() > 1
    1885           4 :         && percent_str[0] == '0'
    1886           8 :         && percent_str[1] == '.')
    1887             :         {
    1888           0 :             percent_str = percent_str.substr(1);
    1889             :         }
    1890             : 
    1891           4 :         std::stringstream decimal_number_stream;
    1892           4 :         decimal_number_stream << decimal_number;
    1893           4 :         std::string decimal_number_str(decimal_number_stream.str());
    1894           4 :         if(decimal_number_str.length() > 1
    1895           4 :         && decimal_number_str[0] == '0'
    1896           8 :         && decimal_number_str[1] == '.')
    1897             :         {
    1898           0 :             decimal_number_str = decimal_number_str.substr(1);
    1899             :         }
    1900             : 
    1901           4 :         std::stringstream expected;
    1902           4 :         switch(static_cast<csspp::output_mode_t>(i))
    1903             :         {
    1904           1 :         case csspp::output_mode_t::COMPACT:
    1905             : expected << "#wrapper div * span a:hover {"
    1906           1 :          << " width: " << integer << ";"
    1907             :          << " height: " << decimal_number_str << ";"
    1908             :          << " font-size: " << percent_str << "%"
    1909             :          << " }\n"
    1910           1 :          << csspp_test::get_close_comment();
    1911           1 :             break;
    1912             : 
    1913           1 :         case csspp::output_mode_t::COMPRESSED:
    1914             : expected << "#wrapper div * span a:hover{"
    1915           1 :          << "width:" << integer << ";"
    1916             :          << "height:" << decimal_number_str << ";"
    1917             :          << "font-size:" << percent_str << "%"
    1918             :          << "}\n"
    1919           1 :          << csspp_test::get_close_comment();
    1920           1 :             break;
    1921             : 
    1922           1 :         case csspp::output_mode_t::EXPANDED:
    1923             : expected << "#wrapper div * span a:hover\n"
    1924             :          << "{\n"
    1925           1 :          << "  width: " << integer << ";\n"
    1926             :          << "  height: " << decimal_number_str << ";\n"
    1927             :          << "  font-size: " << percent_str << "%;\n"
    1928             :          << "}\n"
    1929           1 :          << csspp_test::get_close_comment();
    1930           1 :             break;
    1931             : 
    1932           1 :         case csspp::output_mode_t::TIDY:
    1933             : expected << "#wrapper div * span a:hover{"
    1934           1 :          << "width:" << integer << ";"
    1935             :          << "height:" << decimal_number_str << ";"
    1936             :          << "font-size:" << percent_str << "%"
    1937             :          << "}\n"
    1938           1 :          << csspp_test::get_close_comment();
    1939           1 :             break;
    1940             : 
    1941             :         }
    1942             : 
    1943           4 :         CATCH_REQUIRE(out.str() == expected.str());
    1944           4 :         CATCH_REQUIRE(c.get_root() == n);
    1945           4 :     }
    1946             : 
    1947             :     // no error left over
    1948           1 :     VERIFY_ERRORS("");
    1949           1 : }
    1950             : 
    1951           1 : CATCH_TEST_CASE("Assemble unicode range", "[assembler] [unicode-range-value] [at-keyword]")
    1952             : {
    1953             :     // a valid @supports
    1954           5 :     for(int i(static_cast<int>(csspp::output_mode_t::COMPACT));
    1955           5 :         i <= static_cast<int>(csspp::output_mode_t::TIDY);
    1956             :         ++i)
    1957             :     {
    1958           4 :         std::stringstream ss;
    1959             :         ss << "@font-face\n"
    1960             :            << "{\n"
    1961             :            << "  unicode-range: U+400-4fF;\n"
    1962             :            << "  font-style: italic;\n"
    1963           4 :            << "}\n";
    1964          12 :         csspp::position pos("test.css");
    1965           4 :         csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
    1966             : 
    1967           8 :         csspp::parser p(l);
    1968             : 
    1969           4 :         csspp::node::pointer_t n(p.stylesheet());
    1970             : 
    1971             :         // no errors so far
    1972           4 :         VERIFY_ERRORS("");
    1973             : 
    1974           4 :         csspp::compiler c;
    1975           4 :         c.set_root(n);
    1976           4 :         c.clear_paths();
    1977           4 :         c.set_date_time_variables(csspp_test::get_now());
    1978           4 :         c.add_path(csspp_test::get_script_path());
    1979           4 :         c.add_path(csspp_test::get_version_script_path());
    1980             : 
    1981           4 :         c.compile(false);
    1982             : 
    1983             : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
    1984             : 
    1985           4 :         VERIFY_ERRORS("");
    1986             : 
    1987             : //std::cerr << "Compiler result is: [" << *n << "]\n";
    1988             : 
    1989           4 :         std::stringstream out;
    1990           4 :         csspp::assembler a(out);
    1991           4 :         a.output(n, static_cast<csspp::output_mode_t>(i));
    1992             : 
    1993             : //std::cerr << "----------------- Result is " << static_cast<csspp::output_mode_t>(i) << "\n[" << out.str() << "]\n";
    1994             : 
    1995           4 :         switch(static_cast<csspp::output_mode_t>(i))
    1996             :         {
    1997           1 :         case csspp::output_mode_t::COMPACT:
    1998           1 :             CATCH_REQUIRE(out.str() ==
    1999             : "@font-face \n"
    2000             : "{\n"
    2001             : "unicode-range: U+4??; "
    2002             : "font-style: italic"
    2003             : "}\n"
    2004             : "\n"
    2005             : + csspp_test::get_close_comment()
    2006             :                 );
    2007           1 :             break;
    2008             : 
    2009           1 :         case csspp::output_mode_t::COMPRESSED:
    2010           1 :             CATCH_REQUIRE(out.str() ==
    2011             : "@font-face {unicode-range:U+4??;font-style:italic}\n"
    2012             : + csspp_test::get_close_comment()
    2013             :                 );
    2014           1 :             break;
    2015             : 
    2016           1 :         case csspp::output_mode_t::EXPANDED:
    2017           1 :             CATCH_REQUIRE(out.str() ==
    2018             : "@font-face \n"
    2019             : "{\n"
    2020             : "  unicode-range: U+4??;\n"
    2021             : "  font-style: italic}\n"
    2022             : "\n"
    2023             : + csspp_test::get_close_comment()
    2024             :                 );
    2025           1 :             break;
    2026             : 
    2027           1 :         case csspp::output_mode_t::TIDY:
    2028           1 :             CATCH_REQUIRE(out.str() ==
    2029             : "@font-face \n"
    2030             : "{\n"
    2031             : "unicode-range:U+4??;font-style:italic}\n"
    2032             : "\n"
    2033             : + csspp_test::get_close_comment()
    2034             :                 );
    2035           1 :             break;
    2036             : 
    2037             :         }
    2038             : 
    2039           4 :         CATCH_REQUIRE(c.get_root() == n);
    2040           4 :     }
    2041             : 
    2042             :     // no left over?
    2043           1 :     VERIFY_ERRORS("");
    2044           1 : }
    2045             : 
    2046           1 : CATCH_TEST_CASE("Assemble strings", "[assembler] [strings]")
    2047             : {
    2048             :     // create strings with more single quotes (')
    2049           5 :     for(int i(static_cast<int>(csspp::output_mode_t::COMPACT));
    2050           5 :         i <= static_cast<int>(csspp::output_mode_t::TIDY);
    2051             :         ++i)
    2052             :     {
    2053           4 :         std::stringstream ss;
    2054          12 :         csspp::position pos("test.css");
    2055           4 :         csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
    2056             : 
    2057           4 :         std::string str;
    2058           4 :         int const size(rand() % 20 + 1);
    2059           4 :         int dq(rand() % 5 + 1);
    2060           4 :         int sq(rand() % 8 + dq); // if sq >= dq use " for strings
    2061          42 :         for(int j(0); j < size; ++j)
    2062             :         {
    2063          38 :             if(dq > 0 && rand() % 1 == 0)
    2064             :             {
    2065          15 :                 --dq;
    2066          15 :                 str += '\\';
    2067          15 :                 str += '"';
    2068             :             }
    2069          38 :             if(sq > 0 && rand() % 1 == 0)
    2070             :             {
    2071          21 :                 --sq;
    2072          21 :                 str += '\'';
    2073             :             }
    2074          38 :             str += static_cast<char>(rand() % 26 + 'a');
    2075             :         }
    2076           8 :         while(dq + sq > 0)
    2077             :         {
    2078           4 :             if(dq > 0 && rand() % 1 == 0)
    2079             :             {
    2080           0 :                 --dq;
    2081           0 :                 str += '\\';
    2082           0 :                 str += '"';
    2083             :             }
    2084           4 :             if(sq > 0 && rand() % 1 == 0)
    2085             :             {
    2086           4 :                 --sq;
    2087           4 :                 str += '\'';
    2088             :             }
    2089             :         }
    2090             :         ss << "div::before { content: \""
    2091             :            << str
    2092           4 :            << "\" }";
    2093             : 
    2094           8 :         csspp::parser p(l);
    2095             : 
    2096           4 :         csspp::node::pointer_t n(p.stylesheet());
    2097             : 
    2098           4 :         csspp::compiler c;
    2099           4 :         c.set_root(n);
    2100           4 :         c.set_date_time_variables(csspp_test::get_now());
    2101           4 :         c.add_path(csspp_test::get_script_path());
    2102           4 :         c.add_path(csspp_test::get_version_script_path());
    2103             : 
    2104           4 :         c.compile(false);
    2105             : 
    2106             : //std::cerr << "Compiler result is: [" << *c.get_root() << "]\n";
    2107             : 
    2108           4 :         std::stringstream out;
    2109           4 :         csspp::assembler a(out);
    2110           4 :         a.output(n, static_cast<csspp::output_mode_t>(i));
    2111             : 
    2112             : //std::cerr << "----------------- Result is " << static_cast<csspp::output_mode_t>(i) << "\n[" << out.str() << "]\n";
    2113             : 
    2114           4 :         switch(static_cast<csspp::output_mode_t>(i))
    2115             :         {
    2116           1 :         case csspp::output_mode_t::COMPACT:
    2117           1 :             CATCH_REQUIRE(out.str() ==
    2118             : "div::before { content: \"" + str + "\" }\n"
    2119             : + csspp_test::get_close_comment()
    2120             :                 );
    2121           1 :             break;
    2122             : 
    2123           1 :         case csspp::output_mode_t::COMPRESSED:
    2124           1 :             CATCH_REQUIRE(out.str() ==
    2125             : "div::before{content:\"" + str + "\"}\n"
    2126             : + csspp_test::get_close_comment()
    2127             :                 );
    2128           1 :             break;
    2129             : 
    2130           1 :         case csspp::output_mode_t::EXPANDED:
    2131           1 :             CATCH_REQUIRE(out.str() ==
    2132             : "div::before\n"
    2133             : "{\n"
    2134             : "  content: \"" + str + "\";\n"
    2135             : "}\n"
    2136             : + csspp_test::get_close_comment()
    2137             :                 );
    2138           1 :             break;
    2139             : 
    2140           1 :         case csspp::output_mode_t::TIDY:
    2141           1 :             CATCH_REQUIRE(out.str() ==
    2142             : "div::before{content:\"" + str + "\"}\n"
    2143             : + csspp_test::get_close_comment()
    2144             :                 );
    2145           1 :             break;
    2146             : 
    2147             :         }
    2148             : 
    2149           4 :         CATCH_REQUIRE(c.get_root() == n);
    2150           4 :     }
    2151             : 
    2152             :     // create strings with more double quotes (")
    2153           5 :     for(int i(static_cast<int>(csspp::output_mode_t::COMPACT));
    2154           5 :         i <= static_cast<int>(csspp::output_mode_t::TIDY);
    2155             :         ++i)
    2156             :     {
    2157           4 :         std::stringstream ss;
    2158          12 :         csspp::position pos("test.css");
    2159           4 :         csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
    2160             : 
    2161           4 :         std::string str;
    2162           4 :         int const size(rand() % 20 + 1);
    2163           4 :         int sq(rand() % 5 + 1);
    2164           4 :         int dq(rand() % 8 + 1 + sq);  // we need dq > sq
    2165          36 :         for(int j(0); j < size; ++j)
    2166             :         {
    2167          32 :             if(dq > 0 && rand() % 1 == 0)
    2168             :             {
    2169          14 :                 --dq;
    2170          14 :                 str += '"';
    2171             :             }
    2172          32 :             if(sq > 0 && rand() % 1 == 0)
    2173             :             {
    2174           8 :                 --sq;
    2175           8 :                 str += '\\';
    2176           8 :                 str += '\'';
    2177             :             }
    2178          32 :             str += static_cast<char>(rand() % 26 + 'a');
    2179             :         }
    2180          14 :         while(dq + sq > 0)
    2181             :         {
    2182          10 :             if(dq > 0 && rand() % 1 == 0)
    2183             :             {
    2184          10 :                 --dq;
    2185          10 :                 str += '"';
    2186             :             }
    2187          10 :             if(sq > 0 && rand() % 1 == 0)
    2188             :             {
    2189           1 :                 --sq;
    2190           1 :                 str += '\\';
    2191           1 :                 str += '\'';
    2192             :             }
    2193             :         }
    2194             :         ss << "div::after { content: '"
    2195             :            << str
    2196           4 :            << "' }";
    2197             : 
    2198           8 :         csspp::parser p(l);
    2199             : 
    2200           4 :         csspp::node::pointer_t n(p.stylesheet());
    2201             : 
    2202           4 :         csspp::compiler c;
    2203           4 :         c.set_root(n);
    2204           4 :         c.set_date_time_variables(csspp_test::get_now());
    2205           4 :         c.add_path(csspp_test::get_script_path());
    2206           4 :         c.add_path(csspp_test::get_version_script_path());
    2207             : 
    2208           4 :         c.compile(false);
    2209             : 
    2210             : //std::cerr << "Compiler result is: [" << *c.get_root() << "]\n";
    2211             : 
    2212           4 :         std::stringstream out;
    2213           4 :         csspp::assembler a(out);
    2214           4 :         a.output(n, static_cast<csspp::output_mode_t>(i));
    2215             : 
    2216             : //std::cerr << "----------------- Result is " << static_cast<csspp::output_mode_t>(i) << "\n[" << out.str() << "]\n";
    2217             : 
    2218           4 :         switch(static_cast<csspp::output_mode_t>(i))
    2219             :         {
    2220           1 :         case csspp::output_mode_t::COMPACT:
    2221           1 :             CATCH_REQUIRE(out.str() ==
    2222             : "div::after { content: '" + str + "' }\n"
    2223             : + csspp_test::get_close_comment()
    2224             :                 );
    2225           1 :             break;
    2226             : 
    2227           1 :         case csspp::output_mode_t::COMPRESSED:
    2228           1 :             CATCH_REQUIRE(out.str() ==
    2229             : "div::after{content:'" + str + "'}\n"
    2230             : + csspp_test::get_close_comment()
    2231             :                 );
    2232           1 :             break;
    2233             : 
    2234           1 :         case csspp::output_mode_t::EXPANDED:
    2235           1 :             CATCH_REQUIRE(out.str() ==
    2236             : "div::after\n"
    2237             : "{\n"
    2238             : "  content: '" + str + "';\n"
    2239             : "}\n"
    2240             : + csspp_test::get_close_comment()
    2241             :                 );
    2242           1 :             break;
    2243             : 
    2244           1 :         case csspp::output_mode_t::TIDY:
    2245           1 :             CATCH_REQUIRE(out.str() ==
    2246             : "div::after{content:'" + str + "'}\n"
    2247             : + csspp_test::get_close_comment()
    2248             :                 );
    2249           1 :             break;
    2250             : 
    2251             :         }
    2252             : 
    2253           4 :         CATCH_REQUIRE(c.get_root() == n);
    2254           4 :     }
    2255             : 
    2256             :     // no error left over
    2257           1 :     VERIFY_ERRORS("");
    2258           1 : }
    2259             : 
    2260           1 : CATCH_TEST_CASE("Assemble URI", "[assembler] [uri]")
    2261             : {
    2262             :     // all characters can be inserted as is (no switching to string)
    2263           5 :     for(int i(static_cast<int>(csspp::output_mode_t::COMPACT));
    2264           5 :         i <= static_cast<int>(csspp::output_mode_t::TIDY);
    2265             :         ++i)
    2266             :     {
    2267           4 :         std::stringstream ss;
    2268          12 :         csspp::position pos("test.css");
    2269           4 :         csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
    2270             : 
    2271           4 :         std::string name;
    2272           4 :         int const size(rand() % 20 + 1);
    2273          55 :         for(int j(0); j < size; ++j)
    2274             :         {
    2275          51 :             csspp::wide_char_t c(rand() % 0x110000);
    2276          51 :             while(!is_valid_char(c)
    2277          51 :                || c == '\''
    2278          51 :                || c == '"'
    2279          51 :                || c == '('
    2280          51 :                || c == ')'
    2281         102 :                || l->is_non_printable(c))
    2282             :             {
    2283           0 :                 c = rand() % 0x110000;
    2284             :             }
    2285          51 :             name += l->wctomb(c);
    2286             :         }
    2287             :         ss << "div { background-image: url(/images/"
    2288             :            << name
    2289           4 :            << ".png); }";
    2290             : 
    2291           8 :         csspp::parser p(l);
    2292             : 
    2293           4 :         csspp::node::pointer_t n(p.stylesheet());
    2294             : 
    2295           4 :         csspp::compiler c;
    2296           4 :         c.set_root(n);
    2297           4 :         c.set_date_time_variables(csspp_test::get_now());
    2298           4 :         c.add_path(csspp_test::get_script_path());
    2299           4 :         c.add_path(csspp_test::get_version_script_path());
    2300             : 
    2301           4 :         c.compile(false);
    2302             : 
    2303             : //std::cerr << "Compiler result is: [" << *c.get_root() << "]\n";
    2304             : 
    2305           4 :         std::stringstream out;
    2306           4 :         csspp::assembler a(out);
    2307           4 :         a.output(n, static_cast<csspp::output_mode_t>(i));
    2308             : 
    2309             : //std::cerr << "----------------- Result is " << static_cast<csspp::output_mode_t>(i) << "\n[" << out.str() << "]\n";
    2310             : 
    2311           4 :         switch(static_cast<csspp::output_mode_t>(i))
    2312             :         {
    2313           1 :         case csspp::output_mode_t::COMPACT:
    2314           1 :             CATCH_REQUIRE(out.str() ==
    2315             : "div { background-image: url( /images/" + name + ".png ) }\n"
    2316             : + csspp_test::get_close_comment()
    2317             :                 );
    2318           1 :             break;
    2319             : 
    2320           1 :         case csspp::output_mode_t::COMPRESSED:
    2321           1 :             CATCH_REQUIRE(out.str() ==
    2322             : "div{background-image:url(/images/" + name + ".png)}\n"
    2323             : + csspp_test::get_close_comment()
    2324             :                 );
    2325           1 :             break;
    2326             : 
    2327           1 :         case csspp::output_mode_t::EXPANDED:
    2328           1 :             CATCH_REQUIRE(out.str() ==
    2329             : "div\n"
    2330             : "{\n"
    2331             : "  background-image: url( /images/" + name + ".png );\n"
    2332             : "}\n"
    2333             : + csspp_test::get_close_comment()
    2334             :                 );
    2335           1 :             break;
    2336             : 
    2337           1 :         case csspp::output_mode_t::TIDY:
    2338           1 :             CATCH_REQUIRE(out.str() ==
    2339             : "div{background-image:url(/images/" + name + ".png)}\n"
    2340             : + csspp_test::get_close_comment()
    2341             :                 );
    2342           1 :             break;
    2343             : 
    2344             :         }
    2345             : 
    2346           4 :         CATCH_REQUIRE(c.get_root() == n);
    2347           4 :     }
    2348             : 
    2349             :     // at least one character requires the use of a string
    2350           5 :     for(int i(static_cast<int>(csspp::output_mode_t::COMPACT));
    2351           5 :         i <= static_cast<int>(csspp::output_mode_t::TIDY);
    2352             :         ++i)
    2353             :     {
    2354           4 :         std::stringstream ss;
    2355          12 :         csspp::position pos("test.css");
    2356           4 :         csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
    2357             : 
    2358           4 :         std::string name;
    2359           4 :         csspp::wide_char_t special(L'\0');
    2360           4 :         int const size(rand() % 20 + 1);
    2361          21 :         for(int j(0); j < size; ++j)
    2362             :         {
    2363             :             csspp::wide_char_t c;
    2364          17 :             if(j == size / 2)
    2365             :             {
    2366             :                 // this happens only once and is mandatory since 'size > 0'
    2367             :                 // is always true
    2368           4 :                 c = special = "'\"()"[rand() % 4];
    2369             :             }
    2370             :             else
    2371             :             {
    2372          13 :                 c = rand() % 0x110000;
    2373          13 :                 while(!is_valid_char(c)
    2374          13 :                    || c == '\''
    2375          13 :                    || c == '"'
    2376          13 :                    || c == '('
    2377          13 :                    || c == ')'
    2378          26 :                    || l->is_non_printable(c))
    2379             :                 {
    2380           0 :                     c = rand() % 0x110000;
    2381             :                 }
    2382             :             }
    2383          17 :             name += l->wctomb(c);
    2384             :         }
    2385           4 :         std::string quote;
    2386           4 :         quote += special == '"' ? '\'' : '"';
    2387             :         ss << "div { background-image: url("
    2388             :            << quote
    2389             :            << "/images/"
    2390             :            << name
    2391             :            << ".png"
    2392             :            << quote
    2393           4 :            << "); }";
    2394             : 
    2395           8 :         csspp::parser p(l);
    2396             : 
    2397           4 :         csspp::node::pointer_t n(p.stylesheet());
    2398             : 
    2399           4 :         csspp::compiler c;
    2400           4 :         c.set_root(n);
    2401           4 :         c.set_date_time_variables(csspp_test::get_now());
    2402           4 :         c.add_path(csspp_test::get_script_path());
    2403           4 :         c.add_path(csspp_test::get_version_script_path());
    2404             : 
    2405           4 :         c.compile(false);
    2406             : 
    2407             : //std::cerr << "Compiler result is: [" << *c.get_root() << "]\n";
    2408             : 
    2409           4 :         std::stringstream out;
    2410           4 :         csspp::assembler a(out);
    2411           4 :         a.output(n, static_cast<csspp::output_mode_t>(i));
    2412             : 
    2413             : //std::cerr << "----------------- Result is " << static_cast<csspp::output_mode_t>(i) << "\n[" << out.str() << "]\n";
    2414             : 
    2415           4 :         switch(static_cast<csspp::output_mode_t>(i))
    2416             :         {
    2417           1 :         case csspp::output_mode_t::COMPACT:
    2418           1 :             CATCH_REQUIRE(out.str() ==
    2419             : "div { background-image: url( " + quote + "/images/" + name + ".png" + quote + " ) }\n"
    2420             : + csspp_test::get_close_comment()
    2421             :                 );
    2422           1 :             break;
    2423             : 
    2424           1 :         case csspp::output_mode_t::COMPRESSED:
    2425           1 :             CATCH_REQUIRE(out.str() ==
    2426             : "div{background-image:url(" + quote + "/images/" + name + ".png" + quote + ")}\n"
    2427             : + csspp_test::get_close_comment()
    2428             :                 );
    2429           1 :             break;
    2430             : 
    2431           1 :         case csspp::output_mode_t::EXPANDED:
    2432           1 :             CATCH_REQUIRE(out.str() ==
    2433             : "div\n"
    2434             : "{\n"
    2435             : "  background-image: url( " + quote + "/images/" + name + ".png" + quote + " );\n"
    2436             : "}\n"
    2437             : + csspp_test::get_close_comment()
    2438             :                 );
    2439           1 :             break;
    2440             : 
    2441           1 :         case csspp::output_mode_t::TIDY:
    2442           1 :             CATCH_REQUIRE(out.str() ==
    2443             : "div{background-image:url(" + quote + "/images/" + name + ".png" + quote + ")}\n"
    2444             : + csspp_test::get_close_comment()
    2445             :                 );
    2446           1 :             break;
    2447             : 
    2448             :         }
    2449             : 
    2450           4 :         CATCH_REQUIRE(c.get_root() == n);
    2451           4 :     }
    2452             : 
    2453             :     // no error left over
    2454           1 :     VERIFY_ERRORS("");
    2455           1 : }
    2456             : 
    2457           1 : CATCH_TEST_CASE("Assemble C++ comment", "[assembler] [comment]")
    2458             : {
    2459             :     // One line C++ comment
    2460           5 :     for(int i(static_cast<int>(csspp::output_mode_t::COMPACT));
    2461           5 :         i <= static_cast<int>(csspp::output_mode_t::TIDY);
    2462             :         ++i)
    2463             :     {
    2464           4 :         std::stringstream ss;
    2465             :         ss << "// Copyright (c) 2015-2022  Made to Order Software Corp.  All Rights Reserved. -- Assembler Test Version {$_csspp_version} -- @preserve\n"
    2466           4 :            << "body.error { color: red }\n";
    2467          12 :         csspp::position pos("test.css");
    2468           4 :         csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
    2469             : 
    2470           8 :         csspp::parser p(l);
    2471             : 
    2472           4 :         csspp::node::pointer_t n(p.stylesheet());
    2473             : 
    2474           4 :         VERIFY_ERRORS("test.css(1): warning: C++ comments should not be preserved as they are not supported by most CSS parsers.\n");
    2475             : 
    2476           4 :         csspp::compiler c;
    2477           4 :         c.set_root(n);
    2478           4 :         c.set_date_time_variables(csspp_test::get_now());
    2479           4 :         c.add_path(csspp_test::get_script_path());
    2480           4 :         c.add_path(csspp_test::get_version_script_path());
    2481             : 
    2482           4 :         c.compile(false);
    2483             : 
    2484             : //std::cerr << "Compiler result is: [" << *c.get_root() << "]\n";
    2485             : 
    2486           4 :         std::stringstream out;
    2487           4 :         csspp::assembler a(out);
    2488           4 :         a.output(n, static_cast<csspp::output_mode_t>(i));
    2489             : 
    2490             : //std::cerr << "----------------- Result is " << static_cast<csspp::output_mode_t>(i) << "\n[" << out.str() << "]\n";
    2491             : 
    2492           4 :         switch(static_cast<csspp::output_mode_t>(i))
    2493             :         {
    2494           1 :         case csspp::output_mode_t::COMPACT:
    2495           1 :             CATCH_REQUIRE(out.str() ==
    2496             : "/* Copyright (c) 2015-2022  Made to Order Software Corp.  All Rights Reserved. -- Assembler Test Version " CSSPP_VERSION " -- @preserve */\n"
    2497             : "body.error { color: red }\n"
    2498             : + csspp_test::get_close_comment()
    2499             :                 );
    2500           1 :             break;
    2501             : 
    2502           1 :         case csspp::output_mode_t::COMPRESSED:
    2503           1 :             CATCH_REQUIRE(out.str() ==
    2504             : "/* Copyright (c) 2015-2022  Made to Order Software Corp.  All Rights Reserved. -- Assembler Test Version " CSSPP_VERSION " -- @preserve */\n"
    2505             : "body.error{color:red}\n"
    2506             : + csspp_test::get_close_comment()
    2507             :                 );
    2508           1 :             break;
    2509             : 
    2510           1 :         case csspp::output_mode_t::EXPANDED:
    2511           1 :             CATCH_REQUIRE(out.str() ==
    2512             : "/* Copyright (c) 2015-2022  Made to Order Software Corp.  All Rights Reserved. -- Assembler Test Version " CSSPP_VERSION " -- @preserve */\n"
    2513             : "body.error\n"
    2514             : "{\n"
    2515             : "  color: red;\n"
    2516             : "}\n"
    2517             : + csspp_test::get_close_comment()
    2518             :                 );
    2519           1 :             break;
    2520             : 
    2521           1 :         case csspp::output_mode_t::TIDY:
    2522           1 :             CATCH_REQUIRE(out.str() ==
    2523             : "/* Copyright (c) 2015-2022  Made to Order Software Corp.  All Rights Reserved. -- Assembler Test Version " CSSPP_VERSION " -- @preserve */\n"
    2524             : "body.error{color:red}\n"
    2525             : + csspp_test::get_close_comment()
    2526             :                 );
    2527           1 :             break;
    2528             : 
    2529             :         }
    2530             : 
    2531           4 :         CATCH_REQUIRE(c.get_root() == n);
    2532           4 :     }
    2533             : 
    2534             :     // Multi-line C++ comment
    2535           5 :     for(int i(static_cast<int>(csspp::output_mode_t::COMPACT));
    2536           5 :         i <= static_cast<int>(csspp::output_mode_t::TIDY);
    2537             :         ++i)
    2538             :     {
    2539           4 :         std::stringstream ss;
    2540             :         ss << "// Copyright (c) 2015-2022  Made to Order Software Corp.  All Rights Reserved.\n"
    2541             :            << "// Assembler Test\n"
    2542             :            << "// @preserve\n"
    2543           4 :            << "body.error { color: red }\n";
    2544          12 :         csspp::position pos("test.css");
    2545           4 :         csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
    2546             : 
    2547           8 :         csspp::parser p(l);
    2548             : 
    2549           4 :         csspp::node::pointer_t n(p.stylesheet());
    2550             : 
    2551           4 :         VERIFY_ERRORS("test.css(1): warning: C++ comments should not be preserved as they are not supported by most CSS parsers.\n");
    2552             : 
    2553           4 :         csspp::compiler c;
    2554           4 :         c.set_root(n);
    2555           4 :         c.set_date_time_variables(csspp_test::get_now());
    2556           4 :         c.add_path(csspp_test::get_script_path());
    2557           4 :         c.add_path(csspp_test::get_version_script_path());
    2558             : 
    2559           4 :         c.compile(false);
    2560             : 
    2561             : //std::cerr << "Compiler result is: [" << *c.get_root() << "]\n";
    2562             : 
    2563           4 :         std::stringstream out;
    2564           4 :         csspp::assembler a(out);
    2565           4 :         a.output(n, static_cast<csspp::output_mode_t>(i));
    2566             : 
    2567             : //std::cerr << "----------------- Result is " << static_cast<csspp::output_mode_t>(i) << "\n[" << out.str() << "]\n";
    2568             : 
    2569           4 :         switch(static_cast<csspp::output_mode_t>(i))
    2570             :         {
    2571           1 :         case csspp::output_mode_t::COMPACT:
    2572           1 :             CATCH_REQUIRE(out.str() ==
    2573             : "/* Copyright (c) 2015-2022  Made to Order Software Corp.  All Rights Reserved.\n"
    2574             : " * Assembler Test\n"
    2575             : " * @preserve\n"
    2576             : " */\n"
    2577             : "body.error { color: red }\n"
    2578             : + csspp_test::get_close_comment()
    2579             :                 );
    2580           1 :             break;
    2581             : 
    2582           1 :         case csspp::output_mode_t::COMPRESSED:
    2583           1 :             CATCH_REQUIRE(out.str() ==
    2584             : "/* Copyright (c) 2015-2022  Made to Order Software Corp.  All Rights Reserved.\n"
    2585             : " * Assembler Test\n"
    2586             : " * @preserve\n"
    2587             : " */\n"
    2588             : "body.error{color:red}\n"
    2589             : + csspp_test::get_close_comment()
    2590             :                 );
    2591           1 :             break;
    2592             : 
    2593           1 :         case csspp::output_mode_t::EXPANDED:
    2594           1 :             CATCH_REQUIRE(out.str() ==
    2595             : "/* Copyright (c) 2015-2022  Made to Order Software Corp.  All Rights Reserved.\n"
    2596             : " * Assembler Test\n"
    2597             : " * @preserve\n"
    2598             : " */\n"
    2599             : "body.error\n"
    2600             : "{\n"
    2601             : "  color: red;\n"
    2602             : "}\n"
    2603             : + csspp_test::get_close_comment()
    2604             :                 );
    2605           1 :             break;
    2606             : 
    2607           1 :         case csspp::output_mode_t::TIDY:
    2608           1 :             CATCH_REQUIRE(out.str() ==
    2609             : "/* Copyright (c) 2015-2022  Made to Order Software Corp.  All Rights Reserved.\n"
    2610             : " * Assembler Test\n"
    2611             : " * @preserve\n"
    2612             : " */\n"
    2613             : "body.error{color:red}\n"
    2614             : + csspp_test::get_close_comment()
    2615             :                 );
    2616           1 :             break;
    2617             : 
    2618             :         }
    2619             : 
    2620           4 :         CATCH_REQUIRE(c.get_root() == n);
    2621           4 :     }
    2622             : 
    2623             :     // no error left over
    2624           1 :     VERIFY_ERRORS("");
    2625           1 : }
    2626             : 
    2627           1 : CATCH_TEST_CASE("Assemble @-keyword", "[assembler] [at-keyword]")
    2628             : {
    2629             :     // Standard @document with a sub-rule
    2630           5 :     for(int i(static_cast<int>(csspp::output_mode_t::COMPACT));
    2631           5 :         i <= static_cast<int>(csspp::output_mode_t::TIDY);
    2632             :         ++i)
    2633             :     {
    2634           4 :         std::stringstream ss;
    2635             :         ss << "@document url(http://www.example.com/), regexp(\"https://.*\")\n"
    2636             :            << "{\n"
    2637             :            << "  body { width: 8.5in; height: 9in; }\n"
    2638             :            << "  div { border: .25in unquote(\"solid\") lightgray }\n"
    2639             :            << "}\n"
    2640           4 :            << "#edge { border: 1px unquote('solid') black }\n";
    2641          12 :         csspp::position pos("test.css");
    2642           4 :         csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
    2643             : 
    2644           8 :         csspp::parser p(l);
    2645             : 
    2646           4 :         csspp::node::pointer_t n(p.stylesheet());
    2647             : 
    2648           4 :         csspp::compiler c;
    2649           4 :         c.set_root(n);
    2650           4 :         c.set_date_time_variables(csspp_test::get_now());
    2651           4 :         c.add_path(csspp_test::get_script_path());
    2652           4 :         c.add_path(csspp_test::get_version_script_path());
    2653             : 
    2654           4 :         c.compile(false);
    2655             : 
    2656             : //std::cerr << "Compiler result is: [" << *c.get_root() << "]\n";
    2657             : 
    2658           4 :         std::stringstream out;
    2659           4 :         csspp::assembler a(out);
    2660           4 :         a.output(n, static_cast<csspp::output_mode_t>(i));
    2661             : 
    2662             : //std::cerr << "----------------- Result is " << static_cast<csspp::output_mode_t>(i) << "\n[" << out.str() << "]\n";
    2663             : 
    2664           4 :         switch(static_cast<csspp::output_mode_t>(i))
    2665             :         {
    2666           1 :         case csspp::output_mode_t::COMPACT:
    2667           1 :             CATCH_REQUIRE(out.str() ==
    2668             : "@document url( http://www.example.com/ ), regexp(\"https://.*\")\n"
    2669             : "{\n"
    2670             : "body { width: 8.5in; height: 9in }\n"
    2671             : "div { border: .25in solid #d3d3d3 }\n"
    2672             : "}\n"
    2673             : "\n"
    2674             : "#edge { border: 1px solid #000 }\n"
    2675             : + csspp_test::get_close_comment()
    2676             :                 );
    2677           1 :             break;
    2678             : 
    2679           1 :         case csspp::output_mode_t::COMPRESSED:
    2680           1 :             CATCH_REQUIRE(out.str() ==
    2681             : "@document url(http://www.example.com/),regexp(\"https://.*\"){body{width:8.5in;height:9in}div{border:.25in solid #d3d3d3}}#edge{border:1px solid #000}\n"
    2682             : + csspp_test::get_close_comment()
    2683             :                 );
    2684           1 :             break;
    2685             : 
    2686           1 :         case csspp::output_mode_t::EXPANDED:
    2687           1 :             CATCH_REQUIRE(out.str() ==
    2688             : "@document url( http://www.example.com/ ), regexp(\"https://.*\")\n"
    2689             : "{\n"
    2690             : "body\n"
    2691             : "{\n"
    2692             : "  width: 8.5in;\n"
    2693             : "  height: 9in;\n"
    2694             : "}\n"
    2695             : "div\n"
    2696             : "{\n"
    2697             : "  border: .25in solid #d3d3d3;\n"
    2698             : "}\n"
    2699             : "}\n"
    2700             : "\n"
    2701             : "#edge\n"
    2702             : "{\n"
    2703             : "  border: 1px solid #000;\n"
    2704             : "}\n"
    2705             : + csspp_test::get_close_comment()
    2706             :                 );
    2707           1 :             break;
    2708             : 
    2709           1 :         case csspp::output_mode_t::TIDY:
    2710           1 :             CATCH_REQUIRE(out.str() ==
    2711             : "@document url(http://www.example.com/),regexp(\"https://.*\")\n"
    2712             : "{\n"
    2713             : "body{width:8.5in;height:9in}\n"
    2714             : "div{border:.25in solid #d3d3d3}\n"
    2715             : "}\n"
    2716             : "\n"
    2717             : "#edge{border:1px solid #000}\n"
    2718             : + csspp_test::get_close_comment()
    2719             :                 );
    2720           1 :             break;
    2721             : 
    2722             :         }
    2723             : 
    2724           4 :         CATCH_REQUIRE(c.get_root() == n);
    2725           4 :     }
    2726             : 
    2727             :     // Standard @media with a sub-rule
    2728           5 :     for(int i(static_cast<int>(csspp::output_mode_t::COMPACT));
    2729           5 :         i <= static_cast<int>(csspp::output_mode_t::TIDY);
    2730             :         ++i)
    2731             :     {
    2732           4 :         std::stringstream ss;
    2733             :         ss << "@media screen or (printer and color) { body { width: 8.5in; height: 9in; } }\n"
    2734           4 :            << "#edge { border: 1px solid black }\n";
    2735          12 :         csspp::position pos("test.css");
    2736           4 :         csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
    2737             : 
    2738           8 :         csspp::parser p(l);
    2739             : 
    2740           4 :         csspp::node::pointer_t n(p.stylesheet());
    2741             : 
    2742           4 :         csspp::compiler c;
    2743           4 :         c.set_root(n);
    2744           4 :         c.set_date_time_variables(csspp_test::get_now());
    2745           4 :         c.add_path(csspp_test::get_script_path());
    2746           4 :         c.add_path(csspp_test::get_version_script_path());
    2747             : 
    2748           4 :         c.compile(false);
    2749             : 
    2750             : //std::cerr << "Compiler result is: [" << *c.get_root() << "]\n";
    2751             : 
    2752           4 :         std::stringstream out;
    2753           4 :         csspp::assembler a(out);
    2754           4 :         a.output(n, static_cast<csspp::output_mode_t>(i));
    2755             : 
    2756             : //std::cerr << "----------------- Result is " << static_cast<csspp::output_mode_t>(i) << "\n[" << out.str() << "]\n";
    2757             : 
    2758           4 :         switch(static_cast<csspp::output_mode_t>(i))
    2759             :         {
    2760           1 :         case csspp::output_mode_t::COMPACT:
    2761           1 :             CATCH_REQUIRE(out.str() ==
    2762             : "@media screen or (printer and color) \n"
    2763             : "{\n"
    2764             : "body { width: 8.5in; height: 9in }\n"
    2765             : "}\n"
    2766             : "\n"
    2767             : "#edge { border: 1px solid #000 }\n"
    2768             : + csspp_test::get_close_comment()
    2769             :                 );
    2770           1 :             break;
    2771             : 
    2772           1 :         case csspp::output_mode_t::COMPRESSED:
    2773           1 :             CATCH_REQUIRE(out.str() ==
    2774             : "@media screen or (printer and color){body{width:8.5in;height:9in}}#edge{border:1px solid #000}\n"
    2775             : + csspp_test::get_close_comment()
    2776             :                 );
    2777           1 :             break;
    2778             : 
    2779           1 :         case csspp::output_mode_t::EXPANDED:
    2780           1 :             CATCH_REQUIRE(out.str() ==
    2781             : "@media screen or (printer and color) \n"
    2782             : "{\n"
    2783             : "body\n"
    2784             : "{\n"
    2785             : "  width: 8.5in;\n"
    2786             : "  height: 9in;\n"
    2787             : "}\n"
    2788             : "}\n"
    2789             : "\n"
    2790             : "#edge\n"
    2791             : "{\n"
    2792             : "  border: 1px solid #000;\n"
    2793             : "}\n"
    2794             : + csspp_test::get_close_comment()
    2795             :                 );
    2796           1 :             break;
    2797             : 
    2798           1 :         case csspp::output_mode_t::TIDY:
    2799           1 :             CATCH_REQUIRE(out.str() ==
    2800             : "@media screen or (printer and color)\n"
    2801             : "{\n"
    2802             : "body{width:8.5in;height:9in}\n"
    2803             : "}\n"
    2804             : "\n"
    2805             : "#edge{border:1px solid #000}\n"
    2806             : + csspp_test::get_close_comment()
    2807             :                 );
    2808           1 :             break;
    2809             : 
    2810             :         }
    2811             : 
    2812           4 :         CATCH_REQUIRE(c.get_root() == n);
    2813           4 :     }
    2814             : 
    2815             :     // @media with many parenthesis and multiple sub-rules
    2816           5 :     for(int i(static_cast<int>(csspp::output_mode_t::COMPACT));
    2817           5 :         i <= static_cast<int>(csspp::output_mode_t::TIDY);
    2818             :         ++i)
    2819             :     {
    2820           4 :         std::stringstream ss;
    2821             :         ss << "@media not (screen or ((laser or matrix or jet-printer) and color)) {\n"
    2822             :            << "  body { width: 8.5in; height: 9in; }\n"
    2823             :            << "  div { margin: .15in; padding: .07in; }\n"
    2824             :            << "  p { margin-bottom: 2em; }\n"
    2825             :            << "}\n"
    2826           4 :            << "#edge { border: 1px solid black }\n";
    2827          12 :         csspp::position pos("test.css");
    2828           4 :         csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
    2829             : 
    2830           8 :         csspp::parser p(l);
    2831             : 
    2832           4 :         csspp::node::pointer_t n(p.stylesheet());
    2833             : 
    2834           4 :         csspp::compiler c;
    2835           4 :         c.set_root(n);
    2836           4 :         c.set_date_time_variables(csspp_test::get_now());
    2837           4 :         c.add_path(csspp_test::get_script_path());
    2838           4 :         c.add_path(csspp_test::get_version_script_path());
    2839             : 
    2840           4 :         c.compile(false);
    2841             : 
    2842             : //std::cerr << "Compiler result is: [" << *c.get_root() << "]\n";
    2843             : 
    2844           4 :         std::stringstream out;
    2845           4 :         csspp::assembler a(out);
    2846           4 :         a.output(n, static_cast<csspp::output_mode_t>(i));
    2847             : 
    2848             : //std::cerr << "----------------- Result is " << static_cast<csspp::output_mode_t>(i) << "\n[" << out.str() << "]\n";
    2849             : 
    2850           4 :         switch(static_cast<csspp::output_mode_t>(i))
    2851             :         {
    2852           1 :         case csspp::output_mode_t::COMPACT:
    2853           1 :             CATCH_REQUIRE(out.str() ==
    2854             : "@media not (screen or ((laser or matrix or jet-printer) and color)) \n"
    2855             : "{\n"
    2856             : "body { width: 8.5in; height: 9in }\n"
    2857             : "div { margin: .15in; padding: .07in }\n"
    2858             : "p { margin-bottom: 2em }\n"
    2859             : "}\n"
    2860             : "\n"
    2861             : "#edge { border: 1px solid #000 }\n"
    2862             : + csspp_test::get_close_comment()
    2863             :                 );
    2864           1 :             break;
    2865             : 
    2866           1 :         case csspp::output_mode_t::COMPRESSED:
    2867           1 :             CATCH_REQUIRE(out.str() ==
    2868             : "@media not (screen or ((laser or matrix or jet-printer) and color)){body{width:8.5in;height:9in}div{margin:.15in;padding:.07in}p{margin-bottom:2em}}#edge{border:1px solid #000}\n"
    2869             : + csspp_test::get_close_comment()
    2870             :                 );
    2871           1 :             break;
    2872             : 
    2873           1 :         case csspp::output_mode_t::EXPANDED:
    2874           1 :             CATCH_REQUIRE(out.str() ==
    2875             : "@media not (screen or ((laser or matrix or jet-printer) and color)) \n"
    2876             : "{\n"
    2877             : "body\n"
    2878             : "{\n"
    2879             : "  width: 8.5in;\n"
    2880             : "  height: 9in;\n"
    2881             : "}\n"
    2882             : "div\n"
    2883             : "{\n"
    2884             : "  margin: .15in;\n"
    2885             : "  padding: .07in;\n"
    2886             : "}\n"
    2887             : "p\n"
    2888             : "{\n"
    2889             : "  margin-bottom: 2em;\n"
    2890             : "}\n"
    2891             : "}\n"
    2892             : "\n"
    2893             : "#edge\n"
    2894             : "{\n"
    2895             : "  border: 1px solid #000;\n"
    2896             : "}\n"
    2897             : + csspp_test::get_close_comment()
    2898             :                 );
    2899           1 :             break;
    2900             : 
    2901           1 :         case csspp::output_mode_t::TIDY:
    2902           1 :             CATCH_REQUIRE(out.str() ==
    2903             : "@media not (screen or ((laser or matrix or jet-printer) and color))\n"
    2904             : "{\n"
    2905             : "body{width:8.5in;height:9in}\n"
    2906             : "div{margin:.15in;padding:.07in}\n"
    2907             : "p{margin-bottom:2em}\n"
    2908             : "}\n"
    2909             : "\n"
    2910             : "#edge{border:1px solid #000}\n"
    2911             : + csspp_test::get_close_comment()
    2912             :                 );
    2913           1 :             break;
    2914             : 
    2915             :         }
    2916             : 
    2917           4 :         CATCH_REQUIRE(c.get_root() == n);
    2918           4 :     }
    2919             : 
    2920             :     // simple @import to see the ';' at the end of the line
    2921           5 :     for(int i(static_cast<int>(csspp::output_mode_t::COMPACT));
    2922           5 :         i <= static_cast<int>(csspp::output_mode_t::TIDY);
    2923             :         ++i)
    2924             :     {
    2925           4 :         std::stringstream ss;
    2926           4 :         ss << "@import url(//css.m2osw.com/store/colors.css) only screen or (printer and color);\n";
    2927          12 :         csspp::position pos("test.css");
    2928           4 :         csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
    2929             : 
    2930           8 :         csspp::parser p(l);
    2931             : 
    2932           4 :         csspp::node::pointer_t n(p.stylesheet());
    2933             : 
    2934           4 :         csspp::compiler c;
    2935           4 :         c.set_root(n);
    2936           4 :         c.set_date_time_variables(csspp_test::get_now());
    2937           4 :         c.add_path(csspp_test::get_script_path());
    2938           4 :         c.add_path(csspp_test::get_version_script_path());
    2939             : 
    2940           4 :         c.compile(false);
    2941             : 
    2942             : //std::cerr << "Compiler result is: [" << *c.get_root() << "]\n";
    2943             : 
    2944           4 :         std::stringstream out;
    2945           4 :         csspp::assembler a(out);
    2946           4 :         a.output(n, static_cast<csspp::output_mode_t>(i));
    2947             : 
    2948             : //std::cerr << "----------------- Result is " << static_cast<csspp::output_mode_t>(i) << "\n[" << out.str() << "]\n";
    2949             : 
    2950           4 :         switch(static_cast<csspp::output_mode_t>(i))
    2951             :         {
    2952           1 :         case csspp::output_mode_t::COMPACT:
    2953           1 :             CATCH_REQUIRE(out.str() ==
    2954             : "@import url( //css.m2osw.com/store/colors.css ) only screen or (printer and color) ;\n"
    2955             : + csspp_test::get_close_comment()
    2956             :                 );
    2957           1 :             break;
    2958             : 
    2959           1 :         case csspp::output_mode_t::COMPRESSED:
    2960           1 :             CATCH_REQUIRE(out.str() ==
    2961             : "@import url(//css.m2osw.com/store/colors.css) only screen or (printer and color);\n"
    2962             : + csspp_test::get_close_comment()
    2963             :                 );
    2964           1 :             break;
    2965             : 
    2966           1 :         case csspp::output_mode_t::EXPANDED:
    2967           1 :             CATCH_REQUIRE(out.str() ==
    2968             : "@import url( //css.m2osw.com/store/colors.css ) only screen or (printer and color) ;\n"
    2969             : + csspp_test::get_close_comment()
    2970             :                 );
    2971           1 :             break;
    2972             : 
    2973           1 :         case csspp::output_mode_t::TIDY:
    2974           1 :             CATCH_REQUIRE(out.str() ==
    2975             : "@import url(//css.m2osw.com/store/colors.css) only screen or (printer and color);\n"
    2976             : + csspp_test::get_close_comment()
    2977             :                 );
    2978           1 :             break;
    2979             : 
    2980             :         }
    2981             : 
    2982           4 :         CATCH_REQUIRE(c.get_root() == n);
    2983           4 :     }
    2984             : 
    2985             :     // @keyframes
    2986           5 :     for(int i(static_cast<int>(csspp::output_mode_t::COMPACT));
    2987           5 :         i <= static_cast<int>(csspp::output_mode_t::TIDY);
    2988             :         ++i)
    2989             :     {
    2990           4 :         std::stringstream ss;
    2991             :         ss << "@keyframes name {\n"
    2992             :            << "  from {\n"
    2993             :            << "    left: 0;\n"
    2994             :            << "  }\n"
    2995             :            << "  33% {\n"
    2996             :            << "    left: 5px;\n"
    2997             :            << "  }\n"
    2998             :            << "  67% {\n"
    2999             :            << "    left: 45px;\n"
    3000             :            << "  }\n"
    3001             :            << "  to {\n"
    3002             :            << "    left: 50px;\n"
    3003             :            << "  }\n"
    3004           4 :            << "};\n";
    3005          12 :         csspp::position pos("test.css");
    3006           4 :         csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
    3007             : 
    3008           8 :         csspp::parser p(l);
    3009             : 
    3010           4 :         csspp::node::pointer_t n(p.stylesheet());
    3011             : 
    3012           4 :         csspp::compiler c;
    3013           4 :         c.set_root(n);
    3014           4 :         c.set_date_time_variables(csspp_test::get_now());
    3015           4 :         c.add_path(csspp_test::get_script_path());
    3016           4 :         c.add_path(csspp_test::get_version_script_path());
    3017             : 
    3018           4 :         c.compile(false);
    3019             : 
    3020             : //std::cerr << "Compiler result is: [" << *c.get_root() << "]\n";
    3021             : 
    3022           4 :         std::stringstream out;
    3023           4 :         csspp::assembler a(out);
    3024           4 :         a.output(n, static_cast<csspp::output_mode_t>(i));
    3025             : 
    3026             : //std::cerr << "----------------- Result is " << static_cast<csspp::output_mode_t>(i) << "\n[" << out.str() << "]\n";
    3027             : 
    3028           4 :         switch(static_cast<csspp::output_mode_t>(i))
    3029             :         {
    3030           1 :         case csspp::output_mode_t::COMPACT:
    3031           1 :             CATCH_REQUIRE(out.str() ==
    3032             : "@keyframes name {\n"
    3033             : "0% { left: 0 }\n"
    3034             : "33% { left: 5px }\n"
    3035             : "67% { left: 45px }\n"
    3036             : "to { left: 50px }\n"
    3037             : "}\n"
    3038             : + csspp_test::get_close_comment()
    3039             :                 );
    3040           1 :             break;
    3041             : 
    3042           1 :         case csspp::output_mode_t::COMPRESSED:
    3043           1 :             CATCH_REQUIRE(out.str() ==
    3044             : "@keyframes name{0%{left:0}33%{left:5px}67%{left:45px}to{left:50px}}\n"
    3045             : + csspp_test::get_close_comment()
    3046             :                 );
    3047           1 :             break;
    3048             : 
    3049           1 :         case csspp::output_mode_t::EXPANDED:
    3050           1 :             CATCH_REQUIRE(out.str() ==
    3051             : "@keyframes name {\n"
    3052             : "0%\n"
    3053             : "{\n"
    3054             : "  left: 0;\n"
    3055             : "}\n"
    3056             : "33%\n"
    3057             : "{\n"
    3058             : "  left: 5px;\n"
    3059             : "}\n"
    3060             : "67%\n"
    3061             : "{\n"
    3062             : "  left: 45px;\n"
    3063             : "}\n"
    3064             : "to\n"
    3065             : "{\n"
    3066             : "  left: 50px;\n"
    3067             : "}\n"
    3068             : "}\n"
    3069             : + csspp_test::get_close_comment()
    3070             :                 );
    3071           1 :             break;
    3072             : 
    3073           1 :         case csspp::output_mode_t::TIDY:
    3074           1 :             CATCH_REQUIRE(out.str() ==
    3075             : "@keyframes name{\n"
    3076             : "0%{left:0}\n"
    3077             : "33%{left:5px}\n"
    3078             : "67%{left:45px}\n"
    3079             : "to{left:50px}\n"
    3080             : "}\n"
    3081             : + csspp_test::get_close_comment()
    3082             :                 );
    3083           1 :             break;
    3084             : 
    3085             :         }
    3086             : 
    3087           4 :         CATCH_REQUIRE(c.get_root() == n);
    3088           4 :     }
    3089             : 
    3090             :     // no error left over
    3091           1 :     VERIFY_ERRORS("");
    3092           1 : }
    3093             : 
    3094           1 : CATCH_TEST_CASE("Assemble functions", "[assembler] [function]")
    3095             : {
    3096             :     // Test with gradient() function
    3097           5 :     for(int i(static_cast<int>(csspp::output_mode_t::COMPACT));
    3098           5 :         i <= static_cast<int>(csspp::output_mode_t::TIDY);
    3099             :         ++i)
    3100             :     {
    3101           4 :         std::stringstream ss;
    3102             :         ss << "$box($color, $width, $height): { border: 1px * 3 solid $color; width: $width * 1.5; height: $height };\n"
    3103           4 :            << "a ~ b { -csspp-null: $box(#39458A, 300px, 200px); }\n";
    3104          12 :         csspp::position pos("test.css");
    3105           4 :         csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
    3106             : 
    3107           8 :         csspp::parser p(l);
    3108             : 
    3109           4 :         csspp::node::pointer_t n(p.stylesheet());
    3110             : 
    3111             : //std::cerr << "Parser result is: [" << *n << "]\n";
    3112             : 
    3113           4 :         csspp::compiler c;
    3114           4 :         c.set_root(n);
    3115           4 :         c.set_date_time_variables(csspp_test::get_now());
    3116           4 :         c.add_path(csspp_test::get_script_path());
    3117           4 :         c.add_path(csspp_test::get_version_script_path());
    3118             : 
    3119           4 :         c.compile(false);
    3120             : 
    3121             : //std::cerr << "Compiler result is: [" << *c.get_root() << "]\n";
    3122             : 
    3123           4 :         std::stringstream out;
    3124           4 :         csspp::assembler a(out);
    3125           4 :         a.output(n, static_cast<csspp::output_mode_t>(i));
    3126             : 
    3127             : //std::cerr << "----------------- Result is " << static_cast<csspp::output_mode_t>(i) << "\n[" << out.str() << "]\n";
    3128             : 
    3129           4 :         std::stringstream expected;
    3130           4 :         switch(static_cast<csspp::output_mode_t>(i))
    3131             :         {
    3132           1 :         case csspp::output_mode_t::COMPACT:
    3133           1 : expected << "a ~ b { border: 3px solid #39458a; width: 450px; height: 200px }\n";
    3134           1 :             break;
    3135             : 
    3136           1 :         case csspp::output_mode_t::COMPRESSED:
    3137           1 : expected << "a~b{border:3px solid #39458a;width:450px;height:200px}\n";
    3138           1 :             break;
    3139             : 
    3140           1 :         case csspp::output_mode_t::EXPANDED:
    3141             : expected << "a ~ b\n"
    3142             :  << "{\n"
    3143             :  << "  border: 3px solid #39458a;\n"
    3144             :  << "  width: 450px;\n"
    3145             :  << "  height: 200px;\n"
    3146           1 :  << "}\n";
    3147           1 :             break;
    3148             : 
    3149           1 :         case csspp::output_mode_t::TIDY:
    3150           1 : expected << "a~b{border:3px solid #39458a;width:450px;height:200px}\n";
    3151           1 :             break;
    3152             : 
    3153             :         }
    3154           4 :         expected << csspp_test::get_close_comment();
    3155           4 :         CATCH_REQUIRE(out.str() == expected.str());
    3156             : 
    3157           4 :         CATCH_REQUIRE(c.get_root() == n);
    3158           4 :     }
    3159             : 
    3160             :     // CSS Function which is an internal CSS Preprocess function
    3161             :     // (meaning that it gets interpreted and replaced by a value)
    3162           5 :     for(int i(static_cast<int>(csspp::output_mode_t::COMPACT));
    3163           5 :         i <= static_cast<int>(csspp::output_mode_t::TIDY);
    3164             :         ++i)
    3165             :     {
    3166           4 :         std::stringstream ss;
    3167           4 :         ss << "a b { color: rgba(1 * 7, 2, 3, .5); }\n";
    3168          12 :         csspp::position pos("test.css");
    3169           4 :         csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
    3170             : 
    3171           8 :         csspp::parser p(l);
    3172             : 
    3173           4 :         csspp::node::pointer_t n(p.stylesheet());
    3174             : 
    3175             : //std::cerr << "Parser result is: [" << *n << "]\n";
    3176             : 
    3177           4 :         csspp::compiler c;
    3178           4 :         c.set_root(n);
    3179           4 :         c.set_date_time_variables(csspp_test::get_now());
    3180           4 :         c.add_path(csspp_test::get_script_path());
    3181           4 :         c.add_path(csspp_test::get_version_script_path());
    3182             : 
    3183           4 :         c.compile(false);
    3184             : 
    3185             : //std::cerr << "Compiler result is: [" << *c.get_root() << "]\n";
    3186             : 
    3187           4 :         std::stringstream out;
    3188           4 :         csspp::assembler a(out);
    3189           4 :         a.output(n, static_cast<csspp::output_mode_t>(i));
    3190             : 
    3191             : //std::cerr << "----------------- Result is " << static_cast<csspp::output_mode_t>(i) << "\n[" << out.str() << "]\n";
    3192             : 
    3193           4 :         std::stringstream expected;
    3194           4 :         switch(static_cast<csspp::output_mode_t>(i))
    3195             :         {
    3196           1 :         case csspp::output_mode_t::COMPACT:
    3197           1 : expected << "a b { color: rgba(7,2,3,.5) }\n";  // TODO: add support for spaces in the color::to_string() function?
    3198           1 :             break;
    3199             : 
    3200           1 :         case csspp::output_mode_t::COMPRESSED:
    3201           1 : expected << "a b{color:rgba(7,2,3,.5)}\n";
    3202           1 :             break;
    3203             : 
    3204           1 :         case csspp::output_mode_t::EXPANDED:
    3205             : expected << "a b\n"
    3206             :          << "{\n"
    3207             :          << "  color: rgba(7,2,3,.5);\n"  // TODO: add support for spaces in the color::to_string() function?
    3208           1 :          << "}\n";
    3209           1 :             break;
    3210             : 
    3211           1 :         case csspp::output_mode_t::TIDY:
    3212           1 : expected << "a b{color:rgba(7,2,3,.5)}\n";
    3213           1 :             break;
    3214             : 
    3215             :         }
    3216           4 :         expected << csspp_test::get_close_comment();
    3217           4 :         CATCH_REQUIRE(out.str() == expected.str());
    3218             : 
    3219           4 :         CATCH_REQUIRE(c.get_root() == n);
    3220           4 :     }
    3221             : 
    3222             :     // CSS Function which is not replaced by CSS Proprocessor
    3223           5 :     for(int i(static_cast<int>(csspp::output_mode_t::COMPACT));
    3224           5 :         i <= static_cast<int>(csspp::output_mode_t::TIDY);
    3225             :         ++i)
    3226             :     {
    3227           4 :         std::stringstream ss;
    3228           4 :         ss << "a b { transform: translate(percentage(-.50px), 0); }\n";
    3229          12 :         csspp::position pos("test.css");
    3230           4 :         csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
    3231             : 
    3232           8 :         csspp::parser p(l);
    3233             : 
    3234           4 :         csspp::node::pointer_t n(p.stylesheet());
    3235             : 
    3236             : //std::cerr << "Parser result is: [" << *n << "]\n";
    3237             : 
    3238           4 :         csspp::compiler c;
    3239           4 :         c.set_root(n);
    3240           4 :         c.set_date_time_variables(csspp_test::get_now());
    3241           4 :         c.add_path(csspp_test::get_script_path());
    3242           4 :         c.add_path(csspp_test::get_version_script_path());
    3243             : 
    3244           4 :         c.compile(false);
    3245             : 
    3246             : //std::cerr << "Compiler result is: [" << *c.get_root() << "]\n";
    3247             : 
    3248           4 :         std::stringstream out;
    3249           4 :         csspp::assembler a(out);
    3250           4 :         a.output(n, static_cast<csspp::output_mode_t>(i));
    3251             : 
    3252             : //std::cerr << "----------------- Result is " << static_cast<csspp::output_mode_t>(i) << "\n[" << out.str() << "]\n";
    3253             : 
    3254           4 :         std::stringstream expected;
    3255           4 :         switch(static_cast<csspp::output_mode_t>(i))
    3256             :         {
    3257           1 :         case csspp::output_mode_t::COMPACT:
    3258           1 : expected << "a b { transform: translate(-50%, 0) }\n";
    3259           1 :             break;
    3260             : 
    3261           1 :         case csspp::output_mode_t::COMPRESSED:
    3262           1 : expected << "a b{transform:translate(-50%,0)}\n";
    3263           1 :             break;
    3264             : 
    3265           1 :         case csspp::output_mode_t::EXPANDED:
    3266             : expected << "a b\n"
    3267             :          << "{\n"
    3268             :          << "  transform: translate(-50%, 0);\n"
    3269           1 :          << "}\n";
    3270           1 :             break;
    3271             : 
    3272           1 :         case csspp::output_mode_t::TIDY:
    3273           1 : expected << "a b{transform:translate(-50%,0)}\n";
    3274           1 :             break;
    3275             : 
    3276             :         }
    3277           4 :         expected << csspp_test::get_close_comment();
    3278           4 :         CATCH_REQUIRE(out.str() == expected.str());
    3279             : 
    3280           4 :         CATCH_REQUIRE(c.get_root() == n);
    3281           4 :     }
    3282             : 
    3283             :     // no error left over
    3284           1 :     VERIFY_ERRORS("");
    3285           1 : }
    3286             : 
    3287           1 : CATCH_TEST_CASE("Assemble placeholder", "[assembler] [placeholder]")
    3288             : {
    3289             :     // Test with gradient() function
    3290           5 :     for(int i(static_cast<int>(csspp::output_mode_t::COMPACT));
    3291           5 :         i <= static_cast<int>(csspp::output_mode_t::TIDY);
    3292             :         ++i)
    3293             :     {
    3294           4 :         std::stringstream ss;
    3295             :         ss << "$reddish: #e09756;\n"
    3296             :            << "#context a%extreme { color: blue; font-weight: bold; font-size: 2em }\n"
    3297           4 :            << ".error { color: $reddish }\n";
    3298          12 :         csspp::position pos("test.css");
    3299           4 :         csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
    3300             : 
    3301           8 :         csspp::parser p(l);
    3302             : 
    3303           4 :         csspp::node::pointer_t n(p.stylesheet());
    3304             : 
    3305             : //std::cerr << "Parser result is: [" << *n << "]\n";
    3306             : 
    3307           4 :         csspp::compiler c;
    3308           4 :         c.set_root(n);
    3309           4 :         c.set_date_time_variables(csspp_test::get_now());
    3310           4 :         c.add_path(csspp_test::get_script_path());
    3311           4 :         c.add_path(csspp_test::get_version_script_path());
    3312             : 
    3313           4 :         c.compile(false);
    3314             : 
    3315             : //std::cerr << "Compiler result is: [" << *c.get_root() << "]\n";
    3316             : 
    3317           4 :         std::stringstream out;
    3318           4 :         csspp::assembler a(out);
    3319           4 :         a.output(n, static_cast<csspp::output_mode_t>(i));
    3320             : 
    3321             : //std::cerr << "----------------- Result is " << static_cast<csspp::output_mode_t>(i) << "\n[" << out.str() << "]\n";
    3322             : 
    3323           4 :         std::stringstream expected;
    3324           4 :         switch(static_cast<csspp::output_mode_t>(i))
    3325             :         {
    3326           1 :         case csspp::output_mode_t::COMPACT:
    3327           1 : expected << ".error { color: #e09756 }\n";
    3328           1 :             break;
    3329             : 
    3330           1 :         case csspp::output_mode_t::COMPRESSED:
    3331           1 : expected << ".error{color:#e09756}\n";
    3332           1 :             break;
    3333             : 
    3334           1 :         case csspp::output_mode_t::EXPANDED:
    3335             : expected << ".error\n"
    3336             :  << "{\n"
    3337             :  << "  color: #e09756;\n"
    3338           1 :  << "}\n";
    3339           1 :             break;
    3340             : 
    3341           1 :         case csspp::output_mode_t::TIDY:
    3342           1 : expected << ".error{color:#e09756}\n";
    3343           1 :             break;
    3344             : 
    3345             :         }
    3346           4 :         expected << csspp_test::get_close_comment();
    3347           4 :         CATCH_REQUIRE(out.str() == expected.str());
    3348             : 
    3349           4 :         CATCH_REQUIRE(c.get_root() == n);
    3350           4 :     }
    3351             : 
    3352             :     // no error left over
    3353           1 :     VERIFY_ERRORS("");
    3354           1 : }
    3355             : 
    3356           1 : CATCH_TEST_CASE("Assemble operators", "[assembler] [operators]")
    3357             : {
    3358             :     // Selector unary operator
    3359           5 :     for(int i(static_cast<int>(csspp::output_mode_t::COMPACT));
    3360           5 :         i <= static_cast<int>(csspp::output_mode_t::TIDY);
    3361             :         ++i)
    3362             :     {
    3363           4 :         std::stringstream ss;
    3364           4 :         ss << "a * b { color: red; }\n";
    3365          12 :         csspp::position pos("test.css");
    3366           4 :         csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
    3367             : 
    3368           8 :         csspp::parser p(l);
    3369             : 
    3370           4 :         csspp::node::pointer_t n(p.stylesheet());
    3371             : 
    3372           4 :         csspp::compiler c;
    3373           4 :         c.set_root(n);
    3374           4 :         c.set_date_time_variables(csspp_test::get_now());
    3375           4 :         c.add_path(csspp_test::get_script_path());
    3376           4 :         c.add_path(csspp_test::get_version_script_path());
    3377             : 
    3378           4 :         c.compile(false);
    3379             : 
    3380             : //std::cerr << "Compiler result is: [" << *c.get_root() << "]\n";
    3381             : 
    3382           4 :         std::stringstream out;
    3383           4 :         csspp::assembler a(out);
    3384           4 :         a.output(n, static_cast<csspp::output_mode_t>(i));
    3385             : 
    3386             : //std::cerr << "----------------- Result is " << static_cast<csspp::output_mode_t>(i) << "\n[" << out.str() << "]\n";
    3387             : 
    3388           4 :         std::stringstream expected;
    3389           4 :         switch(static_cast<csspp::output_mode_t>(i))
    3390             :         {
    3391           1 :         case csspp::output_mode_t::COMPACT:
    3392           1 : expected << "a * b { color: red }\n";
    3393           1 :             break;
    3394             : 
    3395           1 :         case csspp::output_mode_t::COMPRESSED:
    3396           1 : expected << "a * b{color:red}\n";
    3397           1 :             break;
    3398             : 
    3399           1 :         case csspp::output_mode_t::EXPANDED:
    3400             : expected << "a * b\n"
    3401             :  << "{\n"
    3402             :  << "  color: red;\n"
    3403           1 :  << "}\n";
    3404           1 :             break;
    3405             : 
    3406           1 :         case csspp::output_mode_t::TIDY:
    3407           1 : expected << "a * b{color:red}\n";
    3408           1 :             break;
    3409             : 
    3410             :         }
    3411           4 :         expected << csspp_test::get_close_comment();
    3412           4 :         CATCH_REQUIRE(out.str() == expected.str());
    3413             : 
    3414           4 :         CATCH_REQUIRE(c.get_root() == n);
    3415           4 :     }
    3416             : 
    3417             :     // Selector binary operators
    3418             :     {
    3419           1 :         char const * selector_operator[] =
    3420             :         {
    3421             :             "+",
    3422             :             "~",
    3423             :             ">"
    3424             :         };
    3425             : 
    3426           4 :         for(size_t op(0); op < sizeof(selector_operator) / sizeof(selector_operator[0]); ++op)
    3427             :         {
    3428          15 :             for(int i(static_cast<int>(csspp::output_mode_t::COMPACT));
    3429          15 :                 i <= static_cast<int>(csspp::output_mode_t::TIDY);
    3430             :                 ++i)
    3431             :             {
    3432          12 :                 std::stringstream ss;
    3433             :                 ss << "a"
    3434          24 :                    << ((rand() % 2) == 0 ? " " : "")
    3435             :                    << selector_operator[op]
    3436          24 :                    << ((rand() % 2) == 0 ? " " : "")
    3437          12 :                    << "b { color: red; }\n";
    3438          36 :                 csspp::position pos("test.css");
    3439          12 :                 csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
    3440             : 
    3441          24 :                 csspp::parser p(l);
    3442             : 
    3443          12 :                 csspp::node::pointer_t n(p.stylesheet());
    3444             : 
    3445          12 :                 csspp::compiler c;
    3446          12 :                 c.set_root(n);
    3447          12 :                 c.set_date_time_variables(csspp_test::get_now());
    3448          12 :                 c.add_path(csspp_test::get_script_path());
    3449          12 :                 c.add_path(csspp_test::get_version_script_path());
    3450             : 
    3451          12 :                 c.compile(false);
    3452             : 
    3453             : //std::cerr << "Compiler result is: [" << *c.get_root() << "]\n";
    3454             : 
    3455          12 :                 std::stringstream out;
    3456          12 :                 csspp::assembler a(out);
    3457          12 :                 a.output(n, static_cast<csspp::output_mode_t>(i));
    3458             : 
    3459             : //std::cerr << "----------------- Result is " << static_cast<csspp::output_mode_t>(i) << "\n[" << out.str() << "]\n";
    3460             : 
    3461          12 :                 std::stringstream expected;
    3462          12 :                 switch(static_cast<csspp::output_mode_t>(i))
    3463             :                 {
    3464           3 :                 case csspp::output_mode_t::COMPACT:
    3465           3 : expected << "a " << selector_operator[op] << " b { color: red }\n";
    3466           3 :                     break;
    3467             : 
    3468           3 :                 case csspp::output_mode_t::COMPRESSED:
    3469           3 : expected << "a" << selector_operator[op] << "b{color:red}\n";
    3470           3 :                     break;
    3471             : 
    3472           3 :                 case csspp::output_mode_t::EXPANDED:
    3473             : expected << "a " << selector_operator[op] << " b\n"
    3474             :          << "{\n"
    3475             :          << "  color: red;\n"
    3476           3 :          << "}\n";
    3477           3 :                     break;
    3478             : 
    3479           3 :                 case csspp::output_mode_t::TIDY:
    3480           3 : expected << "a" << selector_operator[op] << "b{color:red}\n";
    3481           3 :                     break;
    3482             : 
    3483             :                 }
    3484          12 :                 expected << csspp_test::get_close_comment();
    3485          12 :                 CATCH_REQUIRE(out.str() == expected.str());
    3486             : 
    3487          12 :                 CATCH_REQUIRE(c.get_root() == n);
    3488          12 :             }
    3489             :         }
    3490             :     }
    3491             : 
    3492             :     // Attributes binary operators
    3493             :     {
    3494           1 :         char const * attribute_operator[] =
    3495             :         {
    3496             :             "=",
    3497             :             "~=",
    3498             :             "^=",
    3499             :             "$=",
    3500             :             "*=",
    3501             :             "|="
    3502             :         };
    3503             : 
    3504           7 :         for(size_t op(0); op < sizeof(attribute_operator) / sizeof(attribute_operator[0]); ++op)
    3505             :         {
    3506          30 :             for(int i(static_cast<int>(csspp::output_mode_t::COMPACT));
    3507          30 :                 i <= static_cast<int>(csspp::output_mode_t::TIDY);
    3508             :                 ++i)
    3509             :             {
    3510          24 :                 std::stringstream ss;
    3511             :                 ss << "a["
    3512          48 :                    << ((rand() % 2) != 0 ? " " : "")
    3513             :                    << "b"
    3514          48 :                    << ((rand() % 2) != 0 ? " " : "")
    3515             :                    << attribute_operator[op]
    3516          48 :                    << ((rand() % 2) != 0 ? " " : "")
    3517             :                    << "3"
    3518          48 :                    << ((rand() % 2) != 0 ? " " : "")
    3519             :                    << "]"
    3520          48 :                    << ((rand() % 2) != 0 ? "\n" : "")
    3521             :                    << "{"
    3522          48 :                    << ((rand() % 2) != 0 ? " " : "")
    3523             :                    << "color"
    3524          48 :                    << ((rand() % 2) != 0 ? " " : "")
    3525             :                    << ":"
    3526          48 :                    << ((rand() % 2) != 0 ? " " : "")
    3527             :                    << "red"
    3528          48 :                    << ((rand() % 2) != 0 ? " " : "")
    3529          24 :                    << "}\n";
    3530          72 :                 csspp::position pos("test.css");
    3531          24 :                 csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
    3532             : 
    3533          48 :                 csspp::parser p(l);
    3534             : 
    3535          24 :                 csspp::node::pointer_t n(p.stylesheet());
    3536             : 
    3537          24 :                 csspp::compiler c;
    3538          24 :                 c.set_root(n);
    3539          24 :                 c.set_date_time_variables(csspp_test::get_now());
    3540          24 :                 c.add_path(csspp_test::get_script_path());
    3541          24 :                 c.add_path(csspp_test::get_version_script_path());
    3542             : 
    3543          24 :                 c.compile(false);
    3544             : 
    3545             : //std::cerr << "Compiler result is: [" << *c.get_root() << "]\n";
    3546             : 
    3547          24 :                 std::stringstream out;
    3548          24 :                 csspp::assembler a(out);
    3549          24 :                 a.output(n, static_cast<csspp::output_mode_t>(i));
    3550             : 
    3551             : //std::cerr << "----------------- Result is " << static_cast<csspp::output_mode_t>(i) << "\n[" << out.str() << "]\n";
    3552             : 
    3553          24 :                 std::stringstream expected;
    3554          24 :                 switch(static_cast<csspp::output_mode_t>(i))
    3555             :                 {
    3556           6 :                 case csspp::output_mode_t::COMPACT:
    3557           6 : expected << "a[b " << attribute_operator[op] << " 3] { color: red }\n";
    3558           6 :                     break;
    3559             : 
    3560           6 :                 case csspp::output_mode_t::COMPRESSED:
    3561           6 : expected << "a[b" << attribute_operator[op] << "3]{color:red}\n";
    3562           6 :                     break;
    3563             : 
    3564           6 :                 case csspp::output_mode_t::EXPANDED:
    3565             : expected << "a[b " << attribute_operator[op] << " 3]\n"
    3566             :         "{\n"
    3567             :         "  color: red;\n"
    3568           6 :         "}\n";
    3569           6 :                     break;
    3570             : 
    3571           6 :                 case csspp::output_mode_t::TIDY:
    3572           6 : expected << "a[b" << attribute_operator[op] << "3]{color:red}\n";
    3573           6 :                     break;
    3574             : 
    3575             :                 }
    3576          24 :                 expected << csspp_test::get_close_comment();
    3577          24 :                 CATCH_REQUIRE(out.str() == expected.str());
    3578             : 
    3579          24 :                 CATCH_REQUIRE(c.get_root() == n);
    3580          24 :             }
    3581             :         }
    3582             :     }
    3583             : 
    3584             :     // '!' -- EXCLAMATION
    3585           5 :     for(int i(static_cast<int>(csspp::output_mode_t::COMPACT));
    3586           5 :         i <= static_cast<int>(csspp::output_mode_t::TIDY);
    3587             :         ++i)
    3588             :     {
    3589           4 :         std::stringstream ss;
    3590             :         ss << "*[b = 3] { color : red !"
    3591           8 :            << ((rand() % 2) == 0 ? " " : "")
    3592           4 :            << "important; }";
    3593          12 :         csspp::position pos("test.css");
    3594           4 :         csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
    3595             : 
    3596           8 :         csspp::parser p(l);
    3597             : 
    3598           4 :         csspp::node::pointer_t n(p.stylesheet());
    3599             : 
    3600           4 :         csspp::compiler c;
    3601           4 :         c.set_root(n);
    3602           4 :         c.set_date_time_variables(csspp_test::get_now());
    3603           4 :         c.add_path(csspp_test::get_script_path());
    3604           4 :         c.add_path(csspp_test::get_version_script_path());
    3605             : 
    3606           4 :         c.compile(false);
    3607             : 
    3608             : //std::cerr << "Compiler result is: [" << *c.get_root() << "]\n";
    3609             : 
    3610           4 :         std::stringstream out;
    3611           4 :         csspp::assembler a(out);
    3612           4 :         a.output(n, static_cast<csspp::output_mode_t>(i));
    3613             : 
    3614             : //std::cerr << "----------------- Result is " << static_cast<csspp::output_mode_t>(i) << "\n[" << out.str() << "]\n";
    3615             : 
    3616           4 :         switch(static_cast<csspp::output_mode_t>(i))
    3617             :         {
    3618           1 :         case csspp::output_mode_t::COMPACT:
    3619           1 :             CATCH_REQUIRE(out.str() ==
    3620             : "[b = 3] { color: red !important }\n"
    3621             : + csspp_test::get_close_comment()
    3622             :                 );
    3623           1 :             break;
    3624             : 
    3625           1 :         case csspp::output_mode_t::COMPRESSED:
    3626           1 :             CATCH_REQUIRE(out.str() ==
    3627             : "[b=3]{color:red!important}\n"
    3628             : + csspp_test::get_close_comment()
    3629             :                 );
    3630           1 :             break;
    3631             : 
    3632           1 :         case csspp::output_mode_t::EXPANDED:
    3633           1 :             CATCH_REQUIRE(out.str() ==
    3634             : "[b = 3]\n"
    3635             : "{\n"
    3636             : "  color: red !important;\n"
    3637             : "}\n"
    3638             : + csspp_test::get_close_comment()
    3639             :                 );
    3640           1 :             break;
    3641             : 
    3642           1 :         case csspp::output_mode_t::TIDY:
    3643           1 :             CATCH_REQUIRE(out.str() ==
    3644             : "[b=3]{color:red!important}\n"
    3645             : + csspp_test::get_close_comment()
    3646             :                 );
    3647           1 :             break;
    3648             : 
    3649             :         }
    3650             : 
    3651           4 :         CATCH_REQUIRE(c.get_root() == n);
    3652           4 :     }
    3653             : 
    3654             :     // no error left over
    3655           1 :     VERIFY_ERRORS("");
    3656           1 : }
    3657             : 
    3658           1 : CATCH_TEST_CASE("Assembler modes", "[assembler] [mode]")
    3659             : {
    3660           5 :     for(int i(static_cast<int>(csspp::output_mode_t::COMPACT));
    3661           5 :         i <= static_cast<int>(csspp::output_mode_t::TIDY);
    3662             :         ++i)
    3663             :     {
    3664           4 :         std::stringstream ss;
    3665           4 :         ss << static_cast<csspp::output_mode_t>(i);
    3666             : 
    3667           4 :         switch(static_cast<csspp::output_mode_t>(i))
    3668             :         {
    3669           1 :         case csspp::output_mode_t::COMPACT:
    3670           1 :             CATCH_REQUIRE(ss.str() == "COMPACT");
    3671           1 :             break;
    3672             : 
    3673           1 :         case csspp::output_mode_t::COMPRESSED:
    3674           1 :             CATCH_REQUIRE(ss.str() == "COMPRESSED");
    3675           1 :             break;
    3676             : 
    3677           1 :         case csspp::output_mode_t::EXPANDED:
    3678           1 :             CATCH_REQUIRE(ss.str() == "EXPANDED");
    3679           1 :             break;
    3680             : 
    3681           1 :         case csspp::output_mode_t::TIDY:
    3682           1 :             CATCH_REQUIRE(ss.str() == "TIDY");
    3683           1 :             break;
    3684             : 
    3685             :         }
    3686           4 :     }
    3687             : 
    3688             :     // no error left over
    3689           1 :     VERIFY_ERRORS("");
    3690           1 : }
    3691             : 
    3692           1 : CATCH_TEST_CASE("Invalid assembler mode", "[assembler] [mode] [invalid]")
    3693             : {
    3694             :     // with many spaces
    3695         101 :     for(int i(0); i < 100; ++i)
    3696             :     {
    3697         100 :         std::stringstream out;
    3698         100 :         csspp::assembler a(out);
    3699         300 :         csspp::position pos("test.css");
    3700         100 :         csspp::node::pointer_t n(new csspp::node(csspp::node_type_t::LIST, pos));
    3701         100 :         csspp::output_mode_t mode(static_cast<csspp::output_mode_t>(rand()));
    3702         100 :         while(is_valid_mode(mode))
    3703             :         {
    3704           0 :             mode = static_cast<csspp::output_mode_t>(rand());
    3705             :         }
    3706         300 :         CATCH_REQUIRE_THROWS_AS(a.output(n, mode), csspp::csspp_exception_logic);
    3707         100 :     }
    3708             : 
    3709             :     // no error left over
    3710           1 :     VERIFY_ERRORS("");
    3711           1 : }
    3712             : 
    3713           1 : CATCH_TEST_CASE("Inacceptable nodes", "[assembler] [invalid]")
    3714             : {
    3715             :     // list of "invalid" nodes in the assembler
    3716           1 :     csspp::node_type_t node_types[] =
    3717             :     {
    3718             :         csspp::node_type_t::UNKNOWN,
    3719             :         csspp::node_type_t::AND,
    3720             :         csspp::node_type_t::ASSIGNMENT,
    3721             :         csspp::node_type_t::BOOLEAN,
    3722             :         csspp::node_type_t::CDC,
    3723             :         csspp::node_type_t::CDO,
    3724             :         csspp::node_type_t::CLOSE_CURLYBRACKET,
    3725             :         csspp::node_type_t::CLOSE_PARENTHESIS,
    3726             :         csspp::node_type_t::CLOSE_SQUAREBRACKET,
    3727             :         csspp::node_type_t::COLUMN,
    3728             :         csspp::node_type_t::COMMA,
    3729             :         csspp::node_type_t::CONDITIONAL,
    3730             :         csspp::node_type_t::DOLLAR,
    3731             :         csspp::node_type_t::EOF_TOKEN,
    3732             :         csspp::node_type_t::EXCLAMATION,
    3733             :         csspp::node_type_t::GREATER_EQUAL,
    3734             :         csspp::node_type_t::LESS_EQUAL,
    3735             :         csspp::node_type_t::LESS_THAN,
    3736             :         csspp::node_type_t::MODULO,
    3737             :         csspp::node_type_t::NOT_EQUAL,
    3738             :         csspp::node_type_t::NULL_TOKEN,
    3739             :         csspp::node_type_t::PLACEHOLDER,
    3740             :         csspp::node_type_t::POWER,
    3741             :         csspp::node_type_t::REFERENCE,
    3742             :         csspp::node_type_t::SEMICOLON,
    3743             :         csspp::node_type_t::VARIABLE,
    3744             :         csspp::node_type_t::VARIABLE_FUNCTION,
    3745             :         csspp::node_type_t::max_type
    3746             :     };
    3747             : 
    3748           5 :     for(int i(static_cast<int>(csspp::output_mode_t::COMPACT));
    3749           5 :         i <= static_cast<int>(csspp::output_mode_t::TIDY);
    3750             :         ++i)
    3751             :     {
    3752         116 :         for(size_t j(0); j < sizeof(node_types) / sizeof(node_types[0]); ++j)
    3753             :         {
    3754         336 :             csspp::position pos("test.css");
    3755         112 :             csspp::node::pointer_t root(new csspp::node(node_types[j], pos));
    3756             : 
    3757             : //std::cerr << "Compiler result is: [" << *c.get_root() << "]\n";
    3758             : 
    3759         112 :             std::stringstream out;
    3760         112 :             csspp::assembler a(out);
    3761         336 :             CATCH_REQUIRE_THROWS_AS(a.output(root, static_cast<csspp::output_mode_t>(i)), csspp::csspp_exception_logic);
    3762         112 :         }
    3763             :     }
    3764           1 : }
    3765             : 
    3766           1 : CATCH_TEST_CASE("CSS incompatible dimensions", "[assembler] [invalid] [dimension]")
    3767             : {
    3768           5 :     for(int i(static_cast<int>(csspp::output_mode_t::COMPACT));
    3769           5 :         i <= static_cast<int>(csspp::output_mode_t::TIDY);
    3770             :         ++i)
    3771             :     {
    3772           4 :         std::stringstream ss;
    3773           4 :         ss << "span { border: 3px * 5px solid #f7d0cf; }";
    3774          12 :         csspp::position pos("test.css");
    3775           4 :         csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
    3776             : 
    3777           8 :         csspp::parser p(l);
    3778             : 
    3779           4 :         csspp::node::pointer_t n(p.stylesheet());
    3780             : 
    3781           4 :         csspp::compiler c;
    3782           4 :         c.set_root(n);
    3783           4 :         c.set_date_time_variables(csspp_test::get_now());
    3784           4 :         c.add_path(csspp_test::get_script_path());
    3785           4 :         c.add_path(csspp_test::get_version_script_path());
    3786             : 
    3787           4 :         c.compile(false);
    3788             : 
    3789             : //std::cerr << "Compiler result is: [" << *c.get_root() << "]\n";
    3790             : 
    3791             :         // no errors yet
    3792           4 :         VERIFY_ERRORS("");
    3793             : 
    3794           4 :         std::stringstream out;
    3795           4 :         csspp::assembler a(out);
    3796           4 :         a.output(n, static_cast<csspp::output_mode_t>(i));
    3797             : 
    3798             : //std::cerr << "----------------- Result is " << static_cast<csspp::output_mode_t>(i) << "\n[" << out.str() << "]\n";
    3799             : 
    3800           4 :         VERIFY_ERRORS("test.css(1): error: \"px * px\" is not a valid CSS dimension.\n");
    3801             : 
    3802           4 :         CATCH_REQUIRE(c.get_root() == n);
    3803           4 :     }
    3804             : 
    3805             :     // no error left over
    3806           1 :     VERIFY_ERRORS("");
    3807           1 : }
    3808             : 
    3809             : // vim: ts=4 sw=4 et

Generated by: LCOV version 1.14