Merge 'deprecate_appclass_actions' into 'trunk'
Tomas Doran [Thu, 10 Sep 2009 01:14:13 +0000 (01:14 +0000)]
r11046@t0mlaptop (orig r11045):  yousef | 2009-08-07 00:07:07 +0100
Moved action methods from t/lib/TestApp.pm to t/lib/Test/Controller/Root.pm. Uncommented the if statement in lib/Catalyst/Controller.pm that checks for actions in the appclass.

53 files changed:
Changes
MANIFEST.SKIP
Makefile.PL
TODO
lib/Catalyst.pm
lib/Catalyst/Action.pm
lib/Catalyst/ClassData.pm
lib/Catalyst/Component.pm
lib/Catalyst/Controller.pm
lib/Catalyst/DispatchType/Chained.pm
lib/Catalyst/DispatchType/Path.pm
lib/Catalyst/DispatchType/Regex.pm
lib/Catalyst/Dispatcher.pm
lib/Catalyst/Engine.pm
lib/Catalyst/Engine/CGI.pm
lib/Catalyst/Engine/HTTP.pm
lib/Catalyst/Request.pm
lib/Catalyst/Response.pm
lib/Catalyst/Runtime.pm
lib/Catalyst/Stats.pm
t/aggregate/live_component_controller_action_index_or_default.t
t/aggregate/live_component_controller_action_path_matchsingle.t
t/aggregate/live_component_controller_action_regexp.t
t/aggregate/live_component_controller_action_streaming.t
t/aggregate/live_component_controller_anon.t
t/aggregate/live_component_view_single.t
t/aggregate/live_engine_request_escaped_path.t
t/aggregate/live_engine_request_headers.t
t/aggregate/live_engine_request_remote_user.t
t/aggregate/unit_core_uri_for_action.t
t/author/optional_http-server.t [moved from t/optional_http-server.t with 61% similarity]
t/caf_backcompat.t
t/cdi_backcompat_plugin_accessor_override.t [deleted file]
t/custom_exception_class_simple.t [new file with mode: 0644]
t/deprecated.t
t/lib/TestApp.pm
t/lib/TestApp/Action/TestMyAction.pm
t/lib/TestApp/Controller/Action/Streaming.pm
t/lib/TestApp/Controller/Anon.pm
t/lib/TestAppClassExceptionSimpleTest.pm [new file with mode: 0644]
t/lib/TestAppNonMooseController.pm [new file with mode: 0644]
t/lib/TestAppNonMooseController/Controller/Foo.pm [new file with mode: 0644]
t/lib/TestAppNonMooseController/ControllerBase.pm [new file with mode: 0644]
t/optional_http-server-restart.t
t/unit_controller_actions.t [new file with mode: 0644]
t/unit_core_classdata.t
t/unit_core_component_loading.t
t/unit_core_plugin.t
t/unit_core_setup.t
t/unit_core_setup_log.t
t/unit_core_setup_stats.t
t/unit_metaclass_compat_non_moose_controller.t
t/unit_stats.t

diff --git a/Changes b/Changes
index b0d8a94..bba5e3b 100644 (file)
--- a/Changes
+++ b/Changes
@@ -1,4 +1,56 @@
 # This file documents the revision history for Perl extension Catalyst.
+#
+
+    - Add allow_mutable_ancestors option when force inlining a constructor onto
+      applications with plugins defining their own (usually Class::Accessor::Fast)
+      new methods, to avoid warnings generated by upcoming Moose releases
+      as we can make a class (MyApp) immutable when not all of it's superclasses
+      (e.g. plugins not fully Moose converted, but using
+       MooseX::Emulate::Class::Accessor::Fast) are not immutable.
+
+5.80012 2009-09-09 19:09:09
+
+  Bug fixes:
+     - Fix t/optional_http-server.t test.
+     - Fix t/optional_http-server-restart.t test.
+     - Fix duplicate components being loaded at setup time, each component is
+       now loaded at most once + tests.
+     - Fix backward compatibility - hash key configured actions are stored in
+       is returned to 'actions'.
+     - Fix get_action_methods returning duplicate methods when a method is both
+       decorated with method attributes and set as an action in config.
+
+  Refactoring / cleanups:
+     - Reduce minimum supported perl version from 5.8.6 to 5.8.4 as there are
+       many people still running/testing this version with no known issues.
+
+  Tests:
+     - Make the optional_http_server.t test an author only test which must be
+       run by authors to stop it being broken again.
+     - Fix recursion warnings in the test suites.
+
+5.80011 2009-08-23 13:48:15
+
+  Bug fixes:
+      - Remove leftovers of the restarter engine. The removed code caused test
+        failures, which weren't apparent for anyone still having an old version
+        installed in @INC.
+
+5.80010 2009-08-21 23:32:15
+
+  Bug fixes:
+      - Fix and add tests for a regression introduced by 5.80008.
+        Catalyst::Engine is now able to send out data from filehandles larger
+        than the default chunksize of 64k again.
+
+5.80009 2009-08-21 22:21:08
+
+  Bug fixes:
+      - Fix and add tests for generating inner packages inside the COMPONENT
+        method, and those packages being correctly registered as components.
+        This fixes Catalyst::Model::DBIC among others.
+
+5.80008 2009-08-21 17:47:30
 
   Bug fixes:
        - Fix replace_constructor warning to actually work if you make your
          in inner packages might not be registered. This especially affected
          tests.
        - Catalyst::Engine::FastCGI - relax the check for versions of Microsoft
-         IIS. Provides compatibility with Windows 2008 R2 as well as 
+         IIS. Provides compatibility with Windows 2008 R2 as well as
          (hopefully) future versions.
+       - In tests which depend on the values of environment variables,
+         localise the environment, then delete only relevant environment
+         variables (RT#48555)
+       - Fix issue with Engine::HTTP not sending headers properly in some cases
+         (RT#48623)
+       - Make Catalyst::Engine write at least once when finalizing the response
+         body from a filehandle, even if the write is empty. This avoids fail
+         when trying to send out an empty response body from a filehandle.
+       - Catalyst::Engine::HTTP - Accept a fully qualified absolute URI in the
+         Request-URI of the Request-Line
 
   Refactoring / cleanups:
        - Deleted the Restarter engine and its Watcher code. Use the
          new Catalyst::Restarter in a recent Catalyst::Devel instead.
-       - New unit test for Catalyst::Action 'unit_core_action.t' (groditi)
+       - New unit test for Catalyst::Action 'unit_core_action.t'
+       - Bump minimum supported perl version from 5.8.1 to 5.8.6 as there are
+         known issues with 5.8.3.
+       - Debug output uses dynamic column sizing to create more readable output
+         when using a larger $ENV{COLUMNS} setting. (groditi)
 
   New features:
-       - private_path method for Catalyst::Action + docs + tests (groditi)
+       - Added private_path method for Catalyst::Action
+       - Allow uri_for($controller_instance) which will produce a URI
+         for the controller namespace
+       - Break setup_components into two more parts: locate_components and
+         expand_component_module (rjbs)
+       - Allow Components to return anon classed from their COMPONENT method
+         correctly, and have action registration work on Controllers returned
+         as such by adding a catalyst_component_name accessor for all components
+         which returns the component instance's name to be used when building
+         actions etc.
+       - Adding X-Forwarded-Port to allow the frontend proxy to dictate the
+         frontend port (jshirley)
+       - Added Catalyst::Stats->created accessor for the time at the start of
+         the request.
 
   Documentation:
        - Fix POD to refer to ->config(key => $val), rather than
          ->config->{key} = $val, as the latter form is deprecated.
        - Clearer docs for the 'uri_for' method.
+       - Fix POD refering to CGI::Cookie. We're using CGI::Simple::Cookie.
+         (Forrest Cahoon)
 
 5.80007 2009-06-30 23:54:34
 
index 24b316c..d9fcc96 100644 (file)
@@ -1 +1 @@
-^(?!script/\w+\.pl$|TODO$|lib/.+(?<!ROADMAP)\.p(m|od)$|inc/|t/aggregate/.*\.t$|t/.*\.(gif|yml|pl|t)$|t/lib/.*\.pm$|t/something/(Makefile.PL|script/foo/bar/for_dist)$|t/conf/extra.conf.in$|Makefile.PL$|README$|MANIFEST$|Changes$|META.yml$)
+^(?!script/\w+\.pl$|TODO$|lib/.+(?<!ROADMAP)\.p(m|od)$|inc/|t/a(uthor|ggregate)/.*\.t$|t/.*\.(gif|yml|pl|t)$|t/lib/.*\.pm$|t/something/(Makefile.PL|script/foo/bar/for_dist)$|t/conf/extra.conf.in$|Makefile.PL$|README$|MANIFEST$|Changes$|META.yml$)
index 6e8fcc7..6fae99a 100644 (file)
@@ -1,17 +1,26 @@
+use strict;
+use warnings;
 use inc::Module::Install 0.87;
-
-perl_version '5.008001';
+BEGIN { # Make it easy for newbies
+    if ($Module::Install::AUTHOR) {
+        require Module::Install::AuthorRequires;
+        require Module::Install::CheckConflicts;
+        require Module::Install::AuthorTests;
+    }
+}
+perl_version '5.008004';
 
 name 'Catalyst-Runtime';
 all_from 'lib/Catalyst/Runtime.pm';
 
+requires 'List::MoreUtils';
 requires 'namespace::autoclean';
 requires 'namespace::clean';
 requires 'B::Hooks::EndOfScope' => '0.08';
 requires 'MooseX::Emulate::Class::Accessor::Fast' => '0.00801';
 requires 'Class::MOP' => '0.83';
 requires 'Moose' => '0.78';
-requires 'MooseX::MethodAttributes::Inheritable' => '0.14';
+requires 'MooseX::MethodAttributes::Inheritable' => '0.15';
 requires 'Carp';
 requires 'Class::C3::Adopt::NEXT' => '0.07';
 requires 'CGI::Simple::Cookie';
@@ -53,6 +62,7 @@ else {
         map  { glob } qw[t/*.t t/aggregate/*.t];
 }
 
+author_tests 't/author';
 author_requires(map {; $_ => 0 } qw(
   Test::NoTabs
   Test::Pod
@@ -111,7 +121,7 @@ my %conflicts = (
     'Catalyst::Plugin::Upload::Image::Magick' => '0.03',
     'Catalyst::Plugin::ConfigLoader'   => '0.22', # Older versions work but
                                                   # throw Data::Visitor warns
-    'Catalyst::Devel'                  => '0.09',
+    'Catalyst::Devel'                  => '1.19',
     'Catalyst::Plugin::SmartURI'       => '0.032',
     'CatalystX::CRUD'                  => '0.37',
     'Catalyst::Action::RenderView'     => '0.07',
@@ -122,6 +132,7 @@ my %conflicts = (
     'Catalyst::Action::REST'           => '0.67',
     'CatalystX::CRUD'                  => '0.42',
     'CatalystX::CRUD::Model::RDBO'     => '0.20',
+    'Catalyst::View::Mason'            => '0.17',
 );
 check_conflicts(%conflicts);
 
diff --git a/TODO b/TODO
index 2dd12f7..4a2b319 100644 (file)
--- a/TODO
+++ b/TODO
@@ -14,7 +14,7 @@
 # Compatibility warnings to add:
 
   - $self->config should warn as config should only ever be called as a
-    class method.
+    class method (TESTS).
 
 # Proposed functionality / feature additions:
 
@@ -40,7 +40,7 @@ http://github.com/willert/catalyst-plugin-log4perl-simple/tree
 ## App / ctx split:
 
   NOTE - these are notes that t0m thought up after doing back compat for
-         _component_class, may be inaccurate, wrong or missing things
+         catalyst_component_class, may be inaccurate, wrong or missing things
          bug mst (at least) to correct before trying more than the first 2
          steps. Please knock yourself out on the first two however :)
 
@@ -60,4 +60,3 @@ http://github.com/willert/catalyst-plugin-log4perl-simple/tree
   - Profit! (Things like changing the complete app config per vhost, i.e.
     writing a config loader / app class role which dispatches per vhost to
     differently configured apps is piss easy)
-
index 7556e34..44dd8e6 100644 (file)
@@ -27,11 +27,12 @@ use URI::https;
 use Tree::Simple qw/use_weak_refs/;
 use Tree::Simple::Visitor::FindByUID;
 use Class::C3::Adopt::NEXT;
+use List::MoreUtils qw/uniq/;
 use attributes;
 use utf8;
 use Carp qw/croak carp shortmess/;
 
-BEGIN { require 5.008001; }
+BEGIN { require 5.008004; }
 
 has stack => (is => 'ro', default => sub { [] });
 has stash => (is => 'rw', default => sub { {} });
@@ -78,7 +79,7 @@ __PACKAGE__->stats_class('Catalyst::Stats');
 
 # Remember to update this in Catalyst::Runtime as well!
 
-our $VERSION = '5.80007';
+our $VERSION = '5.80012';
 
 {
     my $dev_version = $VERSION =~ /_\d{2}$/;
@@ -645,7 +646,7 @@ If you want to search for models, pass in a regexp as the argument.
 
 sub model {
     my ( $c, $name, @args ) = @_;
-
+    my $appclass = ref($c) || $c;
     if( $name ) {
         my @result = $c->_comp_search_prefixes( $name, qw/Model M/ );
         return map { $c->_filter_component( $_, @args ) } @result if ref $name;
@@ -658,8 +659,8 @@ sub model {
         return $c->model( $c->stash->{current_model} )
           if $c->stash->{current_model};
     }
-    return $c->model( $c->config->{default_model} )
-      if $c->config->{default_model};
+    return $c->model( $appclass->config->{default_model} )
+      if $appclass->config->{default_model};
 
     my( $comp, $rest ) = $c->_comp_search_prefixes( undef, qw/Model M/);
 
@@ -699,6 +700,7 @@ If you want to search for views, pass in a regexp as the argument.
 sub view {
     my ( $c, $name, @args ) = @_;
 
+    my $appclass = ref($c) || $c;
     if( $name ) {
         my @result = $c->_comp_search_prefixes( $name, qw/View V/ );
         return map { $c->_filter_component( $_, @args ) } @result if ref $name;
@@ -711,8 +713,8 @@ sub view {
         return $c->view( $c->stash->{current_view} )
           if $c->stash->{current_view};
     }
-    return $c->view( $c->config->{default_view} )
-      if $c->config->{default_view};
+    return $c->view( $appclass->config->{default_view} )
+      if $appclass->config->{default_view};
 
     my( $comp, $rest ) = $c->_comp_search_prefixes( undef, qw/View V/);
 
@@ -1132,8 +1134,10 @@ EOF
                 . "Class::Accessor(::Fast)?\nPlease pass "
                 . "(replace_constructor => 1)\nwhen making your class immutable.\n";
         }
-        $meta->make_immutable(replace_constructor => 1)
-            unless $meta->is_immutable;
+        $meta->make_immutable(
+            replace_constructor => 1,
+            allow_mutable_ancestors => 1,
+        ) unless $meta->is_immutable;
     };
 
     $class->setup_finalize;
@@ -1174,7 +1178,7 @@ When used as a string, provides a textual URI.
 
 If the first argument is a string, it is taken as a public URI path relative
 to C<< $c->namespace >> (if it doesn't begin with a forward slash) or
-relative to the application root (if it does). It is then merged with 
+relative to the application root (if it does). It is then merged with
 C<< $c->request->base >>; any C<@args> are appended as additional path
 components; and any C<%query_values> are appended as C<?foo=bar> parameters.
 
@@ -1186,13 +1190,13 @@ once the path is resolved, C<uri_for> continues as though a path was
 provided, appending any arguments or parameters and creating an absolute
 URI.
 
-The captures for the current request can be found in 
+The captures for the current request can be found in
 C<< $c->request->captures >>, and actions can be resolved using
 C<< Catalyst::Controller->action_for($name) >>. If you have a private action
 path, use C<< $c->uri_for_action >> instead.
 
   # Equivalent to $c->req->uri
-  $c->uri_for($c->action, $c->req->captures, 
+  $c->uri_for($c->action, $c->req->captures,
       @{ $c->req->args }, $c->req->params);
 
   # For the Foo action in the Bar controller
@@ -1206,6 +1210,12 @@ path, use C<< $c->uri_for_action >> instead.
 sub uri_for {
     my ( $c, $path, @args ) = @_;
 
+    if (blessed($path) && $path->isa('Catalyst::Controller')) {
+        $path = $path->path_prefix;
+        $path =~ s{/+\z}{};
+        $path .= '/';
+    }
+
     if ( blessed($path) ) { # action object
         my $captures = ( scalar @args && ref $args[0] eq 'ARRAY'
                          ? shift(@args)
@@ -1559,9 +1569,9 @@ sub execute {
 
 sub _stats_start_execute {
     my ( $c, $code ) = @_;
-
+    my $appclass = ref($c) || $c;
     return if ( ( $code->name =~ /^_.*/ )
-        && ( !$c->config->{show_internal_actions} ) );
+        && ( !$appclass->config->{show_internal_actions} ) );
 
     my $action_name = $code->reverse();
     $c->counter->{$action_name}++;
@@ -1875,7 +1885,7 @@ sub prepare {
         $c->prepare_read;
 
         # Parse the body unless the user wants it on-demand
-        unless ( $c->config->{parse_on_demand} ) {
+        unless ( ref($c)->config->{parse_on_demand} ) {
             $c->prepare_body;
         }
     }
@@ -2126,40 +2136,32 @@ sub setup_actions { my $c = shift; $c->dispatcher->setup_actions( $c, @_ ) }
 
 =head2 $c->setup_components
 
-Sets up components. Specify a C<setup_components> config option to pass
-additional options directly to L<Module::Pluggable>. To add additional
-search paths, specify a key named C<search_extra> as an array
-reference. Items in the array beginning with C<::> will have the
-application class name prepended to them.
+This method is called internally to set up the application's components.
 
-All components found will also have any
-L<inner packages|Devel::InnerPackage> loaded and set up as components.
-Note, that modules which are B<not> an I<inner package> of the main
-file namespace loaded will not be instantiated as components.
+It finds modules by calling the L<locate_components> method, expands them to
+package names with the L<expand_component_module> method, and then installs
+each component into the application.
+
+The C<setup_components> config option is passed to both of the above methods.
+
+Installation of each component is performed by the L<setup_component> method,
+below.
 
 =cut
 
 sub setup_components {
     my $class = shift;
 
-    my @paths   = qw( ::Controller ::C ::Model ::M ::View ::V );
     my $config  = $class->config->{ setup_components };
-    my $extra   = delete $config->{ search_extra } || [];
 
-    push @paths, @$extra;
-
-    my $locator = Module::Pluggable::Object->new(
-        search_path => [ map { s/^(?=::)/$class/; $_; } @paths ],
-        %$config
-    );
-
-    my @comps = sort { length $a <=> length $b } $locator->plugins;
+    my @comps = sort { length $a <=> length $b }
+                $class->locate_components($config);
     my %comps = map { $_ => 1 } @comps;
 
-    my $deprecated_component_names = grep { /::[CMV]::/ } @comps;
+    my $deprecatedcatalyst_component_names = grep { /::[CMV]::/ } @comps;
     $class->log->warn(qq{Your application is using the deprecated ::[MVC]:: type naming scheme.\n}.
         qq{Please switch your class names to ::Model::, ::View:: and ::Controller: as appropriate.\n}
-    ) if $deprecated_component_names;
+    ) if $deprecatedcatalyst_component_names;
 
     for my $component ( @comps ) {
 
@@ -2168,30 +2170,76 @@ sub setup_components {
         # we know M::P::O found a file on disk so this is safe
 
         Catalyst::Utils::ensure_class_loaded( $component, { ignore_loaded => 1 } );
-        #Class::MOP::load_class($component);
-
-        my $module  = $class->setup_component( $component );
-        my %modules = (
-            $component => $module,
-            map {
-                $_ => $class->setup_component( $_ )
-            } grep {
-              not exists $comps{$_}
-            } Devel::InnerPackage::list_packages( $component )
-        );
 
-        for my $key ( keys %modules ) {
-            $class->components->{ $key } = $modules{ $key };
+        # Needs to be done as soon as the component is loaded, as loading a sub-component
+        # (next time round the loop) can cause us to get the wrong metaclass..
+        $class->_controller_init_base_classes($component);
+    }
+
+    for my $component (@comps) {
+        $class->components->{ $component } = $class->setup_component($component);
+        for my $component ($class->expand_component_module( $component, $config )) {
+            next if $comps{$component};
+            $class->_controller_init_base_classes($component); # Also cover inner packages
+            $class->components->{ $component } = $class->setup_component($component);
         }
     }
 }
 
+=head2 $c->locate_components( $setup_component_config )
+
+This method is meant to provide a list of component modules that should be
+setup for the application.  By default, it will use L<Module::Pluggable>.
+
+Specify a C<setup_components> config option to pass additional options directly
+to L<Module::Pluggable>. To add additional search paths, specify a key named
+C<search_extra> as an array reference. Items in the array beginning with C<::>
+will have the application class name prepended to them.
+
+=cut
+
+sub locate_components {
+    my $class  = shift;
+    my $config = shift;
+
+    my @paths   = qw( ::Controller ::C ::Model ::M ::View ::V );
+    my $extra   = delete $config->{ search_extra } || [];
+
+    push @paths, @$extra;
+
+    my $locator = Module::Pluggable::Object->new(
+        search_path => [ map { s/^(?=::)/$class/; $_; } @paths ],
+        %$config
+    );
+
+    my @comps = $locator->plugins;
+
+    return @comps;
+}
+
+=head2 $c->expand_component_module( $component, $setup_component_config )
+
+Components found by C<locate_components> will be passed to this method, which
+is expected to return a list of component (package) names to be set up.
+
+=cut
+
+sub expand_component_module {
+    my ($class, $module) = @_;
+    return Devel::InnerPackage::list_packages( $module );
+}
+
 =head2 $c->setup_component
 
 =cut
 
+# FIXME - Ugly, ugly hack to ensure the we force initialize non-moose base classes
+#         nearest to Catalyst::Controller first, no matter what order stuff happens
+#         to be loaded. There are TODO tests in Moose for this, see
+#         f2391d17574eff81d911b97be15ea51080500003
 sub _controller_init_base_classes {
     my ($app_class, $component) = @_;
+    return unless $component->isa('Catalyst::Controller');
     foreach my $class ( reverse @{ mro::get_linear_isa($component) } ) {
         Moose::Meta::Class->initialize( $class )
             unless find_meta($class);
@@ -2205,20 +2253,12 @@ sub setup_component {
         return $component;
     }
 
-    # FIXME - Ugly, ugly hack to ensure the we force initialize non-moose base classes
-    #         nearest to Catalyst::Controller first, no matter what order stuff happens
-    #         to be loaded. There are TODO tests in Moose for this, see
-    #         f2391d17574eff81d911b97be15ea51080500003
-    if ($component->isa('Catalyst::Controller')) {
-        $class->_controller_init_base_classes($component);
-    }
-
     my $suffix = Catalyst::Utils::class2classsuffix( $component );
     my $config = $class->config->{ $suffix } || {};
-    # Stash _component_name in the config here, so that custom COMPONENT
+    # Stash catalyst_component_name in the config here, so that custom COMPONENT
     # methods also pass it. local to avoid pointlessly shitting in config
     # for the debug screen, as $component is already the key name.
-    local $config->{_component_name} = $component;
+    local $config->{catalyst_component_name} = $component;
 
     my $instance = eval { $component->COMPONENT( $class, $config ); };
 
@@ -2638,6 +2678,18 @@ changes are made to the request.
     The host value for $c->req->base and $c->req->uri is set to the real
     host, as read from the HTTP X-Forwarded-Host header.
 
+Additionally, you may be running your backend application on an insecure
+connection (port 80) while your frontend proxy is running under SSL.  If there
+is a discrepancy in the ports, use the HTTP header C<X-Forwarded-Port> to
+tell Catalyst what port the frontend listens on.  This will allow all URIs to
+be created properly.
+
+In the case of passing in:
+
+    X-Forwarded-Port: 443
+
+All calls to C<uri_for> will result in an https link, as is expected.
+
 Obviously, your web server must support these headers for this to work.
 
 In a more complex server farm environment where you may have your
@@ -2710,7 +2762,7 @@ acme: Leon Brocard <leon@astray.com>
 
 Andrew Bramble
 
-Andrew Ford
+Andrew Ford E<lt>A.Ford@ford-mason.co.ukE<gt>
 
 Andrew Ruthven
 
@@ -2726,6 +2778,14 @@ chansen: Christian Hansen
 
 chicks: Christopher Hicks
 
+Chisel Wright C<pause@herlpacker.co.uk>
+
+Danijel Milicevic C<me@danijel.de>
+
+David Kamholz E<lt>dkamholz@cpan.orgE<gt>
+
+David Naughton, C<naughton@umn.edu>
+
 David E. Wheeler
 
 dkubb: Dan Kubb <dan.kubb-cpan@onautopilot.com>
@@ -2738,19 +2798,25 @@ esskar: Sascha Kiefer
 
 fireartist: Carl Franks <cfranks@cpan.org>
 
+frew: Arthur Axel "fREW" Schmidt <frioux@gmail.com>
+
 gabb: Danijel Milicevic
 
 Gary Ashton Jones
 
+Gavin Henry C<ghenry@perl.me.uk>
+
 Geoff Richards
 
+groditi: Guillermo Roditi <groditi@gmail.com>
+
 hobbs: Andrew Rodland <andrew@cleverdomain.org>
 
 ilmari: Dagfinn Ilmari MannsÃ¥ker <ilmari@ilmari.org>
 
 jcamacho: Juan Camacho
 
-jester: Jesse Sheidlower
+jester: Jesse Sheidlower C<jester@panix.com>
 
 jhannah: Jay Hannah <jay@jays.net>
 
@@ -2760,6 +2826,10 @@ Johan Lindstrom
 
 jon: Jon Schutz <jjschutz@cpan.org>
 
+Jonathan Rockway C<< <jrockway@cpan.org> >>
+
+Kieren Diment C<kd@totaldatasolution.com>
+
 konobi: Scott McWhirter <konobi@cpan.org>
 
 marcus: Marcus Ramberg <mramberg@cpan.org>
@@ -2790,14 +2860,22 @@ rafl: Florian Ragwitz <rafl@debian.org>
 
 random: Roland Lammel <lammel@cpan.org>
 
+Robert Sedlacek C<< <rs@474.at> >>
+
 sky: Arthur Bergman
 
 t0m: Tomas Doran <bobtfish@bobtfish.net>
 
 Ulf Edvinsson
 
+Viljo Marrandi C<vilts@yahoo.com>
+
+Will Hawes C<info@whawes.co.uk>
+
 willert: Sebastian Willert <willert@cpan.org>
 
+Yuval Kogman, C<nothingmuch@woobling.org>
+
 =head1 LICENSE
 
 This library is free software. You can redistribute it and/or modify it under
index af65452..87b37fd 100644 (file)
@@ -104,7 +104,7 @@ and so on. This determines how the action is dispatched to.
 =head2 class
 
 Returns the name of the component where this action is defined.
-Derived by calling the L<Catalyst::Component/_component_name|_component_name>
+Derived by calling the L<Catalyst::Component/catalyst_component_name|catalyst_component_name>
 method on each component.
 
 =head2 code
index f252f05..9942840 100644 (file)
@@ -6,7 +6,7 @@ use Class::MOP;
 use Moose::Util ();
 
 sub mk_classdata {
-  my ($class, $attribute) = @_;
+  my ($class, $attribute, $warn_on_instance) = @_;
   confess("mk_classdata() is a class method, not an object method")
     if blessed $class;
 
index ee1f99a..fe0ef6f 100644 (file)
@@ -60,13 +60,16 @@ component loader with config() support and a process() method placeholder.
 __PACKAGE__->mk_classdata('_plugins');
 __PACKAGE__->mk_classdata('_config');
 
-has _component_name => ( is => 'ro' ); # Cannot be required => 1 as context
+has catalyst_component_name => ( is => 'ro' ); # Cannot be required => 1 as context
                                        # class @ISA component - HATE
 # Make accessor callable as a class method, as we need to call setup_actions
 # on the application class, which we don't have an instance of, ewwwww
-around _component_name => sub {
+# Also, naughty modules like Catalyst::View::JSON try to write to _everything_,
+# so spit a warning, ignore that (and try to do the right thing anyway) here..
+around catalyst_component_name => sub {
     my ($orig, $self) = (shift, shift);
-    blessed($self) ? $self->$orig(@_) : $self;
+    Carp::cluck("Tried to write to the catalyst_component_name accessor - is your component broken or just mad? (Write ignored - using default value.)") if scalar @_;
+    blessed($self) ? $self->$orig() || blessed($self) : $self;
 };
 
 sub BUILDARGS {
@@ -110,6 +113,8 @@ sub COMPONENT {
 
 sub config {
     my $self = shift;
+    # Uncomment once sane to do so
+    #Carp::cluck("config method called on instance") if ref $self;
     my $config = $self->_config || {};
     if (@_) {
         my $newconfig = { %{@_ > 1 ? {@_} : $_[0]} };
index f23ad4a..6d3c85a 100644 (file)
@@ -2,7 +2,7 @@ package Catalyst::Controller;
 
 use Moose;
 use Moose::Util qw/find_meta/;
-
+use List::MoreUtils qw/uniq/;
 use namespace::clean -except => 'meta';
 
 BEGIN { extends qw/Catalyst::Component MooseX::MethodAttributes::Inheritable/; }
@@ -29,9 +29,9 @@ has action_namespace =>
      predicate => 'has_action_namespace',
     );
 
-has _controller_actions =>
+has actions =>
     (
-     is => 'rw',
+     accessor => '_controller_actions',
      isa => 'HashRef',
      init_arg => undef,
     );
@@ -44,6 +44,8 @@ sub BUILD {
     $self->_controller_actions($attr_value);
 }
 
+
+
 =head1 NAME
 
 Catalyst::Controller - Catalyst Controller base class
@@ -135,28 +137,30 @@ around action_namespace => sub {
     my $orig = shift;
     my ( $self, $c ) = @_;
 
+    my $class = ref($self) || $self;
+    my $appclass = ref($c) || $c;
     if( ref($self) ){
         return $self->$orig if $self->has_action_namespace;
     } else {
-        return $self->config->{namespace} if exists $self->config->{namespace};
+        return $class->config->{namespace} if exists $class->config->{namespace};
     }
 
     my $case_s;
     if( $c ){
-        $case_s = $c->config->{case_sensitive};
+        $case_s = $appclass->config->{case_sensitive};
     } else {
         if ($self->isa('Catalyst')) {
-            $case_s = $self->config->{case_sensitive};
+            $case_s = $class->config->{case_sensitive};
         } else {
             if (ref $self) {
-                $case_s = $self->_application->config->{case_sensitive};
+                $case_s = ref($self->_application)->config->{case_sensitive};
             } else {
                 confess("Can't figure out case_sensitive setting");
             }
         }
     }
 
-    my $namespace = Catalyst::Utils::class2prefix($self->_component_name, $case_s) || '';
+    my $namespace = Catalyst::Utils::class2prefix($self->catalyst_component_name, $case_s) || '';
     $self->$orig($namespace) if ref($self);
     return $namespace;
 };
@@ -177,8 +181,8 @@ around path_prefix => sub {
 
 sub get_action_methods {
     my $self = shift;
-    my $meta = find_meta($self);
-    confess("Metaclass for "
+    my $meta = find_meta($self) || confess("No metaclass setup for $self");
+    confess("Metaclass "
           . ref($meta) . " for "
           . $meta->name
           . " cannot support register_actions." )
@@ -196,7 +200,7 @@ sub get_action_methods {
                   . ( ref $self ) )
           } keys %{ $self->_controller_actions }
     ) if ( ref $self );
-    return @methods;
+    return uniq @methods;
 }
 
 
@@ -207,7 +211,7 @@ sub register_actions {
 
 sub register_action_methods {
     my ( $self, $c, @methods ) = @_;
-    my $class = $self->_component_name;
+    my $class = $self->catalyst_component_name;
     #this is still not correct for some reason.
     my $namespace = $self->action_namespace($c);
 
index 890961d..3654a11 100644 (file)
@@ -80,14 +80,16 @@ sub list {
 
     return unless $self->_endpoints;
 
-    my $column_width = Catalyst::Utils::term_width() - 35 - 9;
+    my $avail_width = Catalyst::Utils::term_width() - 9;
+    my $col1_width = ($avail_width * .50) < 35 ? 35 : int($avail_width * .50);
+    my $col2_width = $avail_width - $col1_width;
     my $paths = Text::SimpleTable->new(
-       [ 35, 'Path Spec' ], [ $column_width, 'Private' ],
+        [ $col1_width, 'Path Spec' ], [ $col2_width, 'Private' ],
     );
 
     my $has_unattached_actions;
     my $unattached_actions = Text::SimpleTable->new(
-        [ 35, 'Private' ], [ $column_width, 'Missing parent' ],
+        [ $col1_width, 'Private' ], [ $col2_width, 'Missing parent' ],
     );
 
     ENDPOINT: foreach my $endpoint (
index 95367ac..545e607 100644 (file)
@@ -47,9 +47,11 @@ Debug output for Path dispatch points
 
 sub list {
     my ( $self, $c ) = @_;
-    my $column_width = Catalyst::Utils::term_width() - 35 - 9;
+    my $avail_width = Catalyst::Utils::term_width() - 9;
+    my $col1_width = ($avail_width * .50) < 35 ? 35 : int($avail_width * .50);
+    my $col2_width = $avail_width - $col1_width;
     my $paths = Text::SimpleTable->new(
-       [ 35, 'Path' ], [ $column_width, 'Private' ]
+       [ $col1_width, 'Path' ], [ $col2_width, 'Private' ]
     );
     foreach my $path ( sort keys %{ $self->_paths } ) {
         my $display_path = $path eq '/' ? $path : "/$path";
index 11a9cbf..0d6da04 100644 (file)
@@ -47,8 +47,12 @@ Output a table of all regex actions, and their private equivalent.
 
 sub list {
     my ( $self, $c ) = @_;
-    my $column_width = Catalyst::Utils::term_width() - 35 - 9;
-    my $re = Text::SimpleTable->new( [ 35, 'Regex' ], [ $column_width, 'Private' ] );
+    my $avail_width = Catalyst::Utils::term_width() - 9;
+    my $col1_width = ($avail_width * .50) < 35 ? 35 : int($avail_width * .50);
+    my $col2_width = $avail_width - $col1_width;
+    my $re = Text::SimpleTable->new(
+        [ $col1_width, 'Regex' ], [ $col2_width, 'Private' ]
+    );
     for my $regex ( @{ $self->_compiled } ) {
         my $action = $regex->{action};
         $re->row( $regex->{path}, "/$action" );
index e90cdc1..3d6573b 100644 (file)
@@ -335,7 +335,7 @@ sub _invoke_as_component {
                 reverse   => "$component_class->$method",
                 class     => $component_class,
                 namespace => Catalyst::Utils::class2prefix(
-                    $component_class, $c->config->{case_sensitive}
+                    $component_class, ref($c)->config->{case_sensitive}
                 ),
             }
         );
@@ -615,9 +615,12 @@ sub setup_actions {
 sub _display_action_tables {
     my ($self, $c) = @_;
 
-    my $column_width = Catalyst::Utils::term_width() - 20 - 36 - 12;
+    my $avail_width = Catalyst::Utils::term_width() - 12;
+    my $col1_width = ($avail_width * .25) < 20 ? 20 : int($avail_width * .25);
+    my $col2_width = ($avail_width * .50) < 36 ? 36 : int($avail_width * .50);
+    my $col3_width =  $avail_width - $col1_width - $col2_width;
     my $privates = Text::SimpleTable->new(
-        [ 20, 'Private' ], [ 36, 'Class' ], [ $column_width, 'Method' ]
+        [ $col1_width, 'Private' ], [ $col2_width, 'Class' ], [ $col3_width, 'Method' ]
     );
 
     my $has_private = 0;
index b9ec98a..443975e 100644 (file)
@@ -48,10 +48,12 @@ sub finalize_body {
     my $body = $c->response->body;
     no warnings 'uninitialized';
     if ( blessed($body) && $body->can('read') or ref($body) eq 'GLOB' ) {
-        while ( !eof $body ) {
-            read $body, my ($buffer), $CHUNKSIZE;
-            last unless $self->write( $c, $buffer );
-        }
+        my $got;
+        do {
+            $got = read $body, my ($buffer), $CHUNKSIZE;
+            $got = 0 unless $self->write( $c, $buffer );
+        } while $got > 0;
+
         close $body;
     }
     else {
@@ -110,7 +112,7 @@ sub finalize_error {
     my ( $self, $c ) = @_;
 
     $c->res->content_type('text/html; charset=utf-8');
-    my $name = $c->config->{name} || join(' ', split('::', ref $c));
+    my $name = ref($c)->config->{name} || join(' ', split('::', ref $c));
 
     my ( $title, $error, $infos );
     if ( $c->debug ) {
@@ -315,13 +317,14 @@ sets up the L<Catalyst::Request> object body using L<HTTP::Body>
 sub prepare_body {
     my ( $self, $c ) = @_;
 
+    my $appclass = ref($c) || $c;
     if ( my $length = $self->read_length ) {
         my $request = $c->request;
         unless ( $request->_body ) {
             my $type = $request->header('Content-Type');
             $request->_body(HTTP::Body->new( $type, $length ));
-            $request->_body->tmpdir( $c->config->{uploadtmp} )
-              if exists $c->config->{uploadtmp};
+            $request->_body->tmpdir( $appclass->config->{uploadtmp} )
+              if exists $appclass->config->{uploadtmp};
         }
 
         while ( my $buffer = $self->read($c) ) {
index 48dc201..8416e09 100644 (file)
@@ -57,9 +57,9 @@ sub prepare_connection {
 
   PROXY_CHECK:
     {
-        unless ( $c->config->{using_frontend_proxy} ) {
+        unless ( ref($c)->config->{using_frontend_proxy} ) {
             last PROXY_CHECK if $ENV{REMOTE_ADDR} ne '127.0.0.1';
-            last PROXY_CHECK if $c->config->{ignore_frontend_proxy};
+            last PROXY_CHECK if ref($c)->config->{ignore_frontend_proxy};
         }
         last PROXY_CHECK unless $ENV{HTTP_X_FORWARDED_FOR};
 
@@ -67,6 +67,9 @@ sub prepare_connection {
         # as 127.0.0.1. Select the most recent upstream IP (last in the list)
         my ($ip) = $ENV{HTTP_X_FORWARDED_FOR} =~ /([^,\s]+)$/;
         $request->address($ip);
+        if ( defined $ENV{HTTP_X_FORWARDED_PORT} ) {
+            $ENV{SERVER_PORT} = $ENV{HTTP_X_FORWARDED_PORT};
+        }
     }
 
     $request->hostname( $ENV{REMOTE_HOST} ) if exists $ENV{REMOTE_HOST};
@@ -123,9 +126,9 @@ sub prepare_path {
     # If we are running as a backend proxy, get the true hostname
   PROXY_CHECK:
     {
-        unless ( $c->config->{using_frontend_proxy} ) {
+        unless ( ref($c)->config->{using_frontend_proxy} ) {
             last PROXY_CHECK if $host !~ /localhost|127.0.0.1/;
-            last PROXY_CHECK if $c->config->{ignore_frontend_proxy};
+            last PROXY_CHECK if ref($c)->config->{ignore_frontend_proxy};
         }
         last PROXY_CHECK unless $ENV{HTTP_X_FORWARDED_HOST};
 
@@ -134,6 +137,9 @@ sub prepare_path {
         # backend could be on any port, so
         # assume frontend is on the default port
         $port = $c->request->secure ? 443 : 80;
+        if ( $ENV{HTTP_X_FORWARDED_PORT} ) {
+            $port = $ENV{HTTP_X_FORWARDED_PORT};
+        }
     }
 
     # set the request URI
index 9626f66..62c5d0b 100644 (file)
@@ -12,10 +12,6 @@ use Socket;
 use IO::Socket::INET ();
 use IO::Select       ();
 
-# For PAR
-require Catalyst::Engine::HTTP::Restarter;
-require Catalyst::Engine::HTTP::Restarter::Watcher;
-
 use constant CHUNKSIZE => 64 * 1024;
 use constant DEBUG     => $ENV{CATALYST_HTTP_DEBUG} || 0;
 
@@ -159,7 +155,7 @@ around write => sub {
     # Prepend the headers if they have not yet been sent
     if ( $self->_has_header_buf ) {
         $self->_warn_on_write_error(
-            $self->$orig($self->_clear_header_buf)
+            $self->$orig($c, $self->_clear_header_buf)
         );
     }
 
@@ -368,6 +364,9 @@ sub _handler {
     while (1) {
         my ( $path, $query_string ) = split /\?/, $uri, 2;
 
+        # URI is not the same as path. Remove scheme, domain name and port from it
+        $path =~ s{^https?://[^/?#]+}{};
+
         # Initialize CGI environment
         local %ENV = (
             PATH_INFO       => $path         || '',
index 4a40516..3383fc6 100644 (file)
@@ -237,8 +237,9 @@ C<http://localhost:3000/some/path> then C<base> is C<http://localhost:3000/>.
 
 =head2 $req->body
 
-Returns the message body of the request, unless Content-Type is
-C<application/x-www-form-urlencoded> or C<multipart/form-data>.
+Returns the message body of the request, as returned by L<HTTP::Body>: a string,
+unless Content-Type is C<application/x-www-form-urlencoded>, C<text/xml>, or
+C<multipart/form-data>, in which case a L<File::Temp> object is returned.
 
 =head2 $req->body_parameters
 
@@ -300,7 +301,7 @@ Returns a reference to a hash containing the cookies.
 
     print $c->request->cookies->{mycookie}->value;
 
-The cookies in the hash are indexed by name, and the values are L<CGI::Cookie>
+The cookies in the hash are indexed by name, and the values are L<CGI::Simple::Cookie>
 objects.
 
 =head2 $req->header
index 595decb..cb73a34 100644 (file)
@@ -102,11 +102,11 @@ it found, while L<Catalyst::View::TT> defaults to C<text/html>.
 
 Returns a reference to a hash containing cookies to be set. The keys of the
 hash are the cookies' names, and their corresponding values are hash
-references used to construct a L<CGI::Cookie> object.
+references used to construct a L<CGI::Simple::Cookie> object.
 
     $c->response->cookies->{foo} = { value => '123' };
 
-The keys of the hash reference on the right correspond to the L<CGI::Cookie>
+The keys of the hash reference on the right correspond to the L<CGI::Simple::Cookie>
 parameters of the same name, except they are used without a leading dash.
 Possible parameters are:
 
index 271d7a5..2cf1bd3 100644 (file)
@@ -3,11 +3,11 @@ package Catalyst::Runtime;
 use strict;
 use warnings;
 
-BEGIN { require 5.008001; }
+BEGIN { require 5.008004; }
 
 # Remember to update this in Catalyst as well!
 
-our $VERSION='5.80007';
+our $VERSION='5.80012';
 
 $VERSION = eval $VERSION;
 
index 46b5ed4..fd6ec8c 100644 (file)
@@ -84,6 +84,10 @@ sub profile {
     return $node->getUID;
 }
 
+sub created {
+    return @{ shift->{tree}->getNodeValue->{t} };
+}
+
 sub elapsed {
     return tv_interval(shift->{tree}->getNodeValue->{t});
 }
@@ -297,6 +301,13 @@ The profiling point will be ignored if the UID has not been previously defined.
 Returns the UID of the current point in the profile tree.  The UID is
 automatically assigned if not explicitly given.
 
+=head2 created
+
+    ($seconds, $microseconds) = $stats->created;
+
+Returns the time the object was created, in C<gettimeofday> format, with
+Unix epoch seconds followed by microseconds.
+
 =head2 elapsed
 
     $elapsed = $stats->elapsed
index e10d6d2..ea5d2c3 100644 (file)
@@ -10,10 +10,13 @@ our $iters;
 
 BEGIN { $iters = $ENV{CAT_BENCH_ITERS} || 1; }
 
-use Test::More tests => 6*$iters;
-
+use Test::More;
 use Catalyst::Test 'TestAppIndexDefault';
 
+plan 'skip_all' if ( $ENV{CATALYST_SERVER} );
+
+plan tests => 6*$iters;
+
 if ( $ENV{CAT_BENCHMARK} ) {
     require Benchmark;
     Benchmark::timethis( $iters, \&run_tests );
index 34ad404..beced91 100644 (file)
@@ -10,9 +10,13 @@ our $iters;
 
 BEGIN { $iters = $ENV{CAT_BENCH_ITERS} || 1; }
 
-use Test::More tests => 3*$iters;
+use Test::More;
 use Catalyst::Test 'TestAppMatchSingleArg';
 
+plan 'skip_all' if ( $ENV{CATALYST_SERVER} );
+
+plan tests => 3*$iters;
+
 if ( $ENV{CAT_BENCHMARK} ) {
     require Benchmark;
     Benchmark::timethis( $iters, \&run_tests );
index 2697940..36a679e 100644 (file)
@@ -131,8 +131,10 @@ sub run_tests {
             'TestApp::Controller::Action::Regexp',
             'Test Class'
         );
+        my $location = $response->header('location');
+        $location =~ s/localhost(:\d+)?/localhost/;
         is(
-            $response->header('location'),
+            $location,
             $url,
             'Redirect URI is the same as the request URI'
         );
index 156956b..4300744 100644 (file)
@@ -10,7 +10,7 @@ our $iters;
 
 BEGIN { $iters = $ENV{CAT_BENCH_ITERS} || 1; }
 
-use Test::More tests => 10*$iters;
+use Test::More tests => 15*$iters;
 use Catalyst::Test 'TestApp';
 
 if ( $ENV{CAT_BENCHMARK} ) {
@@ -69,4 +69,14 @@ EOF
         is( $response->content_length, -s $file, 'Response Content-Length' );
         is( $response->content, $buffer, 'Content is read from filehandle' );
     }
+
+    {
+        my $size = 128 * 1024; # more than one read with the default chunksize
+
+        ok( my $response = request('http://localhost/action/streaming/body_large'), 'Request' );
+        ok( $response->is_success, 'Response Successful 2xx' );
+        is( $response->content_type, 'text/plain', 'Response Content-Type' );
+        is( $response->content_length, $size, 'Response Content-Length' );
+        is( $response->content, "\0" x $size, 'Content is read from filehandle' );
+    }
 }
index 73d3f9c..d7a9a2c 100644 (file)
@@ -11,13 +11,13 @@ use Catalyst::Test 'TestApp';
     my $response = request('http://localhost/anon/test');
     ok($response->is_success);
     is($response->header('X-Component-Name-Action'),
-        'TestApp::Controller::Anon', 'Action can see correct _component_name');
+        'TestApp::Controller::Anon', 'Action can see correct catalyst_component_name');
     isnt($response->header('X-Component-Instance-Name-Action'),
-        'TestApp::Controller::Anon', 'ref($controller) ne _component_name');
+        'TestApp::Controller::Anon', 'ref($controller) ne catalyst_component_name');
     is($response->header('X-Component-Name-Controller'),
-        'TestApp::Controller::Anon', 'Controller can see correct _component_name');
+        'TestApp::Controller::Anon', 'Controller can see correct catalyst_component_name');
     is($response->header('X-Class-In-Action'),
-        'TestApp::Controller::Anon', '$action->class is _component_name');
+        'TestApp::Controller::Anon', '$action->class is catalyst_component_name');
     is($response->header('X-Anon-Trait-Applied'),
         '1', 'Anon controller class has trait applied correctly');
 }
index 9396ffb..15924cd 100644 (file)
@@ -10,9 +10,13 @@ our $iters;
 
 BEGIN { $iters = $ENV{CAT_BENCH_ITERS} || 1; }
 
-use Test::More tests => 3*$iters;
+use Test::More;
 use Catalyst::Test 'TestAppOneView';
 
+plan 'skip_all' if ( $ENV{CATALYST_SERVER} );
+
+plan tests => 3*$iters;
+
 if ( $ENV{CAT_BENCHMARK} ) {
     require Benchmark;
     Benchmark::timethis( $iters, \&run_tests );
index fbc12ba..0512e6a 100644 (file)
@@ -54,8 +54,6 @@ Index: lib/Catalyst/Engine/CGI.pm
 }
 
 # test that request with URL-escaped code works.
-TODO: {
-    local $TODO = 'Actions should match when path parts are url encoded';
     my $request = Catalyst::Utils::request( 'http://localhost/args/param%73/one/two' );
     my $cgi     = HTTP::Request::AsCGI->new( $request, %ENV )->setup;
 
@@ -67,6 +65,8 @@ TODO: {
     TestApp->handle_request( env => \%ENV );
 
     ok( my $response = $cgi->restore->response );
+TODO: {
+    local $TODO = 'Actions should match when path parts are url encoded';
     ok( $response->is_success, 'Response Successful 2xx' );
     is( $response->content, 'onetwo' );
 }
index 551561e..d0ef1f0 100644 (file)
@@ -6,7 +6,7 @@ use warnings;
 use FindBin;
 use lib "$FindBin::Bin/../lib";
 
-use Test::More tests => 17;
+use Test::More tests => 18;
 use Catalyst::Test 'TestApp';
 
 use Catalyst::Request;
@@ -22,6 +22,7 @@ use HTTP::Request::Common;
         'X-Multiple'       => [ 1 .. 5 ],
         'X-Forwarded-Host' => 'frontend.server.com',
         'X-Forwarded-For'  => '192.168.1.1, 1.2.3.4',
+        'X-Forwarded-Port' => 443
     );
  
     ok( my $response = request($request), 'Request' );
@@ -30,6 +31,7 @@ use HTTP::Request::Common;
     like( $response->content, qr/^bless\( .* 'Catalyst::Request' \)$/s, 'Content is a serialized Catalyst::Request' );
     ok( eval '$creq = ' . $response->content, 'Unserialize Catalyst::Request' );
     isa_ok( $creq, 'Catalyst::Request' );
+    ok( $creq->secure, 'Forwarded port sets securet' );
     isa_ok( $creq->headers, 'HTTP::Headers', 'Catalyst::Request->headers' );
     is( $creq->header('X-Whats-Cool'), $request->header('X-Whats-Cool'), 'Catalyst::Request->header X-Whats-Cool' );
     
index 10b071b..7e5cba2 100644 (file)
@@ -37,6 +37,11 @@ use HTTP::Request::Common;
     }
 
     isa_ok( $creq, 'Catalyst::Request' );
-    
-    is( $creq->remote_user, 'dwc', '$c->req->remote_user ok' );
+    SKIP:
+    {
+        if ( $ENV{CATALYST_SERVER} ) {
+            skip 'Using remote server', 1;
+        }
+        is( $creq->remote_user, 'dwc', '$c->req->remote_user ok' );
+    }
 }
index b8f3944..4431f5a 100644 (file)
@@ -8,7 +8,7 @@ use lib "$FindBin::Bin/../lib";
 
 use Test::More;
 
-plan tests => 29;
+plan tests => 30;
 
 use_ok('TestApp');
 
@@ -97,6 +97,10 @@ my $context = TestApp->new( {
                 namespace => 'yada',
               } );
 
+is($context->uri_for($context->controller('Action')),
+   "http://127.0.0.1/foo/yada/action/",
+   "uri_for a controller");
+
 is($context->uri_for($path_action),
    "http://127.0.0.1/foo/action/relative/relative",
    "uri_for correct for path action");
similarity index 61%
rename from t/optional_http-server.t
rename to t/author/optional_http-server.t
index 60f9259..d4a2183 100644 (file)
@@ -1,26 +1,20 @@
 use strict;
 use warnings;
 
-use Test::More;
-BEGIN {
-    plan skip_all => 'set TEST_HTTP to enable this test' unless $ENV{TEST_HTTP};
-}
+use Test::More tests => 1;
 
 use File::Path;
 use FindBin;
 use IPC::Open3;
 use IO::Socket;
 
-eval "use Catalyst::Devel 1.0";
-plan skip_all => 'Catalyst::Devel required' if $@;
-eval "use File::Copy::Recursive";
-plan skip_all => 'File::Copy::Recursive required' if $@;
-plan tests => 1;
+use Catalyst::Devel 1.0;
+use File::Copy::Recursive;
 
 # Run a single test by providing it as the first arg
 my $single_test = shift;
 
-my $tmpdir = "$FindBin::Bin/../t/tmp";
+my $tmpdir = "$FindBin::Bin/../../t/tmp";
 
 # clean up
 rmtree $tmpdir if -d $tmpdir;
@@ -28,24 +22,28 @@ rmtree $tmpdir if -d $tmpdir;
 # create a TestApp and copy the test libs into it
 mkdir $tmpdir;
 chdir $tmpdir;
-system( $^X, "-I$FindBin::Bin/../lib", "$FindBin::Bin/../script/catalyst.pl", 'TestApp' );
+system( $^X, "-I$FindBin::Bin/../../lib", "$FindBin::Bin/../../script/catalyst.pl", 'TestApp' );
 chdir "$FindBin::Bin/..";
-File::Copy::Recursive::dircopy( 't/lib', 't/tmp/TestApp/lib' );
+File::Copy::Recursive::dircopy( '../t/lib', '../t/tmp/TestApp/lib' ) or die;
 
 # remove TestApp's tests
-rmtree 't/tmp/TestApp/t';
+rmtree '../t/tmp/TestApp/t' or die;
 
 # spawn the standalone HTTP server
 my $port = 30000 + int rand(1 + 10000);
-my $pid = open3( undef, my $server, undef,
-  $^X, "-I$FindBin::Bin/../lib",
-  "$FindBin::Bin/../t/tmp/TestApp/script/testapp_server.pl", '-port', $port )
+my @cmd = ($^X, "-I$FindBin::Bin/../../lib",
+  "$FindBin::Bin/../../t/tmp/TestApp/script/testapp_server.pl", '-port', $port );
+my $pid = open3( undef, my $server, undef, @cmd)
     or die "Unable to spawn standalone HTTP server: $!";
 
 # wait for it to start
 print "Waiting for server to start...\n";
+my $timeout = 30;
+my $count = 0;
 while ( check_port( 'localhost', $port ) != 1 ) {
     sleep 1;
+    die("Server did not start within $timeout seconds: " . join(' ', @cmd))
+        if $count++ > $timeout;
 }
 
 # run the testsuite against the HTTP server
@@ -53,10 +51,10 @@ $ENV{CATALYST_SERVER} = "http://localhost:$port";
 
 my $return;
 if ( $single_test ) {
-    $return = system( "$^X -Ilib/ $single_test" );
+    $return = system( "$^X -I../lib/ $single_test" );
 }
 else {
-    $return = prove( '-r', '-Ilib/', glob('t/aggregate/live_*.t') );
+    $return = prove( '-r', '-I../lib/', glob('../t/aggregate/live_*.t') );
 }
 
 # shut it down
@@ -64,7 +62,7 @@ kill 'INT', $pid;
 close $server;
 
 # clean up
-rmtree "$FindBin::Bin/../t/tmp" if -d "$FindBin::Bin/../t/tmp";
+rmtree "$FindBin::Bin/../../t/tmp" if -d "$FindBin::Bin/../../t/tmp";
 
 is( $return, 0, 'live tests' );
 
index d8c67c2..27d8fa9 100644 (file)
@@ -12,7 +12,6 @@ my @modules = qw/
     Catalyst::Component
     Catalyst::Dispatcher
     Catalyst::DispatchType
-    Catalyst::Engine::HTTP::Restarter::Watcher
     Catalyst::Engine
     Catalyst::Log
     Catalyst::Request::Upload
diff --git a/t/cdi_backcompat_plugin_accessor_override.t b/t/cdi_backcompat_plugin_accessor_override.t
deleted file mode 100644 (file)
index d3efa18..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-use strict;
-use warnings;
-use lib 't/lib';
-
-use Test::More tests => 2;
-use Test::Exception;
-
-# Force a stack trace.
-use Carp;
-$SIG{__DIE__} = \&Carp::confess;
-
-{
-    package CDICompatTestApp;
-    use Catalyst qw/
-           +CDICompatTestPlugin
-    /;
-    # Calling ->config here (before we call setup). With CDI/Cat 5.70 this
-    # causes *CDICompatTestApp::_config to have a class data accessor created.
-    
-    # If this doesn't happen, then later when we've added CDICompatTestPlugin
-    # to @ISA, we fail in the overridden ->setup method when we call ->config
-    # again, as we get the CAF accessor from CDICompatTestPlugin, not the one
-    # created in this package as a side-effect of this call. :-(
-    __PACKAGE__->config;
-}
-
-SKIP: {
-  skip 'Not trying to replicate the nasty CDI hackness', 2;
-  lives_ok {
-      CDICompatTestApp->setup;
-  } 'Setup app with plugins which says use base qw/Class::Accessor::Fast/';
-
-  # And the plugin's setup_finished method should have been run, as accessors
-  # are not created in MyApp until the data is written to.
-  {
-      no warnings 'once';
-      is $CDICompatTestPlugin::Data::HAS_RUN_SETUP_FINISHED, 1, 'Plugin setup_finish run';
-  }
-}
\ No newline at end of file
diff --git a/t/custom_exception_class_simple.t b/t/custom_exception_class_simple.t
new file mode 100644 (file)
index 0000000..e87ed80
--- /dev/null
@@ -0,0 +1,18 @@
+#!/usr/bin/env perl
+
+use strict;
+use warnings;
+use FindBin qw/$Bin/;
+use lib "$Bin/lib";
+use Test::More tests => 1;
+use Test::Exception;
+
+TODO: {
+    local $TODO = 'Does not work yet';
+
+lives_ok {
+    require TestAppClassExceptionSimpleTest;
+} 'Can load application';
+
+}
+
index cfb5adf..b30df89 100644 (file)
@@ -16,6 +16,8 @@ my $mvc_warnings;
 BEGIN {
     my $logger = Class::MOP::Class->create_anon_class(
     methods => {
+        debug => sub {0},
+        info  => sub {0},
         warn => sub {
             if ($_[1] =~ /switch your class names/) {
                $mvc_warnings++;
index b6d9374..a2fc0b2 100644 (file)
@@ -67,7 +67,7 @@ sub execute {
             @executed
         );
     }
-
+    no warnings 'recursion';
     return $c->SUPER::execute(@_);
 }
 
index 77e2caa..1240b0e 100644 (file)
@@ -9,7 +9,7 @@ sub execute {
     my $self = shift;
     my ( $controller, $c, $test ) = @_;
     $c->res->header( 'X-TestAppActionTestMyAction', 'MyAction works' );
-    $c->res->header( 'X-Component-Name-Action', $controller->_component_name);
+    $c->res->header( 'X-Component-Name-Action', $controller->catalyst_component_name);
     $c->res->header( 'X-Component-Instance-Name-Action', ref($controller));
     $c->res->header( 'X-Class-In-Action', $self->class);
     $self->next::method(@_);
index 5a757b0..08c7c65 100644 (file)
@@ -16,7 +16,7 @@ EOF
 
 sub body : Local {
     my ( $self, $c ) = @_;
-    
+
     my $file = "$FindBin::Bin/../lib/TestApp/Controller/Action/Streaming.pm";
     my $fh = IO::File->new( $file, 'r' );
     if ( defined $fh ) {
@@ -27,4 +27,16 @@ sub body : Local {
     }
 }
 
+sub body_large : Local {
+    my ($self, $c) = @_;
+
+    # more than one write with the default chunksize
+    my $size = 128 * 1024;
+
+    my $data = "\0" x $size;
+    open my $fh, '<', \$data;
+    $c->res->content_length($size);
+    $c->res->body($fh);
+}
+
 1;
index 9832715..68b4fd6 100644 (file)
@@ -32,7 +32,7 @@ sub COMPONENT { # Don't do this yourself, use CatalystX::Component::Traits!
 
 sub test : Local ActionClass('+TestApp::Action::TestMyAction') {
     my ($self, $c) = @_;
-    $c->res->header('X-Component-Name-Controller', $self->_component_name);
+    $c->res->header('X-Component-Name-Controller', $self->catalyst_component_name);
     $c->res->body('It works');
 }
 
diff --git a/t/lib/TestAppClassExceptionSimpleTest.pm b/t/lib/TestAppClassExceptionSimpleTest.pm
new file mode 100644 (file)
index 0000000..aef61be
--- /dev/null
@@ -0,0 +1,19 @@
+package TestAppClassExceptionSimpleTest::Exception;
+use strict;
+use warnings;
+
+sub throw {}
+
+#########
+
+package TestAppClassExceptionSimpleTest;
+use strict;
+use warnings;
+
+BEGIN { $Catalyst::Exception::CATALYST_EXCEPTION_CLASS = 'TestAppClassExceptionSimpleTest::Exception'; }
+
+use Catalyst;
+
+__PACKAGE__->setup;
+
+1;
diff --git a/t/lib/TestAppNonMooseController.pm b/t/lib/TestAppNonMooseController.pm
new file mode 100644 (file)
index 0000000..8507aba
--- /dev/null
@@ -0,0 +1,8 @@
+package TestAppNonMooseController;
+use base qw/Catalyst/;
+use Catalyst;
+
+__PACKAGE__->setup;
+
+1;
+
diff --git a/t/lib/TestAppNonMooseController/Controller/Foo.pm b/t/lib/TestAppNonMooseController/Controller/Foo.pm
new file mode 100644 (file)
index 0000000..36b036c
--- /dev/null
@@ -0,0 +1,5 @@
+package TestAppNonMooseController::Controller::Foo;
+use base qw/TestAppNonMooseController::ControllerBase/;
+
+1;
+
diff --git a/t/lib/TestAppNonMooseController/ControllerBase.pm b/t/lib/TestAppNonMooseController/ControllerBase.pm
new file mode 100644 (file)
index 0000000..406df4b
--- /dev/null
@@ -0,0 +1,5 @@
+package TestAppNonMooseController::ControllerBase;
+use base qw/Catalyst::Controller/;
+
+1;
+
index 39f475a..3d3cb3f 100644 (file)
@@ -45,10 +45,11 @@ rmtree 't/tmp/TestApp/t';
 my $port = 30000 + int rand( 1 + 10000 );
 
 my( $server, $pid );
-$pid = open3( undef, $server, undef,
-  $^X, "-I$FindBin::Bin/../lib",
+my @cmd = ($^X, "-I$FindBin::Bin/../lib", "-I$FindBin::Bin/lib",
   "$FindBin::Bin/../t/tmp/TestApp/script/testapp_server.pl", '-port',
-  $port, '-restart' )
+  $port, '-restart');
+
+$pid = open3( undef, $server, undef, @cmd )
     or die "Unable to spawn standalone HTTP server: $!";
 
 # switch to non-blocking reads so we can fail
@@ -67,11 +68,9 @@ my @files = (
     "$FindBin::Bin/../t/tmp/TestApp/lib/TestApp.pm",
     "$FindBin::Bin/../t/tmp/TestApp/lib/TestApp/Controller/Action/Begin.pm",
     "$FindBin::Bin/../t/tmp/TestApp/lib/TestApp/Controller/Immutable.pm",
+    "$FindBin::Bin/../t/tmp/TestApp/lib/TestApp/Controller/Immutable/HardToReload.pm",
 );
 
-push(@files, "$FindBin::Bin/../t/tmp/TestApp/lib/TestApp/Controller/Immutable/HardToReload.pm")
-    if Catalyst::Engine::HTTP::Restarter::Watcher::DETECT_PACKAGE_COMPILATION();
-
 # change some files and make sure the server restarts itself
 NON_ERROR_RESTART:
 for ( 1 .. 20 ) {
@@ -84,7 +83,6 @@ for ( 1 .. 20 ) {
     # give the server time to notice the change and restart
     my $count = 0;
     my $line;
-
     while ( ( $line || '' ) !~ /can connect/ ) {
         # wait for restart message
         $line = $server->getline;
diff --git a/t/unit_controller_actions.t b/t/unit_controller_actions.t
new file mode 100644 (file)
index 0000000..26e603d
--- /dev/null
@@ -0,0 +1,26 @@
+use strict;
+use warnings;
+use Test::More tests => 4;
+
+use Catalyst ();
+{
+    package TestController;
+    use Moose;
+    BEGIN { extends 'Catalyst::Controller' }
+
+    sub action : Local {}
+
+    sub foo : Path {}
+
+    no Moose;
+}
+
+my $mock_app = Class::MOP::Class->create_anon_class( superclasses => ['Catalyst'] );
+my $app = $mock_app->name->new;
+my $controller = TestController->new($app, {actions => { foo => { Path => '/some/path' }}});
+
+ok $controller->can('_controller_actions');
+is_deeply $controller->_controller_actions => { foo => { Path => '/some/path' }};
+is_deeply $controller->{actions} => { foo => { Path => '/some/path' }}; # Back compat.
+is_deeply [ sort grep { ! /^_/ } map { $_->name } $controller->get_action_methods ], [sort qw/action foo/];
+
index 6d60a96..d054dc6 100644 (file)
@@ -100,3 +100,7 @@ is(refaddr(ClassDataTest->_hashref), refaddr($hashref3));
 is(refaddr(ClassDataTest->_scalarref), refaddr($scalarref3));
 is(refaddr(ClassDataTest->_coderef), refaddr($coderef3));
 is(ClassDataTest->_scalar, $scalar3);
+
+my $i = bless {}, 'ClassDataTest';
+$i->_scalar('foo');
+
index 42f1eac..1944ab6 100644 (file)
@@ -2,7 +2,7 @@
 # (do not forget to update the number of components in test 3 as well)
 # 5 extra tests for the loading options
 # One test for components in inner packages
-use Test::More tests => 2 + 6 * 24 + 5 + 1;
+use Test::More tests => 2 + 6 * 24 + 8 + 1;
 
 use strict;
 use warnings;
@@ -175,6 +175,9 @@ sub COMPONENT {
     my \$self = shift->next::method(\@_);
     no strict 'refs';
     *{\__PACKAGE__ . "::whoami"} = sub { return \__PACKAGE__; };
+    *${appclass}::Model::TopLevel::GENERATED::ACCEPT_CONTEXT = sub {
+        return bless {}, 'FooBarBazQuux';
+    };
     \$self;
 }
 
@@ -190,8 +193,10 @@ write_component_file([$libdir, $appclass, 'Model', 'TopLevel'], 'Nested', <<EOF)
 package ${appclass}::Model::TopLevel::Nested;
 use base 'Catalyst::Model';
 
+my \$called=0;
 no warnings 'redefine';
-sub COMPONENT { return shift->next::method(\@_); }
+sub COMPONENT { \$called++;return shift->next::method(\@_); }
+sub called { return \$called };
 1;
 
 EOF
@@ -199,6 +204,11 @@ EOF
 eval "package $appclass; use Catalyst; __PACKAGE__->setup";
 
 is($@, '', "Didn't load component twice");
+is($appclass->model('TopLevel::Nested')->called,1, 'COMPONENT called once');
+
+ok($appclass->model('TopLevel::Generated'), 'Have generated model');
+is(ref($appclass->model('TopLevel::Generated')), 'FooBarBazQuux',
+    'ACCEPT_CONTEXT in generated inner package fired as expected');
 
 $appclass = "InnerComponent";
 
index 93d08d8..03d16f6 100644 (file)
@@ -21,6 +21,9 @@ my $warnings = 0;
 use PluginTestApp;
 my $logger = Class::MOP::Class->create_anon_class(
     methods => {
+        error => sub {0},
+        debug => sub {0},
+        info => sub {0},
         warn => sub {
             if ($_[1] =~ /plugin method is deprecated/) {
                $warnings++;
@@ -40,6 +43,8 @@ is( $warnings, 0, 'no warnings' );
 #         for Catalyst 5.9
 ok( get("/run_time_plugins"),     "get ok" );
 
+local $ENV{CATALYST_DEBUG} = 0;
+
 is( $warnings, 1, '1 warning' );
 
 use_ok 'TestApp';
@@ -56,3 +61,4 @@ my @expected = qw(
 # Faux::Plugin is no longer reported
 is_deeply [ TestApp->registered_plugins ], \@expected,
   'registered_plugins() should only report the plugins for the current class';
+
index 00ee842..cbc5aac 100644 (file)
@@ -26,12 +26,17 @@ sub build_test_app_with_setup {
     return $name;
 }
 
-local %ENV; # Don't allow env variables to mess us up.
+local %ENV = %ENV;
+
+# Remove all relevant env variables to avoid accidental fail
+foreach my $name (grep { /^(CATALYST|TESTAPP)/ } keys %ENV) {
+    delete $ENV{$name};
+}
 
 {
-    my $app = build_test_app_with_setup('MyTestDebug', '-Debug');
+    my $app = build_test_app_with_setup('TestAppMyTestDebug', '-Debug');
 
-    ok my $c = MyTestDebug->new, 'Get debug app object';
+    ok my $c = $app->new, 'Get debug app object';
     ok my $log = $c->log, 'Get log object';
     isa_ok $log, 'Catalyst::Log', 'It should be a Catalyst::Log object';
     ok $log->is_warn, 'Warnings should be enabled';
@@ -43,7 +48,7 @@ local %ENV; # Don't allow env variables to mess us up.
 }
 
 {
-    my $app = build_test_app_with_setup('MyTestLogParam', '-Log=warn,error,fatal');
+    my $app = build_test_app_with_setup('TestAppMyTestLogParam', '-Log=warn,error,fatal');
 
     ok my $c = $app->new, 'Get log app object';
     ok my $log = $c->log, 'Get log object';
@@ -56,7 +61,7 @@ local %ENV; # Don't allow env variables to mess us up.
     ok !$c->debug, 'Catalyst debugging is off';
 }
 {
-    my $app = build_test_app_with_setup('MyTestNoParams');
+    my $app = build_test_app_with_setup('TestAppMyTestNoParams');
 
     ok my $c = $app->new, 'Get log app object';
     ok my $log = $c->log, 'Get log object';
@@ -72,12 +77,12 @@ my $log_meta = Class::MOP::Class->create_anon_class(
     methods => { map { $_ => sub { 0 } } qw/debug error fatal info warn/ },
 );
 {
-    package MyTestAppWithOwnLogger;
+    package TestAppWithOwnLogger;
     use base qw/Catalyst/;
     __PACKAGE__->log($log_meta->new_object);
     __PACKAGE__->setup('-Debug');
 }
 
-ok my $c = MyTestAppWithOwnLogger->new, 'Get with own logger app object';
+ok my $c = TestAppWithOwnLogger->new, 'Get with own logger app object';
 ok $c->debug, '$c->debug is true';
 
index 401ea99..1406944 100644 (file)
@@ -27,10 +27,15 @@ sub test_log_object {
     }
 }
 
-local %ENV; # Ensure blank or someone, somewhere will fail..
+local %ENV = %ENV;
+
+# Remove all relevant env variables to avoid accidental fail
+foreach my $name (grep { /^(CATALYST|TESTAPP)/ } keys %ENV) {
+    delete $ENV{$name};
+}
 
 {
-    my $app = mock_app('TestLogAppParseLevels');
+    my $app = mock_app('TestAppParseLogLevels');
     $app->setup_log('error,warn');
     ok !$app->debug, 'Not in debug mode';
     test_log_object($app->log,
@@ -42,8 +47,9 @@ local %ENV; # Ensure blank or someone, somewhere will fail..
     );
 }
 {
-    local %ENV = ( CATALYST_DEBUG => 1 );
-    my $app = mock_app('TestLogAppDebugEnvSet');
+    local %ENV = %ENV;
+    $ENV{CATALYST_DEBUG} = 1;
+    my $app = mock_app('TestAppLogDebugEnvSet');
     $app->setup_log('');
     ok $app->debug, 'In debug mode';
     test_log_object($app->log,
@@ -55,8 +61,9 @@ local %ENV; # Ensure blank or someone, somewhere will fail..
     );
 }
 {
-    local %ENV = ( CATALYST_DEBUG => 0 );
-    my $app = mock_app('TestLogAppDebugEnvUnset');
+    local %ENV = %ENV;
+    $ENV{CATALYST_DEBUG} = 0;
+    my $app = mock_app('TestAppLogDebugEnvUnset');
     $app->setup_log('warn');
     ok !$app->debug, 'Not In debug mode';
     test_log_object($app->log,
@@ -68,7 +75,7 @@ local %ENV; # Ensure blank or someone, somewhere will fail..
     );
 }
 {
-    my $app = mock_app('TestLogAppEmptyString');
+    my $app = mock_app('TestAppLogEmptyString');
     $app->setup_log('');
     ok !$app->debug, 'Not In debug mode';
     # Note that by default, you get _all_ the log levels turned on
@@ -81,7 +88,7 @@ local %ENV; # Ensure blank or someone, somewhere will fail..
     );
 }
 {
-    my $app = mock_app('TestLogAppDebugOnly');
+    my $app = mock_app('TestAppLogDebugOnly');
     $app->setup_log('debug');
     ok $app->debug, 'In debug mode';
     test_log_object($app->log,
index 8cc979f..11ef840 100644 (file)
@@ -22,40 +22,46 @@ my $mock_log = Class::MOP::Class->create_anon_class(
 sub mock_app {
     my $name = shift;
     %log_messages = (); # Flatten log messages.
-    print "Setting up mock application: $name\n";
     my $meta = Moose->init_meta( for_class => $name );
     $meta->superclasses('Catalyst');
     $meta->add_method('log', sub { $mock_log }); 
     return $meta->name;
 }
 
-local %ENV; # Ensure blank or someone, somewhere will fail..
+local %ENV = %ENV;
+
+# Remove all relevant env variables to avoid accidental fail
+foreach my $name (grep { /^(CATALYST|TESTAPP)/ } keys %ENV) {
+    delete $ENV{$name};
+}
 
 {
-    my $app = mock_app('TestNoStats');
+    my $app = mock_app('TestAppNoStats');
     $app->setup_stats();
     ok !$app->use_stats, 'stats off by default';
 }
 {
-    my $app = mock_app('TestStats');
+    my $app = mock_app('TestAppStats');
     $app->setup_stats(1);
     ok $app->use_stats, 'stats on if you say >setup_stats(1)';
 }
 {
-    my $app = mock_app('TestStatsDebugTurnsStatsOn');
+    my $app = mock_app('TestAppStatsDebugTurnsStatsOn');
     $app->meta->add_method('debug' => sub { 1 });
     $app->setup_stats();
     ok $app->use_stats, 'debug on turns stats on';
 }
 {
-    local %ENV = ( CATALYST_STATS => 1 );
-    my $app = mock_app('TestStatsAppStatsEnvSet');
+    local %ENV = %ENV;
+    $ENV{CATALYST_STATS} = 1;
+    my $app = mock_app('TestAppStatsEnvSet');
     $app->setup_stats();
     ok $app->use_stats, 'ENV turns stats on';
 }
 {
-    local %ENV = ( CATALYST_STATS => 0 );
-    my $app = mock_app('TestStatsAppStatsEnvUnset');
+    local %ENV = %ENV;
+    $ENV{CATALYST_STATS} = 0;
+    my $app = mock_app('TestAppStatsEnvUnset');
     $app->meta->add_method('debug' => sub { 1 });
     $app->setup_stats(1);
     ok !$app->use_stats, 'ENV turns stats off, even when debug on and ->setup_stats(1)';
index cb3c1e2..3b91ef2 100644 (file)
@@ -1,23 +1,12 @@
-use Catalyst ();
+use strict;
+use warnings;
 
-{
-    package TestApp;
-    use base qw/Catalyst/;
-}
-{
-    package TestApp::Controller::Base;
-    use base qw/Catalyst::Controller/;
-}
-{
-    package TestApp::Controller::Other;
-    use base qw/TestApp::Controller::Base/;
-}
-
-TestApp->setup_component('TestApp::Controller::Other');
-TestApp->setup_component('TestApp::Controller::Base');
+use FindBin;
+use lib "$FindBin::Bin/lib";
 
 use Test::More tests => 1;
 use Test::Exception;
+use TestAppNonMooseController;
 
 # Metaclass init order causes fail.
 # There are TODO tests in Moose for this, see
@@ -25,6 +14,6 @@ use Test::Exception;
 # after which the evil kludge in core can die in a fire.
 
 lives_ok {
-    TestApp::Controller::Base->get_action_methods
+    TestAppNonMooseController::ControllerBase->get_action_methods
 } 'Base class->get_action_methods ok when sub class initialized first';
 
index 928b48e..676f354 100644 (file)
@@ -3,7 +3,7 @@
 use strict;
 use warnings;
 
-use Test::More tests => 12;
+use Test::More tests => 13;
 use Time::HiRes qw/gettimeofday/;
 use Tree::Simple;
 
@@ -19,6 +19,8 @@ BEGIN { use_ok("Catalyst::Stats") };
     my $stats = Catalyst::Stats->new;
     is (ref($stats), "Catalyst::Stats", "new");
 
+    is_deeply([ $stats->created ], [0, 0], "created time");
+
     my @expected; # level, string, time
 
     $fudge_t[0] = 1;