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 expression.cpp file: "?:" operator. 22 : * 23 : * This test runs a battery of tests agains the expression.cpp "?:" 24 : * (conditional) operator to ensure full coverage and that all possible 25 : * left hand side and right hand side types are checked for the equality 26 : * CSS Preprocessor extensions. 27 : * 28 : * Note that all the tests use the full chain: lexer, parser, compiler, 29 : * and assembler to make sure the results are correct. So these tests 30 : * exercise the assembler even more than the assembler tests, except that 31 : * it only checks that compressed results are correct instead of all 32 : * output modes, since its only goal is covering all the possible 33 : * expression cases and not the assembler, compiler, parser, and lexer 34 : * classes. 35 : */ 36 : 37 : // csspp 38 : // 39 : #include <csspp/compiler.h> 40 : 41 : #include <csspp/assembler.h> 42 : #include <csspp/exception.h> 43 : #include <csspp/parser.h> 44 : 45 : 46 : // self 47 : // 48 : #include "catch_main.h" 49 : 50 : 51 : // C++ 52 : // 53 : #include <sstream> 54 : 55 : 56 : // last include 57 : // 58 : #include <snapdev/poison.h> 59 : 60 : 61 : 62 3 : CATCH_TEST_CASE("Expression boolean ? a : b", "[expression] [conditional]") 63 : { 64 3 : CATCH_START_SECTION("check 10 = 3 ? 9 : 5") 65 : { 66 1 : std::stringstream ss; 67 1 : ss << "div { z-index: 10 = 3 ? 9 : 5; }"; 68 3 : csspp::position pos("test.css"); 69 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos)); 70 : 71 2 : csspp::parser p(l); 72 : 73 1 : csspp::node::pointer_t n(p.stylesheet()); 74 : 75 1 : csspp::compiler c; 76 1 : c.set_root(n); 77 1 : c.set_date_time_variables(csspp_test::get_now()); 78 1 : c.add_path(csspp_test::get_script_path()); 79 1 : c.add_path(csspp_test::get_version_script_path()); 80 : 81 1 : c.compile(false); 82 : 83 : //std::cerr << "Compiler result is: [" << *c.get_root() << "]\n"; 84 : 85 : // to verify that the result is still an INTEGER we have to 86 : // test the root node here 87 1 : std::stringstream compiler_out; 88 1 : compiler_out << *n; 89 1 : VERIFY_TREES(compiler_out.str(), 90 : 91 : "LIST\n" 92 : + csspp_test::get_default_variables() + 93 : " COMPONENT_VALUE\n" 94 : " ARG\n" 95 : " IDENTIFIER \"div\"\n" 96 : " OPEN_CURLYBRACKET B:true\n" 97 : " DECLARATION \"z-index\"\n" 98 : " ARG\n" 99 : " INTEGER \"\" I:5\n" 100 : + csspp_test::get_close_comment(true) 101 : 102 : ); 103 : 104 1 : std::stringstream assembler_out; 105 1 : csspp::assembler a(assembler_out); 106 1 : a.output(n, csspp::output_mode_t::COMPRESSED); 107 : 108 : //std::cerr << "----------------- Result is " << static_cast<csspp::output_mode_t>(i) << "\n[" << out.str() << "]\n"; 109 : 110 1 : CATCH_REQUIRE(assembler_out.str() == 111 : 112 : "div{z-index:5}\n" 113 : + csspp_test::get_close_comment() 114 : 115 : ); 116 : 117 1 : CATCH_REQUIRE(c.get_root() == n); 118 1 : } 119 3 : CATCH_END_SECTION() 120 : 121 3 : CATCH_START_SECTION("check 10 != 3 ? 9 : 5") 122 : { 123 1 : std::stringstream ss; 124 1 : ss << "div { z-index: 10 != 3 ? 9 : 5; }"; 125 3 : csspp::position pos("test.css"); 126 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos)); 127 : 128 2 : csspp::parser p(l); 129 : 130 1 : csspp::node::pointer_t n(p.stylesheet()); 131 : 132 1 : csspp::compiler c; 133 1 : c.set_root(n); 134 1 : c.set_date_time_variables(csspp_test::get_now()); 135 1 : c.add_path(csspp_test::get_script_path()); 136 1 : c.add_path(csspp_test::get_version_script_path()); 137 : 138 1 : c.compile(false); 139 : 140 : //std::cerr << "Compiler result is: [" << *c.get_root() << "]\n"; 141 : 142 : // to verify that the result is still an INTEGER we have to 143 : // test the root node here 144 1 : std::stringstream compiler_out; 145 1 : compiler_out << *n; 146 1 : VERIFY_TREES(compiler_out.str(), 147 : 148 : "LIST\n" 149 : + csspp_test::get_default_variables() + 150 : " COMPONENT_VALUE\n" 151 : " ARG\n" 152 : " IDENTIFIER \"div\"\n" 153 : " OPEN_CURLYBRACKET B:true\n" 154 : " DECLARATION \"z-index\"\n" 155 : " ARG\n" 156 : " INTEGER \"\" I:9\n" 157 : + csspp_test::get_close_comment(true) 158 : 159 : ); 160 : 161 1 : std::stringstream assembler_out; 162 1 : csspp::assembler a(assembler_out); 163 1 : a.output(n, csspp::output_mode_t::COMPRESSED); 164 : 165 : //std::cerr << "----------------- Result is " << static_cast<csspp::output_mode_t>(i) << "\n[" << out.str() << "]\n"; 166 : 167 1 : CATCH_REQUIRE(assembler_out.str() == 168 : 169 : "div{z-index:9}\n" 170 : + csspp_test::get_close_comment() 171 : 172 : ); 173 : 174 1 : CATCH_REQUIRE(c.get_root() == n); 175 1 : } 176 3 : CATCH_END_SECTION() 177 : 178 3 : CATCH_START_SECTION("check 10 != 3 ? \"string\" : 5") 179 : { 180 1 : std::stringstream ss; 181 1 : ss << "div { content: 10 != 3 ? \"string\" : 5; }"; 182 3 : csspp::position pos("test.css"); 183 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos)); 184 : 185 2 : csspp::parser p(l); 186 : 187 1 : csspp::node::pointer_t n(p.stylesheet()); 188 : 189 1 : csspp::compiler c; 190 1 : c.set_root(n); 191 1 : c.set_date_time_variables(csspp_test::get_now()); 192 1 : c.add_path(csspp_test::get_script_path()); 193 1 : c.add_path(csspp_test::get_version_script_path()); 194 : 195 1 : c.compile(false); 196 : 197 : //std::cerr << "Compiler result is: [" << *c.get_root() << "]\n"; 198 : 199 : // to verify that the result is still an INTEGER we have to 200 : // test the root node here 201 1 : std::stringstream compiler_out; 202 1 : compiler_out << *n; 203 1 : VERIFY_TREES(compiler_out.str(), 204 : 205 : "LIST\n" 206 : + csspp_test::get_default_variables() + 207 : " COMPONENT_VALUE\n" 208 : " ARG\n" 209 : " IDENTIFIER \"div\"\n" 210 : " OPEN_CURLYBRACKET B:true\n" 211 : " DECLARATION \"content\"\n" 212 : " ARG\n" 213 : " STRING \"string\"\n" 214 : + csspp_test::get_close_comment(true) 215 : 216 : ); 217 : 218 1 : std::stringstream assembler_out; 219 1 : csspp::assembler a(assembler_out); 220 1 : a.output(n, csspp::output_mode_t::COMPRESSED); 221 : 222 : //std::cerr << "----------------- Result is " << static_cast<csspp::output_mode_t>(i) << "\n[" << out.str() << "]\n"; 223 : 224 1 : CATCH_REQUIRE(assembler_out.str() == 225 : 226 : "div{content:\"string\"}\n" 227 : + csspp_test::get_close_comment() 228 : 229 : ); 230 : 231 1 : CATCH_REQUIRE(c.get_root() == n); 232 1 : } 233 3 : CATCH_END_SECTION() 234 : 235 : // no error left over 236 3 : VERIFY_ERRORS(""); 237 3 : } 238 : 239 6 : CATCH_TEST_CASE("Expression invalid ? invalid : invalid", "[expression] [conditional] [invalid]") 240 : { 241 6 : CATCH_START_SECTION("just ? is not a valid number") 242 : { 243 1 : std::stringstream ss; 244 1 : ss << "div { border: ?; }"; 245 3 : csspp::position pos("test.css"); 246 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos)); 247 : 248 2 : csspp::parser p(l); 249 : 250 1 : csspp::node::pointer_t n(p.stylesheet()); 251 : 252 1 : csspp::compiler c; 253 1 : c.set_root(n); 254 1 : c.set_date_time_variables(csspp_test::get_now()); 255 1 : c.add_path(csspp_test::get_script_path()); 256 1 : c.add_path(csspp_test::get_version_script_path()); 257 : 258 1 : c.compile(false); 259 : 260 : //std::cerr << "Compiler result is: [" << *c.get_root() << "]\n"; 261 : 262 1 : VERIFY_ERRORS("test.css(1): error: unsupported type CONDITIONAL as a unary expression token.\n"); 263 : 264 1 : CATCH_REQUIRE(c.get_root() == n); 265 1 : } 266 6 : CATCH_END_SECTION() 267 : 268 6 : CATCH_START_SECTION("number ? ? ... is invalid") 269 : { 270 1 : std::stringstream ss; 271 1 : ss << "div { width: 10px ? ?; }"; 272 3 : csspp::position pos("test.css"); 273 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos)); 274 : 275 2 : csspp::parser p(l); 276 : 277 1 : csspp::node::pointer_t n(p.stylesheet()); 278 : 279 1 : csspp::compiler c; 280 1 : c.set_root(n); 281 1 : c.set_date_time_variables(csspp_test::get_now()); 282 1 : c.add_path(csspp_test::get_script_path()); 283 1 : c.add_path(csspp_test::get_version_script_path()); 284 : 285 1 : c.compile(false); 286 : 287 : //std::cerr << "Compiler result is: [" << *c.get_root() << "]\n"; 288 : 289 1 : VERIFY_ERRORS("test.css(1): error: unsupported type CONDITIONAL as a unary expression token.\n"); 290 : 291 1 : CATCH_REQUIRE(c.get_root() == n); 292 1 : } 293 6 : CATCH_END_SECTION() 294 : 295 6 : CATCH_START_SECTION("true ? 3em : ? is invalid") 296 : { 297 1 : std::stringstream ss; 298 1 : ss << "div { width: true ? 3em : ?; }"; 299 3 : csspp::position pos("test.css"); 300 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos)); 301 : 302 2 : csspp::parser p(l); 303 : 304 1 : csspp::node::pointer_t n(p.stylesheet()); 305 : 306 1 : csspp::compiler c; 307 1 : c.set_root(n); 308 1 : c.set_date_time_variables(csspp_test::get_now()); 309 1 : c.add_path(csspp_test::get_script_path()); 310 1 : c.add_path(csspp_test::get_version_script_path()); 311 : 312 1 : c.compile(false); 313 : 314 : //std::cerr << "Compiler result is: [" << *c.get_root() << "]\n"; 315 : 316 1 : VERIFY_ERRORS("test.css(1): error: unsupported type EOF_TOKEN as a unary expression token.\n"); 317 : 318 1 : CATCH_REQUIRE(c.get_root() == n); 319 1 : } 320 6 : CATCH_END_SECTION() 321 : 322 6 : CATCH_START_SECTION("true ? 3em 10em is invalid, missing ':'") 323 : { 324 1 : std::stringstream ss; 325 1 : ss << "div { width: true ? 3em 10em; }"; 326 3 : csspp::position pos("test.css"); 327 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos)); 328 : 329 2 : csspp::parser p(l); 330 : 331 1 : csspp::node::pointer_t n(p.stylesheet()); 332 : 333 1 : csspp::compiler c; 334 1 : c.set_root(n); 335 1 : c.set_date_time_variables(csspp_test::get_now()); 336 1 : c.add_path(csspp_test::get_script_path()); 337 1 : c.add_path(csspp_test::get_version_script_path()); 338 : 339 1 : c.compile(false); 340 : 341 : //std::cerr << "Compiler result is: [" << *c.get_root() << "]\n"; 342 : 343 1 : VERIFY_ERRORS("test.css(1): error: a mandatory ':' was expected after a '?' first expression.\n"); 344 : 345 1 : CATCH_REQUIRE(c.get_root() == n); 346 1 : } 347 6 : CATCH_END_SECTION() 348 : 349 6 : CATCH_START_SECTION("unicode-range ? 3em : 10em is invalid, not a boolean") 350 : { 351 1 : std::stringstream ss; 352 1 : ss << "div { width: unicode-range ? 3em : 10em; }"; 353 3 : csspp::position pos("test.css"); 354 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos)); 355 : 356 2 : csspp::parser p(l); 357 : 358 1 : csspp::node::pointer_t n(p.stylesheet()); 359 : 360 1 : csspp::compiler c; 361 1 : c.set_root(n); 362 1 : c.set_date_time_variables(csspp_test::get_now()); 363 1 : c.add_path(csspp_test::get_script_path()); 364 1 : c.add_path(csspp_test::get_version_script_path()); 365 : 366 1 : c.compile(false); 367 : 368 : //std::cerr << "Compiler result is: [" << *c.get_root() << "]\n"; 369 : 370 1 : VERIFY_ERRORS("test.css(1): error: a boolean expression was expected.\n"); 371 : 372 1 : CATCH_REQUIRE(c.get_root() == n); 373 1 : } 374 6 : CATCH_END_SECTION() 375 : 376 6 : CATCH_START_SECTION("' false ? 3em : ' is invalid, something's missing") 377 : { 378 1 : std::stringstream ss; 379 1 : ss << "div { width: false ? 3em : ; }"; 380 3 : csspp::position pos("test.css"); 381 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos)); 382 : 383 2 : csspp::parser p(l); 384 : 385 1 : csspp::node::pointer_t n(p.stylesheet()); 386 : 387 1 : csspp::compiler c; 388 1 : c.set_root(n); 389 1 : c.set_date_time_variables(csspp_test::get_now()); 390 1 : c.add_path(csspp_test::get_script_path()); 391 1 : c.add_path(csspp_test::get_version_script_path()); 392 : 393 1 : c.compile(false); 394 : 395 : //std::cerr << "Compiler result is: [" << *c.get_root() << "]\n"; 396 : 397 1 : VERIFY_ERRORS("test.css(1): error: unsupported type EOF_TOKEN as a unary expression token.\n"); 398 : 399 1 : CATCH_REQUIRE(c.get_root() == n); 400 1 : } 401 6 : CATCH_END_SECTION() 402 : 403 : // no error left over 404 6 : VERIFY_ERRORS(""); 405 6 : } 406 : 407 : // vim: ts=4 sw=4 et