~ubuntu-branches/ubuntu/utopic/coreutils/utopic-proposed

« back to all changes in this revision

Viewing changes to tests/misc/numfmt.pl

  • Committer: Colin Watson
  • Date: 2013-10-30 15:48:33 UTC
  • mfrom: (8.3.5 sid)
  • Revision ID: cjwatson@canonical.com-20131030154833-xdt6e1yfffqom1c4
merge from Debian 8.21-1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#!/usr/bin/perl
 
2
# Basic tests for "numfmt".
 
3
 
 
4
# Copyright (C) 2012 Free Software Foundation, Inc.
 
5
 
 
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.
 
10
 
 
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.
 
15
 
 
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/>.
 
18
 
 
19
use strict;
 
20
 
 
21
(my $program_name = $0) =~ s|.*/||;
 
22
my $prog = 'numfmt';
 
23
 
 
24
# TODO: add localization tests with "grouping"
 
25
# Turn off localization of executable's output.
 
26
@ENV{qw(LANGUAGE LANG LC_ALL)} = ('C') x 3;
 
27
 
 
28
my $locale = $ENV{LOCALE_FR_UTF8};
 
29
! defined $locale || $locale eq 'none'
 
30
  and $locale = 'C';
 
31
 
 
32
my @Tests =
 
33
    (
 
34
     ['1', '1234',             {OUT => "1234"}],
 
35
     ['2', '--from=si 1K',     {OUT => "1000"}],
 
36
     ['3', '--from=iec 1K',    {OUT => "1024"}],
 
37
     ['4', '--from=auto 1K',   {OUT => "1000"}],
 
38
     ['5', '--from=auto 1Ki',  {OUT => "1024"}],
 
39
     ['5.1', '--from=iec-i 1Ki',  {OUT => "1024"}],
 
40
 
 
41
     ['6', {IN_PIPE => "1234\n"},            {OUT => "1234"}],
 
42
     ['7', '--from=si', {IN_PIPE => "2K\n"}, {OUT => "2000"}],
 
43
     ['7a', '--invalid=fail', {IN_PIPE => "no_NL"}, {OUT => "no_NL"},
 
44
              {ERR => "$prog: invalid number: 'no_NL'\n"},
 
45
              {EXIT => '2'}],
 
46
 
 
47
     ['8',  '--to=si 2000',                   {OUT => "2.0K"}],
 
48
     ['9',  '--to=si 2001',                   {OUT => "2.1K"}],
 
49
     ['10', '--to=si 1999',                   {OUT => "2.0K"}],
 
50
     ['11', '--to=si --round=down   2001',   {OUT => "2.0K"}],
 
51
     ['12', '--to=si --round=down   1999',   {OUT => "1.9K"}],
 
52
     ['13', '--to=si --round=up 1901',   {OUT => "2.0K"}],
 
53
     ['14', '--to=si --round=down   1901',   {OUT => "1.9K"}],
 
54
     ['15', '--to=si --round=nearest 1901',   {OUT => "1.9K"}],
 
55
     ['16', '--to=si --round=nearest 1945',   {OUT => "1.9K"}],
 
56
     ['17', '--to=si --round=nearest 1955',   {OUT => "2.0K"}],
 
57
 
 
58
     ['18',  '--to=iec 2048',                  {OUT => "2.0K"}],
 
59
     ['19',  '--to=iec 2049',                  {OUT => "2.1K"}],
 
60
     ['20', '--to=iec 2047',                   {OUT => "2.0K"}],
 
61
     ['21', '--to=iec --round=down   2049',   {OUT => "2.0K"}],
 
62
     ['22', '--to=iec --round=down   2047',   {OUT => "1.9K"}],
 
63
     ['23', '--to=iec --round=up 2040',   {OUT => "2.0K"}],
 
64
     ['24', '--to=iec --round=down   2040',   {OUT => "1.9K"}],
 
65
     ['25', '--to=iec --round=nearest 1996',   {OUT => "1.9K"}],
 
66
     ['26', '--to=iec --round=nearest 1997',   {OUT => "2.0K"}],
 
67
     ['27', '--to=iec-i 2048',                  {OUT => "2.0Ki"}],
 
68
 
 
69
     ['neg-1', '-- -1234',                     {OUT => "-1234"}],
 
70
     ['neg-2', '--padding=5 -- -1234',         {OUT => "-1234"}],
 
71
     ['neg-3', '--padding=6 -- -1234',         {OUT => " -1234"}],
 
72
     ['neg-4', '--to=iec -- 9100 -9100',       {OUT => "8.9K\n-8.9K"}],
 
73
     ['neg-5', '-- -0.1',                      {OUT => "-0.1"}],
 
74
     ['neg-6', '-- -0',                        {OUT => "0"}],
 
75
     ['neg-7', '-- -0.-1',
 
76
              {ERR => "$prog: invalid number: '-0.-1'\n"},
 
77
              {EXIT => '2'}],
 
78
 
 
79
     ['float-1', '1.1',                        {OUT => "1.1"}],
 
80
     ['float-2', '1.22',                       {OUT => "1.22"}],
 
81
     ['float-3', '1.22.',
 
82
             {ERR => "$prog: invalid suffix in input: '1.22.'\n"},
 
83
             {EXIT => '2'}],
 
84
 
 
85
     ['unit-1', '--from-unit=512 4',   {OUT => "2048"}],
 
86
     ['unit-2', '--to-unit=512 2048',   {OUT => "4"}],
 
87
     ['unit-3', '--from-unit=512 --from=si 4M',   {OUT => "2048000000"}],
 
88
     ['unit-4', '--from-unit=512 --from=iec --to=iec 4M',   {OUT => "2.0G"}],
 
89
     ['unit-5', '--from-unit=AA --from=iec --to=iec 4M',
 
90
             {ERR => "$prog: invalid unit size: 'AA'\n"},
 
91
             {EXIT => '1'}],
 
92
     ['unit-6', '--from-unit=54W --from=iec --to=iec 4M',
 
93
             {ERR => "$prog: invalid unit size: '54W'\n"},
 
94
             {EXIT => '1'}],
 
95
     # Not fully documented.. "--{from,to}-unit" can accept IEC suffixes
 
96
     ['unit-7', '--from-unit=2K --to=iec 30', {OUT=>"60K"}],
 
97
     ['unit-8', '--from-unit=1234567890123456789012345 --to=iec 30',
 
98
             {ERR => "$prog: invalid unit size: '1234567890123456789012345'\n"},
 
99
             {EXIT => '1'}],
 
100
     ['unit-9', '--from-unit=0 1',
 
101
             {ERR => "$prog: invalid unit size: '0'\n"},
 
102
             {EXIT => '1'}],
 
103
     ['unit-10', '--to-unit=0 1',
 
104
             {ERR => "$prog: invalid unit size: '0'\n"},
 
105
             {EXIT => '1'}],
 
106
 
 
107
     # Test Suffix logic
 
108
     ['suf-1', '4000',    {OUT=>'4000'}],
 
109
     ['suf-2', '4Q',
 
110
             {ERR => "$prog: invalid suffix in input: '4Q'\n"},
 
111
             {EXIT => '2'}],
 
112
     ['suf-2.1', '4M',
 
113
             {ERR => "$prog: rejecting suffix " .
 
114
             "in input: '4M' (consider using --from)\n"},
 
115
             {EXIT => '2'}],
 
116
     ['suf-3', '--from=si 4M',  {OUT=>'4000000'}],
 
117
     ['suf-4', '--from=si 4Q',
 
118
             {ERR => "$prog: invalid suffix in input: '4Q'\n"},
 
119
             {EXIT => '2'}],
 
120
     ['suf-5', '--from=si 4MQ',
 
121
             {ERR => "$prog: invalid suffix in input '4MQ': 'Q'\n"},
 
122
             {EXIT => '2'}],
 
123
 
 
124
     ['suf-6', '--from=iec 4M',  {OUT=>'4194304'}],
 
125
     ['suf-7', '--from=auto 4M',  {OUT=>'4000000'}],
 
126
     ['suf-8', '--from=auto 4Mi',  {OUT=>'4194304'}],
 
127
     ['suf-9', '--from=auto 4MiQ',
 
128
             {ERR => "$prog: invalid suffix in input '4MiQ': 'Q'\n"},
 
129
             {EXIT => '2'}],
 
130
     ['suf-10', '--from=auto 4QiQ',
 
131
             {ERR => "$prog: invalid suffix in input: '4QiQ'\n"},
 
132
             {EXIT => '2'}],
 
133
 
 
134
     # characters after a white space are OK - printed as-is
 
135
     ['suf-11', '"4 M"',     {OUT=>'4 M'}],
 
136
 
 
137
     # Custom suffix
 
138
     ['suf-12', '--suffix=Foo 70Foo',               {OUT=>'70Foo'}],
 
139
     ['suf-13', '--suffix=Foo 70',                  {OUT=>'70Foo'}],
 
140
     ['suf-14', '--suffix=Foo --from=si 70K',       {OUT=>'70000Foo'}],
 
141
     ['suf-15', '--suffix=Foo --from=si 70KFoo',    {OUT=>'70000Foo'}],
 
142
     ['suf-16', '--suffix=Foo --to=si   7000Foo',    {OUT=>'7.0KFoo'}],
 
143
     ['suf-17', '--suffix=Foo --to=si   7000Bar',
 
144
              {ERR => "$prog: invalid suffix in input: '7000Bar'\n"},
 
145
              {EXIT => '2'}],
 
146
     ['suf-18', '--suffix=Foo --to=si   7000FooF',
 
147
              {ERR => "$prog: invalid suffix in input: '7000FooF'\n"},
 
148
              {EXIT => '2'}],
 
149
     # space(s) between number and suffix.  Note only field 1 is used
 
150
     # by default so specify the NUL delimiter to consider the whole "line".
 
151
     ['suf-19', "-d '' --from=si '4.0 K'",         {OUT => "4000"}],
 
152
 
 
153
     ## GROUPING
 
154
 
 
155
     # "C" locale - no grouping (locale-specific tests, below)
 
156
     ['grp-1', '--from=si --grouping 7M',   {OUT=>'7000000'}],
 
157
     ['grp-2', '--from=si --to=si --grouping 7M',
 
158
              {ERR => "$prog: grouping cannot be combined with --to\n"},
 
159
              {EXIT => '1'}],
 
160
 
 
161
 
 
162
     ## Padding
 
163
     ['pad-1', '--padding=10 5',             {OUT=>'         5'}],
 
164
     ['pad-2', '--padding=-10 5',            {OUT=>'5         '}],
 
165
     ['pad-3', '--padding=A 5',
 
166
             {ERR => "$prog: invalid padding value 'A'\n"},
 
167
             {EXIT => '1'}],
 
168
     ['pad-3.1', '--padding=0 5',
 
169
             {ERR => "$prog: invalid padding value '0'\n"},
 
170
             {EXIT => '1'}],
 
171
     ['pad-4', '--padding=10 --to=si 50000',             {OUT=>'       50K'}],
 
172
     ['pad-5', '--padding=-10 --to=si 50000',            {OUT=>'50K       '}],
 
173
 
 
174
     # padding too narrow
 
175
     ['pad-6', '--padding=2 --to=si 1000', {OUT=>'1.0K'}],
 
176
 
 
177
 
 
178
     # Padding + suffix
 
179
     ['pad-7', '--padding=10 --suffix=foo --to=si 50000',
 
180
             {OUT=>'    50Kfoo'}],
 
181
     ['pad-8', '--padding=-10 --suffix=foo --to=si 50000',
 
182
             {OUT=>'50Kfoo    '}],
 
183
 
 
184
 
 
185
     # Delimiters
 
186
     ['delim-1', '--delimiter=: --from=auto 40M:',   {OUT=>'40000000:'}],
 
187
     ['delim-2', '--delimiter="" --from=auto "40 M"',{OUT=>'40000000'}],
 
188
     ['delim-3', '--delimiter=" " --from=auto "40M Foo"',{OUT=>'40000000 Foo'}],
 
189
     ['delim-4', '--delimiter=: --from=auto 40M:60M',  {OUT=>'40000000:60M'}],
 
190
     ['delim-5', '-d: --field=2 --from=auto :40M:60M',  {OUT=>':40000000:60M'}],
 
191
     ['delim-6', '--delimiter=: --field 3 --from=auto 40M:60M',
 
192
             {EXIT=>2},
 
193
             {ERR=>"$prog: input line is too short, no numbers found " .
 
194
                   "to convert in field 3\n"}],
 
195
 
 
196
     #Fields
 
197
     ['field-1', '--field A',
 
198
             {ERR => "$prog: invalid field value 'A'\n"},
 
199
             {EXIT => '1'}],
 
200
     ['field-1.1', '--field -5',
 
201
             {ERR => "$prog: invalid field value '-5'\n"},
 
202
             {EXIT => '1'}],
 
203
     ['field-2', '--field 2 --from=auto "Hello 40M World 90G"',
 
204
             {OUT=>'Hello 40000000 World 90G'}],
 
205
     ['field-3', '--field 3 --from=auto "Hello 40M World 90G"',
 
206
             {ERR=>"$prog: invalid number: 'World'\n"},
 
207
             {EXIT => 2},],
 
208
     # Last field - no text after number
 
209
     ['field-4', '--field 4 --from=auto "Hello 40M World 90G"',
 
210
             {OUT=>"Hello 40M World 90000000000"}],
 
211
     # Last field - a delimiter after the number
 
212
     ['field-5', '--field 4 --from=auto "Hello 40M World 90G "',
 
213
             {OUT=>"Hello 40M World 90000000000 "}],
 
214
 
 
215
     # Mix Fields + Delimiters
 
216
     ['field-6', '--delimiter=: --field 2 --from=auto "Hello:40M:World:90G"',
 
217
             {OUT=>"Hello:40000000:World:90G"}],
 
218
 
 
219
     # not enough fields
 
220
     ['field-8', '--field 3 --to=si "Hello World"',
 
221
             {EXIT=>2},
 
222
             {ERR=>"$prog: input line is too short, no numbers found " .
 
223
                   "to convert in field 3\n"}],
 
224
 
 
225
     # Auto-consume white-space, setup auto-padding
 
226
     ['whitespace-1', '--to=si --field 2 "A    500 B"', {OUT=>"A    500 B"}],
 
227
     ['whitespace-2', '--to=si --field 2 "A   5000 B"', {OUT=>"A   5.0K B"}],
 
228
     ['whitespace-3', '--to=si "  500"', {OUT=>"  500"}],
 
229
     ['whitespace-4', '--to=si " 6500"', {OUT=>" 6.5K"}],
 
230
     # NOTE: auto-padding is not enabled if the value is on the first
 
231
     #       field and there's no white-space before it.
 
232
     ['whitespace-5', '--to=si "6000000"', {OUT=>"6.0M"}],
 
233
     # but if there is whitespace, assume auto-padding is desired.
 
234
     ['whitespace-6', '--to=si " 6000000"', {OUT=>"    6.0M"}],
 
235
 
 
236
     # auto-padding - lines have same padding-width
 
237
     #  (padding_buffer will be alloc'd just once)
 
238
     ['whitespace-7', '--to=si --field 2',
 
239
             {IN_PIPE=>"rootfs    100000\n" .
 
240
                       "udevxx   2000000\n"},
 
241
             {OUT    =>"rootfs      100K\n" .
 
242
                       "udevxx      2.0M"}],
 
243
     # auto-padding - second line requires a
 
244
     # larger padding (padding-buffer needs to be realloc'd)
 
245
     ['whitespace-8', '--to=si --field 2',
 
246
             {IN_PIPE=>"rootfs    100000\n" .
 
247
                       "udev         20000000\n"},
 
248
             {OUT    =>"rootfs      100K\n" .
 
249
                       "udev              20M"}],
 
250
 
 
251
 
 
252
     # Corner-cases:
 
253
     # weird mix of identical suffix,delimiters
 
254
     # The priority is:
 
255
     #   1. delimiters (and fields) are parsed (in process_line()
 
256
     #   2. optional custom suffix is removed (in process_suffixed_number())
 
257
     #   3. Remaining suffixes must be valid SI/IEC (in human_xstrtol())
 
258
 
 
259
     # custom suffix comes BEFORE SI/IEC suffix,
 
260
     #   so these are 40 of "M", not 40,000,000.
 
261
     ['mix-1', '--suffix=M --from=si 40M',     {OUT=>"40M"}],
 
262
 
 
263
     # These are fourty-million Ms .
 
264
     ['mix-2', '--suffix=M --from=si 40MM',     {OUT=>"40000000M"}],
 
265
 
 
266
     ['mix-3', '--suffix=M --from=auto 40MM',     {OUT=>"40000000M"}],
 
267
     ['mix-4', '--suffix=M --from=auto 40MiM',     {OUT=>"41943040M"}],
 
268
     ['mix-5', '--suffix=M --to=si --from=si 4MM',     {OUT=>"4.0MM"}],
 
269
 
 
270
     # This might be confusing to the user, but it's legit:
 
271
     # The M in the output is the custom suffix, not Mega.
 
272
     ['mix-6', '--suffix=M 40',     {OUT=>"40M"}],
 
273
     ['mix-7', '--suffix=M 4000000',     {OUT=>"4000000M"}],
 
274
     ['mix-8', '--suffix=M --to=si 4000000',     {OUT=>"4.0MM"}],
 
275
 
 
276
     # The output 'M' is the custom suffix.
 
277
     ['mix-10', '--delimiter=M --suffix=M 40',     {OUT=>"40M"}],
 
278
 
 
279
     # The INPUT 'M' is a delimiter (delimiters are top priority)
 
280
     # The output contains one M for custom suffix, and one 'M' delimiter.
 
281
     ['mix-11', '--delimiter=M --suffix=M 40M',     {OUT=>"40MM"}],
 
282
 
 
283
     # Same as above, the "M" is NOT treated as a mega SI prefix,
 
284
     ['mix-12', '--delimiter=M --from=si --suffix=M 40M',     {OUT=>"40MM"}],
 
285
 
 
286
     # The 'M' is treated as a delimiter, and so the input value is '4000'
 
287
     ['mix-13', '--delimiter=M --to=si --from=auto 4000M5000M9000',
 
288
             {OUT=>"4.0KM5000M9000"}],
 
289
     # 'M' is the delimiter, so the second input field is '5000'
 
290
     ['mix-14', '--delimiter=M --field 2 --from=auto --to=si 4000M5000M9000',
 
291
             {OUT=>"4000M5.0KM9000"}],
 
292
 
 
293
 
 
294
 
 
295
     ## Header testing
 
296
 
 
297
     # header - silently ignored with command line parameters
 
298
     ['header-1', '--header --to=iec 4096', {OUT=>"4.0K"}],
 
299
 
 
300
     # header warning with --debug
 
301
     ['header-2', '--debug --header --to=iec 4096', {OUT=>"4.0K"},
 
302
             {ERR=>"$prog: --header ignored with command-line input\n"}],
 
303
 
 
304
     ['header-3', '--header=A',
 
305
             {ERR=>"$prog: invalid header value 'A'\n"},
 
306
             {EXIT => 1},],
 
307
     ['header-4', '--header=0',
 
308
             {ERR=>"$prog: invalid header value '0'\n"},
 
309
             {EXIT => 1},],
 
310
     ['header-5', '--header=-6',
 
311
             {ERR=>"$prog: invalid header value '-6'\n"},
 
312
             {EXIT => 1},],
 
313
     ['header-6', '--debug --header --to=iec',
 
314
             {IN_PIPE=>"size\n5000\n90000\n"},
 
315
             {OUT=>"size\n4.9K\n88K"}],
 
316
     ['header-7', '--debug --header=3 --to=iec',
 
317
             {IN_PIPE=>"hello\nworld\nsize\n5000\n90000\n"},
 
318
             {OUT=>"hello\nworld\nsize\n4.9K\n88K"}],
 
319
     # header, but no actual content
 
320
     ['header-8', '--header=2 --to=iec',
 
321
             {IN_PIPE=>"hello\nworld\n"},
 
322
             {OUT=>"hello\nworld"}],
 
323
     # not enough header lines
 
324
     ['header-9', '--header=3 --to=iec',
 
325
             {IN_PIPE=>"hello\nworld\n"},
 
326
             {OUT=>"hello\nworld"}],
 
327
 
 
328
 
 
329
     ## human_strtod testing
 
330
 
 
331
     # NO_DIGITS_FOUND
 
332
     ['strtod-1', '--from=si "foo"',
 
333
             {ERR=>"$prog: invalid number: 'foo'\n"},
 
334
             {EXIT=> 2}],
 
335
     ['strtod-2', '--from=si ""',
 
336
             {ERR=>"$prog: invalid number: ''\n"},
 
337
             {EXIT=> 2}],
 
338
 
 
339
     # INTEGRAL_OVERFLOW
 
340
     ['strtod-3', '--from=si "1234567890123456789012345678901234567890'.
 
341
                  '1234567890123456789012345678901234567890"',
 
342
             {ERR=>"$prog: value too large to be converted: '" .
 
343
                     "1234567890123456789012345678901234567890" .
 
344
                     "1234567890123456789012345678901234567890'\n",
 
345
                     },
 
346
             {EXIT=> 2}],
 
347
 
 
348
     # FRACTION_NO_DIGITS_FOUND
 
349
     ['strtod-5', '--from=si 12.',
 
350
             {ERR=>"$prog: invalid number: '12.'\n"},
 
351
             {EXIT=>2}],
 
352
     ['strtod-6', '--from=si 12.K',
 
353
             {ERR=>"$prog: invalid number: '12.K'\n"},
 
354
             {EXIT=>2}],
 
355
 
 
356
     # whitespace is not allowed after decimal-point
 
357
     ['strtod-6.1', '--from=si --delimiter=, "12.  2"',
 
358
             {ERR=>"$prog: invalid number: '12.  2'\n"},
 
359
             {EXIT=>2}],
 
360
 
 
361
     # FRACTION_OVERFLOW
 
362
     ['strtod-7', '--from=si "12.1234567890123456789012345678901234567890'.
 
363
                  '1234567890123456789012345678901234567890"',
 
364
             {ERR=>"$prog: value too large to be converted: '" .
 
365
                     "12.1234567890123456789012345678901234567890" .
 
366
                     "1234567890123456789012345678901234567890'\n",
 
367
                     },
 
368
             {EXIT=> 2}],
 
369
 
 
370
     # INVALID_SUFFIX
 
371
     ['strtod-9', '--from=si 12.2Q',
 
372
             {ERR=>"$prog: invalid suffix in input: '12.2Q'\n"},
 
373
             {EXIT=>2}],
 
374
 
 
375
     # VALID_BUT_FORBIDDEN_SUFFIX
 
376
     ['strtod-10', '12M',
 
377
             {ERR => "$prog: rejecting suffix " .
 
378
                     "in input: '12M' (consider using --from)\n"},
 
379
             {EXIT=>2}],
 
380
 
 
381
     # MISSING_I_SUFFIX
 
382
     ['strtod-11', '--from=iec-i 12M',
 
383
             {ERR => "$prog: missing 'i' suffix in input: " .
 
384
                     "'12M' (e.g Ki/Mi/Gi)\n"},
 
385
             {EXIT=>2}],
 
386
 
 
387
     #
 
388
     # Test double_to_human()
 
389
     #
 
390
 
 
391
     # 1K and smaller
 
392
     ['dbl-to-human-1','--to=si 800',  {OUT=>"800"}],
 
393
     ['dbl-to-human-2','--to=si 0',  {OUT=>"0"}],
 
394
     ['dbl-to-human-2.1','--to=si 999',  {OUT=>"999"}],
 
395
     ['dbl-to-human-2.2','--to=si 1000',  {OUT=>"1.0K"}],
 
396
     #NOTE: the following are consistent with "ls -lh" output
 
397
     ['dbl-to-human-2.3','--to=iec 999',  {OUT=>"999"}],
 
398
     ['dbl-to-human-2.4','--to=iec 1023',  {OUT=>"1023"}],
 
399
     ['dbl-to-human-2.5','--to=iec 1024',  {OUT=>"1.0K"}],
 
400
     ['dbl-to-human-2.6','--to=iec 1025',  {OUT=>"1.1K"}],
 
401
     ['dbl-to-human-2.7','--to=iec 0',  {OUT=>"0"}],
 
402
     # no "i" suffix if output has no suffix
 
403
     ['dbl-to-human-2.8','--to=iec-i 0',  {OUT=>"0"}],
 
404
 
 
405
     # values resulting in "N.Nx" output
 
406
     ['dbl-to-human-3','--to=si 8000', {OUT=>"8.0K"}],
 
407
     ['dbl-to-human-3.1','--to=si 8001', {OUT=>"8.1K"}],
 
408
     ['dbl-to-human-4','--to=si --round=down 8001', {OUT=>"8.0K"}],
 
409
 
 
410
     ['dbl-to-human-5','--to=si --round=down 3500', {OUT=>"3.5K"}],
 
411
     ['dbl-to-human-6','--to=si --round=nearest 3500', {OUT=>"3.5K"}],
 
412
     ['dbl-to-human-7','--to=si --round=up 3500', {OUT=>"3.5K"}],
 
413
 
 
414
     ['dbl-to-human-8','--to=si --round=down    3501', {OUT=>"3.5K"}],
 
415
     ['dbl-to-human-9','--to=si --round=nearest  3501', {OUT=>"3.5K"}],
 
416
     ['dbl-to-human-10','--to=si --round=up 3501', {OUT=>"3.6K"}],
 
417
 
 
418
     ['dbl-to-human-11','--to=si --round=nearest  3550', {OUT=>"3.6K"}],
 
419
     ['dbl-to-human-12','--to=si --from=si 999.89K', {OUT=>"1.0M"}],
 
420
     ['dbl-to-human-13','--to=si --from=si 9.9K', {OUT=>"9.9K"}],
 
421
     ['dbl-to-human-14','--to=si 9900', {OUT=>"9.9K"}],
 
422
     ['dbl-to-human-15','--to=iec --from=si 3.3K', {OUT=>"3.3K"}],
 
423
     ['dbl-to-human-16','--to=iec --round=down --from=si 3.3K', {OUT=>"3.2K"}],
 
424
 
 
425
     # values resulting in 'NNx' output
 
426
     ['dbl-to-human-17','--to=si 9999', {OUT=>"10K"}],
 
427
     ['dbl-to-human-18','--to=si --round=down 35000', {OUT=>"35K"}],
 
428
     ['dbl-to-human-19','--to=iec 35000', {OUT=>"35K"}],
 
429
     ['dbl-to-human-20','--to=iec --round=down 35000', {OUT=>"34K"}],
 
430
     ['dbl-to-human-21','--to=iec 35000000', {OUT=>"34M"}],
 
431
     ['dbl-to-human-22','--to=iec --round=down 35000000', {OUT=>"33M"}],
 
432
     ['dbl-to-human-23','--to=si  35000001', {OUT=>"36M"}],
 
433
     ['dbl-to-human-24','--to=si --from=si  9.99M', {OUT=>"10M"}],
 
434
     ['dbl-to-human-25','--to=si --from=iec 9.99M', {OUT=>"11M"}],
 
435
     ['dbl-to-human-25.1','--to=iec 99999', {OUT=>"98K"}],
 
436
 
 
437
     # values resulting in 'NNNx' output
 
438
     ['dbl-to-human-26','--to=si 999000000000', {OUT=>"999G"}],
 
439
     ['dbl-to-human-27','--to=iec 999000000000', {OUT=>"931G"}],
 
440
     ['dbl-to-human-28','--to=si 123600000000000', {OUT=>"124T"}],
 
441
     ['dbl-to-human-29','--to=si 998123', {OUT=>"999K"}],
 
442
     ['dbl-to-human-30','--to=si --round=nearest 998123', {OUT=>"998K"}],
 
443
     ['dbl-to-human-31','--to=si 99999', {OUT=>"100K"}],
 
444
     ['dbl-to-human-32','--to=iec 102399', {OUT=>"100K"}],
 
445
     ['dbl-to-human-33','--to=iec-i 102399', {OUT=>"100Ki"}],
 
446
 
 
447
 
 
448
     # Default --round=from-zero
 
449
     ['round-1','--to-unit=1024 -- 6000 -6000',
 
450
             {OUT=>"6\n-6"}],
 
451
     ['round-2','--to-unit=1024 -- 6000.0 -6000.0',
 
452
             {OUT=>"5.9\n-5.9"}],
 
453
     ['round-3','--to-unit=1024 -- 6000.00 -6000.00',
 
454
             {OUT=>"5.86\n-5.86"}],
 
455
     ['round-4','--to-unit=1024 -- 6000.000 -6000.000',
 
456
             {OUT=>"5.860\n-5.860"}],
 
457
     ['round-5','--to-unit=1024 -- 6000.0000 -6000.0000',
 
458
             {OUT=>"5.8594\n-5.8594"}],
 
459
     # --round=up
 
460
     ['round-1-up','--round=up --to-unit=1024 -- 6000 -6000',
 
461
             {OUT=>"6\n-5"}],
 
462
     ['round-2-up','--round=up --to-unit=1024 -- 6000.0 -6000.0',
 
463
             {OUT=>"5.9\n-5.8"}],
 
464
     ['round-3-up','--round=up --to-unit=1024 -- 6000.00 -6000.00',
 
465
             {OUT=>"5.86\n-5.85"}],
 
466
     ['round-4-up','--round=up --to-unit=1024 -- 6000.000 -6000.000',
 
467
             {OUT=>"5.860\n-5.859"}],
 
468
     ['round-5-up','--round=up --to-unit=1024 -- 6000.0000 -6000.0000',
 
469
             {OUT=>"5.8594\n-5.8593"}],
 
470
     # --round=down
 
471
     ['round-1-down','--round=down --to-unit=1024 -- 6000 -6000',
 
472
             {OUT=>"5\n-6"}],
 
473
     ['round-2-down','--round=down --to-unit=1024 -- 6000.0 -6000.0',
 
474
             {OUT=>"5.8\n-5.9"}],
 
475
     ['round-3-down','--round=down --to-unit=1024 -- 6000.00 -6000.00',
 
476
             {OUT=>"5.85\n-5.86"}],
 
477
     ['round-4-down','--round=down --to-unit=1024 -- 6000.000 -6000.000',
 
478
             {OUT=>"5.859\n-5.860"}],
 
479
     ['round-5-down','--round=down --to-unit=1024 -- 6000.0000 -6000.0000',
 
480
             {OUT=>"5.8593\n-5.8594"}],
 
481
     # --round=towards-zero
 
482
     ['round-1-to-zero','--ro=towards-zero --to-u=1024 -- 6000 -6000',
 
483
             {OUT=>"5\n-5"}],
 
484
     ['round-2-to-zero','--ro=towards-zero --to-u=1024 -- 6000.0 -6000.0',
 
485
             {OUT=>"5.8\n-5.8"}],
 
486
     ['round-3-to-zero','--ro=towards-zero --to-u=1024 -- 6000.00 -6000.00',
 
487
             {OUT=>"5.85\n-5.85"}],
 
488
     ['round-4-to-zero','--ro=towards-zero --to-u=1024 -- 6000.000 -6000.000',
 
489
             {OUT=>"5.859\n-5.859"}],
 
490
     ['round-5-to-zero','--ro=towards-zero --to-u=1024 -- 6000.0000 -6000.0000',
 
491
             {OUT=>"5.8593\n-5.8593"}],
 
492
     # --round=nearest
 
493
     ['round-1-near','--ro=nearest --to-u=1024 -- 6000 -6000',
 
494
             {OUT=>"6\n-6"}],
 
495
     ['round-2-near','--ro=nearest --to-u=1024 -- 6000.0 -6000.0',
 
496
             {OUT=>"5.9\n-5.9"}],
 
497
     ['round-3-near','--ro=nearest --to-u=1024 -- 6000.00 -6000.00',
 
498
             {OUT=>"5.86\n-5.86"}],
 
499
     ['round-4-near','--ro=nearest --to-u=1024 -- 6000.000 -6000.000',
 
500
             {OUT=>"5.859\n-5.859"}],
 
501
     ['round-5-near','--ro=nearest --to-u=1024 -- 6000.0000 -6000.0000',
 
502
             {OUT=>"5.8594\n-5.8594"}],
 
503
 
 
504
 
 
505
     # Large Values
 
506
     ['large-1','1000000000000000', {OUT=>"1000000000000000"}],
 
507
     # 18 digits is OK
 
508
     ['large-2','1000000000000000000', {OUT=>"1000000000000000000"}],
 
509
     # 19 digits is too much (without output scaling)
 
510
     ['large-3','10000000000000000000',
 
511
             {ERR => "$prog: value too large to be printed: '1e+19' " .
 
512
                     "(consider using --to)\n"},
 
513
             {EXIT=>2}],
 
514
 
 
515
     # Test input:
 
516
     # Up to 27 digits is OK.
 
517
     ['large-3.1', '--to=si                           1', {OUT=>   "1"}],
 
518
     ['large-3.2', '--to=si                          10', {OUT=>  "10"}],
 
519
     ['large-3.3', '--to=si                         100', {OUT=> "100"}],
 
520
     ['large-3.4', '--to=si                        1000', {OUT=>"1.0K"}],
 
521
     ['large-3.5', '--to=si                       10000', {OUT=> "10K"}],
 
522
     ['large-3.6', '--to=si                      100000', {OUT=>"100K"}],
 
523
     ['large-3.7', '--to=si                     1000000', {OUT=>"1.0M"}],
 
524
     ['large-3.8', '--to=si                    10000000', {OUT=> "10M"}],
 
525
     ['large-3.9', '--to=si                   100000000', {OUT=>"100M"}],
 
526
     ['large-3.10','--to=si                  1000000000', {OUT=>"1.0G"}],
 
527
     ['large-3.11','--to=si                 10000000000', {OUT=> "10G"}],
 
528
     ['large-3.12','--to=si                100000000000', {OUT=>"100G"}],
 
529
     ['large-3.13','--to=si               1000000000000', {OUT=>"1.0T"}],
 
530
     ['large-3.14','--to=si              10000000000000', {OUT=> "10T"}],
 
531
     ['large-3.15','--to=si             100000000000000', {OUT=>"100T"}],
 
532
     ['large-3.16','--to=si            1000000000000000', {OUT=>"1.0P"}],
 
533
     ['large-3.17','--to=si           10000000000000000', {OUT=> "10P"}],
 
534
     ['large-3.18','--to=si          100000000000000000', {OUT=>"100P"}],
 
535
     ['large-3.19','--to=si         1000000000000000000', {OUT=>"1.0E"}],
 
536
     ['large-3.20','--to=si        10000000000000000000', {OUT=> "10E"}],
 
537
     ['large-3.21','--to=si       210000000000000000000', {OUT=>"210E"}],
 
538
     ['large-3.22','--to=si      3210000000000000000000', {OUT=>"3.3Z"}],
 
539
     ['large-3.23','--to=si     43210000000000000000000', {OUT=> "44Z"}],
 
540
     ['large-3.24','--to=si    543210000000000000000000', {OUT=>"544Z"}],
 
541
     ['large-3.25','--to=si   6543210000000000000000000', {OUT=>"6.6Y"}],
 
542
     ['large-3.26','--to=si  76543210000000000000000000', {OUT=> "77Y"}],
 
543
     ['large-3.27','--to=si 876543210000000000000000000', {OUT=>"877Y"}],
 
544
 
 
545
     # More than 27 digits is not OK
 
546
     ['large-3.28','--to=si 9876543210000000000000000000',
 
547
             {ERR => "$prog: value too large to be converted: " .
 
548
                     "'9876543210000000000000000000'\n"},
 
549
             {EXIT => 2}],
 
550
 
 
551
     # Test Output
 
552
     ['large-4.1', '--from=si  9.7M',               {OUT=>"9700000"}],
 
553
     ['large-4.2', '--from=si  10M',              {OUT =>"10000000"}],
 
554
     ['large-4.3', '--from=si  200M',            {OUT =>"200000000"}],
 
555
     ['large-4.4', '--from=si  3G',             {OUT =>"3000000000"}],
 
556
     ['large-4.5', '--from=si  40G',           {OUT =>"40000000000"}],
 
557
     ['large-4.6', '--from=si  500G',         {OUT =>"500000000000"}],
 
558
     ['large-4.7', '--from=si  6T',          {OUT =>"6000000000000"}],
 
559
     ['large-4.8', '--from=si  70T',        {OUT =>"70000000000000"}],
 
560
     ['large-4.9', '--from=si  800T',      {OUT =>"800000000000000"}],
 
561
     ['large-4.10','--from=si  9P',       {OUT =>"9000000000000000"}],
 
562
     ['large-4.11','--from=si  10P',     {OUT =>"10000000000000000"}],
 
563
     ['large-4.12','--from=si  200P',   {OUT =>"200000000000000000"}],
 
564
     ['large-4.13','--from=si  3E',    {OUT =>"3000000000000000000"}],
 
565
 
 
566
     # More than 18 digits of output without scaling - no good.
 
567
     ['large-4.14','--from=si  40E',
 
568
             {ERR => "$prog: value too large to be printed: '4e+19' " .
 
569
                     "(consider using --to)\n"},
 
570
             {EXIT => 2}],
 
571
     ['large-4.15','--from=si  500E',
 
572
             {ERR => "$prog: value too large to be printed: '5e+20' " .
 
573
                     "(consider using --to)\n"},
 
574
             {EXIT => 2}],
 
575
     ['large-4.16','--from=si  6Z',
 
576
             {ERR => "$prog: value too large to be printed: '6e+21' " .
 
577
                     "(consider using --to)\n"},
 
578
             {EXIT => 2}],
 
579
     ['large-4.17','--from=si  70Z',
 
580
             {ERR => "$prog: value too large to be printed: '7e+22' " .
 
581
                     "(consider using --to)\n"},
 
582
             {EXIT => 2}],
 
583
     ['large-4.18','--from=si  800Z',
 
584
             {ERR => "$prog: value too large to be printed: '8e+23' " .
 
585
                     "(consider using --to)\n"},
 
586
             {EXIT => 2}],
 
587
     ['large-4.19','--from=si  9Y',
 
588
             {ERR => "$prog: value too large to be printed: '9e+24' " .
 
589
                     "(consider using --to)\n"},
 
590
             {EXIT => 2}],
 
591
     ['large-4.20','--from=si  10Y',
 
592
             {ERR => "$prog: value too large to be printed: '1e+25' " .
 
593
                     "(consider using --to)\n"},
 
594
             {EXIT => 2}],
 
595
     ['large-4.21','--from=si  200Y',
 
596
             {ERR => "$prog: value too large to be printed: '2e+26' " .
 
597
                     "(consider using --to)\n"},
 
598
             {EXIT => 2}],
 
599
 
 
600
     ['large-5.1','--to=si 1000000000000000000', {OUT=>"1.0E"}],
 
601
     ['large-5','--from=si --to=si 2E', {OUT=>"2.0E"}],
 
602
     ['large-6','--from=si --to=si 3.4Z', {OUT=>"3.4Z"}],
 
603
     ['large-7','--from=si --to=si 80Y', {OUT=>"80Y"}],
 
604
     ['large-8','--from=si --to=si 9000Z', {OUT=>"9.0Y"}],
 
605
 
 
606
     ['large-10','--from=si --to=si 999Y', {OUT=>"999Y"}],
 
607
     ['large-11','--from=si --to=iec 999Y', {OUT=>"827Y"}],
 
608
     ['large-12','--from=si --round=down --to=iec 999Y', {OUT=>"826Y"}],
 
609
 
 
610
     # units can also affect the output
 
611
     ['large-13','--from=si --from-unit=1000000 9P',
 
612
             {ERR => "$prog: value too large to be printed: '9e+21' " .
 
613
                     "(consider using --to)\n"},
 
614
             {EXIT => 2}],
 
615
     ['large-13.1','--from=si --from-unit=1000000 --to=si 9P', {OUT=>"9.0Z"}],
 
616
 
 
617
     # Numbers>999Y are never acceptable, regardless of scaling
 
618
     ['large-14','--from=si --to=si 999Y', {OUT=>"999Y"}],
 
619
     ['large-14.1','--from=si --to=si 1000Y',
 
620
             {ERR => "$prog: value too large to be printed: '1e+27' " .
 
621
                     "(cannot handle values > 999Y)\n"},
 
622
             {EXIT => 2}],
 
623
     ['large-14.2','--from=si --to=si --from-unit=10000 1Y',
 
624
             {ERR => "$prog: value too large to be printed: '1e+28' " .
 
625
                     "(cannot handle values > 999Y)\n"},
 
626
             {EXIT => 2}],
 
627
 
 
628
     # debug warnings
 
629
     ['debug-1', '--debug 4096', {OUT=>"4096"},
 
630
             {ERR=>"$prog: no conversion option specified\n"}],
 
631
     # '--padding' is a valid conversion option - no warning should be printed
 
632
     ['debug-1.1', '--debug --padding 10 4096', {OUT=>"      4096"}],
 
633
     ['debug-2', '--debug --grouping --from=si 4.0K', {OUT=>"4000"},
 
634
             {ERR=>"$prog: grouping has no effect in this locale\n"}],
 
635
     ['debug-4', '--to=si --debug 12345678901234567890',
 
636
             {OUT=>"13E"},
 
637
             {ERR=>"$prog: large input value '12345678901234567890':" .
 
638
                   " possible precision loss\n"}],
 
639
     ['debug-5', '--to=si --from=si --debug 1.12345678901234567890Y',
 
640
             {OUT=>"1.2Y"},
 
641
             {ERR=>"$prog: large input value '1.12345678901234567890Y':" .
 
642
                   " possible precision loss\n"}],
 
643
 
 
644
     # dev-debug messages - the actual messages don't matter
 
645
     # just ensure the program works, and for code coverage testing.
 
646
     ['devdebug-1', '---debug --from=si 4.9K', {OUT=>"4900"},
 
647
             {ERR=>""},
 
648
             {ERR_SUBST=>"s/.*//msg"}],
 
649
     ['devdebug-2', '---debug 4900', {OUT=>"4900"},
 
650
             {ERR=>""},
 
651
             {ERR_SUBST=>"s/.*//msg"}],
 
652
     ['devdebug-3', '---debug --from=auto 4Mi', {OUT=>"4194304"},
 
653
             {ERR=>""},
 
654
             {ERR_SUBST=>"s/.*//msg"}],
 
655
     ['devdebug-4', '---debug --to=si 4000000', {OUT=>"4.0M"},
 
656
             {ERR=>""},
 
657
             {ERR_SUBST=>"s/.*//msg"}],
 
658
     ['devdebug-5', '---debug --to=si --padding=5 4000000', {OUT=>" 4.0M"},
 
659
             {ERR=>""},
 
660
             {ERR_SUBST=>"s/.*//msg"}],
 
661
     ['devdebug-6', '---debug --suffix=Foo 1234Foo', {OUT=>"1234Foo"},
 
662
             {ERR=>""},
 
663
             {ERR_SUBST=>"s/.*//msg"}],
 
664
     ['devdebug-7', '---debug --suffix=Foo 1234', {OUT=>"1234Foo"},
 
665
             {ERR=>""},
 
666
             {ERR_SUBST=>"s/.*//msg"}],
 
667
     ['devdebug-9', '---debug --grouping 10000', {OUT=>"10000"},
 
668
             {ERR=>""},
 
669
             {ERR_SUBST=>"s/.*//msg"}],
 
670
     ['devdebug-10', '---debug --format %f 10000', {OUT=>"10000"},
 
671
             {ERR=>""},
 
672
             {ERR_SUBST=>"s/.*//msg"}],
 
673
     ['devdebug-11', '---debug --format "%\'-10f" 10000',{OUT=>"10000     "},
 
674
             {ERR=>""},
 
675
             {ERR_SUBST=>"s/.*//msg"}],
 
676
     ['devdebug-12', '---debug --field 2 A',{OUT=>""},
 
677
             {ERR=>""}, {EXIT=>2},
 
678
             {ERR_SUBST=>"s/.*//msg"}],
 
679
 
 
680
     # Invalid parameters
 
681
     ['help-1', '--foobar',
 
682
             {ERR=>"$prog: unrecognized option '--foobar'\n" .
 
683
                   "Try '$prog --help' for more information.\n"},
 
684
             {EXIT=>1}],
 
685
 
 
686
     ## Format string - check error detection
 
687
     ['fmt-err-1', '--format ""',
 
688
             {ERR=>"$prog: format '' has no % directive\n"},
 
689
             {EXIT=>1}],
 
690
     ['fmt-err-2', '--format "hello"',
 
691
             {ERR=>"$prog: format 'hello' has no % directive\n"},
 
692
             {EXIT=>1}],
 
693
     ['fmt-err-3', '--format "hello%"',
 
694
             {ERR=>"$prog: format 'hello%' ends in %\n"},
 
695
             {EXIT=>1}],
 
696
     ['fmt-err-4', '--format "%d"',
 
697
             {ERR=>"$prog: invalid format '%d', " .
 
698
                   "directive must be %['][-][N]f\n"},
 
699
             {EXIT=>1}],
 
700
     ['fmt-err-5', '--format "% -43 f"',
 
701
             {ERR=>"$prog: invalid format '% -43 f', " .
 
702
                   "directive must be %['][-][N]f\n"},
 
703
             {EXIT=>1}],
 
704
     ['fmt-err-6', '--format "%f %f"',
 
705
             {ERR=>"$prog: format '%f %f' has too many % directives\n"},
 
706
             {EXIT=>1}],
 
707
     ['fmt-err-7', '--format "%123456789012345678901234567890f"',
 
708
             {ERR=>"$prog: invalid format '%123456789012345678901234567890f'".
 
709
                   " (width overflow)\n"},
 
710
             {EXIT=>1}],
 
711
     ['fmt-err-8', '--format "%f" --padding 20',
 
712
             {ERR=>"$prog: --padding cannot be combined with --format\n"},
 
713
             {EXIT=>1}],
 
714
     ['fmt-err-9', '--format "%f" --grouping',
 
715
             {ERR=>"$prog: --grouping cannot be combined with --format\n"},
 
716
             {EXIT=>1}],
 
717
     ['fmt-err-10', '--format "%\'f" --to=si',
 
718
             {ERR=>"$prog: grouping cannot be combined with --to\n"},
 
719
             {EXIT=>1}],
 
720
     ['fmt-err-11', '--debug --format "%\'f" 5000', {OUT=>"5000"},
 
721
             {ERR=>"$prog: grouping has no effect in this locale\n"}],
 
722
 
 
723
     ## Format string - check some corner cases
 
724
     ['fmt-1', '--format "%% %f" 5000', {OUT=>"%%5000"}],
 
725
     ['fmt-2', '--format "%f %%" 5000', {OUT=>"5000 %%"}],
 
726
 
 
727
     ['fmt-3', '--format "--%f--" 5000000', {OUT=>"--5000000--"}],
 
728
     ['fmt-4', '--format "--%f--" --to=si 5000000', {OUT=>"--5.0M--"}],
 
729
 
 
730
     ['fmt-5', '--format "--%10f--" --to=si 5000000',{OUT=>"--      5.0M--"}],
 
731
     ['fmt-6', '--format "--%-10f--" --to=si 5000000',{OUT=>"--5.0M      --"}],
 
732
     ['fmt-7', '--format "--%10f--" 5000000',{OUT=>"--   5000000--"}],
 
733
     ['fmt-8', '--format "--%-10f--" 5000000',{OUT=>"--5000000   --"}],
 
734
 
 
735
     # too-short width
 
736
     ['fmt-9', '--format "--%5f--" 5000000',{OUT=>"--5000000--"}],
 
737
 
 
738
     # Format + Suffix
 
739
     ['fmt-10', '--format "--%10f--" --suffix Foo 50', {OUT=>"--     50Foo--"}],
 
740
     ['fmt-11', '--format "--%-10f--" --suffix Foo 50',{OUT=>"--50Foo     --"}],
 
741
 
 
742
     # Grouping in C locale - no grouping effect
 
743
     ['fmt-12', '--format "%\'f" 50000',{OUT=>"50000"}],
 
744
     ['fmt-13', '--format "%\'10f" 50000', {OUT=>"     50000"}],
 
745
     ['fmt-14', '--format "%\'-10f" 50000',{OUT=>"50000     "}],
 
746
 
 
747
     # Very large format strings
 
748
     ['fmt-15', '--format "--%100000f--" --to=si 4200',
 
749
                  {OUT=>"--" . " " x 99996 . "4.2K--" }],
 
750
 
 
751
 
 
752
     ## Check all errors again, this time with --invalid=fail
 
753
     ##  Input will be printed without conversion,
 
754
     ##  and exit code will be 2
 
755
     ['ign-err-1', '--invalid=fail 4Q',
 
756
             {ERR => "$prog: invalid suffix in input: '4Q'\n"},
 
757
             {OUT => "4Q\n"},
 
758
             {EXIT => 2}],
 
759
     ['ign-err-2', '--invalid=fail 4M',
 
760
             {ERR => "$prog: rejecting suffix " .
 
761
             "in input: '4M' (consider using --from)\n"},
 
762
             {OUT => "4M\n"},
 
763
             {EXIT => 2}],
 
764
     ['ign-err-3', '--invalid=fail --from=si 4MQ',
 
765
             {ERR => "$prog: invalid suffix in input '4MQ': 'Q'\n"},
 
766
             {OUT => "4MQ\n"},
 
767
             {EXIT => 2}],
 
768
     ['ign-err-4', '--invalid=fail --suffix=Foo --to=si   7000FooF',
 
769
              {ERR => "$prog: invalid suffix in input: '7000FooF'\n"},
 
770
              {OUT => "7000FooF\n"},
 
771
              {EXIT => 2}],
 
772
     ['ign-err-5','--invalid=fail --field 3 --from=auto "Hello 40M World 90G"',
 
773
             {ERR => "$prog: invalid number: 'World'\n"},
 
774
             {OUT => "Hello 40M World 90G\n"},
 
775
             {EXIT => 2}],
 
776
     ['ign-err-6', '--invalid=fail --field 3 --to=si "Hello World"',
 
777
             {ERR => "$prog: input line is too short, no numbers found " .
 
778
                     "to convert in field 3\n"},
 
779
             {OUT => "Hello World\n"},
 
780
             {EXIT => 2}],
 
781
     ['ign-err-7', '--invalid=fail --from=si "foo"',
 
782
             {ERR => "$prog: invalid number: 'foo'\n"},
 
783
             {OUT => "foo\n"},
 
784
             {EXIT=> 2}],
 
785
     ['ign-err-8', '--invalid=fail 12M',
 
786
             {ERR => "$prog: rejecting suffix " .
 
787
                     "in input: '12M' (consider using --from)\n"},
 
788
             {OUT => "12M\n"},
 
789
             {EXIT => 2}],
 
790
     ['ign-err-9', '--invalid=fail --from=iec-i 12M',
 
791
             {ERR => "$prog: missing 'i' suffix in input: " .
 
792
                     "'12M' (e.g Ki/Mi/Gi)\n"},
 
793
             {OUT => "12M\n"},
 
794
             {EXIT=>2}],
 
795
     ['ign-err-10','--invalid=fail 10000000000000000000',
 
796
             {ERR => "$prog: value too large to be printed: '1e+19' " .
 
797
                     "(consider using --to)\n"},
 
798
             {OUT => "10000000000000000000\n"},
 
799
             {EXIT=>2}],
 
800
     ['ign-err-11','--invalid=fail --to=si 9876543210000000000000000000',
 
801
             {ERR => "$prog: value too large to be converted: " .
 
802
                     "'9876543210000000000000000000'\n"},
 
803
             {OUT => "9876543210000000000000000000\n"},
 
804
             {EXIT => 2}],
 
805
 
 
806
     ## Ignore Errors with multiple conversions
 
807
     ['ign-err-m1', '--invalid=ignore --to=si 1000 2000 bad 3000',
 
808
             {OUT => "1.0K\n2.0K\nbad\n3.0K"},
 
809
             {EXIT => 0}],
 
810
     ['ign-err-m1.1', '--invalid=ignore --to=si',
 
811
             {IN_PIPE => "1000\n2000\nbad\n3000\n"},
 
812
             {OUT => "1.0K\n2.0K\nbad\n3.0K"},
 
813
             {EXIT => 0}],
 
814
     ['ign-err-m1.3', '--invalid=fail --debug --to=si 1000 2000 3000',
 
815
             {OUT => "1.0K\n2.0K\n3.0K"},
 
816
             {EXIT => 0}],
 
817
     ['ign-err-m2', '--invalid=fail --to=si 1000 Foo 3000',
 
818
             {OUT => "1.0K\nFoo\n3.0K\n"},
 
819
             {ERR => "$prog: invalid number: 'Foo'\n"},
 
820
             {EXIT => 2}],
 
821
     ['ign-err-m2.1', '--invalid=warn --to=si',
 
822
             {IN_PIPE => "1000\nFoo\n3000\n"},
 
823
             {OUT => "1.0K\nFoo\n3.0K"},
 
824
             {ERR => "$prog: invalid number: 'Foo'\n"},
 
825
             {EXIT => 0}],
 
826
 
 
827
     # --debug will trigger a final warning at EOF
 
828
     ['ign-err-m2.2', '--invalid=fail --debug --to=si 1000 Foo 3000',
 
829
             {OUT => "1.0K\nFoo\n3.0K\n"},
 
830
             {ERR => "$prog: invalid number: 'Foo'\n" .
 
831
                     "$prog: failed to convert some of the input numbers\n"},
 
832
             {EXIT => 2}],
 
833
 
 
834
     ['ign-err-m3', '--invalid=fail --field 2 --from=si --to=iec',
 
835
             {IN_PIPE => "A 1K x\nB 2M y\nC 3G z\n"},
 
836
             {OUT => "A 1000 x\nB 2.0M y\nC 2.8G z"},
 
837
             {EXIT => 0}],
 
838
     # invalid input on one of the fields
 
839
     ['ign-err-m3.1', '--invalid=fail --field 2 --from=si --to=iec',
 
840
             {IN_PIPE => "A 1K x\nB Foo y\nC 3G z\n"},
 
841
             {OUT => "A 1000 x\nB Foo y\nC 2.8G z\n"},
 
842
             {ERR => "$prog: invalid number: 'Foo'\n"},
 
843
             {EXIT => 2}],
 
844
     # one of the lines is too short
 
845
     ['ign-err-m3.2', '--invalid=fail --field 2 --from=si --to=iec',
 
846
             {IN_PIPE => "A 1K x\nB\nC 3G z\n"},
 
847
             {OUT => "A 1000 x\nB\nC 2.8G z\n"},
 
848
             {ERR => "$prog: input line is too short, no numbers found " .
 
849
                     "to convert in field 2\n"},
 
850
             {EXIT => 2}],
 
851
    );
 
852
 
 
853
my @Locale_Tests =
 
854
  (
 
855
     # Locale that supports grouping, but without '--grouping' parameter
 
856
     ['lcl-grp-1', '--from=si 7M',   {OUT=>"7000000"},
 
857
             {ENV=>"LC_ALL=$locale"}],
 
858
 
 
859
     # Locale with grouping
 
860
     ['lcl-grp-2', '--from=si --grouping 7M',   {OUT=>"7 000 000"},
 
861
             {ENV=>"LC_ALL=$locale"}],
 
862
 
 
863
     # Locale with grouping and debug - no debug warning message
 
864
     ['lcl-grp-3', '--from=si --debug --grouping 7M',   {OUT=>"7 000 000"},
 
865
             {ENV=>"LC_ALL=$locale"}],
 
866
 
 
867
     # Input with locale'd decimal-point
 
868
     ['lcl-stdtod-1', '--from=si 12,2K', {OUT=>"12200"},
 
869
             {ENV=>"LC_ALL=$locale"}],
 
870
 
 
871
     ['lcl-dbl-to-human-1', '--to=si 1100', {OUT=>"1,1K"},
 
872
             {ENV=>"LC_ALL=$locale"}],
 
873
 
 
874
     # Format + Grouping
 
875
     ['lcl-fmt-1', '--format "%\'f" 50000',{OUT=>"50 000"},
 
876
             {ENV=>"LC_ALL=$locale"}],
 
877
     ['lcl-fmt-2', '--format "--%\'10f--" 50000', {OUT=>"--    50 000--"},
 
878
             {ENV=>"LC_ALL=$locale"}],
 
879
     ['lcl-fmt-3', '--format "--%\'-10f--" 50000',{OUT=>"--50 000    --"},
 
880
             {ENV=>"LC_ALL=$locale"}],
 
881
     ['lcl-fmt-4', '--format "--%-10f--" --to=si 5000000',
 
882
             {OUT=>"--5,0M      --"},
 
883
             {ENV=>"LC_ALL=$locale"}],
 
884
 
 
885
  );
 
886
if ($locale ne 'C')
 
887
  {
 
888
    # Reset locale to 'C' if LOCALE_FR_UTF8 doesn't output as expected
 
889
    # as determined by the separate printf program.
 
890
    open(LOC_NUM, "LC_ALL=$locale printf \"%'d\" 1234|")
 
891
      or die "Can't fork command: $!";
 
892
    my $loc_num = <LOC_NUM>;
 
893
    close(LOC_NUM) || die "Failed to read grouped number from printf";
 
894
    if ($loc_num ne '1 234')
 
895
      {
 
896
        warn "skipping locale grouping tests as 1234 groups like $loc_num\n";
 
897
        $locale = 'C';
 
898
      }
 
899
  }
 
900
push @Tests, @Locale_Tests if $locale ne 'C';
 
901
 
 
902
## Check all valid/invalid suffixes
 
903
foreach my $suf ( 'A' .. 'Z', 'a' .. 'z' ) {
 
904
  if ( $suf =~ /^[KMGTPEZY]$/ )
 
905
    {
 
906
      push @Tests, ["auto-suf-si-$suf","--from=si --to=si 1$suf",
 
907
              {OUT=>"1.0$suf"}];
 
908
      push @Tests, ["auto-suf-iec-$suf","--from=iec --to=iec 1$suf",
 
909
              {OUT=>"1.0$suf"}];
 
910
      push @Tests, ["auto-suf-auto-$suf","--from=auto --to=iec 1${suf}i",
 
911
              {OUT=>"1.0$suf"}];
 
912
      push @Tests, ["auto-suf-iec-to-ieci-$suf","--from=iec --to=iec-i 1${suf}",
 
913
              {OUT=>"1.0${suf}i"}];
 
914
      push @Tests, ["auto-suf-ieci-to-iec-$suf",
 
915
              "--from=iec-i --to=iec 1${suf}i",{OUT=>"1.0${suf}"}];
 
916
    }
 
917
  else
 
918
    {
 
919
      push @Tests, ["auto-suf-si-$suf","--from=si --to=si 1$suf",
 
920
              {ERR=>"$prog: invalid suffix in input: '1${suf}'\n"},
 
921
              {EXIT=>2}];
 
922
    }
 
923
}
 
924
 
 
925
# Prepend the command line argument and append a newline to end
 
926
# of each expected 'OUT' string.
 
927
my $t;
 
928
 
 
929
Test:
 
930
foreach $t (@Tests)
 
931
  {
 
932
    # Don't fiddle with expected OUT string if there's a nonzero exit status.
 
933
    foreach my $e (@$t)
 
934
      {
 
935
        ref $e eq 'HASH' && exists $e->{EXIT} && $e->{EXIT}
 
936
          and next Test;
 
937
      }
 
938
 
 
939
    foreach my $e (@$t)
 
940
      {
 
941
        ref $e eq 'HASH' && exists $e->{OUT}
 
942
          and $e->{OUT} .= "\n"
 
943
      }
 
944
  }
 
945
 
 
946
my $save_temps = $ENV{SAVE_TEMPS};
 
947
my $verbose = $ENV{VERBOSE};
 
948
 
 
949
my $fail = run_tests ($program_name, $prog, \@Tests, $save_temps, $verbose);
 
950
exit $fail;