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