Line data Source code
1 : // Copyright (c) 2015-2022 Made to Order Software Corp. All Rights Reserved
2 : //
3 : // https://snapwebsites.org/project/csspp
4 : // contact@m2osw.com
5 : //
6 : // This program is free software; you can redistribute it and/or modify
7 : // it under the terms of the GNU General Public License as published by
8 : // the Free Software Foundation; either version 2 of the License, or
9 : // (at your option) any later version.
10 : //
11 : // This program is distributed in the hope that it will be useful,
12 : // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 : // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 : // GNU General Public License for more details.
15 : //
16 : // You should have received a copy of the GNU General Public License along
17 : // with this program; if not, write to the Free Software Foundation, Inc.,
18 : // 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 :
20 : /** \file
21 : * \brief Test the expression.cpp file: "&&" operator.
22 : *
23 : * This test runs a battery of tests agains the expression.cpp "&&" (logical
24 : * and) operator to ensure full coverage and that all possible left
25 : * hand side and right hand side types are checked for the equality
26 : * CSS Preprocessor extensions.
27 : *
28 : * Note that all the tests use the full chain: lexer, parser, compiler,
29 : * and assembler to make sure the results are correct. So these tests
30 : * exercise the assembler even more than the assembler tests, except that
31 : * it only checks that compressed results are correct instead of all
32 : * output modes, since its only goal is covering all the possible
33 : * expression cases and not the assembler, compiler, parser, and lexer
34 : * classes.
35 : */
36 :
37 : // csspp
38 : //
39 : #include <csspp/assembler.h>
40 : #include <csspp/compiler.h>
41 : #include <csspp/exception.h>
42 : #include <csspp/parser.h>
43 :
44 :
45 : // self
46 : //
47 : #include "catch_main.h"
48 :
49 :
50 : // C++
51 : //
52 : #include <sstream>
53 :
54 :
55 : // last include
56 : //
57 : #include <snapdev/poison.h>
58 :
59 :
60 :
61 1 : CATCH_TEST_CASE("Expression value && value", "[expression] [logical-and]")
62 : {
63 : struct value_t
64 : {
65 : char const * f_string;
66 : bool f_true;
67 : };
68 :
69 1 : value_t const values[] =
70 : {
71 : { "10", true },
72 : { "3", true },
73 : { "0", false },
74 : { "10.2", true },
75 : { "3.7", true },
76 : { "0.0", false },
77 : { "5.1%", true },
78 : { "1%", true },
79 : { "0%", false },
80 : { "0.0%", false },
81 : { "true", true },
82 : { "false", false },
83 : { "null", false },
84 : { "black", false },
85 : { "#7194F0", true },
86 : { "white", true },
87 : { "''", false },
88 : { "'black'", true },
89 : { "'empty'", true },
90 : { "'false'", true }
91 : };
92 1 : size_t const value_count(sizeof(values) / sizeof(values[0]));
93 :
94 21 : for(size_t i(0); i < value_count; ++i)
95 : {
96 420 : for(size_t j(0); j < value_count; ++j)
97 : {
98 400 : std::stringstream ss;
99 : ss << "div { z-index: "
100 400 : << values[i].f_string
101 800 : << (rand() & 1 ? " && " : " and ")
102 400 : << values[j].f_string
103 400 : << " ? 9 : 5; }";
104 1200 : csspp::position pos("test.css");
105 400 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
106 :
107 800 : csspp::parser p(l);
108 :
109 400 : csspp::node::pointer_t n(p.stylesheet());
110 :
111 400 : csspp::compiler c;
112 400 : c.set_root(n);
113 400 : c.set_date_time_variables(csspp_test::get_now());
114 400 : c.add_path(csspp_test::get_script_path());
115 400 : c.add_path(csspp_test::get_version_script_path());
116 :
117 400 : c.compile(false);
118 :
119 : //std::cerr << "Compiler result is: [" << *c.get_root() << "]\n";
120 :
121 : // to verify that the result is still an INTEGER we have to
122 : // test the root node here
123 400 : std::stringstream compiler_out;
124 400 : compiler_out << *n;
125 400 : VERIFY_TREES(compiler_out.str(),
126 :
127 : "LIST\n"
128 : + csspp_test::get_default_variables() +
129 : " COMPONENT_VALUE\n"
130 : " ARG\n"
131 : " IDENTIFIER \"div\"\n"
132 : " OPEN_CURLYBRACKET B:true\n"
133 : " DECLARATION \"z-index\"\n"
134 : " ARG\n"
135 : " INTEGER \"\" I:" + (values[i].f_true && values[j].f_true ? "9" : "5") + "\n"
136 : + csspp_test::get_close_comment(true)
137 :
138 : );
139 :
140 400 : std::stringstream assembler_out;
141 400 : csspp::assembler a(assembler_out);
142 400 : a.output(n, csspp::output_mode_t::COMPRESSED);
143 :
144 : //std::cerr << "----------------- Result is " << static_cast<csspp::output_mode_t>(i) << "\n[" << out.str() << "]\n";
145 :
146 400 : CATCH_REQUIRE(assembler_out.str() ==
147 :
148 : std::string("div{z-index:") + (values[i].f_true && values[j].f_true ? "9" : "5") + "}\n"
149 : + csspp_test::get_close_comment()
150 :
151 : );
152 :
153 400 : CATCH_REQUIRE(c.get_root() == n);
154 400 : }
155 : }
156 :
157 : // no error left over
158 1 : VERIFY_ERRORS("");
159 1 : }
160 :
161 3 : CATCH_TEST_CASE("Expression invalid && invalid", "[expression] [logical-and] [invalid]")
162 : {
163 3 : CATCH_START_SECTION("just ? is not a valid boolean")
164 : {
165 1 : std::stringstream ss;
166 1 : ss << "div { border: ?; }";
167 3 : csspp::position pos("test.css");
168 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
169 :
170 2 : csspp::parser p(l);
171 :
172 1 : csspp::node::pointer_t n(p.stylesheet());
173 :
174 1 : csspp::compiler c;
175 1 : c.set_root(n);
176 1 : c.set_date_time_variables(csspp_test::get_now());
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 << "Compiler result is: [" << *c.get_root() << "]\n";
183 :
184 1 : VERIFY_ERRORS("test.css(1): error: unsupported type CONDITIONAL as a unary expression token.\n");
185 :
186 1 : CATCH_REQUIRE(c.get_root() == n);
187 1 : }
188 3 : CATCH_END_SECTION()
189 :
190 3 : CATCH_START_SECTION("boolean && ? is invalid")
191 : {
192 1 : std::stringstream ss;
193 1 : ss << "div { width: true && ?; }";
194 3 : csspp::position pos("test.css");
195 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
196 :
197 2 : csspp::parser p(l);
198 :
199 1 : csspp::node::pointer_t n(p.stylesheet());
200 :
201 1 : csspp::compiler c;
202 1 : c.set_root(n);
203 1 : c.set_date_time_variables(csspp_test::get_now());
204 1 : c.add_path(csspp_test::get_script_path());
205 1 : c.add_path(csspp_test::get_version_script_path());
206 :
207 1 : c.compile(false);
208 :
209 : //std::cerr << "Compiler result is: [" << *c.get_root() << "]\n";
210 :
211 1 : VERIFY_ERRORS("test.css(1): error: unsupported type CONDITIONAL as a unary expression token.\n");
212 :
213 1 : CATCH_REQUIRE(c.get_root() == n);
214 1 : }
215 3 : CATCH_END_SECTION()
216 :
217 3 : CATCH_START_SECTION("boolean && U+A?? is invalid")
218 : {
219 1 : std::stringstream ss;
220 1 : ss << "div { width: false && U+A??; }";
221 3 : csspp::position pos("test.css");
222 1 : csspp::lexer::pointer_t l(new csspp::lexer(ss, pos));
223 :
224 2 : csspp::parser p(l);
225 :
226 1 : csspp::node::pointer_t n(p.stylesheet());
227 :
228 1 : csspp::compiler c;
229 1 : c.set_root(n);
230 1 : c.set_date_time_variables(csspp_test::get_now());
231 1 : c.add_path(csspp_test::get_script_path());
232 1 : c.add_path(csspp_test::get_version_script_path());
233 :
234 1 : c.compile(false);
235 :
236 : //std::cerr << "Compiler result is: [" << *c.get_root() << "]\n";
237 :
238 1 : VERIFY_ERRORS("test.css(1): error: a boolean expression was expected.\n");
239 :
240 1 : CATCH_REQUIRE(c.get_root() == n);
241 1 : }
242 3 : CATCH_END_SECTION()
243 :
244 : // no error left over
245 3 : VERIFY_ERRORS("");
246 3 : }
247 :
248 : // vim: ts=4 sw=4 et
|