File Coverage

blib/lib/Apache/Voodoo/Test.pm
Criterion Covered Total %
statement 15 229 6.5
branch 0 64 0.0
condition 0 9 0.0
subroutine 5 45 11.1
pod 0 40 0.0
total 20 387 5.1


line stmt bran cond sub pod time code
1             =pod #####################################################################################
2              
3             =head1 NAME
4              
5             Apache::Voodoo::Test - Testing harness for Apache Voodoo applications.
6              
7             =head1 SYNOPSIS
8              
9             Provides a testing harness for Apache Voodoo applications.
10              
11             Complete documentation is available at http://www.apachevoodoo.com
12              
13             =cut ###############################################################################
14             package Apache::Voodoo::Test;
15              
16             $VERSION = "3.0200";
17              
18 1     1   4464 use strict;
  1         3  
  1         41  
19              
20 1     1   6 use Time::HiRes;
  1         2  
  1         10  
21 1     1   114 use File::Spec;
  1         3  
  1         27  
22              
23 1     1   6 use Apache::Voodoo::Constants;
  1         1  
  1         23  
24 1     1   5 use Apache::Voodoo::Engine;
  1         9  
  1         2789  
25              
26             sub new {
27 0     0 0   my $class = shift;
28 0           my %opts = @_;
29              
30 0 0         die "id is a required parameter" unless $opts{'id'};
31              
32 0           my $self = {};
33 0           bless $self, $class;
34              
35 0           $self->{'id'} = $opts{'id'};
36              
37 0           $self->{'constants'} = Apache::Voodoo::Constants->new();
38              
39             # If they've specified an alternate config file for testing,
40             # reach behind the scenes and make the engine look for it intead.
41 0 0         $self->{'constants'}->{'CONF_FILE'} = $opts{'config_file'} if ($opts{'config_file'});
42              
43 0           $self->{'engine'} = Apache::Voodoo::Engine->new(
44             'mp' => $self,
45             'only_start' => $opts{'id'},
46             'constants' => $self->{'constants'}
47             );
48              
49 0           $self->{'engine'}->init_app();
50 0           $self->{'engine'}->begin_run();
51              
52             # FIXME: Hack to prefer my extended version of Pod::WSDL over the
53             # one on CPAN. This will need to stay in place until either the
54             # author of Pod::WSDL replys or I release my own version.
55 0           $self->{'pwsdl'} = undef;
56 0           eval {
57 0           require Pod::WSDL2;
58 0           $self->{'pwsdl'} = 'Pod::WSDL2';
59             };
60 0 0         if ($@) {
61 0           eval {
62 0           require Pod::WSDL;
63 0           $self->{'pwsdl'} = 'Pod::WSDL';
64             };
65             }
66              
67 0           return $self;
68             }
69              
70             sub make_request {
71 0     0 0   my $self = shift;
72              
73 0           $self->set_request();
74              
75 0 0         if ($_[0] =~ /^(GET|POST|PUT|DELETE)$/) {
76 0           $self->method(shift);
77 0           $self->uri(shift);
78             }
79             else {
80 0           $self->method('GET');
81 0           $self->uri(shift);
82             }
83              
84 0           $self->parameters(@_);
85              
86             ####################
87             # URI translation jazz to get down to a proper filename
88             ####################
89 0           my $uri = $self->uri();
90 0 0         if ($uri =~ /\/$/o) {
91 0           return $self->redirect($uri."index");
92             }
93              
94 0           my $filename = $self->filename();
95              
96             # remove the optional trailing .tmpl
97 0           $filename =~ s/\.tmpl$//o;
98 0           $uri =~ s/\.tmpl$//o;
99              
100 0 0         unless (-e "$filename.tmpl") { return $self->declined; }
  0            
101 0 0         unless (-r "$filename.tmpl") { return $self->forbidden; }
  0            
102              
103             ####################
104             # Get paramaters
105             ####################
106 0           my $params;
107 0           eval {
108 0           $params = $self->{'engine'}->parse_params();
109             };
110 0 0         if (my $e = Exception::Class->caught()) {
111 0           warn "$e";
112 0           $self->server_error;
113             }
114              
115             ####################
116             # History capture
117             ####################
118 0 0 0       if ($self->is_get &&
      0        
119             !$params->{ajax_mode} &&
120             !$params->{return}
121             ) {
122 0           $self->{'engine'}->history_capture($uri,$params);
123             }
124              
125             ####################
126             # Execute the controllers
127             ####################
128 0           my $content;
129 0           eval {
130 0           $content = $self->{'engine'}->execute_controllers($uri,$params);
131             };
132 0 0         if (my $e = Exception::Class->caught()) {
133 0 0         if ($e->isa("Apache::Voodoo::Exception::Application::Redirect")) {
    0          
    0          
    0          
134 0           $self->{'engine'}->status($self->redirect);
135 0           return $self->redirect($e->target());
136             }
137             elsif ($e->isa("Apache::Voodoo::Exception::Application::RawData")) {
138 0 0         $self->header_out(each %{$e->headers}) if (ref($e->headers) eq "HASH");
  0            
139 0           $self->content_type($e->content_type);
140 0           $self->print($e->data);
141              
142 0           $self->{'engine'}->status($self->ok);
143 0           return $self->ok;
144             }
145             elsif ($e->isa("Apache::Voodoo::Exception::Application::Unauthorized")) {
146 0           $self->{'engine'}->status($self->unauthorized);
147 0           return $self->unauthorized;
148             }
149             elsif (! $e->isa("Apache::Voodoo::Exception::Application")) {
150             # Apache::Voodoo::Exception::RunTime
151             # Apache::Voodoo::Exception::RunTime::BadCommand
152             # Apache::Voodoo::Exception::RunTime::BadReturn
153             # Exception::Class::DBI
154 0 0         unless ($self->{'engine'}->is_devel_mode()) {
155 0           warn "$@";
156 0           $self->{'engine'}->status($self->server_error);
157 0           return $self->server_error;
158             }
159              
160             }
161 0           $content = $e;
162             }
163              
164 0           $self->{'controller_output'} = $content;
165 0           my $view = $self->{'engine'}->execute_view($content);
166              
167             # output content
168 0           $self->content_type($view->content_type());
169 0           $self->print($view->output());
170              
171             ####################
172             # Clean up
173             ####################
174 0           $self->{'engine'}->status($self->ok);
175 0           $view->finish();
176              
177 0           return $self->ok;
178             }
179              
180             sub get_wsdl {
181 0     0 0   my $self = shift;
182 0           my $uri = $self->uri(shift);
183              
184 0 0         unless ($self->{pwsdl}) {
185 0           $self->content_type('text/plain');
186 0           $self->print("No WSDL generator installed. Either install Pod::WSDL or Pod::WSDL2");
187 0           return $self->ok;
188             }
189              
190             # copied straight from Soap.pm
191             # FIXME hack. Shouldn't be looking in there to get this
192 0           $uri =~ s/^\/+//;
193              
194 0 0         unless ($self->{'engine'}->_app->{'controllers'}->{$uri}) {
195 0           return $self->not_found();
196             }
197              
198 0           my $m = ref($self->{'engine'}->_app->{'controllers'}->{$uri});
199 0 0         if ($m eq "Apache::Voodoo::Loader::Dynamic") {
200 0           $m = ref($self->{'engine'}->_app->{'controllers'}->{$uri}->{'object'});
201             }
202             # FIXME here ends the hackery
203              
204 0           my $wsdl;
205 0           eval {
206             # FIXME the other part of the Pod::WSDL version hack
207 0           $wsdl = $self->{'pwsdl'}->new(
208             source => $m,
209             location => $self->server_url().$uri,
210             pretty => 1,
211             withDocumentation => 1
212             );
213 0           $wsdl->targetNS($self->server_url());
214             };
215 0 0         if ($@) {
216 0           $self->content_type('text/plain');
217 0           $self->print("Error generating WDSL:\n\n$@");
218             }
219             else {
220 0           $self->content_type('text/xml');
221 0           $self->print($wsdl->WSDL);
222             }
223              
224 0           return $self->ok;
225             }
226              
227             sub get_dbh {
228 0     0 0   my $self = shift;
229 0           return $self->{'engine'}->{'dbh'};
230             }
231              
232             sub get_session {
233 0     0 0   my $self = shift;
234 0           return $self->{'engine'}->{'session'};
235             }
236              
237             sub get_model {
238 0     0 0   my $self = shift;
239 0           my $model = shift;
240              
241 0           return $self->{'engine'}->get_model($self->{'id'},$model);
242             }
243              
244             sub set_request {
245 0     0 0   my $self = shift;
246              
247 0           $self->{'request_id'} = Time::HiRes::time;
248              
249 0           foreach (qw(uri cookiejar content_type is_get redirected_to controller_output)) {
250 0           delete $self->{$_};
251             }
252              
253 0           foreach (qw(err_header_out header_out header_in)) {
254 0           $self->{$_} = [];
255             }
256              
257 0           foreach (qw(parameters)) {
258 0           $self->{$_} = {};
259             }
260              
261 0           $self->{'method'} = 'GET';
262 0           $self->{'remote_host'} = 'localhost';
263 0           $self->{'remote_ip'} = '127.0.0.1';
264             }
265              
266 0     0 0   sub request_id { return $_[0]->{'request_id'}; }
267              
268             # TODO
269 0     0 0   sub dir_config { undef; }
270              
271             sub uri {
272 0     0 0   my $self = shift;
273              
274 0 0         if ($_[0]) {
275 0           $self->{'uri'} = $_[0];
276 0           $self->{'uri'} =~ s/^\///g;
277             }
278 0           return $self->{'uri'};
279             }
280              
281             sub filename {
282 0     0 0   my $self = shift;
283 0           return File::Spec->catfile(
284             $self->{'constants'}->install_path(),
285             $self->{'id'},
286             $self->{'constants'}->tmpl_path(),
287             $self->{'uri'}
288             );
289             }
290              
291             sub method {
292 0     0 0   my $self = shift;
293              
294 0 0         if ($_[0] =~ /^(get|post)$/) {
295 0           $self->{'method'} = uc($_[0]);
296             }
297              
298 0           return $self->{'method'};
299             }
300              
301              
302             sub print {
303 0     0 0   my $self = shift;
304              
305 0           $self->{'output'} .= $_[0];
306             }
307              
308             sub controller_output {
309 0     0 0   my $self = shift;
310 0           return $self->{'controller_output'};
311             }
312              
313             sub output {
314 0     0 0   my $self = shift;
315 0           return $self->{'output'};
316             }
317              
318 0     0 0   sub is_get { return ($_[0]->method eq "GET"); }
319 0     0 0   sub get_app_id { return $_[0]->{"id"}; }
320 0     0 0   sub site_root { return "/"; }
321              
322             sub remote_ip {
323 0     0 0   my $self = shift;
324 0 0         $self->{'remote_ip'} = $_[0] if $_[0];
325 0           return $self->{'remote_ip'};
326             }
327              
328             sub remote_host {
329 0     0 0   my $self = shift;
330 0 0         $self->{'remote_host'} = $_[0] if $_[0];
331 0           return $self->{'remote_host'};
332             }
333              
334             sub server_url {
335 0     0 0   return "http://localhost/";
336             }
337              
338 0     0 0   sub if_modified_since {
339             }
340              
341             sub register_cleanup {
342 0     0 0   my $self = shift;
343              
344             }
345              
346 0     0 0   sub status { return $_[0]->{'status'}; }
347              
348 0     0 0   sub declined { my $self = shift; $self->{'status'} = "DECLINED"; return $self->{'status'}; }
  0            
  0            
349 0     0 0   sub forbidden { my $self = shift; $self->{'status'} = "FORBIDDEN"; return $self->{'status'}; }
  0            
  0            
350 0     0 0   sub unauthorized { my $self = shift; $self->{'status'} = "AUTH_REQUIRED"; return $self->{'status'}; }
  0            
  0            
351 0     0 0   sub ok { my $self = shift; $self->{'status'} = "OK"; return $self->{'status'}; }
  0            
  0            
352 0     0 0   sub server_error { my $self = shift; $self->{'status'} = "SERVER_ERROR"; return $self->{'status'}; }
  0            
  0            
353 0     0 0   sub not_found { my $self = shift; $self->{'status'} = "NOT_FOUND"; return $self->{'status'}; }
  0            
  0            
354              
355             sub content_type {
356 0     0 0   my $self = shift;
357              
358 0 0         $self->{'content_type'} = shift if scalar(@_);
359 0           return $self->{'content_type'};
360             }
361              
362             sub err_header_out {
363 0     0 0   my $self = shift;
364              
365 0 0         push(@{$self->{'err_header_out'}},@_) if scalar(@_);
  0            
366 0           return $self->{'err_header_out'};
367             }
368              
369             sub header_out {
370 0     0 0   my $self = shift;
371              
372 0 0         push(@{$self->{'header_out'}},@_) if scalar(@_);
  0            
373 0           return $self->{'header_out'};
374             }
375              
376             sub header_in {
377 0     0 0   my $self = shift;
378              
379 0 0         push(@{$self->{'header_in'}},@_) if scalar(@_);
  0            
380 0           return $self->{'header_in'};
381             }
382              
383 0     0 0   sub redirected_to { return $_[0]->{'redirected_to'}; }
384             sub redirect {
385 0     0 0   my $self = shift;
386 0           my $loc = shift;
387              
388 0           $self->{'redirected_to'} = $loc;
389 0           $self->{'status'} = "REDIRECT";
390              
391 0           return "REDIRECT";
392             }
393              
394             sub parameters {
395 0     0 0   my $self = shift;
396              
397 0 0         if (scalar(@_)) {
398 0 0 0       if (scalar(@_) == 1 && ref($_[0]) eq "HASH") {
399 0           $self->{'parameters'} = shift;
400             }
401             else {
402 0           $self->{'parameters'} = [ @_ ];
403             }
404             }
405              
406 0           return $self->{'parameters'};
407             }
408              
409             sub parse_params {
410 0     0 0   my $self = shift;
411 0           my $upload_max = shift;
412              
413 0 0         if (ref($self->{'parameters'}) eq "HASH") {
414 0           return $self->{'parameters'};
415             }
416             else {
417 0           my $params = {};
418 0           my $c=0;
419 0           foreach (@{$self->{'parameters'}}) {
  0            
420 0 0         if (ref($_) eq "HASH") {
421 0           while (my ($k,$v) = each %{$_}) {
  0            
422 0           $params->{$k} = $v;
423             }
424             }
425 0           $params->{'ARGV'}->[$c] = $_;
426 0           $c++;
427             }
428 0           return $params;
429             }
430             }
431              
432             sub set_cookie {
433 0     0 0   my $self = shift;
434              
435 0           my $name = shift;
436 0           my $value = shift;
437 0           my $expires = shift;
438              
439 0           $self->{"cookie"}->{$name} = {
440             value => $value,
441             domain => $self->remote_host()
442             };
443              
444 0           $self->err_header_out('Set-Cookie' => "$name=$value; path=/; domain=".$self->remote_host() ."; HttpOnly");
445             }
446              
447             sub get_cookie {
448 0     0 0   my $self = shift;
449 0           my $name = shift;
450              
451 0           return $self->{'cookie'}->{$name}->{'value'};
452             }
453              
454             1;
455              
456             ################################################################################
457             # Copyright (c) 2005-2010 Steven Edwards (maverick@smurfbane.org).
458             # All rights reserved.
459             #
460             # You may use and distribute Apache::Voodoo under the terms described in the
461             # LICENSE file include in this package. The summary is it's a legalese version
462             # of the Artistic License :)
463             #
464             ################################################################################