Run the fuzzing corpora as tests.
[openssl.git] / test / testlib / OpenSSL / Test.pm
index ca2e369a2095a93c182a4e27fc9edd0033ee42b9..0c3b9104e9190b9f17ee8b8f1a1945929608602d 100644 (file)
@@ -1,3 +1,10 @@
+# Copyright 2016 The OpenSSL Project Authors. All Rights Reserved.
+#
+# Licensed under the OpenSSL license (the "License").  You may not use
+# this file except in compliance with the License.  You can obtain a copy
+# in the file LICENSE in the source distribution or at
+# https://www.openssl.org/source/license.html
+
 package OpenSSL::Test;
 
 use strict;
@@ -9,7 +16,8 @@ use Exporter;
 use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS);
 $VERSION = "0.8";
 @ISA = qw(Exporter);
-@EXPORT = (@Test::More::EXPORT, qw(setup indir app perlapp test perltest run));
+@EXPORT = (@Test::More::EXPORT, qw(setup indir app fuzz  perlapp test perltest
+                                   run));
 @EXPORT_OK = (@Test::More::EXPORT_OK, qw(bldtop_dir bldtop_file
                                          srctop_dir srctop_file
                                          pipe with cmdstr quotify));
@@ -60,6 +68,11 @@ my $test_name = undef;
 # (mandatory), BIN_D, TEST_D, UTIL_D and RESULT_D.
 my %directories = ();
 
+# The environment variables that gave us the contents in %directories.  These
+# get modified whenever we change directories, so that subprocesses can use
+# the values of those environment variables as well
+my @direnv = ();
+
 # A bool saying if we shall stop all testing if the current recipe has failing
 # tests or not.  This is set by setup() if the environment variable STOPTEST
 # is defined with a non-empty value.
@@ -273,6 +286,13 @@ sub app {
                 return __build_cmd($num, \&__apps_file, $cmd, %opts); }
 }
 
+sub fuzz {
+    my $cmd = shift;
+    my %opts = @_;
+    return sub { my $num = shift;
+                return __build_cmd($num, \&__fuzz_file, $cmd, %opts); }
+}
+
 sub test {
     my $cmd = shift;
     my %opts = @_;
@@ -341,6 +361,18 @@ sub run {
     my $r = 0;
     my $e = 0;
 
+    # In non-verbose, we want to shut up the command interpreter, in case
+    # it has something to complain about.  On VMS, it might complain both
+    # on stdout and stderr
+    my $save_STDOUT;
+    my $save_STDERR;
+    if ($ENV{HARNESS_ACTIVE} && !$ENV{HARNESS_VERBOSE}) {
+        open $save_STDOUT, '>&', \*STDOUT or die "Can't dup STDOUT: $!";
+        open $save_STDERR, '>&', \*STDERR or die "Can't dup STDERR: $!";
+        open STDOUT, ">", devnull();
+        open STDERR, ">", devnull();
+    }
+
     # The dance we do with $? is the same dance the Unix shells appear to
     # do.  For example, a program that gets aborted (and therefore signals
     # SIGABRT = 6) will appear to exit with the code 134.  We mimic this
@@ -354,6 +386,13 @@ sub run {
        $r = $hooks{exit_checker}->($e);
     }
 
+    if ($ENV{HARNESS_ACTIVE} && !$ENV{HARNESS_VERBOSE}) {
+        close STDOUT;
+        close STDERR;
+        open STDOUT, '>&', $save_STDOUT or die "Can't restore STDOUT: $!";
+        open STDERR, '>&', $save_STDERR or die "Can't restore STDERR: $!";
+    }
+
     print STDERR "$prefix$display_cmd => $e\n"
         if !$ENV{HARNESS_ACTIVE} || $ENV{HARNESS_VERBOSE};
 
@@ -670,10 +709,19 @@ sub __env {
     $directories{BLDTOP}  = $ENV{BLDTOP} || $ENV{TOP};
     $directories{BLDAPPS} = $ENV{BIN_D}  || __bldtop_dir("apps");
     $directories{SRCAPPS} =                 __srctop_dir("apps");
+    $directories{BLDFUZZ} =                 __bldtop_dir("fuzz");
+    $directories{SRCFUZZ} =                 __srctop_dir("fuzz");
     $directories{BLDTEST} = $ENV{TEST_D} || __bldtop_dir("test");
     $directories{SRCTEST} =                 __srctop_dir("test");
     $directories{RESULTS} = $ENV{RESULT_D} || $directories{BLDTEST};
 
+    push @direnv, "TOP"       if $ENV{TOP};
+    push @direnv, "SRCTOP"    if $ENV{SRCTOP};
+    push @direnv, "BLDTOP"    if $ENV{BLDTOP};
+    push @direnv, "BIN_D"     if $ENV{BIN_D};
+    push @direnv, "TEST_D"    if $ENV{TEST_D};
+    push @direnv, "RESULT_D"  if $ENV{RESULT_D};
+
     $end_with_bailout    = $ENV{STOPTEST} ? 1 : 0;
 };
 
@@ -716,8 +764,8 @@ sub __exeext {
 sub __test_file {
     BAIL_OUT("Must run setup() first") if (! $test_name);
 
-    my $f = pop . __exeext();
-    $f = catfile($directories{BLDTEST},@_,$f);
+    my $f = pop;
+    $f = catfile($directories{BLDTEST},@_,$f . __exeext());
     $f = catfile($directories{SRCTEST},@_,$f) unless -x $f;
     return $f;
 }
@@ -734,12 +782,21 @@ sub __perltest_file {
 sub __apps_file {
     BAIL_OUT("Must run setup() first") if (! $test_name);
 
-    my $f = pop . __exeext();
-    $f = catfile($directories{BLDAPPS},@_,$f);
+    my $f = pop;
+    $f = catfile($directories{BLDAPPS},@_,$f . __exeext());
     $f = catfile($directories{SRCAPPS},@_,$f) unless -x $f;
     return $f;
 }
 
+sub __fuzz_file {
+    BAIL_OUT("Must run setup() first") if (! $test_name);
+
+    my $f = pop;
+    $f = catfile($directories{BLDFUZZ},@_,$f . __exeext());
+    $f = catfile($directories{SRCFUZZ},@_,$f) unless -x $f;
+    return $f;
+}
+
 sub __perlapps_file {
     BAIL_OUT("Must run setup() first") if (! $test_name);
 
@@ -783,12 +840,10 @@ sub __cwd {
        mkpath($dir);
     }
 
-    # Should we just bail out here as well?  I'm unsure.
-    return undef unless chdir($dir);
-
-    if ($opts{cleanup}) {
-       rmtree(".", { safe => 0, keep_root => 1 });
-    }
+    # We are recalculating the directories we keep track of, but need to save
+    # away the result for after having moved into the new directory.
+    my %tmp_directories = ();
+    my %tmp_ENV = ();
 
     # For each of these directory variables, figure out where they are relative
     # to the directory we want to move to if they aren't absolute (if they are,
@@ -797,10 +852,37 @@ sub __cwd {
     foreach (@dirtags) {
        if (!file_name_is_absolute($directories{$_})) {
            my $newpath = abs2rel(rel2abs($directories{$_}), rel2abs($dir));
-           $directories{$_} = $newpath;
+           $tmp_directories{$_} = $newpath;
+       }
+    }
+
+    # Treat each environment variable that was used to get us the values in
+    # %directories the same was as the paths in %directories, so any sub
+    # process can use their values properly as well
+    foreach (@direnv) {
+       if (!file_name_is_absolute($ENV{$_})) {
+           my $newpath = abs2rel(rel2abs($ENV{$_}), rel2abs($dir));
+           $tmp_ENV{$_} = $newpath;
        }
     }
 
+    # Should we just bail out here as well?  I'm unsure.
+    return undef unless chdir($dir);
+
+    if ($opts{cleanup}) {
+       rmtree(".", { safe => 0, keep_root => 1 });
+    }
+
+    # We put back new values carefully.  Doing the obvious
+    # %directories = ( %tmp_irectories )
+    # will clear out any value that happens to be an absolute path
+    foreach (keys %tmp_directories) {
+        $directories{$_} = $tmp_directories{$_};
+    }
+    foreach (keys %tmp_ENV) {
+        $ENV{$_} = $tmp_ENV{$_};
+    }
+
     if ($debug) {
        print STDERR "DEBUG: __cwd(), directories and files:\n";
        print STDERR "  \$directories{BLDTEST} = \"$directories{BLDTEST}\"\n";