xref: /illumos-gate/usr/src/test/util-tests/tests/sed/bsd/multi_test.ksh (revision dd72704bd9e794056c558153663c739e2012d721)
1#!/bin/ksh -p
2#
3# Copyright (c) 1992 Diomidis Spinellis.
4# Copyright (c) 1992, 1993
5#	The Regents of the University of California.  All rights reserved.
6#
7# Redistribution and use in source and binary forms, with or without
8# modification, are permitted provided that the following conditions
9# are met:
10# 1. Redistributions of source code must retain the above copyright
11#    notice, this list of conditions and the following disclaimer.
12# 2. Redistributions in binary form must reproduce the above copyright
13#    notice, this list of conditions and the following disclaimer in the
14#    documentation and/or other materials provided with the distribution.
15# 3. Neither the name of the University nor the names of its contributors
16#    may be used to endorse or promote products derived from this software
17#    without specific prior written permission.
18#
19# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22# ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29# SUCH DAMAGE.
30#
31#	@(#)sed.test	8.1 (Berkeley) 6/6/93
32#
33#	$FreeBSD$
34#
35
36# sed Regression Tests
37#
38# The directory regress.test.out contains the expected test results
39#
40# These are the regression tests mostly created during the development
41# of the BSD sed.  Each test should have a unique mark name, which is
42# used for naming the corresponding file in regress.multitest.out.
43
44SRCDIR=$(dirname $0)
45
46SED=${SED:=/usr/bin/sed}
47
48#
49# Sanitize the environment so we're able to operate with known good
50# defaults. Note, tests such as 7.1 require that we're in the C locale.
51#
52unalias -a
53export LANG=C
54
55typeset -i err=0
56typeset -i pass=0
57typeset -i fail=0
58
59fatal() {
60	echo "[FATAL] $*" > /dev/stderr
61	exit 1
62}
63
64main()
65{
66	REGRESS=${SRCDIR}/regress.multitest.out
67	[[ -d $REGRESS ]] || fatal "Could not locate regress directory"
68
69	DICT=/usr/share/lib/dict/words
70	[[ -r $DICT ]] || fatal "Coult not read dictionary $DICT"
71
72	OPDIR=$(mktemp -d)
73	[[ -n "$OPDIR" && -d "$OPDIR" ]] || \
74	    fatal "Could not create output directory"
75
76	awk 'END { for (i = 1; i < 15; i++) print "l1_" i}' \
77	    </dev/null >$OPDIR/lines1
78	awk 'END { for (i = 1; i < 10; i++) print "l2_" i}' \
79	    </dev/null >$OPDIR/lines2
80	[[ -s $OPDIR/lines1 && -s $OPDIR/lines2 ]] || \
81	    fatal "Could not seed lines files"
82
83	lines1=$OPDIR/lines1
84	lines2=$OPDIR/lines2
85	lines3=$OPDIR/lines3
86	lines4=$OPDIR/lines4
87	script1=$OPDIR/script1
88	script2=$OPDIR/script2
89
90	exec 4>&1 5>&2
91	tests
92	exec 1>&4 2>&5
93
94	# Remove temporary files
95	rm -rf $OPDIR/
96}
97
98tests()
99{
100	MARK=0
101
102	test_args
103	test_addr
104	test_group
105	test_acid
106	test_branch
107	test_pattern
108	test_print
109	test_subst
110	test_error
111	# Handle the result of the last test
112	result
113}
114
115# Display a test's result
116result()
117{
118	if [ "$TODO" = '1' ] ; then
119		TODO='TODO '
120	else
121		TODO=''
122	fi
123	if ! [ -r $REGRESS/${TESTNAME} ] ; then
124		echo "Seeding $REGRESS/${TESTNAME} with current result" 1>&2
125		cp $OPDIR/current.out $REGRESS/${TESTNAME}
126	fi
127	if cmp -s $REGRESS/${TESTNAME} $OPDIR/current.out ; then
128		echo "[PASS] $MARK $TESTNAME # $TODO$OCOMMENT"
129		((pass++))
130	else
131		echo "[FAIL] $MARK $TESTNAME # $TODO$OCOMMENT"
132		if [[ -z "$TODO" ]]; then
133			diff -u $REGRESS/${TESTNAME} $OPDIR/current.out
134			((fail++))
135			err=1
136		fi
137	fi 1>&4 2>&5
138}
139
140# Mark the beginning of each test
141mark()
142{
143	[ $MARK -gt 0 ] && result
144	OCOMMENT=$COMMENT
145	MARK=`expr $MARK + 1`
146	TESTNAME=$1
147	exec 1>&4 2>&5
148	exec >"$OPDIR/current.out"
149}
150
151test_args()
152{
153	COMMENT='Argument parsing - first type'
154	mark '1.1'
155	$SED 's/^/e1_/p' $lines1
156	mark '1.2' ; $SED -n 's/^/e1_/p' $lines1
157	mark '1.3'
158	$SED 's/^/e1_/p' <$lines1
159	mark '1.4' ; $SED -n 's/^/e1_/p' <$lines1
160	COMMENT='Argument parsing - second type'
161	mark '1.4.1'
162	$SED -e '' <$lines1
163	echo 's/^/s1_/p' >$script1
164	echo 's/^/s2_/p' >$script2
165	mark '1.5'
166	$SED -f $script1 $lines1
167	mark '1.6'
168	$SED -f $script1 <$lines1
169	mark '1.7'
170	$SED -e 's/^/e1_/p' $lines1
171	mark '1.8'
172	$SED -e 's/^/e1_/p' <$lines1
173	mark '1.9' ; $SED -n -f $script1 $lines1
174	mark '1.10' ; $SED -n -f $script1 <$lines1
175	mark '1.11' ; $SED -n -e 's/^/e1_/p' $lines1
176	mark '1.12'
177	$SED -n -e 's/^/e1_/p' <$lines1
178	mark '1.13'
179	$SED -e 's/^/e1_/p' -e 's/^/e2_/p' $lines1
180	mark '1.14'
181	$SED -f $script1 -f $script2 $lines1
182	mark '1.15'
183	$SED -e 's/^/e1_/p' -f $script1 $lines1
184	mark '1.16'
185	$SED -e 's/^/e1_/p' $lines1 $lines1
186	# POSIX D11.2:11251
187	mark '1.17' ; $SED p <$lines1 $lines1
188cat >$script1 <<EOF
189#n
190# A comment
191
192p
193EOF
194	mark '1.18' ; $SED -f $script1 <$lines1 $lines1
195}
196
197test_addr()
198{
199	COMMENT='Address ranges'
200	mark '2.1' ; $SED -n -e '4p' $lines1
201	mark '2.2' ; $SED -n -e '20p' $lines1 $lines2
202	mark '2.3' ; $SED -n -e '$p' $lines1
203	mark '2.4' ; $SED -n -e '$p' $lines1 $lines2
204	mark '2.5' ; $SED -n -e '$a\
205hello' /dev/null
206	mark '2.6' ; $SED -n -e '$p' $lines1 /dev/null $lines2
207	# Should not print anything
208	mark '2.7' ; $SED -n -e '20p' $lines1
209	mark '2.8' ; $SED -n -e '/NOTFOUND/p' $lines1
210	mark '2.9' ; $SED -n '/l1_7/p' $lines1
211	mark '2.10' ; $SED -n ' /l1_7/ p' $lines1
212	mark '2.11' ; $SED -n '\_l1\_7_p' $lines1
213	mark '2.12' ; $SED -n '1,4p' $lines1
214	mark '2.13' ; $SED -n '1,$p' $lines1 $lines2
215	mark '2.14' ; $SED -n '1,/l2_9/p' $lines1 $lines2
216	mark '2.15' ; $SED -n '/4/,$p' $lines1 $lines2
217	mark '2.16' ; $SED -n '/4/,20p' $lines1 $lines2
218	mark '2.17' ; $SED -n '/4/,/10/p' $lines1 $lines2
219	mark '2.18' ; $SED -n '/l2_3/,/l1_8/p' $lines1 $lines2
220	mark '2.19' ; $SED -n '12,3p' $lines1 $lines2
221	mark '2.20' ; $SED -n '/l1_7/,3p' $lines1 $lines2
222	mark '2.21' ; $SED -n '13,+4p' $lines1 $lines2
223	mark '2.22' ; $SED -n '/l1_6/,+2p' $lines1 $lines2
224	# For PR bin/192108
225	mark '2.23'; $SED -n '12,+1p' $lines1
226}
227
228test_group()
229{
230	COMMENT='Brace and other grouping'
231	mark '3.1' ; $SED -e '
2324,12 {
233	s/^/^/
234	s/$/$/
235	s/_/T/
236}' $lines1
237	mark '3.2' ; $SED -e '
2384,12 {
239	s/^/^/
240	/6/,/10/ {
241		s/$/$/
242		/8/ s/_/T/
243	}
244}' $lines1
245	mark '3.3' ; $SED -e '
2464,12 !{
247	s/^/^/
248	/6/,/10/ !{
249		s/$/$/
250		/8/ !s/_/T/
251	}
252}' $lines1
253	mark '3.4' ; $SED -e '4,12!s/^/^/' $lines1
254}
255
256test_acid()
257{
258	COMMENT='Commands a c d and i'
259	mark '4.1' ; $SED -n -e '
260s/^/before_i/p
26120i\
262inserted
263s/^/after_i/p
264' $lines1 $lines2
265	mark '4.2' ; $SED -n -e '
2665,12s/^/5-12/
267s/^/before_a/p
268/5-12/a\
269appended
270s/^/after_a/p
271' $lines1 $lines2
272	mark '4.3'
273	$SED -n -e '
274s/^/^/p
275/l1_/a\
276appended
2778,10N
278s/$/$/p
279' $lines1 $lines2
280	mark '4.4' ; $SED -n -e '
281c\
282hello
283' $lines1
284	mark '4.5' ; $SED -n -e '
2858c\
286hello
287' $lines1
288	mark '4.6' ; $SED -n -e '
2893,14c\
290hello
291' $lines1
292# SunOS and GNU sed behave differently.   We follow POSIX
293	mark '4.7' ; $SED -n -e '
2948,3c\
295hello
296' $lines1
297	mark '4.8' ; $SED d <$lines1
298}
299
300test_branch()
301{
302	COMMENT='Labels and branching'
303	mark '5.1' ; $SED -n -e '
304b label4
305:label3
306s/^/label3_/p
307b end
308:label4
3092,12b label1
310b label2
311:label1
312s/^/label1_/p
313b
314:label2
315s/^/label2_/p
316b label3
317:end
318' $lines1
319	mark '5.2'
320	$SED -n -e '
321s/l1_/l2_/
322t ok
323b
324:ok
325s/^/tested /p
326' $lines1 $lines2
327# SunOS and GNU sed behave as follows: lines 9-$ aren't printed at all
328	mark '5.3' ; $SED -n -e '
3295,8b inside
3301,5 {
331	s/^/^/p
332	:inside
333	s/$/$/p
334}
335' $lines1
336# Check that t clears the substitution done flag
337	mark '5.4' ; $SED -n -e '
3381,8s/^/^/
339t l1
340:l1
341t l2
342s/$/$/p
343b
344:l2
345s/^/ERROR/
346' $lines1
347# Check that reading a line clears the substitution done flag
348	mark '5.5'
349	$SED -n -e '
350t l2
3511,8s/^/^/p
3522,7N
353b
354:l2
355s/^/ERROR/p
356' $lines1
357	mark '5.6' ; $SED 5q $lines1
358	mark '5.7' ; $SED -e '
3595i\
360hello
3615q' $lines1
362# Branch across block boundary
363	mark '5.8' ; $SED -e '
364{
365:b
366}
367s/l/m/
368tb' $lines1
369}
370
371test_pattern()
372{
373COMMENT='Pattern space commands'
374# Check that the pattern space is deleted
375	mark '6.1' ; $SED -n -e '
376c\
377changed
378p
379' $lines1
380	mark '6.2' ; $SED -n -e '
3814d
382p
383' $lines1
384	mark '6.3'
385	$SED -e 'N;N;N;D' $lines1
386	mark '6.4' ; $SED -e '
3872h
3883H
3894g
3905G
3916x
3926p
3936x
3946p
395' $lines1
396	mark '6.5' ; $SED -e '4n' $lines1
397	mark '6.6' ; $SED -n -e '4n' $lines1
398}
399
400test_print()
401{
402	COMMENT='Print and file routines'
403	awk 'END {for (i = 1; i < 256; i++) printf("%c", i);print "\n"}' \
404		</dev/null >$lines3
405	# GNU and SunOS sed behave differently here
406	mark '7.1'
407	$SED -n l $lines3
408	mark '7.2' ; $SED -e '/l2_/=' $lines1 $lines2
409	rm -f $lines4
410	mark '7.3' ; $SED -e "3,12w $lines4" $lines1
411	COMMENT='w results'
412	cat $lines4
413	mark '7.4' ; $SED -e "4r $lines2" $lines1
414	mark '7.5' ; $SED -e '5r /dev/dds' $lines1
415	mark '7.6' ; $SED -e '6r /dev/null' $lines1
416	mark '7.7'
417	$SED '200q' $DICT | $SED 's$.*$s/^/&/w tmpdir/&$' >$script1
418	rm -rf tmpdir
419	mkdir tmpdir
420	$SED -f $script1 $lines1
421	cat tmpdir/*
422	rm -rf tmpdir
423	mark '7.8'
424	echo line1 > $lines3
425	echo "" >> $lines3
426	$SED -n -e '$p' $lines3 /dev/null
427
428}
429
430test_subst()
431{
432	COMMENT='Substitution commands'
433	mark '8.1' ; $SED -e 's/./X/g' $lines1
434	mark '8.2' ; $SED -e 's,.,X,g' $lines1
435# SunOS sed thinks we are escaping . as wildcard, not as separator
436	mark '8.3'
437	$SED -e 's.\..X.g' $lines1
438	mark '8.4' ; $SED -e 's/[\/]/Q/' $lines1
439	mark '8.5' ; $SED -e 's_\__X_' $lines1
440	mark '8.6' ; $SED -e 's/./(&)/g' $lines1
441	mark '8.7' ; $SED -e 's/./(\&)/g' $lines1
442	mark '8.8' ; $SED -e 's/\(.\)\(.\)\(.\)/x\3x\2x\1/g' $lines1
443	mark '8.9' ; $SED -e 's/_/u0\
444u1\
445u2/g' $lines1
446	mark '8.10'
447	$SED -e 's/./X/4' $lines1
448	rm -f $lines4
449	mark '8.11' ; $SED -e "s/1/X/w $lines4" $lines1
450	COMMENT='s wfile results'
451	cat $lines4
452	mark '8.12' ; $SED -e 's/[123]/X/g' $lines1
453	mark '8.13' ; $SED -e 'y/0123456789/9876543210/' $lines1
454	mark '8.14' ;
455	$SED -e 'y10\123456789198765432\101' $lines1
456	mark '8.15' ; $SED -e '1N;2y/\n/X/' $lines1
457	mark '8.16'
458	echo 'eeefff' | $SED -e '
459		p
460		s/e/X/p
461		:x
462		s//Y/p
463		# Establish limit counter in the hold space
464		# GNU sed version 3.02 enters into an infinite loop here
465		x
466		/.\{10\}/ {
467			s/.*/ERROR/
468			b
469		}
470		s/.*/&./
471		x
472		/f/bx
473	'
474	# POSIX does not say that this should work,
475	# but it does for GNU, BSD, and SunOS
476	mark '8.17' ; $SED -e 's/[/]/Q/' $lines1
477
478	COMMENT='[ as an s delimiter and its escapes'
479	mark '8.18' ; $SED -e 's[_[X[' $lines1
480	# This is a matter of interpretation
481	# POSIX 1003.1, 2004 says "Within the BRE and the replacement,
482	# the BRE delimiter itself can be used as a *literal* character
483	# if it is preceded by a backslash"
484	# SunOS 5.1 /usr/bin/sed and Mac OS X follow the literal POSIX
485	# interpretation.
486	# GNU sed version 4.1.5 treats \[ as the beginning of a character
487	# set specification (both with --posix and without).
488	mark '8.19' ; $SED 's/l/[/' $lines1 | $SED -e 's[\[.[X['
489	mark '8.20' ; $SED 's/l/[/' $lines1 | $SED -e 's[\[.[X\[['
490	COMMENT='\\ in y command'
491	mark '8.21'
492	echo 'a\\b(c' | \
493	$SED 'y%ABCDEFGHIJKLMNOPQRSTUVWXYZ, /\\()"%abcdefghijklmnopqrstuvwxyz,------%'
494	COMMENT='\\n in a character class'
495	mark '8.22' ; (echo 1; echo 2) | $SED -n '1{;N;s/[\n]/X/;p;}'
496	COMMENT='\\n in a BRE'
497	mark '8.23' ; (echo 1; echo 2) | $SED -n '1{;N;s/\n/X/;p;}'
498}
499
500test_error()
501{
502	COMMENT='Error cases'
503	mark '9.1' ; $SED -x 2>/dev/null ; echo $?
504	mark '9.2' ; $SED -f 2>/dev/null ; echo $?
505	mark '9.3' ; $SED -e 2>/dev/null ; echo $?
506	mark '9.4' ; $SED -f /dev/xyzzyxyzy 2>/dev/null ; echo $?
507	mark '9.5' ; $SED p /dev/xyzzyxyzy 2>/dev/null ; echo $?
508	mark '9.6' ; $SED -f /bin/sh 2>/dev/null ; echo $?
509	mark '9.7' ; $SED '{' 2>/dev/null ; echo $?
510	mark '9.8' ; $SED '{' 2>/dev/null ; echo $?
511	mark '9.9' ; $SED '/hello/' 2>/dev/null ; echo $?
512	mark '9.10' ; $SED '1,/hello/' 2>/dev/null ; echo $?
513	mark '9.11' ; $SED -e '-5p' 2>/dev/null ; echo $?
514	mark '9.12' ; $SED '/jj' 2>/dev/null ; echo $?
515	mark '9.13' ; $SED 'a hello' 2>/dev/null ; echo $?
516	mark '9.14' ; $SED 'a \ hello' 2>/dev/null ; echo $?
517	mark '9.15' ; $SED 'b foo' 2>/dev/null ; echo $?
518	mark '9.16' ; $SED 'd hello' 2>/dev/null ; echo $?
519	mark '9.17' ; $SED 's/aa' 2>/dev/null ; echo $?
520	mark '9.18' ; $SED 's/aa/' 2>/dev/null ; echo $?
521	mark '9.19' ; $SED 's/a/b' 2>/dev/null ; echo $?
522	mark '9.20' ; $SED 's/a/b/c/d' 2>/dev/null ; echo $?
523	mark '9.21' ; $SED 's/a/b/ 1 2' 2>/dev/null ; echo $?
524	mark '9.22' ; $SED 's/a/b/ 1 g' 2>/dev/null ; echo $?
525	mark '9.23' ; $SED 's/a/b/w' 2>/dev/null ; echo $?
526	mark '9.24' ; $SED 'y/aa' 2>/dev/null ; echo $?
527	mark '9.25' ; $SED 'y/aa/b/' 2>/dev/null ; echo $?
528	mark '9.26' ; $SED 'y/aa/' 2>/dev/null ; echo $?
529	mark '9.27' ; $SED 'y/a/b' 2>/dev/null ; echo $?
530	mark '9.28' ; $SED 'y/a/b/c/d' 2>/dev/null ; echo $?
531	mark '9.29' ; $SED '!' 2>/dev/null ; echo $?
532	mark '9.30' ; $SED supercalifrangolisticexprialidociussupercalifrangolisticexcius 2>/dev/null ; echo $?
533	mark '9.31' ; $SED '' /dev/null 2>/dev/null ; echo $?
534}
535
536main
537echo "Pass/fail - $pass/$fail"
538exit $err
539