File Coverage

lib/Win32/TestServerManager.pm
Criterion Covered Total %
statement 10 12 83.3
branch n/a
condition n/a
subroutine 4 4 100.0
pod n/a
total 14 16 87.5


line stmt bran cond sub pod time code
1             package Win32::TestServerManager;
2            
3 1     1   100174 use strict;
  1         2  
  1         41  
4 1     1   5 use warnings;
  1         2  
  1         31  
5 1     1   6 use Carp;
  1         6  
  1         73  
6 1     1   22811 use Win32;
  0            
  0            
7             use Win32::Process;
8             use File::Spec;
9            
10             our $VERSION = '0.04';
11            
12             sub new {
13             my $class = shift;
14            
15             bless {}, $class;
16             }
17            
18             sub spawn {
19             my ($self, $id, $args, $options) = @_;
20            
21             $self->kill($id) if $self->{$id};
22            
23             if ( !defined $args ) { $options = {}; $args = ''; }
24             elsif ( ref $args eq 'HASH' ) { $options = $args; $args = ''; }
25            
26             if ( !defined $options ) { $options = {}; }
27             elsif ( ref $options ne 'HASH' ) {
28             croak "Usage: ->spawn( id, args, { options } )";
29             }
30            
31             $args .= ' ' . $options->{args} if $options->{args};
32            
33             my $executable = $options->{executable} || $^X;
34            
35             my $flag = $options->{cflag} || NORMAL_PRIORITY_CLASS;
36             $flag |= CREATE_NEW_CONSOLE if $options->{new_console};
37             $flag |= CREATE_NO_WINDOW if $options->{no_window};
38            
39             my $workdir = $options->{working_dir} || '.';
40            
41             if ( $options->{create_server_with} ) {
42             my $code = $options->{create_server_with};
43             if ( ref $code eq 'CODE' ) {
44             require B::Deparse;
45             my $deparser = B::Deparse->new;
46             $code = $deparser->coderef2text( $code );
47             }
48             require File::Temp;
49             require File::Slurp;
50             my $tmpfile = File::Temp::tempnam( $workdir => '_tmp' );
51             File::Slurp::write_file( $tmpfile, $code );
52             $args = "$args $tmpfile";
53             $self->{$id}->{tmpfile} = $tmpfile;
54             }
55            
56             $self->{$id}->{dont_kill} = $options->{dont_kill};
57            
58             Win32::Process::Create(my $process,
59             $executable,
60             "$executable $args",
61             0,
62             $flag,
63             File::Spec->rel2abs($workdir),
64             ) or croak Win32::FormatMessage( Win32::GetLastError() );
65            
66             $self->{$id}->{process} = $process;
67             }
68            
69             sub instance {
70             my ($self, $id) = @_;
71             return exists $self->{$id} ? $self->{$id} : undef;
72             }
73            
74             sub process {
75             my ($self, $id) = @_;
76             if ( my $instance = $self->instance($id) ) {
77             return exists $instance->{process} ? $instance->{process} : undef;
78             }
79             return;
80             }
81            
82             sub instances {
83             my $self = shift;
84             keys %{ $self };
85             }
86            
87             sub pid {
88             my ($self, $id) = @_;
89            
90             if ( my $instance = $self->{$id} ) {
91             return $instance->{process}->GetProcessID;
92             }
93             return;
94             }
95            
96             sub kill {
97             my ($self, $id, $exitcode) = @_;
98            
99             $exitcode = 0 unless defined $exitcode;
100            
101             if ( my $instance = delete $self->{$id} ) {
102             if ( $instance->{tmpfile} ) {
103             my $counter = 0;
104             while ( $counter++ < 3 ) {
105             unlink $instance->{tmpfile};
106             last unless -f $instance->{tmpfile};
107             sleep 1;
108             $counter++;
109             }
110             }
111             return if $instance->{dont_kill};
112            
113             $instance->{process}->Kill($exitcode);
114             }
115             }
116            
117             sub DESTROY {
118             my $self = shift;
119            
120             foreach my $id ( keys %{ $self } ) {
121             $self->kill($id);
122             }
123             }
124            
125             1;
126            
127             __END__