xref: /openbsd/regress/usr.bin/sort/stests (revision 73471bf0)
1#!/bin/sh -
2#	$OpenBSD: stests,v 1.18 2018/05/31 15:40:24 millert Exp $
3#	from: @(#)stests	8.1 (Berkeley) 6/6/93
4
5#Latest version.  My sort passes all tests because I wrote it.
6#We differ only on 25E and 25H.
7#(I found at least one bug in constructing test 25, and was driven
8#to rewrite field parsing to clarify it.)
9#
10#In 25E, -k2.3,2.1b, the fields are not necessarily out of order.
11#Even if they were, it would be legal (11752-3), although certainly
12#justification for warning.
13#
14#On 25H, your answer is as defensible as mine.  (Our suggestion
15#*1 backs mine.)
16
17: ${SORTPROG=sort}
18export SORTPROG
19
20# Tests for the Unix sort utility
21# Test POSIX features except for locale.
22# Test some nonstandard features if present.
23
24# Other tests should be made for files too big to fit in memory.
25
26# Currently we only test the C locale
27LANG=C
28LC_ALL=C
29export LANG LC_ALL
30
31# Initialize switches for nonstandard features.
32# Use parenthesized settings for supported features.
33
34o=:	# officially obsolescent features: +1 -2, misplaced -o (o=)
35g=:	# -g numeric sort including e-format numbers (g=)
36M=:	# -M sort by month names (M=)
37s=:	# -s stable, do not compare raw bytes on equal keys (s=)
38S=:	# -S user-specified memory size (S=-S10000)
39
40# Detect what features are supported, assuming bad options cause
41# errors.  Set switches accordingly.
42
43echo obsolescent and nonstandard features recognized, if any:
44if $SORTPROG +0 </dev/null 2>/dev/null; then o=
45				echo '	+1 -2'; fi
46if $SORTPROG /dev/null -o xx 2>/dev/null; then o=
47				echo '	displaced -o'; fi
48if $SORTPROG -g </dev/null 2>/dev/null; then g=
49				echo '	-g g-format numbers'; fi
50if $SORTPROG -M </dev/null 2>/dev/null; then M=
51				echo '	-M months'; fi
52if $SORTPROG -s </dev/null 2>/dev/null; then s=
53				echo '	-s stable'; fi
54if $SORTPROG -S10000 </dev/null 2>/dev/null; then S=-S10000
55				echo '	-S space'; fi
56if $SORTPROG -T. </dev/null 2>/dev/null; then
57				echo '	-T tempdir (not exercised)'; fi
58
59
60export TEST	# major sequence number of test
61
62trap "rm -f -- -k in in1 out xx -k xsort linecount fields; exit" 0 1 2 13 15
63
64# xsort testno options
65# Sort file "in" with specified options.
66# Compare with file "out" if that is supplied,
67# otherwise make plausibility checks on output
68
69#	"sum" must be dumb; insensitive to the
70#	order of lines within a file.
71#	System V sum is suitable; we use perl's builtin sum support.
72
73PATH=.:$PATH
74export PATH
75cat <<'!' >xsort; chmod +x xsort
76
77	sum() {
78		perl -e 'local $/; $sum = unpack("%32W*",<>) % 65535; $total = tell(STDIN); print "$sum $total\n"'
79	}
80
81	X=$1; shift
82
83	if $SORTPROG "$@" in >xx  &&  $SORTPROG -c "$@" xx
84	then
85		if test -f out
86		then
87			cmp xx out >/dev/null && exit 0
88			echo $TEST$X comparison failed
89		else
90			test "`sum <in`" = "`sum <xx`" && exit 0
91			echo $TEST$X checksum failed
92		fi
93	else
94		echo $TEST$X failed
95	fi
96	exit 1
97!
98
99# linecount testno file count
100# declares the given "testno" to be in error if number of
101# lines in "file" differs from "count"
102
103cat <<'!' >linecount; chmod +x linecount
104awk 'END{ if(NR!='$3') print "'$TEST$1' failed" }' $2
105!
106
107rm -f out
108
109#---------------------------------------------------------------
110TEST=01; echo $TEST	# -c status, checksum
111			# obsolescent features go together
112cat <<! >in
113b
114a
115!
116rm -f out -o
117
118$SORTPROG -c in 2>/dev/null && echo ${TEST}A failed
119
120xsort B || echo '"sum"' is probably unsuitable - see comments
121
122$o $SORTPROG +0 in -o in || echo ${TEST}c failed
123
124#---------------------------------------------------------------
125TEST=02; echo $TEST	# output from -c, none from -C
126cat <<! >in
127x
128y
129!
130
131$SORTPROG -cr in >out 2>xx && echo ${TEST}A failed
132test -s out && echo ${TEST}B failed
133test -s xx || echo ${TEST}C failed
134$SORTPROG -Cr in >out 2>xx && echo ${TEST}D failed
135test -s out && echo ${TEST}E failed
136test -s xx && echo ${TEST}F failed
137
138#---------------------------------------------------------------
139TEST=03; echo $TEST	# -n
140cat <<! >in
141-99.0
142-99.1
143-.0002
144-10
1452
1460010.000000000000000000000000000000000001
14710
1483x
149x
150!
151cat <<! >out
152-99.1
153-99.0
154-10
155-.0002
156x
1572
1583x
15910
1600010.000000000000000000000000000000000001
161!
162
163xsort "" -n
164
165#---------------------------------------------------------------
166TEST=04; echo $TEST	# -b without fields, piping, -c status return
167cat <<! >in
168  b
169 a
170!
171cp in out
172
173xsort A -b
174xsort B -k1 -b
175
176cat in | $SORTPROG | cat >xx
177cmp xx out >/dev/null || echo ${TEST}C failed
178
179$SORTPROG in | $SORTPROG -cr 2>/dev/null && echo ${TEST}D failed
180
181#---------------------------------------------------------------
182TEST=05; echo $TEST	# fields, reverse fields, -c status return
183cat <<! >in
184b b p
185a b q
186x a
187!
188cat <<! >out
189x a
190a b q
191b b p
192!
193
194$o xsort A +1 -2
195
196$o xsort B +1 -2 +2r
197
198xsort C -k 2,2
199
200xsort D -k 2,2 -k 3r
201
202xsort E -k 2,2.0
203
204xsort F -k 2,2 -k 1,1 -k 3
205
206$SORTPROG -c -k 2 in 2>/dev/null && echo ${TEST}G failed
207
208#---------------------------------------------------------------
209TEST=06; echo $TEST	# -t
210cat <<! >in
211a:
212a!
213!
214cp in out
215
216$o xsort A -t : -r +0
217
218$o xsort B -t : +0 -1
219
220xsort C -t : -r -k 1
221
222xsort D -t : -k 1,1
223
224#---------------------------------------------------------------
225TEST=07; echo $TEST	# -t, character positions in fields
226	# -t: as 1 arg is not strictly conforming, but classical
227cat <<! >in
228: ab
229:bac
230!
231cat <<! >out
232:bac
233: ab
234!
235
236$o xsort A -b -t: +1.1
237
238$o xsort B -t: +1.1r
239
240xsort C -b -t: -k 2.2
241
242xsort D -t: -k 2.2r
243
244#---------------------------------------------------------------
245TEST=08; echo $TEST	# space and tab as -t characters
246cat <<! >in
247 b c
248 b	c
249	b c
250!
251cp in out
252
253xsort A -t ' ' -k2,2
254
255xsort B -t ' ' -k2.1,2.0
256
257cat <<! >out
258 b c
259	b c
260 b	c
261!
262
263xsort C -t '	' -k2,2
264
265xsort D -t '	' -k2.1,2.0
266
267cat <<! >out
268 b	c
269	b c
270 b c
271!
272
273xsort E -k2
274
275cat <<! >out
276	b c
277 b	c
278 b c
279!
280
281xsort F -k2b
282
283#---------------------------------------------------------------
284TEST=09; echo $TEST	# alphabetic as -t character
285cat <<! >in
286zXa
287yXa
288zXb
289!
290cp in out
291
292xsort "" -tX -k2 -k1r,1
293
294#---------------------------------------------------------------
295TEST=10; echo $TEST	# -m
296cat <<! >in
297a
298ab
299ab
300bc
301ca
302!
303cat <<! >in1
304Z
305a
306aa
307ac
308c
309!
310cat <<! >out
311Z
312a
313a
314aa
315ab
316ab
317ac
318bc
319c
320ca
321!
322
323$SORTPROG -m in in1 >xx
324cmp xx out >/dev/null || echo $TEST failed
325
326#---------------------------------------------------------------
327TEST=11; echo $TEST	# multiple files, -o overwites input, -m, -mu
328cat <<! >in
329a
330b
331c
332d
333!
334
335$SORTPROG -o xx     in in in in in in in in in in in in in in in in in
336linecount A xx 68
337$SORTPROG -o in -mu in in in in in in in in in in in in in in in in in
338linecount B in 4
339$SORTPROG -o in -m  in in in in in in in in in in in in in in in in in
340
341cmp in xx >/dev/null || echo ${TEST}C failed
342
343#---------------------------------------------------------------
344TEST=12; echo $TEST	# does -mu pick the first among equals?
345cat <<! >in
3463B
3473b
3483B2
349~3B2
3504.1
35141
3525
3535.
354!
355cat <<! >out
3563B
3573B2
3584.1
3595
360!
361
362xsort A -mudf || echo "(other behavior is legal, not classical)"
363
364xsort B -mudf -k1 || echo "(other behavior is legal, not classical)"
365
366#---------------------------------------------------------------
367TEST=13; echo $TEST	# long records (>8000 bytes, keys >16000), -r
368awk '
369BEGIN {	x="x"
370	for(i=1; i<=12; i++) x = x x
371	for(i=15; i<=25; i++) print x i
372}' >in
373awk '
374BEGIN {	x="x"
375	for(i=1; i<=12; i++) x = x x
376	for(i=25; i>=15; i--) print x i
377}' >out
378
379xsort A -r
380
381xsort B -k 1,1r -k 1
382
383#---------------------------------------------------------------
384TEST=14; echo $TEST "(3 long parts)"
385awk 'BEGIN { for(i=0; i<100000; i++) print rand() }' | grep -v e >in
386rm -f out
387
388xsort A; echo $TEST "(part A done)"
389
390xsort B -n; echo $TEST "(part B done)"
391
392# next test is unclean: xx is a hidden side-effect of xsort
393
394awk '
395	$0 < x { print "test '${TEST}C' failed"; exit }
396	$0 "" != x { print >"out"; x = $0 }
397' xx
398
399xsort C -n -u
400
401#---------------------------------------------------------------
402TEST=15; echo $TEST "(long)"	# force intermediate files if possible
403awk 'BEGIN { for(i=0; i<20000; i++) print rand() }' >in
404rm -f out
405
406xsort A -r $y
407
408$SORTPROG -r in | awk '$0 "x" != x { print ; x = $0 "x" }' >out
409
410xsort B -u -r $y
411
412#---------------------------------------------------------------
413TEST=16; echo $TEST	# -nr, -nm, file name -
414awk 'BEGIN { for(i=-100; i<=100; i+=2) printf "%.10d\n", i }' >in
415
416awk 'BEGIN { for(i=-99; i<=100; i+=2) print i }' | $SORTPROG -nr in - >xx
417awk '$0+0 != 101-NR { print "'${TEST}A' failed"; exit }' xx
418
419awk 'BEGIN { for(i=-99; i<=100; i+=2) print i }' | $SORTPROG -mn in - >xx
420awk '$0+0 != -101+NR { print "'${TEST}B' failed"; exit }' xx
421
422#---------------------------------------------------------------
423TEST=17; echo $TEST	# -d, fields without end, modifier override
424cat <<! >in
425a-B
426a+b
427a b
428A+b
429a	b
430!
431cat <<! >out
432a	b
433a b
434A+b
435a-B
436a+b
437!
438
439$o xsort A -df +0 +0d
440
441xsort B -df -k 1 -k 1d
442
443#---------------------------------------------------------------
444TEST=18; echo $TEST	# -u on key only
445cat <<! >in
44612	y
44713	z
44812	x
449!
450cat <<! >out
45112	x
45212	y
45313	z
454!
455
456$o xsort A +0 -1
457
458xsort B -k 1,1
459
460$SORTPROG -u -k 1,1 in >xx
461linecount C xx 2
462
463#---------------------------------------------------------------
464TEST=19; echo $TEST	# -i, -d, -f
465cat <<! >xx.c
466#include <stdio.h>
467void run(int i, int j){ for( ; i<=j; i++) printf("%.3o %c\n",i,i); }
468int main(){	run(0, 011);		/* 012=='\n' */
469	run(013, 0377); }
470!
471cc xx.c
472a.out >in
473cat <<! >xx.c
474#include <stdio.h>
475void run(int i, int j){ for( ; i<=j; i++) printf("%.3o %c\n",i,i); }
476int main(){ run(0, 011);
477	run(013, ' '-1);
478	run(0177, 0377);
479	run(' ', 0176); }
480!
481cc xx.c
482a.out >out
483
484xsort A -i -k 2
485
486cat <<! >xx.c
487#include <stdio.h>
488void run(int i, int j){ for( ; i<=j; i++) printf("%.3o %c\n",i,i); }
489int main(){	run(0, 010);		/* 011=='\t', 012=='\n' */
490	run(013, ' '-1);
491	run(' '+1, '0'-1);
492	run('9'+1, 'A'-1);
493	run('Z'+1, 'a'-1);
494	run('z'+1, 0377);
495	run('\t', '\t');
496	run(' ', ' ');
497	run('0', '9');
498	run('A', 'Z');
499	run('a', 'z'); }
500!
501cc xx.c
502a.out >out
503
504xsort B -d -k 2
505
506cat <<! >xx.c
507#include <stdio.h>
508void run(int i, int j){ for( ; i<=j; i++) printf("%.3o %c\n",i,i); }
509int main(){	int i;
510	run(0, 011);
511	run(013, 'A'-1);
512	for(i='A'; i<='Z'; i++)
513		printf("%.3o %c\n%.3o %c\n",i,i,i+040,i+040);
514	run('Z'+1, 'a'-1);
515	run('z'+1, 0377); }
516!
517cc xx.c
518a.out >out
519rm xx.c
520
521xsort C -f -k 2
522
523#---------------------------------------------------------------
524TEST=20; echo $TEST	# -d, -f, -b applies only to fields
525cat <<! >in
526 b
527'C
528a
529!
530cp in out
531
532xsort A -d
533
534xsort B -f
535
536cat <<! >out
537 b
538a
539'C
540!
541
542xsort C -dfb
543
544#---------------------------------------------------------------
545TEST=21; echo $TEST	# behavior of null bytes
546cat <<'!' >xx.c
547#include <stdio.h>
548int main() { printf("%cb\n%ca\n",0,0); }
549!
550cc xx.c
551a.out >in
552$SORTPROG in >xx
553cmp in xx >/dev/null && echo ${TEST}A failed
554test "`wc -c <in`" = "`wc -c <xx`" || echo ${TEST}B failed
555rm xx.c a.out
556
557#---------------------------------------------------------------
558TEST=22; echo $TEST	# field limits
559cat <<! >in
560a	2
561a	1
562b	2
563b	1
564!
565cat <<! >out
566b	1
567b	2
568a	1
569a	2
570!
571
572xsort "" -r -k1,1 -k2n
573
574#---------------------------------------------------------------
575TEST=23; echo $TEST	# empty file
576
577$SORTPROG -o xx </dev/null
578cmp xx /dev/null 2>/dev/null || echo ${TEST}A failed
579
580$SORTPROG -c </dev/null || echo ${TEST}B failed
581
582$SORTPROG -cu </dev/null || echo ${TEST}C failed
583
584#---------------------------------------------------------------
585TEST=24; echo $TEST	# many fields
586cat <<! >in
5870:2:3:4:5:6:7:8:9
5881:1:3:4:5:6:7:8:9
5891:2:2:4:5:6:7:8:9
5901:2:3:3:5:6:7:8:9
5911:2:3:4:4:6:7:8:9
5921:2:3:4:5:5:7:8:9
5931:2:3:4:5:6:6:8:9
5941:2:3:4:5:6:7:7:9
5951:2:3:4:5:6:7:8:8
596!
597cat <<! >out
5981:2:3:4:5:6:7:8:8
5991:2:3:4:5:6:7:7:9
6001:2:3:4:5:6:6:8:9
6011:2:3:4:5:5:7:8:9
6021:2:3:4:4:6:7:8:9
6031:2:3:3:5:6:7:8:9
6041:2:2:4:5:6:7:8:9
6051:1:3:4:5:6:7:8:9
6060:2:3:4:5:6:7:8:9
607!
608
609xsort "" -t: -k9 -k8 -k7 -k6 -k5 -k4 -k3 -k2 -k1
610
611#---------------------------------------------------------------
612TEST=25; echo $TEST	# variously specified alpha fields
613			# numbers give the correct orderings
614cat <<! >in
61501:04:19:01:16:01:21:01 a
61602:03:13:15:13:19:15:02  a
61703:02:07:09:07:13:09:03   a
61804:01:01:03:01:07:03:04    a
61905:08:20:16:17:02:20:05 aa
62006:07:14:18:14:20:14:06  aa
62107:06:08:10:08:14:08:07   aa
62208:05:02:04:02:08:02:08    aa
62309:16:22:02:22:04:24:13 b
62410:15:16:20:19:22:18:14  b
62511:14:10:12:10:16:12:15   b
62612:13:04:06:04:10:06:16    b
62713:24:24:22:24:06:22:21 bb
62814:23:18:24:21:24:16:22  bb
62915:22:12:14:12:18:10:23   bb
63016:21:06:08:06:12:04:24    bb
63117:12:21:21:18:03:19:09 ab
63218:11:15:19:15:21:13:10  ab
63319:10:09:11:09:15:07:11   ab
63420:09:03:05:03:09:01:12    ab
63521:20:23:17:23:05:23:17 ba
63622:19:17:23:20:23:17:18  ba
63723:18:11:13:11:17:11:19   ba
63824:17:05:07:05:11:05:20    ba
639!
640$SORTPROG -k2b -k2 in >xx &&
641	$SORTPROG -c -t: -k2n xx 2>/dev/null || echo ${TEST}A failed
642$SORTPROG -k2,2.1b -k2 in >xx &&
643	$SORTPROG -c -t: -k3n xx 2>/dev/null || echo ${TEST}B failed
644$SORTPROG -k2.3 -k2 in >xx &&
645	$SORTPROG -c -t: -k4n xx 2>/dev/null || echo ${TEST}C failed
646$SORTPROG -k2b,2.3 -k2 in >xx &&
647	$SORTPROG -c -t: -k5n xx 2>/dev/null || echo ${TEST}D failed
648$SORTPROG -k2.3,2.1b -k2 in >xx &&
649	$SORTPROG -c -t: -k6n xx 2>/dev/null || echo ${TEST}E failed
650$SORTPROG -k2,2.1b -k2r in >xx &&
651	$SORTPROG -c -t: -k7n xx 2>/dev/null || echo ${TEST}F failed
652$SORTPROG -b -k2,2 -k2 in >xx &&
653	$SORTPROG -c -t: -k8n xx 2>/dev/null || echo ${TEST}G failed
654$SORTPROG -b -k2,2b -k2 in >xx &&		# perhaps same as G
655	$SORTPROG -c -t: -k8n xx 2>/dev/null || echo ${TEST}H failed\
656 "(standard is not clear on this)"
657
658#---------------------------------------------------------------
659TEST=26; echo $TEST	# empty fields, out of bounds fields
660cat <<! >in
6610 5
6621 4
6632 3
6643 2
6654 1
6665 0
667!
668cp in out
669
670xsort "" -k2.2,2.1 -k2.3,2.4
671
672#---------------------------------------------------------------
673TEST=27; echo $TEST	# displaced -o
674rm -f out
675
676$o $SORTPROG /dev/null -o out || $o echo ${TEST}B failed
677$o test -f out || $o echo ${TEST}C failed
678
679#---------------------------------------------------------------
680TEST=28; echo $TEST	# apparently nonmonotone field specs
681cat <<! >in
682aaaa c
683x a
6840 b
685!
686cp in out
687
688$o xsort A +1 -0.3 +1.4 -1.5
689
690xsort B -k2,1.3 -k2.5,2.5
691
692#---------------------------------------------------------------
693TEST=29; echo $TEST	# determination of end of option list
694cat >-k <<!
695x
696!
697rm -f out -c
698
699$SORTPROG -- -k </dev/null >xx || echo ${TEST}A argument failed
700cmp xx -k || echo ${TEST}A comparison failed
701
702$SORTPROG - -c </dev/null 2>/dev/null && echo ${TEST}B failed
703rm -- -k
704
705#---------------------------------------------------------------
706TEST=30; echo $TEST	# missing newline
707awk 'BEGIN{ printf "%s", "x"}' | $SORTPROG >xx
708wc -c <xx | awk '$1!=2{ print "'${TEST}' failed" }'
709
710#---------------------------------------------------------------
711TEST=31; echo $TEST	# -M, multiple fields
712cat <<! >in
713jan 10 1900
714Feb 26 1900
715feb 25 1900
716January xx 1900
717August 11 1900
718jan 15 1990
719feb 22 1990
720mar 15 1990
721apr 1 1990
722may 45 1990
723jun 14 1990
724jul 4 1990
725aug 1~ 1990
726aug 11 1990
727sep 1 1990
728oct 12 1990
729nov 24 1990
730dec 25 1990
731never 3 1990
732 Dec 25 1990
733!
734cat <<! >out
735January xx 1900
736jan 10 1900
737feb 25 1900
738Feb 26 1900
739August 11 1900
740never 3 1990
741jan 15 1990
742feb 22 1990
743mar 15 1990
744apr 1 1990
745may 45 1990
746jun 14 1990
747jul 4 1990
748aug 1~ 1990
749aug 11 1990
750sep 1 1990
751oct 12 1990
752nov 24 1990
753 Dec 25 1990
754dec 25 1990
755!
756
757$M xsort "" -k3n -k1M -k2n
758
759#---------------------------------------------------------------
760TEST=32; echo $TEST	# -M case insensitivity, -r
761cat <<! >in
762x
763june
764january
765december
766!
767cat <<! >out
768december
769june
770january
771x
772!
773
774$M xsort "" -Mr
775
776#---------------------------------------------------------------
777TEST=33; echo $TEST	# -g
778cat <<! >in
7792
7801
78110
782.2
7831e
7841E1
7851e.
786!
787cat <<! >out
788.2
7891
7901e
7911e.
7922
79310
7941E1
795!
796
797$g xsort "" -g
798
799#---------------------------------------------------------------
800TEST=34; echo $TEST	# -g wide operands
801cat <<! >in
802.9999999999999999
803099999999999999999999e-21
804099999999999999999999e-19
805.1e1
806!
807cat <<! >out
808099999999999999999999e-21
809.9999999999999999
810.1e1
811099999999999999999999e-19
812!
813
814$g xsort A -g
815
816cat <<! >out
817.1e1
818.9999999999999999
819099999999999999999999e-19
820099999999999999999999e-21
821!
822
823xsort B -n
824
825#---------------------------------------------------------------
826TEST=35; echo $TEST	#-g, -u with different fp reps
827cat <<! >in
828+0
829-0
8300.10
831+.1
832-.1
833-100e-3
834x
835!
836cat <<! >out
837-.1
838-100e-3
839+0
840-0
841x
842+.1
8430.10
844!
845
846$g xsort A -g
847
848$g $SORTPROG -gu in >xx && $g $SORTPROG -c -gu xx || echo ${TEST}B failed
849$g linecount C xx 3
850
851#---------------------------------------------------------------
852TEST=36; echo $TEST	# -s
853cat <<! >in
854a 2
855b 1
856c 2
857a 1
858b 2
859c 1
860!
861cat <<! >out
862a 2
863a 1
864b 1
865b 2
866c 2
867c 1
868!
869
870$s xsort "" -s -k1,1
871
872#---------------------------------------------------------------
873TEST=37; echo $TEST	# -s, multiple files
874cat <<! >in
875c 2
876a 2
877!
878cat <<! >in1
879c 1
880b 1
881a 1
882!
883cat <<! >out
884c 2
885b 1
886a 2
887!
888
889$s $SORTPROG -smru -k1,1 in in in1 in1 >xx
890$s cmp xx out >/dev/null || echo $TEST failed
891
892#---------------------------------------------------------------
893TEST=38; echo $TEST	# -s
894$s awk '
895	BEGIN {
896		for(i=1; i<50; i++)
897			for(j=1; j<=i; j++) {
898				print i, 2 >"in"
899				print i, 1 >"in1"
900			}
901	}'
902
903$s $SORTPROG -m -s -k1,1n in in1 >out
904
905$s awk '
906	func stop()	{ print "'$TEST' failed"; exit }
907	$1!=last1 	{ if(count!=last1 || $2!=2) stop();
908			  count = 0}
909	$1==last1 && $2!=last2 { if(count!=last1 || $2!=1) stop();
910				 count = 0 }
911			{ count++; last1 = $1; last2 = $2 }
912	' out
913
914#---------------------------------------------------------------
915TEST=39; echo $TEST	# sort already sorted dictionary
916
917dict=/usr/share/dict/words
918
919$SORTPROG -f $dict > out
920
921cmp -s out $dict || echo $TEST failed - $SORTPROG -f $dict
922
923#---------------------------------------------------------------
924TEST=40; echo "$TEST (long)"    # long lines test
925
926line1="abcdefghijklmnopqrstabcdefghijklmnopqrstabcdefghijklmnopqrstabcdefghij"
927line2="bcdefghijklmnopqrstabcdefghijklmnopqrstabcdefghijklmnopqrstabcdefghijk"
928
929rm -f in out
930
931# generate two out-of-order long lines (roughly 70 KB each), and try sort
932# them
933awk '
934BEGIN {
935	line1 = "'"${line1}"'"
936	line2 = "'"${line2}"'"
937	for(i=0; i<10; i++) {
938		line1 = line1 line1
939		line2 = line2 line2
940	}
941	print line2 > "in"
942	print line1 > "in"
943
944	print line1 > "out"
945	print line2 > "out"
946}'
947
948xsort "A"
949
950# generate already sorted file using $dict, only append space and
951# long string to each line to make lines longer than usual
952# use only first 200 lines (sort file approx. 14MB)
953cat $dict | awk '
954BEGIN {
955	line = "'"$line1"'"
956	for(i=0; i<10; i++)
957		line = line line
958	idx = 0
959}
960{ print $1 " " line; if (idx++ > 200) exit 0 }' > in
961ln -sf in out
962xsort "B" -f
963rm -f in out
964#---------------------------------------------------------------
965TEST=41; echo "$TEST"
966
967# sort okay at reps=87381, broken at 87382
968# on 64-bit platforms, it's already broken at 87382/2
969
970awk '
971BEGIN {
972	reps=87382
973	i=0
974	while (i++ < reps) {
975		print "lo0" > "in"
976		print "ce0" > "in"
977		print "ce1" > "in"
978	}
979	print "ce0" > "out"
980	print "ce1" > "out"
981	print "lo0" > "out"
982
983}'
984
985xsort A -u
986#---------------------------------------------------------------
987TEST=42; echo $TEST	# overwrite permissions
988
989omask=`umask`
990:> in
991:> out
992
993umask 000
994chmod 0643 out
995$SORTPROG -o out in
996ls -l out | grep -e -rw-r---wx -q || echo ${TEST}A failed
997chmod u-w out
998$SORTPROG -o out in 2>/dev/null && echo ${TEST}B failed
999chmod 0643 out
1000$SORTPROG -o out in out
1001ls -l out | grep -e -rw-r---wx -q || echo ${TEST}C failed
1002umask 071
1003$SORTPROG -o out out
1004ls -l out | grep -e -rw-r---wx -q || echo ${TEST}D failed
1005chmod u-w out
1006$SORTPROG -o out out 2>/dev/null && echo ${TEST}F failed
1007
1008rm -f in out
1009umask $omask
1010#---------------------------------------------------------------
1011TEST=43; echo $TEST	# -c/-C should not overwrite output file
1012
1013cat <<! >out
1014x
1015y
1016!
1017cp out xx
1018
1019$SORTPROG -c -o xx xx 2>/dev/null || echo ${TEST}A failed
1020cmp -s xx out || echo ${TEST}B failed
1021$SORTPROG -cr -o xx xx 2>/dev/null && echo ${TEST}C failed
1022cmp -s xx out || echo ${TEST}D failed
1023$SORTPROG -C -o xx xx 2>/dev/null || echo ${TEST}E failed
1024cmp -s xx out || echo ${TEST}F failed
1025$SORTPROG -Cr -o xx xx 2>/dev/null && echo ${TEST}G failed
1026cmp -s xx out || echo ${TEST}G failed
1027
1028#---------------------------------------------------------------
1029TEST=44; echo $TEST	# only a single input file allowed for -c/-C
1030
1031cat <<! >in
1032x
1033y
1034!
1035cp in out
1036
1037$SORTPROG -c in out 2>/dev/null
1038test $? -eq 2 || echo ${TEST}A failed
1039$SORTPROG -C in out 2>/dev/null
1040test $? -eq 2 || echo ${TEST}B failed
1041
1042#---------------------------------------------------------------
1043TEST=45; echo $TEST	# field limits with -b
1044cat <<! >in
1045 a	2
1046a	1
1047 b	2
1048b	1
1049!
1050cat <<! >out
1051b	1
1052 b	2
1053a	1
1054 a	2
1055!
1056
1057xsort "" -br -k1,1 -k2n
1058