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