xref: /third_party/openssl/util/perl/OpenSSL/Test.pm (revision e1051a39)
1e1051a39Sopenharmony_ci# Copyright 2016-2021 The OpenSSL Project Authors. All Rights Reserved.
2e1051a39Sopenharmony_ci#
3e1051a39Sopenharmony_ci# Licensed under the Apache License 2.0 (the "License").  You may not use
4e1051a39Sopenharmony_ci# this file except in compliance with the License.  You can obtain a copy
5e1051a39Sopenharmony_ci# in the file LICENSE in the source distribution or at
6e1051a39Sopenharmony_ci# https://www.openssl.org/source/license.html
7e1051a39Sopenharmony_ci
8e1051a39Sopenharmony_cipackage OpenSSL::Test;
9e1051a39Sopenharmony_ci
10e1051a39Sopenharmony_ciuse strict;
11e1051a39Sopenharmony_ciuse warnings;
12e1051a39Sopenharmony_ci
13e1051a39Sopenharmony_ciuse Test::More 0.96;
14e1051a39Sopenharmony_ci
15e1051a39Sopenharmony_ciuse Exporter;
16e1051a39Sopenharmony_ciuse vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS);
17e1051a39Sopenharmony_ci$VERSION = "1.0";
18e1051a39Sopenharmony_ci@ISA = qw(Exporter);
19e1051a39Sopenharmony_ci@EXPORT = (@Test::More::EXPORT, qw(setup run indir cmd app fuzz test
20e1051a39Sopenharmony_ci                                   perlapp perltest subtest));
21e1051a39Sopenharmony_ci@EXPORT_OK = (@Test::More::EXPORT_OK, qw(bldtop_dir bldtop_file
22e1051a39Sopenharmony_ci                                         srctop_dir srctop_file
23e1051a39Sopenharmony_ci                                         data_file data_dir
24e1051a39Sopenharmony_ci                                         result_file result_dir
25e1051a39Sopenharmony_ci                                         pipe with cmdstr
26e1051a39Sopenharmony_ci                                         openssl_versions
27e1051a39Sopenharmony_ci                                         ok_nofips is_nofips isnt_nofips));
28e1051a39Sopenharmony_ci
29e1051a39Sopenharmony_ci=head1 NAME
30e1051a39Sopenharmony_ci
31e1051a39Sopenharmony_ciOpenSSL::Test - a private extension of Test::More
32e1051a39Sopenharmony_ci
33e1051a39Sopenharmony_ci=head1 SYNOPSIS
34e1051a39Sopenharmony_ci
35e1051a39Sopenharmony_ci  use OpenSSL::Test;
36e1051a39Sopenharmony_ci
37e1051a39Sopenharmony_ci  setup("my_test_name");
38e1051a39Sopenharmony_ci
39e1051a39Sopenharmony_ci  plan tests => 2;
40e1051a39Sopenharmony_ci
41e1051a39Sopenharmony_ci  ok(run(app(["openssl", "version"])), "check for openssl presence");
42e1051a39Sopenharmony_ci
43e1051a39Sopenharmony_ci  indir "subdir" => sub {
44e1051a39Sopenharmony_ci    ok(run(test(["sometest", "arg1"], stdout => "foo.txt")),
45e1051a39Sopenharmony_ci       "run sometest with output to foo.txt");
46e1051a39Sopenharmony_ci  };
47e1051a39Sopenharmony_ci
48e1051a39Sopenharmony_ci=head1 DESCRIPTION
49e1051a39Sopenharmony_ci
50e1051a39Sopenharmony_ciThis module is a private extension of L<Test::More> for testing OpenSSL.
51e1051a39Sopenharmony_ciIn addition to the Test::More functions, it also provides functions that
52e1051a39Sopenharmony_cieasily find the diverse programs within a OpenSSL build tree, as well as
53e1051a39Sopenharmony_cisome other useful functions.
54e1051a39Sopenharmony_ci
55e1051a39Sopenharmony_ciThis module I<depends> on the environment variables C<$TOP> or C<$SRCTOP>
56e1051a39Sopenharmony_ciand C<$BLDTOP>.  Without one of the combinations it refuses to work.
57e1051a39Sopenharmony_ciSee L</ENVIRONMENT> below.
58e1051a39Sopenharmony_ci
59e1051a39Sopenharmony_ciWith each test recipe, a parallel data directory with (almost) the same name
60e1051a39Sopenharmony_cias the recipe is possible in the source directory tree.  For example, for a
61e1051a39Sopenharmony_cirecipe C<$SRCTOP/test/recipes/99-foo.t>, there could be a directory
62e1051a39Sopenharmony_ciC<$SRCTOP/test/recipes/99-foo_data/>.
63e1051a39Sopenharmony_ci
64e1051a39Sopenharmony_ci=cut
65e1051a39Sopenharmony_ci
66e1051a39Sopenharmony_ciuse File::Copy;
67e1051a39Sopenharmony_ciuse File::Spec::Functions qw/file_name_is_absolute curdir canonpath splitdir
68e1051a39Sopenharmony_ci                             catdir catfile splitpath catpath devnull abs2rel/;
69e1051a39Sopenharmony_ciuse File::Path 2.00 qw/rmtree mkpath/;
70e1051a39Sopenharmony_ciuse File::Basename;
71e1051a39Sopenharmony_ciuse Cwd qw/getcwd abs_path/;
72e1051a39Sopenharmony_ciuse OpenSSL::Util;
73e1051a39Sopenharmony_ci
74e1051a39Sopenharmony_cimy $level = 0;
75e1051a39Sopenharmony_ci
76e1051a39Sopenharmony_ci# The name of the test.  This is set by setup() and is used in the other
77e1051a39Sopenharmony_ci# functions to verify that setup() has been used.
78e1051a39Sopenharmony_cimy $test_name = undef;
79e1051a39Sopenharmony_ci
80e1051a39Sopenharmony_ci# Directories we want to keep track of TOP, APPS, TEST and RESULTS are the
81e1051a39Sopenharmony_ci# ones we're interested in, corresponding to the environment variables TOP
82e1051a39Sopenharmony_ci# (mandatory), BIN_D, TEST_D, UTIL_D and RESULT_D.
83e1051a39Sopenharmony_cimy %directories = ();
84e1051a39Sopenharmony_ci
85e1051a39Sopenharmony_ci# The environment variables that gave us the contents in %directories.  These
86e1051a39Sopenharmony_ci# get modified whenever we change directories, so that subprocesses can use
87e1051a39Sopenharmony_ci# the values of those environment variables as well
88e1051a39Sopenharmony_cimy @direnv = ();
89e1051a39Sopenharmony_ci
90e1051a39Sopenharmony_ci# A bool saying if we shall stop all testing if the current recipe has failing
91e1051a39Sopenharmony_ci# tests or not.  This is set by setup() if the environment variable STOPTEST
92e1051a39Sopenharmony_ci# is defined with a non-empty value.
93e1051a39Sopenharmony_cimy $end_with_bailout = 0;
94e1051a39Sopenharmony_ci
95e1051a39Sopenharmony_ci# A set of hooks that is affected by with() and may be used in diverse places.
96e1051a39Sopenharmony_ci# All hooks are expected to be CODE references.
97e1051a39Sopenharmony_cimy %hooks = (
98e1051a39Sopenharmony_ci
99e1051a39Sopenharmony_ci    # exit_checker is used by run() directly after completion of a command.
100e1051a39Sopenharmony_ci    # it receives the exit code from that command and is expected to return
101e1051a39Sopenharmony_ci    # 1 (for success) or 0 (for failure).  This is the status value that run()
102e1051a39Sopenharmony_ci    # will give back (through the |statusvar| reference and as returned value
103e1051a39Sopenharmony_ci    # when capture => 1 doesn't apply).
104e1051a39Sopenharmony_ci    exit_checker => sub { return shift == 0 ? 1 : 0 },
105e1051a39Sopenharmony_ci
106e1051a39Sopenharmony_ci    );
107e1051a39Sopenharmony_ci
108e1051a39Sopenharmony_ci# Debug flag, to be set manually when needed
109e1051a39Sopenharmony_cimy $debug = 0;
110e1051a39Sopenharmony_ci
111e1051a39Sopenharmony_ci=head2 Main functions
112e1051a39Sopenharmony_ci
113e1051a39Sopenharmony_ciThe following functions are exported by default when using C<OpenSSL::Test>.
114e1051a39Sopenharmony_ci
115e1051a39Sopenharmony_ci=cut
116e1051a39Sopenharmony_ci
117e1051a39Sopenharmony_ci=over 4
118e1051a39Sopenharmony_ci
119e1051a39Sopenharmony_ci=item B<setup "NAME">
120e1051a39Sopenharmony_ci
121e1051a39Sopenharmony_ciC<setup> is used for initial setup, and it is mandatory that it's used.
122e1051a39Sopenharmony_ciIf it's not used in a OpenSSL test recipe, the rest of the recipe will
123e1051a39Sopenharmony_cimost likely refuse to run.
124e1051a39Sopenharmony_ci
125e1051a39Sopenharmony_ciC<setup> checks for environment variables (see L</ENVIRONMENT> below),
126e1051a39Sopenharmony_cichecks that C<$TOP/Configure> or C<$SRCTOP/Configure> exists, C<chdir>
127e1051a39Sopenharmony_ciinto the results directory (defined by the C<$RESULT_D> environment
128e1051a39Sopenharmony_civariable if defined, otherwise C<$BLDTOP/test-runs> or C<$TOP/test-runs>,
129e1051a39Sopenharmony_ciwhichever is defined).
130e1051a39Sopenharmony_ci
131e1051a39Sopenharmony_ci=back
132e1051a39Sopenharmony_ci
133e1051a39Sopenharmony_ci=cut
134e1051a39Sopenharmony_ci
135e1051a39Sopenharmony_cisub setup {
136e1051a39Sopenharmony_ci    my $old_test_name = $test_name;
137e1051a39Sopenharmony_ci    $test_name = shift;
138e1051a39Sopenharmony_ci    my %opts = @_;
139e1051a39Sopenharmony_ci
140e1051a39Sopenharmony_ci    BAIL_OUT("setup() must receive a name") unless $test_name;
141e1051a39Sopenharmony_ci    warn "setup() detected test name change.  Innocuous, so we continue...\n"
142e1051a39Sopenharmony_ci        if $old_test_name && $old_test_name ne $test_name;
143e1051a39Sopenharmony_ci
144e1051a39Sopenharmony_ci    return if $old_test_name;
145e1051a39Sopenharmony_ci
146e1051a39Sopenharmony_ci    BAIL_OUT("setup() needs \$TOP or \$SRCTOP and \$BLDTOP to be defined")
147e1051a39Sopenharmony_ci        unless $ENV{TOP} || ($ENV{SRCTOP} && $ENV{BLDTOP});
148e1051a39Sopenharmony_ci    BAIL_OUT("setup() found both \$TOP and \$SRCTOP or \$BLDTOP...")
149e1051a39Sopenharmony_ci        if $ENV{TOP} && ($ENV{SRCTOP} || $ENV{BLDTOP});
150e1051a39Sopenharmony_ci
151e1051a39Sopenharmony_ci    __env();
152e1051a39Sopenharmony_ci
153e1051a39Sopenharmony_ci    BAIL_OUT("setup() expects the file Configure in the source top directory")
154e1051a39Sopenharmony_ci        unless -f srctop_file("Configure");
155e1051a39Sopenharmony_ci
156e1051a39Sopenharmony_ci    note "The results of this test will end up in $directories{RESULTS}"
157e1051a39Sopenharmony_ci        unless $opts{quiet};
158e1051a39Sopenharmony_ci
159e1051a39Sopenharmony_ci    __cwd($directories{RESULTS});
160e1051a39Sopenharmony_ci}
161e1051a39Sopenharmony_ci
162e1051a39Sopenharmony_ci=over 4
163e1051a39Sopenharmony_ci
164e1051a39Sopenharmony_ci=item B<indir "SUBDIR" =E<gt> sub BLOCK, OPTS>
165e1051a39Sopenharmony_ci
166e1051a39Sopenharmony_ciC<indir> is used to run a part of the recipe in a different directory than
167e1051a39Sopenharmony_cithe one C<setup> moved into, usually a subdirectory, given by SUBDIR.
168e1051a39Sopenharmony_ciThe part of the recipe that's run there is given by the codeblock BLOCK.
169e1051a39Sopenharmony_ci
170e1051a39Sopenharmony_ciC<indir> takes some additional options OPTS that affect the subdirectory:
171e1051a39Sopenharmony_ci
172e1051a39Sopenharmony_ci=over 4
173e1051a39Sopenharmony_ci
174e1051a39Sopenharmony_ci=item B<create =E<gt> 0|1>
175e1051a39Sopenharmony_ci
176e1051a39Sopenharmony_ciWhen set to 1 (or any value that perl perceives as true), the subdirectory
177e1051a39Sopenharmony_ciwill be created if it doesn't already exist.  This happens before BLOCK
178e1051a39Sopenharmony_ciis executed.
179e1051a39Sopenharmony_ci
180e1051a39Sopenharmony_ci=back
181e1051a39Sopenharmony_ci
182e1051a39Sopenharmony_ciAn example:
183e1051a39Sopenharmony_ci
184e1051a39Sopenharmony_ci  indir "foo" => sub {
185e1051a39Sopenharmony_ci      ok(run(app(["openssl", "version"]), stdout => "foo.txt"));
186e1051a39Sopenharmony_ci      if (ok(open(RESULT, "foo.txt"), "reading foo.txt")) {
187e1051a39Sopenharmony_ci          my $line = <RESULT>;
188e1051a39Sopenharmony_ci          close RESULT;
189e1051a39Sopenharmony_ci          is($line, qr/^OpenSSL 1\./,
190e1051a39Sopenharmony_ci             "check that we're using OpenSSL 1.x.x");
191e1051a39Sopenharmony_ci      }
192e1051a39Sopenharmony_ci  }, create => 1;
193e1051a39Sopenharmony_ci
194e1051a39Sopenharmony_ci=back
195e1051a39Sopenharmony_ci
196e1051a39Sopenharmony_ci=cut
197e1051a39Sopenharmony_ci
198e1051a39Sopenharmony_cisub indir {
199e1051a39Sopenharmony_ci    my $subdir = shift;
200e1051a39Sopenharmony_ci    my $codeblock = shift;
201e1051a39Sopenharmony_ci    my %opts = @_;
202e1051a39Sopenharmony_ci
203e1051a39Sopenharmony_ci    my $reverse = __cwd($subdir,%opts);
204e1051a39Sopenharmony_ci    BAIL_OUT("FAILURE: indir, \"$subdir\" wasn't possible to move into")
205e1051a39Sopenharmony_ci	unless $reverse;
206e1051a39Sopenharmony_ci
207e1051a39Sopenharmony_ci    $codeblock->();
208e1051a39Sopenharmony_ci
209e1051a39Sopenharmony_ci    __cwd($reverse);
210e1051a39Sopenharmony_ci}
211e1051a39Sopenharmony_ci
212e1051a39Sopenharmony_ci=over 4
213e1051a39Sopenharmony_ci
214e1051a39Sopenharmony_ci=item B<cmd ARRAYREF, OPTS>
215e1051a39Sopenharmony_ci
216e1051a39Sopenharmony_ciThis functions build up a platform dependent command based on the
217e1051a39Sopenharmony_ciinput.  It takes a reference to a list that is the executable or
218e1051a39Sopenharmony_ciscript and its arguments, and some additional options (described
219e1051a39Sopenharmony_cifurther on).  Where necessary, the command will be wrapped in a
220e1051a39Sopenharmony_cisuitable environment to make sure the correct shared libraries are
221e1051a39Sopenharmony_ciused (currently only on Unix).
222e1051a39Sopenharmony_ci
223e1051a39Sopenharmony_ciIt returns a CODEREF to be used by C<run>, C<pipe> or C<cmdstr>.
224e1051a39Sopenharmony_ci
225e1051a39Sopenharmony_ciThe options that C<cmd> (as well as its derivatives described below) can take
226e1051a39Sopenharmony_ciare in the form of hash values:
227e1051a39Sopenharmony_ci
228e1051a39Sopenharmony_ci=over 4
229e1051a39Sopenharmony_ci
230e1051a39Sopenharmony_ci=item B<stdin =E<gt> PATH>
231e1051a39Sopenharmony_ci
232e1051a39Sopenharmony_ci=item B<stdout =E<gt> PATH>
233e1051a39Sopenharmony_ci
234e1051a39Sopenharmony_ci=item B<stderr =E<gt> PATH>
235e1051a39Sopenharmony_ci
236e1051a39Sopenharmony_ciIn all three cases, the corresponding standard input, output or error is
237e1051a39Sopenharmony_ciredirected from (for stdin) or to (for the others) a file given by the
238e1051a39Sopenharmony_cistring PATH, I<or>, if the value is C<undef>, C</dev/null> or similar.
239e1051a39Sopenharmony_ci
240e1051a39Sopenharmony_ci=back
241e1051a39Sopenharmony_ci
242e1051a39Sopenharmony_ci=item B<app ARRAYREF, OPTS>
243e1051a39Sopenharmony_ci
244e1051a39Sopenharmony_ci=item B<test ARRAYREF, OPTS>
245e1051a39Sopenharmony_ci
246e1051a39Sopenharmony_ciBoth of these are specific applications of C<cmd>, with just a couple
247e1051a39Sopenharmony_ciof small difference:
248e1051a39Sopenharmony_ci
249e1051a39Sopenharmony_ciC<app> expects to find the given command (the first item in the given list
250e1051a39Sopenharmony_cireference) as an executable in C<$BIN_D> (if defined, otherwise C<$TOP/apps>
251e1051a39Sopenharmony_cior C<$BLDTOP/apps>).
252e1051a39Sopenharmony_ci
253e1051a39Sopenharmony_ciC<test> expects to find the given command (the first item in the given list
254e1051a39Sopenharmony_cireference) as an executable in C<$TEST_D> (if defined, otherwise C<$TOP/test>
255e1051a39Sopenharmony_cior C<$BLDTOP/test>).
256e1051a39Sopenharmony_ci
257e1051a39Sopenharmony_ciAlso, for both C<app> and C<test>, the command may be prefixed with
258e1051a39Sopenharmony_cithe content of the environment variable C<$EXE_SHELL>, which is useful
259e1051a39Sopenharmony_ciin case OpenSSL has been cross compiled.
260e1051a39Sopenharmony_ci
261e1051a39Sopenharmony_ci=item B<perlapp ARRAYREF, OPTS>
262e1051a39Sopenharmony_ci
263e1051a39Sopenharmony_ci=item B<perltest ARRAYREF, OPTS>
264e1051a39Sopenharmony_ci
265e1051a39Sopenharmony_ciThese are also specific applications of C<cmd>, where the interpreter
266e1051a39Sopenharmony_ciis predefined to be C<perl>, and they expect the script to be
267e1051a39Sopenharmony_ciinterpreted to reside in the same location as C<app> and C<test>.
268e1051a39Sopenharmony_ci
269e1051a39Sopenharmony_ciC<perlapp> and C<perltest> will also take the following option:
270e1051a39Sopenharmony_ci
271e1051a39Sopenharmony_ci=over 4
272e1051a39Sopenharmony_ci
273e1051a39Sopenharmony_ci=item B<interpreter_args =E<gt> ARRAYref>
274e1051a39Sopenharmony_ci
275e1051a39Sopenharmony_ciThe array reference is a set of arguments for the interpreter rather
276e1051a39Sopenharmony_cithan the script.  Take care so that none of them can be seen as a
277e1051a39Sopenharmony_ciscript!  Flags and their eventual arguments only!
278e1051a39Sopenharmony_ci
279e1051a39Sopenharmony_ci=back
280e1051a39Sopenharmony_ci
281e1051a39Sopenharmony_ciAn example:
282e1051a39Sopenharmony_ci
283e1051a39Sopenharmony_ci  ok(run(perlapp(["foo.pl", "arg1"],
284e1051a39Sopenharmony_ci                 interpreter_args => [ "-I", srctop_dir("test") ])));
285e1051a39Sopenharmony_ci
286e1051a39Sopenharmony_ci=back
287e1051a39Sopenharmony_ci
288e1051a39Sopenharmony_ci=begin comment
289e1051a39Sopenharmony_ci
290e1051a39Sopenharmony_ciOne might wonder over the complexity of C<apps>, C<fuzz>, C<test>, ...
291e1051a39Sopenharmony_ciwith all the lazy evaluations and all that.  The reason for this is that
292e1051a39Sopenharmony_ciwe want to make sure the directory in which those programs are found are
293e1051a39Sopenharmony_cicorrect at the time these commands are used.  Consider the following code
294e1051a39Sopenharmony_cisnippet:
295e1051a39Sopenharmony_ci
296e1051a39Sopenharmony_ci  my $cmd = app(["openssl", ...]);
297e1051a39Sopenharmony_ci
298e1051a39Sopenharmony_ci  indir "foo", sub {
299e1051a39Sopenharmony_ci      ok(run($cmd), "Testing foo")
300e1051a39Sopenharmony_ci  };
301e1051a39Sopenharmony_ci
302e1051a39Sopenharmony_ciIf there wasn't this lazy evaluation, the directory where C<openssl> is
303e1051a39Sopenharmony_cifound would be incorrect at the time C<run> is called, because it was
304e1051a39Sopenharmony_cicalculated before we moved into the directory "foo".
305e1051a39Sopenharmony_ci
306e1051a39Sopenharmony_ci=end comment
307e1051a39Sopenharmony_ci
308e1051a39Sopenharmony_ci=cut
309e1051a39Sopenharmony_ci
310e1051a39Sopenharmony_cisub cmd {
311e1051a39Sopenharmony_ci    my $cmd = shift;
312e1051a39Sopenharmony_ci    my %opts = @_;
313e1051a39Sopenharmony_ci    return sub {
314e1051a39Sopenharmony_ci        my $num = shift;
315e1051a39Sopenharmony_ci        # Make a copy to not destroy the caller's array
316e1051a39Sopenharmony_ci        my @cmdargs = ( @$cmd );
317e1051a39Sopenharmony_ci        my @prog = __wrap_cmd(shift @cmdargs, $opts{exe_shell} // ());
318e1051a39Sopenharmony_ci
319e1051a39Sopenharmony_ci        return __decorate_cmd($num, [ @prog, fixup_cmd_elements(@cmdargs) ],
320e1051a39Sopenharmony_ci                              %opts);
321e1051a39Sopenharmony_ci    }
322e1051a39Sopenharmony_ci}
323e1051a39Sopenharmony_ci
324e1051a39Sopenharmony_cisub app {
325e1051a39Sopenharmony_ci    my $cmd = shift;
326e1051a39Sopenharmony_ci    my %opts = @_;
327e1051a39Sopenharmony_ci    return sub {
328e1051a39Sopenharmony_ci        my @cmdargs = ( @{$cmd} );
329e1051a39Sopenharmony_ci        my @prog = __fixup_prg(__apps_file(shift @cmdargs, __exeext()));
330e1051a39Sopenharmony_ci        return cmd([ @prog, @cmdargs ],
331e1051a39Sopenharmony_ci                   exe_shell => $ENV{EXE_SHELL}, %opts) -> (shift);
332e1051a39Sopenharmony_ci    }
333e1051a39Sopenharmony_ci}
334e1051a39Sopenharmony_ci
335e1051a39Sopenharmony_cisub fuzz {
336e1051a39Sopenharmony_ci    my $cmd = shift;
337e1051a39Sopenharmony_ci    my %opts = @_;
338e1051a39Sopenharmony_ci    return sub {
339e1051a39Sopenharmony_ci        my @cmdargs = ( @{$cmd} );
340e1051a39Sopenharmony_ci        my @prog = __fixup_prg(__fuzz_file(shift @cmdargs, __exeext()));
341e1051a39Sopenharmony_ci        return cmd([ @prog, @cmdargs ],
342e1051a39Sopenharmony_ci                   exe_shell => $ENV{EXE_SHELL}, %opts) -> (shift);
343e1051a39Sopenharmony_ci    }
344e1051a39Sopenharmony_ci}
345e1051a39Sopenharmony_ci
346e1051a39Sopenharmony_cisub test {
347e1051a39Sopenharmony_ci    my $cmd = shift;
348e1051a39Sopenharmony_ci    my %opts = @_;
349e1051a39Sopenharmony_ci    return sub {
350e1051a39Sopenharmony_ci        my @cmdargs = ( @{$cmd} );
351e1051a39Sopenharmony_ci        my @prog = __fixup_prg(__test_file(shift @cmdargs, __exeext()));
352e1051a39Sopenharmony_ci        return cmd([ @prog, @cmdargs ],
353e1051a39Sopenharmony_ci                   exe_shell => $ENV{EXE_SHELL}, %opts) -> (shift);
354e1051a39Sopenharmony_ci    }
355e1051a39Sopenharmony_ci}
356e1051a39Sopenharmony_ci
357e1051a39Sopenharmony_cisub perlapp {
358e1051a39Sopenharmony_ci    my $cmd = shift;
359e1051a39Sopenharmony_ci    my %opts = @_;
360e1051a39Sopenharmony_ci    return sub {
361e1051a39Sopenharmony_ci        my @interpreter_args = defined $opts{interpreter_args} ?
362e1051a39Sopenharmony_ci            @{$opts{interpreter_args}} : ();
363e1051a39Sopenharmony_ci        my @interpreter = __fixup_prg($^X);
364e1051a39Sopenharmony_ci        my @cmdargs = ( @{$cmd} );
365e1051a39Sopenharmony_ci        my @prog = __apps_file(shift @cmdargs, undef);
366e1051a39Sopenharmony_ci        return cmd([ @interpreter, @interpreter_args,
367e1051a39Sopenharmony_ci                     @prog, @cmdargs ], %opts) -> (shift);
368e1051a39Sopenharmony_ci    }
369e1051a39Sopenharmony_ci}
370e1051a39Sopenharmony_ci
371e1051a39Sopenharmony_cisub perltest {
372e1051a39Sopenharmony_ci    my $cmd = shift;
373e1051a39Sopenharmony_ci    my %opts = @_;
374e1051a39Sopenharmony_ci    return sub {
375e1051a39Sopenharmony_ci        my @interpreter_args = defined $opts{interpreter_args} ?
376e1051a39Sopenharmony_ci            @{$opts{interpreter_args}} : ();
377e1051a39Sopenharmony_ci        my @interpreter = __fixup_prg($^X);
378e1051a39Sopenharmony_ci        my @cmdargs = ( @{$cmd} );
379e1051a39Sopenharmony_ci        my @prog = __test_file(shift @cmdargs, undef);
380e1051a39Sopenharmony_ci        return cmd([ @interpreter, @interpreter_args,
381e1051a39Sopenharmony_ci                     @prog, @cmdargs ], %opts) -> (shift);
382e1051a39Sopenharmony_ci    }
383e1051a39Sopenharmony_ci}
384e1051a39Sopenharmony_ci
385e1051a39Sopenharmony_ci=over 4
386e1051a39Sopenharmony_ci
387e1051a39Sopenharmony_ci=item B<run CODEREF, OPTS>
388e1051a39Sopenharmony_ci
389e1051a39Sopenharmony_ciCODEREF is expected to be the value return by C<cmd> or any of its
390e1051a39Sopenharmony_ciderivatives, anything else will most likely cause an error unless you
391e1051a39Sopenharmony_ciknow what you're doing.
392e1051a39Sopenharmony_ci
393e1051a39Sopenharmony_ciC<run> executes the command returned by CODEREF and return either the
394e1051a39Sopenharmony_ciresulting standard output (if the option C<capture> is set true) or a boolean
395e1051a39Sopenharmony_ciindicating if the command succeeded or not.
396e1051a39Sopenharmony_ci
397e1051a39Sopenharmony_ciThe options that C<run> can take are in the form of hash values:
398e1051a39Sopenharmony_ci
399e1051a39Sopenharmony_ci=over 4
400e1051a39Sopenharmony_ci
401e1051a39Sopenharmony_ci=item B<capture =E<gt> 0|1>
402e1051a39Sopenharmony_ci
403e1051a39Sopenharmony_ciIf true, the command will be executed with a perl backtick,
404e1051a39Sopenharmony_ciand C<run> will return the resulting standard output as an array of lines.
405e1051a39Sopenharmony_ciIf false or not given, the command will be executed with C<system()>,
406e1051a39Sopenharmony_ciand C<run> will return 1 if the command was successful or 0 if it wasn't.
407e1051a39Sopenharmony_ci
408e1051a39Sopenharmony_ci=item B<prefix =E<gt> EXPR>
409e1051a39Sopenharmony_ci
410e1051a39Sopenharmony_ciIf specified, EXPR will be used as a string to prefix the output from the
411e1051a39Sopenharmony_cicommand.  This is useful if the output contains lines starting with C<ok >
412e1051a39Sopenharmony_cior C<not ok > that can disturb Test::Harness.
413e1051a39Sopenharmony_ci
414e1051a39Sopenharmony_ci=item B<statusvar =E<gt> VARREF>
415e1051a39Sopenharmony_ci
416e1051a39Sopenharmony_ciIf used, B<VARREF> must be a reference to a scalar variable.  It will be
417e1051a39Sopenharmony_ciassigned a boolean indicating if the command succeeded or not.  This is
418e1051a39Sopenharmony_ciparticularly useful together with B<capture>.
419e1051a39Sopenharmony_ci
420e1051a39Sopenharmony_ci=back
421e1051a39Sopenharmony_ci
422e1051a39Sopenharmony_ciUsually 1 indicates that the command was successful and 0 indicates failure.
423e1051a39Sopenharmony_ciFor further discussion on what is considered a successful command or not, see
424e1051a39Sopenharmony_cithe function C<with> further down.
425e1051a39Sopenharmony_ci
426e1051a39Sopenharmony_ci=back
427e1051a39Sopenharmony_ci
428e1051a39Sopenharmony_ci=cut
429e1051a39Sopenharmony_ci
430e1051a39Sopenharmony_cisub run {
431e1051a39Sopenharmony_ci    my ($cmd, $display_cmd) = shift->(0);
432e1051a39Sopenharmony_ci    my %opts = @_;
433e1051a39Sopenharmony_ci
434e1051a39Sopenharmony_ci    return () if !$cmd;
435e1051a39Sopenharmony_ci
436e1051a39Sopenharmony_ci    my $prefix = "";
437e1051a39Sopenharmony_ci    if ( $^O eq "VMS" ) {	# VMS
438e1051a39Sopenharmony_ci	$prefix = "pipe ";
439e1051a39Sopenharmony_ci    }
440e1051a39Sopenharmony_ci
441e1051a39Sopenharmony_ci    my @r = ();
442e1051a39Sopenharmony_ci    my $r = 0;
443e1051a39Sopenharmony_ci    my $e = 0;
444e1051a39Sopenharmony_ci
445e1051a39Sopenharmony_ci    die "OpenSSL::Test::run(): statusvar value not a scalar reference"
446e1051a39Sopenharmony_ci        if $opts{statusvar} && ref($opts{statusvar}) ne "SCALAR";
447e1051a39Sopenharmony_ci
448e1051a39Sopenharmony_ci    # For some reason, program output, or even output from this function
449e1051a39Sopenharmony_ci    # somehow isn't caught by TAP::Harness (TAP::Parser?) on VMS, so we're
450e1051a39Sopenharmony_ci    # silencing it specifically there until further notice.
451e1051a39Sopenharmony_ci    my $save_STDOUT;
452e1051a39Sopenharmony_ci    my $save_STDERR;
453e1051a39Sopenharmony_ci    if ($^O eq 'VMS') {
454e1051a39Sopenharmony_ci        # In non-verbose, we want to shut up the command interpreter, in case
455e1051a39Sopenharmony_ci        # it has something to complain about.  On VMS, it might complain both
456e1051a39Sopenharmony_ci        # on stdout and stderr
457e1051a39Sopenharmony_ci        if ($ENV{HARNESS_ACTIVE} && !$ENV{HARNESS_VERBOSE}) {
458e1051a39Sopenharmony_ci            open $save_STDOUT, '>&', \*STDOUT or die "Can't dup STDOUT: $!";
459e1051a39Sopenharmony_ci            open $save_STDERR, '>&', \*STDERR or die "Can't dup STDERR: $!";
460e1051a39Sopenharmony_ci            open STDOUT, ">", devnull();
461e1051a39Sopenharmony_ci            open STDERR, ">", devnull();
462e1051a39Sopenharmony_ci        }
463e1051a39Sopenharmony_ci    }
464e1051a39Sopenharmony_ci
465e1051a39Sopenharmony_ci    $ENV{HARNESS_OSSL_LEVEL} = $level + 1;
466e1051a39Sopenharmony_ci
467e1051a39Sopenharmony_ci    # The dance we do with $? is the same dance the Unix shells appear to
468e1051a39Sopenharmony_ci    # do.  For example, a program that gets aborted (and therefore signals
469e1051a39Sopenharmony_ci    # SIGABRT = 6) will appear to exit with the code 134.  We mimic this
470e1051a39Sopenharmony_ci    # to make it easier to compare with a manual run of the command.
471e1051a39Sopenharmony_ci    if ($opts{capture} || defined($opts{prefix})) {
472e1051a39Sopenharmony_ci	my $pipe;
473e1051a39Sopenharmony_ci	local $_;
474e1051a39Sopenharmony_ci
475e1051a39Sopenharmony_ci	open($pipe, '-|', "$prefix$cmd") or die "Can't start command: $!";
476e1051a39Sopenharmony_ci	while(<$pipe>) {
477e1051a39Sopenharmony_ci	    my $l = ($opts{prefix} // "") . $_;
478e1051a39Sopenharmony_ci	    if ($opts{capture}) {
479e1051a39Sopenharmony_ci		push @r, $l;
480e1051a39Sopenharmony_ci	    } else {
481e1051a39Sopenharmony_ci		print STDOUT $l;
482e1051a39Sopenharmony_ci	    }
483e1051a39Sopenharmony_ci	}
484e1051a39Sopenharmony_ci	close $pipe;
485e1051a39Sopenharmony_ci    } else {
486e1051a39Sopenharmony_ci	$ENV{HARNESS_OSSL_PREFIX} = "# ";
487e1051a39Sopenharmony_ci	system("$prefix$cmd");
488e1051a39Sopenharmony_ci	delete $ENV{HARNESS_OSSL_PREFIX};
489e1051a39Sopenharmony_ci    }
490e1051a39Sopenharmony_ci    $e = ($? & 0x7f) ? ($? & 0x7f)|0x80 : ($? >> 8);
491e1051a39Sopenharmony_ci    $r = $hooks{exit_checker}->($e);
492e1051a39Sopenharmony_ci    if ($opts{statusvar}) {
493e1051a39Sopenharmony_ci        ${$opts{statusvar}} = $r;
494e1051a39Sopenharmony_ci    }
495e1051a39Sopenharmony_ci
496e1051a39Sopenharmony_ci    # Restore STDOUT / STDERR on VMS
497e1051a39Sopenharmony_ci    if ($^O eq 'VMS') {
498e1051a39Sopenharmony_ci        if ($ENV{HARNESS_ACTIVE} && !$ENV{HARNESS_VERBOSE}) {
499e1051a39Sopenharmony_ci            close STDOUT;
500e1051a39Sopenharmony_ci            close STDERR;
501e1051a39Sopenharmony_ci            open STDOUT, '>&', $save_STDOUT or die "Can't restore STDOUT: $!";
502e1051a39Sopenharmony_ci            open STDERR, '>&', $save_STDERR or die "Can't restore STDERR: $!";
503e1051a39Sopenharmony_ci        }
504e1051a39Sopenharmony_ci
505e1051a39Sopenharmony_ci        print STDERR "$prefix$display_cmd => $e\n"
506e1051a39Sopenharmony_ci            if !$ENV{HARNESS_ACTIVE} || $ENV{HARNESS_VERBOSE};
507e1051a39Sopenharmony_ci    } else {
508e1051a39Sopenharmony_ci        print STDERR "$prefix$display_cmd => $e\n";
509e1051a39Sopenharmony_ci    }
510e1051a39Sopenharmony_ci
511e1051a39Sopenharmony_ci    # At this point, $? stops being interesting, and unfortunately,
512e1051a39Sopenharmony_ci    # there are Test::More versions that get picky if we leave it
513e1051a39Sopenharmony_ci    # non-zero.
514e1051a39Sopenharmony_ci    $? = 0;
515e1051a39Sopenharmony_ci
516e1051a39Sopenharmony_ci    if ($opts{capture}) {
517e1051a39Sopenharmony_ci	return @r;
518e1051a39Sopenharmony_ci    } else {
519e1051a39Sopenharmony_ci	return $r;
520e1051a39Sopenharmony_ci    }
521e1051a39Sopenharmony_ci}
522e1051a39Sopenharmony_ci
523e1051a39Sopenharmony_ciEND {
524e1051a39Sopenharmony_ci    my $tb = Test::More->builder;
525e1051a39Sopenharmony_ci    my $failure = scalar(grep { $_ == 0; } $tb->summary);
526e1051a39Sopenharmony_ci    if ($failure && $end_with_bailout) {
527e1051a39Sopenharmony_ci	BAIL_OUT("Stoptest!");
528e1051a39Sopenharmony_ci    }
529e1051a39Sopenharmony_ci}
530e1051a39Sopenharmony_ci
531e1051a39Sopenharmony_ci=head2 Utility functions
532e1051a39Sopenharmony_ci
533e1051a39Sopenharmony_ciThe following functions are exported on request when using C<OpenSSL::Test>.
534e1051a39Sopenharmony_ci
535e1051a39Sopenharmony_ci  # To only get the bldtop_file and srctop_file functions.
536e1051a39Sopenharmony_ci  use OpenSSL::Test qw/bldtop_file srctop_file/;
537e1051a39Sopenharmony_ci
538e1051a39Sopenharmony_ci  # To only get the bldtop_file function in addition to the default ones.
539e1051a39Sopenharmony_ci  use OpenSSL::Test qw/:DEFAULT bldtop_file/;
540e1051a39Sopenharmony_ci
541e1051a39Sopenharmony_ci=cut
542e1051a39Sopenharmony_ci
543e1051a39Sopenharmony_ci# Utility functions, exported on request
544e1051a39Sopenharmony_ci
545e1051a39Sopenharmony_ci=over 4
546e1051a39Sopenharmony_ci
547e1051a39Sopenharmony_ci=item B<bldtop_dir LIST>
548e1051a39Sopenharmony_ci
549e1051a39Sopenharmony_ciLIST is a list of directories that make up a path from the top of the OpenSSL
550e1051a39Sopenharmony_cibuild directory (as indicated by the environment variable C<$TOP> or
551e1051a39Sopenharmony_ciC<$BLDTOP>).
552e1051a39Sopenharmony_ciC<bldtop_dir> returns the resulting directory as a string, adapted to the local
553e1051a39Sopenharmony_cioperating system.
554e1051a39Sopenharmony_ci
555e1051a39Sopenharmony_ci=back
556e1051a39Sopenharmony_ci
557e1051a39Sopenharmony_ci=cut
558e1051a39Sopenharmony_ci
559e1051a39Sopenharmony_cisub bldtop_dir {
560e1051a39Sopenharmony_ci    return __bldtop_dir(@_);	# This caters for operating systems that have
561e1051a39Sopenharmony_ci				# a very distinct syntax for directories.
562e1051a39Sopenharmony_ci}
563e1051a39Sopenharmony_ci
564e1051a39Sopenharmony_ci=over 4
565e1051a39Sopenharmony_ci
566e1051a39Sopenharmony_ci=item B<bldtop_file LIST, FILENAME>
567e1051a39Sopenharmony_ci
568e1051a39Sopenharmony_ciLIST is a list of directories that make up a path from the top of the OpenSSL
569e1051a39Sopenharmony_cibuild directory (as indicated by the environment variable C<$TOP> or
570e1051a39Sopenharmony_ciC<$BLDTOP>) and FILENAME is the name of a file located in that directory path.
571e1051a39Sopenharmony_ciC<bldtop_file> returns the resulting file path as a string, adapted to the local
572e1051a39Sopenharmony_cioperating system.
573e1051a39Sopenharmony_ci
574e1051a39Sopenharmony_ci=back
575e1051a39Sopenharmony_ci
576e1051a39Sopenharmony_ci=cut
577e1051a39Sopenharmony_ci
578e1051a39Sopenharmony_cisub bldtop_file {
579e1051a39Sopenharmony_ci    return __bldtop_file(@_);
580e1051a39Sopenharmony_ci}
581e1051a39Sopenharmony_ci
582e1051a39Sopenharmony_ci=over 4
583e1051a39Sopenharmony_ci
584e1051a39Sopenharmony_ci=item B<srctop_dir LIST>
585e1051a39Sopenharmony_ci
586e1051a39Sopenharmony_ciLIST is a list of directories that make up a path from the top of the OpenSSL
587e1051a39Sopenharmony_cisource directory (as indicated by the environment variable C<$TOP> or
588e1051a39Sopenharmony_ciC<$SRCTOP>).
589e1051a39Sopenharmony_ciC<srctop_dir> returns the resulting directory as a string, adapted to the local
590e1051a39Sopenharmony_cioperating system.
591e1051a39Sopenharmony_ci
592e1051a39Sopenharmony_ci=back
593e1051a39Sopenharmony_ci
594e1051a39Sopenharmony_ci=cut
595e1051a39Sopenharmony_ci
596e1051a39Sopenharmony_cisub srctop_dir {
597e1051a39Sopenharmony_ci    return __srctop_dir(@_);	# This caters for operating systems that have
598e1051a39Sopenharmony_ci				# a very distinct syntax for directories.
599e1051a39Sopenharmony_ci}
600e1051a39Sopenharmony_ci
601e1051a39Sopenharmony_ci=over 4
602e1051a39Sopenharmony_ci
603e1051a39Sopenharmony_ci=item B<srctop_file LIST, FILENAME>
604e1051a39Sopenharmony_ci
605e1051a39Sopenharmony_ciLIST is a list of directories that make up a path from the top of the OpenSSL
606e1051a39Sopenharmony_cisource directory (as indicated by the environment variable C<$TOP> or
607e1051a39Sopenharmony_ciC<$SRCTOP>) and FILENAME is the name of a file located in that directory path.
608e1051a39Sopenharmony_ciC<srctop_file> returns the resulting file path as a string, adapted to the local
609e1051a39Sopenharmony_cioperating system.
610e1051a39Sopenharmony_ci
611e1051a39Sopenharmony_ci=back
612e1051a39Sopenharmony_ci
613e1051a39Sopenharmony_ci=cut
614e1051a39Sopenharmony_ci
615e1051a39Sopenharmony_cisub srctop_file {
616e1051a39Sopenharmony_ci    return __srctop_file(@_);
617e1051a39Sopenharmony_ci}
618e1051a39Sopenharmony_ci
619e1051a39Sopenharmony_ci=over 4
620e1051a39Sopenharmony_ci
621e1051a39Sopenharmony_ci=item B<data_dir LIST>
622e1051a39Sopenharmony_ci
623e1051a39Sopenharmony_ciLIST is a list of directories that make up a path from the data directory
624e1051a39Sopenharmony_ciassociated with the test (see L</DESCRIPTION> above).
625e1051a39Sopenharmony_ciC<data_dir> returns the resulting directory as a string, adapted to the local
626e1051a39Sopenharmony_cioperating system.
627e1051a39Sopenharmony_ci
628e1051a39Sopenharmony_ci=back
629e1051a39Sopenharmony_ci
630e1051a39Sopenharmony_ci=cut
631e1051a39Sopenharmony_ci
632e1051a39Sopenharmony_cisub data_dir {
633e1051a39Sopenharmony_ci    return __data_dir(@_);
634e1051a39Sopenharmony_ci}
635e1051a39Sopenharmony_ci
636e1051a39Sopenharmony_ci=over 4
637e1051a39Sopenharmony_ci
638e1051a39Sopenharmony_ci=item B<data_file LIST, FILENAME>
639e1051a39Sopenharmony_ci
640e1051a39Sopenharmony_ciLIST is a list of directories that make up a path from the data directory
641e1051a39Sopenharmony_ciassociated with the test (see L</DESCRIPTION> above) and FILENAME is the name
642e1051a39Sopenharmony_ciof a file located in that directory path.  C<data_file> returns the resulting
643e1051a39Sopenharmony_cifile path as a string, adapted to the local operating system.
644e1051a39Sopenharmony_ci
645e1051a39Sopenharmony_ci=back
646e1051a39Sopenharmony_ci
647e1051a39Sopenharmony_ci=cut
648e1051a39Sopenharmony_ci
649e1051a39Sopenharmony_cisub data_file {
650e1051a39Sopenharmony_ci    return __data_file(@_);
651e1051a39Sopenharmony_ci}
652e1051a39Sopenharmony_ci
653e1051a39Sopenharmony_ci=over 4
654e1051a39Sopenharmony_ci
655e1051a39Sopenharmony_ci=item B<result_dir>
656e1051a39Sopenharmony_ci
657e1051a39Sopenharmony_ciC<result_dir> returns the directory where test output files should be placed
658e1051a39Sopenharmony_cias a string, adapted to the local operating system.
659e1051a39Sopenharmony_ci
660e1051a39Sopenharmony_ci=back
661e1051a39Sopenharmony_ci
662e1051a39Sopenharmony_ci=cut
663e1051a39Sopenharmony_ci
664e1051a39Sopenharmony_cisub result_dir {
665e1051a39Sopenharmony_ci    BAIL_OUT("Must run setup() first") if (! $test_name);
666e1051a39Sopenharmony_ci
667e1051a39Sopenharmony_ci    return catfile($directories{RESULTS});
668e1051a39Sopenharmony_ci}
669e1051a39Sopenharmony_ci
670e1051a39Sopenharmony_ci=over 4
671e1051a39Sopenharmony_ci
672e1051a39Sopenharmony_ci=item B<result_file FILENAME>
673e1051a39Sopenharmony_ci
674e1051a39Sopenharmony_ciFILENAME is the name of a test output file.
675e1051a39Sopenharmony_ciC<result_file> returns the path of the given file as a string,
676e1051a39Sopenharmony_ciprepending to the file name the path to the directory where test output files
677e1051a39Sopenharmony_cishould be placed, adapted to the local operating system.
678e1051a39Sopenharmony_ci
679e1051a39Sopenharmony_ci=back
680e1051a39Sopenharmony_ci
681e1051a39Sopenharmony_ci=cut
682e1051a39Sopenharmony_ci
683e1051a39Sopenharmony_cisub result_file {
684e1051a39Sopenharmony_ci    BAIL_OUT("Must run setup() first") if (! $test_name);
685e1051a39Sopenharmony_ci
686e1051a39Sopenharmony_ci    my $f = pop;
687e1051a39Sopenharmony_ci    return catfile(result_dir(),@_,$f);
688e1051a39Sopenharmony_ci}
689e1051a39Sopenharmony_ci
690e1051a39Sopenharmony_ci=over 4
691e1051a39Sopenharmony_ci
692e1051a39Sopenharmony_ci=item B<pipe LIST>
693e1051a39Sopenharmony_ci
694e1051a39Sopenharmony_ciLIST is a list of CODEREFs returned by C<app> or C<test>, from which C<pipe>
695e1051a39Sopenharmony_cicreates a new command composed of all the given commands put together in a
696e1051a39Sopenharmony_cipipe.  C<pipe> returns a new CODEREF in the same manner as C<app> or C<test>,
697e1051a39Sopenharmony_cito be passed to C<run> for execution.
698e1051a39Sopenharmony_ci
699e1051a39Sopenharmony_ci=back
700e1051a39Sopenharmony_ci
701e1051a39Sopenharmony_ci=cut
702e1051a39Sopenharmony_ci
703e1051a39Sopenharmony_cisub pipe {
704e1051a39Sopenharmony_ci    my @cmds = @_;
705e1051a39Sopenharmony_ci    return
706e1051a39Sopenharmony_ci	sub {
707e1051a39Sopenharmony_ci	    my @cs  = ();
708e1051a39Sopenharmony_ci	    my @dcs = ();
709e1051a39Sopenharmony_ci	    my @els = ();
710e1051a39Sopenharmony_ci	    my $counter = 0;
711e1051a39Sopenharmony_ci	    foreach (@cmds) {
712e1051a39Sopenharmony_ci		my ($c, $dc, @el) = $_->(++$counter);
713e1051a39Sopenharmony_ci
714e1051a39Sopenharmony_ci		return () if !$c;
715e1051a39Sopenharmony_ci
716e1051a39Sopenharmony_ci		push @cs, $c;
717e1051a39Sopenharmony_ci		push @dcs, $dc;
718e1051a39Sopenharmony_ci		push @els, @el;
719e1051a39Sopenharmony_ci	    }
720e1051a39Sopenharmony_ci	    return (
721e1051a39Sopenharmony_ci		join(" | ", @cs),
722e1051a39Sopenharmony_ci		join(" | ", @dcs),
723e1051a39Sopenharmony_ci		@els
724e1051a39Sopenharmony_ci		);
725e1051a39Sopenharmony_ci    };
726e1051a39Sopenharmony_ci}
727e1051a39Sopenharmony_ci
728e1051a39Sopenharmony_ci=over 4
729e1051a39Sopenharmony_ci
730e1051a39Sopenharmony_ci=item B<with HASHREF, CODEREF>
731e1051a39Sopenharmony_ci
732e1051a39Sopenharmony_ciC<with> will temporarily install hooks given by the HASHREF and then execute
733e1051a39Sopenharmony_cithe given CODEREF.  Hooks are usually expected to have a coderef as value.
734e1051a39Sopenharmony_ci
735e1051a39Sopenharmony_ciThe currently available hoosk are:
736e1051a39Sopenharmony_ci
737e1051a39Sopenharmony_ci=over 4
738e1051a39Sopenharmony_ci
739e1051a39Sopenharmony_ci=item B<exit_checker =E<gt> CODEREF>
740e1051a39Sopenharmony_ci
741e1051a39Sopenharmony_ciThis hook is executed after C<run> has performed its given command.  The
742e1051a39Sopenharmony_ciCODEREF receives the exit code as only argument and is expected to return
743e1051a39Sopenharmony_ci1 (if the exit code indicated success) or 0 (if the exit code indicated
744e1051a39Sopenharmony_cifailure).
745e1051a39Sopenharmony_ci
746e1051a39Sopenharmony_ci=back
747e1051a39Sopenharmony_ci
748e1051a39Sopenharmony_ci=back
749e1051a39Sopenharmony_ci
750e1051a39Sopenharmony_ci=cut
751e1051a39Sopenharmony_ci
752e1051a39Sopenharmony_cisub with {
753e1051a39Sopenharmony_ci    my $opts = shift;
754e1051a39Sopenharmony_ci    my %opts = %{$opts};
755e1051a39Sopenharmony_ci    my $codeblock = shift;
756e1051a39Sopenharmony_ci
757e1051a39Sopenharmony_ci    my %saved_hooks = ();
758e1051a39Sopenharmony_ci
759e1051a39Sopenharmony_ci    foreach (keys %opts) {
760e1051a39Sopenharmony_ci	$saved_hooks{$_} = $hooks{$_}	if exists($hooks{$_});
761e1051a39Sopenharmony_ci	$hooks{$_} = $opts{$_};
762e1051a39Sopenharmony_ci    }
763e1051a39Sopenharmony_ci
764e1051a39Sopenharmony_ci    $codeblock->();
765e1051a39Sopenharmony_ci
766e1051a39Sopenharmony_ci    foreach (keys %saved_hooks) {
767e1051a39Sopenharmony_ci	$hooks{$_} = $saved_hooks{$_};
768e1051a39Sopenharmony_ci    }
769e1051a39Sopenharmony_ci}
770e1051a39Sopenharmony_ci
771e1051a39Sopenharmony_ci=over 4
772e1051a39Sopenharmony_ci
773e1051a39Sopenharmony_ci=item B<cmdstr CODEREF, OPTS>
774e1051a39Sopenharmony_ci
775e1051a39Sopenharmony_ciC<cmdstr> takes a CODEREF from C<app> or C<test> and simply returns the
776e1051a39Sopenharmony_cicommand as a string.
777e1051a39Sopenharmony_ci
778e1051a39Sopenharmony_ciC<cmdstr> takes some additional options OPTS that affect the string returned:
779e1051a39Sopenharmony_ci
780e1051a39Sopenharmony_ci=over 4
781e1051a39Sopenharmony_ci
782e1051a39Sopenharmony_ci=item B<display =E<gt> 0|1>
783e1051a39Sopenharmony_ci
784e1051a39Sopenharmony_ciWhen set to 0, the returned string will be with all decorations, such as a
785e1051a39Sopenharmony_cipossible redirect of stderr to the null device.  This is suitable if the
786e1051a39Sopenharmony_cistring is to be used directly in a recipe.
787e1051a39Sopenharmony_ci
788e1051a39Sopenharmony_ciWhen set to 1, the returned string will be without extra decorations.  This
789e1051a39Sopenharmony_ciis suitable for display if that is desired (doesn't confuse people with all
790e1051a39Sopenharmony_ciinternal stuff), or if it's used to pass a command down to a subprocess.
791e1051a39Sopenharmony_ci
792e1051a39Sopenharmony_ciDefault: 0
793e1051a39Sopenharmony_ci
794e1051a39Sopenharmony_ci=back
795e1051a39Sopenharmony_ci
796e1051a39Sopenharmony_ci=back
797e1051a39Sopenharmony_ci
798e1051a39Sopenharmony_ci=cut
799e1051a39Sopenharmony_ci
800e1051a39Sopenharmony_cisub cmdstr {
801e1051a39Sopenharmony_ci    my ($cmd, $display_cmd) = shift->(0);
802e1051a39Sopenharmony_ci    my %opts = @_;
803e1051a39Sopenharmony_ci
804e1051a39Sopenharmony_ci    if ($opts{display}) {
805e1051a39Sopenharmony_ci        return $display_cmd;
806e1051a39Sopenharmony_ci    } else {
807e1051a39Sopenharmony_ci        return $cmd;
808e1051a39Sopenharmony_ci    }
809e1051a39Sopenharmony_ci}
810e1051a39Sopenharmony_ci
811e1051a39Sopenharmony_ci=over 4
812e1051a39Sopenharmony_ci
813e1051a39Sopenharmony_ci=over 4
814e1051a39Sopenharmony_ci
815e1051a39Sopenharmony_ci=item B<openssl_versions>
816e1051a39Sopenharmony_ci
817e1051a39Sopenharmony_ciReturns a list of two version numbers, the first representing the build
818e1051a39Sopenharmony_civersion, the second representing the library version.  See opensslv.h for
819e1051a39Sopenharmony_cimore information on those numbers.
820e1051a39Sopenharmony_ci
821e1051a39Sopenharmony_ci=back
822e1051a39Sopenharmony_ci
823e1051a39Sopenharmony_ci=cut
824e1051a39Sopenharmony_ci
825e1051a39Sopenharmony_cimy @versions = ();
826e1051a39Sopenharmony_cisub openssl_versions {
827e1051a39Sopenharmony_ci    unless (@versions) {
828e1051a39Sopenharmony_ci        my %lines =
829e1051a39Sopenharmony_ci            map { s/\R$//;
830e1051a39Sopenharmony_ci                  /^(.*): (.*)$/;
831e1051a39Sopenharmony_ci                  $1 => $2 }
832e1051a39Sopenharmony_ci            run(test(['versions']), capture => 1);
833e1051a39Sopenharmony_ci        @versions = ( $lines{'Build version'}, $lines{'Library version'} );
834e1051a39Sopenharmony_ci    }
835e1051a39Sopenharmony_ci    return @versions;
836e1051a39Sopenharmony_ci}
837e1051a39Sopenharmony_ci
838e1051a39Sopenharmony_ci=over 4
839e1051a39Sopenharmony_ci
840e1051a39Sopenharmony_ci=item B<ok_nofips EXPR, TEST_NAME>
841e1051a39Sopenharmony_ci
842e1051a39Sopenharmony_ciC<ok_nofips> is equivalent to using C<ok> when the environment variable
843e1051a39Sopenharmony_ciC<FIPS_MODE> is undefined, otherwise it is equivalent to C<not ok>. This can be
844e1051a39Sopenharmony_ciused for C<ok> tests that must fail when testing a FIPS provider. The parameters
845e1051a39Sopenharmony_ciare the same as used by C<ok> which is an expression EXPR followed by the test
846e1051a39Sopenharmony_cidescription TEST_NAME.
847e1051a39Sopenharmony_ci
848e1051a39Sopenharmony_ciAn example:
849e1051a39Sopenharmony_ci
850e1051a39Sopenharmony_ci  ok_nofips(run(app(["md5.pl"])), "md5 should fail in fips mode");
851e1051a39Sopenharmony_ci
852e1051a39Sopenharmony_ci=item B<is_nofips EXPR1, EXPR2, TEST_NAME>
853e1051a39Sopenharmony_ci
854e1051a39Sopenharmony_ciC<is_nofips> is equivalent to using C<is> when the environment variable
855e1051a39Sopenharmony_ciC<FIPS_MODE> is undefined, otherwise it is equivalent to C<isnt>. This can be
856e1051a39Sopenharmony_ciused for C<is> tests that must fail when testing a FIPS provider. The parameters
857e1051a39Sopenharmony_ciare the same as used by C<is> which has 2 arguments EXPR1 and EXPR2 that can be
858e1051a39Sopenharmony_cicompared using eq or ne, followed by a test description TEST_NAME.
859e1051a39Sopenharmony_ci
860e1051a39Sopenharmony_ciAn example:
861e1051a39Sopenharmony_ci
862e1051a39Sopenharmony_ci  is_nofips(ultimate_answer(), 42,  "Meaning of Life");
863e1051a39Sopenharmony_ci
864e1051a39Sopenharmony_ci=item B<isnt_nofips EXPR1, EXPR2, TEST_NAME>
865e1051a39Sopenharmony_ci
866e1051a39Sopenharmony_ciC<isnt_nofips> is equivalent to using C<isnt> when the environment variable
867e1051a39Sopenharmony_ciC<FIPS_MODE> is undefined, otherwise it is equivalent to C<is>. This can be
868e1051a39Sopenharmony_ciused for C<isnt> tests that must fail when testing a FIPS provider. The
869e1051a39Sopenharmony_ciparameters are the same as used by C<isnt> which has 2 arguments EXPR1 and EXPR2
870e1051a39Sopenharmony_cithat can be compared using ne or eq, followed by a test description TEST_NAME.
871e1051a39Sopenharmony_ci
872e1051a39Sopenharmony_ciAn example:
873e1051a39Sopenharmony_ci
874e1051a39Sopenharmony_ci  isnt_nofips($foo, '',  "Got some foo");
875e1051a39Sopenharmony_ci
876e1051a39Sopenharmony_ci=back
877e1051a39Sopenharmony_ci
878e1051a39Sopenharmony_ci=cut
879e1051a39Sopenharmony_ci
880e1051a39Sopenharmony_cisub ok_nofips {
881e1051a39Sopenharmony_ci    return ok(!$_[0], @_[1..$#_]) if defined $ENV{FIPS_MODE};
882e1051a39Sopenharmony_ci    return ok($_[0], @_[1..$#_]);
883e1051a39Sopenharmony_ci}
884e1051a39Sopenharmony_ci
885e1051a39Sopenharmony_cisub is_nofips {
886e1051a39Sopenharmony_ci    return isnt($_[0], $_[1], @_[2..$#_]) if defined $ENV{FIPS_MODE};
887e1051a39Sopenharmony_ci    return is($_[0], $_[1], @_[2..$#_]);
888e1051a39Sopenharmony_ci}
889e1051a39Sopenharmony_ci
890e1051a39Sopenharmony_cisub isnt_nofips {
891e1051a39Sopenharmony_ci    return is($_[0], $_[1], @_[2..$#_]) if defined $ENV{FIPS_MODE};
892e1051a39Sopenharmony_ci    return isnt($_[0], $_[1], @_[2..$#_]);
893e1051a39Sopenharmony_ci}
894e1051a39Sopenharmony_ci
895e1051a39Sopenharmony_ci######################################################################
896e1051a39Sopenharmony_ci# private functions.  These are never exported.
897e1051a39Sopenharmony_ci
898e1051a39Sopenharmony_ci=head1 ENVIRONMENT
899e1051a39Sopenharmony_ci
900e1051a39Sopenharmony_ciOpenSSL::Test depends on some environment variables.
901e1051a39Sopenharmony_ci
902e1051a39Sopenharmony_ci=over 4
903e1051a39Sopenharmony_ci
904e1051a39Sopenharmony_ci=item B<TOP>
905e1051a39Sopenharmony_ci
906e1051a39Sopenharmony_ciThis environment variable is mandatory.  C<setup> will check that it's
907e1051a39Sopenharmony_cidefined and that it's a directory that contains the file C<Configure>.
908e1051a39Sopenharmony_ciIf this isn't so, C<setup> will C<BAIL_OUT>.
909e1051a39Sopenharmony_ci
910e1051a39Sopenharmony_ci=item B<BIN_D>
911e1051a39Sopenharmony_ci
912e1051a39Sopenharmony_ciIf defined, its value should be the directory where the openssl application
913e1051a39Sopenharmony_ciis located.  Defaults to C<$TOP/apps> (adapted to the operating system).
914e1051a39Sopenharmony_ci
915e1051a39Sopenharmony_ci=item B<TEST_D>
916e1051a39Sopenharmony_ci
917e1051a39Sopenharmony_ciIf defined, its value should be the directory where the test applications
918e1051a39Sopenharmony_ciare located.  Defaults to C<$TOP/test> (adapted to the operating system).
919e1051a39Sopenharmony_ci
920e1051a39Sopenharmony_ci=item B<STOPTEST>
921e1051a39Sopenharmony_ci
922e1051a39Sopenharmony_ciIf defined, it puts testing in a different mode, where a recipe with
923e1051a39Sopenharmony_cifailures will result in a C<BAIL_OUT> at the end of its run.
924e1051a39Sopenharmony_ci
925e1051a39Sopenharmony_ci=item B<FIPS_MODE>
926e1051a39Sopenharmony_ci
927e1051a39Sopenharmony_ciIf defined it indicates that the FIPS provider is being tested. Tests may use
928e1051a39Sopenharmony_ciB<ok_nofips>, B<is_nofips> and B<isnt_nofips> to invert test results
929e1051a39Sopenharmony_cii.e. Some tests may only work in non FIPS mode.
930e1051a39Sopenharmony_ci
931e1051a39Sopenharmony_ci=back
932e1051a39Sopenharmony_ci
933e1051a39Sopenharmony_ci=cut
934e1051a39Sopenharmony_ci
935e1051a39Sopenharmony_cisub __env {
936e1051a39Sopenharmony_ci    (my $recipe_datadir = basename($0)) =~ s/\.t$/_data/i;
937e1051a39Sopenharmony_ci
938e1051a39Sopenharmony_ci    $directories{SRCTOP}    = abs_path($ENV{SRCTOP} || $ENV{TOP});
939e1051a39Sopenharmony_ci    $directories{BLDTOP}    = abs_path($ENV{BLDTOP} || $ENV{TOP});
940e1051a39Sopenharmony_ci    $directories{BLDAPPS}   = $ENV{BIN_D}  || __bldtop_dir("apps");
941e1051a39Sopenharmony_ci    $directories{SRCAPPS}   =                 __srctop_dir("apps");
942e1051a39Sopenharmony_ci    $directories{BLDFUZZ}   =                 __bldtop_dir("fuzz");
943e1051a39Sopenharmony_ci    $directories{SRCFUZZ}   =                 __srctop_dir("fuzz");
944e1051a39Sopenharmony_ci    $directories{BLDTEST}   = $ENV{TEST_D} || __bldtop_dir("test");
945e1051a39Sopenharmony_ci    $directories{SRCTEST}   =                 __srctop_dir("test");
946e1051a39Sopenharmony_ci    $directories{SRCDATA}   =                 __srctop_dir("test", "recipes",
947e1051a39Sopenharmony_ci                                                           $recipe_datadir);
948e1051a39Sopenharmony_ci    $directories{RESULTTOP} = $ENV{RESULT_D} || __bldtop_dir("test-runs");
949e1051a39Sopenharmony_ci    $directories{RESULTS}   = catdir($directories{RESULTTOP}, $test_name);
950e1051a39Sopenharmony_ci
951e1051a39Sopenharmony_ci    # Create result directory dynamically
952e1051a39Sopenharmony_ci    rmtree($directories{RESULTS}, { safe => 0, keep_root => 1 });
953e1051a39Sopenharmony_ci    mkpath($directories{RESULTS});
954e1051a39Sopenharmony_ci
955e1051a39Sopenharmony_ci    # All directories are assumed to exist, except for SRCDATA.  If that one
956e1051a39Sopenharmony_ci    # doesn't exist, just drop it.
957e1051a39Sopenharmony_ci    delete $directories{SRCDATA} unless -d $directories{SRCDATA};
958e1051a39Sopenharmony_ci
959e1051a39Sopenharmony_ci    push @direnv, "TOP"       if $ENV{TOP};
960e1051a39Sopenharmony_ci    push @direnv, "SRCTOP"    if $ENV{SRCTOP};
961e1051a39Sopenharmony_ci    push @direnv, "BLDTOP"    if $ENV{BLDTOP};
962e1051a39Sopenharmony_ci    push @direnv, "BIN_D"     if $ENV{BIN_D};
963e1051a39Sopenharmony_ci    push @direnv, "TEST_D"    if $ENV{TEST_D};
964e1051a39Sopenharmony_ci    push @direnv, "RESULT_D"  if $ENV{RESULT_D};
965e1051a39Sopenharmony_ci
966e1051a39Sopenharmony_ci    $end_with_bailout = $ENV{STOPTEST} ? 1 : 0;
967e1051a39Sopenharmony_ci};
968e1051a39Sopenharmony_ci
969e1051a39Sopenharmony_ci# __srctop_file and __srctop_dir are helpers to build file and directory
970e1051a39Sopenharmony_ci# names on top of the source directory.  They depend on $SRCTOP, and
971e1051a39Sopenharmony_ci# therefore on the proper use of setup() and when needed, indir().
972e1051a39Sopenharmony_ci# __bldtop_file and __bldtop_dir do the same thing but relative to $BLDTOP.
973e1051a39Sopenharmony_ci# __srctop_file and __bldtop_file take the same kind of argument as
974e1051a39Sopenharmony_ci# File::Spec::Functions::catfile.
975e1051a39Sopenharmony_ci# Similarly, __srctop_dir and __bldtop_dir take the same kind of argument
976e1051a39Sopenharmony_ci# as File::Spec::Functions::catdir
977e1051a39Sopenharmony_cisub __srctop_file {
978e1051a39Sopenharmony_ci    BAIL_OUT("Must run setup() first") if (! $test_name);
979e1051a39Sopenharmony_ci
980e1051a39Sopenharmony_ci    my $f = pop;
981e1051a39Sopenharmony_ci    return abs2rel(catfile($directories{SRCTOP},@_,$f),getcwd);
982e1051a39Sopenharmony_ci}
983e1051a39Sopenharmony_ci
984e1051a39Sopenharmony_cisub __srctop_dir {
985e1051a39Sopenharmony_ci    BAIL_OUT("Must run setup() first") if (! $test_name);
986e1051a39Sopenharmony_ci
987e1051a39Sopenharmony_ci    return abs2rel(catdir($directories{SRCTOP},@_), getcwd);
988e1051a39Sopenharmony_ci}
989e1051a39Sopenharmony_ci
990e1051a39Sopenharmony_cisub __bldtop_file {
991e1051a39Sopenharmony_ci    BAIL_OUT("Must run setup() first") if (! $test_name);
992e1051a39Sopenharmony_ci
993e1051a39Sopenharmony_ci    my $f = pop;
994e1051a39Sopenharmony_ci    return abs2rel(catfile($directories{BLDTOP},@_,$f), getcwd);
995e1051a39Sopenharmony_ci}
996e1051a39Sopenharmony_ci
997e1051a39Sopenharmony_cisub __bldtop_dir {
998e1051a39Sopenharmony_ci    BAIL_OUT("Must run setup() first") if (! $test_name);
999e1051a39Sopenharmony_ci
1000e1051a39Sopenharmony_ci    return abs2rel(catdir($directories{BLDTOP},@_), getcwd);
1001e1051a39Sopenharmony_ci}
1002e1051a39Sopenharmony_ci
1003e1051a39Sopenharmony_ci# __exeext is a function that returns the platform dependent file extension
1004e1051a39Sopenharmony_ci# for executable binaries, or the value of the environment variable $EXE_EXT
1005e1051a39Sopenharmony_ci# if that one is defined.
1006e1051a39Sopenharmony_cisub __exeext {
1007e1051a39Sopenharmony_ci    my $ext = "";
1008e1051a39Sopenharmony_ci    if ($^O eq "VMS" ) {	# VMS
1009e1051a39Sopenharmony_ci	$ext = ".exe";
1010e1051a39Sopenharmony_ci    } elsif ($^O eq "MSWin32") { # Windows
1011e1051a39Sopenharmony_ci	$ext = ".exe";
1012e1051a39Sopenharmony_ci    }
1013e1051a39Sopenharmony_ci    return $ENV{"EXE_EXT"} || $ext;
1014e1051a39Sopenharmony_ci}
1015e1051a39Sopenharmony_ci
1016e1051a39Sopenharmony_ci# __test_file, __apps_file and __fuzz_file return the full path to a file
1017e1051a39Sopenharmony_ci# relative to the test/, apps/ or fuzz/ directory in the build tree or the
1018e1051a39Sopenharmony_ci# source tree, depending on where the file is found.  Note that when looking
1019e1051a39Sopenharmony_ci# in the build tree, the file name with an added extension is looked for, if
1020e1051a39Sopenharmony_ci# an extension is given.  The intent is to look for executable binaries (in
1021e1051a39Sopenharmony_ci# the build tree) or possibly scripts (in the source tree).
1022e1051a39Sopenharmony_ci# These functions all take the same arguments as File::Spec::Functions::catfile,
1023e1051a39Sopenharmony_ci# *plus* a mandatory extension argument.  This extension argument can be undef,
1024e1051a39Sopenharmony_ci# and is ignored in such a case.
1025e1051a39Sopenharmony_cisub __test_file {
1026e1051a39Sopenharmony_ci    BAIL_OUT("Must run setup() first") if (! $test_name);
1027e1051a39Sopenharmony_ci
1028e1051a39Sopenharmony_ci    my $e = pop || "";
1029e1051a39Sopenharmony_ci    my $f = pop;
1030e1051a39Sopenharmony_ci    my $out = catfile($directories{BLDTEST},@_,$f . $e);
1031e1051a39Sopenharmony_ci    $out = catfile($directories{SRCTEST},@_,$f) unless -f $out;
1032e1051a39Sopenharmony_ci    return $out;
1033e1051a39Sopenharmony_ci}
1034e1051a39Sopenharmony_ci
1035e1051a39Sopenharmony_cisub __apps_file {
1036e1051a39Sopenharmony_ci    BAIL_OUT("Must run setup() first") if (! $test_name);
1037e1051a39Sopenharmony_ci
1038e1051a39Sopenharmony_ci    my $e = pop || "";
1039e1051a39Sopenharmony_ci    my $f = pop;
1040e1051a39Sopenharmony_ci    my $out = catfile($directories{BLDAPPS},@_,$f . $e);
1041e1051a39Sopenharmony_ci    $out = catfile($directories{SRCAPPS},@_,$f) unless -f $out;
1042e1051a39Sopenharmony_ci    return $out;
1043e1051a39Sopenharmony_ci}
1044e1051a39Sopenharmony_ci
1045e1051a39Sopenharmony_cisub __fuzz_file {
1046e1051a39Sopenharmony_ci    BAIL_OUT("Must run setup() first") if (! $test_name);
1047e1051a39Sopenharmony_ci
1048e1051a39Sopenharmony_ci    my $e = pop || "";
1049e1051a39Sopenharmony_ci    my $f = pop;
1050e1051a39Sopenharmony_ci    my $out = catfile($directories{BLDFUZZ},@_,$f . $e);
1051e1051a39Sopenharmony_ci    $out = catfile($directories{SRCFUZZ},@_,$f) unless -f $out;
1052e1051a39Sopenharmony_ci    return $out;
1053e1051a39Sopenharmony_ci}
1054e1051a39Sopenharmony_ci
1055e1051a39Sopenharmony_cisub __data_file {
1056e1051a39Sopenharmony_ci    BAIL_OUT("Must run setup() first") if (! $test_name);
1057e1051a39Sopenharmony_ci
1058e1051a39Sopenharmony_ci    return undef unless exists $directories{SRCDATA};
1059e1051a39Sopenharmony_ci
1060e1051a39Sopenharmony_ci    my $f = pop;
1061e1051a39Sopenharmony_ci    return catfile($directories{SRCDATA},@_,$f);
1062e1051a39Sopenharmony_ci}
1063e1051a39Sopenharmony_ci
1064e1051a39Sopenharmony_cisub __data_dir {
1065e1051a39Sopenharmony_ci    BAIL_OUT("Must run setup() first") if (! $test_name);
1066e1051a39Sopenharmony_ci
1067e1051a39Sopenharmony_ci    return undef unless exists $directories{SRCDATA};
1068e1051a39Sopenharmony_ci
1069e1051a39Sopenharmony_ci    return catdir($directories{SRCDATA},@_);
1070e1051a39Sopenharmony_ci}
1071e1051a39Sopenharmony_ci
1072e1051a39Sopenharmony_ci# __cwd DIR
1073e1051a39Sopenharmony_ci# __cwd DIR, OPTS
1074e1051a39Sopenharmony_ci#
1075e1051a39Sopenharmony_ci# __cwd changes directory to DIR (string) and changes all the relative
1076e1051a39Sopenharmony_ci# entries in %directories accordingly.  OPTS is an optional series of
1077e1051a39Sopenharmony_ci# hash style arguments to alter __cwd's behavior:
1078e1051a39Sopenharmony_ci#
1079e1051a39Sopenharmony_ci#    create = 0|1       The directory we move to is created if 1, not if 0.
1080e1051a39Sopenharmony_ci
1081e1051a39Sopenharmony_cisub __cwd {
1082e1051a39Sopenharmony_ci    my $dir = catdir(shift);
1083e1051a39Sopenharmony_ci    my %opts = @_;
1084e1051a39Sopenharmony_ci
1085e1051a39Sopenharmony_ci    # If the directory is to be created, we must do that before using
1086e1051a39Sopenharmony_ci    # abs_path().
1087e1051a39Sopenharmony_ci    $dir = canonpath($dir);
1088e1051a39Sopenharmony_ci    if ($opts{create}) {
1089e1051a39Sopenharmony_ci	mkpath($dir);
1090e1051a39Sopenharmony_ci    }
1091e1051a39Sopenharmony_ci
1092e1051a39Sopenharmony_ci    my $abscurdir = abs_path(curdir());
1093e1051a39Sopenharmony_ci    my $absdir = abs_path($dir);
1094e1051a39Sopenharmony_ci    my $reverse = abs2rel($abscurdir, $absdir);
1095e1051a39Sopenharmony_ci
1096e1051a39Sopenharmony_ci    # PARANOIA: if we're not moving anywhere, we do nothing more
1097e1051a39Sopenharmony_ci    if ($abscurdir eq $absdir) {
1098e1051a39Sopenharmony_ci	return $reverse;
1099e1051a39Sopenharmony_ci    }
1100e1051a39Sopenharmony_ci
1101e1051a39Sopenharmony_ci    # Do not support a move to a different volume for now.  Maybe later.
1102e1051a39Sopenharmony_ci    BAIL_OUT("FAILURE: \"$dir\" moves to a different volume, not supported")
1103e1051a39Sopenharmony_ci	if $reverse eq $abscurdir;
1104e1051a39Sopenharmony_ci
1105e1051a39Sopenharmony_ci    # If someone happened to give a directory that leads back to the current,
1106e1051a39Sopenharmony_ci    # it's extremely silly to do anything more, so just simulate that we did
1107e1051a39Sopenharmony_ci    # move.
1108e1051a39Sopenharmony_ci    # In this case, we won't even clean it out, for safety's sake.
1109e1051a39Sopenharmony_ci    return "." if $reverse eq "";
1110e1051a39Sopenharmony_ci
1111e1051a39Sopenharmony_ci    # We are recalculating the directories we keep track of, but need to save
1112e1051a39Sopenharmony_ci    # away the result for after having moved into the new directory.
1113e1051a39Sopenharmony_ci    my %tmp_directories = ();
1114e1051a39Sopenharmony_ci    my %tmp_ENV = ();
1115e1051a39Sopenharmony_ci
1116e1051a39Sopenharmony_ci    # For each of these directory variables, figure out where they are relative
1117e1051a39Sopenharmony_ci    # to the directory we want to move to if they aren't absolute (if they are,
1118e1051a39Sopenharmony_ci    # they don't change!)
1119e1051a39Sopenharmony_ci    my @dirtags = sort keys %directories;
1120e1051a39Sopenharmony_ci    foreach (@dirtags) {
1121e1051a39Sopenharmony_ci	if (!file_name_is_absolute($directories{$_})) {
1122e1051a39Sopenharmony_ci	    my $oldpath = abs_path($directories{$_});
1123e1051a39Sopenharmony_ci	    my $newpath = abs2rel($oldpath, $absdir);
1124e1051a39Sopenharmony_ci	    if ($debug) {
1125e1051a39Sopenharmony_ci		print STDERR "DEBUG: [dir $_] old path: $oldpath\n";
1126e1051a39Sopenharmony_ci		print STDERR "DEBUG: [dir $_] new base: $absdir\n";
1127e1051a39Sopenharmony_ci		print STDERR "DEBUG: [dir $_] resulting new path: $newpath\n";
1128e1051a39Sopenharmony_ci	    }
1129e1051a39Sopenharmony_ci	    $tmp_directories{$_} = $newpath;
1130e1051a39Sopenharmony_ci	}
1131e1051a39Sopenharmony_ci    }
1132e1051a39Sopenharmony_ci
1133e1051a39Sopenharmony_ci    # Treat each environment variable that was used to get us the values in
1134e1051a39Sopenharmony_ci    # %directories the same was as the paths in %directories, so any sub
1135e1051a39Sopenharmony_ci    # process can use their values properly as well
1136e1051a39Sopenharmony_ci    foreach (@direnv) {
1137e1051a39Sopenharmony_ci	if (!file_name_is_absolute($ENV{$_})) {
1138e1051a39Sopenharmony_ci	    my $oldpath = abs_path($ENV{$_});
1139e1051a39Sopenharmony_ci	    my $newpath = abs2rel($oldpath, $absdir);
1140e1051a39Sopenharmony_ci	    if ($debug) {
1141e1051a39Sopenharmony_ci		print STDERR "DEBUG: [env $_] old path: $oldpath\n";
1142e1051a39Sopenharmony_ci		print STDERR "DEBUG: [env $_] new base: $absdir\n";
1143e1051a39Sopenharmony_ci		print STDERR "DEBUG: [env $_] resulting new path: $newpath\n";
1144e1051a39Sopenharmony_ci	    }
1145e1051a39Sopenharmony_ci	    $tmp_ENV{$_} = $newpath;
1146e1051a39Sopenharmony_ci	}
1147e1051a39Sopenharmony_ci    }
1148e1051a39Sopenharmony_ci
1149e1051a39Sopenharmony_ci    # Should we just bail out here as well?  I'm unsure.
1150e1051a39Sopenharmony_ci    return undef unless chdir($dir);
1151e1051a39Sopenharmony_ci
1152e1051a39Sopenharmony_ci    # We put back new values carefully.  Doing the obvious
1153e1051a39Sopenharmony_ci    # %directories = ( %tmp_directories )
1154e1051a39Sopenharmony_ci    # will clear out any value that happens to be an absolute path
1155e1051a39Sopenharmony_ci    foreach (keys %tmp_directories) {
1156e1051a39Sopenharmony_ci        $directories{$_} = $tmp_directories{$_};
1157e1051a39Sopenharmony_ci    }
1158e1051a39Sopenharmony_ci    foreach (keys %tmp_ENV) {
1159e1051a39Sopenharmony_ci        $ENV{$_} = $tmp_ENV{$_};
1160e1051a39Sopenharmony_ci    }
1161e1051a39Sopenharmony_ci
1162e1051a39Sopenharmony_ci    if ($debug) {
1163e1051a39Sopenharmony_ci	print STDERR "DEBUG: __cwd(), directories and files:\n";
1164e1051a39Sopenharmony_ci	print STDERR "	Moving from $abscurdir\n";
1165e1051a39Sopenharmony_ci	print STDERR "	Moving to $absdir\n";
1166e1051a39Sopenharmony_ci	print STDERR "\n";
1167e1051a39Sopenharmony_ci	print STDERR "	\$directories{BLDTEST} = \"$directories{BLDTEST}\"\n";
1168e1051a39Sopenharmony_ci	print STDERR "	\$directories{SRCTEST} = \"$directories{SRCTEST}\"\n";
1169e1051a39Sopenharmony_ci	print STDERR "	\$directories{SRCDATA} = \"$directories{SRCDATA}\"\n"
1170e1051a39Sopenharmony_ci            if exists $directories{SRCDATA};
1171e1051a39Sopenharmony_ci	print STDERR "	\$directories{RESULTS} = \"$directories{RESULTS}\"\n";
1172e1051a39Sopenharmony_ci	print STDERR "	\$directories{BLDAPPS} = \"$directories{BLDAPPS}\"\n";
1173e1051a39Sopenharmony_ci	print STDERR "	\$directories{SRCAPPS} = \"$directories{SRCAPPS}\"\n";
1174e1051a39Sopenharmony_ci	print STDERR "	\$directories{SRCTOP}  = \"$directories{SRCTOP}\"\n";
1175e1051a39Sopenharmony_ci	print STDERR "	\$directories{BLDTOP}  = \"$directories{BLDTOP}\"\n";
1176e1051a39Sopenharmony_ci	print STDERR "\n";
1177e1051a39Sopenharmony_ci	print STDERR "  the way back is \"$reverse\"\n";
1178e1051a39Sopenharmony_ci    }
1179e1051a39Sopenharmony_ci
1180e1051a39Sopenharmony_ci    return $reverse;
1181e1051a39Sopenharmony_ci}
1182e1051a39Sopenharmony_ci
1183e1051a39Sopenharmony_ci# __wrap_cmd CMD
1184e1051a39Sopenharmony_ci# __wrap_cmd CMD, EXE_SHELL
1185e1051a39Sopenharmony_ci#
1186e1051a39Sopenharmony_ci# __wrap_cmd "wraps" CMD (string) with a beginning command that makes sure
1187e1051a39Sopenharmony_ci# the command gets executed with an appropriate environment.  If EXE_SHELL
1188e1051a39Sopenharmony_ci# is given, it is used as the beginning command.
1189e1051a39Sopenharmony_ci#
1190e1051a39Sopenharmony_ci# __wrap_cmd returns a list that should be used to build up a larger list
1191e1051a39Sopenharmony_ci# of command tokens, or be joined together like this:
1192e1051a39Sopenharmony_ci#
1193e1051a39Sopenharmony_ci#    join(" ", __wrap_cmd($cmd))
1194e1051a39Sopenharmony_cisub __wrap_cmd {
1195e1051a39Sopenharmony_ci    my $cmd = shift;
1196e1051a39Sopenharmony_ci    my $exe_shell = shift;
1197e1051a39Sopenharmony_ci
1198e1051a39Sopenharmony_ci    my @prefix = ();
1199e1051a39Sopenharmony_ci
1200e1051a39Sopenharmony_ci    if (defined($exe_shell)) {
1201e1051a39Sopenharmony_ci        # If $exe_shell is defined, trust it
1202e1051a39Sopenharmony_ci        @prefix = ( $exe_shell );
1203e1051a39Sopenharmony_ci    } else {
1204e1051a39Sopenharmony_ci        # Otherwise, use the standard wrapper
1205e1051a39Sopenharmony_ci        my $std_wrapper = __bldtop_file("util", "wrap.pl");
1206e1051a39Sopenharmony_ci
1207e1051a39Sopenharmony_ci        if ($^O eq "VMS" || $^O eq "MSWin32") {
1208e1051a39Sopenharmony_ci            # On VMS and Windows, we run the perl executable explicitly,
1209e1051a39Sopenharmony_ci            # with necessary fixups.  We might not need that for Windows,
1210e1051a39Sopenharmony_ci            # but that depends on if the user has associated the '.pl'
1211e1051a39Sopenharmony_ci            # extension with a perl interpreter, so better be safe.
1212e1051a39Sopenharmony_ci            @prefix = ( __fixup_prg($^X), $std_wrapper );
1213e1051a39Sopenharmony_ci        } else {
1214e1051a39Sopenharmony_ci            # Otherwise, we assume Unix semantics, and trust that the #!
1215e1051a39Sopenharmony_ci            # line activates perl for us.
1216e1051a39Sopenharmony_ci            @prefix = ( $std_wrapper );
1217e1051a39Sopenharmony_ci        }
1218e1051a39Sopenharmony_ci    }
1219e1051a39Sopenharmony_ci
1220e1051a39Sopenharmony_ci    return (@prefix, $cmd);
1221e1051a39Sopenharmony_ci}
1222e1051a39Sopenharmony_ci
1223e1051a39Sopenharmony_ci# __fixup_prg PROG
1224e1051a39Sopenharmony_ci#
1225e1051a39Sopenharmony_ci# __fixup_prg does whatever fixup is needed to execute an executable binary
1226e1051a39Sopenharmony_ci# given by PROG (string).
1227e1051a39Sopenharmony_ci#
1228e1051a39Sopenharmony_ci# __fixup_prg returns a string with the possibly prefixed program path spec.
1229e1051a39Sopenharmony_cisub __fixup_prg {
1230e1051a39Sopenharmony_ci    my $prog = shift;
1231e1051a39Sopenharmony_ci
1232e1051a39Sopenharmony_ci    return join(' ', fixup_cmd($prog));
1233e1051a39Sopenharmony_ci}
1234e1051a39Sopenharmony_ci
1235e1051a39Sopenharmony_ci# __decorate_cmd NUM, CMDARRAYREF
1236e1051a39Sopenharmony_ci#
1237e1051a39Sopenharmony_ci# __decorate_cmd takes a command number NUM and a command token array
1238e1051a39Sopenharmony_ci# CMDARRAYREF, builds up a command string from them and decorates it
1239e1051a39Sopenharmony_ci# with necessary redirections.
1240e1051a39Sopenharmony_ci# __decorate_cmd returns a list of two strings, one with the command
1241e1051a39Sopenharmony_ci# string to actually be used, the other to be displayed for the user.
1242e1051a39Sopenharmony_ci# The reason these strings might differ is that we redirect stderr to
1243e1051a39Sopenharmony_ci# the null device unless we're verbose and unless the user has
1244e1051a39Sopenharmony_ci# explicitly specified a stderr redirection.
1245e1051a39Sopenharmony_cisub __decorate_cmd {
1246e1051a39Sopenharmony_ci    BAIL_OUT("Must run setup() first") if (! $test_name);
1247e1051a39Sopenharmony_ci
1248e1051a39Sopenharmony_ci    my $num = shift;
1249e1051a39Sopenharmony_ci    my $cmd = shift;
1250e1051a39Sopenharmony_ci    my %opts = @_;
1251e1051a39Sopenharmony_ci
1252e1051a39Sopenharmony_ci    my $cmdstr = join(" ", @$cmd);
1253e1051a39Sopenharmony_ci    my $null = devnull();
1254e1051a39Sopenharmony_ci    my $fileornull = sub { $_[0] ? $_[0] : $null; };
1255e1051a39Sopenharmony_ci    my $stdin = "";
1256e1051a39Sopenharmony_ci    my $stdout = "";
1257e1051a39Sopenharmony_ci    my $stderr = "";
1258e1051a39Sopenharmony_ci    my $saved_stderr = undef;
1259e1051a39Sopenharmony_ci    $stdin = " < ".$fileornull->($opts{stdin})  if exists($opts{stdin});
1260e1051a39Sopenharmony_ci    $stdout= " > ".$fileornull->($opts{stdout}) if exists($opts{stdout});
1261e1051a39Sopenharmony_ci    $stderr=" 2> ".$fileornull->($opts{stderr}) if exists($opts{stderr});
1262e1051a39Sopenharmony_ci
1263e1051a39Sopenharmony_ci    my $display_cmd = "$cmdstr$stdin$stdout$stderr";
1264e1051a39Sopenharmony_ci
1265e1051a39Sopenharmony_ci    # VMS program output escapes TAP::Parser
1266e1051a39Sopenharmony_ci    if ($^O eq 'VMS') {
1267e1051a39Sopenharmony_ci        $stderr=" 2> ".$null
1268e1051a39Sopenharmony_ci            unless $stderr || !$ENV{HARNESS_ACTIVE} || $ENV{HARNESS_VERBOSE};
1269e1051a39Sopenharmony_ci    }
1270e1051a39Sopenharmony_ci
1271e1051a39Sopenharmony_ci    $cmdstr .= "$stdin$stdout$stderr";
1272e1051a39Sopenharmony_ci
1273e1051a39Sopenharmony_ci    if ($debug) {
1274e1051a39Sopenharmony_ci	print STDERR "DEBUG[__decorate_cmd]: \$cmdstr = \"$cmdstr\"\n";
1275e1051a39Sopenharmony_ci	print STDERR "DEBUG[__decorate_cmd]: \$display_cmd = \"$display_cmd\"\n";
1276e1051a39Sopenharmony_ci    }
1277e1051a39Sopenharmony_ci
1278e1051a39Sopenharmony_ci    return ($cmdstr, $display_cmd);
1279e1051a39Sopenharmony_ci}
1280e1051a39Sopenharmony_ci
1281e1051a39Sopenharmony_ci=head1 SEE ALSO
1282e1051a39Sopenharmony_ci
1283e1051a39Sopenharmony_ciL<Test::More>, L<Test::Harness>
1284e1051a39Sopenharmony_ci
1285e1051a39Sopenharmony_ci=head1 AUTHORS
1286e1051a39Sopenharmony_ci
1287e1051a39Sopenharmony_ciRichard Levitte E<lt>levitte@openssl.orgE<gt> with assistance and
1288e1051a39Sopenharmony_ciinspiration from Andy Polyakov E<lt>appro@openssl.org<gt>.
1289e1051a39Sopenharmony_ci
1290e1051a39Sopenharmony_ci=cut
1291e1051a39Sopenharmony_ci
1292e1051a39Sopenharmony_cino warnings 'redefine';
1293e1051a39Sopenharmony_cisub subtest {
1294e1051a39Sopenharmony_ci    $level++;
1295e1051a39Sopenharmony_ci
1296e1051a39Sopenharmony_ci    Test::More::subtest @_;
1297e1051a39Sopenharmony_ci
1298e1051a39Sopenharmony_ci    $level--;
1299e1051a39Sopenharmony_ci};
1300e1051a39Sopenharmony_ci
1301e1051a39Sopenharmony_ci1;
1302