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/message.h> 24 : 25 : 26 : 27 : // self 28 : // 29 : #include "catch_main.h" 30 : 31 : 32 : // libutf8 33 : // 34 : #include <libutf8/iterator.h> 35 : #include <libutf8/libutf8.h> 36 : 37 : 38 : // snapdev 39 : // 40 : #include <snapdev/safe_stream.h> 41 : 42 : 43 : // C++ 44 : // 45 : #include <iomanip> 46 : 47 : 48 : // last include 49 : // 50 : #include <snapdev/poison.h> 51 : 52 : 53 : 54 : 55 : #include "catch_node_data.ci" 56 : 57 : 58 : 59 : 60 1 : CATCH_TEST_CASE("node_display_all_types", "[node][display][type]") 61 : { 62 1 : CATCH_START_SECTION("node_display_all_types: display all types") 63 : { 64 : // display all the different types available 65 : // this is "easy" so we do not have to test all 66 : // the potential flags, attributes, etc. 67 : // 68 219 : for(size_t i(0); i < g_node_types_size; ++i) 69 : { 70 : // get the type 71 218 : as2js::node_t const node_type(g_node_types[i].f_type); 72 218 : int node_type_int(static_cast<int>(node_type)); 73 : 74 : // get the next type of node 75 218 : as2js::node::pointer_t node(std::make_shared<as2js::node>(node_type)); 76 : 77 : // check the type 78 218 : CATCH_REQUIRE(node->get_type() == node_type); 79 : 80 218 : std::stringstream out; 81 218 : out << *node; 82 : 83 : // build the expected message 84 218 : std::stringstream expected; 85 : // indent is expected to be exactly 2 on startup and here we only have one line 86 : expected 87 218 : << node << ": " << std::setfill('0') << std::setw(2) << 2 88 218 : << std::setfill(' ') << '.' << std::setw(2) << ""; 89 218 : if(node_type_int == -1) 90 : { 91 : // special case for negative number (EOF) 92 : // 93 1 : expected << " -1"; 94 : } 95 : else 96 : { 97 217 : expected << std::setw(4) << std::setfill('0') << node_type_int; 98 : } 99 218 : expected << std::setfill('\0') << ": " << g_node_types[i].f_name; 100 : 101 : // add the type as a character if it represents just one character 102 218 : if(node_type_int > ' ' && node_type_int < 0x7F) 103 : { 104 24 : expected << " = '" << static_cast<char>(node_type_int) << "'"; 105 : } 106 : 107 218 : switch(node_type) 108 : { 109 21 : case as2js::node_t::NODE_BREAK: 110 : case as2js::node_t::NODE_CLASS: 111 : case as2js::node_t::NODE_CONTINUE: 112 : case as2js::node_t::NODE_ENUM: 113 : case as2js::node_t::NODE_FUNCTION: 114 : case as2js::node_t::NODE_GOTO: 115 : case as2js::node_t::NODE_IDENTIFIER: 116 : case as2js::node_t::NODE_IMPORT: 117 : case as2js::node_t::NODE_INTERFACE: 118 : case as2js::node_t::NODE_LABEL: 119 : case as2js::node_t::NODE_NAMESPACE: 120 : case as2js::node_t::NODE_PACKAGE: 121 : case as2js::node_t::NODE_REGULAR_EXPRESSION: 122 : case as2js::node_t::NODE_STRING: 123 : case as2js::node_t::NODE_TEMPLATE: 124 : case as2js::node_t::NODE_TEMPLATE_HEAD: 125 : case as2js::node_t::NODE_TEMPLATE_MIDDLE: 126 : case as2js::node_t::NODE_TEMPLATE_TAIL: 127 : case as2js::node_t::NODE_VARIABLE: 128 : case as2js::node_t::NODE_VAR_ATTRIBUTES: 129 : case as2js::node_t::NODE_VIDENTIFIER: 130 21 : output_str(expected, node->get_string()); 131 21 : break; 132 : 133 1 : case as2js::node_t::NODE_INTEGER: 134 : expected 135 3 : << ": " << node->get_integer().get() 136 1 : << ", 0x" 137 1 : << std::hex 138 : << std::setw(16) 139 1 : << std::setfill('0') 140 2 : << node->get_integer().get() 141 1 : << std::dec 142 : << std::setw(0) 143 3 : << std::setfill('\0'); 144 1 : break; 145 : 146 1 : case as2js::node_t::NODE_FLOATING_POINT: 147 1 : expected << ": " << node->get_floating_point().get(); 148 1 : break; 149 : 150 1 : case as2js::node_t::NODE_PARAM: 151 1 : output_str(expected, node->get_string()); 152 1 : expected << ":"; 153 1 : break; 154 : 155 8 : case as2js::node_t::NODE_CALL: 156 : case as2js::node_t::NODE_CATCH: 157 : case as2js::node_t::NODE_DIRECTIVE_LIST: 158 : case as2js::node_t::NODE_FOR: 159 : case as2js::node_t::NODE_PARAM_MATCH: 160 : case as2js::node_t::NODE_SWITCH: 161 : case as2js::node_t::NODE_TYPE: 162 : case as2js::node_t::NODE_VAR: 163 8 : expected << ":"; 164 8 : break; 165 : 166 186 : default: 167 186 : break; 168 : 169 : } 170 218 : expected << " (" << node->get_position() << ")" << std::endl; 171 : 172 : //std::cerr << "output [" << out.str() << "]\n"; 173 : //std::cerr << "expected [" << expected.str() << "]\n"; 174 : 175 218 : CATCH_REQUIRE(out.str() == expected.str()); 176 218 : } 177 : } 178 1 : CATCH_END_SECTION() 179 1 : } 180 : 181 : 182 1 : CATCH_TEST_CASE("node_display_unicode_string", "[node][display][unicode][string]") 183 : { 184 1 : CATCH_START_SECTION("node_display_unicode_string: verify Unicode") 185 : { 186 1 : int got_all(0); 187 8661 : for(std::size_t idx(0); idx < 100 || got_all != 7; ++idx) 188 : { 189 : // get a string node 190 8660 : as2js::node::pointer_t node(std::make_shared<as2js::node>(as2js::node_t::NODE_STRING)); 191 : 192 : // generate a random string 193 : // 194 8660 : std::string s; 195 2225620 : for(int j(0); j < 256; ++j) 196 : { 197 2216960 : char32_t c(U'\0'); 198 : do 199 : { 200 4184309 : c = ((rand() << 16) ^ rand()) & 0x1FFFFF; 201 : } 202 : while(c == U'\0' // skip null char 203 4184307 : || c > 0x10FFFF // too large (not unicode) 204 6405348 : || (c >= 0xD800 && c <= 0xDFFF)); // surrogate 205 2216960 : if(c < 0x7F) 206 : { 207 231 : got_all |= 1; 208 231 : if(c == '\'') 209 : { 210 1 : got_all |= 4; 211 : } 212 : } 213 : else 214 : { 215 2216729 : got_all |= 2; 216 : } 217 2216960 : s += libutf8::to_u8string(c); 218 : } 219 : 220 : // save random string in node 221 8660 : node->set_string(s); 222 : 223 : // display that now 224 8660 : std::stringstream out; 225 8660 : out << *node; 226 : 227 : // build the expected message 228 8660 : std::stringstream expected; 229 : // indent is expected to be exactly 2 on startup and here we only have one line 230 : expected 231 : << node 232 : << ": " 233 : << std::setfill('0') 234 8660 : << std::setw(2) 235 : << 2 236 : << std::setfill(' ') 237 : << '.' 238 : << std::setw(2) 239 : << "" 240 : << std::setw(4) 241 8660 : << std::setfill('0') 242 : << static_cast<int>(static_cast<as2js::node_t>(as2js::node_t::NODE_STRING)) 243 : << std::setfill('\0') 244 8660 : << ": STRING"; 245 8660 : output_str(expected, s); 246 8660 : expected << " (" << node->get_position() << ")" << std::endl; 247 : 248 : //std::cerr << "output [" << out.str() << "]\n"; 249 : //std::cerr << "expected [" << expected.str() << "]\n"; 250 : 251 8660 : CATCH_REQUIRE(out.str() == expected.str()); 252 8660 : } 253 : } 254 1 : CATCH_END_SECTION() 255 1 : } 256 : 257 : 258 1 : CATCH_TEST_CASE("node_display_flags", "[node][display][flags]") 259 : { 260 1 : CATCH_START_SECTION("node_display_flags: verify flags get printed") 261 : { 262 : // go through all the node types 263 : // 264 219 : for(std::size_t i(0); i < g_node_types_size; ++i) 265 : { 266 218 : std::size_t max_flags(0); 267 218 : for(flags_per_node_t const *flags(g_node_types[i].f_node_flags); 268 305 : flags->f_flag != as2js::flag_t::NODE_FLAG_max; 269 : ++flags) 270 : { 271 87 : ++max_flags; 272 : } 273 218 : if(max_flags == 0) 274 : { 275 : // ignore types without flags, they are not interesting here 276 : // 277 199 : continue; 278 : } 279 : 280 19 : as2js::node::pointer_t node(std::make_shared<as2js::node>(g_node_types[i].f_type)); 281 : 282 19 : if((g_node_types[i].f_flags & TEST_NODE_ACCEPT_STRING) != 0) 283 : { 284 11 : std::string const s(SNAP_CATCH2_NAMESPACE::random_string(0, 20, SNAP_CATCH2_NAMESPACE::character_t::CHARACTER_UNICODE)); 285 11 : node->set_string(s); 286 11 : } 287 : 288 19 : CATCH_REQUIRE(max_flags < sizeof(std::size_t) * 8); 289 19 : std::size_t const possibilities_max(1 << max_flags); 290 99531 : for(std::size_t j(0); j < possibilities_max; ++j) 291 : { 292 99512 : int pos(0); 293 99512 : for(flags_per_node_t const *flags(g_node_types[i].f_node_flags); 294 1585332 : flags->f_flag != as2js::flag_t::NODE_FLAG_max; 295 1485820 : ++flags, ++pos) 296 : { 297 1485820 : node->set_flag(flags->f_flag, ((1 << pos) & j) != 0); 298 : } 299 : 300 : // display that now 301 : // 302 99512 : std::stringstream out; 303 99512 : out << *node; 304 : 305 : // build the expected message 306 : // 307 99512 : std::stringstream expected; 308 : 309 : // indent is expected to be exactly 2 on startup and here we only have one line 310 : // 311 99512 : expected << node << ": " << std::setfill('0') << std::setw(2) << 2 << std::setfill(' ') << '.' << std::setw(2) << "" 312 99512 : << std::setw(4) << std::setfill('0') << static_cast<int>(g_node_types[i].f_type) 313 99512 : << std::setfill('\0') << ": " << g_node_types[i].f_name; 314 : 315 99512 : switch(g_node_types[i].f_type) 316 : { 317 65698 : case as2js::node_t::NODE_BREAK: 318 : case as2js::node_t::NODE_CLASS: 319 : case as2js::node_t::NODE_CONTINUE: 320 : case as2js::node_t::NODE_ENUM: 321 : case as2js::node_t::NODE_FUNCTION: 322 : case as2js::node_t::NODE_GOTO: 323 : case as2js::node_t::NODE_IDENTIFIER: 324 : case as2js::node_t::NODE_IMPORT: 325 : case as2js::node_t::NODE_INTERFACE: 326 : case as2js::node_t::NODE_LABEL: 327 : case as2js::node_t::NODE_NAMESPACE: 328 : case as2js::node_t::NODE_PACKAGE: 329 : case as2js::node_t::NODE_STRING: 330 : case as2js::node_t::NODE_VARIABLE: 331 : case as2js::node_t::NODE_VAR_ATTRIBUTES: 332 : case as2js::node_t::NODE_VIDENTIFIER: 333 65698 : output_str(expected, node->get_string()); 334 65698 : break; 335 : 336 0 : case as2js::node_t::NODE_INTEGER: 337 : expected 338 0 : << ": " 339 0 : << node->get_integer().get() 340 0 : << ", 0x" 341 0 : << std::hex 342 : << std::setw(16) 343 0 : << std::setfill('0') 344 0 : << node->get_integer().get() 345 0 : << std::dec 346 : << std::setw(0) 347 0 : << std::setfill('\0'); 348 0 : break; 349 : 350 0 : case as2js::node_t::NODE_FLOATING_POINT: 351 0 : expected << ": " << node->get_floating_point().get(); 352 0 : break; 353 : 354 1024 : case as2js::node_t::NODE_PARAM: 355 1024 : output_str(expected, node->get_string()); 356 1024 : expected << ':'; 357 1024 : break; 358 : 359 : //case as2js::node_t::NODE_PARAM_MATCH: 360 32790 : default: 361 32790 : expected << ':'; 362 32790 : break; 363 : 364 : } 365 : 366 99512 : pos = 0; 367 99512 : for(flags_per_node_t const *flags(g_node_types[i].f_node_flags); 368 1585332 : flags->f_flag != as2js::flag_t::NODE_FLAG_max; 369 1485820 : ++flags, ++pos) 370 : { 371 1485820 : if(((1 << pos) & j) != 0) 372 : { 373 742910 : expected << ' ' << flags->f_name; 374 : } 375 : } 376 : 377 99512 : expected << " (" << node->get_position() << ")" << std::endl; 378 : 379 : //std::cerr << "output [" << out.str() << "]\n"; 380 : //std::cerr << "expected [" << expected.str() << "]\n"; 381 : 382 99512 : CATCH_REQUIRE(out.str() == expected.str()); 383 99512 : } 384 19 : } 385 : } 386 1 : CATCH_END_SECTION() 387 1 : } 388 : 389 : 390 1 : CATCH_TEST_CASE("node_display_types_attributes", "[node][display][attributes]") 391 : { 392 1 : CATCH_START_SECTION("node_display_types_attributes: verify attributes get displayed") 393 : { 394 : // Test all the attributes in the output 395 : // 396 : // Note that we test all the attributes, although we always test 397 : // exactly 2 attributes in common... we may enhance this algorithm 398 : // later to test all the attributes in all possible combinasons, 399 : // but that is a bit tricky because of the conflicts. 400 : // 401 11 : for(int i(0); i < 10; ++i) 402 : { 403 : // create a node that is not a NODE_PROGRAM 404 : // (i.e. a node that accepts all attributes) 405 : std::size_t idx_node; 406 : do 407 : { 408 10 : idx_node = rand() % g_node_types_size; 409 : } 410 10 : while(g_node_types[idx_node].f_type == as2js::node_t::NODE_PROGRAM); 411 10 : as2js::node::pointer_t node(std::make_shared<as2js::node>(g_node_types[idx_node].f_type)); 412 : 413 10 : switch(g_node_types[idx_node].f_type) 414 : { 415 0 : case as2js::node_t::NODE_PARAM: 416 0 : node->set_string("param1"); 417 0 : break; 418 : 419 10 : default: 420 10 : break; 421 : 422 : } 423 : 424 : // need to test all combinatorial cases... 425 60 : for(std::size_t j(0); j < g_groups_of_attributes_size; ++j) 426 : { 427 : // go through the list of attributes that generate conflicts 428 190 : for(as2js::attribute_t const *attr_list(g_groups_of_attributes[j].f_attributes); 429 190 : *attr_list != as2js::attribute_t::NODE_ATTR_max; 430 : ++attr_list) 431 : { 432 140 : if(*attr_list == as2js::attribute_t::NODE_ATTR_TYPE) 433 : { 434 0 : switch(node->get_type()) 435 : { 436 0 : case as2js::node_t::NODE_ADD: 437 : case as2js::node_t::NODE_ARRAY: 438 : case as2js::node_t::NODE_ARRAY_LITERAL: 439 : case as2js::node_t::NODE_AS: 440 : case as2js::node_t::NODE_ASSIGNMENT: 441 : case as2js::node_t::NODE_ASSIGNMENT_ADD: 442 : case as2js::node_t::NODE_ASSIGNMENT_BITWISE_AND: 443 : case as2js::node_t::NODE_ASSIGNMENT_BITWISE_OR: 444 : case as2js::node_t::NODE_ASSIGNMENT_BITWISE_XOR: 445 : case as2js::node_t::NODE_ASSIGNMENT_DIVIDE: 446 : case as2js::node_t::NODE_ASSIGNMENT_LOGICAL_AND: 447 : case as2js::node_t::NODE_ASSIGNMENT_LOGICAL_OR: 448 : case as2js::node_t::NODE_ASSIGNMENT_LOGICAL_XOR: 449 : case as2js::node_t::NODE_ASSIGNMENT_MAXIMUM: 450 : case as2js::node_t::NODE_ASSIGNMENT_MINIMUM: 451 : case as2js::node_t::NODE_ASSIGNMENT_MODULO: 452 : case as2js::node_t::NODE_ASSIGNMENT_MULTIPLY: 453 : case as2js::node_t::NODE_ASSIGNMENT_POWER: 454 : case as2js::node_t::NODE_ASSIGNMENT_ROTATE_LEFT: 455 : case as2js::node_t::NODE_ASSIGNMENT_ROTATE_RIGHT: 456 : case as2js::node_t::NODE_ASSIGNMENT_SHIFT_LEFT: 457 : case as2js::node_t::NODE_ASSIGNMENT_SHIFT_RIGHT: 458 : case as2js::node_t::NODE_ASSIGNMENT_SHIFT_RIGHT_UNSIGNED: 459 : case as2js::node_t::NODE_ASSIGNMENT_SUBTRACT: 460 : case as2js::node_t::NODE_BITWISE_AND: 461 : case as2js::node_t::NODE_BITWISE_NOT: 462 : case as2js::node_t::NODE_BITWISE_OR: 463 : case as2js::node_t::NODE_BITWISE_XOR: 464 : case as2js::node_t::NODE_CALL: 465 : case as2js::node_t::NODE_CONDITIONAL: 466 : case as2js::node_t::NODE_DECREMENT: 467 : case as2js::node_t::NODE_DELETE: 468 : case as2js::node_t::NODE_DIVIDE: 469 : case as2js::node_t::NODE_EQUAL: 470 : case as2js::node_t::NODE_FALSE: 471 : case as2js::node_t::NODE_FLOATING_POINT: 472 : case as2js::node_t::NODE_FUNCTION: 473 : case as2js::node_t::NODE_GREATER: 474 : case as2js::node_t::NODE_GREATER_EQUAL: 475 : case as2js::node_t::NODE_IDENTIFIER: 476 : case as2js::node_t::NODE_IN: 477 : case as2js::node_t::NODE_INCREMENT: 478 : case as2js::node_t::NODE_INSTANCEOF: 479 : case as2js::node_t::NODE_INTEGER: 480 : case as2js::node_t::NODE_IS: 481 : case as2js::node_t::NODE_LESS: 482 : case as2js::node_t::NODE_LESS_EQUAL: 483 : case as2js::node_t::NODE_LIST: 484 : case as2js::node_t::NODE_LOGICAL_AND: 485 : case as2js::node_t::NODE_LOGICAL_NOT: 486 : case as2js::node_t::NODE_LOGICAL_OR: 487 : case as2js::node_t::NODE_LOGICAL_XOR: 488 : case as2js::node_t::NODE_MATCH: 489 : case as2js::node_t::NODE_MAXIMUM: 490 : case as2js::node_t::NODE_MEMBER: 491 : case as2js::node_t::NODE_MINIMUM: 492 : case as2js::node_t::NODE_MODULO: 493 : case as2js::node_t::NODE_MULTIPLY: 494 : case as2js::node_t::NODE_NAME: 495 : case as2js::node_t::NODE_NEW: 496 : case as2js::node_t::NODE_NOT_EQUAL: 497 : case as2js::node_t::NODE_NULL: 498 : case as2js::node_t::NODE_OBJECT_LITERAL: 499 : case as2js::node_t::NODE_POST_DECREMENT: 500 : case as2js::node_t::NODE_POST_INCREMENT: 501 : case as2js::node_t::NODE_POWER: 502 : case as2js::node_t::NODE_PRIVATE: 503 : case as2js::node_t::NODE_PUBLIC: 504 : case as2js::node_t::NODE_RANGE: 505 : case as2js::node_t::NODE_ROTATE_LEFT: 506 : case as2js::node_t::NODE_ROTATE_RIGHT: 507 : case as2js::node_t::NODE_SCOPE: 508 : case as2js::node_t::NODE_SHIFT_LEFT: 509 : case as2js::node_t::NODE_SHIFT_RIGHT: 510 : case as2js::node_t::NODE_SHIFT_RIGHT_UNSIGNED: 511 : case as2js::node_t::NODE_STRICTLY_EQUAL: 512 : case as2js::node_t::NODE_STRICTLY_NOT_EQUAL: 513 : case as2js::node_t::NODE_STRING: 514 : case as2js::node_t::NODE_SUBTRACT: 515 : case as2js::node_t::NODE_SUPER: 516 : case as2js::node_t::NODE_THIS: 517 : case as2js::node_t::NODE_TRUE: 518 : case as2js::node_t::NODE_TYPEOF: 519 : case as2js::node_t::NODE_UNDEFINED: 520 : case as2js::node_t::NODE_VIDENTIFIER: 521 : case as2js::node_t::NODE_VOID: 522 0 : break;; 523 : 524 0 : default: 525 : // with any other types we would get an error 526 : // 527 0 : continue; 528 : 529 : } 530 : } 531 : 532 : // set that one attribute first 533 : // 534 140 : node->set_attribute(*attr_list, true); 535 : 536 : // test against all the other attributes 537 : // 538 4340 : for(int a(0); a < static_cast<int>(as2js::attribute_t::NODE_ATTR_max); ++a) 539 : { 540 : // no need to test with itself, we do that earlier 541 : // 542 4200 : if(static_cast<as2js::attribute_t>(a) == *attr_list) 543 : { 544 140 : CATCH_REQUIRE(node->get_attribute(*attr_list)); 545 140 : continue; 546 140 : } 547 : 548 4060 : if(static_cast<as2js::attribute_t>(a) == as2js::attribute_t::NODE_ATTR_TYPE) 549 : { 550 140 : switch(node->get_type()) 551 : { 552 28 : case as2js::node_t::NODE_ADD: 553 : case as2js::node_t::NODE_ARRAY: 554 : case as2js::node_t::NODE_ARRAY_LITERAL: 555 : case as2js::node_t::NODE_AS: 556 : case as2js::node_t::NODE_ASSIGNMENT: 557 : case as2js::node_t::NODE_ASSIGNMENT_ADD: 558 : case as2js::node_t::NODE_ASSIGNMENT_BITWISE_AND: 559 : case as2js::node_t::NODE_ASSIGNMENT_BITWISE_OR: 560 : case as2js::node_t::NODE_ASSIGNMENT_BITWISE_XOR: 561 : case as2js::node_t::NODE_ASSIGNMENT_DIVIDE: 562 : case as2js::node_t::NODE_ASSIGNMENT_LOGICAL_AND: 563 : case as2js::node_t::NODE_ASSIGNMENT_LOGICAL_OR: 564 : case as2js::node_t::NODE_ASSIGNMENT_LOGICAL_XOR: 565 : case as2js::node_t::NODE_ASSIGNMENT_MAXIMUM: 566 : case as2js::node_t::NODE_ASSIGNMENT_MINIMUM: 567 : case as2js::node_t::NODE_ASSIGNMENT_MODULO: 568 : case as2js::node_t::NODE_ASSIGNMENT_MULTIPLY: 569 : case as2js::node_t::NODE_ASSIGNMENT_POWER: 570 : case as2js::node_t::NODE_ASSIGNMENT_ROTATE_LEFT: 571 : case as2js::node_t::NODE_ASSIGNMENT_ROTATE_RIGHT: 572 : case as2js::node_t::NODE_ASSIGNMENT_SHIFT_LEFT: 573 : case as2js::node_t::NODE_ASSIGNMENT_SHIFT_RIGHT: 574 : case as2js::node_t::NODE_ASSIGNMENT_SHIFT_RIGHT_UNSIGNED: 575 : case as2js::node_t::NODE_ASSIGNMENT_SUBTRACT: 576 : case as2js::node_t::NODE_BITWISE_AND: 577 : case as2js::node_t::NODE_BITWISE_NOT: 578 : case as2js::node_t::NODE_BITWISE_OR: 579 : case as2js::node_t::NODE_BITWISE_XOR: 580 : case as2js::node_t::NODE_CALL: 581 : case as2js::node_t::NODE_CONDITIONAL: 582 : case as2js::node_t::NODE_DECREMENT: 583 : case as2js::node_t::NODE_DELETE: 584 : case as2js::node_t::NODE_DIVIDE: 585 : case as2js::node_t::NODE_EQUAL: 586 : case as2js::node_t::NODE_FALSE: 587 : case as2js::node_t::NODE_FLOATING_POINT: 588 : case as2js::node_t::NODE_FUNCTION: 589 : case as2js::node_t::NODE_GREATER: 590 : case as2js::node_t::NODE_GREATER_EQUAL: 591 : case as2js::node_t::NODE_IDENTIFIER: 592 : case as2js::node_t::NODE_IN: 593 : case as2js::node_t::NODE_INCREMENT: 594 : case as2js::node_t::NODE_INSTANCEOF: 595 : case as2js::node_t::NODE_INTEGER: 596 : case as2js::node_t::NODE_IS: 597 : case as2js::node_t::NODE_LESS: 598 : case as2js::node_t::NODE_LESS_EQUAL: 599 : case as2js::node_t::NODE_LIST: 600 : case as2js::node_t::NODE_LOGICAL_AND: 601 : case as2js::node_t::NODE_LOGICAL_NOT: 602 : case as2js::node_t::NODE_LOGICAL_OR: 603 : case as2js::node_t::NODE_LOGICAL_XOR: 604 : case as2js::node_t::NODE_MATCH: 605 : case as2js::node_t::NODE_MAXIMUM: 606 : case as2js::node_t::NODE_MEMBER: 607 : case as2js::node_t::NODE_MINIMUM: 608 : case as2js::node_t::NODE_MODULO: 609 : case as2js::node_t::NODE_MULTIPLY: 610 : case as2js::node_t::NODE_NAME: 611 : case as2js::node_t::NODE_NEW: 612 : case as2js::node_t::NODE_NOT_EQUAL: 613 : case as2js::node_t::NODE_NULL: 614 : case as2js::node_t::NODE_OBJECT_LITERAL: 615 : case as2js::node_t::NODE_POST_DECREMENT: 616 : case as2js::node_t::NODE_POST_INCREMENT: 617 : case as2js::node_t::NODE_POWER: 618 : case as2js::node_t::NODE_PRIVATE: 619 : case as2js::node_t::NODE_PUBLIC: 620 : case as2js::node_t::NODE_RANGE: 621 : case as2js::node_t::NODE_ROTATE_LEFT: 622 : case as2js::node_t::NODE_ROTATE_RIGHT: 623 : case as2js::node_t::NODE_SCOPE: 624 : case as2js::node_t::NODE_SHIFT_LEFT: 625 : case as2js::node_t::NODE_SHIFT_RIGHT: 626 : case as2js::node_t::NODE_SHIFT_RIGHT_UNSIGNED: 627 : case as2js::node_t::NODE_STRICTLY_EQUAL: 628 : case as2js::node_t::NODE_STRICTLY_NOT_EQUAL: 629 : case as2js::node_t::NODE_STRING: 630 : case as2js::node_t::NODE_SUBTRACT: 631 : case as2js::node_t::NODE_SUPER: 632 : case as2js::node_t::NODE_THIS: 633 : case as2js::node_t::NODE_TRUE: 634 : case as2js::node_t::NODE_TYPEOF: 635 : case as2js::node_t::NODE_UNDEFINED: 636 : case as2js::node_t::NODE_VIDENTIFIER: 637 : case as2js::node_t::NODE_VOID: 638 28 : break;; 639 : 640 112 : default: 641 : // with any other types we would get an error 642 112 : continue; 643 : 644 : } 645 : } 646 : 647 : // is attribute 'a' in conflict with attribute '*attr_list'? 648 : // 649 3948 : if(!in_conflict(j, *attr_list, static_cast<as2js::attribute_t>(a))) 650 : { 651 : // if in conflict we do not care much here because the 652 : // display is going to be exactly the same 653 : // 654 3628 : node->set_attribute(static_cast<as2js::attribute_t>(a), true); 655 : 656 : // display that now 657 : // 658 3628 : std::stringstream out; 659 3628 : out << *node; 660 : 661 : // build the expected message 662 : // 663 3628 : std::stringstream expected; 664 : 665 : // indent is expected to be exactly 2 on startup and here we only have one line 666 : // 667 : expected 668 : << node 669 : << ": " 670 : << std::setfill('0') 671 3628 : << std::setw(2) 672 : << 2 673 : << std::setfill(' ') 674 : << '.' 675 : << std::setw(2) 676 3628 : << ""; 677 3628 : if(g_node_types[idx_node].f_type == as2js::node_t::NODE_EOF) 678 : { 679 : expected 680 : << std::setw(4) 681 360 : << std::setfill(' ') 682 360 : << static_cast<int>(g_node_types[idx_node].f_type); 683 : } 684 : else 685 : { 686 : expected 687 : << std::setw(4) 688 3268 : << std::setfill('0') 689 3268 : << static_cast<int>(g_node_types[idx_node].f_type); 690 : } 691 : expected 692 : << std::setfill('\0') 693 : << ": " 694 3628 : << g_node_types[idx_node].f_name; 695 : 696 : // add the type as a character if it represents just one character 697 : // 698 3628 : if(static_cast<int>(g_node_types[idx_node].f_type) > ' ' 699 3268 : && static_cast<int>(g_node_types[idx_node].f_type) < 0x7F) 700 : { 701 360 : expected << " = '" << static_cast<char>(static_cast<int>(g_node_types[idx_node].f_type)) << "'"; 702 : } 703 : 704 3628 : switch(g_node_types[idx_node].f_type) 705 : { 706 0 : case as2js::node_t::NODE_BREAK: 707 : case as2js::node_t::NODE_CLASS: 708 : case as2js::node_t::NODE_CONTINUE: 709 : case as2js::node_t::NODE_ENUM: 710 : case as2js::node_t::NODE_FUNCTION: 711 : case as2js::node_t::NODE_GOTO: 712 : case as2js::node_t::NODE_IDENTIFIER: 713 : case as2js::node_t::NODE_IMPORT: 714 : case as2js::node_t::NODE_INTERFACE: 715 : case as2js::node_t::NODE_LABEL: 716 : case as2js::node_t::NODE_NAMESPACE: 717 : case as2js::node_t::NODE_PACKAGE: 718 : case as2js::node_t::NODE_REGULAR_EXPRESSION: 719 : case as2js::node_t::NODE_STRING: 720 : case as2js::node_t::NODE_TEMPLATE: 721 : case as2js::node_t::NODE_TEMPLATE_HEAD: 722 : case as2js::node_t::NODE_TEMPLATE_MIDDLE: 723 : case as2js::node_t::NODE_TEMPLATE_TAIL: 724 : case as2js::node_t::NODE_VARIABLE: 725 : case as2js::node_t::NODE_VAR_ATTRIBUTES: 726 : case as2js::node_t::NODE_VIDENTIFIER: 727 0 : output_str(expected, node->get_string()); 728 0 : break; 729 : 730 0 : case as2js::node_t::NODE_INTEGER: 731 : expected 732 0 : << ": " << node->get_integer().get() 733 0 : << ", 0x" 734 0 : << std::hex 735 : << std::setw(16) 736 0 : << std::setfill('0') 737 0 : << node->get_integer().get() 738 0 : << std::dec << std::setw(0) 739 0 : << std::setfill('\0'); 740 0 : break; 741 : 742 0 : case as2js::node_t::NODE_FLOATING_POINT: 743 0 : expected << ": " << node->get_floating_point().get(); 744 0 : break; 745 : 746 0 : case as2js::node_t::NODE_CALL: 747 : case as2js::node_t::NODE_CATCH: 748 : case as2js::node_t::NODE_DIRECTIVE_LIST: 749 : case as2js::node_t::NODE_FOR: 750 : case as2js::node_t::NODE_PARAM_MATCH: 751 : case as2js::node_t::NODE_SWITCH: 752 : case as2js::node_t::NODE_TYPE: 753 : case as2js::node_t::NODE_VAR: 754 0 : expected << ":"; 755 0 : break; 756 : 757 0 : case as2js::node_t::NODE_PARAM: 758 0 : expected << ": 'param1':"; 759 0 : break; 760 : 761 3628 : default: 762 3628 : break; 763 : 764 : } 765 : 766 3628 : int pa(a); 767 3628 : int pb(static_cast<int>(*attr_list)); 768 3628 : if(pa > pb) 769 : { 770 1918 : std::swap(pa, pb); 771 : } 772 3628 : expected << " attrs: " << g_attribute_names[pa] << " " << g_attribute_names[pb]; 773 : 774 3628 : expected << " (" << node->get_position() << ")" << std::endl; 775 : 776 : //std::cerr << " output [" << out.str() << "]\n"; 777 : //std::cerr << "expected [" << expected.str() << "] (for: " << static_cast<int>(*attr_list) << " / " << a << ")\n"; 778 : 779 3628 : CATCH_REQUIRE(out.str() == expected.str()); 780 : 781 3628 : node->set_attribute(static_cast<as2js::attribute_t>(a), false); 782 3628 : } 783 : } 784 : 785 : // we are done with that loop, restore the attribute to the default 786 140 : node->set_attribute(*attr_list, false); 787 : } 788 : } 789 10 : } 790 : } 791 1 : CATCH_END_SECTION() 792 1 : } 793 : 794 : 795 1 : CATCH_TEST_CASE("node_display_tree", "[node][display][tree]") 796 : { 797 1 : CATCH_START_SECTION("node_display_tree: display a tree of nodes") 798 : { 799 : // create all the nodes as the lexer would do 800 1 : as2js::node::pointer_t root(std::make_shared<as2js::node>(as2js::node_t::NODE_ROOT)); 801 1 : as2js::position pos; 802 1 : pos.reset_counters(22); 803 1 : pos.set_filename("display.js"); 804 1 : root->set_position(pos); 805 1 : as2js::node::pointer_t directive_list_a(std::make_shared<as2js::node>(as2js::node_t::NODE_DIRECTIVE_LIST)); 806 1 : as2js::node::pointer_t directive_list_b(std::make_shared<as2js::node>(as2js::node_t::NODE_DIRECTIVE_LIST)); 807 1 : directive_list_b->set_flag(as2js::flag_t::NODE_DIRECTIVE_LIST_FLAG_NEW_VARIABLES, true); 808 1 : as2js::node::pointer_t assignment(std::make_shared<as2js::node>(as2js::node_t::NODE_ASSIGNMENT)); 809 1 : as2js::node::pointer_t identifier_a(std::make_shared<as2js::node>(as2js::node_t::NODE_IDENTIFIER)); 810 1 : identifier_a->set_string("a"); 811 1 : identifier_a->set_attribute(as2js::attribute_t::NODE_ATTR_TRUE, true); 812 1 : as2js::node::pointer_t power(std::make_shared<as2js::node>(as2js::node_t::NODE_POWER)); 813 1 : as2js::node::pointer_t member(std::make_shared<as2js::node>(as2js::node_t::NODE_MEMBER)); 814 1 : as2js::node::pointer_t identifier_math(std::make_shared<as2js::node>(as2js::node_t::NODE_IDENTIFIER)); 815 1 : identifier_math->set_string("Math"); 816 1 : identifier_math->set_attribute(as2js::attribute_t::NODE_ATTR_NATIVE, true); 817 1 : as2js::node::pointer_t math_type(std::make_shared<as2js::node>(as2js::node_t::NODE_IDENTIFIER)); 818 1 : math_type->set_string("Math"); 819 1 : identifier_math->set_type_node(math_type); 820 1 : as2js::node::pointer_t math_instance(std::make_shared<as2js::node>(as2js::node_t::NODE_IDENTIFIER)); 821 1 : math_instance->set_string("m"); 822 1 : identifier_math->set_instance(math_instance); 823 1 : as2js::node::pointer_t identifier_e(std::make_shared<as2js::node>(as2js::node_t::NODE_IDENTIFIER)); 824 1 : identifier_e->set_string("e"); 825 1 : identifier_e->set_flag(as2js::flag_t::NODE_IDENTIFIER_FLAG_TYPED, true); 826 1 : as2js::node::pointer_t e_type(std::make_shared<as2js::node>(as2js::node_t::NODE_IDENTIFIER)); 827 1 : e_type->set_string("Float"); 828 1 : identifier_e->set_type_node(e_type); 829 1 : as2js::node::pointer_t literal(std::make_shared<as2js::node>(as2js::node_t::NODE_FLOATING_POINT)); 830 1 : as2js::floating_point f; 831 1 : f.set(1.424); 832 1 : literal->set_floating_point(f); 833 1 : as2js::node::pointer_t function(std::make_shared<as2js::node>(as2js::node_t::NODE_FUNCTION)); 834 1 : function->set_string("my_func"); 835 1 : as2js::node::pointer_t func_var(std::make_shared<as2js::node>(as2js::node_t::NODE_VAR)); 836 1 : as2js::node::pointer_t func_variable(std::make_shared<as2js::node>(as2js::node_t::NODE_VARIABLE)); 837 1 : func_variable->set_string("q"); 838 1 : as2js::node::pointer_t label(std::make_shared<as2js::node>(as2js::node_t::NODE_LABEL)); 839 1 : label->set_string("ignore"); 840 1 : function->add_label(label); 841 1 : function->add_variable(func_variable); 842 : 843 : // build the tree as the parser would do 844 1 : root->append_child(directive_list_a); 845 1 : root->append_child(directive_list_b); 846 1 : directive_list_a->append_child(assignment); 847 1 : assignment->append_child(identifier_a); 848 1 : assignment->insert_child(-1, power); 849 1 : power->append_child(member); 850 1 : power->insert_child(1, literal); 851 1 : member->append_child(identifier_e); 852 1 : member->insert_child(0, identifier_math); 853 1 : directive_list_b->append_child(function); 854 1 : function->append_child(func_var); 855 1 : func_var->append_child(func_variable); 856 1 : function->append_child(label); 857 : 858 : // now test the output 859 1 : std::stringstream out; 860 1 : out << *root; 861 : 862 : // build the expected message 863 1 : std::stringstream expected; 864 : 865 : // ROOT 866 1 : expected << root << ": " << std::setfill('0') << std::setw(2) << 2 << std::setfill(' ') << '.' << std::setw(2) << "" 867 1 : << std::setw(4) << std::setfill('0') << static_cast<int>(static_cast<as2js::node_t>(as2js::node_t::NODE_ROOT)) 868 : << std::setfill('\0') << ": ROOT" 869 1 : << " (" << root->get_position() << ")" << std::endl; 870 : 871 : // DIRECTIVE_LIST A 872 1 : expected << directive_list_a << ": " << std::setfill('0') << std::setw(2) << 3 << std::setfill(' ') << '-' << std::setw(3) << "" 873 1 : << std::setw(4) << std::setfill('0') << static_cast<int>(static_cast<as2js::node_t>(as2js::node_t::NODE_DIRECTIVE_LIST)) 874 : << std::setfill('\0') << ": DIRECTIVE_LIST:" 875 1 : << " (" << directive_list_a->get_position() << ")" << std::endl; 876 : 877 : // ASSIGNMENT 878 1 : expected << assignment << ": " << std::setfill('0') << std::setw(2) << 4 << std::setfill(' ') << '-' << std::setw(4) << "" 879 1 : << std::setw(4) << std::setfill('0') << static_cast<int>(static_cast<as2js::node_t>(as2js::node_t::NODE_ASSIGNMENT)) 880 : << std::setfill('\0') << ": ASSIGNMENT = '='" 881 1 : << " (" << assignment->get_position() << ")" << std::endl; 882 : 883 : // IDENTIFIER A 884 1 : expected << identifier_a << ": " << std::setfill('0') << std::setw(2) << 5 << std::setfill(' ') << '-' << std::setw(5) << "" 885 1 : << std::setw(4) << std::setfill('0') << static_cast<int>(static_cast<as2js::node_t>(as2js::node_t::NODE_IDENTIFIER)) 886 : << std::setfill('\0') << ": IDENTIFIER: 'a' attrs: TRUE" 887 1 : << " (" << identifier_a->get_position() << ")" << std::endl; 888 : 889 : // POWER 890 1 : expected << power << ": " << std::setfill('0') << std::setw(2) << 5 << std::setfill(' ') << '-' << std::setw(5) << "" 891 1 : << std::setw(4) << std::setfill('0') << static_cast<int>(static_cast<as2js::node_t>(as2js::node_t::NODE_POWER)) 892 : << std::setfill('\0') << ": POWER" 893 1 : << " (" << power->get_position() << ")" << std::endl; 894 : 895 : // MEMBER 896 1 : expected << member << ": " << std::setfill('0') << std::setw(2) << 6 << std::setfill(' ') << '-' << std::setw(6) << "" 897 1 : << std::setw(4) << std::setfill('0') << static_cast<int>(static_cast<as2js::node_t>(as2js::node_t::NODE_MEMBER)) 898 : << std::setfill('\0') << ": MEMBER = '.'" 899 1 : << " (" << member->get_position() << ")" << std::endl; 900 : 901 : // IDENTIFIER MATH 902 1 : expected << identifier_math << ": " << std::setfill('0') << std::setw(2) << 7 << std::setfill(' ') << '-' << std::setw(7) << "" 903 1 : << std::setw(4) << std::setfill('0') << static_cast<int>(static_cast<as2js::node_t>(as2js::node_t::NODE_IDENTIFIER)) 904 : << std::setfill('\0') << ": IDENTIFIER: 'Math' Instance: " << math_instance << " Type node: " << math_type << " attrs: NATIVE" 905 1 : << " (" << identifier_math->get_position() << ")" << std::endl; 906 : 907 : // IDENTIFIER E 908 1 : expected << identifier_e << ": " << std::setfill('0') << std::setw(2) << 7 << std::setfill(' ') << '-' << std::setw(7) << "" 909 1 : << std::setw(4) << std::setfill('0') << static_cast<int>(static_cast<as2js::node_t>(as2js::node_t::NODE_IDENTIFIER)) 910 : << std::setfill('\0') << ": IDENTIFIER: 'e' TYPED Type node: " << e_type 911 1 : << " (" << identifier_e->get_position() << ")" << std::endl; 912 : 913 : // FLOATING_POINT 914 1 : expected << literal << ": " << std::setfill('0') << std::setw(2) << 6 << std::setfill(' ') << '-' << std::setw(6) << "" 915 1 : << std::setw(4) << std::setfill('0') << static_cast<int>(static_cast<as2js::node_t>(as2js::node_t::NODE_FLOATING_POINT)) 916 : << std::setfill('\0') << ": FLOATING_POINT: 1.424" 917 1 : << " (" << literal->get_position() << ")" << std::endl; 918 : 919 : // DIRECTIVE_LIST B 920 1 : expected << directive_list_b << ": " << std::setfill('0') << std::setw(2) << 3 << std::setfill(' ') << '-' << std::setw(3) << "" 921 1 : << std::setw(4) << std::setfill('0') << static_cast<int>(static_cast<as2js::node_t>(as2js::node_t::NODE_DIRECTIVE_LIST)) 922 : << std::setfill('\0') << ": DIRECTIVE_LIST: NEW-VARIABLES" 923 1 : << " (" << directive_list_b->get_position() << ")" << std::endl; 924 : 925 : // FUNCTION 926 1 : expected << function << ": " << std::setfill('0') << std::setw(2) << 4 << std::setfill(' ') << '-' << std::setw(4) << "" 927 1 : << std::setw(4) << std::setfill('0') << static_cast<int>(static_cast<as2js::node_t>(as2js::node_t::NODE_FUNCTION)) 928 : << std::setfill('\0') << ": FUNCTION: 'my_func'" 929 1 : << " (" << function->get_position() << ")" << std::endl; 930 : 931 : // VAR 932 1 : expected << func_var << ": " << std::setfill('0') << std::setw(2) << 5 << std::setfill(' ') << '-' << std::setw(5) << "" 933 1 : << std::setw(4) << std::setfill('0') << static_cast<int>(static_cast<as2js::node_t>(as2js::node_t::NODE_VAR)) 934 : << std::setfill('\0') << ": VAR:" 935 1 : << " (" << func_var->get_position() << ")" << std::endl; 936 : 937 : // VARIABLE 938 1 : expected << func_variable << ": " << std::setfill('0') << std::setw(2) << 6 << std::setfill(' ') << '-' << std::setw(6) << "" 939 1 : << std::setw(4) << std::setfill('0') << static_cast<int>(static_cast<as2js::node_t>(as2js::node_t::NODE_VARIABLE)) 940 : << std::setfill('\0') << ": VARIABLE: 'q'" 941 1 : << " (" << func_variable->get_position() << ")" << std::endl; 942 : 943 : // LABEL 944 1 : expected << label << ": " << std::setfill('0') << std::setw(2) << 5 << std::setfill(' ') << '-' << std::setw(5) << "" 945 1 : << std::setw(4) << std::setfill('0') << static_cast<int>(static_cast<as2js::node_t>(as2js::node_t::NODE_LABEL)) 946 : << std::setfill('\0') << ": LABEL: 'ignore'" 947 1 : << " (" << label->get_position() << ")" << std::endl; 948 : 949 : // VARIABLE 950 1 : expected << func_variable << ": " << std::setfill('0') << std::setw(2) << 5 << std::setfill(' ') << '=' << std::setw(5) << "" 951 1 : << std::setw(4) << std::setfill('0') << static_cast<int>(static_cast<as2js::node_t>(as2js::node_t::NODE_VARIABLE)) 952 : << std::setfill('\0') << ": VARIABLE: 'q'" 953 1 : << " (" << func_variable->get_position() << ")" << std::endl; 954 : 955 : // LABEL 956 1 : expected << label << ": " << std::setfill('0') << std::setw(2) << 5 << std::setfill(' ') << ':' << std::setw(5) << "" 957 1 : << std::setw(4) << std::setfill('0') << static_cast<int>(static_cast<as2js::node_t>(as2js::node_t::NODE_LABEL)) 958 : << std::setfill('\0') << ": LABEL: 'ignore'" 959 1 : << " (" << label->get_position() << ")" << std::endl; 960 : 961 : //std::cerr << "output [" << out.str() << "]\n"; 962 : //std::cerr << "expected [" << expected.str() << "]\n"; 963 : 964 1 : CATCH_REQUIRE(out.str() == expected.str()); 965 1 : } 966 1 : CATCH_END_SECTION() 967 1 : } 968 : 969 : 970 : // vim: ts=4 sw=4 et