Line data Source code
1 : // Copyright (c) 2011-2023 Made to Order Software Corp. All Rights Reserved
2 : //
3 : // https://snapwebsites.org/project/as2js
4 : // contact@m2osw.com
5 : //
6 : // This program is free software: you can redistribute it and/or modify
7 : // it under the terms of the GNU General Public License as published by
8 : // the Free Software Foundation, either version 3 of the License, or
9 : // (at your option) any later version.
10 : //
11 : // This program is distributed in the hope that it will be useful,
12 : // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 : // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 : // GNU General Public License for more details.
15 : //
16 : // You should have received a copy of the GNU General Public License
17 : // along with this program. If not, see <https://www.gnu.org/licenses/>.
18 :
19 : // as2js
20 : //
21 : #include <as2js/node.h>
22 :
23 : #include <as2js/exception.h>
24 : #include <as2js/message.h>
25 :
26 :
27 : // self
28 : //
29 : #include "catch_main.h"
30 :
31 :
32 : // snapdev
33 : //
34 : #include <snapdev/not_reached.h>
35 : #include <snapdev/ostream_to_buf.h>
36 : #include <snapdev/safe_stream.h>
37 : #include <snapdev/tokenize_string.h>
38 :
39 :
40 : // libutf8
41 : //
42 : #include <libutf8/iterator.h>
43 :
44 :
45 : // C++
46 : //
47 : #include <cstring>
48 : #include <algorithm>
49 : #include <iomanip>
50 :
51 :
52 : // C
53 : //
54 : #include <signal.h>
55 : #include <sys/wait.h>
56 :
57 :
58 : // last include
59 : //
60 : #include <snapdev/poison.h>
61 :
62 :
63 :
64 :
65 : #include "catch_node_data.ci"
66 :
67 :
68 :
69 : namespace
70 : {
71 :
72 :
73 2 : int quick_exec(std::string const & cmd)
74 : {
75 2 : int const child_pid(fork());
76 4 : if(child_pid < 0)
77 : {
78 0 : int const e(errno);
79 0 : std::cerr << "error: fork() failed: "
80 : << e
81 : << ", "
82 0 : << strerror(e)
83 0 : << "\n";
84 0 : return -1;
85 : }
86 :
87 4 : if(child_pid != 0)
88 : {
89 : // parent just waits on the child
90 : //
91 2 : int status(0);
92 2 : pid_t const pid(waitpid(child_pid, &status, 0));
93 2 : if(pid != child_pid)
94 : {
95 0 : std::cerr << "error: waitpid() returned "
96 : << pid
97 0 : << ", expected: "
98 : << child_pid
99 0 : << " instead.\n";
100 0 : return 128;
101 : }
102 :
103 2 : if(!WIFEXITED(status))
104 : {
105 0 : std::cerr << "error: waitpid() returned with a status other than \"exited\".\n";
106 0 : return 128;
107 : }
108 2 : else if(WIFSIGNALED(status))
109 : {
110 0 : std::cerr << "error: child was signaled.\n";
111 0 : return 128;
112 : }
113 : else
114 : {
115 2 : return WEXITSTATUS(status);
116 : }
117 : }
118 :
119 2 : std::vector<std::string> arg_strings;
120 2 : snapdev::tokenize_string(arg_strings, cmd, {" "}, true);
121 :
122 4 : std::vector<char *> args(arg_strings.size() + 1);
123 5 : for(std::size_t idx(0); idx < arg_strings.size(); ++idx)
124 : {
125 3 : args[idx] = const_cast<char *>(arg_strings[idx].c_str());
126 : }
127 :
128 2 : execvp(args[0], args.data());
129 :
130 : // it should never return
131 : //
132 2 : snapdev::NOT_REACHED();
133 0 : }
134 :
135 :
136 :
137 : }
138 :
139 :
140 :
141 :
142 :
143 :
144 :
145 2 : CATCH_TEST_CASE("node_types", "[node][type]")
146 : {
147 2 : CATCH_START_SECTION("node_types: all types (defined in catch_node.ci)")
148 : {
149 2 : std::vector<bool> valid_types(static_cast<std::size_t>(as2js::node_t::NODE_max) + 1);
150 187 : for(std::size_t i(0); i < g_node_types_size; ++i)
151 : {
152 : //std::cerr << "--- working on node type: [" << g_node_types[i].f_name << "] (" << static_cast<std::size_t>(g_node_types[i].f_type) << ")\n";
153 186 : if(static_cast<std::size_t>(g_node_types[i].f_type) < static_cast<std::size_t>(as2js::node_t::NODE_max))
154 : {
155 185 : valid_types[static_cast<std::size_t>(g_node_types[i].f_type)] = true;
156 : }
157 :
158 : // define the type
159 186 : as2js::node_t const node_type(g_node_types[i].f_type);
160 :
161 186 : CATCH_REQUIRE(strcmp(as2js::node::type_to_string(node_type), g_node_types[i].f_name) == 0);
162 :
163 186 : if(static_cast<std::size_t>(node_type) > static_cast<std::size_t>(as2js::node_t::NODE_max)
164 1 : && node_type != as2js::node_t::NODE_EOF)
165 : {
166 0 : std::cerr << "Somehow a node type (" << static_cast<int>(node_type)
167 0 : << ") is larger than the maximum allowed ("
168 0 : << (static_cast<int>(as2js::node_t::NODE_max) - 1) << ")" << std::endl;
169 0 : CATCH_REQUIRE(node_type == as2js::node_t::NODE_EOF);
170 : }
171 :
172 : // get the next type of node
173 186 : as2js::node::pointer_t node(std::make_shared<as2js::node>(node_type));
174 :
175 : // check the type
176 186 : CATCH_REQUIRE(node->get_type() == node_type);
177 :
178 : // get the name
179 186 : char const *name(node->get_type_name());
180 : //std::cerr << "type = " << static_cast<int>(node_type) << " / " << name << "\n";
181 186 : CATCH_REQUIRE(strcmp(name, g_node_types[i].f_name) == 0);
182 :
183 : // test functions determining general types
184 186 : CATCH_REQUIRE((node->is_number() == false || node->is_number() == true));
185 186 : CATCH_REQUIRE(static_cast<as2js::node const *>(node.get())->is_number() ^ ((g_node_types[i].f_flags & TEST_NODE_IS_NUMBER) == 0));
186 :
187 : // This NaN test is not sufficient for strings
188 186 : CATCH_REQUIRE((node->is_nan() == false || node->is_nan() == true));
189 186 : CATCH_REQUIRE(static_cast<as2js::node const *>(node.get())->is_nan() ^ ((g_node_types[i].f_flags & TEST_NODE_IS_NAN) == 0));
190 :
191 186 : CATCH_REQUIRE((node->is_integer() == false || node->is_integer() == true));
192 186 : CATCH_REQUIRE(static_cast<as2js::node const *>(node.get())->is_integer() ^ ((g_node_types[i].f_flags & TEST_NODE_IS_INTEGER) == 0));
193 :
194 186 : CATCH_REQUIRE((node->is_floating_point() == false || node->is_floating_point() == true));
195 186 : CATCH_REQUIRE(static_cast<as2js::node const *>(node.get())->is_floating_point() ^ ((g_node_types[i].f_flags & TEST_NODE_IS_FLOATING_POINT) == 0));
196 :
197 186 : CATCH_REQUIRE((node->is_boolean() == false || node->is_boolean() == true));
198 186 : CATCH_REQUIRE(static_cast<as2js::node const *>(node.get())->is_boolean() ^ ((g_node_types[i].f_flags & TEST_NODE_IS_BOOLEAN) == 0));
199 :
200 186 : CATCH_REQUIRE((node->is_true() == false || node->is_true() == true));
201 186 : CATCH_REQUIRE(static_cast<as2js::node const *>(node.get())->is_true() ^ ((g_node_types[i].f_flags & TEST_NODE_IS_TRUE) == 0));
202 :
203 186 : CATCH_REQUIRE((node->is_false() == false || node->is_false() == true));
204 186 : CATCH_REQUIRE(static_cast<as2js::node const *>(node.get())->is_false() ^ ((g_node_types[i].f_flags & TEST_NODE_IS_FALSE) == 0));
205 :
206 186 : CATCH_REQUIRE((node->is_string() == false || node->is_string() == true));
207 186 : CATCH_REQUIRE(static_cast<as2js::node const *>(node.get())->is_string() ^ ((g_node_types[i].f_flags & TEST_NODE_IS_STRING) == 0));
208 :
209 186 : CATCH_REQUIRE((node->is_undefined() == false || node->is_undefined() == true));
210 186 : CATCH_REQUIRE(static_cast<as2js::node const *>(node.get())->is_undefined() ^ ((g_node_types[i].f_flags & TEST_NODE_IS_UNDEFINED) == 0));
211 :
212 186 : CATCH_REQUIRE((node->is_null() == false || node->is_null() == true));
213 186 : CATCH_REQUIRE(static_cast<as2js::node const *>(node.get())->is_null() ^ ((g_node_types[i].f_flags & TEST_NODE_IS_NULL) == 0));
214 :
215 186 : CATCH_REQUIRE((node->is_identifier() == false || node->is_identifier() == true));
216 186 : CATCH_REQUIRE(static_cast<as2js::node const *>(node.get())->is_identifier() ^ ((g_node_types[i].f_flags & TEST_NODE_IS_IDENTIFIER) == 0));
217 :
218 186 : CATCH_REQUIRE((node->is_literal() == false || node->is_literal() == true));
219 186 : CATCH_REQUIRE(static_cast<as2js::node const *>(node.get())->is_literal() ^ ((g_node_types[i].f_flags & (
220 : TEST_NODE_IS_INTEGER
221 : | TEST_NODE_IS_FLOATING_POINT
222 : | TEST_NODE_IS_TRUE
223 : | TEST_NODE_IS_FALSE
224 : | TEST_NODE_IS_STRING
225 : | TEST_NODE_IS_UNDEFINED
226 : | TEST_NODE_IS_NULL)) == 0));
227 :
228 186 : if(!node->is_literal())
229 : {
230 179 : as2js::node::pointer_t literal(std::make_shared<as2js::node>(as2js::node_t::NODE_STRING));
231 179 : CATCH_REQUIRE(as2js::node::compare(node, literal, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_ERROR);
232 179 : CATCH_REQUIRE(as2js::node::compare(node, literal, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_ERROR);
233 179 : CATCH_REQUIRE(as2js::node::compare(node, literal, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_ERROR);
234 179 : CATCH_REQUIRE(as2js::node::compare(literal, node, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_ERROR);
235 179 : CATCH_REQUIRE(as2js::node::compare(literal, node, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_ERROR);
236 179 : CATCH_REQUIRE(as2js::node::compare(literal, node, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_ERROR);
237 179 : CATCH_REQUIRE(as2js::node::compare(literal, node, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_ERROR);
238 179 : }
239 :
240 186 : CATCH_REQUIRE((node->has_side_effects() == false || node->has_side_effects() == true));
241 186 : CATCH_REQUIRE(static_cast<as2js::node const *>(node.get())->has_side_effects() ^ ((g_node_types[i].f_flags & TEST_NODE_HAS_SIDE_EFFECTS) == 0));
242 :
243 186 : if(g_node_types[i].f_operator != nullptr)
244 : {
245 63 : char const *op(as2js::node::operator_to_string(g_node_types[i].f_type));
246 63 : CATCH_REQUIRE(op != nullptr);
247 63 : CATCH_REQUIRE(strcmp(g_node_types[i].f_operator, op) == 0);
248 : //std::cerr << " testing " << node->get_type_name() << " from " << op << std::endl;
249 63 : CATCH_REQUIRE(as2js::node::string_to_operator(op) == g_node_types[i].f_type);
250 :
251 : // check the special case for not equal
252 63 : if(strcmp(g_node_types[i].f_operator, "!=") == 0)
253 : {
254 1 : CATCH_REQUIRE(as2js::node::string_to_operator("<>") == g_node_types[i].f_type);
255 : }
256 :
257 : // check the special case for assignment
258 63 : if(strcmp(g_node_types[i].f_operator, "=") == 0)
259 : {
260 1 : CATCH_REQUIRE(as2js::node::string_to_operator(":=") == g_node_types[i].f_type);
261 : }
262 : }
263 : else
264 : {
265 : // static function can also be called from the node pointer
266 : //std::cerr << " testing " << node->get_type_name() << std::endl;
267 123 : CATCH_REQUIRE(node->operator_to_string(g_node_types[i].f_type) == nullptr);
268 123 : CATCH_REQUIRE(as2js::node::string_to_operator(node->get_type_name()) == as2js::node_t::NODE_UNKNOWN);
269 : }
270 :
271 186 : if((g_node_types[i].f_flags & TEST_NODE_IS_SWITCH_OPERATOR) == 0)
272 : {
273 : // only NODE_PARAM_MATCH accepts this call
274 170 : as2js::node::pointer_t node_switch(std::make_shared<as2js::node>(as2js::node_t::NODE_SWITCH));
275 170 : CATCH_REQUIRE_THROWS_MATCHES(
276 : node_switch->set_switch_operator(node_type)
277 : , as2js::internal_error
278 : , Catch::Matchers::ExceptionMessage(
279 : "internal_error: set_switch_operator() called with an operator which is not valid for switch."));
280 170 : }
281 : else
282 : {
283 16 : as2js::node::pointer_t node_switch(std::make_shared<as2js::node>(as2js::node_t::NODE_SWITCH));
284 16 : node_switch->set_switch_operator(node_type);
285 16 : CATCH_REQUIRE(node_switch->get_switch_operator() == node_type);
286 16 : }
287 186 : if(node_type != as2js::node_t::NODE_SWITCH)
288 : {
289 : // a valid operator, but not a valid node to set
290 185 : CATCH_REQUIRE_THROWS_MATCHES(
291 : node->set_switch_operator(as2js::node_t::NODE_STRICTLY_EQUAL)
292 : , as2js::internal_error
293 : , Catch::Matchers::ExceptionMessage(
294 : "internal_error: set_switch_operator() called on a node which is not a switch node."));
295 : // not a valid node to get
296 185 : CATCH_REQUIRE_THROWS_MATCHES(
297 : node->get_switch_operator()
298 : , as2js::internal_error
299 : , Catch::Matchers::ExceptionMessage(
300 : "internal_error: get_switch_operator() called on a node which is not a switch node."));
301 : }
302 :
303 186 : if((g_node_types[i].f_flags & TEST_NODE_IS_PARAM_MATCH) == 0)
304 : {
305 : // only NODE_PARAM_MATCH accepts this call
306 185 : CATCH_REQUIRE_THROWS_MATCHES(
307 : node->set_param_size(10)
308 : , as2js::internal_error
309 : , Catch::Matchers::ExceptionMessage(
310 : "internal_error: set_param_size() called with a node other than a \"NODE_PARAM_MATCH\"."));
311 : }
312 : else
313 : {
314 : // zero is not acceptable
315 1 : CATCH_REQUIRE_THROWS_MATCHES(
316 : node->set_param_size(0)
317 : , as2js::internal_error
318 : , Catch::Matchers::ExceptionMessage(
319 : "internal_error: set_param_size() was called with a size of zero."));
320 : // this one is accepted
321 1 : node->set_param_size(10);
322 : // cannot change the size once set
323 1 : CATCH_REQUIRE_THROWS_MATCHES(
324 : node->set_param_size(10)
325 : , as2js::internal_error
326 : , Catch::Matchers::ExceptionMessage(
327 : "internal_error: set_param_size() called twice."));
328 : }
329 :
330 186 : if((g_node_types[i].f_flags & TEST_NODE_IS_BOOLEAN) == 0)
331 : {
332 184 : CATCH_REQUIRE_THROWS_MATCHES(
333 : node->get_boolean()
334 : , as2js::internal_error
335 : , Catch::Matchers::ExceptionMessage(
336 : "internal_error: get_boolean() called with a non-Boolean node type."));
337 184 : CATCH_REQUIRE_THROWS_MATCHES(
338 : node->set_boolean(rand() & 1)
339 : , as2js::internal_error
340 : , Catch::Matchers::ExceptionMessage(
341 : "internal_error: set_boolean() called with a non-Boolean node type."));
342 : }
343 2 : else if((g_node_types[i].f_flags & TEST_NODE_IS_TRUE) != 0)
344 : {
345 1 : CATCH_REQUIRE(node->get_boolean());
346 : }
347 : else
348 : {
349 1 : CATCH_REQUIRE(!node->get_boolean());
350 : }
351 :
352 186 : if((g_node_types[i].f_flags & TEST_NODE_IS_INTEGER) == 0)
353 : {
354 185 : CATCH_REQUIRE_THROWS_MATCHES(
355 : node->get_integer()
356 : , as2js::internal_error
357 : , Catch::Matchers::ExceptionMessage(
358 : "internal_error: get_integer() called with a non-integer node type."));
359 185 : as2js::integer random(rand());
360 185 : CATCH_REQUIRE_THROWS_MATCHES(
361 : node->set_integer(random)
362 : , as2js::internal_error
363 : , Catch::Matchers::ExceptionMessage(
364 : "internal_error: set_integer() called with a non-integer node type."));
365 : }
366 :
367 186 : if((g_node_types[i].f_flags & TEST_NODE_IS_FLOATING_POINT) == 0)
368 : {
369 185 : CATCH_REQUIRE_THROWS_MATCHES(
370 : node->get_floating_point()
371 : , as2js::internal_error
372 : , Catch::Matchers::ExceptionMessage(
373 : "internal_error: get_floating_point() called with a non-floating point node type."));
374 :
375 185 : as2js::floating_point random(rand());
376 185 : CATCH_REQUIRE_THROWS_MATCHES(
377 : node->set_floating_point(random)
378 : , as2js::internal_error
379 : , Catch::Matchers::ExceptionMessage(
380 : "internal_error: set_floating_point() called with a non-floating point node type."));
381 : }
382 :
383 : // here we have a special case as "many" different nodes accept
384 : // a string to represent one thing or another
385 : //
386 186 : if((g_node_types[i].f_flags & TEST_NODE_ACCEPT_STRING) == 0)
387 : {
388 163 : CATCH_REQUIRE_THROWS_MATCHES(
389 : node->get_string()
390 : , as2js::internal_error
391 : , Catch::Matchers::ExceptionMessage(
392 : "internal_error: get_string() called with non-string node type: \""
393 : + std::string(as2js::node::type_to_string(node_type))
394 : + "\"."));
395 815 : CATCH_REQUIRE_THROWS_MATCHES(
396 : node->set_string("test")
397 : , as2js::internal_error
398 : , Catch::Matchers::ExceptionMessage(
399 : "internal_error: set_string() called with a non-string node type."));
400 : }
401 : else
402 : {
403 23 : node->set_string("random test");
404 23 : CATCH_REQUIRE(node->get_string() == "random test");
405 : }
406 :
407 : // first test the flags that this type of node accepts
408 186 : std::bitset<static_cast<int>(as2js::flag_t::NODE_FLAG_max)> valid_flags;
409 266 : for(flags_per_node_t const *node_flags(g_node_types[i].f_node_flags);
410 266 : node_flags->f_flag != as2js::flag_t::NODE_FLAG_max;
411 : ++node_flags)
412 : {
413 : // mark this specific flag as valid
414 80 : valid_flags[static_cast<int>(node_flags->f_flag)] = true;
415 :
416 80 : as2js::flag_set_t set;
417 80 : CATCH_REQUIRE(node->compare_all_flags(set));
418 :
419 :
420 : // before we set it, always false
421 80 : CATCH_REQUIRE_FALSE(node->get_flag(node_flags->f_flag));
422 80 : node->set_flag(node_flags->f_flag, true);
423 80 : CATCH_REQUIRE(node->get_flag(node_flags->f_flag));
424 :
425 80 : CATCH_REQUIRE_FALSE(node->compare_all_flags(set));
426 80 : set[static_cast<int>(node_flags->f_flag)] = true;
427 80 : CATCH_REQUIRE(node->compare_all_flags(set));
428 :
429 80 : node->set_flag(node_flags->f_flag, false);
430 80 : CATCH_REQUIRE_FALSE(node->get_flag(node_flags->f_flag));
431 : }
432 :
433 : // now test all the other flags
434 10788 : for(int j(-5); j <= static_cast<int>(as2js::flag_t::NODE_FLAG_max) + 5; ++j)
435 : {
436 19158 : if(j < 0
437 9672 : || j >= static_cast<int>(as2js::flag_t::NODE_FLAG_max)
438 28830 : || !valid_flags[j])
439 : {
440 10522 : std::stringstream ss;
441 10522 : ss << *node;
442 21044 : std::string flag_name("<out of range>");
443 10522 : if(j >= 0
444 9592 : && j < static_cast<int>(as2js::flag_t::NODE_FLAG_max))
445 : {
446 8476 : flag_name = as2js::node::flag_to_string(static_cast<as2js::flag_t>(j));
447 : }
448 : #if 0
449 : std::cerr << "--- [ERROR NOT HAPPENING?] internal_error: node_flag.cpp: node::verify_flag(): node type: "
450 : + std::string(g_node_types[i].f_name)
451 : + " flag ("
452 : + flag_name
453 : + "/"
454 : + std::to_string(j)
455 : + ") / type mismatch ("
456 : + node->get_type_name()
457 : + '/'
458 : + std::to_string(static_cast<int>(node->get_type()))
459 : + ") for node:\n"
460 : + ss.str()
461 : + '\n';
462 : #endif
463 10522 : CATCH_REQUIRE_THROWS_MATCHES(
464 : node->get_flag(static_cast<as2js::flag_t>(j))
465 : , as2js::internal_error
466 : , Catch::Matchers::ExceptionMessage(
467 : "internal_error: node_flag.cpp: node::verify_flag(): flag ("
468 : + flag_name
469 : + "/"
470 : + std::to_string(j)
471 : + ") / type mismatch ("
472 : + as2js::node::type_to_string(node->get_type())
473 : + ':'
474 : + std::to_string(static_cast<int>(node->get_type()))
475 : + ") for node:\n"
476 : + ss.str()
477 : + '\n'));
478 10522 : CATCH_REQUIRE_THROWS_MATCHES(
479 : node->set_flag(static_cast<as2js::flag_t>(j), true)
480 : , as2js::internal_error
481 : , Catch::Matchers::ExceptionMessage(
482 : "internal_error: node_flag.cpp: node::verify_flag(): flag ("
483 : + flag_name
484 : + "/"
485 : + std::to_string(j)
486 : + ") / type mismatch ("
487 : + as2js::node::type_to_string(node->get_type())
488 : + ':'
489 : + std::to_string(static_cast<int>(node->get_type()))
490 : + ") for node:\n"
491 : + ss.str()
492 : + '\n'));
493 10522 : CATCH_REQUIRE_THROWS_MATCHES(
494 : node->set_flag(static_cast<as2js::flag_t>(j), false)
495 : , as2js::internal_error
496 : , Catch::Matchers::ExceptionMessage(
497 : "internal_error: node_flag.cpp: node::verify_flag(): flag ("
498 : + flag_name
499 : + "/"
500 : + std::to_string(j)
501 : + ") / type mismatch ("
502 : + as2js::node::type_to_string(node->get_type())
503 : + ':'
504 : + std::to_string(static_cast<int>(node->get_type()))
505 : + ") for node:\n"
506 : + ss.str()
507 : + '\n'));
508 10522 : }
509 : }
510 :
511 : // test completely invalid attribute indices
512 1116 : for(int j(-5); j < 0; ++j)
513 : {
514 930 : CATCH_REQUIRE_THROWS_MATCHES(
515 : node->get_attribute(static_cast<as2js::attribute_t>(j))
516 : , as2js::internal_error
517 : , Catch::Matchers::ExceptionMessage(
518 : "internal_error: unknown attribute number in node::attribute_to_string()."));
519 930 : CATCH_REQUIRE_THROWS_MATCHES(
520 : node->set_attribute(static_cast<as2js::attribute_t>(j), true)
521 : , as2js::internal_error
522 : , Catch::Matchers::ExceptionMessage(
523 : "internal_error: unknown attribute number in node::attribute_to_string()."));
524 930 : CATCH_REQUIRE_THROWS_MATCHES(
525 : node->set_attribute(static_cast<as2js::attribute_t>(j), false)
526 : , as2js::internal_error
527 : , Catch::Matchers::ExceptionMessage(
528 : "internal_error: unknown attribute number in node::attribute_to_string()."));
529 930 : CATCH_REQUIRE_THROWS_MATCHES(
530 : node->attribute_to_string(static_cast<as2js::attribute_t>(j))
531 : , as2js::internal_error
532 : , Catch::Matchers::ExceptionMessage(
533 : "internal_error: unknown attribute number in node::attribute_to_string()."));
534 930 : CATCH_REQUIRE_THROWS_MATCHES(
535 : as2js::node::attribute_to_string(static_cast<as2js::attribute_t>(j))
536 : , as2js::internal_error
537 : , Catch::Matchers::ExceptionMessage(
538 : "internal_error: unknown attribute number in node::attribute_to_string()."));
539 : }
540 1302 : for(int j(static_cast<int>(as2js::attribute_t::NODE_ATTR_max));
541 1302 : j <= static_cast<int>(as2js::attribute_t::NODE_ATTR_max) + 5;
542 : ++j)
543 : {
544 1116 : CATCH_REQUIRE_THROWS_MATCHES(
545 : node->get_attribute(static_cast<as2js::attribute_t>(j))
546 : , as2js::internal_error
547 : , Catch::Matchers::ExceptionMessage(
548 : "internal_error: unknown attribute number in node::attribute_to_string()."));
549 1116 : CATCH_REQUIRE_THROWS_MATCHES(
550 : node->set_attribute(static_cast<as2js::attribute_t>(j), true)
551 : , as2js::internal_error
552 : , Catch::Matchers::ExceptionMessage(
553 : "internal_error: unknown attribute number in node::attribute_to_string()."));
554 1116 : CATCH_REQUIRE_THROWS_MATCHES(
555 : node->set_attribute(static_cast<as2js::attribute_t>(j), false)
556 : , as2js::internal_error
557 : , Catch::Matchers::ExceptionMessage(
558 : "internal_error: unknown attribute number in node::attribute_to_string()."));
559 1116 : CATCH_REQUIRE_THROWS_MATCHES(
560 : node->attribute_to_string(static_cast<as2js::attribute_t>(j))
561 : , as2js::internal_error
562 : , Catch::Matchers::ExceptionMessage(
563 : "internal_error: unknown attribute number in node::attribute_to_string()."));
564 1116 : CATCH_REQUIRE_THROWS_MATCHES(
565 : as2js::node::attribute_to_string(static_cast<as2js::attribute_t>(j))
566 : , as2js::internal_error
567 : , Catch::Matchers::ExceptionMessage(
568 : "internal_error: unknown attribute number in node::attribute_to_string()."));
569 : }
570 :
571 : // attributes can be assigned to all types except NODE_PROGRAM
572 : // which only accepts NODE_DEFINED
573 5580 : for(int j(0); j < static_cast<int>(as2js::attribute_t::NODE_ATTR_max); ++j)
574 : {
575 5394 : bool valid(true);
576 5394 : switch(node_type)
577 : {
578 29 : case as2js::node_t::NODE_PROGRAM:
579 29 : valid = j == static_cast<int>(as2js::attribute_t::NODE_ATTR_DEFINED);
580 29 : break;
581 :
582 2494 : case as2js::node_t::NODE_ADD:
583 : case as2js::node_t::NODE_ARRAY:
584 : case as2js::node_t::NODE_ARRAY_LITERAL:
585 : case as2js::node_t::NODE_AS:
586 : case as2js::node_t::NODE_ASSIGNMENT:
587 : case as2js::node_t::NODE_ASSIGNMENT_ADD:
588 : case as2js::node_t::NODE_ASSIGNMENT_BITWISE_AND:
589 : case as2js::node_t::NODE_ASSIGNMENT_BITWISE_OR:
590 : case as2js::node_t::NODE_ASSIGNMENT_BITWISE_XOR:
591 : case as2js::node_t::NODE_ASSIGNMENT_DIVIDE:
592 : case as2js::node_t::NODE_ASSIGNMENT_LOGICAL_AND:
593 : case as2js::node_t::NODE_ASSIGNMENT_LOGICAL_OR:
594 : case as2js::node_t::NODE_ASSIGNMENT_LOGICAL_XOR:
595 : case as2js::node_t::NODE_ASSIGNMENT_MAXIMUM:
596 : case as2js::node_t::NODE_ASSIGNMENT_MINIMUM:
597 : case as2js::node_t::NODE_ASSIGNMENT_MODULO:
598 : case as2js::node_t::NODE_ASSIGNMENT_MULTIPLY:
599 : case as2js::node_t::NODE_ASSIGNMENT_POWER:
600 : case as2js::node_t::NODE_ASSIGNMENT_ROTATE_LEFT:
601 : case as2js::node_t::NODE_ASSIGNMENT_ROTATE_RIGHT:
602 : case as2js::node_t::NODE_ASSIGNMENT_SHIFT_LEFT:
603 : case as2js::node_t::NODE_ASSIGNMENT_SHIFT_RIGHT:
604 : case as2js::node_t::NODE_ASSIGNMENT_SHIFT_RIGHT_UNSIGNED:
605 : case as2js::node_t::NODE_ASSIGNMENT_SUBTRACT:
606 : case as2js::node_t::NODE_BITWISE_AND:
607 : case as2js::node_t::NODE_BITWISE_NOT:
608 : case as2js::node_t::NODE_BITWISE_OR:
609 : case as2js::node_t::NODE_BITWISE_XOR:
610 : case as2js::node_t::NODE_CALL:
611 : case as2js::node_t::NODE_CONDITIONAL:
612 : case as2js::node_t::NODE_DECREMENT:
613 : case as2js::node_t::NODE_DELETE:
614 : case as2js::node_t::NODE_DIVIDE:
615 : case as2js::node_t::NODE_EQUAL:
616 : case as2js::node_t::NODE_FALSE:
617 : case as2js::node_t::NODE_FLOATING_POINT:
618 : case as2js::node_t::NODE_FUNCTION:
619 : case as2js::node_t::NODE_GREATER:
620 : case as2js::node_t::NODE_GREATER_EQUAL:
621 : case as2js::node_t::NODE_IDENTIFIER:
622 : case as2js::node_t::NODE_IN:
623 : case as2js::node_t::NODE_INCREMENT:
624 : case as2js::node_t::NODE_INSTANCEOF:
625 : case as2js::node_t::NODE_INTEGER:
626 : case as2js::node_t::NODE_IS:
627 : case as2js::node_t::NODE_LESS:
628 : case as2js::node_t::NODE_LESS_EQUAL:
629 : case as2js::node_t::NODE_LIST:
630 : case as2js::node_t::NODE_LOGICAL_AND:
631 : case as2js::node_t::NODE_LOGICAL_NOT:
632 : case as2js::node_t::NODE_LOGICAL_OR:
633 : case as2js::node_t::NODE_LOGICAL_XOR:
634 : case as2js::node_t::NODE_MATCH:
635 : case as2js::node_t::NODE_MAXIMUM:
636 : case as2js::node_t::NODE_MEMBER:
637 : case as2js::node_t::NODE_MINIMUM:
638 : case as2js::node_t::NODE_MODULO:
639 : case as2js::node_t::NODE_MULTIPLY:
640 : case as2js::node_t::NODE_NAME:
641 : case as2js::node_t::NODE_NEW:
642 : case as2js::node_t::NODE_NOT_EQUAL:
643 : case as2js::node_t::NODE_NULL:
644 : case as2js::node_t::NODE_OBJECT_LITERAL:
645 : case as2js::node_t::NODE_POST_DECREMENT:
646 : case as2js::node_t::NODE_POST_INCREMENT:
647 : case as2js::node_t::NODE_POWER:
648 : case as2js::node_t::NODE_PRIVATE:
649 : case as2js::node_t::NODE_PUBLIC:
650 : case as2js::node_t::NODE_RANGE:
651 : case as2js::node_t::NODE_ROTATE_LEFT:
652 : case as2js::node_t::NODE_ROTATE_RIGHT:
653 : case as2js::node_t::NODE_SCOPE:
654 : case as2js::node_t::NODE_SHIFT_LEFT:
655 : case as2js::node_t::NODE_SHIFT_RIGHT:
656 : case as2js::node_t::NODE_SHIFT_RIGHT_UNSIGNED:
657 : case as2js::node_t::NODE_STRICTLY_EQUAL:
658 : case as2js::node_t::NODE_STRICTLY_NOT_EQUAL:
659 : case as2js::node_t::NODE_STRING:
660 : case as2js::node_t::NODE_SUBTRACT:
661 : case as2js::node_t::NODE_SUPER:
662 : case as2js::node_t::NODE_THIS:
663 : case as2js::node_t::NODE_TRUE:
664 : case as2js::node_t::NODE_TYPEOF:
665 : case as2js::node_t::NODE_UNDEFINED:
666 : case as2js::node_t::NODE_VIDENTIFIER:
667 : case as2js::node_t::NODE_VOID:
668 2494 : break;
669 :
670 2871 : default:
671 : // any other type and you get an exception
672 2871 : valid = j != static_cast<int>(as2js::attribute_t::NODE_ATTR_TYPE);
673 2871 : break;
674 :
675 : }
676 :
677 : //if(node_type == as2js::node_t::NODE_PROGRAM
678 : //&& j != static_cast<int>(as2js::attribute_t::NODE_ATTR_DEFINED))
679 5394 : if(!valid)
680 : {
681 127 : CATCH_REQUIRE_THROWS_MATCHES(
682 : node->get_attribute(static_cast<as2js::attribute_t>(j))
683 : , as2js::internal_error
684 : , Catch::Matchers::ExceptionMessage(
685 : "internal_error: node \""
686 : + std::string(as2js::node::type_to_string(node->get_type()))
687 : + "\" does not like attribute \""
688 : + as2js::node::attribute_to_string(static_cast<as2js::attribute_t>(j))
689 : + "\" in node::verify_attribute()."));
690 127 : CATCH_REQUIRE_THROWS_MATCHES(
691 : node->set_attribute(static_cast<as2js::attribute_t>(j), true)
692 : , as2js::internal_error
693 : , Catch::Matchers::ExceptionMessage(
694 : "internal_error: node \""
695 : + std::string(as2js::node::type_to_string(node->get_type()))
696 : + "\" does not like attribute \""
697 : + as2js::node::attribute_to_string(static_cast<as2js::attribute_t>(j))
698 : + "\" in node::verify_attribute()."));
699 127 : CATCH_REQUIRE_THROWS_MATCHES(
700 : node->set_attribute(static_cast<as2js::attribute_t>(j), false)
701 : , as2js::internal_error
702 : , Catch::Matchers::ExceptionMessage(
703 : "internal_error: node \""
704 : + std::string(as2js::node::type_to_string(node->get_type()))
705 : + "\" does not like attribute \""
706 : + as2js::node::attribute_to_string(static_cast<as2js::attribute_t>(j))
707 : + "\" in node::verify_attribute()."));
708 : }
709 : else
710 : {
711 : // before we set it, always false
712 5267 : CATCH_REQUIRE(!node->get_attribute(static_cast<as2js::attribute_t>(j)));
713 5267 : node->set_attribute(static_cast<as2js::attribute_t>(j), true);
714 5267 : CATCH_REQUIRE(node->get_attribute(static_cast<as2js::attribute_t>(j)));
715 : // since we reset them all we won't have a problem with conflicts in this loop
716 5267 : node->set_attribute(static_cast<as2js::attribute_t>(j), false);
717 5267 : CATCH_REQUIRE(!node->get_attribute(static_cast<as2js::attribute_t>(j)));
718 : }
719 5394 : char const *attr_name1(node->attribute_to_string(static_cast<as2js::attribute_t>(j)));
720 5394 : CATCH_REQUIRE(attr_name1 != nullptr);
721 5394 : char const *attr_name2(as2js::node::attribute_to_string(static_cast<as2js::attribute_t>(j)));
722 5394 : CATCH_REQUIRE(attr_name2 != nullptr);
723 5394 : CATCH_REQUIRE(strcmp(attr_name1, attr_name2) == 0);
724 :
725 5394 : switch(static_cast<as2js::attribute_t>(j))
726 : {
727 372 : case as2js::attribute_t::NODE_ATTR_PUBLIC: CATCH_REQUIRE(strcmp(attr_name1, "PUBLIC") == 0); break;
728 372 : case as2js::attribute_t::NODE_ATTR_PRIVATE: CATCH_REQUIRE(strcmp(attr_name1, "PRIVATE") == 0); break;
729 372 : case as2js::attribute_t::NODE_ATTR_PROTECTED: CATCH_REQUIRE(strcmp(attr_name1, "PROTECTED") == 0); break;
730 372 : case as2js::attribute_t::NODE_ATTR_INTERNAL: CATCH_REQUIRE(strcmp(attr_name1, "INTERNAL") == 0); break;
731 372 : case as2js::attribute_t::NODE_ATTR_TRANSIENT: CATCH_REQUIRE(strcmp(attr_name1, "TRANSIENT") == 0); break;
732 372 : case as2js::attribute_t::NODE_ATTR_VOLATILE: CATCH_REQUIRE(strcmp(attr_name1, "VOLATILE") == 0); break;
733 372 : case as2js::attribute_t::NODE_ATTR_STATIC: CATCH_REQUIRE(strcmp(attr_name1, "STATIC") == 0); break;
734 372 : case as2js::attribute_t::NODE_ATTR_ABSTRACT: CATCH_REQUIRE(strcmp(attr_name1, "ABSTRACT") == 0); break;
735 372 : case as2js::attribute_t::NODE_ATTR_VIRTUAL: CATCH_REQUIRE(strcmp(attr_name1, "VIRTUAL") == 0); break;
736 372 : case as2js::attribute_t::NODE_ATTR_ARRAY: CATCH_REQUIRE(strcmp(attr_name1, "ARRAY") == 0); break;
737 372 : case as2js::attribute_t::NODE_ATTR_INLINE: CATCH_REQUIRE(strcmp(attr_name1, "INLINE") == 0); break;
738 372 : case as2js::attribute_t::NODE_ATTR_REQUIRE_ELSE: CATCH_REQUIRE(strcmp(attr_name1, "REQUIRE_ELSE") == 0); break;
739 372 : case as2js::attribute_t::NODE_ATTR_ENSURE_THEN: CATCH_REQUIRE(strcmp(attr_name1, "ENSURE_THEN") == 0); break;
740 372 : case as2js::attribute_t::NODE_ATTR_NATIVE: CATCH_REQUIRE(strcmp(attr_name1, "NATIVE") == 0); break;
741 372 : case as2js::attribute_t::NODE_ATTR_DEPRECATED: CATCH_REQUIRE(strcmp(attr_name1, "DEPRECATED") == 0); break;
742 372 : case as2js::attribute_t::NODE_ATTR_UNSAFE: CATCH_REQUIRE(strcmp(attr_name1, "UNSAFE") == 0); break;
743 372 : case as2js::attribute_t::NODE_ATTR_EXTERN: CATCH_REQUIRE(strcmp(attr_name1, "EXTERN") == 0); break;
744 372 : case as2js::attribute_t::NODE_ATTR_CONSTRUCTOR: CATCH_REQUIRE(strcmp(attr_name1, "CONSTRUCTOR") == 0); break;
745 372 : case as2js::attribute_t::NODE_ATTR_FINAL: CATCH_REQUIRE(strcmp(attr_name1, "FINAL") == 0); break;
746 372 : case as2js::attribute_t::NODE_ATTR_ENUMERABLE: CATCH_REQUIRE(strcmp(attr_name1, "ENUMERABLE") == 0); break;
747 372 : case as2js::attribute_t::NODE_ATTR_TRUE: CATCH_REQUIRE(strcmp(attr_name1, "TRUE") == 0); break;
748 372 : case as2js::attribute_t::NODE_ATTR_FALSE: CATCH_REQUIRE(strcmp(attr_name1, "FALSE") == 0); break;
749 372 : case as2js::attribute_t::NODE_ATTR_UNUSED: CATCH_REQUIRE(strcmp(attr_name1, "UNUSED") == 0); break;
750 372 : case as2js::attribute_t::NODE_ATTR_DYNAMIC: CATCH_REQUIRE(strcmp(attr_name1, "DYNAMIC") == 0); break;
751 372 : case as2js::attribute_t::NODE_ATTR_FOREACH: CATCH_REQUIRE(strcmp(attr_name1, "FOREACH") == 0); break;
752 372 : case as2js::attribute_t::NODE_ATTR_NOBREAK: CATCH_REQUIRE(strcmp(attr_name1, "NOBREAK") == 0); break;
753 372 : case as2js::attribute_t::NODE_ATTR_AUTOBREAK: CATCH_REQUIRE(strcmp(attr_name1, "AUTOBREAK") == 0); break;
754 372 : case as2js::attribute_t::NODE_ATTR_TYPE: CATCH_REQUIRE(strcmp(attr_name1, "TYPE") == 0); break;
755 372 : case as2js::attribute_t::NODE_ATTR_DEFINED: CATCH_REQUIRE(strcmp(attr_name1, "DEFINED") == 0); break;
756 0 : case as2js::attribute_t::NODE_ATTR_max: CATCH_REQUIRE(!"attribute max should not be checked in this test"); break;
757 : }
758 : }
759 :
760 : // cloning is available for basic nodes
761 : //
762 186 : if((g_node_types[i].f_flags & TEST_NODE_IS_BASIC) == 0)
763 : {
764 178 : CATCH_REQUIRE_THROWS_MATCHES(
765 : node->clone_basic_node()
766 : , as2js::internal_error
767 : , Catch::Matchers::ExceptionMessage(
768 : "internal_error: node.cpp: clone_basic_node(): called with a node which is not considered to be a basic node."));
769 : }
770 : else
771 : {
772 : // TODO: better test what is copied and what is not copied
773 : //
774 8 : as2js::node::pointer_t clone(node->clone_basic_node());
775 8 : CATCH_REQUIRE(node->get_type() == clone->get_type());
776 : //CATCH_REQUIRE(node->get_flag(...) == clone->get_flag(...));
777 8 : CATCH_REQUIRE(node->get_attribute_node() == clone->get_attribute_node());
778 : //CATCH_REQUIRE(node->get_attribute(...) == clone->get_attribute(...));
779 : //CATCH_REQUIRE(node->get_switch_operator() == clone->get_switch_operator()); -- none of these nodes are NODE_SWITCH
780 8 : CATCH_REQUIRE(node->is_locked() == clone->is_locked());
781 8 : CATCH_REQUIRE(node->get_position() == clone->get_position());
782 8 : CATCH_REQUIRE(node->get_instance() == clone->get_instance());
783 8 : CATCH_REQUIRE(node->get_goto_enter() == clone->get_goto_enter());
784 8 : CATCH_REQUIRE(node->get_goto_exit() == clone->get_goto_exit());
785 : //CATCH_REQUIRE(node->get_variable(...) == clone->get_variable(...));
786 : //CATCH_REQUIRE(node->find_label(...) == clone->find_label(...));
787 8 : }
788 186 : }
789 :
790 : // as we may be adding new node types without updating the tests,
791 : // here we verify that all node types that were not checked are
792 : // indeed invalid
793 : //
794 : // the vector is important because the node type numbers are not
795 : // incremental; some make use of the input character (i.e. '=' and
796 : // '!' are node types for the assignment and logical not) then we
797 : // jump to number 1001
798 : //
799 1163 : for(std::size_t i(0); i <= static_cast<std::size_t>(as2js::node_t::NODE_max); ++i)
800 : {
801 1162 : if(!valid_types[i])
802 : {
803 : // WARNING: if an errror occurs here it is likely because
804 : // the corresponding node type is new and the test
805 : // was not yet updated; i.e. if the node is now
806 : // considered valid, then we are expected to
807 : // return from the make_shared<>() instead of
808 : // throwing as expected by the test for invalid
809 : // nodes
810 : //
811 : // also... this does not work if you also cannot
812 : // create the node (i.e. I added a type, added the
813 : // parsing in the lexer, did not add the type to
814 : // the node::node() constructor)
815 : //
816 : //std::cerr << "--- creating node with 'invalid' type: " << i << " || " << static_cast<int>(as2js::node_t::NODE_YIELD) << "\n";
817 977 : as2js::node_t const node_type(static_cast<as2js::node_t>(i));
818 977 : CATCH_REQUIRE_THROWS_MATCHES(
819 : std::make_shared<as2js::node>(node_type)
820 : , as2js::incompatible_type
821 : , Catch::Matchers::ExceptionMessage(
822 : "as2js_exception: unknown node type number, "
823 : + std::to_string(i)
824 : + ", used to create a node."));
825 : }
826 : }
827 1 : }
828 2 : CATCH_END_SECTION()
829 :
830 2 : CATCH_START_SECTION("node_types: node types outside the defined range")
831 : {
832 : // test with completely random numbers too (outside of the
833 : // standard range of node types)
834 : //
835 101 : for(size_t i(0); i < 100; ++i)
836 : {
837 100 : int32_t j((rand() << 16) ^ rand());
838 100 : if(j < -1 || j >= static_cast<ssize_t>(as2js::node_t::NODE_max))
839 : {
840 100 : as2js::node_t node_type(static_cast<as2js::node_t>(j));
841 100 : CATCH_REQUIRE_THROWS_MATCHES(
842 : std::make_shared<as2js::node>(node_type)
843 : , as2js::incompatible_type
844 : , Catch::Matchers::ExceptionMessage(
845 : "as2js_exception: unknown node type number, "
846 : + std::to_string(j)
847 : + ", used to create a node."));
848 : }
849 : }
850 : }
851 2 : CATCH_END_SECTION()
852 2 : }
853 :
854 :
855 1 : CATCH_TEST_CASE("node_compare", "[node][compare]")
856 : {
857 1 : CATCH_START_SECTION("node_compare: NULL value")
858 : {
859 1 : as2js::node::pointer_t node1_true(std::make_shared<as2js::node>(as2js::node_t::NODE_TRUE));
860 1 : as2js::node::pointer_t node2_false(std::make_shared<as2js::node>(as2js::node_t::NODE_FALSE));
861 1 : as2js::node::pointer_t node3_true(std::make_shared<as2js::node>(as2js::node_t::NODE_TRUE));
862 1 : as2js::node::pointer_t node4_false(std::make_shared<as2js::node>(as2js::node_t::NODE_FALSE));
863 :
864 1 : as2js::node::pointer_t node5_33(std::make_shared<as2js::node>(as2js::node_t::NODE_INTEGER));
865 1 : as2js::integer i33;
866 1 : i33.set(33);
867 1 : node5_33->set_integer(i33);
868 :
869 1 : as2js::node::pointer_t node6_101(std::make_shared<as2js::node>(as2js::node_t::NODE_INTEGER));
870 1 : as2js::integer i101;
871 1 : i101.set(101);
872 1 : node6_101->set_integer(i101);
873 :
874 1 : as2js::node::pointer_t node7_33(std::make_shared<as2js::node>(as2js::node_t::NODE_FLOATING_POINT));
875 1 : as2js::floating_point f33;
876 1 : f33.set(3.3);
877 1 : node7_33->set_floating_point(f33);
878 :
879 1 : as2js::node::pointer_t node7_nearly33(std::make_shared<as2js::node>(as2js::node_t::NODE_FLOATING_POINT));
880 1 : as2js::floating_point fnearly33;
881 1 : fnearly33.set(3.300001);
882 1 : node7_nearly33->set_floating_point(fnearly33);
883 :
884 1 : as2js::node::pointer_t node8_101(std::make_shared<as2js::node>(as2js::node_t::NODE_FLOATING_POINT));
885 1 : as2js::floating_point f101;
886 1 : f101.set(1.01);
887 1 : node8_101->set_floating_point(f101);
888 :
889 1 : as2js::node::pointer_t node9_null(std::make_shared<as2js::node>(as2js::node_t::NODE_NULL));
890 1 : as2js::node::pointer_t node10_null(std::make_shared<as2js::node>(as2js::node_t::NODE_NULL));
891 :
892 1 : as2js::node::pointer_t node11_undefined(std::make_shared<as2js::node>(as2js::node_t::NODE_UNDEFINED));
893 1 : as2js::node::pointer_t node12_undefined(std::make_shared<as2js::node>(as2js::node_t::NODE_UNDEFINED));
894 :
895 1 : as2js::node::pointer_t node13_empty_string(std::make_shared<as2js::node>(as2js::node_t::NODE_STRING));
896 1 : as2js::node::pointer_t node14_blah(std::make_shared<as2js::node>(as2js::node_t::NODE_STRING));
897 1 : node14_blah->set_string("blah");
898 1 : as2js::node::pointer_t node15_foo(std::make_shared<as2js::node>(as2js::node_t::NODE_STRING));
899 1 : node15_foo->set_string("foo");
900 1 : as2js::node::pointer_t node16_07(std::make_shared<as2js::node>(as2js::node_t::NODE_STRING));
901 1 : node16_07->set_string("0.7");
902 1 : as2js::node::pointer_t node17_nearly33(std::make_shared<as2js::node>(as2js::node_t::NODE_STRING));
903 1 : node17_nearly33->set_string("3.300001");
904 :
905 : // BOOLEAN
906 1 : CATCH_REQUIRE(as2js::node::compare(node1_true, node1_true, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_EQUAL);
907 1 : CATCH_REQUIRE(as2js::node::compare(node1_true, node3_true, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_EQUAL);
908 1 : CATCH_REQUIRE(as2js::node::compare(node3_true, node1_true, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_EQUAL);
909 1 : CATCH_REQUIRE(as2js::node::compare(node3_true, node3_true, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_EQUAL);
910 :
911 1 : CATCH_REQUIRE(as2js::node::compare(node1_true, node1_true, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_EQUAL);
912 1 : CATCH_REQUIRE(as2js::node::compare(node1_true, node3_true, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_EQUAL);
913 1 : CATCH_REQUIRE(as2js::node::compare(node3_true, node1_true, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_EQUAL);
914 1 : CATCH_REQUIRE(as2js::node::compare(node3_true, node3_true, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_EQUAL);
915 :
916 1 : CATCH_REQUIRE(as2js::node::compare(node1_true, node1_true, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_EQUAL);
917 1 : CATCH_REQUIRE(as2js::node::compare(node1_true, node3_true, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_EQUAL);
918 1 : CATCH_REQUIRE(as2js::node::compare(node3_true, node1_true, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_EQUAL);
919 1 : CATCH_REQUIRE(as2js::node::compare(node3_true, node3_true, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_EQUAL);
920 :
921 1 : CATCH_REQUIRE(as2js::node::compare(node2_false, node2_false, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_EQUAL);
922 1 : CATCH_REQUIRE(as2js::node::compare(node2_false, node4_false, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_EQUAL);
923 1 : CATCH_REQUIRE(as2js::node::compare(node4_false, node2_false, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_EQUAL);
924 1 : CATCH_REQUIRE(as2js::node::compare(node4_false, node4_false, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_EQUAL);
925 :
926 1 : CATCH_REQUIRE(as2js::node::compare(node2_false, node2_false, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_EQUAL);
927 1 : CATCH_REQUIRE(as2js::node::compare(node2_false, node4_false, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_EQUAL);
928 1 : CATCH_REQUIRE(as2js::node::compare(node4_false, node2_false, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_EQUAL);
929 1 : CATCH_REQUIRE(as2js::node::compare(node4_false, node4_false, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_EQUAL);
930 :
931 1 : CATCH_REQUIRE(as2js::node::compare(node2_false, node2_false, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_EQUAL);
932 1 : CATCH_REQUIRE(as2js::node::compare(node2_false, node4_false, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_EQUAL);
933 1 : CATCH_REQUIRE(as2js::node::compare(node4_false, node2_false, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_EQUAL);
934 1 : CATCH_REQUIRE(as2js::node::compare(node4_false, node4_false, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_EQUAL);
935 :
936 1 : CATCH_REQUIRE(as2js::node::compare(node1_true, node2_false, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_GREATER);
937 1 : CATCH_REQUIRE(as2js::node::compare(node3_true, node2_false, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_GREATER);
938 1 : CATCH_REQUIRE(as2js::node::compare(node1_true, node4_false, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_GREATER);
939 1 : CATCH_REQUIRE(as2js::node::compare(node3_true, node4_false, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_GREATER);
940 :
941 1 : CATCH_REQUIRE(as2js::node::compare(node1_true, node2_false, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_GREATER);
942 1 : CATCH_REQUIRE(as2js::node::compare(node3_true, node2_false, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_GREATER);
943 1 : CATCH_REQUIRE(as2js::node::compare(node1_true, node4_false, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_GREATER);
944 1 : CATCH_REQUIRE(as2js::node::compare(node3_true, node4_false, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_GREATER);
945 :
946 1 : CATCH_REQUIRE(as2js::node::compare(node1_true, node2_false, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_GREATER);
947 1 : CATCH_REQUIRE(as2js::node::compare(node3_true, node2_false, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_GREATER);
948 1 : CATCH_REQUIRE(as2js::node::compare(node1_true, node4_false, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_GREATER);
949 1 : CATCH_REQUIRE(as2js::node::compare(node3_true, node4_false, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_GREATER);
950 :
951 1 : CATCH_REQUIRE(as2js::node::compare(node2_false, node1_true, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_LESS);
952 1 : CATCH_REQUIRE(as2js::node::compare(node2_false, node3_true, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_LESS);
953 1 : CATCH_REQUIRE(as2js::node::compare(node4_false, node1_true, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_LESS);
954 1 : CATCH_REQUIRE(as2js::node::compare(node4_false, node3_true, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_LESS);
955 :
956 1 : CATCH_REQUIRE(as2js::node::compare(node2_false, node1_true, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_LESS);
957 1 : CATCH_REQUIRE(as2js::node::compare(node2_false, node3_true, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_LESS);
958 1 : CATCH_REQUIRE(as2js::node::compare(node4_false, node1_true, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_LESS);
959 1 : CATCH_REQUIRE(as2js::node::compare(node4_false, node3_true, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_LESS);
960 :
961 1 : CATCH_REQUIRE(as2js::node::compare(node2_false, node1_true, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_LESS);
962 1 : CATCH_REQUIRE(as2js::node::compare(node2_false, node3_true, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_LESS);
963 1 : CATCH_REQUIRE(as2js::node::compare(node4_false, node1_true, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_LESS);
964 1 : CATCH_REQUIRE(as2js::node::compare(node4_false, node3_true, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_LESS);
965 :
966 : // FLOAT
967 1 : CATCH_REQUIRE(as2js::node::compare(node7_33, node7_33, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_EQUAL);
968 1 : CATCH_REQUIRE(as2js::node::compare(node7_33, node7_nearly33, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_LESS);
969 1 : CATCH_REQUIRE(as2js::node::compare(node7_nearly33, node7_33, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_GREATER);
970 1 : CATCH_REQUIRE(as2js::node::compare(node7_33, node17_nearly33, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_UNORDERED);
971 1 : CATCH_REQUIRE(as2js::node::compare(node17_nearly33, node7_33, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_UNORDERED);
972 1 : CATCH_REQUIRE(as2js::node::compare(node7_33, node8_101, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_GREATER);
973 1 : CATCH_REQUIRE(as2js::node::compare(node8_101, node7_33, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_LESS);
974 1 : CATCH_REQUIRE(as2js::node::compare(node8_101, node8_101, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_EQUAL);
975 :
976 1 : CATCH_REQUIRE(as2js::node::compare(node7_33, node7_33, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_EQUAL);
977 1 : CATCH_REQUIRE(as2js::node::compare(node7_33, node7_nearly33, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_LESS);
978 1 : CATCH_REQUIRE(as2js::node::compare(node7_nearly33, node7_33, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_GREATER);
979 1 : CATCH_REQUIRE(as2js::node::compare(node7_33, node17_nearly33, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_LESS);
980 1 : CATCH_REQUIRE(as2js::node::compare(node17_nearly33, node7_33, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_GREATER);
981 1 : CATCH_REQUIRE(as2js::node::compare(node7_33, node8_101, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_GREATER);
982 1 : CATCH_REQUIRE(as2js::node::compare(node8_101, node7_33, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_LESS);
983 1 : CATCH_REQUIRE(as2js::node::compare(node8_101, node8_101, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_EQUAL);
984 :
985 1 : CATCH_REQUIRE(as2js::node::compare(node7_33, node7_33, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_EQUAL);
986 1 : CATCH_REQUIRE(as2js::node::compare(node7_33, node7_nearly33, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_EQUAL);
987 1 : CATCH_REQUIRE(as2js::node::compare(node7_nearly33, node7_33, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_EQUAL);
988 1 : CATCH_REQUIRE(as2js::node::compare(node7_33, node17_nearly33, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_EQUAL);
989 1 : CATCH_REQUIRE(as2js::node::compare(node17_nearly33, node7_33, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_EQUAL);
990 1 : CATCH_REQUIRE(as2js::node::compare(node7_33, node8_101, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_GREATER);
991 1 : CATCH_REQUIRE(as2js::node::compare(node8_101, node7_33, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_LESS);
992 1 : CATCH_REQUIRE(as2js::node::compare(node8_101, node8_101, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_EQUAL);
993 :
994 : // INTEGER
995 1 : CATCH_REQUIRE(as2js::node::compare(node5_33, node5_33, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_EQUAL);
996 1 : CATCH_REQUIRE(as2js::node::compare(node5_33, node6_101, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_LESS);
997 1 : CATCH_REQUIRE(as2js::node::compare(node6_101, node5_33, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_GREATER);
998 1 : CATCH_REQUIRE(as2js::node::compare(node6_101, node6_101, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_EQUAL);
999 :
1000 1 : CATCH_REQUIRE(as2js::node::compare(node5_33, node5_33, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_EQUAL);
1001 1 : CATCH_REQUIRE(as2js::node::compare(node5_33, node6_101, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_LESS);
1002 1 : CATCH_REQUIRE(as2js::node::compare(node6_101, node5_33, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_GREATER);
1003 1 : CATCH_REQUIRE(as2js::node::compare(node6_101, node6_101, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_EQUAL);
1004 :
1005 1 : CATCH_REQUIRE(as2js::node::compare(node5_33, node5_33, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_EQUAL);
1006 1 : CATCH_REQUIRE(as2js::node::compare(node5_33, node6_101, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_LESS);
1007 1 : CATCH_REQUIRE(as2js::node::compare(node6_101, node5_33, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_GREATER);
1008 1 : CATCH_REQUIRE(as2js::node::compare(node6_101, node6_101, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_EQUAL);
1009 :
1010 : // NULL
1011 1 : CATCH_REQUIRE(as2js::node::compare(node9_null, node9_null, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_EQUAL);
1012 1 : CATCH_REQUIRE(as2js::node::compare(node9_null, node10_null, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_EQUAL);
1013 1 : CATCH_REQUIRE(as2js::node::compare(node10_null, node9_null, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_EQUAL);
1014 1 : CATCH_REQUIRE(as2js::node::compare(node10_null, node10_null, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_EQUAL);
1015 :
1016 1 : CATCH_REQUIRE(as2js::node::compare(node9_null, node9_null, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_EQUAL);
1017 1 : CATCH_REQUIRE(as2js::node::compare(node9_null, node10_null, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_EQUAL);
1018 1 : CATCH_REQUIRE(as2js::node::compare(node10_null, node9_null, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_EQUAL);
1019 1 : CATCH_REQUIRE(as2js::node::compare(node10_null, node10_null, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_EQUAL);
1020 :
1021 1 : CATCH_REQUIRE(as2js::node::compare(node9_null, node9_null, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_EQUAL);
1022 1 : CATCH_REQUIRE(as2js::node::compare(node9_null, node10_null, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_EQUAL);
1023 1 : CATCH_REQUIRE(as2js::node::compare(node10_null, node9_null, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_EQUAL);
1024 1 : CATCH_REQUIRE(as2js::node::compare(node10_null, node10_null, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_EQUAL);
1025 :
1026 : // UNDEFINED
1027 1 : CATCH_REQUIRE(as2js::node::compare(node11_undefined, node11_undefined, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_EQUAL);
1028 1 : CATCH_REQUIRE(as2js::node::compare(node11_undefined, node12_undefined, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_EQUAL);
1029 1 : CATCH_REQUIRE(as2js::node::compare(node12_undefined, node11_undefined, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_EQUAL);
1030 1 : CATCH_REQUIRE(as2js::node::compare(node12_undefined, node12_undefined, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_EQUAL);
1031 :
1032 1 : CATCH_REQUIRE(as2js::node::compare(node11_undefined, node11_undefined, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_EQUAL);
1033 1 : CATCH_REQUIRE(as2js::node::compare(node11_undefined, node12_undefined, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_EQUAL);
1034 1 : CATCH_REQUIRE(as2js::node::compare(node12_undefined, node11_undefined, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_EQUAL);
1035 1 : CATCH_REQUIRE(as2js::node::compare(node12_undefined, node12_undefined, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_EQUAL);
1036 :
1037 1 : CATCH_REQUIRE(as2js::node::compare(node11_undefined, node11_undefined, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_EQUAL);
1038 1 : CATCH_REQUIRE(as2js::node::compare(node11_undefined, node12_undefined, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_EQUAL);
1039 1 : CATCH_REQUIRE(as2js::node::compare(node12_undefined, node11_undefined, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_EQUAL);
1040 1 : CATCH_REQUIRE(as2js::node::compare(node12_undefined, node12_undefined, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_EQUAL);
1041 :
1042 : // STRING
1043 1 : CATCH_REQUIRE(as2js::node::compare(node13_empty_string, node13_empty_string, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_EQUAL);
1044 1 : CATCH_REQUIRE(as2js::node::compare(node13_empty_string, node14_blah, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_LESS);
1045 1 : CATCH_REQUIRE(as2js::node::compare(node13_empty_string, node15_foo, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_LESS);
1046 1 : CATCH_REQUIRE(as2js::node::compare(node14_blah, node13_empty_string, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_GREATER);
1047 1 : CATCH_REQUIRE(as2js::node::compare(node14_blah, node14_blah, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_EQUAL);
1048 1 : CATCH_REQUIRE(as2js::node::compare(node14_blah, node15_foo, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_LESS);
1049 1 : CATCH_REQUIRE(as2js::node::compare(node15_foo, node13_empty_string, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_GREATER);
1050 1 : CATCH_REQUIRE(as2js::node::compare(node15_foo, node14_blah, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_GREATER);
1051 1 : CATCH_REQUIRE(as2js::node::compare(node15_foo, node15_foo, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_EQUAL);
1052 :
1053 1 : CATCH_REQUIRE(as2js::node::compare(node13_empty_string, node13_empty_string, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_EQUAL);
1054 1 : CATCH_REQUIRE(as2js::node::compare(node13_empty_string, node14_blah, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_LESS);
1055 1 : CATCH_REQUIRE(as2js::node::compare(node13_empty_string, node15_foo, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_LESS);
1056 1 : CATCH_REQUIRE(as2js::node::compare(node14_blah, node13_empty_string, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_GREATER);
1057 1 : CATCH_REQUIRE(as2js::node::compare(node14_blah, node14_blah, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_EQUAL);
1058 1 : CATCH_REQUIRE(as2js::node::compare(node14_blah, node15_foo, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_LESS);
1059 1 : CATCH_REQUIRE(as2js::node::compare(node15_foo, node13_empty_string, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_GREATER);
1060 1 : CATCH_REQUIRE(as2js::node::compare(node15_foo, node14_blah, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_GREATER);
1061 1 : CATCH_REQUIRE(as2js::node::compare(node15_foo, node15_foo, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_EQUAL);
1062 :
1063 1 : CATCH_REQUIRE(as2js::node::compare(node13_empty_string, node13_empty_string, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_EQUAL);
1064 1 : CATCH_REQUIRE(as2js::node::compare(node13_empty_string, node14_blah, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_LESS);
1065 1 : CATCH_REQUIRE(as2js::node::compare(node13_empty_string, node15_foo, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_LESS);
1066 1 : CATCH_REQUIRE(as2js::node::compare(node14_blah, node13_empty_string, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_GREATER);
1067 1 : CATCH_REQUIRE(as2js::node::compare(node14_blah, node14_blah, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_EQUAL);
1068 1 : CATCH_REQUIRE(as2js::node::compare(node14_blah, node15_foo, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_LESS);
1069 1 : CATCH_REQUIRE(as2js::node::compare(node15_foo, node13_empty_string, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_GREATER);
1070 1 : CATCH_REQUIRE(as2js::node::compare(node15_foo, node14_blah, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_GREATER);
1071 1 : CATCH_REQUIRE(as2js::node::compare(node15_foo, node15_foo, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_EQUAL);
1072 :
1073 : // NULL vs UNDEFINED
1074 1 : CATCH_REQUIRE(as2js::node::compare(node9_null, node11_undefined, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_UNORDERED);
1075 1 : CATCH_REQUIRE(as2js::node::compare(node9_null, node12_undefined, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_UNORDERED);
1076 1 : CATCH_REQUIRE(as2js::node::compare(node10_null, node11_undefined, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_UNORDERED);
1077 1 : CATCH_REQUIRE(as2js::node::compare(node10_null, node12_undefined, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_UNORDERED);
1078 1 : CATCH_REQUIRE(as2js::node::compare(node11_undefined, node9_null, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_UNORDERED);
1079 1 : CATCH_REQUIRE(as2js::node::compare(node12_undefined, node9_null, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_UNORDERED);
1080 1 : CATCH_REQUIRE(as2js::node::compare(node11_undefined, node10_null, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_UNORDERED);
1081 1 : CATCH_REQUIRE(as2js::node::compare(node12_undefined, node10_null, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_UNORDERED);
1082 :
1083 1 : CATCH_REQUIRE(as2js::node::compare(node9_null, node11_undefined, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_EQUAL);
1084 1 : CATCH_REQUIRE(as2js::node::compare(node9_null, node12_undefined, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_EQUAL);
1085 1 : CATCH_REQUIRE(as2js::node::compare(node10_null, node11_undefined, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_EQUAL);
1086 1 : CATCH_REQUIRE(as2js::node::compare(node10_null, node12_undefined, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_EQUAL);
1087 1 : CATCH_REQUIRE(as2js::node::compare(node11_undefined, node9_null, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_EQUAL);
1088 1 : CATCH_REQUIRE(as2js::node::compare(node12_undefined, node9_null, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_EQUAL);
1089 1 : CATCH_REQUIRE(as2js::node::compare(node11_undefined, node10_null, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_EQUAL);
1090 1 : CATCH_REQUIRE(as2js::node::compare(node12_undefined, node10_null, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_EQUAL);
1091 :
1092 1 : CATCH_REQUIRE(as2js::node::compare(node9_null, node11_undefined, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_EQUAL);
1093 1 : CATCH_REQUIRE(as2js::node::compare(node9_null, node12_undefined, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_EQUAL);
1094 1 : CATCH_REQUIRE(as2js::node::compare(node10_null, node11_undefined, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_EQUAL);
1095 1 : CATCH_REQUIRE(as2js::node::compare(node10_null, node12_undefined, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_EQUAL);
1096 1 : CATCH_REQUIRE(as2js::node::compare(node11_undefined, node9_null, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_EQUAL);
1097 1 : CATCH_REQUIRE(as2js::node::compare(node12_undefined, node9_null, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_EQUAL);
1098 1 : CATCH_REQUIRE(as2js::node::compare(node11_undefined, node10_null, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_EQUAL);
1099 1 : CATCH_REQUIRE(as2js::node::compare(node12_undefined, node10_null, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_EQUAL);
1100 :
1101 : // <any> against FLOATING_POINT
1102 1 : CATCH_REQUIRE(as2js::node::compare(node1_true, node7_33, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_UNORDERED);
1103 1 : CATCH_REQUIRE(as2js::node::compare(node2_false, node7_33, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_UNORDERED);
1104 1 : CATCH_REQUIRE(as2js::node::compare(node5_33, node7_33, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_UNORDERED);
1105 1 : CATCH_REQUIRE(as2js::node::compare(node6_101, node7_33, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_UNORDERED);
1106 1 : CATCH_REQUIRE(as2js::node::compare(node9_null, node7_33, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_UNORDERED);
1107 1 : CATCH_REQUIRE(as2js::node::compare(node11_undefined, node7_33, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_UNORDERED);
1108 1 : CATCH_REQUIRE(as2js::node::compare(node13_empty_string, node7_33, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_UNORDERED);
1109 1 : CATCH_REQUIRE(as2js::node::compare(node14_blah, node7_33, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_UNORDERED);
1110 1 : CATCH_REQUIRE(as2js::node::compare(node16_07, node7_33, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_UNORDERED);
1111 :
1112 1 : CATCH_REQUIRE(as2js::node::compare(node1_true, node7_33, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_LESS);
1113 1 : CATCH_REQUIRE(as2js::node::compare(node2_false, node7_33, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_LESS);
1114 1 : CATCH_REQUIRE(as2js::node::compare(node5_33, node7_33, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_GREATER);
1115 1 : CATCH_REQUIRE(as2js::node::compare(node6_101, node7_33, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_GREATER);
1116 1 : CATCH_REQUIRE(as2js::node::compare(node9_null, node7_33, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_LESS);
1117 1 : CATCH_REQUIRE(as2js::node::compare(node11_undefined, node7_33, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_UNORDERED);
1118 1 : CATCH_REQUIRE(as2js::node::compare(node13_empty_string, node7_33, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_LESS);
1119 1 : CATCH_REQUIRE(as2js::node::compare(node14_blah, node7_33, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_UNORDERED);
1120 1 : CATCH_REQUIRE(as2js::node::compare(node16_07, node7_33, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_LESS);
1121 :
1122 1 : CATCH_REQUIRE(as2js::node::compare(node1_true, node7_33, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_LESS);
1123 1 : CATCH_REQUIRE(as2js::node::compare(node2_false, node7_33, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_LESS);
1124 1 : CATCH_REQUIRE(as2js::node::compare(node5_33, node7_33, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_GREATER);
1125 1 : CATCH_REQUIRE(as2js::node::compare(node6_101, node7_33, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_GREATER);
1126 1 : CATCH_REQUIRE(as2js::node::compare(node9_null, node7_33, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_LESS);
1127 1 : CATCH_REQUIRE(as2js::node::compare(node11_undefined, node7_33, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_UNORDERED);
1128 1 : CATCH_REQUIRE(as2js::node::compare(node13_empty_string, node7_33, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_LESS);
1129 1 : CATCH_REQUIRE(as2js::node::compare(node14_blah, node7_33, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_UNORDERED);
1130 1 : CATCH_REQUIRE(as2js::node::compare(node16_07, node7_33, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_LESS);
1131 :
1132 : // FLOATING_POINT against <any>
1133 1 : CATCH_REQUIRE(as2js::node::compare(node8_101, node1_true, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_UNORDERED);
1134 1 : CATCH_REQUIRE(as2js::node::compare(node8_101, node2_false, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_UNORDERED);
1135 1 : CATCH_REQUIRE(as2js::node::compare(node8_101, node5_33, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_UNORDERED);
1136 1 : CATCH_REQUIRE(as2js::node::compare(node8_101, node6_101, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_UNORDERED);
1137 1 : CATCH_REQUIRE(as2js::node::compare(node8_101, node9_null, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_UNORDERED);
1138 1 : CATCH_REQUIRE(as2js::node::compare(node8_101, node11_undefined, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_UNORDERED);
1139 1 : CATCH_REQUIRE(as2js::node::compare(node8_101, node13_empty_string, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_UNORDERED);
1140 1 : CATCH_REQUIRE(as2js::node::compare(node8_101, node14_blah, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_UNORDERED);
1141 1 : CATCH_REQUIRE(as2js::node::compare(node8_101, node16_07, as2js::compare_mode_t::COMPARE_STRICT) == as2js::compare_t::COMPARE_UNORDERED);
1142 :
1143 1 : CATCH_REQUIRE(as2js::node::compare(node8_101, node1_true, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_GREATER);
1144 1 : CATCH_REQUIRE(as2js::node::compare(node8_101, node2_false, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_GREATER);
1145 1 : CATCH_REQUIRE(as2js::node::compare(node8_101, node5_33, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_LESS);
1146 1 : CATCH_REQUIRE(as2js::node::compare(node8_101, node6_101, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_LESS);
1147 1 : CATCH_REQUIRE(as2js::node::compare(node8_101, node9_null, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_GREATER);
1148 1 : CATCH_REQUIRE(as2js::node::compare(node8_101, node11_undefined, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_UNORDERED);
1149 1 : CATCH_REQUIRE(as2js::node::compare(node8_101, node13_empty_string, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_GREATER);
1150 1 : CATCH_REQUIRE(as2js::node::compare(node8_101, node14_blah, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_UNORDERED);
1151 1 : CATCH_REQUIRE(as2js::node::compare(node8_101, node16_07, as2js::compare_mode_t::COMPARE_LOOSE) == as2js::compare_t::COMPARE_GREATER);
1152 :
1153 1 : CATCH_REQUIRE(as2js::node::compare(node8_101, node2_false, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_GREATER);
1154 1 : CATCH_REQUIRE(as2js::node::compare(node8_101, node5_33, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_LESS);
1155 1 : CATCH_REQUIRE(as2js::node::compare(node8_101, node6_101, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_LESS);
1156 1 : CATCH_REQUIRE(as2js::node::compare(node8_101, node9_null, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_GREATER);
1157 1 : CATCH_REQUIRE(as2js::node::compare(node8_101, node11_undefined, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_UNORDERED);
1158 1 : CATCH_REQUIRE(as2js::node::compare(node8_101, node13_empty_string, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_GREATER);
1159 1 : CATCH_REQUIRE(as2js::node::compare(node8_101, node14_blah, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_UNORDERED);
1160 1 : CATCH_REQUIRE(as2js::node::compare(node8_101, node16_07, as2js::compare_mode_t::COMPARE_SMART) == as2js::compare_t::COMPARE_GREATER);
1161 1 : }
1162 1 : CATCH_END_SECTION()
1163 1 : }
1164 :
1165 :
1166 3 : CATCH_TEST_CASE("node_conversions", "[node][conversion]")
1167 : {
1168 3 : CATCH_START_SECTION("node_conversions: simple")
1169 : {
1170 : // first test simple conversions
1171 187 : for(size_t i(0); i < g_node_types_size; ++i)
1172 : {
1173 : // original type
1174 186 : as2js::node_t original_type(g_node_types[i].f_type);
1175 :
1176 : // all nodes can be converted to UNKNOWN
1177 : {
1178 186 : as2js::node::pointer_t node(std::make_shared<as2js::node>(original_type));
1179 : {
1180 186 : snapdev::ostream_to_buf<char> out(std::cerr);
1181 372 : as2js::node_lock lock(node);
1182 186 : CATCH_REQUIRE_THROWS_MATCHES(
1183 : node->to_unknown()
1184 : , as2js::locked_node
1185 : , Catch::Matchers::ExceptionMessage(
1186 : "as2js_exception: trying to modify a locked node."));
1187 186 : CATCH_REQUIRE(node->get_type() == original_type);
1188 186 : CATCH_REQUIRE(out.str().substr(0, 65) == "error: The following node is locked and thus cannot be modified:\n");
1189 186 : }
1190 186 : node->to_unknown();
1191 186 : CATCH_REQUIRE(node->get_type() == as2js::node_t::NODE_UNKNOWN);
1192 186 : }
1193 :
1194 : // CALL can be convert to AS
1195 : {
1196 186 : as2js::node::pointer_t node(std::make_shared<as2js::node>(original_type));
1197 : {
1198 186 : snapdev::ostream_to_buf<char> out(std::cerr);
1199 372 : as2js::node_lock lock(node);
1200 186 : CATCH_REQUIRE_THROWS_MATCHES(
1201 : node->to_as()
1202 : , as2js::locked_node
1203 : , Catch::Matchers::ExceptionMessage(
1204 : "as2js_exception: trying to modify a locked node."));
1205 186 : CATCH_REQUIRE(node->get_type() == original_type);
1206 186 : CATCH_REQUIRE(out.str().substr(0, 65) == "error: The following node is locked and thus cannot be modified:\n");
1207 186 : }
1208 186 : if(original_type == as2js::node_t::NODE_CALL)
1209 : {
1210 : // in this case it works
1211 1 : CATCH_REQUIRE(node->to_as());
1212 1 : CATCH_REQUIRE(node->get_type() == as2js::node_t::NODE_AS);
1213 : }
1214 : else
1215 : {
1216 : // in this case it fails
1217 185 : CATCH_REQUIRE(!node->to_as());
1218 185 : CATCH_REQUIRE(node->get_type() == original_type);
1219 : }
1220 186 : }
1221 :
1222 : // test what would happen if we were to call to_boolean()
1223 : {
1224 186 : as2js::node::pointer_t node(std::make_shared<as2js::node>(original_type));
1225 : {
1226 372 : as2js::node_lock lock(node);
1227 186 : node->to_boolean_type_only();
1228 186 : CATCH_REQUIRE(node->get_type() == original_type);
1229 186 : }
1230 186 : as2js::node_t new_type(node->to_boolean_type_only());
1231 186 : switch(original_type)
1232 : {
1233 1 : case as2js::node_t::NODE_TRUE:
1234 1 : CATCH_REQUIRE(new_type == as2js::node_t::NODE_TRUE);
1235 1 : break;
1236 :
1237 6 : case as2js::node_t::NODE_FALSE:
1238 : case as2js::node_t::NODE_NULL:
1239 : case as2js::node_t::NODE_UNDEFINED:
1240 : case as2js::node_t::NODE_INTEGER: // by default integers are set to zero
1241 : case as2js::node_t::NODE_FLOATING_POINT: // by default floating points are set to zero
1242 : case as2js::node_t::NODE_STRING: // by default strings are empty
1243 6 : CATCH_REQUIRE(new_type == as2js::node_t::NODE_FALSE);
1244 6 : break;
1245 :
1246 179 : default:
1247 179 : CATCH_REQUIRE(new_type == as2js::node_t::NODE_UNDEFINED);
1248 179 : break;
1249 :
1250 : }
1251 186 : }
1252 :
1253 : // a few nodes can be converted to a boolean value
1254 : {
1255 186 : as2js::node::pointer_t node(std::make_shared<as2js::node>(original_type));
1256 : {
1257 186 : snapdev::ostream_to_buf<char> out(std::cerr);
1258 372 : as2js::node_lock lock(node);
1259 186 : CATCH_REQUIRE_THROWS_MATCHES(
1260 : node->to_boolean()
1261 : , as2js::locked_node
1262 : , Catch::Matchers::ExceptionMessage(
1263 : "as2js_exception: trying to modify a locked node."));
1264 186 : CATCH_REQUIRE(node->get_type() == original_type);
1265 186 : CATCH_REQUIRE(out.str().substr(0, 65) == "error: The following node is locked and thus cannot be modified:\n");
1266 186 : }
1267 186 : switch(original_type)
1268 : {
1269 1 : case as2js::node_t::NODE_TRUE:
1270 1 : CATCH_REQUIRE(node->to_boolean());
1271 1 : CATCH_REQUIRE(node->get_type() == as2js::node_t::NODE_TRUE);
1272 1 : break;
1273 :
1274 6 : case as2js::node_t::NODE_FALSE:
1275 : case as2js::node_t::NODE_NULL:
1276 : case as2js::node_t::NODE_UNDEFINED:
1277 : case as2js::node_t::NODE_INTEGER: // by default integers are set to zero
1278 : case as2js::node_t::NODE_FLOATING_POINT: // by default floating points are set to zero
1279 : case as2js::node_t::NODE_STRING: // by default strings are empty
1280 6 : CATCH_REQUIRE(node->to_boolean());
1281 6 : CATCH_REQUIRE(node->get_type() == as2js::node_t::NODE_FALSE);
1282 6 : break;
1283 :
1284 179 : default:
1285 179 : CATCH_REQUIRE(!node->to_boolean());
1286 179 : CATCH_REQUIRE(node->get_type() == original_type);
1287 179 : break;
1288 :
1289 : }
1290 186 : }
1291 :
1292 : // a couple types of nodes can be converted to a CALL
1293 : {
1294 186 : as2js::node::pointer_t node(std::make_shared<as2js::node>(original_type));
1295 : {
1296 186 : snapdev::ostream_to_buf<char> out(std::cerr);
1297 372 : as2js::node_lock lock(node);
1298 186 : CATCH_REQUIRE_THROWS_MATCHES(
1299 : node->to_call()
1300 : , as2js::locked_node
1301 : , Catch::Matchers::ExceptionMessage(
1302 : "as2js_exception: trying to modify a locked node."));
1303 186 : CATCH_REQUIRE(node->get_type() == original_type);
1304 186 : CATCH_REQUIRE(out.str().substr(0, 65) == "error: The following node is locked and thus cannot be modified:\n");
1305 186 : }
1306 186 : switch(original_type)
1307 : {
1308 62 : case as2js::node_t::NODE_ADD:
1309 : case as2js::node_t::NODE_ALMOST_EQUAL:
1310 : case as2js::node_t::NODE_ARRAY:
1311 : case as2js::node_t::NODE_ASSIGNMENT:
1312 : case as2js::node_t::NODE_ASSIGNMENT_ADD:
1313 : case as2js::node_t::NODE_ASSIGNMENT_BITWISE_AND:
1314 : case as2js::node_t::NODE_ASSIGNMENT_BITWISE_OR:
1315 : case as2js::node_t::NODE_ASSIGNMENT_BITWISE_XOR:
1316 : case as2js::node_t::NODE_ASSIGNMENT_DIVIDE:
1317 : case as2js::node_t::NODE_ASSIGNMENT_LOGICAL_AND:
1318 : case as2js::node_t::NODE_ASSIGNMENT_LOGICAL_OR:
1319 : case as2js::node_t::NODE_ASSIGNMENT_LOGICAL_XOR:
1320 : case as2js::node_t::NODE_ASSIGNMENT_MAXIMUM:
1321 : case as2js::node_t::NODE_ASSIGNMENT_MINIMUM:
1322 : case as2js::node_t::NODE_ASSIGNMENT_MODULO:
1323 : case as2js::node_t::NODE_ASSIGNMENT_MULTIPLY:
1324 : case as2js::node_t::NODE_ASSIGNMENT_POWER:
1325 : case as2js::node_t::NODE_ASSIGNMENT_ROTATE_LEFT:
1326 : case as2js::node_t::NODE_ASSIGNMENT_ROTATE_RIGHT:
1327 : case as2js::node_t::NODE_ASSIGNMENT_SHIFT_LEFT:
1328 : case as2js::node_t::NODE_ASSIGNMENT_SHIFT_RIGHT:
1329 : case as2js::node_t::NODE_ASSIGNMENT_SHIFT_RIGHT_UNSIGNED:
1330 : case as2js::node_t::NODE_ASSIGNMENT_SUBTRACT:
1331 : case as2js::node_t::NODE_BITWISE_AND:
1332 : case as2js::node_t::NODE_BITWISE_NOT:
1333 : case as2js::node_t::NODE_BITWISE_OR:
1334 : case as2js::node_t::NODE_BITWISE_XOR:
1335 : case as2js::node_t::NODE_COMMA:
1336 : case as2js::node_t::NODE_COMPARE:
1337 : case as2js::node_t::NODE_DECREMENT:
1338 : case as2js::node_t::NODE_DIVIDE:
1339 : case as2js::node_t::NODE_EQUAL:
1340 : case as2js::node_t::NODE_GREATER:
1341 : case as2js::node_t::NODE_GREATER_EQUAL:
1342 : case as2js::node_t::NODE_INCREMENT:
1343 : case as2js::node_t::NODE_LESS:
1344 : case as2js::node_t::NODE_LESS_EQUAL:
1345 : case as2js::node_t::NODE_LIST:
1346 : case as2js::node_t::NODE_LOGICAL_AND:
1347 : case as2js::node_t::NODE_LOGICAL_NOT:
1348 : case as2js::node_t::NODE_LOGICAL_OR:
1349 : case as2js::node_t::NODE_LOGICAL_XOR:
1350 : case as2js::node_t::NODE_MATCH:
1351 : case as2js::node_t::NODE_MAXIMUM:
1352 : case as2js::node_t::NODE_MEMBER:
1353 : case as2js::node_t::NODE_MINIMUM:
1354 : case as2js::node_t::NODE_MODULO:
1355 : case as2js::node_t::NODE_MULTIPLY:
1356 : case as2js::node_t::NODE_NOT_EQUAL:
1357 : case as2js::node_t::NODE_NOT_MATCH:
1358 : case as2js::node_t::NODE_POST_DECREMENT:
1359 : case as2js::node_t::NODE_POST_INCREMENT:
1360 : case as2js::node_t::NODE_POWER:
1361 : case as2js::node_t::NODE_ROTATE_LEFT:
1362 : case as2js::node_t::NODE_ROTATE_RIGHT:
1363 : case as2js::node_t::NODE_SHIFT_LEFT:
1364 : case as2js::node_t::NODE_SHIFT_RIGHT:
1365 : case as2js::node_t::NODE_SHIFT_RIGHT_UNSIGNED:
1366 : case as2js::node_t::NODE_SMART_MATCH:
1367 : case as2js::node_t::NODE_STRICTLY_EQUAL:
1368 : case as2js::node_t::NODE_STRICTLY_NOT_EQUAL:
1369 : case as2js::node_t::NODE_SUBTRACT:
1370 62 : CATCH_REQUIRE(node->to_call());
1371 62 : CATCH_REQUIRE(node->get_type() == as2js::node_t::NODE_CALL);
1372 62 : break;
1373 :
1374 124 : default:
1375 124 : CATCH_REQUIRE(!node->to_call());
1376 124 : CATCH_REQUIRE(node->get_type() == original_type);
1377 124 : break;
1378 :
1379 : }
1380 186 : }
1381 :
1382 : // a few types of nodes can be converted to an INTEGER
1383 : {
1384 186 : as2js::node::pointer_t node(std::make_shared<as2js::node>(original_type));
1385 : {
1386 186 : snapdev::ostream_to_buf<char> out(std::cerr);
1387 372 : as2js::node_lock lock(node);
1388 186 : CATCH_REQUIRE_THROWS_MATCHES(
1389 : node->to_integer()
1390 : , as2js::locked_node
1391 : , Catch::Matchers::ExceptionMessage(
1392 : "as2js_exception: trying to modify a locked node."));
1393 186 : CATCH_REQUIRE(node->get_type() == original_type);
1394 186 : CATCH_REQUIRE(out.str().substr(0, 65) == "error: The following node is locked and thus cannot be modified:\n");
1395 186 : }
1396 186 : switch(original_type)
1397 : {
1398 1 : case as2js::node_t::NODE_INTEGER: // no change
1399 1 : CATCH_REQUIRE(node->to_integer());
1400 1 : CATCH_REQUIRE(node->get_type() == as2js::node_t::NODE_INTEGER);
1401 1 : break;
1402 :
1403 1 : case as2js::node_t::NODE_FLOATING_POINT:
1404 1 : CATCH_REQUIRE(node->to_integer());
1405 1 : CATCH_REQUIRE(node->get_type() == as2js::node_t::NODE_INTEGER);
1406 1 : break;
1407 :
1408 3 : case as2js::node_t::NODE_FALSE:
1409 : case as2js::node_t::NODE_NULL:
1410 : case as2js::node_t::NODE_UNDEFINED:
1411 3 : CATCH_REQUIRE(node->to_integer());
1412 3 : CATCH_REQUIRE(node->get_type() == as2js::node_t::NODE_INTEGER);
1413 3 : CATCH_REQUIRE(node->get_integer().get() == 0);
1414 3 : break;
1415 :
1416 1 : case as2js::node_t::NODE_STRING: // empty string to start with...
1417 1 : CATCH_REQUIRE(node->to_integer());
1418 1 : CATCH_REQUIRE(node->get_type() == as2js::node_t::NODE_INTEGER);
1419 1 : CATCH_REQUIRE(node->get_integer().get() == 0);
1420 :
1421 : // if not empty...
1422 : {
1423 1 : as2js::node::pointer_t node_str(std::make_shared<as2js::node>(original_type));
1424 1 : node_str->set_string("34");
1425 1 : CATCH_REQUIRE(node_str->to_integer());
1426 1 : CATCH_REQUIRE(node_str->get_type() == as2js::node_t::NODE_INTEGER);
1427 1 : CATCH_REQUIRE(node_str->get_integer().get() == 34);
1428 1 : }
1429 : {
1430 1 : as2js::node::pointer_t node_str(std::make_shared<as2js::node>(original_type));
1431 1 : node_str->set_string("+84");
1432 1 : CATCH_REQUIRE(node_str->to_integer());
1433 1 : CATCH_REQUIRE(node_str->get_type() == as2js::node_t::NODE_INTEGER);
1434 1 : CATCH_REQUIRE(node_str->get_integer().get() == 84);
1435 1 : }
1436 : {
1437 1 : as2js::node::pointer_t node_str(std::make_shared<as2js::node>(original_type));
1438 1 : node_str->set_string("-37");
1439 1 : CATCH_REQUIRE(node_str->to_integer());
1440 1 : CATCH_REQUIRE(node_str->get_type() == as2js::node_t::NODE_INTEGER);
1441 1 : CATCH_REQUIRE(node_str->get_integer().get() == -37);
1442 1 : }
1443 : {
1444 1 : as2js::node::pointer_t node_str(std::make_shared<as2js::node>(original_type));
1445 1 : node_str->set_string("3.4");
1446 1 : CATCH_REQUIRE(node_str->to_integer());
1447 1 : CATCH_REQUIRE(node_str->get_type() == as2js::node_t::NODE_INTEGER);
1448 1 : CATCH_REQUIRE(node_str->get_integer().get() == 3);
1449 1 : }
1450 : {
1451 1 : as2js::node::pointer_t node_str(std::make_shared<as2js::node>(original_type));
1452 1 : node_str->set_string("34e+5");
1453 1 : CATCH_REQUIRE(node_str->to_integer());
1454 1 : CATCH_REQUIRE(node_str->get_type() == as2js::node_t::NODE_INTEGER);
1455 1 : CATCH_REQUIRE(node_str->get_integer().get() == 3400000);
1456 1 : }
1457 : {
1458 1 : as2js::node::pointer_t node_str(std::make_shared<as2js::node>(original_type));
1459 1 : node_str->set_string("some NaN");
1460 1 : CATCH_REQUIRE(node_str->to_integer());
1461 1 : CATCH_REQUIRE(node_str->get_type() == as2js::node_t::NODE_INTEGER);
1462 1 : CATCH_REQUIRE(node_str->get_integer().get() == 0);
1463 1 : }
1464 : break;
1465 :
1466 1 : case as2js::node_t::NODE_TRUE:
1467 1 : CATCH_REQUIRE(node->to_integer());
1468 1 : CATCH_REQUIRE(node->get_type() == as2js::node_t::NODE_INTEGER);
1469 1 : CATCH_REQUIRE(node->get_integer().get() == 1);
1470 1 : break;
1471 :
1472 179 : default:
1473 179 : CATCH_REQUIRE(!node->to_integer());
1474 179 : CATCH_REQUIRE(node->get_type() == original_type);
1475 179 : break;
1476 :
1477 : }
1478 186 : }
1479 :
1480 : // a few types of nodes can be converted to a FLOATING_POINT
1481 : {
1482 186 : as2js::node::pointer_t node(std::make_shared<as2js::node>(original_type));
1483 : {
1484 186 : snapdev::ostream_to_buf<char> out(std::cerr);
1485 372 : as2js::node_lock lock(node);
1486 186 : CATCH_REQUIRE_THROWS_MATCHES(
1487 : node->to_floating_point()
1488 : , as2js::locked_node
1489 : , Catch::Matchers::ExceptionMessage(
1490 : "as2js_exception: trying to modify a locked node."));
1491 186 : CATCH_REQUIRE(node->get_type() == original_type);
1492 186 : CATCH_REQUIRE(out.str().substr(0, 65) == "error: The following node is locked and thus cannot be modified:\n");
1493 186 : }
1494 186 : switch(original_type)
1495 : {
1496 1 : case as2js::node_t::NODE_INTEGER: // no change
1497 1 : CATCH_REQUIRE(node->to_floating_point());
1498 1 : CATCH_REQUIRE(node->get_type() == as2js::node_t::NODE_FLOATING_POINT);
1499 1 : break;
1500 :
1501 1 : case as2js::node_t::NODE_FLOATING_POINT:
1502 1 : CATCH_REQUIRE(node->to_floating_point());
1503 1 : CATCH_REQUIRE(node->get_type() == as2js::node_t::NODE_FLOATING_POINT);
1504 1 : break;
1505 :
1506 3 : case as2js::node_t::NODE_FALSE:
1507 : case as2js::node_t::NODE_NULL:
1508 : case as2js::node_t::NODE_STRING:
1509 3 : CATCH_REQUIRE(node->to_floating_point());
1510 3 : CATCH_REQUIRE(node->get_type() == as2js::node_t::NODE_FLOATING_POINT);
1511 : {
1512 : #pragma GCC diagnostic push
1513 : #pragma GCC diagnostic ignored "-Wfloat-equal"
1514 3 : bool const is_zero(node->get_floating_point().get() == 0.0);
1515 : #pragma GCC diagnostic pop
1516 3 : CATCH_REQUIRE(is_zero);
1517 : }
1518 3 : break;
1519 :
1520 1 : case as2js::node_t::NODE_TRUE:
1521 1 : CATCH_REQUIRE(node->to_floating_point());
1522 1 : CATCH_REQUIRE(node->get_type() == as2js::node_t::NODE_FLOATING_POINT);
1523 : {
1524 : #pragma GCC diagnostic push
1525 : #pragma GCC diagnostic ignored "-Wfloat-equal"
1526 1 : bool const is_one(node->get_floating_point().get() == 1.0);
1527 : #pragma GCC diagnostic pop
1528 1 : CATCH_REQUIRE(is_one);
1529 : }
1530 1 : break;
1531 :
1532 1 : case as2js::node_t::NODE_UNDEFINED:
1533 1 : CATCH_REQUIRE(node->to_floating_point());
1534 1 : CATCH_REQUIRE(node->get_type() == as2js::node_t::NODE_FLOATING_POINT);
1535 1 : CATCH_REQUIRE(node->get_floating_point().is_nan());
1536 1 : break;
1537 :
1538 179 : default:
1539 179 : CATCH_REQUIRE(!node->to_floating_point());
1540 179 : CATCH_REQUIRE(node->get_type() == original_type);
1541 179 : break;
1542 :
1543 : }
1544 186 : }
1545 :
1546 : // IDENTIFIER can be converted to LABEL
1547 : {
1548 186 : as2js::node::pointer_t node(std::make_shared<as2js::node>(original_type));
1549 : {
1550 186 : snapdev::ostream_to_buf<char> out(std::cerr);
1551 372 : as2js::node_lock lock(node);
1552 186 : CATCH_REQUIRE_THROWS_MATCHES(
1553 : node->to_label()
1554 : , as2js::locked_node
1555 : , Catch::Matchers::ExceptionMessage(
1556 : "as2js_exception: trying to modify a locked node."));
1557 186 : CATCH_REQUIRE(node->get_type() == original_type);
1558 186 : CATCH_REQUIRE(out.str().substr(0, 65) == "error: The following node is locked and thus cannot be modified:\n");
1559 186 : }
1560 186 : if(original_type == as2js::node_t::NODE_IDENTIFIER)
1561 : {
1562 : // in this case it works
1563 1 : node->to_label();
1564 1 : CATCH_REQUIRE(node->get_type() == as2js::node_t::NODE_LABEL);
1565 : }
1566 : else
1567 : {
1568 : // this one fails with a soft error (returns false)
1569 185 : CATCH_REQUIRE(!node->to_label());
1570 185 : CATCH_REQUIRE(node->get_type() == original_type);
1571 : }
1572 186 : }
1573 :
1574 : // a few types of nodes can be converted to a Number
1575 : {
1576 186 : as2js::node::pointer_t node(std::make_shared<as2js::node>(original_type));
1577 : {
1578 186 : snapdev::ostream_to_buf<char> out(std::cerr);
1579 372 : as2js::node_lock lock(node);
1580 186 : CATCH_REQUIRE_THROWS_MATCHES(
1581 : node->to_number()
1582 : , as2js::locked_node
1583 : , Catch::Matchers::ExceptionMessage(
1584 : "as2js_exception: trying to modify a locked node."));
1585 186 : CATCH_REQUIRE(node->get_type() == original_type);
1586 186 : CATCH_REQUIRE(out.str().substr(0, 65) == "error: The following node is locked and thus cannot be modified:\n");
1587 186 : }
1588 186 : switch(original_type)
1589 : {
1590 2 : case as2js::node_t::NODE_INTEGER: // no change!
1591 : case as2js::node_t::NODE_FLOATING_POINT: // no change!
1592 2 : CATCH_REQUIRE(node->to_number());
1593 2 : CATCH_REQUIRE(node->get_type() == original_type);
1594 2 : break;
1595 :
1596 2 : case as2js::node_t::NODE_FALSE:
1597 : case as2js::node_t::NODE_NULL:
1598 2 : CATCH_REQUIRE(node->to_number());
1599 2 : CATCH_REQUIRE(node->get_type() == as2js::node_t::NODE_INTEGER);
1600 2 : CATCH_REQUIRE(node->get_integer().get() == 0);
1601 2 : break;
1602 :
1603 1 : case as2js::node_t::NODE_TRUE:
1604 1 : CATCH_REQUIRE(node->to_number());
1605 1 : CATCH_REQUIRE(node->get_type() == as2js::node_t::NODE_INTEGER);
1606 1 : CATCH_REQUIRE(node->get_integer().get() == 1);
1607 1 : break;
1608 :
1609 1 : case as2js::node_t::NODE_STRING: // empty strings represent 0 here
1610 1 : CATCH_REQUIRE(node->to_number());
1611 1 : CATCH_REQUIRE(node->get_type() == as2js::node_t::NODE_FLOATING_POINT);
1612 : {
1613 : #pragma GCC diagnostic push
1614 : #pragma GCC diagnostic ignored "-Wfloat-equal"
1615 1 : bool const is_zero(node->get_floating_point().get() == 0.0);
1616 : #pragma GCC diagnostic pop
1617 1 : CATCH_REQUIRE(is_zero);
1618 : }
1619 1 : break;
1620 :
1621 1 : case as2js::node_t::NODE_UNDEFINED:
1622 : //std::cerr << " . type = " << static_cast<int>(original_type) << " / " << node->get_type_name() << "\n";
1623 1 : CATCH_REQUIRE(node->to_number());
1624 1 : CATCH_REQUIRE(node->get_type() == as2js::node_t::NODE_FLOATING_POINT);
1625 1 : CATCH_REQUIRE(node->get_floating_point().is_nan());
1626 1 : break;
1627 :
1628 179 : default:
1629 179 : CATCH_REQUIRE(!node->to_number());
1630 179 : CATCH_REQUIRE(node->get_type() == original_type);
1631 179 : break;
1632 :
1633 : }
1634 186 : }
1635 :
1636 : // a few types of nodes can be converted to a STRING
1637 : {
1638 186 : as2js::node::pointer_t node(std::make_shared<as2js::node>(original_type));
1639 : {
1640 186 : snapdev::ostream_to_buf<char> out(std::cerr);
1641 372 : as2js::node_lock lock(node);
1642 186 : CATCH_REQUIRE_THROWS_MATCHES(
1643 : node->to_string()
1644 : , as2js::locked_node
1645 : , Catch::Matchers::ExceptionMessage(
1646 : "as2js_exception: trying to modify a locked node."));
1647 186 : CATCH_REQUIRE(node->get_type() == original_type);
1648 186 : CATCH_REQUIRE(out.str().substr(0, 65) == "error: The following node is locked and thus cannot be modified:\n");
1649 186 : }
1650 186 : switch(original_type)
1651 : {
1652 5 : case as2js::node_t::NODE_STRING:
1653 : case as2js::node_t::NODE_TEMPLATE:
1654 : case as2js::node_t::NODE_TEMPLATE_HEAD:
1655 : case as2js::node_t::NODE_TEMPLATE_MIDDLE:
1656 : case as2js::node_t::NODE_TEMPLATE_TAIL:
1657 5 : CATCH_REQUIRE(node->to_string());
1658 5 : CATCH_REQUIRE(node->get_type() == as2js::node_t::NODE_STRING);
1659 5 : CATCH_REQUIRE(node->get_string() == "");
1660 5 : break;
1661 :
1662 2 : case as2js::node_t::NODE_FLOATING_POINT:
1663 : case as2js::node_t::NODE_INTEGER:
1664 : // by default numbers are zero; we have other tests
1665 : // to verify the conversion
1666 2 : CATCH_REQUIRE(node->to_string());
1667 2 : CATCH_REQUIRE(node->get_type() == as2js::node_t::NODE_STRING);
1668 2 : CATCH_REQUIRE(node->get_string() == "0");
1669 2 : break;
1670 :
1671 1 : case as2js::node_t::NODE_FALSE:
1672 1 : CATCH_REQUIRE(node->to_string());
1673 1 : CATCH_REQUIRE(node->get_type() == as2js::node_t::NODE_STRING);
1674 1 : CATCH_REQUIRE(node->get_string() == "false");
1675 1 : break;
1676 :
1677 1 : case as2js::node_t::NODE_TRUE:
1678 1 : CATCH_REQUIRE(node->to_string());
1679 1 : CATCH_REQUIRE(node->get_type() == as2js::node_t::NODE_STRING);
1680 1 : CATCH_REQUIRE(node->get_string() == "true");
1681 1 : break;
1682 :
1683 1 : case as2js::node_t::NODE_NULL:
1684 1 : CATCH_REQUIRE(node->to_string());
1685 1 : CATCH_REQUIRE(node->get_type() == as2js::node_t::NODE_STRING);
1686 1 : CATCH_REQUIRE(node->get_string() == "null");
1687 1 : break;
1688 :
1689 1 : case as2js::node_t::NODE_UNDEFINED:
1690 1 : CATCH_REQUIRE(node->to_string());
1691 1 : CATCH_REQUIRE(node->get_type() == as2js::node_t::NODE_STRING);
1692 1 : CATCH_REQUIRE(node->get_string() == "undefined");
1693 1 : break;
1694 :
1695 1 : case as2js::node_t::NODE_IDENTIFIER: // the string remains the same
1696 : //case as2js::node_t::NODE_VIDENTIFIER: // should the VIDENTIFIER be supported too?
1697 1 : CATCH_REQUIRE(node->to_string());
1698 1 : CATCH_REQUIRE(node->get_type() == as2js::node_t::NODE_STRING);
1699 1 : break;
1700 :
1701 174 : default:
1702 174 : CATCH_REQUIRE(!node->to_string());
1703 174 : CATCH_REQUIRE(node->get_type() == original_type);
1704 174 : break;
1705 :
1706 : }
1707 186 : }
1708 :
1709 : // a few types of nodes can be converted to an IDENTIFIER
1710 : {
1711 186 : as2js::node::pointer_t node(std::make_shared<as2js::node>(original_type));
1712 : {
1713 186 : snapdev::ostream_to_buf<char> out(std::cerr);
1714 372 : as2js::node_lock lock(node);
1715 186 : CATCH_REQUIRE_THROWS_MATCHES(
1716 : node->to_identifier()
1717 : , as2js::locked_node
1718 : , Catch::Matchers::ExceptionMessage(
1719 : "as2js_exception: trying to modify a locked node."));
1720 186 : CATCH_REQUIRE(node->get_type() == original_type);
1721 186 : CATCH_REQUIRE(out.str().substr(0, 65) == "error: The following node is locked and thus cannot be modified:\n");
1722 186 : }
1723 186 : switch(original_type)
1724 : {
1725 59 : case as2js::node_t::NODE_ADD:
1726 : case as2js::node_t::NODE_ALMOST_EQUAL:
1727 : case as2js::node_t::NODE_ASSIGNMENT:
1728 : case as2js::node_t::NODE_ASSIGNMENT_ADD:
1729 : case as2js::node_t::NODE_ASSIGNMENT_BITWISE_AND:
1730 : case as2js::node_t::NODE_ASSIGNMENT_BITWISE_OR:
1731 : case as2js::node_t::NODE_ASSIGNMENT_BITWISE_XOR:
1732 : case as2js::node_t::NODE_ASSIGNMENT_DIVIDE:
1733 : case as2js::node_t::NODE_ASSIGNMENT_LOGICAL_AND:
1734 : case as2js::node_t::NODE_ASSIGNMENT_LOGICAL_OR:
1735 : case as2js::node_t::NODE_ASSIGNMENT_LOGICAL_XOR:
1736 : case as2js::node_t::NODE_ASSIGNMENT_MAXIMUM:
1737 : case as2js::node_t::NODE_ASSIGNMENT_MINIMUM:
1738 : case as2js::node_t::NODE_ASSIGNMENT_MODULO:
1739 : case as2js::node_t::NODE_ASSIGNMENT_MULTIPLY:
1740 : case as2js::node_t::NODE_ASSIGNMENT_POWER:
1741 : case as2js::node_t::NODE_ASSIGNMENT_ROTATE_LEFT:
1742 : case as2js::node_t::NODE_ASSIGNMENT_ROTATE_RIGHT:
1743 : case as2js::node_t::NODE_ASSIGNMENT_SHIFT_LEFT:
1744 : case as2js::node_t::NODE_ASSIGNMENT_SHIFT_RIGHT:
1745 : case as2js::node_t::NODE_ASSIGNMENT_SHIFT_RIGHT_UNSIGNED:
1746 : case as2js::node_t::NODE_ASSIGNMENT_SUBTRACT:
1747 : case as2js::node_t::NODE_BITWISE_AND:
1748 : case as2js::node_t::NODE_BITWISE_NOT:
1749 : case as2js::node_t::NODE_BITWISE_OR:
1750 : case as2js::node_t::NODE_BITWISE_XOR:
1751 : case as2js::node_t::NODE_COMMA:
1752 : case as2js::node_t::NODE_COMPARE:
1753 : case as2js::node_t::NODE_DECREMENT:
1754 : case as2js::node_t::NODE_DIVIDE:
1755 : case as2js::node_t::NODE_EQUAL:
1756 : case as2js::node_t::NODE_GREATER:
1757 : case as2js::node_t::NODE_GREATER_EQUAL:
1758 : case as2js::node_t::NODE_INCREMENT:
1759 : case as2js::node_t::NODE_LESS:
1760 : case as2js::node_t::NODE_LESS_EQUAL:
1761 : case as2js::node_t::NODE_LOGICAL_AND:
1762 : case as2js::node_t::NODE_LOGICAL_NOT:
1763 : case as2js::node_t::NODE_LOGICAL_OR:
1764 : case as2js::node_t::NODE_LOGICAL_XOR:
1765 : case as2js::node_t::NODE_MATCH:
1766 : case as2js::node_t::NODE_MAXIMUM:
1767 : case as2js::node_t::NODE_MINIMUM:
1768 : case as2js::node_t::NODE_MODULO:
1769 : case as2js::node_t::NODE_MULTIPLY:
1770 : case as2js::node_t::NODE_NOT_EQUAL:
1771 : case as2js::node_t::NODE_NOT_MATCH:
1772 : case as2js::node_t::NODE_POST_DECREMENT:
1773 : case as2js::node_t::NODE_POST_INCREMENT:
1774 : case as2js::node_t::NODE_POWER:
1775 : case as2js::node_t::NODE_ROTATE_LEFT:
1776 : case as2js::node_t::NODE_ROTATE_RIGHT:
1777 : case as2js::node_t::NODE_SHIFT_LEFT:
1778 : case as2js::node_t::NODE_SHIFT_RIGHT:
1779 : case as2js::node_t::NODE_SHIFT_RIGHT_UNSIGNED:
1780 : case as2js::node_t::NODE_SMART_MATCH:
1781 : case as2js::node_t::NODE_STRICTLY_EQUAL:
1782 : case as2js::node_t::NODE_STRICTLY_NOT_EQUAL:
1783 : case as2js::node_t::NODE_SUBTRACT:
1784 59 : CATCH_REQUIRE(node->to_identifier());
1785 59 : CATCH_REQUIRE(node->get_type() == as2js::node_t::NODE_IDENTIFIER);
1786 59 : CATCH_REQUIRE(node->get_string() == as2js::node::operator_to_string(original_type));
1787 59 : break;
1788 :
1789 1 : case as2js::node_t::NODE_DELETE:
1790 1 : CATCH_REQUIRE(node->to_identifier());
1791 1 : CATCH_REQUIRE(node->get_type() == as2js::node_t::NODE_IDENTIFIER);
1792 1 : CATCH_REQUIRE(node->get_string() == "delete");
1793 1 : break;
1794 :
1795 2 : case as2js::node_t::NODE_IDENTIFIER:
1796 : case as2js::node_t::NODE_STRING:
1797 2 : CATCH_REQUIRE(node->to_identifier());
1798 2 : CATCH_REQUIRE(node->get_type() == as2js::node_t::NODE_IDENTIFIER);
1799 2 : CATCH_REQUIRE(node->get_string() == "");
1800 2 : break;
1801 :
1802 1 : case as2js::node_t::NODE_PRIVATE:
1803 1 : CATCH_REQUIRE(node->to_identifier());
1804 1 : CATCH_REQUIRE(node->get_type() == as2js::node_t::NODE_IDENTIFIER);
1805 1 : CATCH_REQUIRE(node->get_string() == "private");
1806 1 : break;
1807 :
1808 1 : case as2js::node_t::NODE_PROTECTED:
1809 1 : CATCH_REQUIRE(node->to_identifier());
1810 1 : CATCH_REQUIRE(node->get_type() == as2js::node_t::NODE_IDENTIFIER);
1811 1 : CATCH_REQUIRE(node->get_string() == "protected");
1812 1 : break;
1813 :
1814 1 : case as2js::node_t::NODE_PUBLIC:
1815 1 : CATCH_REQUIRE(node->to_identifier());
1816 1 : CATCH_REQUIRE(node->get_type() == as2js::node_t::NODE_IDENTIFIER);
1817 1 : CATCH_REQUIRE(node->get_string() == "public");
1818 1 : break;
1819 :
1820 121 : default:
1821 121 : if(node->to_identifier())
1822 : {
1823 0 : std::cerr << "--- it worked... for " << as2js::node::type_to_string(original_type) << "\n";
1824 : }
1825 121 : CATCH_REQUIRE(!node->to_identifier());
1826 121 : CATCH_REQUIRE(node->get_type() == original_type);
1827 121 : break;
1828 :
1829 : }
1830 186 : }
1831 :
1832 : // IDENTIFIER can be converted to VIDENTIFIER
1833 : {
1834 186 : as2js::node::pointer_t node(std::make_shared<as2js::node>(original_type));
1835 : {
1836 186 : snapdev::ostream_to_buf<char> out(std::cerr);
1837 372 : as2js::node_lock lock(node);
1838 186 : CATCH_REQUIRE_THROWS_MATCHES(
1839 : node->to_videntifier()
1840 : , as2js::locked_node
1841 : , Catch::Matchers::ExceptionMessage(
1842 : "as2js_exception: trying to modify a locked node."));
1843 186 : CATCH_REQUIRE(node->get_type() == original_type);
1844 186 : CATCH_REQUIRE(out.str().substr(0, 65) == "error: The following node is locked and thus cannot be modified:\n");
1845 186 : }
1846 186 : if(original_type == as2js::node_t::NODE_IDENTIFIER)
1847 : {
1848 : // in this case it works
1849 1 : node->to_videntifier();
1850 1 : CATCH_REQUIRE(node->get_type() == as2js::node_t::NODE_VIDENTIFIER);
1851 : }
1852 : else
1853 : {
1854 : // this one fails dramatically
1855 185 : CATCH_REQUIRE_THROWS_MATCHES(
1856 : node->to_videntifier()
1857 : , as2js::internal_error
1858 : , Catch::Matchers::ExceptionMessage(
1859 : "internal_error: to_videntifier() called with a node other than a \"NODE_IDENTIFIER\" node."));
1860 185 : CATCH_REQUIRE(node->get_type() == original_type);
1861 : }
1862 186 : }
1863 :
1864 : // VARIABLE can be converted to VAR_ATTRIBUTES
1865 : {
1866 186 : as2js::node::pointer_t node(std::make_shared<as2js::node>(original_type));
1867 : {
1868 186 : snapdev::ostream_to_buf<char> out(std::cerr);
1869 372 : as2js::node_lock lock(node);
1870 186 : CATCH_REQUIRE_THROWS_MATCHES(
1871 : node->to_var_attributes()
1872 : , as2js::locked_node
1873 : , Catch::Matchers::ExceptionMessage(
1874 : "as2js_exception: trying to modify a locked node."));
1875 186 : CATCH_REQUIRE(node->get_type() == original_type);
1876 186 : CATCH_REQUIRE(out.str().substr(0, 65) == "error: The following node is locked and thus cannot be modified:\n");
1877 186 : }
1878 186 : if(original_type == as2js::node_t::NODE_VARIABLE)
1879 : {
1880 : // in this case it works
1881 1 : node->to_var_attributes();
1882 1 : CATCH_REQUIRE(node->get_type() == as2js::node_t::NODE_VAR_ATTRIBUTES);
1883 : }
1884 : else
1885 : {
1886 : // in this case it fails
1887 185 : CATCH_REQUIRE_THROWS_MATCHES(
1888 : node->to_var_attributes()
1889 : , as2js::internal_error
1890 : , Catch::Matchers::ExceptionMessage(
1891 : "internal_error: to_var_attribute() called with a node other than a \"NODE_VARIABLE\" node."));
1892 185 : CATCH_REQUIRE(node->get_type() == original_type);
1893 : }
1894 186 : }
1895 : }
1896 : }
1897 3 : CATCH_END_SECTION()
1898 :
1899 3 : CATCH_START_SECTION("node_conversions: NULL value")
1900 : {
1901 1 : bool got_dot(false);
1902 101 : for(int i(0); i < 100; ++i)
1903 : {
1904 : // Integer to other types
1905 : {
1906 100 : as2js::integer j((static_cast<int64_t>(rand()) << 48)
1907 100 : ^ (static_cast<int64_t>(rand()) << 32)
1908 100 : ^ (static_cast<int64_t>(rand()) << 16)
1909 100 : ^ (static_cast<int64_t>(rand()) << 0));
1910 :
1911 : {
1912 100 : as2js::node::pointer_t node(std::make_shared<as2js::node>(as2js::node_t::NODE_INTEGER));
1913 100 : node->set_integer(j);
1914 100 : as2js::floating_point invalid;
1915 100 : CATCH_REQUIRE_THROWS_MATCHES(
1916 : node->set_floating_point(invalid)
1917 : , as2js::internal_error
1918 : , Catch::Matchers::ExceptionMessage(
1919 : "internal_error: set_floating_point() called with a non-floating point node type."));
1920 100 : CATCH_REQUIRE(node->get_type() == as2js::node_t::NODE_INTEGER);
1921 100 : CATCH_REQUIRE(node->to_integer());
1922 : // probably always true here; we had false in the loop prior
1923 100 : CATCH_REQUIRE(node->get_integer().get() == j.get());
1924 100 : }
1925 :
1926 : {
1927 100 : as2js::node::pointer_t node(std::make_shared<as2js::node>(as2js::node_t::NODE_INTEGER));
1928 100 : node->set_integer(j);
1929 100 : CATCH_REQUIRE(node->to_number());
1930 : // probably always true here; we had false in the loop prior
1931 100 : CATCH_REQUIRE(node->get_type() == as2js::node_t::NODE_INTEGER);
1932 100 : CATCH_REQUIRE(node->get_integer().get() == j.get());
1933 100 : }
1934 :
1935 : {
1936 100 : as2js::node::pointer_t node(std::make_shared<as2js::node>(as2js::node_t::NODE_INTEGER));
1937 100 : node->set_integer(j);
1938 100 : as2js::node_t bool_type(node->to_boolean_type_only());
1939 : // probably always true here; we had false in the loop prior
1940 100 : CATCH_REQUIRE(bool_type == (j.get() ? as2js::node_t::NODE_TRUE : as2js::node_t::NODE_FALSE));
1941 100 : }
1942 :
1943 : {
1944 100 : as2js::node::pointer_t node(std::make_shared<as2js::node>(as2js::node_t::NODE_INTEGER));
1945 100 : node->set_integer(j);
1946 100 : CATCH_REQUIRE(node->to_boolean());
1947 : // probably always true here; we had false in the loop prior
1948 100 : CATCH_REQUIRE(node->get_type() == (j.get() ? as2js::node_t::NODE_TRUE : as2js::node_t::NODE_FALSE));
1949 100 : }
1950 :
1951 : {
1952 100 : as2js::node::pointer_t node(std::make_shared<as2js::node>(as2js::node_t::NODE_INTEGER));
1953 100 : node->set_integer(j);
1954 100 : CATCH_REQUIRE(node->to_floating_point());
1955 : // probably always true here; we had false in the loop prior
1956 100 : CATCH_REQUIRE(node->get_type() == as2js::node_t::NODE_FLOATING_POINT);
1957 100 : as2js::floating_point flt(j.get());
1958 100 : CATCH_REQUIRE(node->get_floating_point().nearly_equal(flt, 0.0001));
1959 100 : }
1960 :
1961 : {
1962 100 : as2js::node::pointer_t node(std::make_shared<as2js::node>(as2js::node_t::NODE_INTEGER));
1963 100 : node->set_integer(j);
1964 100 : CATCH_REQUIRE(node->to_string());
1965 : // probably always true here; we had false in the loop prior
1966 100 : CATCH_REQUIRE(node->get_type() == as2js::node_t::NODE_STRING);
1967 100 : CATCH_REQUIRE(node->get_string() == std::string(std::to_string(j.get())));
1968 100 : }
1969 : }
1970 :
1971 : // Floating point to other values
1972 100 : bool first(true);
1973 : do
1974 : {
1975 : // generate a random 64 bit number
1976 : //
1977 142 : double s1(rand() & 1 ? -1 : 1);
1978 142 : double n1(static_cast<double>((static_cast<int64_t>(rand()) << 48)
1979 142 : ^ (static_cast<int64_t>(rand()) << 32)
1980 142 : ^ (static_cast<int64_t>(rand()) << 16)
1981 142 : ^ (static_cast<int64_t>(rand()) << 0)));
1982 142 : double d1(static_cast<double>((static_cast<int64_t>(rand()) << 48)
1983 142 : ^ (static_cast<int64_t>(rand()) << 32)
1984 142 : ^ (static_cast<int64_t>(rand()) << 16)
1985 142 : ^ (static_cast<int64_t>(rand()) << 0)));
1986 142 : if(!first && n1 >= d1)
1987 : {
1988 : // the dot is easier to reach with very small numbers
1989 : // so create a small number immediately
1990 16 : std::swap(n1, d1);
1991 16 : d1 *= 1e+4;
1992 : }
1993 142 : double r(n1 / d1 * s1);
1994 142 : as2js::floating_point j(r);
1995 :
1996 : {
1997 142 : as2js::node::pointer_t node(std::make_shared<as2js::node>(as2js::node_t::NODE_FLOATING_POINT));
1998 142 : node->set_floating_point(j);
1999 142 : CATCH_REQUIRE(node->to_integer());
2000 142 : CATCH_REQUIRE(node->get_integer().get() == static_cast<as2js::integer::value_type>(j.get()));
2001 142 : }
2002 :
2003 : {
2004 142 : as2js::node::pointer_t node(std::make_shared<as2js::node>(as2js::node_t::NODE_FLOATING_POINT));
2005 142 : node->set_floating_point(j);
2006 142 : CATCH_REQUIRE(node->to_number());
2007 142 : CATCH_REQUIRE(node->get_type() == as2js::node_t::NODE_FLOATING_POINT);
2008 : {
2009 : #pragma GCC diagnostic push
2010 : #pragma GCC diagnostic ignored "-Wfloat-equal"
2011 142 : bool const is_equal(node->get_floating_point().get() == j.get());
2012 : #pragma GCC diagnostic pop
2013 142 : CATCH_REQUIRE(is_equal);
2014 : }
2015 142 : }
2016 :
2017 : {
2018 142 : as2js::node::pointer_t node(std::make_shared<as2js::node>(as2js::node_t::NODE_FLOATING_POINT));
2019 142 : node->set_floating_point(j);
2020 142 : as2js::node_t bool_type(node->to_boolean_type_only());
2021 : // probably always true here; we had false in the loop prior
2022 : #pragma GCC diagnostic push
2023 : #pragma GCC diagnostic ignored "-Wfloat-equal"
2024 142 : bool const is_zero(j.get() == 0.0);
2025 : #pragma GCC diagnostic pop
2026 142 : CATCH_REQUIRE(bool_type == (is_zero ? as2js::node_t::NODE_FALSE : as2js::node_t::NODE_TRUE));
2027 142 : }
2028 :
2029 : {
2030 142 : as2js::node::pointer_t node(std::make_shared<as2js::node>(as2js::node_t::NODE_FLOATING_POINT));
2031 142 : node->set_floating_point(j);
2032 142 : CATCH_REQUIRE(node->to_boolean());
2033 : // probably always true here; we had false in the loop prior
2034 : #pragma GCC diagnostic push
2035 : #pragma GCC diagnostic ignored "-Wfloat-equal"
2036 142 : bool const is_zero(j.get() == 0.0);
2037 : #pragma GCC diagnostic pop
2038 142 : CATCH_REQUIRE(node->get_type() == (is_zero ? as2js::node_t::NODE_FALSE : as2js::node_t::NODE_TRUE));
2039 :
2040 : // also test the set_boolean() with valid values
2041 142 : node->set_boolean(true);
2042 142 : CATCH_REQUIRE(node->get_type() == as2js::node_t::NODE_TRUE);
2043 142 : node->set_boolean(false);
2044 142 : CATCH_REQUIRE(node->get_type() == as2js::node_t::NODE_FALSE);
2045 142 : }
2046 :
2047 : {
2048 142 : as2js::node::pointer_t node(std::make_shared<as2js::node>(as2js::node_t::NODE_FLOATING_POINT));
2049 142 : node->set_floating_point(j);
2050 142 : CATCH_REQUIRE(node->to_floating_point());
2051 142 : CATCH_REQUIRE(node->get_type() == as2js::node_t::NODE_FLOATING_POINT);
2052 : #pragma GCC diagnostic push
2053 : #pragma GCC diagnostic ignored "-Wfloat-equal"
2054 142 : bool const is_equal(node->get_floating_point().get() == j.get());
2055 : #pragma GCC diagnostic pop
2056 142 : CATCH_REQUIRE(is_equal);
2057 142 : }
2058 :
2059 : {
2060 142 : as2js::node::pointer_t node(std::make_shared<as2js::node>(as2js::node_t::NODE_FLOATING_POINT));
2061 142 : node->set_floating_point(j);
2062 142 : CATCH_REQUIRE(node->to_string());
2063 142 : CATCH_REQUIRE(node->get_type() == as2js::node_t::NODE_STRING);
2064 142 : std::string str(std::string(std::to_string(j.get())));
2065 142 : if(str.find('.') != std::string::npos)
2066 : {
2067 : // remove all least significant zeroes if any
2068 160 : while(str.back() == '0')
2069 : {
2070 18 : str.pop_back();
2071 : }
2072 : // make sure the number does not end with a period
2073 142 : if(str.back() == '.')
2074 : {
2075 1 : str.pop_back();
2076 1 : got_dot = true;
2077 : }
2078 : }
2079 142 : CATCH_REQUIRE(node->get_string() == str);
2080 142 : }
2081 142 : first = false;
2082 : }
2083 142 : while(!got_dot);
2084 : }
2085 : }
2086 3 : CATCH_END_SECTION()
2087 :
2088 3 : CATCH_START_SECTION("node_conversions: special floating point values")
2089 : {
2090 : // verify special floating point values
2091 : //
2092 : { // NaN -> string
2093 1 : as2js::floating_point j;
2094 1 : as2js::node::pointer_t node(std::make_shared<as2js::node>(as2js::node_t::NODE_FLOATING_POINT));
2095 1 : j.set_nan();
2096 1 : node->set_floating_point(j);
2097 1 : CATCH_REQUIRE(node->to_string());
2098 1 : CATCH_REQUIRE(node->get_type() == as2js::node_t::NODE_STRING);
2099 1 : CATCH_REQUIRE(node->get_string() == "NaN");
2100 1 : }
2101 : { // NaN -> integer
2102 1 : as2js::floating_point j;
2103 1 : as2js::node::pointer_t node(std::make_shared<as2js::node>(as2js::node_t::NODE_FLOATING_POINT));
2104 1 : j.set_nan();
2105 1 : node->set_floating_point(j);
2106 1 : CATCH_REQUIRE(node->to_integer());
2107 1 : CATCH_REQUIRE(node->get_type() == as2js::node_t::NODE_INTEGER);
2108 1 : CATCH_REQUIRE(node->get_integer().get() == 0);
2109 1 : }
2110 : { // +Infinity
2111 1 : as2js::floating_point j;
2112 1 : as2js::node::pointer_t node(std::make_shared<as2js::node>(as2js::node_t::NODE_FLOATING_POINT));
2113 1 : j.set_infinity();
2114 1 : node->set_floating_point(j);
2115 1 : CATCH_REQUIRE(node->to_string());
2116 1 : CATCH_REQUIRE(node->get_type() == as2js::node_t::NODE_STRING);
2117 1 : CATCH_REQUIRE(node->get_string() == "Infinity");
2118 1 : }
2119 : { // +Infinity
2120 1 : as2js::floating_point j;
2121 1 : as2js::node::pointer_t node(std::make_shared<as2js::node>(as2js::node_t::NODE_FLOATING_POINT));
2122 1 : j.set_infinity();
2123 1 : node->set_floating_point(j);
2124 1 : CATCH_REQUIRE(node->to_integer());
2125 1 : CATCH_REQUIRE(node->get_type() == as2js::node_t::NODE_INTEGER);
2126 1 : CATCH_REQUIRE(node->get_integer().get() == 0);
2127 1 : }
2128 : { // -Infinity
2129 1 : as2js::floating_point j;
2130 1 : as2js::node::pointer_t node(std::make_shared<as2js::node>(as2js::node_t::NODE_FLOATING_POINT));
2131 1 : j.set_infinity();
2132 1 : j.set(-j.get());
2133 1 : node->set_floating_point(j);
2134 1 : CATCH_REQUIRE(node->to_string());
2135 1 : CATCH_REQUIRE(node->get_type() == as2js::node_t::NODE_STRING);
2136 1 : CATCH_REQUIRE(node->get_string() == "-Infinity");
2137 1 : }
2138 : { // +Infinity
2139 1 : as2js::floating_point j;
2140 1 : as2js::node::pointer_t node(std::make_shared<as2js::node>(as2js::node_t::NODE_FLOATING_POINT));
2141 1 : j.set_infinity();
2142 1 : j.set(-j.get());
2143 1 : node->set_floating_point(j);
2144 1 : CATCH_REQUIRE(node->to_integer());
2145 1 : CATCH_REQUIRE(node->get_type() == as2js::node_t::NODE_INTEGER);
2146 1 : CATCH_REQUIRE(node->get_integer().get() == 0);
2147 1 : }
2148 : }
2149 3 : CATCH_END_SECTION()
2150 3 : }
2151 :
2152 :
2153 4 : CATCH_TEST_CASE("node_tree", "[node][tree]")
2154 : {
2155 : class tracked_node
2156 : : public as2js::node
2157 : {
2158 : public:
2159 34814 : tracked_node(as2js::node_t type, int & count)
2160 34814 : : node(type)
2161 34814 : , f_count(count)
2162 : {
2163 34814 : ++f_count;
2164 34814 : }
2165 :
2166 34814 : virtual ~tracked_node()
2167 34814 : {
2168 34814 : --f_count;
2169 34814 : }
2170 :
2171 : private:
2172 : int & f_count;
2173 : };
2174 :
2175 : // a few basic tests
2176 4 : CATCH_START_SECTION("node_tree: basics")
2177 : {
2178 : // counter to know how many nodes we currently have allocated
2179 : //
2180 1 : int counter(0);
2181 :
2182 : {
2183 2 : as2js::node::pointer_t parent(std::make_shared<tracked_node>(as2js::node_t::NODE_DIRECTIVE_LIST, counter));
2184 :
2185 1 : CATCH_REQUIRE_THROWS_MATCHES(
2186 : parent->get_child(-1)
2187 : , as2js::out_of_range
2188 : , Catch::Matchers::ExceptionMessage(
2189 : "out_of_range: get_child(): index is too large for the number of children available."));
2190 1 : CATCH_REQUIRE_THROWS_MATCHES(
2191 : parent->get_child(0)
2192 : , as2js::out_of_range
2193 : , Catch::Matchers::ExceptionMessage(
2194 : "out_of_range: get_child(): index is too large for the number of children available."));
2195 1 : CATCH_REQUIRE_THROWS_MATCHES(
2196 : parent->get_child(1)
2197 : , as2js::out_of_range
2198 : , Catch::Matchers::ExceptionMessage(
2199 : "out_of_range: get_child(): index is too large for the number of children available."));
2200 :
2201 : // now we properly test whether the append_child(),
2202 : // insert_child(), and set_child() functions are used
2203 : // with a null pointer (which is considered illegal)
2204 1 : as2js::node::pointer_t null_pointer;
2205 3 : CATCH_REQUIRE_THROWS_MATCHES(
2206 : parent->append_child(null_pointer)
2207 : , as2js::invalid_data
2208 : , Catch::Matchers::ExceptionMessage(
2209 : "as2js_exception: cannot append a child if its pointer is null."));
2210 3 : CATCH_REQUIRE_THROWS_MATCHES(
2211 : parent->insert_child(123, null_pointer)
2212 : , as2js::invalid_data
2213 : , Catch::Matchers::ExceptionMessage(
2214 : "as2js_exception: cannot insert a child if its pointer is null."));
2215 3 : CATCH_REQUIRE_THROWS_MATCHES(
2216 : parent->set_child(9, null_pointer)
2217 : , as2js::invalid_data
2218 : , Catch::Matchers::ExceptionMessage(
2219 : "as2js_exception: cannot set a child if its pointer is null."));
2220 :
2221 21 : for(int i(0); i < 20; ++i)
2222 : {
2223 40 : as2js::node::pointer_t child(std::make_shared<tracked_node>(as2js::node_t::NODE_DIRECTIVE_LIST, counter));
2224 20 : parent->append_child(child);
2225 :
2226 20 : CATCH_REQUIRE_THROWS_MATCHES(
2227 : parent->get_child(-1)
2228 : , as2js::out_of_range
2229 : , Catch::Matchers::ExceptionMessage(
2230 : "out_of_range: get_child(): index is too large for the number of children available."));
2231 230 : for(int j(0); j <= i; ++j)
2232 : {
2233 210 : as2js::node::pointer_t c(parent->get_child(j));
2234 210 : CATCH_REQUIRE(c != nullptr);
2235 210 : if(i == j)
2236 : {
2237 20 : CATCH_REQUIRE(c == child);
2238 : }
2239 :
2240 : // set_parent() with -1 does nothing when the parent
2241 : // of the child is the same
2242 : //
2243 210 : child->set_parent(parent, -1);
2244 210 : }
2245 20 : CATCH_REQUIRE_THROWS_MATCHES(
2246 : parent->get_child(i + 1)
2247 : , as2js::out_of_range
2248 : , Catch::Matchers::ExceptionMessage(
2249 : "out_of_range: get_child(): index is too large for the number of children available."));
2250 20 : CATCH_REQUIRE_THROWS_MATCHES(
2251 : parent->get_child(i + 2)
2252 : , as2js::out_of_range
2253 : , Catch::Matchers::ExceptionMessage(
2254 : "out_of_range: get_child(): index is too large for the number of children available."));
2255 20 : }
2256 1 : }
2257 :
2258 : // did we deleted as many nodes as we created?
2259 : //
2260 1 : CATCH_REQUIRE(counter == 0);
2261 : }
2262 4 : CATCH_END_SECTION()
2263 :
2264 4 : CATCH_START_SECTION("node_tree: parent/child of any type")
2265 : {
2266 : // counter to know how many nodes we currently have allocated
2267 : //
2268 1 : int counter(0);
2269 :
2270 : // first test: try with all types as the parent and children
2271 187 : for(size_t i(0); i < g_node_types_size; ++i)
2272 : {
2273 : // type
2274 186 : as2js::node_t parent_type(g_node_types[i].f_type);
2275 :
2276 372 : as2js::node::pointer_t parent(std::make_shared<tracked_node>(parent_type, counter));
2277 186 : CATCH_REQUIRE(parent->get_children_size() == 0);
2278 :
2279 186 : size_t valid_children(0);
2280 34782 : for(size_t j(0); j < g_node_types_size; ++j)
2281 : {
2282 34596 : as2js::node_t child_type(g_node_types[j].f_type);
2283 :
2284 69192 : as2js::node::pointer_t child(std::make_shared<tracked_node>(child_type, counter));
2285 :
2286 : //std::cerr << "parent " << parent->get_type_name() << " child " << child->get_type_name() << "\n";
2287 : // some nodes cannot be parents...
2288 34596 : switch(parent_type)
2289 : {
2290 10230 : case as2js::node_t::NODE_ABSTRACT:
2291 : case as2js::node_t::NODE_ASYNC:
2292 : case as2js::node_t::NODE_AUTO:
2293 : case as2js::node_t::NODE_AWAIT:
2294 : case as2js::node_t::NODE_BOOLEAN:
2295 : case as2js::node_t::NODE_BREAK:
2296 : case as2js::node_t::NODE_BYTE:
2297 : case as2js::node_t::NODE_CLOSE_CURVLY_BRACKET:
2298 : case as2js::node_t::NODE_CLOSE_PARENTHESIS:
2299 : case as2js::node_t::NODE_CLOSE_SQUARE_BRACKET:
2300 : case as2js::node_t::NODE_CHAR:
2301 : case as2js::node_t::NODE_COLON:
2302 : case as2js::node_t::NODE_COMMA:
2303 : case as2js::node_t::NODE_CONST:
2304 : case as2js::node_t::NODE_CONTINUE:
2305 : case as2js::node_t::NODE_DEFAULT:
2306 : case as2js::node_t::NODE_DOUBLE:
2307 : case as2js::node_t::NODE_ELSE:
2308 : case as2js::node_t::NODE_THEN:
2309 : case as2js::node_t::NODE_EMPTY:
2310 : case as2js::node_t::NODE_EOF:
2311 : case as2js::node_t::NODE_IDENTIFIER:
2312 : case as2js::node_t::NODE_INLINE:
2313 : case as2js::node_t::NODE_INTEGER:
2314 : case as2js::node_t::NODE_FALSE:
2315 : case as2js::node_t::NODE_FINAL:
2316 : case as2js::node_t::NODE_FLOAT:
2317 : case as2js::node_t::NODE_FLOATING_POINT:
2318 : case as2js::node_t::NODE_GOTO:
2319 : case as2js::node_t::NODE_LONG:
2320 : case as2js::node_t::NODE_NATIVE:
2321 : case as2js::node_t::NODE_NULL:
2322 : case as2js::node_t::NODE_OPEN_CURVLY_BRACKET:
2323 : case as2js::node_t::NODE_OPEN_PARENTHESIS:
2324 : case as2js::node_t::NODE_OPEN_SQUARE_BRACKET:
2325 : case as2js::node_t::NODE_PRIVATE:
2326 : case as2js::node_t::NODE_PROTECTED:
2327 : case as2js::node_t::NODE_PUBLIC:
2328 : case as2js::node_t::NODE_REGULAR_EXPRESSION:
2329 : case as2js::node_t::NODE_REST:
2330 : case as2js::node_t::NODE_SEMICOLON:
2331 : case as2js::node_t::NODE_SHORT:
2332 : case as2js::node_t::NODE_STRING:
2333 : case as2js::node_t::NODE_STATIC:
2334 : case as2js::node_t::NODE_TEMPLATE:
2335 : case as2js::node_t::NODE_TEMPLATE_HEAD:
2336 : case as2js::node_t::NODE_TEMPLATE_MIDDLE:
2337 : case as2js::node_t::NODE_TEMPLATE_TAIL:
2338 : case as2js::node_t::NODE_THIS:
2339 : case as2js::node_t::NODE_TRANSIENT:
2340 : case as2js::node_t::NODE_TRUE:
2341 : case as2js::node_t::NODE_UNDEFINED:
2342 : case as2js::node_t::NODE_VIDENTIFIER:
2343 : case as2js::node_t::NODE_VOID:
2344 : case as2js::node_t::NODE_VOLATILE:
2345 : // append child to parent must fail
2346 10230 : if(rand() & 1)
2347 : {
2348 15243 : CATCH_REQUIRE_THROWS_MATCHES(
2349 : parent->append_child(child)
2350 : , as2js::incompatible_type
2351 : , Catch::Matchers::ExceptionMessage(
2352 : "as2js_exception: invalid type: \""
2353 : + std::string(parent->get_type_name())
2354 : + "\" used as a parent node of child with type: \""
2355 : + std::string(child->get_type_name())
2356 : + "\"."));
2357 : }
2358 : else
2359 : {
2360 15447 : CATCH_REQUIRE_THROWS_MATCHES(
2361 : child->set_parent(parent)
2362 : , as2js::incompatible_type
2363 : , Catch::Matchers::ExceptionMessage(
2364 : "as2js_exception: invalid type: \""
2365 : + std::string(parent->get_type_name())
2366 : + "\" used as a parent node of child with type: \""
2367 : + std::string(child->get_type_name())
2368 : + "\"."));
2369 : }
2370 10230 : break;
2371 :
2372 24366 : default:
2373 24366 : switch(child_type)
2374 : {
2375 1703 : case as2js::node_t::NODE_CLOSE_CURVLY_BRACKET:
2376 : case as2js::node_t::NODE_CLOSE_PARENTHESIS:
2377 : case as2js::node_t::NODE_CLOSE_SQUARE_BRACKET:
2378 : case as2js::node_t::NODE_COLON:
2379 : case as2js::node_t::NODE_COMMA:
2380 : case as2js::node_t::NODE_ELSE:
2381 : case as2js::node_t::NODE_THEN:
2382 : case as2js::node_t::NODE_EOF:
2383 : case as2js::node_t::NODE_OPEN_CURVLY_BRACKET:
2384 : case as2js::node_t::NODE_OPEN_PARENTHESIS:
2385 : case as2js::node_t::NODE_OPEN_SQUARE_BRACKET:
2386 : case as2js::node_t::NODE_ROOT:
2387 : case as2js::node_t::NODE_SEMICOLON:
2388 : // append child to parent must fail
2389 1703 : if(rand() & 1)
2390 : {
2391 2658 : CATCH_REQUIRE_THROWS_MATCHES(
2392 : parent->append_child(child)
2393 : , as2js::incompatible_type
2394 : , Catch::Matchers::ExceptionMessage(
2395 : "as2js_exception: invalid type: \""
2396 : + std::string(child->get_type_name())
2397 : + "\" used as a child node of parent type: \""
2398 : + parent->get_type_name()
2399 : + "\"."));
2400 : }
2401 : else
2402 : {
2403 2451 : CATCH_REQUIRE_THROWS_MATCHES(
2404 : child->set_parent(parent)
2405 : , as2js::incompatible_type
2406 : , Catch::Matchers::ExceptionMessage(
2407 : "as2js_exception: invalid type: \""
2408 : + std::string(child->get_type_name())
2409 : + "\" used as a child node of parent type: \""
2410 : + parent->get_type_name()
2411 : + "\"."));
2412 : }
2413 1703 : break;
2414 :
2415 22663 : default:
2416 : // append child to parent
2417 22663 : if(rand() & 1)
2418 : {
2419 11376 : parent->append_child(child);
2420 : }
2421 : else
2422 : {
2423 11287 : child->set_parent(parent);
2424 : }
2425 :
2426 22663 : CATCH_REQUIRE(parent->get_children_size() == valid_children + 1);
2427 22663 : CATCH_REQUIRE(child->get_parent() == parent);
2428 22663 : CATCH_REQUIRE(child->get_offset() == valid_children);
2429 22663 : CATCH_REQUIRE(parent->get_child(valid_children) == child);
2430 22663 : CATCH_REQUIRE(parent->find_first_child(child_type) == child);
2431 22663 : CATCH_REQUIRE(!parent->find_next_child(child, child_type));
2432 :
2433 22663 : ++valid_children;
2434 22663 : break;
2435 :
2436 : }
2437 24366 : break;
2438 :
2439 : }
2440 34596 : }
2441 186 : }
2442 :
2443 : // did we deleted as many nodes as we created?
2444 : //
2445 1 : CATCH_REQUIRE(counter == 0);
2446 : }
2447 4 : CATCH_END_SECTION()
2448 :
2449 : // Test a more realistic tree with a few nodes and make sure we
2450 : // can apply certain function and that the tree exactly results
2451 : // in what we expect
2452 4 : CATCH_START_SECTION("node_tree: realistic tree")
2453 : {
2454 : // counter to know how many nodes we currently have allocated
2455 : //
2456 1 : int counter(0);
2457 :
2458 : {
2459 : // 1. Create the following in directive a:
2460 : //
2461 : // // first block (directive_a)
2462 : // {
2463 : // a = Math.e ** 1.424;
2464 : // }
2465 : // // second block (directive_b)
2466 : // {
2467 : // }
2468 : //
2469 : // 2. Move it to directive b
2470 : //
2471 : // // first block (directive_a)
2472 : // {
2473 : // }
2474 : // // second block (directive_b)
2475 : // {
2476 : // a = Math.e ** 1.424;
2477 : // }
2478 : //
2479 : // 3. Verify that it worked
2480 : //
2481 :
2482 : // create all the nodes as the lexer would do
2483 2 : as2js::node::pointer_t root(std::make_shared<tracked_node>(as2js::node_t::NODE_ROOT, counter));
2484 1 : as2js::position pos;
2485 1 : pos.reset_counters(22);
2486 1 : pos.set_filename("test.js");
2487 1 : root->set_position(pos);
2488 2 : as2js::node::pointer_t directive_list_a(std::make_shared<tracked_node>(as2js::node_t::NODE_DIRECTIVE_LIST, counter));
2489 2 : as2js::node::pointer_t directive_list_b(std::make_shared<tracked_node>(as2js::node_t::NODE_DIRECTIVE_LIST, counter));
2490 2 : as2js::node::pointer_t assignment(std::make_shared<tracked_node>(as2js::node_t::NODE_ASSIGNMENT, counter));
2491 2 : as2js::node::pointer_t identifier_a(std::make_shared<tracked_node>(as2js::node_t::NODE_IDENTIFIER, counter));
2492 1 : identifier_a->set_string("a");
2493 2 : as2js::node::pointer_t power(std::make_shared<tracked_node>(as2js::node_t::NODE_POWER, counter));
2494 2 : as2js::node::pointer_t member(std::make_shared<tracked_node>(as2js::node_t::NODE_MEMBER, counter));
2495 2 : as2js::node::pointer_t identifier_math(std::make_shared<tracked_node>(as2js::node_t::NODE_IDENTIFIER, counter));
2496 1 : identifier_math->set_string("Math");
2497 2 : as2js::node::pointer_t identifier_e(std::make_shared<tracked_node>(as2js::node_t::NODE_IDENTIFIER, counter));
2498 1 : identifier_e->set_string("e");
2499 2 : as2js::node::pointer_t literal(std::make_shared<tracked_node>(as2js::node_t::NODE_FLOATING_POINT, counter));
2500 1 : as2js::floating_point f;
2501 1 : f.set(1.424);
2502 1 : literal->set_floating_point(f);
2503 :
2504 : // build the tree as the parser would do
2505 1 : root->append_child(directive_list_a);
2506 1 : root->append_child(directive_list_b);
2507 1 : directive_list_a->append_child(assignment);
2508 1 : assignment->append_child(identifier_a);
2509 1 : assignment->insert_child(-1, power);
2510 1 : power->append_child(member);
2511 3 : CATCH_REQUIRE_THROWS_MATCHES(
2512 : power->insert_child(10, literal)
2513 : , as2js::out_of_range
2514 : , Catch::Matchers::ExceptionMessage(
2515 : "out_of_range: trying to insert a node at index 10 which is larger than 1."));
2516 1 : power->insert_child(1, literal);
2517 1 : member->append_child(identifier_e);
2518 1 : member->insert_child(0, identifier_math);
2519 :
2520 : // verify we can unlock mid-way
2521 2 : as2js::node_lock temp_lock(member);
2522 1 : CATCH_REQUIRE(member->is_locked());
2523 1 : temp_lock.unlock();
2524 1 : CATCH_REQUIRE(!member->is_locked());
2525 :
2526 : // as a complement to testing the lock, make sure that emptiness
2527 : // (i.e. null pointer) is properly handled all the way
2528 : {
2529 1 : as2js::node::pointer_t empty;
2530 2 : as2js::node_lock empty_lock(empty);
2531 1 : }
2532 : {
2533 1 : as2js::node::pointer_t empty;
2534 2 : as2js::node_lock empty_lock(empty);
2535 1 : empty_lock.unlock();
2536 1 : }
2537 :
2538 : // apply some tests
2539 1 : CATCH_REQUIRE(root->get_children_size() == 2);
2540 1 : CATCH_REQUIRE(directive_list_a->get_children_size() == 1);
2541 1 : CATCH_REQUIRE(directive_list_a->get_child(0) == assignment);
2542 1 : CATCH_REQUIRE(directive_list_b->get_children_size() == 0);
2543 1 : CATCH_REQUIRE(assignment->get_children_size() == 2);
2544 1 : CATCH_REQUIRE(assignment->get_child(0) == identifier_a);
2545 1 : CATCH_REQUIRE(assignment->get_child(1) == power);
2546 1 : CATCH_REQUIRE(identifier_a->get_children_size() == 0);
2547 1 : CATCH_REQUIRE(power->get_children_size() == 2);
2548 1 : CATCH_REQUIRE(power->get_child(0) == member);
2549 1 : CATCH_REQUIRE(power->get_child(1) == literal);
2550 1 : CATCH_REQUIRE(member->get_children_size() == 2);
2551 1 : CATCH_REQUIRE(member->get_child(0) == identifier_math);
2552 1 : CATCH_REQUIRE(member->get_child(1) == identifier_e);
2553 1 : CATCH_REQUIRE(identifier_math->get_children_size() == 0);
2554 1 : CATCH_REQUIRE(identifier_e->get_children_size() == 0);
2555 1 : CATCH_REQUIRE(literal->get_children_size() == 0);
2556 :
2557 1 : CATCH_REQUIRE(root->has_side_effects());
2558 1 : CATCH_REQUIRE(directive_list_a->has_side_effects());
2559 1 : CATCH_REQUIRE(!directive_list_b->has_side_effects());
2560 1 : CATCH_REQUIRE(!power->has_side_effects());
2561 :
2562 : // now move the assignment from a to b
2563 1 : assignment->set_parent(directive_list_b);
2564 :
2565 1 : CATCH_REQUIRE(root->get_children_size() == 2);
2566 1 : CATCH_REQUIRE(directive_list_a->get_children_size() == 0);
2567 1 : CATCH_REQUIRE(directive_list_b->get_children_size() == 1);
2568 1 : CATCH_REQUIRE(directive_list_b->get_child(0) == assignment);
2569 1 : CATCH_REQUIRE(assignment->get_children_size() == 2);
2570 1 : CATCH_REQUIRE(assignment->get_child(0) == identifier_a);
2571 1 : CATCH_REQUIRE(assignment->get_child(1) == power);
2572 1 : CATCH_REQUIRE(identifier_a->get_children_size() == 0);
2573 1 : CATCH_REQUIRE(power->get_children_size() == 2);
2574 1 : CATCH_REQUIRE(power->get_child(0) == member);
2575 1 : CATCH_REQUIRE(power->get_child(1) == literal);
2576 1 : CATCH_REQUIRE(member->get_children_size() == 2);
2577 1 : CATCH_REQUIRE(member->get_child(0) == identifier_math);
2578 1 : CATCH_REQUIRE(member->get_child(1) == identifier_e);
2579 1 : CATCH_REQUIRE(identifier_math->get_children_size() == 0);
2580 1 : CATCH_REQUIRE(identifier_e->get_children_size() == 0);
2581 1 : CATCH_REQUIRE(literal->get_children_size() == 0);
2582 :
2583 1 : power->delete_child(0);
2584 1 : CATCH_REQUIRE(power->get_children_size() == 1);
2585 1 : CATCH_REQUIRE(power->get_child(0) == literal);
2586 :
2587 1 : power->insert_child(0, member);
2588 1 : CATCH_REQUIRE(power->get_children_size() == 2);
2589 1 : CATCH_REQUIRE(power->get_child(0) == member);
2590 1 : CATCH_REQUIRE(power->get_child(1) == literal);
2591 :
2592 1 : CATCH_REQUIRE(root->has_side_effects());
2593 1 : CATCH_REQUIRE(!directive_list_a->has_side_effects());
2594 1 : CATCH_REQUIRE(directive_list_b->has_side_effects());
2595 1 : CATCH_REQUIRE(!power->has_side_effects());
2596 :
2597 : // create a new literal
2598 2 : as2js::node::pointer_t literal_seven(std::make_shared<tracked_node>(as2js::node_t::NODE_FLOATING_POINT, counter));
2599 1 : as2js::floating_point f7;
2600 1 : f7.set(-7.33312);
2601 1 : literal_seven->set_floating_point(f7);
2602 1 : directive_list_a->append_child(literal_seven);
2603 1 : CATCH_REQUIRE(directive_list_a->get_children_size() == 1);
2604 1 : CATCH_REQUIRE(directive_list_a->get_child(0) == literal_seven);
2605 :
2606 : // now replace the old literal with the new one (i.e. a full move actually)
2607 1 : power->set_child(1, literal_seven);
2608 1 : CATCH_REQUIRE(power->get_children_size() == 2);
2609 1 : CATCH_REQUIRE(power->get_child(0) == member);
2610 1 : CATCH_REQUIRE(power->get_child(1) == literal_seven);
2611 :
2612 : // replace with itself should work just fine
2613 1 : power->set_child(0, member);
2614 1 : CATCH_REQUIRE(power->get_children_size() == 2);
2615 1 : CATCH_REQUIRE(power->get_child(0) == member);
2616 1 : CATCH_REQUIRE(power->get_child(1) == literal_seven);
2617 :
2618 : // verify that a replace fails if the node pointer is null
2619 1 : as2js::node::pointer_t null_pointer;
2620 3 : CATCH_REQUIRE_THROWS_MATCHES(
2621 : literal_seven->replace_with(null_pointer)
2622 : , as2js::invalid_data
2623 : , Catch::Matchers::ExceptionMessage(
2624 : "as2js_exception: cannot replace with a node if its pointer is null."));
2625 :
2626 : // replace with the old literal
2627 1 : literal_seven->replace_with(literal);
2628 1 : CATCH_REQUIRE(power->get_children_size() == 2);
2629 1 : CATCH_REQUIRE(power->get_child(0) == member);
2630 1 : CATCH_REQUIRE(power->get_child(1) == literal);
2631 :
2632 : // verify that a node without a parent generates an exception
2633 3 : CATCH_REQUIRE_THROWS_MATCHES(
2634 : root->replace_with(literal_seven)
2635 : , as2js::no_parent
2636 : , Catch::Matchers::ExceptionMessage(
2637 : "as2js_exception: trying to replace a node which has no parent."));
2638 :
2639 : // verify that we cannot get an offset on a node without a parent
2640 1 : CATCH_REQUIRE_THROWS_MATCHES(
2641 : root->get_offset()
2642 : , as2js::no_parent
2643 : , Catch::Matchers::ExceptionMessage(
2644 : "as2js_exception: get_offset() only works against nodes that have a parent."));
2645 :
2646 : // check out our tree textually
2647 : //std::cout << std::endl << *root << std::endl;
2648 :
2649 : // finally mark a node as unknown and call clean_tree()
2650 1 : CATCH_REQUIRE(!member->is_locked());
2651 : {
2652 1 : snapdev::ostream_to_buf<char> out(std::cerr);
2653 2 : as2js::node_lock lock(member);
2654 1 : CATCH_REQUIRE(member->is_locked());
2655 1 : CATCH_REQUIRE_THROWS_MATCHES(
2656 : member->to_unknown()
2657 : , as2js::locked_node
2658 : , Catch::Matchers::ExceptionMessage(
2659 : "as2js_exception: trying to modify a locked node."));
2660 1 : CATCH_REQUIRE(member->get_type() == as2js::node_t::NODE_MEMBER);
2661 1 : CATCH_REQUIRE(out.str().substr(0, 65) == "error: The following node is locked and thus cannot be modified:\n");
2662 1 : }
2663 1 : CATCH_REQUIRE(!member->is_locked());
2664 : // try too many unlock!
2665 1 : CATCH_REQUIRE_THROWS_MATCHES(
2666 : member->unlock()
2667 : , as2js::internal_error
2668 : , Catch::Matchers::ExceptionMessage(
2669 : "internal_error: somehow the node::unlock() function was called when the lock counter is zero."));
2670 1 : member->to_unknown();
2671 1 : CATCH_REQUIRE(member->get_type() == as2js::node_t::NODE_UNKNOWN);
2672 : {
2673 1 : snapdev::ostream_to_buf<char> out(std::cerr);
2674 2 : as2js::node_lock lock(member);
2675 1 : CATCH_REQUIRE_THROWS_MATCHES(
2676 : root->clean_tree()
2677 : , as2js::locked_node
2678 : , Catch::Matchers::ExceptionMessage(
2679 : "as2js_exception: trying to modify a locked node."));
2680 1 : CATCH_REQUIRE(member->get_type() == as2js::node_t::NODE_UNKNOWN);
2681 1 : CATCH_REQUIRE(member->get_parent());
2682 1 : CATCH_REQUIRE(out.str().substr(0, 65) == "error: The following node is locked and thus cannot be modified:\n");
2683 1 : }
2684 1 : root->clean_tree();
2685 :
2686 : // check that the tree looks as expected
2687 1 : CATCH_REQUIRE(root->get_children_size() == 2);
2688 1 : CATCH_REQUIRE(directive_list_a->get_children_size() == 0);
2689 1 : CATCH_REQUIRE(directive_list_b->get_children_size() == 1);
2690 1 : CATCH_REQUIRE(directive_list_b->get_child(0) == assignment);
2691 1 : CATCH_REQUIRE(assignment->get_children_size() == 2);
2692 1 : CATCH_REQUIRE(assignment->get_child(0) == identifier_a);
2693 1 : CATCH_REQUIRE(assignment->get_child(1) == power);
2694 1 : CATCH_REQUIRE(identifier_a->get_children_size() == 0);
2695 1 : CATCH_REQUIRE(power->get_children_size() == 1);
2696 : // Although member is not in the tree anymore, its children
2697 : // are still there as expected (because we hold a smart pointers
2698 : // to all of that)
2699 : //CATCH_REQUIRE(power->get_child(0) == member);
2700 1 : CATCH_REQUIRE(power->get_child(0) == literal);
2701 1 : CATCH_REQUIRE(!member->get_parent());
2702 1 : CATCH_REQUIRE(member->get_children_size() == 2);
2703 1 : CATCH_REQUIRE(member->get_child(0) == identifier_math);
2704 1 : CATCH_REQUIRE(member->get_child(1) == identifier_e);
2705 1 : CATCH_REQUIRE(identifier_math->get_children_size() == 0);
2706 1 : CATCH_REQUIRE(identifier_math->get_parent() == member);
2707 1 : CATCH_REQUIRE(identifier_e->get_children_size() == 0);
2708 1 : CATCH_REQUIRE(identifier_e->get_parent() == member);
2709 1 : CATCH_REQUIRE(literal->get_children_size() == 0);
2710 1 : }
2711 :
2712 : // did we deleted as many nodes as we created?
2713 : //
2714 1 : CATCH_REQUIRE(counter == 0);
2715 : }
2716 4 : CATCH_END_SECTION()
2717 :
2718 4 : CATCH_START_SECTION("node_tree: verify find_next_node() properly")
2719 : {
2720 1 : as2js::node::pointer_t root(std::make_shared<as2js::node>(as2js::node_t::NODE_ROOT));
2721 1 : as2js::node::pointer_t list1(std::make_shared<as2js::node>(as2js::node_t::NODE_DIRECTIVE_LIST));
2722 1 : as2js::node::pointer_t list2(std::make_shared<as2js::node>(as2js::node_t::NODE_DIRECTIVE_LIST));
2723 1 : as2js::node::pointer_t list3(std::make_shared<as2js::node>(as2js::node_t::NODE_DIRECTIVE_LIST));
2724 1 : as2js::node::pointer_t list4(std::make_shared<as2js::node>(as2js::node_t::NODE_DIRECTIVE_LIST));
2725 1 : as2js::node::pointer_t list5(std::make_shared<as2js::node>(as2js::node_t::NODE_DIRECTIVE_LIST));
2726 :
2727 1 : root->append_child(list1);
2728 1 : root->append_child(list2);
2729 1 : root->append_child(list3);
2730 1 : root->append_child(list4);
2731 1 : root->append_child(list5);
2732 :
2733 1 : CATCH_REQUIRE(root->find_first_child(as2js::node_t::NODE_DIRECTIVE_LIST) == list1);
2734 1 : CATCH_REQUIRE(root->find_next_child(nullptr, as2js::node_t::NODE_DIRECTIVE_LIST) == list1);
2735 :
2736 1 : CATCH_REQUIRE(root->find_next_child(list1, as2js::node_t::NODE_DIRECTIVE_LIST) == list2);
2737 1 : CATCH_REQUIRE(root->find_next_child(list2, as2js::node_t::NODE_DIRECTIVE_LIST) == list3);
2738 1 : CATCH_REQUIRE(root->find_next_child(list3, as2js::node_t::NODE_DIRECTIVE_LIST) == list4);
2739 1 : CATCH_REQUIRE(root->find_next_child(list4, as2js::node_t::NODE_DIRECTIVE_LIST) == list5);
2740 :
2741 1 : CATCH_REQUIRE(root->find_next_child(list5, as2js::node_t::NODE_DIRECTIVE_LIST) == nullptr);
2742 1 : }
2743 4 : CATCH_END_SECTION()
2744 4 : }
2745 :
2746 :
2747 2 : CATCH_TEST_CASE("node_lock", "[node][lock]")
2748 : {
2749 2 : CATCH_START_SECTION("node_lock: verify lock counter (proper lock/unlock)")
2750 : {
2751 1 : as2js::node::pointer_t n(std::make_shared<as2js::node>(as2js::node_t::NODE_CLASS));
2752 1 : CATCH_REQUIRE_FALSE(n->is_locked());
2753 2 : as2js::node_lock lock(n);
2754 1 : CATCH_REQUIRE(n->is_locked());
2755 :
2756 : // we get a double unlock error in the ~node_lock() function
2757 : // but have a catch() which ignores the fact...
2758 : //
2759 : // i.e. the correct way would be to instead do:
2760 : //
2761 : // lock.unlock();
2762 : //
2763 1 : n->unlock();
2764 1 : CATCH_REQUIRE_FALSE(n->is_locked());
2765 1 : }
2766 2 : CATCH_END_SECTION()
2767 :
2768 2 : CATCH_START_SECTION("node_lock: verify lock counter (missing unlock)")
2769 : {
2770 : // in normal circumstances, skip that test...
2771 : //
2772 : // there is a kernel bug in older Linux versions (Ubuntu 18.04 and
2773 : // older for sure; kernel 4.15.0-200-generic still displayed that
2774 : // behavior)
2775 : //
2776 1 : if(SNAP_CATCH2_NAMESPACE::g_run_destructive)
2777 : {
2778 0 : std::cout << "info: skipping section; test can lock up in fork() on older versions of Linux; use --destructive to run the test on its own (which generally works on alls systems).\n";
2779 0 : CATCH_REQUIRE(true);
2780 0 : return;
2781 : }
2782 :
2783 : // manual lock, no unlock before deletion...
2784 : //
2785 : // that generates an std::terminate so we use an external test
2786 : // and verify that it fails with an abort() when we do not have
2787 : // the unlock
2788 : //
2789 : // WARNING: using system() means using a shell and that failed
2790 : // so I have my own quick_exec() to skip on the shell
2791 : //
2792 1 : std::string cmd(SNAP_CATCH2_NAMESPACE::g_binary_dir());
2793 1 : cmd += "/tests/locked-node";
2794 : //std::cerr << "--- system(\"" << cmd << "\"); ..." << std::endl;
2795 : //int r(system(cmd.c_str()));
2796 1 : int r(quick_exec(cmd));
2797 1 : CATCH_REQUIRE(r == 0);
2798 1 : cmd += " -u";
2799 : //std::cerr << "--- system(\"" << cmd << "\"); ..." << std::endl;
2800 : //r = system(cmd.c_str());
2801 1 : r = quick_exec(cmd);
2802 1 : CATCH_REQUIRE(r == 1);
2803 : //if(!WIFEXITED(r))
2804 : //{
2805 : // CATCH_REQUIRE("not exited?" == nullptr);
2806 : //}
2807 : //else if(WIFSIGNALED(r))
2808 : //{
2809 : // CATCH_REQUIRE("signaled?" == nullptr);
2810 : //}
2811 : //else
2812 : //{
2813 : // int const exit_code(WEXITSTATUS(r));
2814 : // if(exit_code != SIGABRT + 128)
2815 : // {
2816 : // CATCH_REQUIRE(exit_code != SIGABRT + 128);
2817 : // }
2818 : //}
2819 1 : }
2820 2 : CATCH_END_SECTION()
2821 : }
2822 :
2823 :
2824 1 : CATCH_TEST_CASE("node_parameter", "[node][parameter]")
2825 : {
2826 1 : CATCH_START_SECTION("node_parameter: verify node parameters")
2827 : {
2828 1 : as2js::node::pointer_t match(std::make_shared<as2js::node>(as2js::node_t::NODE_PARAM_MATCH));
2829 :
2830 1 : CATCH_REQUIRE(match->get_param_size() == 0);
2831 :
2832 : // zero is not acceptable
2833 1 : CATCH_REQUIRE_THROWS_MATCHES(
2834 : match->set_param_size(0)
2835 : , as2js::internal_error
2836 : , Catch::Matchers::ExceptionMessage(
2837 : "internal_error: set_param_size() was called with a size of zero."));
2838 :
2839 1 : match->set_param_size(5);
2840 1 : CATCH_REQUIRE(match->get_param_size() == 5);
2841 :
2842 : // cannot change the size once set
2843 1 : CATCH_REQUIRE_THROWS_MATCHES(
2844 : match->set_param_size(10)
2845 : , as2js::internal_error
2846 : , Catch::Matchers::ExceptionMessage(
2847 : "internal_error: set_param_size() called twice."));
2848 :
2849 1 : CATCH_REQUIRE(match->get_param_size() == 5);
2850 :
2851 : // first set the depth, try with an out of range index too
2852 6 : for(int i(-5); i < 0; ++i)
2853 : {
2854 5 : CATCH_REQUIRE_THROWS_MATCHES(
2855 : match->set_param_depth(i, rand())
2856 : , as2js::out_of_range
2857 : , Catch::Matchers::ExceptionMessage(
2858 : "out_of_range: set_param_depth() called with an index out of range."));
2859 : }
2860 1 : ssize_t depths[5];
2861 6 : for(int i(0); i < 5; ++i)
2862 : {
2863 5 : depths[i] = rand();
2864 5 : match->set_param_depth(i, depths[i]);
2865 : }
2866 7 : for(int i(5); i <= 10; ++i)
2867 : {
2868 6 : CATCH_REQUIRE_THROWS_MATCHES(
2869 : match->set_param_depth(i, rand())
2870 : , as2js::out_of_range
2871 : , Catch::Matchers::ExceptionMessage(
2872 : "out_of_range: set_param_depth() called with an index out of range."));
2873 : }
2874 :
2875 : // now test that what we saved can be read back, also with some out of range
2876 6 : for(int i(-5); i < 0; ++i)
2877 : {
2878 5 : CATCH_REQUIRE_THROWS_MATCHES(
2879 : match->get_param_depth(i)
2880 : , as2js::out_of_range
2881 : , Catch::Matchers::ExceptionMessage(
2882 : "out_of_range: get_param_depth() called with an out of range index."));
2883 : }
2884 6 : for(int i(0); i < 5; ++i)
2885 : {
2886 5 : CATCH_REQUIRE(match->get_param_depth(i) == depths[i]);
2887 : }
2888 6 : for(int i(5); i < 10; ++i)
2889 : {
2890 5 : CATCH_REQUIRE_THROWS_MATCHES(
2891 : match->get_param_depth(i)
2892 : , as2js::out_of_range
2893 : , Catch::Matchers::ExceptionMessage(
2894 : "out_of_range: get_param_depth() called with an out of range index."));
2895 : }
2896 :
2897 : // second set the index, try with an out of range index too
2898 6 : for(int i(-5); i < 0; ++i)
2899 : {
2900 5 : CATCH_REQUIRE_THROWS_MATCHES(
2901 : match->set_param_index(i, rand() % 5)
2902 : , as2js::out_of_range
2903 : , Catch::Matchers::ExceptionMessage(
2904 : "out_of_range: set_param_index() called with one or both indexes out of range."));
2905 5 : CATCH_REQUIRE_THROWS_MATCHES(
2906 : match->set_param_index(i, rand())
2907 : , as2js::out_of_range
2908 : , Catch::Matchers::ExceptionMessage(
2909 : "out_of_range: set_param_index() called with one or both indexes out of range."));
2910 : }
2911 1 : size_t index[5];
2912 6 : for(int i(0); i < 5; ++i)
2913 : {
2914 5 : index[i] = rand() % 5;
2915 5 : match->set_param_index(i, index[i]);
2916 :
2917 : // if 'j' is invalid, then just throw
2918 : // and do not change the valid value
2919 55 : for(int k(0); k < 10; ++k)
2920 : {
2921 50 : int j(0);
2922 : do
2923 : {
2924 50 : j = rand();
2925 : }
2926 50 : while(j >= 0 && j <= 5);
2927 50 : CATCH_REQUIRE_THROWS_MATCHES(
2928 : match->set_param_index(i, j)
2929 : , as2js::out_of_range
2930 : , Catch::Matchers::ExceptionMessage(
2931 : "out_of_range: set_param_index() called with one or both indexes out of range."));
2932 : }
2933 : }
2934 7 : for(int i(5); i <= 10; ++i)
2935 : {
2936 6 : CATCH_REQUIRE_THROWS_MATCHES(
2937 : match->set_param_index(i, rand() % 5)
2938 : , as2js::out_of_range
2939 : , Catch::Matchers::ExceptionMessage(
2940 : "out_of_range: set_param_index() called with one or both indexes out of range."));
2941 6 : CATCH_REQUIRE_THROWS_MATCHES(
2942 : match->set_param_index(i, rand())
2943 : , as2js::out_of_range
2944 : , Catch::Matchers::ExceptionMessage(
2945 : "out_of_range: set_param_index() called with one or both indexes out of range."));
2946 : }
2947 :
2948 : // now test that what we saved can be read back, also with some out of range
2949 6 : for(int i(-5); i < 0; ++i)
2950 : {
2951 5 : CATCH_REQUIRE_THROWS_MATCHES(
2952 : match->get_param_index(i)
2953 : , as2js::out_of_range
2954 : , Catch::Matchers::ExceptionMessage(
2955 : "out_of_range: set_param_index() called with an index out of range."));
2956 : }
2957 6 : for(int i(0); i < 5; ++i)
2958 : {
2959 5 : CATCH_REQUIRE(match->get_param_index(i) == index[i]);
2960 : }
2961 6 : for(int i(5); i < 10; ++i)
2962 : {
2963 5 : CATCH_REQUIRE_THROWS_MATCHES(
2964 : match->get_param_index(i)
2965 : , as2js::out_of_range
2966 : , Catch::Matchers::ExceptionMessage(
2967 : "out_of_range: set_param_index() called with an index out of range."));
2968 : }
2969 1 : }
2970 1 : CATCH_END_SECTION()
2971 1 : }
2972 :
2973 :
2974 1 : CATCH_TEST_CASE("node_position", "[node][position]")
2975 : {
2976 1 : CATCH_START_SECTION("node_position: verify position computation")
2977 : {
2978 1 : as2js::position pos;
2979 1 : pos.set_filename("file.js");
2980 1 : int total_line(1);
2981 10 : for(int page(1); page < 10; ++page)
2982 : {
2983 9 : int paragraphs(rand() % 10 + 10);
2984 9 : int page_line(1);
2985 9 : int paragraph(1);
2986 900 : for(int line(1); line < 100; ++line)
2987 : {
2988 891 : CATCH_REQUIRE(pos.get_page() == page);
2989 891 : CATCH_REQUIRE(pos.get_page_line() == page_line);
2990 891 : CATCH_REQUIRE(pos.get_paragraph() == paragraph);
2991 891 : CATCH_REQUIRE(pos.get_line() == total_line);
2992 :
2993 891 : std::stringstream pos_str;
2994 891 : pos_str << pos;
2995 891 : std::stringstream test_str;
2996 891 : test_str << "file.js:" << total_line << ":";
2997 891 : CATCH_REQUIRE(pos_str.str() == test_str.str());
2998 :
2999 : // create any valid type of node
3000 891 : size_t const idx(rand() % g_node_types_size);
3001 891 : as2js::node::pointer_t node(std::make_shared<as2js::node>(g_node_types[idx].f_type));
3002 :
3003 : // set our current position in there
3004 891 : node->set_position(pos);
3005 :
3006 : // verify that the node position is equal to ours
3007 891 : as2js::position const& node_pos(node->get_position());
3008 891 : CATCH_REQUIRE(node_pos.get_page() == page);
3009 891 : CATCH_REQUIRE(node_pos.get_page_line() == page_line);
3010 891 : CATCH_REQUIRE(node_pos.get_paragraph() == paragraph);
3011 891 : CATCH_REQUIRE(node_pos.get_line() == total_line);
3012 :
3013 891 : std::stringstream node_pos_str;
3014 891 : node_pos_str << node_pos;
3015 891 : std::stringstream node_test_str;
3016 891 : node_test_str << "file.js:" << total_line << ":";
3017 891 : CATCH_REQUIRE(node_pos_str.str() == node_test_str.str());
3018 :
3019 : // create a replacement now
3020 891 : size_t const idx_replacement(rand() % g_node_types_size);
3021 891 : as2js::node::pointer_t replacement(node->create_replacement(g_node_types[idx_replacement].f_type));
3022 :
3023 : // verify that the replacement position is equal to ours
3024 : // (and thus the node's)
3025 891 : as2js::position const& replacement_pos(node->get_position());
3026 891 : CATCH_REQUIRE(replacement_pos.get_page() == page);
3027 891 : CATCH_REQUIRE(replacement_pos.get_page_line() == page_line);
3028 891 : CATCH_REQUIRE(replacement_pos.get_paragraph() == paragraph);
3029 891 : CATCH_REQUIRE(replacement_pos.get_line() == total_line);
3030 :
3031 891 : std::stringstream replacement_pos_str;
3032 891 : replacement_pos_str << replacement_pos;
3033 891 : std::stringstream replacement_test_str;
3034 891 : replacement_test_str << "file.js:" << total_line << ":";
3035 891 : CATCH_REQUIRE(replacement_pos_str.str() == replacement_test_str.str());
3036 :
3037 : // verify that the node position has not changed
3038 891 : as2js::position const& node_pos2(node->get_position());
3039 891 : CATCH_REQUIRE(node_pos2.get_page() == page);
3040 891 : CATCH_REQUIRE(node_pos2.get_page_line() == page_line);
3041 891 : CATCH_REQUIRE(node_pos2.get_paragraph() == paragraph);
3042 891 : CATCH_REQUIRE(node_pos2.get_line() == total_line);
3043 :
3044 891 : std::stringstream node_pos2_str;
3045 891 : node_pos2_str << node_pos2;
3046 891 : std::stringstream node_test2_str;
3047 891 : node_test2_str << "file.js:" << total_line << ":";
3048 891 : CATCH_REQUIRE(node_pos2_str.str() == node_test2_str.str());
3049 :
3050 : // go to the next line, paragraph, etc.
3051 891 : if(line % paragraphs == 0)
3052 : {
3053 58 : pos.new_paragraph();
3054 58 : ++paragraph;
3055 : }
3056 891 : pos.new_line();
3057 891 : ++total_line;
3058 891 : ++page_line;
3059 891 : }
3060 9 : pos.new_page();
3061 : }
3062 1 : }
3063 1 : CATCH_END_SECTION()
3064 1 : }
3065 :
3066 :
3067 1 : CATCH_TEST_CASE("node_links", "[node][link]")
3068 : {
3069 1 : CATCH_START_SECTION("node_links: verify node linking")
3070 : {
3071 11 : for(int i(0); i < 10; ++i)
3072 : {
3073 : // create any valid type of node
3074 10 : size_t const idx_node(rand() % g_node_types_size);
3075 10 : as2js::node::pointer_t node(std::make_shared<as2js::node>(g_node_types[idx_node].f_type));
3076 :
3077 10 : size_t const idx_bad_link(rand() % g_node_types_size);
3078 10 : as2js::node::pointer_t bad_link(std::make_shared<as2js::node>(g_node_types[idx_bad_link].f_type));
3079 :
3080 : // check various links
3081 :
3082 : { // instance
3083 10 : as2js::node::pointer_t link(std::make_shared<as2js::node>(as2js::node_t::NODE_CLASS));
3084 10 : node->set_instance(link);
3085 10 : CATCH_REQUIRE(node->get_instance() == link);
3086 :
3087 10 : as2js::node::pointer_t other_link(std::make_shared<as2js::node>(as2js::node_t::NODE_CLASS));
3088 10 : node->set_instance(other_link);
3089 10 : CATCH_REQUIRE(node->get_instance() == other_link);
3090 10 : }
3091 10 : CATCH_REQUIRE(!node->get_instance()); // weak pointer, reset to null
3092 :
3093 : { // type
3094 10 : as2js::node::pointer_t link(std::make_shared<as2js::node>(as2js::node_t::NODE_IDENTIFIER));
3095 10 : node->set_type_node(link);
3096 10 : CATCH_REQUIRE(node->get_type_node() == link);
3097 :
3098 10 : as2js::node::pointer_t other_link(std::make_shared<as2js::node>(as2js::node_t::NODE_IDENTIFIER));
3099 10 : node->set_type_node(other_link);
3100 10 : CATCH_REQUIRE(node->get_type_node() == other_link);
3101 10 : }
3102 10 : CATCH_REQUIRE(!node->get_type_node()); // weak pointer, reset to null
3103 :
3104 : { // attributes
3105 10 : as2js::node::pointer_t link(std::make_shared<as2js::node>(as2js::node_t::NODE_ATTRIBUTES));
3106 10 : node->set_attribute_node(link);
3107 10 : CATCH_REQUIRE(node->get_attribute_node() == link);
3108 :
3109 10 : as2js::node::pointer_t other_link(std::make_shared<as2js::node>(as2js::node_t::NODE_ATTRIBUTES));
3110 10 : node->set_attribute_node(other_link);
3111 10 : CATCH_REQUIRE(node->get_attribute_node() == other_link);
3112 10 : }
3113 10 : CATCH_REQUIRE(node->get_attribute_node()); // NOT a weak pointer for attributes
3114 :
3115 : { // goto exit
3116 10 : as2js::node::pointer_t link(std::make_shared<as2js::node>(as2js::node_t::NODE_LABEL));
3117 10 : node->set_goto_exit(link);
3118 10 : CATCH_REQUIRE(node->get_goto_exit() == link);
3119 :
3120 10 : as2js::node::pointer_t other_link(std::make_shared<as2js::node>(as2js::node_t::NODE_LABEL));
3121 10 : node->set_goto_exit(other_link);
3122 10 : CATCH_REQUIRE(node->get_goto_exit() == other_link);
3123 10 : }
3124 10 : CATCH_REQUIRE(!node->get_goto_exit()); // weak pointer, reset to null
3125 :
3126 : { // goto enter
3127 10 : as2js::node::pointer_t link(std::make_shared<as2js::node>(as2js::node_t::NODE_LABEL));
3128 10 : node->set_goto_enter(link);
3129 10 : CATCH_REQUIRE(node->get_goto_enter() == link);
3130 :
3131 10 : as2js::node::pointer_t other_link(std::make_shared<as2js::node>(as2js::node_t::NODE_LABEL));
3132 10 : node->set_goto_enter(other_link);
3133 10 : CATCH_REQUIRE(node->get_goto_enter() == other_link);
3134 10 : }
3135 10 : CATCH_REQUIRE(!node->get_goto_enter()); // weak pointer, reset to null
3136 10 : }
3137 : }
3138 1 : CATCH_END_SECTION()
3139 1 : }
3140 :
3141 :
3142 1 : CATCH_TEST_CASE("node_variable", "[node][variable]")
3143 : {
3144 1 : CATCH_START_SECTION("node_variable: verify variables")
3145 : {
3146 11 : for(int i(0); i < 10; ++i)
3147 : {
3148 : // create any valid type of node
3149 10 : size_t const idx_node(rand() % g_node_types_size);
3150 10 : as2js::node::pointer_t node(std::make_shared<as2js::node>(g_node_types[idx_node].f_type));
3151 :
3152 : // create a node that is not a NODE_VARIABLE
3153 : size_t idx_bad_link;
3154 : do
3155 : {
3156 10 : idx_bad_link = rand() % g_node_types_size;
3157 : }
3158 10 : while(g_node_types[idx_bad_link].f_type == as2js::node_t::NODE_VARIABLE);
3159 10 : as2js::node::pointer_t not_variable(std::make_shared<as2js::node>(g_node_types[idx_bad_link].f_type));
3160 30 : CATCH_REQUIRE_THROWS_MATCHES(
3161 : node->add_variable(not_variable)
3162 : , as2js::incompatible_type
3163 : , Catch::Matchers::ExceptionMessage(
3164 : "as2js_exception: the node parameter of the add_variable() function must be a \"NODE_VARIABLE\"."));
3165 :
3166 : // add 10 valid variables
3167 120 : as2js::node::pointer_t variables[10];
3168 110 : for(size_t j(0); j < 10; ++j)
3169 : {
3170 100 : CATCH_REQUIRE(node->get_variable_size() == j);
3171 :
3172 100 : variables[j].reset(new as2js::node(as2js::node_t::NODE_VARIABLE));
3173 100 : node->add_variable(variables[j]);
3174 : }
3175 10 : CATCH_REQUIRE(node->get_variable_size() == 10);
3176 :
3177 : // try with offsets that are too small
3178 110 : for(int j(-10); j < 0; ++j)
3179 : {
3180 100 : CATCH_REQUIRE_THROWS_MATCHES(
3181 : node->get_variable(j)
3182 : , as2js::out_of_range
3183 : , Catch::Matchers::ExceptionMessage(
3184 : "out_of_range: get_variable() called with an out of range index."));
3185 : }
3186 :
3187 : // then verify that the variables are indeed valid
3188 110 : for(int j(0); j < 10; ++j)
3189 : {
3190 100 : CATCH_REQUIRE(node->get_variable(j) == variables[j]);
3191 : }
3192 :
3193 : // try with offsets that are too large
3194 120 : for(int j(10); j <= 20; ++j)
3195 : {
3196 110 : CATCH_REQUIRE_THROWS_MATCHES(
3197 : node->get_variable(j)
3198 : , as2js::out_of_range
3199 : , Catch::Matchers::ExceptionMessage(
3200 : "out_of_range: get_variable() called with an out of range index."));
3201 : }
3202 120 : }
3203 : }
3204 1 : CATCH_END_SECTION()
3205 1 : }
3206 :
3207 :
3208 1 : CATCH_TEST_CASE("node_label", "[node][label]")
3209 : {
3210 1 : CATCH_START_SECTION("node_label: verify labelling")
3211 : {
3212 11 : for(int i(0); i < 10; ++i)
3213 : {
3214 : // create a NODE_FUNCTION
3215 10 : as2js::node::pointer_t function(std::make_shared<as2js::node>(as2js::node_t::NODE_FUNCTION));
3216 :
3217 : // create a node that is not a NODE_LABEL
3218 : size_t idx_bad_label;
3219 : do
3220 : {
3221 10 : idx_bad_label = rand() % g_node_types_size;
3222 : }
3223 10 : while(g_node_types[idx_bad_label].f_type == as2js::node_t::NODE_LABEL);
3224 10 : as2js::node::pointer_t not_label(std::make_shared<as2js::node>(g_node_types[idx_bad_label].f_type));
3225 30 : CATCH_REQUIRE_THROWS_MATCHES(
3226 : function->add_label(not_label)
3227 : , as2js::incompatible_type
3228 : , Catch::Matchers::ExceptionMessage(
3229 : "as2js_exception: invalid type of node to call add_label() with."));
3230 :
3231 110 : for(int j(0); j < 10; ++j)
3232 : {
3233 : // create a node that is not a NODE_LABEL
3234 100 : as2js::node::pointer_t label(std::make_shared<as2js::node>(as2js::node_t::NODE_LABEL));
3235 :
3236 : // create a node that is not a NODE_FUNCTION
3237 : size_t idx_bad_function;
3238 : do
3239 : {
3240 100 : idx_bad_function = rand() % g_node_types_size;
3241 : }
3242 100 : while(g_node_types[idx_bad_function].f_type == as2js::node_t::NODE_FUNCTION);
3243 100 : as2js::node::pointer_t not_function(std::make_shared<as2js::node>(g_node_types[idx_bad_function].f_type));
3244 300 : CATCH_REQUIRE_THROWS_MATCHES(
3245 : not_function->add_label(label)
3246 : , as2js::incompatible_type
3247 : , Catch::Matchers::ExceptionMessage(
3248 : "as2js_exception: invalid type of node to call add_label() with."));
3249 :
3250 : // labels need to have a name
3251 300 : CATCH_REQUIRE_THROWS_MATCHES(
3252 : function->add_label(label)
3253 : , as2js::incompatible_data
3254 : , Catch::Matchers::ExceptionMessage(
3255 : "as2js_exception: a label without a valid name cannot be added to a function."));
3256 :
3257 : // save the label with a name
3258 200 : std::string label_name("label" + std::to_string(j));
3259 100 : label->set_string(label_name);
3260 100 : function->add_label(label);
3261 :
3262 : // trying to add two labels (or the same) with the same name err
3263 300 : CATCH_REQUIRE_THROWS_MATCHES(
3264 : function->add_label(label)
3265 : , as2js::already_defined
3266 : , Catch::Matchers::ExceptionMessage(
3267 : "as2js_exception: a label with the same name is already defined in this function."));
3268 :
3269 : // verify that we can find that label
3270 100 : CATCH_REQUIRE(function->find_label(label_name) == label);
3271 100 : }
3272 10 : }
3273 : }
3274 1 : CATCH_END_SECTION()
3275 1 : }
3276 :
3277 :
3278 1 : CATCH_TEST_CASE("node_attribute", "[node][attribute]")
3279 : {
3280 1 : CATCH_START_SECTION("node_attribute: verify setting attributes on nodes")
3281 : {
3282 11 : for(int i(0); i < 10; ++i)
3283 : {
3284 : // create a node that is not a NODE_PROGRAM
3285 : // (i.e. a node that accepts all attributes)
3286 : size_t idx_node;
3287 : do
3288 : {
3289 11 : idx_node = rand() % g_node_types_size;
3290 : }
3291 11 : while(g_node_types[idx_node].f_type == as2js::node_t::NODE_PROGRAM);
3292 10 : as2js::node::pointer_t node(std::make_shared<as2js::node>(g_node_types[idx_node].f_type));
3293 :
3294 : // need to test all combinatorial cases...
3295 60 : for(size_t j(0); j < g_groups_of_attributes_size; ++j)
3296 : {
3297 : // go through the list of attributes that generate conflicts
3298 190 : for(as2js::attribute_t const *attr_list(g_groups_of_attributes[j].f_attributes);
3299 190 : *attr_list != as2js::attribute_t::NODE_ATTR_max;
3300 : ++attr_list)
3301 : {
3302 140 : if(*attr_list == as2js::attribute_t::NODE_ATTR_TYPE)
3303 : {
3304 0 : switch(node->get_type())
3305 : {
3306 0 : case as2js::node_t::NODE_ADD:
3307 : case as2js::node_t::NODE_ARRAY:
3308 : case as2js::node_t::NODE_ARRAY_LITERAL:
3309 : case as2js::node_t::NODE_AS:
3310 : case as2js::node_t::NODE_ASSIGNMENT:
3311 : case as2js::node_t::NODE_ASSIGNMENT_ADD:
3312 : case as2js::node_t::NODE_ASSIGNMENT_BITWISE_AND:
3313 : case as2js::node_t::NODE_ASSIGNMENT_BITWISE_OR:
3314 : case as2js::node_t::NODE_ASSIGNMENT_BITWISE_XOR:
3315 : case as2js::node_t::NODE_ASSIGNMENT_DIVIDE:
3316 : case as2js::node_t::NODE_ASSIGNMENT_LOGICAL_AND:
3317 : case as2js::node_t::NODE_ASSIGNMENT_LOGICAL_OR:
3318 : case as2js::node_t::NODE_ASSIGNMENT_LOGICAL_XOR:
3319 : case as2js::node_t::NODE_ASSIGNMENT_MAXIMUM:
3320 : case as2js::node_t::NODE_ASSIGNMENT_MINIMUM:
3321 : case as2js::node_t::NODE_ASSIGNMENT_MODULO:
3322 : case as2js::node_t::NODE_ASSIGNMENT_MULTIPLY:
3323 : case as2js::node_t::NODE_ASSIGNMENT_POWER:
3324 : case as2js::node_t::NODE_ASSIGNMENT_ROTATE_LEFT:
3325 : case as2js::node_t::NODE_ASSIGNMENT_ROTATE_RIGHT:
3326 : case as2js::node_t::NODE_ASSIGNMENT_SHIFT_LEFT:
3327 : case as2js::node_t::NODE_ASSIGNMENT_SHIFT_RIGHT:
3328 : case as2js::node_t::NODE_ASSIGNMENT_SHIFT_RIGHT_UNSIGNED:
3329 : case as2js::node_t::NODE_ASSIGNMENT_SUBTRACT:
3330 : case as2js::node_t::NODE_BITWISE_AND:
3331 : case as2js::node_t::NODE_BITWISE_NOT:
3332 : case as2js::node_t::NODE_BITWISE_OR:
3333 : case as2js::node_t::NODE_BITWISE_XOR:
3334 : case as2js::node_t::NODE_CALL:
3335 : case as2js::node_t::NODE_CONDITIONAL:
3336 : case as2js::node_t::NODE_DECREMENT:
3337 : case as2js::node_t::NODE_DELETE:
3338 : case as2js::node_t::NODE_DIVIDE:
3339 : case as2js::node_t::NODE_EQUAL:
3340 : case as2js::node_t::NODE_FALSE:
3341 : case as2js::node_t::NODE_FLOATING_POINT:
3342 : case as2js::node_t::NODE_FUNCTION:
3343 : case as2js::node_t::NODE_GREATER:
3344 : case as2js::node_t::NODE_GREATER_EQUAL:
3345 : case as2js::node_t::NODE_IDENTIFIER:
3346 : case as2js::node_t::NODE_IN:
3347 : case as2js::node_t::NODE_INCREMENT:
3348 : case as2js::node_t::NODE_INSTANCEOF:
3349 : case as2js::node_t::NODE_INTEGER:
3350 : case as2js::node_t::NODE_IS:
3351 : case as2js::node_t::NODE_LESS:
3352 : case as2js::node_t::NODE_LESS_EQUAL:
3353 : case as2js::node_t::NODE_LIST:
3354 : case as2js::node_t::NODE_LOGICAL_AND:
3355 : case as2js::node_t::NODE_LOGICAL_NOT:
3356 : case as2js::node_t::NODE_LOGICAL_OR:
3357 : case as2js::node_t::NODE_LOGICAL_XOR:
3358 : case as2js::node_t::NODE_MATCH:
3359 : case as2js::node_t::NODE_MAXIMUM:
3360 : case as2js::node_t::NODE_MEMBER:
3361 : case as2js::node_t::NODE_MINIMUM:
3362 : case as2js::node_t::NODE_MODULO:
3363 : case as2js::node_t::NODE_MULTIPLY:
3364 : case as2js::node_t::NODE_NAME:
3365 : case as2js::node_t::NODE_NEW:
3366 : case as2js::node_t::NODE_NOT_EQUAL:
3367 : case as2js::node_t::NODE_NULL:
3368 : case as2js::node_t::NODE_OBJECT_LITERAL:
3369 : case as2js::node_t::NODE_POST_DECREMENT:
3370 : case as2js::node_t::NODE_POST_INCREMENT:
3371 : case as2js::node_t::NODE_POWER:
3372 : case as2js::node_t::NODE_PRIVATE:
3373 : case as2js::node_t::NODE_PUBLIC:
3374 : case as2js::node_t::NODE_RANGE:
3375 : case as2js::node_t::NODE_ROTATE_LEFT:
3376 : case as2js::node_t::NODE_ROTATE_RIGHT:
3377 : case as2js::node_t::NODE_SCOPE:
3378 : case as2js::node_t::NODE_SHIFT_LEFT:
3379 : case as2js::node_t::NODE_SHIFT_RIGHT:
3380 : case as2js::node_t::NODE_SHIFT_RIGHT_UNSIGNED:
3381 : case as2js::node_t::NODE_STRICTLY_EQUAL:
3382 : case as2js::node_t::NODE_STRICTLY_NOT_EQUAL:
3383 : case as2js::node_t::NODE_STRING:
3384 : case as2js::node_t::NODE_SUBTRACT:
3385 : case as2js::node_t::NODE_SUPER:
3386 : case as2js::node_t::NODE_THIS:
3387 : case as2js::node_t::NODE_TRUE:
3388 : case as2js::node_t::NODE_TYPEOF:
3389 : case as2js::node_t::NODE_UNDEFINED:
3390 : case as2js::node_t::NODE_VIDENTIFIER:
3391 : case as2js::node_t::NODE_VOID:
3392 0 : break;;
3393 :
3394 0 : default:
3395 : // with any other types we would get an error
3396 0 : continue;
3397 :
3398 : }
3399 : }
3400 :
3401 140 : as2js::attribute_set_t set;
3402 140 : CATCH_REQUIRE(node->compare_all_attributes(set));
3403 :
3404 : // set that one attribute first
3405 140 : node->set_attribute(*attr_list, true);
3406 :
3407 140 : CATCH_REQUIRE(!node->compare_all_attributes(set));
3408 140 : set[static_cast<int>(*attr_list)] = true;
3409 140 : CATCH_REQUIRE(node->compare_all_attributes(set));
3410 :
3411 420 : std::string str(g_attribute_names[static_cast<int>(*attr_list)]);
3412 :
3413 : // test against all the other attributes
3414 4200 : for(int a(0); a < static_cast<int>(as2js::attribute_t::NODE_ATTR_max); ++a)
3415 : {
3416 : // no need to test with itself, we do that earlier
3417 4060 : if(static_cast<as2js::attribute_t>(a) == *attr_list)
3418 : {
3419 140 : continue;
3420 : }
3421 :
3422 3920 : if(static_cast<as2js::attribute_t>(a) == as2js::attribute_t::NODE_ATTR_TYPE)
3423 : {
3424 140 : switch(node->get_type())
3425 : {
3426 56 : case as2js::node_t::NODE_ADD:
3427 : case as2js::node_t::NODE_ARRAY:
3428 : case as2js::node_t::NODE_ARRAY_LITERAL:
3429 : case as2js::node_t::NODE_AS:
3430 : case as2js::node_t::NODE_ASSIGNMENT:
3431 : case as2js::node_t::NODE_ASSIGNMENT_ADD:
3432 : case as2js::node_t::NODE_ASSIGNMENT_BITWISE_AND:
3433 : case as2js::node_t::NODE_ASSIGNMENT_BITWISE_OR:
3434 : case as2js::node_t::NODE_ASSIGNMENT_BITWISE_XOR:
3435 : case as2js::node_t::NODE_ASSIGNMENT_DIVIDE:
3436 : case as2js::node_t::NODE_ASSIGNMENT_LOGICAL_AND:
3437 : case as2js::node_t::NODE_ASSIGNMENT_LOGICAL_OR:
3438 : case as2js::node_t::NODE_ASSIGNMENT_LOGICAL_XOR:
3439 : case as2js::node_t::NODE_ASSIGNMENT_MAXIMUM:
3440 : case as2js::node_t::NODE_ASSIGNMENT_MINIMUM:
3441 : case as2js::node_t::NODE_ASSIGNMENT_MODULO:
3442 : case as2js::node_t::NODE_ASSIGNMENT_MULTIPLY:
3443 : case as2js::node_t::NODE_ASSIGNMENT_POWER:
3444 : case as2js::node_t::NODE_ASSIGNMENT_ROTATE_LEFT:
3445 : case as2js::node_t::NODE_ASSIGNMENT_ROTATE_RIGHT:
3446 : case as2js::node_t::NODE_ASSIGNMENT_SHIFT_LEFT:
3447 : case as2js::node_t::NODE_ASSIGNMENT_SHIFT_RIGHT:
3448 : case as2js::node_t::NODE_ASSIGNMENT_SHIFT_RIGHT_UNSIGNED:
3449 : case as2js::node_t::NODE_ASSIGNMENT_SUBTRACT:
3450 : case as2js::node_t::NODE_BITWISE_AND:
3451 : case as2js::node_t::NODE_BITWISE_NOT:
3452 : case as2js::node_t::NODE_BITWISE_OR:
3453 : case as2js::node_t::NODE_BITWISE_XOR:
3454 : case as2js::node_t::NODE_CALL:
3455 : case as2js::node_t::NODE_CONDITIONAL:
3456 : case as2js::node_t::NODE_DECREMENT:
3457 : case as2js::node_t::NODE_DELETE:
3458 : case as2js::node_t::NODE_DIVIDE:
3459 : case as2js::node_t::NODE_EQUAL:
3460 : case as2js::node_t::NODE_FALSE:
3461 : case as2js::node_t::NODE_FLOATING_POINT:
3462 : case as2js::node_t::NODE_FUNCTION:
3463 : case as2js::node_t::NODE_GREATER:
3464 : case as2js::node_t::NODE_GREATER_EQUAL:
3465 : case as2js::node_t::NODE_IDENTIFIER:
3466 : case as2js::node_t::NODE_IN:
3467 : case as2js::node_t::NODE_INCREMENT:
3468 : case as2js::node_t::NODE_INSTANCEOF:
3469 : case as2js::node_t::NODE_INTEGER:
3470 : case as2js::node_t::NODE_IS:
3471 : case as2js::node_t::NODE_LESS:
3472 : case as2js::node_t::NODE_LESS_EQUAL:
3473 : case as2js::node_t::NODE_LIST:
3474 : case as2js::node_t::NODE_LOGICAL_AND:
3475 : case as2js::node_t::NODE_LOGICAL_NOT:
3476 : case as2js::node_t::NODE_LOGICAL_OR:
3477 : case as2js::node_t::NODE_LOGICAL_XOR:
3478 : case as2js::node_t::NODE_MATCH:
3479 : case as2js::node_t::NODE_MAXIMUM:
3480 : case as2js::node_t::NODE_MEMBER:
3481 : case as2js::node_t::NODE_MINIMUM:
3482 : case as2js::node_t::NODE_MODULO:
3483 : case as2js::node_t::NODE_MULTIPLY:
3484 : case as2js::node_t::NODE_NAME:
3485 : case as2js::node_t::NODE_NEW:
3486 : case as2js::node_t::NODE_NOT_EQUAL:
3487 : case as2js::node_t::NODE_NULL:
3488 : case as2js::node_t::NODE_OBJECT_LITERAL:
3489 : case as2js::node_t::NODE_POST_DECREMENT:
3490 : case as2js::node_t::NODE_POST_INCREMENT:
3491 : case as2js::node_t::NODE_POWER:
3492 : case as2js::node_t::NODE_PRIVATE:
3493 : case as2js::node_t::NODE_PUBLIC:
3494 : case as2js::node_t::NODE_RANGE:
3495 : case as2js::node_t::NODE_ROTATE_LEFT:
3496 : case as2js::node_t::NODE_ROTATE_RIGHT:
3497 : case as2js::node_t::NODE_SCOPE:
3498 : case as2js::node_t::NODE_SHIFT_LEFT:
3499 : case as2js::node_t::NODE_SHIFT_RIGHT:
3500 : case as2js::node_t::NODE_SHIFT_RIGHT_UNSIGNED:
3501 : case as2js::node_t::NODE_STRICTLY_EQUAL:
3502 : case as2js::node_t::NODE_STRICTLY_NOT_EQUAL:
3503 : case as2js::node_t::NODE_STRING:
3504 : case as2js::node_t::NODE_SUBTRACT:
3505 : case as2js::node_t::NODE_SUPER:
3506 : case as2js::node_t::NODE_THIS:
3507 : case as2js::node_t::NODE_TRUE:
3508 : case as2js::node_t::NODE_TYPEOF:
3509 : case as2js::node_t::NODE_UNDEFINED:
3510 : case as2js::node_t::NODE_VIDENTIFIER:
3511 : case as2js::node_t::NODE_VOID:
3512 56 : break;;
3513 :
3514 84 : default:
3515 : // with any other types we would get an error
3516 84 : continue;
3517 :
3518 : }
3519 : }
3520 :
3521 : // is attribute 'a' in conflict with attribute '*attr_list'?
3522 3836 : if(in_conflict(j, *attr_list, static_cast<as2js::attribute_t>(a)))
3523 : {
3524 320 : test_callback c;
3525 320 : c.f_expected_message_level = as2js::message_level_t::MESSAGE_LEVEL_ERROR;
3526 320 : c.f_expected_error_code = as2js::err_code_t::AS_ERR_INVALID_ATTRIBUTES;
3527 320 : c.f_expected_pos.set_filename("unknown-file");
3528 320 : c.f_expected_pos.set_function("unknown-func");
3529 320 : c.f_expected_message = "Attributes " + std::string(g_groups_of_attributes[j].f_names) + " are mutually exclusive. Only one of them can be used.";
3530 :
3531 : //std::cerr << "next conflict: " << c.f_expected_message << "\n";
3532 : // if in conflict, trying to set the flag generates
3533 : // an error
3534 320 : CATCH_REQUIRE(!node->get_attribute(static_cast<as2js::attribute_t>(a)));
3535 320 : node->set_attribute(static_cast<as2js::attribute_t>(a), true);
3536 : // the set_attribute() did not change the attribute because it is
3537 : // in conflict with another attribute which is set at this time...
3538 320 : CATCH_REQUIRE(!node->get_attribute(static_cast<as2js::attribute_t>(a)));
3539 320 : }
3540 : else
3541 : {
3542 : // before we set it, always false
3543 : //std::cerr << "next valid attr: " << static_cast<int>(*attr_list) << " against " << a << "\n";
3544 3516 : CATCH_REQUIRE(!node->get_attribute(static_cast<as2js::attribute_t>(a)));
3545 3516 : node->set_attribute(static_cast<as2js::attribute_t>(a), true);
3546 3516 : CATCH_REQUIRE(node->get_attribute(static_cast<as2js::attribute_t>(a)));
3547 3516 : node->set_attribute(static_cast<as2js::attribute_t>(a), false);
3548 3516 : CATCH_REQUIRE(!node->get_attribute(static_cast<as2js::attribute_t>(a)));
3549 : }
3550 : }
3551 :
3552 : // we are done with that loop, restore the attribute to the default
3553 140 : node->set_attribute(*attr_list, false);
3554 : }
3555 : }
3556 10 : }
3557 : }
3558 1 : CATCH_END_SECTION()
3559 1 : }
3560 :
3561 :
3562 1 : CATCH_TEST_CASE("node_attribute_tree", "[node][attribute][tree]")
3563 : {
3564 1 : CATCH_START_SECTION("node_attribute_tree: check attributes in a tree")
3565 : {
3566 : // here we create a tree of nodes that we can then test with various
3567 : // attributes using the set_attribute_tree() function
3568 : //
3569 : // the tree is very specific to make it easier to handle the test; there
3570 : // is no need to test every single case (every attribute) since we do that
3571 : // in other tests; this test is to make sure the tree is followed as
3572 : // expected (all leaves are hit)
3573 : //
3574 1 : as2js::node::pointer_t root(std::make_shared<as2js::node>(as2js::node_t::NODE_ROOT));
3575 :
3576 : // block
3577 1 : as2js::node::pointer_t directive_list(std::make_shared<as2js::node>(as2js::node_t::NODE_DIRECTIVE_LIST));
3578 1 : root->append_child(directive_list);
3579 :
3580 : // { for( ...
3581 1 : as2js::node::pointer_t for_loop(std::make_shared<as2js::node>(as2js::node_t::NODE_FOR));
3582 1 : directive_list->append_child(for_loop);
3583 :
3584 : // { for( ... , ...
3585 1 : as2js::node::pointer_t init(std::make_shared<as2js::node>(as2js::node_t::NODE_LIST));
3586 1 : for_loop->append_child(init);
3587 :
3588 1 : as2js::node::pointer_t var1(std::make_shared<as2js::node>(as2js::node_t::NODE_VAR));
3589 1 : init->append_child(var1);
3590 :
3591 1 : as2js::node::pointer_t variable1(std::make_shared<as2js::node>(as2js::node_t::NODE_VARIABLE));
3592 1 : var1->append_child(variable1);
3593 :
3594 : // { for(i
3595 1 : as2js::node::pointer_t variable_name1(std::make_shared<as2js::node>(as2js::node_t::NODE_IDENTIFIER));
3596 1 : variable_name1->set_string("i");
3597 1 : variable1->append_child(variable_name1);
3598 :
3599 : // { for(i :=
3600 1 : as2js::node::pointer_t value1(std::make_shared<as2js::node>(as2js::node_t::NODE_SET));
3601 1 : variable1->append_child(value1);
3602 :
3603 : // { for(i := ... + ...
3604 1 : as2js::node::pointer_t add1(std::make_shared<as2js::node>(as2js::node_t::NODE_ADD));
3605 1 : value1->append_child(add1);
3606 :
3607 : // { for(i := a + ...
3608 1 : as2js::node::pointer_t var_a1(std::make_shared<as2js::node>(as2js::node_t::NODE_IDENTIFIER));
3609 1 : var_a1->set_string("a");
3610 1 : add1->append_child(var_a1);
3611 :
3612 : // { for(i := a + b
3613 1 : as2js::node::pointer_t var_b1(std::make_shared<as2js::node>(as2js::node_t::NODE_IDENTIFIER));
3614 1 : var_b1->set_string("b");
3615 1 : add1->append_child(var_b1);
3616 :
3617 : // { for(i := a + b,
3618 1 : as2js::node::pointer_t var2(std::make_shared<as2js::node>(as2js::node_t::NODE_VAR));
3619 1 : init->append_child(var2);
3620 :
3621 1 : as2js::node::pointer_t variable2(std::make_shared<as2js::node>(as2js::node_t::NODE_VARIABLE));
3622 1 : var2->append_child(variable2);
3623 :
3624 : // { for(i := a + b, j
3625 1 : as2js::node::pointer_t variable_name2(std::make_shared<as2js::node>(as2js::node_t::NODE_IDENTIFIER));
3626 1 : variable_name2->set_string("j");
3627 1 : variable2->append_child(variable_name2);
3628 :
3629 : // { for(i := a + b, j :=
3630 1 : as2js::node::pointer_t value2(std::make_shared<as2js::node>(as2js::node_t::NODE_SET));
3631 1 : variable2->append_child(value2);
3632 :
3633 : // { for(i := a + b, j := ... / ...
3634 1 : as2js::node::pointer_t divide2(std::make_shared<as2js::node>(as2js::node_t::NODE_DIVIDE));
3635 1 : value2->append_child(divide2);
3636 :
3637 : // { for(i := a + b, j := c / ...
3638 1 : as2js::node::pointer_t var_a2(std::make_shared<as2js::node>(as2js::node_t::NODE_IDENTIFIER));
3639 1 : var_a2->set_string("c");
3640 1 : divide2->append_child(var_a2);
3641 :
3642 : // { for(i := a + b, j := c / d
3643 1 : as2js::node::pointer_t var_b2(std::make_shared<as2js::node>(as2js::node_t::NODE_IDENTIFIER));
3644 1 : var_b2->set_string("d");
3645 1 : divide2->append_child(var_b2);
3646 :
3647 : // { for(i := a + b, j := c / d; ... < ...
3648 1 : as2js::node::pointer_t less(std::make_shared<as2js::node>(as2js::node_t::NODE_LESS));
3649 1 : for_loop->append_child(less);
3650 :
3651 : // { for(i := a + b, j := c / d; i < ...
3652 1 : as2js::node::pointer_t var_i2(std::make_shared<as2js::node>(as2js::node_t::NODE_IDENTIFIER));
3653 1 : var_i2->set_string("i");
3654 1 : less->append_child(var_i2);
3655 :
3656 : // { for(i := a + b, j := c / d; i < 100;
3657 1 : as2js::node::pointer_t one_hunder(std::make_shared<as2js::node>(as2js::node_t::NODE_INTEGER));
3658 1 : one_hunder->set_integer(100);
3659 1 : less->append_child(one_hunder);
3660 :
3661 : // { for(i := a + b, j := c / d; i < 100; ++...)
3662 1 : as2js::node::pointer_t increment(std::make_shared<as2js::node>(as2js::node_t::NODE_INCREMENT));
3663 1 : for_loop->append_child(increment);
3664 :
3665 : // { for(i := a + b, j := c / d; i < 100; ++i)
3666 1 : as2js::node::pointer_t var_i3(std::make_shared<as2js::node>(as2js::node_t::NODE_IDENTIFIER));
3667 1 : var_i3->set_string("i");
3668 1 : increment->append_child(var_i3);
3669 :
3670 : // { for(i := a + b, j := c / d; i < 100; ++i) { ... } }
3671 1 : as2js::node::pointer_t block_list(std::make_shared<as2js::node>(as2js::node_t::NODE_DIRECTIVE_LIST));
3672 1 : for_loop->append_child(block_list);
3673 :
3674 : // { for(i := a + b, j := c / d; i < 100; ++i) { ...(...); } }
3675 1 : as2js::node::pointer_t func(std::make_shared<as2js::node>(as2js::node_t::NODE_CALL));
3676 1 : block_list->append_child(func);
3677 :
3678 : // { for(i := a + b, j := c / d; i < 100; ++i) { func(...); } }
3679 1 : as2js::node::pointer_t var_i4(std::make_shared<as2js::node>(as2js::node_t::NODE_IDENTIFIER));
3680 1 : var_i4->set_string("func");
3681 1 : func->append_child(var_i4);
3682 :
3683 : // { for(i := a + b, j := c / d; i < 100; ++i) { func(...); } }
3684 1 : as2js::node::pointer_t param_list(std::make_shared<as2js::node>(as2js::node_t::NODE_LIST));
3685 1 : func->append_child(param_list);
3686 :
3687 : // { for(i := a + b, j := c / d; i < 100; ++i) { func(i, ...); } }
3688 1 : as2js::node::pointer_t var_i5(std::make_shared<as2js::node>(as2js::node_t::NODE_IDENTIFIER));
3689 1 : var_i5->set_string("i");
3690 1 : param_list->append_child(var_i5);
3691 :
3692 : // { for(i := a + b, j := c / d; i < 100; ++i) { func(i, j); } }
3693 1 : as2js::node::pointer_t var_i6(std::make_shared<as2js::node>(as2js::node_t::NODE_IDENTIFIER));
3694 1 : var_i6->set_string("j");
3695 1 : param_list->append_child(var_i6);
3696 :
3697 : // since we have a tree with parents we can test an invalid parent
3698 : // which itself has a parent and get an error including the parent
3699 : // information
3700 1 : as2js::node::pointer_t test_list(std::make_shared<as2js::node>(as2js::node_t::NODE_DIRECTIVE_LIST));
3701 3 : CATCH_REQUIRE_THROWS_MATCHES(
3702 : test_list->set_parent(var_i5, 0)
3703 : , as2js::incompatible_type
3704 : , Catch::Matchers::ExceptionMessage(
3705 : "as2js_exception: invalid type: \"IDENTIFIER\" used as a parent node of child with type: \"DIRECTIVE_LIST\"."));
3706 :
3707 : // the DEFINED attribute applies to all types of nodes so it is easy to
3708 : // use... (would the test benefit from testing other attributes?)
3709 1 : root->set_attribute_tree(as2js::attribute_t::NODE_ATTR_DEFINED, true);
3710 1 : CATCH_REQUIRE(root->get_attribute(as2js::attribute_t::NODE_ATTR_DEFINED));
3711 1 : CATCH_REQUIRE(directive_list->get_attribute(as2js::attribute_t::NODE_ATTR_DEFINED));
3712 1 : CATCH_REQUIRE(for_loop->get_attribute(as2js::attribute_t::NODE_ATTR_DEFINED));
3713 1 : CATCH_REQUIRE(init->get_attribute(as2js::attribute_t::NODE_ATTR_DEFINED));
3714 1 : CATCH_REQUIRE(var1->get_attribute(as2js::attribute_t::NODE_ATTR_DEFINED));
3715 1 : CATCH_REQUIRE(variable1->get_attribute(as2js::attribute_t::NODE_ATTR_DEFINED));
3716 1 : CATCH_REQUIRE(variable_name1->get_attribute(as2js::attribute_t::NODE_ATTR_DEFINED));
3717 1 : CATCH_REQUIRE(value1->get_attribute(as2js::attribute_t::NODE_ATTR_DEFINED));
3718 1 : CATCH_REQUIRE(add1->get_attribute(as2js::attribute_t::NODE_ATTR_DEFINED));
3719 1 : CATCH_REQUIRE(var_a1->get_attribute(as2js::attribute_t::NODE_ATTR_DEFINED));
3720 1 : CATCH_REQUIRE(var_b1->get_attribute(as2js::attribute_t::NODE_ATTR_DEFINED));
3721 1 : CATCH_REQUIRE(var2->get_attribute(as2js::attribute_t::NODE_ATTR_DEFINED));
3722 1 : CATCH_REQUIRE(variable2->get_attribute(as2js::attribute_t::NODE_ATTR_DEFINED));
3723 1 : CATCH_REQUIRE(variable_name2->get_attribute(as2js::attribute_t::NODE_ATTR_DEFINED));
3724 1 : CATCH_REQUIRE(value2->get_attribute(as2js::attribute_t::NODE_ATTR_DEFINED));
3725 1 : CATCH_REQUIRE(divide2->get_attribute(as2js::attribute_t::NODE_ATTR_DEFINED));
3726 1 : CATCH_REQUIRE(var_a2->get_attribute(as2js::attribute_t::NODE_ATTR_DEFINED));
3727 1 : CATCH_REQUIRE(var_b2->get_attribute(as2js::attribute_t::NODE_ATTR_DEFINED));
3728 1 : CATCH_REQUIRE(less->get_attribute(as2js::attribute_t::NODE_ATTR_DEFINED));
3729 1 : CATCH_REQUIRE(var_i2->get_attribute(as2js::attribute_t::NODE_ATTR_DEFINED));
3730 1 : CATCH_REQUIRE(one_hunder->get_attribute(as2js::attribute_t::NODE_ATTR_DEFINED));
3731 1 : CATCH_REQUIRE(increment->get_attribute(as2js::attribute_t::NODE_ATTR_DEFINED));
3732 1 : CATCH_REQUIRE(var_i3->get_attribute(as2js::attribute_t::NODE_ATTR_DEFINED));
3733 1 : CATCH_REQUIRE(block_list->get_attribute(as2js::attribute_t::NODE_ATTR_DEFINED));
3734 1 : CATCH_REQUIRE(func->get_attribute(as2js::attribute_t::NODE_ATTR_DEFINED));
3735 1 : CATCH_REQUIRE(var_i4->get_attribute(as2js::attribute_t::NODE_ATTR_DEFINED));
3736 1 : CATCH_REQUIRE(param_list->get_attribute(as2js::attribute_t::NODE_ATTR_DEFINED));
3737 1 : CATCH_REQUIRE(var_i5->get_attribute(as2js::attribute_t::NODE_ATTR_DEFINED));
3738 1 : CATCH_REQUIRE(var_i6->get_attribute(as2js::attribute_t::NODE_ATTR_DEFINED));
3739 :
3740 : // now test the clearing of the attribute
3741 1 : root->set_attribute_tree(as2js::attribute_t::NODE_ATTR_DEFINED, false);
3742 1 : CATCH_REQUIRE(!root->get_attribute(as2js::attribute_t::NODE_ATTR_DEFINED));
3743 1 : CATCH_REQUIRE(!directive_list->get_attribute(as2js::attribute_t::NODE_ATTR_DEFINED));
3744 1 : CATCH_REQUIRE(!for_loop->get_attribute(as2js::attribute_t::NODE_ATTR_DEFINED));
3745 1 : CATCH_REQUIRE(!init->get_attribute(as2js::attribute_t::NODE_ATTR_DEFINED));
3746 1 : CATCH_REQUIRE(!var1->get_attribute(as2js::attribute_t::NODE_ATTR_DEFINED));
3747 1 : CATCH_REQUIRE(!variable1->get_attribute(as2js::attribute_t::NODE_ATTR_DEFINED));
3748 1 : CATCH_REQUIRE(!variable_name1->get_attribute(as2js::attribute_t::NODE_ATTR_DEFINED));
3749 1 : CATCH_REQUIRE(!value1->get_attribute(as2js::attribute_t::NODE_ATTR_DEFINED));
3750 1 : CATCH_REQUIRE(!add1->get_attribute(as2js::attribute_t::NODE_ATTR_DEFINED));
3751 1 : CATCH_REQUIRE(!var_a1->get_attribute(as2js::attribute_t::NODE_ATTR_DEFINED));
3752 1 : CATCH_REQUIRE(!var_b1->get_attribute(as2js::attribute_t::NODE_ATTR_DEFINED));
3753 1 : CATCH_REQUIRE(!var2->get_attribute(as2js::attribute_t::NODE_ATTR_DEFINED));
3754 1 : CATCH_REQUIRE(!variable2->get_attribute(as2js::attribute_t::NODE_ATTR_DEFINED));
3755 1 : CATCH_REQUIRE(!variable_name2->get_attribute(as2js::attribute_t::NODE_ATTR_DEFINED));
3756 1 : CATCH_REQUIRE(!value2->get_attribute(as2js::attribute_t::NODE_ATTR_DEFINED));
3757 1 : CATCH_REQUIRE(!divide2->get_attribute(as2js::attribute_t::NODE_ATTR_DEFINED));
3758 1 : CATCH_REQUIRE(!var_a2->get_attribute(as2js::attribute_t::NODE_ATTR_DEFINED));
3759 1 : CATCH_REQUIRE(!var_b2->get_attribute(as2js::attribute_t::NODE_ATTR_DEFINED));
3760 1 : CATCH_REQUIRE(!less->get_attribute(as2js::attribute_t::NODE_ATTR_DEFINED));
3761 1 : CATCH_REQUIRE(!var_i2->get_attribute(as2js::attribute_t::NODE_ATTR_DEFINED));
3762 1 : CATCH_REQUIRE(!one_hunder->get_attribute(as2js::attribute_t::NODE_ATTR_DEFINED));
3763 1 : CATCH_REQUIRE(!increment->get_attribute(as2js::attribute_t::NODE_ATTR_DEFINED));
3764 1 : CATCH_REQUIRE(!var_i3->get_attribute(as2js::attribute_t::NODE_ATTR_DEFINED));
3765 1 : CATCH_REQUIRE(!block_list->get_attribute(as2js::attribute_t::NODE_ATTR_DEFINED));
3766 1 : CATCH_REQUIRE(!func->get_attribute(as2js::attribute_t::NODE_ATTR_DEFINED));
3767 1 : CATCH_REQUIRE(!var_i4->get_attribute(as2js::attribute_t::NODE_ATTR_DEFINED));
3768 1 : CATCH_REQUIRE(!param_list->get_attribute(as2js::attribute_t::NODE_ATTR_DEFINED));
3769 1 : CATCH_REQUIRE(!var_i5->get_attribute(as2js::attribute_t::NODE_ATTR_DEFINED));
3770 1 : CATCH_REQUIRE(!var_i6->get_attribute(as2js::attribute_t::NODE_ATTR_DEFINED));
3771 1 : }
3772 1 : CATCH_END_SECTION()
3773 1 : }
3774 :
3775 :
3776 :
3777 : // vim: ts=4 sw=4 et
|