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 compiler.cpp file.
22 : *
23 : * This test runs a battery of tests agains the compiler.cpp file to ensure
24 : * full coverage and many edge cases as expected by CSS 3 and many of the
25 : * CSS Preprocessor extensions.
26 : */
27 :
28 : // csspp
29 : //
30 : #include <csspp/compiler.h>
31 :
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 <unistd.h>
52 : #include <sys/stat.h>
53 :
54 :
55 : // last include
56 : //
57 : #include <snapdev/poison.h>
58 :
59 :
60 :
61 1 : void free_char(char * ptr)
62 : {
63 1 : free(ptr);
64 1 : }
65 :
66 1 : CATCH_TEST_CASE("Compile set_date_time_variables() called too soon", "[compiler] [invalid]")
67 : {
68 1 : csspp::compiler c;
69 1 : CATCH_REQUIRE_THROWS_AS(c.set_date_time_variables(csspp_test::get_now()), csspp::csspp_exception_logic);
70 2 : }
71 :
72 1 : CATCH_TEST_CASE("Compile simple stylesheets", "[compiler] [stylesheet] [attribute]")
73 : {
74 : // with many spaces
75 : {
76 1 : std::stringstream ss;
77 : ss << "/* testing compile */"
78 : << "body, a[q] > b[p=\"344.5\"] + c[z=33] ~ d[e], html *[ ff = fire ] *.blue { background : white url( /images/background.png ) }"
79 1 : << "/* @preserver test \"Compile Simple Stylesheet\" */";
80 3 : csspp::position pos("test.css");
81 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
82 :
83 2 : csspp::parser p(l);
84 :
85 1 : csspp::node::pointer_t n(p.stylesheet());
86 :
87 : // no errors so far
88 1 : VERIFY_ERRORS("");
89 :
90 1 : csspp::compiler c;
91 1 : c.set_root(n);
92 1 : c.set_date_time_variables(csspp_test::get_now());
93 1 : c.clear_paths();
94 1 : c.add_path(csspp_test::get_script_path());
95 1 : c.add_path(csspp_test::get_version_script_path());
96 :
97 1 : c.compile(false);
98 :
99 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
100 :
101 1 : std::stringstream out;
102 1 : out << *n;
103 1 : VERIFY_TREES(out.str(),
104 :
105 : "LIST\n"
106 : + csspp_test::get_default_variables() +
107 : " COMPONENT_VALUE\n"
108 : " ARG\n"
109 : " IDENTIFIER \"body\"\n"
110 : " ARG\n"
111 : " IDENTIFIER \"a\"\n"
112 : " OPEN_SQUAREBRACKET\n"
113 : " IDENTIFIER \"q\"\n"
114 : " GREATER_THAN\n"
115 : " IDENTIFIER \"b\"\n"
116 : " OPEN_SQUAREBRACKET\n"
117 : " IDENTIFIER \"p\"\n"
118 : " EQUAL\n"
119 : " STRING \"344.5\"\n"
120 : " ADD\n"
121 : " IDENTIFIER \"c\"\n"
122 : " OPEN_SQUAREBRACKET\n"
123 : " IDENTIFIER \"z\"\n"
124 : " EQUAL\n"
125 : " INTEGER \"\" I:33\n"
126 : " PRECEDED\n"
127 : " IDENTIFIER \"d\"\n"
128 : " OPEN_SQUAREBRACKET\n"
129 : " IDENTIFIER \"e\"\n"
130 : " ARG\n"
131 : " IDENTIFIER \"html\"\n"
132 : " WHITESPACE\n"
133 : " OPEN_SQUAREBRACKET\n"
134 : " IDENTIFIER \"ff\"\n"
135 : " EQUAL\n"
136 : " IDENTIFIER \"fire\"\n"
137 : " WHITESPACE\n"
138 : " PERIOD\n"
139 : " IDENTIFIER \"blue\"\n"
140 : " OPEN_CURLYBRACKET B:true\n"
141 : " DECLARATION \"background\"\n"
142 : " ARG\n"
143 : " COLOR H:ffffffff\n"
144 : " WHITESPACE\n"
145 : " URL \"/images/background.png\"\n"
146 : " COMMENT \"@preserver test \"Compile Simple Stylesheet\"\" I:1\n"
147 : + csspp_test::get_close_comment(true)
148 :
149 : );
150 :
151 : // no error left over
152 1 : VERIFY_ERRORS("");
153 :
154 1 : CATCH_REQUIRE(c.get_root() == n);
155 1 : }
156 :
157 : // without spaces
158 : {
159 1 : std::stringstream ss;
160 : ss << "/* testing compile */"
161 : << "body,a[q]>b[p=\"344.5\"]+c[z=33]~d[e],html *[ff=fire] *.blue { background:white url(/images/background.png) }"
162 1 : << "/* @preserver test \"Compile Simple Stylesheet\" with version #{$_csspp_major}.#{$_csspp_minor} */";
163 3 : csspp::position pos("test.css");
164 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
165 :
166 2 : csspp::parser p(l);
167 :
168 1 : csspp::node::pointer_t n(p.stylesheet());
169 :
170 : // no errors so far
171 1 : VERIFY_ERRORS("");
172 :
173 1 : csspp::compiler c;
174 1 : c.set_root(n);
175 1 : c.set_date_time_variables(csspp_test::get_now());
176 1 : c.clear_paths();
177 1 : c.add_path(csspp_test::get_script_path());
178 1 : c.add_path(csspp_test::get_version_script_path());
179 :
180 1 : c.compile(false);
181 :
182 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
183 :
184 1 : std::stringstream out;
185 1 : out << *n;
186 1 : VERIFY_TREES(out.str(),
187 :
188 : "LIST\n"
189 : + csspp_test::get_default_variables() +
190 : " COMPONENT_VALUE\n"
191 : " ARG\n"
192 : " IDENTIFIER \"body\"\n"
193 : " ARG\n"
194 : " IDENTIFIER \"a\"\n"
195 : " OPEN_SQUAREBRACKET\n"
196 : " IDENTIFIER \"q\"\n"
197 : " GREATER_THAN\n"
198 : " IDENTIFIER \"b\"\n"
199 : " OPEN_SQUAREBRACKET\n"
200 : " IDENTIFIER \"p\"\n"
201 : " EQUAL\n"
202 : " STRING \"344.5\"\n"
203 : " ADD\n"
204 : " IDENTIFIER \"c\"\n"
205 : " OPEN_SQUAREBRACKET\n"
206 : " IDENTIFIER \"z\"\n"
207 : " EQUAL\n"
208 : " INTEGER \"\" I:33\n"
209 : " PRECEDED\n"
210 : " IDENTIFIER \"d\"\n"
211 : " OPEN_SQUAREBRACKET\n"
212 : " IDENTIFIER \"e\"\n"
213 : " ARG\n"
214 : " IDENTIFIER \"html\"\n"
215 : " WHITESPACE\n"
216 : " OPEN_SQUAREBRACKET\n"
217 : " IDENTIFIER \"ff\"\n"
218 : " EQUAL\n"
219 : " IDENTIFIER \"fire\"\n"
220 : " WHITESPACE\n"
221 : " PERIOD\n"
222 : " IDENTIFIER \"blue\"\n"
223 : " OPEN_CURLYBRACKET B:true\n"
224 : " DECLARATION \"background\"\n"
225 : " ARG\n"
226 : " COLOR H:ffffffff\n"
227 : " WHITESPACE\n"
228 : " URL \"/images/background.png\"\n"
229 : " COMMENT \"@preserver test \"Compile Simple Stylesheet\" with version 1.0\" I:1\n"
230 : + csspp_test::get_close_comment(true)
231 :
232 : );
233 :
234 : // no error left over
235 1 : VERIFY_ERRORS("");
236 :
237 1 : CATCH_REQUIRE(c.get_root() == n);
238 1 : }
239 :
240 : // rules with !important
241 : {
242 1 : std::stringstream ss;
243 1 : ss << "div.blackness { color: red !important }";
244 3 : csspp::position pos("test.css");
245 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
246 :
247 2 : csspp::parser p(l);
248 :
249 1 : csspp::node::pointer_t n(p.stylesheet());
250 :
251 : // no errors so far
252 1 : VERIFY_ERRORS("");
253 :
254 1 : csspp::compiler c;
255 1 : c.set_root(n);
256 1 : c.set_date_time_variables(csspp_test::get_now());
257 1 : c.clear_paths();
258 1 : c.add_path(csspp_test::get_script_path());
259 1 : c.add_path(csspp_test::get_version_script_path());
260 :
261 1 : c.compile(false);
262 :
263 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
264 :
265 1 : std::stringstream out;
266 1 : out << *n;
267 1 : VERIFY_TREES(out.str(),
268 :
269 : "LIST\n"
270 : + csspp_test::get_default_variables() +
271 : " COMPONENT_VALUE\n"
272 : " ARG\n"
273 : " IDENTIFIER \"div\"\n"
274 : " PERIOD\n"
275 : " IDENTIFIER \"blackness\"\n"
276 : " OPEN_CURLYBRACKET B:true\n"
277 : " DECLARATION \"color\" F:important\n"
278 : " ARG\n"
279 : " COLOR H:ff0000ff\n"
280 : + csspp_test::get_close_comment(true)
281 :
282 : );
283 :
284 : // no error left over
285 1 : VERIFY_ERRORS("");
286 :
287 1 : CATCH_REQUIRE(c.get_root() == n);
288 1 : }
289 :
290 : // rules with ! important
291 : {
292 1 : std::stringstream ss;
293 1 : ss << "div.blackness { color: red ! important }";
294 3 : csspp::position pos("test.css");
295 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
296 :
297 2 : csspp::parser p(l);
298 :
299 1 : csspp::node::pointer_t n(p.stylesheet());
300 :
301 : // no errors so far
302 1 : VERIFY_ERRORS("");
303 :
304 1 : csspp::compiler c;
305 1 : c.set_root(n);
306 1 : c.set_date_time_variables(csspp_test::get_now());
307 1 : c.clear_paths();
308 1 : c.add_path(csspp_test::get_script_path());
309 1 : c.add_path(csspp_test::get_version_script_path());
310 :
311 1 : c.compile(false);
312 :
313 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
314 :
315 1 : std::stringstream out;
316 1 : out << *n;
317 1 : VERIFY_TREES(out.str(),
318 :
319 : "LIST\n"
320 : + csspp_test::get_default_variables() +
321 : " COMPONENT_VALUE\n"
322 : " ARG\n"
323 : " IDENTIFIER \"div\"\n"
324 : " PERIOD\n"
325 : " IDENTIFIER \"blackness\"\n"
326 : " OPEN_CURLYBRACKET B:true\n"
327 : " DECLARATION \"color\" F:important\n"
328 : " ARG\n"
329 : " COLOR H:ff0000ff\n"
330 : + csspp_test::get_close_comment(true)
331 :
332 : );
333 :
334 : // no error left over
335 1 : VERIFY_ERRORS("");
336 :
337 1 : CATCH_REQUIRE(c.get_root() == n);
338 1 : }
339 :
340 : // rules with !important and no spaces
341 : {
342 1 : std::stringstream ss;
343 1 : ss << "div.blackness { color: red!important }";
344 3 : csspp::position pos("test.css");
345 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
346 :
347 2 : csspp::parser p(l);
348 :
349 1 : csspp::node::pointer_t n(p.stylesheet());
350 :
351 : // no errors so far
352 1 : VERIFY_ERRORS("");
353 :
354 1 : csspp::compiler c;
355 1 : c.set_root(n);
356 1 : c.set_date_time_variables(csspp_test::get_now());
357 1 : c.clear_paths();
358 1 : c.add_path(csspp_test::get_script_path());
359 1 : c.add_path(csspp_test::get_version_script_path());
360 :
361 1 : c.compile(false);
362 :
363 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
364 :
365 1 : std::stringstream out;
366 1 : out << *n;
367 1 : VERIFY_TREES(out.str(),
368 :
369 : "LIST\n"
370 : + csspp_test::get_default_variables() +
371 : " COMPONENT_VALUE\n"
372 : " ARG\n"
373 : " IDENTIFIER \"div\"\n"
374 : " PERIOD\n"
375 : " IDENTIFIER \"blackness\"\n"
376 : " OPEN_CURLYBRACKET B:true\n"
377 : " DECLARATION \"color\" F:important\n"
378 : " ARG\n"
379 : " COLOR H:ff0000ff\n"
380 : + csspp_test::get_close_comment(true)
381 :
382 : );
383 :
384 : // no error left over
385 1 : VERIFY_ERRORS("");
386 :
387 1 : CATCH_REQUIRE(c.get_root() == n);
388 1 : }
389 :
390 : // empty rules have to compile too
391 : {
392 1 : std::stringstream ss;
393 : ss << "div.blackness section.light span.clear\n"
394 : << "{\n"
395 1 : << "}\n";
396 3 : csspp::position pos("test.css");
397 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
398 :
399 2 : csspp::parser p(l);
400 :
401 1 : csspp::node::pointer_t n(p.stylesheet());
402 :
403 : // no errors so far
404 1 : VERIFY_ERRORS("");
405 :
406 1 : csspp::compiler c;
407 1 : c.set_root(n);
408 1 : c.set_date_time_variables(csspp_test::get_now());
409 1 : c.clear_paths();
410 1 : c.add_path(csspp_test::get_script_path());
411 1 : c.add_path(csspp_test::get_version_script_path());
412 :
413 1 : c.compile(false);
414 :
415 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
416 :
417 1 : std::stringstream out;
418 1 : out << *n;
419 1 : VERIFY_TREES(out.str(),
420 :
421 : "LIST\n"
422 : + csspp_test::get_default_variables()
423 : + csspp_test::get_close_comment(true)
424 :
425 : );
426 :
427 : // no error left over
428 1 : VERIFY_ERRORS("");
429 :
430 1 : CATCH_REQUIRE(c.get_root() == n);
431 1 : }
432 :
433 : // special IE8 value which has to be skipped
434 : {
435 1 : std::stringstream ss;
436 : ss << ".transparent img\n"
437 : << "{\n"
438 : << " $alpha: 5% * 4;\n"
439 : << " filter: opacity($alpha);\n"
440 : << " filter: alpha( opacity=20 );\n"
441 1 : << "}\n";
442 3 : csspp::position pos("test.css");
443 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
444 :
445 2 : csspp::parser p(l);
446 :
447 1 : csspp::node::pointer_t n(p.stylesheet());
448 :
449 : // no errors so far
450 1 : VERIFY_ERRORS("");
451 :
452 1 : csspp::compiler c;
453 1 : c.set_root(n);
454 1 : c.set_date_time_variables(csspp_test::get_now());
455 1 : c.clear_paths();
456 1 : c.add_path(csspp_test::get_script_path());
457 1 : c.add_path(csspp_test::get_version_script_path());
458 :
459 1 : c.compile(false);
460 :
461 : // no error left over
462 1 : VERIFY_ERRORS(
463 : "test.css(4): warning: the alpha(), chroma() and similar functions of the filter field are Internet Explorer specific extensions which are not supported across browsers.\n"
464 : "test.css(5): warning: the alpha(), chroma() and similar functions of the filter field are Internet Explorer specific extensions which are not supported across browsers.\n"
465 : );
466 :
467 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
468 :
469 1 : std::stringstream out;
470 1 : out << *n;
471 1 : VERIFY_TREES(out.str(),
472 :
473 : "LIST\n"
474 : + csspp_test::get_default_variables() +
475 : " COMPONENT_VALUE\n"
476 : " ARG\n"
477 : " PERIOD\n"
478 : " IDENTIFIER \"transparent\"\n"
479 : " WHITESPACE\n"
480 : " IDENTIFIER \"img\"\n"
481 : " OPEN_CURLYBRACKET B:true\n"
482 : " V:alpha\n"
483 : " LIST\n"
484 : " VARIABLE \"alpha\"\n"
485 : " LIST\n"
486 : " PERCENT D:0.05\n"
487 : " WHITESPACE\n"
488 : " MULTIPLY\n"
489 : " WHITESPACE\n"
490 : " INTEGER \"\" I:4\n"
491 : " LIST\n"
492 : " DECLARATION \"filter\"\n"
493 : " FUNCTION \"opacity\"\n"
494 : " PERCENT D:0.05\n"
495 : " WHITESPACE\n"
496 : " MULTIPLY\n"
497 : " WHITESPACE\n"
498 : " INTEGER \"\" I:4\n"
499 : " DECLARATION \"filter\"\n"
500 : " FUNCTION \"alpha\"\n"
501 : " IDENTIFIER \"opacity\"\n"
502 : " EQUAL\n"
503 : " INTEGER \"\" I:20\n"
504 : + csspp_test::get_close_comment(true)
505 :
506 : );
507 :
508 : // no error left over
509 1 : VERIFY_ERRORS("");
510 :
511 1 : CATCH_REQUIRE(c.get_root() == n);
512 1 : }
513 :
514 : // a simple test with '--no-logo' specified
515 : {
516 1 : std::stringstream ss;
517 : ss << ".box\n"
518 : << "{\n"
519 : << " color: $_csspp_no_logo ? red : blue;\n"
520 1 : << "}\n";
521 3 : csspp::position pos("test.css");
522 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
523 :
524 2 : csspp::parser p(l);
525 :
526 1 : csspp::node::pointer_t n(p.stylesheet());
527 :
528 : // no errors so far
529 1 : VERIFY_ERRORS("");
530 :
531 1 : csspp::compiler c;
532 1 : c.set_root(n);
533 1 : c.set_date_time_variables(csspp_test::get_now());
534 1 : c.set_no_logo();
535 1 : c.clear_paths();
536 1 : c.add_path(csspp_test::get_script_path());
537 1 : c.add_path(csspp_test::get_version_script_path());
538 :
539 1 : c.compile(false);
540 :
541 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
542 :
543 : // no error left over
544 1 : VERIFY_ERRORS("");
545 :
546 1 : std::stringstream out;
547 1 : out << *n;
548 1 : VERIFY_TREES(out.str(),
549 :
550 : "LIST\n"
551 : + csspp_test::get_default_variables(csspp_test::flag_no_logo_true) +
552 : " COMPONENT_VALUE\n"
553 : " ARG\n"
554 : " PERIOD\n"
555 : " IDENTIFIER \"box\"\n"
556 : " OPEN_CURLYBRACKET B:true\n"
557 : " DECLARATION \"color\"\n"
558 : " ARG\n"
559 : " COLOR H:ff0000ff\n"
560 : //+ csspp_test::get_close_comment(true) -- with --no-logo this is gone
561 :
562 : );
563 :
564 : // no error left over
565 1 : VERIFY_ERRORS("");
566 :
567 1 : CATCH_REQUIRE(c.get_root() == n);
568 1 : }
569 1 : }
570 :
571 5 : CATCH_TEST_CASE("Compile user defined functions", "[compiler] [function]")
572 : {
573 5 : CATCH_START_SECTION("deg2rad() function and translate() CSS function")
574 : {
575 1 : std::stringstream ss;
576 : ss << "/* testing user defined functions */\n"
577 : << "body { angle : deg2rad( 32deg ) }\n"
578 : << "a b { transform: translate(12%, 0); }\n"
579 1 : << "/* @preserver test \"Compile User Functions\" */\n";
580 3 : csspp::position pos("test.css");
581 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
582 :
583 2 : csspp::parser p(l);
584 :
585 1 : csspp::node::pointer_t n(p.stylesheet());
586 :
587 : // no errors so far
588 1 : VERIFY_ERRORS("");
589 :
590 1 : csspp::compiler c;
591 1 : c.set_root(n);
592 1 : c.set_date_time_variables(csspp_test::get_now());
593 1 : c.clear_paths();
594 1 : c.add_path(csspp_test::get_script_path());
595 1 : c.add_path(csspp_test::get_version_script_path());
596 :
597 1 : c.compile(false);
598 :
599 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
600 :
601 1 : std::stringstream out;
602 1 : out << *n;
603 1 : VERIFY_TREES(out.str(),
604 :
605 : "LIST\n"
606 : + csspp_test::get_default_variables() +
607 : " COMPONENT_VALUE\n"
608 : " ARG\n"
609 : " IDENTIFIER \"body\"\n"
610 : " OPEN_CURLYBRACKET B:true\n"
611 : " DECLARATION \"angle\"\n"
612 : " ARG\n"
613 : " DECIMAL_NUMBER \"rad\" D:0.559\n"
614 : " COMPONENT_VALUE\n"
615 : " ARG\n"
616 : " IDENTIFIER \"a\"\n"
617 : " WHITESPACE\n"
618 : " IDENTIFIER \"b\"\n"
619 : " OPEN_CURLYBRACKET B:true\n"
620 : " DECLARATION \"transform\"\n"
621 : " ARG\n"
622 : " FUNCTION \"translate\"\n"
623 : " ARG\n"
624 : " PERCENT D:0.12\n"
625 : " ARG\n"
626 : " INTEGER \"\" I:0\n"
627 : " COMMENT \"@preserver test \"Compile User Functions\"\" I:1\n"
628 : + csspp_test::get_close_comment(true)
629 :
630 : );
631 :
632 : // no error left over
633 1 : VERIFY_ERRORS("");
634 :
635 1 : CATCH_REQUIRE(c.get_root() == n);
636 1 : }
637 5 : CATCH_END_SECTION()
638 :
639 5 : CATCH_START_SECTION("define an $undefined variable but no undefined() function")
640 : {
641 : // this is not invalid, until we check for all the CSS function names
642 1 : std::stringstream ss;
643 : ss << "/* testing user defined functions */\n"
644 : << "$zzzundefined: 12%;\n"
645 : << "body { angle : zzzundefined( 3rad ) }\n"
646 1 : << "/* @preserver test \"Compile User Functions\" */\n";
647 3 : csspp::position pos("test.css");
648 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
649 :
650 2 : csspp::parser p(l);
651 :
652 1 : csspp::node::pointer_t n(p.stylesheet());
653 :
654 : // no errors so far
655 1 : VERIFY_ERRORS("");
656 :
657 1 : csspp::compiler c;
658 1 : c.set_root(n);
659 1 : c.set_date_time_variables(csspp_test::get_now());
660 1 : c.clear_paths();
661 1 : c.add_path(csspp_test::get_script_path());
662 1 : c.add_path(csspp_test::get_version_script_path());
663 :
664 1 : c.compile(false);
665 :
666 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
667 :
668 1 : std::stringstream out;
669 1 : out << *n;
670 1 : VERIFY_TREES(out.str(),
671 :
672 : "LIST\n"
673 : + csspp_test::get_default_variables() +
674 : " V:zzzundefined\n"
675 : " LIST\n"
676 : " VARIABLE \"zzzundefined\"\n"
677 : " PERCENT D:0.12\n"
678 : " COMPONENT_VALUE\n"
679 : " ARG\n"
680 : " IDENTIFIER \"body\"\n"
681 : " OPEN_CURLYBRACKET B:true\n"
682 : " DECLARATION \"angle\"\n"
683 : " ARG\n"
684 : " FUNCTION \"zzzundefined\"\n"
685 : " ARG\n"
686 : " INTEGER \"rad\" I:3\n"
687 : " COMMENT \"@preserver test \"Compile User Functions\"\" I:1\n"
688 : + csspp_test::get_close_comment(true)
689 :
690 : );
691 :
692 : // no error left over
693 1 : VERIFY_ERRORS("");
694 :
695 1 : CATCH_REQUIRE(c.get_root() == n);
696 1 : }
697 5 : CATCH_END_SECTION()
698 :
699 5 : CATCH_START_SECTION("function with default parameters")
700 : {
701 : // this is not invalid, until we check for all the CSS function names
702 1 : std::stringstream ss;
703 : ss << "/* testing user defined functions */\n"
704 : << "body { color : mix(lightgrey, moccasin) }\n"
705 1 : << "/* @preserver test \"Compile User Functions\" */\n";
706 3 : csspp::position pos("test.css");
707 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
708 :
709 2 : csspp::parser p(l);
710 :
711 1 : csspp::node::pointer_t n(p.stylesheet());
712 :
713 : // no errors so far
714 1 : VERIFY_ERRORS("");
715 :
716 1 : csspp::compiler c;
717 1 : c.set_root(n);
718 1 : c.set_date_time_variables(csspp_test::get_now());
719 1 : c.clear_paths();
720 1 : c.add_path(csspp_test::get_script_path());
721 1 : c.add_path(csspp_test::get_version_script_path());
722 :
723 1 : c.compile(false);
724 :
725 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
726 :
727 1 : std::stringstream out;
728 1 : out << *n;
729 1 : VERIFY_TREES(out.str(),
730 :
731 : "LIST\n"
732 : + csspp_test::get_default_variables() +
733 : " COMPONENT_VALUE\n"
734 : " ARG\n"
735 : " IDENTIFIER \"body\"\n"
736 : " OPEN_CURLYBRACKET B:true\n"
737 : " DECLARATION \"color\"\n"
738 : " ARG\n"
739 : " COLOR H:ffc4dce9\n"
740 : " COMMENT \"@preserver test \"Compile User Functions\"\" I:1\n"
741 : + csspp_test::get_close_comment(true)
742 :
743 : );
744 :
745 : // no error left over
746 1 : VERIFY_ERRORS("");
747 :
748 1 : CATCH_REQUIRE(c.get_root() == n);
749 1 : }
750 5 : CATCH_END_SECTION()
751 :
752 5 : CATCH_START_SECTION("function with *complex* default parameter")
753 : {
754 : // this is not invalid, until we check for all the CSS function names
755 1 : std::stringstream ss;
756 : ss << "/* testing user defined functions */\n"
757 : << "@mixin zzz_my_func($normal, $complex: 3px 7% #ff39af) { @return 3; }\n"
758 : << "body { z-index : zzz_my_func('fromage') }\n"
759 1 : << "/* @preserver test \"Compile User Functions\" */\n";
760 3 : csspp::position pos("test.css");
761 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
762 :
763 2 : csspp::parser p(l);
764 :
765 1 : csspp::node::pointer_t n(p.stylesheet());
766 :
767 : // no errors so far
768 1 : VERIFY_ERRORS("");
769 :
770 1 : csspp::compiler c;
771 1 : c.set_root(n);
772 1 : c.set_date_time_variables(csspp_test::get_now());
773 1 : c.clear_paths();
774 1 : c.add_path(csspp_test::get_script_path());
775 1 : c.add_path(csspp_test::get_version_script_path());
776 :
777 1 : c.compile(false);
778 :
779 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
780 :
781 1 : std::stringstream out;
782 1 : out << *n;
783 1 : VERIFY_TREES(out.str(),
784 :
785 : "LIST\n"
786 : + csspp_test::get_default_variables() +
787 : " V:zzz_my_func\n"
788 : " LIST\n"
789 : " FUNCTION \"zzz_my_func\"\n"
790 : " ARG\n"
791 : " VARIABLE \"normal\"\n"
792 : " ARG\n"
793 : " VARIABLE \"complex\"\n"
794 : " INTEGER \"px\" I:3\n"
795 : " WHITESPACE\n"
796 : " PERCENT D:0.07\n"
797 : " WHITESPACE\n"
798 : " HASH \"ff39af\"\n"
799 : " OPEN_CURLYBRACKET B:true\n"
800 : " COMPONENT_VALUE\n"
801 : " AT_KEYWORD \"return\" I:0\n"
802 : " INTEGER \"\" I:3\n"
803 : " COMPONENT_VALUE\n"
804 : " ARG\n"
805 : " IDENTIFIER \"body\"\n"
806 : " OPEN_CURLYBRACKET B:true\n"
807 : " DECLARATION \"z-index\"\n"
808 : " ARG\n"
809 : " INTEGER \"\" I:3\n"
810 : " COMMENT \"@preserver test \"Compile User Functions\"\" I:1\n"
811 : + csspp_test::get_close_comment(true)
812 :
813 : );
814 :
815 : // no error left over
816 1 : VERIFY_ERRORS("");
817 :
818 1 : CATCH_REQUIRE(c.get_root() == n);
819 1 : }
820 5 : CATCH_END_SECTION()
821 :
822 5 : CATCH_START_SECTION("function called with a *complex* parameter")
823 : {
824 : // this is not invalid, until we check for all the CSS function names
825 1 : std::stringstream ss;
826 : ss << "/* testing user defined functions */\n"
827 : << "@mixin zzz_my_func($complex) { @return 3; }\n"
828 : << "body { z-index : zzz_my_func('fromage' 3px rational) }\n"
829 1 : << "/* @preserver test \"Compile User Functions\" */\n";
830 3 : csspp::position pos("test.css");
831 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
832 :
833 2 : csspp::parser p(l);
834 :
835 1 : csspp::node::pointer_t n(p.stylesheet());
836 :
837 : // no errors so far
838 1 : VERIFY_ERRORS("");
839 :
840 1 : csspp::compiler c;
841 1 : c.set_root(n);
842 1 : c.set_date_time_variables(csspp_test::get_now());
843 1 : c.clear_paths();
844 1 : c.add_path(csspp_test::get_script_path());
845 1 : c.add_path(csspp_test::get_version_script_path());
846 :
847 1 : c.compile(false);
848 :
849 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
850 :
851 1 : std::stringstream out;
852 1 : out << *n;
853 1 : VERIFY_TREES(out.str(),
854 :
855 : "LIST\n"
856 : + csspp_test::get_default_variables() +
857 : " V:zzz_my_func\n"
858 : " LIST\n"
859 : " FUNCTION \"zzz_my_func\"\n"
860 : " ARG\n"
861 : " VARIABLE \"complex\"\n"
862 : " OPEN_CURLYBRACKET B:true\n"
863 : " COMPONENT_VALUE\n"
864 : " AT_KEYWORD \"return\" I:0\n"
865 : " INTEGER \"\" I:3\n"
866 : " COMPONENT_VALUE\n"
867 : " ARG\n"
868 : " IDENTIFIER \"body\"\n"
869 : " OPEN_CURLYBRACKET B:true\n"
870 : " DECLARATION \"z-index\"\n"
871 : " ARG\n"
872 : " INTEGER \"\" I:3\n"
873 : " COMMENT \"@preserver test \"Compile User Functions\"\" I:1\n"
874 : + csspp_test::get_close_comment(true)
875 :
876 : );
877 :
878 : // no error left over
879 1 : VERIFY_ERRORS("");
880 :
881 1 : CATCH_REQUIRE(c.get_root() == n);
882 1 : }
883 5 : CATCH_END_SECTION()
884 5 : }
885 :
886 4 : CATCH_TEST_CASE("Compile invalid declaration in link with user defined functions", "[compiler] [invalid] [function]")
887 : {
888 4 : CATCH_START_SECTION("attempt to call a function with an invalid definition")
889 : {
890 1 : std::stringstream ss;
891 : ss << "/* testing user defined functions */\n"
892 : << "@mixin my_func($good, bad) { @return 3; }\n"
893 : << "body { angle : my_func( 32deg, -3px ) }\n"
894 1 : << "/* @preserver test \"Compile Invalid Functions\" */\n";
895 3 : csspp::position pos("test.css");
896 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
897 :
898 2 : csspp::parser p(l);
899 :
900 1 : csspp::node::pointer_t n(p.stylesheet());
901 :
902 : // no errors so far
903 1 : VERIFY_ERRORS("");
904 :
905 1 : csspp::compiler c;
906 1 : c.set_root(n);
907 1 : c.set_date_time_variables(csspp_test::get_now());
908 1 : c.clear_paths();
909 1 : c.add_path(csspp_test::get_script_path());
910 1 : c.add_path(csspp_test::get_version_script_path());
911 :
912 1 : c.compile(false);
913 :
914 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
915 :
916 : // no error left over
917 1 : VERIFY_ERRORS("test.css(2): error: function declarations expect variables for each of their arguments, not a IDENTIFIER.\n");
918 :
919 1 : CATCH_REQUIRE(c.get_root() == n);
920 1 : }
921 4 : CATCH_END_SECTION()
922 :
923 4 : CATCH_START_SECTION("attempt to call a function with a missing argument")
924 : {
925 1 : std::stringstream ss;
926 : ss << "/* testing user defined functions */\n"
927 : << "body { color : desaturate( white ) }\n"
928 1 : << "/* @preserver test \"Compile Invalid Functions\" */\n";
929 3 : csspp::position pos("test.css");
930 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
931 :
932 2 : csspp::parser p(l);
933 :
934 1 : csspp::node::pointer_t n(p.stylesheet());
935 :
936 : // no errors so far
937 1 : VERIFY_ERRORS("");
938 :
939 1 : csspp::compiler c;
940 1 : c.set_root(n);
941 1 : c.set_date_time_variables(csspp_test::get_now());
942 1 : c.clear_paths();
943 1 : c.add_path(csspp_test::get_script_path());
944 1 : c.add_path(csspp_test::get_version_script_path());
945 :
946 1 : c.compile(false);
947 :
948 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
949 :
950 : // no error left over
951 1 : VERIFY_ERRORS("scripts/system/functions.scss(39): error: missing function variable named \"percent\" when calling desaturate();.\n");
952 :
953 1 : CATCH_REQUIRE(c.get_root() == n);
954 1 : }
955 4 : CATCH_END_SECTION()
956 :
957 4 : CATCH_START_SECTION("@return is empty")
958 : {
959 1 : std::stringstream ss;
960 : ss << "/* testing user defined functions */\n"
961 : << "@mixin zzz_my_func() { @return { nothing; } }\n"
962 : << "body { color : zzz_my_func( ) }\n"
963 1 : << "/* @preserver test \"Compile Invalid Functions\" */\n";
964 3 : csspp::position pos("test.css");
965 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
966 :
967 2 : csspp::parser p(l);
968 :
969 1 : csspp::node::pointer_t n(p.stylesheet());
970 :
971 : // no errors so far
972 1 : VERIFY_ERRORS("");
973 :
974 1 : csspp::compiler c;
975 1 : c.set_root(n);
976 1 : c.set_date_time_variables(csspp_test::get_now());
977 1 : c.clear_paths();
978 1 : c.add_path(csspp_test::get_script_path());
979 1 : c.add_path(csspp_test::get_version_script_path());
980 :
981 1 : c.compile(false);
982 :
983 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
984 :
985 : // no error left over
986 1 : VERIFY_ERRORS("test.css(2): error: @return must be followed by a valid expression.\n");
987 :
988 1 : CATCH_REQUIRE(c.get_root() == n);
989 1 : }
990 4 : CATCH_END_SECTION()
991 :
992 4 : CATCH_START_SECTION("@return with an invalid expression")
993 : {
994 1 : std::stringstream ss;
995 : ss << "/* testing user defined functions */\n"
996 : << "@mixin zzz_my_func() { @return -; }\n"
997 : << "body { color : zzz_my_func( ) }\n"
998 1 : << "/* @preserver test \"Compile Invalid Functions\" */\n";
999 3 : csspp::position pos("test.css");
1000 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
1001 :
1002 2 : csspp::parser p(l);
1003 :
1004 1 : csspp::node::pointer_t n(p.stylesheet());
1005 :
1006 : // no errors so far
1007 1 : VERIFY_ERRORS("");
1008 :
1009 1 : csspp::compiler c;
1010 1 : c.set_root(n);
1011 1 : c.set_date_time_variables(csspp_test::get_now());
1012 1 : c.clear_paths();
1013 1 : c.add_path(csspp_test::get_script_path());
1014 1 : c.add_path(csspp_test::get_version_script_path());
1015 :
1016 1 : c.compile(false);
1017 :
1018 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
1019 :
1020 : // no error left over
1021 1 : VERIFY_ERRORS("test.css(2): error: unsupported type EOF_TOKEN as a unary expression token.\n");
1022 :
1023 1 : CATCH_REQUIRE(c.get_root() == n);
1024 1 : }
1025 4 : CATCH_END_SECTION()
1026 :
1027 4 : VERIFY_ERRORS("");
1028 4 : }
1029 :
1030 1 : CATCH_TEST_CASE("Check all argify", "[compiler] [stylesheet]")
1031 : {
1032 : // valid argify with/without spaces
1033 : {
1034 1 : std::stringstream ss;
1035 : ss << "a,b{color:red}\n"
1036 : << "a, b{color:hsl(0,100%,50%)}\n"
1037 : << "a,b ,c{color:rgb(255,0,0)}\n"
1038 : << "a , b,c{color:hsla(0,100%,50%,1)}\n"
1039 : << "a{color:rgba(255,0,0,1)}\n"
1040 : << "a {color:red}\n"
1041 1 : << "a,b {color:red}\n"
1042 : ;
1043 3 : csspp::position pos("test.css");
1044 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
1045 :
1046 2 : csspp::parser p(l);
1047 :
1048 1 : csspp::node::pointer_t n(p.stylesheet());
1049 :
1050 : // no errors so far
1051 1 : VERIFY_ERRORS("");
1052 :
1053 1 : csspp::compiler c;
1054 1 : c.set_root(n);
1055 1 : c.clear_paths();
1056 1 : c.add_path(csspp_test::get_script_path());
1057 1 : c.add_path(csspp_test::get_version_script_path());
1058 :
1059 1 : c.compile(true);
1060 :
1061 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
1062 :
1063 1 : std::stringstream out;
1064 1 : out << *n;
1065 1 : VERIFY_TREES(out.str(),
1066 :
1067 : "LIST\n"
1068 : " COMPONENT_VALUE\n"
1069 : " ARG\n"
1070 : " IDENTIFIER \"a\"\n"
1071 : " ARG\n"
1072 : " IDENTIFIER \"b\"\n"
1073 : " OPEN_CURLYBRACKET B:true\n"
1074 : " DECLARATION \"color\"\n"
1075 : " ARG\n"
1076 : " COLOR H:ff0000ff\n"
1077 : " COMPONENT_VALUE\n"
1078 : " ARG\n"
1079 : " IDENTIFIER \"a\"\n"
1080 : " ARG\n"
1081 : " IDENTIFIER \"b\"\n"
1082 : " OPEN_CURLYBRACKET B:true\n"
1083 : " DECLARATION \"color\"\n"
1084 : " ARG\n"
1085 : " COLOR H:ff0000ff\n"
1086 : " COMPONENT_VALUE\n"
1087 : " ARG\n"
1088 : " IDENTIFIER \"a\"\n"
1089 : " ARG\n"
1090 : " IDENTIFIER \"b\"\n"
1091 : " ARG\n"
1092 : " IDENTIFIER \"c\"\n"
1093 : " OPEN_CURLYBRACKET B:true\n"
1094 : " DECLARATION \"color\"\n"
1095 : " ARG\n"
1096 : " COLOR H:ff0000ff\n"
1097 : " COMPONENT_VALUE\n"
1098 : " ARG\n"
1099 : " IDENTIFIER \"a\"\n"
1100 : " ARG\n"
1101 : " IDENTIFIER \"b\"\n"
1102 : " ARG\n"
1103 : " IDENTIFIER \"c\"\n"
1104 : " OPEN_CURLYBRACKET B:true\n"
1105 : " DECLARATION \"color\"\n"
1106 : " ARG\n"
1107 : " COLOR H:ff0000ff\n"
1108 : " COMPONENT_VALUE\n"
1109 : " ARG\n"
1110 : " IDENTIFIER \"a\"\n"
1111 : " OPEN_CURLYBRACKET B:true\n"
1112 : " DECLARATION \"color\"\n"
1113 : " ARG\n"
1114 : " COLOR H:ff0000ff\n"
1115 : " COMPONENT_VALUE\n"
1116 : " ARG\n"
1117 : " IDENTIFIER \"a\"\n"
1118 : " OPEN_CURLYBRACKET B:true\n"
1119 : " DECLARATION \"color\"\n"
1120 : " ARG\n"
1121 : " COLOR H:ff0000ff\n"
1122 : " COMPONENT_VALUE\n"
1123 : " ARG\n"
1124 : " IDENTIFIER \"a\"\n"
1125 : " ARG\n"
1126 : " IDENTIFIER \"b\"\n"
1127 : " OPEN_CURLYBRACKET B:true\n"
1128 : " DECLARATION \"color\"\n"
1129 : " ARG\n"
1130 : " COLOR H:ff0000ff\n"
1131 :
1132 : );
1133 :
1134 : // no error left over
1135 1 : VERIFY_ERRORS("");
1136 :
1137 1 : CATCH_REQUIRE(c.get_root() == n);
1138 1 : }
1139 :
1140 : // now check declarations with multiple entries like text-shadow
1141 : {
1142 1 : std::stringstream ss;
1143 : ss << "a, b\n"
1144 : << "{\n"
1145 : << " text-shadow: 1px 3px 2px #f0e933, 7px 1px 5px #88ff45;\n"
1146 : << " box-shadow: 2.5em 4.3em 1.25em #ffee33, 7.3px 1.25px 4.11px #88ff55, 3.32em 2.45em 4.11em #ee5599;\n"
1147 1 : << "}\n";
1148 3 : csspp::position pos("test.css");
1149 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
1150 :
1151 2 : csspp::parser p(l);
1152 :
1153 1 : csspp::node::pointer_t n(p.stylesheet());
1154 :
1155 : // no errors so far
1156 1 : VERIFY_ERRORS("");
1157 :
1158 1 : csspp::compiler c;
1159 1 : c.set_root(n);
1160 1 : c.clear_paths();
1161 1 : c.add_path(csspp_test::get_script_path());
1162 1 : c.add_path(csspp_test::get_version_script_path());
1163 :
1164 1 : c.compile(true);
1165 :
1166 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
1167 :
1168 1 : std::stringstream out;
1169 1 : out << *n;
1170 1 : VERIFY_TREES(out.str(),
1171 :
1172 : "LIST\n"
1173 : " COMPONENT_VALUE\n"
1174 : " ARG\n"
1175 : " IDENTIFIER \"a\"\n"
1176 : " ARG\n"
1177 : " IDENTIFIER \"b\"\n"
1178 : " OPEN_CURLYBRACKET B:true\n"
1179 : " LIST\n"
1180 : " DECLARATION \"text-shadow\"\n"
1181 : " ARG\n"
1182 : " INTEGER \"px\" I:1\n"
1183 : " WHITESPACE\n"
1184 : " INTEGER \"px\" I:3\n"
1185 : " WHITESPACE\n"
1186 : " INTEGER \"px\" I:2\n"
1187 : " WHITESPACE\n"
1188 : " COLOR H:ff33e9f0\n"
1189 : " ARG\n"
1190 : " INTEGER \"px\" I:7\n"
1191 : " WHITESPACE\n"
1192 : " INTEGER \"px\" I:1\n"
1193 : " WHITESPACE\n"
1194 : " INTEGER \"px\" I:5\n"
1195 : " WHITESPACE\n"
1196 : " COLOR H:ff45ff88\n"
1197 : " DECLARATION \"box-shadow\"\n"
1198 : " ARG\n"
1199 : " DECIMAL_NUMBER \"em\" D:2.5\n"
1200 : " WHITESPACE\n"
1201 : " DECIMAL_NUMBER \"em\" D:4.3\n"
1202 : " WHITESPACE\n"
1203 : " DECIMAL_NUMBER \"em\" D:1.25\n"
1204 : " WHITESPACE\n"
1205 : " COLOR H:ff33eeff\n"
1206 : " ARG\n"
1207 : " DECIMAL_NUMBER \"px\" D:7.3\n"
1208 : " WHITESPACE\n"
1209 : " DECIMAL_NUMBER \"px\" D:1.25\n"
1210 : " WHITESPACE\n"
1211 : " DECIMAL_NUMBER \"px\" D:4.11\n"
1212 : " WHITESPACE\n"
1213 : " COLOR H:ff55ff88\n"
1214 : " ARG\n"
1215 : " DECIMAL_NUMBER \"em\" D:3.32\n"
1216 : " WHITESPACE\n"
1217 : " DECIMAL_NUMBER \"em\" D:2.45\n"
1218 : " WHITESPACE\n"
1219 : " DECIMAL_NUMBER \"em\" D:4.11\n"
1220 : " WHITESPACE\n"
1221 : " COLOR H:ff9955ee\n"
1222 :
1223 : );
1224 :
1225 : // no error left over
1226 1 : VERIFY_ERRORS("");
1227 :
1228 1 : CATCH_REQUIRE(c.get_root() == n);
1229 1 : }
1230 1 : }
1231 :
1232 1 : CATCH_TEST_CASE("Invalid arguments", "[compiler] [invalid]")
1233 : {
1234 : // A starting comma is illegal
1235 : {
1236 1 : std::stringstream ss;
1237 1 : ss << ",a{color:red}\n";
1238 3 : csspp::position pos("test.css");
1239 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
1240 :
1241 2 : csspp::parser p(l);
1242 :
1243 1 : csspp::node::pointer_t n(p.stylesheet());
1244 :
1245 : // no errors so far
1246 1 : VERIFY_ERRORS("");
1247 :
1248 1 : csspp::compiler c;
1249 1 : c.set_root(n);
1250 1 : c.clear_paths();
1251 1 : c.add_path(csspp_test::get_script_path());
1252 1 : c.add_path(csspp_test::get_version_script_path());
1253 :
1254 1 : c.compile(true);
1255 :
1256 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
1257 :
1258 : // no error left over
1259 1 : VERIFY_ERRORS("test.css(1): error: dangling comma at the beginning of a list of arguments or selectors.\n");
1260 :
1261 1 : CATCH_REQUIRE(c.get_root() == n);
1262 1 : }
1263 :
1264 : // An ending comma is illegal
1265 : {
1266 1 : std::stringstream ss;
1267 1 : ss << "a,{color:red}\n";
1268 3 : csspp::position pos("test.css");
1269 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
1270 :
1271 2 : csspp::parser p(l);
1272 :
1273 1 : csspp::node::pointer_t n(p.stylesheet());
1274 :
1275 : // no errors so far
1276 1 : VERIFY_ERRORS("");
1277 :
1278 1 : csspp::compiler c;
1279 1 : c.set_root(n);
1280 1 : c.clear_paths();
1281 1 : c.add_path(csspp_test::get_script_path());
1282 1 : c.add_path(csspp_test::get_version_script_path());
1283 :
1284 1 : c.compile(true);
1285 :
1286 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
1287 :
1288 : // no error left over
1289 1 : VERIFY_ERRORS("test.css(1): error: dangling comma at the end of a list of arguments or selectors.\n");
1290 :
1291 1 : CATCH_REQUIRE(c.get_root() == n);
1292 1 : }
1293 :
1294 : // Two commas in a row is illegal
1295 : {
1296 1 : std::stringstream ss;
1297 1 : ss << "a,,b{color:red}\n";
1298 3 : csspp::position pos("test.css");
1299 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
1300 :
1301 2 : csspp::parser p(l);
1302 :
1303 1 : csspp::node::pointer_t n(p.stylesheet());
1304 :
1305 : // no errors so far
1306 1 : VERIFY_ERRORS("");
1307 :
1308 1 : csspp::compiler c;
1309 1 : c.set_root(n);
1310 1 : c.clear_paths();
1311 1 : c.add_path(csspp_test::get_script_path());
1312 1 : c.add_path(csspp_test::get_version_script_path());
1313 :
1314 1 : c.compile(true);
1315 :
1316 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
1317 :
1318 : // no error left over
1319 1 : VERIFY_ERRORS("test.css(1): error: two commas in a row are invalid in a list of arguments or selectors.\n");
1320 :
1321 1 : CATCH_REQUIRE(c.get_root() == n);
1322 1 : }
1323 :
1324 : // Just a comma is illegal
1325 : {
1326 1 : std::stringstream ss;
1327 1 : ss << ",{color:red}\n";
1328 3 : csspp::position pos("test.css");
1329 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
1330 :
1331 2 : csspp::parser p(l);
1332 :
1333 1 : csspp::node::pointer_t n(p.stylesheet());
1334 :
1335 : // no errors so far
1336 1 : VERIFY_ERRORS("");
1337 :
1338 1 : csspp::compiler c;
1339 1 : c.set_root(n);
1340 1 : c.clear_paths();
1341 1 : c.add_path(csspp_test::get_script_path());
1342 1 : c.add_path(csspp_test::get_version_script_path());
1343 :
1344 1 : c.compile(true);
1345 :
1346 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
1347 :
1348 : // no error left over
1349 1 : VERIFY_ERRORS("test.css(1): error: dangling comma at the beginning of a list of arguments or selectors.\n");
1350 :
1351 1 : CATCH_REQUIRE(c.get_root() == n);
1352 1 : }
1353 :
1354 : // A repeated hash
1355 : {
1356 1 : std::stringstream ss;
1357 1 : ss << "#color div #color { color : red }";
1358 3 : csspp::position pos("test.css");
1359 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
1360 :
1361 2 : csspp::parser p(l);
1362 :
1363 1 : csspp::node::pointer_t n(p.stylesheet());
1364 :
1365 : // no errors so far
1366 1 : VERIFY_ERRORS("");
1367 :
1368 1 : csspp::compiler c;
1369 1 : c.set_root(n);
1370 1 : c.clear_paths();
1371 1 : c.add_path(csspp_test::get_script_path());
1372 1 : c.add_path(csspp_test::get_version_script_path());
1373 :
1374 1 : c.compile(true);
1375 :
1376 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
1377 :
1378 1 : VERIFY_ERRORS("test.css(1): error: found #color twice in selector: \"#color div #color\".\n");
1379 :
1380 1 : CATCH_REQUIRE(c.get_root() == n);
1381 1 : }
1382 :
1383 : // rules with !important at the wrong place
1384 : {
1385 1 : std::stringstream ss;
1386 1 : ss << "div.blackness { color: !important red }";
1387 3 : csspp::position pos("test.css");
1388 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
1389 :
1390 2 : csspp::parser p(l);
1391 :
1392 1 : csspp::node::pointer_t n(p.stylesheet());
1393 :
1394 : // no errors so far
1395 1 : VERIFY_ERRORS("");
1396 :
1397 1 : csspp::compiler c;
1398 1 : c.set_root(n);
1399 1 : c.set_date_time_variables(csspp_test::get_now());
1400 1 : c.clear_paths();
1401 1 : c.add_path(csspp_test::get_script_path());
1402 1 : c.add_path(csspp_test::get_version_script_path());
1403 :
1404 1 : c.compile(false);
1405 :
1406 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
1407 :
1408 1 : VERIFY_ERRORS("test.css(1): warning: A special flag, !important in this case, must only appear at the end of a declaration.\n");
1409 :
1410 1 : std::stringstream out;
1411 1 : out << *n;
1412 1 : VERIFY_TREES(out.str(),
1413 :
1414 : "LIST\n"
1415 : + csspp_test::get_default_variables() +
1416 : " COMPONENT_VALUE\n"
1417 : " ARG\n"
1418 : " IDENTIFIER \"div\"\n"
1419 : " PERIOD\n"
1420 : " IDENTIFIER \"blackness\"\n"
1421 : " OPEN_CURLYBRACKET B:true\n"
1422 : " DECLARATION \"color\" F:important\n"
1423 : " ARG\n"
1424 : " COLOR H:ff0000ff\n"
1425 : + csspp_test::get_close_comment(true)
1426 :
1427 : );
1428 :
1429 : // no error left over
1430 1 : VERIFY_ERRORS("");
1431 :
1432 1 : CATCH_REQUIRE(c.get_root() == n);
1433 1 : }
1434 :
1435 : // no error left over
1436 1 : VERIFY_ERRORS("");
1437 1 : }
1438 :
1439 1 : CATCH_TEST_CASE("Selector attribute tests", "[compiler] [stylesheet] [attribute]")
1440 : {
1441 1 : char const * op[] =
1442 : {
1443 : "=", "EQUAL",
1444 : "~=", "INCLUDE_MATCH",
1445 : "^=", "PREFIX_MATCH",
1446 : "$=", "SUFFIX_MATCH",
1447 : "*=", "SUBSTRING_MATCH",
1448 : "|=", "DASH_MATCH"
1449 : };
1450 1 : char const * val[] =
1451 : {
1452 : "c", "IDENTIFIER \"c\"",
1453 : "' c '", "STRING \" c \"",
1454 : "123", "INTEGER \"\" I:123",
1455 : "1.23", "DECIMAL_NUMBER \"\" D:1.23"
1456 : };
1457 :
1458 : // TODO: rewrite that one to use a few less lines
1459 7 : for(size_t i(0); i < sizeof(op) / sizeof(op[0]); i += 2)
1460 : {
1461 30 : for(size_t j(0); j < sizeof(val) / sizeof(val[0]); j += 2)
1462 : {
1463 408 : for(size_t k(0); k < (1 << 4); ++k)
1464 : {
1465 : // a[b op c | 'str' | 123 | 1.23] {color:red}
1466 384 : std::stringstream ss;
1467 384 : ss << "a[";
1468 384 : if((k & (1 << 0)) != 0)
1469 : {
1470 192 : ss << " ";
1471 : }
1472 384 : ss << "b";
1473 384 : if((k & (1 << 1)) != 0)
1474 : {
1475 192 : ss << " ";
1476 : }
1477 384 : ss << op[i];
1478 384 : if((k & (1 << 2)) != 0)
1479 : {
1480 192 : ss << " ";
1481 : }
1482 384 : ss << val[j];
1483 384 : if((k & (1 << 3)) != 0)
1484 : {
1485 192 : ss << " ";
1486 : }
1487 : ss << "]"
1488 768 : << (rand() % 2 == 0 ? " " : "")
1489 : << "{"
1490 768 : << (rand() % 2 == 0 ? " " : "")
1491 : << "color:"
1492 768 : << (rand() % 2 == 0 ? "rgb(255,0,0)" : "rgba(255,0,0,1.0)")
1493 768 : << (rand() % 2 == 0 ? " " : "")
1494 384 : << "}\n";
1495 1152 : csspp::position pos("test.css");
1496 384 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
1497 :
1498 768 : csspp::parser p(l);
1499 :
1500 384 : csspp::node::pointer_t n(p.stylesheet());
1501 :
1502 : // no errors so far
1503 384 : VERIFY_ERRORS("");
1504 :
1505 384 : csspp::compiler c;
1506 384 : c.set_root(n);
1507 384 : c.clear_paths();
1508 384 : c.add_path(csspp_test::get_script_path());
1509 384 : c.add_path(csspp_test::get_version_script_path());
1510 :
1511 384 : c.compile(true);
1512 :
1513 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
1514 :
1515 384 : VERIFY_ERRORS("");
1516 :
1517 384 : std::stringstream out;
1518 384 : out << *n;
1519 384 : std::stringstream expected;
1520 : expected <<
1521 : "LIST\n"
1522 : " COMPONENT_VALUE\n"
1523 : " ARG\n"
1524 : " IDENTIFIER \"a\"\n"
1525 : " OPEN_SQUAREBRACKET\n"
1526 : " IDENTIFIER \"b\"\n"
1527 384 : << " " << op[i + 1] << "\n"
1528 384 : << " " << val[j + 1] << "\n"
1529 : " OPEN_CURLYBRACKET B:true\n"
1530 : " DECLARATION \"color\"\n"
1531 : " ARG\n"
1532 384 : " COLOR H:ff0000ff\n"
1533 : ;
1534 384 : VERIFY_TREES(out.str(), expected.str());
1535 :
1536 384 : CATCH_REQUIRE(c.get_root() == n);
1537 384 : }
1538 : }
1539 : }
1540 :
1541 : // a[b!=c]
1542 5 : for(size_t j(0); j < sizeof(val) / sizeof(val[0]); j += 2)
1543 : {
1544 68 : for(size_t k(0); k < (1 << 4); ++k)
1545 : {
1546 64 : std::stringstream ss;
1547 64 : ss << "a[";
1548 64 : if((k & (1 << 0)) != 0)
1549 : {
1550 32 : ss << " ";
1551 : }
1552 64 : ss << "b";
1553 64 : if((k & (1 << 1)) != 0)
1554 : {
1555 32 : ss << " ";
1556 : }
1557 64 : ss << "!=";
1558 64 : if((k & (1 << 2)) != 0)
1559 : {
1560 32 : ss << " ";
1561 : }
1562 64 : ss << val[j];
1563 64 : if((k & (1 << 3)) != 0)
1564 : {
1565 32 : ss << " ";
1566 : }
1567 : ss << "]"
1568 128 : << (rand() % 2 == 0 ? " " : "")
1569 : << "{"
1570 128 : << (rand() % 2 == 0 ? " " : "")
1571 : << "color:red"
1572 128 : << (rand() % 2 == 0 ? " " : "")
1573 64 : << "}\n";
1574 192 : csspp::position pos("test.css");
1575 64 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
1576 :
1577 128 : csspp::parser p(l);
1578 :
1579 64 : csspp::node::pointer_t n(p.stylesheet());
1580 :
1581 : // no errors so far
1582 64 : VERIFY_ERRORS("");
1583 :
1584 64 : csspp::compiler c;
1585 64 : c.set_root(n);
1586 64 : c.clear_paths();
1587 64 : c.add_path(csspp_test::get_script_path());
1588 64 : c.add_path(csspp_test::get_version_script_path());
1589 :
1590 64 : c.compile(true);
1591 :
1592 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
1593 :
1594 64 : VERIFY_ERRORS("");
1595 :
1596 64 : std::stringstream out;
1597 64 : out << *n;
1598 64 : std::stringstream expected;
1599 : expected <<
1600 : "LIST\n"
1601 : " COMPONENT_VALUE\n"
1602 : " ARG\n"
1603 : " IDENTIFIER \"a\"\n"
1604 : " COLON\n"
1605 : " FUNCTION \"not\"\n"
1606 : " OPEN_SQUAREBRACKET\n"
1607 : " IDENTIFIER \"b\"\n"
1608 : " EQUAL\n"
1609 64 : " " << val[j + 1] << "\n"
1610 : " OPEN_CURLYBRACKET B:true\n"
1611 : " DECLARATION \"color\"\n"
1612 : " ARG\n"
1613 64 : " COLOR H:ff0000ff\n"
1614 : ;
1615 64 : VERIFY_TREES(out.str(), expected.str());
1616 :
1617 64 : CATCH_REQUIRE(c.get_root() == n);
1618 64 : }
1619 : }
1620 :
1621 : // Test with just 'b' and various spaces combinations
1622 5 : for(size_t k(0); k < (1 << 2); ++k)
1623 : {
1624 : // a[b] {color:red}
1625 4 : std::stringstream ss;
1626 4 : ss << "a[";
1627 4 : if((k & (1 << 0)) != 0)
1628 : {
1629 2 : ss << " ";
1630 : }
1631 4 : ss << "b";
1632 4 : if((k & (1 << 1)) != 0)
1633 : {
1634 2 : ss << " ";
1635 : }
1636 : ss << "]"
1637 8 : << (rand() % 2 == 0 ? " " : "")
1638 : << "{"
1639 8 : << (rand() % 2 == 0 ? " " : "")
1640 : << "color:red"
1641 8 : << (rand() % 2 == 0 ? " " : "")
1642 4 : << "}\n";
1643 12 : csspp::position pos("test.css");
1644 4 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
1645 :
1646 8 : csspp::parser p(l);
1647 :
1648 4 : csspp::node::pointer_t n(p.stylesheet());
1649 :
1650 : // no errors so far
1651 4 : VERIFY_ERRORS("");
1652 :
1653 4 : csspp::compiler c;
1654 4 : c.set_root(n);
1655 4 : c.clear_paths();
1656 4 : c.add_path(csspp_test::get_script_path());
1657 4 : c.add_path(csspp_test::get_version_script_path());
1658 :
1659 4 : c.compile(true);
1660 :
1661 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
1662 :
1663 4 : VERIFY_ERRORS("");
1664 :
1665 4 : std::stringstream out;
1666 4 : out << *n;
1667 4 : std::stringstream expected;
1668 : expected <<
1669 : "LIST\n"
1670 : " COMPONENT_VALUE\n"
1671 : " ARG\n"
1672 : " IDENTIFIER \"a\"\n"
1673 : " OPEN_SQUAREBRACKET\n"
1674 : " IDENTIFIER \"b\"\n"
1675 : " OPEN_CURLYBRACKET B:true\n"
1676 : " DECLARATION \"color\"\n"
1677 : " ARG\n"
1678 4 : " COLOR H:ff0000ff\n"
1679 : ;
1680 4 : VERIFY_TREES(out.str(), expected.str());
1681 :
1682 4 : CATCH_REQUIRE(c.get_root() == n);
1683 4 : }
1684 1 : }
1685 :
1686 6 : CATCH_TEST_CASE("Invalid attributes", "[compiler] [invalid]")
1687 : {
1688 : // attribute name cannot be an integer, decimal number, opening
1689 : // brackets or parenthesis, delimiter, etc. only an identifier
1690 6 : CATCH_START_SECTION("Missing operator or value")
1691 : {
1692 1 : char const * invalid_value[] =
1693 : {
1694 : "123",
1695 : "1.23",
1696 : "'1.23'",
1697 : "1.23%",
1698 : "(b)",
1699 : "[b]",
1700 : "{b}",
1701 : "+b",
1702 : //"@b",
1703 : //"<!--",
1704 : //"-->",
1705 : //")",
1706 : //"}",
1707 : ",b,",
1708 : "/* @preserve this comment */",
1709 : "|=b",
1710 : "/b",
1711 : "$ b",
1712 : "=b",
1713 : "!b",
1714 : "b(1)",
1715 : ">b",
1716 : "#123",
1717 : "~=b",
1718 : "*b",
1719 : ".top",
1720 : "%name",
1721 : "~b",
1722 : "&b",
1723 : "|b",
1724 : //";b",
1725 : };
1726 :
1727 26 : for(auto iv : invalid_value)
1728 : {
1729 25 : std::stringstream ss;
1730 25 : ss << "a[" << iv << "]{color:red}\n";
1731 75 : csspp::position pos("test.css");
1732 : //std::cerr << "Test <<<" << ss.str() << ">>>\n";
1733 25 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
1734 :
1735 50 : csspp::parser p(l);
1736 :
1737 25 : csspp::node::pointer_t n(p.stylesheet());
1738 :
1739 : // no errors so far
1740 25 : VERIFY_ERRORS("");
1741 :
1742 25 : csspp::compiler c;
1743 25 : c.set_root(n);
1744 25 : c.clear_paths();
1745 25 : c.add_path(csspp_test::get_script_path());
1746 25 : c.add_path(csspp_test::get_version_script_path());
1747 :
1748 25 : c.compile(true);
1749 :
1750 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
1751 :
1752 25 : VERIFY_ERRORS("test.css(1): error: an attribute selector expects to first find an identifier.\n");
1753 :
1754 25 : CATCH_REQUIRE(c.get_root() == n);
1755 25 : }
1756 : }
1757 6 : CATCH_END_SECTION()
1758 :
1759 : // attribute only accept a very few binary operators: =, |=, ~=, $=, ^=, *=
1760 : // anything else is an error (including another identifier)
1761 6 : CATCH_START_SECTION("Not an attribute operator")
1762 : {
1763 1 : char const * invalid_value[] =
1764 : {
1765 : "identifier-too",
1766 : "123",
1767 : "1.23",
1768 : "'1.23'",
1769 : "1.23%",
1770 : "(b)",
1771 : "[b]",
1772 : //"{b}", -- causes parser/lexer problems at this time... not too sure whether that's normal though
1773 : "+",
1774 : ",",
1775 : "/* @preserve this comment */",
1776 : "/",
1777 : "$",
1778 : "!",
1779 : ">",
1780 : ">=",
1781 : "<=",
1782 : "<",
1783 : ":=",
1784 : "?",
1785 : "&&",
1786 : "#123",
1787 : "*",
1788 : "**",
1789 : ".top",
1790 : "%name",
1791 : "~",
1792 : "&",
1793 : "|",
1794 : "||"
1795 : };
1796 :
1797 30 : for(auto iv : invalid_value)
1798 : {
1799 29 : std::stringstream ss;
1800 29 : ss << "a[b " << iv << " c]{color:red}\n";
1801 87 : csspp::position pos("test.css");
1802 : //std::cerr << "Test <<<" << ss.str() << ">>>\n";
1803 29 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
1804 :
1805 58 : csspp::parser p(l);
1806 :
1807 29 : csspp::node::pointer_t n(p.stylesheet());
1808 :
1809 : // no errors so far
1810 29 : VERIFY_ERRORS("");
1811 :
1812 29 : csspp::compiler c;
1813 29 : c.set_root(n);
1814 :
1815 29 : c.compile(true);
1816 :
1817 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
1818 :
1819 29 : VERIFY_ERRORS("test.css(1): error: expected attribute operator missing, supported operators are '=', '!=', '~=', '^=', '$=', '*=', and '|='.\n");
1820 :
1821 29 : CATCH_REQUIRE(c.get_root() == n);
1822 29 : }
1823 : }
1824 6 : CATCH_END_SECTION()
1825 :
1826 : // attribute and a binary operators: =, |=, ~=, $=, ^=, *=
1827 : // not followed by any value
1828 6 : CATCH_START_SECTION("Valid operators, missing right hand side value")
1829 : {
1830 1 : char const * invalid_value[] =
1831 : {
1832 : "=",
1833 : " =",
1834 : "= ",
1835 : " = ",
1836 : "!=",
1837 : " !=",
1838 : "!= ",
1839 : " != ",
1840 : "|=",
1841 : " |=",
1842 : "|= ",
1843 : " |= ",
1844 : "~=",
1845 : " ~=",
1846 : "~= ",
1847 : " ~= ",
1848 : "$=",
1849 : " $=",
1850 : "$= ",
1851 : " $= ",
1852 : "^=",
1853 : " ^=",
1854 : "^= ",
1855 : " ^= ",
1856 : "*=",
1857 : " *=",
1858 : "*= ",
1859 : " *= ",
1860 : };
1861 :
1862 29 : for(auto iv : invalid_value)
1863 : {
1864 28 : std::stringstream ss;
1865 28 : ss << "a[b" << iv << "]{color:red}\n";
1866 84 : csspp::position pos("test.css");
1867 : //std::cerr << "Test <<<" << ss.str() << ">>>\n";
1868 28 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
1869 :
1870 56 : csspp::parser p(l);
1871 :
1872 28 : csspp::node::pointer_t n(p.stylesheet());
1873 :
1874 : // no errors so far
1875 28 : VERIFY_ERRORS("");
1876 :
1877 28 : csspp::compiler c;
1878 28 : c.set_root(n);
1879 :
1880 28 : c.compile(true);
1881 :
1882 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
1883 :
1884 28 : VERIFY_ERRORS("test.css(1): error: the attribute selector is expected to be an IDENTIFIER optionally followed by an operator and a value.\n");
1885 :
1886 28 : CATCH_REQUIRE(c.get_root() == n);
1887 28 : }
1888 : }
1889 6 : CATCH_END_SECTION()
1890 :
1891 : // attribute value can only be identifier, string, integer,
1892 : // and decimal number
1893 6 : CATCH_START_SECTION("Valid operators, invalid right hand side value")
1894 : {
1895 1 : char const * invalid_value[] =
1896 : {
1897 : "1.23%",
1898 : "(b)",
1899 : "[b]",
1900 : "{b}",
1901 : "+",
1902 : //"@b",
1903 : //"<!--",
1904 : //"-->",
1905 : //")",
1906 : //"}",
1907 : ",",
1908 : "/* @preserve this comment */",
1909 : "|=",
1910 : "/",
1911 : "$",
1912 : //"=",
1913 : //"!",
1914 : ">",
1915 : "#123",
1916 : "~=",
1917 : "*",
1918 : ".top",
1919 : "%name",
1920 : "~",
1921 : "&",
1922 : "|",
1923 : //";b",
1924 : };
1925 1 : char const *op[] =
1926 : {
1927 : "=",
1928 : "|=",
1929 : "~=",
1930 : "$=",
1931 : "^=",
1932 : "*="
1933 : };
1934 :
1935 20 : for(auto iv : invalid_value)
1936 : {
1937 19 : std::stringstream ss;
1938 19 : ss << "a[b" << op[rand() % 6] << iv << "]{color:red}\n";
1939 57 : csspp::position pos("test.css");
1940 : //std::cerr << "Test <<<" << ss.str() << ">>>\n";
1941 19 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
1942 :
1943 38 : csspp::parser p(l);
1944 :
1945 19 : csspp::node::pointer_t n(p.stylesheet());
1946 :
1947 : // no errors so far
1948 19 : VERIFY_ERRORS("");
1949 :
1950 19 : csspp::compiler c;
1951 19 : c.set_root(n);
1952 :
1953 19 : c.compile(true);
1954 :
1955 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
1956 :
1957 : // the node that caused a problem is:
1958 : // LIST
1959 : // COMPONENT_VALUE
1960 : // ARG
1961 : // ...
1962 : // OPEN_SQUAREBRACKET
1963 : // ...
1964 : // ...
1965 : // <this one>
1966 76 : csspp::node::pointer_t op_node(n->get_child(0)->get_child(0)->get_child(1)->get_child(2));
1967 :
1968 19 : std::stringstream errmsg;
1969 19 : errmsg << "test.css(1): error: attribute selector value must be an identifier, a string, an integer, or a decimal number, a "
1970 19 : << op_node->get_type()
1971 19 : << " is not acceptable.\n";
1972 19 : VERIFY_ERRORS(errmsg.str());
1973 :
1974 19 : CATCH_REQUIRE(c.get_root() == n);
1975 19 : }
1976 :
1977 20 : for(auto iv : invalid_value)
1978 : {
1979 19 : std::stringstream ss;
1980 19 : ss << "a[b" << op[rand() % 6] << " " << iv << "]{color:red}\n";
1981 57 : csspp::position pos("test.css");
1982 : //std::cerr << "Test <<<" << ss.str() << ">>>\n";
1983 19 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
1984 :
1985 38 : csspp::parser p(l);
1986 :
1987 19 : csspp::node::pointer_t n(p.stylesheet());
1988 :
1989 : // no errors so far
1990 19 : VERIFY_ERRORS("");
1991 :
1992 19 : csspp::compiler c;
1993 19 : c.set_root(n);
1994 :
1995 19 : c.compile(true);
1996 :
1997 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
1998 :
1999 : // the node that caused a problem is:
2000 : // LIST
2001 : // COMPONENT_VALUE
2002 : // ARG
2003 : // ...
2004 : // OPEN_SQUAREBRACKET
2005 : // ...
2006 : // ...
2007 : // <this one>
2008 76 : csspp::node::pointer_t op_node(n->get_child(0)->get_child(0)->get_child(1)->get_child(2));
2009 :
2010 19 : std::stringstream errmsg;
2011 19 : errmsg << "test.css(1): error: attribute selector value must be an identifier, a string, an integer, or a decimal number, a "
2012 19 : << op_node->get_type()
2013 19 : << " is not acceptable.\n";
2014 19 : VERIFY_ERRORS(errmsg.str());
2015 :
2016 19 : CATCH_REQUIRE(c.get_root() == n);
2017 19 : }
2018 :
2019 20 : for(auto iv : invalid_value)
2020 : {
2021 19 : std::stringstream ss;
2022 19 : ss << "a[b" << op[rand() % 6] << iv << " ]{color:red}\n";
2023 57 : csspp::position pos("test.css");
2024 : //std::cerr << "Test <<<" << ss.str() << ">>>\n";
2025 19 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
2026 :
2027 38 : csspp::parser p(l);
2028 :
2029 19 : csspp::node::pointer_t n(p.stylesheet());
2030 :
2031 : // no errors so far
2032 19 : VERIFY_ERRORS("");
2033 :
2034 19 : csspp::compiler c;
2035 19 : c.set_root(n);
2036 :
2037 19 : c.compile(true);
2038 :
2039 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
2040 :
2041 : // the node that caused a problem is:
2042 : // LIST
2043 : // COMPONENT_VALUE
2044 : // ARG
2045 : // ...
2046 : // OPEN_SQUAREBRACKET
2047 : // ...
2048 : // ...
2049 : // <this one>
2050 76 : csspp::node::pointer_t op_node(n->get_child(0)->get_child(0)->get_child(1)->get_child(2));
2051 :
2052 19 : std::stringstream errmsg;
2053 19 : errmsg << "test.css(1): error: attribute selector value must be an identifier, a string, an integer, or a decimal number, a "
2054 19 : << op_node->get_type()
2055 19 : << " is not acceptable.\n";
2056 19 : VERIFY_ERRORS(errmsg.str());
2057 :
2058 19 : CATCH_REQUIRE(c.get_root() == n);
2059 19 : }
2060 :
2061 20 : for(auto iv : invalid_value)
2062 : {
2063 19 : std::stringstream ss;
2064 19 : ss << "a[b" << op[rand() % 6] << " " << iv << " ]{color:red}\n";
2065 57 : csspp::position pos("test.css");
2066 : //std::cerr << "Test <<<" << ss.str() << ">>>\n";
2067 19 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
2068 :
2069 38 : csspp::parser p(l);
2070 :
2071 19 : csspp::node::pointer_t n(p.stylesheet());
2072 :
2073 : // no errors so far
2074 19 : VERIFY_ERRORS("");
2075 :
2076 19 : csspp::compiler c;
2077 19 : c.set_root(n);
2078 :
2079 19 : c.compile(true);
2080 :
2081 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
2082 :
2083 : // the node that caused a problem is:
2084 : // LIST
2085 : // COMPONENT_VALUE
2086 : // ARG
2087 : // ...
2088 : // OPEN_SQUAREBRACKET
2089 : // ...
2090 : // ...
2091 : // <this one>
2092 76 : csspp::node::pointer_t op_node(n->get_child(0)->get_child(0)->get_child(1)->get_child(2));
2093 :
2094 19 : std::stringstream errmsg;
2095 19 : errmsg << "test.css(1): error: attribute selector value must be an identifier, a string, an integer, or a decimal number, a "
2096 19 : << op_node->get_type()
2097 19 : << " is not acceptable.\n";
2098 19 : VERIFY_ERRORS(errmsg.str());
2099 :
2100 19 : CATCH_REQUIRE(c.get_root() == n);
2101 19 : }
2102 : }
2103 6 : CATCH_END_SECTION()
2104 :
2105 : // attribute value can only be one token
2106 6 : CATCH_START_SECTION("Valid operators, right hand side value followed by something")
2107 : {
2108 1 : char const * invalid_value[] =
2109 : {
2110 : "identifier",
2111 : "123",
2112 : "1.23",
2113 : "'1.23'",
2114 : "1.23%",
2115 : "(b)",
2116 : "[b]",
2117 : "{b}",
2118 : "+",
2119 : //"@b",
2120 : //"<!--",
2121 : //"-->",
2122 : //")",
2123 : //"}",
2124 : ",",
2125 : "/* @preserve this comment */",
2126 : "|=",
2127 : "/",
2128 : "$",
2129 : "=",
2130 : //"!",
2131 : ">",
2132 : "#123",
2133 : "~=",
2134 : "*",
2135 : ".top",
2136 : "%name",
2137 : "~",
2138 : "&",
2139 : "|",
2140 : //";b",
2141 : };
2142 1 : char const *op[] =
2143 : {
2144 : "=",
2145 : "|=",
2146 : "~=",
2147 : "$=",
2148 : "^=",
2149 : "*="
2150 : };
2151 :
2152 25 : for(auto iv : invalid_value)
2153 : {
2154 : // without a space these gets glued to "c"
2155 48 : std::string const v(iv);
2156 24 : if(v == "identifier" // "cidentifier"
2157 23 : || v == "123" // "c123"
2158 47 : || v[0] == '(') // "c(...)"
2159 : {
2160 3 : continue;
2161 : }
2162 21 : std::stringstream ss;
2163 21 : ss << "a[b" << op[rand() % 6] << "c" << iv << "]{color:red}\n";
2164 63 : csspp::position pos("test.css");
2165 : //std::cerr << "Test <<<" << ss.str() << ">>>\n";
2166 21 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
2167 :
2168 42 : csspp::parser p(l);
2169 :
2170 21 : csspp::node::pointer_t n(p.stylesheet());
2171 :
2172 : // no errors so far
2173 21 : VERIFY_ERRORS("");
2174 :
2175 21 : csspp::compiler c;
2176 21 : c.set_root(n);
2177 :
2178 21 : c.compile(true);
2179 :
2180 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
2181 :
2182 : // the node that caused a problem is:
2183 : // LIST
2184 : // COMPONENT_VALUE
2185 : // ARG
2186 : // ...
2187 : // OPEN_SQUAREBRACKET
2188 : // ...
2189 : // ...
2190 : // <this one>
2191 84 : csspp::node::pointer_t op_node(n->get_child(0)->get_child(0)->get_child(1)->get_child(3));
2192 :
2193 21 : std::stringstream errmsg;
2194 21 : errmsg << "test.css(1): error: attribute selector cannot be followed by more than one value, found "
2195 21 : << op_node->get_type()
2196 21 : << " after the value, missing quotes?\n";
2197 21 : VERIFY_ERRORS(errmsg.str());
2198 :
2199 21 : CATCH_REQUIRE(c.get_root() == n);
2200 24 : }
2201 :
2202 25 : for(auto iv : invalid_value)
2203 : {
2204 24 : std::stringstream ss;
2205 24 : ss << "a[b" << op[rand() % 6] << "c " << iv << "]{color:red}\n";
2206 72 : csspp::position pos("test.css");
2207 : //std::cerr << "Test <<<" << ss.str() << ">>>\n";
2208 24 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
2209 :
2210 48 : csspp::parser p(l);
2211 :
2212 24 : csspp::node::pointer_t n(p.stylesheet());
2213 :
2214 : // no errors so far
2215 24 : VERIFY_ERRORS("");
2216 :
2217 24 : csspp::compiler c;
2218 24 : c.set_root(n);
2219 :
2220 24 : c.compile(true);
2221 :
2222 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
2223 :
2224 : // the node that caused a problem is:
2225 : // LIST
2226 : // COMPONENT_VALUE
2227 : // ARG
2228 : // ...
2229 : // OPEN_SQUAREBRACKET
2230 : // ...
2231 : // ...
2232 : // <this one>
2233 96 : csspp::node::pointer_t op_node(n->get_child(0)->get_child(0)->get_child(1)->get_child(3));
2234 :
2235 24 : std::stringstream errmsg;
2236 24 : errmsg << "test.css(1): error: attribute selector cannot be followed by more than one value, found "
2237 24 : << op_node->get_type()
2238 24 : << " after the value, missing quotes?\n";
2239 24 : VERIFY_ERRORS(errmsg.str());
2240 :
2241 24 : CATCH_REQUIRE(c.get_root() == n);
2242 24 : }
2243 :
2244 25 : for(auto iv : invalid_value)
2245 : {
2246 : // without a space these gets glued to "c"
2247 48 : std::string const v(iv);
2248 24 : if(v == "identifier" // "cidentifier"
2249 23 : || v == "123" // "c123"
2250 47 : || v[0] == '(') // "c(...)"
2251 : {
2252 3 : continue;
2253 : }
2254 21 : std::stringstream ss;
2255 21 : ss << "a[b" << op[rand() % 6] << "c" << iv << " ]{color:red}\n";
2256 63 : csspp::position pos("test.css");
2257 : //std::cerr << "Test <<<" << ss.str() << ">>>\n";
2258 21 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
2259 :
2260 42 : csspp::parser p(l);
2261 :
2262 21 : csspp::node::pointer_t n(p.stylesheet());
2263 :
2264 : // no errors so far
2265 21 : VERIFY_ERRORS("");
2266 :
2267 21 : csspp::compiler c;
2268 21 : c.set_root(n);
2269 :
2270 21 : c.compile(true);
2271 :
2272 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
2273 :
2274 : // the node that caused a problem is:
2275 : // LIST
2276 : // COMPONENT_VALUE
2277 : // ARG
2278 : // ...
2279 : // OPEN_SQUAREBRACKET
2280 : // ...
2281 : // ...
2282 : // <this one>
2283 84 : csspp::node::pointer_t op_node(n->get_child(0)->get_child(0)->get_child(1)->get_child(3));
2284 :
2285 21 : std::stringstream errmsg;
2286 21 : errmsg << "test.css(1): error: attribute selector cannot be followed by more than one value, found "
2287 21 : << op_node->get_type()
2288 21 : << " after the value, missing quotes?\n";
2289 21 : VERIFY_ERRORS(errmsg.str());
2290 :
2291 21 : CATCH_REQUIRE(c.get_root() == n);
2292 24 : }
2293 :
2294 25 : for(auto iv : invalid_value)
2295 : {
2296 24 : std::stringstream ss;
2297 24 : ss << "a[b" << op[rand() % 6] << "c " << iv << " ]{color:red}\n";
2298 72 : csspp::position pos("test.css");
2299 : //std::cerr << "Test <<<" << ss.str() << ">>>\n";
2300 24 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
2301 :
2302 48 : csspp::parser p(l);
2303 :
2304 24 : csspp::node::pointer_t n(p.stylesheet());
2305 :
2306 : // no errors so far
2307 24 : VERIFY_ERRORS("");
2308 :
2309 24 : csspp::compiler c;
2310 24 : c.set_root(n);
2311 :
2312 24 : c.compile(true);
2313 :
2314 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
2315 :
2316 : // the node that caused a problem is:
2317 : // LIST
2318 : // COMPONENT_VALUE
2319 : // ARG
2320 : // ...
2321 : // OPEN_SQUAREBRACKET
2322 : // ...
2323 : // ...
2324 : // <this one>
2325 96 : csspp::node::pointer_t op_node(n->get_child(0)->get_child(0)->get_child(1)->get_child(3));
2326 :
2327 24 : std::stringstream errmsg;
2328 24 : errmsg << "test.css(1): error: attribute selector cannot be followed by more than one value, found "
2329 24 : << op_node->get_type()
2330 24 : << " after the value, missing quotes?\n";
2331 24 : VERIFY_ERRORS(errmsg.str());
2332 :
2333 24 : CATCH_REQUIRE(c.get_root() == n);
2334 24 : }
2335 : }
2336 6 : CATCH_END_SECTION()
2337 :
2338 : // attribute value can only be one token
2339 6 : CATCH_START_SECTION("Valid operators, right hand side value missing, no spaces")
2340 : {
2341 1 : char const *op[] =
2342 : {
2343 : "=",
2344 : "!=",
2345 : "|=",
2346 : "~=",
2347 : "$=",
2348 : "^=",
2349 : "*="
2350 : };
2351 :
2352 8 : for(auto o : op)
2353 : {
2354 7 : std::stringstream ss;
2355 7 : ss << "a[b" << o << "]{color:red}\n";
2356 21 : csspp::position pos("test.css");
2357 : //std::cerr << "Test <<<" << ss.str() << ">>>\n";
2358 7 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
2359 :
2360 14 : csspp::parser p(l);
2361 :
2362 7 : csspp::node::pointer_t n(p.stylesheet());
2363 :
2364 : // no errors so far
2365 7 : VERIFY_ERRORS("");
2366 :
2367 7 : csspp::compiler c;
2368 7 : c.set_root(n);
2369 :
2370 7 : c.compile(true);
2371 :
2372 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
2373 :
2374 : // the node that caused a problem is:
2375 : // LIST
2376 : // COMPONENT_VALUE
2377 : // ARG
2378 : // ...
2379 : // OPEN_SQUAREBRACKET
2380 : // ...
2381 : // ...
2382 : // <this one>
2383 : //csspp::node::pointer_t op_node(n->get_child(0)->get_child(0)->get_child(1)->get_child(3));
2384 :
2385 7 : std::stringstream errmsg;
2386 7 : errmsg << "test.css(1): error: the attribute selector is expected to be an IDENTIFIER optionally followed by an operator and a value.\n";
2387 7 : VERIFY_ERRORS(errmsg.str());
2388 :
2389 7 : CATCH_REQUIRE(c.get_root() == n);
2390 7 : }
2391 :
2392 8 : for(auto o : op)
2393 : {
2394 7 : std::stringstream ss;
2395 7 : ss << "a[b" << o << " ]{color:red}\n";
2396 21 : csspp::position pos("test.css");
2397 : //std::cerr << "Test <<<" << ss.str() << ">>>\n";
2398 7 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
2399 :
2400 14 : csspp::parser p(l);
2401 :
2402 7 : csspp::node::pointer_t n(p.stylesheet());
2403 :
2404 : // no errors so far
2405 7 : VERIFY_ERRORS("");
2406 :
2407 7 : csspp::compiler c;
2408 7 : c.set_root(n);
2409 :
2410 7 : c.compile(true);
2411 :
2412 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
2413 :
2414 : // the node that caused a problem is:
2415 : // LIST
2416 : // COMPONENT_VALUE
2417 : // ARG
2418 : // ...
2419 : // OPEN_SQUAREBRACKET
2420 : // ...
2421 : // ...
2422 : // <this one>
2423 : //csspp::node::pointer_t op_node(n->get_child(0)->get_child(0)->get_child(1)->get_child(3));
2424 :
2425 7 : std::stringstream errmsg;
2426 7 : errmsg << "test.css(1): error: the attribute selector is expected to be an IDENTIFIER optionally followed by an operator and a value.\n";
2427 7 : VERIFY_ERRORS(errmsg.str());
2428 :
2429 7 : CATCH_REQUIRE(c.get_root() == n);
2430 7 : }
2431 : }
2432 6 : CATCH_END_SECTION()
2433 :
2434 : // no error left over
2435 6 : VERIFY_ERRORS("");
2436 6 : }
2437 :
2438 1 : CATCH_TEST_CASE("Undefined paths", "[compiler] [invalid]")
2439 : {
2440 : // compile without defining the paths
2441 : //
2442 : // (The result may be a success if you installed CSS Preprocessor
2443 : // before since it will look for the scripts at "the right place!"
2444 : // when the packages are installed properly on a system.)
2445 : {
2446 1 : std::stringstream ss;
2447 1 : ss << ":lang(fr) {color:red}";
2448 3 : csspp::position pos("test.css");
2449 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
2450 :
2451 2 : csspp::parser p(l);
2452 :
2453 1 : csspp::node::pointer_t n(p.stylesheet());
2454 :
2455 : // no errors so far
2456 1 : VERIFY_ERRORS("");
2457 :
2458 1 : csspp::compiler c;
2459 1 : c.set_root(n);
2460 1 : c.clear_paths();
2461 : // c.add_path(...); -- check system default
2462 : //c.add_path(csspp_test::get_script_path());
2463 : //c.add_path(csspp_test::get_version_script_path());
2464 :
2465 1 : std::stringstream ignore;
2466 1 : csspp::safe_error_stream_t safe_output(ignore);
2467 :
2468 : try
2469 : {
2470 1 : c.compile(true);
2471 :
2472 : // in case the system scripts are there, we want to check
2473 : // that the result is fine
2474 0 : std::stringstream out;
2475 0 : out << *n;
2476 0 : VERIFY_TREES(out.str(),
2477 :
2478 : "LIST\n"
2479 : " COMPONENT_VALUE\n"
2480 : " ARG\n"
2481 : " COLON\n"
2482 : " FUNCTION \"lang\"\n"
2483 : " IDENTIFIER \"fr\"\n"
2484 : " OPEN_CURLYBRACKET B:true\n"
2485 : " DECLARATION \"color\"\n"
2486 : " ARG\n"
2487 : " COLOR H:ff0000ff\n"
2488 :
2489 : );
2490 :
2491 0 : }
2492 1 : catch(csspp::csspp_exception_exit const &)
2493 : {
2494 1 : CATCH_REQUIRE(ignore.str() == "validation/pseudo-nth-functions(1): fatal: validation script \"validation/pseudo-nth-functions\" was not found.\n");
2495 1 : }
2496 :
2497 1 : CATCH_REQUIRE(c.get_root() == n);
2498 1 : }
2499 :
2500 : // no left over?
2501 1 : VERIFY_ERRORS("");
2502 1 : }
2503 :
2504 1 : CATCH_TEST_CASE("Simple terms", "[compiler] [stylesheet]")
2505 : {
2506 : // simple terms are:
2507 : // HASH
2508 : // IDENTIFIER
2509 : // IDENTIFIER '|' IDENTIFIER
2510 : // IDENTIFIER '|' '*'
2511 : // '*'
2512 : // '*' '|' IDENTIFIER
2513 : // '*' '|' '*'
2514 : // '|' IDENTIFIER
2515 : // '|' '*'
2516 : // ':' IDENTIFIER -- see below
2517 : // ':' FUNCTION ... ')'
2518 : // '.' IDENTIFIER
2519 : // '[' ... ']'
2520 : {
2521 1 : std::stringstream ss;
2522 : ss << "#abd identifier ns|id namespace|* * *|abc *|*"
2523 : << " |abc |* a:root :nth-child(3n+4) .class [foo]"
2524 1 : << "{color:red;width:12px}";
2525 3 : csspp::position pos("test.css");
2526 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
2527 :
2528 2 : csspp::parser p(l);
2529 :
2530 1 : csspp::node::pointer_t n(p.stylesheet());
2531 :
2532 : // no errors so far
2533 1 : VERIFY_ERRORS("");
2534 :
2535 1 : csspp::compiler c;
2536 1 : c.set_root(n);
2537 1 : c.clear_paths();
2538 1 : c.add_path(csspp_test::get_script_path());
2539 1 : c.add_path(csspp_test::get_version_script_path());
2540 :
2541 1 : c.compile(true);
2542 :
2543 : // no error left over
2544 1 : VERIFY_ERRORS("");
2545 :
2546 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
2547 :
2548 1 : std::stringstream out;
2549 1 : out << *n;
2550 1 : VERIFY_TREES(out.str(),
2551 :
2552 : "LIST\n"
2553 : " COMPONENT_VALUE\n"
2554 : " ARG\n"
2555 : // #abd
2556 : " HASH \"abd\"\n"
2557 : " WHITESPACE\n"
2558 : // identifier
2559 : " IDENTIFIER \"identifier\"\n"
2560 : " WHITESPACE\n"
2561 : // ns|id
2562 : " IDENTIFIER \"ns\"\n"
2563 : " SCOPE\n"
2564 : " IDENTIFIER \"id\"\n"
2565 : " WHITESPACE\n"
2566 : // namespace|*
2567 : " IDENTIFIER \"namespace\"\n"
2568 : " SCOPE\n"
2569 : " MULTIPLY\n"
2570 : " WHITESPACE\n"
2571 : // *
2572 : " MULTIPLY\n"
2573 : " WHITESPACE\n"
2574 : // *|abc
2575 : " MULTIPLY\n"
2576 : " SCOPE\n"
2577 : " IDENTIFIER \"abc\"\n"
2578 : " WHITESPACE\n"
2579 : // *|*
2580 : " MULTIPLY\n"
2581 : " SCOPE\n"
2582 : " MULTIPLY\n"
2583 : " WHITESPACE\n"
2584 : // |abc
2585 : " SCOPE\n"
2586 : " IDENTIFIER \"abc\"\n"
2587 : " WHITESPACE\n"
2588 : // |*
2589 : " SCOPE\n"
2590 : " MULTIPLY\n"
2591 : " WHITESPACE\n"
2592 : // a:root
2593 : " IDENTIFIER \"a\"\n"
2594 : " COLON\n"
2595 : " IDENTIFIER \"root\"\n"
2596 : " WHITESPACE\n"
2597 : // :nth-child
2598 : " COLON\n"
2599 : " FUNCTION \"nth-child\"\n"
2600 : " AN_PLUS_B S:3n+4\n"
2601 : " WHITESPACE\n"
2602 : // .class
2603 : " PERIOD\n"
2604 : " IDENTIFIER \"class\"\n"
2605 : //" WHITESPACE\n"
2606 : // [foo]
2607 : " OPEN_SQUAREBRACKET\n"
2608 : " IDENTIFIER \"foo\"\n"
2609 : // {color:red}
2610 : " OPEN_CURLYBRACKET B:true\n"
2611 : " LIST\n"
2612 : " DECLARATION \"color\"\n"
2613 : " ARG\n"
2614 : " COLOR H:ff0000ff\n"
2615 : " DECLARATION \"width\"\n"
2616 : " ARG\n"
2617 : " INTEGER \"px\" I:12\n"
2618 :
2619 : );
2620 :
2621 : // no error left over
2622 1 : VERIFY_ERRORS("");
2623 :
2624 1 : CATCH_REQUIRE(c.get_root() == n);
2625 1 : }
2626 :
2627 : // check all pseudo-classes
2628 : {
2629 1 : char const * pseudo_name_table[] =
2630 : {
2631 : "root",
2632 : "first-child",
2633 : "last-child",
2634 : "first-of-type",
2635 : "last-of-type",
2636 : "only-child",
2637 : "only-of-type",
2638 : "empty",
2639 : "link",
2640 : "visited",
2641 : "active",
2642 : "hover",
2643 : "focus",
2644 : "target",
2645 : "enabled",
2646 : "disabled",
2647 : "checked"
2648 : };
2649 :
2650 18 : for(auto pseudo_name : pseudo_name_table)
2651 : {
2652 :
2653 17 : std::stringstream ss;
2654 : ss << ":"
2655 : << pseudo_name
2656 17 : << "{color:red}\n";
2657 51 : csspp::position pos("test.css");
2658 17 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
2659 :
2660 34 : csspp::parser p(l);
2661 :
2662 17 : csspp::node::pointer_t n(p.stylesheet());
2663 :
2664 : // no errors so far
2665 17 : VERIFY_ERRORS("");
2666 :
2667 17 : csspp::compiler c;
2668 17 : c.set_root(n);
2669 17 : c.clear_paths();
2670 17 : c.add_path(csspp_test::get_script_path());
2671 17 : c.add_path(csspp_test::get_version_script_path());
2672 :
2673 17 : c.compile(true);
2674 :
2675 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
2676 :
2677 17 : std::stringstream out;
2678 17 : out << *n;
2679 17 : VERIFY_TREES(out.str(),
2680 :
2681 : "LIST\n"
2682 : " COMPONENT_VALUE\n"
2683 : " ARG\n"
2684 : " COLON\n"
2685 : " IDENTIFIER \"" + std::string(pseudo_name) + "\"\n"
2686 : " OPEN_CURLYBRACKET B:true\n"
2687 : " DECLARATION \"color\"\n"
2688 : " ARG\n"
2689 : " COLOR H:ff0000ff\n"
2690 :
2691 : );
2692 :
2693 17 : CATCH_REQUIRE(c.get_root() == n);
2694 17 : }
2695 :
2696 : // no error left over
2697 1 : VERIFY_ERRORS("");
2698 : }
2699 :
2700 : // check all pseudo-classes
2701 : {
2702 1 : char const * pseudo_name_table[] =
2703 : {
2704 : "root",
2705 : "first-child",
2706 : "last-child",
2707 : "first-of-type",
2708 : "last-of-type",
2709 : "only-child",
2710 : "only-of-type",
2711 : "empty",
2712 : "link",
2713 : "visited",
2714 : "active",
2715 : "hover",
2716 : "focus",
2717 : "target",
2718 : "enabled",
2719 : "disabled",
2720 : "checked"
2721 : };
2722 :
2723 18 : for(auto pseudo_name : pseudo_name_table)
2724 : {
2725 :
2726 17 : std::stringstream ss;
2727 : ss << ":"
2728 : << pseudo_name
2729 17 : << "{color:red}\n";
2730 51 : csspp::position pos("test.css");
2731 17 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
2732 :
2733 34 : csspp::parser p(l);
2734 :
2735 17 : csspp::node::pointer_t n(p.stylesheet());
2736 :
2737 : // no errors so far
2738 17 : VERIFY_ERRORS("");
2739 :
2740 17 : csspp::compiler c;
2741 17 : c.set_root(n);
2742 17 : c.clear_paths();
2743 17 : c.add_path(csspp_test::get_script_path());
2744 17 : c.add_path(csspp_test::get_version_script_path());
2745 :
2746 17 : c.compile(true);
2747 :
2748 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
2749 :
2750 17 : std::stringstream out;
2751 17 : out << *n;
2752 17 : VERIFY_TREES(out.str(),
2753 :
2754 : "LIST\n"
2755 : " COMPONENT_VALUE\n"
2756 : " ARG\n"
2757 : " COLON\n"
2758 : " IDENTIFIER \"" + std::string(pseudo_name) + "\"\n"
2759 : " OPEN_CURLYBRACKET B:true\n"
2760 : " DECLARATION \"color\"\n"
2761 : " ARG\n"
2762 : " COLOR H:ff0000ff\n"
2763 :
2764 : );
2765 :
2766 17 : CATCH_REQUIRE(c.get_root() == n);
2767 17 : }
2768 :
2769 : // no error left over
2770 1 : VERIFY_ERRORS("");
2771 : }
2772 :
2773 : // test all nth pseudo-functions
2774 : {
2775 1 : char const * nth_functions[] =
2776 : {
2777 : "child",
2778 : "last-child",
2779 : "of-type",
2780 : "last-of-type"
2781 : };
2782 5 : for(size_t i(0); i < sizeof(nth_functions) / sizeof(nth_functions[0]); ++i)
2783 : {
2784 4 : std::stringstream ss;
2785 : ss << "div a:nth-" << nth_functions[i] << "(3n+1)"
2786 4 : << "{color:#651}";
2787 12 : csspp::position pos("test.css");
2788 4 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
2789 :
2790 8 : csspp::parser p(l);
2791 :
2792 4 : csspp::node::pointer_t n(p.stylesheet());
2793 :
2794 : // no errors so far
2795 4 : VERIFY_ERRORS("");
2796 :
2797 4 : csspp::compiler c;
2798 4 : c.set_root(n);
2799 4 : c.clear_paths();
2800 4 : c.add_path(csspp_test::get_script_path());
2801 4 : c.add_path(csspp_test::get_version_script_path());
2802 :
2803 4 : c.compile(true);
2804 :
2805 : // no error left over
2806 4 : VERIFY_ERRORS("");
2807 :
2808 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
2809 :
2810 4 : std::stringstream out;
2811 4 : out << *n;
2812 4 : VERIFY_TREES(out.str(),
2813 :
2814 : "LIST\n"
2815 : " COMPONENT_VALUE\n"
2816 : " ARG\n"
2817 : // #abd
2818 : " IDENTIFIER \"div\"\n"
2819 : " WHITESPACE\n"
2820 : // identifier
2821 : " IDENTIFIER \"a\"\n"
2822 : " COLON\n"
2823 : " FUNCTION \"nth-" + std::string(nth_functions[i]) + "\"\n"
2824 : " AN_PLUS_B S:3n+1\n"
2825 : // {color:blue}
2826 : " OPEN_CURLYBRACKET B:true\n"
2827 : " DECLARATION \"color\"\n"
2828 : " ARG\n"
2829 : " COLOR H:ff115566\n"
2830 :
2831 : );
2832 :
2833 4 : CATCH_REQUIRE(c.get_root() == n);
2834 4 : }
2835 :
2836 : // no error left over
2837 1 : VERIFY_ERRORS("");
2838 : }
2839 :
2840 : // test the lang() function
2841 : {
2842 1 : std::stringstream ss;
2843 : ss << "div q:lang(zu-za)"
2844 1 : << "{color:#651}";
2845 3 : csspp::position pos("test.css");
2846 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
2847 :
2848 2 : csspp::parser p(l);
2849 :
2850 1 : csspp::node::pointer_t n(p.stylesheet());
2851 :
2852 : // no errors so far
2853 1 : VERIFY_ERRORS("");
2854 :
2855 1 : csspp::compiler c;
2856 1 : c.set_root(n);
2857 1 : c.clear_paths();
2858 1 : c.add_path(csspp_test::get_script_path());
2859 1 : c.add_path(csspp_test::get_version_script_path());
2860 :
2861 1 : c.compile(true);
2862 :
2863 : // no error left over
2864 1 : VERIFY_ERRORS("");
2865 :
2866 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
2867 :
2868 1 : std::stringstream out;
2869 1 : out << *n;
2870 1 : VERIFY_TREES(out.str(),
2871 :
2872 : "LIST\n"
2873 : " COMPONENT_VALUE\n"
2874 : " ARG\n"
2875 : // #abd
2876 : " IDENTIFIER \"div\"\n"
2877 : " WHITESPACE\n"
2878 : // identifier
2879 : " IDENTIFIER \"q\"\n"
2880 : " COLON\n"
2881 : " FUNCTION \"lang\"\n"
2882 : " IDENTIFIER \"zu-za\"\n"
2883 : // {color:#651}
2884 : " OPEN_CURLYBRACKET B:true\n"
2885 : " DECLARATION \"color\"\n"
2886 : " ARG\n"
2887 : " COLOR H:ff115566\n"
2888 :
2889 : );
2890 :
2891 : // no error left over
2892 1 : VERIFY_ERRORS("");
2893 :
2894 1 : CATCH_REQUIRE(c.get_root() == n);
2895 1 : }
2896 :
2897 : // test the lang() function with 3 parameters
2898 : {
2899 1 : std::stringstream ss;
2900 : ss << "div b:lang(fr-ca-nc)"
2901 1 : << "{color:brisque}";
2902 3 : csspp::position pos("test.css");
2903 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
2904 :
2905 2 : csspp::parser p(l);
2906 :
2907 1 : csspp::node::pointer_t n(p.stylesheet());
2908 :
2909 : // no errors so far
2910 1 : VERIFY_ERRORS("");
2911 :
2912 1 : csspp::compiler c;
2913 1 : c.set_root(n);
2914 1 : c.clear_paths();
2915 1 : c.add_path(csspp_test::get_script_path());
2916 1 : c.add_path(csspp_test::get_version_script_path());
2917 :
2918 1 : c.compile(true);
2919 :
2920 : // no error left over
2921 1 : VERIFY_ERRORS("");
2922 :
2923 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
2924 :
2925 1 : std::stringstream out;
2926 1 : out << *n;
2927 1 : VERIFY_TREES(out.str(),
2928 :
2929 : "LIST\n"
2930 : " COMPONENT_VALUE\n"
2931 : " ARG\n"
2932 : // #abd
2933 : " IDENTIFIER \"div\"\n"
2934 : " WHITESPACE\n"
2935 : // identifier
2936 : " IDENTIFIER \"b\"\n"
2937 : " COLON\n"
2938 : " FUNCTION \"lang\"\n"
2939 : " IDENTIFIER \"fr-ca-nc\"\n"
2940 : // {color:#651}
2941 : " OPEN_CURLYBRACKET B:true\n"
2942 : " DECLARATION \"color\"\n"
2943 : " ARG\n"
2944 : " IDENTIFIER \"brisque\"\n"
2945 :
2946 : );
2947 :
2948 : // no error left over
2949 1 : VERIFY_ERRORS("");
2950 :
2951 1 : CATCH_REQUIRE(c.get_root() == n);
2952 1 : }
2953 :
2954 : // test the lang() multiple times to verify that the cache works
2955 : {
2956 1 : std::stringstream ss;
2957 : ss << "div b:lang(qu-vg-rr),section i:lang(ks-sm-dp)"
2958 1 : << "{color:brisque}";
2959 3 : csspp::position pos("test.css");
2960 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
2961 :
2962 2 : csspp::parser p(l);
2963 :
2964 1 : csspp::node::pointer_t n(p.stylesheet());
2965 :
2966 : // no errors so far
2967 1 : VERIFY_ERRORS("");
2968 :
2969 1 : csspp::compiler c;
2970 1 : c.set_root(n);
2971 1 : c.clear_paths();
2972 1 : c.add_path(csspp_test::get_script_path());
2973 1 : c.add_path(csspp_test::get_version_script_path());
2974 :
2975 1 : c.compile(true);
2976 :
2977 : // no error left over
2978 1 : VERIFY_ERRORS("");
2979 :
2980 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
2981 :
2982 1 : std::stringstream out;
2983 1 : out << *n;
2984 1 : VERIFY_TREES(out.str(),
2985 :
2986 : "LIST\n"
2987 : " COMPONENT_VALUE\n"
2988 : " ARG\n"
2989 : // #abd
2990 : " IDENTIFIER \"div\"\n"
2991 : " WHITESPACE\n"
2992 : // identifier
2993 : " IDENTIFIER \"b\"\n"
2994 : " COLON\n"
2995 : " FUNCTION \"lang\"\n"
2996 : " IDENTIFIER \"qu-vg-rr\"\n"
2997 : " ARG\n"
2998 : // #abd
2999 : " IDENTIFIER \"section\"\n"
3000 : " WHITESPACE\n"
3001 : // identifier
3002 : " IDENTIFIER \"i\"\n"
3003 : " COLON\n"
3004 : " FUNCTION \"lang\"\n"
3005 : " IDENTIFIER \"ks-sm-dp\"\n"
3006 : // {color:#651}
3007 : " OPEN_CURLYBRACKET B:true\n"
3008 : " DECLARATION \"color\"\n"
3009 : " ARG\n"
3010 : " IDENTIFIER \"brisque\"\n"
3011 :
3012 : );
3013 :
3014 : // no error left over
3015 1 : VERIFY_ERRORS("");
3016 :
3017 1 : CATCH_REQUIRE(c.get_root() == n);
3018 1 : }
3019 :
3020 : // one :not(...)
3021 : {
3022 1 : std::stringstream ss;
3023 1 : ss << "div:not(.chocolate) {color:coral}";
3024 3 : csspp::position pos("test.css");
3025 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
3026 :
3027 2 : csspp::parser p(l);
3028 :
3029 1 : csspp::node::pointer_t n(p.stylesheet());
3030 :
3031 : // no errors so far
3032 1 : VERIFY_ERRORS("");
3033 :
3034 1 : csspp::compiler c;
3035 1 : c.set_root(n);
3036 1 : c.clear_paths();
3037 1 : c.add_path(csspp_test::get_script_path());
3038 1 : c.add_path(csspp_test::get_version_script_path());
3039 :
3040 1 : c.compile(true);
3041 :
3042 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
3043 :
3044 1 : std::stringstream out;
3045 1 : out << *n;
3046 1 : VERIFY_TREES(out.str(),
3047 :
3048 : "LIST\n"
3049 : " COMPONENT_VALUE\n"
3050 : " ARG\n"
3051 : // #abd
3052 : " IDENTIFIER \"div\"\n"
3053 : // :not(...)
3054 : " COLON\n"
3055 : " FUNCTION \"not\"\n"
3056 : " PERIOD\n"
3057 : " IDENTIFIER \"chocolate\"\n"
3058 : // {color:coral}
3059 : " OPEN_CURLYBRACKET B:true\n"
3060 : " DECLARATION \"color\"\n"
3061 : " ARG\n"
3062 : " COLOR H:ff507fff\n"
3063 :
3064 : );
3065 :
3066 1 : VERIFY_ERRORS("");
3067 :
3068 1 : CATCH_REQUIRE(c.get_root() == n);
3069 1 : }
3070 :
3071 : // two :not(...) in a row
3072 : {
3073 1 : std::stringstream ss;
3074 1 : ss << "div:not(.red):not(.blue) {color:coral}";
3075 3 : csspp::position pos("test.css");
3076 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
3077 :
3078 2 : csspp::parser p(l);
3079 :
3080 1 : csspp::node::pointer_t n(p.stylesheet());
3081 :
3082 : // no errors so far
3083 1 : VERIFY_ERRORS("");
3084 :
3085 1 : csspp::compiler c;
3086 1 : c.set_root(n);
3087 1 : c.clear_paths();
3088 1 : c.add_path(csspp_test::get_script_path());
3089 1 : c.add_path(csspp_test::get_version_script_path());
3090 :
3091 1 : c.compile(true);
3092 :
3093 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
3094 :
3095 1 : std::stringstream out;
3096 1 : out << *n;
3097 1 : VERIFY_TREES(out.str(),
3098 :
3099 : "LIST\n"
3100 : " COMPONENT_VALUE\n"
3101 : " ARG\n"
3102 : // #abd
3103 : " IDENTIFIER \"div\"\n"
3104 : // :not(...)
3105 : " COLON\n"
3106 : " FUNCTION \"not\"\n"
3107 : " PERIOD\n"
3108 : " IDENTIFIER \"red\"\n"
3109 : // :not(...)
3110 : " COLON\n"
3111 : " FUNCTION \"not\"\n"
3112 : " PERIOD\n"
3113 : " IDENTIFIER \"blue\"\n"
3114 : // {color:coral}
3115 : " OPEN_CURLYBRACKET B:true\n"
3116 : " DECLARATION \"color\"\n"
3117 : " ARG\n"
3118 : " COLOR H:ff507fff\n"
3119 :
3120 : );
3121 :
3122 1 : VERIFY_ERRORS("");
3123 :
3124 1 : CATCH_REQUIRE(c.get_root() == n);
3125 1 : }
3126 :
3127 : // two #hash generate an information message
3128 : {
3129 1 : std::stringstream ss;
3130 1 : ss << "#first and #second {color:coral}";
3131 3 : csspp::position pos("test.css");
3132 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
3133 :
3134 2 : csspp::parser p(l);
3135 :
3136 1 : csspp::node::pointer_t n(p.stylesheet());
3137 :
3138 : // no errors so far
3139 1 : VERIFY_ERRORS("");
3140 :
3141 1 : csspp::compiler c;
3142 1 : c.set_root(n);
3143 1 : c.clear_paths();
3144 1 : c.add_path(csspp_test::get_script_path());
3145 1 : c.add_path(csspp_test::get_version_script_path());
3146 :
3147 1 : c.compile(true);
3148 :
3149 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
3150 :
3151 1 : VERIFY_ERRORS("test.css(1): info: found multiple #id entries, note that in most cases, assuming your HTML is proper (identifiers are not repeated) then only the last #id is necessary.\n");
3152 :
3153 1 : std::stringstream out;
3154 1 : out << *n;
3155 1 : VERIFY_TREES(out.str(),
3156 :
3157 : "LIST\n"
3158 : " COMPONENT_VALUE\n"
3159 : " ARG\n"
3160 : // #first #second
3161 : " HASH \"first\"\n"
3162 : " WHITESPACE\n"
3163 : " IDENTIFIER \"and\"\n"
3164 : " WHITESPACE\n"
3165 : " HASH \"second\"\n"
3166 : // {color:coral}
3167 : " OPEN_CURLYBRACKET B:true\n"
3168 : " DECLARATION \"color\"\n"
3169 : " ARG\n"
3170 : " COLOR H:ff507fff\n"
3171 :
3172 : );
3173 :
3174 1 : CATCH_REQUIRE(c.get_root() == n);
3175 1 : }
3176 1 : }
3177 :
3178 1 : CATCH_TEST_CASE("Invalid simple terms", "[compiler] [invalid]")
3179 : {
3180 : // two terms in one :not(...)
3181 : {
3182 1 : std::stringstream ss;
3183 1 : ss << "div:not(.red.blue) {color:coral}";
3184 3 : csspp::position pos("test.css");
3185 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
3186 :
3187 2 : csspp::parser p(l);
3188 :
3189 1 : csspp::node::pointer_t n(p.stylesheet());
3190 :
3191 : // no errors so far
3192 1 : VERIFY_ERRORS("");
3193 :
3194 1 : csspp::compiler c;
3195 1 : c.set_root(n);
3196 1 : c.clear_paths();
3197 1 : c.add_path(csspp_test::get_script_path());
3198 1 : c.add_path(csspp_test::get_version_script_path());
3199 :
3200 1 : c.compile(true);
3201 :
3202 1 : VERIFY_ERRORS("test.css(1): error: the :not() function accepts at most one simple term.\n");
3203 :
3204 1 : CATCH_REQUIRE(c.get_root() == n);
3205 1 : }
3206 :
3207 : // scope must be followed by * or IDENTIFIER
3208 : {
3209 1 : std::stringstream ss;
3210 1 : ss << "*| {color:red}";
3211 3 : csspp::position pos("test.css");
3212 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
3213 :
3214 2 : csspp::parser p(l);
3215 :
3216 1 : csspp::node::pointer_t n(p.stylesheet());
3217 :
3218 : // no errors so far
3219 1 : VERIFY_ERRORS("");
3220 :
3221 1 : csspp::compiler c;
3222 1 : c.set_root(n);
3223 1 : c.clear_paths();
3224 1 : c.add_path(csspp_test::get_script_path());
3225 1 : c.add_path(csspp_test::get_version_script_path());
3226 :
3227 1 : c.compile(true);
3228 :
3229 1 : VERIFY_ERRORS("test.css(1): error: the scope operator (|) requires a right hand side identifier or '*'.\n");
3230 :
3231 1 : CATCH_REQUIRE(c.get_root() == n);
3232 1 : }
3233 :
3234 : // scope must be followed by * or IDENTIFIER
3235 : {
3236 1 : std::stringstream ss;
3237 1 : ss << "*|.white {color:red}";
3238 3 : csspp::position pos("test.css");
3239 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
3240 :
3241 2 : csspp::parser p(l);
3242 :
3243 1 : csspp::node::pointer_t n(p.stylesheet());
3244 :
3245 : // no errors so far
3246 1 : VERIFY_ERRORS("");
3247 :
3248 1 : csspp::compiler c;
3249 1 : c.set_root(n);
3250 1 : c.clear_paths();
3251 1 : c.add_path(csspp_test::get_script_path());
3252 1 : c.add_path(csspp_test::get_version_script_path());
3253 :
3254 1 : c.compile(true);
3255 :
3256 1 : VERIFY_ERRORS("test.css(1): error: the right hand side of a scope operator (|) must be an identifier or '*'.\n");
3257 :
3258 1 : CATCH_REQUIRE(c.get_root() == n);
3259 1 : }
3260 :
3261 : // scope must be followed by * or IDENTIFIER
3262 : {
3263 1 : std::stringstream ss;
3264 1 : ss << "div.white | {color:red}";
3265 3 : csspp::position pos("test.css");
3266 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
3267 :
3268 2 : csspp::parser p(l);
3269 :
3270 1 : csspp::node::pointer_t n(p.stylesheet());
3271 :
3272 : // no errors so far
3273 1 : VERIFY_ERRORS("");
3274 :
3275 1 : csspp::compiler c;
3276 1 : c.set_root(n);
3277 1 : c.clear_paths();
3278 1 : c.add_path(csspp_test::get_script_path());
3279 1 : c.add_path(csspp_test::get_version_script_path());
3280 :
3281 1 : c.compile(true);
3282 :
3283 1 : VERIFY_ERRORS("test.css(1): error: a scope selector (|) must be followed by an identifier or '*'.\n");
3284 :
3285 1 : CATCH_REQUIRE(c.get_root() == n);
3286 1 : }
3287 :
3288 : // scope must be followed by * or IDENTIFIER
3289 : {
3290 1 : std::stringstream ss;
3291 1 : ss << "div.white |#hash {color:red}";
3292 3 : csspp::position pos("test.css");
3293 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
3294 :
3295 2 : csspp::parser p(l);
3296 :
3297 1 : csspp::node::pointer_t n(p.stylesheet());
3298 :
3299 : // no errors so far
3300 1 : VERIFY_ERRORS("");
3301 :
3302 1 : csspp::compiler c;
3303 1 : c.set_root(n);
3304 1 : c.clear_paths();
3305 1 : c.add_path(csspp_test::get_script_path());
3306 1 : c.add_path(csspp_test::get_version_script_path());
3307 :
3308 1 : c.compile(true);
3309 :
3310 1 : VERIFY_ERRORS("test.css(1): error: the right hand side of a scope operator (|) must be an identifier or '*'.\n");
3311 :
3312 1 : CATCH_REQUIRE(c.get_root() == n);
3313 1 : }
3314 :
3315 : // scope must be followed by * or IDENTIFIER
3316 : {
3317 1 : std::stringstream ss;
3318 1 : ss << "#hash and #hash {color:red}";
3319 3 : csspp::position pos("test.css");
3320 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
3321 :
3322 2 : csspp::parser p(l);
3323 :
3324 1 : csspp::node::pointer_t n(p.stylesheet());
3325 :
3326 : // no errors so far
3327 1 : VERIFY_ERRORS("");
3328 :
3329 1 : csspp::compiler c;
3330 1 : c.set_root(n);
3331 1 : c.clear_paths();
3332 1 : c.add_path(csspp_test::get_script_path());
3333 1 : c.add_path(csspp_test::get_version_script_path());
3334 :
3335 1 : c.compile(true);
3336 :
3337 1 : VERIFY_ERRORS("test.css(1): error: found #hash twice in selector: \"#hash and #hash\".\n");
3338 :
3339 1 : CATCH_REQUIRE(c.get_root() == n);
3340 1 : }
3341 :
3342 : // ':' must be followed by an IDENTIFIER or a FUNCTION
3343 : {
3344 1 : std::stringstream ss;
3345 1 : ss << "div.white : {color:red}";
3346 3 : csspp::position pos("test.css");
3347 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
3348 :
3349 2 : csspp::parser p(l);
3350 :
3351 1 : csspp::node::pointer_t n(p.stylesheet());
3352 :
3353 : // no errors so far
3354 1 : VERIFY_ERRORS("");
3355 :
3356 1 : csspp::compiler c;
3357 1 : c.set_root(n);
3358 1 : c.clear_paths();
3359 1 : c.add_path(csspp_test::get_script_path());
3360 1 : c.add_path(csspp_test::get_version_script_path());
3361 :
3362 1 : c.compile(true);
3363 :
3364 1 : VERIFY_ERRORS("test.css(1): error: a selector list cannot end with a standalone ':'.\n");
3365 :
3366 1 : CATCH_REQUIRE(c.get_root() == n);
3367 1 : }
3368 :
3369 : // ':' must be followed a known pseudo-class name
3370 : {
3371 1 : std::stringstream ss;
3372 1 : ss << "div.white :unknown {color:red}";
3373 3 : csspp::position pos("test.css");
3374 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
3375 :
3376 2 : csspp::parser p(l);
3377 :
3378 1 : csspp::node::pointer_t n(p.stylesheet());
3379 :
3380 : // no errors so far
3381 1 : VERIFY_ERRORS("");
3382 :
3383 1 : csspp::compiler c;
3384 1 : c.set_root(n);
3385 1 : c.clear_paths();
3386 1 : c.add_path(csspp_test::get_script_path());
3387 1 : c.add_path(csspp_test::get_version_script_path());
3388 :
3389 1 : c.compile(true);
3390 :
3391 1 : VERIFY_ERRORS("scripts/validation/pseudo-classes.scss(38): error: unknown is not a valid name for a pseudo class; CSS only supports root, first-child, last-child, first-of-type, last-of-type, only-child, only-of-type, empty, link, visitived, active, hover, focus, target, enabled, disabled, and checked. (functions are not included in this list since you did not use '(' at the end of the word.)\n");
3392 :
3393 1 : CATCH_REQUIRE(c.get_root() == n);
3394 1 : }
3395 :
3396 : // ':' must be followed a known pseudo-function name
3397 : {
3398 1 : std::stringstream ss;
3399 1 : ss << "div.white :unknown() {color:red}";
3400 3 : csspp::position pos("test.css");
3401 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
3402 :
3403 2 : csspp::parser p(l);
3404 :
3405 1 : csspp::node::pointer_t n(p.stylesheet());
3406 :
3407 : // no errors so far
3408 1 : VERIFY_ERRORS("");
3409 :
3410 1 : csspp::compiler c;
3411 1 : c.set_root(n);
3412 1 : c.clear_paths();
3413 1 : c.add_path(csspp_test::get_script_path());
3414 1 : c.add_path(csspp_test::get_version_script_path());
3415 :
3416 1 : c.compile(true);
3417 :
3418 1 : VERIFY_ERRORS("scripts/validation/pseudo-functions.scss(20): error: unknown is not a valid name for a pseudo function; CSS only supports lang() and not().\n");
3419 :
3420 1 : CATCH_REQUIRE(c.get_root() == n);
3421 1 : }
3422 :
3423 : // ':' must be followed an identifier or a function
3424 : {
3425 1 : std::stringstream ss;
3426 1 : ss << "div.white :.shark {color:red}";
3427 3 : csspp::position pos("test.css");
3428 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
3429 :
3430 2 : csspp::parser p(l);
3431 :
3432 1 : csspp::node::pointer_t n(p.stylesheet());
3433 :
3434 : // no errors so far
3435 1 : VERIFY_ERRORS("");
3436 :
3437 1 : csspp::compiler c;
3438 1 : c.set_root(n);
3439 1 : c.clear_paths();
3440 1 : c.add_path(csspp_test::get_script_path());
3441 1 : c.add_path(csspp_test::get_version_script_path());
3442 :
3443 1 : c.compile(true);
3444 :
3445 1 : VERIFY_ERRORS("test.css(1): error: a ':' selector must be followed by an identifier or a function, a PERIOD was found instead.\n");
3446 :
3447 1 : CATCH_REQUIRE(c.get_root() == n);
3448 1 : }
3449 :
3450 : // '>' at the wrong place
3451 : {
3452 1 : std::stringstream ss;
3453 1 : ss << "div.white > {color:red}";
3454 3 : csspp::position pos("test.css");
3455 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
3456 :
3457 2 : csspp::parser p(l);
3458 :
3459 1 : csspp::node::pointer_t n(p.stylesheet());
3460 :
3461 : // no errors so far
3462 1 : VERIFY_ERRORS("");
3463 :
3464 1 : csspp::compiler c;
3465 1 : c.set_root(n);
3466 1 : c.clear_paths();
3467 1 : c.add_path(csspp_test::get_script_path());
3468 1 : c.add_path(csspp_test::get_version_script_path());
3469 :
3470 1 : c.compile(true);
3471 :
3472 1 : VERIFY_ERRORS("test.css(1): error: found token GREATER_THAN, which is expected to be followed by another selector term.\n");
3473 :
3474 1 : CATCH_REQUIRE(c.get_root() == n);
3475 1 : }
3476 :
3477 : // :not(INTEGER) is not good
3478 : {
3479 1 : std::stringstream ss;
3480 1 : ss << "div.white:not(11) {color:red}";
3481 3 : csspp::position pos("test.css");
3482 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
3483 :
3484 2 : csspp::parser p(l);
3485 :
3486 1 : csspp::node::pointer_t n(p.stylesheet());
3487 :
3488 : // no errors so far
3489 1 : VERIFY_ERRORS("");
3490 :
3491 1 : csspp::compiler c;
3492 1 : c.set_root(n);
3493 1 : c.clear_paths();
3494 1 : c.add_path(csspp_test::get_script_path());
3495 1 : c.add_path(csspp_test::get_version_script_path());
3496 :
3497 1 : c.compile(true);
3498 :
3499 1 : VERIFY_ERRORS("test.css(1): error: found token INTEGER, which is not a valid selector token (simple term).\n");
3500 :
3501 1 : CATCH_REQUIRE(c.get_root() == n);
3502 1 : }
3503 :
3504 : // :not(FUNCTION) is not good
3505 : {
3506 1 : std::stringstream ss;
3507 1 : ss << "div.white:not(func()) {color:red}";
3508 3 : csspp::position pos("test.css");
3509 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
3510 :
3511 2 : csspp::parser p(l);
3512 :
3513 1 : csspp::node::pointer_t n(p.stylesheet());
3514 :
3515 : // no errors so far
3516 1 : VERIFY_ERRORS("");
3517 :
3518 1 : csspp::compiler c;
3519 1 : c.set_root(n);
3520 1 : c.clear_paths();
3521 1 : c.add_path(csspp_test::get_script_path());
3522 1 : c.add_path(csspp_test::get_version_script_path());
3523 :
3524 1 : c.compile(true);
3525 :
3526 1 : VERIFY_ERRORS("test.css(1): error: found function \"func()\", which may be a valid selector token but only if immediately preceeded by one ':' (simple term).\n");
3527 :
3528 1 : CATCH_REQUIRE(c.get_root() == n);
3529 1 : }
3530 :
3531 : // :not(>) is not good
3532 : {
3533 1 : std::stringstream ss;
3534 1 : ss << "div.white:not(>) {color:red}";
3535 3 : csspp::position pos("test.css");
3536 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
3537 :
3538 2 : csspp::parser p(l);
3539 :
3540 1 : csspp::node::pointer_t n(p.stylesheet());
3541 :
3542 : // no errors so far
3543 1 : VERIFY_ERRORS("");
3544 :
3545 1 : csspp::compiler c;
3546 1 : c.set_root(n);
3547 1 : c.clear_paths();
3548 1 : c.add_path(csspp_test::get_script_path());
3549 1 : c.add_path(csspp_test::get_version_script_path());
3550 :
3551 1 : c.compile(true);
3552 :
3553 1 : VERIFY_ERRORS("test.css(1): error: found token GREATER_THAN, which cannot be used to start a selector expression.\n");
3554 :
3555 1 : CATCH_REQUIRE(c.get_root() == n);
3556 1 : }
3557 :
3558 : // :not(+) is not good
3559 : {
3560 1 : std::stringstream ss;
3561 1 : ss << "div.white:not(+) {color:red}";
3562 3 : csspp::position pos("test.css");
3563 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
3564 :
3565 2 : csspp::parser p(l);
3566 :
3567 1 : csspp::node::pointer_t n(p.stylesheet());
3568 :
3569 : // no errors so far
3570 1 : VERIFY_ERRORS("");
3571 :
3572 1 : csspp::compiler c;
3573 1 : c.set_root(n);
3574 1 : c.clear_paths();
3575 1 : c.add_path(csspp_test::get_script_path());
3576 1 : c.add_path(csspp_test::get_version_script_path());
3577 :
3578 1 : c.compile(true);
3579 :
3580 1 : VERIFY_ERRORS("test.css(1): error: found token ADD, which cannot be used to start a selector expression.\n");
3581 :
3582 1 : CATCH_REQUIRE(c.get_root() == n);
3583 1 : }
3584 :
3585 : // :not(~) is not good
3586 : {
3587 1 : std::stringstream ss;
3588 1 : ss << "div.white:not(~) {color:red}";
3589 3 : csspp::position pos("test.css");
3590 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
3591 :
3592 2 : csspp::parser p(l);
3593 :
3594 1 : csspp::node::pointer_t n(p.stylesheet());
3595 :
3596 : // no errors so far
3597 1 : VERIFY_ERRORS("");
3598 :
3599 1 : csspp::compiler c;
3600 1 : c.set_root(n);
3601 1 : c.clear_paths();
3602 1 : c.add_path(csspp_test::get_script_path());
3603 1 : c.add_path(csspp_test::get_version_script_path());
3604 :
3605 1 : c.compile(true);
3606 :
3607 1 : VERIFY_ERRORS("test.css(1): error: found token PRECEDED, which cannot be used to start a selector expression.\n");
3608 :
3609 1 : CATCH_REQUIRE(c.get_root() == n);
3610 1 : }
3611 :
3612 : // :not(:) is not good
3613 : {
3614 1 : std::stringstream ss;
3615 1 : ss << "div.white:not(:) {color:red}";
3616 3 : csspp::position pos("test.css");
3617 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
3618 :
3619 2 : csspp::parser p(l);
3620 :
3621 1 : csspp::node::pointer_t n(p.stylesheet());
3622 :
3623 : // no errors so far
3624 1 : VERIFY_ERRORS("");
3625 :
3626 1 : csspp::compiler c;
3627 1 : c.set_root(n);
3628 1 : c.clear_paths();
3629 1 : c.add_path(csspp_test::get_script_path());
3630 1 : c.add_path(csspp_test::get_version_script_path());
3631 :
3632 1 : c.compile(true);
3633 :
3634 1 : VERIFY_ERRORS("test.css(1): error: a selector list cannot end with a standalone ':'.\n");
3635 :
3636 1 : CATCH_REQUIRE(c.get_root() == n);
3637 1 : }
3638 :
3639 : // '.' by itself (at the end)
3640 : {
3641 1 : std::stringstream ss;
3642 1 : ss << "div.lone . {color:red}";
3643 3 : csspp::position pos("test.css");
3644 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
3645 :
3646 2 : csspp::parser p(l);
3647 :
3648 1 : csspp::node::pointer_t n(p.stylesheet());
3649 :
3650 : // no errors so far
3651 1 : VERIFY_ERRORS("");
3652 :
3653 1 : csspp::compiler c;
3654 1 : c.set_root(n);
3655 1 : c.clear_paths();
3656 1 : c.add_path(csspp_test::get_script_path());
3657 1 : c.add_path(csspp_test::get_version_script_path());
3658 :
3659 1 : c.compile(true);
3660 :
3661 1 : VERIFY_ERRORS("test.css(1): error: a selector list cannot end with a standalone '.'.\n");
3662 :
3663 1 : CATCH_REQUIRE(c.get_root() == n);
3664 1 : }
3665 :
3666 : // '.' must be followed by IDENTIFIER
3667 : {
3668 1 : std::stringstream ss;
3669 1 : ss << "div.lone .< {color:red}";
3670 3 : csspp::position pos("test.css");
3671 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
3672 :
3673 2 : csspp::parser p(l);
3674 :
3675 1 : csspp::node::pointer_t n(p.stylesheet());
3676 :
3677 : // no errors so far
3678 1 : VERIFY_ERRORS("");
3679 :
3680 1 : csspp::compiler c;
3681 1 : c.set_root(n);
3682 1 : c.clear_paths();
3683 1 : c.add_path(csspp_test::get_script_path());
3684 1 : c.add_path(csspp_test::get_version_script_path());
3685 :
3686 1 : c.compile(true);
3687 :
3688 1 : VERIFY_ERRORS("test.css(1): error: a class selector (after a period: '.') must be an identifier.\n");
3689 :
3690 1 : CATCH_REQUIRE(c.get_root() == n);
3691 1 : }
3692 :
3693 : // test an invalid An+B in an :nth-child() function
3694 : {
3695 1 : std::stringstream ss;
3696 1 : ss << "div:nth-child(3+5) {color:red}";
3697 3 : csspp::position pos("test.css");
3698 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
3699 :
3700 2 : csspp::parser p(l);
3701 :
3702 1 : csspp::node::pointer_t n(p.stylesheet());
3703 :
3704 : // no errors so far
3705 1 : VERIFY_ERRORS("");
3706 :
3707 1 : csspp::compiler c;
3708 1 : c.set_root(n);
3709 1 : c.clear_paths();
3710 1 : c.add_path(csspp_test::get_script_path());
3711 1 : c.add_path(csspp_test::get_version_script_path());
3712 :
3713 1 : c.compile(true);
3714 :
3715 1 : VERIFY_ERRORS("test.css(1): error: The first number has to be followed by the 'n' character.\n");
3716 :
3717 1 : CATCH_REQUIRE(c.get_root() == n);
3718 1 : }
3719 :
3720 : // :not(:not(...))
3721 : {
3722 1 : std::stringstream ss;
3723 1 : ss << "div:not(:not(.red)) {color:red}";
3724 3 : csspp::position pos("test.css");
3725 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
3726 :
3727 2 : csspp::parser p(l);
3728 :
3729 1 : csspp::node::pointer_t n(p.stylesheet());
3730 :
3731 : // no errors so far
3732 1 : VERIFY_ERRORS("");
3733 :
3734 1 : csspp::compiler c;
3735 1 : c.set_root(n);
3736 1 : c.clear_paths();
3737 1 : c.add_path(csspp_test::get_script_path());
3738 1 : c.add_path(csspp_test::get_version_script_path());
3739 :
3740 1 : c.compile(true);
3741 :
3742 1 : VERIFY_ERRORS("test.css(1): error: the :not() selector does not accept an inner :not().\n");
3743 :
3744 1 : CATCH_REQUIRE(c.get_root() == n);
3745 1 : }
3746 :
3747 : // :not(:.white)
3748 : {
3749 1 : std::stringstream ss;
3750 1 : ss << "div:not(:.white) {color:red}";
3751 3 : csspp::position pos("test.css");
3752 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
3753 :
3754 2 : csspp::parser p(l);
3755 :
3756 1 : csspp::node::pointer_t n(p.stylesheet());
3757 :
3758 : // no errors so far
3759 1 : VERIFY_ERRORS("");
3760 :
3761 1 : csspp::compiler c;
3762 1 : c.set_root(n);
3763 1 : c.clear_paths();
3764 1 : c.add_path(csspp_test::get_script_path());
3765 1 : c.add_path(csspp_test::get_version_script_path());
3766 :
3767 1 : c.compile(true);
3768 :
3769 1 : VERIFY_ERRORS("test.css(1): error: a ':' selector must be followed by an identifier or a function, a FUNCTION was found instead.\n");
3770 :
3771 1 : CATCH_REQUIRE(c.get_root() == n);
3772 1 : }
3773 :
3774 : // :lang() accepts only one argument
3775 : {
3776 1 : std::stringstream ss;
3777 1 : ss << "div:lang(red blue) {color:bisque}";
3778 3 : csspp::position pos("test.css");
3779 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
3780 :
3781 2 : csspp::parser p(l);
3782 :
3783 1 : csspp::node::pointer_t n(p.stylesheet());
3784 :
3785 : // no errors so far
3786 1 : VERIFY_ERRORS("");
3787 :
3788 1 : csspp::compiler c;
3789 1 : c.set_root(n);
3790 1 : c.clear_paths();
3791 1 : c.add_path(csspp_test::get_script_path());
3792 1 : c.add_path(csspp_test::get_version_script_path());
3793 :
3794 1 : c.compile(true);
3795 :
3796 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
3797 :
3798 1 : VERIFY_ERRORS("test.css(1): error: a lang() function selector must have exactly one identifier as its parameter.\n");
3799 :
3800 1 : CATCH_REQUIRE(c.get_root() == n);
3801 1 : }
3802 :
3803 : // invalid name for :lang()
3804 : {
3805 1 : std::stringstream ss;
3806 1 : ss << "div:lang(notalanguagename) {color:bisque}";
3807 3 : csspp::position pos("test.css");
3808 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
3809 :
3810 2 : csspp::parser p(l);
3811 :
3812 1 : csspp::node::pointer_t n(p.stylesheet());
3813 :
3814 : // no errors so far
3815 1 : VERIFY_ERRORS("");
3816 :
3817 1 : csspp::compiler c;
3818 1 : c.set_root(n);
3819 1 : c.clear_paths();
3820 1 : c.add_path(csspp_test::get_script_path());
3821 1 : c.add_path(csspp_test::get_version_script_path());
3822 :
3823 1 : c.compile(true);
3824 :
3825 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
3826 :
3827 1 : VERIFY_ERRORS("scripts/validation/languages.scss(154): error: notalanguagename is not a valid language name for :lang().\n");
3828 :
3829 1 : CATCH_REQUIRE(c.get_root() == n);
3830 1 : }
3831 :
3832 : // invalid name for :lang(), with a valid country
3833 : {
3834 1 : std::stringstream ss;
3835 1 : ss << "div:lang(stillnotalanguagename-us) {color:bisque}";
3836 3 : csspp::position pos("test.css");
3837 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
3838 :
3839 2 : csspp::parser p(l);
3840 :
3841 1 : csspp::node::pointer_t n(p.stylesheet());
3842 :
3843 : // no errors so far
3844 1 : VERIFY_ERRORS("");
3845 :
3846 1 : csspp::compiler c;
3847 1 : c.set_root(n);
3848 1 : c.clear_paths();
3849 1 : c.add_path(csspp_test::get_script_path());
3850 1 : c.add_path(csspp_test::get_version_script_path());
3851 :
3852 1 : c.compile(true);
3853 :
3854 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
3855 :
3856 1 : VERIFY_ERRORS("scripts/validation/languages.scss(154): error: stillnotalanguagename is not a valid language name for :lang().\n");
3857 :
3858 1 : CATCH_REQUIRE(c.get_root() == n);
3859 1 : }
3860 :
3861 : // invalid name for :lang(), with a valid country
3862 : {
3863 1 : std::stringstream ss;
3864 1 : ss << "div:lang(mn-withaninvalidcountry-andmore) {color:bisque}";
3865 3 : csspp::position pos("test.css");
3866 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
3867 :
3868 2 : csspp::parser p(l);
3869 :
3870 1 : csspp::node::pointer_t n(p.stylesheet());
3871 :
3872 : // no errors so far
3873 1 : VERIFY_ERRORS("");
3874 :
3875 1 : csspp::compiler c;
3876 1 : c.set_root(n);
3877 1 : c.clear_paths();
3878 1 : c.add_path(csspp_test::get_script_path());
3879 1 : c.add_path(csspp_test::get_version_script_path());
3880 :
3881 1 : c.compile(true);
3882 :
3883 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
3884 :
3885 1 : VERIFY_ERRORS("scripts/validation/countries.scss(267): error: withaninvalidcountry is not a valid country name for :lang().\n");
3886 :
3887 1 : CATCH_REQUIRE(c.get_root() == n);
3888 1 : }
3889 :
3890 : // :lang() name must be an identifier
3891 : {
3892 1 : std::stringstream ss;
3893 1 : ss << "div:lang(\"de\") {color:bisque}";
3894 3 : csspp::position pos("test.css");
3895 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
3896 :
3897 2 : csspp::parser p(l);
3898 :
3899 1 : csspp::node::pointer_t n(p.stylesheet());
3900 :
3901 : // no errors so far
3902 1 : VERIFY_ERRORS("");
3903 :
3904 1 : csspp::compiler c;
3905 1 : c.set_root(n);
3906 1 : c.clear_paths();
3907 1 : c.add_path(csspp_test::get_script_path());
3908 1 : c.add_path(csspp_test::get_version_script_path());
3909 :
3910 1 : c.compile(true);
3911 :
3912 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
3913 :
3914 1 : VERIFY_ERRORS("test.css(1): error: a lang() function selector expects an identifier as its parameter.\n");
3915 :
3916 1 : CATCH_REQUIRE(c.get_root() == n);
3917 1 : }
3918 :
3919 : // no left over?
3920 1 : VERIFY_ERRORS("");
3921 1 : }
3922 :
3923 8 : CATCH_TEST_CASE("Complex terms", "[compiler] [stylesheet]")
3924 : {
3925 : // [complex] terms are:
3926 : // term: simple-term
3927 : // | PLACEHOLDER
3928 : // | REFERENCE
3929 : // | ':' FUNCTION (="not") component-value-list ')'
3930 : // | ':' ':' IDENTIFIER
3931 :
3932 8 : CATCH_START_SECTION("test a placeholder")
3933 : {
3934 1 : std::stringstream ss;
3935 : ss << "div p%image"
3936 1 : << "{color:blue}";
3937 3 : csspp::position pos("test.css");
3938 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
3939 :
3940 2 : csspp::parser p(l);
3941 :
3942 1 : csspp::node::pointer_t n(p.stylesheet());
3943 :
3944 : //std::cerr << "Parser result is: [" << *n << "]\n";
3945 :
3946 : // no errors so far
3947 1 : VERIFY_ERRORS("");
3948 :
3949 1 : csspp::compiler c;
3950 1 : c.set_root(n);
3951 1 : c.clear_paths();
3952 1 : c.add_path(csspp_test::get_script_path());
3953 1 : c.add_path(csspp_test::get_version_script_path());
3954 :
3955 1 : c.compile(true);
3956 :
3957 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
3958 :
3959 : // no error left over
3960 1 : VERIFY_ERRORS("");
3961 :
3962 1 : std::stringstream out;
3963 1 : out << *n;
3964 1 : VERIFY_TREES(out.str(),
3965 :
3966 : "LIST\n"
3967 : " COMPONENT_VALUE\n"
3968 : " ARG\n"
3969 : // #abd
3970 : " IDENTIFIER \"div\"\n"
3971 : " WHITESPACE\n"
3972 : // identifier
3973 : " IDENTIFIER \"p\"\n"
3974 : " PLACEHOLDER \"image\"\n"
3975 : // {color:blue}
3976 : " OPEN_CURLYBRACKET B:true\n"
3977 : " DECLARATION \"color\"\n"
3978 : " ARG\n"
3979 : " COLOR H:ffff0000\n"
3980 :
3981 : );
3982 :
3983 : // no error left over
3984 1 : VERIFY_ERRORS("");
3985 :
3986 1 : CATCH_REQUIRE(c.get_root() == n);
3987 1 : }
3988 8 : CATCH_END_SECTION()
3989 :
3990 8 : CATCH_START_SECTION("test a reference")
3991 : {
3992 1 : std::stringstream ss;
3993 : ss << "div a"
3994 1 : << "{color:blue;&:hover{color:red}}";
3995 3 : csspp::position pos("test.css");
3996 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
3997 :
3998 2 : csspp::parser p(l);
3999 :
4000 1 : csspp::node::pointer_t n(p.stylesheet());
4001 :
4002 : // no errors so far
4003 1 : VERIFY_ERRORS("");
4004 :
4005 1 : csspp::compiler c;
4006 1 : c.set_root(n);
4007 1 : c.clear_paths();
4008 1 : c.add_path(csspp_test::get_script_path());
4009 1 : c.add_path(csspp_test::get_version_script_path());
4010 :
4011 1 : c.compile(true);
4012 :
4013 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
4014 :
4015 : // no error left over
4016 1 : VERIFY_ERRORS("");
4017 :
4018 1 : std::stringstream out;
4019 1 : out << *n;
4020 1 : VERIFY_TREES(out.str(),
4021 :
4022 : "LIST\n"
4023 : " COMPONENT_VALUE\n"
4024 : " ARG\n"
4025 : // #abd
4026 : " IDENTIFIER \"div\"\n"
4027 : " WHITESPACE\n"
4028 : // identifier
4029 : " IDENTIFIER \"a\"\n"
4030 : // {color:blue}
4031 : " OPEN_CURLYBRACKET B:true\n"
4032 : " LIST\n"
4033 : " DECLARATION \"color\"\n"
4034 : " ARG\n"
4035 : " COLOR H:ffff0000\n"
4036 : " COMPONENT_VALUE\n"
4037 : " ARG\n"
4038 : // &:hover
4039 : " IDENTIFIER \"div\"\n"
4040 : " WHITESPACE\n"
4041 : " IDENTIFIER \"a\"\n"
4042 : " COLON\n"
4043 : " IDENTIFIER \"hover\"\n"
4044 : " OPEN_CURLYBRACKET B:true\n"
4045 : " DECLARATION \"color\"\n"
4046 : " ARG\n"
4047 : " COLOR H:ff0000ff\n"
4048 :
4049 : );
4050 :
4051 : // no error left over
4052 1 : VERIFY_ERRORS("");
4053 :
4054 1 : CATCH_REQUIRE(c.get_root() == n);
4055 1 : }
4056 8 : CATCH_END_SECTION()
4057 :
4058 8 : CATCH_START_SECTION("test the not() function")
4059 : {
4060 1 : std::stringstream ss;
4061 : ss << "div a:not(:hover)"
4062 1 : << "{color:#175}";
4063 3 : csspp::position pos("test.css");
4064 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
4065 :
4066 2 : csspp::parser p(l);
4067 :
4068 1 : csspp::node::pointer_t n(p.stylesheet());
4069 :
4070 : // no errors so far
4071 1 : VERIFY_ERRORS("");
4072 :
4073 1 : csspp::compiler c;
4074 1 : c.set_root(n);
4075 1 : c.clear_paths();
4076 1 : c.add_path(csspp_test::get_script_path());
4077 1 : c.add_path(csspp_test::get_version_script_path());
4078 :
4079 1 : c.compile(true);
4080 :
4081 : // no error left over
4082 1 : VERIFY_ERRORS("");
4083 :
4084 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
4085 :
4086 1 : std::stringstream out;
4087 1 : out << *n;
4088 1 : VERIFY_TREES(out.str(),
4089 :
4090 : "LIST\n"
4091 : " COMPONENT_VALUE\n"
4092 : " ARG\n"
4093 : // #abd
4094 : " IDENTIFIER \"div\"\n"
4095 : " WHITESPACE\n"
4096 : // identifier
4097 : " IDENTIFIER \"a\"\n"
4098 : " COLON\n"
4099 : " FUNCTION \"not\"\n"
4100 : " COLON\n"
4101 : " IDENTIFIER \"hover\"\n"
4102 : // {color:blue}
4103 : " OPEN_CURLYBRACKET B:true\n"
4104 : " DECLARATION \"color\"\n"
4105 : " ARG\n"
4106 : " COLOR H:ff557711\n"
4107 :
4108 : );
4109 :
4110 : // no error left over
4111 1 : VERIFY_ERRORS("");
4112 :
4113 1 : CATCH_REQUIRE(c.get_root() == n);
4114 1 : }
4115 8 : CATCH_END_SECTION()
4116 :
4117 8 : CATCH_START_SECTION("test the not() function + a sub-function")
4118 : {
4119 1 : std::stringstream ss;
4120 : ss << "div a:not(:nth-last-of-type(5n+3))"
4121 1 : << "{color:#175}";
4122 3 : csspp::position pos("test.css");
4123 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
4124 :
4125 2 : csspp::parser p(l);
4126 :
4127 1 : csspp::node::pointer_t n(p.stylesheet());
4128 :
4129 : // no errors so far
4130 1 : VERIFY_ERRORS("");
4131 :
4132 1 : csspp::compiler c;
4133 1 : c.set_root(n);
4134 1 : c.clear_paths();
4135 1 : c.add_path(csspp_test::get_script_path());
4136 1 : c.add_path(csspp_test::get_version_script_path());
4137 :
4138 1 : c.compile(true);
4139 :
4140 : // no error left over
4141 1 : VERIFY_ERRORS("");
4142 :
4143 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
4144 :
4145 1 : std::stringstream out;
4146 1 : out << *n;
4147 1 : VERIFY_TREES(out.str(),
4148 :
4149 : "LIST\n"
4150 : " COMPONENT_VALUE\n"
4151 : " ARG\n"
4152 : // #abd
4153 : " IDENTIFIER \"div\"\n"
4154 : " WHITESPACE\n"
4155 : // identifier
4156 : " IDENTIFIER \"a\"\n"
4157 : " COLON\n"
4158 : " FUNCTION \"not\"\n"
4159 : " COLON\n"
4160 : " FUNCTION \"nth-last-of-type\"\n"
4161 : " AN_PLUS_B S:5n+3\n"
4162 : // {color:blue}
4163 : " OPEN_CURLYBRACKET B:true\n"
4164 : " DECLARATION \"color\"\n"
4165 : " ARG\n"
4166 : " COLOR H:ff557711\n"
4167 :
4168 : );
4169 :
4170 : // no error left over
4171 1 : VERIFY_ERRORS("");
4172 :
4173 1 : CATCH_REQUIRE(c.get_root() == n);
4174 1 : }
4175 8 : CATCH_END_SECTION()
4176 :
4177 8 : CATCH_START_SECTION("check all pseudo-elements")
4178 : {
4179 1 : char const * pseudo_name_table[] =
4180 : {
4181 : "first-line",
4182 : "first-letter",
4183 : "before",
4184 : "after"
4185 : };
4186 :
4187 5 : for(auto pseudo_name : pseudo_name_table)
4188 : {
4189 4 : std::stringstream ss;
4190 : ss << "div ::"
4191 : << pseudo_name
4192 4 : << "{color:teal}\n";
4193 12 : csspp::position pos("test.css");
4194 4 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
4195 :
4196 8 : csspp::parser p(l);
4197 :
4198 4 : csspp::node::pointer_t n(p.stylesheet());
4199 :
4200 : // no errors so far
4201 4 : VERIFY_ERRORS("");
4202 :
4203 4 : csspp::compiler c;
4204 4 : c.set_root(n);
4205 4 : c.clear_paths();
4206 4 : c.add_path(csspp_test::get_script_path());
4207 4 : c.add_path(csspp_test::get_version_script_path());
4208 :
4209 4 : c.compile(true);
4210 :
4211 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
4212 :
4213 4 : std::stringstream out;
4214 4 : out << *n;
4215 4 : VERIFY_TREES(out.str(),
4216 :
4217 : "LIST\n"
4218 : " COMPONENT_VALUE\n"
4219 : " ARG\n"
4220 : " IDENTIFIER \"div\"\n"
4221 : " WHITESPACE\n"
4222 : " COLON\n"
4223 : " COLON\n"
4224 : " IDENTIFIER \"" + std::string(pseudo_name) + "\"\n"
4225 : " OPEN_CURLYBRACKET B:true\n"
4226 : " DECLARATION \"color\"\n"
4227 : " ARG\n"
4228 : " COLOR H:ff808000\n"
4229 :
4230 : );
4231 :
4232 4 : CATCH_REQUIRE(c.get_root() == n);
4233 4 : }
4234 :
4235 : // no error left over
4236 1 : VERIFY_ERRORS("");
4237 : }
4238 8 : CATCH_END_SECTION()
4239 :
4240 8 : CATCH_START_SECTION("check filter with alpha() function")
4241 : {
4242 1 : std::stringstream ss;
4243 : ss << "div {\n"
4244 : << " font: 15px/150% helvetica;\n"
4245 : << " filter: alpha(opacity=20);\n"
4246 1 : << "}\n";
4247 3 : csspp::position pos("test.css");
4248 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
4249 :
4250 2 : csspp::parser p(l);
4251 :
4252 1 : csspp::node::pointer_t n(p.stylesheet());
4253 :
4254 : // no errors so far
4255 1 : VERIFY_ERRORS("");
4256 :
4257 1 : csspp::compiler c;
4258 1 : c.set_root(n);
4259 1 : c.clear_paths();
4260 1 : c.add_path(csspp_test::get_script_path());
4261 1 : c.add_path(csspp_test::get_version_script_path());
4262 :
4263 1 : c.compile(true);
4264 :
4265 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
4266 :
4267 1 : VERIFY_ERRORS("test.css(3): warning: the alpha(), chroma() and similar functions of the filter field are Internet Explorer specific extensions which are not supported across browsers.\n");
4268 :
4269 1 : std::stringstream out;
4270 1 : out << *n;
4271 1 : VERIFY_TREES(out.str(),
4272 :
4273 : "LIST\n"
4274 : " COMPONENT_VALUE\n"
4275 : " ARG\n"
4276 : " IDENTIFIER \"div\"\n"
4277 : " OPEN_CURLYBRACKET B:true\n"
4278 : " LIST\n"
4279 : " DECLARATION \"font\"\n"
4280 : " ARG\n"
4281 : " FONT_METRICS FM:15px/150%\n"
4282 : " WHITESPACE\n"
4283 : " IDENTIFIER \"helvetica\"\n"
4284 : " DECLARATION \"filter\"\n"
4285 : " FUNCTION \"alpha\"\n"
4286 : " IDENTIFIER \"opacity\"\n"
4287 : " EQUAL\n"
4288 : " INTEGER \"\" I:20\n"
4289 :
4290 : );
4291 :
4292 1 : CATCH_REQUIRE(c.get_root() == n);
4293 :
4294 : // no error left over
4295 1 : VERIFY_ERRORS("");
4296 1 : }
4297 8 : CATCH_END_SECTION()
4298 :
4299 8 : CATCH_START_SECTION("check \"-filter\" with alpha() function")
4300 : {
4301 1 : std::stringstream ss;
4302 : ss << "div {\n"
4303 : << " font: 15px/150% helvetica;\n"
4304 : << " -filter: alpha(opacity=20);\n"
4305 1 : << "}\n";
4306 3 : csspp::position pos("test.css");
4307 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
4308 :
4309 2 : csspp::parser p(l);
4310 :
4311 1 : csspp::node::pointer_t n(p.stylesheet());
4312 :
4313 : // no errors so far
4314 1 : VERIFY_ERRORS("");
4315 :
4316 1 : csspp::compiler c;
4317 1 : c.set_root(n);
4318 1 : c.clear_paths();
4319 1 : c.add_path(csspp_test::get_script_path());
4320 1 : c.add_path(csspp_test::get_version_script_path());
4321 :
4322 1 : c.compile(true);
4323 :
4324 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
4325 :
4326 1 : VERIFY_ERRORS("test.css(3): warning: the alpha(), chroma() and similar functions of the filter field are Internet Explorer specific extensions which are not supported across browsers.\n");
4327 :
4328 1 : std::stringstream out;
4329 1 : out << *n;
4330 1 : VERIFY_TREES(out.str(),
4331 :
4332 : "LIST\n"
4333 : " COMPONENT_VALUE\n"
4334 : " ARG\n"
4335 : " IDENTIFIER \"div\"\n"
4336 : " OPEN_CURLYBRACKET B:true\n"
4337 : " LIST\n"
4338 : " DECLARATION \"font\"\n"
4339 : " ARG\n"
4340 : " FONT_METRICS FM:15px/150%\n"
4341 : " WHITESPACE\n"
4342 : " IDENTIFIER \"helvetica\"\n"
4343 : " DECLARATION \"-filter\"\n"
4344 : " FUNCTION \"alpha\"\n"
4345 : " IDENTIFIER \"opacity\"\n"
4346 : " EQUAL\n"
4347 : " INTEGER \"\" I:20\n"
4348 :
4349 : );
4350 :
4351 1 : CATCH_REQUIRE(c.get_root() == n);
4352 :
4353 : // no error left over
4354 1 : VERIFY_ERRORS("");
4355 1 : }
4356 8 : CATCH_END_SECTION()
4357 :
4358 8 : CATCH_START_SECTION("check progid:...")
4359 : {
4360 1 : std::stringstream ss;
4361 : ss << "div {\n"
4362 : << " -filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(opacity=20);\n"
4363 : << " font: 17.2px/1.35em;\n"
4364 1 : << "}\n";
4365 3 : csspp::position pos("test.css");
4366 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
4367 :
4368 2 : csspp::parser p(l);
4369 :
4370 1 : csspp::node::pointer_t n(p.stylesheet());
4371 :
4372 : // no errors so far
4373 1 : VERIFY_ERRORS("");
4374 :
4375 1 : csspp::compiler c;
4376 1 : c.set_root(n);
4377 1 : c.clear_paths();
4378 1 : c.add_path(csspp_test::get_script_path());
4379 1 : c.add_path(csspp_test::get_version_script_path());
4380 :
4381 1 : c.compile(true);
4382 :
4383 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
4384 :
4385 1 : VERIFY_ERRORS("test.css(2): warning: the alpha(), chroma() and similar functions of the filter field are Internet Explorer specific extensions which are not supported across browsers.\n");
4386 :
4387 1 : std::stringstream out;
4388 1 : out << *n;
4389 1 : VERIFY_TREES(out.str(),
4390 :
4391 : "LIST\n"
4392 : " COMPONENT_VALUE\n"
4393 : " ARG\n"
4394 : " IDENTIFIER \"div\"\n"
4395 : " OPEN_CURLYBRACKET B:true\n"
4396 : " LIST\n"
4397 : " DECLARATION \"-filter\"\n"
4398 : " IDENTIFIER \"progid\"\n"
4399 : " COLON\n"
4400 : " IDENTIFIER \"DXImageTransform\"\n"
4401 : " PERIOD\n"
4402 : " IDENTIFIER \"Microsoft\"\n"
4403 : " PERIOD\n"
4404 : " FUNCTION \"alphaimageloader\"\n" // functions names always in lowercase...
4405 : " IDENTIFIER \"opacity\"\n"
4406 : " EQUAL\n"
4407 : " INTEGER \"\" I:20\n"
4408 : " DECLARATION \"font\"\n"
4409 : " ARG\n"
4410 : " FONT_METRICS FM:17.2px/1.35em\n"
4411 :
4412 : );
4413 :
4414 1 : CATCH_REQUIRE(c.get_root() == n);
4415 :
4416 : // no error left over
4417 1 : VERIFY_ERRORS("");
4418 1 : }
4419 8 : CATCH_END_SECTION()
4420 8 : }
4421 :
4422 1 : CATCH_TEST_CASE("Invalid complex terms", "[compiler] [invalid]")
4423 : {
4424 : // '::' must be followed by an IDENTIFIER
4425 : {
4426 1 : std::stringstream ss;
4427 1 : ss << "div.white :: {color:red}";
4428 3 : csspp::position pos("test.css");
4429 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
4430 :
4431 2 : csspp::parser p(l);
4432 :
4433 1 : csspp::node::pointer_t n(p.stylesheet());
4434 :
4435 : // no errors so far
4436 1 : VERIFY_ERRORS("");
4437 :
4438 1 : csspp::compiler c;
4439 1 : c.set_root(n);
4440 1 : c.clear_paths();
4441 1 : c.add_path(csspp_test::get_script_path());
4442 1 : c.add_path(csspp_test::get_version_script_path());
4443 :
4444 1 : c.compile(true);
4445 :
4446 1 : VERIFY_ERRORS("test.css(1): error: a selector list cannot end with a '::' without an identifier after it.\n");
4447 :
4448 1 : CATCH_REQUIRE(c.get_root() == n);
4449 1 : }
4450 :
4451 : // '::' must be followed a known pseudo-element name
4452 : {
4453 1 : std::stringstream ss;
4454 1 : ss << "div.white ::unknown {color:red}";
4455 3 : csspp::position pos("test.css");
4456 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
4457 :
4458 2 : csspp::parser p(l);
4459 :
4460 1 : csspp::node::pointer_t n(p.stylesheet());
4461 :
4462 : // no errors so far
4463 1 : VERIFY_ERRORS("");
4464 :
4465 1 : csspp::compiler c;
4466 1 : c.set_root(n);
4467 1 : c.clear_paths();
4468 1 : c.add_path(csspp_test::get_script_path());
4469 1 : c.add_path(csspp_test::get_version_script_path());
4470 :
4471 1 : c.compile(true);
4472 :
4473 1 : VERIFY_ERRORS("scripts/validation/pseudo-elements.scss(39): error: unknown is not a valid name for a pseudo element; CSS only supports after, before, first-letter, first-line, grammar-error, marker, placeholder, selection, and spelling-error.\n");
4474 1 : }
4475 :
4476 : // '::' must be followed an IDENTIFIER
4477 : {
4478 1 : std::stringstream ss;
4479 1 : ss << "div.white ::.shark {color:red}";
4480 3 : csspp::position pos("test.css");
4481 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
4482 :
4483 2 : csspp::parser p(l);
4484 :
4485 1 : csspp::node::pointer_t n(p.stylesheet());
4486 :
4487 : // no errors so far
4488 1 : VERIFY_ERRORS("");
4489 :
4490 1 : csspp::compiler c;
4491 1 : c.set_root(n);
4492 1 : c.clear_paths();
4493 1 : c.add_path(csspp_test::get_script_path());
4494 1 : c.add_path(csspp_test::get_version_script_path());
4495 :
4496 1 : c.compile(true);
4497 :
4498 1 : VERIFY_ERRORS("test.css(1): error: a pseudo element name (defined after a '::' in a list of selectors) must be defined using an identifier.\n");
4499 :
4500 1 : CATCH_REQUIRE(c.get_root() == n);
4501 1 : }
4502 :
4503 : // '>' cannot start a selector list
4504 : {
4505 1 : std::stringstream ss;
4506 1 : ss << "> div.white {color:red}";
4507 3 : csspp::position pos("test.css");
4508 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
4509 :
4510 2 : csspp::parser p(l);
4511 :
4512 1 : csspp::node::pointer_t n(p.stylesheet());
4513 :
4514 : // no errors so far
4515 1 : VERIFY_ERRORS("");
4516 :
4517 1 : csspp::compiler c;
4518 1 : c.set_root(n);
4519 1 : c.clear_paths();
4520 1 : c.add_path(csspp_test::get_script_path());
4521 1 : c.add_path(csspp_test::get_version_script_path());
4522 :
4523 1 : c.compile(true);
4524 :
4525 1 : VERIFY_ERRORS("test.css(1): error: found token GREATER_THAN, which cannot be used to start a selector expression.\n");
4526 :
4527 1 : CATCH_REQUIRE(c.get_root() == n);
4528 1 : }
4529 :
4530 : // '+' cannot start a selector list
4531 : {
4532 1 : std::stringstream ss;
4533 1 : ss << "+ div.white {color:red}";
4534 3 : csspp::position pos("test.css");
4535 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
4536 :
4537 2 : csspp::parser p(l);
4538 :
4539 1 : csspp::node::pointer_t n(p.stylesheet());
4540 :
4541 : // no errors so far
4542 1 : VERIFY_ERRORS("");
4543 :
4544 1 : csspp::compiler c;
4545 1 : c.set_root(n);
4546 1 : c.clear_paths();
4547 1 : c.add_path(csspp_test::get_script_path());
4548 1 : c.add_path(csspp_test::get_version_script_path());
4549 :
4550 1 : c.compile(true);
4551 :
4552 1 : VERIFY_ERRORS("test.css(1): error: found token ADD, which cannot be used to start a selector expression.\n");
4553 :
4554 1 : CATCH_REQUIRE(c.get_root() == n);
4555 1 : }
4556 :
4557 : // '~' cannot start a selector list
4558 : {
4559 1 : std::stringstream ss;
4560 1 : ss << "~ div.white {color:red}";
4561 3 : csspp::position pos("test.css");
4562 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
4563 :
4564 2 : csspp::parser p(l);
4565 :
4566 1 : csspp::node::pointer_t n(p.stylesheet());
4567 :
4568 : // no errors so far
4569 1 : VERIFY_ERRORS("");
4570 :
4571 1 : csspp::compiler c;
4572 1 : c.set_root(n);
4573 1 : c.clear_paths();
4574 1 : c.add_path(csspp_test::get_script_path());
4575 1 : c.add_path(csspp_test::get_version_script_path());
4576 :
4577 1 : c.compile(true);
4578 :
4579 1 : VERIFY_ERRORS("test.css(1): error: found token PRECEDED, which cannot be used to start a selector expression.\n");
4580 :
4581 1 : CATCH_REQUIRE(c.get_root() == n);
4582 1 : }
4583 :
4584 : // selector cannot start with a FUNCTION
4585 : {
4586 1 : std::stringstream ss;
4587 1 : ss << "func() div.white {color:red}";
4588 3 : csspp::position pos("test.css");
4589 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
4590 :
4591 2 : csspp::parser p(l);
4592 :
4593 1 : csspp::node::pointer_t n(p.stylesheet());
4594 :
4595 : // no errors so far
4596 1 : VERIFY_ERRORS("");
4597 :
4598 1 : csspp::compiler c;
4599 1 : c.set_root(n);
4600 1 : c.clear_paths();
4601 1 : c.add_path(csspp_test::get_script_path());
4602 1 : c.add_path(csspp_test::get_version_script_path());
4603 :
4604 1 : c.compile(true);
4605 :
4606 1 : VERIFY_ERRORS("test.css(1): error: found function \"func()\", which may be a valid selector token but only if immediately preceeded by one ':' (term).\n");
4607 :
4608 1 : CATCH_REQUIRE(c.get_root() == n);
4609 1 : }
4610 :
4611 : // selectors do not support INTEGER
4612 : {
4613 1 : std::stringstream ss;
4614 1 : ss << "13 div.white {color:red}";
4615 3 : csspp::position pos("test.css");
4616 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
4617 :
4618 2 : csspp::parser p(l);
4619 :
4620 1 : csspp::node::pointer_t n(p.stylesheet());
4621 :
4622 : // no errors so far
4623 1 : VERIFY_ERRORS("");
4624 :
4625 1 : csspp::compiler c;
4626 1 : c.set_root(n);
4627 1 : c.clear_paths();
4628 1 : c.add_path(csspp_test::get_script_path());
4629 1 : c.add_path(csspp_test::get_version_script_path());
4630 :
4631 1 : c.compile(true);
4632 :
4633 1 : VERIFY_ERRORS("test.css(1): error: found token INTEGER, which is not a valid selector token (term).\n");
4634 :
4635 1 : CATCH_REQUIRE(c.get_root() == n);
4636 1 : }
4637 :
4638 : // selectors do not support DECIMAL_NUMBER
4639 : {
4640 1 : std::stringstream ss;
4641 1 : ss << "13.25 div.white {color:red}";
4642 3 : csspp::position pos("test.css");
4643 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
4644 :
4645 2 : csspp::parser p(l);
4646 :
4647 1 : csspp::node::pointer_t n(p.stylesheet());
4648 :
4649 : // no errors so far
4650 1 : VERIFY_ERRORS("");
4651 :
4652 1 : csspp::compiler c;
4653 1 : c.set_root(n);
4654 1 : c.clear_paths();
4655 1 : c.add_path(csspp_test::get_script_path());
4656 1 : c.add_path(csspp_test::get_version_script_path());
4657 :
4658 1 : c.compile(true);
4659 :
4660 1 : VERIFY_ERRORS("test.css(1): error: found token DECIMAL_NUMBER, which is not a valid selector token (term).\n");
4661 :
4662 1 : CATCH_REQUIRE(c.get_root() == n);
4663 1 : }
4664 :
4665 : // selectors do not support PERCENT
4666 : {
4667 1 : std::stringstream ss;
4668 1 : ss << "13% div.white {color:red}";
4669 3 : csspp::position pos("test.css");
4670 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
4671 :
4672 2 : csspp::parser p(l);
4673 :
4674 1 : csspp::node::pointer_t n(p.stylesheet());
4675 :
4676 : // no errors so far
4677 1 : VERIFY_ERRORS("");
4678 :
4679 1 : csspp::compiler c;
4680 1 : c.set_root(n);
4681 1 : c.clear_paths();
4682 1 : c.add_path(csspp_test::get_script_path());
4683 1 : c.add_path(csspp_test::get_version_script_path());
4684 :
4685 1 : c.compile(true);
4686 :
4687 1 : VERIFY_ERRORS("test.css(1): error: found token PERCENT, which is not a valid selector token (term).\n");
4688 :
4689 1 : CATCH_REQUIRE(c.get_root() == n);
4690 1 : }
4691 :
4692 : // check pseudo-elements not at the end
4693 : {
4694 1 : char const * pseudo_name_table[] =
4695 : {
4696 : "first-line",
4697 : "first-letter",
4698 : "before",
4699 : "after"
4700 : };
4701 :
4702 5 : for(auto pseudo_name : pseudo_name_table)
4703 : {
4704 4 : std::stringstream ss;
4705 : ss << "div ::"
4706 : << pseudo_name
4707 4 : << " span {color:teal}\n";
4708 12 : csspp::position pos("test.css");
4709 4 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
4710 :
4711 8 : csspp::parser p(l);
4712 :
4713 4 : csspp::node::pointer_t n(p.stylesheet());
4714 :
4715 : // no errors so far
4716 4 : VERIFY_ERRORS("");
4717 :
4718 4 : csspp::compiler c;
4719 4 : c.set_root(n);
4720 4 : c.clear_paths();
4721 4 : c.add_path(csspp_test::get_script_path());
4722 4 : c.add_path(csspp_test::get_version_script_path());
4723 :
4724 4 : c.compile(true);
4725 :
4726 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
4727 :
4728 4 : VERIFY_ERRORS("test.css(1): error: a pseudo element name (defined after a '::' in a list of selectors) must be defined as the last element in the list of selectors.\n");
4729 :
4730 4 : CATCH_REQUIRE(c.get_root() == n);
4731 4 : }
4732 :
4733 : // no error left over
4734 1 : VERIFY_ERRORS("");
4735 : }
4736 :
4737 : // check the few invalid characters before "identifier ':' ..."
4738 : {
4739 1 : std::stringstream ss;
4740 : ss << "div {\n"
4741 : << " *border: 1px solid #fff;\n"
4742 : << " .filter: opacity(0.2);\n"
4743 : << " #color: chocolate;\n"
4744 : << " !exclamation: 100px * 3;\n"
4745 1 : << "}\n";
4746 3 : csspp::position pos("test.css");
4747 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
4748 :
4749 2 : csspp::parser p(l);
4750 :
4751 1 : csspp::node::pointer_t n(p.stylesheet());
4752 :
4753 : // no errors so far
4754 1 : VERIFY_ERRORS("");
4755 :
4756 1 : csspp::compiler c;
4757 1 : c.set_root(n);
4758 1 : c.clear_paths();
4759 1 : c.add_path(csspp_test::get_script_path());
4760 1 : c.add_path(csspp_test::get_version_script_path());
4761 :
4762 1 : c.compile(true);
4763 :
4764 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
4765 :
4766 1 : VERIFY_ERRORS(
4767 : "test.css(2): warning: the '[*|.|!]<field-name>: ...' syntax is not allowed in csspp, we offer other ways to control field names per browser and do not allow such tricks.\n"
4768 : "test.css(3): warning: the '[*|.|!]<field-name>: ...' syntax is not allowed in csspp, we offer other ways to control field names per browser and do not allow such tricks.\n"
4769 : "test.css(3): warning: the alpha(), chroma() and similar functions of the filter field are Internet Explorer specific extensions which are not supported across browsers.\n"
4770 : "test.css(4): warning: the '#<field-name>: ...' syntax is not allowed in csspp, we offer other ways to control field names per browser and do not allow such tricks.\n"
4771 : "test.css(5): warning: the '#<field-name>: ...' syntax is not allowed in csspp, we offer other ways to control field names per browser and do not allow such tricks.\n"
4772 : );
4773 :
4774 1 : std::stringstream out;
4775 1 : out << *n;
4776 1 : VERIFY_TREES(out.str(),
4777 :
4778 : "LIST\n"
4779 : " COMPONENT_VALUE\n"
4780 : " ARG\n"
4781 : " IDENTIFIER \"div\"\n"
4782 : " OPEN_CURLYBRACKET B:true\n"
4783 : " LIST\n"
4784 : " DECLARATION \"border\"\n"
4785 : " ARG\n"
4786 : " INTEGER \"px\" I:1\n"
4787 : " WHITESPACE\n"
4788 : " IDENTIFIER \"solid\"\n"
4789 : " WHITESPACE\n"
4790 : " COLOR H:ffffffff\n"
4791 : " DECLARATION \"filter\"\n"
4792 : " FUNCTION \"opacity\"\n"
4793 : " DECIMAL_NUMBER \"\" D:0.2\n"
4794 : " DECLARATION \"color\"\n"
4795 : " ARG\n"
4796 : " COLOR H:ff1e69d2\n"
4797 : " DECLARATION \"exclamation\"\n"
4798 : " ARG\n"
4799 : " INTEGER \"px\" I:300\n"
4800 :
4801 : );
4802 :
4803 1 : CATCH_REQUIRE(c.get_root() == n);
4804 :
4805 : // no error left over
4806 1 : VERIFY_ERRORS("");
4807 1 : }
4808 :
4809 : // check that & cannot be used in the middle of a selector list
4810 : {
4811 1 : std::stringstream ss;
4812 : ss << "div {\n"
4813 : << " span &:hover {\n"
4814 : << " border: 1px solid #fff;\n"
4815 : << " }\n"
4816 1 : << "}\n";
4817 3 : csspp::position pos("test.css");
4818 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
4819 :
4820 2 : csspp::parser p(l);
4821 :
4822 1 : csspp::node::pointer_t n(p.stylesheet());
4823 :
4824 : // no errors so far
4825 1 : VERIFY_ERRORS("");
4826 :
4827 1 : csspp::compiler c;
4828 1 : c.set_root(n);
4829 1 : c.clear_paths();
4830 1 : c.add_path(csspp_test::get_script_path());
4831 1 : c.add_path(csspp_test::get_version_script_path());
4832 :
4833 1 : c.compile(true);
4834 :
4835 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
4836 :
4837 1 : VERIFY_ERRORS(
4838 : "test.css(1): error: a selector reference (&) can only appear as the very first item in a list of selectors.\n"
4839 : );
4840 :
4841 1 : CATCH_REQUIRE(c.get_root() == n);
4842 1 : }
4843 :
4844 : // no left over?
4845 1 : VERIFY_ERRORS("");
4846 1 : }
4847 :
4848 1 : CATCH_TEST_CASE("Invalid node", "[compiler] [invalid]")
4849 : {
4850 : // create a fake node tree with some invalid node types to
4851 : // exercise the compile() switch default entry
4852 : {
4853 1 : csspp::node_type_t invalid_types[] =
4854 : {
4855 : csspp::node_type_t::COMMA,
4856 : csspp::node_type_t::ADD,
4857 : csspp::node_type_t::CLOSE_CURLYBRACKET,
4858 : };
4859 :
4860 4 : for(size_t idx(0); idx < sizeof(invalid_types) / sizeof(invalid_types[0]); ++idx)
4861 : {
4862 9 : csspp::position pos("invalid-types.scss");
4863 3 : csspp::node::pointer_t n(new csspp::node(invalid_types[idx], pos));
4864 :
4865 3 : csspp::compiler c;
4866 3 : c.set_root(n);
4867 3 : c.clear_paths();
4868 3 : c.add_path(csspp_test::get_script_path());
4869 3 : c.add_path(csspp_test::get_version_script_path());
4870 :
4871 3 : CATCH_REQUIRE_THROWS_AS(c.compile(true), csspp::csspp_exception_unexpected_token);
4872 :
4873 3 : CATCH_REQUIRE(c.get_root() == n);
4874 3 : }
4875 : }
4876 :
4877 : // qualified rule must start with an identifier
4878 : {
4879 1 : std::stringstream ss;
4880 1 : ss << "{color:red}";
4881 3 : csspp::position pos("test.css");
4882 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
4883 :
4884 2 : csspp::parser p(l);
4885 :
4886 1 : csspp::node::pointer_t n(p.stylesheet());
4887 :
4888 : // no errors so far
4889 1 : VERIFY_ERRORS("");
4890 :
4891 1 : csspp::compiler c;
4892 1 : c.set_root(n);
4893 1 : c.clear_paths();
4894 1 : c.add_path(csspp_test::get_script_path());
4895 1 : c.add_path(csspp_test::get_version_script_path());
4896 :
4897 1 : c.compile(true);
4898 :
4899 1 : VERIFY_ERRORS("test.css(1): error: a qualified rule without selectors is not valid.\n");
4900 :
4901 1 : CATCH_REQUIRE(c.get_root() == n);
4902 1 : }
4903 :
4904 : // qualified rule must start with an identifier
4905 : {
4906 1 : std::stringstream ss;
4907 1 : ss << "this would be a declaration without a colon;";
4908 3 : csspp::position pos("test.css");
4909 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
4910 :
4911 2 : csspp::parser p(l);
4912 :
4913 1 : csspp::node::pointer_t n(p.stylesheet());
4914 :
4915 : // the qualified rule is invalid...
4916 1 : VERIFY_ERRORS("test.css(1): error: A qualified rule must end with a { ... } block.\n");
4917 :
4918 : // ...but we still compile it so we get a specific error that we do
4919 : // not get otherwise.
4920 1 : csspp::compiler c;
4921 1 : c.set_root(n);
4922 1 : c.clear_paths();
4923 1 : c.add_path(csspp_test::get_script_path());
4924 1 : c.add_path(csspp_test::get_version_script_path());
4925 :
4926 1 : c.compile(true);
4927 :
4928 1 : VERIFY_ERRORS("test.css(1): error: expected a ':' after the identifier of this declaration value; got a: COMPONENT_VALUE instead.\n");
4929 :
4930 1 : CATCH_REQUIRE(c.get_root() == n);
4931 1 : }
4932 :
4933 : // a declaration needs an identifier
4934 : {
4935 1 : std::stringstream ss;
4936 1 : ss << "rule{+: red;}";
4937 3 : csspp::position pos("test.css");
4938 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
4939 :
4940 2 : csspp::parser p(l);
4941 :
4942 1 : csspp::node::pointer_t n(p.stylesheet());
4943 :
4944 : // no errors so far
4945 1 : VERIFY_ERRORS("");
4946 :
4947 1 : csspp::compiler c;
4948 1 : c.set_root(n);
4949 1 : c.clear_paths();
4950 1 : c.add_path(csspp_test::get_script_path());
4951 1 : c.add_path(csspp_test::get_version_script_path());
4952 :
4953 1 : c.compile(true);
4954 :
4955 1 : VERIFY_ERRORS("test.css(1): error: expected an identifier to start a declaration value; got a: ADD instead.\n");
4956 :
4957 1 : CATCH_REQUIRE(c.get_root() == n);
4958 1 : }
4959 :
4960 : // a declaration needs an identifier
4961 : {
4962 1 : std::stringstream ss;
4963 : ss << "div {\n"
4964 : << " font-size: 80%;\n"
4965 : << " font-style; italic;\n"
4966 : << " text-align: right;\n"
4967 1 : << "}\n";
4968 3 : csspp::position pos("test.css");
4969 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
4970 :
4971 2 : csspp::parser p(l);
4972 :
4973 1 : csspp::node::pointer_t n(p.stylesheet());
4974 :
4975 : // no errors so far
4976 1 : VERIFY_ERRORS("");
4977 :
4978 1 : csspp::compiler c;
4979 1 : c.set_root(n);
4980 1 : c.clear_paths();
4981 1 : c.add_path(csspp_test::get_script_path());
4982 1 : c.add_path(csspp_test::get_version_script_path());
4983 :
4984 1 : c.compile(true);
4985 :
4986 1 : VERIFY_ERRORS(
4987 : "test.css(2): error: somehow a declaration list is missing a field name or ':'.\n"
4988 : "test.css(3): error: somehow a declaration list is missing a field name or ':'.\n"
4989 : );
4990 :
4991 1 : CATCH_REQUIRE(c.get_root() == n);
4992 1 : }
4993 :
4994 : // no left over?
4995 1 : VERIFY_ERRORS("");
4996 1 : }
4997 :
4998 1 : CATCH_TEST_CASE("Compile font metrics", "[compiler] [font-metrics]")
4999 : {
5000 : // define a sub-declaration inside a declaration
5001 : {
5002 1 : std::stringstream ss;
5003 : ss << "body {\n"
5004 : << "\tbackground-color: white;\n"
5005 : << "\tcolor: #333;\n"
5006 : << "\tfont: 62.5%/1.5 \"Helvetica Neue\", Helvetica, Verdana, Arial, FreeSans, \"Liberation Sans\", sans-serif;\n"
5007 1 : << "}\n";
5008 3 : csspp::position pos("test.css");
5009 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
5010 :
5011 2 : csspp::parser p(l);
5012 :
5013 1 : csspp::node::pointer_t n(p.stylesheet());
5014 :
5015 : // no errors so far
5016 1 : VERIFY_ERRORS("");
5017 :
5018 1 : csspp::compiler c;
5019 1 : c.set_root(n);
5020 1 : c.clear_paths();
5021 1 : c.add_path(csspp_test::get_script_path());
5022 1 : c.add_path(csspp_test::get_version_script_path());
5023 :
5024 1 : c.compile(true);
5025 :
5026 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
5027 :
5028 : //VERIFY_ERRORS("");
5029 :
5030 1 : std::stringstream out;
5031 1 : out << *n;
5032 1 : VERIFY_TREES(out.str(),
5033 :
5034 : "LIST\n"
5035 : " COMPONENT_VALUE\n"
5036 : " ARG\n"
5037 : " IDENTIFIER \"body\"\n"
5038 : " OPEN_CURLYBRACKET B:true\n"
5039 : " LIST\n"
5040 : " DECLARATION \"background-color\"\n"
5041 : " ARG\n"
5042 : " COLOR H:ffffffff\n"
5043 : " DECLARATION \"color\"\n"
5044 : " ARG\n"
5045 : " COLOR H:ff333333\n"
5046 : " DECLARATION \"font\"\n"
5047 : " ARG\n"
5048 : " FONT_METRICS FM:62.5%/1.5\n"
5049 : " WHITESPACE\n"
5050 : " STRING \"Helvetica Neue\"\n"
5051 : " ARG\n"
5052 : " IDENTIFIER \"Helvetica\"\n"
5053 : " ARG\n"
5054 : " IDENTIFIER \"Verdana\"\n"
5055 : " ARG\n"
5056 : " IDENTIFIER \"Arial\"\n"
5057 : " ARG\n"
5058 : " IDENTIFIER \"FreeSans\"\n"
5059 : " ARG\n"
5060 : " STRING \"Liberation Sans\"\n"
5061 : " ARG\n"
5062 : " IDENTIFIER \"sans-serif\"\n"
5063 :
5064 : );
5065 :
5066 1 : CATCH_REQUIRE(c.get_root() == n);
5067 1 : }
5068 :
5069 : // define a sub-declaration inside a declaration
5070 : {
5071 1 : std::stringstream ss;
5072 : ss << "body {\n"
5073 : << "\tfont: 15pt/135% \"Helvetica Neue\", Helvetica, Verdana, Arial, FreeSans, \"Liberation Sans\", sans-serif;\n"
5074 : << "\tcolor: #333;\n"
5075 : << "\tbackground-color: white;\n"
5076 1 : << "}\n";
5077 3 : csspp::position pos("test.css");
5078 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
5079 :
5080 2 : csspp::parser p(l);
5081 :
5082 1 : csspp::node::pointer_t n(p.stylesheet());
5083 :
5084 : // no errors so far
5085 1 : VERIFY_ERRORS("");
5086 :
5087 1 : csspp::compiler c;
5088 1 : c.set_root(n);
5089 1 : c.clear_paths();
5090 1 : c.add_path(csspp_test::get_script_path());
5091 1 : c.add_path(csspp_test::get_version_script_path());
5092 :
5093 1 : c.compile(true);
5094 :
5095 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
5096 :
5097 : //VERIFY_ERRORS("");
5098 :
5099 1 : std::stringstream out;
5100 1 : out << *n;
5101 1 : VERIFY_TREES(out.str(),
5102 :
5103 : "LIST\n"
5104 : " COMPONENT_VALUE\n"
5105 : " ARG\n"
5106 : " IDENTIFIER \"body\"\n"
5107 : " OPEN_CURLYBRACKET B:true\n"
5108 : " LIST\n"
5109 : " DECLARATION \"font\"\n"
5110 : " ARG\n"
5111 : " FONT_METRICS FM:15pt/135%\n"
5112 : " WHITESPACE\n"
5113 : " STRING \"Helvetica Neue\"\n"
5114 : " ARG\n"
5115 : " IDENTIFIER \"Helvetica\"\n"
5116 : " ARG\n"
5117 : " IDENTIFIER \"Verdana\"\n"
5118 : " ARG\n"
5119 : " IDENTIFIER \"Arial\"\n"
5120 : " ARG\n"
5121 : " IDENTIFIER \"FreeSans\"\n"
5122 : " ARG\n"
5123 : " STRING \"Liberation Sans\"\n"
5124 : " ARG\n"
5125 : " IDENTIFIER \"sans-serif\"\n"
5126 : " DECLARATION \"color\"\n"
5127 : " ARG\n"
5128 : " COLOR H:ff333333\n"
5129 : " DECLARATION \"background-color\"\n"
5130 : " ARG\n"
5131 : " COLOR H:ffffffff\n"
5132 :
5133 : );
5134 :
5135 1 : CATCH_REQUIRE(c.get_root() == n);
5136 1 : }
5137 :
5138 : // still no errors
5139 1 : VERIFY_ERRORS("");
5140 1 : }
5141 :
5142 1 : CATCH_TEST_CASE("Nested declarations", "[compiler] [nested]")
5143 : {
5144 : // define a sub-declaration inside a declaration
5145 : {
5146 1 : std::stringstream ss;
5147 : ss << "div\n"
5148 : << "{\n"
5149 : << " font:\n"
5150 : << " {\n"
5151 : << " color: red;\n"
5152 : << " family: 34px white \n"
5153 : << " {\n"
5154 : << " name: helvetica;\n"
5155 : << " group: sans-serif;\n"
5156 : << " };\n"
5157 : << " size: 3px + 5px;\n"
5158 : << " };\n"
5159 : << " a\n"
5160 : << " {\n"
5161 : << " text-decoration: underline;\n"
5162 : << " &:hover\n"
5163 : << " {\n"
5164 : << " text-align: center;\n"
5165 : << " }\n"
5166 : << " }\n"
5167 1 : << "}\n";
5168 3 : csspp::position pos("test.css");
5169 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
5170 :
5171 2 : csspp::parser p(l);
5172 :
5173 1 : csspp::node::pointer_t n(p.stylesheet());
5174 :
5175 : // no errors so far
5176 1 : VERIFY_ERRORS("");
5177 :
5178 1 : csspp::compiler c;
5179 1 : c.set_root(n);
5180 1 : c.clear_paths();
5181 1 : c.add_path(csspp_test::get_script_path());
5182 1 : c.add_path(csspp_test::get_version_script_path());
5183 :
5184 1 : c.compile(true);
5185 :
5186 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
5187 :
5188 1 : VERIFY_ERRORS("");
5189 :
5190 1 : std::stringstream out;
5191 1 : out << *n;
5192 1 : VERIFY_TREES(out.str(),
5193 :
5194 : "LIST\n"
5195 : " COMPONENT_VALUE\n"
5196 : " ARG\n"
5197 : " IDENTIFIER \"div\"\n"
5198 : " OPEN_CURLYBRACKET B:true\n"
5199 : " LIST\n"
5200 : " DECLARATION \"font-color\"\n"
5201 : " ARG\n"
5202 : " COLOR H:ff0000ff\n"
5203 : " DECLARATION \"font-family\"\n"
5204 : " ARG\n"
5205 : " INTEGER \"px\" I:34\n"
5206 : " WHITESPACE\n"
5207 : " COLOR H:ffffffff\n"
5208 : " DECLARATION \"font-family-name\"\n"
5209 : " ARG\n"
5210 : " IDENTIFIER \"helvetica\"\n"
5211 : " DECLARATION \"font-family-group\"\n"
5212 : " ARG\n"
5213 : " IDENTIFIER \"sans-serif\"\n"
5214 : " DECLARATION \"font-size\"\n"
5215 : " ARG\n"
5216 : " INTEGER \"px\" I:8\n"
5217 : " COMPONENT_VALUE\n"
5218 : " ARG\n"
5219 : " IDENTIFIER \"div\"\n"
5220 : " WHITESPACE\n"
5221 : " IDENTIFIER \"a\"\n"
5222 : " OPEN_CURLYBRACKET B:true\n"
5223 : " LIST\n"
5224 : " DECLARATION \"text-decoration\"\n"
5225 : " ARG\n"
5226 : " IDENTIFIER \"underline\"\n"
5227 : " COMPONENT_VALUE\n"
5228 : " ARG\n"
5229 : " IDENTIFIER \"div\"\n"
5230 : " WHITESPACE\n"
5231 : " IDENTIFIER \"a\"\n"
5232 : " COLON\n"
5233 : " IDENTIFIER \"hover\"\n"
5234 : " OPEN_CURLYBRACKET B:true\n"
5235 : " DECLARATION \"text-align\"\n"
5236 : " ARG\n"
5237 : " IDENTIFIER \"center\"\n"
5238 :
5239 : );
5240 :
5241 1 : CATCH_REQUIRE(c.get_root() == n);
5242 1 : }
5243 :
5244 : // define a sub-declaration inside a declaration
5245 : {
5246 1 : std::stringstream ss;
5247 : ss << "div { margin: { left: 300px + 51px / 3; top: 3px + 5px }; }"
5248 : << " $size: 300px;"
5249 1 : << " p { margin: 10px + $size * 3 25px - $size * 3 }";
5250 3 : csspp::position pos("test.css");
5251 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
5252 :
5253 2 : csspp::parser p(l);
5254 :
5255 1 : csspp::node::pointer_t n(p.stylesheet());
5256 :
5257 : // no errors so far
5258 1 : VERIFY_ERRORS("");
5259 :
5260 1 : csspp::compiler c;
5261 1 : c.set_root(n);
5262 1 : c.clear_paths();
5263 1 : c.add_path(csspp_test::get_script_path());
5264 1 : c.add_path(csspp_test::get_version_script_path());
5265 :
5266 1 : c.compile(true);
5267 :
5268 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
5269 :
5270 1 : VERIFY_ERRORS("");
5271 :
5272 1 : std::stringstream out;
5273 1 : out << *n;
5274 1 : VERIFY_TREES(out.str(),
5275 :
5276 : "LIST\n"
5277 : " V:size\n"
5278 : " LIST\n"
5279 : " VARIABLE \"size\"\n"
5280 : " INTEGER \"px\" I:300\n"
5281 : " COMPONENT_VALUE\n"
5282 : " ARG\n"
5283 : " IDENTIFIER \"div\"\n"
5284 : " OPEN_CURLYBRACKET B:true\n"
5285 : " DECLARATION \"margin-left\"\n"
5286 : " ARG\n"
5287 : " INTEGER \"px\" I:317\n"
5288 : " DECLARATION \"margin-top\"\n"
5289 : " ARG\n"
5290 : " INTEGER \"px\" I:8\n"
5291 : " COMPONENT_VALUE\n"
5292 : " ARG\n"
5293 : " IDENTIFIER \"p\"\n"
5294 : " OPEN_CURLYBRACKET B:true\n"
5295 : " DECLARATION \"margin\"\n"
5296 : " ARG\n"
5297 : " INTEGER \"px\" I:910\n"
5298 : " WHITESPACE\n"
5299 : " INTEGER \"px\" I:-875\n"
5300 :
5301 : );
5302 :
5303 1 : CATCH_REQUIRE(c.get_root() == n);
5304 1 : }
5305 :
5306 1 : CATCH_START_SECTION("just one sub-declaration inside a field definition")
5307 : {
5308 1 : std::stringstream ss;
5309 1 : ss << "p.boxed { border: { width: 25px + 5px; }; }";
5310 3 : csspp::position pos("test.css");
5311 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
5312 :
5313 2 : csspp::parser p(l);
5314 :
5315 1 : csspp::node::pointer_t n(p.stylesheet());
5316 :
5317 : // no errors so far
5318 1 : VERIFY_ERRORS("");
5319 :
5320 1 : csspp::compiler c;
5321 1 : c.set_root(n);
5322 1 : c.clear_paths();
5323 1 : c.add_path(csspp_test::get_script_path());
5324 1 : c.add_path(csspp_test::get_version_script_path());
5325 :
5326 1 : c.compile(true);
5327 :
5328 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
5329 :
5330 1 : VERIFY_ERRORS("");
5331 :
5332 1 : std::stringstream out;
5333 1 : out << *n;
5334 1 : VERIFY_TREES(out.str(),
5335 :
5336 : "LIST\n"
5337 : " COMPONENT_VALUE\n"
5338 : " ARG\n"
5339 : " IDENTIFIER \"p\"\n"
5340 : " PERIOD\n"
5341 : " IDENTIFIER \"boxed\"\n"
5342 : " OPEN_CURLYBRACKET B:true\n"
5343 : " DECLARATION \"border-width\"\n"
5344 : " ARG\n"
5345 : " INTEGER \"px\" I:30\n"
5346 :
5347 : );
5348 :
5349 1 : CATCH_REQUIRE(c.get_root() == n);
5350 1 : }
5351 1 : CATCH_END_SECTION()
5352 :
5353 : // define the sub-declaration in a variable
5354 : {
5355 1 : std::stringstream ss;
5356 : ss << "$m : { left: 300px + 51px / 3; top: 3px + 5px };"
5357 1 : << " div { margin: $m; }";
5358 3 : csspp::position pos("test.css");
5359 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
5360 :
5361 2 : csspp::parser p(l);
5362 :
5363 1 : csspp::node::pointer_t n(p.stylesheet());
5364 :
5365 : // no errors so far
5366 1 : VERIFY_ERRORS("");
5367 :
5368 1 : csspp::compiler c;
5369 1 : c.set_root(n);
5370 1 : c.clear_paths();
5371 1 : c.add_path(csspp_test::get_script_path());
5372 1 : c.add_path(csspp_test::get_version_script_path());
5373 :
5374 1 : c.compile(true);
5375 :
5376 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
5377 :
5378 1 : VERIFY_ERRORS("");
5379 :
5380 1 : std::stringstream out;
5381 1 : out << *n;
5382 1 : VERIFY_TREES(out.str(),
5383 :
5384 : "LIST\n"
5385 : " V:m\n"
5386 : " LIST\n"
5387 : " VARIABLE \"m\"\n"
5388 : " OPEN_CURLYBRACKET B:false\n"
5389 : " LIST\n"
5390 : " COMPONENT_VALUE\n"
5391 : " IDENTIFIER \"left\"\n"
5392 : " COLON\n"
5393 : " WHITESPACE\n"
5394 : " INTEGER \"px\" I:300\n"
5395 : " WHITESPACE\n"
5396 : " ADD\n"
5397 : " WHITESPACE\n"
5398 : " INTEGER \"px\" I:51\n"
5399 : " WHITESPACE\n"
5400 : " DIVIDE\n"
5401 : " WHITESPACE\n"
5402 : " INTEGER \"\" I:3\n"
5403 : " COMPONENT_VALUE\n"
5404 : " IDENTIFIER \"top\"\n"
5405 : " COLON\n"
5406 : " WHITESPACE\n"
5407 : " INTEGER \"px\" I:3\n"
5408 : " WHITESPACE\n"
5409 : " ADD\n"
5410 : " WHITESPACE\n"
5411 : " INTEGER \"px\" I:5\n"
5412 : " COMPONENT_VALUE\n"
5413 : " ARG\n"
5414 : " IDENTIFIER \"div\"\n"
5415 : " OPEN_CURLYBRACKET B:true\n"
5416 : " DECLARATION \"margin-left\"\n"
5417 : " ARG\n"
5418 : " INTEGER \"px\" I:317\n"
5419 : " DECLARATION \"margin-top\"\n"
5420 : " ARG\n"
5421 : " INTEGER \"px\" I:8\n"
5422 :
5423 : );
5424 :
5425 1 : CATCH_REQUIRE(c.get_root() == n);
5426 1 : }
5427 :
5428 : // 5 levels nested declarations
5429 : {
5430 1 : std::stringstream ss;
5431 : ss << "border {\n"
5432 : << " left: 0;\n"
5433 : << " width {\n"
5434 : << " right {\n"
5435 : << " height: 300px + 51px / 3;\n"
5436 : << " top {\n"
5437 : << " color { edge: white; };\n"
5438 : << " position: 3px + 5px;\n"
5439 : << " chain { key: attached; };\n"
5440 : << " };"
5441 : << " };"
5442 : << " };"
5443 : << " height {\n"
5444 : << " position: 33px;\n"
5445 : << " };\n"
5446 1 : << "}";
5447 3 : csspp::position pos("test.css");
5448 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
5449 :
5450 2 : csspp::parser p(l);
5451 :
5452 1 : csspp::node::pointer_t n(p.stylesheet());
5453 :
5454 : //std::cerr << "Parser result is: [" << *n << "]\n";
5455 :
5456 : // no errors so far
5457 1 : VERIFY_ERRORS("");
5458 :
5459 1 : csspp::compiler c;
5460 1 : c.set_root(n);
5461 1 : c.clear_paths();
5462 1 : c.add_path(csspp_test::get_script_path());
5463 1 : c.add_path(csspp_test::get_version_script_path());
5464 :
5465 1 : c.compile(true);
5466 :
5467 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
5468 :
5469 1 : VERIFY_ERRORS("");
5470 :
5471 1 : std::stringstream out;
5472 1 : out << *n;
5473 1 : VERIFY_TREES(out.str(),
5474 :
5475 : "LIST\n"
5476 : " COMPONENT_VALUE\n"
5477 : " ARG\n"
5478 : " IDENTIFIER \"border\"\n"
5479 : " OPEN_CURLYBRACKET B:true\n"
5480 : " LIST\n"
5481 : " DECLARATION \"left\"\n"
5482 : " ARG\n"
5483 : " INTEGER \"\" I:0\n"
5484 : " COMPONENT_VALUE\n"
5485 : " ARG\n"
5486 : " IDENTIFIER \"border\"\n"
5487 : " WHITESPACE\n"
5488 : " IDENTIFIER \"width\"\n"
5489 : " OPEN_CURLYBRACKET B:true\n"
5490 : " COMPONENT_VALUE\n"
5491 : " ARG\n"
5492 : " IDENTIFIER \"border\"\n"
5493 : " WHITESPACE\n"
5494 : " IDENTIFIER \"width\"\n"
5495 : " WHITESPACE\n"
5496 : " IDENTIFIER \"right\"\n"
5497 : " OPEN_CURLYBRACKET B:true\n"
5498 : " LIST\n"
5499 : " DECLARATION \"height\"\n"
5500 : " ARG\n"
5501 : " INTEGER \"px\" I:317\n"
5502 : " COMPONENT_VALUE\n"
5503 : " ARG\n"
5504 : " IDENTIFIER \"border\"\n"
5505 : " WHITESPACE\n"
5506 : " IDENTIFIER \"width\"\n"
5507 : " WHITESPACE\n"
5508 : " IDENTIFIER \"right\"\n"
5509 : " WHITESPACE\n"
5510 : " IDENTIFIER \"top\"\n"
5511 : " OPEN_CURLYBRACKET B:true\n"
5512 : " LIST\n"
5513 : " DECLARATION \"position\"\n"
5514 : " ARG\n"
5515 : " INTEGER \"px\" I:8\n"
5516 : " COMPONENT_VALUE\n"
5517 : " ARG\n"
5518 : " IDENTIFIER \"border\"\n"
5519 : " WHITESPACE\n"
5520 : " IDENTIFIER \"width\"\n"
5521 : " WHITESPACE\n"
5522 : " IDENTIFIER \"right\"\n"
5523 : " WHITESPACE\n"
5524 : " IDENTIFIER \"top\"\n"
5525 : " WHITESPACE\n"
5526 : " IDENTIFIER \"color\"\n"
5527 : " OPEN_CURLYBRACKET B:true\n"
5528 : " DECLARATION \"edge\"\n"
5529 : " ARG\n"
5530 : " COLOR H:ffffffff\n"
5531 : " COMPONENT_VALUE\n"
5532 : " ARG\n"
5533 : " IDENTIFIER \"border\"\n"
5534 : " WHITESPACE\n"
5535 : " IDENTIFIER \"width\"\n"
5536 : " WHITESPACE\n"
5537 : " IDENTIFIER \"right\"\n"
5538 : " WHITESPACE\n"
5539 : " IDENTIFIER \"top\"\n"
5540 : " WHITESPACE\n"
5541 : " IDENTIFIER \"chain\"\n"
5542 : " OPEN_CURLYBRACKET B:true\n"
5543 : " DECLARATION \"key\"\n"
5544 : " ARG\n"
5545 : " IDENTIFIER \"attached\"\n"
5546 : " COMPONENT_VALUE\n"
5547 : " ARG\n"
5548 : " IDENTIFIER \"border\"\n"
5549 : " WHITESPACE\n"
5550 : " IDENTIFIER \"height\"\n"
5551 : " OPEN_CURLYBRACKET B:true\n"
5552 : " DECLARATION \"position\"\n"
5553 : " ARG\n"
5554 : " INTEGER \"px\" I:33\n"
5555 :
5556 : );
5557 :
5558 1 : CATCH_REQUIRE(c.get_root() == n);
5559 1 : }
5560 :
5561 : // Test that functions prevent a field to look like a declaration
5562 : {
5563 1 : std::stringstream ss;
5564 : ss << "border {\n"
5565 : << " left:not(.long) div{color: red};\n"
5566 1 : << "}";
5567 3 : csspp::position pos("test.css");
5568 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
5569 :
5570 2 : csspp::parser p(l);
5571 :
5572 1 : csspp::node::pointer_t n(p.stylesheet());
5573 :
5574 : //std::cerr << "Parser result is: [" << *n << "]\n";
5575 :
5576 : // no errors so far
5577 1 : VERIFY_ERRORS("");
5578 :
5579 1 : csspp::compiler c;
5580 1 : c.set_root(n);
5581 1 : c.clear_paths();
5582 1 : c.add_path(csspp_test::get_script_path());
5583 1 : c.add_path(csspp_test::get_version_script_path());
5584 :
5585 1 : c.compile(true);
5586 :
5587 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
5588 :
5589 1 : VERIFY_ERRORS("");
5590 :
5591 1 : std::stringstream out;
5592 1 : out << *n;
5593 1 : VERIFY_TREES(out.str(),
5594 :
5595 : //ss << "border {\n"
5596 : // << " left:not(.long) div{color: red};\n"
5597 : // << "}";
5598 : "LIST\n"
5599 : " COMPONENT_VALUE\n"
5600 : " ARG\n"
5601 : " IDENTIFIER \"border\"\n"
5602 : " OPEN_CURLYBRACKET B:true\n"
5603 : " COMPONENT_VALUE\n"
5604 : " ARG\n"
5605 : " IDENTIFIER \"border\"\n"
5606 : " WHITESPACE\n"
5607 : " IDENTIFIER \"left\"\n"
5608 : " COLON\n"
5609 : " FUNCTION \"not\"\n"
5610 : " PERIOD\n"
5611 : " IDENTIFIER \"long\"\n"
5612 : " WHITESPACE\n"
5613 : " IDENTIFIER \"div\"\n"
5614 : " OPEN_CURLYBRACKET B:true\n"
5615 : " DECLARATION \"color\"\n"
5616 : " ARG\n"
5617 : " COLOR H:ff0000ff\n"
5618 :
5619 : );
5620 :
5621 1 : CATCH_REQUIRE(c.get_root() == n);
5622 1 : }
5623 :
5624 : // // define the sub-declaration in a variable
5625 : // {
5626 : //std::cerr << "------------------------------------------------ WORKING ON straight entry\n";
5627 : // std::stringstream ss;
5628 : // ss << "$m : left: 300px + 51px / 3; top: 3px + 5px;"
5629 : // << " div { margin: $m; }";
5630 : // csspp::position pos("test.css");
5631 : // csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
5632 : //
5633 : // csspp::parser p(l);
5634 : //
5635 : // csspp::node::pointer_t n(p.stylesheet());
5636 : //
5637 : // // no errors so far
5638 : // VERIFY_ERRORS("");
5639 : //
5640 : // csspp::compiler c;
5641 : // c.set_root(n);
5642 : // c.clear_paths();
5643 : // c.add_path(csspp_test::get_script_path());
5644 : // c.add_path(csspp_test::get_version_script_path());
5645 : //
5646 : // c.compile(true);
5647 : //
5648 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
5649 : //
5650 : // VERIFY_ERRORS("");
5651 : //
5652 : // std::stringstream out;
5653 : // out << *n;
5654 : // VERIFY_TREES(out.str(),
5655 : //
5656 : //"LIST\n"
5657 : //" V:m\n"
5658 : //" OPEN_CURLYBRACKET\n"
5659 : //" COMPONENT_VALUE\n"
5660 : //" IDENTIFIER \"left\"\n"
5661 : ////" COLON\n"
5662 : ////" WHITESPACE\n"
5663 : ////" INTEGER \"px\" I:300\n"
5664 : ////" WHITESPACE\n"
5665 : ////" ADD\n"
5666 : ////" WHITESPACE\n"
5667 : ////" INTEGER \"px\" I:51\n"
5668 : ////" WHITESPACE\n"
5669 : ////" DIVIDE\n"
5670 : ////" WHITESPACE\n"
5671 : ////" INTEGER \"\" I:3\n"
5672 : //" COMPONENT_VALUE\n"
5673 : //" IDENTIFIER \"top\"\n"
5674 : ////" COLON\n"
5675 : ////" WHITESPACE\n"
5676 : ////" INTEGER \"px\" I:3\n"
5677 : ////" WHITESPACE\n"
5678 : ////" ADD\n"
5679 : ////" WHITESPACE\n"
5680 : ////" INTEGER \"px\" I:5\n"
5681 : //" COMPONENT_VALUE\n"
5682 : //" ARG\n"
5683 : //" IDENTIFIER \"div\"\n"
5684 : //" OPEN_CURLYBRACKET\n"
5685 : //" DECLARATION \"margin\"\n"
5686 : //" DECLARATION \"left\"\n"
5687 : //" INTEGER \"px\" I:317\n"
5688 : //" DECLARATION \"top\"\n"
5689 : //" INTEGER \"px\" I:8\n"
5690 : //
5691 : // );
5692 : //
5693 : // CATCH_REQUIRE(c.get_root() == n);
5694 : // }
5695 :
5696 : // no left over?
5697 1 : VERIFY_ERRORS("");
5698 1 : }
5699 :
5700 1 : CATCH_TEST_CASE("Invalid nested declarations", "[compiler] [nested] [invalid]")
5701 : {
5702 : // define a sub-declaration inside a declaration
5703 : {
5704 1 : std::stringstream ss;
5705 : ss << "div\n"
5706 : << "{\n"
5707 : << " font:\n"
5708 : << " {\n"
5709 : << " color: red;\n"
5710 : << " span { margin: 0; }" // <- you cannot do that
5711 : << " };\n"
5712 1 : << "}\n";
5713 3 : csspp::position pos("test.css");
5714 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
5715 :
5716 2 : csspp::parser p(l);
5717 :
5718 1 : csspp::node::pointer_t n(p.stylesheet());
5719 :
5720 : // no errors so far
5721 1 : VERIFY_ERRORS("");
5722 :
5723 1 : csspp::compiler c;
5724 1 : c.set_root(n);
5725 1 : c.clear_paths();
5726 1 : c.add_path(csspp_test::get_script_path());
5727 1 : c.add_path(csspp_test::get_version_script_path());
5728 :
5729 1 : c.compile(true);
5730 :
5731 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
5732 :
5733 1 : VERIFY_ERRORS("test.css(5): error: a nested declaration cannot include a rule.\n");
5734 :
5735 1 : CATCH_REQUIRE(c.get_root() == n);
5736 1 : }
5737 :
5738 : // no left over?
5739 1 : VERIFY_ERRORS("");
5740 1 : }
5741 :
5742 1 : CATCH_TEST_CASE("Advanced variables", "[compiler] [variable]")
5743 : {
5744 : // define a variable function with a parameter
5745 : {
5746 1 : std::stringstream ss;
5747 : ss << "$m( $width, $border: 1px ) : { left: $width + 51px / 3; top: $border + 5px };"
5748 1 : << " div { margin: $m(300px, 3px); }";
5749 3 : csspp::position pos("test.css");
5750 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
5751 :
5752 2 : csspp::parser p(l);
5753 :
5754 1 : csspp::node::pointer_t n(p.stylesheet());
5755 :
5756 : //std::cerr << "Parser result is: [" << *n << "]\n";
5757 :
5758 : // no errors so far
5759 1 : VERIFY_ERRORS("");
5760 :
5761 1 : csspp::compiler c;
5762 1 : c.set_root(n);
5763 1 : c.clear_paths();
5764 1 : c.add_path(csspp_test::get_script_path());
5765 1 : c.add_path(csspp_test::get_version_script_path());
5766 :
5767 1 : c.compile(true);
5768 :
5769 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
5770 :
5771 1 : VERIFY_ERRORS("");
5772 :
5773 1 : std::stringstream out;
5774 1 : out << *n;
5775 1 : VERIFY_TREES(out.str(),
5776 :
5777 : "LIST\n"
5778 : " V:m\n"
5779 : " LIST\n"
5780 : " VARIABLE_FUNCTION \"m\"\n"
5781 : " ARG\n"
5782 : " VARIABLE \"width\"\n"
5783 : " ARG\n"
5784 : " VARIABLE \"border\"\n"
5785 : " INTEGER \"px\" I:1\n"
5786 : " OPEN_CURLYBRACKET B:false\n"
5787 : " LIST\n"
5788 : " COMPONENT_VALUE\n"
5789 : " IDENTIFIER \"left\"\n"
5790 : " COLON\n"
5791 : " WHITESPACE\n"
5792 : " VARIABLE \"width\"\n"
5793 : " WHITESPACE\n"
5794 : " ADD\n"
5795 : " WHITESPACE\n"
5796 : " INTEGER \"px\" I:51\n"
5797 : " WHITESPACE\n"
5798 : " DIVIDE\n"
5799 : " WHITESPACE\n"
5800 : " INTEGER \"\" I:3\n"
5801 : " COMPONENT_VALUE\n"
5802 : " IDENTIFIER \"top\"\n"
5803 : " COLON\n"
5804 : " WHITESPACE\n"
5805 : " VARIABLE \"border\"\n"
5806 : " WHITESPACE\n"
5807 : " ADD\n"
5808 : " WHITESPACE\n"
5809 : " INTEGER \"px\" I:5\n"
5810 : " COMPONENT_VALUE\n"
5811 : " ARG\n"
5812 : " IDENTIFIER \"div\"\n"
5813 : " OPEN_CURLYBRACKET B:true\n"
5814 : " DECLARATION \"margin-left\"\n"
5815 : " ARG\n"
5816 : " INTEGER \"px\" I:317\n"
5817 : " DECLARATION \"margin-top\"\n"
5818 : " ARG\n"
5819 : " INTEGER \"px\" I:8\n"
5820 :
5821 : );
5822 :
5823 1 : CATCH_REQUIRE(c.get_root() == n);
5824 1 : }
5825 :
5826 : // define a variable function with a parameter and more spaces
5827 : {
5828 1 : std::stringstream ss;
5829 : ss << "$m( $width, $border : 1px ) : { left: $width + 51px / 3; top: $border + 5px };"
5830 1 : << " div { margin: $m(300px, 3px); }";
5831 3 : csspp::position pos("test.css");
5832 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
5833 :
5834 2 : csspp::parser p(l);
5835 :
5836 1 : csspp::node::pointer_t n(p.stylesheet());
5837 :
5838 : // no errors so far
5839 1 : VERIFY_ERRORS("");
5840 :
5841 1 : csspp::compiler c;
5842 1 : c.set_root(n);
5843 1 : c.clear_paths();
5844 1 : c.add_path(csspp_test::get_script_path());
5845 1 : c.add_path(csspp_test::get_version_script_path());
5846 :
5847 1 : c.compile(true);
5848 :
5849 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
5850 :
5851 1 : VERIFY_ERRORS("");
5852 :
5853 1 : std::stringstream out;
5854 1 : out << *n;
5855 1 : VERIFY_TREES(out.str(),
5856 :
5857 : "LIST\n"
5858 : " V:m\n"
5859 : " LIST\n"
5860 : " VARIABLE_FUNCTION \"m\"\n"
5861 : " ARG\n"
5862 : " VARIABLE \"width\"\n"
5863 : " ARG\n"
5864 : " VARIABLE \"border\"\n"
5865 : " INTEGER \"px\" I:1\n"
5866 : " OPEN_CURLYBRACKET B:false\n"
5867 : " LIST\n"
5868 : " COMPONENT_VALUE\n"
5869 : " IDENTIFIER \"left\"\n"
5870 : " COLON\n"
5871 : " WHITESPACE\n"
5872 : " VARIABLE \"width\"\n"
5873 : " WHITESPACE\n"
5874 : " ADD\n"
5875 : " WHITESPACE\n"
5876 : " INTEGER \"px\" I:51\n"
5877 : " WHITESPACE\n"
5878 : " DIVIDE\n"
5879 : " WHITESPACE\n"
5880 : " INTEGER \"\" I:3\n"
5881 : " COMPONENT_VALUE\n"
5882 : " IDENTIFIER \"top\"\n"
5883 : " COLON\n"
5884 : " WHITESPACE\n"
5885 : " VARIABLE \"border\"\n"
5886 : " WHITESPACE\n"
5887 : " ADD\n"
5888 : " WHITESPACE\n"
5889 : " INTEGER \"px\" I:5\n"
5890 : " COMPONENT_VALUE\n"
5891 : " ARG\n"
5892 : " IDENTIFIER \"div\"\n"
5893 : " OPEN_CURLYBRACKET B:true\n"
5894 : " DECLARATION \"margin-left\"\n"
5895 : " ARG\n"
5896 : " INTEGER \"px\" I:317\n"
5897 : " DECLARATION \"margin-top\"\n"
5898 : " ARG\n"
5899 : " INTEGER \"px\" I:8\n"
5900 :
5901 : );
5902 :
5903 1 : CATCH_REQUIRE(c.get_root() == n);
5904 1 : }
5905 :
5906 : // test a variable function default parameter
5907 : {
5908 1 : std::stringstream ss;
5909 : ss << "$m( $width, $border: 1px ) : { left: $width + 51px / 3; top: $border + 5px };"
5910 1 : << " div { margin: $m(300px); }";
5911 3 : csspp::position pos("test.css");
5912 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
5913 :
5914 2 : csspp::parser p(l);
5915 :
5916 1 : csspp::node::pointer_t n(p.stylesheet());
5917 :
5918 : // no errors so far
5919 1 : VERIFY_ERRORS("");
5920 :
5921 1 : csspp::compiler c;
5922 1 : c.set_root(n);
5923 1 : c.clear_paths();
5924 1 : c.add_path(csspp_test::get_script_path());
5925 1 : c.add_path(csspp_test::get_version_script_path());
5926 :
5927 1 : c.compile(true);
5928 :
5929 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
5930 :
5931 1 : VERIFY_ERRORS("");
5932 :
5933 1 : std::stringstream out;
5934 1 : out << *n;
5935 1 : VERIFY_TREES(out.str(),
5936 :
5937 : "LIST\n"
5938 : " V:m\n"
5939 : " LIST\n"
5940 : " VARIABLE_FUNCTION \"m\"\n"
5941 : " ARG\n"
5942 : " VARIABLE \"width\"\n"
5943 : " ARG\n"
5944 : " VARIABLE \"border\"\n"
5945 : " INTEGER \"px\" I:1\n"
5946 : " OPEN_CURLYBRACKET B:false\n"
5947 : " LIST\n"
5948 : " COMPONENT_VALUE\n"
5949 : " IDENTIFIER \"left\"\n"
5950 : " COLON\n"
5951 : " WHITESPACE\n"
5952 : " VARIABLE \"width\"\n"
5953 : " WHITESPACE\n"
5954 : " ADD\n"
5955 : " WHITESPACE\n"
5956 : " INTEGER \"px\" I:51\n"
5957 : " WHITESPACE\n"
5958 : " DIVIDE\n"
5959 : " WHITESPACE\n"
5960 : " INTEGER \"\" I:3\n"
5961 : " COMPONENT_VALUE\n"
5962 : " IDENTIFIER \"top\"\n"
5963 : " COLON\n"
5964 : " WHITESPACE\n"
5965 : " VARIABLE \"border\"\n"
5966 : " WHITESPACE\n"
5967 : " ADD\n"
5968 : " WHITESPACE\n"
5969 : " INTEGER \"px\" I:5\n"
5970 : " COMPONENT_VALUE\n"
5971 : " ARG\n"
5972 : " IDENTIFIER \"div\"\n"
5973 : " OPEN_CURLYBRACKET B:true\n"
5974 : " DECLARATION \"margin-left\"\n"
5975 : " ARG\n"
5976 : " INTEGER \"px\" I:317\n"
5977 : " DECLARATION \"margin-top\"\n"
5978 : " ARG\n"
5979 : " INTEGER \"px\" I:6\n"
5980 :
5981 : );
5982 :
5983 1 : CATCH_REQUIRE(c.get_root() == n);
5984 1 : }
5985 :
5986 : // a multi value default
5987 : {
5988 1 : std::stringstream ss;
5989 : ss << "$m( $width, $border: 1px 3px ) : { left: $width + 51px / 3; top: $border };"
5990 1 : << " div { margin: $m(300px); }";
5991 3 : csspp::position pos("test.css");
5992 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
5993 :
5994 2 : csspp::parser p(l);
5995 :
5996 1 : csspp::node::pointer_t n(p.stylesheet());
5997 :
5998 : // no errors so far
5999 1 : VERIFY_ERRORS("");
6000 :
6001 1 : csspp::compiler c;
6002 1 : c.set_root(n);
6003 1 : c.clear_paths();
6004 1 : c.add_path(csspp_test::get_script_path());
6005 1 : c.add_path(csspp_test::get_version_script_path());
6006 :
6007 1 : c.compile(true);
6008 :
6009 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
6010 :
6011 1 : VERIFY_ERRORS("");
6012 :
6013 1 : std::stringstream out;
6014 1 : out << *n;
6015 1 : VERIFY_TREES(out.str(),
6016 :
6017 : "LIST\n"
6018 : " V:m\n"
6019 : " LIST\n"
6020 : " VARIABLE_FUNCTION \"m\"\n"
6021 : " ARG\n"
6022 : " VARIABLE \"width\"\n"
6023 : " ARG\n"
6024 : " VARIABLE \"border\"\n"
6025 : " INTEGER \"px\" I:1\n"
6026 : " WHITESPACE\n"
6027 : " INTEGER \"px\" I:3\n"
6028 : " OPEN_CURLYBRACKET B:false\n"
6029 : " LIST\n"
6030 : " COMPONENT_VALUE\n"
6031 : " IDENTIFIER \"left\"\n"
6032 : " COLON\n"
6033 : " WHITESPACE\n"
6034 : " VARIABLE \"width\"\n"
6035 : " WHITESPACE\n"
6036 : " ADD\n"
6037 : " WHITESPACE\n"
6038 : " INTEGER \"px\" I:51\n"
6039 : " WHITESPACE\n"
6040 : " DIVIDE\n"
6041 : " WHITESPACE\n"
6042 : " INTEGER \"\" I:3\n"
6043 : " COMPONENT_VALUE\n"
6044 : " IDENTIFIER \"top\"\n"
6045 : " COLON\n"
6046 : " WHITESPACE\n"
6047 : " VARIABLE \"border\"\n"
6048 : " COMPONENT_VALUE\n"
6049 : " ARG\n"
6050 : " IDENTIFIER \"div\"\n"
6051 : " OPEN_CURLYBRACKET B:true\n"
6052 : " DECLARATION \"margin-left\"\n"
6053 : " ARG\n"
6054 : " INTEGER \"px\" I:317\n"
6055 : " DECLARATION \"margin-top\"\n"
6056 : " ARG\n"
6057 : " INTEGER \"px\" I:1\n"
6058 : " WHITESPACE\n"
6059 : " INTEGER \"px\" I:3\n"
6060 :
6061 : );
6062 :
6063 1 : CATCH_REQUIRE(c.get_root() == n);
6064 1 : }
6065 :
6066 : // a variable function with multiple fields copied
6067 : {
6068 1 : std::stringstream ss;
6069 : ss << "$m( $border ) : { $border };"
6070 1 : << " br { border: $m(3px 1px 2px 4px); }";
6071 3 : csspp::position pos("test.css");
6072 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
6073 :
6074 2 : csspp::parser p(l);
6075 :
6076 1 : csspp::node::pointer_t n(p.stylesheet());
6077 :
6078 : //std::cerr << "Parser result is: [" << *n << "]\n";
6079 :
6080 : // no errors so far
6081 1 : VERIFY_ERRORS("");
6082 :
6083 1 : csspp::compiler c;
6084 1 : c.set_root(n);
6085 1 : c.clear_paths();
6086 1 : c.add_path(csspp_test::get_script_path());
6087 1 : c.add_path(csspp_test::get_version_script_path());
6088 :
6089 1 : c.compile(true);
6090 :
6091 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
6092 :
6093 1 : VERIFY_ERRORS("");
6094 :
6095 1 : std::stringstream out;
6096 1 : out << *n;
6097 1 : VERIFY_TREES(out.str(),
6098 :
6099 : "LIST\n"
6100 : " V:m\n"
6101 : " LIST\n"
6102 : " VARIABLE_FUNCTION \"m\"\n"
6103 : " ARG\n"
6104 : " VARIABLE \"border\"\n"
6105 : " OPEN_CURLYBRACKET B:false\n"
6106 : " COMPONENT_VALUE\n"
6107 : " VARIABLE \"border\"\n"
6108 : " COMPONENT_VALUE\n"
6109 : " ARG\n"
6110 : " IDENTIFIER \"br\"\n"
6111 : " OPEN_CURLYBRACKET B:true\n"
6112 : " DECLARATION \"border\"\n"
6113 : " ARG\n"
6114 : " INTEGER \"px\" I:3\n"
6115 : " WHITESPACE\n"
6116 : " INTEGER \"px\" I:1\n"
6117 : " WHITESPACE\n"
6118 : " INTEGER \"px\" I:2\n"
6119 : " WHITESPACE\n"
6120 : " INTEGER \"px\" I:4\n"
6121 :
6122 : );
6123 :
6124 1 : CATCH_REQUIRE(c.get_root() == n);
6125 1 : }
6126 :
6127 : // test a default variable
6128 : {
6129 1 : std::stringstream ss;
6130 : ss << "$m : 300px;\n"
6131 : << "$m : 53px !default;\n"
6132 1 : << "div { margin: $m; }";
6133 3 : csspp::position pos("test.css");
6134 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
6135 :
6136 2 : csspp::parser p(l);
6137 :
6138 1 : csspp::node::pointer_t n(p.stylesheet());
6139 :
6140 : // no errors so far
6141 1 : VERIFY_ERRORS("");
6142 :
6143 1 : csspp::compiler c;
6144 1 : c.set_root(n);
6145 1 : c.clear_paths();
6146 1 : c.add_path(csspp_test::get_script_path());
6147 1 : c.add_path(csspp_test::get_version_script_path());
6148 :
6149 1 : c.compile(true);
6150 :
6151 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
6152 :
6153 1 : VERIFY_ERRORS("");
6154 :
6155 1 : std::stringstream out;
6156 1 : out << *n;
6157 1 : VERIFY_TREES(out.str(),
6158 :
6159 : "LIST\n"
6160 : " V:m\n"
6161 : " LIST\n"
6162 : " VARIABLE \"m\"\n"
6163 : " INTEGER \"px\" I:300\n"
6164 : " COMPONENT_VALUE\n"
6165 : " ARG\n"
6166 : " IDENTIFIER \"div\"\n"
6167 : " OPEN_CURLYBRACKET B:true\n"
6168 : " DECLARATION \"margin\"\n"
6169 : " ARG\n"
6170 : " INTEGER \"px\" I:300\n"
6171 :
6172 : );
6173 :
6174 1 : CATCH_REQUIRE(c.get_root() == n);
6175 1 : }
6176 :
6177 : // test a variable inside a qualified rule {}-block
6178 : {
6179 1 : std::stringstream ss;
6180 : ss << "div { $size: 300px;\n"
6181 : << " entry: {\n"
6182 : << " width: $size;\n"
6183 : << " height: $size * 3 / 4;\n"
6184 : << " };\n"
6185 : << " junior: $size + 13px;\n"
6186 1 : << "}";
6187 3 : csspp::position pos("test.css");
6188 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
6189 :
6190 2 : csspp::parser p(l);
6191 :
6192 1 : csspp::node::pointer_t n(p.stylesheet());
6193 :
6194 : //std::cerr << "Parser result is: [" << *n << "]\n";
6195 :
6196 : // no errors so far
6197 1 : VERIFY_ERRORS("");
6198 :
6199 1 : csspp::compiler c;
6200 1 : c.set_root(n);
6201 1 : c.clear_paths();
6202 1 : c.add_path(csspp_test::get_script_path());
6203 1 : c.add_path(csspp_test::get_version_script_path());
6204 :
6205 1 : c.compile(true);
6206 :
6207 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
6208 :
6209 1 : VERIFY_ERRORS("");
6210 :
6211 1 : std::stringstream out;
6212 1 : out << *n;
6213 1 : VERIFY_TREES(out.str(),
6214 :
6215 : "LIST\n"
6216 : " COMPONENT_VALUE\n"
6217 : " ARG\n"
6218 : " IDENTIFIER \"div\"\n"
6219 : " OPEN_CURLYBRACKET B:true\n"
6220 : " V:size\n"
6221 : " LIST\n"
6222 : " VARIABLE \"size\"\n"
6223 : " INTEGER \"px\" I:300\n"
6224 : " LIST\n"
6225 : " DECLARATION \"entry-width\"\n"
6226 : " ARG\n"
6227 : " INTEGER \"px\" I:300\n"
6228 : " DECLARATION \"entry-height\"\n"
6229 : " ARG\n"
6230 : " INTEGER \"px\" I:225\n"
6231 : " DECLARATION \"junior\"\n"
6232 : " ARG\n"
6233 : " INTEGER \"px\" I:313\n"
6234 :
6235 : );
6236 :
6237 1 : CATCH_REQUIRE(c.get_root() == n);
6238 1 : }
6239 :
6240 : // test that blocks define locations to save variables as expected
6241 : {
6242 1 : std::stringstream ss;
6243 : ss << "$size: 100px;\n"
6244 : << "div { $size: 300px;\n"
6245 : << " entry: {\n"
6246 : << " $size: 50px;\n"
6247 : << " width: $size;\n"
6248 : << " height: $size * 3 / 4;\n"
6249 : << " };\n"
6250 : << " junior: $size + 13px;\n"
6251 : << "}\n"
6252 1 : << "section { diameter: $size }\n";
6253 3 : csspp::position pos("test.css");
6254 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
6255 :
6256 2 : csspp::parser p(l);
6257 :
6258 1 : csspp::node::pointer_t n(p.stylesheet());
6259 :
6260 : // no errors so far
6261 1 : VERIFY_ERRORS("");
6262 :
6263 1 : csspp::compiler c;
6264 1 : c.set_root(n);
6265 1 : c.clear_paths();
6266 1 : c.add_path(csspp_test::get_script_path());
6267 1 : c.add_path(csspp_test::get_version_script_path());
6268 :
6269 1 : c.compile(true);
6270 :
6271 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
6272 :
6273 1 : VERIFY_ERRORS("");
6274 :
6275 1 : std::stringstream out;
6276 1 : out << *n;
6277 1 : VERIFY_TREES(out.str(),
6278 :
6279 : "LIST\n"
6280 : " V:size\n"
6281 : " LIST\n"
6282 : " VARIABLE \"size\"\n"
6283 : " INTEGER \"px\" I:100\n"
6284 : " COMPONENT_VALUE\n"
6285 : " ARG\n"
6286 : " IDENTIFIER \"div\"\n"
6287 : " OPEN_CURLYBRACKET B:true\n"
6288 : " V:size\n"
6289 : " LIST\n"
6290 : " VARIABLE \"size\"\n"
6291 : " INTEGER \"px\" I:300\n"
6292 : " LIST\n"
6293 : " DECLARATION \"entry-width\"\n"
6294 : " ARG\n"
6295 : " INTEGER \"px\" I:50\n"
6296 : " DECLARATION \"entry-height\"\n"
6297 : " ARG\n"
6298 : " INTEGER \"px\" I:37\n"
6299 : " DECLARATION \"junior\"\n"
6300 : " ARG\n"
6301 : " INTEGER \"px\" I:313\n"
6302 : " COMPONENT_VALUE\n"
6303 : " ARG\n"
6304 : " IDENTIFIER \"section\"\n"
6305 : " OPEN_CURLYBRACKET B:true\n"
6306 : " DECLARATION \"diameter\"\n"
6307 : " ARG\n"
6308 : " INTEGER \"px\" I:100\n"
6309 :
6310 : );
6311 :
6312 1 : CATCH_REQUIRE(c.get_root() == n);
6313 1 : }
6314 :
6315 : // test that !global forces definitions to be global
6316 : {
6317 1 : std::stringstream ss;
6318 : ss << "$size: 100px;\n"
6319 : << "div { $size: 300px !global;\n"
6320 : << " entry: {\n"
6321 : << " $size: 50px ! global;\n"
6322 : << " width: $size;\n"
6323 : << " height: $size * 3 / 4;\n"
6324 : << " };\n"
6325 : << " junior: $size + 13px;\n"
6326 : << "}\n"
6327 1 : << "section { diameter: $size }\n";
6328 3 : csspp::position pos("test.css");
6329 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
6330 :
6331 2 : csspp::parser p(l);
6332 :
6333 1 : csspp::node::pointer_t n(p.stylesheet());
6334 :
6335 : // no errors so far
6336 1 : VERIFY_ERRORS("");
6337 :
6338 1 : csspp::compiler c;
6339 1 : c.set_root(n);
6340 1 : c.clear_paths();
6341 1 : c.add_path(csspp_test::get_script_path());
6342 1 : c.add_path(csspp_test::get_version_script_path());
6343 :
6344 1 : c.compile(true);
6345 :
6346 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
6347 :
6348 1 : VERIFY_ERRORS("");
6349 :
6350 1 : std::stringstream out;
6351 1 : out << *n;
6352 1 : VERIFY_TREES(out.str(),
6353 :
6354 : "LIST\n"
6355 : " V:size\n"
6356 : " LIST\n"
6357 : " VARIABLE \"size\"\n"
6358 : " INTEGER \"px\" I:50\n"
6359 : " COMPONENT_VALUE\n"
6360 : " ARG\n"
6361 : " IDENTIFIER \"div\"\n"
6362 : " OPEN_CURLYBRACKET B:true\n"
6363 : " LIST\n"
6364 : " DECLARATION \"entry-width\"\n"
6365 : " ARG\n"
6366 : " INTEGER \"px\" I:50\n"
6367 : " DECLARATION \"entry-height\"\n"
6368 : " ARG\n"
6369 : " INTEGER \"px\" I:37\n"
6370 : " DECLARATION \"junior\"\n"
6371 : " ARG\n"
6372 : " INTEGER \"px\" I:63\n"
6373 : " COMPONENT_VALUE\n"
6374 : " ARG\n"
6375 : " IDENTIFIER \"section\"\n"
6376 : " OPEN_CURLYBRACKET B:true\n"
6377 : " DECLARATION \"diameter\"\n"
6378 : " ARG\n"
6379 : " INTEGER \"px\" I:50\n"
6380 :
6381 : );
6382 :
6383 1 : CATCH_REQUIRE(c.get_root() == n);
6384 1 : }
6385 :
6386 : // test that !default prevents redefinitions of existing variables
6387 : {
6388 1 : std::stringstream ss;
6389 : ss << "$size: 100px;\n"
6390 : << "div { $size: 300px !default;\n"
6391 : << " entry: {\n"
6392 : << " $size: 50px ! default;\n"
6393 : << " width: $size;\n"
6394 : << " height: $size * 3 / 4;\n"
6395 : << " };\n"
6396 : << " junior: $size + 13px;\n"
6397 : << "}\n"
6398 1 : << "section { diameter: $size }\n";
6399 3 : csspp::position pos("test.css");
6400 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
6401 :
6402 2 : csspp::parser p(l);
6403 :
6404 1 : csspp::node::pointer_t n(p.stylesheet());
6405 :
6406 : // no errors so far
6407 1 : VERIFY_ERRORS("");
6408 :
6409 1 : csspp::compiler c;
6410 1 : c.set_root(n);
6411 1 : c.clear_paths();
6412 1 : c.add_path(csspp_test::get_script_path());
6413 1 : c.add_path(csspp_test::get_version_script_path());
6414 :
6415 1 : c.compile(true);
6416 :
6417 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
6418 :
6419 1 : VERIFY_ERRORS("");
6420 :
6421 1 : std::stringstream out;
6422 1 : out << *n;
6423 1 : VERIFY_TREES(out.str(),
6424 :
6425 : "LIST\n"
6426 : " V:size\n"
6427 : " LIST\n"
6428 : " VARIABLE \"size\"\n"
6429 : " INTEGER \"px\" I:100\n"
6430 : " COMPONENT_VALUE\n"
6431 : " ARG\n"
6432 : " IDENTIFIER \"div\"\n"
6433 : " OPEN_CURLYBRACKET B:true\n"
6434 : " LIST\n"
6435 : " DECLARATION \"entry-width\"\n"
6436 : " ARG\n"
6437 : " INTEGER \"px\" I:100\n"
6438 : " DECLARATION \"entry-height\"\n"
6439 : " ARG\n"
6440 : " INTEGER \"px\" I:75\n"
6441 : " DECLARATION \"junior\"\n"
6442 : " ARG\n"
6443 : " INTEGER \"px\" I:113\n"
6444 : " COMPONENT_VALUE\n"
6445 : " ARG\n"
6446 : " IDENTIFIER \"section\"\n"
6447 : " OPEN_CURLYBRACKET B:true\n"
6448 : " DECLARATION \"diameter\"\n"
6449 : " ARG\n"
6450 : " INTEGER \"px\" I:100\n"
6451 :
6452 : );
6453 :
6454 1 : CATCH_REQUIRE(c.get_root() == n);
6455 1 : }
6456 :
6457 : // test a null variable
6458 : {
6459 1 : std::stringstream ss;
6460 : ss << "$empty-variable: null;\n"
6461 1 : << "div { border: 1px solid $empty-variable; }\n";
6462 3 : csspp::position pos("test.css");
6463 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
6464 :
6465 2 : csspp::parser p(l);
6466 :
6467 1 : csspp::node::pointer_t n(p.stylesheet());
6468 :
6469 : // no errors so far
6470 1 : VERIFY_ERRORS("");
6471 :
6472 1 : csspp::compiler c;
6473 1 : c.set_root(n);
6474 1 : c.clear_paths();
6475 1 : c.add_path(csspp_test::get_script_path());
6476 1 : c.add_path(csspp_test::get_version_script_path());
6477 :
6478 1 : c.compile(true);
6479 :
6480 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
6481 :
6482 1 : VERIFY_ERRORS("");
6483 :
6484 1 : std::stringstream out;
6485 1 : out << *n;
6486 1 : VERIFY_TREES(out.str(),
6487 :
6488 : "LIST\n"
6489 : " V:empty_variable\n"
6490 : " LIST\n"
6491 : " VARIABLE \"empty_variable\"\n"
6492 : " NULL_TOKEN\n"
6493 : " COMPONENT_VALUE\n"
6494 : " ARG\n"
6495 : " IDENTIFIER \"div\"\n"
6496 : " OPEN_CURLYBRACKET B:true\n"
6497 : " DECLARATION \"border\"\n"
6498 : " ARG\n"
6499 : " INTEGER \"px\" I:1\n"
6500 : " WHITESPACE\n"
6501 : " IDENTIFIER \"solid\"\n"
6502 :
6503 : );
6504 :
6505 1 : CATCH_REQUIRE(c.get_root() == n);
6506 1 : }
6507 :
6508 : // test inexistant variable when 'accept empty' flag is ON
6509 : {
6510 1 : std::stringstream ss;
6511 1 : ss << "div { border: 1px solid $undefined; }\n";
6512 3 : csspp::position pos("test.css");
6513 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
6514 :
6515 2 : csspp::parser p(l);
6516 :
6517 1 : csspp::node::pointer_t n(p.stylesheet());
6518 :
6519 : // no errors so far
6520 1 : VERIFY_ERRORS("");
6521 :
6522 1 : csspp::compiler c;
6523 1 : c.set_root(n);
6524 1 : c.clear_paths();
6525 1 : c.set_empty_on_undefined_variable(true);
6526 1 : c.add_path(csspp_test::get_script_path());
6527 1 : c.add_path(csspp_test::get_version_script_path());
6528 :
6529 1 : c.compile(true);
6530 :
6531 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
6532 :
6533 1 : VERIFY_ERRORS("");
6534 :
6535 1 : std::stringstream out;
6536 1 : out << *n;
6537 1 : VERIFY_TREES(out.str(),
6538 :
6539 : "LIST\n"
6540 : " COMPONENT_VALUE\n"
6541 : " ARG\n"
6542 : " IDENTIFIER \"div\"\n"
6543 : " OPEN_CURLYBRACKET B:true\n"
6544 : " DECLARATION \"border\"\n"
6545 : " ARG\n"
6546 : " INTEGER \"px\" I:1\n"
6547 : " WHITESPACE\n"
6548 : " IDENTIFIER \"solid\"\n"
6549 :
6550 : );
6551 :
6552 1 : CATCH_REQUIRE(c.get_root() == n);
6553 1 : }
6554 :
6555 : // test @include instead of $blah
6556 : {
6557 1 : std::stringstream ss;
6558 : ss << "$var: { div { border: 1px solid #ffe093; } };"
6559 1 : << "@include var;\n";
6560 3 : csspp::position pos("test.css");
6561 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
6562 :
6563 2 : csspp::parser p(l);
6564 :
6565 1 : csspp::node::pointer_t n(p.stylesheet());
6566 :
6567 : // no errors so far
6568 1 : VERIFY_ERRORS("");
6569 :
6570 1 : csspp::compiler c;
6571 1 : c.set_root(n);
6572 1 : c.clear_paths();
6573 1 : c.set_empty_on_undefined_variable(true);
6574 1 : c.add_path(csspp_test::get_script_path());
6575 1 : c.add_path(csspp_test::get_version_script_path());
6576 :
6577 1 : c.compile(true);
6578 :
6579 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
6580 :
6581 1 : VERIFY_ERRORS("");
6582 :
6583 1 : std::stringstream out;
6584 1 : out << *n;
6585 1 : VERIFY_TREES(out.str(),
6586 :
6587 : "LIST\n"
6588 : " V:var\n"
6589 : " LIST\n"
6590 : " VARIABLE \"var\"\n"
6591 : " OPEN_CURLYBRACKET B:false\n"
6592 : " COMPONENT_VALUE\n"
6593 : " IDENTIFIER \"div\"\n"
6594 : " OPEN_CURLYBRACKET B:true\n"
6595 : " COMPONENT_VALUE\n"
6596 : " IDENTIFIER \"border\"\n"
6597 : " COLON\n"
6598 : " WHITESPACE\n"
6599 : " INTEGER \"px\" I:1\n"
6600 : " WHITESPACE\n"
6601 : " IDENTIFIER \"solid\"\n"
6602 : " WHITESPACE\n"
6603 : " HASH \"ffe093\"\n"
6604 : " COMPONENT_VALUE\n"
6605 : " ARG\n"
6606 : " IDENTIFIER \"div\"\n"
6607 : " OPEN_CURLYBRACKET B:true\n"
6608 : " DECLARATION \"border\"\n"
6609 : " ARG\n"
6610 : " INTEGER \"px\" I:1\n"
6611 : " WHITESPACE\n"
6612 : " IDENTIFIER \"solid\"\n"
6613 : " WHITESPACE\n"
6614 : " COLOR H:ff93e0ff\n"
6615 :
6616 : );
6617 :
6618 1 : CATCH_REQUIRE(c.get_root() == n);
6619 1 : }
6620 :
6621 : // test @include with a function definition
6622 : {
6623 1 : std::stringstream ss;
6624 : ss << "$var($width): { div { border: $width solid #ffe093; } };"
6625 1 : << "@include var(7px);\n";
6626 3 : csspp::position pos("test.css");
6627 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
6628 :
6629 2 : csspp::parser p(l);
6630 :
6631 1 : csspp::node::pointer_t n(p.stylesheet());
6632 :
6633 : // no errors so far
6634 1 : VERIFY_ERRORS("");
6635 :
6636 1 : csspp::compiler c;
6637 1 : c.set_root(n);
6638 1 : c.clear_paths();
6639 1 : c.set_empty_on_undefined_variable(true);
6640 1 : c.add_path(csspp_test::get_script_path());
6641 1 : c.add_path(csspp_test::get_version_script_path());
6642 :
6643 1 : c.compile(true);
6644 :
6645 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
6646 :
6647 1 : VERIFY_ERRORS("");
6648 :
6649 1 : std::stringstream out;
6650 1 : out << *n;
6651 1 : VERIFY_TREES(out.str(),
6652 :
6653 : "LIST\n"
6654 : " V:var\n"
6655 : " LIST\n"
6656 : " VARIABLE_FUNCTION \"var\"\n"
6657 : " ARG\n"
6658 : " VARIABLE \"width\"\n"
6659 : " OPEN_CURLYBRACKET B:false\n"
6660 : " COMPONENT_VALUE\n"
6661 : " IDENTIFIER \"div\"\n"
6662 : " OPEN_CURLYBRACKET B:true\n"
6663 : " COMPONENT_VALUE\n"
6664 : " IDENTIFIER \"border\"\n"
6665 : " COLON\n"
6666 : " WHITESPACE\n"
6667 : " VARIABLE \"width\"\n"
6668 : " WHITESPACE\n"
6669 : " IDENTIFIER \"solid\"\n"
6670 : " WHITESPACE\n"
6671 : " HASH \"ffe093\"\n"
6672 : " COMPONENT_VALUE\n"
6673 : " ARG\n"
6674 : " IDENTIFIER \"div\"\n"
6675 : " OPEN_CURLYBRACKET B:true\n"
6676 : " DECLARATION \"border\"\n"
6677 : " ARG\n"
6678 : " INTEGER \"px\" I:7\n"
6679 : " WHITESPACE\n"
6680 : " IDENTIFIER \"solid\"\n"
6681 : " WHITESPACE\n"
6682 : " COLOR H:ff93e0ff\n"
6683 :
6684 : );
6685 :
6686 1 : CATCH_REQUIRE(c.get_root() == n);
6687 1 : }
6688 :
6689 : // test @include with @mixin
6690 : {
6691 1 : std::stringstream ss;
6692 : ss << "@mixin nice-button { div { border: 3px solid #ffe093; } }"
6693 1 : << "@include nice-button;\n";
6694 3 : csspp::position pos("test.css");
6695 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
6696 :
6697 2 : csspp::parser p(l);
6698 :
6699 1 : csspp::node::pointer_t n(p.stylesheet());
6700 :
6701 : //std::cerr << "Parser result is: [" << *n << "]\n";
6702 :
6703 : // no errors so far
6704 1 : VERIFY_ERRORS("");
6705 :
6706 1 : csspp::compiler c;
6707 1 : c.set_root(n);
6708 1 : c.clear_paths();
6709 1 : c.set_empty_on_undefined_variable(true);
6710 1 : c.add_path(csspp_test::get_script_path());
6711 1 : c.add_path(csspp_test::get_version_script_path());
6712 :
6713 1 : c.compile(true);
6714 :
6715 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
6716 :
6717 1 : VERIFY_ERRORS("");
6718 :
6719 1 : std::stringstream out;
6720 1 : out << *n;
6721 1 : VERIFY_TREES(out.str(),
6722 :
6723 : "LIST\n"
6724 : " V:nice-button\n"
6725 : " LIST\n"
6726 : " IDENTIFIER \"nice-button\"\n"
6727 : " OPEN_CURLYBRACKET B:true\n"
6728 : " COMPONENT_VALUE\n"
6729 : " IDENTIFIER \"div\"\n"
6730 : " OPEN_CURLYBRACKET B:true\n"
6731 : " COMPONENT_VALUE\n"
6732 : " IDENTIFIER \"border\"\n"
6733 : " COLON\n"
6734 : " WHITESPACE\n"
6735 : " INTEGER \"px\" I:3\n"
6736 : " WHITESPACE\n"
6737 : " IDENTIFIER \"solid\"\n"
6738 : " WHITESPACE\n"
6739 : " HASH \"ffe093\"\n"
6740 : " COMPONENT_VALUE\n"
6741 : " ARG\n"
6742 : " IDENTIFIER \"div\"\n"
6743 : " OPEN_CURLYBRACKET B:true\n"
6744 : " DECLARATION \"border\"\n"
6745 : " ARG\n"
6746 : " INTEGER \"px\" I:3\n"
6747 : " WHITESPACE\n"
6748 : " IDENTIFIER \"solid\"\n"
6749 : " WHITESPACE\n"
6750 : " COLOR H:ff93e0ff\n"
6751 :
6752 : );
6753 :
6754 1 : CATCH_REQUIRE(c.get_root() == n);
6755 1 : }
6756 :
6757 : // test @include with @mixin
6758 : {
6759 1 : std::stringstream ss;
6760 : ss << "@mixin var($width) { div { border: $width solid #ffe093; } }"
6761 1 : << "@include var(7px);\n";
6762 3 : csspp::position pos("test.css");
6763 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
6764 :
6765 2 : csspp::parser p(l);
6766 :
6767 1 : csspp::node::pointer_t n(p.stylesheet());
6768 :
6769 : //std::cerr << "Parser result is: [" << *n << "]\n";
6770 :
6771 : // no errors so far
6772 1 : VERIFY_ERRORS("");
6773 :
6774 1 : csspp::compiler c;
6775 1 : c.set_root(n);
6776 1 : c.clear_paths();
6777 1 : c.set_empty_on_undefined_variable(true);
6778 1 : c.add_path(csspp_test::get_script_path());
6779 1 : c.add_path(csspp_test::get_version_script_path());
6780 :
6781 1 : c.compile(true);
6782 :
6783 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
6784 :
6785 1 : VERIFY_ERRORS("");
6786 :
6787 1 : std::stringstream out;
6788 1 : out << *n;
6789 1 : VERIFY_TREES(out.str(),
6790 :
6791 : "LIST\n"
6792 : " V:var\n"
6793 : " LIST\n"
6794 : " FUNCTION \"var\"\n"
6795 : " ARG\n"
6796 : " VARIABLE \"width\"\n"
6797 : " OPEN_CURLYBRACKET B:true\n"
6798 : " COMPONENT_VALUE\n"
6799 : " IDENTIFIER \"div\"\n"
6800 : " OPEN_CURLYBRACKET B:true\n"
6801 : " COMPONENT_VALUE\n"
6802 : " IDENTIFIER \"border\"\n"
6803 : " COLON\n"
6804 : " WHITESPACE\n"
6805 : " VARIABLE \"width\"\n"
6806 : " WHITESPACE\n"
6807 : " IDENTIFIER \"solid\"\n"
6808 : " WHITESPACE\n"
6809 : " HASH \"ffe093\"\n"
6810 : " COMPONENT_VALUE\n"
6811 : " ARG\n"
6812 : " IDENTIFIER \"div\"\n"
6813 : " OPEN_CURLYBRACKET B:true\n"
6814 : " DECLARATION \"border\"\n"
6815 : " ARG\n"
6816 : " INTEGER \"px\" I:7\n"
6817 : " WHITESPACE\n"
6818 : " IDENTIFIER \"solid\"\n"
6819 : " WHITESPACE\n"
6820 : " COLOR H:ff93e0ff\n"
6821 :
6822 : );
6823 :
6824 1 : CATCH_REQUIRE(c.get_root() == n);
6825 1 : }
6826 :
6827 : // test $var with @mixin definition
6828 : {
6829 1 : std::stringstream ss;
6830 : ss << "@mixin var { 1px solid #ff0000 }"
6831 1 : << "div {border:$var}\n";
6832 3 : csspp::position pos("test.css");
6833 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
6834 :
6835 2 : csspp::parser p(l);
6836 :
6837 1 : csspp::node::pointer_t n(p.stylesheet());
6838 :
6839 : //std::cerr << "Parser result is: [" << *n << "]\n";
6840 :
6841 : // no errors so far
6842 1 : VERIFY_ERRORS("");
6843 :
6844 1 : csspp::compiler c;
6845 1 : c.set_root(n);
6846 1 : c.clear_paths();
6847 1 : c.set_empty_on_undefined_variable(true);
6848 1 : c.add_path(csspp_test::get_script_path());
6849 1 : c.add_path(csspp_test::get_version_script_path());
6850 :
6851 1 : c.compile(true);
6852 :
6853 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
6854 :
6855 1 : VERIFY_ERRORS("");
6856 :
6857 1 : std::stringstream out;
6858 1 : out << *n;
6859 1 : VERIFY_TREES(out.str(),
6860 :
6861 : "LIST\n"
6862 : " V:var\n"
6863 : " LIST\n"
6864 : " IDENTIFIER \"var\"\n"
6865 : " OPEN_CURLYBRACKET B:true\n"
6866 : " COMPONENT_VALUE\n"
6867 : " INTEGER \"px\" I:1\n"
6868 : " WHITESPACE\n"
6869 : " IDENTIFIER \"solid\"\n"
6870 : " WHITESPACE\n"
6871 : " HASH \"ff0000\"\n"
6872 : " COMPONENT_VALUE\n"
6873 : " ARG\n"
6874 : " IDENTIFIER \"div\"\n"
6875 : " OPEN_CURLYBRACKET B:true\n"
6876 : " DECLARATION \"border\"\n"
6877 : " ARG\n"
6878 : " INTEGER \"px\" I:1\n"
6879 : " WHITESPACE\n"
6880 : " IDENTIFIER \"solid\"\n"
6881 : " WHITESPACE\n"
6882 : " COLOR H:ff0000ff\n"
6883 :
6884 : );
6885 :
6886 1 : CATCH_REQUIRE(c.get_root() == n);
6887 1 : }
6888 :
6889 : // test $var with @mixin definition
6890 : {
6891 1 : std::stringstream ss;
6892 : ss << "@mixin var { rock.paper#scissors }"
6893 1 : << "$var {border:blue}\n";
6894 3 : csspp::position pos("test.css");
6895 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
6896 :
6897 2 : csspp::parser p(l);
6898 :
6899 1 : csspp::node::pointer_t n(p.stylesheet());
6900 :
6901 : //std::cerr << "Parser result is: [" << *n << "]\n";
6902 :
6903 : // no errors so far
6904 1 : VERIFY_ERRORS("");
6905 :
6906 1 : csspp::compiler c;
6907 1 : c.set_root(n);
6908 1 : c.clear_paths();
6909 1 : c.set_empty_on_undefined_variable(true);
6910 1 : c.add_path(csspp_test::get_script_path());
6911 1 : c.add_path(csspp_test::get_version_script_path());
6912 :
6913 1 : c.compile(true);
6914 :
6915 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
6916 :
6917 : //VERIFY_ERRORS("test.css(1): info: found an #id entry which is not at the beginning of the list of selectors; unless your HTML changes that much, #id should be the first selector only.\n");
6918 1 : VERIFY_ERRORS("");
6919 :
6920 1 : std::stringstream out;
6921 1 : out << *n;
6922 1 : VERIFY_TREES(out.str(),
6923 :
6924 : "LIST\n"
6925 : " V:var\n"
6926 : " LIST\n"
6927 : " IDENTIFIER \"var\"\n"
6928 : " OPEN_CURLYBRACKET B:true\n"
6929 : " COMPONENT_VALUE\n"
6930 : " IDENTIFIER \"rock\"\n"
6931 : " PERIOD\n"
6932 : " IDENTIFIER \"paper\"\n"
6933 : " HASH \"scissors\"\n"
6934 : " COMPONENT_VALUE\n"
6935 : " ARG\n"
6936 : " IDENTIFIER \"rock\"\n"
6937 : " PERIOD\n"
6938 : " IDENTIFIER \"paper\"\n"
6939 : " HASH \"scissors\"\n"
6940 : " OPEN_CURLYBRACKET B:true\n"
6941 : " DECLARATION \"border\"\n"
6942 : " ARG\n"
6943 : " COLOR H:ffff0000\n"
6944 :
6945 : );
6946 :
6947 1 : CATCH_REQUIRE(c.get_root() == n);
6948 1 : }
6949 :
6950 : // test $var with @mixin definition
6951 : {
6952 1 : std::stringstream ss;
6953 : ss << "@mixin var { rock.paper#scissors, with.more#selectors }"
6954 1 : << "$var {border:blue}\n";
6955 3 : csspp::position pos("test.css");
6956 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
6957 :
6958 2 : csspp::parser p(l);
6959 :
6960 1 : csspp::node::pointer_t n(p.stylesheet());
6961 :
6962 : //std::cerr << "Parser result is: [" << *n << "]\n";
6963 :
6964 : // no errors so far
6965 1 : VERIFY_ERRORS("");
6966 :
6967 1 : csspp::compiler c;
6968 1 : c.set_root(n);
6969 1 : c.clear_paths();
6970 1 : c.set_empty_on_undefined_variable(true);
6971 1 : c.add_path(csspp_test::get_script_path());
6972 1 : c.add_path(csspp_test::get_version_script_path());
6973 :
6974 1 : c.compile(true);
6975 :
6976 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
6977 :
6978 : //VERIFY_ERRORS(
6979 : // "test.css(1): info: found an #id entry which is not at the beginning of the list of selectors; unless your HTML changes that much, #id should be the first selector only.\n"
6980 : // "test.css(1): info: found an #id entry which is not at the beginning of the list of selectors; unless your HTML changes that much, #id should be the first selector only.\n"
6981 : // );
6982 1 : VERIFY_ERRORS("");
6983 :
6984 1 : std::stringstream out;
6985 1 : out << *n;
6986 1 : VERIFY_TREES(out.str(),
6987 :
6988 : "LIST\n"
6989 : " V:var\n"
6990 : " LIST\n"
6991 : " IDENTIFIER \"var\"\n"
6992 : " OPEN_CURLYBRACKET B:true\n"
6993 : " COMPONENT_VALUE\n"
6994 : " IDENTIFIER \"rock\"\n"
6995 : " PERIOD\n"
6996 : " IDENTIFIER \"paper\"\n"
6997 : " HASH \"scissors\"\n"
6998 : " COMMA\n"
6999 : " WHITESPACE\n"
7000 : " IDENTIFIER \"with\"\n"
7001 : " PERIOD\n"
7002 : " IDENTIFIER \"more\"\n"
7003 : " HASH \"selectors\"\n"
7004 : " COMPONENT_VALUE\n"
7005 : " ARG\n"
7006 : " IDENTIFIER \"rock\"\n"
7007 : " PERIOD\n"
7008 : " IDENTIFIER \"paper\"\n"
7009 : " HASH \"scissors\"\n"
7010 : " ARG\n"
7011 : " IDENTIFIER \"with\"\n"
7012 : " PERIOD\n"
7013 : " IDENTIFIER \"more\"\n"
7014 : " HASH \"selectors\"\n"
7015 : " OPEN_CURLYBRACKET B:true\n"
7016 : " DECLARATION \"border\"\n"
7017 : " ARG\n"
7018 : " COLOR H:ffff0000\n"
7019 :
7020 : );
7021 :
7022 1 : CATCH_REQUIRE(c.get_root() == n);
7023 1 : }
7024 :
7025 : // test $var with @mixin definition
7026 : {
7027 1 : std::stringstream ss;
7028 : ss << "@mixin var { rock.paper#scissors{border:blue} }"
7029 1 : << "div {$var}\n";
7030 3 : csspp::position pos("test.css");
7031 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
7032 :
7033 2 : csspp::parser p(l);
7034 :
7035 1 : csspp::node::pointer_t n(p.stylesheet());
7036 :
7037 : //std::cerr << "Parser result is: [" << *n << "]\n";
7038 :
7039 : // no errors so far
7040 1 : VERIFY_ERRORS("");
7041 :
7042 1 : csspp::compiler c;
7043 1 : c.set_root(n);
7044 1 : c.clear_paths();
7045 1 : c.set_empty_on_undefined_variable(true);
7046 1 : c.add_path(csspp_test::get_script_path());
7047 1 : c.add_path(csspp_test::get_version_script_path());
7048 :
7049 1 : c.compile(true);
7050 :
7051 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
7052 :
7053 : //VERIFY_ERRORS("test.css(1): info: found an #id entry which is not at the beginning of the list of selectors; unless your HTML changes that much, #id should be the first selector only.\n");
7054 1 : VERIFY_ERRORS("");
7055 :
7056 1 : std::stringstream out;
7057 1 : out << *n;
7058 1 : VERIFY_TREES(out.str(),
7059 :
7060 : "LIST\n"
7061 : " V:var\n"
7062 : " LIST\n"
7063 : " IDENTIFIER \"var\"\n"
7064 : " OPEN_CURLYBRACKET B:true\n"
7065 : " COMPONENT_VALUE\n"
7066 : " IDENTIFIER \"rock\"\n"
7067 : " PERIOD\n"
7068 : " IDENTIFIER \"paper\"\n"
7069 : " HASH \"scissors\"\n"
7070 : " OPEN_CURLYBRACKET B:true\n"
7071 : " COMPONENT_VALUE\n"
7072 : " IDENTIFIER \"border\"\n"
7073 : " COLON\n"
7074 : " IDENTIFIER \"blue\"\n"
7075 : " COMPONENT_VALUE\n"
7076 : " ARG\n"
7077 : " IDENTIFIER \"div\"\n"
7078 : " OPEN_CURLYBRACKET B:true\n"
7079 : " COMPONENT_VALUE\n"
7080 : " ARG\n"
7081 : " IDENTIFIER \"div\"\n"
7082 : " WHITESPACE\n"
7083 : " IDENTIFIER \"rock\"\n"
7084 : " PERIOD\n"
7085 : " IDENTIFIER \"paper\"\n"
7086 : " HASH \"scissors\"\n"
7087 : " OPEN_CURLYBRACKET B:true\n"
7088 : " DECLARATION \"border\"\n"
7089 : " ARG\n"
7090 : " COLOR H:ffff0000\n"
7091 :
7092 : );
7093 :
7094 1 : CATCH_REQUIRE(c.get_root() == n);
7095 1 : }
7096 :
7097 : // test $var with @mixin definition
7098 : {
7099 1 : std::stringstream ss;
7100 : ss << "@mixin var { border : 1px solid #eeeeee }"
7101 1 : << "div {$var}\n";
7102 3 : csspp::position pos("test.css");
7103 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
7104 :
7105 2 : csspp::parser p(l);
7106 :
7107 1 : csspp::node::pointer_t n(p.stylesheet());
7108 :
7109 : //std::cerr << "Parser result is: [" << *n << "]\n";
7110 :
7111 : // no errors so far
7112 1 : VERIFY_ERRORS("");
7113 :
7114 1 : csspp::compiler c;
7115 1 : c.set_root(n);
7116 1 : c.clear_paths();
7117 1 : c.set_empty_on_undefined_variable(true);
7118 1 : c.add_path(csspp_test::get_script_path());
7119 1 : c.add_path(csspp_test::get_version_script_path());
7120 :
7121 1 : c.compile(true);
7122 :
7123 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
7124 :
7125 1 : VERIFY_ERRORS("");
7126 :
7127 1 : std::stringstream out;
7128 1 : out << *n;
7129 1 : VERIFY_TREES(out.str(),
7130 :
7131 : "LIST\n"
7132 : " V:var\n"
7133 : " LIST\n"
7134 : " IDENTIFIER \"var\"\n"
7135 : " OPEN_CURLYBRACKET B:true\n"
7136 : " COMPONENT_VALUE\n"
7137 : " IDENTIFIER \"border\"\n"
7138 : " WHITESPACE\n"
7139 : " COLON\n"
7140 : " WHITESPACE\n"
7141 : " INTEGER \"px\" I:1\n"
7142 : " WHITESPACE\n"
7143 : " IDENTIFIER \"solid\"\n"
7144 : " WHITESPACE\n"
7145 : " HASH \"eeeeee\"\n"
7146 : " COMPONENT_VALUE\n"
7147 : " ARG\n"
7148 : " IDENTIFIER \"div\"\n"
7149 : " OPEN_CURLYBRACKET B:true\n"
7150 : " DECLARATION \"border\"\n"
7151 : " ARG\n"
7152 : " INTEGER \"px\" I:1\n"
7153 : " WHITESPACE\n"
7154 : " IDENTIFIER \"solid\"\n"
7155 : " WHITESPACE\n"
7156 : " COLOR H:ffeeeeee\n"
7157 :
7158 : );
7159 :
7160 1 : CATCH_REQUIRE(c.get_root() == n);
7161 1 : }
7162 :
7163 : // test $var with @mixin definition
7164 : {
7165 1 : std::stringstream ss;
7166 : ss << "@mixin var{border:1px solid #eeeeee}"
7167 1 : << "div{$var}\n";
7168 3 : csspp::position pos("test.css");
7169 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
7170 :
7171 2 : csspp::parser p(l);
7172 :
7173 1 : csspp::node::pointer_t n(p.stylesheet());
7174 :
7175 : //std::cerr << "Parser result is: [" << *n << "]\n";
7176 :
7177 : // no errors so far
7178 1 : VERIFY_ERRORS("");
7179 :
7180 1 : csspp::compiler c;
7181 1 : c.set_root(n);
7182 1 : c.clear_paths();
7183 1 : c.set_empty_on_undefined_variable(true);
7184 1 : c.add_path(csspp_test::get_script_path());
7185 1 : c.add_path(csspp_test::get_version_script_path());
7186 :
7187 1 : c.compile(true);
7188 :
7189 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
7190 :
7191 1 : VERIFY_ERRORS("");
7192 :
7193 1 : std::stringstream out;
7194 1 : out << *n;
7195 1 : VERIFY_TREES(out.str(),
7196 :
7197 : "LIST\n"
7198 : " V:var\n"
7199 : " LIST\n"
7200 : " IDENTIFIER \"var\"\n"
7201 : " OPEN_CURLYBRACKET B:true\n"
7202 : " COMPONENT_VALUE\n"
7203 : " IDENTIFIER \"border\"\n"
7204 : " COLON\n"
7205 : " INTEGER \"px\" I:1\n"
7206 : " WHITESPACE\n"
7207 : " IDENTIFIER \"solid\"\n"
7208 : " WHITESPACE\n"
7209 : " HASH \"eeeeee\"\n"
7210 : " COMPONENT_VALUE\n"
7211 : " ARG\n"
7212 : " IDENTIFIER \"div\"\n"
7213 : " OPEN_CURLYBRACKET B:true\n"
7214 : " DECLARATION \"border\"\n"
7215 : " ARG\n"
7216 : " INTEGER \"px\" I:1\n"
7217 : " WHITESPACE\n"
7218 : " IDENTIFIER \"solid\"\n"
7219 : " WHITESPACE\n"
7220 : " COLOR H:ffeeeeee\n"
7221 :
7222 : );
7223 :
7224 1 : CATCH_REQUIRE(c.get_root() == n);
7225 1 : }
7226 :
7227 : // test $var with @mixin definition
7228 : {
7229 : struct mixin_info_t
7230 : {
7231 5 : mixin_info_t(char const *selector, char const *v1, char const *r1, char const *r2 = nullptr, char const *r3 = nullptr, char const *r4 = nullptr, char const *r5 = nullptr)
7232 5 : : f_selector(selector)
7233 : {
7234 5 : f_result.push_back(r1);
7235 5 : if(r2)
7236 : {
7237 5 : f_result.push_back(r2);
7238 5 : if(r3)
7239 : {
7240 2 : f_result.push_back(r3);
7241 2 : if(r4)
7242 : {
7243 1 : f_result.push_back(r4);
7244 1 : if(r5)
7245 : {
7246 1 : f_result.push_back(r5);
7247 : }
7248 : }
7249 : }
7250 : }
7251 :
7252 5 : if(v1)
7253 : {
7254 1 : f_variable.push_back(v1);
7255 : }
7256 5 : if(strcmp(r1, "WHITESPACE") != 0)
7257 : {
7258 1 : f_variable.push_back(r1);
7259 : }
7260 5 : if(r2)
7261 : {
7262 5 : f_variable.push_back(r2);
7263 5 : if(r3)
7264 : {
7265 2 : f_variable.push_back(r3);
7266 2 : if(r4)
7267 : {
7268 1 : f_variable.push_back(r4);
7269 1 : if(r5)
7270 : {
7271 1 : f_variable.push_back(r5);
7272 : }
7273 : }
7274 : }
7275 : }
7276 5 : }
7277 :
7278 : std::string f_selector = std::string();
7279 : std::vector<std::string> f_variable = std::vector<std::string>();
7280 : std::vector<std::string> f_result = std::vector<std::string>();
7281 : };
7282 1 : mixin_info_t * start[5];
7283 1 : start[0] = new mixin_info_t("*", nullptr, "WHITESPACE", "MULTIPLY");
7284 1 : start[1] = new mixin_info_t("[foo='bar']", nullptr, "WHITESPACE", "OPEN_SQUAREBRACKET", " IDENTIFIER \"foo\"", " EQUAL", " STRING \"bar\"");
7285 1 : start[2] = new mixin_info_t(".color", nullptr, "WHITESPACE", "PERIOD", "IDENTIFIER \"color\"");
7286 1 : start[3] = new mixin_info_t("&:hover", "REFERENCE", "COLON", "IDENTIFIER \"hover\"");
7287 1 : start[4] = new mixin_info_t("#peculiar", nullptr, "WHITESPACE", "HASH \"peculiar\"");
7288 :
7289 6 : for(size_t i(0); i < sizeof(start) / sizeof(start[0]); ++i)
7290 : {
7291 :
7292 5 : std::stringstream ss;
7293 5 : ss << "@mixin var{" << start[i]->f_selector << " div p{color:#eeeeee}}"
7294 5 : << "div{$var}\n";
7295 15 : csspp::position pos("test.css");
7296 5 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
7297 :
7298 10 : csspp::parser p(l);
7299 :
7300 5 : csspp::node::pointer_t n(p.stylesheet());
7301 :
7302 : //std::cerr << "Parser result is: [" << *n << "]\n";
7303 :
7304 : // no errors so far
7305 5 : VERIFY_ERRORS("");
7306 :
7307 5 : csspp::compiler c;
7308 5 : c.set_root(n);
7309 5 : c.clear_paths();
7310 5 : c.set_empty_on_undefined_variable(true);
7311 5 : c.add_path(csspp_test::get_script_path());
7312 5 : c.add_path(csspp_test::get_version_script_path());
7313 :
7314 5 : c.compile(true);
7315 :
7316 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
7317 :
7318 5 : VERIFY_ERRORS("");
7319 :
7320 5 : std::stringstream out;
7321 5 : out << *n;
7322 :
7323 5 : std::stringstream expected;
7324 : expected <<
7325 : "LIST\n"
7326 : " V:var\n"
7327 : " LIST\n"
7328 : " IDENTIFIER \"var\"\n"
7329 : " OPEN_CURLYBRACKET B:true\n"
7330 5 : " COMPONENT_VALUE\n";
7331 :
7332 16 : for(auto s : start[i]->f_variable)
7333 : {
7334 11 : expected << " " << s << "\n";
7335 11 : }
7336 :
7337 : expected <<
7338 : " WHITESPACE\n"
7339 : " IDENTIFIER \"div\"\n"
7340 : " WHITESPACE\n"
7341 : " IDENTIFIER \"p\"\n"
7342 : " OPEN_CURLYBRACKET B:true\n"
7343 : " COMPONENT_VALUE\n"
7344 : " IDENTIFIER \"color\"\n"
7345 : " COLON\n"
7346 : " HASH \"eeeeee\"\n"
7347 : " COMPONENT_VALUE\n"
7348 : " ARG\n"
7349 : " IDENTIFIER \"div\"\n"
7350 : " OPEN_CURLYBRACKET B:true\n"
7351 : " COMPONENT_VALUE\n"
7352 : " ARG\n"
7353 5 : " IDENTIFIER \"div\"\n";
7354 :
7355 19 : for(auto s : start[i]->f_result)
7356 : {
7357 14 : expected << " " << s << "\n";
7358 14 : }
7359 :
7360 : expected <<
7361 : " WHITESPACE\n"
7362 : " IDENTIFIER \"div\"\n"
7363 : " WHITESPACE\n"
7364 : " IDENTIFIER \"p\"\n"
7365 : " OPEN_CURLYBRACKET B:true\n"
7366 : " DECLARATION \"color\"\n"
7367 : " ARG\n"
7368 5 : " COLOR H:ffeeeeee\n";
7369 :
7370 5 : VERIFY_TREES(out.str(), expected.str());
7371 :
7372 5 : CATCH_REQUIRE(c.get_root() == n);
7373 5 : }
7374 :
7375 1 : delete start[0];
7376 1 : delete start[1];
7377 1 : delete start[2];
7378 1 : delete start[3];
7379 1 : delete start[4];
7380 : }
7381 :
7382 : // test $var with @mixin definition
7383 : {
7384 1 : std::stringstream ss;
7385 : ss << "$var: { * div p { color: #eeeeee } };\n"
7386 1 : << "div { $var }\n";
7387 3 : csspp::position pos("test.css");
7388 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
7389 :
7390 2 : csspp::parser p(l);
7391 :
7392 1 : csspp::node::pointer_t n(p.stylesheet());
7393 :
7394 : //std::cerr << "Parser result is: [" << *n << "]\n";
7395 :
7396 : // no errors so far
7397 1 : VERIFY_ERRORS("");
7398 :
7399 1 : csspp::compiler c;
7400 1 : c.set_root(n);
7401 1 : c.clear_paths();
7402 1 : c.set_empty_on_undefined_variable(true);
7403 1 : c.add_path(csspp_test::get_script_path());
7404 1 : c.add_path(csspp_test::get_version_script_path());
7405 :
7406 1 : c.compile(true);
7407 :
7408 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
7409 :
7410 1 : VERIFY_ERRORS("");
7411 :
7412 1 : std::stringstream out;
7413 1 : out << *n;
7414 :
7415 1 : VERIFY_TREES(out.str(),
7416 :
7417 : "LIST\n"
7418 : " V:var\n"
7419 : " LIST\n"
7420 : " VARIABLE \"var\"\n"
7421 : " OPEN_CURLYBRACKET B:false\n"
7422 : " COMPONENT_VALUE\n"
7423 : " MULTIPLY\n"
7424 : " WHITESPACE\n"
7425 : " IDENTIFIER \"div\"\n"
7426 : " WHITESPACE\n"
7427 : " IDENTIFIER \"p\"\n"
7428 : " OPEN_CURLYBRACKET B:true\n"
7429 : " COMPONENT_VALUE\n"
7430 : " IDENTIFIER \"color\"\n"
7431 : " COLON\n"
7432 : " WHITESPACE\n"
7433 : " HASH \"eeeeee\"\n"
7434 : " COMPONENT_VALUE\n"
7435 : " ARG\n"
7436 : " IDENTIFIER \"div\"\n"
7437 : " OPEN_CURLYBRACKET B:true\n"
7438 : " COMPONENT_VALUE\n"
7439 : " ARG\n"
7440 : " IDENTIFIER \"div\"\n"
7441 : " WHITESPACE\n"
7442 : " MULTIPLY\n"
7443 : " WHITESPACE\n"
7444 : " IDENTIFIER \"div\"\n"
7445 : " WHITESPACE\n"
7446 : " IDENTIFIER \"p\"\n"
7447 : " OPEN_CURLYBRACKET B:true\n"
7448 : " DECLARATION \"color\"\n"
7449 : " ARG\n"
7450 : " COLOR H:ffeeeeee\n"
7451 :
7452 : );
7453 :
7454 1 : CATCH_REQUIRE(c.get_root() == n);
7455 1 : }
7456 :
7457 : // wrote this test out of a mistake really,
7458 : // but it generates an empty {}-block which is a good test
7459 : {
7460 1 : std::stringstream ss;
7461 : ss << "$b: border;"
7462 : << "$v: 1px solid white;"
7463 1 : << "div{$b: $v}\n";
7464 3 : csspp::position pos("test.css");
7465 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
7466 :
7467 2 : csspp::parser p(l);
7468 :
7469 1 : csspp::node::pointer_t n(p.stylesheet());
7470 :
7471 : //std::cerr << "Parser result is: [" << *n << "]\n";
7472 :
7473 : // no errors so far
7474 1 : VERIFY_ERRORS("");
7475 :
7476 1 : csspp::compiler c;
7477 1 : c.set_root(n);
7478 1 : c.clear_paths();
7479 1 : c.set_empty_on_undefined_variable(true);
7480 1 : c.add_path(csspp_test::get_script_path());
7481 1 : c.add_path(csspp_test::get_version_script_path());
7482 :
7483 1 : c.compile(true);
7484 :
7485 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
7486 :
7487 1 : VERIFY_ERRORS("");
7488 :
7489 1 : std::stringstream out;
7490 1 : out << *n;
7491 1 : VERIFY_TREES(out.str(),
7492 :
7493 : "LIST\n"
7494 : " V:b\n"
7495 : " LIST\n"
7496 : " VARIABLE \"b\"\n"
7497 : " IDENTIFIER \"border\"\n"
7498 : " V:v\n"
7499 : " LIST\n"
7500 : " VARIABLE \"v\"\n"
7501 : " LIST\n"
7502 : " INTEGER \"px\" I:1\n"
7503 : " WHITESPACE\n"
7504 : " IDENTIFIER \"solid\"\n"
7505 : " WHITESPACE\n"
7506 : " IDENTIFIER \"white\"\n"
7507 :
7508 : );
7509 :
7510 1 : CATCH_REQUIRE(c.get_root() == n);
7511 1 : }
7512 :
7513 : // no left over?
7514 1 : VERIFY_ERRORS("");
7515 1 : }
7516 :
7517 1 : CATCH_TEST_CASE("Invalid variables", "[compiler] [variable] [invalid]")
7518 : {
7519 : // undefined variable with whitespace before
7520 : {
7521 1 : std::stringstream ss;
7522 1 : ss << "div { margin: $m; }";
7523 3 : csspp::position pos("test.css");
7524 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
7525 :
7526 2 : csspp::parser p(l);
7527 :
7528 1 : csspp::node::pointer_t n(p.stylesheet());
7529 :
7530 : // no errors so far
7531 1 : VERIFY_ERRORS("");
7532 :
7533 1 : csspp::compiler c;
7534 1 : c.set_root(n);
7535 1 : c.clear_paths();
7536 1 : c.add_path(csspp_test::get_script_path());
7537 1 : c.add_path(csspp_test::get_version_script_path());
7538 :
7539 1 : c.compile(true);
7540 :
7541 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
7542 :
7543 1 : VERIFY_ERRORS(
7544 : "test.css(1): error: variable named \"m\" is not set.\n"
7545 : "test.css(1): error: somehow a declaration list is missing fields, this happens if you used an invalid variable.\n"
7546 : );
7547 :
7548 1 : CATCH_REQUIRE(c.get_root() == n);
7549 1 : }
7550 :
7551 : // null variable in a place where something is required
7552 : {
7553 1 : std::stringstream ss;
7554 : ss << "$m: null;\n"
7555 1 : << "div { margin: $m; }\n";
7556 3 : csspp::position pos("test.css");
7557 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
7558 :
7559 2 : csspp::parser p(l);
7560 :
7561 1 : csspp::node::pointer_t n(p.stylesheet());
7562 :
7563 : // no errors so far
7564 1 : VERIFY_ERRORS("");
7565 :
7566 1 : csspp::compiler c;
7567 1 : c.set_root(n);
7568 1 : c.clear_paths();
7569 1 : c.add_path(csspp_test::get_script_path());
7570 1 : c.add_path(csspp_test::get_version_script_path());
7571 :
7572 1 : c.compile(true);
7573 :
7574 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
7575 :
7576 1 : VERIFY_ERRORS(
7577 : "test.css(2): error: somehow a declaration list is missing fields, this happens if you used an invalid variable.\n"
7578 : );
7579 :
7580 1 : CATCH_REQUIRE(c.get_root() == n);
7581 1 : }
7582 :
7583 : // undefined variable without whitespace
7584 : {
7585 1 : std::stringstream ss;
7586 1 : ss << "div{margin:$m;}";
7587 3 : csspp::position pos("test.css");
7588 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
7589 :
7590 2 : csspp::parser p(l);
7591 :
7592 1 : csspp::node::pointer_t n(p.stylesheet());
7593 :
7594 : // no errors so far
7595 1 : VERIFY_ERRORS("");
7596 :
7597 1 : csspp::compiler c;
7598 1 : c.set_root(n);
7599 1 : c.clear_paths();
7600 1 : c.add_path(csspp_test::get_script_path());
7601 1 : c.add_path(csspp_test::get_version_script_path());
7602 :
7603 1 : c.compile(true);
7604 :
7605 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
7606 :
7607 1 : VERIFY_ERRORS(
7608 : "test.css(1): error: variable named \"m\" is not set.\n"
7609 : "test.css(1): error: somehow a declaration list is missing fields, this happens if you used an invalid variable.\n"
7610 : );
7611 :
7612 1 : CATCH_REQUIRE(c.get_root() == n);
7613 1 : }
7614 :
7615 : // variable type mismatch (func/var)
7616 : {
7617 1 : std::stringstream ss;
7618 : ss << "$m($p): $p / 3;"
7619 1 : << "div { margin: $m; }";
7620 3 : csspp::position pos("test.css");
7621 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
7622 :
7623 2 : csspp::parser p(l);
7624 :
7625 1 : csspp::node::pointer_t n(p.stylesheet());
7626 :
7627 : // no errors so far
7628 1 : VERIFY_ERRORS("");
7629 :
7630 1 : csspp::compiler c;
7631 1 : c.set_root(n);
7632 1 : c.clear_paths();
7633 1 : c.add_path(csspp_test::get_script_path());
7634 1 : c.add_path(csspp_test::get_version_script_path());
7635 :
7636 1 : c.compile(true);
7637 :
7638 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
7639 :
7640 1 : VERIFY_ERRORS(
7641 : "test.css(1): error: variable named \"m\" is not a function and it cannot be referenced as such.\n"
7642 : "test.css(1): error: somehow a declaration list is missing fields, this happens if you used an invalid variable.\n"
7643 : );
7644 :
7645 1 : CATCH_REQUIRE(c.get_root() == n);
7646 1 : }
7647 :
7648 : // variable type mismatch (var/func)
7649 : {
7650 1 : std::stringstream ss;
7651 : ss << "$m: 3px;"
7652 1 : << "div { margin: $m(6px); }";
7653 3 : csspp::position pos("test.css");
7654 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
7655 :
7656 2 : csspp::parser p(l);
7657 :
7658 1 : csspp::node::pointer_t n(p.stylesheet());
7659 :
7660 : // no errors so far
7661 1 : VERIFY_ERRORS("");
7662 :
7663 1 : csspp::compiler c;
7664 1 : c.set_root(n);
7665 1 : c.clear_paths();
7666 1 : c.add_path(csspp_test::get_script_path());
7667 1 : c.add_path(csspp_test::get_version_script_path());
7668 :
7669 1 : c.compile(true);
7670 :
7671 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
7672 :
7673 1 : VERIFY_ERRORS(
7674 : "test.css(1): error: variable named \"m\" is a function and it can only be referenced with a function ($m() or @include m;).\n"
7675 : "test.css(1): error: somehow a declaration list is missing fields, this happens if you used an invalid variable.\n"
7676 : );
7677 :
7678 1 : CATCH_REQUIRE(c.get_root() == n);
7679 1 : }
7680 :
7681 : // variable is missing in function call
7682 : {
7683 1 : std::stringstream ss;
7684 : ss << "$sum($a1, $a2, $a3): $a1 + $a2 + $a3;"
7685 1 : << "div { margin: $sum(6px, 309px); }";
7686 3 : csspp::position pos("test.css");
7687 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
7688 :
7689 2 : csspp::parser p(l);
7690 :
7691 1 : csspp::node::pointer_t n(p.stylesheet());
7692 :
7693 : // no errors so far
7694 1 : VERIFY_ERRORS("");
7695 :
7696 1 : csspp::compiler c;
7697 1 : c.set_root(n);
7698 1 : c.clear_paths();
7699 1 : c.add_path(csspp_test::get_script_path());
7700 1 : c.add_path(csspp_test::get_version_script_path());
7701 :
7702 1 : c.compile(true);
7703 :
7704 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
7705 :
7706 1 : VERIFY_ERRORS(
7707 : "test.css(1): error: missing function variable named \"a3\" when calling sum() or using @include sum();).\n"
7708 : "test.css(1): error: somehow a declaration list is missing fields, this happens if you used an invalid variable.\n"
7709 : );
7710 :
7711 1 : CATCH_REQUIRE(c.get_root() == n);
7712 1 : }
7713 :
7714 : // variable parameter is not a variable
7715 : {
7716 1 : std::stringstream ss;
7717 : ss << "$sum(a1): $a1;"
7718 1 : << "div { margin: $sum(6px); }";
7719 3 : csspp::position pos("test.css");
7720 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
7721 :
7722 2 : csspp::parser p(l);
7723 :
7724 1 : csspp::node::pointer_t n(p.stylesheet());
7725 :
7726 : // no errors so far
7727 1 : VERIFY_ERRORS("");
7728 :
7729 1 : csspp::compiler c;
7730 1 : c.set_root(n);
7731 1 : c.clear_paths();
7732 1 : c.add_path(csspp_test::get_script_path());
7733 1 : c.add_path(csspp_test::get_version_script_path());
7734 :
7735 1 : c.compile(true);
7736 :
7737 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
7738 :
7739 1 : VERIFY_ERRORS(
7740 : "test.css(1): error: function declarations expect variables for each of their arguments, not a IDENTIFIER.\n"
7741 : //"test.css(1): error: function declaration requires all parameters to be variables, IDENTIFIER is not acceptable.\n" -- removed not useful
7742 : "test.css(1): error: somehow a declaration list is missing fields, this happens if you used an invalid variable.\n"
7743 : );
7744 :
7745 1 : CATCH_REQUIRE(c.get_root() == n);
7746 1 : }
7747 :
7748 : // missing value for optional parameter
7749 : {
7750 1 : std::stringstream ss;
7751 : ss << "$sum($a1, $a2: 3px, $a3): ($a1+$a2)/$a3;"
7752 1 : << "div { margin: $sum(6px, 7px, 3); }";
7753 3 : csspp::position pos("test.css");
7754 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
7755 :
7756 2 : csspp::parser p(l);
7757 :
7758 1 : csspp::node::pointer_t n(p.stylesheet());
7759 :
7760 : // no errors so far
7761 1 : VERIFY_ERRORS("");
7762 :
7763 1 : csspp::compiler c;
7764 1 : c.set_root(n);
7765 1 : c.clear_paths();
7766 1 : c.add_path(csspp_test::get_script_path());
7767 1 : c.add_path(csspp_test::get_version_script_path());
7768 :
7769 1 : c.compile(true);
7770 :
7771 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
7772 :
7773 1 : VERIFY_ERRORS(
7774 : "test.css(1): error: function declarations with optional parameters must make all parameters optional from the first one that is given an optional value up to the end of the list of arguments.\n"
7775 : //"test.css(1): error: unsupported type LIST as a unary expression token.\n"
7776 : );
7777 :
7778 1 : CATCH_REQUIRE(c.get_root() == n);
7779 1 : }
7780 :
7781 : // missing ':' to define the optional value
7782 : {
7783 1 : std::stringstream ss;
7784 : ss << "$sum($a1, $a2 3px, $a3): ($a1+$a2)/$a3;"
7785 1 : << "div { margin: $sum(6px, 7px, 3); }";
7786 3 : csspp::position pos("test.css");
7787 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
7788 :
7789 2 : csspp::parser p(l);
7790 :
7791 1 : csspp::node::pointer_t n(p.stylesheet());
7792 :
7793 : // no errors so far
7794 1 : VERIFY_ERRORS("");
7795 :
7796 1 : csspp::compiler c;
7797 1 : c.set_root(n);
7798 1 : c.clear_paths();
7799 1 : c.add_path(csspp_test::get_script_path());
7800 1 : c.add_path(csspp_test::get_version_script_path());
7801 :
7802 1 : c.compile(true);
7803 :
7804 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
7805 :
7806 1 : VERIFY_ERRORS(
7807 : "test.css(1): error: function declarations expect variable with optional parameters to use a ':' after the variable name and before the optional value.\n"
7808 : //"test.css(1): error: unsupported type LIST as a unary expression token.\n"
7809 : );
7810 :
7811 1 : CATCH_REQUIRE(c.get_root() == n);
7812 1 : }
7813 :
7814 : // test @include with something else than an identifier or function
7815 : {
7816 1 : std::stringstream ss;
7817 1 : ss << "@include url(invalid/token/for/include);\n";
7818 3 : csspp::position pos("test.css");
7819 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
7820 :
7821 2 : csspp::parser p(l);
7822 :
7823 1 : csspp::node::pointer_t n(p.stylesheet());
7824 :
7825 : // no errors so far
7826 1 : VERIFY_ERRORS("");
7827 :
7828 1 : csspp::compiler c;
7829 1 : c.set_root(n);
7830 1 : c.clear_paths();
7831 1 : c.set_empty_on_undefined_variable(true);
7832 1 : c.add_path(csspp_test::get_script_path());
7833 1 : c.add_path(csspp_test::get_version_script_path());
7834 :
7835 1 : c.compile(true);
7836 :
7837 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
7838 :
7839 1 : VERIFY_ERRORS("test.css(1): error: @include is expected to be followed by an IDENTIFIER or a FUNCTION naming the variable/mixin to include.\n");
7840 :
7841 1 : CATCH_REQUIRE(c.get_root() == n);
7842 1 : }
7843 :
7844 : // test @include with something else than an identifier or function
7845 : {
7846 1 : std::stringstream ss;
7847 : ss << "$empty:null;\n"
7848 1 : << "$empty{color:pink;}\n";
7849 3 : csspp::position pos("test.css");
7850 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
7851 :
7852 2 : csspp::parser p(l);
7853 :
7854 1 : csspp::node::pointer_t n(p.stylesheet());
7855 :
7856 : // no errors so far
7857 1 : VERIFY_ERRORS("");
7858 :
7859 1 : csspp::compiler c;
7860 1 : c.set_root(n);
7861 1 : c.clear_paths();
7862 1 : c.set_empty_on_undefined_variable(true);
7863 1 : c.add_path(csspp_test::get_script_path());
7864 1 : c.add_path(csspp_test::get_version_script_path());
7865 :
7866 1 : c.compile(true);
7867 :
7868 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
7869 :
7870 1 : VERIFY_ERRORS("test.css(2): error: a qualified rule without selectors is not valid.\n");
7871 :
7872 1 : CATCH_REQUIRE(c.get_root() == n);
7873 1 : }
7874 :
7875 : // @mixin with one parameter
7876 : {
7877 1 : std::stringstream ss;
7878 1 : ss << "@mixin nice-button;";
7879 3 : csspp::position pos("test.css");
7880 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
7881 :
7882 2 : csspp::parser p(l);
7883 :
7884 1 : csspp::node::pointer_t n(p.stylesheet());
7885 :
7886 : //std::cerr << "Parser result is: [" << *n << "]\n";
7887 :
7888 : // no errors so far
7889 1 : VERIFY_ERRORS("");
7890 :
7891 1 : csspp::compiler c;
7892 1 : c.set_root(n);
7893 1 : c.clear_paths();
7894 1 : c.set_empty_on_undefined_variable(true);
7895 1 : c.add_path(csspp_test::get_script_path());
7896 1 : c.add_path(csspp_test::get_version_script_path());
7897 :
7898 1 : c.compile(true);
7899 :
7900 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
7901 :
7902 1 : VERIFY_ERRORS("test.css(1): error: a @mixin definition expects exactly two parameters: an identifier or function and a {}-block.\n");
7903 :
7904 1 : CATCH_REQUIRE(c.get_root() == n);
7905 1 : }
7906 :
7907 : // @mixin with one parameter
7908 : {
7909 1 : std::stringstream ss;
7910 1 : ss << "@mixin { div { border: 3px solid #ffe093; } }";
7911 3 : csspp::position pos("test.css");
7912 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
7913 :
7914 2 : csspp::parser p(l);
7915 :
7916 1 : csspp::node::pointer_t n(p.stylesheet());
7917 :
7918 : //std::cerr << "Parser result is: [" << *n << "]\n";
7919 :
7920 : // no errors so far
7921 1 : VERIFY_ERRORS("");
7922 :
7923 1 : csspp::compiler c;
7924 1 : c.set_root(n);
7925 1 : c.clear_paths();
7926 1 : c.set_empty_on_undefined_variable(true);
7927 1 : c.add_path(csspp_test::get_script_path());
7928 1 : c.add_path(csspp_test::get_version_script_path());
7929 :
7930 1 : c.compile(true);
7931 :
7932 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
7933 :
7934 1 : VERIFY_ERRORS("test.css(1): error: a @mixin definition expects exactly two parameters: an identifier or function and a {}-block.\n");
7935 :
7936 1 : CATCH_REQUIRE(c.get_root() == n);
7937 1 : }
7938 :
7939 : // @mixin with too many entries (i.e. "color" " " "#ff3241")
7940 : {
7941 1 : std::stringstream ss;
7942 1 : ss << "@mixin color #ff3241;";
7943 3 : csspp::position pos("test.css");
7944 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
7945 :
7946 2 : csspp::parser p(l);
7947 :
7948 1 : csspp::node::pointer_t n(p.stylesheet());
7949 :
7950 : //std::cerr << "Parser result is: [" << *n << "]\n";
7951 :
7952 : // no errors so far
7953 1 : VERIFY_ERRORS("");
7954 :
7955 1 : csspp::compiler c;
7956 1 : c.set_root(n);
7957 1 : c.clear_paths();
7958 1 : c.set_empty_on_undefined_variable(true);
7959 1 : c.add_path(csspp_test::get_script_path());
7960 1 : c.add_path(csspp_test::get_version_script_path());
7961 :
7962 1 : c.compile(true);
7963 :
7964 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
7965 :
7966 1 : VERIFY_ERRORS("test.css(1): error: a @mixin definition expects exactly two parameters: an identifier or function and a {}-block.\n");
7967 :
7968 1 : CATCH_REQUIRE(c.get_root() == n);
7969 1 : }
7970 :
7971 : // @mixin not with a {}-block
7972 : {
7973 1 : std::stringstream ss;
7974 1 : ss << "@mixin color#ff3241;";
7975 3 : csspp::position pos("test.css");
7976 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
7977 :
7978 2 : csspp::parser p(l);
7979 :
7980 1 : csspp::node::pointer_t n(p.stylesheet());
7981 :
7982 : //std::cerr << "Parser result is: [" << *n << "]\n";
7983 :
7984 : // no errors so far
7985 1 : VERIFY_ERRORS("");
7986 :
7987 1 : csspp::compiler c;
7988 1 : c.set_root(n);
7989 1 : c.clear_paths();
7990 1 : c.set_empty_on_undefined_variable(true);
7991 1 : c.add_path(csspp_test::get_script_path());
7992 1 : c.add_path(csspp_test::get_version_script_path());
7993 :
7994 1 : c.compile(true);
7995 :
7996 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
7997 :
7998 1 : VERIFY_ERRORS("test.css(1): error: a @mixin definition expects a {}-block as its second parameter.\n");
7999 :
8000 1 : CATCH_REQUIRE(c.get_root() == n);
8001 1 : }
8002 :
8003 : // @mixin not with a IDENTIFIER or FUNCTION as first parameter
8004 : {
8005 1 : std::stringstream ss;
8006 1 : ss << "@mixin #ff3241 { color: full; }";
8007 3 : csspp::position pos("test.css");
8008 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
8009 :
8010 2 : csspp::parser p(l);
8011 :
8012 1 : csspp::node::pointer_t n(p.stylesheet());
8013 :
8014 : //std::cerr << "Parser result is: [" << *n << "]\n";
8015 :
8016 : // no errors so far
8017 1 : VERIFY_ERRORS("");
8018 :
8019 1 : csspp::compiler c;
8020 1 : c.set_root(n);
8021 1 : c.clear_paths();
8022 1 : c.set_empty_on_undefined_variable(true);
8023 1 : c.add_path(csspp_test::get_script_path());
8024 1 : c.add_path(csspp_test::get_version_script_path());
8025 :
8026 1 : c.compile(true);
8027 :
8028 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
8029 :
8030 1 : VERIFY_ERRORS("test.css(1): error: a @mixin expects either an IDENTIFIER or a FUNCTION as its first parameter.\n");
8031 :
8032 1 : CATCH_REQUIRE(c.get_root() == n);
8033 1 : }
8034 :
8035 : // @mixin with VARIABLE generates an special error
8036 : {
8037 1 : std::stringstream ss;
8038 1 : ss << "@mixin $var { color: full; }";
8039 3 : csspp::position pos("test.css");
8040 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
8041 :
8042 2 : csspp::parser p(l);
8043 :
8044 1 : csspp::node::pointer_t n(p.stylesheet());
8045 :
8046 : //std::cerr << "Parser result is: [" << *n << "]\n";
8047 :
8048 : // no errors so far
8049 1 : VERIFY_ERRORS("");
8050 :
8051 1 : csspp::compiler c;
8052 1 : c.set_root(n);
8053 1 : c.clear_paths();
8054 1 : c.set_empty_on_undefined_variable(true);
8055 1 : c.add_path(csspp_test::get_script_path());
8056 1 : c.add_path(csspp_test::get_version_script_path());
8057 :
8058 1 : c.compile(true);
8059 :
8060 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
8061 :
8062 1 : VERIFY_ERRORS("test.css(1): error: a @mixin must use an IDENTIFIER or FUNCTION and no a VARIABLE or VARIABLE_FUNCTION.\n");
8063 :
8064 1 : CATCH_REQUIRE(c.get_root() == n);
8065 1 : }
8066 :
8067 : // @mixin with VARIABLE generates an special error
8068 : {
8069 1 : std::stringstream ss;
8070 1 : ss << "@mixin $var($a1, $a2) { color: $a1 + $a2 / 2.5; }";
8071 3 : csspp::position pos("test.css");
8072 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
8073 :
8074 2 : csspp::parser p(l);
8075 :
8076 1 : csspp::node::pointer_t n(p.stylesheet());
8077 :
8078 : //std::cerr << "Parser result is: [" << *n << "]\n";
8079 :
8080 : // no errors so far
8081 1 : VERIFY_ERRORS("");
8082 :
8083 1 : csspp::compiler c;
8084 1 : c.set_root(n);
8085 1 : c.clear_paths();
8086 1 : c.set_empty_on_undefined_variable(true);
8087 1 : c.add_path(csspp_test::get_script_path());
8088 1 : c.add_path(csspp_test::get_version_script_path());
8089 :
8090 1 : c.compile(true);
8091 :
8092 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
8093 :
8094 1 : VERIFY_ERRORS("test.css(1): error: a @mixin must use an IDENTIFIER or FUNCTION and no a VARIABLE or VARIABLE_FUNCTION.\n");
8095 :
8096 1 : CATCH_REQUIRE(c.get_root() == n);
8097 1 : }
8098 :
8099 : // try !global at the wrong place and see the warning
8100 : {
8101 1 : std::stringstream ss;
8102 : ss << "$size: 100px;\n"
8103 : << "div { $size: !global 300px;\n"
8104 : << " entry: {\n"
8105 : << " $size: ! global 50px;\n"
8106 : << " width: $size;\n"
8107 : << " height: $size * 3 / 4;\n"
8108 : << " };\n"
8109 : << " junior: $size + 13px;\n"
8110 : << "}\n"
8111 1 : << "section { diameter: $size }\n";
8112 3 : csspp::position pos("test.css");
8113 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
8114 :
8115 2 : csspp::parser p(l);
8116 :
8117 1 : csspp::node::pointer_t n(p.stylesheet());
8118 :
8119 : // no errors so far
8120 1 : VERIFY_ERRORS("");
8121 :
8122 1 : csspp::compiler c;
8123 1 : c.set_root(n);
8124 1 : c.clear_paths();
8125 1 : c.add_path(csspp_test::get_script_path());
8126 1 : c.add_path(csspp_test::get_version_script_path());
8127 :
8128 1 : c.compile(true);
8129 :
8130 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
8131 :
8132 1 : VERIFY_ERRORS(
8133 : "test.css(2): warning: A special flag, !global in this case, must only appear at the end of a declaration.\n"
8134 : "test.css(3): warning: A special flag, !global in this case, must only appear at the end of a declaration.\n"
8135 : );
8136 :
8137 1 : std::stringstream out;
8138 1 : out << *n;
8139 1 : VERIFY_TREES(out.str(),
8140 :
8141 : "LIST\n"
8142 : " V:size\n"
8143 : " LIST\n"
8144 : " VARIABLE \"size\"\n"
8145 : " INTEGER \"px\" I:50\n"
8146 : " COMPONENT_VALUE\n"
8147 : " ARG\n"
8148 : " IDENTIFIER \"div\"\n"
8149 : " OPEN_CURLYBRACKET B:true\n"
8150 : " LIST\n"
8151 : " DECLARATION \"entry-width\"\n"
8152 : " ARG\n"
8153 : " INTEGER \"px\" I:50\n"
8154 : " DECLARATION \"entry-height\"\n"
8155 : " ARG\n"
8156 : " INTEGER \"px\" I:37\n"
8157 : " DECLARATION \"junior\"\n"
8158 : " ARG\n"
8159 : " INTEGER \"px\" I:63\n"
8160 : " COMPONENT_VALUE\n"
8161 : " ARG\n"
8162 : " IDENTIFIER \"section\"\n"
8163 : " OPEN_CURLYBRACKET B:true\n"
8164 : " DECLARATION \"diameter\"\n"
8165 : " ARG\n"
8166 : " INTEGER \"px\" I:50\n"
8167 :
8168 : );
8169 :
8170 1 : CATCH_REQUIRE(c.get_root() == n);
8171 1 : }
8172 :
8173 : // try !default at the wrong place and see the warning
8174 : {
8175 1 : std::stringstream ss;
8176 : ss << "$size: 100px;\n"
8177 : << "div { $size: !default 300px;\n"
8178 : << " entry: {\n"
8179 : << " $size: ! default 50px;\n"
8180 : << " width: $size;\n"
8181 : << " height: $size * 3 / 4;\n"
8182 : << " };\n"
8183 : << " junior: $size + 13px;\n"
8184 : << "}\n"
8185 1 : << "section { diameter: $size }\n";
8186 3 : csspp::position pos("test.css");
8187 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
8188 :
8189 2 : csspp::parser p(l);
8190 :
8191 1 : csspp::node::pointer_t n(p.stylesheet());
8192 :
8193 : // no errors so far
8194 1 : VERIFY_ERRORS("");
8195 :
8196 1 : csspp::compiler c;
8197 1 : c.set_root(n);
8198 1 : c.clear_paths();
8199 1 : c.add_path(csspp_test::get_script_path());
8200 1 : c.add_path(csspp_test::get_version_script_path());
8201 :
8202 1 : c.compile(true);
8203 :
8204 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
8205 :
8206 1 : VERIFY_ERRORS(
8207 : "test.css(2): warning: A special flag, !default in this case, must only appear at the end of a declaration.\n"
8208 : "test.css(3): warning: A special flag, !default in this case, must only appear at the end of a declaration.\n"
8209 : );
8210 :
8211 1 : std::stringstream out;
8212 1 : out << *n;
8213 1 : VERIFY_TREES(out.str(),
8214 :
8215 : "LIST\n"
8216 : " V:size\n"
8217 : " LIST\n"
8218 : " VARIABLE \"size\"\n"
8219 : " INTEGER \"px\" I:100\n"
8220 : " COMPONENT_VALUE\n"
8221 : " ARG\n"
8222 : " IDENTIFIER \"div\"\n"
8223 : " OPEN_CURLYBRACKET B:true\n"
8224 : " LIST\n"
8225 : " DECLARATION \"entry-width\"\n"
8226 : " ARG\n"
8227 : " INTEGER \"px\" I:100\n"
8228 : " DECLARATION \"entry-height\"\n"
8229 : " ARG\n"
8230 : " INTEGER \"px\" I:75\n"
8231 : " DECLARATION \"junior\"\n"
8232 : " ARG\n"
8233 : " INTEGER \"px\" I:113\n"
8234 : " COMPONENT_VALUE\n"
8235 : " ARG\n"
8236 : " IDENTIFIER \"section\"\n"
8237 : " OPEN_CURLYBRACKET B:true\n"
8238 : " DECLARATION \"diameter\"\n"
8239 : " ARG\n"
8240 : " INTEGER \"px\" I:100\n"
8241 :
8242 : );
8243 :
8244 1 : CATCH_REQUIRE(c.get_root() == n);
8245 1 : }
8246 :
8247 : // no left over?
8248 1 : VERIFY_ERRORS("");
8249 1 : }
8250 :
8251 1 : CATCH_TEST_CASE("At-Keyword ignored", "[compiler] [at-keyword]")
8252 : {
8253 : // make sure @<not supported> is left alone as expected by CSS 3
8254 : {
8255 1 : std::stringstream ss;
8256 1 : ss << "@unknown \"This works?\";";
8257 3 : csspp::position pos("test.css");
8258 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
8259 :
8260 2 : csspp::parser p(l);
8261 :
8262 1 : csspp::node::pointer_t n(p.stylesheet());
8263 :
8264 : // no errors so far
8265 1 : VERIFY_ERRORS("");
8266 :
8267 1 : csspp::compiler c;
8268 1 : c.set_root(n);
8269 1 : c.clear_paths();
8270 1 : c.add_path(csspp_test::get_script_path());
8271 1 : c.add_path(csspp_test::get_version_script_path());
8272 :
8273 1 : c.compile(true);
8274 :
8275 1 : VERIFY_ERRORS("");
8276 :
8277 1 : std::stringstream out;
8278 1 : out << *n;
8279 1 : VERIFY_TREES(out.str(),
8280 :
8281 : "LIST\n"
8282 : " AT_KEYWORD \"unknown\" I:0\n"
8283 : " STRING \"This works?\"\n"
8284 :
8285 : );
8286 :
8287 1 : CATCH_REQUIRE(c.get_root() == n);
8288 1 : }
8289 :
8290 : // make sure @<not supported> is left alone as expected by CSS 3
8291 : {
8292 1 : std::stringstream ss;
8293 1 : ss << "@unknown \"Question?\" { this one has a block }";
8294 3 : csspp::position pos("test.css");
8295 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
8296 :
8297 2 : csspp::parser p(l);
8298 :
8299 1 : csspp::node::pointer_t n(p.stylesheet());
8300 :
8301 : // no errors so far
8302 1 : VERIFY_ERRORS("");
8303 :
8304 1 : csspp::compiler c;
8305 1 : c.set_root(n);
8306 1 : c.clear_paths();
8307 1 : c.add_path(csspp_test::get_script_path());
8308 1 : c.add_path(csspp_test::get_version_script_path());
8309 :
8310 1 : c.compile(true);
8311 :
8312 1 : VERIFY_ERRORS("");
8313 :
8314 1 : std::stringstream out;
8315 1 : out << *n;
8316 1 : VERIFY_TREES(out.str(),
8317 :
8318 : "LIST\n"
8319 : " AT_KEYWORD \"unknown\" I:0\n"
8320 : " STRING \"Question?\"\n"
8321 : " OPEN_CURLYBRACKET B:true\n"
8322 : " COMPONENT_VALUE\n"
8323 : " IDENTIFIER \"this\"\n"
8324 : " WHITESPACE\n"
8325 : " IDENTIFIER \"one\"\n"
8326 : " WHITESPACE\n"
8327 : " IDENTIFIER \"has\"\n"
8328 : " WHITESPACE\n"
8329 : " IDENTIFIER \"a\"\n"
8330 : " WHITESPACE\n"
8331 : " IDENTIFIER \"block\"\n"
8332 :
8333 : );
8334 :
8335 1 : CATCH_REQUIRE(c.get_root() == n);
8336 1 : }
8337 :
8338 : // no left over?
8339 1 : VERIFY_ERRORS("");
8340 1 : }
8341 :
8342 1 : CATCH_TEST_CASE("At-Keyword messages", "[compiler] [output]")
8343 : {
8344 : // generate an error with @error
8345 : {
8346 1 : std::stringstream ss;
8347 1 : ss << "@error \"This is an error.\";";
8348 3 : csspp::position pos("test.css");
8349 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
8350 :
8351 2 : csspp::parser p(l);
8352 :
8353 1 : csspp::node::pointer_t n(p.stylesheet());
8354 :
8355 : // no errors so far
8356 1 : VERIFY_ERRORS("");
8357 :
8358 1 : csspp::compiler c;
8359 1 : c.set_root(n);
8360 1 : c.clear_paths();
8361 1 : c.add_path(csspp_test::get_script_path());
8362 1 : c.add_path(csspp_test::get_version_script_path());
8363 :
8364 1 : c.compile(true);
8365 :
8366 1 : VERIFY_ERRORS("test.css(1): error: This is an error.\n");
8367 :
8368 1 : CATCH_REQUIRE(c.get_root() == n);
8369 1 : }
8370 :
8371 : // generate a warning with @warning
8372 : {
8373 1 : std::stringstream ss;
8374 1 : ss << "@warning \"This is a warning.\";";
8375 3 : csspp::position pos("test.css");
8376 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
8377 :
8378 2 : csspp::parser p(l);
8379 :
8380 1 : csspp::node::pointer_t n(p.stylesheet());
8381 :
8382 : // no errors so far
8383 1 : VERIFY_ERRORS("");
8384 :
8385 1 : csspp::compiler c;
8386 1 : c.set_root(n);
8387 1 : c.clear_paths();
8388 1 : c.add_path(csspp_test::get_script_path());
8389 1 : c.add_path(csspp_test::get_version_script_path());
8390 :
8391 1 : c.compile(true);
8392 :
8393 1 : VERIFY_ERRORS("test.css(1): warning: This is a warning.\n");
8394 :
8395 1 : CATCH_REQUIRE(c.get_root() == n);
8396 1 : }
8397 :
8398 : // output a message with @info
8399 : {
8400 1 : std::stringstream ss;
8401 1 : ss << "@info \"This is an info message.\";";
8402 3 : csspp::position pos("test.css");
8403 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
8404 :
8405 2 : csspp::parser p(l);
8406 :
8407 1 : csspp::node::pointer_t n(p.stylesheet());
8408 :
8409 : // no errors so far
8410 1 : VERIFY_ERRORS("");
8411 :
8412 1 : csspp::compiler c;
8413 1 : c.set_root(n);
8414 1 : c.clear_paths();
8415 1 : c.add_path(csspp_test::get_script_path());
8416 1 : c.add_path(csspp_test::get_version_script_path());
8417 :
8418 1 : c.compile(true);
8419 :
8420 1 : VERIFY_ERRORS("test.css(1): info: This is an info message.\n");
8421 :
8422 1 : CATCH_REQUIRE(c.get_root() == n);
8423 1 : }
8424 :
8425 : // make sure @message does the same as @info
8426 : {
8427 1 : std::stringstream ss;
8428 1 : ss << "@message \"This is an info message.\";";
8429 3 : csspp::position pos("test.css");
8430 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
8431 :
8432 2 : csspp::parser p(l);
8433 :
8434 1 : csspp::node::pointer_t n(p.stylesheet());
8435 :
8436 : // no errors so far
8437 1 : VERIFY_ERRORS("");
8438 :
8439 1 : csspp::compiler c;
8440 1 : c.set_root(n);
8441 1 : c.clear_paths();
8442 1 : c.add_path(csspp_test::get_script_path());
8443 1 : c.add_path(csspp_test::get_version_script_path());
8444 :
8445 1 : c.compile(true);
8446 :
8447 1 : VERIFY_ERRORS("test.css(1): info: This is an info message.\n");
8448 :
8449 1 : CATCH_REQUIRE(c.get_root() == n);
8450 1 : }
8451 :
8452 : // test @debug does nothing by default
8453 : {
8454 1 : std::stringstream ss;
8455 1 : ss << "@debug \"This is a debug message.\";";
8456 3 : csspp::position pos("test.css");
8457 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
8458 :
8459 2 : csspp::parser p(l);
8460 :
8461 1 : csspp::node::pointer_t n(p.stylesheet());
8462 :
8463 : // no errors so far
8464 1 : VERIFY_ERRORS("");
8465 :
8466 1 : csspp::compiler c;
8467 1 : c.set_root(n);
8468 1 : c.clear_paths();
8469 1 : c.add_path(csspp_test::get_script_path());
8470 1 : c.add_path(csspp_test::get_version_script_path());
8471 :
8472 1 : c.compile(true);
8473 :
8474 : // by default debug messages do not make it to the output
8475 1 : VERIFY_ERRORS("");
8476 :
8477 1 : CATCH_REQUIRE(c.get_root() == n);
8478 1 : }
8479 :
8480 : // make sure @debug does the same as @info
8481 : {
8482 1 : std::stringstream ss;
8483 1 : ss << "@debug \"This is a debug message.\";";
8484 3 : csspp::position pos("test.css");
8485 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
8486 :
8487 2 : csspp::parser p(l);
8488 :
8489 1 : csspp::node::pointer_t n(p.stylesheet());
8490 :
8491 : // no errors so far
8492 1 : VERIFY_ERRORS("");
8493 :
8494 1 : csspp::compiler c;
8495 1 : c.set_root(n);
8496 1 : c.clear_paths();
8497 1 : c.add_path(csspp_test::get_script_path());
8498 1 : c.add_path(csspp_test::get_version_script_path());
8499 :
8500 1 : csspp::error::instance().set_show_debug(true);
8501 1 : c.compile(true);
8502 1 : csspp::error::instance().set_show_debug(false);
8503 :
8504 1 : VERIFY_ERRORS("test.css(1): debug: This is a debug message.\n");
8505 :
8506 1 : CATCH_REQUIRE(c.get_root() == n);
8507 1 : }
8508 :
8509 : // no left over?
8510 1 : VERIFY_ERRORS("");
8511 1 : }
8512 :
8513 1 : CATCH_TEST_CASE("At-Keyword with qualified rules", "[compiler] [at-keyword]")
8514 : {
8515 : // a valid @document
8516 : {
8517 1 : std::stringstream ss;
8518 1 : ss << "@document { body { content: \"Utf-16\" } }\n";
8519 3 : csspp::position pos("test.css");
8520 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
8521 :
8522 2 : csspp::parser p(l);
8523 :
8524 1 : csspp::node::pointer_t n(p.stylesheet());
8525 :
8526 : // no errors so far
8527 1 : VERIFY_ERRORS("");
8528 :
8529 1 : csspp::compiler c;
8530 1 : c.set_root(n);
8531 1 : c.clear_paths();
8532 1 : c.add_path(csspp_test::get_script_path());
8533 1 : c.add_path(csspp_test::get_version_script_path());
8534 :
8535 1 : c.compile(true);
8536 :
8537 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
8538 :
8539 1 : VERIFY_ERRORS("");
8540 :
8541 1 : std::stringstream out;
8542 1 : out << *n;
8543 1 : VERIFY_TREES(out.str(),
8544 :
8545 : "LIST\n"
8546 : " AT_KEYWORD \"document\" I:0\n"
8547 : " OPEN_CURLYBRACKET B:true\n"
8548 : " COMPONENT_VALUE\n"
8549 : " ARG\n"
8550 : " IDENTIFIER \"body\"\n"
8551 : " OPEN_CURLYBRACKET B:true\n"
8552 : " DECLARATION \"content\"\n"
8553 : " ARG\n"
8554 : " STRING \"Utf-16\"\n"
8555 :
8556 : );
8557 :
8558 1 : CATCH_REQUIRE(c.get_root() == n);
8559 1 : }
8560 :
8561 : // a valid @document with @if inside of there
8562 : {
8563 1 : std::stringstream ss;
8564 : ss << "$agent: 'Firefox';\n"
8565 : << "@document {\n"
8566 : << "body { content: \"Utf-16\" }\n"
8567 : << "@if $agent = 'Firefox' { body { margin: 0 } div { border: 1px solid white } }\n"
8568 1 : << " }\n";
8569 3 : csspp::position pos("test.css");
8570 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
8571 :
8572 2 : csspp::parser p(l);
8573 :
8574 1 : csspp::node::pointer_t n(p.stylesheet());
8575 :
8576 : // no errors so far
8577 1 : VERIFY_ERRORS("");
8578 :
8579 1 : csspp::compiler c;
8580 1 : c.set_root(n);
8581 1 : c.clear_paths();
8582 1 : c.add_path(csspp_test::get_script_path());
8583 1 : c.add_path(csspp_test::get_version_script_path());
8584 :
8585 1 : c.compile(true);
8586 :
8587 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
8588 :
8589 1 : VERIFY_ERRORS("");
8590 :
8591 1 : std::stringstream out;
8592 1 : out << *n;
8593 1 : VERIFY_TREES(out.str(),
8594 :
8595 : "LIST\n"
8596 : " V:agent\n"
8597 : " LIST\n"
8598 : " VARIABLE \"agent\"\n"
8599 : " STRING \"Firefox\"\n"
8600 : " AT_KEYWORD \"document\" I:0\n"
8601 : " OPEN_CURLYBRACKET B:true\n"
8602 : " COMPONENT_VALUE\n"
8603 : " ARG\n"
8604 : " IDENTIFIER \"body\"\n"
8605 : " OPEN_CURLYBRACKET B:true\n"
8606 : " DECLARATION \"content\"\n"
8607 : " ARG\n"
8608 : " STRING \"Utf-16\"\n"
8609 : " COMPONENT_VALUE\n"
8610 : " ARG\n"
8611 : " IDENTIFIER \"body\"\n"
8612 : " OPEN_CURLYBRACKET B:true\n"
8613 : " DECLARATION \"margin\"\n"
8614 : " ARG\n"
8615 : " INTEGER \"\" I:0\n"
8616 : " COMPONENT_VALUE\n"
8617 : " ARG\n"
8618 : " IDENTIFIER \"div\"\n"
8619 : " OPEN_CURLYBRACKET B:true\n"
8620 : " DECLARATION \"border\"\n"
8621 : " ARG\n"
8622 : " INTEGER \"px\" I:1\n"
8623 : " WHITESPACE\n"
8624 : " IDENTIFIER \"solid\"\n"
8625 : " WHITESPACE\n"
8626 : " COLOR H:ffffffff\n"
8627 :
8628 : );
8629 :
8630 1 : CATCH_REQUIRE(c.get_root() == n);
8631 1 : }
8632 :
8633 : // a valid @media
8634 : {
8635 1 : std::stringstream ss;
8636 1 : ss << "@media screen { i { font-style: normal } }\n";
8637 3 : csspp::position pos("test.css");
8638 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
8639 :
8640 2 : csspp::parser p(l);
8641 :
8642 1 : csspp::node::pointer_t n(p.stylesheet());
8643 :
8644 : // no errors so far
8645 1 : VERIFY_ERRORS("");
8646 :
8647 1 : csspp::compiler c;
8648 1 : c.set_root(n);
8649 1 : c.clear_paths();
8650 1 : c.add_path(csspp_test::get_script_path());
8651 1 : c.add_path(csspp_test::get_version_script_path());
8652 :
8653 1 : c.compile(true);
8654 :
8655 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
8656 :
8657 1 : VERIFY_ERRORS("");
8658 :
8659 1 : std::stringstream out;
8660 1 : out << *n;
8661 1 : VERIFY_TREES(out.str(),
8662 :
8663 : "LIST\n"
8664 : " AT_KEYWORD \"media\" I:0\n"
8665 : " ARG\n"
8666 : " IDENTIFIER \"screen\"\n"
8667 : " OPEN_CURLYBRACKET B:true\n"
8668 : " COMPONENT_VALUE\n"
8669 : " ARG\n"
8670 : " IDENTIFIER \"i\"\n"
8671 : " OPEN_CURLYBRACKET B:true\n"
8672 : " DECLARATION \"font-style\"\n"
8673 : " ARG\n"
8674 : " IDENTIFIER \"normal\"\n"
8675 :
8676 : );
8677 :
8678 1 : CATCH_REQUIRE(c.get_root() == n);
8679 1 : }
8680 :
8681 : // nested @media
8682 : {
8683 1 : std::stringstream ss;
8684 : ss << "@media screen {\n"
8685 : << " i { font-style: normal }\n"
8686 : << " @media max-width(12cm) {\n"
8687 : << " b { font-weight: normal }\n"
8688 : << " }\n"
8689 1 : << "}\n";
8690 3 : csspp::position pos("test.css");
8691 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
8692 :
8693 2 : csspp::parser p(l);
8694 :
8695 1 : csspp::node::pointer_t n(p.stylesheet());
8696 :
8697 : // no errors so far
8698 1 : VERIFY_ERRORS("");
8699 :
8700 1 : csspp::compiler c;
8701 1 : c.set_root(n);
8702 1 : c.clear_paths();
8703 1 : c.add_path(csspp_test::get_script_path());
8704 1 : c.add_path(csspp_test::get_version_script_path());
8705 :
8706 1 : c.compile(true);
8707 :
8708 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
8709 :
8710 1 : VERIFY_ERRORS("");
8711 :
8712 1 : std::stringstream out;
8713 1 : out << *n;
8714 1 : VERIFY_TREES(out.str(),
8715 :
8716 : "LIST\n"
8717 : " AT_KEYWORD \"media\" I:0\n"
8718 : " ARG\n"
8719 : " IDENTIFIER \"screen\"\n"
8720 : " OPEN_CURLYBRACKET B:true\n"
8721 : " COMPONENT_VALUE\n"
8722 : " ARG\n"
8723 : " IDENTIFIER \"i\"\n"
8724 : " OPEN_CURLYBRACKET B:true\n"
8725 : " DECLARATION \"font-style\"\n"
8726 : " ARG\n"
8727 : " IDENTIFIER \"normal\"\n"
8728 : " COMPONENT_VALUE\n"
8729 : " AT_KEYWORD \"media\" I:0\n"
8730 : " ARG\n"
8731 : " FUNCTION \"max-width\"\n"
8732 : " INTEGER \"cm\" I:12\n"
8733 : " OPEN_CURLYBRACKET B:true\n"
8734 : " COMPONENT_VALUE\n"
8735 : " ARG\n"
8736 : " IDENTIFIER \"b\"\n"
8737 : " OPEN_CURLYBRACKET B:true\n"
8738 : " DECLARATION \"font-weight\"\n"
8739 : " ARG\n"
8740 : " IDENTIFIER \"normal\"\n"
8741 :
8742 : );
8743 :
8744 1 : CATCH_REQUIRE(c.get_root() == n);
8745 1 : }
8746 :
8747 : // a valid @supports
8748 : {
8749 1 : std::stringstream ss;
8750 1 : ss << "@supports not (screen and desktop) { b { font-weight: normal } }\n";
8751 3 : csspp::position pos("test.css");
8752 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
8753 :
8754 2 : csspp::parser p(l);
8755 :
8756 1 : csspp::node::pointer_t n(p.stylesheet());
8757 :
8758 : // no errors so far
8759 1 : VERIFY_ERRORS("");
8760 :
8761 1 : csspp::compiler c;
8762 1 : c.set_root(n);
8763 1 : c.clear_paths();
8764 1 : c.add_path(csspp_test::get_script_path());
8765 1 : c.add_path(csspp_test::get_version_script_path());
8766 :
8767 1 : c.compile(true);
8768 :
8769 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
8770 :
8771 1 : VERIFY_ERRORS("");
8772 :
8773 1 : std::stringstream out;
8774 1 : out << *n;
8775 1 : VERIFY_TREES(out.str(),
8776 :
8777 : "LIST\n"
8778 : " AT_KEYWORD \"supports\" I:0\n"
8779 : " ARG\n"
8780 : " IDENTIFIER \"not\"\n"
8781 : " OPEN_PARENTHESIS\n"
8782 : " IDENTIFIER \"screen\"\n"
8783 : " WHITESPACE\n"
8784 : " IDENTIFIER \"and\"\n"
8785 : " WHITESPACE\n"
8786 : " IDENTIFIER \"desktop\"\n"
8787 : " OPEN_CURLYBRACKET B:true\n"
8788 : " COMPONENT_VALUE\n"
8789 : " ARG\n"
8790 : " IDENTIFIER \"b\"\n"
8791 : " OPEN_CURLYBRACKET B:true\n"
8792 : " DECLARATION \"font-weight\"\n"
8793 : " ARG\n"
8794 : " IDENTIFIER \"normal\"\n"
8795 :
8796 : );
8797 :
8798 1 : CATCH_REQUIRE(c.get_root() == n);
8799 1 : }
8800 :
8801 : // no left over?
8802 1 : VERIFY_ERRORS("");
8803 1 : }
8804 :
8805 1 : CATCH_TEST_CASE("Invalid at-keyword expecting qualified rules", "[compiler] [at-keyword]")
8806 : {
8807 : // a @supports without a {}-block
8808 : {
8809 1 : std::stringstream ss;
8810 1 : ss << "@supports not (screen and desktop);\n";
8811 3 : csspp::position pos("test.css");
8812 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
8813 :
8814 2 : csspp::parser p(l);
8815 :
8816 1 : csspp::node::pointer_t n(p.stylesheet());
8817 :
8818 : // no errors so far
8819 1 : VERIFY_ERRORS("");
8820 :
8821 1 : csspp::compiler c;
8822 1 : c.set_root(n);
8823 1 : c.clear_paths();
8824 1 : c.add_path(csspp_test::get_script_path());
8825 1 : c.add_path(csspp_test::get_version_script_path());
8826 :
8827 1 : c.compile(true);
8828 :
8829 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
8830 :
8831 1 : VERIFY_ERRORS("");
8832 :
8833 1 : std::stringstream out;
8834 1 : out << *n;
8835 1 : VERIFY_TREES(out.str(),
8836 :
8837 : "LIST\n"
8838 : " AT_KEYWORD \"supports\" I:0\n"
8839 : " IDENTIFIER \"not\"\n"
8840 : " OPEN_PARENTHESIS\n"
8841 : " IDENTIFIER \"screen\"\n"
8842 : " WHITESPACE\n"
8843 : " IDENTIFIER \"and\"\n"
8844 : " WHITESPACE\n"
8845 : " IDENTIFIER \"desktop\"\n"
8846 :
8847 : );
8848 :
8849 1 : CATCH_REQUIRE(c.get_root() == n);
8850 1 : }
8851 :
8852 : // no left over?
8853 1 : VERIFY_ERRORS("");
8854 1 : }
8855 :
8856 1 : CATCH_TEST_CASE("At-Keyword with declarations", "[compiler] [at-keyword]")
8857 : {
8858 : // a valid @page
8859 : {
8860 1 : std::stringstream ss;
8861 1 : ss << "@page { left: 2in; right: 2.2in; }\n";
8862 3 : csspp::position pos("test.css");
8863 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
8864 :
8865 2 : csspp::parser p(l);
8866 :
8867 1 : csspp::node::pointer_t n(p.stylesheet());
8868 :
8869 : // no errors so far
8870 1 : VERIFY_ERRORS("");
8871 :
8872 1 : csspp::compiler c;
8873 1 : c.set_root(n);
8874 1 : c.clear_paths();
8875 1 : c.add_path(csspp_test::get_script_path());
8876 1 : c.add_path(csspp_test::get_version_script_path());
8877 :
8878 1 : c.compile(true);
8879 :
8880 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
8881 :
8882 1 : VERIFY_ERRORS("");
8883 :
8884 1 : std::stringstream out;
8885 1 : out << *n;
8886 1 : VERIFY_TREES(out.str(),
8887 :
8888 : "LIST\n"
8889 : " AT_KEYWORD \"page\" I:0\n"
8890 : " OPEN_CURLYBRACKET B:true\n"
8891 : " LIST\n"
8892 : " DECLARATION \"left\"\n"
8893 : " ARG\n"
8894 : " INTEGER \"in\" I:2\n"
8895 : " DECLARATION \"right\"\n"
8896 : " ARG\n"
8897 : " DECIMAL_NUMBER \"in\" D:2.2\n"
8898 :
8899 : );
8900 :
8901 1 : CATCH_REQUIRE(c.get_root() == n);
8902 1 : }
8903 :
8904 : // @page with an @media inside
8905 : {
8906 1 : std::stringstream ss;
8907 : ss << "@page {\n"
8908 : << " left: 2in;\n"
8909 : << " right: 2.2in;\n"
8910 : << " @media screen {\n"
8911 : << " .arg { color: grey }\n"
8912 : << " }\n"
8913 1 : << "}\n";
8914 3 : csspp::position pos("test.css");
8915 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
8916 :
8917 2 : csspp::parser p(l);
8918 :
8919 1 : csspp::node::pointer_t n(p.stylesheet());
8920 :
8921 : // no errors so far
8922 1 : VERIFY_ERRORS("");
8923 :
8924 1 : csspp::compiler c;
8925 1 : c.set_root(n);
8926 1 : c.clear_paths();
8927 1 : c.add_path(csspp_test::get_script_path());
8928 1 : c.add_path(csspp_test::get_version_script_path());
8929 :
8930 1 : c.compile(true);
8931 :
8932 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
8933 :
8934 1 : VERIFY_ERRORS("");
8935 :
8936 1 : std::stringstream out;
8937 1 : out << *n;
8938 1 : VERIFY_TREES(out.str(),
8939 :
8940 : "LIST\n"
8941 : " AT_KEYWORD \"page\" I:0\n"
8942 : " OPEN_CURLYBRACKET B:true\n"
8943 : " LIST\n"
8944 : " DECLARATION \"left\"\n"
8945 : " ARG\n"
8946 : " INTEGER \"in\" I:2\n"
8947 : " DECLARATION \"right\"\n"
8948 : " ARG\n"
8949 : " DECIMAL_NUMBER \"in\" D:2.2\n"
8950 : " COMPONENT_VALUE\n"
8951 : " AT_KEYWORD \"media\" I:0\n"
8952 : " ARG\n"
8953 : " IDENTIFIER \"screen\"\n"
8954 : " OPEN_CURLYBRACKET B:true\n"
8955 : " COMPONENT_VALUE\n"
8956 : " ARG\n"
8957 : " PERIOD\n"
8958 : " IDENTIFIER \"arg\"\n"
8959 : " OPEN_CURLYBRACKET B:true\n"
8960 : " DECLARATION \"color\"\n"
8961 : " ARG\n"
8962 : " COLOR H:ff808080\n"
8963 :
8964 : );
8965 :
8966 1 : CATCH_REQUIRE(c.get_root() == n);
8967 1 : }
8968 :
8969 : // a valid @supports
8970 : {
8971 1 : std::stringstream ss;
8972 1 : ss << "@font-face{unicode-range: U+4??;font-style:italic}\n";
8973 3 : csspp::position pos("test.css");
8974 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
8975 :
8976 2 : csspp::parser p(l);
8977 :
8978 1 : csspp::node::pointer_t n(p.stylesheet());
8979 :
8980 : // no errors so far
8981 1 : VERIFY_ERRORS("");
8982 :
8983 1 : csspp::compiler c;
8984 1 : c.set_root(n);
8985 1 : c.clear_paths();
8986 1 : c.add_path(csspp_test::get_script_path());
8987 1 : c.add_path(csspp_test::get_version_script_path());
8988 :
8989 1 : c.compile(true);
8990 :
8991 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
8992 :
8993 1 : VERIFY_ERRORS("");
8994 :
8995 1 : std::stringstream out;
8996 1 : out << *n;
8997 1 : VERIFY_TREES(out.str(),
8998 :
8999 : "LIST\n"
9000 : " AT_KEYWORD \"font-face\" I:0\n"
9001 : " OPEN_CURLYBRACKET B:true\n"
9002 : " LIST\n"
9003 : " DECLARATION \"unicode-range\"\n"
9004 : " ARG\n"
9005 : " UNICODE_RANGE I:5493263172608\n"
9006 : " DECLARATION \"font-style\"\n"
9007 : " ARG\n"
9008 : " IDENTIFIER \"italic\"\n"
9009 :
9010 : );
9011 :
9012 1 : CATCH_REQUIRE(c.get_root() == n);
9013 1 : }
9014 :
9015 : // no left over?
9016 1 : VERIFY_ERRORS("");
9017 1 : }
9018 :
9019 1 : CATCH_TEST_CASE("Charset", "[compiler] [invalid]")
9020 : {
9021 : // a valid @charset
9022 : {
9023 1 : std::stringstream ss;
9024 : ss << "@charset \"Utf-8\";\n"
9025 1 : << "html{margin:0}\n";
9026 3 : csspp::position pos("test.css");
9027 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
9028 :
9029 2 : csspp::parser p(l);
9030 :
9031 1 : csspp::node::pointer_t n(p.stylesheet());
9032 :
9033 : // no errors so far
9034 1 : VERIFY_ERRORS("");
9035 :
9036 1 : csspp::compiler c;
9037 1 : c.set_root(n);
9038 1 : c.clear_paths();
9039 1 : c.add_path(csspp_test::get_script_path());
9040 1 : c.add_path(csspp_test::get_version_script_path());
9041 :
9042 1 : c.compile(true);
9043 :
9044 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
9045 :
9046 1 : VERIFY_ERRORS("");
9047 :
9048 1 : std::stringstream out;
9049 1 : out << *n;
9050 1 : VERIFY_TREES(out.str(),
9051 :
9052 : "LIST\n"
9053 : " COMPONENT_VALUE\n"
9054 : " ARG\n"
9055 : " IDENTIFIER \"html\"\n"
9056 : " OPEN_CURLYBRACKET B:true\n"
9057 : " DECLARATION \"margin\"\n"
9058 : " ARG\n"
9059 : " INTEGER \"\" I:0\n"
9060 :
9061 : );
9062 :
9063 1 : CATCH_REQUIRE(c.get_root() == n);
9064 1 : }
9065 :
9066 : // a valid @charset with many spaces
9067 : {
9068 1 : std::stringstream ss;
9069 : ss << " @charset \" UTF-8 \" ;\n"
9070 1 : << "html{margin:0}\n";
9071 3 : csspp::position pos("test.css");
9072 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
9073 :
9074 2 : csspp::parser p(l);
9075 :
9076 1 : csspp::node::pointer_t n(p.stylesheet());
9077 :
9078 : // no errors so far
9079 1 : VERIFY_ERRORS("");
9080 :
9081 1 : csspp::compiler c;
9082 1 : c.set_root(n);
9083 1 : c.clear_paths();
9084 1 : c.add_path(csspp_test::get_script_path());
9085 1 : c.add_path(csspp_test::get_version_script_path());
9086 :
9087 1 : c.compile(true);
9088 :
9089 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
9090 :
9091 1 : VERIFY_ERRORS("");
9092 :
9093 1 : std::stringstream out;
9094 1 : out << *n;
9095 1 : VERIFY_TREES(out.str(),
9096 :
9097 : "LIST\n"
9098 : " COMPONENT_VALUE\n"
9099 : " ARG\n"
9100 : " IDENTIFIER \"html\"\n"
9101 : " OPEN_CURLYBRACKET B:true\n"
9102 : " DECLARATION \"margin\"\n"
9103 : " ARG\n"
9104 : " INTEGER \"\" I:0\n"
9105 :
9106 : );
9107 :
9108 1 : CATCH_REQUIRE(c.get_root() == n);
9109 1 : }
9110 :
9111 : // an @charset with a refused encoding
9112 : {
9113 1 : std::stringstream ss;
9114 : ss << "@charset \"iso-8859-6\";\n"
9115 1 : << "html{margin:0}\n";
9116 3 : csspp::position pos("test.css");
9117 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
9118 :
9119 2 : csspp::parser p(l);
9120 :
9121 1 : csspp::node::pointer_t n(p.stylesheet());
9122 :
9123 : // no errors so far
9124 1 : VERIFY_ERRORS("");
9125 :
9126 1 : csspp::compiler c;
9127 1 : c.set_root(n);
9128 1 : c.clear_paths();
9129 1 : c.add_path(csspp_test::get_script_path());
9130 1 : c.add_path(csspp_test::get_version_script_path());
9131 :
9132 1 : c.compile(true);
9133 :
9134 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
9135 :
9136 1 : VERIFY_ERRORS("test.css(1): error: we only support @charset \"utf-8\";, any other encoding is refused.\n");
9137 :
9138 1 : std::stringstream out;
9139 1 : out << *n;
9140 1 : VERIFY_TREES(out.str(),
9141 :
9142 : "LIST\n"
9143 : " COMPONENT_VALUE\n"
9144 : " ARG\n"
9145 : " IDENTIFIER \"html\"\n"
9146 : " OPEN_CURLYBRACKET B:true\n"
9147 : " DECLARATION \"margin\"\n"
9148 : " ARG\n"
9149 : " INTEGER \"\" I:0\n"
9150 :
9151 : );
9152 :
9153 1 : CATCH_REQUIRE(c.get_root() == n);
9154 1 : }
9155 :
9156 : // an @charset with a decimal number
9157 : {
9158 1 : std::stringstream ss;
9159 : ss << "@charset 8859.6;\n"
9160 1 : << "html{margin:0}\n";
9161 3 : csspp::position pos("test.css");
9162 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
9163 :
9164 2 : csspp::parser p(l);
9165 :
9166 1 : csspp::node::pointer_t n(p.stylesheet());
9167 :
9168 : // no errors so far
9169 1 : VERIFY_ERRORS("");
9170 :
9171 1 : csspp::compiler c;
9172 1 : c.set_root(n);
9173 1 : c.clear_paths();
9174 1 : c.add_path(csspp_test::get_script_path());
9175 1 : c.add_path(csspp_test::get_version_script_path());
9176 :
9177 1 : c.compile(true);
9178 :
9179 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
9180 :
9181 1 : VERIFY_ERRORS("test.css(1): error: the @charset is expected to be followed by exactly one string.\n");
9182 :
9183 1 : std::stringstream out;
9184 1 : out << *n;
9185 1 : VERIFY_TREES(out.str(),
9186 :
9187 : "LIST\n"
9188 : " COMPONENT_VALUE\n"
9189 : " ARG\n"
9190 : " IDENTIFIER \"html\"\n"
9191 : " OPEN_CURLYBRACKET B:true\n"
9192 : " DECLARATION \"margin\"\n"
9193 : " ARG\n"
9194 : " INTEGER \"\" I:0\n"
9195 :
9196 : );
9197 :
9198 1 : CATCH_REQUIRE(c.get_root() == n);
9199 1 : }
9200 :
9201 : // no left over?
9202 1 : VERIFY_ERRORS("");
9203 1 : }
9204 :
9205 1 : CATCH_TEST_CASE("Conditional compilation", "[compiler] [conditional]")
9206 : {
9207 : // script with @if / @else if / @else keywords
9208 : {
9209 1 : std::stringstream ss;
9210 : ss << "$var: true;\n"
9211 : << "@if $var { @message \"Got here! (1)\" ; }\n"
9212 : << "@else if $var { @message \"Got here! (2)\";}\n"
9213 : << "@else{@message\"Got here! (3)\";}\n"
9214 1 : << "ul { list: cross; }";
9215 3 : csspp::position pos("test.css");
9216 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
9217 :
9218 2 : csspp::parser p(l);
9219 :
9220 1 : csspp::node::pointer_t n(p.stylesheet());
9221 :
9222 : //std::cerr << "Parser result is: [" << *n << "]\n";
9223 :
9224 : // no errors so far
9225 1 : VERIFY_ERRORS("");
9226 :
9227 1 : csspp::compiler c;
9228 1 : c.set_root(n);
9229 1 : c.clear_paths();
9230 1 : c.add_path(csspp_test::get_script_path());
9231 1 : c.add_path(csspp_test::get_version_script_path());
9232 :
9233 1 : c.compile(true);
9234 :
9235 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
9236 :
9237 1 : VERIFY_ERRORS("test.css(2): info: Got here! (1)\n");
9238 :
9239 1 : std::stringstream out;
9240 1 : out << *n;
9241 1 : VERIFY_TREES(out.str(),
9242 :
9243 : "LIST\n"
9244 : " V:var\n"
9245 : " LIST\n"
9246 : " VARIABLE \"var\"\n"
9247 : " IDENTIFIER \"true\"\n"
9248 : " COMPONENT_VALUE\n"
9249 : " ARG\n"
9250 : " IDENTIFIER \"ul\"\n"
9251 : " OPEN_CURLYBRACKET B:true\n"
9252 : " DECLARATION \"list\"\n"
9253 : " ARG\n"
9254 : " IDENTIFIER \"cross\"\n"
9255 :
9256 : );
9257 :
9258 1 : CATCH_REQUIRE(c.get_root() == n);
9259 1 : }
9260 :
9261 : // script with @if / @else if / @else keywords
9262 : {
9263 1 : std::stringstream ss;
9264 : ss << "$var: 2;\n"
9265 : << "@if $var = 1 { @message \"Got here! (1)\" ; }\n"
9266 : << "@else if $var = 2 { @message \"Got here! (2)\";}\n"
9267 : << "@else{@message\"Got here! (3)\";}\n"
9268 1 : << "ul { list: cross; }";
9269 3 : csspp::position pos("test.css");
9270 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
9271 :
9272 2 : csspp::parser p(l);
9273 :
9274 1 : csspp::node::pointer_t n(p.stylesheet());
9275 :
9276 : // no errors so far
9277 1 : VERIFY_ERRORS("");
9278 :
9279 1 : csspp::compiler c;
9280 1 : c.set_root(n);
9281 1 : c.clear_paths();
9282 1 : c.add_path(csspp_test::get_script_path());
9283 1 : c.add_path(csspp_test::get_version_script_path());
9284 :
9285 1 : c.compile(true);
9286 :
9287 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
9288 :
9289 1 : VERIFY_ERRORS("test.css(3): info: Got here! (2)\n");
9290 :
9291 1 : std::stringstream out;
9292 1 : out << *n;
9293 1 : VERIFY_TREES(out.str(),
9294 :
9295 : "LIST\n"
9296 : " V:var\n"
9297 : " LIST\n"
9298 : " VARIABLE \"var\"\n"
9299 : " INTEGER \"\" I:2\n"
9300 : " COMPONENT_VALUE\n"
9301 : " ARG\n"
9302 : " IDENTIFIER \"ul\"\n"
9303 : " OPEN_CURLYBRACKET B:true\n"
9304 : " DECLARATION \"list\"\n"
9305 : " ARG\n"
9306 : " IDENTIFIER \"cross\"\n"
9307 :
9308 : );
9309 :
9310 1 : CATCH_REQUIRE(c.get_root() == n);
9311 1 : }
9312 :
9313 : // script with @if / @else if / @else keywords
9314 : {
9315 1 : std::stringstream ss;
9316 : ss << "$var: -192;\n"
9317 : << "@if $var = 1 { @message \"Got here! (1)\" ; }\n"
9318 : << "@else if $var = 2 { @message \"Got here! (2)\";}\n"
9319 : << "@else{@message\"Got here! (3)\";}\n"
9320 1 : << "ul { list: cross; }";
9321 3 : csspp::position pos("test.css");
9322 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
9323 :
9324 2 : csspp::parser p(l);
9325 :
9326 1 : csspp::node::pointer_t n(p.stylesheet());
9327 :
9328 : // no errors so far
9329 1 : VERIFY_ERRORS("");
9330 :
9331 1 : csspp::compiler c;
9332 1 : c.set_root(n);
9333 1 : c.clear_paths();
9334 1 : c.add_path(csspp_test::get_script_path());
9335 1 : c.add_path(csspp_test::get_version_script_path());
9336 :
9337 1 : c.compile(true);
9338 :
9339 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
9340 :
9341 1 : VERIFY_ERRORS("test.css(4): info: Got here! (3)\n");
9342 :
9343 1 : std::stringstream out;
9344 1 : out << *n;
9345 1 : VERIFY_TREES(out.str(),
9346 :
9347 : "LIST\n"
9348 : " V:var\n"
9349 : " LIST\n"
9350 : " VARIABLE \"var\"\n"
9351 : " INTEGER \"\" I:-192\n"
9352 : " COMPONENT_VALUE\n"
9353 : " ARG\n"
9354 : " IDENTIFIER \"ul\"\n"
9355 : " OPEN_CURLYBRACKET B:true\n"
9356 : " DECLARATION \"list\"\n"
9357 : " ARG\n"
9358 : " IDENTIFIER \"cross\"\n"
9359 :
9360 : );
9361 :
9362 1 : CATCH_REQUIRE(c.get_root() == n);
9363 1 : }
9364 :
9365 : // no left over?
9366 1 : VERIFY_ERRORS("");
9367 1 : }
9368 :
9369 1 : CATCH_TEST_CASE("Invalid conditional", "[compiler] [conditional] [invalid]")
9370 : {
9371 : // script with @if / @else if / @else keywords
9372 : // invalid "@else if" which includes an expression
9373 : {
9374 1 : std::stringstream ss;
9375 : ss << "$zzvar: false;\n"
9376 : << "@if { @message \"Got here! (1)\" ; }\n"
9377 : << "@else if { @message \"Got here! (2)\";}\n"
9378 : << "@else{@message\"Got here! (3)\";}\n"
9379 1 : << "ul { list: cross; }";
9380 3 : csspp::position pos("test.css");
9381 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
9382 :
9383 2 : csspp::parser p(l);
9384 :
9385 1 : csspp::node::pointer_t n(p.stylesheet());
9386 :
9387 : //std::cerr << "Parser result is: [" << *n << "]\n";
9388 :
9389 : // no errors so far
9390 1 : VERIFY_ERRORS("");
9391 :
9392 1 : csspp::compiler c;
9393 1 : c.set_root(n);
9394 1 : c.set_date_time_variables(csspp_test::get_now());
9395 1 : c.clear_paths();
9396 1 : c.add_path(csspp_test::get_script_path());
9397 1 : c.add_path(csspp_test::get_version_script_path());
9398 :
9399 1 : c.compile(false);
9400 :
9401 : //std::cerr << "Compiler result is: [" << *c.get_root() << "]\n";
9402 :
9403 1 : VERIFY_ERRORS(
9404 : "test.css(2): error: @if is expected to have exactly 2 parameters: an expression and a block. This @if has 1 parameters.\n"
9405 : "test.css(3): error: '@else if ...' is missing an expression or a block.\n"
9406 : //"test.css(3): error: a standalone @else is not legal, it has to be preceeded by an @if ... or @else if ...\n"
9407 : //"test.css(4): error: a standalone @else is not legal, it has to be preceeded by an @if ... or @else if ...\n"
9408 : );
9409 :
9410 1 : std::stringstream out;
9411 1 : out << *n;
9412 1 : VERIFY_TREES(out.str(),
9413 :
9414 : "LIST\n"
9415 : + csspp_test::get_default_variables() +
9416 : " V:zzvar\n"
9417 : " LIST\n"
9418 : " VARIABLE \"zzvar\"\n"
9419 : " IDENTIFIER \"false\"\n"
9420 : " COMPONENT_VALUE\n"
9421 : " ARG\n"
9422 : " IDENTIFIER \"ul\"\n"
9423 : " OPEN_CURLYBRACKET B:true\n"
9424 : " DECLARATION \"list\"\n"
9425 : " ARG\n"
9426 : " IDENTIFIER \"cross\"\n"
9427 : + csspp_test::get_close_comment(true)
9428 :
9429 : );
9430 :
9431 1 : CATCH_REQUIRE(c.get_root() == n);
9432 1 : }
9433 :
9434 : // script with @if / @else if / @else keywords
9435 : // invalid "@else if" which includes an expression
9436 : {
9437 1 : std::stringstream ss;
9438 : ss << "$var: false;\n"
9439 : << "@if $var { @message \"Got here! (1)\" ; }\n"
9440 : << "@else if + { @message \"Got here! (2)\";}\n"
9441 : << "@else{@message\"Got here! (3)\";}\n"
9442 1 : << "ul { list: cross; }";
9443 3 : csspp::position pos("test.css");
9444 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
9445 :
9446 2 : csspp::parser p(l);
9447 :
9448 1 : csspp::node::pointer_t n(p.stylesheet());
9449 :
9450 : // no errors so far
9451 1 : VERIFY_ERRORS("");
9452 :
9453 1 : csspp::compiler c;
9454 1 : c.set_root(n);
9455 1 : c.clear_paths();
9456 1 : c.add_path(csspp_test::get_script_path());
9457 1 : c.add_path(csspp_test::get_version_script_path());
9458 :
9459 1 : c.compile(true);
9460 :
9461 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
9462 :
9463 1 : VERIFY_ERRORS(
9464 : "test.css(3): error: unsupported type OPEN_CURLYBRACKET as a unary expression token.\n"
9465 : "test.css(3): error: '@else { ... }' is expected to have 1 parameter, '@else if ... { ... }' is expected to have 2 parameters. This @else has 2 parameters.\n"
9466 : //"test.css(4): error: a standalone @else is not legal, it has to be preceeded by an @if ... or @else if ...\n"
9467 : );
9468 :
9469 1 : std::stringstream out;
9470 1 : out << *n;
9471 1 : VERIFY_TREES(out.str(),
9472 :
9473 : "LIST\n"
9474 : " V:var\n"
9475 : " LIST\n"
9476 : " VARIABLE \"var\"\n"
9477 : " IDENTIFIER \"false\"\n"
9478 : " COMPONENT_VALUE\n"
9479 : " ARG\n"
9480 : " IDENTIFIER \"ul\"\n"
9481 : " OPEN_CURLYBRACKET B:true\n"
9482 : " DECLARATION \"list\"\n"
9483 : " ARG\n"
9484 : " IDENTIFIER \"cross\"\n"
9485 :
9486 : );
9487 :
9488 1 : CATCH_REQUIRE(c.get_root() == n);
9489 1 : }
9490 :
9491 : // script with @if / @else if / @else keywords
9492 : // invalid "@else" which includes an expression
9493 : {
9494 1 : std::stringstream ss;
9495 : ss << "$var: false;\n"
9496 : << "@if $var { @message \"Got here! (1)\" ; }\n"
9497 : << "@else if $var { @message \"Got here! (2)\";}\n"
9498 : << "@else $var {@message\"Got here! (3)\";}\n" // TODO: this doesn't get caught?!
9499 1 : << "ul { list: cross; }";
9500 3 : csspp::position pos("test.css");
9501 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
9502 :
9503 2 : csspp::parser p(l);
9504 :
9505 1 : csspp::node::pointer_t n(p.stylesheet());
9506 :
9507 : // no errors so far
9508 1 : VERIFY_ERRORS("");
9509 :
9510 1 : csspp::compiler c;
9511 1 : c.set_root(n);
9512 1 : c.clear_paths();
9513 1 : c.add_path(csspp_test::get_script_path());
9514 1 : c.add_path(csspp_test::get_version_script_path());
9515 :
9516 1 : c.compile(true);
9517 :
9518 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
9519 :
9520 1 : VERIFY_ERRORS(""
9521 : "test.css(4): error: '@else { ... }' is expected to have 1 parameter, '@else if ... { ... }' is expected to have 2 parameters. This @else has 2 parameters.\n"
9522 : //"test.css(3): error: '@else if ...' is missing an expression or a block.\n"
9523 : //"test.css(3): error: '@else { ... }' cannot follow another '@else { ... }'. Maybe you are missing an 'if expr'?\n"
9524 : //"test.css(4): error: a standalone @else is not legal, it has to be preceeded by an @if ... or @else if ...\n"
9525 : //"test.css(3): info: Got here! (2)\n"
9526 : );
9527 :
9528 1 : std::stringstream out;
9529 1 : out << *n;
9530 1 : VERIFY_TREES(out.str(),
9531 :
9532 : "LIST\n"
9533 : " V:var\n"
9534 : " LIST\n"
9535 : " VARIABLE \"var\"\n"
9536 : " IDENTIFIER \"false\"\n"
9537 : " COMPONENT_VALUE\n"
9538 : " ARG\n"
9539 : " IDENTIFIER \"ul\"\n"
9540 : " OPEN_CURLYBRACKET B:true\n"
9541 : " DECLARATION \"list\"\n"
9542 : " ARG\n"
9543 : " IDENTIFIER \"cross\"\n"
9544 :
9545 : );
9546 :
9547 1 : CATCH_REQUIRE(c.get_root() == n);
9548 1 : }
9549 :
9550 : // script with @if / @else if / @else keywords
9551 : // spurious "@else"
9552 : {
9553 1 : std::stringstream ss;
9554 : ss << "$var: false;\n"
9555 : << "@if $var { @message \"Got here! (1)\" ; }\n"
9556 : << "@else if $var { @message \"Got here! (2)\";}\n"
9557 : << "@else {@message\"Got here! (3)\";}\n"
9558 : << "@else { @message\"Spurious! (4)\";}\n"
9559 1 : << "ul { list: cross; }";
9560 3 : csspp::position pos("test.css");
9561 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
9562 :
9563 2 : csspp::parser p(l);
9564 :
9565 1 : csspp::node::pointer_t n(p.stylesheet());
9566 :
9567 : // no errors so far
9568 1 : VERIFY_ERRORS("");
9569 :
9570 1 : csspp::compiler c;
9571 1 : c.set_root(n);
9572 1 : c.clear_paths();
9573 1 : c.add_path(csspp_test::get_script_path());
9574 1 : c.add_path(csspp_test::get_version_script_path());
9575 :
9576 1 : c.compile(true);
9577 :
9578 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
9579 :
9580 1 : VERIFY_ERRORS(""
9581 : "test.css(4): error: '@else { ... }' cannot follow another '@else { ... }'. Maybe you are missing an 'if expr'?\n"
9582 : "test.css(5): error: a standalone @else is not legal, it has to be preceeded by an @if ... or @else if ...\n"
9583 : //"test.css(4): info: Got here! (3)\n"
9584 : );
9585 :
9586 1 : std::stringstream out;
9587 1 : out << *n;
9588 1 : VERIFY_TREES(out.str(),
9589 :
9590 : "LIST\n"
9591 : " V:var\n"
9592 : " LIST\n"
9593 : " VARIABLE \"var\"\n"
9594 : " IDENTIFIER \"false\"\n"
9595 : " COMPONENT_VALUE\n"
9596 : " ARG\n"
9597 : " IDENTIFIER \"ul\"\n"
9598 : " OPEN_CURLYBRACKET B:true\n"
9599 : " DECLARATION \"list\"\n"
9600 : " ARG\n"
9601 : " IDENTIFIER \"cross\"\n"
9602 :
9603 : );
9604 :
9605 1 : CATCH_REQUIRE(c.get_root() == n);
9606 1 : }
9607 :
9608 : // no left over?
9609 1 : VERIFY_ERRORS("");
9610 1 : }
9611 :
9612 1 : CATCH_TEST_CASE("User @import", "[compiler] [at-keyword]")
9613 : {
9614 : // @import with a valid URL
9615 : {
9616 : // write a file (in a block so it gets flushed and closed)
9617 : {
9618 1 : std::ofstream importing;
9619 1 : importing.open("importing.scss");
9620 1 : CATCH_REQUIRE(!!importing);
9621 1 : importing << "/* @preserve this worked! {$_csspp_version} */";
9622 1 : }
9623 1 : std::stringstream ss;
9624 : {
9625 1 : std::unique_ptr<char, void (*)(char *)> cwd(get_current_dir_name(), free_char);
9626 : ss << "@import url(file://"
9627 1 : << cwd.get()
9628 1 : << "/importing.scss);";
9629 1 : }
9630 3 : csspp::position pos("test.css");
9631 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
9632 :
9633 2 : csspp::parser p(l);
9634 :
9635 1 : csspp::node::pointer_t n(p.stylesheet());
9636 :
9637 : // no errors so far
9638 1 : VERIFY_ERRORS("");
9639 :
9640 1 : csspp::compiler c;
9641 1 : c.set_root(n);
9642 1 : c.set_date_time_variables(csspp_test::get_now());
9643 1 : c.clear_paths();
9644 1 : c.add_path(csspp_test::get_script_path());
9645 1 : c.add_path(csspp_test::get_version_script_path());
9646 :
9647 1 : c.compile(false);
9648 :
9649 1 : VERIFY_ERRORS("");
9650 :
9651 1 : std::stringstream out;
9652 1 : out << *n;
9653 1 : VERIFY_TREES(out.str(),
9654 :
9655 : "LIST\n"
9656 : + csspp_test::get_default_variables() +
9657 : " COMMENT \"@preserve this worked! " CSSPP_VERSION "\" I:1\n"
9658 : + csspp_test::get_close_comment(true)
9659 :
9660 : );
9661 :
9662 1 : unlink("importing.scss");
9663 :
9664 1 : CATCH_REQUIRE(c.get_root() == n);
9665 1 : }
9666 :
9667 : // @import with a valid path as a URL (thus not recognized as a file://)
9668 : {
9669 1 : std::stringstream ss;
9670 1 : ss << "@import url(system/version);";
9671 3 : csspp::position pos("test.css");
9672 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
9673 :
9674 2 : csspp::parser p(l);
9675 :
9676 1 : csspp::node::pointer_t n(p.stylesheet());
9677 :
9678 : // no errors so far
9679 1 : VERIFY_ERRORS("");
9680 :
9681 1 : csspp::compiler c;
9682 1 : c.set_root(n);
9683 1 : c.clear_paths();
9684 1 : c.add_path(csspp_test::get_script_path());
9685 1 : c.add_path(csspp_test::get_version_script_path());
9686 :
9687 1 : c.compile(true);
9688 :
9689 1 : VERIFY_ERRORS("");
9690 :
9691 1 : std::stringstream out;
9692 1 : out << *n;
9693 1 : VERIFY_TREES(out.str(),
9694 :
9695 : "LIST\n"
9696 : " AT_KEYWORD \"import\" I:0\n"
9697 : " URL \"system/version\"\n"
9698 :
9699 : );
9700 :
9701 1 : CATCH_REQUIRE(c.get_root() == n);
9702 1 : }
9703 :
9704 : // @import with a valid path as a URL (thus not recognized as a file://)
9705 : {
9706 1 : std::stringstream ss;
9707 1 : ss << "@import 'http://csspp.org/css/special.css';";
9708 3 : csspp::position pos("test.css");
9709 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
9710 :
9711 2 : csspp::parser p(l);
9712 :
9713 1 : csspp::node::pointer_t n(p.stylesheet());
9714 :
9715 : // no errors so far
9716 1 : VERIFY_ERRORS("");
9717 :
9718 1 : csspp::compiler c;
9719 1 : c.set_root(n);
9720 1 : c.clear_paths();
9721 1 : c.add_path(csspp_test::get_script_path());
9722 1 : c.add_path(csspp_test::get_version_script_path());
9723 :
9724 1 : c.compile(true);
9725 :
9726 1 : VERIFY_ERRORS("");
9727 :
9728 1 : std::stringstream out;
9729 1 : out << *n;
9730 1 : VERIFY_TREES(out.str(),
9731 :
9732 : "LIST\n"
9733 : " AT_KEYWORD \"import\" I:0\n"
9734 : " STRING \"http://csspp.org/css/special.css\"\n"
9735 :
9736 : );
9737 :
9738 1 : CATCH_REQUIRE(c.get_root() == n);
9739 1 : }
9740 :
9741 : // no left over?
9742 1 : VERIFY_ERRORS("");
9743 1 : }
9744 :
9745 1 : CATCH_TEST_CASE("Invalid @import", "[compiler] [at-keyword] [invalid]")
9746 : {
9747 : // @import with URL representing a an inexistant file
9748 : {
9749 1 : std::stringstream ss;
9750 1 : ss << "@import url(file:///this/shall/not/exist/anywhere/on/your/drive);";
9751 3 : csspp::position pos("test.css");
9752 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
9753 :
9754 2 : csspp::parser p(l);
9755 :
9756 1 : csspp::node::pointer_t n(p.stylesheet());
9757 :
9758 : // no errors so far
9759 1 : VERIFY_ERRORS("");
9760 :
9761 1 : csspp::compiler c;
9762 1 : c.set_root(n);
9763 1 : c.clear_paths();
9764 1 : c.add_path(csspp_test::get_script_path());
9765 1 : c.add_path(csspp_test::get_version_script_path());
9766 :
9767 1 : c.compile(true);
9768 :
9769 1 : VERIFY_ERRORS("test.css(1): info: @import uri(/this/shall/not/exist/anywhere/on/your/drive); left alone by the CSS Preprocessor, no matching file found.\n");
9770 :
9771 1 : std::stringstream out;
9772 1 : out << *n;
9773 1 : VERIFY_TREES(out.str(),
9774 :
9775 : "LIST\n"
9776 : " AT_KEYWORD \"import\" I:0\n"
9777 : " URL \"file:///this/shall/not/exist/anywhere/on/your/drive\"\n"
9778 :
9779 : );
9780 :
9781 1 : CATCH_REQUIRE(c.get_root() == n);
9782 1 : }
9783 :
9784 : // @import with URL representing a an inexistant file
9785 : {
9786 1 : std::stringstream ss;
9787 1 : ss << "@import url(file://this/shall/not/exist/either/on/your/drive);";
9788 3 : csspp::position pos("test.css");
9789 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
9790 :
9791 2 : csspp::parser p(l);
9792 :
9793 1 : csspp::node::pointer_t n(p.stylesheet());
9794 :
9795 : // no errors so far
9796 1 : VERIFY_ERRORS("");
9797 :
9798 1 : csspp::compiler c;
9799 1 : c.set_root(n);
9800 1 : c.clear_paths();
9801 1 : c.add_path(csspp_test::get_script_path());
9802 1 : c.add_path(csspp_test::get_version_script_path());
9803 :
9804 1 : c.compile(true);
9805 :
9806 1 : VERIFY_ERRORS("test.css(1): info: @import uri(/this/shall/not/exist/either/on/your/drive); left alone by the CSS Preprocessor, no matching file found.\n");
9807 :
9808 1 : std::stringstream out;
9809 1 : out << *n;
9810 1 : VERIFY_TREES(out.str(),
9811 :
9812 : "LIST\n"
9813 : " AT_KEYWORD \"import\" I:0\n"
9814 : " URL \"file://this/shall/not/exist/either/on/your/drive\"\n"
9815 :
9816 : );
9817 :
9818 1 : CATCH_REQUIRE(c.get_root() == n);
9819 1 : }
9820 :
9821 : // @import with a string that includes a URL
9822 : {
9823 1 : std::stringstream ss;
9824 1 : ss << "@import \"file://this/shall/not/ever/exist/on/your/drive\";";
9825 3 : csspp::position pos("test.css");
9826 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
9827 :
9828 2 : csspp::parser p(l);
9829 :
9830 1 : csspp::node::pointer_t n(p.stylesheet());
9831 :
9832 : // no errors so far
9833 1 : VERIFY_ERRORS("");
9834 :
9835 1 : csspp::compiler c;
9836 1 : c.set_root(n);
9837 1 : c.clear_paths();
9838 1 : c.add_path(csspp_test::get_script_path());
9839 1 : c.add_path(csspp_test::get_version_script_path());
9840 :
9841 1 : c.compile(true);
9842 :
9843 1 : VERIFY_ERRORS("test.css(1): info: @import \"/this/shall/not/ever/exist/on/your/drive\"; left alone by the CSS Preprocessor, no matching file found.\n");
9844 :
9845 1 : std::stringstream out;
9846 1 : out << *n;
9847 1 : VERIFY_TREES(out.str(),
9848 :
9849 : "LIST\n"
9850 : " AT_KEYWORD \"import\" I:0\n"
9851 : " STRING \"file://this/shall/not/ever/exist/on/your/drive\"\n"
9852 :
9853 : );
9854 :
9855 1 : CATCH_REQUIRE(c.get_root() == n);
9856 1 : }
9857 :
9858 : // @import with a string that includes a URL
9859 : {
9860 1 : std::stringstream ss;
9861 1 : ss << "@import \"include/a/file:///in/the/filename/but/still/a/regular/filename\";";
9862 3 : csspp::position pos("test.css");
9863 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
9864 :
9865 2 : csspp::parser p(l);
9866 :
9867 1 : csspp::node::pointer_t n(p.stylesheet());
9868 :
9869 : // no errors so far
9870 1 : VERIFY_ERRORS("");
9871 :
9872 1 : csspp::compiler c;
9873 1 : c.set_root(n);
9874 1 : c.clear_paths();
9875 1 : c.add_path(csspp_test::get_script_path());
9876 1 : c.add_path(csspp_test::get_version_script_path());
9877 :
9878 1 : c.compile(true);
9879 :
9880 1 : VERIFY_ERRORS("test.css(1): info: @import \"include/a/file:///in/the/filename/but/still/a/regular/filename\"; left alone by the CSS Preprocessor, no matching file found.\n");
9881 :
9882 1 : std::stringstream out;
9883 1 : out << *n;
9884 1 : VERIFY_TREES(out.str(),
9885 :
9886 : "LIST\n"
9887 : " AT_KEYWORD \"import\" I:0\n"
9888 : " STRING \"include/a/file:///in/the/filename/but/still/a/regular/filename\"\n"
9889 :
9890 : );
9891 :
9892 1 : CATCH_REQUIRE(c.get_root() == n);
9893 1 : }
9894 :
9895 : // @import a script named "" (empty string!)
9896 : {
9897 1 : std::stringstream ss;
9898 1 : ss << "@import \"\";";
9899 3 : csspp::position pos("test.css");
9900 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
9901 :
9902 2 : csspp::parser p(l);
9903 :
9904 1 : csspp::node::pointer_t n(p.stylesheet());
9905 :
9906 : // no errors so far
9907 1 : VERIFY_ERRORS("");
9908 :
9909 1 : csspp::compiler c;
9910 1 : c.set_root(n);
9911 1 : c.clear_paths();
9912 1 : c.add_path(csspp_test::get_script_path());
9913 1 : c.add_path(csspp_test::get_version_script_path());
9914 :
9915 1 : c.compile(true);
9916 :
9917 1 : VERIFY_ERRORS("test.css(1): error: @import \"\"; and @import url(); are not valid.\n");
9918 :
9919 1 : std::stringstream out;
9920 1 : out << *n;
9921 1 : VERIFY_TREES(out.str(),
9922 :
9923 : "LIST\n"
9924 : " AT_KEYWORD \"import\" I:0\n"
9925 : " STRING \"\"\n"
9926 :
9927 : );
9928 :
9929 1 : CATCH_REQUIRE(c.get_root() == n);
9930 1 : }
9931 :
9932 : // no left over?
9933 1 : VERIFY_ERRORS("");
9934 1 : }
9935 :
9936 1 : CATCH_TEST_CASE("Invalid variable in comment", "[compiler] [conditional] [invalid]")
9937 : {
9938 : // variable is not defined
9939 : {
9940 1 : std::stringstream ss;
9941 1 : ss << "/* @preserve this variable is #{$unknown} */\n";
9942 3 : csspp::position pos("test.css");
9943 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
9944 :
9945 2 : csspp::parser p(l);
9946 :
9947 1 : csspp::node::pointer_t n(p.stylesheet());
9948 :
9949 : // no errors so far
9950 1 : VERIFY_ERRORS("");
9951 :
9952 1 : csspp::compiler c;
9953 1 : c.set_root(n);
9954 1 : c.set_date_time_variables(csspp_test::get_now());
9955 1 : c.clear_paths();
9956 1 : c.add_path(csspp_test::get_script_path());
9957 1 : c.add_path(csspp_test::get_version_script_path());
9958 :
9959 1 : c.compile(false);
9960 :
9961 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
9962 :
9963 1 : VERIFY_ERRORS(
9964 : "test.css(1): warning: variable named \"unknown\", used in a comment, is not set.\n"
9965 : );
9966 :
9967 1 : CATCH_REQUIRE(c.get_root() == n);
9968 1 : }
9969 :
9970 : // variable is not defined
9971 : {
9972 1 : std::stringstream ss;
9973 : ss << "$func($arg): { color: $arg + #010101; };\n"
9974 1 : << "/* @preserve this variable is #{$func(#030303)} */\n";
9975 3 : csspp::position pos("test.css");
9976 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
9977 :
9978 2 : csspp::parser p(l);
9979 :
9980 1 : csspp::node::pointer_t n(p.stylesheet());
9981 :
9982 : // no errors so far
9983 1 : VERIFY_ERRORS("");
9984 :
9985 1 : csspp::compiler c;
9986 1 : c.set_root(n);
9987 1 : c.set_date_time_variables(csspp_test::get_now());
9988 1 : c.clear_paths();
9989 1 : c.add_path(csspp_test::get_script_path());
9990 1 : c.add_path(csspp_test::get_version_script_path());
9991 :
9992 1 : c.compile(false);
9993 :
9994 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
9995 :
9996 1 : VERIFY_ERRORS(
9997 : "test.css(2): warning: variable named \"func\", is a function which is not supported in a comment.\n"
9998 : );
9999 :
10000 1 : CATCH_REQUIRE(c.get_root() == n);
10001 1 : }
10002 :
10003 : // variable is not defined
10004 : {
10005 1 : std::stringstream ss;
10006 : ss << "$simple_var: { color: #0568FF + #010101; };\n"
10007 1 : << "/* @preserve this variable is #{$simple_var(#030303)} */\n";
10008 3 : csspp::position pos("test.css");
10009 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
10010 :
10011 2 : csspp::parser p(l);
10012 :
10013 1 : csspp::node::pointer_t n(p.stylesheet());
10014 :
10015 : // no errors so far
10016 1 : VERIFY_ERRORS("");
10017 :
10018 1 : csspp::compiler c;
10019 1 : c.set_root(n);
10020 1 : c.set_date_time_variables(csspp_test::get_now());
10021 1 : c.clear_paths();
10022 1 : c.add_path(csspp_test::get_script_path());
10023 1 : c.add_path(csspp_test::get_version_script_path());
10024 :
10025 1 : c.compile(false);
10026 :
10027 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
10028 :
10029 1 : VERIFY_ERRORS(
10030 : "test.css(2): warning: variable named \"simple_var\", is not a function, yet you referenced it as such (and functions are not yet supported in comments).\n"
10031 : );
10032 :
10033 1 : CATCH_REQUIRE(c.get_root() == n);
10034 1 : }
10035 :
10036 : // no left over?
10037 1 : VERIFY_ERRORS("");
10038 1 : }
10039 :
10040 1 : CATCH_TEST_CASE("Compile keyframes", "[compiler] [stylesheet] [attribute]")
10041 : {
10042 : {
10043 1 : std::stringstream ss;
10044 : ss << "/* testing keyframes */"
10045 : << "normal { right: 45px; }\n"
10046 : << "@keyframes progress-bar-stripes\n"
10047 : "{\n"
10048 : " from {\n"
10049 : " background-position: 40px 0;\n"
10050 : " left: 0;\n"
10051 : " }\n"
10052 : " 30% {\n"
10053 : " background-position: 30px 0;\n"
10054 : " left: 20px;\n"
10055 : " }\n"
10056 : " 60% {\n"
10057 : " background-position: 5px 0;\n"
10058 : " left: 27px;\n"
10059 : " }\n"
10060 : " to {\n"
10061 : " background-position: 0 0;\n"
10062 : " left: 35px;\n"
10063 : " }\n"
10064 : "}\n"
10065 1 : << "/* @preserver test \"Compile keyframes\" */";
10066 3 : csspp::position pos("test.css");
10067 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
10068 :
10069 2 : csspp::parser p(l);
10070 :
10071 1 : csspp::node::pointer_t n(p.stylesheet());
10072 :
10073 : // no errors so far
10074 1 : VERIFY_ERRORS("");
10075 :
10076 1 : csspp::compiler c;
10077 1 : c.set_root(n);
10078 1 : c.set_date_time_variables(csspp_test::get_now());
10079 1 : c.clear_paths();
10080 1 : c.add_path(csspp_test::get_script_path());
10081 1 : c.add_path(csspp_test::get_version_script_path());
10082 :
10083 1 : c.compile(false);
10084 :
10085 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
10086 :
10087 1 : std::stringstream out;
10088 1 : out << *n;
10089 1 : VERIFY_TREES(out.str(),
10090 :
10091 : "LIST\n"
10092 : + csspp_test::get_default_variables() +
10093 : " COMPONENT_VALUE\n"
10094 : " ARG\n"
10095 : " IDENTIFIER \"normal\"\n"
10096 : " OPEN_CURLYBRACKET B:true\n"
10097 : " DECLARATION \"right\"\n"
10098 : " ARG\n"
10099 : " INTEGER \"px\" I:45\n"
10100 : " AT_KEYWORD \"keyframes\" I:0\n"
10101 : " IDENTIFIER \"progress-bar-stripes\"\n"
10102 : " FRAME D:0\n"
10103 : " DECLARATION \"background-position\"\n"
10104 : " ARG\n"
10105 : " INTEGER \"px\" I:40\n"
10106 : " WHITESPACE\n"
10107 : " INTEGER \"\" I:0\n"
10108 : " DECLARATION \"left\"\n"
10109 : " ARG\n"
10110 : " INTEGER \"\" I:0\n"
10111 : " FRAME D:0.3\n"
10112 : " DECLARATION \"background-position\"\n"
10113 : " ARG\n"
10114 : " INTEGER \"px\" I:30\n"
10115 : " WHITESPACE\n"
10116 : " INTEGER \"\" I:0\n"
10117 : " DECLARATION \"left\"\n"
10118 : " ARG\n"
10119 : " INTEGER \"px\" I:20\n"
10120 : " FRAME D:0.6\n"
10121 : " DECLARATION \"background-position\"\n"
10122 : " ARG\n"
10123 : " INTEGER \"px\" I:5\n"
10124 : " WHITESPACE\n"
10125 : " INTEGER \"\" I:0\n"
10126 : " DECLARATION \"left\"\n"
10127 : " ARG\n"
10128 : " INTEGER \"px\" I:27\n"
10129 : " FRAME D:1\n"
10130 : " DECLARATION \"background-position\"\n"
10131 : " ARG\n"
10132 : " INTEGER \"\" I:0\n"
10133 : " WHITESPACE\n"
10134 : " INTEGER \"\" I:0\n"
10135 : " DECLARATION \"left\"\n"
10136 : " ARG\n"
10137 : " INTEGER \"px\" I:35\n"
10138 : " COMMENT \"@preserver test \"Compile keyframes\"\" I:1\n"
10139 : + csspp_test::get_close_comment(true)
10140 :
10141 : );
10142 :
10143 : // no error left over
10144 1 : VERIFY_ERRORS("");
10145 :
10146 1 : CATCH_REQUIRE(c.get_root() == n);
10147 1 : }
10148 :
10149 : // without spaces
10150 : {
10151 1 : std::stringstream ss;
10152 : ss << "/* testing compile */"
10153 : << "body,a[q]>b[p=\"344.5\"]+c[z=33]~d[e],html *[ff=fire] *.blue { background:white url(/images/background.png) }"
10154 1 : << "/* @preserver test \"Compile Simple Stylesheet\" with version #{$_csspp_major}.#{$_csspp_minor} */";
10155 3 : csspp::position pos("test.css");
10156 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
10157 :
10158 2 : csspp::parser p(l);
10159 :
10160 1 : csspp::node::pointer_t n(p.stylesheet());
10161 :
10162 : // no errors so far
10163 1 : VERIFY_ERRORS("");
10164 :
10165 1 : csspp::compiler c;
10166 1 : c.set_root(n);
10167 1 : c.set_date_time_variables(csspp_test::get_now());
10168 1 : c.clear_paths();
10169 1 : c.add_path(csspp_test::get_script_path());
10170 1 : c.add_path(csspp_test::get_version_script_path());
10171 :
10172 1 : c.compile(false);
10173 :
10174 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
10175 :
10176 1 : std::stringstream out;
10177 1 : out << *n;
10178 1 : VERIFY_TREES(out.str(),
10179 :
10180 : "LIST\n"
10181 : + csspp_test::get_default_variables() +
10182 : " COMPONENT_VALUE\n"
10183 : " ARG\n"
10184 : " IDENTIFIER \"body\"\n"
10185 : " ARG\n"
10186 : " IDENTIFIER \"a\"\n"
10187 : " OPEN_SQUAREBRACKET\n"
10188 : " IDENTIFIER \"q\"\n"
10189 : " GREATER_THAN\n"
10190 : " IDENTIFIER \"b\"\n"
10191 : " OPEN_SQUAREBRACKET\n"
10192 : " IDENTIFIER \"p\"\n"
10193 : " EQUAL\n"
10194 : " STRING \"344.5\"\n"
10195 : " ADD\n"
10196 : " IDENTIFIER \"c\"\n"
10197 : " OPEN_SQUAREBRACKET\n"
10198 : " IDENTIFIER \"z\"\n"
10199 : " EQUAL\n"
10200 : " INTEGER \"\" I:33\n"
10201 : " PRECEDED\n"
10202 : " IDENTIFIER \"d\"\n"
10203 : " OPEN_SQUAREBRACKET\n"
10204 : " IDENTIFIER \"e\"\n"
10205 : " ARG\n"
10206 : " IDENTIFIER \"html\"\n"
10207 : " WHITESPACE\n"
10208 : " OPEN_SQUAREBRACKET\n"
10209 : " IDENTIFIER \"ff\"\n"
10210 : " EQUAL\n"
10211 : " IDENTIFIER \"fire\"\n"
10212 : " WHITESPACE\n"
10213 : " PERIOD\n"
10214 : " IDENTIFIER \"blue\"\n"
10215 : " OPEN_CURLYBRACKET B:true\n"
10216 : " DECLARATION \"background\"\n"
10217 : " ARG\n"
10218 : " COLOR H:ffffffff\n"
10219 : " WHITESPACE\n"
10220 : " URL \"/images/background.png\"\n"
10221 : " COMMENT \"@preserver test \"Compile Simple Stylesheet\" with version 1.0\" I:1\n"
10222 : + csspp_test::get_close_comment(true)
10223 :
10224 : );
10225 :
10226 : // no error left over
10227 1 : VERIFY_ERRORS("");
10228 :
10229 1 : CATCH_REQUIRE(c.get_root() == n);
10230 1 : }
10231 :
10232 : // rules with !important
10233 : {
10234 1 : std::stringstream ss;
10235 1 : ss << "div.blackness { color: red !important }";
10236 3 : csspp::position pos("test.css");
10237 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
10238 :
10239 2 : csspp::parser p(l);
10240 :
10241 1 : csspp::node::pointer_t n(p.stylesheet());
10242 :
10243 : // no errors so far
10244 1 : VERIFY_ERRORS("");
10245 :
10246 1 : csspp::compiler c;
10247 1 : c.set_root(n);
10248 1 : c.set_date_time_variables(csspp_test::get_now());
10249 1 : c.clear_paths();
10250 1 : c.add_path(csspp_test::get_script_path());
10251 1 : c.add_path(csspp_test::get_version_script_path());
10252 :
10253 1 : c.compile(false);
10254 :
10255 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
10256 :
10257 1 : std::stringstream out;
10258 1 : out << *n;
10259 1 : VERIFY_TREES(out.str(),
10260 :
10261 : "LIST\n"
10262 : + csspp_test::get_default_variables() +
10263 : " COMPONENT_VALUE\n"
10264 : " ARG\n"
10265 : " IDENTIFIER \"div\"\n"
10266 : " PERIOD\n"
10267 : " IDENTIFIER \"blackness\"\n"
10268 : " OPEN_CURLYBRACKET B:true\n"
10269 : " DECLARATION \"color\" F:important\n"
10270 : " ARG\n"
10271 : " COLOR H:ff0000ff\n"
10272 : + csspp_test::get_close_comment(true)
10273 :
10274 : );
10275 :
10276 : // no error left over
10277 1 : VERIFY_ERRORS("");
10278 :
10279 1 : CATCH_REQUIRE(c.get_root() == n);
10280 1 : }
10281 :
10282 : // rules with ! important
10283 : {
10284 1 : std::stringstream ss;
10285 1 : ss << "div.blackness { color: red ! important }";
10286 3 : csspp::position pos("test.css");
10287 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
10288 :
10289 2 : csspp::parser p(l);
10290 :
10291 1 : csspp::node::pointer_t n(p.stylesheet());
10292 :
10293 : // no errors so far
10294 1 : VERIFY_ERRORS("");
10295 :
10296 1 : csspp::compiler c;
10297 1 : c.set_root(n);
10298 1 : c.set_date_time_variables(csspp_test::get_now());
10299 1 : c.clear_paths();
10300 1 : c.add_path(csspp_test::get_script_path());
10301 1 : c.add_path(csspp_test::get_version_script_path());
10302 :
10303 1 : c.compile(false);
10304 :
10305 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
10306 :
10307 1 : std::stringstream out;
10308 1 : out << *n;
10309 1 : VERIFY_TREES(out.str(),
10310 :
10311 : "LIST\n"
10312 : + csspp_test::get_default_variables() +
10313 : " COMPONENT_VALUE\n"
10314 : " ARG\n"
10315 : " IDENTIFIER \"div\"\n"
10316 : " PERIOD\n"
10317 : " IDENTIFIER \"blackness\"\n"
10318 : " OPEN_CURLYBRACKET B:true\n"
10319 : " DECLARATION \"color\" F:important\n"
10320 : " ARG\n"
10321 : " COLOR H:ff0000ff\n"
10322 : + csspp_test::get_close_comment(true)
10323 :
10324 : );
10325 :
10326 : // no error left over
10327 1 : VERIFY_ERRORS("");
10328 :
10329 1 : CATCH_REQUIRE(c.get_root() == n);
10330 1 : }
10331 :
10332 : // rules with !important and no spaces
10333 : {
10334 1 : std::stringstream ss;
10335 1 : ss << "div.blackness { color: red!important }";
10336 3 : csspp::position pos("test.css");
10337 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
10338 :
10339 2 : csspp::parser p(l);
10340 :
10341 1 : csspp::node::pointer_t n(p.stylesheet());
10342 :
10343 : // no errors so far
10344 1 : VERIFY_ERRORS("");
10345 :
10346 1 : csspp::compiler c;
10347 1 : c.set_root(n);
10348 1 : c.set_date_time_variables(csspp_test::get_now());
10349 1 : c.clear_paths();
10350 1 : c.add_path(csspp_test::get_script_path());
10351 1 : c.add_path(csspp_test::get_version_script_path());
10352 :
10353 1 : c.compile(false);
10354 :
10355 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
10356 :
10357 1 : std::stringstream out;
10358 1 : out << *n;
10359 1 : VERIFY_TREES(out.str(),
10360 :
10361 : "LIST\n"
10362 : + csspp_test::get_default_variables() +
10363 : " COMPONENT_VALUE\n"
10364 : " ARG\n"
10365 : " IDENTIFIER \"div\"\n"
10366 : " PERIOD\n"
10367 : " IDENTIFIER \"blackness\"\n"
10368 : " OPEN_CURLYBRACKET B:true\n"
10369 : " DECLARATION \"color\" F:important\n"
10370 : " ARG\n"
10371 : " COLOR H:ff0000ff\n"
10372 : + csspp_test::get_close_comment(true)
10373 :
10374 : );
10375 :
10376 : // no error left over
10377 1 : VERIFY_ERRORS("");
10378 :
10379 1 : CATCH_REQUIRE(c.get_root() == n);
10380 1 : }
10381 :
10382 : // empty rules have to compile too
10383 : {
10384 1 : std::stringstream ss;
10385 : ss << "div.blackness section.light span.clear\n"
10386 : << "{\n"
10387 1 : << "}\n";
10388 3 : csspp::position pos("test.css");
10389 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
10390 :
10391 2 : csspp::parser p(l);
10392 :
10393 1 : csspp::node::pointer_t n(p.stylesheet());
10394 :
10395 : // no errors so far
10396 1 : VERIFY_ERRORS("");
10397 :
10398 1 : csspp::compiler c;
10399 1 : c.set_root(n);
10400 1 : c.set_date_time_variables(csspp_test::get_now());
10401 1 : c.clear_paths();
10402 1 : c.add_path(csspp_test::get_script_path());
10403 1 : c.add_path(csspp_test::get_version_script_path());
10404 :
10405 1 : c.compile(false);
10406 :
10407 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
10408 :
10409 1 : std::stringstream out;
10410 1 : out << *n;
10411 1 : VERIFY_TREES(out.str(),
10412 :
10413 : "LIST\n"
10414 : + csspp_test::get_default_variables()
10415 : + csspp_test::get_close_comment(true)
10416 :
10417 : );
10418 :
10419 : // no error left over
10420 1 : VERIFY_ERRORS("");
10421 :
10422 1 : CATCH_REQUIRE(c.get_root() == n);
10423 1 : }
10424 :
10425 : // special IE8 value which has to be skipped
10426 : {
10427 1 : std::stringstream ss;
10428 : ss << ".transparent img\n"
10429 : << "{\n"
10430 : << " $alpha: 5% * 4;\n"
10431 : << " filter: opacity($alpha);\n"
10432 : << " filter: alpha( opacity=20 );\n"
10433 1 : << "}\n";
10434 3 : csspp::position pos("test.css");
10435 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
10436 :
10437 2 : csspp::parser p(l);
10438 :
10439 1 : csspp::node::pointer_t n(p.stylesheet());
10440 :
10441 : // no errors so far
10442 1 : VERIFY_ERRORS("");
10443 :
10444 1 : csspp::compiler c;
10445 1 : c.set_root(n);
10446 1 : c.set_date_time_variables(csspp_test::get_now());
10447 1 : c.clear_paths();
10448 1 : c.add_path(csspp_test::get_script_path());
10449 1 : c.add_path(csspp_test::get_version_script_path());
10450 :
10451 1 : c.compile(false);
10452 :
10453 : // no error left over
10454 1 : VERIFY_ERRORS(
10455 : "test.css(4): warning: the alpha(), chroma() and similar functions of the filter field are Internet Explorer specific extensions which are not supported across browsers.\n"
10456 : "test.css(5): warning: the alpha(), chroma() and similar functions of the filter field are Internet Explorer specific extensions which are not supported across browsers.\n"
10457 : );
10458 :
10459 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
10460 :
10461 1 : std::stringstream out;
10462 1 : out << *n;
10463 1 : VERIFY_TREES(out.str(),
10464 :
10465 : "LIST\n"
10466 : + csspp_test::get_default_variables() +
10467 : " COMPONENT_VALUE\n"
10468 : " ARG\n"
10469 : " PERIOD\n"
10470 : " IDENTIFIER \"transparent\"\n"
10471 : " WHITESPACE\n"
10472 : " IDENTIFIER \"img\"\n"
10473 : " OPEN_CURLYBRACKET B:true\n"
10474 : " V:alpha\n"
10475 : " LIST\n"
10476 : " VARIABLE \"alpha\"\n"
10477 : " LIST\n"
10478 : " PERCENT D:0.05\n"
10479 : " WHITESPACE\n"
10480 : " MULTIPLY\n"
10481 : " WHITESPACE\n"
10482 : " INTEGER \"\" I:4\n"
10483 : " LIST\n"
10484 : " DECLARATION \"filter\"\n"
10485 : " FUNCTION \"opacity\"\n"
10486 : " PERCENT D:0.05\n"
10487 : " WHITESPACE\n"
10488 : " MULTIPLY\n"
10489 : " WHITESPACE\n"
10490 : " INTEGER \"\" I:4\n"
10491 : " DECLARATION \"filter\"\n"
10492 : " FUNCTION \"alpha\"\n"
10493 : " IDENTIFIER \"opacity\"\n"
10494 : " EQUAL\n"
10495 : " INTEGER \"\" I:20\n"
10496 : + csspp_test::get_close_comment(true)
10497 :
10498 : );
10499 :
10500 : // no error left over
10501 1 : VERIFY_ERRORS("");
10502 :
10503 1 : CATCH_REQUIRE(c.get_root() == n);
10504 1 : }
10505 :
10506 : // a simple test with '--no-logo' specified
10507 : {
10508 1 : std::stringstream ss;
10509 : ss << ".box\n"
10510 : << "{\n"
10511 : << " color: $_csspp_no_logo ? red : blue;\n"
10512 1 : << "}\n";
10513 3 : csspp::position pos("test.css");
10514 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
10515 :
10516 2 : csspp::parser p(l);
10517 :
10518 1 : csspp::node::pointer_t n(p.stylesheet());
10519 :
10520 : // no errors so far
10521 1 : VERIFY_ERRORS("");
10522 :
10523 1 : csspp::compiler c;
10524 1 : c.set_root(n);
10525 1 : c.set_date_time_variables(csspp_test::get_now());
10526 1 : c.set_no_logo();
10527 1 : c.clear_paths();
10528 1 : c.add_path(csspp_test::get_script_path());
10529 1 : c.add_path(csspp_test::get_version_script_path());
10530 :
10531 1 : c.compile(false);
10532 :
10533 : //std::cerr << "Result is: [" << *c.get_root() << "]\n";
10534 :
10535 : // no error left over
10536 1 : VERIFY_ERRORS("");
10537 :
10538 1 : std::stringstream out;
10539 1 : out << *n;
10540 1 : VERIFY_TREES(out.str(),
10541 :
10542 : "LIST\n"
10543 : + csspp_test::get_default_variables(csspp_test::flag_no_logo_true) +
10544 : " COMPONENT_VALUE\n"
10545 : " ARG\n"
10546 : " PERIOD\n"
10547 : " IDENTIFIER \"box\"\n"
10548 : " OPEN_CURLYBRACKET B:true\n"
10549 : " DECLARATION \"color\"\n"
10550 : " ARG\n"
10551 : " COLOR H:ff0000ff\n"
10552 : //+ csspp_test::get_close_comment(true) -- with --no-logo this is gone
10553 :
10554 : );
10555 :
10556 : // no error left over
10557 1 : VERIFY_ERRORS("");
10558 :
10559 1 : CATCH_REQUIRE(c.get_root() == n);
10560 1 : }
10561 1 : }
10562 :
10563 : // This does not work under Linux, the ifstream.open() accepts a
10564 : // directory name as input without generating an error
10565 : //
10566 : //CATCH_TEST_CASE("Cannot open file", "[compiler] [invalid] [input]")
10567 : //{
10568 : // // generate an error with @error
10569 : // {
10570 : // // create a directory in place of the script, so it exists
10571 : // // and is readable but cannot be opened
10572 : // rmdir("pseudo-nth-functions.scss"); // in case you run more than once
10573 : // CATCH_REQUIRE(mkdir("pseudo-nth-functions.scss", 0700) == 0);
10574 : //
10575 : // std::stringstream ss;
10576 : // ss << "div:nth-child(3n+2){font-style:normal}";
10577 : // csspp::position pos("test.css");
10578 : // csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
10579 : //
10580 : // csspp::parser p(l);
10581 : //
10582 : // csspp::node::pointer_t n(p.stylesheet());
10583 : //
10584 : // // no errors so far
10585 : // VERIFY_ERRORS("");
10586 : //
10587 : // csspp::compiler c;
10588 : // c.set_root(n);
10589 : // c.clear_paths();
10590 : // c.add_path(".");
10591 : //
10592 : // CATCH_REQUIRE_THROWS_AS(c.compile(true), csspp::csspp_exception_exit);
10593 : //
10594 : // // TODO: use an RAII class instead
10595 : // rmdir("pseudo-nth-functions.scss"); // in case you run more than once
10596 : //
10597 : // VERIFY_ERRORS("pseudo-nth-functions(1): fatal: validation script \"pseudo-nth-functions\" was not found.\n");
10598 : //
10599 : // CATCH_REQUIRE(c.get_root() == n);
10600 : // }
10601 : //
10602 : // // no left over?
10603 : // VERIFY_ERRORS("");
10604 : //}
10605 :
10606 : // vim: ts=4 sw=4 et
|