File Coverage

blib/lib/Test/UnixCmdWrap.pm
Criterion Covered Total %
statement 53 53 100.0
branch 14 14 100.0
condition 11 13 84.6
subroutine 13 13 100.0
pod 2 2 100.0
total 93 95 97.8


line stmt bran cond sub pod time code
1             # -*- Perl -*-
2             #
3             # Test::UnixCmdWrap - test unix commands with various assumptions
4              
5             package Test::UnixCmdWrap;
6              
7 2     2   158784 use 5.24.0;
  2         14  
8 2     2   11 use warnings;
  2         4  
  2         64  
9 2     2   10 use Cwd qw(getcwd);
  2         5  
  2         79  
10 2     2   21 use Carp qw(croak);
  2         4  
  2         90  
11 2     2   861 use File::Spec::Functions qw(catfile);
  2         1564  
  2         115  
12 2     2   1054 use Moo;
  2         20614  
  2         9  
13 2     2   3190 use Test::Cmd ();
  2         12200  
  2         96  
14 2     2   587 use Test::Differences qw(eq_or_diff);
  2         15841  
  2         139  
15 2     2   15 use Test::More;
  2         16  
  2         25  
16 2     2   1567 use Test::UnixExit qw(exit_is exit_is_nonzero);
  2         1319  
  2         1176  
17              
18             our $VERSION = '0.03';
19              
20             has cmd => (
21             is => 'rwp',
22             default => sub {
23             # t/foo.t -> ./foo with restrictive sanity checks on what is
24             # consided valid for a command name--"foo.sh" is not a valid
25             # command name, get rid of that dangly thing at the end, or
26             # manually supply your own Test::Cmd object. 38 characters is
27             # the longest command name I can find on my OpenBSD 6.5 system
28             if ( $0 =~ m{^t/([A-Za-z0-9_][A-Za-z0-9_-]{0,127})\.t$} ) {
29             my $file = $1;
30             return Test::Cmd->new( prog => catfile( getcwd(), $1 ), workdir => '' );
31             } else {
32             croak "could not extract command name from $0";
33             }
34             },
35             );
36             has prog => ( is => 'lazy', );
37              
38 1     1   64 sub _build_prog { $_[0]->cmd->prog }
39              
40             sub BUILD {
41 4     4 1 24182 my ( $self, $args ) = @_;
42 4 100 100     127 if ( exists $args->{cmd} and !ref $args->{cmd} ) {
43             # TODO may need to fully qualify this path depending on how that
44             # interacts with chdir (or if the caller is making any of those)
45 2         31 $self->_set_cmd( Test::Cmd->new( prog => $args->{cmd}, workdir => '' ) );
46             }
47             }
48              
49             sub run {
50 8     8 1 20361 my ( $self, %p ) = @_;
51              
52 8   100     136 $p{env} //= {};
53             # no news is good news. and here is the default
54 8   100     43 $p{status} //= 0;
55 8   66     113 $p{stderr} //= qr/^$/;
56 8   66     85 $p{stdout} //= qr/^$/;
57              
58 8         39 my $cmd = $self->cmd;
59 8 100       57 my $name = $cmd->prog . ( exists $p{args} ? ' ' . $p{args} : '' );
60              
61 8         174 local @ENV{ keys $p{env}->%* } = values $p{env}->%*;
62              
63 8 100       42 $cmd->run( map { exists $p{$_} ? ( $_ => $p{$_} ) : () } qw(args chdir stdin) );
  24         131  
64              
65             # tests relative to the caller so the test failures don't point at
66             # lines of this function
67 8         114026 local $Test::Builder::Level = $Test::Builder::Level + 1;
68              
69             # probably should be paired with { status => 1 } and that the
70             # process being tested is expected to die (with some unknown
71             # status code)
72 8         80 my $status = $?;
73 8 100       104 $status = exit_is_nonzero( $status ) if $p{munge_status};
74              
75 8         266 exit_is( $status, $p{status}, "STATUS $name" );
76             # for some commands a regex suffices but for others want to compare
77             # expected lines NOTE this is sloppy about trailing whitespace which
78             # many but not all things may be forgiving of
79 8 100       11205 if ( ref $p{stdout} eq 'ARRAY' ) {
80 2         214 eq_or_diff( [ map { s/\s+$//r } split $/, $cmd->stdout ],
81 1         52 $p{stdout}, 'STDOUT ' . $name );
82             } else {
83 7 100       86 ok( $cmd->stdout =~ m/$p{stdout}/, 'STDOUT ' . $name )
84             or diag 'STDOUT ' . $cmd->stdout;
85             }
86 8 100       8018 ok( $cmd->stderr =~ m/$p{stderr}/, 'STDERR ' . $name )
87             or diag 'STDERR ' . $cmd->stderr;
88              
89             # for when the caller needs to poke at the results for something not
90             # covered by the above
91 8         5967 return $cmd;
92             }
93              
94             1;
95             __END__