Tizen 2.0 Release
[external/tizen-coreutils.git] / tests / mk-script
1 #! /usr/bin/perl -w
2 # -*- perl -*-
3 # Make test scripts.
4
5 # Copyright (C) 1998, 2000, 2001, 2002, 2003, 2005 Free Software
6 # Foundation, Inc.
7
8 # This program is free software; you can redistribute it and/or modify
9 # it under the terms of the GNU General Public License as published by
10 # the Free Software Foundation; either version 2 of the License, or
11 # (at your option) any later version.
12
13 # This program is distributed in the hope that it will be useful,
14 # but WITHOUT ANY WARRANTY; without even the implied warranty of
15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 # GNU General Public License for more details.
17
18 # You should have received a copy of the GNU General Public License
19 # along with this program; if not, write to the Free Software
20 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21 # 02110-1301, USA.
22
23 my $In = '.I';
24 my $Out = '.O';
25 my $Exp = '.X';
26 my $Err = '.E';
27
28 require 5.002;
29 use strict;
30 use POSIX qw (assert);
31
32 (my $ME = $0) =~ s|.*/||;
33
34 BEGIN { push @INC, '.' if '.' ne '.'; }
35 use Test;
36
37 my $srcdir = shift;
38
39 sub validate
40 {
41   my %seen;
42   my %seen_8dot3;
43
44   my $bad_test_name;
45   my $test_vector;
46   foreach $test_vector (Test::test_vector ())
47     {
48       my ($test_name, $flags, $in_spec, $expected, $e_ret_code, $rest) =
49         @$test_vector;
50       die "$0: wrong number of elements in test $test_name\n"
51         if (!defined $e_ret_code || defined $rest);
52       assert (!ref $test_name);
53       assert (!ref $flags);
54       assert (!ref $e_ret_code);
55
56       die "$0: duplicate test name \`$test_name'\n"
57         if (defined $seen{$test_name});
58       $seen{$test_name} = 1;
59
60       if (0)
61         {
62           my $t8 = lc substr $test_name, 0, 8;
63           if ($seen_8dot3{$t8})
64             {
65               warn "$ME: 8.3 test name conflict: "
66                 . "$test_name, $seen_8dot3{$t8}\n";
67               $bad_test_name = 1;
68             }
69           $seen_8dot3{$t8} = $test_name;
70         }
71     }
72
73   $bad_test_name
74     and exit 1;
75 }
76
77 # Given a spec for the input file(s) or expected output file of a single
78 # test, create a file for any string.  A file is created for each literal
79 # string -- not for named files.  Whether a perl `string' is treated as
80 # a string to be put in a file for a test or the name of an existing file
81 # depends on how many references have to be traversed to get from
82 # the top level variable to the actual string literal.
83 # If $SPEC is a literal Perl string (not a reference), then treat $SPEC
84 # as the contents of a file.
85 # If $SPEC is a hash reference, then there are no inputs.
86 # If $SPEC is an array reference, consider each element of the array.
87 # If the element is a string reference, treat the string as the name of
88 # an existing file.  Otherwise, the element must be a string and is treated
89 # just like a scalar $SPEC.  When a file is created, its name is derived
90 # from the name TEST_NAME of the corresponding test and the TYPE of file.
91 # E.g., the inputs for test `3a' would be named t3a.in1 and t3a.in2, and
92 # the expected output for test `7c' would be named t7c.exp.
93 #
94 # Also, return two lists of file names:
95 # - maintainer-generated files -- names of files created by this function
96 # - files named explicitly in Test.pm
97
98 sub spec_to_list ($$$)
99 {
100   my ($spec, $test_name, $type) = @_;
101
102   assert ($type eq $In || $type eq $Exp);
103
104   my @explicit_file;
105   my @maint_gen_file;
106   my @content_string;
107
108   # If SPEC is a hash reference, return empty lists.
109   if (ref $spec eq 'HASH')
110     {
111       assert ($type eq $In);
112       return {
113         EXPLICIT => \@explicit_file,
114         MAINT_GEN => \@maint_gen_file
115         };
116     }
117
118   if (ref $spec)
119     {
120       assert (ref $spec eq 'ARRAY' || ref $spec eq 'HASH');
121       my $file_spec;
122       foreach $file_spec (@$spec)
123         {
124           # A file spec may be a string or a reference.
125           # If it's a string, that string is to be the contents of a
126           # generated (by this script) file with name derived from the
127           # name of this test.
128           # If it's a reference, then it must be the name of an existing
129           # file.
130           if (ref $file_spec)
131             {
132               my $r = ref $file_spec;
133               die "bad test: $test_name is $r\n"
134                 if ref $file_spec ne 'SCALAR';
135               my $existing_file = $$file_spec;
136               # FIXME: make sure $existing_file exists somewhere.
137               push (@explicit_file, $existing_file);
138             }
139           else
140             {
141               push (@content_string, $file_spec);
142             }
143         }
144     }
145   else
146     {
147       push (@content_string, $spec);
148     }
149
150   my $i = 1;
151   my $file_contents;
152   foreach $file_contents (@content_string)
153     {
154       my $suffix = (@content_string > 1 ? $i : '');
155       my $maint_gen_file = "$test_name$type$suffix";
156       push (@maint_gen_file, $maint_gen_file);
157       open (F, ">$srcdir/$maint_gen_file") || die "$0: $maint_gen_file: $!\n";
158       print F $file_contents;
159       close (F) || die "$0: $maint_gen_file: $!\n";
160       ++$i;
161     }
162
163   my $n_fail = 0;
164   foreach $i (@explicit_file, @maint_gen_file)
165     {
166       my $max_len = 14;
167       if (length ($i) > $max_len)
168         {
169           warn "$0: $i: generated test file name would be longer than"
170             . " $max_len characters\n";
171           ++$n_fail;
172         }
173     }
174   exit (1) if $n_fail;
175
176   my %h = (
177     EXPLICIT => \@explicit_file,
178     MAINT_GEN => \@maint_gen_file
179   );
180
181   return \%h;
182 }
183
184 sub wrap
185 {
186   my ($preferred_line_len, @tok) = @_;
187   assert ($preferred_line_len > 0);
188   my @lines;
189   my $line = '';
190   my $word;
191   foreach $word (@tok)
192     {
193       if ($line && length ($line) + 1 + length ($word) > $preferred_line_len)
194         {
195           push (@lines, $line);
196           $line = $word;
197           next;
198         }
199       my $sp = ($line ? ' ' : '');
200       $line .= "$sp$word";
201     }
202   push (@lines, $line);
203   return @lines;
204 }
205
206 # ~~~~~~~ main ~~~~~~~~
207 {
208   $| = 1;
209
210   die "Usage: $0: srcdir program-name\n" if @ARGV != 1;
211
212   my $xx = $ARGV[0];
213
214   if ($xx eq '--list')
215     {
216       validate ();
217       # Output three lists of files:
218       # EXPLICIT -- file names specified in Test.pm
219       # MAINT_GEN -- maintainer-generated files
220       # RUN_GEN -- files created when running the tests
221       my $test_vector;
222       my @exp;
223       my @maint;
224       my @run;
225       foreach $test_vector (Test::test_vector ())
226         {
227           my ($test_name, $flags, $in_spec, $exp_spec, $e_ret_code)
228             = @$test_vector;
229
230           push (@run, ("$test_name$Out", "$test_name$Err"));
231
232           my $in = spec_to_list ($in_spec, $test_name, $In);
233           push (@exp, @{$in->{EXPLICIT}});
234           push (@maint, @{$in->{MAINT_GEN}});
235
236           my $e = spec_to_list ($exp_spec, $test_name, $Exp);
237           push (@exp, @{$e->{EXPLICIT}});
238           push (@maint, @{$e->{MAINT_GEN}});
239         }
240
241       # The list of explicitly mentioned files may contain duplicates.
242       # Eliminated any duplicates.
243       my %e = map {$_ => 1} @exp;
244       @exp = sort keys %e;
245
246       my $len = 77;
247       print join (" \\\n", wrap ($len, 'explicit =', @exp)), "\n";
248       print join (" \\\n", wrap ($len, 'maint_gen =', @maint)), "\n";
249       print join (" \\\n", wrap ($len, 'run_gen =', @run)), "\n";
250
251       exit 0;
252     }
253
254   print <<EOF1;
255 #! /bin/sh
256 # This script was generated automatically by $ME.
257 case \$# in
258   0\) xx='$xx';;
259   *\) xx="\$1";;
260 esac
261 test "\$VERBOSE" && echo=echo || echo=:
262 \$echo testing program: \$xx
263 errors=0
264 test "\$srcdir" || srcdir=.
265 test "\$VERBOSE" && \$xx --version 2> /dev/null
266
267 # Make sure we get English translations.
268 LANGUAGE=C
269 export LANGUAGE
270 LC_ALL=C
271 export LC_ALL
272 LANG=C
273 export LANG
274
275 EOF1
276
277   validate ();
278
279   my $n_tests = 0;
280   my $test_vector;
281   foreach $test_vector (Test::test_vector ())
282     {
283       my ($test_name, $flags, $in_spec, $exp_spec, $e_ret_code)
284         = @$test_vector;
285
286       my $in = spec_to_list ($in_spec, $test_name, $In);
287
288       my @srcdir_rel_in_file;
289       my $f;
290       foreach $f (@{$in->{EXPLICIT}}, @{$in->{MAINT_GEN}})
291         {
292           push (@srcdir_rel_in_file, "\$srcdir/$f");
293         }
294
295       my $exp = spec_to_list ($exp_spec, $test_name, $Exp);
296       my @all = (@{$exp->{EXPLICIT}}, @{$exp->{MAINT_GEN}});
297       assert (@all == 1);
298       my $exp_name = "\$srcdir/$all[0]";
299       my $out = "$test_name$Out";
300       my $err_output = "$test_name$Err";
301
302       my %valid_via = map {$_ => 1} qw (REDIR FILE PIPE);
303       my %via_msg_string = (REDIR => '<', FILE => 'F', PIPE => '|');
304
305       # Inhibit warnings about `used only once'.
306       die if 0 && $Test::input_via{$test_name} && $Test::input_via_default;
307       die if 0 && $Test::env{$test_name} && $Test::env_default;
308
309       my $vias = $Test::input_via{$test_name} || $Test::input_via_default
310         || {FILE => 0};
311
312       my $n_vias = keys %$vias;
313       my $via;
314       foreach $via (sort keys %$vias)
315         {
316           my $cmd;
317           my $val = $vias->{$via};
318           my $via_msg = ($n_vias == 1 ? '' : $via_msg_string{$via});
319           my $file_args = join (' ', @srcdir_rel_in_file);
320
321           my $env = $Test::env{$test_name} || $Test::env_default || [''];
322           @$env == 1
323             or die "$ME: unexpected environment: @$env\n";
324           $env = $env->[0];
325           my $env_prefix = ($env ? "$env " : '');
326
327           if ($via eq 'FILE')
328             {
329               $cmd = "$env_prefix\$xx $flags $file_args > $out 2> $err_output";
330             }
331           elsif ($via eq 'PIPE')
332             {
333               $via_msg = "|$val" if $val;
334               $val ||= 'cat';
335               $cmd = "$val $file_args | $env_prefix\$xx $flags"
336                 . " > $out 2> $err_output";
337             }
338           else
339             {
340               assert (@srcdir_rel_in_file == 1);
341               $cmd = "$env_prefix\$xx $flags"
342                 . " < $file_args > $out 2> $err_output";
343             }
344
345           my $e = $env;
346           my $sep = ($via_msg && $e ? ':' : '');
347           my $msg = "$e$sep$via_msg";
348           $msg = "($msg)" if $msg;
349           my $t_name = "$test_name$msg";
350           ++$n_tests;
351           print <<EOF;
352 $cmd
353 code=\$?
354 if test \$code != $e_ret_code; then
355   \$echo "Test $t_name failed: \$xx return code \$code differs from expected value $e_ret_code" 1>&2
356   errors=`expr \$errors + 1`
357 else
358   cmp $out $exp_name > /dev/null 2>&1
359   case \$? in
360     0) if test "\$VERBOSE"; then \$echo "passed $t_name"; fi;;
361     1) \$echo "Test $t_name failed: files $out and $exp_name differ" 1>&2
362        (diff -c $out $exp_name) 2> /dev/null
363        errors=`expr \$errors + 1`;;
364     2) \$echo "Test $t_name may have failed." 1>&2
365        \$echo The command \"cmp $out $exp_name\" failed. 1>&2
366        errors=`expr \$errors + 1`;;
367   esac
368 fi
369 test -s $err_output || rm -f $err_output
370 EOF
371         }
372     }
373   print <<EOF3
374 if test \$errors = 0; then
375   \$echo Passed all $n_tests tests. 1>&2
376 else
377   \$echo Failed \$errors tests. 1>&2
378 fi
379 test \$errors = 0 || errors=1
380 exit \$errors
381 EOF3
382 }