4 # Copyright (C) 2006-2016 Free Software Foundation, Inc.
6 # This program is free software: you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation, either version 3 of the License, or
9 # (at your option) any later version.
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
16 # You should have received a copy of the GNU General Public License
17 # along with this program. If not, see <http://www.gnu.org/licenses/>.
21 (my $ME = $0) =~ s
|.*/||;
23 # Turn off localization of executable's output.
24 @ENV{qw(LANGUAGE LANG LC_ALL)} = ('C') x
3;
26 my $mb_locale = $ENV{LOCALE_FR_UTF8
};
27 ! defined $mb_locale || $mb_locale eq 'none'
31 my $try = "Try '$prog --help' for more information.\n";
32 my $from_field1 = "$prog: fields are numbered from 1\n$try";
33 my $from_pos1 = "$prog: byte/character positions are numbered from 1\n$try";
34 my $inval_fld = "$prog: invalid field range\n$try";
35 my $inval_pos = "$prog: invalid byte or character range\n$try";
36 my $no_endpoint = "$prog: invalid range with no endpoint: -\n$try";
37 my $nofield = "$prog: an input delimiter may be specified only when " .
38 "operating on fields\n$try";
42 # Provoke a double-free in cut from coreutils-6.7.
43 ['dbl-free', '-f2-', {IN
=>{f
=>'x'}}, {IN
=>{g
=>'y'}}, {OUT
=>"x\ny\n"}],
45 # This failed (as it should) even before coreutils-6.9.90,
46 # but cut from 6.9.90 produces a more useful diagnostic.
47 ['zero-1', '-b0', {ERR
=>$from_pos1}, {EXIT
=> 1} ],
49 # Up to coreutils-6.9, specifying a range of 0-2 was not an error.
50 # It was treated just like "-2".
51 ['zero-2', '-f0-2', {ERR
=>$from_field1}, {EXIT
=> 1} ],
53 # Up to coreutils-8.20, specifying a range of 0- was not an error.
54 ['zero-3b', '-b0-', {ERR
=>$from_pos1}, {EXIT
=> 1} ],
55 ['zero-3c', '-c0-', {ERR
=>$from_pos1}, {EXIT
=> 1} ],
56 ['zero-3f', '-f0-', {ERR
=>$from_field1}, {EXIT
=> 1} ],
58 ['1', '-d:', '-f1,3-', {IN
=>"a:b:c\n"}, {OUT
=>"a:c\n"}],
59 ['2', '-d:', '-f1,3-', {IN
=>"a:b:c\n"}, {OUT
=>"a:c\n"}],
60 ['3', qw(-d: -f2-), {IN
=>"a:b:c\n"}, {OUT
=>"b:c\n"}],
61 ['4', qw(-d: -f4), {IN
=>"a:b:c\n"}, {OUT
=>"\n"}],
62 ['5', qw(-d: -f4), {IN
=>""}, {OUT
=>""}],
63 ['6', '-c4', {IN
=>"123\n"}, {OUT
=>"\n"}],
64 ['7', '-c4', {IN
=>"123"}, {OUT
=>"\n"}],
65 ['8', '-c4', {IN
=>"123\n1"}, {OUT
=>"\n\n"}],
66 ['9', '-c4', {IN
=>""}, {OUT
=>""}],
67 ['a', qw(-s -d:), '-f3-', {IN
=>"a:b:c\n"}, {OUT
=>"c\n"}],
68 ['b', qw(-s -d:), '-f2,3', {IN
=>"a:b:c\n"}, {OUT
=>"b:c\n"}],
69 ['c', qw(-s -d:), '-f1,3', {IN
=>"a:b:c\n"}, {OUT
=>"a:c\n"}],
70 # Trailing colon should not be output
71 ['d', qw(-s -d:), '-f1,3', {IN
=>"a:b:c:\n"}, {OUT
=>"a:c\n"}],
72 ['e', qw(-s -d:), '-f3-', {IN
=>"a:b:c:\n"}, {OUT
=>"c:\n"}],
73 ['f', qw(-s -d:), '-f3-4', {IN
=>"a:b:c:\n"}, {OUT
=>"c:\n"}],
74 ['g', qw(-s -d:), '-f3,4', {IN
=>"a:b:c:\n"}, {OUT
=>"c:\n"}],
75 # Make sure -s suppresses non-delimited lines
76 ['h', qw(-s -d:), '-f2,3', {IN
=>"abc\n"}, {OUT
=>""}],
78 ['i', qw(-d: -f1-3), {IN
=>":::\n"}, {OUT
=>"::\n"}],
79 ['j', qw(-d: -f1-4), {IN
=>":::\n"}, {OUT
=>":::\n"}],
80 ['k', qw(-d: -f2-3), {IN
=>":::\n"}, {OUT
=>":\n"}],
81 ['l', qw(-d: -f2-4), {IN
=>":::\n"}, {OUT
=>"::\n"}],
82 ['m', qw(-s -d: -f1-3), {IN
=>":::\n"}, {OUT
=>"::\n"}],
83 ['n', qw(-s -d: -f1-4), {IN
=>":::\n"}, {OUT
=>":::\n"}],
84 ['o', qw(-s -d: -f2-3), {IN
=>":::\n"}, {OUT
=>":\n"}],
85 ['p', qw(-s -d: -f2-4), {IN
=>":::\n"}, {OUT
=>"::\n"}],
86 ['q', qw(-s -d: -f2-4), {IN
=>":::\n:\n"}, {OUT
=>"::\n\n"}],
87 ['r', qw(-s -d: -f2-4), {IN
=>":::\n:1\n"}, {OUT
=>"::\n1\n"}],
88 ['s', qw(-s -d: -f1-4), {IN
=>":::\n:a\n"}, {OUT
=>":::\n:a\n"}],
89 ['t', qw(-s -d: -f3-), {IN
=>":::\n:1\n"}, {OUT
=>":\n\n"}],
90 # Make sure it handles empty input properly, with and without -s.
91 ['u', qw(-s -f3-), {IN
=>""}, {OUT
=>""}],
92 ['v', '-f3-', {IN
=>""}, {OUT
=>""}],
93 # Make sure it handles empty input properly.
94 ['w', qw(-b 1), {IN
=>""}, {OUT
=>""}],
95 ['x', qw(-s -d: -f2-4), {IN
=>":\n"}, {OUT
=>"\n"}],
97 # -s may be used only with -f
98 ['y', qw(-s -b4), {IN
=>":\n"}, {OUT
=>""}, {EXIT
=>1},
99 {ERR
=>"$prog: suppressing non-delimited lines makes sense\n"
100 . "\tonly when operating on fields\n$try"}],
101 # You must specify bytes or fields (or chars)
102 ['z', '', {IN
=>":\n"}, {OUT
=>""}, {EXIT
=>1},
103 {ERR
=>"$prog: you must specify a list of bytes, characters, or fields\n$try"}
106 ['empty-fl', qw(-f ''), {IN
=>":\n"}, {OUT
=>""}, {EXIT
=>1},
107 {ERR
=>$from_field1}],
109 ['missing-fl', qw(-f --), {IN
=>":\n"}, {OUT
=>""}, {EXIT
=>1},
112 ['empty-bl', qw(-b ''), {IN
=>":\n"}, {OUT
=>""}, {EXIT
=>1}, {ERR
=>$from_pos1}],
114 ['missing-bl', qw(-b --), {IN
=>":\n"}, {OUT
=>""}, {EXIT
=>1},
117 # This test fails with cut from textutils-1.22.
118 ['empty-f1', '-f1', {IN
=>""}, {OUT
=>""}],
120 ['empty-f2', '-f2', {IN
=>""}, {OUT
=>""}],
122 ['o-delim', qw(-d: --out=_), '-f2,3', {IN
=>"a:b:c\n"}, {OUT
=>"b_c\n"}],
123 ['nul-idelim', qw(-d '' --out=_), '-f2,3', {IN
=>"a\0b\0c\n"}, {OUT
=>"b_c\n"}],
124 ['nul-odelim', qw(-d: --out=), '-f2,3', {IN
=>"a:b:c\n"}, {OUT
=>"b\0c\n"}],
125 ['multichar-od', qw(-d: --out=_._), '-f2,3', {IN
=>"a:b:c\n"},
128 # Ensure delim is not allowed without a field
129 # Prior to 8.21, a NUL delim was allowed without a field
130 ['delim-no-field1', qw(-d ''), '-b1', {EXIT
=>1}, {ERR
=>$nofield}],
131 ['delim-no-field2', qw(-d:), '-b1', {EXIT
=>1}, {ERR
=>$nofield}],
133 # Prior to 1.22i, you couldn't use a delimiter that would sign-extend.
134 ['8bit-delim', '-d', "\255", '--out=_', '-f2,3', {IN
=>"a\255b\255c\n"},
137 # newline processing for fields
138 ['newline-1', '-f1-', {IN
=>"a\nb"}, {OUT
=>"a\nb\n"}],
139 ['newline-2', '-f1-', {IN
=>""}, {OUT
=>""}],
140 ['newline-3', '-d:', '-f1', {IN
=>"a:1\nb:2\n"}, {OUT
=>"a\nb\n"}],
141 ['newline-4', '-d:', '-f1', {IN
=>"a:1\nb:2"}, {OUT
=>"a\nb\n"}],
142 ['newline-5', '-d:', '-f2', {IN
=>"a:1\nb:2\n"}, {OUT
=>"1\n2\n"}],
143 ['newline-6', '-d:', '-f2', {IN
=>"a:1\nb:2"}, {OUT
=>"1\n2\n"}],
144 ['newline-7', '-s', '-d:', '-f1', {IN
=>"a:1\nb:2"}, {OUT
=>"a\nb\n"}],
145 ['newline-8', '-s', '-d:', '-f1', {IN
=>"a:1\nb:2\n"}, {OUT
=>"a\nb\n"}],
146 ['newline-9', '-s', '-d:', '-f1', {IN
=>"a1\nb2"}, {OUT
=>""}],
147 ['newline-10', '-s', '-d:', '-f1,2', {IN
=>"a:1\nb:2"}, {OUT
=>"a:1\nb:2\n"}],
148 ['newline-11', '-s', '-d:', '-f1,2', {IN
=>"a:1\nb:2\n"}, {OUT
=>"a:1\nb:2\n"}],
149 ['newline-12', '-s', '-d:', '-f1', {IN
=>"a:1\nb:"}, {OUT
=>"a\nb\n"}],
150 ['newline-13', '-d:', '-f1-', {IN
=>"a1:\n:"}, {OUT
=>"a1:\n:\n"}],
151 # newline processing for fields when -d == '\n'
152 ['newline-14', "-d'\n'", '-f1', {IN
=>"a:1\nb:"}, {OUT
=>"a:1\n"}],
153 ['newline-15', '-s', "-d'\n'", '-f1', {IN
=>"a:1\nb:"}, {OUT
=>"a:1\n"}],
154 ['newline-16', '-s', "-d'\n'", '-f2', {IN
=>"\nb"}, {OUT
=>"b\n"}],
155 ['newline-17', '-s', "-d'\n'", '-f1', {IN
=>"\nb"}, {OUT
=>"\n"}],
156 ['newline-18', "-d'\n'", '-f2', {IN
=>"\nb"}, {OUT
=>"b\n"}],
157 ['newline-19', "-d'\n'", '-f1', {IN
=>"\nb"}, {OUT
=>"\n"}],
158 ['newline-20', '-s', "-d'\n'", '-f1-', {IN
=>"\n"}, {OUT
=>"\n"}],
159 ['newline-21', '-s', "-d'\n'", '-f1-', {IN
=>"\nb"}, {OUT
=>"\nb\n"}],
160 ['newline-22', "-d'\n'", '-f1-', {IN
=>"\nb"}, {OUT
=>"\nb\n"}],
161 ['newline-23', "-d'\n'", '-f1-', '--ou=:', {IN
=>"a\nb\n"}, {OUT
=>"a:b\n"}],
162 ['newline-24', "-d'\n'", '-f1,2', '--ou=:', {IN
=>"a\nb\n"}, {OUT
=>"a:b\n"}],
165 ['zerot-1', "-z", '-c1', {IN
=>"ab\0cd\0"}, {OUT
=>"a\0c\0"}],
166 ['zerot-2', "-z", '-c1', {IN
=>"ab\0cd"}, {OUT
=>"a\0c\0"}],
167 ['zerot-3', '-z -f1-', {IN
=>""}, {OUT
=>""}],
168 ['zerot-4', '-z -d:', '-f1', {IN
=>"a:1\0b:2"}, {OUT
=>"a\0b\0"}],
169 ['zerot-5', '-z -d:', '-f1-', {IN
=>"a1:\0:"}, {OUT
=>"a1:\0:\0"}],
170 ['zerot-6', "-z -d ''", '-f1,2', '--ou=:', {IN
=>"a\0b\0"}, {OUT
=>"a:b\0"}],
173 ['out-delim1', '-c1-3,5-', '--output-d=:', {IN
=>"abcdefg\n"},
175 # A totally overlapped field shouldn't change anything:
176 ['out-delim2', '-c1-3,2,5-', '--output-d=:', {IN
=>"abcdefg\n"},
178 # Partial overlap: index '2' is not at the start of a range.
179 ['out-delim3', '-c1-3,2-4,6', '--output-d=:', {IN
=>"abcdefg\n"},
181 ['out-delim3a', '-c1-3,2-4,6-', '--output-d=:', {IN
=>"abcdefg\n"},
183 # Ensure that the following two commands produce the same output.
184 # Before an off-by-1 fix, the output from the former would not contain a ':'.
185 ['out-delim4', '-c4-,2-3', '--output-d=:',
186 {IN
=>"abcdefg\n"}, {OUT
=>"bc:defg\n"}],
187 ['out-delim5', '-c2-3,4-', '--output-d=:',
188 {IN
=>"abcdefg\n"}, {OUT
=>"bc:defg\n"}],
189 # This test would fail for cut from coreutils-5.0.1 and earlier.
190 ['out-delim6', '-c2,1-3', '--output-d=:', {IN
=>"abc\n"}, {OUT
=>"abc\n"}],
192 ['od-abut', '-b1-2,3-4', '--output-d=:', {IN
=>"abcd\n"}, {OUT
=>"ab:cd\n"}],
193 ['od-overlap', '-b1-2,2', '--output-d=:', {IN
=>"abc\n"}, {OUT
=>"ab\n"}],
194 ['od-overlap2', '-b1-2,2-', '--output-d=:', {IN
=>"abc\n"}, {OUT
=>"abc\n"}],
195 ['od-overlap3', '-b1-3,2-', '--output-d=:', {IN
=>"abcd\n"}, {OUT
=>"abcd\n"}],
196 ['od-overlap4', '-b1-3,2-3', '--output-d=:', {IN
=>"abcd\n"}, {OUT
=>"abc\n"}],
197 ['od-overlap5', '-b1-3,1-4', '--output-d=:',
198 {IN
=>"abcde\n"}, {OUT
=>"abcd\n"}],
200 # None of the following invalid ranges provoked an error up to coreutils-6.9.
201 ['inval1', qw(-f 2-0), {IN
=>''}, {OUT
=>''}, {EXIT
=>1},
202 {ERR
=>"$prog: invalid decreasing range\n$try"}],
203 ['inval2', qw(-f -), {IN
=>''}, {OUT
=>''}, {EXIT
=>1}, {ERR
=>$no_endpoint}],
204 ['inval3', '-f', '4,-', {IN
=>''}, {OUT
=>''}, {EXIT
=>1}, {ERR
=>$no_endpoint}],
205 ['inval4', '-f', '1-2,-', {IN
=>''}, {OUT
=>''}, {EXIT
=>1},
206 {ERR
=>$no_endpoint}],
207 ['inval5', '-f', '1-,-', {IN
=>''}, {OUT
=>''}, {EXIT
=>1}, {ERR
=>$no_endpoint}],
208 ['inval6', '-f', '-1,-', {IN
=>''}, {OUT
=>''}, {EXIT
=>1}, {ERR
=>$no_endpoint}],
209 # This would evoke a segfault from 5.3.0..8.10
210 ['big-unbounded-b', '--output-d=:', '-b1234567890-', {IN
=>''}, {OUT
=>''}],
211 ['big-unbounded-b2a', '--output-d=:', '-b1,9-', {IN
=>'123456789'},
213 ['big-unbounded-b2b', '--output-d=:', '-b1,1234567890-', {IN
=>''}, {OUT
=>''}],
214 ['big-unbounded-c', '--output-d=:', '-c1234567890-', {IN
=>''}, {OUT
=>''}],
215 ['big-unbounded-f', '--output-d=:', '-f1234567890-', {IN
=>''}, {OUT
=>''}],
217 ['overlapping-unbounded-1', '-b3-,2-', {IN
=>"1234\n"}, {OUT
=>"234\n"}],
218 ['overlapping-unbounded-2', '-b2-,3-', {IN
=>"1234\n"}, {OUT
=>"234\n"}],
220 # When printing output delimiters, and with one or more ranges subsumed
221 # by a to-EOL range, cut 8.20 and earlier would print extraneous delimiters.
222 ['EOL-subsumed-1', '--output-d=: -b2-,3,4-4,5',
223 {IN
=>"123456\n"}, {OUT
=>"23456\n"}],
224 ['EOL-subsumed-2', '--output-d=: -b3,4-4,5,2-',
225 {IN
=>"123456\n"}, {OUT
=>"23456\n"}],
226 ['EOL-subsumed-3', '--complement -b3,4-4,5,2-',
227 {IN
=>"123456\n"}, {OUT
=>"1\n"}],
228 ['EOL-subsumed-4', '--output-d=: -b1-2,2-3,3-',
229 {IN
=>"1234\n"}, {OUT
=>"1234\n"}],
232 if ($mb_locale ne 'C')
234 # Duplicate each test vector, appending "-mb" to the test name and
235 # inserting {ENV => "LC_ALL=$mb_locale"} in the copy, so that we
236 # provide coverage for the distro-added multi-byte code paths.
238 foreach my $t (@Tests)
241 my $test_name = shift @new_t;
243 push @new, ["$test_name-mb", @new_t, {ENV
=> "LC_ALL=$mb_locale"}];
249 @Tests = triple_test \
@Tests;
251 my $save_temps = $ENV{DEBUG
};
252 my $verbose = $ENV{VERBOSE
};
254 my $fail = run_tests
($ME, $prog, \
@Tests, $save_temps, $verbose);