1" Test various aspects of the Vim script language. 2" Most of this was formerly in test49. 3 4"------------------------------------------------------------------------------- 5" Test environment {{{1 6"------------------------------------------------------------------------------- 7 8com! XpathINIT let g:Xpath = '' 9com! -nargs=1 -bar Xpath let g:Xpath = g:Xpath . <args> 10 11" Append a message to the "messages" file 12func Xout(text) 13 split messages 14 $put =a:text 15 wq 16endfunc 17 18com! -nargs=1 Xout call Xout(<args>) 19 20" MakeScript() - Make a script file from a function. {{{2 21" 22" Create a script that consists of the body of the function a:funcname. 23" Replace any ":return" by a ":finish", any argument variable by a global 24" variable, and every ":call" by a ":source" for the next following argument 25" in the variable argument list. This function is useful if similar tests are 26" to be made for a ":return" from a function call or a ":finish" in a script 27" file. 28function! MakeScript(funcname, ...) 29 let script = tempname() 30 execute "redir! >" . script 31 execute "function" a:funcname 32 redir END 33 execute "edit" script 34 " Delete the "function" and the "endfunction" lines. Do not include the 35 " word "function" in the pattern since it might be translated if LANG is 36 " set. When MakeScript() is being debugged, this deletes also the debugging 37 " output of its line 3 and 4. 38 exec '1,/.*' . a:funcname . '(.*)/d' 39 /^\d*\s*endfunction\>/,$d 40 %s/^\d*//e 41 %s/return/finish/e 42 %s/\<a:\(\h\w*\)/g:\1/ge 43 normal gg0 44 let cnt = 0 45 while search('\<call\s*\%(\u\|s:\)\w*\s*(.*)', 'W') > 0 46 let cnt = cnt + 1 47 s/\<call\s*\%(\u\|s:\)\w*\s*(.*)/\='source ' . a:{cnt}/ 48 endwhile 49 g/^\s*$/d 50 write 51 bwipeout 52 return script 53endfunc 54 55" ExecAsScript - Source a temporary script made from a function. {{{2 56" 57" Make a temporary script file from the function a:funcname, ":source" it, and 58" delete it afterwards. However, if an exception is thrown the file may remain, 59" the caller should call DeleteTheScript() afterwards. 60let s:script_name = '' 61function! ExecAsScript(funcname) 62 " Make a script from the function passed as argument. 63 let s:script_name = MakeScript(a:funcname) 64 65 " Source and delete the script. 66 exec "source" s:script_name 67 call delete(s:script_name) 68 let s:script_name = '' 69endfunction 70 71function! DeleteTheScript() 72 if s:script_name 73 call delete(s:script_name) 74 let s:script_name = '' 75 endif 76endfunc 77 78com! -nargs=1 -bar ExecAsScript call ExecAsScript(<f-args>) 79 80 81"------------------------------------------------------------------------------- 82" Test 1: :endwhile in function {{{1 83" 84" Detect if a broken loop is (incorrectly) reactivated by the 85" :endwhile. Use a :return to prevent an endless loop, and make 86" this test first to get a meaningful result on an error before other 87" tests will hang. 88"------------------------------------------------------------------------------- 89 90function! T1_F() 91 Xpath 'a' 92 let first = 1 93 while 1 94 Xpath 'b' 95 if first 96 Xpath 'c' 97 let first = 0 98 break 99 else 100 Xpath 'd' 101 return 102 endif 103 endwhile 104endfunction 105 106function! T1_G() 107 Xpath 'h' 108 let first = 1 109 while 1 110 Xpath 'i' 111 if first 112 Xpath 'j' 113 let first = 0 114 break 115 else 116 Xpath 'k' 117 return 118 endif 119 if 1 " unmatched :if 120 endwhile 121endfunction 122 123func Test_endwhile_function() 124 XpathINIT 125 call T1_F() 126 Xpath 'F' 127 128 try 129 call T1_G() 130 catch 131 " Catch missing :endif 132 call assert_true(v:exception =~ 'E171') 133 Xpath 'x' 134 endtry 135 Xpath 'G' 136 137 call assert_equal('abcFhijxG', g:Xpath) 138endfunc 139 140"------------------------------------------------------------------------------- 141" Test 2: :endwhile in script {{{1 142" 143" Detect if a broken loop is (incorrectly) reactivated by the 144" :endwhile. Use a :finish to prevent an endless loop, and place 145" this test before others that might hang to get a meaningful result 146" on an error. 147" 148" This test executes the bodies of the functions T1_F and T1_G from 149" the previous test as script files (:return replaced by :finish). 150"------------------------------------------------------------------------------- 151 152func Test_endwhile_script() 153 XpathINIT 154 ExecAsScript T1_F 155 Xpath 'F' 156 call DeleteTheScript() 157 158 try 159 ExecAsScript T1_G 160 catch 161 " Catch missing :endif 162 call assert_true(v:exception =~ 'E171') 163 Xpath 'x' 164 endtry 165 Xpath 'G' 166 call DeleteTheScript() 167 168 call assert_equal('abcFhijxG', g:Xpath) 169endfunc 170 171"------------------------------------------------------------------------------- 172" Test 3: :if, :elseif, :while, :continue, :break {{{1 173"------------------------------------------------------------------------------- 174 175function Test_if_while() 176 XpathINIT 177 if 1 178 Xpath 'a' 179 let loops = 3 180 while loops > -1 " main loop: loops == 3, 2, 1 (which breaks) 181 if loops <= 0 182 let break_err = 1 183 let loops = -1 184 else 185 Xpath 'b' . loops 186 endif 187 if (loops == 2) 188 while loops == 2 " dummy loop 189 Xpath 'c' . loops 190 let loops = loops - 1 191 continue " stop dummy loop 192 Xpath 'd' . loops 193 endwhile 194 continue " continue main loop 195 Xpath 'e' . loops 196 elseif (loops == 1) 197 let p = 1 198 while p " dummy loop 199 Xpath 'f' . loops 200 let p = 0 201 break " break dummy loop 202 Xpath 'g' . loops 203 endwhile 204 Xpath 'h' . loops 205 unlet p 206 break " break main loop 207 Xpath 'i' . loops 208 endif 209 if (loops > 0) 210 Xpath 'j' . loops 211 endif 212 while loops == 3 " dummy loop 213 let loops = loops - 1 214 endwhile " end dummy loop 215 endwhile " end main loop 216 Xpath 'k' 217 else 218 Xpath 'l' 219 endif 220 Xpath 'm' 221 if exists("break_err") 222 Xpath 'm' 223 unlet break_err 224 endif 225 226 unlet loops 227 228 call assert_equal('ab3j3b2c2b1f1h1km', g:Xpath) 229endfunc 230 231"------------------------------------------------------------------------------- 232" Test 4: :return {{{1 233"------------------------------------------------------------------------------- 234 235function! T4_F() 236 if 1 237 Xpath 'a' 238 let loops = 3 239 while loops > 0 " 3: 2: 1: 240 Xpath 'b' . loops 241 if (loops == 2) 242 Xpath 'c' . loops 243 return 244 Xpath 'd' . loops 245 endif 246 Xpath 'e' . loops 247 let loops = loops - 1 248 endwhile 249 Xpath 'f' 250 else 251 Xpath 'g' 252 endif 253endfunction 254 255function Test_return() 256 XpathINIT 257 call T4_F() 258 Xpath '4' 259 260 call assert_equal('ab3e3b2c24', g:Xpath) 261endfunction 262 263 264"------------------------------------------------------------------------------- 265" Test 5: :finish {{{1 266" 267" This test executes the body of the function T4_F from the previous 268" test as a script file (:return replaced by :finish). 269"------------------------------------------------------------------------------- 270 271function Test_finish() 272 XpathINIT 273 ExecAsScript T4_F 274 Xpath '5' 275 call DeleteTheScript() 276 277 call assert_equal('ab3e3b2c25', g:Xpath) 278endfunction 279 280 281 282"------------------------------------------------------------------------------- 283" Test 6: Defining functions in :while loops {{{1 284" 285" Functions can be defined inside other functions. An inner function 286" gets defined when the outer function is executed. Functions may 287" also be defined inside while loops. Expressions in braces for 288" defining the function name are allowed. 289" 290" The functions are defined when sourcing the script, only the 291" resulting path is checked in the test function. 292"------------------------------------------------------------------------------- 293 294XpathINIT 295 296" The command CALL collects the argument of all its invocations in "calls" 297" when used from a function (that is, when the global variable "calls" needs 298" the "g:" prefix). This is to check that the function code is skipped when 299" the function is defined. For inner functions, do so only if the outer 300" function is not being executed. 301" 302let calls = "" 303com! -nargs=1 CALL 304 \ if !exists("calls") && !exists("outer") | 305 \ let g:calls = g:calls . <args> | 306 \ endif 307 308let i = 0 309while i < 3 310 let i = i + 1 311 if i == 1 312 Xpath 'a' 313 function! F1(arg) 314 CALL a:arg 315 let outer = 1 316 317 let j = 0 318 while j < 1 319 Xpath 'b' 320 let j = j + 1 321 function! G1(arg) 322 CALL a:arg 323 endfunction 324 Xpath 'c' 325 endwhile 326 endfunction 327 Xpath 'd' 328 329 continue 330 endif 331 332 Xpath 'e' . i 333 function! F{i}(i, arg) 334 CALL a:arg 335 let outer = 1 336 337 if a:i == 3 338 Xpath 'f' 339 endif 340 let k = 0 341 while k < 3 342 Xpath 'g' . k 343 let k = k + 1 344 function! G{a:i}{k}(arg) 345 CALL a:arg 346 endfunction 347 Xpath 'h' . k 348 endwhile 349 endfunction 350 Xpath 'i' 351 352endwhile 353 354if exists("*G1") 355 Xpath 'j' 356endif 357if exists("*F1") 358 call F1("F1") 359 if exists("*G1") 360 call G1("G1") 361 endif 362endif 363 364if exists("G21") || exists("G22") || exists("G23") 365 Xpath 'k' 366endif 367if exists("*F2") 368 call F2(2, "F2") 369 if exists("*G21") 370 call G21("G21") 371 endif 372 if exists("*G22") 373 call G22("G22") 374 endif 375 if exists("*G23") 376 call G23("G23") 377 endif 378endif 379 380if exists("G31") || exists("G32") || exists("G33") 381 Xpath 'l' 382endif 383if exists("*F3") 384 call F3(3, "F3") 385 if exists("*G31") 386 call G31("G31") 387 endif 388 if exists("*G32") 389 call G32("G32") 390 endif 391 if exists("*G33") 392 call G33("G33") 393 endif 394endif 395 396Xpath 'm' 397 398let g:test6_result = g:Xpath 399let g:test6_calls = calls 400 401unlet calls 402delfunction F1 403delfunction G1 404delfunction F2 405delfunction G21 406delfunction G22 407delfunction G23 408delfunction G31 409delfunction G32 410delfunction G33 411 412function Test_defining_functions() 413 call assert_equal('ade2ie3ibcg0h1g1h2g2h3fg0h1g1h2g2h3m', g:test6_result) 414 call assert_equal('F1G1F2G21G22G23F3G31G32G33', g:test6_calls) 415endfunc 416 417"------------------------------------------------------------------------------- 418" Test 7: Continuing on errors outside functions {{{1 419" 420" On an error outside a function, the script processing continues 421" at the line following the outermost :endif or :endwhile. When not 422" inside an :if or :while, the script processing continues at the next 423" line. 424"------------------------------------------------------------------------------- 425 426XpathINIT 427 428if 1 429 Xpath 'a' 430 while 1 431 Xpath 'b' 432 asdf 433 Xpath 'c' 434 break 435 endwhile | Xpath 'd' 436 Xpath 'e' 437endif | Xpath 'f' 438Xpath 'g' 439 440while 1 441 Xpath 'h' 442 if 1 443 Xpath 'i' 444 asdf 445 Xpath 'j' 446 endif | Xpath 'k' 447 Xpath 'l' 448 break 449endwhile | Xpath 'm' 450Xpath 'n' 451 452asdf 453Xpath 'o' 454 455asdf | Xpath 'p' 456Xpath 'q' 457 458let g:test7_result = g:Xpath 459 460func Test_error_in_script() 461 call assert_equal('abghinoq', g:test7_result) 462endfunc 463 464"------------------------------------------------------------------------------- 465" Test 8: Aborting and continuing on errors inside functions {{{1 466" 467" On an error inside a function without the "abort" attribute, the 468" script processing continues at the next line (unless the error was 469" in a :return command). On an error inside a function with the 470" "abort" attribute, the function is aborted and the script processing 471" continues after the function call; the value -1 is returned then. 472"------------------------------------------------------------------------------- 473 474XpathINIT 475 476function! T8_F() 477 if 1 478 Xpath 'a' 479 while 1 480 Xpath 'b' 481 asdf 482 Xpath 'c' 483 asdf | Xpath 'd' 484 Xpath 'e' 485 break 486 endwhile 487 Xpath 'f' 488 endif | Xpath 'g' 489 Xpath 'h' 490 491 while 1 492 Xpath 'i' 493 if 1 494 Xpath 'j' 495 asdf 496 Xpath 'k' 497 asdf | Xpath 'l' 498 Xpath 'm' 499 endif 500 Xpath 'n' 501 break 502 endwhile | Xpath 'o' 503 Xpath 'p' 504 505 return novar " returns (default return value 0) 506 Xpath 'q' 507 return 1 " not reached 508endfunction 509 510function! T8_G() abort 511 if 1 512 Xpath 'r' 513 while 1 514 Xpath 's' 515 asdf " returns -1 516 Xpath 't' 517 break 518 endwhile 519 Xpath 'v' 520 endif | Xpath 'w' 521 Xpath 'x' 522 523 return -4 " not reached 524endfunction 525 526function! T8_H() abort 527 while 1 528 Xpath 'A' 529 if 1 530 Xpath 'B' 531 asdf " returns -1 532 Xpath 'C' 533 endif 534 Xpath 'D' 535 break 536 endwhile | Xpath 'E' 537 Xpath 'F' 538 539 return -4 " not reached 540endfunction 541 542" Aborted functions (T8_G and T8_H) return -1. 543let g:test8_sum = (T8_F() + 1) - 4 * T8_G() - 8 * T8_H() 544Xpath 'X' 545let g:test8_result = g:Xpath 546 547func Test_error_in_function() 548 call assert_equal(13, g:test8_sum) 549 call assert_equal('abcefghijkmnoprsABX', g:test8_result) 550 551 delfunction T8_F 552 delfunction T8_G 553 delfunction T8_H 554endfunc 555 556 557"------------------------------------------------------------------------------- 558" Test 9: Continuing after aborted functions {{{1 559" 560" When a function with the "abort" attribute is aborted due to an 561" error, the next function back in the call hierarchy without an 562" "abort" attribute continues; the value -1 is returned then. 563"------------------------------------------------------------------------------- 564 565XpathINIT 566 567function! F() abort 568 Xpath 'a' 569 let result = G() " not aborted 570 Xpath 'b' 571 if result != 2 572 Xpath 'c' 573 endif 574 return 1 575endfunction 576 577function! G() " no abort attribute 578 Xpath 'd' 579 if H() != -1 " aborted 580 Xpath 'e' 581 endif 582 Xpath 'f' 583 return 2 584endfunction 585 586function! H() abort 587 Xpath 'g' 588 call I() " aborted 589 Xpath 'h' 590 return 4 591endfunction 592 593function! I() abort 594 Xpath 'i' 595 asdf " error 596 Xpath 'j' 597 return 8 598endfunction 599 600if F() != 1 601 Xpath 'k' 602endif 603 604let g:test9_result = g:Xpath 605 606delfunction F 607delfunction G 608delfunction H 609delfunction I 610 611func Test_func_abort() 612 call assert_equal('adgifb', g:test9_result) 613endfunc 614 615 616"------------------------------------------------------------------------------- 617" Test 10: :if, :elseif, :while argument parsing {{{1 618" 619" A '"' or '|' in an argument expression must not be mixed up with 620" a comment or a next command after a bar. Parsing errors should 621" be recognized. 622"------------------------------------------------------------------------------- 623 624XpathINIT 625 626function! MSG(enr, emsg) 627 let english = v:lang == "C" || v:lang =~ '^[Ee]n' 628 if a:enr == "" 629 Xout "TODO: Add message number for:" a:emsg 630 let v:errmsg = ":" . v:errmsg 631 endif 632 let match = 1 633 if v:errmsg !~ '^'.a:enr.':' || (english && v:errmsg !~ a:emsg) 634 let match = 0 635 if v:errmsg == "" 636 Xout "Message missing." 637 else 638 let v:errmsg = v:errmsg->escape('"') 639 Xout "Unexpected message:" v:errmsg 640 endif 641 endif 642 return match 643endfunc 644 645if 1 || strlen("\"") | Xpath 'a' 646 Xpath 'b' 647endif 648Xpath 'c' 649 650if 0 651elseif 1 || strlen("\"") | Xpath 'd' 652 Xpath 'e' 653endif 654Xpath 'f' 655 656while 1 || strlen("\"") | Xpath 'g' 657 Xpath 'h' 658 break 659endwhile 660Xpath 'i' 661 662let v:errmsg = "" 663if 1 ||| strlen("\"") | Xpath 'j' 664 Xpath 'k' 665endif 666Xpath 'l' 667if !MSG('E15', "Invalid expression") 668 Xpath 'm' 669endif 670 671let v:errmsg = "" 672if 0 673elseif 1 ||| strlen("\"") | Xpath 'n' 674 Xpath 'o' 675endif 676Xpath 'p' 677if !MSG('E15', "Invalid expression") 678 Xpath 'q' 679endif 680 681let v:errmsg = "" 682while 1 ||| strlen("\"") | Xpath 'r' 683 Xpath 's' 684 break 685endwhile 686Xpath 't' 687if !MSG('E15', "Invalid expression") 688 Xpath 'u' 689endif 690 691let g:test10_result = g:Xpath 692delfunction MSG 693 694func Test_expr_parsing() 695 call assert_equal('abcdefghilpt', g:test10_result) 696endfunc 697 698 699"------------------------------------------------------------------------------- 700" Test 11: :if, :elseif, :while argument evaluation after abort {{{1 701" 702" When code is skipped over due to an error, the boolean argument to 703" an :if, :elseif, or :while must not be evaluated. 704"------------------------------------------------------------------------------- 705 706XpathINIT 707 708let calls = 0 709 710function! P(num) 711 let g:calls = g:calls + a:num " side effect on call 712 return 0 713endfunction 714 715if 1 716 Xpath 'a' 717 asdf " error 718 Xpath 'b' 719 if P(1) " should not be called 720 Xpath 'c' 721 elseif !P(2) " should not be called 722 Xpath 'd' 723 else 724 Xpath 'e' 725 endif 726 Xpath 'f' 727 while P(4) " should not be called 728 Xpath 'g' 729 endwhile 730 Xpath 'h' 731endif 732Xpath 'x' 733 734let g:test11_calls = calls 735let g:test11_result = g:Xpath 736 737unlet calls 738delfunction P 739 740func Test_arg_abort() 741 call assert_equal(0, g:test11_calls) 742 call assert_equal('ax', g:test11_result) 743endfunc 744 745 746"------------------------------------------------------------------------------- 747" Test 12: Expressions in braces in skipped code {{{1 748" 749" In code skipped over due to an error or inactive conditional, 750" an expression in braces as part of a variable or function name 751" should not be evaluated. 752"------------------------------------------------------------------------------- 753 754XpathINIT 755 756function! NULL() 757 Xpath 'a' 758 return 0 759endfunction 760 761function! ZERO() 762 Xpath 'b' 763 return 0 764endfunction 765 766function! F0() 767 Xpath 'c' 768endfunction 769 770function! F1(arg) 771 Xpath 'e' 772endfunction 773 774let V0 = 1 775 776Xpath 'f' 777echo 0 ? F{NULL() + V{ZERO()}}() : 1 778 779Xpath 'g' 780if 0 781 Xpath 'h' 782 call F{NULL() + V{ZERO()}}() 783endif 784 785Xpath 'i' 786if 1 787 asdf " error 788 Xpath 'j' 789 call F1(F{NULL() + V{ZERO()}}()) 790endif 791 792Xpath 'k' 793if 1 794 asdf " error 795 Xpath 'l' 796 call F{NULL() + V{ZERO()}}() 797endif 798 799let g:test12_result = g:Xpath 800 801func Test_braces_skipped() 802 call assert_equal('fgik', g:test12_result) 803endfunc 804 805 806"------------------------------------------------------------------------------- 807" Test 13: Failure in argument evaluation for :while {{{1 808" 809" A failure in the expression evaluation for the condition of a :while 810" causes the whole :while loop until the matching :endwhile being 811" ignored. Continuation is at the next following line. 812"------------------------------------------------------------------------------- 813 814XpathINIT 815 816Xpath 'a' 817while asdf 818 Xpath 'b' 819 while 1 820 Xpath 'c' 821 break 822 endwhile 823 Xpath 'd' 824 break 825endwhile 826Xpath 'e' 827 828while asdf | Xpath 'f' | endwhile | Xpath 'g' 829Xpath 'h' 830let g:test13_result = g:Xpath 831 832func Test_while_fail() 833 call assert_equal('aeh', g:test13_result) 834endfunc 835 836 837"------------------------------------------------------------------------------- 838" Test 14: Failure in argument evaluation for :if {{{1 839" 840" A failure in the expression evaluation for the condition of an :if 841" does not cause the corresponding :else or :endif being matched to 842" a previous :if/:elseif. Neither of both branches of the failed :if 843" are executed. 844"------------------------------------------------------------------------------- 845 846XpathINIT 847 848function! F() 849 Xpath 'a' 850 let x = 0 851 if x " false 852 Xpath 'b' 853 elseif !x " always true 854 Xpath 'c' 855 let x = 1 856 if g:boolvar " possibly undefined 857 Xpath 'd' 858 else 859 Xpath 'e' 860 endif 861 Xpath 'f' 862 elseif x " never executed 863 Xpath 'g' 864 endif 865 Xpath 'h' 866endfunction 867 868let boolvar = 1 869call F() 870Xpath '-' 871 872unlet boolvar 873call F() 874let g:test14_result = g:Xpath 875 876delfunction F 877 878func Test_if_fail() 879 call assert_equal('acdfh-acfh', g:test14_result) 880endfunc 881 882 883"------------------------------------------------------------------------------- 884" Test 15: Failure in argument evaluation for :if (bar) {{{1 885" 886" Like previous test, except that the failing :if ... | ... | :endif 887" is in a single line. 888"------------------------------------------------------------------------------- 889 890XpathINIT 891 892function! F() 893 Xpath 'a' 894 let x = 0 895 if x " false 896 Xpath 'b' 897 elseif !x " always true 898 Xpath 'c' 899 let x = 1 900 if g:boolvar | Xpath 'd' | else | Xpath 'e' | endif 901 Xpath 'f' 902 elseif x " never executed 903 Xpath 'g' 904 endif 905 Xpath 'h' 906endfunction 907 908let boolvar = 1 909call F() 910Xpath '-' 911 912unlet boolvar 913call F() 914let g:test15_result = g:Xpath 915 916delfunction F 917 918func Test_if_bar_fail() 919 call assert_equal('acdfh-acfh', g:test15_result) 920endfunc 921 922"------------------------------------------------------------------------------- 923" Test 16: Double :else or :elseif after :else {{{1 924" 925" Multiple :elses or an :elseif after an :else are forbidden. 926"------------------------------------------------------------------------------- 927 928func T16_F() abort 929 if 0 930 Xpath 'a' 931 else 932 Xpath 'b' 933 else " aborts function 934 Xpath 'c' 935 endif 936 Xpath 'd' 937endfunc 938 939func T16_G() abort 940 if 0 941 Xpath 'a' 942 else 943 Xpath 'b' 944 elseif 1 " aborts function 945 Xpath 'c' 946 else 947 Xpath 'd' 948 endif 949 Xpath 'e' 950endfunc 951 952func T16_H() abort 953 if 0 954 Xpath 'a' 955 elseif 0 956 Xpath 'b' 957 else 958 Xpath 'c' 959 else " aborts function 960 Xpath 'd' 961 endif 962 Xpath 'e' 963endfunc 964 965func T16_I() abort 966 if 0 967 Xpath 'a' 968 elseif 0 969 Xpath 'b' 970 else 971 Xpath 'c' 972 elseif 1 " aborts function 973 Xpath 'd' 974 else 975 Xpath 'e' 976 endif 977 Xpath 'f' 978endfunc 979 980func Test_Multi_Else() 981 XpathINIT 982 try 983 call T16_F() 984 catch /E583:/ 985 Xpath 'e' 986 endtry 987 call assert_equal('be', g:Xpath) 988 989 XpathINIT 990 try 991 call T16_G() 992 catch /E584:/ 993 Xpath 'f' 994 endtry 995 call assert_equal('bf', g:Xpath) 996 997 XpathINIT 998 try 999 call T16_H() 1000 catch /E583:/ 1001 Xpath 'f' 1002 endtry 1003 call assert_equal('cf', g:Xpath) 1004 1005 XpathINIT 1006 try 1007 call T16_I() 1008 catch /E584:/ 1009 Xpath 'g' 1010 endtry 1011 call assert_equal('cg', g:Xpath) 1012endfunc 1013 1014"------------------------------------------------------------------------------- 1015" Test 17: Nesting of unmatched :if or :endif inside a :while {{{1 1016" 1017" The :while/:endwhile takes precedence in nesting over an unclosed 1018" :if or an unopened :endif. 1019"------------------------------------------------------------------------------- 1020 1021" While loops inside a function are continued on error. 1022func T17_F() 1023 let loops = 3 1024 while loops > 0 1025 let loops -= 1 1026 Xpath 'a' . loops 1027 if (loops == 1) 1028 Xpath 'b' . loops 1029 continue 1030 elseif (loops == 0) 1031 Xpath 'c' . loops 1032 break 1033 elseif 1 1034 Xpath 'd' . loops 1035 " endif missing! 1036 endwhile " :endwhile after :if 1 1037 Xpath 'e' 1038endfunc 1039 1040func T17_G() 1041 let loops = 2 1042 while loops > 0 1043 let loops -= 1 1044 Xpath 'a' . loops 1045 if 0 1046 Xpath 'b' . loops 1047 " endif missing 1048 endwhile " :endwhile after :if 0 1049endfunc 1050 1051func T17_H() 1052 let loops = 2 1053 while loops > 0 1054 let loops -= 1 1055 Xpath 'a' . loops 1056 " if missing! 1057 endif " :endif without :if in while 1058 Xpath 'b' . loops 1059 endwhile 1060endfunc 1061 1062" Error continuation outside a function is at the outermost :endwhile or :endif. 1063XpathINIT 1064let v:errmsg = '' 1065let loops = 2 1066while loops > 0 1067 let loops -= 1 1068 Xpath 'a' . loops 1069 if 0 1070 Xpath 'b' . loops 1071 " endif missing! Following :endwhile fails. 1072endwhile | Xpath 'c' 1073Xpath 'd' 1074call assert_match('E171:', v:errmsg) 1075call assert_equal('a1d', g:Xpath) 1076 1077func Test_unmatched_if_in_while() 1078 XpathINIT 1079 call assert_fails('call T17_F()', 'E171:') 1080 call assert_equal('a2d2a1b1a0c0e', g:Xpath) 1081 1082 XpathINIT 1083 call assert_fails('call T17_G()', 'E171:') 1084 call assert_equal('a1a0', g:Xpath) 1085 1086 XpathINIT 1087 call assert_fails('call T17_H()', 'E580:') 1088 call assert_equal('a1b1a0b0', g:Xpath) 1089endfunc 1090 1091"------------------------------------------------------------------------------- 1092"------------------------------------------------------------------------------- 1093"------------------------------------------------------------------------------- 1094" Test 87 using (expr) ? funcref : funcref {{{1 1095" 1096" Vim needs to correctly parse the funcref and even when it does 1097" not execute the funcref, it needs to consume the trailing () 1098"------------------------------------------------------------------------------- 1099 1100func Add2(x1, x2) 1101 return a:x1 + a:x2 1102endfu 1103 1104func GetStr() 1105 return "abcdefghijklmnopqrstuvwxyp" 1106endfu 1107 1108func Test_funcref_with_condexpr() 1109 call assert_equal(5, function('Add2')(2,3)) 1110 1111 call assert_equal(3, 1 ? function('Add2')(1,2) : function('Add2')(2,3)) 1112 call assert_equal(5, 0 ? function('Add2')(1,2) : function('Add2')(2,3)) 1113 " Make sure, GetStr() still works. 1114 call assert_equal('abcdefghijk', GetStr()[0:10]) 1115endfunc 1116 1117"------------------------------------------------------------------------------- 1118" Test 90: Recognizing {} in variable name. {{{1 1119"------------------------------------------------------------------------------- 1120 1121func Test_curlies() 1122 let s:var = 66 1123 let ns = 's' 1124 call assert_equal(66, {ns}:var) 1125 1126 let g:a = {} 1127 let g:b = 't' 1128 let g:a[g:b] = 77 1129 call assert_equal(77, g:a['t']) 1130endfunc 1131 1132"------------------------------------------------------------------------------- 1133" Test 91: using type(). {{{1 1134"------------------------------------------------------------------------------- 1135 1136func Test_type() 1137 call assert_equal(0, type(0)) 1138 call assert_equal(1, type("")) 1139 call assert_equal(2, type(function("tr"))) 1140 call assert_equal(2, type(function("tr", [8]))) 1141 call assert_equal(3, type([])) 1142 call assert_equal(4, type({})) 1143 call assert_equal(5, type(0.0)) 1144 call assert_equal(6, type(v:false)) 1145 call assert_equal(6, type(v:true)) 1146 call assert_equal(7, type(v:null)) 1147 call assert_equal(v:t_number, type(0)) 1148 call assert_equal(v:t_string, type("")) 1149 call assert_equal(v:t_func, type(function("tr"))) 1150 call assert_equal(v:t_list, type([])) 1151 call assert_equal(v:t_dict, type({})) 1152 call assert_equal(v:t_float, type(0.0)) 1153 call assert_equal(v:t_bool, type(v:false)) 1154 call assert_equal(v:t_bool, type(v:true)) 1155 call assert_equal(v:t_string, type(v:_null_string)) 1156 call assert_equal(v:t_list, type(v:_null_list)) 1157 call assert_equal(v:t_dict, type(v:_null_dict)) 1158 call assert_equal(v:t_blob, type(v:_null_blob)) 1159endfunc 1160 1161"------------------------------------------------------------------------------- 1162" Test 92: skipping code {{{1 1163"------------------------------------------------------------------------------- 1164 1165func Test_skip() 1166 let Fn = function('Test_type') 1167 call assert_false(0 && Fn[1]) 1168 call assert_false(0 && string(Fn)) 1169 call assert_false(0 && len(Fn)) 1170 let l = [] 1171 call assert_false(0 && l[1]) 1172 call assert_false(0 && string(l)) 1173 call assert_false(0 && len(l)) 1174 let f = 1.0 1175 call assert_false(0 && f[1]) 1176 call assert_false(0 && string(f)) 1177 call assert_false(0 && len(f)) 1178 let sp = v:null 1179 call assert_false(0 && sp[1]) 1180 call assert_false(0 && string(sp)) 1181 call assert_false(0 && len(sp)) 1182 1183endfunc 1184 1185"------------------------------------------------------------------------------- 1186" Test 93: :echo and string() {{{1 1187"------------------------------------------------------------------------------- 1188 1189func Test_echo_and_string() 1190 " String 1191 let a = 'foo bar' 1192 redir => result 1193 echo a 1194 echo string(a) 1195 redir END 1196 let l = split(result, "\n") 1197 call assert_equal(["foo bar", 1198 \ "'foo bar'"], l) 1199 1200 " Float 1201 if has('float') 1202 let a = -1.2e0 1203 redir => result 1204 echo a 1205 echo string(a) 1206 redir END 1207 let l = split(result, "\n") 1208 call assert_equal(["-1.2", 1209 \ "-1.2"], l) 1210 endif 1211 1212 " Funcref 1213 redir => result 1214 echo function('string') 1215 echo string(function('string')) 1216 redir END 1217 let l = split(result, "\n") 1218 call assert_equal(["string", 1219 \ "function('string')"], l) 1220 1221 " Empty dictionaries in a list 1222 let a = {} 1223 redir => result 1224 echo [a, a, a] 1225 echo string([a, a, a]) 1226 redir END 1227 let l = split(result, "\n") 1228 call assert_equal(["[{}, {}, {}]", 1229 \ "[{}, {}, {}]"], l) 1230 1231 " Empty dictionaries in a dictionary 1232 let a = {} 1233 let b = {"a": a, "b": a} 1234 redir => result 1235 echo b 1236 echo string(b) 1237 redir END 1238 let l = split(result, "\n") 1239 call assert_equal(["{'a': {}, 'b': {}}", 1240 \ "{'a': {}, 'b': {}}"], l) 1241 1242 " Empty lists in a list 1243 let a = [] 1244 redir => result 1245 echo [a, a, a] 1246 echo string([a, a, a]) 1247 redir END 1248 let l = split(result, "\n") 1249 call assert_equal(["[[], [], []]", 1250 \ "[[], [], []]"], l) 1251 1252 " Empty lists in a dictionary 1253 let a = [] 1254 let b = {"a": a, "b": a} 1255 redir => result 1256 echo b 1257 echo string(b) 1258 redir END 1259 let l = split(result, "\n") 1260 call assert_equal(["{'a': [], 'b': []}", 1261 \ "{'a': [], 'b': []}"], l) 1262endfunc 1263 1264"------------------------------------------------------------------------------- 1265" Test 94: 64-bit Numbers {{{1 1266"------------------------------------------------------------------------------- 1267 1268func Test_num64() 1269 call assert_notequal( 4294967296, 0) 1270 call assert_notequal(-4294967296, 0) 1271 call assert_equal( 4294967296, 0xFFFFffff + 1) 1272 call assert_equal(-4294967296, -0xFFFFffff - 1) 1273 1274 call assert_equal( 9223372036854775807, 1 / 0) 1275 call assert_equal(-9223372036854775807, -1 / 0) 1276 call assert_equal(-9223372036854775807 - 1, 0 / 0) 1277 1278 if has('float') 1279 call assert_equal( 0x7FFFffffFFFFffff, float2nr( 1.0e150)) 1280 call assert_equal(-0x7FFFffffFFFFffff, float2nr(-1.0e150)) 1281 endif 1282 1283 let rng = range(0xFFFFffff, 0x100000001) 1284 call assert_equal([0xFFFFffff, 0x100000000, 0x100000001], rng) 1285 call assert_equal(0x100000001, max(rng)) 1286 call assert_equal(0xFFFFffff, min(rng)) 1287 call assert_equal(rng, sort(range(0x100000001, 0xFFFFffff, -1), 'N')) 1288endfunc 1289 1290"------------------------------------------------------------------------------- 1291" Test 95: lines of :append, :change, :insert {{{1 1292"------------------------------------------------------------------------------- 1293 1294function! DefineFunction(name, body) 1295 let func = join(['function! ' . a:name . '()'] + a:body + ['endfunction'], "\n") 1296 exec func 1297endfunction 1298 1299func Test_script_lines() 1300 " :append 1301 try 1302 call DefineFunction('T_Append', [ 1303 \ 'append', 1304 \ 'py <<EOS', 1305 \ '.', 1306 \ ]) 1307 catch 1308 call assert_report("Can't define function") 1309 endtry 1310 try 1311 call DefineFunction('T_Append', [ 1312 \ 'append', 1313 \ 'abc', 1314 \ ]) 1315 call assert_report("Shouldn't be able to define function") 1316 catch 1317 call assert_exception('Vim(function):E126: Missing :endfunction') 1318 endtry 1319 1320 " :change 1321 try 1322 call DefineFunction('T_Change', [ 1323 \ 'change', 1324 \ 'py <<EOS', 1325 \ '.', 1326 \ ]) 1327 catch 1328 call assert_report("Can't define function") 1329 endtry 1330 try 1331 call DefineFunction('T_Change', [ 1332 \ 'change', 1333 \ 'abc', 1334 \ ]) 1335 call assert_report("Shouldn't be able to define function") 1336 catch 1337 call assert_exception('Vim(function):E126: Missing :endfunction') 1338 endtry 1339 1340 " :insert 1341 try 1342 call DefineFunction('T_Insert', [ 1343 \ 'insert', 1344 \ 'py <<EOS', 1345 \ '.', 1346 \ ]) 1347 catch 1348 call assert_report("Can't define function") 1349 endtry 1350 try 1351 call DefineFunction('T_Insert', [ 1352 \ 'insert', 1353 \ 'abc', 1354 \ ]) 1355 call assert_report("Shouldn't be able to define function") 1356 catch 1357 call assert_exception('Vim(function):E126: Missing :endfunction') 1358 endtry 1359endfunc 1360 1361"------------------------------------------------------------------------------- 1362" Test 96: line continuation {{{1 1363" 1364" Undefined behavior was detected by ubsan with line continuation 1365" after an empty line. 1366"------------------------------------------------------------------------------- 1367func Test_script_emty_line_continuation() 1368 1369 \ 1370endfunc 1371 1372"------------------------------------------------------------------------------- 1373" Test 97: bitwise functions {{{1 1374"------------------------------------------------------------------------------- 1375func Test_bitwise_functions() 1376 " and 1377 call assert_equal(127, and(127, 127)) 1378 call assert_equal(16, and(127, 16)) 1379 eval 127->and(16)->assert_equal(16) 1380 call assert_equal(0, and(127, 128)) 1381 call assert_fails("call and(1.0, 1)", 'E805:') 1382 call assert_fails("call and([], 1)", 'E745:') 1383 call assert_fails("call and({}, 1)", 'E728:') 1384 call assert_fails("call and(1, 1.0)", 'E805:') 1385 call assert_fails("call and(1, [])", 'E745:') 1386 call assert_fails("call and(1, {})", 'E728:') 1387 " or 1388 call assert_equal(23, or(16, 7)) 1389 call assert_equal(15, or(8, 7)) 1390 eval 8->or(7)->assert_equal(15) 1391 call assert_equal(123, or(0, 123)) 1392 call assert_fails("call or(1.0, 1)", 'E805:') 1393 call assert_fails("call or([], 1)", 'E745:') 1394 call assert_fails("call or({}, 1)", 'E728:') 1395 call assert_fails("call or(1, 1.0)", 'E805:') 1396 call assert_fails("call or(1, [])", 'E745:') 1397 call assert_fails("call or(1, {})", 'E728:') 1398 " xor 1399 call assert_equal(0, xor(127, 127)) 1400 call assert_equal(111, xor(127, 16)) 1401 eval 127->xor(16)->assert_equal(111) 1402 call assert_equal(255, xor(127, 128)) 1403 call assert_fails("call xor(1.0, 1)", 'E805:') 1404 call assert_fails("call xor([], 1)", 'E745:') 1405 call assert_fails("call xor({}, 1)", 'E728:') 1406 call assert_fails("call xor(1, 1.0)", 'E805:') 1407 call assert_fails("call xor(1, [])", 'E745:') 1408 call assert_fails("call xor(1, {})", 'E728:') 1409 " invert 1410 call assert_equal(65408, and(invert(127), 65535)) 1411 eval 127->invert()->and(65535)->assert_equal(65408) 1412 call assert_equal(65519, and(invert(16), 65535)) 1413 call assert_equal(65407, and(invert(128), 65535)) 1414 call assert_fails("call invert(1.0)", 'E805:') 1415 call assert_fails("call invert([])", 'E745:') 1416 call assert_fails("call invert({})", 'E728:') 1417endfunc 1418 1419" Test trailing text after :endfunction {{{1 1420func Test_endfunction_trailing() 1421 call assert_false(exists('*Xtest')) 1422 1423 exe "func Xtest()\necho 'hello'\nendfunc\nlet done = 'yes'" 1424 call assert_true(exists('*Xtest')) 1425 call assert_equal('yes', done) 1426 delfunc Xtest 1427 unlet done 1428 1429 exe "func Xtest()\necho 'hello'\nendfunc|let done = 'yes'" 1430 call assert_true(exists('*Xtest')) 1431 call assert_equal('yes', done) 1432 delfunc Xtest 1433 unlet done 1434 1435 " trailing line break 1436 exe "func Xtest()\necho 'hello'\nendfunc\n" 1437 call assert_true(exists('*Xtest')) 1438 delfunc Xtest 1439 1440 set verbose=1 1441 exe "func Xtest()\necho 'hello'\nendfunc \" garbage" 1442 call assert_notmatch('W22:', split(execute('1messages'), "\n")[0]) 1443 call assert_true(exists('*Xtest')) 1444 delfunc Xtest 1445 1446 exe "func Xtest()\necho 'hello'\nendfunc garbage" 1447 call assert_match('W22:', split(execute('1messages'), "\n")[0]) 1448 call assert_true(exists('*Xtest')) 1449 delfunc Xtest 1450 set verbose=0 1451 1452 function Foo() 1453 echo 'hello' 1454 endfunction | echo 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' 1455 delfunc Foo 1456endfunc 1457 1458func Test_delfunction_force() 1459 delfunc! Xtest 1460 delfunc! Xtest 1461 func Xtest() 1462 echo 'nothing' 1463 endfunc 1464 delfunc! Xtest 1465 delfunc! Xtest 1466endfunc 1467 1468" Test using bang after user command {{{1 1469func Test_user_command_with_bang() 1470 command -bang Nieuw let nieuw = 1 1471 Ni! 1472 call assert_equal(1, nieuw) 1473 unlet nieuw 1474 delcommand Nieuw 1475endfunc 1476 1477" Test for script-local function 1478func <SID>DoLast() 1479 call append(line('$'), "last line") 1480endfunc 1481 1482func s:DoNothing() 1483 call append(line('$'), "nothing line") 1484endfunc 1485 1486func Test_script_local_func() 1487 set nocp nomore viminfo+=nviminfo 1488 new 1489 nnoremap <buffer> _x :call <SID>DoNothing()<bar>call <SID>DoLast()<bar>delfunc <SID>DoNothing<bar>delfunc <SID>DoLast<cr> 1490 1491 normal _x 1492 call assert_equal('nothing line', getline(2)) 1493 call assert_equal('last line', getline(3)) 1494 enew! | close 1495endfunc 1496 1497func Test_compound_assignment_operators() 1498 " Test for number 1499 let x = 1 1500 let x += 10 1501 call assert_equal(11, x) 1502 let x -= 5 1503 call assert_equal(6, x) 1504 let x *= 4 1505 call assert_equal(24, x) 1506 let x /= 3 1507 call assert_equal(8, x) 1508 let x %= 3 1509 call assert_equal(2, x) 1510 let x .= 'n' 1511 call assert_equal('2n', x) 1512 1513 " Test special cases: division or modulus with 0. 1514 let x = 1 1515 let x /= 0 1516 call assert_equal(0x7FFFFFFFFFFFFFFF, x) 1517 1518 let x = -1 1519 let x /= 0 1520 call assert_equal(-0x7FFFFFFFFFFFFFFF, x) 1521 1522 let x = 0 1523 let x /= 0 1524 call assert_equal(-0x7FFFFFFFFFFFFFFF - 1, x) 1525 1526 let x = 1 1527 let x %= 0 1528 call assert_equal(0, x) 1529 1530 let x = -1 1531 let x %= 0 1532 call assert_equal(0, x) 1533 1534 let x = 0 1535 let x %= 0 1536 call assert_equal(0, x) 1537 1538 " Test for string 1539 let x = 'str' 1540 let x .= 'ing' 1541 call assert_equal('string', x) 1542 let x += 1 1543 call assert_equal(1, x) 1544 1545 if has('float') 1546 " Test for float 1547 let x -= 1.5 1548 call assert_equal(-0.5, x) 1549 let x = 0.5 1550 let x += 4.5 1551 call assert_equal(5.0, x) 1552 let x -= 1.5 1553 call assert_equal(3.5, x) 1554 let x *= 3.0 1555 call assert_equal(10.5, x) 1556 let x /= 2.5 1557 call assert_equal(4.2, x) 1558 call assert_fails('let x %= 0.5', 'E734') 1559 call assert_fails('let x .= "f"', 'E734') 1560 endif 1561 1562 " Test for environment variable 1563 let $FOO = 1 1564 call assert_fails('let $FOO += 1', 'E734') 1565 call assert_fails('let $FOO -= 1', 'E734') 1566 call assert_fails('let $FOO *= 1', 'E734') 1567 call assert_fails('let $FOO /= 1', 'E734') 1568 call assert_fails('let $FOO %= 1', 'E734') 1569 let $FOO .= 's' 1570 call assert_equal('1s', $FOO) 1571 unlet $FOO 1572 1573 " Test for option variable (type: number) 1574 let &scrolljump = 1 1575 let &scrolljump += 5 1576 call assert_equal(6, &scrolljump) 1577 let &scrolljump -= 2 1578 call assert_equal(4, &scrolljump) 1579 let &scrolljump *= 3 1580 call assert_equal(12, &scrolljump) 1581 let &scrolljump /= 2 1582 call assert_equal(6, &scrolljump) 1583 let &scrolljump %= 5 1584 call assert_equal(1, &scrolljump) 1585 call assert_fails('let &scrolljump .= "j"', 'E734') 1586 set scrolljump&vim 1587 1588 " Test for register 1589 let @/ = 1 1590 call assert_fails('let @/ += 1', 'E734') 1591 call assert_fails('let @/ -= 1', 'E734') 1592 call assert_fails('let @/ *= 1', 'E734') 1593 call assert_fails('let @/ /= 1', 'E734') 1594 call assert_fails('let @/ %= 1', 'E734') 1595 let @/ .= 's' 1596 call assert_equal('1s', @/) 1597 let @/ = '' 1598endfunc 1599 1600func Test_unlet_env() 1601 let $TESTVAR = 'yes' 1602 call assert_equal('yes', $TESTVAR) 1603 call assert_fails('lockvar $TESTVAR', 'E940') 1604 call assert_fails('unlockvar $TESTVAR', 'E940') 1605 call assert_equal('yes', $TESTVAR) 1606 if 0 1607 unlet $TESTVAR 1608 endif 1609 call assert_equal('yes', $TESTVAR) 1610 unlet $TESTVAR 1611 call assert_equal('', $TESTVAR) 1612endfunc 1613 1614func Test_funccall_garbage_collect() 1615 func Func(x, ...) 1616 call add(a:x, a:000) 1617 endfunc 1618 call Func([], []) 1619 " Must not crash cause by invalid freeing 1620 call test_garbagecollect_now() 1621 call assert_true(v:true) 1622 delfunc Func 1623endfunc 1624 1625func Test_function_defined_line() 1626 if has('gui_running') 1627 " Can't catch the output of gvim. 1628 return 1629 endif 1630 1631 let lines =<< trim [CODE] 1632 " F1 1633 func F1() 1634 " F2 1635 func F2() 1636 " 1637 " 1638 " 1639 return 1640 endfunc 1641 " F3 1642 execute "func F3()\n\n\n\nreturn\nendfunc" 1643 " F4 1644 execute "func F4()\n 1645 \\n 1646 \\n 1647 \\n 1648 \return\n 1649 \endfunc" 1650 endfunc 1651 " F5 1652 execute "func F5()\n\n\n\nreturn\nendfunc" 1653 " F6 1654 execute "func F6()\n 1655 \\n 1656 \\n 1657 \\n 1658 \return\n 1659 \endfunc" 1660 call F1() 1661 verbose func F1 1662 verbose func F2 1663 verbose func F3 1664 verbose func F4 1665 verbose func F5 1666 verbose func F6 1667 qall! 1668 [CODE] 1669 1670 call writefile(lines, 'Xtest.vim') 1671 let res = system(v:progpath .. ' --clean -es -X -S Xtest.vim') 1672 call assert_equal(0, v:shell_error) 1673 1674 let m = matchstr(res, 'function F1()[^[:print:]]*[[:print:]]*') 1675 call assert_match(' line 2$', m) 1676 1677 let m = matchstr(res, 'function F2()[^[:print:]]*[[:print:]]*') 1678 call assert_match(' line 4$', m) 1679 1680 let m = matchstr(res, 'function F3()[^[:print:]]*[[:print:]]*') 1681 call assert_match(' line 11$', m) 1682 1683 let m = matchstr(res, 'function F4()[^[:print:]]*[[:print:]]*') 1684 call assert_match(' line 13$', m) 1685 1686 let m = matchstr(res, 'function F5()[^[:print:]]*[[:print:]]*') 1687 call assert_match(' line 21$', m) 1688 1689 let m = matchstr(res, 'function F6()[^[:print:]]*[[:print:]]*') 1690 call assert_match(' line 23$', m) 1691 1692 call delete('Xtest.vim') 1693endfunc 1694 1695"------------------------------------------------------------------------------- 1696" Modelines {{{1 1697" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker 1698"------------------------------------------------------------------------------- 1699