.\" Automatically generated by Pod::Man 4.14 (Pod::Simple 3.43) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" .\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). .\" Fear. Run. Save yourself. No user-serviceable parts. . \" fudge factors for nroff and troff .if n \{\ . ds #H 0 . ds #V .8m . ds #F .3m . ds #[ \f1 . ds #] \fP .\} .if t \{\ . ds #H ((1u-(\\\\n(.fu%2u))*.13m) . ds #V .6m . ds #F 0 . ds #[ \& . ds #] \& .\} . \" simple accents for nroff and troff .if n \{\ . ds ' \& . ds ` \& . ds ^ \& . ds , \& . ds ~ ~ . ds / .\} .if t \{\ . ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" . ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' . ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' . ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' . ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' . ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' .\} . \" troff and (daisy-wheel) nroff accents .ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' .ds 8 \h'\*(#H'\(*b\h'-\*(#H' .ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] .ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' .ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' .ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] .ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] .ds ae a\h'-(\w'a'u*4/10)'e .ds Ae A\h'-(\w'A'u*4/10)'E . \" corrections for vroff .if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' .if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' . \" for low resolution devices (crt and lpr) .if \n(.H>23 .if \n(.V>19 \ \{\ . ds : e . ds 8 ss . ds o a . ds d- d\h'-1'\(ga . ds D- D\h'-1'\(hy . ds th \o'bp' . ds Th \o'LP' . ds ae ae . ds Ae AE .\} .rm #[ #] #H #V #F C .\" ======================================================================== .\" .IX Title "Test2::Tools::Command 3pm" .TH Test2::Tools::Command 3pm "2023-01-15" "perl v5.36.0" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" Test2::Tools::Command \- test simple unix commands .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 1 \& use Test2::Tools::Command; \& \& # test some typical unix tools; implicit checks are that status \& # is 0, and that stdout and stderr are the empty string, unless \& # otherwise specified \& command { args => [ \*(Aqtrue\*(Aq ] }; \& command { args => [ \*(Aqfalse\*(Aq ], status => 1 }; \& command { args => [ \*(Aqecho\*(Aq, \*(Aqfoo\*(Aq ], stdout => "foo\en" }; \& \& # subsequent args are prefixed with this \& local @Test2::Tools::Command::command = ( \*(Aqperl\*(Aq, \*(Aq\-E\*(Aq ); \& \& # return values and a variety of the options available \& my ($result, $exit_status, $stdout_ref, $stderr_ref) = \& command { args => [ q{say "out";warn "err";kill TERM => $$} ], \& chdir => \*(Aq/some/dir\*(Aq, \& env => { API_KEY => 42 }, \& stdin => "printed to program\en", \& stdout => qr/out/, \& stderr => qr/err/, \& status => { code => 0, signal => 15, iscore => 0 }, \& timeout => 7 }; \& \& # check on a $? exit status word from somewhere \& is_exit $?, 42; \& is_exit $?, { code => 0, signal => 9, iscore => 0 }; .Ve .SH "DESCRIPTION" .IX Header "DESCRIPTION" This module tests that commands given particular arguments result in particular outputs by way of the exit status word, standard output, and standard error. Various parameters to the \fBcommand\fR function alter exactly how this is done, in addition to variables that can be set. .PP The commands are expected to be simple, for example filters that maybe accept standard input and respond with some but not too much output. Interactive or otherwise complicated commands will need some other module such as Expect to test them, as will programs that generate too much output. .PP Also, \fBis_exit\fR is provided to check on the 16\-bit exit status word from other code. .SH "VARIABLES" .IX Header "VARIABLES" These are not exported. .IP "\fB\f(CB@command\fB\fR" 4 .IX Item "@command" Custom command to prefix any commands run by \fBcommand\fR with, for example to specify a test program that will be used in many subsequent tests .Sp .Vb 2 \& local @Test2::Tools::Command::command = ($^X, \*(Aq\-\-\*(Aq, \*(Aqbin/foo\*(Aq); \& command { args => [ \*(Aqbar\*(Aq, \*(Aq\-c\*(Aq, \*(Aqbaz\*(Aq ] }; .Ve .Sp will result in \f(CW\*(C`perl \-\- bin/foo bar \-c baz\*(C'\fR being run. .Sp If \fIchdir\fR is used, a command that uses a relative path may need to be fully qualified, e.g. with \f(CW\*(C`rel2abs\*(C'\fR of File::Spec::Functions. .IP "\fB\f(CB$timeout\fB\fR" 4 .IX Item "$timeout" Seconds after which commands will be timed out via \f(CW\*(C`alarm\*(C'\fR if a \&\fItimeout\fR is not given to \fBcommand\fR. 30 by default. .SH "FUNCTIONS" .IX Header "FUNCTIONS" \&\fBcommand\fR is exported by default; this can be disabled by using this module with an empty import list. The test keys are \fIstatus\fR, \&\fIstdout\fR, and \fIstderr\fR. The other keys influence how the command is run or change test metadata. .IP "\fBcommand\fR \fIhashref\fR" 4 .IX Item "command hashref" Runs a command and executes one or more tests on the results, depending on the contents of \fIhashref\fR, which may contain: .RS 4 .IP "\fIargs\fR => \fIarrayref\fR" 4 .IX Item "args => arrayref" List of arguments to run the command with. The argument list will be prefixed by the \fB\f(CB@command\fB\fR variable, if that is set. .IP "\fIbinmode\fR => \fIlayer\fR" 4 .IX Item "binmode => layer" If set, \fIlayer\fR will be set on the filehandles wired to the command via the \f(CW\*(C`binmode\*(C'\fR function. See also open. .IP "\fIchdir\fR => \fIdirectory\fR" 4 .IX Item "chdir => directory" Attempt to \f(CW\*(C`chdir\*(C'\fR into \fIdirectory\fR or failing that will throw an exception, by way of File::chdir. .Sp A command that uses a relative path may need to be fully qualified, e.g. with \f(CW\*(C`rel2abs\*(C'\fR of File::Spec::Functions. .IP "\fIenv\fR => \fIhashref\fR" 4 .IX Item "env => hashref" Set the environment for the command to include the keys and values present in \fIhashref\fR. This is additive only; environment variables that must not be set must be deleted from \f(CW%ENV\fR, or the command wrapped with a command that can reset the environment, such as \fBenv\fR\|(1). .IP "\fIname\fR => \fIstring\fR" 4 .IX Item "name => string" Custom name for the tests. Otherwise, the full command executed is used in the test name, which may not be ideal. .IP "\fImunge_signal\fR => \fIboolean\fR" 4 .IX Item "munge_signal => boolean" If the signal number of the 16\-bit exit status word is not zero, the signal will be munged to have the value \f(CW1\fR. .IP "\fImunge_status\fR => \fIboolean\fR" 4 .IX Item "munge_status => boolean" If the exit code of the 16\-bit exit status word is not zero, the code will be munged to have the value \f(CW1\fR. Use this where the program being tested is unpredictable as to what non-zero exit code it will use. .IP "\fIstatus\fR => \fIcode-or-hashref\fR" 4 .IX Item "status => code-or-hashref" Expect the given value as the 16\-bit exit status word. By default \f(CW0\fR for the exit code is assumed. This can be specified in two different forms; the following two are equivalent: .Sp .Vb 2 \& status => 42 \& status => { code => 42, iscore => 0, signal => 0 } .Ve .Sp Obviously the 16\-bit exit status word is decomposed into a hash reference. If the program is instead expected to exit by a \s-1SIGPIPE,\s0 one might use: .Sp .Vb 1 \& status => { code => 0, iscore => 0, signal => 13 } .Ve .Sp See also \fImunge_signal\fR and \fImunge_status\fR. .IP "\fIstdin\fR => \fIdata\fR" 4 .IX Item "stdin => data" If present, \fIdata\fR will be printed to the command and then standard input will be closed. Otherwise, nothing is done with standard input. .IP "\fIstdout\fR => \fIqr-or-string\fR" 4 .IX Item "stdout => qr-or-string" Expect that the standard output of the command exactly matches the given string, or if the string is a \f(CW\*(C`qr//\*(C'\fR regular expression, that the output matches that expression. .IP "\fIstderr\fR => \fIqr-or-string\fR" 4 .IX Item "stderr => qr-or-string" Expect that the standard err of the command exactly matches the given string, or if the string is a \f(CW\*(C`qr//\*(C'\fR regular expression, that the stderr matches that expression. .IP "\fItimeout\fR => \fIseconds\fR" 4 .IX Item "timeout => seconds" Set a custom timeout for the \f(CW\*(C`alarm\*(C'\fR call that wraps the command. The variable \fB\f(CB$timeout\fB\fR will be used if this is unset. .RE .RS 4 .Sp \&\fBcommand\fR returns a list consisting of the result of the tests, the original 16\-bit exit status word, and scalar references to strings that contain the standard output and standard error of the test program, if any. .Sp .Vb 1 \& my ($result, $status, $out_ref, $err_ref) = command { ... .Ve .RE .IP "\fBis_exit\fR \fIstatus\fR [ \fIcode-or-hashref\fR [ \fItest-name\fR ] ]" 4 .IX Item "is_exit status [ code-or-hashref [ test-name ] ]" This routine checks that a 16\-bit exit status word (usually by way of the \f(CW$?\fR variable) conforms to some code or hash reference. The hash reference may contain \fImungle_signal\fR and \fImunge_status\fR that will turn non-zero signal or codes into \f(CW1\fR. .Sp .Vb 2 \& is_exit $?, 42; \& is_exit $?, { code => 0, signal => 9, iscore => 0 }; .Ve .SH "BUGS" .IX Header "BUGS" None known. There are probably portability problems if you stray from the unix path. .SH "SEE ALSO" .IX Header "SEE ALSO" Test2::Suite .PP Expect may be necessary to test complicated programs. .PP IPC::Open3 is used to run programs; this may run into portability problems on systems that stray from the way of unix? .SH "COPYRIGHT AND LICENSE" .IX Header "COPYRIGHT AND LICENSE" Copyright 2022 Jeremy Mates .PP This program is distributed under the (Revised) \s-1BSD\s0 License: