File Coverage

blib/lib/PITA/Guest.pm
Criterion Covered Total %
statement 19 21 90.4
branch n/a
condition n/a
subroutine 7 7 100.0
pod n/a
total 26 28 92.8


line stmt bran cond sub pod time code
1             package PITA::Guest;
2              
3             =pod
4              
5             =head1 NAME
6              
7             PITA::Guest - The PITA Guest abstract, a container for running tests
8              
9             =head1 DESCRIPTION
10              
11             All testing is run inside a Guest, a container object usually involving
12             a system image and a configuration.
13              
14             This class implements the Guest abstraction.
15              
16             =head1 METHODS
17              
18             =cut
19              
20 1     1   1877 use 5.008;
  1         3  
  1         31  
21 1     1   4 use strict;
  1         2  
  1         28  
22 1     1   2641 use Process ();
  1         218  
  1         18  
23 1     1   6 use File::Spec ();
  1         1  
  1         15  
24 1     1   6 use File::Basename ();
  1         1  
  1         43  
25 1     1   871 use Params::Util ();
  1         5680  
  1         28  
26 1     1   546 use PITA::XML ();
  0            
  0            
27              
28             our $VERSION = '0.60';
29             our @ISA = 'Process';
30              
31              
32              
33              
34              
35             #####################################################################
36             # Constructors
37              
38             =pod
39              
40             =head2 new
41              
42             $guest = PITA::Guest->new( 'guest-51231.pita' );
43             $guest = PITA::Guest->new( \$file_content );
44             $guest = PITA::Guest->new( $guest_xml_object );
45              
46             The C constructor creates a new B object from an XML
47             description. It takes a single param of either a L
48             object, a string which is the name of a PITA file containing the XML
49             description, or a SCALAR reference (which may be a constant SCALAR ref)
50             containing the XML.
51              
52             Returns a new C object, or dies on error.
53              
54             =cut
55              
56             sub new {
57             my $class = shift;
58              
59             # Handle the param
60             my $file = undef;
61             my $guest_xml = undef;
62             if ( Params::Util::_INSTANCE($_[0], 'PITA::XML::Guest') ) {
63             $guest_xml = shift;
64              
65             } elsif ( Params::Util::_STRING($_[0]) ) {
66             $file = shift;
67             unless ( -f $file ) {
68             Carp::croak('Did not provide a valid filename');
69             }
70             $guest_xml = PITA::XML::Guest->read($file);
71              
72             } else {
73             Carp::croak("Invalid param provided to PITA::Guest::new");
74             }
75              
76             # Create the object
77             my $self = bless {
78             file => $file,
79             guestxml => $guest_xml,
80             driver => undef,
81             }, $class;
82              
83             # If and only if the Guest has an image, save its absolute path
84             if ( $self->guestxml->files ) {
85             my $filexml = ($self->guestxml->files)[0];
86             my $filename = $filexml->filename;
87             if ( File::Spec->file_name_is_absolute( $filename ) ) {
88             $self->{absimage} = $filename;
89             } elsif ( defined $file ) {
90             $filename = File::Spec->catfile(
91             File::Basename::dirname($file),
92             $filename,
93             );
94             unless ( File::Spec->file_name_is_absolute( $filename ) ){
95             $filename = File::Spec->rel2abs( $filename );
96             }
97             $self->{absimage} = $filename;
98             } elsif ( defined $guest_xml->base ) {
99             $filename = File::Spec->catfile(
100             $guest_xml->base,
101             $filename,
102             );
103             unless ( File::Spec->file_name_is_absolute( $filename ) ){
104             $filename = File::Spec->rel2abs( $filename );
105             }
106             $self->{absimage} = $filename;
107             } else {
108             die "Unable to locate image file for guest";
109             }
110             }
111              
112             # Create the driver
113             my $driver = 'PITA::Guest::Driver::' . $self->guestxml->driver;
114             eval "require $driver"; die $@ if $@;
115             my %params = ( guest => $self->guestxml );
116             if ( $self->{absimage} ) {
117             $params{absimage} = $self->{absimage};
118             }
119             if ( $self->{minicpan} ) {
120             $params{minicpan} = $self->{minicpan};
121             }
122             if ( $driver->isa('PITA::Guest::Driver::Image') ) {
123             $params{support_server_addr} = '127.0.0.1';
124             $params{support_server_port} = 12345;
125             }
126             $self->{driver} = $driver->new( %params );
127              
128             $self;
129             }
130              
131              
132              
133              
134              
135             #####################################################################
136             # Accessors
137              
138             =pod
139              
140             =head2 file
141              
142             The C accessor returns the name of the file the Guest object was
143             created from.
144              
145             =cut
146              
147             sub file {
148             $_[0]->{file};
149             }
150              
151             =pod
152              
153             =head2 guestxml
154              
155             The L file loads to a L object which is
156             held internally.
157              
158             The C accessor returns the L object.
159              
160             =cut
161              
162             sub guestxml {
163             $_[0]->{guestxml};
164             }
165              
166             =pod
167              
168             =head2 discovered
169              
170             The C method returns true if the Guest has gone through the
171             discovery process that identifies testing platforms in the Guest, or false
172             if not.
173              
174             =cut
175              
176             sub discovered {
177             $_[0]->guestxml->discovered;
178             }
179              
180             =pod
181              
182             =head2 driver
183              
184             The C method returns the L object within the
185             L that the tests are run through.
186              
187             =cut
188              
189             sub driver {
190             $_[0]->{driver};
191             }
192              
193              
194              
195              
196              
197             #####################################################################
198             # Main Methods
199              
200             =pod
201              
202             =head2 ping
203              
204             All guests are required to identify themselves.
205              
206             The C method is dispatched to the driver and does whatever is
207             necesary to determine if the guest is live (and actually a
208             C)
209              
210             Returns true (may take up to 5 minutes) or false if not.
211              
212             =cut
213              
214             sub ping {
215             $_[0]->driver->ping;
216             }
217              
218             =pod
219              
220             =head2 discover
221              
222             Most often the detailed of a Guest are provided without identifying
223             what is set up inside them.
224              
225             The C method is dispatched to the driver, loading the Guest
226             and interrogating it to determine the testing platforms available from
227             it.
228              
229             Returns true (may take up to 5 minutes) if the testing platforms are
230             correctly discovered, or dies if not.
231              
232             =cut
233              
234             sub discover {
235             $_[0]->driver->discover;
236             }
237              
238             =pod
239              
240             =head2 test
241              
242             $response = $guest->test( 'request.pita' );
243              
244             The C method executes a single testing request.
245              
246             It takes as argument the name of a L file with a
247             ErequestE at the root. Loads the request and dispatches
248             it to the driver, which will load the Guest, inject the test
249             request and package, and then hand back the response once it is
250             completed.
251              
252             Depending on the package, this could take from minutes to hours to
253             run.
254              
255             Returns a L object, or dies on error.
256              
257             =cut
258              
259             sub test {
260             my $self = shift;
261             my $filename = Params::Util::_STRING(shift);
262             unless ( $filename and -f $filename and -r _ ) {
263             Carp::croak('Did not provide a request file');
264             }
265              
266             # Load the request object
267             my $request = PITA::XML::Request->read($filename);
268             unless ( $request ) {
269             Carp::croak('Failed to load request file');
270             }
271              
272             # Locate the archive file, converting the request
273             # filename to absolute if needed.
274             ### FIXME: If the tag can contain anything
275             ### other than a raw filename, this code is not
276             ### portable, and needs improving to split the
277             ### first before appending.
278             my $archive = File::Basename::dirname($filename);
279             $archive = File::Spec->catfile( $archive, $request->file->filename );
280             unless ( $archive and -f $archive and -r _ ) {
281             Carp::croak('Failed to find archive, or insufficient permissions');
282             }
283             unless ( File::Spec->file_name_is_absolute( $archive ) ) {
284             $archive = File::Spec->rel2abs( $archive );
285             }
286             $request->file->{filename} = $archive;
287              
288             # Just use the first platform until we write a selection method
289             my $platform = ($self->guestxml->platforms)[0];
290             unless ( Params::Util::_INSTANCE($platform, 'PITA::XML::Platform') ) {
291             Carp::croak('Could not autoselect a platform');
292             }
293              
294             # Hand off the testing request to the driver
295             $self->driver->test( $request, $platform );
296             }
297              
298             =pod
299              
300             =head2 save
301              
302             The L object remembers the name of the file it was loaded from.
303              
304             If you run C, then afterwards your can run C to save the
305             now-discovered Guest back to a file.
306              
307             Returns true or dies on error.
308              
309             =cut
310              
311             sub save {
312             my $self = shift;
313             unless ( defined $self->file ) {
314             Carp::croak("No file to save to");
315             }
316             $self->guestxml->write( $self->file );
317             }
318              
319             1;
320              
321             =pod
322              
323             =head1 SUPPORT
324              
325             Bugs should be reported via the CPAN bug tracker at
326              
327             L
328              
329             For other issues, contact the author.
330              
331             =head1 AUTHOR
332              
333             Adam Kennedy Eadamk@cpan.orgE
334              
335             =head1 SEE ALSO
336              
337             The Practical Image Testing Architecture (L)
338              
339             L, L
340              
341             =head1 COPYRIGHT
342              
343             Copyright 2005 - 2011 Adam Kennedy.
344              
345             This program is free software; you can redistribute
346             it and/or modify it under the same terms as Perl itself.
347              
348             The full text of the license can be found in the
349             LICENSE file included with this module.
350              
351             =cut