1########################################################################
2#                                                                      #
3#               This software is part of the ast package               #
4#          Copyright (c) 1996-2011 AT&T Intellectual Property          #
5#                      and is licensed under the                       #
6#                 Eclipse Public License, Version 1.0                  #
7#                    by AT&T Intellectual Property                     #
8#                                                                      #
9#                A copy of the License is available at                 #
10#          http://www.eclipse.org/org/documents/epl-v10.html           #
11#         (with md5 checksum b35adb5213ca9657e911e9befb180842)         #
12#                                                                      #
13#              Information and Software Systems Research               #
14#                            AT&T Research                             #
15#                           Florham Park NJ                            #
16#                                                                      #
17#                 Glenn Fowler <gsf@research.att.com>                  #
18#                   Phong Vo <kpv@research.att.com>                    #
19#              Doug McIlroy <doug@research.bell-labs.com>              #
20#                                                                      #
21########################################################################
22: sorttest [ sort test-options ... ]
23# Tests for the Unix sort utility
24# Test Posix features except for locale.
25# Test some nonstandard features if present.
26
27AWK=awk
28CC=${CC:-${TESTCC:-cc}}
29LC_ALL=C
30NAWK=nawk
31SUM=sum
32SORT=sort
33TMP=sort.tmp
34
35export TEST AWK CC LC_ALL SUM SORT TMP
36
37case $# in
380)	set $SORT ;;
39esac
40
41# Some intermediate file tests require ~100 fds,
42# and some systems have low ~64 fds defaults.
43(ulimit -n 128) >/dev/null 2>&1 && ulimit -n 128
44
45# Other tests may be needed for files too big to fit in memory;
46# see TEST=15 below
47
48SORT=$1
49shift
50SORT_ARGS="$@"
51path=`pwd`:$PATH:/usr/5bin:/bin:/usr/bin
52ifs=${IFS-'
53	 '}
54IFS=":"
55set $path
56IFS=$ifs
57for dir
58do	case $dir in
59	"")	continue ;;
60	esac
61	case $NAWK in
62	*/*)	;;
63	*)	if	test -x $dir/$NAWK
64		then	NAWK=$dir/$NAWK
65		else	case $AWK in
66			*/*)	;;
67			*)	test -x $dir/$AWK && AWK=$dir/$AWK ;;
68			esac
69		fi
70		;;
71	esac
72	case $SORT in
73	*/*)	;;
74	*)	test -x $dir/$SORT && SORT=$dir/$SORT ;;
75	esac
76	case $SUM in
77	*/*)	;;
78	*)	if	test -x $dir/$SUM
79		then	AB='abc
80pdq
81xyz'
82			BA='xyz
83pdq
84abc'
85			ab=`echo "$AB" | $SUM 2>/dev/null`
86			ba=`echo "$BA" | $SUM 2>/dev/null`
87			case $ab in
88			$ba)	SUM=$dir/$SUM
89				;;
90			*)	for old in -o '-o 2' -s -xatt
91				do	ab=`echo "$AB" | $dir/$SUM $old 2>/dev/null`
92					case $ab in
93					?*)	ba=`echo "$BA" | $dir/$SUM $old 2>/dev/null`
94						case $ab in
95						$ba)	SUM="$dir/$SUM $old"
96							break
97							;;
98						esac
99						;;
100					esac
101				done
102				;;
103			esac
104		fi
105		;;
106	esac
107done
108case $NAWK in
109*/*)	AWK=$NAWK ;;
110esac
111echo pathname and options of item under test
112echo "	$SORT	$SORT_ARGS"
113echo
114SORT="$SORT $SORT_ARGS"
115
116# All work done in local temp dir.
117
118trap "cd ..; rm -rf $TMP; exit" 0 1 2 13 15
119rm -rf $TMP
120if	mkdir $TMP
121then	cd $TMP
122else	echo "mkdir $TMP FAILED"
123	exit 1
124fi
125
126# Initialize switches for nonstandard features.
127# Use parenthesized settings for supported features.
128
129o=:	# officially obsolescent features: +1 -2
130O=:	# really obsolescent features: displaced -o (o=)
131g=:	# -g numeric sort including e-format numbers (g=)
132k=:	# -Rr -k.p.l fixed records and fields
133M=:	# -M sort by month names (M=)
134s=:	# -s stable, do not compare raw bytes on equal keys (s=)
135S=:	# -S unstable, compare raw bytes on equal keys (S=)
136x=:	# -x method, alternate sort method (x=)
137X=:	# -Xtest, -Xread ensures read over memory map
138y=	# -y user-specified memory size (y=-y4096)
139
140# Detect what features are supported, assuming bad options cause
141# errors.  Set switches accordingly.
142
143echo obsolescent and nonstandard features recognized, if any
144if $SORT +0 </dev/null 2>/dev/null; then o=
145				echo '	+1 -2'; fi
146if $SORT /dev/null -o xx 2>/dev/null; then O=
147				echo '	displaced -o'; fi
148if $SORT -g </dev/null 2>/dev/null; then g=
149				echo '	-g g-format numbers'; fi
150if test Xcx.by.az = X`echo by.cx.az | $SORT -R3 -k.2.1 2>/dev/null`; then k=
151				echo '	-Rr -k.p:l fixed length records'; fi
152if $SORT -M </dev/null 2>/dev/null; then M=
153				echo '	-M months'; fi
154if $SORT -s </dev/null 2>/dev/null; then s=
155				echo '	-s stable'; fi
156if $SORT -S </dev/null 2>/dev/null; then S=
157				echo '	-S unstable'; fi
158if $SORT -x default </dev/null 2>/dev/null; then x=
159				echo '	-x method'; fi
160if test Xok = X`$SORT -Xtest 2>/dev/null`; then X=
161				echo '	-Xread ensures read instead of memory map'; fi
162if $SORT -y4096 </dev/null 2>/dev/null; then y=-y4096
163				echo '	-y space'; fi
164if $SORT -z10000 </dev/null 2>/dev/null; then
165				echo '	-z recsize (not exercised)'; fi
166if $SORT -T. </dev/null 2>/dev/null; then
167				echo '	-T tempdir (not exercised)'; fi
168
169# xsort testno options
170# Sort file "in" with specified options.
171# Compare with file "out" if that is supplied,
172# otherwise make plausibility checks on output
173
174cat >xsort <<!
175
176	case \$1 in
177	-)	F=-; shift ;;
178	*)	F=in ;;
179	esac
180	X=\$1; shift
181
182	if \$SORT "\$@" \$F >xx  &&  \$SORT -c "\$@" xx 2>/dev/null
183	then
184		if test -f out
185		then
186			cmp -s xx out >/dev/null && exit 0
187			echo \$TEST\$X comparison FAILED
188		else
189			test "\`$SUM <in\`" = "\`$SUM <xx\`" && exit 0
190			echo \$TEST\$X checksum FAILED
191		fi
192	else
193		echo \$TEST\$X FAILED
194	fi
195	exit 1
196!
197chmod +x xsort
198
199# ysort options
200# called to check diagnostics
201
202cat <<! >ysort
203error=0 warning=0 works=0
204$SORT "\$@" 2>out <in >in1 || error=1
205test -s out && warning=1
206test -s in1 && works=1
207case \$error\$warning\$works in
208000)	echo "	\$@" does not indicate trouble, but does not sort ;;
209001)	echo "	\$@" does not indicate trouble ;;
210010)	echo "	\$@" warns, does not sort, and yields exit status zero ;;
211011)	echo "	\$@" warns and continues ;;
212100)	echo "	\$@" yields nonzero exit status and does not sort ;;
213101)	echo "	\$@" yields nonzero exit status, but sorts ;;
214111)	echo "	\$@" warns and yields nonzero exit status, but sorts
215esac
216!
217chmod +x ysort
218
219# linecount testno file count
220# declares the given "testno" to be in error if number of
221# lines in "file" differs from "count"
222
223cat >linecount <<'!'
224$AWK 'END{ if(NR!='$3') print "'$TEST$1' FAILED" }' $2
225!
226chmod +x linecount
227
228# instability by default for the standard
229
230case $S in
231'')	SORT="$SORT -S" ;;
232esac
233
234# check behavior in questionable cases
235
236echo
237echo "behavior in questionable cases (other than message and exit)"
238echo hi >in
239
240rm -f nosuchfile
241./ysort nosuchfile
242
243if	test ! -f unwritablefile
244then	echo x >unwritablefile
245	chmod 0 unwritablefile
246fi
247./ysort -o unwritablefile </dev/null
248
249cat in | ./ysort - -
250
251./ysort -- in
252
253for i in -k -k0 -k-1 -k1, -kb -k1,2u -t -o
254do	./ysort $i
255done
256
257$g ./ysort -n -g
258$M ./ysort -n -M
259./ysort -d -i
260./ysort -n -i
261./ysort -c in in
262./ysort -t. -t:
263
264for i in -a -e -h -j -p -q -v -w -x -0 -1 -2
265do	./ysort $i
266done
267
268$g false && ./ysort -g
269$s false && ./ysort -s
270$z false && ./ysort -z
271
272case "$y" in
273"")	./ysort -y
274esac
275
276./ysort -k1,1 -f
277
278cat >in <<!
279A	b
280a	bc
281a	Bd
282B
283!
284cat >in1 <<!
285A	b
286B
287a	bc
288a	Bd
289!
290cat >in2 <<!
291A	b
292B
293a	Bd
294a	bc
295!
296
297if $SORT -k1,1 -f -k2,2 <in >out 2>/dev/null
298then
299	opt="-k1,1 -f -k2,2 :"
300	if cmp -s out in >/dev/null
301	then	echo "	$opt -f applies to fields 1 and 2"
302	elif cmp -s out in1 >/dev/null
303	then	echo "	$opt -f applies to field 2 only"
304	elif cmp -s out in1 >/dev/null
305	then	echo "	$opt -f ineffectual"
306	elif cmp -s out /dev/null >/dev/null
307	then	echo "	$opt exit status zero, but no output"
308	else	echo "	$opt inexplicable"
309	fi
310fi
311
312# generate large data here to smooth the test feedback
313
314echo
315echo "generating large data files for tests that follow (long)"
316$AWK 'BEGIN { for(i=0; i<100000; i++) print rand() }' </dev/null |
317	 grep -v e >14.in
318$AWK 'BEGIN {
319	x = "xxxxxxxxxx"
320	x = x x x x x x x x
321	for(i=0; i<8000; i++) print rand(), x }' >15.in </dev/null
322rm -f in out
323
324echo
325echo test numbers denote progress, not trouble
326
327# check for and loop on alternate methods
328
329case $x in
330'')	set `$SORT --list < /dev/null | sed 's/[ 	].*//'` ;;
331*)	set '' ;;
332esac
333
334COMMAND=$SORT
335while	:
336do	case $# in
337	0)		break ;;
338	esac
339	METHOD=$1
340	shift
341	case $METHOD in
342	check|copy|verify)
343			continue
344			;;
345	'')		echo
346			;;
347	*)		SORT="$COMMAND -x $METHOD"
348			echo
349			echo "testing the $METHOD method"
350			echo
351			;;
352	esac
353
354#---------------------------------------------------------------
355TEST=01; echo $TEST	"-c status, checksum"
356			# obsolescent features go together
357cat >in <<!
358b
359a
360!
361rm -f out -o
362
363$SORT -c in 2>/dev/null && echo ${TEST}A FAILED
364
365./xsort B || echo ${TEST}B $SUM is probably unsuitable - see comments
366
367$o $SORT -o in +0 in || echo ${TEST}C FAILED
368
369#---------------------------------------------------------------
370TEST=02; echo $TEST	"output from -c"
371cat >in <<!
372x
373y
374!
375
376$SORT -cr in >out 2>xx && echo ${TEST}A FAILED
377test -s out && echo ${TEST}B FAILED
378test -s xx || echo option -c is quiet "(legal, not classical)"
379
380$SORT -c /dev/null 2>xx || echo ${TEST}C FAILED
381test -s xx && echo ${TEST}D FAILED
382
383#---------------------------------------------------------------
384TEST=03; echo $TEST	"-n"
385cat >in <<!
386-99.0
387-99.1
388-.0002
389  -10
3902
3912.0x
3922.0.1
3930010.000000000000000000000000000000000001
39410
3953x
396x
397!
398cat >out <<!
399-99.1
400-99.0
401  -10
402-.0002
403x
4042
4052.0.1
4062.0x
4073x
40810
4090010.000000000000000000000000000000000001
410!
411
412./xsort "" -n
413
414#---------------------------------------------------------------
415TEST=04; echo $TEST	"-b without fields, piping, -c status return"
416cat >in <<!
417  b
418 a
419!
420cp in out
421
422./xsort A -b
423
424cat in | $SORT | cat >xx
425cmp -s xx out >/dev/null || echo ${TEST}B FAILED
426
427$SORT in | $SORT -cr 2>/dev/null && echo ${TEST}C FAILED
428
429#---------------------------------------------------------------
430TEST=05; echo $TEST	"fields, reverse fields, -c status return"
431cat >in <<!
432b b p
433a b q
434x a
435!
436cat >out <<!
437x a
438a b q
439b b p
440!
441
442$o ./xsort A +1 -2
443
444$o ./xsort B +1 -2 +2r
445
446./xsort C -k 2,2
447
448./xsort D -k 2,2 -k 3r
449
450./xsort E -k 2,2.0
451
452./xsort F -k 2,2 -k 1,1 -k 3
453
454$SORT -c -k 2 in 2>/dev/null && ${TEST}G FAILED
455
456#---------------------------------------------------------------
457TEST=06; echo $TEST	"-t"
458cat >in <<!
459a:
460a!
461!
462cp in out
463
464$o ./xsort A -t : -r +0
465
466$o ./xsort B -t : +0 -1
467
468./xsort C -t : -r -k 1
469
470./xsort D -t : -k 1,1
471
472#---------------------------------------------------------------
473TEST=07; echo $TEST	"-t, character positions in fields"
474	# -t: as 1 arg is not strictly conforming, but classical
475cat >in <<!
476: ab
477:bac
478!
479cat >out <<!
480:bac
481: ab
482!
483
484$o ./xsort A -b -t: +1.1
485
486$o ./xsort B -t: +1.1r
487
488./xsort C -b -t: -k 2.2
489
490./xsort D -t: -k 2.2r
491
492#---------------------------------------------------------------
493TEST=08; echo $TEST	"space and tab as -t characters"
494cat >in <<!
495 b c
496 b	c
497	b c
498!
499cp in out
500
501./xsort A -t ' ' -k2,2
502
503./xsort B -t ' ' -k2.1,2.0
504
505cat >out <<!
506 b c
507	b c
508 b	c
509!
510
511./xsort C -t '	' -k2,2
512
513./xsort D -t '	' -k2.1,2.0
514
515cat >out <<!
516 b	c
517	b c
518 b c
519!
520
521./xsort E -k2
522
523cat >out <<!
524	b c
525 b	c
526 b c
527!
528
529./xsort F -k2b
530
531#---------------------------------------------------------------
532TEST=09; echo $TEST	"alphabetic as -t character"
533cat >in <<!
534zXa
535yXa
536zXb
537!
538cp in out
539
540./xsort "" -tX -k2 -k1r,1
541
542#---------------------------------------------------------------
543TEST=10; echo $TEST	"-m"
544cat >in <<!
545a
546ab
547ab
548bc
549ca
550!
551cat >in1 <<!
552Z
553a
554aa
555ac
556c
557!
558cat >out <<!
559Z
560a
561a
562aa
563ab
564ab
565ac
566bc
567c
568ca
569!
570
571$SORT -m in in1 >xx
572cmp -s xx out >/dev/null || echo ${TEST}A FAILED
573
574#---------------------------------------------------------------
575TEST=11; echo $TEST	"multiple files, -o overwites input, -m, -mu"
576cat >in <<!
577a
578b
579c
580d
581!
582
583$SORT -o xx     in in in in in in in in in in in in in in in in in
584./linecount A xx 68
585$SORT -o in -mu in in in in in in in in in in in in in in in in in
586./linecount B in 4
587$SORT -o in -m  in in in in in in in in in in in in in in in in in
588
589cmp -s in xx >/dev/null || echo ${TEST}C FAILED
590
591#---------------------------------------------------------------
592TEST=12; echo $TEST	"does -mu pick the first among equals?"
593cat >in <<!
5943B
5953b
5963B2
597~3B2
5984.1
59941
6005
6015.
602!
603cat >out <<!
6043B
6053B2
6064.1
6075
608!
609
610./xsort A -mudf || echo "(other behavior is legal, not classical)"
611
612./xsort B -mudf -k1 || echo "(other behavior is legal, not classical)"
613
614#---------------------------------------------------------------
615TEST=13; echo $TEST	"long records (>8000 bytes, keys >16000), -r"
616$AWK '
617BEGIN {	x="x"
618	for(i=1; i<=12; i++) x = x x
619	for(i=15; i<=25; i++) print x i
620}' >in </dev/null
621$AWK '
622BEGIN {	x="x"
623	for(i=1; i<=12; i++) x = x x
624	for(i=25; i>=15; i--) print x i
625}' >out </dev/null
626
627./xsort A -r
628
629./xsort B -k 1,1r -k 1
630
631#---------------------------------------------------------------
632TEST=14; echo $TEST	"-n and -u"
633cp 14.in in
634rm -f out
635
636./xsort A
637
638./xsort B -n
639
640# next test is unclean: xx is a hidden side-effect of xsort
641
642$AWK '
643	$0 < x { print "test '${TEST}C' FAILED"; exit }
644	"X" $0 != "X" x { print >"out"; x = $0 }
645' xx
646
647./xsort C -n -u
648
649#---------------------------------------------------------------
650TEST=15; echo $TEST 	"force intermediate files if possible"
651#	option -y4096 ($y) should force a multi-stage internal merge
652#	option -Xread ($X) should force read over mmap
653case "$y" in
654"")	echo ${TEST} inadequate test of large files - revise parameters
655esac
656
657cp 15.in in
658rm -f out
659
660./xsort A -r $y
661cat in | ./xsort - B -r $y
662$X ./xsort C -r $y -Xread
663$X cat in | $X ./xsort - D -r $y -Xread
664
665rm -f in1
666$SORT -r -o in1 in
667$AWK '$0 "x" != x { print ; x = $0 "x" }' in1 >out
668
669./xsort E -u -r $y
670cat in | ./xsort - F -u -r $y
671$X ./xsort G -u -r $y -Xread
672$X cat in | $X ./xsort - H -u -r $y -Xread
673
674$SORT -r -u -m -o in1 in1
675cmp -s in1 out >/dev/null || echo ${TEST}I FAILED
676rm in in1 out
677
678#---------------------------------------------------------------
679TEST=16; echo $TEST	"-nr, -nm, file name -"
680$AWK 'BEGIN { for(i=-100; i<=100; i+=2) printf "%.10d\n", i }' >in </dev/null
681
682$AWK 'BEGIN { for(i=-99; i<=100; i+=2) print i }' </dev/null |
683	 $SORT -nr in - >xx
684$AWK '$0+0 != 101-NR { print "'${TEST}A' FAILED"; exit }' xx
685
686$AWK 'BEGIN { for(i=-99; i<=100; i+=2) print i }' </dev/null |
687	 $SORT -mn - in >xx
688$AWK '$0+0 != -101+NR { print "'${TEST}B' FAILED"; exit }' xx
689
690#---------------------------------------------------------------
691TEST=17; echo $TEST	"-d, fields without end, modifier override"
692cat >in <<!
693a-B
694a+b
695a b
696A+b
697a	b
698!
699cat >out <<!
700a	b
701a b
702A+b
703a-B
704a+b
705!
706
707$o ./xsort A -df +0 +0d
708
709./xsort B -df -k 1 -k 1d
710
711#---------------------------------------------------------------
712TEST=18; echo $TEST	"-u on key only"
713cat >in <<!
71412	y
71513	z
71612	x
717!
718cat >out <<!
71912	x
72012	y
72113	z
722!
723
724$o ./xsort A +0 -1
725
726./xsort B -k 1,1
727
728$SORT -u -k 1,1 in >xx
729./linecount C xx 2
730
731#---------------------------------------------------------------
732TEST=19; echo $TEST	"-i, -d, -f"
733cat >xx.c <<!
734#include <stdio.h>
735static void run(int i, int j){ for( ; i<=j; i++) printf("%.3o %c\n",i,i); }
736int main(){	run(0, 011);		/* 012=='\n' */
737	run(013, 0377);
738	return 0; }
739!
740$CC -o xx.exe xx.c
741./xx.exe >in
742cat >xx.c <<!
743#include <stdio.h>
744static void run(int i, int j){ for( ; i<=j; i++) printf("%.3o %c\n",i,i); }
745int main(){ run(0, 011);
746	run(013, ' '-1);
747	run(0177, 0377);
748	run(' ', 0176);
749	return 0; }
750!
751$CC -o xx.exe xx.c
752./xx.exe >out
753
754./xsort A -i -k 2
755
756cat >xx.c <<!
757#include <stdio.h>
758static void run(int i, int j){ for( ; i<=j; i++) printf("%.3o %c\n",i,i); }
759int main(){	run(0, 010);		/* 011=='\t', 012=='\n' */
760	run(013, ' '-1);
761	run(' '+1, '0'-1);
762	run('9'+1, 'A'-1);
763	run('Z'+1, 'a'-1);
764	run('z'+1, 0377);
765	run('\t', '\t');
766	run(' ', ' ');
767	run('0', '9');
768	run('A', 'Z');
769	run('a', 'z');
770	return 0; }
771!
772$CC -o xx.exe xx.c
773./xx.exe >out
774
775./xsort B -d -k 2
776
777cat >xx.c <<!
778#include <stdio.h>
779static void run(int i, int j){ for( ; i<=j; i++) printf("%.3o %c\n",i,i); }
780int main(){	int i;
781	run(0, 011);
782	run(013, 'A'-1);
783	for(i='A'; i<='Z'; i++)
784		printf("%.3o %c\n%.3o %c\n",i,i,i+040,i+040);
785	run('Z'+1, 'a'-1);
786	run('z'+1, 0377);
787	return 0; }
788!
789$CC -o xx.exe xx.c
790./xx.exe >out
791rm -f xx.c xx.o xx.exe
792
793./xsort C -f -k 2
794
795#---------------------------------------------------------------
796TEST=20; echo $TEST	"-d, -f, -b applies only to fields"
797cat >in <<!
798 b
799'C
800a
801!
802cp in out
803
804./xsort A -d
805
806./xsort B -f
807
808cat >out <<!
809 b
810a
811'C
812!
813
814./xsort C -dfb
815
816#---------------------------------------------------------------
817TEST=21; echo $TEST	"behavior of null bytes"
818cat >xx.c <<'!'
819#include <stdio.h>
820int main() { printf("\n%cb\n%ca\n",0,0); return 0; }
821!
822$CC -o xx.exe xx.c
823./xx.exe >in
824$SORT -u in >xx
825cmp -s in xx >/dev/null && echo ${TEST}A FAILED
826test "`wc -c <in`" = "`wc -c <xx`" || echo ${TEST}B FAILED
827rm -f xx.c xx.o xx.exe
828
829#---------------------------------------------------------------
830TEST=22; echo $TEST	"field limits"
831cat >in <<!
832a	2
833a	1
834b	2
835b	1
836!
837cat >out <<!
838b	1
839b	2
840a	1
841a	2
842!
843
844./xsort "" -r -k1,1 -k2n
845
846#---------------------------------------------------------------
847TEST=23; echo $TEST	"empty file, compact -o"
848
849echo hi >xx
850
851$SORT -oxx </dev/null
852cmp -s xx /dev/null >/dev/null || echo ${TEST}A FAILED
853
854$SORT -c </dev/null || echo ${TEST}B FAILED
855
856$SORT -cu </dev/null || echo ${TEST}C FAILED
857
858#---------------------------------------------------------------
859TEST=24; echo $TEST	"many fields"
860cat >in <<!
8610:2:3:4:5:6:7:8:9
8621:1:3:4:5:6:7:8:9
8631:2:2:4:5:6:7:8:9
8641:2:3:3:5:6:7:8:9
8651:2:3:4:4:6:7:8:9
8661:2:3:4:5:5:7:8:9
8671:2:3:4:5:6:6:8:9
8681:2:3:4:5:6:7:7:9
8691:2:3:4:5:6:7:8:8
870!
871cat >out <<!
8721:2:3:4:5:6:7:8:8
8731:2:3:4:5:6:7:7:9
8741:2:3:4:5:6:6:8:9
8751:2:3:4:5:5:7:8:9
8761:2:3:4:4:6:7:8:9
8771:2:3:3:5:6:7:8:9
8781:2:2:4:5:6:7:8:9
8791:1:3:4:5:6:7:8:9
8800:2:3:4:5:6:7:8:9
881!
882
883./xsort "" -t: -k9 -k8 -k7 -k6 -k5 -k4 -k3 -k2 -k1
884
885#---------------------------------------------------------------
886TEST=25; echo $TEST	"variously specified alpha fields"
887			# numbers give the correct orderings
888cat >in <<!
88901:04:19:01:16:01:21:01 a
89002:03:13:15:13:19:15:02  a
89103:02:07:09:07:13:09:03   a
89204:01:01:03:01:07:03:04    a
89305:08:20:16:17:02:20:05 aa
89406:07:14:18:14:20:14:06  aa
89507:06:08:10:08:14:08:07   aa
89608:05:02:04:02:08:02:08    aa
89709:16:22:02:22:04:24:13 b
89810:15:16:20:19:22:18:14  b
89911:14:10:12:10:16:12:15   b
90012:13:04:06:04:10:06:16    b
90113:24:24:22:24:06:22:21 bb
90214:23:18:24:21:24:16:22  bb
90315:22:12:14:12:18:10:23   bb
90416:21:06:08:06:12:04:24    bb
90517:12:21:21:18:03:19:09 ab
90618:11:15:19:15:21:13:10  ab
90719:10:09:11:09:15:07:11   ab
90820:09:03:05:03:09:01:12    ab
90921:20:23:17:23:05:23:17 ba
91022:19:17:23:20:23:17:18  ba
91123:18:11:13:11:17:11:19   ba
91224:17:05:07:05:11:05:20    ba
913!
914$SORT -k2b -k2 in >xx
915	$SORT -c -t: -k2n xx 2>/dev/null || echo ${TEST}A FAILED
916$SORT -k2,2.1b -k2 in >xx
917	$SORT -c -t: -k3n xx 2>/dev/null || echo ${TEST}B FAILED
918$SORT -k2.3 -k2 in >xx
919	$SORT -c -t: -k4n xx 2>/dev/null || echo ${TEST}C FAILED
920$SORT -k2b,2.3 -k2 in >xx
921	$SORT -c -t: -k5n xx 2>/dev/null || echo ${TEST}D FAILED
922$SORT -k2.3,2.1b -k2 in >xx
923	$SORT -c -t: -k6n xx 2>/dev/null || echo ${TEST}E FAILED
924$SORT -k2,2.1b -k2r in >xx
925	$SORT -c -t: -k7n xx 2>/dev/null || echo ${TEST}F FAILED
926$SORT -b -k2,2 -k2 in >xx
927	$SORT -c -t: -k8n xx 2>/dev/null || echo ${TEST}G FAILED
928$SORT -b -k2,2b -k2 in >xx 			# perhaps same as G
929	$SORT -c -t: -k3n xx 2>/dev/null || echo ${TEST}H FAILED\
930 "(standard is not clear on this)"
931
932#---------------------------------------------------------------
933TEST=26; echo $TEST	"empty fields, out of bounds fields	"
934cat >in <<!
9350 5
9361 4
9372 3
9383 2
9394 1
9405 0
941!
942cp in out
943
944./xsort "" -k2.2,2.1 -k2.3,2.4
945
946#---------------------------------------------------------------
947TEST=27; echo $TEST	"displaced -o"
948rm -f out
949
950$O $SORT /dev/null -o out || $o echo ${TEST}B FAILED
951$O test -f out || $O echo ${TEST}C FAILED
952
953#---------------------------------------------------------------
954TEST=28; echo $TEST	"apparently nonmonotone field specs"
955cat >in <<!
956aaaa c
957x a
9580 b
959!
960cp in out
961
962$o ./xsort A +1 -0.3 +1.4 -1.5
963
964./xsort B -k2,1.3 -k2.5,2.5
965
966#---------------------------------------------------------------
967TEST=29; echo $TEST	"determination of end of option list"
968cat >-k <<!
969x
970!
971rm -f out -c
972
973$SORT -- -k </dev/null >xx || echo ${TEST}A argument FAILED
974cmp -s xx -k || echo ${TEST}A comparison FAILED
975
976cat >in <<!
977xxx
978!
979>-
980>-o
981>in1
982
983$SORT -- -o in1 - <in >out
984cmp -s in out >/dev/null || echo ${TEST}C FAILED
985test -s in1 && echo ${TEST}D FAILED
986
987#---------------------------------------------------------------
988TEST=30; echo $TEST	"missing newline"
989$AWK 'BEGIN{ printf "%s", "x"}' >in
990echo x >out
991
992./xsort "" 2>/dev/null
993
994#---------------------------------------------------------------
995TEST=31; echo $TEST	"-M, multiple fields"
996cat >in <<!
997jan 10 1900
998Feb 26 1900
999feb 25 1900
1000January xx 1900
1001August 11 1900
1002jan 15 1990
1003feb 22 1990
1004mar 15 1990
1005apr 1 1990
1006may 45 1990
1007jun 14 1990
1008jul 4 1990
1009aug 1~ 1990
1010aug 11 1990
1011sep 1 1990
1012oct 12 1990
1013nov 24 1990
1014dec 25 1990
1015never 3 1990
1016 Dec 25 1990
1017!
1018cat >out <<!
1019January xx 1900
1020jan 10 1900
1021feb 25 1900
1022Feb 26 1900
1023August 11 1900
1024never 3 1990
1025jan 15 1990
1026feb 22 1990
1027mar 15 1990
1028apr 1 1990
1029may 45 1990
1030jun 14 1990
1031jul 4 1990
1032aug 1~ 1990
1033aug 11 1990
1034sep 1 1990
1035oct 12 1990
1036nov 24 1990
1037 Dec 25 1990
1038dec 25 1990
1039!
1040
1041$M ./xsort "" -k3n -k1M -k2n
1042
1043#---------------------------------------------------------------
1044TEST=32; echo $TEST	"-M case insensitivity, -r"
1045cat >in <<!
1046x
1047june
1048january
1049december
1050!
1051cat >out <<!
1052december
1053june
1054january
1055x
1056!
1057
1058$M ./xsort "" -Mr
1059
1060#---------------------------------------------------------------
1061TEST=33; echo $TEST	"-g, big enough for IEEE floating point"
1062cat >in <<!
10632
10641
106510
10661e-1
1067.2
10681e
10691E1
10701e.
10713e+308
10723e307
10731e-308
10741e-307
1075!
1076cat >out <<!
10771e-308
10781e-307
10791e-1
1080.2
10811
10821e
10831e.
10842
108510
10861E1
10873e307
10883e+308
1089!
1090
1091$g ./xsort "" -g
1092
1093#---------------------------------------------------------------
1094TEST=34; echo $TEST	"-g wide operands"
1095cat >in <<!
1096.99999999999999999999
1097099999999999999999999e-21
1098099999999999999999999e-19
1099.1e1
1100!
1101cat >out <<!
1102099999999999999999999e-21
1103.99999999999999999999
1104.1e1
1105099999999999999999999e-19
1106!
1107
1108$g ./xsort A -g
1109
1110cat >out <<!
1111.1e1
1112.99999999999999999999
1113099999999999999999999e-19
1114099999999999999999999e-21
1115!
1116
1117./xsort B -n
1118
1119#---------------------------------------------------------------
1120TEST=35; echo $TEST	"-g, -u with different fp reps"
1121cat >in <<!
1122+0
1123-0
11240
11250.10
1126+.1
1127-.1
1128-100e-3x
1129x
1130!
1131cat >out <<!
1132-.1
1133-100e-3x
1134+0
1135-0
11360
1137x
1138+.1
11390.10
1140!
1141
1142$g ./xsort A -g
1143
1144$g $SORT -gu in >xx && $g $SORT -c -gu xx || echo ${TEST}B FAILED
1145$g ./linecount C xx 3
1146
1147#---------------------------------------------------------------
1148TEST=36; echo $TEST	"-s"
1149cat >in <<!
1150a 2
1151b 1
1152c 2
1153a 1
1154b 2
1155c 1
1156!
1157cat >out <<!
1158a 2
1159a 1
1160b 1
1161b 2
1162c 2
1163c 1
1164!
1165
1166$s ./xsort "" -s -k1,1
1167
1168#---------------------------------------------------------------
1169TEST=37; echo $TEST	"-s, multiple files"
1170cat >in <<!
1171a 2
1172c 2
1173!
1174cat >in1 <<!
1175a 1
1176b 1
1177c 1
1178!
1179
1180cat >out <<!
1181a 2
1182b 1
1183c 2
1184!
1185
1186$s $SORT -su -k1,1 in in in1 in1 >xx
1187$s cmp -s xx out >/dev/null || echo ${TEST}A FAILED
1188
1189cat >out <<!
1190c 1
1191b 1
1192a 1
1193!
1194
1195$s $SORT -sru -k1,1 in in in1 in1 >xx
1196$s cmp -s xx out >/dev/null || echo ${TEST}B FAILED
1197
1198#---------------------------------------------------------------
1199TEST=38; echo $TEST	"-s"
1200$s $AWK '
1201	BEGIN {
1202		for(i=1; i<50; i++)
1203			for(j=1; j<=i; j++) {
1204				print i, 2 >"in"
1205				print i, 1 >"in1"
1206			}
1207	}' </dev/null
1208
1209$s $SORT -m -s -k1,1n in in1 >out
1210
1211$s $AWK '
1212	func stop()	{ print "'$TEST' FAILED"; exit }
1213	$1!=last1 	{ if(count!=last1 || $2!=2) stop();
1214			  count = 0}
1215	$1==last1 && $2!=last2 { if(count!=last1 || $2!=1) stop();
1216				 count = 0 }
1217			{ count++; last1 = $1; last2 = $2 }
1218	' out
1219
1220#---------------------------------------------------------------
1221TEST=39; echo $TEST	"empty fields"
1222cat >in <<!
1223bXXa
1224aXXb
1225!
1226cp in out
1227
1228./xsort A -k3 -tX
1229./xsort B -k2 -tX
1230./xsort C -r -k2,2 -tX
1231./xsort D -r -k4 -tX
1232
1233#---------------------------------------------------------------
1234TEST=40; echo $TEST	"deceptive field boundaries"
1235cat >in <<!
1236    1.2
1237  1.10
1238!
1239cp in out
1240
1241./xsort A -t. -k1,1n -k2,2n
1242./xsort B -t. -k1nr -k2n
1243
1244cat >in <<!
1245  feb
1246  jan
1247 jan
1248feb
1249!
1250cp in out
1251
1252$M ./xsort C -k1.1,1.4M
1253#---------------------------------------------------------------
1254TEST=41; echo $TEST	"fixed length records"
1255echo bdpoweonwekjbkgizohoeioilasho > in
1256echo hozopoonbkkjoieigishwewebdlao > out
1257
1258$k ./xsort A -s -r -R2 -k.2.1
1259
1260( echo; echo ) >> in
1261
1262cat >out <<!
1263zoweweshpoonoio
1264lakjhogieibkbd
1265
1266!
1267
1268$k ./xsort B -s -r -R2
1269
1270echo ' aza zaz mzm mam
1271
1272
1273' > in
1274
1275echo ' zaz mam mzm aza
1276
1277
1278' > out
1279
1280$k ./xsort C -s -r -R4 -k.2.1
1281$k ./xsort D -s -r -R4 -k1.2,1.2
1282
1283echo ' zaz mzm mam aza
1284
1285
1286' > out
1287
1288$k ./xsort E -s -r -R4 -k.2.2
1289$k ./xsort F -s -r -R4 -k1.2,1.3
1290$k ./xsort G -s -r -R4 -k1.2,1.2 -k1.3,1.3
1291
1292echo ' mzm aza zaz mam
1293
1294
1295' > out
1296
1297$k ./xsort H -s -r -R4 -k1.3,1.3 -k1.2,1.2
1298
1299done
1300