Imported Upstream version 1.8.8
[platform/upstream/doxygen.git] / testing / runtests.pl
1 #!/usr/bin/perl
2
3 # perl script to execute doxygen's regression test suite.
4 #
5 # Copyright (C) 1997-2014 by Dimitri van Heesch.
6 #
7 # Permission to use, copy, modify, and distribute this software and its
8 # documentation under the terms of the GNU General Public License is hereby 
9 # granted. No representations are made about the suitability of this software 
10 # for any purpose. It is provided "as is" without express or implied warranty.
11 # See the GNU General Public License for more details.
12 #
13 # Documents produced by Doxygen are derivative works derived from the
14 # input used in their production; they are not affected by this license.
15
16 use strict;
17 use warnings;
18
19 use Getopt::Long;
20 use Test::More;
21 use File::Path qw(make_path remove_tree);
22 use File::Copy qw(copy);
23
24 my $Test = Test::Builder->new;
25 my $opt_doxygen_exe = 'doxygen';
26 my $opt_xmllint_exe = 'xmllint';
27 my $opt_updateref = '';
28 my @opt_test_ids;
29 my $opt_all = '';
30
31 GetOptions( 'updateref'  => \$opt_updateref,
32             'doxygen=s'  => \$opt_doxygen_exe,
33             'xmllint=s'  => \$opt_xmllint_exe,
34             'id=i'       => \@opt_test_ids,
35             'all'        => \$opt_all
36           );
37
38 sub read_two_files {
39   my $first   = shift;
40   my $second  = shift;
41   my $filter  = shift;
42   my $success = 1;
43   my @errors;
44
45   unless (open FIRST, "$first") {
46     $success = 0;
47     push @errors, "$first absent";
48   }
49   unless (open SECOND, "$second") {
50     $success = 0;
51     push @errors, "$second absent";
52   }
53   return ($success, @errors) unless $success;
54
55   my $first_lines  = join "",<FIRST>;
56   my $second_lines = join "",<SECOND>;
57   
58   close FIRST;
59   close SECOND;
60
61   return ($success, $first_lines, $second_lines);
62 }
63
64 sub compare_ok {
65   my $got_file      = shift;
66   my $expected_file = shift;
67   my $name          = shift;
68   my @read_result   = read_two_files($got_file, $expected_file);
69   my $files_exist   = shift @read_result;
70
71   if ($files_exist) {
72     my ($got, $expected) = @read_result;
73     my $diff = `diff -u $got_file $expected_file`;
74     my $failed = length $diff;
75     return ($failed,"Difference between generated output and reference:\n$diff");
76   }
77   else {
78     return (1,join "\n", @read_result);
79   }
80 }
81
82 sub chop_volatile {
83   my $line = shift;
84   $line =~ s/version="\d\.\d.\d+"/version=""/g; # strip version
85   $line =~ s/file=".*\/(.*)"/file="$1"/g; # strip location
86   return $line;
87 }
88
89 sub get_config {
90   my $file = shift;
91   my %config;
92   open F,"<$file";
93   while (<F>) {
94     if (/\/\/\s*(\S+):\s*(.*)$/) {
95       my $key = $1;
96       my $val = $2;
97       chomp $val;
98       $config{$key} = [] unless defined $config{$key};
99       push @{$config{$key}},$val;
100     }
101   }
102   return %config;
103 }
104
105 sub perform_test {
106   my $test_file = shift;
107   my %config = get_config($test_file);
108   my $test_name = "[$test_file]: $config{'objective'}[0]";
109   my $test_id = $test_file;
110   $test_id =~ s/^(\d+).*$/$1/;
111   my $test_out = "test_output_${test_id}";
112
113   if (scalar($config{'check'})==0) {
114     $Test->ok(0, $test_name);
115     $Test->diag("Test doesn't specify any files to check");
116     return;
117   }
118
119   # prepare test environment
120   remove_tree("$test_out");
121   make_path("$test_out");
122   copy("Doxyfile","$test_out");
123   open(F,">>$test_out/Doxyfile");
124   print F "INPUT = $test_file\n";
125   print F "XML_OUTPUT = $test_out/out\n";
126   foreach my $cfg (@{$config{'config'}}) {
127     print F "$cfg\n";
128   }
129   close(F);
130
131   # run doxygen
132   if (system("$opt_doxygen_exe $test_out/Doxyfile")!=0) {
133     $Test->ok(0, $test_name);
134     $Test->diag("Failed to run doxygen");
135     return;
136   } 
137
138   # look for files to check against the reference
139   foreach my $fn (@{$config{'check'}}) {
140     if (!-f "$test_out/out/$fn") {
141       $Test->ok(0, $test_name);
142       $Test->diag("Non-existing file $test_out/out/$fn after 'check:' statement");
143       return;
144     }
145     # run xmllint on the output file
146     my @lines = `$opt_xmllint_exe --format --noblanks --nowarning $test_out/out/$fn`;
147     if (scalar(@lines)>0 && open(F,">$test_out/$fn")) {
148       foreach my $line (@lines) {
149         print F chop_volatile($line);
150       }
151       close(F);
152     } else {
153       $Test->ok(0, $test_name);
154       $Test->diag("Failed to run xmllint on the doxygen output file $test_out/out/$fn");
155     }
156     my ($failed,$msg) = compare_ok("$test_out/$fn","$test_id/$fn",$test_name);
157     if ($failed) {
158       $Test->ok(0, $test_name);
159       $Test->diag($msg);
160       return;
161     }
162   }
163
164   # test passed
165   remove_tree("$test_out");
166   $Test->ok(1, $test_name);
167 }
168
169 sub update_test {
170   my $test_file = shift;
171   my %config = get_config($test_file);
172   my $test_name = "[$test_file]: $config{'objective'}[0]";
173   my $test_id = $test_file;
174   $test_id =~ s/^(\d+).*$/$1/;
175   my $test_out = $test_id;
176
177   # prepare reference environment
178   remove_tree("$test_out");
179   make_path("$test_out");
180   copy("Doxyfile","$test_out");
181   open(F,">>$test_out/Doxyfile");
182   print F "INPUT = $test_file\n";
183   print F "XML_OUTPUT = $test_out/out\n";
184   foreach my $cfg (@{$config{'config'}}) {
185     print F "$cfg\n";
186   }
187   close(F);
188
189   print "Updating reference for $test_name\n";
190
191   # run doxygen
192   if (system("$opt_doxygen_exe $test_out/Doxyfile")!=0) {
193     print("Error: failed to run doxygen");
194     return;
195   } 
196   my $err=0;
197
198   # look for files to prepare as reference
199   foreach my $fn (@{$config{'check'}}) {
200     if (!-f "$test_out/out/$fn") {
201       printf("Error: Non-existing file $test_out/out/$fn after 'check:' statement\n");
202       $err=1;
203     }
204     # run xmllint on the output file
205     if (!$err) {
206       my @lines = `$opt_xmllint_exe --format --noblanks --nowarning $test_out/out/$fn`;
207       if (scalar(@lines)>0 && open(F,">$test_out/$fn")) {
208         foreach my $line (@lines) {
209           print F chop_volatile($line);
210         }
211         close(F);
212       } else {
213         printf("Error: Failed to run xmllint on the doxygen output file $test_out/out/$fn\n");
214         $err=1;
215       }
216     }
217   }
218
219   if (!$err) {
220     # clean-up
221     remove_tree("$test_out/out");
222     unlink("$test_out/Doxyfile");
223   }
224 }
225
226 # get the tests
227 my @tests;
228 if (scalar(@opt_test_ids)==0 && $opt_updateref && !$opt_all) {
229   printf("Error: updateref option requires -id to update a test or -all to update all\n");
230   exit(1);
231 }
232 if (scalar(@opt_test_ids)>0) {
233   foreach my $t (@opt_test_ids) {
234     push @tests, glob("${t}_* 0${t}_* 00${t}_*");
235   }
236 } else {
237   @tests = glob('[0-9][0-9][0-9]_*');
238 }
239
240 if ($opt_updateref) {
241   # update reference
242   foreach my $test (@tests) {
243     update_test($test);
244   }
245 } else {
246   # run tests
247   plan tests => scalar(@tests);
248   foreach my $test (@tests) {
249     perform_test($test);
250   }
251 }
252