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 187 : for(size_t i(0); i < g_node_types_size; ++i) 69 : { 70 : // get the type 71 186 : as2js::node_t const node_type(g_node_types[i].f_type); 72 186 : int node_type_int(static_cast<int>(node_type)); 73 : 74 : // get the next type of node 75 186 : as2js::node::pointer_t node(std::make_shared<as2js::node>(node_type)); 76 : 77 : // check the type 78 186 : CATCH_REQUIRE(node->get_type() == node_type); 79 : 80 186 : std::stringstream out; 81 186 : out << *node; 82 : 83 : // build the expected message 84 186 : std::stringstream expected; 85 : // indent is expected to be exactly 2 on startup and here we only have one line 86 : expected 87 186 : << node << ": " << std::setfill('0') << std::setw(2) << 2 88 186 : << std::setfill(' ') << '.' << std::setw(2) << ""; 89 186 : if(node_type_int == -1) 90 : { 91 : // special case for negative number (EOF) 92 : // 93 1 : expected << " -1"; 94 : } 95 : else 96 : { 97 185 : expected << std::setw(4) << std::setfill('0') << node_type_int; 98 : } 99 186 : 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 186 : if(node_type_int > ' ' && node_type_int < 0x7F) 103 : { 104 24 : expected << " = '" << static_cast<char>(node_type_int) << "'"; 105 : } 106 : 107 186 : 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 154 : default: 167 154 : break; 168 : 169 : } 170 186 : expected << " (" << node->get_position() << ")" << std::endl; 171 : 172 : //std::cerr << "output [" << out.str() << "]\n"; 173 : //std::cerr << "expected [" << expected.str() << "]\n"; 174 : 175 186 : CATCH_REQUIRE(out.str() == expected.str()); 176 186 : } 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 5027 : for(std::size_t idx(0); idx < 100 || got_all != 7; ++idx) 188 : { 189 : // get a string node 190 5026 : as2js::node::pointer_t node(std::make_shared<as2js::node>(as2js::node_t::NODE_STRING)); 191 : 192 : // generate a random string 193 : // 194 5026 : std::string s; 195 1291682 : for(int j(0); j < 256; ++j) 196 : { 197 1286656 : char32_t c(U'\0'); 198 : do 199 : { 200 2427566 : c = ((rand() << 16) ^ rand()) & 0x1FFFFF; 201 : } 202 : while(c == U'\0' // skip null char 203 2427566 : || c > 0x10FFFF // too large (not unicode) 204 3716631 : || (c >= 0xD800 && c <= 0xDFFF)); // surrogate 205 1286656 : if(c < 0x7F) 206 : { 207 147 : got_all |= 1; 208 147 : if(c == '\'') 209 : { 210 1 : got_all |= 4; 211 : } 212 : } 213 : else 214 : { 215 1286509 : got_all |= 2; 216 : } 217 1286656 : s += libutf8::to_u8string(c); 218 : } 219 : 220 : // save random string in node 221 5026 : node->set_string(s); 222 : 223 : // display that now 224 5026 : std::stringstream out; 225 5026 : out << *node; 226 : 227 : // build the expected message 228 5026 : 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 5026 : << std::setw(2) 235 : << 2 236 : << std::setfill(' ') 237 : << '.' 238 : << std::setw(2) 239 : << "" 240 : << std::setw(4) 241 5026 : << std::setfill('0') 242 : << static_cast<int>(static_cast<as2js::node_t>(as2js::node_t::NODE_STRING)) 243 : << std::setfill('\0') 244 5026 : << ": STRING"; 245 5026 : output_str(expected, s); 246 5026 : expected << " (" << node->get_position() << ")" << std::endl; 247 : 248 : //std::cerr << "output [" << out.str() << "]\n"; 249 : //std::cerr << "expected [" << expected.str() << "]\n"; 250 : 251 5026 : CATCH_REQUIRE(out.str() == expected.str()); 252 5026 : } 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 187 : for(std::size_t i(0); i < g_node_types_size; ++i) 265 : { 266 186 : std::size_t max_flags(0); 267 186 : for(flags_per_node_t const *flags(g_node_types[i].f_node_flags); 268 266 : flags->f_flag != as2js::flag_t::NODE_FLAG_max; 269 : ++flags) 270 : { 271 80 : ++max_flags; 272 : } 273 186 : if(max_flags == 0) 274 : { 275 : // ignore types without flags, they are not interesting here 276 : // 277 167 : 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 25801 : for(std::size_t j(0); j < possibilities_max; ++j) 291 : { 292 25782 : int pos(0); 293 25782 : for(flags_per_node_t const *flags(g_node_types[i].f_node_flags); 294 356524 : flags->f_flag != as2js::flag_t::NODE_FLAG_max; 295 330742 : ++flags, ++pos) 296 : { 297 330742 : node->set_flag(flags->f_flag, ((1 << pos) & j) != 0); 298 : } 299 : 300 : // display that now 301 : // 302 25782 : std::stringstream out; 303 25782 : out << *node; 304 : 305 : // build the expected message 306 : // 307 25782 : std::stringstream expected; 308 : 309 : // indent is expected to be exactly 2 on startup and here we only have one line 310 : // 311 25782 : expected << node << ": " << std::setfill('0') << std::setw(2) << 2 << std::setfill(' ') << '.' << std::setw(2) << "" 312 25782 : << std::setw(4) << std::setfill('0') << static_cast<int>(g_node_types[i].f_type) 313 25782 : << std::setfill('\0') << ": " << g_node_types[i].f_name; 314 : 315 25782 : switch(g_node_types[i].f_type) 316 : { 317 16546 : 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 16546 : output_str(expected, node->get_string()); 334 16546 : 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 8212 : default: 361 8212 : expected << ':'; 362 8212 : break; 363 : 364 : } 365 : 366 25782 : pos = 0; 367 25782 : for(flags_per_node_t const *flags(g_node_types[i].f_node_flags); 368 356524 : flags->f_flag != as2js::flag_t::NODE_FLAG_max; 369 330742 : ++flags, ++pos) 370 : { 371 330742 : if(((1 << pos) & j) != 0) 372 : { 373 165371 : expected << ' ' << flags->f_name; 374 : } 375 : } 376 : 377 25782 : expected << " (" << node->get_position() << ")" << std::endl; 378 : 379 : //std::cerr << "output [" << out.str() << "]\n"; 380 : //std::cerr << "expected [" << expected.str() << "]\n"; 381 : 382 25782 : CATCH_REQUIRE(out.str() == expected.str()); 383 25782 : } 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 0 : continue; 527 : 528 : } 529 : } 530 : 531 : // set that one attribute first 532 140 : node->set_attribute(*attr_list, true); 533 : 534 : // test against all the other attributes 535 4200 : for(int a(0); a < static_cast<int>(as2js::attribute_t::NODE_ATTR_max); ++a) 536 : { 537 : // no need to test with itself, we do that earlier 538 4060 : if(static_cast<as2js::attribute_t>(a) == *attr_list) 539 : { 540 140 : continue; 541 : } 542 : 543 3920 : if(static_cast<as2js::attribute_t>(a) == as2js::attribute_t::NODE_ATTR_TYPE) 544 : { 545 140 : switch(node->get_type()) 546 : { 547 56 : case as2js::node_t::NODE_ADD: 548 : case as2js::node_t::NODE_ARRAY: 549 : case as2js::node_t::NODE_ARRAY_LITERAL: 550 : case as2js::node_t::NODE_AS: 551 : case as2js::node_t::NODE_ASSIGNMENT: 552 : case as2js::node_t::NODE_ASSIGNMENT_ADD: 553 : case as2js::node_t::NODE_ASSIGNMENT_BITWISE_AND: 554 : case as2js::node_t::NODE_ASSIGNMENT_BITWISE_OR: 555 : case as2js::node_t::NODE_ASSIGNMENT_BITWISE_XOR: 556 : case as2js::node_t::NODE_ASSIGNMENT_DIVIDE: 557 : case as2js::node_t::NODE_ASSIGNMENT_LOGICAL_AND: 558 : case as2js::node_t::NODE_ASSIGNMENT_LOGICAL_OR: 559 : case as2js::node_t::NODE_ASSIGNMENT_LOGICAL_XOR: 560 : case as2js::node_t::NODE_ASSIGNMENT_MAXIMUM: 561 : case as2js::node_t::NODE_ASSIGNMENT_MINIMUM: 562 : case as2js::node_t::NODE_ASSIGNMENT_MODULO: 563 : case as2js::node_t::NODE_ASSIGNMENT_MULTIPLY: 564 : case as2js::node_t::NODE_ASSIGNMENT_POWER: 565 : case as2js::node_t::NODE_ASSIGNMENT_ROTATE_LEFT: 566 : case as2js::node_t::NODE_ASSIGNMENT_ROTATE_RIGHT: 567 : case as2js::node_t::NODE_ASSIGNMENT_SHIFT_LEFT: 568 : case as2js::node_t::NODE_ASSIGNMENT_SHIFT_RIGHT: 569 : case as2js::node_t::NODE_ASSIGNMENT_SHIFT_RIGHT_UNSIGNED: 570 : case as2js::node_t::NODE_ASSIGNMENT_SUBTRACT: 571 : case as2js::node_t::NODE_BITWISE_AND: 572 : case as2js::node_t::NODE_BITWISE_NOT: 573 : case as2js::node_t::NODE_BITWISE_OR: 574 : case as2js::node_t::NODE_BITWISE_XOR: 575 : case as2js::node_t::NODE_CALL: 576 : case as2js::node_t::NODE_CONDITIONAL: 577 : case as2js::node_t::NODE_DECREMENT: 578 : case as2js::node_t::NODE_DELETE: 579 : case as2js::node_t::NODE_DIVIDE: 580 : case as2js::node_t::NODE_EQUAL: 581 : case as2js::node_t::NODE_FALSE: 582 : case as2js::node_t::NODE_FLOATING_POINT: 583 : case as2js::node_t::NODE_FUNCTION: 584 : case as2js::node_t::NODE_GREATER: 585 : case as2js::node_t::NODE_GREATER_EQUAL: 586 : case as2js::node_t::NODE_IDENTIFIER: 587 : case as2js::node_t::NODE_IN: 588 : case as2js::node_t::NODE_INCREMENT: 589 : case as2js::node_t::NODE_INSTANCEOF: 590 : case as2js::node_t::NODE_INTEGER: 591 : case as2js::node_t::NODE_IS: 592 : case as2js::node_t::NODE_LESS: 593 : case as2js::node_t::NODE_LESS_EQUAL: 594 : case as2js::node_t::NODE_LIST: 595 : case as2js::node_t::NODE_LOGICAL_AND: 596 : case as2js::node_t::NODE_LOGICAL_NOT: 597 : case as2js::node_t::NODE_LOGICAL_OR: 598 : case as2js::node_t::NODE_LOGICAL_XOR: 599 : case as2js::node_t::NODE_MATCH: 600 : case as2js::node_t::NODE_MAXIMUM: 601 : case as2js::node_t::NODE_MEMBER: 602 : case as2js::node_t::NODE_MINIMUM: 603 : case as2js::node_t::NODE_MODULO: 604 : case as2js::node_t::NODE_MULTIPLY: 605 : case as2js::node_t::NODE_NAME: 606 : case as2js::node_t::NODE_NEW: 607 : case as2js::node_t::NODE_NOT_EQUAL: 608 : case as2js::node_t::NODE_NULL: 609 : case as2js::node_t::NODE_OBJECT_LITERAL: 610 : case as2js::node_t::NODE_POST_DECREMENT: 611 : case as2js::node_t::NODE_POST_INCREMENT: 612 : case as2js::node_t::NODE_POWER: 613 : case as2js::node_t::NODE_PRIVATE: 614 : case as2js::node_t::NODE_PUBLIC: 615 : case as2js::node_t::NODE_RANGE: 616 : case as2js::node_t::NODE_ROTATE_LEFT: 617 : case as2js::node_t::NODE_ROTATE_RIGHT: 618 : case as2js::node_t::NODE_SCOPE: 619 : case as2js::node_t::NODE_SHIFT_LEFT: 620 : case as2js::node_t::NODE_SHIFT_RIGHT: 621 : case as2js::node_t::NODE_SHIFT_RIGHT_UNSIGNED: 622 : case as2js::node_t::NODE_STRICTLY_EQUAL: 623 : case as2js::node_t::NODE_STRICTLY_NOT_EQUAL: 624 : case as2js::node_t::NODE_STRING: 625 : case as2js::node_t::NODE_SUBTRACT: 626 : case as2js::node_t::NODE_SUPER: 627 : case as2js::node_t::NODE_THIS: 628 : case as2js::node_t::NODE_TRUE: 629 : case as2js::node_t::NODE_TYPEOF: 630 : case as2js::node_t::NODE_UNDEFINED: 631 : case as2js::node_t::NODE_VIDENTIFIER: 632 : case as2js::node_t::NODE_VOID: 633 56 : break;; 634 : 635 84 : default: 636 : // with any other types we would get an error 637 84 : continue; 638 : 639 : } 640 : } 641 : 642 : // is attribute 'a' in conflict with attribute '*attr_list'? 643 : // 644 3836 : if(!in_conflict(j, *attr_list, static_cast<as2js::attribute_t>(a))) 645 : { 646 : // if in conflict we do not care much here because the 647 : // display is going to be exactly the same 648 : // 649 3516 : node->set_attribute(static_cast<as2js::attribute_t>(a), true); 650 : 651 : // display that now 652 : // 653 3516 : std::stringstream out; 654 3516 : out << *node; 655 : 656 : // build the expected message 657 : // 658 3516 : std::stringstream expected; 659 : 660 : // indent is expected to be exactly 2 on startup and here we only have one line 661 : // 662 : expected 663 : << node 664 : << ": " 665 : << std::setfill('0') 666 3516 : << std::setw(2) 667 : << 2 668 : << std::setfill(' ') 669 : << '.' 670 : << std::setw(2) 671 3516 : << ""; 672 3516 : if(g_node_types[idx_node].f_type == as2js::node_t::NODE_EOF) 673 : { 674 : expected 675 : << std::setw(4) 676 0 : << std::setfill(' ') 677 0 : << static_cast<int>(g_node_types[idx_node].f_type); 678 : } 679 : else 680 : { 681 : expected 682 : << std::setw(4) 683 3516 : << std::setfill('0') 684 3516 : << static_cast<int>(g_node_types[idx_node].f_type); 685 : } 686 : expected 687 : << std::setfill('\0') 688 : << ": " 689 3516 : << g_node_types[idx_node].f_name; 690 : 691 : // add the type as a character if it represents just one character 692 : // 693 3516 : if(static_cast<int>(g_node_types[idx_node].f_type) > ' ' 694 3516 : && static_cast<int>(g_node_types[idx_node].f_type) < 0x7F) 695 : { 696 706 : expected << " = '" << static_cast<char>(static_cast<int>(g_node_types[idx_node].f_type)) << "'"; 697 : } 698 : 699 3516 : switch(g_node_types[idx_node].f_type) 700 : { 701 346 : case as2js::node_t::NODE_BREAK: 702 : case as2js::node_t::NODE_CLASS: 703 : case as2js::node_t::NODE_CONTINUE: 704 : case as2js::node_t::NODE_ENUM: 705 : case as2js::node_t::NODE_FUNCTION: 706 : case as2js::node_t::NODE_GOTO: 707 : case as2js::node_t::NODE_IDENTIFIER: 708 : case as2js::node_t::NODE_IMPORT: 709 : case as2js::node_t::NODE_INTERFACE: 710 : case as2js::node_t::NODE_LABEL: 711 : case as2js::node_t::NODE_NAMESPACE: 712 : case as2js::node_t::NODE_PACKAGE: 713 : case as2js::node_t::NODE_REGULAR_EXPRESSION: 714 : case as2js::node_t::NODE_STRING: 715 : case as2js::node_t::NODE_TEMPLATE: 716 : case as2js::node_t::NODE_TEMPLATE_HEAD: 717 : case as2js::node_t::NODE_TEMPLATE_MIDDLE: 718 : case as2js::node_t::NODE_TEMPLATE_TAIL: 719 : case as2js::node_t::NODE_VARIABLE: 720 : case as2js::node_t::NODE_VAR_ATTRIBUTES: 721 : case as2js::node_t::NODE_VIDENTIFIER: 722 346 : output_str(expected, node->get_string()); 723 346 : break; 724 : 725 0 : case as2js::node_t::NODE_INTEGER: 726 : expected 727 0 : << ": " << node->get_integer().get() 728 0 : << ", 0x" 729 0 : << std::hex 730 : << std::setw(16) 731 0 : << std::setfill('0') 732 0 : << node->get_integer().get() 733 0 : << std::dec << std::setw(0) 734 0 : << std::setfill('\0'); 735 0 : break; 736 : 737 0 : case as2js::node_t::NODE_FLOATING_POINT: 738 0 : expected << ": " << node->get_floating_point().get(); 739 0 : break; 740 : 741 0 : case as2js::node_t::NODE_CALL: 742 : case as2js::node_t::NODE_CATCH: 743 : case as2js::node_t::NODE_DIRECTIVE_LIST: 744 : case as2js::node_t::NODE_FOR: 745 : case as2js::node_t::NODE_PARAM_MATCH: 746 : case as2js::node_t::NODE_SWITCH: 747 : case as2js::node_t::NODE_TYPE: 748 : case as2js::node_t::NODE_VAR: 749 0 : expected << ":"; 750 0 : break; 751 : 752 0 : case as2js::node_t::NODE_PARAM: 753 0 : expected << ": 'param1':"; 754 0 : break; 755 : 756 3170 : default: 757 3170 : break; 758 : 759 : } 760 : 761 3516 : int pa(a); 762 3516 : int pb(static_cast<int>(*attr_list)); 763 3516 : if(pa > pb) 764 : { 765 1866 : std::swap(pa, pb); 766 : } 767 3516 : expected << " attrs: " << g_attribute_names[pa] << " " << g_attribute_names[pb]; 768 : 769 3516 : expected << " (" << node->get_position() << ")" << std::endl; 770 : 771 : //std::cerr << " output [" << out.str() << "]\n"; 772 : //std::cerr << "expected [" << expected.str() << "] (for: " << static_cast<int>(*attr_list) << " / " << a << ")\n"; 773 : 774 3516 : CATCH_REQUIRE(out.str() == expected.str()); 775 : 776 3516 : node->set_attribute(static_cast<as2js::attribute_t>(a), false); 777 3516 : } 778 : } 779 : 780 : // we are done with that loop, restore the attribute to the default 781 140 : node->set_attribute(*attr_list, false); 782 : } 783 : } 784 10 : } 785 : } 786 1 : CATCH_END_SECTION() 787 1 : } 788 : 789 : 790 1 : CATCH_TEST_CASE("node_display_tree", "[node][display][tree]") 791 : { 792 1 : CATCH_START_SECTION("node_display_tree: display a tree of nodes") 793 : { 794 : // create all the nodes as the lexer would do 795 1 : as2js::node::pointer_t root(std::make_shared<as2js::node>(as2js::node_t::NODE_ROOT)); 796 1 : as2js::position pos; 797 1 : pos.reset_counters(22); 798 1 : pos.set_filename("display.js"); 799 1 : root->set_position(pos); 800 1 : as2js::node::pointer_t directive_list_a(std::make_shared<as2js::node>(as2js::node_t::NODE_DIRECTIVE_LIST)); 801 1 : as2js::node::pointer_t directive_list_b(std::make_shared<as2js::node>(as2js::node_t::NODE_DIRECTIVE_LIST)); 802 1 : directive_list_b->set_flag(as2js::flag_t::NODE_DIRECTIVE_LIST_FLAG_NEW_VARIABLES, true); 803 1 : as2js::node::pointer_t assignment(std::make_shared<as2js::node>(as2js::node_t::NODE_ASSIGNMENT)); 804 1 : as2js::node::pointer_t identifier_a(std::make_shared<as2js::node>(as2js::node_t::NODE_IDENTIFIER)); 805 1 : identifier_a->set_string("a"); 806 1 : identifier_a->set_attribute(as2js::attribute_t::NODE_ATTR_TRUE, true); 807 1 : as2js::node::pointer_t power(std::make_shared<as2js::node>(as2js::node_t::NODE_POWER)); 808 1 : as2js::node::pointer_t member(std::make_shared<as2js::node>(as2js::node_t::NODE_MEMBER)); 809 1 : as2js::node::pointer_t identifier_math(std::make_shared<as2js::node>(as2js::node_t::NODE_IDENTIFIER)); 810 1 : identifier_math->set_string("Math"); 811 1 : identifier_math->set_attribute(as2js::attribute_t::NODE_ATTR_NATIVE, true); 812 1 : as2js::node::pointer_t math_type(std::make_shared<as2js::node>(as2js::node_t::NODE_IDENTIFIER)); 813 1 : math_type->set_string("Math"); 814 1 : identifier_math->set_type_node(math_type); 815 1 : as2js::node::pointer_t math_instance(std::make_shared<as2js::node>(as2js::node_t::NODE_IDENTIFIER)); 816 1 : math_instance->set_string("m"); 817 1 : identifier_math->set_instance(math_instance); 818 1 : as2js::node::pointer_t identifier_e(std::make_shared<as2js::node>(as2js::node_t::NODE_IDENTIFIER)); 819 1 : identifier_e->set_string("e"); 820 1 : identifier_e->set_flag(as2js::flag_t::NODE_IDENTIFIER_FLAG_TYPED, true); 821 1 : as2js::node::pointer_t e_type(std::make_shared<as2js::node>(as2js::node_t::NODE_IDENTIFIER)); 822 1 : e_type->set_string("Float"); 823 1 : identifier_e->set_type_node(e_type); 824 1 : as2js::node::pointer_t literal(std::make_shared<as2js::node>(as2js::node_t::NODE_FLOATING_POINT)); 825 1 : as2js::floating_point f; 826 1 : f.set(1.424); 827 1 : literal->set_floating_point(f); 828 1 : as2js::node::pointer_t function(std::make_shared<as2js::node>(as2js::node_t::NODE_FUNCTION)); 829 1 : function->set_string("my_func"); 830 1 : as2js::node::pointer_t func_var(std::make_shared<as2js::node>(as2js::node_t::NODE_VAR)); 831 1 : as2js::node::pointer_t func_variable(std::make_shared<as2js::node>(as2js::node_t::NODE_VARIABLE)); 832 1 : func_variable->set_string("q"); 833 1 : as2js::node::pointer_t label(std::make_shared<as2js::node>(as2js::node_t::NODE_LABEL)); 834 1 : label->set_string("ignore"); 835 1 : function->add_label(label); 836 1 : function->add_variable(func_variable); 837 : 838 : // build the tree as the parser would do 839 1 : root->append_child(directive_list_a); 840 1 : root->append_child(directive_list_b); 841 1 : directive_list_a->append_child(assignment); 842 1 : assignment->append_child(identifier_a); 843 1 : assignment->insert_child(-1, power); 844 1 : power->append_child(member); 845 1 : power->insert_child(1, literal); 846 1 : member->append_child(identifier_e); 847 1 : member->insert_child(0, identifier_math); 848 1 : directive_list_b->append_child(function); 849 1 : function->append_child(func_var); 850 1 : func_var->append_child(func_variable); 851 1 : function->append_child(label); 852 : 853 : // now test the output 854 1 : std::stringstream out; 855 1 : out << *root; 856 : 857 : // build the expected message 858 1 : std::stringstream expected; 859 : 860 : // ROOT 861 1 : expected << root << ": " << std::setfill('0') << std::setw(2) << 2 << std::setfill(' ') << '.' << std::setw(2) << "" 862 1 : << std::setw(4) << std::setfill('0') << static_cast<int>(static_cast<as2js::node_t>(as2js::node_t::NODE_ROOT)) 863 : << std::setfill('\0') << ": ROOT" 864 1 : << " (" << root->get_position() << ")" << std::endl; 865 : 866 : // DIRECTIVE_LIST A 867 1 : expected << directive_list_a << ": " << std::setfill('0') << std::setw(2) << 3 << std::setfill(' ') << '-' << std::setw(3) << "" 868 1 : << std::setw(4) << std::setfill('0') << static_cast<int>(static_cast<as2js::node_t>(as2js::node_t::NODE_DIRECTIVE_LIST)) 869 : << std::setfill('\0') << ": DIRECTIVE_LIST:" 870 1 : << " (" << directive_list_a->get_position() << ")" << std::endl; 871 : 872 : // ASSIGNMENT 873 1 : expected << assignment << ": " << std::setfill('0') << std::setw(2) << 4 << std::setfill(' ') << '-' << std::setw(4) << "" 874 1 : << std::setw(4) << std::setfill('0') << static_cast<int>(static_cast<as2js::node_t>(as2js::node_t::NODE_ASSIGNMENT)) 875 : << std::setfill('\0') << ": ASSIGNMENT = '='" 876 1 : << " (" << assignment->get_position() << ")" << std::endl; 877 : 878 : // IDENTIFIER A 879 1 : expected << identifier_a << ": " << std::setfill('0') << std::setw(2) << 5 << std::setfill(' ') << '-' << std::setw(5) << "" 880 1 : << std::setw(4) << std::setfill('0') << static_cast<int>(static_cast<as2js::node_t>(as2js::node_t::NODE_IDENTIFIER)) 881 : << std::setfill('\0') << ": IDENTIFIER: 'a' attrs: TRUE" 882 1 : << " (" << identifier_a->get_position() << ")" << std::endl; 883 : 884 : // POWER 885 1 : expected << power << ": " << std::setfill('0') << std::setw(2) << 5 << std::setfill(' ') << '-' << std::setw(5) << "" 886 1 : << std::setw(4) << std::setfill('0') << static_cast<int>(static_cast<as2js::node_t>(as2js::node_t::NODE_POWER)) 887 : << std::setfill('\0') << ": POWER" 888 1 : << " (" << power->get_position() << ")" << std::endl; 889 : 890 : // MEMBER 891 1 : expected << member << ": " << std::setfill('0') << std::setw(2) << 6 << std::setfill(' ') << '-' << std::setw(6) << "" 892 1 : << std::setw(4) << std::setfill('0') << static_cast<int>(static_cast<as2js::node_t>(as2js::node_t::NODE_MEMBER)) 893 : << std::setfill('\0') << ": MEMBER = '.'" 894 1 : << " (" << member->get_position() << ")" << std::endl; 895 : 896 : // IDENTIFIER MATH 897 1 : expected << identifier_math << ": " << std::setfill('0') << std::setw(2) << 7 << std::setfill(' ') << '-' << std::setw(7) << "" 898 1 : << std::setw(4) << std::setfill('0') << static_cast<int>(static_cast<as2js::node_t>(as2js::node_t::NODE_IDENTIFIER)) 899 : << std::setfill('\0') << ": IDENTIFIER: 'Math' Instance: " << math_instance << " Type node: " << math_type << " attrs: NATIVE" 900 1 : << " (" << identifier_math->get_position() << ")" << std::endl; 901 : 902 : // IDENTIFIER E 903 1 : expected << identifier_e << ": " << std::setfill('0') << std::setw(2) << 7 << std::setfill(' ') << '-' << std::setw(7) << "" 904 1 : << std::setw(4) << std::setfill('0') << static_cast<int>(static_cast<as2js::node_t>(as2js::node_t::NODE_IDENTIFIER)) 905 : << std::setfill('\0') << ": IDENTIFIER: 'e' TYPED Type node: " << e_type 906 1 : << " (" << identifier_e->get_position() << ")" << std::endl; 907 : 908 : // FLOATING_POINT 909 1 : expected << literal << ": " << std::setfill('0') << std::setw(2) << 6 << std::setfill(' ') << '-' << std::setw(6) << "" 910 1 : << std::setw(4) << std::setfill('0') << static_cast<int>(static_cast<as2js::node_t>(as2js::node_t::NODE_FLOATING_POINT)) 911 : << std::setfill('\0') << ": FLOATING_POINT: 1.424" 912 1 : << " (" << literal->get_position() << ")" << std::endl; 913 : 914 : // DIRECTIVE_LIST B 915 1 : expected << directive_list_b << ": " << std::setfill('0') << std::setw(2) << 3 << std::setfill(' ') << '-' << std::setw(3) << "" 916 1 : << std::setw(4) << std::setfill('0') << static_cast<int>(static_cast<as2js::node_t>(as2js::node_t::NODE_DIRECTIVE_LIST)) 917 : << std::setfill('\0') << ": DIRECTIVE_LIST: NEW-VARIABLES" 918 1 : << " (" << directive_list_b->get_position() << ")" << std::endl; 919 : 920 : // FUNCTION 921 1 : expected << function << ": " << std::setfill('0') << std::setw(2) << 4 << std::setfill(' ') << '-' << std::setw(4) << "" 922 1 : << std::setw(4) << std::setfill('0') << static_cast<int>(static_cast<as2js::node_t>(as2js::node_t::NODE_FUNCTION)) 923 : << std::setfill('\0') << ": FUNCTION: 'my_func'" 924 1 : << " (" << function->get_position() << ")" << std::endl; 925 : 926 : // VAR 927 1 : expected << func_var << ": " << std::setfill('0') << std::setw(2) << 5 << std::setfill(' ') << '-' << std::setw(5) << "" 928 1 : << std::setw(4) << std::setfill('0') << static_cast<int>(static_cast<as2js::node_t>(as2js::node_t::NODE_VAR)) 929 : << std::setfill('\0') << ": VAR:" 930 1 : << " (" << func_var->get_position() << ")" << std::endl; 931 : 932 : // VARIABLE 933 1 : expected << func_variable << ": " << std::setfill('0') << std::setw(2) << 6 << std::setfill(' ') << '-' << std::setw(6) << "" 934 1 : << std::setw(4) << std::setfill('0') << static_cast<int>(static_cast<as2js::node_t>(as2js::node_t::NODE_VARIABLE)) 935 : << std::setfill('\0') << ": VARIABLE: 'q'" 936 1 : << " (" << func_variable->get_position() << ")" << std::endl; 937 : 938 : // LABEL 939 1 : expected << label << ": " << std::setfill('0') << std::setw(2) << 5 << std::setfill(' ') << '-' << std::setw(5) << "" 940 1 : << std::setw(4) << std::setfill('0') << static_cast<int>(static_cast<as2js::node_t>(as2js::node_t::NODE_LABEL)) 941 : << std::setfill('\0') << ": LABEL: 'ignore'" 942 1 : << " (" << label->get_position() << ")" << std::endl; 943 : 944 : // VARIABLE 945 1 : expected << func_variable << ": " << std::setfill('0') << std::setw(2) << 5 << std::setfill(' ') << '=' << std::setw(5) << "" 946 1 : << std::setw(4) << std::setfill('0') << static_cast<int>(static_cast<as2js::node_t>(as2js::node_t::NODE_VARIABLE)) 947 : << std::setfill('\0') << ": VARIABLE: 'q'" 948 1 : << " (" << func_variable->get_position() << ")" << std::endl; 949 : 950 : // LABEL 951 1 : expected << label << ": " << std::setfill('0') << std::setw(2) << 5 << std::setfill(' ') << ':' << std::setw(5) << "" 952 1 : << std::setw(4) << std::setfill('0') << static_cast<int>(static_cast<as2js::node_t>(as2js::node_t::NODE_LABEL)) 953 : << std::setfill('\0') << ": LABEL: 'ignore'" 954 1 : << " (" << label->get_position() << ")" << std::endl; 955 : 956 : //std::cerr << "output [" << out.str() << "]\n"; 957 : //std::cerr << "expected [" << expected.str() << "]\n"; 958 : 959 1 : CATCH_REQUIRE(out.str() == expected.str()); 960 1 : } 961 1 : CATCH_END_SECTION() 962 1 : } 963 : 964 : 965 : // vim: ts=4 sw=4 et