source: tags/svn.1.5.4/UNIT_TESTER/reporter.pl

Last change on this file was 8040, checked in by westram, 13 years ago

merge from dev [7975] [8034] [8002] [8004]

  • unit tests
    • added TEST_ASSERT_MEM_EQUAL
    • dump log if tests are disabled (even if warning is not printed)
    • do not prototype 'NOTEST_' (used to disable tests)
  • Property svn:executable set to *
File size: 6.9 KB
Line 
1#!/usr/bin/perl
2
3use strict;
4use warnings;
5
6# --------------------------------------------------------------------------------
7
8my $logdirectory = undef;
9my $slow_delay = undef;
10
11# --------------------------------------------------------------------------------
12
13sub getModtime($) {
14  my ($file_or_dir) = @_;
15  if (-f $file_or_dir or -d $file_or_dir) {
16    my @st = stat($file_or_dir);
17    if (not @st) { die "can't stat '$file_or_dir' ($!)"; }
18    return $st[9];
19  }
20  return 0; # does not exist -> use epoch
21}
22sub getAge($) { my ($file_or_dir) = @_; return time-getModtime($file_or_dir); }
23
24# --------------------------------------------------------------------------------
25
26# when file $slow_stamp exists, slow tests get skipped (see sym2testcode.pl@SkipSlow)
27my $slow_stamp = 'skipslow.stamp';
28my $slow_age   = getAge($slow_stamp); # seconds since of last successful slow test
29
30sub shall_run_slow() { return (($slow_delay==0) or ($slow_age>($slow_delay*60))); }
31
32sub slow_init() {
33  if (shall_run_slow()) {
34    print "Running SLOW tests\n";
35    unlink($slow_stamp);
36  }
37  else {
38    print "Skipping SLOW tests\n";
39  }
40}
41
42sub slow_cleanup($) {
43  my ($tests_failed) = @_;
44
45  if (shall_run_slow() and not $tests_failed) {
46    system("touch $slow_stamp");
47  }
48}
49
50# --------------------------------------------------------------------------------
51
52sub get_existing_logs() {
53  my @logs;
54  opendir(LOGDIR,$logdirectory) || die "can't read directory '$logdirectory' (Reason: $!)";
55  foreach (readdir(LOGDIR)) {
56    if (/\.log$/o) { push @logs, $logdirectory.'/'.$_; }
57  }
58  closedir(LOGDIR);
59  return @logs;
60}
61
62sub do_init() {
63  if (-d $logdirectory) {
64    my @logs = get_existing_logs();
65    foreach (@logs) { unlink($_) || die "can't unlink '$_' (Reason: $!)"; }
66  }
67  slow_init();
68  return undef;
69}
70# --------------------------------------------------------------------------------
71
72my $tests    = 0;
73my $skipped  = 0;
74my $passed   = 0;
75my $failed   = 0;
76my $warnings = 0;
77my $elapsed  = 0;
78my $crashed  = 0;
79my $valgrind = 0;
80
81my $max_dur      = 0;
82my $max_dur_unit = undef;
83
84sub parse_log($) {
85  # parse reports generated by UnitTester.cxx@generateReport
86  my ($log) = @_;
87  open(LOG,$log) || die "can't open '$log' (Reason: $!)";
88
89  my $tests_this   = 0;
90  my $skipped_this = 0;
91  my $passedALL    = 0;
92  my $seenSummary  = 0;
93  my $curr_target  = undef;
94
95  my $dump_log = 0;
96
97  while ($_ = <LOG>) {
98    chomp;
99    if (/^UnitTester:/) {
100      if (/tests=([0-9]+)/)   { $tests_this += $1; $seenSummary=1; }
101      if (/skipped=([0-9]+)/) { $skipped_this += $1; $dump_log = 1; }
102
103      if (/passed=([0-9]+)/)  { $passed += $1; }
104      if (/passed=ALL/)       { $passedALL = 1; }
105
106      if (/failed=([0-9]+)/)  { $failed += $1; $dump_log = 1; }
107      if (/warnings=([0-9]+)/)  { $warnings += $1; if ($failed==0) { $dump_log = 1; } }
108      if (/target=([^\s]+)/)  { $curr_target = $1; }
109      if (/time=([0-9.]+)/)   {
110        $elapsed += $1;
111        if ($1>$max_dur) {
112          $max_dur = $1;
113          if (not defined $curr_target) { die "Don't know current target"; }
114          $max_dur_unit = $curr_target;
115        }
116      }
117      if (/valgrind.*error/)  { $valgrind++; $dump_log = 1; }
118      if (/coverage/)  { $dump_log = 1; }
119    }
120  }
121  close(LOG);
122
123  if (not $seenSummary) { $dump_log = 1; }
124
125  if ($dump_log==1) {
126    open(LOG,$log) || die "can't open '$log' (Reason: $!)";
127    my $line;
128    while (defined($line=<LOG>)) { print $line; }
129    close(LOG);
130  }
131  else {
132    my $log_ptr = $log;
133    $log_ptr =~ s/^\./UNIT_TESTER/;
134    print "Suppressing dispensable $log_ptr\n";
135  }
136
137  if (not $seenSummary) {
138    print "Warning: No summary found in '$log' (maybe the test did not compile or crashed)\n";
139    $crashed++;
140  }
141
142  $tests   += $tests_this;
143  $skipped += $skipped_this;
144
145  if ($passedALL==1) { $passed += ($tests_this-$skipped_this); }
146}
147
148sub percent($$) {
149  my ($part,$all) = @_;
150  if ($all) {
151    my $percent = 100*$part/$all;
152    return sprintf("%5.1f%%", $percent);
153  }
154  else {
155    $part==0 || die;
156    return "  0.0%";
157  }
158}
159
160sub slow_note() {
161  return (shall_run_slow() ? "" : " (slow tests skipped)");
162}
163
164my $BigOk = <<EndOk;
165  __  __ _    _  _
166 /  \\(  / )  (_)( \\
167(  O ))  (    _  ) )
168 \\__/(__\\_)  (_)(_/
169EndOk
170
171my $BigFailed = <<EndFailed;
172 ____  __   __  __    ____  ____   _
173(  __)/ _\\ (  )(  )  (  __)(    \\ / \\
174 ) _)/    \\ )( / (_/\\ ) _)  ) D ( \\_/
175(__) \\_/\\_/(__)\\____/(____)(____/ (_)
176EndFailed
177
178
179sub print_summary($) {
180  my ($tests_failed) = @_;
181  print "\n-------------------- [ Unit-test summary ] --------------------\n";
182
183  my @summary = ();
184
185  push @summary, sprintf(" Tests   : %5i", $tests);
186  push @summary, sprintf(" Skipped : %5i =%s%s", $skipped, percent($skipped,$tests), slow_note());
187  push @summary, sprintf(" Passed  : %5i =%s", $passed, percent($passed,$tests));
188  push @summary, sprintf(" Failed  : %5i =%s", $failed, percent($failed,$tests));
189  push @summary, sprintf(" Sum.dur.: %5i ms", $elapsed);
190  if (defined $max_dur_unit) {
191    push @summary, sprintf(" Max.dur.: %5i ms (%s)", $max_dur, $max_dur_unit);
192  }
193  push @summary, sprintf(" Crashed : %5i units", $crashed);
194  push @summary, sprintf(" Warnings: %5i", $warnings);
195  if ($valgrind>0) {
196    push @summary, sprintf(" Valgrind: %5i failures", $valgrind);
197  }
198
199  my @big;
200  my $Big = $tests_failed ? $BigFailed : $BigOk;
201  @big= split '\n', $Big;
202
203  my $vOffset = scalar(@summary) - scalar(@big);
204  if ($vOffset<0) { $vOffset = 0; }
205
206  my $col = 0;
207  for (my $i=0; $i<scalar(@big); $i++) {
208    my $j = $i+$vOffset;
209    my $len = length($summary[$j]);
210    if ($len>$col) { $col = $len; }
211  }
212
213  $col += 6; # add horizontal offset
214
215  for (my $i=0; $i<scalar(@big); $i++) {
216    my $j = $i+$vOffset;
217    my $padded = $summary[$j];
218    my $len = length($padded);
219    while ($len<$col) { $padded .= ' '; $len++; }
220    $summary[$j] = $padded.$big[$i];
221  }
222
223  foreach (@summary) { print $_."\n"; }
224}
225
226sub do_report() {
227  my @logs = get_existing_logs();
228  foreach (@logs) {
229    parse_log($_);
230  }
231
232  my $tests_failed = (($failed>0) or ($crashed>0) or ($valgrind>0));
233  print_summary($tests_failed);
234  slow_cleanup($tests_failed);
235  if ($tests_failed) {
236    die "tests failed\n";
237  }
238  return undef;
239}
240
241# --------------------------------------------------------------------------------
242
243sub main() {
244  my $error = undef;
245  my $cb    = undef;
246  {
247    my $args = scalar(@ARGV);
248    if ($args==3) {
249      my $command   = shift @ARGV;
250
251      if ($command eq 'init') { $cb = \&do_init; }
252      elsif ($command eq 'report') { $cb = \&do_report; }
253      else { $error = "Unknown command '$command'"; }
254
255      if (not $error) {
256        $logdirectory = shift @ARGV;
257        $slow_delay = shift @ARGV;
258      }
259    }
260    else {
261      $error = 'Wrong number of arguments';
262    }
263  }
264  if ($error) {
265    print "Usage: reporter.pl [init|report] logdirectory slow-delay\n";
266    print "       slow-delay    >0 => run slow tests only every slow-delay minutes\n";
267  }
268  else {
269    eval { $error = &$cb(); };
270    if ($@) { $error = $@; }
271  }
272  if ($error) { die "Error: ".$error; }
273}
274main();
Note: See TracBrowser for help on using the repository browser.