1# This file is part of grecs -*- Autotest -*- 2# Copyright (C) 2014-2016 Sergey Poznyakoff 3# 4# Grecs is free software; you can redistribute it and/or modify 5# it under the terms of the GNU General Public License as published by 6# the Free Software Foundation; either version 3, or (at your option) 7# any later version. 8# 9# Grecs is distributed in the hope that it will be useful, 10# but WITHOUT ANY WARRANTY; without even the implied warranty of 11# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12# GNU General Public License for more details. 13# 14# You should have received a copy of the GNU General Public License 15# along with Grecs. If not, see <http://www.gnu.org/licenses/>. 16 17AT_BANNER(Wordsplit) 18 19m4_pushdef([wspnum],[0]) 20m4_pushdef([wspid]) 21m4_pushdef([wspgroupnum]) 22m4_pushdef([wspgroupname]) 23 24m4_pushdef([genkw],[dnl 25m4_define([wspid],m4_format([wordsplit%03d wsp%03d],wspnum))dnl 26m4_if(wspgroupname,,,[m4_define([wspid],wspid[ ]dnl 27m4_format(wspgroupname[ ]wspgroupname[%03d],wspgroupnum))dnl 28m4_define([wspgroupnum],m4_incr(wspgroupnum))])dnl 29m4_define([wspnum],m4_incr(wspnum))dnl 30wspid]) 31 32m4_pushdef([WSPGROUP],[ 33m4_define([wspgroupname],$1) 34m4_define([wspgroupnum],0)]) 35 36dnl ------------------------------------------------------------ 37dnl TESTWSP([NAME], [KW = `'], [OPTS], [INPUT], [STDOUT = `'], 38dnl [STDERR = `'], [ENV], [PROLOGUE]) 39dnl 40m4_pushdef([TESTWSP],[ 41AT_SETUP([$1]) 42AT_KEYWORDS([wordsplit wsp ]genkw[ $2]) 43AT_CHECK([$8 44$7 wsp $3 <<'EOT' 45[$4] 46EOT 47], 48[0], 49[$5], 50[$6]) 51AT_CLEANUP 52]) 53 54dnl ------------------------------------------------------------ 55dnl The first part reproduces legacy argcv tests 56dnl ------------------------------------------------------------ 57 58TESTWSP([simple input],[wsp-simple],[], 59[1 2 3], 60[NF: 3 610: 1 621: 2 632: 3 64]) 65 66TESTWSP([quoted space],[wsp-quoted],[], 67[quoted\ space], 68[NF: 1 690: "quoted space" 70]) 71 72TESTWSP([tab character],[wsp-tab],[], 73[a "tab character"], 74[NF: 2 750: a 761: tab\tcharacter 77]) 78 79WSPGROUP(wsp-escape) 80TESTWSP([octal and hex escapes],[],[], 81[\157\143\164\141\154\40and\x20\x68\x65\x78], 82[NF: 1 830: "octal and hex" 84]) 85 86TESTWSP([octal and hex escapes 2],[],[], 87[\157\143\164\141\154\40 and \x20\x68\x65\x78], 88[NF: 3 890: "octal " 901: and 912: " hex" 92]) 93 94TESTWSP([escape representation],[],[], 95[A\x3-\48\39], 96[NF: 1 970: A\003-\0048\0039 98]) 99 100WSPGROUP() 101 102dnl ------------------------------------------------------------ 103dnl Test worsplit-specific behavior 104dnl ------------------------------------------------------------ 105TESTWSP([append],[wsp-append],[append], 106[jeden dwa trzy 107cztery 108piec szesc], 109[NF: 3 1100: jeden 1111: dwa 1122: trzy 113NF: 4 1140: jeden 1151: dwa 1162: trzy 1173: cztery 118NF: 6 1190: jeden 1201: dwa 1212: trzy 1223: cztery 1234: piec 1245: szesc 125]) 126 127TESTWSP([dooffs],[wsp-doofs ],[dooffs 3 jeden dwa trzy], 128[cztery piec], 129[NF: 2 (3) 130(0): jeden 131(1): dwa 132(2): trzy 1333: cztery 1344: piec 135]) 136 137WSPGROUP(wsp-var) 138 139TESTWSP([variable substitutions: single var],[],[], 140[a $FOO test], 141[NF: 3 1420: a 1431: bar 1442: test 145], 146[], 147[FOO=bar]) 148 149TESTWSP([variable substitutions: concatenated vars],[], 150[], 151[a $FOO${BAR}ent test], 152[NF: 3 1530: a 1541: stringent 1552: test 156], 157[], 158[FOO=str BAR=ing]) 159 160TESTWSP([variable substitutions: field splitting],[],[], 161[a $FOO test], 162[NF: 4 1630: a 1641: variable 1652: substitution 1663: test 167], 168[], 169[FOO="variable substitution"]) 170 171TESTWSP([variable substitutions: double-quoted variable],[],[], 172[a "$FOO" test], 173[NF: 3 1740: a 1751: "variable substitution" 1762: test 177], 178[], 179[FOO="variable substitution"]) 180 181TESTWSP([variable substitutions: single-quoted variable],[],[], 182[a '$FOO' test], 183[NF: 3 1840: a 1851: $FOO 1862: test 187], 188[], 189[FOO="variable substitution"]) 190 191TESTWSP([undefined variables 1],[],[], 192[a $FOO test a${FOO}b], 193[NF: 3 1940: a 1951: test 1962: ab 197], 198[], 199[unset FOO;]) 200 201TESTWSP([undefined variables 2],[],[keepundef], 202[a $FOO test a${FOO}b], 203[NF: 4 2040: a 2051: $FOO 2062: test 2073: a${FOO}b 208], 209[], 210[unset FOO;]) 211 212TESTWSP([warn about undefined variables],[],[warnundef], 213[$FOO], 214[NF: 0 215], 216[warning: undefined variable `FOO' 217], 218[unset FOO;]) 219 220TESTWSP([bail out on undefined variables],[],[undef], 221[$FOO], 222[], 223[undefined variable 224], 225[unset FOO;]) 226 227TESTWSP([disable variable expansion],[],[novar], 228[$FOO], 229[NF: 1 2300: $FOO 231], 232[], 233[FOO=bar]) 234 235TESTWSP([K/V environment],[wsp-env-kv wsp-env_kv], 236[env_kv], 237[$FOO a$BAZ], 238[NF: 2 2390: bar 2401: aqux 241], 242[], 243[FOO=bar BAZ=qux]) 244 245TESTWSP([nosplit with expansion],[wsp-var-nosplit],[nosplit], 246[a $FOO test], 247[NF: 1 2480: "a variable expansion test\n" 249], 250[], 251[FOO="variable expansion"]) 252 253TESTWSP([nosplit without expansion],[],[nosplit novar], 254[a $FOO test], 255[NF: 1 2560: "a $FOO test\n" 257], 258[], 259[FOO="variable expansion"]) 260 261TESTWSP([default value (defined)],[],[], 262[${FOO:-bar}], 263[NF: 1 2640: qux 265], 266[], 267[FOO=qux]) 268 269TESTWSP([default value],[],[], 270[${FOO:-bar}], 271[NF: 1 2720: bar 273]) 274 275TESTWSP([default value (defined)],[],[], 276[${FOO:-bar}], 277[NF: 1 2780: qux 279], 280[], 281[FOO=qux]) 282 283TESTWSP([default value (:- null)],[],[], 284[${FOO:-bar}], 285[NF: 1 2860: bar 287], 288[], 289[FOO=]) 290 291TESTWSP([default value (- null)],[],[], 292[${FOO-bar}], 293[NF: 0 294], 295[], 296[FOO=]) 297 298TESTWSP([default value (- null, unset)],[],[], 299[${FOO-bar}], 300[NF: 1 3010: bar 302]) 303 304TESTWSP([assign default values],[],[], 305[${FOO=bar} 306$FOO], 307[NF: 1 3080: bar 309NF: 1 3100: bar 311]) 312 313TESTWSP([default error message (var defined)],[],[], 314[a ${FOO:?} test], 315[NF: 3 3160: a 3171: bar 3182: test 319], 320[], 321[FOO=bar]) 322 323TESTWSP([default error message],[],[], 324[${FOO:?}], 325[NF: 0 326], 327[FOO: variable null or not set 328]) 329 330TESTWSP([custom error message (defined)],[wsp-custom-err wsp-custom-err00],[], 331[a ${FOO:?please define it} test], 332[NF: 3 3330: a 3341: bar 3352: test 336], 337[], 338[FOO=bar]) 339 340TESTWSP([custom error message],[wsp-custom-err wsp-custom-err01],[], 341[a ${FOO:?please define it} test], 342[NF: 2 3430: a 3441: test 345], 346[FOO: please define it 347]) 348 349TESTWSP([alternate value (defined)],[wsp-alt wsp-alt00],[], 350[a ${FOO:+isset} test], 351[NF: 3 3520: a 3531: isset 3542: test 355], 356[], 357[FOO=bar]) 358 359TESTWSP([alternate value],[wsp-alt wsp-alt01],[], 360[a ${FOO:+isset} test], 361[NF: 2 3620: a 3631: test 364], 365[], 366[unset FOO;]) 367 368TESTWSP([getvar],[wsp-getvar], 369[foo=bar x=quux], 370[begin $foo $x end], 371[NF: 4 3720: begin 3731: bar 3742: quux 3753: end 376], 377[], 378[], 379[unset foo; unset x]) 380 381TESTWSP([getvar and env],[wsp-getvar], 382[foo=bar x=quux y=xur], 383[begin $foo $TVAR $x $y end], 384[NF: 6 3850: begin 3861: bar 3872: 12 3883: quux 3894: zwar 3905: end 391], 392[], 393[TVAR=12 y=zwar], 394[unset foo; unset x]) 395 396TESTWSP([getvar, alternate value],[wsp-getvar], 397[foo=bar], 398[a ${foo:+isset}], 399[NF: 2 4000: a 4011: isset 402]) 403 404WSPGROUP() 405 406TESTWSP([ignore quotes],[wsp-ignore-quotes ],[-quote], 407["a text"], 408[NF: 2 4090: "\"a" 4101: "text\"" 411]) 412 413WSPGROUP(wsp-delim) 414 415TESTWSP([custom delimiters (squeeze)],[], 416[delim : -ws trimnl], 417[semicolon: separated::list: of :words], 418[NF: 5 4190: semicolon 4201: " separated" 4212: list 4223: " of " 4234: words 424]) 425 426TESTWSP([custom delimiters (no squeeze)],[], 427[delim : -ws -squeeze_delims trimnl], 428[semicolon: separated::list: of :words], 429[NF: 6 4300: semicolon 4311: " separated" 4322: "" 4333: list 4344: " of " 4355: words 436]) 437 438TESTWSP([custom, with returned delimiters],[], 439[delim : -ws trimnl return_delims], 440[semicolon: separated::list: of :words], 441[NF: 9 4420: semicolon 4431: : 4442: " separated" 4453: : 4464: list 4475: : 4486: " of " 4497: : 4508: words 451]) 452 453TESTWSP([custom, with returned & squeezed delimiters],[], 454[delim : -ws trimnl return_delims -squeeze_delims], 455[semicolon: separated::list: of :words], 456[NF: 10 4570: semicolon 4581: : 4592: " separated" 4603: : 4614: : 4625: list 4636: : 4647: " of " 4658: : 4669: words 467]) 468 469WSPGROUP(wsp-sed) 470 471TESTWSP([sed expressions],[],[sed], 472[arg1 s/foo/bar/g;s/bar baz/quz quux/ arg2], 473[NF: 3 4740: arg1 4751: "s/foo/bar/g;s/bar baz/quz quux/" 4762: arg2 477]) 478 479WSPGROUP() 480 481TESTWSP([C escapes on],[wcp-c-escape],[cescapes], 482[a\ttab form\ffeed and new\nline], 483[NF: 4 4840: a\ttab 4851: form\ffeed 4862: and 4873: new\nline 488]) 489 490TESTWSP([C escapes off],[wcp-c-escape-off],[-cescapes], 491[a\ttab form\ffeed and new\nline], 492[NF: 4 4930: attab 4941: formffeed 4952: and 4963: newnline 497]) 498 499TESTWSP([ws elimination],[wsp-ws-elim],[delim ' ()' ws return_delims], 500[( list items )], 501[NF: 4 5020: ( 5031: list 5042: items 5053: ) 506]) 507 508TESTWSP([ws elimination + return delim],[wsp-ws-elim-ret], 509[-default novar nocmd delim ":," return_delims ws dquote], 510["foo" : "bar", "quux" : "baaz" ], 511[NF: 7 5120: foo 5131: : 5142: bar 5153: , 5164: quux 5175: : 5186: baaz 519]) 520 521TESTWSP([empty quotes],[wsp-empty-quotes],[delim : ws return_delims], 522[t=""], 523[NF: 1 5240: t= 525]) 526 527TESTWSP([delimiter following empty quotes], 528[],[delim : ws return_delims], 529[t="":r], 530[NF: 3 5310: t= 5321: : 5332: r 534]) 535 536TESTWSP([suppress ws trimming within quotes], 537[], 538[default delim , ws return_delims], 539[nocomponent,nonewline, formatfield="In message %{text}, "], 540[NF: 5 5410: nocomponent 5421: , 5432: nonewline 5443: , 5454: "formatfield=In message %{text}, " 546]) 547 548TESTWSP([unescape], 549[wsp-unescape wsp-unescape-simple], 550[-default novar nocmd quote escape ':+:\\""'], 551[\Seen "quote \"" "bs \\"], 552[NF: 3 5530: \\Seen 5541: "quote \"" 5552: "bs \\" 556]) 557 558TESTWSP([unescape: word/quote], 559[wsp-unescape wsp-unescape-word], 560[-default novar nocmd quote escape-word '\\""' escape-quote ':+0x:\\""'], 561[\Seen "quote \"" "bs \\" "3\x31 \101" 3\x31 \101], 562[NF: 6 5630: Seen 5641: "quote \"" 5652: "bs \\" 5663: "31 A" 5674: 3x31 5685: 101 569]) 570 571TESTWSP([dquote],[],[-default novar nocmd dquote], 572[a "quoted example" isn't it], 573[NF: 4 5740: a 5751: "quoted example" 5762: isn't 5773: it 578]) 579 580TESTWSP([squote],[],[-default novar nocmd squote], 581[a 'quoted example' isn"t it], 582[NF: 4 5830: a 5841: "quoted example" 5852: "isn\"t" 5863: it 587]) 588 589WSPGROUP(wsp-incr) 590 591TESTWSP([incremental],[],[incremental], 592[incremental "input test" line 593 594 595], 596[NF: 1 5970: incremental 598NF: 1 5990: "input test" 600NF: 1 6010: line 602], 603[input exhausted 604]) 605 606TESTWSP([incremental append],[],[incremental append], 607[incremental "input test" line 608 609 610], 611[NF: 1 6120: incremental 613NF: 2 6140: incremental 6151: "input test" 616NF: 3 6170: incremental 6181: "input test" 6192: line 620], 621[input exhausted 622]) 623 624TESTWSP([incremental ws], 625[],[return_delims -squeeze_delims incremental ws], 626[a list test 627 628 629], 630[NF: 1 6310: a 632NF: 1 6330: list 634NF: 1 6350: test 636], 637[input exhausted 638]) 639 640TESTWSP([incremental nosplit],[],[incremental nosplit], 641[incremental "input test" line 642], 643[NF: 1 6440: "incremental \"input test\" line" 645], 646[input exhausted 647]) 648 649dnl Something that doesn't fit into TESTWSP 650 651AT_SETUP([simple command substitution]) 652AT_KEYWORDS([wordsplit wsp wsp-cmd wsp-cmd-1]) 653AT_CHECK([ 654mkdir dir 655> dir/file 656 657wsp -nocmd <<'EOT' 658begin $(find dir) end 659EOT 660], 661[0], 662[NF: 4 6630: begin 6641: dir 6652: dir/file 6663: end 667]) 668AT_CLEANUP 669 670AT_SETUP([quoted command substitution]) 671AT_KEYWORDS([wordsplit wsp wsp-cmd wsp-cmd-2]) 672AT_CHECK([ 673mkdir dir 674> dir/file 675 676wsp -nocmd <<'EOT' 677begin "$(find dir)" end 678EOT 679], 680[0], 681[NF: 3 6820: begin 6831: "dir dir/file" 6842: end 685]) 686AT_CLEANUP 687 688AT_SETUP([coalesced command substitution]) 689AT_KEYWORDS([wordsplit wsp wsp-cmd wsp-cmd-3]) 690AT_CHECK([ 691mkdir dir 692> dir/file 693 694wsp -nocmd <<'EOT' 695begin($(find dir))end 696EOT 697], 698[0], 699[NF: 2 7000: begin(dir 7011: dir/file)end 702]) 703AT_CLEANUP 704 705AT_SETUP([quoted coalesced command substitution]) 706AT_KEYWORDS([wordsplit wsp wsp-cmd wsp-cmd-4]) 707AT_CHECK([ 708mkdir dir 709> dir/file 710 711wsp -nocmd <<'EOT' 712"begin($(find dir))end" 713EOT 714], 715[0], 716[NF: 1 7170: "begin(dir dir/file)end" 718]) 719AT_CLEANUP 720 721AT_SETUP([variable and command substitution]) 722AT_KEYWORDS([wordsplit wsp wsp-var wsp-var24 wsp-cmd wsp-cmd-5]) 723AT_CHECK([ 724mkdir dir 725> dir/file 726 727DIR=dir wsp -nocmd -novar<<'EOT' 728begin $DIR $(find $DIR) end 729EOT 730], 731[0], 732[NF: 5 7330: begin 7341: dir 7352: dir 7363: dir/file 7374: end 738]) 739AT_CLEANUP 740 741AT_SETUP([variable expansion and command substitution in quotes]) 742AT_KEYWORDS([wordsplit wsp wsp-var wsp-var25 wsp-cmd wsp-cmd-6]) 743AT_CHECK([ 744mkdir dir 745> dir/file 746 747DIR=dir BEGIN=begin wsp -nocmd -novar<<'EOT' 748"${BEGIN}($(find $DIR))end" 749EOT 750], 751[0], 752[NF: 1 7530: "begin(dir dir/file)end" 754]) 755AT_CLEANUP 756 757AT_SETUP([nested commands]) 758AT_KEYWORDS([wordsplit wsp wsp-cmd]) 759AT_CHECK([ 760AT_DATA([input],[foo 761bar 762baz 763]) 764SUFFIX=put wsp -nocmd -novar <<'EOT' 765$(echo output $(cat in$SUFFIX)) 766EOT 767], 768[0], 769[NF: 4 7700: output 7711: foo 7722: bar 7733: baz 774]) 775AT_CLEANUP 776 777AT_SETUP([pathname expansion]) 778AT_KEYWORDS([wordsplit wsp wsp-path wsp-path-1]) 779AT_CHECK([ 780mkdir dir 781> dir/1.c 782> dir/2.c 783> dir/3.b 784 785wsp pathexpand<<'EOT' 786begin dir/*.c end 787EOT 788], 789[0], 790[NF: 4 7910: begin 7921: dir/1.c 7932: dir/2.c 7943: end 795]) 796AT_CLEANUP 797 798AT_SETUP([pathname expansion: no match]) 799AT_KEYWORDS([wordsplit wsp wsp-path wsp-path-2]) 800AT_CHECK([ 801mkdir dir 802> dir/1.c 803> dir/2.b 804 805wsp pathexpand<<'EOT' 806begin dir/*.d end 807EOT 808], 809[0], 810[NF: 3 8110: begin 8121: dir/*.d 8132: end 814]) 815AT_CLEANUP 816 817AT_SETUP([pathname expansion: nullglob]) 818AT_KEYWORDS([wordsplit wsp wsp-path wsp-path-3]) 819AT_CHECK([ 820mkdir dir 821> dir/1.c 822> dir/2.b 823 824wsp pathexpand nullglob<<'EOT' 825begin dir/*.d end 826EOT 827], 828[0], 829[NF: 2 8300: begin 8311: end 832]) 833AT_CLEANUP 834 835AT_SETUP([pathname expansion: failglob]) 836AT_KEYWORDS([wordsplit wsp wsp-path wsp-path-4]) 837AT_CHECK([ 838mkdir dir 839> dir/1.c 840> dir/2.b 841 842wsp pathexpand failglob<<'EOT' 843begin dir/*.d end 844EOT 845], 846[0], 847[], 848[no files match pattern dir/*.d 849]) 850AT_CLEANUP 851 852TESTWSP([append],[],[-- extra arguments follow], 853[some words and], 854[NF: 6 8550: some 8561: words 8572: and 8583: extra 8594: arguments 8605: follow 861]) 862 863TESTWSP([append + dooffs + env],[], 864[dooffs 2 preface words V=2 -- extra arguments follow], 865[some words and var=$V], 866[NF: 7 (2) 867(0): preface 868(1): words 8692: some 8703: words 8714: and 8725: var=2 8736: extra 8747: arguments 8758: follow 876]) 877 878m4_popdef([TESTWSP]) 879m4_popdef([wspnum]) 880m4_popdef([wspid]) 881m4_popdef([genkw]) 882m4_popdef([wspgroupnum]) 883m4_popdef([wspgroupname]) 884m4_popdef([WSPGROUP]) 885