run_tests.pl 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. #! /usr/bin/env perl
  2. # Copyright 2015-2018 The OpenSSL Project Authors. All Rights Reserved.
  3. #
  4. # Licensed under the Apache License 2.0 (the "License"). You may not use
  5. # this file except in compliance with the License. You can obtain a copy
  6. # in the file LICENSE in the source distribution or at
  7. # https://www.openssl.org/source/license.html
  8. use strict;
  9. use warnings;
  10. # Recognise VERBOSE and V which is common on other projects.
  11. # Additionally, also recognise VERBOSE_FAILURE and VF.
  12. BEGIN {
  13. $ENV{HARNESS_VERBOSE} = "yes" if $ENV{VERBOSE} || $ENV{V};
  14. $ENV{HARNESS_VERBOSE_FAILURE} = "yes" if $ENV{VERBOSE_FAILURE} || $ENV{VF};
  15. }
  16. use File::Spec::Functions qw/catdir catfile curdir abs2rel rel2abs/;
  17. use File::Basename;
  18. use FindBin;
  19. use lib "$FindBin::Bin/../util/perl";
  20. use OpenSSL::Glob;
  21. my $srctop = $ENV{SRCTOP} || $ENV{TOP};
  22. my $bldtop = $ENV{BLDTOP} || $ENV{TOP};
  23. my $recipesdir = catdir($srctop, "test", "recipes");
  24. my $libdir = rel2abs(catdir($srctop, "util", "perl"));
  25. $ENV{OPENSSL_CONF} = catdir($srctop, "apps", "openssl.cnf");
  26. my %tapargs =
  27. ( verbosity => $ENV{HARNESS_VERBOSE} ? 1 : 0,
  28. lib => [ $libdir ],
  29. switches => '-w',
  30. merge => 1,
  31. );
  32. # Additional OpenSSL special TAP arguments. Because we can't pass them via
  33. # TAP::Harness->new(), they will be accessed directly, see the
  34. # TAP::Parser::OpenSSL implementation further down
  35. my %openssl_args = ();
  36. $openssl_args{'failure_verbosity'} =
  37. $ENV{HARNESS_VERBOSE_FAILURE} && $tapargs{verbosity} < 1 ? 1 : 0;
  38. my $outfilename = $ENV{HARNESS_TAP_COPY};
  39. open $openssl_args{'tap_copy'}, ">$outfilename"
  40. or die "Trying to create $outfilename: $!\n"
  41. if defined $outfilename;
  42. my @alltests = find_matching_tests("*");
  43. my %tests = ();
  44. my $initial_arg = 1;
  45. foreach my $arg (@ARGV ? @ARGV : ('alltests')) {
  46. if ($arg eq 'list') {
  47. foreach (@alltests) {
  48. (my $x = basename($_)) =~ s|^[0-9][0-9]-(.*)\.t$|$1|;
  49. print $x,"\n";
  50. }
  51. exit 0;
  52. }
  53. if ($arg eq 'alltests') {
  54. warn "'alltests' encountered, ignoring everything before that...\n"
  55. unless $initial_arg;
  56. %tests = map { $_ => basename($_) } @alltests;
  57. } elsif ($arg =~ m/^(-?)(.*)/) {
  58. my $sign = $1;
  59. my $test = $2;
  60. my @matches = find_matching_tests($test);
  61. # If '-foo' is the first arg, it's short for 'alltests -foo'
  62. if ($sign eq '-' && $initial_arg) {
  63. %tests = map { $_ => basename($_) } @alltests;
  64. }
  65. if (scalar @matches == 0) {
  66. warn "Test $test found no match, skipping ",
  67. ($sign eq '-' ? "removal" : "addition"),
  68. "...\n";
  69. } else {
  70. foreach $test (@matches) {
  71. if ($sign eq '-') {
  72. delete $tests{$test};
  73. } else {
  74. $tests{$test} = basename($test);
  75. }
  76. }
  77. }
  78. } else {
  79. warn "I don't know what '$arg' is about, ignoring...\n";
  80. }
  81. $initial_arg = 0;
  82. }
  83. sub find_matching_tests {
  84. my ($glob) = @_;
  85. if ($glob =~ m|^[\d\[\]\?\-]+$|) {
  86. return glob(catfile($recipesdir,"$glob-*.t"));
  87. }
  88. return glob(catfile($recipesdir,"*-$glob.t"));
  89. }
  90. # The following is quite a bit of hackery to adapt to both TAP::Harness
  91. # and Test::Harness, depending on what's available.
  92. # The TAP::Harness hack allows support for HARNESS_VERBOSE_FAILURE and
  93. # HARNESS_TAP_COPY, while the Test::Harness hack can't, because the pre
  94. # TAP::Harness Test::Harness simply doesn't have support for this sort of
  95. # thing.
  96. #
  97. # We use eval to avoid undue interruption if TAP::Harness isn't present.
  98. my $package;
  99. my $eres;
  100. $eres = eval {
  101. package TAP::Parser::OpenSSL;
  102. use parent 'TAP::Parser';
  103. sub new {
  104. my $class = shift;
  105. my %opts = %{ shift() };
  106. # We rely heavily on perl closures to make failure verbosity work
  107. # We need to do so, because there's no way to safely pass extra
  108. # objects down all the way to the TAP::Parser::Result object
  109. my @failure_output = ();
  110. my %callbacks = ();
  111. if ($openssl_args{failure_verbosity}
  112. || defined $openssl_args{tap_copy}) {
  113. $callbacks{ALL} = sub {
  114. my $self = shift;
  115. my $fh = $openssl_args{tap_copy};
  116. print $fh $self->as_string, "\n"
  117. if defined $fh;
  118. push @failure_output, $self->as_string
  119. if $openssl_args{failure_verbosity} > 0;
  120. };
  121. }
  122. if ($openssl_args{failure_verbosity} > 0) {
  123. $callbacks{EOF} = sub {
  124. my $self = shift;
  125. # We know we are a TAP::Parser::Aggregator object
  126. if (scalar $self->failed > 0 && @failure_output) {
  127. # We add an extra empty line, because in the case of a
  128. # progress counter, we're still at the end of that progress
  129. # line.
  130. print $_, "\n" foreach (("", @failure_output));
  131. }
  132. };
  133. }
  134. if (keys %callbacks) {
  135. # If %opts already has a callbacks element, the order here
  136. # ensures we do not override it
  137. %opts = ( callbacks => { %callbacks }, %opts );
  138. }
  139. return $class->SUPER::new({ %opts });
  140. }
  141. package TAP::Harness::OpenSSL;
  142. use parent 'TAP::Harness';
  143. package main;
  144. $tapargs{parser_class} = "TAP::Parser::OpenSSL";
  145. $package = 'TAP::Harness::OpenSSL';
  146. };
  147. unless (defined $eres) {
  148. $eres = eval {
  149. # Fake TAP::Harness in case it's not loaded
  150. package TAP::Harness::fake;
  151. use parent 'Test::Harness';
  152. sub new {
  153. my $class = shift;
  154. my %args = %{ shift() };
  155. return bless { %args }, $class;
  156. }
  157. sub runtests {
  158. my $self = shift;
  159. # Pre TAP::Harness Test::Harness doesn't support [ filename, name ]
  160. # elements, so convert such elements to just be the filename
  161. my @args = map { ref($_) eq 'ARRAY' ? $_->[0] : $_ } @_;
  162. my @switches = ();
  163. if ($self->{switches}) {
  164. push @switches, $self->{switches};
  165. }
  166. if ($self->{lib}) {
  167. foreach (@{$self->{lib}}) {
  168. my $l = $_;
  169. # It seems that $switches is getting interpreted with 'eval'
  170. # or something like that, and that we need to take care of
  171. # backslashes or they will disappear along the way.
  172. $l =~ s|\\|\\\\|g if $^O eq "MSWin32";
  173. push @switches, "-I$l";
  174. }
  175. }
  176. $Test::Harness::switches = join(' ', @switches);
  177. Test::Harness::runtests(@args);
  178. }
  179. package main;
  180. $package = 'TAP::Harness::fake';
  181. };
  182. }
  183. unless (defined $eres) {
  184. print $@,"\n" if $@;
  185. print $!,"\n" if $!;
  186. exit 127;
  187. }
  188. my $harness = $package->new(\%tapargs);
  189. my $ret =
  190. $harness->runtests(map { [ abs2rel($_, rel2abs(curdir())), $tests{$_} ] }
  191. sort keys %tests);
  192. # $ret->has_errors may be any number, not just 0 or 1. On VMS, numbers
  193. # from 2 and on are used as is as VMS statuses, which has severity encoded
  194. # in the lower 3 bits. 0 and 1, on the other hand, generate SUCCESS and
  195. # FAILURE, so for currect reporting on all platforms, we make sure the only
  196. # exit codes are 0 and 1. Double-bang is the trick to do so.
  197. exit !!$ret->has_errors if (ref($ret) eq "TAP::Parser::Aggregator");
  198. # If this isn't a TAP::Parser::Aggregator, it's the pre-TAP test harness,
  199. # which simply dies at the end if any test failed, so we don't need to bother
  200. # with any exit code in that case.