Script 'mail_helper' called by obssrc
Hello community,
here is the log from the commit of package perl-Mojolicious for
openSUSE:Factory checked in at 2021-04-14 10:11:19
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/perl-Mojolicious (Old)
and /work/SRC/openSUSE:Factory/.perl-Mojolicious.new.2401 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "perl-Mojolicious"
Wed Apr 14 10:11:19 2021 rev:157 rq:885053 version:9.16
Changes:
--------
--- /work/SRC/openSUSE:Factory/perl-Mojolicious/perl-Mojolicious.changes
2021-04-12 17:10:28.830572683 +0200
+++
/work/SRC/openSUSE:Factory/.perl-Mojolicious.new.2401/perl-Mojolicious.changes
2021-04-14 10:11:50.429580961 +0200
@@ -1,0 +2,13 @@
+Sat Apr 10 03:07:42 UTC 2021 - Tina M??ller <[email protected]>
+
+- updated to 9.16
+ see /usr/share/doc/packages/perl-Mojolicious/Changes
+
+ 9.16 2021-04-08
+ - Added support for format inheritance.
+ - Improved Mojo::Server::CGI with support for before_server_start hook.
+
+ 9.15 2021-03-30
+ - Improved form generator in Mojo::UserAgent::Transactor to allow custom
Content-Disposition headers.
+
+-------------------------------------------------------------------
Old:
----
Mojolicious-9.14.tar.gz
New:
----
Mojolicious-9.16.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ perl-Mojolicious.spec ++++++
--- /var/tmp/diff_new_pack.bzAuC8/_old 2021-04-14 10:11:50.813581609 +0200
+++ /var/tmp/diff_new_pack.bzAuC8/_new 2021-04-14 10:11:50.813581609 +0200
@@ -18,7 +18,7 @@
%define cpan_name Mojolicious
Name: perl-Mojolicious
-Version: 9.14
+Version: 9.16
Release: 0
Summary: Real-time web framework
License: Artistic-2.0
++++++ Mojolicious-9.14.tar.gz -> Mojolicious-9.16.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/Mojolicious-9.14/Changes new/Mojolicious-9.16/Changes
--- old/Mojolicious-9.14/Changes 2021-03-22 23:36:17.000000000 +0100
+++ new/Mojolicious-9.16/Changes 2021-04-08 22:25:13.000000000 +0200
@@ -1,4 +1,11 @@
+9.16 2021-04-08
+ - Added support for format inheritance.
+ - Improved Mojo::Server::CGI with support for before_server_start hook.
+
+9.15 2021-03-30
+ - Improved form generator in Mojo::UserAgent::Transactor to allow custom
Content-Disposition headers.
+
9.14 2021-03-23
- Added EXPERIMENTAL support for :text pseudo-class to Mojo::DOM::CSS.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/Mojolicious-9.14/META.json
new/Mojolicious-9.16/META.json
--- old/Mojolicious-9.14/META.json 2021-03-23 23:53:35.000000000 +0100
+++ new/Mojolicious-9.16/META.json 2021-04-09 13:29:58.000000000 +0200
@@ -63,6 +63,6 @@
"web" : "https://webchat.freenode.net/#mojo"
}
},
- "version" : "9.14",
+ "version" : "9.16",
"x_serialization_backend" : "JSON::PP version 4.06"
}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/Mojolicious-9.14/META.yml
new/Mojolicious-9.16/META.yml
--- old/Mojolicious-9.14/META.yml 2021-03-23 23:53:35.000000000 +0100
+++ new/Mojolicious-9.16/META.yml 2021-04-09 13:29:58.000000000 +0200
@@ -34,5 +34,5 @@
homepage: https://mojolicious.org
license: http://www.opensource.org/licenses/artistic-license-2.0
repository: https://github.com/mojolicious/mojo.git
-version: '9.14'
+version: '9.16'
x_serialization_backend: 'CPAN::Meta::YAML version 0.018'
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/Mojolicious-9.14/lib/Mojo/Server/CGI.pm
new/Mojolicious-9.16/lib/Mojo/Server/CGI.pm
--- old/Mojolicious-9.14/lib/Mojo/Server/CGI.pm 2021-01-29 18:08:08.000000000
+0100
+++ new/Mojolicious-9.16/lib/Mojo/Server/CGI.pm 2021-04-06 18:55:46.000000000
+0200
@@ -6,6 +6,7 @@
sub run {
my $self = shift;
+ $self->app->server($self);
my $tx = $self->build_tx;
my $req = $tx->req->parse(\%ENV);
$tx->local_port($ENV{SERVER_PORT})->remote_address($ENV{REMOTE_ADDR});
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/Mojolicious-9.14/lib/Mojo/UserAgent/Transactor.pm
new/Mojolicious-9.16/lib/Mojo/UserAgent/Transactor.pm
--- old/Mojolicious-9.14/lib/Mojo/UserAgent/Transactor.pm 2021-01-29
18:08:08.000000000 +0100
+++ new/Mojolicious-9.16/lib/Mojo/UserAgent/Transactor.pm 2021-03-30
23:53:21.000000000 +0200
@@ -261,7 +261,7 @@
}
# Content-Disposition
- next unless defined $name;
+ next if !defined $name || defined $headers->content_disposition;
$name = url_escape $name, '"';
$name = encode $charset, $name if $charset;
my $disposition = qq{form-data; name="$name"};
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/Mojolicious-9.14/lib/Mojolicious/Command/Author/generate/app.pm
new/Mojolicious-9.16/lib/Mojolicious/Command/Author/generate/app.pm
--- old/Mojolicious-9.14/lib/Mojolicious/Command/Author/generate/app.pm
2021-01-29 18:08:08.000000000 +0100
+++ new/Mojolicious-9.16/lib/Mojolicious/Command/Author/generate/app.pm
2021-03-29 19:43:25.000000000 +0200
@@ -51,6 +51,7 @@
mojo generate app
mojo generate app TestApp
+ mojo generate app My::TestApp
Options:
-h, --help Show this summary of available options
@@ -133,7 +134,7 @@
my $r = $self->routes;
# Normal route to controller
- $r->get('/')->to('example#welcome');
+ $r->get('/')->to('Example#welcome');
}
1;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/Mojolicious-9.14/lib/Mojolicious/Guides/Routing.pod
new/Mojolicious-9.16/lib/Mojolicious/Guides/Routing.pod
--- old/Mojolicious-9.14/lib/Mojolicious/Guides/Routing.pod 2021-03-20
02:40:44.000000000 +0100
+++ new/Mojolicious-9.16/lib/Mojolicious/Guides/Routing.pod 2021-04-08
22:24:17.000000000 +0200
@@ -568,6 +568,18 @@
# /foo.txt -> {controller => 'foo', action => 'bar', format => 'txt'}
$r->get('/foo' => [format => ['html', 'txt']])->to('foo#bar', format =>
undef);
+Formats can be inherited by nested routes.
+
+ # /foo -> {controller => 'foo', action => 'one', format => undef}
+ # /foo.html -> {controller => 'foo', action => 'one', format => 'html'}
+ # /foo.json -> {controller => 'foo', action => 'one', format => 'json'}
+ # /bar -> {controller => 'bar', action => 'two', format => undef}
+ # /bar.html -> {controller => 'bar', action => 'two', format => 'html'}
+ # /bar.json -> {controller => 'bar', action => 'two', format => 'json'}
+ my $with_format = $r->any('/' => [format => ['html', 'json']])->to(format =>
undef);
+ $with_format->get('/foo')->to('foo#one');
+ $with_format->get('/bar')->to('bar#two');
+
A C<format> value can also be passed to L<Mojolicious::Controller/"url_for">.
# /foo/23.txt -> {controller => 'foo', action => 'bar', id => 23, format =>
'txt'}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/Mojolicious-9.14/lib/Mojolicious/Routes/Route.pm
new/Mojolicious-9.16/lib/Mojolicious/Routes/Route.pm
--- old/Mojolicious-9.14/lib/Mojolicious/Routes/Route.pm 2021-03-20
02:21:13.000000000 +0100
+++ new/Mojolicious-9.16/lib/Mojolicious/Routes/Route.pm 2021-04-08
22:24:17.000000000 +0200
@@ -217,11 +217,16 @@
sub _route {
my $self = shift;
- my $route = $self->add_child(__PACKAGE__->new->parse(@_))->children->[-1];
- croak qq{Route pattern "@{[$route->pattern->unparsed]}" contains a reserved
stash value}
- if grep { $self->is_reserved($_) } @{$route->pattern->placeholders};
- my $format = $self->pattern->constraints->{format};
- $route->pattern->constraints->{format} //= 1 if defined $format && $format
eq '1';
+ my $route =
$self->add_child(__PACKAGE__->new->parse(@_))->children->[-1];
+ my $new_pattern = $route->pattern;
+ croak qq{Route pattern "@{[$new_pattern->unparsed]}" contains a reserved
stash value}
+ if grep { $self->is_reserved($_) } @{$new_pattern->placeholders};
+
+ my $old_pattern = $self->pattern;
+ my $constraints = $old_pattern->constraints;
+ $new_pattern->constraints->{format} //= $constraints->{format} if exists
$constraints->{format};
+ my $defaults = $old_pattern->defaults;
+ $new_pattern->defaults->{format} //= $defaults->{format} if exists
$defaults->{format};
return $route;
}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/Mojolicious-9.14/lib/Mojolicious/Validator.pm
new/Mojolicious-9.16/lib/Mojolicious/Validator.pm
--- old/Mojolicious-9.14/lib/Mojolicious/Validator.pm 2021-03-14
18:05:50.000000000 +0100
+++ new/Mojolicious-9.16/lib/Mojolicious/Validator.pm 2021-04-07
17:14:40.000000000 +0200
@@ -169,7 +169,7 @@
my $filters = $validator->filters;
$validator = $validator->filters({trim => sub {...}});
-Registered filters, by default only L</"not_empty"> and L</"trim"> are already
defined.
+Registered filters, by default only L</"comma_separated">, L</"not_empty"> and
L</"trim"> are already defined.
=head1 METHODS
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/Mojolicious-9.14/lib/Mojolicious.pm
new/Mojolicious-9.16/lib/Mojolicious.pm
--- old/Mojolicious-9.14/lib/Mojolicious.pm 2021-03-22 12:33:05.000000000
+0100
+++ new/Mojolicious-9.16/lib/Mojolicious.pm 2021-04-06 18:55:28.000000000
+0200
@@ -56,7 +56,7 @@
has validator => sub { Mojolicious::Validator->new };
our $CODENAME = 'Waffle';
-our $VERSION = '9.14';
+our $VERSION = '9.16';
sub BUILD_DYNAMIC {
my ($class, $method, $dyn_methods) = @_;
@@ -253,7 +253,7 @@
=head2 before_server_start
Emitted right before the application server is started, for web servers that
support it, which includes all the
-built-in ones (except for L<Mojo::Server::CGI>).
+built-in ones.
$app->hook(before_server_start => sub ($server, $app) {...});
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/Mojolicious-9.14/t/mojo/cgi.t
new/Mojolicious-9.16/t/mojo/cgi.t
--- old/Mojolicious-9.14/t/mojo/cgi.t 2021-02-17 15:28:38.000000000 +0100
+++ new/Mojolicious-9.16/t/mojo/cgi.t 2021-04-06 18:55:40.000000000 +0200
@@ -155,6 +155,35 @@
is $res->json->{bar}, 'baz', 'right value';
};
+subtest 'Binding' => sub {
+ my @server;
+ app->hook(
+ before_server_start => sub {
+ my ($server, $app) = @_;
+ push @server, ref $server, $app->mode;
+ }
+ );
+
+ my $msg = '';
+ local *STDOUT;
+ open STDOUT, '>', \$msg;
+ local %ENV = (
+ PATH_INFO => '/',
+ REQUEST_METHOD => 'GET',
+ SCRIPT_NAME => '/',
+ HTTP_HOST => 'localhost:8080',
+ SERVER_PROTOCOL => 'HTTP/1.0'
+ );
+ is(Mojolicious::Command::cgi->new(app => app)->run, 200, 'right status');
+ my $res = Mojo::Message::Response->new->parse("HTTP/1.1 200 OK\x0d\x0a$msg");
+ is $res->code, 200, 'right status';
+ is $res->headers->status, '200 OK', 'right "Status"
value';
+ is $res->headers->content_length, 21, 'right
"Content-Length" value';
+ is $res->headers->content_type, 'text/html;charset=UTF-8', 'right
"Content-Type" value';
+ is $res->body, 'Your Mojo is working!', 'right content';
+ is_deeply \@server, ['Mojo::Server::CGI', 'development'], 'hook has been
emitted once';
+};
+
subtest 'Reverse proxy' => sub {
my $msg = '';
local *STDOUT;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/Mojolicious-9.14/t/mojo/hypnotoad.t
new/Mojolicious-9.16/t/mojo/hypnotoad.t
--- old/Mojolicious-9.14/t/mojo/hypnotoad.t 2021-02-17 15:28:38.000000000
+0100
+++ new/Mojolicious-9.16/t/mojo/hypnotoad.t 2021-04-06 20:55:29.000000000
+0200
@@ -13,8 +13,7 @@
use Mojo::Server::Hypnotoad;
use Mojo::UserAgent;
-# Configure
-{
+subtest 'Configure' => sub {
my $hypnotoad = Mojo::Server::Hypnotoad->new;
$hypnotoad->prefork->app->config->{myserver} = {
accepts => 13,
@@ -54,15 +53,15 @@
is_deeply $hypnotoad->prefork->trusted_proxies, ['127.0.0.0/8'], 'right
value';
is $hypnotoad->prefork->workers, 7, 'right value';
is $hypnotoad->upgrade_timeout, 45, 'right value';
-}
+};
-# Prepare script
-my $dir = tempdir;
-my $script = $dir->child('myapp.pl');
-my $log = $dir->child('mojo.log');
-my $port1 = Mojo::IOLoop::Server->generate_port;
-my $port2 = Mojo::IOLoop::Server->generate_port;
-$script->spurt(<<EOF);
+subtest 'Hot deployment' => sub {
+ my $dir = tempdir;
+ my $script = $dir->child('myapp.pl');
+ my $log = $dir->child('mojo.log');
+ my $port1 = Mojo::IOLoop::Server->generate_port;
+ my $port2 = Mojo::IOLoop::Server->generate_port;
+ $script->spurt(<<EOF);
use Mojolicious::Lite;
use Mojo::IOLoop;
@@ -97,85 +96,79 @@
app->start;
EOF
-# Start
-my $prefix = curfile->dirname->dirname->sibling('script');
-open my $start, '-|', $^X, "$prefix/hypnotoad", $script;
-sleep 3;
-sleep 1 while !_port($port2);
-my $old = _pid();
-
-# Application is alive
-my $ua = Mojo::UserAgent->new;
-my $tx = $ua->get("http://127.0.0.1:$port1/hello");
-ok $tx->is_finished, 'transaction is finished';
-ok $tx->keep_alive, 'connection will be kept alive';
-ok !$tx->kept_alive, 'connection was not kept alive';
-is $tx->res->code, 200, 'right status';
-is $tx->res->body, 'Hello Hypnotoad!', 'right content';
-
-# Application is alive (second port)
-$tx = $ua->get("http://127.0.0.1:$port2/hello");
-ok $tx->is_finished, 'transaction is finished';
-ok $tx->keep_alive, 'connection will be kept alive';
-ok !$tx->kept_alive, 'connection was not kept alive';
-is $tx->res->code, 200, 'right status';
-is $tx->res->body, 'Hello Hypnotoad!', 'right content';
-
-# Same result
-$tx = $ua->get("http://127.0.0.1:$port1/hello");
-ok $tx->is_finished, 'transaction is finished';
-ok $tx->keep_alive, 'connection will be kept alive';
-ok $tx->kept_alive, 'connection was kept alive';
-is $tx->res->code, 200, 'right status';
-is $tx->res->body, 'Hello Hypnotoad!', 'right content';
-
-# Same result (second port)
-$tx = $ua->get("http://127.0.0.1:$port2/hello");
-ok $tx->is_finished, 'transaction is finished';
-ok $tx->keep_alive, 'connection will be kept alive';
-ok $tx->kept_alive, 'connection was kept alive';
-is $tx->res->code, 200, 'right status';
-is $tx->res->body, 'Hello Hypnotoad!', 'right content';
+ my $prefix = curfile->dirname->dirname->sibling('script');
+ open my $start, '-|', $^X, "$prefix/hypnotoad", $script;
+ sleep 3;
+ sleep 1 while !_port($port2);
+ my $old = _pid($dir->child('hypnotoad.pid'));
+ my $ua = Mojo::UserAgent->new;
+
+ subtest 'Application is alive' => sub {
+ my $tx = $ua->get("http://127.0.0.1:$port1/hello");
+ ok $tx->is_finished, 'transaction is finished';
+ ok $tx->keep_alive, 'connection will be kept alive';
+ ok !$tx->kept_alive, 'connection was not kept alive';
+ is $tx->res->code, 200, 'right status';
+ is $tx->res->body, 'Hello Hypnotoad!', 'right content';
+
+ $tx = $ua->get("http://127.0.0.1:$port2/hello");
+ ok $tx->is_finished, 'transaction is finished';
+ ok $tx->keep_alive, 'connection will be kept alive';
+ ok !$tx->kept_alive, 'connection was not kept alive';
+ is $tx->res->code, 200, 'right status';
+ is $tx->res->body, 'Hello Hypnotoad!', 'right content';
+
+ $tx = $ua->get("http://127.0.0.1:$port1/hello");
+ ok $tx->is_finished, 'transaction is finished';
+ ok $tx->keep_alive, 'connection will be kept alive';
+ ok $tx->kept_alive, 'connection was kept alive';
+ is $tx->res->code, 200, 'right status';
+ is $tx->res->body, 'Hello Hypnotoad!', 'right content';
+
+ $tx = $ua->get("http://127.0.0.1:$port2/hello");
+ ok $tx->is_finished, 'transaction is finished';
+ ok $tx->keep_alive, 'connection will be kept alive';
+ ok $tx->kept_alive, 'connection was kept alive';
+ is $tx->res->code, 200, 'right status';
+ is $tx->res->body, 'Hello Hypnotoad!', 'right content';
+ };
-# Update script (broken)
-$script->spurt(<<'EOF');
+ $script->spurt(<<'EOF');
use Mojolicious::Lite;
die if $ENV{HYPNOTOAD_PID};
app->start;
EOF
-open my $hot_deploy, '-|', $^X, "$prefix/hypnotoad", $script;
+ open my $hot_deploy, '-|', $^X, "$prefix/hypnotoad", $script;
-# Wait for hot deployment to fail
-while (1) {
- last if $log->slurp =~ qr/Zero downtime software upgrade failed/;
- sleep 1;
-}
-
-# Connection did not get lost
-$tx = $ua->get("http://127.0.0.1:$port1/hello");
-ok $tx->is_finished, 'transaction is finished';
-ok $tx->keep_alive, 'connection will be kept alive';
-ok $tx->kept_alive, 'connection was kept alive';
-is $tx->res->code, 200, 'right status';
-is $tx->res->body, 'Hello Hypnotoad!', 'right content';
-
-# Connection did not get lost (second port)
-$tx = $ua->get("http://127.0.0.1:$port2/hello");
-ok $tx->is_finished, 'transaction is finished';
-ok $tx->keep_alive, 'connection will be kept alive';
-ok $tx->kept_alive, 'connection was kept alive';
-is $tx->res->code, 200, 'right status';
-is $tx->res->body, 'Hello Hypnotoad!', 'right content';
-
-# Request that will be served after graceful shutdown has been initiated
-$tx = $ua->build_tx(GET => "http://127.0.0.1:$port1/graceful");
-$ua->start($tx => sub { });
-Mojo::IOLoop->one_tick until $tx->req->is_finished;
+ while (1) {
+ last if $log->slurp =~ qr/Zero downtime software upgrade failed/;
+ sleep 1;
+ }
+
+ subtest 'Connection did not get lost' => sub {
+ my $tx = $ua->get("http://127.0.0.1:$port1/hello");
+ ok $tx->is_finished, 'transaction is finished';
+ ok $tx->keep_alive, 'connection will be kept alive';
+ ok $tx->kept_alive, 'connection was kept alive';
+ is $tx->res->code, 200, 'right status';
+ is $tx->res->body, 'Hello Hypnotoad!', 'right content';
+
+ $tx = $ua->get("http://127.0.0.1:$port2/hello");
+ ok $tx->is_finished, 'transaction is finished';
+ ok $tx->keep_alive, 'connection will be kept alive';
+ ok $tx->kept_alive, 'connection was kept alive';
+ is $tx->res->code, 200, 'right status';
+ is $tx->res->body, 'Hello Hypnotoad!', 'right content';
+ };
-# Update script
-$script->spurt(<<EOF);
+ subtest 'Request that will be served after graceful shutdown has been
initiated' => sub {
+ my $tx = $ua->build_tx(GET => "http://127.0.0.1:$port1/graceful");
+ $ua->start($tx => sub { });
+ Mojo::IOLoop->one_tick until $tx->req->is_finished;
+
+ $script->spurt(<<EOF);
use Mojolicious::Lite;
app->log->path('$log');
@@ -198,75 +191,75 @@
app->start;
EOF
-open $hot_deploy, '-|', $^X, "$prefix/hypnotoad", $script;
+ open $hot_deploy, '-|', $^X, "$prefix/hypnotoad", $script;
+
+ while (1) {
+ sleep 1;
+ next unless my $new = _pid($dir->child('hypnotoad.pid'));
+ last if $new ne $old;
+ }
-# Wait for hot deployment to finish
-while (1) {
- sleep 1;
- next unless my $new = _pid();
- last if $new ne $old;
-}
-
-# Request that will be served by an old worker that is still running
-Mojo::IOLoop->one_tick until $tx->is_finished;
-ok !$tx->keep_alive, 'connection will not be kept alive';
-ok !$tx->kept_alive, 'connection was not kept alive';
-is $tx->res->code, 200, 'right status';
-is $tx->res->body, 'Graceful shutdown!', 'right content';
-
-# One uncertain request that may or may not be served by the old worker
-$tx = $ua->get("http://127.0.0.1:$port1/hello");
-is $tx->res->code, 200, 'right status';
-$tx = $ua->get("http://127.0.0.1:$port2/hello");
-is $tx->res->code, 200, 'right status';
-
-# Application has been reloaded
-$tx = $ua->get("http://127.0.0.1:$port1/hello");
-ok $tx->is_finished, 'transaction is finished';
-ok !$tx->keep_alive, 'connection will not be kept alive';
-ok !$tx->kept_alive, 'connection was not kept alive';
-is $tx->res->code, 200, 'right status';
-my $first = $tx->res->body;
-like $first, qr/Hello World \d+!/, 'right content';
-
-# Application has been reloaded (second port)
-$tx = $ua->get("http://127.0.0.1:$port2/hello");
-ok $tx->is_finished, 'transaction is finished';
-ok !$tx->keep_alive, 'connection will not be kept alive';
-ok !$tx->kept_alive, 'connection was not kept alive';
-is $tx->res->code, 200, 'right status';
-is $tx->res->body, $first, 'same content';
-
-# Same result
-$tx = $ua->get("http://127.0.0.1:$port1/hello");
-ok $tx->is_finished, 'transaction is finished';
-ok !$tx->keep_alive, 'connection will not be kept alive';
-ok !$tx->kept_alive, 'connection was not kept alive';
-is $tx->res->code, 200, 'right status';
-my $second = $tx->res->body;
-isnt $first, $second, 'different content';
-like $second, qr/Hello World \d+!/, 'right content';
-
-# Same result (second port)
-$tx = $ua->get("http://127.0.0.1:$port2/hello");
-ok $tx->is_finished, 'transaction is finished';
-ok !$tx->keep_alive, 'connection will not be kept alive';
-ok !$tx->kept_alive, 'connection was not kept alive';
-is $tx->res->code, 200, 'right status';
-is $tx->res->body, $second, 'same content';
-
-# Stop
-open my $stop, '-|', $^X, "$prefix/hypnotoad", $script, '-s';
-sleep 1 while _port($port2);
-
-# Check log
-$log = $log->slurp;
-like $log, qr/Worker \d+ started/, 'right
message';
-like $log, qr/Starting zero downtime software upgrade \(180 seconds\)/, 'right
message';
-like $log, qr/Upgrade successful, stopping $old/, 'right
message';
+ Mojo::IOLoop->one_tick until $tx->is_finished;
+ ok !$tx->keep_alive, 'connection will not be kept alive';
+ ok !$tx->kept_alive, 'connection was not kept alive';
+ is $tx->res->code, 200, 'right status';
+ is $tx->res->body, 'Graceful shutdown!', 'right content';
+ };
+
+ subtest 'One uncertain request that may or may not be served by the old
worker' => sub {
+ my $tx = $ua->get("http://127.0.0.1:$port1/hello");
+ is $tx->res->code, 200, 'right status';
+ $tx = $ua->get("http://127.0.0.1:$port2/hello");
+ is $tx->res->code, 200, 'right status';
+ };
+
+ subtest 'Application has been reloaded' => sub {
+ my $tx = $ua->get("http://127.0.0.1:$port1/hello");
+ ok $tx->is_finished, 'transaction is finished';
+ ok !$tx->keep_alive, 'connection will not be kept alive';
+ ok !$tx->kept_alive, 'connection was not kept alive';
+ is $tx->res->code, 200, 'right status';
+ my $first = $tx->res->body;
+ like $first, qr/Hello World \d+!/, 'right content';
+
+ $tx = $ua->get("http://127.0.0.1:$port2/hello");
+ ok $tx->is_finished, 'transaction is finished';
+ ok !$tx->keep_alive, 'connection will not be kept alive';
+ ok !$tx->kept_alive, 'connection was not kept alive';
+ is $tx->res->code, 200, 'right status';
+ is $tx->res->body, $first, 'same content';
+
+ $tx = $ua->get("http://127.0.0.1:$port1/hello");
+ ok $tx->is_finished, 'transaction is finished';
+ ok !$tx->keep_alive, 'connection will not be kept alive';
+ ok !$tx->kept_alive, 'connection was not kept alive';
+ is $tx->res->code, 200, 'right status';
+ my $second = $tx->res->body;
+ isnt $first, $second, 'different content';
+ like $second, qr/Hello World \d+!/, 'right content';
+
+ $tx = $ua->get("http://127.0.0.1:$port2/hello");
+ ok $tx->is_finished, 'transaction is finished';
+ ok !$tx->keep_alive, 'connection will not be kept alive';
+ ok !$tx->kept_alive, 'connection was not kept alive';
+ is $tx->res->code, 200, 'right status';
+ is $tx->res->body, $second, 'same content';
+ };
+
+ open my $stop, '-|', $^X, "$prefix/hypnotoad", $script, '-s';
+ sleep 1 while _port($port2);
+
+ subtest 'Check log' => sub {
+ my $log = $log->slurp;
+ like $log, qr/Worker \d+ started/,
'right message';
+ like $log, qr/Starting zero downtime software upgrade \(180 seconds\)/,
'right message';
+ like $log, qr/Upgrade successful, stopping $old/,
'right message';
+ };
+};
sub _pid {
- return undef unless open my $file, '<', $dir->child('hypnotoad.pid');
+ my $path = shift;
+ return undef unless open my $file, '<', $path;
my $pid = <$file>;
chomp $pid;
return $pid;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/Mojolicious-9.14/t/mojo/morbo.t
new/Mojolicious-9.16/t/mojo/morbo.t
--- old/Mojolicious-9.14/t/mojo/morbo.t 2021-01-27 16:04:19.000000000 +0100
+++ new/Mojolicious-9.16/t/mojo/morbo.t 2021-03-29 19:41:19.000000000 +0200
@@ -9,7 +9,7 @@
use Mojo::File qw(curfile);
use lib curfile->sibling('lib')->to_string;
-use IO::Socket::INET;
+use IO::Socket::INET ();
use Mojo::File qw(tempdir);
use Mojo::IOLoop::Server;
use Mojo::Server::Morbo::Backend;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/Mojolicious-9.14/t/mojo/prefork.t
new/Mojolicious-9.16/t/mojo/prefork.t
--- old/Mojolicious-9.14/t/mojo/prefork.t 2021-01-27 16:04:18.000000000
+0100
+++ new/Mojolicious-9.16/t/mojo/prefork.t 2021-04-06 20:38:25.000000000
+0200
@@ -11,126 +11,130 @@
use Mojo::Server::Prefork;
use Mojo::UserAgent;
-# Manage and clean up PID file
-my $prefork = Mojo::Server::Prefork->new;
-my $dir = tempdir;
-ok $prefork->pid_file, 'has default path';
-my $file = $dir->child('prefork.pid');
-$prefork->pid_file($file);
-ok !$prefork->check_pid, 'no process id';
-$prefork->ensure_pid_file(-23);
-ok -e $file, 'file exists';
-is path($file)->slurp, "-23\n", 'right process id';
-ok !$prefork->check_pid, 'no process id';
-ok !-e $file, 'file has been cleaned up';
-$prefork->ensure_pid_file($$);
-ok -e $file, 'file exists';
-is path($file)->slurp, "$$\n", 'right process id';
-is $prefork->check_pid, $$, 'right process id';
-undef $prefork;
-ok !-e $file, 'file has been cleaned up';
-
-# Bad PID file
-my $bad = curfile->sibling('does_not_exist', 'test.pid');
-$prefork = Mojo::Server::Prefork->new(pid_file => $bad);
-$prefork->app->log->level('debug')->unsubscribe('message');
-my $log = '';
-my $cb = $prefork->app->log->on(message => sub { $log .= pop });
-eval { $prefork->ensure_pid_file($$) };
-like $@, qr/Can't create process id file/, 'right error';
-unlike $log, qr/Creating process id file/, 'right message';
-like $log, qr/Can't create process id file/, 'right message';
-$prefork->app->log->unsubscribe(message => $cb);
-
-# Multiple workers and graceful shutdown
-my $port = Mojo::IOLoop::Server::->generate_port;
-$prefork = Mojo::Server::Prefork->new(heartbeat_interval => 0.5, listen =>
["http://*:$port"], pid_file => $file);
-$prefork->unsubscribe('request');
-$prefork->on(
- request => sub {
- my ($prefork, $tx) = @_;
- $tx->res->code(200)->body('just works!');
- $tx->resume;
- }
-);
-is $prefork->workers, 4, 'start with four workers';
-my (@spawn, @reap, $worker, $tx, $graceful);
-$prefork->on(spawn => sub { push @spawn, pop });
-$prefork->on(
- heartbeat => sub {
- my ($prefork, $pid) = @_;
- $worker = $pid;
- return if $prefork->healthy < 4;
- $tx = Mojo::UserAgent->new->get("http://127.0.0.1:$port");
- kill 'QUIT', $$;
- }
-);
-$prefork->on(reap => sub { push @reap, pop });
-$prefork->on(finish => sub { $graceful = pop });
-$prefork->app->log->level('debug')->unsubscribe('message');
-$log = '';
-$cb = $prefork->app->log->on(message => sub { $log .= pop });
-is $prefork->healthy, 0, 'no healthy workers';
-my @server;
-$prefork->app->hook(
- before_server_start => sub {
- my ($server, $app) = @_;
- push @server, $server->workers, $app->mode;
- }
-);
-$prefork->run;
-is_deeply \@server, [4, 'development'], 'hook has been emitted once';
-is scalar @spawn, 4, 'four workers spawned';
-is scalar @reap, 4, 'four workers reaped';
-ok !!grep { $worker eq $_ } @spawn, 'worker has a heartbeat';
-ok $graceful, 'server has been stopped gracefully';
-is_deeply [sort @spawn], [sort @reap], 'same process ids';
-is $tx->res->code, 200, 'right status';
-is $tx->res->body, 'just works!', 'right content';
-like $log, qr/Listening at/, 'right
message';
-like $log, qr/Manager $$ started/, 'right
message';
-like $log, qr/Creating process id file/, 'right
message';
-like $log, qr/Stopping worker $spawn[0] gracefully \(120 seconds\)/, 'right
message';
-like $log, qr/Worker $spawn[0] stopped/, 'right
message';
-like $log, qr/Manager $$ stopped/, 'right
message';
-$prefork->app->log->unsubscribe(message => $cb);
-
-# Process id file
-is $prefork->check_pid, $$, 'right process id';
-my $pid = $prefork->pid_file;
-ok -e $pid, 'process id file has been created';
-undef $prefork;
-ok !-e $pid, 'process id file has been removed';
-
-# One worker and immediate shutdown
-$port = Mojo::IOLoop::Server->generate_port;
-$prefork
- = Mojo::Server::Prefork->new(accepts => 500, heartbeat_interval => 0.5,
listen => ["http://*:$port"], workers => 1);
-$prefork->unsubscribe('request');
-$prefork->on(
- request => sub {
- my ($prefork, $tx) = @_;
- $tx->res->code(200)->body('works too!');
- $tx->resume;
- }
-);
-my $count = $tx = $graceful = undef;
-@spawn = @reap = ();
-$prefork->on(spawn => sub { push @spawn, pop });
-$prefork->once(
- heartbeat => sub {
- $tx = Mojo::UserAgent->new->get("http://127.0.0.1:$port");
- kill 'TERM', $$;
- }
-);
-$prefork->on(reap => sub { push @reap, pop });
-$prefork->on(finish => sub { $graceful = pop });
-$prefork->run;
-is $prefork->ioloop->max_accepts, 500, 'right value';
-is scalar @spawn, 1, 'one worker spawned';
-is scalar @reap, 1, 'one worker reaped';
-ok !$graceful, 'server has been stopped immediately';
-is $tx->res->code, 200, 'right status';
-is $tx->res->body, 'works too!', 'right content';
+subtest 'Manage and clean up PID file' => sub {
+ my $prefork = Mojo::Server::Prefork->new;
+ my $dir = tempdir;
+ ok $prefork->pid_file, 'has default path';
+ my $file = $dir->child('prefork.pid');
+ $prefork->pid_file($file);
+ ok !$prefork->check_pid, 'no process id';
+ $prefork->ensure_pid_file(-23);
+ ok -e $file, 'file exists';
+ is path($file)->slurp, "-23\n", 'right process id';
+ ok !$prefork->check_pid, 'no process id';
+ ok !-e $file, 'file has been cleaned up';
+ $prefork->ensure_pid_file($$);
+ ok -e $file, 'file exists';
+ is path($file)->slurp, "$$\n", 'right process id';
+ is $prefork->check_pid, $$, 'right process id';
+ undef $prefork;
+ ok !-e $file, 'file has been cleaned up';
+};
+
+subtest 'Bad PID file' => sub {
+ my $bad = curfile->sibling('does_not_exist', 'test.pid');
+ my $prefork = Mojo::Server::Prefork->new(pid_file => $bad);
+ $prefork->app->log->level('debug')->unsubscribe('message');
+ my $log = '';
+ my $cb = $prefork->app->log->on(message => sub { $log .= pop });
+ eval { $prefork->ensure_pid_file($$) };
+ like $@, qr/Can't create process id file/, 'right error';
+ unlike $log, qr/Creating process id file/, 'right message';
+ like $log, qr/Can't create process id file/, 'right message';
+ $prefork->app->log->unsubscribe(message => $cb);
+};
+
+subtest 'Multiple workers and graceful shutdown' => sub {
+ my $dir = tempdir;
+ my $file = $dir->child('prefork.pid');
+ my $port = Mojo::IOLoop::Server::->generate_port;
+ my $prefork = Mojo::Server::Prefork->new(heartbeat_interval => 0.5, listen
=> ["http://*:$port"], pid_file => $file);
+ $prefork->unsubscribe('request');
+ $prefork->on(
+ request => sub {
+ my ($prefork, $tx) = @_;
+ $tx->res->code(200)->body('just works!');
+ $tx->resume;
+ }
+ );
+ is $prefork->workers, 4, 'start with four workers';
+ my (@spawn, @reap, $worker, $tx, $graceful);
+ $prefork->on(spawn => sub { push @spawn, pop });
+ $prefork->on(
+ heartbeat => sub {
+ my ($prefork, $pid) = @_;
+ $worker = $pid;
+ return if $prefork->healthy < 4;
+ $tx = Mojo::UserAgent->new->get("http://127.0.0.1:$port");
+ kill 'QUIT', $$;
+ }
+ );
+ $prefork->on(reap => sub { push @reap, pop });
+ $prefork->on(finish => sub { $graceful = pop });
+ $prefork->app->log->level('debug')->unsubscribe('message');
+ my $log = '';
+ my $cb = $prefork->app->log->on(message => sub { $log .= pop });
+ is $prefork->healthy, 0, 'no healthy workers';
+ my @server;
+ $prefork->app->hook(
+ before_server_start => sub {
+ my ($server, $app) = @_;
+ push @server, $server->workers, $app->mode;
+ }
+ );
+ $prefork->run;
+ is_deeply \@server, [4, 'development'], 'hook has been emitted once';
+ is scalar @spawn, 4, 'four workers spawned';
+ is scalar @reap, 4, 'four workers reaped';
+ ok !!grep { $worker eq $_ } @spawn, 'worker has a heartbeat';
+ ok $graceful, 'server has been stopped gracefully';
+ is_deeply [sort @spawn], [sort @reap], 'same process ids';
+ is $tx->res->code, 200, 'right status';
+ is $tx->res->body, 'just works!', 'right content';
+ like $log, qr/Listening at/, 'right
message';
+ like $log, qr/Manager $$ started/, 'right
message';
+ like $log, qr/Creating process id file/, 'right
message';
+ like $log, qr/Stopping worker $spawn[0] gracefully \(120 seconds\)/, 'right
message';
+ like $log, qr/Worker $spawn[0] stopped/, 'right
message';
+ like $log, qr/Manager $$ stopped/, 'right
message';
+ $prefork->app->log->unsubscribe(message => $cb);
+
+ is $prefork->check_pid, $$, 'right process id';
+ my $pid = $prefork->pid_file;
+ ok -e $pid, 'process id file has been created';
+ undef $prefork;
+ ok !-e $pid, 'process id file has been removed';
+};
+
+subtest 'One worker and immediate shutdown' => sub {
+ my $port = Mojo::IOLoop::Server->generate_port;
+ my $prefork
+ = Mojo::Server::Prefork->new(accepts => 500, heartbeat_interval => 0.5,
listen => ["http://*:$port"], workers => 1);
+ my (@spawn, @reap, $tx, $graceful, $count);
+ $prefork->unsubscribe('request');
+ $prefork->on(
+ request => sub {
+ my ($prefork, $tx) = @_;
+ $tx->res->code(200)->body('works too!');
+ $tx->resume;
+ }
+ );
+ $prefork->on(spawn => sub { push @spawn, pop });
+ $prefork->once(
+ heartbeat => sub {
+ $tx = Mojo::UserAgent->new->get("http://127.0.0.1:$port");
+ kill 'TERM', $$;
+ }
+ );
+ $prefork->on(reap => sub { push @reap, pop });
+ $prefork->on(finish => sub { $graceful = pop });
+ $prefork->run;
+ is $prefork->ioloop->max_accepts, 500, 'right value';
+ is scalar @spawn, 1, 'one worker spawned';
+ is scalar @reap, 1, 'one worker reaped';
+ ok !$graceful, 'server has been stopped immediately';
+ is $tx->res->code, 200, 'right status';
+ is $tx->res->body, 'works too!', 'right content';
+};
done_testing();
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/Mojolicious-9.14/t/mojo/transactor.t
new/Mojolicious-9.16/t/mojo/transactor.t
--- old/Mojolicious-9.14/t/mojo/transactor.t 2021-01-27 16:04:35.000000000
+0100
+++ new/Mojolicious-9.16/t/mojo/transactor.t 2021-03-30 23:53:25.000000000
+0200
@@ -259,6 +259,22 @@
is $tx->req->content->parts->[1], undef, 'no more parts';
};
+subtest 'Multipart form with custom Content-Disposition header' => sub {
+ my $tx = $t->tx(POST => 'http://example.com/foo' => form =>
+ {mytext => {file => __FILE__, 'Content-Disposition' => 'form-data;
name="works"'}});
+ is $tx->req->url->to_abs, 'http://example.com/foo', 'right URL';
+ is $tx->req->method, 'POST', 'right method';
+ is $tx->req->headers->content_type, 'multipart/form-data', 'right
"Content-Type" value';
+ unlike $tx->req->content->parts->[0]->headers->content_disposition,
qr/"transactor.t"/,
+ 'different "Content-Disposition" value';
+ is $tx->req->content->parts->[0]->headers->content_disposition, 'form-data;
name="works"',
+ 'right "Content-Disposition" value';
+ like $tx->req->content->parts->[0]->asset->slurp, qr/mytext/, 'right part';
+ ok $tx->req->content->parts->[0]->asset->is_file, 'stored in file';
+ ok !$tx->req->content->parts->[0]->headers->header('file'), 'no "file"
header';
+ is $tx->req->content->parts->[1], undef, 'no more parts';
+};
+
subtest 'Multipart form with asset and custom content type' => sub {
my $tx = $t->tx(POST => 'http://example.com/foo' => {'Content-Type' =>
'multipart/mojo-form'} => form =>
{mytext => {file => Mojo::Asset::File->new(path => __FILE__)}});
@@ -372,8 +388,9 @@
is $tx->req->headers->content_type, undef, 'no "Content-Type" value';
like $tx->req->content->parts->[0]->asset->slurp, qr/mytext/, 'right part';
ok $tx->req->content->parts->[0]->asset->is_file, 'stored in file';
- ok !$tx->req->content->parts->[0]->headers->header('file'), 'no "file"
header';
- is $tx->req->content->parts->[0]->headers->dnt, 1, 'right "DNT" header';
+ is $tx->req->content->parts->[0]->headers->header('file'), undef, 'no "file"
header';
+ is $tx->req->content->parts->[0]->headers->content_disposition, undef, 'no
"Content-Disposition" value';
+ is $tx->req->content->parts->[0]->headers->dnt, 1,
'right "DNT" header';
is $tx->req->content->parts->[1], undef, 'no more parts';
};
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/Mojolicious-9.14/t/mojolicious/routes.t
new/Mojolicious-9.16/t/mojolicious/routes.t
--- old/Mojolicious-9.14/t/mojolicious/routes.t 2021-03-20 15:58:23.000000000
+0100
+++ new/Mojolicious-9.16/t/mojolicious/routes.t 2021-04-08 22:24:17.000000000
+0200
@@ -210,6 +210,25 @@
$custom->pattern->quote_start('{')->quote_end('}')->placeholder_start('.')->relaxed_start('$')->wildcard_start('@');
$custom->parse('/custom_pattern/a_{.one}_b/{$two}/{@three}');
+# /inherit/first.html
+# /inherit/first.json
+# /inherit/second
+# /inherit/second.html
+# /inherit/second.json
+my $inherit_format = $r->any('/inherit' => [format => ['json', 'html']]);
+$inherit_format->get('/first')->to('inherit#first');
+$inherit_format->get('/second')->to('inherit#second', format => undef);
+
+# /inherit2/first
+# /inherit2/first.xml
+# /inherit2/second
+# /inherit2/second.html
+# /inherit2/third
+my $inherit_format2 = $r->any('/inherit2' => [format =>
['xml']])->to('inherit#', format => undef);
+$inherit_format2->get('/first')->to('#first', format => 'html');
+$inherit_format2->post('/second' => [format => ['html']])->to('#second');
+$inherit_format2->get('/third' => [format => 0])->to('#third');
+
subtest 'Cached lookup' => sub {
my $fast = $r->any('/fast');
is $r->find('fast'), $fast, 'fast route found';
@@ -664,6 +683,71 @@
is_deeply $m->stack, [], 'empty stack';
};
+subtest 'Format inheritance' => sub {
+ my $c = Mojolicious::Controller->new;
+ my $m = Mojolicious::Routes::Match->new(root => $r);
+ $m->find($c => {method => 'GET', path => '/inherit/first.html'});
+ is_deeply $m->stack, [{controller => 'inherit', action => 'first', format =>
'html'}], 'right structure';
+ is $m->path_for->{path}, '/inherit/first.html', 'right path';
+ is $m->path_for(format => undef)->{path}, '/inherit/first', 'right path';
+ $m = Mojolicious::Routes::Match->new(root => $r);
+ $m->find($c => {method => 'GET', path => '/inherit/first.json'});
+ is_deeply $m->stack, [{controller => 'inherit', action => 'first', format =>
'json'}], 'right structure';
+ is $m->path_for->{path}, '/inherit/first.json', 'right path';
+ $m = Mojolicious::Routes::Match->new(root => $r);
+ $m->find($c => {method => 'GET', path => '/inherit/first'});
+ is_deeply $m->stack, [], 'empty stack';
+ $m = Mojolicious::Routes::Match->new(root => $r);
+ $m->find($c => {method => 'GET', path => '/inherit/first.xml'});
+ is_deeply $m->stack, [], 'empty stack';
+
+ $m = Mojolicious::Routes::Match->new(root => $r);
+ $m->find($c => {method => 'GET', path => '/inherit/second.html'});
+ is_deeply $m->stack, [{controller => 'inherit', action => 'second', format
=> 'html'}], 'right structure';
+ is $m->path_for->{path}, '/inherit/second.html', 'right path';
+ is $m->path_for(format => undef)->{path}, '/inherit/second', 'right path';
+ $m = Mojolicious::Routes::Match->new(root => $r);
+ $m->find($c => {method => 'GET', path => '/inherit/second.json'});
+ is_deeply $m->stack, [{controller => 'inherit', action => 'second', format
=> 'json'}], 'right structure';
+ is $m->path_for->{path}, '/inherit/second.json', 'right path';
+ $m = Mojolicious::Routes::Match->new(root => $r);
+ $m->find($c => {method => 'GET', path => '/inherit/second'});
+ is_deeply $m->stack, [{controller => 'inherit', action => 'second', format
=> undef}], 'right structure';
+ is $m->path_for->{path}, '/inherit/second', 'right path';
+
+ $m = Mojolicious::Routes::Match->new(root => $r);
+ $m->find($c => {method => 'GET', path => '/inherit2/first'});
+ is_deeply $m->stack, [{controller => 'inherit', action => 'first', format =>
'html'}], 'right structure';
+ is $m->path_for->{path}, '/inherit2/first.html', 'right path';
+ $m = Mojolicious::Routes::Match->new(root => $r);
+ $m->find($c => {method => 'GET', path => '/inherit2/first.xml'});
+ is_deeply $m->stack, [{controller => 'inherit', action => 'first', format =>
'xml'}], 'right structure';
+ is $m->path_for->{path}, '/inherit2/first.xml', 'right path';
+ $m = Mojolicious::Routes::Match->new(root => $r);
+ $m->find($c => {method => 'GET', path => '/inherit2/first.html'});
+ is_deeply $m->stack, [], 'empty stack';
+
+ $m = Mojolicious::Routes::Match->new(root => $r);
+ $m->find($c => {method => 'POST', path => '/inherit2/second'});
+ is_deeply $m->stack, [{controller => 'inherit', action => 'second', format
=> undef}], 'right structure';
+ is $m->path_for->{path}, '/inherit2/second', 'right path';
+ $m = Mojolicious::Routes::Match->new(root => $r);
+ $m->find($c => {method => 'POST', path => '/inherit2/second.html'});
+ is_deeply $m->stack, [{controller => 'inherit', action => 'second', format
=> 'html'}], 'right structure';
+ is $m->path_for->{path}, '/inherit2/second.html', 'right path';
+ $m = Mojolicious::Routes::Match->new(root => $r);
+ $m->find($c => {method => 'POST', path => '/inherit2/second.xml'});
+ is_deeply $m->stack, [], 'empty stack';
+
+ $m = Mojolicious::Routes::Match->new(root => $r);
+ $m->find($c => {method => 'GET', path => '/inherit2/third'});
+ is_deeply $m->stack, [{controller => 'inherit', action => 'third', format =>
undef}], 'right structure';
+ is $m->path_for->{path}, '/inherit2/third', 'right path';
+ $m = Mojolicious::Routes::Match->new(root => $r);
+ $m->find($c => {method => 'GET', path => '/inherit2/third.xml'});
+ is_deeply $m->stack, [], 'empty stack';
+};
+
subtest 'Request methods' => sub {
my $c = Mojolicious::Controller->new;
my $m = Mojolicious::Routes::Match->new(root => $r);