xref: /illumos-gate/usr/src/test/util-tests/tests/sed/bsd/multi_test.ksh (revision c94be9439c4f0773ef60e2cec21d548359cfea20)
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
48typeset -i err=0
49typeset -i pass=0
50typeset -i fail=0
51
52fatal() {
53	echo "[FATAL] $*" > /dev/stderr
54	exit 1
55}
56
57main()
58{
59	REGRESS=${SRCDIR}/regress.multitest.out
60	[[ -d $REGRESS ]] || fatal "Could not locate regress directory"
61
62	DICT=/usr/share/lib/dict/words
63	[[ -r $DICT ]] || fatal "Coult not read dictionary $DICT"
64
65	OPDIR=$(mktemp -d)
66	[[ -n "$OPDIR" && -d "$OPDIR" ]] || \
67	    fatal "Could not create output directory"
68
69	awk 'END { for (i = 1; i < 15; i++) print "l1_" i}' \
70	    </dev/null >$OPDIR/lines1
71	awk 'END { for (i = 1; i < 10; i++) print "l2_" i}' \
72	    </dev/null >$OPDIR/lines2
73	[[ -s $OPDIR/lines1 && -s $OPDIR/lines2 ]] || \
74	    fatal "Could not seed lines files"
75
76	lines1=$OPDIR/lines1
77	lines2=$OPDIR/lines2
78	lines3=$OPDIR/lines3
79	lines4=$OPDIR/lines4
80	script1=$OPDIR/script1
81	script2=$OPDIR/script2
82
83	exec 4>&1 5>&2
84	tests
85	exec 1>&4 2>&5
86
87	# Remove temporary files
88	rm -rf $OPDIR/
89}
90
91tests()
92{
93	MARK=0
94
95	test_args
96	test_addr
97	test_group
98	test_acid
99	test_branch
100	test_pattern
101	test_print
102	test_subst
103	test_error
104	# Handle the result of the last test
105	result
106}
107
108# Display a test's result
109result()
110{
111	if [ "$TODO" = '1' ] ; then
112		TODO='TODO '
113	else
114		TODO=''
115	fi
116	if ! [ -r $REGRESS/${TESTNAME} ] ; then
117		echo "Seeding $REGRESS/${TESTNAME} with current result" 1>&2
118		cp $OPDIR/current.out $REGRESS/${TESTNAME}
119	fi
120	if cmp -s $REGRESS/${TESTNAME} $OPDIR/current.out ; then
121		echo "[PASS] $MARK $TESTNAME # $TODO$OCOMMENT"
122		((pass++))
123	else
124		echo "[FAIL] $MARK $TESTNAME # $TODO$OCOMMENT"
125		if [[ -z "$TODO" ]]; then
126			diff -u $REGRESS/${TESTNAME} $OPDIR/current.out
127			((fail++))
128			err=1
129		fi
130	fi 1>&4 2>&5
131}
132
133# Mark the beginning of each test
134mark()
135{
136	[ $MARK -gt 0 ] && result
137	OCOMMENT=$COMMENT
138	MARK=`expr $MARK + 1`
139	TESTNAME=$1
140	exec 1>&4 2>&5
141	exec >"$OPDIR/current.out"
142}
143
144test_args()
145{
146	COMMENT='Argument parsing - first type'
147	mark '1.1'
148	$SED 's/^/e1_/p' $lines1
149	mark '1.2' ; $SED -n 's/^/e1_/p' $lines1
150	mark '1.3'
151	$SED 's/^/e1_/p' <$lines1
152	mark '1.4' ; $SED -n 's/^/e1_/p' <$lines1
153	COMMENT='Argument parsing - second type'
154	mark '1.4.1'
155	$SED -e '' <$lines1
156	echo 's/^/s1_/p' >$script1
157	echo 's/^/s2_/p' >$script2
158	mark '1.5'
159	$SED -f $script1 $lines1
160	mark '1.6'
161	$SED -f $script1 <$lines1
162	mark '1.7'
163	$SED -e 's/^/e1_/p' $lines1
164	mark '1.8'
165	$SED -e 's/^/e1_/p' <$lines1
166	mark '1.9' ; $SED -n -f $script1 $lines1
167	mark '1.10' ; $SED -n -f $script1 <$lines1
168	mark '1.11' ; $SED -n -e 's/^/e1_/p' $lines1
169	mark '1.12'
170	$SED -n -e 's/^/e1_/p' <$lines1
171	mark '1.13'
172	$SED -e 's/^/e1_/p' -e 's/^/e2_/p' $lines1
173	mark '1.14'
174	$SED -f $script1 -f $script2 $lines1
175	mark '1.15'
176	$SED -e 's/^/e1_/p' -f $script1 $lines1
177	mark '1.16'
178	$SED -e 's/^/e1_/p' $lines1 $lines1
179	# POSIX D11.2:11251
180	mark '1.17' ; $SED p <$lines1 $lines1
181cat >$script1 <<EOF
182#n
183# A comment
184
185p
186EOF
187	mark '1.18' ; $SED -f $script1 <$lines1 $lines1
188}
189
190test_addr()
191{
192	COMMENT='Address ranges'
193	mark '2.1' ; $SED -n -e '4p' $lines1
194	mark '2.2' ; $SED -n -e '20p' $lines1 $lines2
195	mark '2.3' ; $SED -n -e '$p' $lines1
196	mark '2.4' ; $SED -n -e '$p' $lines1 $lines2
197	mark '2.5' ; $SED -n -e '$a\
198hello' /dev/null
199	mark '2.6' ; $SED -n -e '$p' $lines1 /dev/null $lines2
200	# Should not print anything
201	mark '2.7' ; $SED -n -e '20p' $lines1
202	mark '2.8' ; $SED -n -e '/NOTFOUND/p' $lines1
203	mark '2.9' ; $SED -n '/l1_7/p' $lines1
204	mark '2.10' ; $SED -n ' /l1_7/ p' $lines1
205	mark '2.11' ; $SED -n '\_l1\_7_p' $lines1
206	mark '2.12' ; $SED -n '1,4p' $lines1
207	mark '2.13' ; $SED -n '1,$p' $lines1 $lines2
208	mark '2.14' ; $SED -n '1,/l2_9/p' $lines1 $lines2
209	mark '2.15' ; $SED -n '/4/,$p' $lines1 $lines2
210	mark '2.16' ; $SED -n '/4/,20p' $lines1 $lines2
211	mark '2.17' ; $SED -n '/4/,/10/p' $lines1 $lines2
212	mark '2.18' ; $SED -n '/l2_3/,/l1_8/p' $lines1 $lines2
213	mark '2.19' ; $SED -n '12,3p' $lines1 $lines2
214	mark '2.20' ; $SED -n '/l1_7/,3p' $lines1 $lines2
215	mark '2.21' ; $SED -n '13,+4p' $lines1 $lines2
216	mark '2.22' ; $SED -n '/l1_6/,+2p' $lines1 $lines2
217	# For PR bin/192108
218	mark '2.23'; $SED -n '12,+1p' $lines1
219}
220
221test_group()
222{
223	COMMENT='Brace and other grouping'
224	mark '3.1' ; $SED -e '
2254,12 {
226	s/^/^/
227	s/$/$/
228	s/_/T/
229}' $lines1
230	mark '3.2' ; $SED -e '
2314,12 {
232	s/^/^/
233	/6/,/10/ {
234		s/$/$/
235		/8/ s/_/T/
236	}
237}' $lines1
238	mark '3.3' ; $SED -e '
2394,12 !{
240	s/^/^/
241	/6/,/10/ !{
242		s/$/$/
243		/8/ !s/_/T/
244	}
245}' $lines1
246	mark '3.4' ; $SED -e '4,12!s/^/^/' $lines1
247}
248
249test_acid()
250{
251	COMMENT='Commands a c d and i'
252	mark '4.1' ; $SED -n -e '
253s/^/before_i/p
25420i\
255inserted
256s/^/after_i/p
257' $lines1 $lines2
258	mark '4.2' ; $SED -n -e '
2595,12s/^/5-12/
260s/^/before_a/p
261/5-12/a\
262appended
263s/^/after_a/p
264' $lines1 $lines2
265	mark '4.3'
266	$SED -n -e '
267s/^/^/p
268/l1_/a\
269appended
2708,10N
271s/$/$/p
272' $lines1 $lines2
273	mark '4.4' ; $SED -n -e '
274c\
275hello
276' $lines1
277	mark '4.5' ; $SED -n -e '
2788c\
279hello
280' $lines1
281	mark '4.6' ; $SED -n -e '
2823,14c\
283hello
284' $lines1
285# SunOS and GNU sed behave differently.   We follow POSIX
286	mark '4.7' ; $SED -n -e '
2878,3c\
288hello
289' $lines1
290	mark '4.8' ; $SED d <$lines1
291}
292
293test_branch()
294{
295	COMMENT='Labels and branching'
296	mark '5.1' ; $SED -n -e '
297b label4
298:label3
299s/^/label3_/p
300b end
301:label4
3022,12b label1
303b label2
304:label1
305s/^/label1_/p
306b
307:label2
308s/^/label2_/p
309b label3
310:end
311' $lines1
312	mark '5.2'
313	$SED -n -e '
314s/l1_/l2_/
315t ok
316b
317:ok
318s/^/tested /p
319' $lines1 $lines2
320# SunOS and GNU sed behave as follows: lines 9-$ aren't printed at all
321	mark '5.3' ; $SED -n -e '
3225,8b inside
3231,5 {
324	s/^/^/p
325	:inside
326	s/$/$/p
327}
328' $lines1
329# Check that t clears the substitution done flag
330	mark '5.4' ; $SED -n -e '
3311,8s/^/^/
332t l1
333:l1
334t l2
335s/$/$/p
336b
337:l2
338s/^/ERROR/
339' $lines1
340# Check that reading a line clears the substitution done flag
341	mark '5.5'
342	$SED -n -e '
343t l2
3441,8s/^/^/p
3452,7N
346b
347:l2
348s/^/ERROR/p
349' $lines1
350	mark '5.6' ; $SED 5q $lines1
351	mark '5.7' ; $SED -e '
3525i\
353hello
3545q' $lines1
355# Branch across block boundary
356	mark '5.8' ; $SED -e '
357{
358:b
359}
360s/l/m/
361tb' $lines1
362}
363
364test_pattern()
365{
366COMMENT='Pattern space commands'
367# Check that the pattern space is deleted
368	mark '6.1' ; $SED -n -e '
369c\
370changed
371p
372' $lines1
373	mark '6.2' ; $SED -n -e '
3744d
375p
376' $lines1
377	mark '6.3'
378	$SED -e 'N;N;N;D' $lines1
379	mark '6.4' ; $SED -e '
3802h
3813H
3824g
3835G
3846x
3856p
3866x
3876p
388' $lines1
389	mark '6.5' ; $SED -e '4n' $lines1
390	mark '6.6' ; $SED -n -e '4n' $lines1
391}
392
393test_print()
394{
395	COMMENT='Print and file routines'
396	awk 'END {for (i = 1; i < 256; i++) printf("%c", i);print "\n"}' \
397		</dev/null >$lines3
398	# GNU and SunOS sed behave differently here
399	mark '7.1'
400	$SED -n l $lines3
401	mark '7.2' ; $SED -e '/l2_/=' $lines1 $lines2
402	rm -f $lines4
403	mark '7.3' ; $SED -e "3,12w $lines4" $lines1
404	COMMENT='w results'
405	cat $lines4
406	mark '7.4' ; $SED -e "4r $lines2" $lines1
407	mark '7.5' ; $SED -e '5r /dev/dds' $lines1
408	mark '7.6' ; $SED -e '6r /dev/null' $lines1
409	mark '7.7'
410	$SED '200q' $DICT | $SED 's$.*$s/^/&/w tmpdir/&$' >$script1
411	rm -rf tmpdir
412	mkdir tmpdir
413	$SED -f $script1 $lines1
414	cat tmpdir/*
415	rm -rf tmpdir
416	mark '7.8'
417	echo line1 > $lines3
418	echo "" >> $lines3
419	$SED -n -e '$p' $lines3 /dev/null
420
421}
422
423test_subst()
424{
425	COMMENT='Substitution commands'
426	mark '8.1' ; $SED -e 's/./X/g' $lines1
427	mark '8.2' ; $SED -e 's,.,X,g' $lines1
428# SunOS sed thinks we are escaping . as wildcard, not as separator
429	mark '8.3'
430	$SED -e 's.\..X.g' $lines1
431	mark '8.4' ; $SED -e 's/[\/]/Q/' $lines1
432	mark '8.5' ; $SED -e 's_\__X_' $lines1
433	mark '8.6' ; $SED -e 's/./(&)/g' $lines1
434	mark '8.7' ; $SED -e 's/./(\&)/g' $lines1
435	mark '8.8' ; $SED -e 's/\(.\)\(.\)\(.\)/x\3x\2x\1/g' $lines1
436	mark '8.9' ; $SED -e 's/_/u0\
437u1\
438u2/g' $lines1
439	mark '8.10'
440	$SED -e 's/./X/4' $lines1
441	rm -f $lines4
442	mark '8.11' ; $SED -e "s/1/X/w $lines4" $lines1
443	COMMENT='s wfile results'
444	cat $lines4
445	mark '8.12' ; $SED -e 's/[123]/X/g' $lines1
446	mark '8.13' ; $SED -e 'y/0123456789/9876543210/' $lines1
447	mark '8.14' ;
448	$SED -e 'y10\123456789198765432\101' $lines1
449	mark '8.15' ; $SED -e '1N;2y/\n/X/' $lines1
450	mark '8.16'
451	echo 'eeefff' | $SED -e '
452		p
453		s/e/X/p
454		:x
455		s//Y/p
456		# Establish limit counter in the hold space
457		# GNU sed version 3.02 enters into an infinite loop here
458		x
459		/.\{10\}/ {
460			s/.*/ERROR/
461			b
462		}
463		s/.*/&./
464		x
465		/f/bx
466	'
467	# POSIX does not say that this should work,
468	# but it does for GNU, BSD, and SunOS
469	mark '8.17' ; $SED -e 's/[/]/Q/' $lines1
470
471	COMMENT='[ as an s delimiter and its escapes'
472	mark '8.18' ; $SED -e 's[_[X[' $lines1
473	# This is a matter of interpretation
474	# POSIX 1003.1, 2004 says "Within the BRE and the replacement,
475	# the BRE delimiter itself can be used as a *literal* character
476	# if it is preceded by a backslash"
477	# SunOS 5.1 /usr/bin/sed and Mac OS X follow the literal POSIX
478	# interpretation.
479	# GNU sed version 4.1.5 treats \[ as the beginning of a character
480	# set specification (both with --posix and without).
481	mark '8.19' ; $SED 's/l/[/' $lines1 | $SED -e 's[\[.[X['
482	mark '8.20' ; $SED 's/l/[/' $lines1 | $SED -e 's[\[.[X\[['
483	COMMENT='\\ in y command'
484	mark '8.21'
485	echo 'a\\b(c' | \
486	$SED 'y%ABCDEFGHIJKLMNOPQRSTUVWXYZ, /\\()"%abcdefghijklmnopqrstuvwxyz,------%'
487	COMMENT='\\n in a character class'
488	mark '8.22' ; (echo 1; echo 2) | $SED -n '1{;N;s/[\n]/X/;p;}'
489	COMMENT='\\n in a BRE'
490	mark '8.23' ; (echo 1; echo 2) | $SED -n '1{;N;s/\n/X/;p;}'
491}
492
493test_error()
494{
495	COMMENT='Error cases'
496	mark '9.1' ; $SED -x 2>/dev/null ; echo $?
497	mark '9.2' ; $SED -f 2>/dev/null ; echo $?
498	mark '9.3' ; $SED -e 2>/dev/null ; echo $?
499	mark '9.4' ; $SED -f /dev/xyzzyxyzy 2>/dev/null ; echo $?
500	mark '9.5' ; $SED p /dev/xyzzyxyzy 2>/dev/null ; echo $?
501	mark '9.6' ; $SED -f /bin/sh 2>/dev/null ; echo $?
502	mark '9.7' ; $SED '{' 2>/dev/null ; echo $?
503	mark '9.8' ; $SED '{' 2>/dev/null ; echo $?
504	mark '9.9' ; $SED '/hello/' 2>/dev/null ; echo $?
505	mark '9.10' ; $SED '1,/hello/' 2>/dev/null ; echo $?
506	mark '9.11' ; $SED -e '-5p' 2>/dev/null ; echo $?
507	mark '9.12' ; $SED '/jj' 2>/dev/null ; echo $?
508	mark '9.13' ; $SED 'a hello' 2>/dev/null ; echo $?
509	mark '9.14' ; $SED 'a \ hello' 2>/dev/null ; echo $?
510	mark '9.15' ; $SED 'b foo' 2>/dev/null ; echo $?
511	mark '9.16' ; $SED 'd hello' 2>/dev/null ; echo $?
512	mark '9.17' ; $SED 's/aa' 2>/dev/null ; echo $?
513	mark '9.18' ; $SED 's/aa/' 2>/dev/null ; echo $?
514	mark '9.19' ; $SED 's/a/b' 2>/dev/null ; echo $?
515	mark '9.20' ; $SED 's/a/b/c/d' 2>/dev/null ; echo $?
516	mark '9.21' ; $SED 's/a/b/ 1 2' 2>/dev/null ; echo $?
517	mark '9.22' ; $SED 's/a/b/ 1 g' 2>/dev/null ; echo $?
518	mark '9.23' ; $SED 's/a/b/w' 2>/dev/null ; echo $?
519	mark '9.24' ; $SED 'y/aa' 2>/dev/null ; echo $?
520	mark '9.25' ; $SED 'y/aa/b/' 2>/dev/null ; echo $?
521	mark '9.26' ; $SED 'y/aa/' 2>/dev/null ; echo $?
522	mark '9.27' ; $SED 'y/a/b' 2>/dev/null ; echo $?
523	mark '9.28' ; $SED 'y/a/b/c/d' 2>/dev/null ; echo $?
524	mark '9.29' ; $SED '!' 2>/dev/null ; echo $?
525	mark '9.30' ; $SED supercalifrangolisticexprialidociussupercalifrangolisticexcius 2>/dev/null ; echo $?
526	mark '9.31' ; $SED '' /dev/null 2>/dev/null ; echo $?
527}
528
529main
530echo "Pass/fail - $pass/$fail"
531exit $err
532