Skip to content

Commit

Permalink
Merge pull request #1683 from markogrady1/convert-longpolling_lite_ap…
Browse files Browse the repository at this point in the history
…p-to-use-subtests

convert t/mojolicious/longpolling_lite_app.t to use subtests
  • Loading branch information
mergify[bot] authored Feb 13, 2021
2 parents dcb4a05 + 2ff9cb0 commit 73f6fda
Showing 1 changed file with 141 additions and 126 deletions.
267 changes: 141 additions & 126 deletions t/mojolicious/longpolling_lite_app.t
Original file line number Diff line number Diff line change
Expand Up @@ -159,132 +159,147 @@ get '/too_long' => sub {

my $t = Test::Mojo->new;

# Stream without delay and finish
$t->app->log->level('debug')->unsubscribe('message');
my $log = '';
my $cb = $t->app->log->on(message => sub { $log .= pop });
my $stash;
$t->app->plugins->once(before_dispatch => sub { $stash = shift->stash });
$t->get_ok('/write')->status_is(200)->header_is(Server => 'Mojolicious (Perl)')->content_type_is('text/plain')
->content_is('this was short.');
Mojo::IOLoop->one_tick until $stash->{finished};
ok !$t->tx->kept_alive, 'connection was not kept alive';
ok !$t->tx->keep_alive, 'connection will not be kept alive';
is $stash->{finished}, 1, 'finish event has been emitted once';
ok $stash->{destroyed}, 'controller has been destroyed';
unlike $log, qr/Nothing has been rendered, expecting delayed response/, 'right message';
$t->app->log->unsubscribe(message => $cb);

# Stream without delay and content length
$t->get_ok('/write/length')->status_is(200)->header_is(Server => 'Mojolicious (Perl)')->content_type_is('text/plain')
->content_is('this was short and plain.');
ok !$t->tx->kept_alive, 'connection was not kept alive';
ok $t->tx->keep_alive, 'connection will be kept alive';

# Stream without delay and empty write
$t->get_ok('/write/nolength')->status_is(200)->header_is(Server => 'Mojolicious (Perl)')
->header_is('Content-Length' => undef)->content_type_is('text/plain')
->content_is('this was short and had no length.');
ok $t->tx->kept_alive, 'connection was kept alive';
ok !$t->tx->keep_alive, 'connection will not be kept alive';

# Chunked response with delay
$stash = undef;
$t->app->plugins->once(before_dispatch => sub { $stash = shift->stash });
$t->get_ok('/longpoll/chunked')->status_is(200)->header_is(Server => 'Mojolicious (Perl)')
->content_type_is('text/plain')->content_is('hi there, whats up?');
Mojo::IOLoop->one_tick until $stash->{finished};
ok !$t->tx->kept_alive, 'connection was not kept alive';
ok $t->tx->keep_alive, 'connection will be kept alive';
is $stash->{finished}, 1, 'finish event has been emitted once';
ok $stash->{destroyed}, 'controller has been destroyed';

# Interrupted by closing the connection
$stash = undef;
$t->app->plugins->once(before_dispatch => sub { $stash = shift->stash });
my $port = $t->ua->server->url->port;
Mojo::IOLoop->client(
{port => $port} => sub {
my ($loop, $err, $stream) = @_;
$stream->on(read => sub { shift->close });
$stream->write("GET /longpoll/chunked HTTP/1.1\x0d\x0a\x0d\x0a");
}
);
Mojo::IOLoop->one_tick until $stash->{finished};
is $stash->{finished}, 1, 'finish event has been emitted once';
ok $stash->{destroyed}, 'controller has been destroyed';

# Interrupted by raising an error
my $tx = $t->ua->build_tx(GET => '/longpoll/chunked');
my $buffer = '';
$tx->res->content->unsubscribe('read')->on(
read => sub {
my ($content, $chunk) = @_;
$buffer .= $chunk;
$tx->res->error({message => 'Interrupted'}) if length $buffer == 3;
}
);
$t->ua->start($tx);
is $tx->res->code, 200, 'right status';
is $tx->res->error->{message}, 'Interrupted', 'right error';
is $buffer, 'hi ', 'right content';

# Stream with delay and content length
$stash = undef;
$t->app->plugins->once(before_dispatch => sub { $stash = shift->stash });
$t->get_ok('/longpoll/length')->status_is(200)->header_is(Server => 'Mojolicious (Perl)')
->content_type_is('text/plain')->content_is('hi there plain, whats up?');
is $stash->{drain}, 1, 'drain event has been emitted once';

# Stream with delay and finish
$t->get_ok('/longpoll/nolength')->status_is(200)->header_is(Server => 'Mojolicious (Perl)')
->header_is('Content-Length' => undef)->content_type_is('text/plain')->content_is('hi there, what length?');
ok !$t->tx->keep_alive, 'connection will not be kept alive';

# The drain event should be emitted on the next reactor tick
$stash = undef;
$t->app->plugins->once(before_dispatch => sub { $stash = shift->stash });
$t->get_ok('/longpoll/order')->status_is(200)->header_is(Server => 'Mojolicious (Perl)')
->content_is('First, second, third!');
is $stash->{order}, 1, 'the drain event was emitted on the next reactor tick';

# Static file with cookies and session
$log = '';
$cb = $t->app->log->on(message => sub { $log .= pop });
$t->get_ok('/longpoll/static')->status_is(200)->header_is(Server => 'Mojolicious (Perl)')
->header_like('Set-Cookie' => qr/bar=baz/)->header_like('Set-Cookie' => qr/mojolicious=/)
->content_type_is('text/plain;charset=UTF-8')->content_is("Hello Mojo from a static file!\n");
like $log, qr/Nothing has been rendered, expecting delayed response/, 'right message';
$t->app->log->unsubscribe(message => $cb);

# Custom response
$t->get_ok('/longpoll/dynamic')->status_is(201)->header_is(Server => 'Mojolicious (Perl)')
->header_like('Set-Cookie' => qr/baz=yada/)->content_is('Dynamic!');

# Chunked response streaming with drain event
$stash = undef;
$t->app->plugins->once(before_dispatch => sub { $stash = shift->stash });
$t->get_ok('/stream')->status_is(200)->header_is(Server => 'Mojolicious (Perl)')->content_is('0123456789');
is $stash->{subscribers}, 0, 'no leaking subscribers';
ok $stash->{destroyed}, 'controller has been destroyed';

# Rendering of template
$stash = undef;
$t->app->plugins->once(before_dispatch => sub { $stash = shift->stash });
$t->get_ok('/render')->status_is(200)->header_is(Server => 'Mojolicious (Perl)')->content_is('Finish!');
Mojo::IOLoop->one_tick until $stash->{destroyed};
ok !$stash->{writing}, 'finish event timing is right';
ok $stash->{destroyed}, 'controller has been destroyed';

# Request timeout
$tx = $t->ua->request_timeout(0.5)->get('/too_long');
is $tx->error->{message}, 'Request timeout', 'right error';
$t->ua->request_timeout(0);

# Inactivity timeout
$tx = $t->ua->inactivity_timeout(0.5)->get('/too_long');
is $tx->error->{message}, 'Inactivity timeout', 'right error';
$t->ua->inactivity_timeout(20);
subtest 'Stream without delay and finish' => sub {
$t->app->log->level('debug')->unsubscribe('message');
my $log = '';
my $cb = $t->app->log->on(message => sub { $log .= pop });
my $stash;
$t->app->plugins->once(before_dispatch => sub { $stash = shift->stash });
$t->get_ok('/write')->status_is(200)->header_is(Server => 'Mojolicious (Perl)')->content_type_is('text/plain')
->content_is('this was short.');
Mojo::IOLoop->one_tick until $stash->{finished};
ok !$t->tx->kept_alive, 'connection was not kept alive';
ok !$t->tx->keep_alive, 'connection will not be kept alive';
is $stash->{finished}, 1, 'finish event has been emitted once';
ok $stash->{destroyed}, 'controller has been destroyed';
unlike $log, qr/Nothing has been rendered, expecting delayed response/, 'right message';
$t->app->log->unsubscribe(message => $cb);
};

subtest 'Stream without delay and content length' => sub {
$t->get_ok('/write/length')->status_is(200)->header_is(Server => 'Mojolicious (Perl)')->content_type_is('text/plain')
->content_is('this was short and plain.');
ok !$t->tx->kept_alive, 'connection was not kept alive';
ok $t->tx->keep_alive, 'connection will be kept alive';
};

subtest 'Stream without delay and empty write' => sub {
$t->get_ok('/write/nolength')->status_is(200)->header_is(Server => 'Mojolicious (Perl)')
->header_is('Content-Length' => undef)->content_type_is('text/plain')
->content_is('this was short and had no length.');
ok $t->tx->kept_alive, 'connection was kept alive';
ok !$t->tx->keep_alive, 'connection will not be kept alive';
};

subtest 'Chunked response with delay' => sub {
my $stash = undef;
$t->app->plugins->once(before_dispatch => sub { $stash = shift->stash });
$t->get_ok('/longpoll/chunked')->status_is(200)->header_is(Server => 'Mojolicious (Perl)')
->content_type_is('text/plain')->content_is('hi there, whats up?');
Mojo::IOLoop->one_tick until $stash->{finished};
ok !$t->tx->kept_alive, 'connection was not kept alive';
ok $t->tx->keep_alive, 'connection will be kept alive';
is $stash->{finished}, 1, 'finish event has been emitted once';
ok $stash->{destroyed}, 'controller has been destroyed';
};

subtest 'Interrupted by closing the connection' => sub {
my $stash = undef;
$t->app->plugins->once(before_dispatch => sub { $stash = shift->stash });
my $port = $t->ua->server->url->port;
Mojo::IOLoop->client(
{port => $port} => sub {
my ($loop, $err, $stream) = @_;
$stream->on(read => sub { shift->close });
$stream->write("GET /longpoll/chunked HTTP/1.1\x0d\x0a\x0d\x0a");
}
);
Mojo::IOLoop->one_tick until $stash->{finished};
is $stash->{finished}, 1, 'finish event has been emitted once';
ok $stash->{destroyed}, 'controller has been destroyed';
};

subtest 'Interrupted by raising an error' => sub {
my $tx = $t->ua->build_tx(GET => '/longpoll/chunked');
my $buffer = '';
$tx->res->content->unsubscribe('read')->on(
read => sub {
my ($content, $chunk) = @_;
$buffer .= $chunk;
$tx->res->error({message => 'Interrupted'}) if length $buffer == 3;
}
);
$t->ua->start($tx);
is $tx->res->code, 200, 'right status';
is $tx->res->error->{message}, 'Interrupted', 'right error';
is $buffer, 'hi ', 'right content';
};

subtest 'Stream with delay and content length' => sub {
my $stash = undef;
$t->app->plugins->once(before_dispatch => sub { $stash = shift->stash });
$t->get_ok('/longpoll/length')->status_is(200)->header_is(Server => 'Mojolicious (Perl)')
->content_type_is('text/plain')->content_is('hi there plain, whats up?');
is $stash->{drain}, 1, 'drain event has been emitted once';
};

subtest 'Stream with delay and finish' => sub {
$t->get_ok('/longpoll/nolength')->status_is(200)->header_is(Server => 'Mojolicious (Perl)')
->header_is('Content-Length' => undef)->content_type_is('text/plain')->content_is('hi there, what length?');
ok !$t->tx->keep_alive, 'connection will not be kept alive';
};

subtest 'The drain event should be emitted on the next reactor tick' => sub {
my $stash = undef;
$t->app->plugins->once(before_dispatch => sub { $stash = shift->stash });
$t->get_ok('/longpoll/order')->status_is(200)->header_is(Server => 'Mojolicious (Perl)')
->content_is('First, second, third!');
is $stash->{order}, 1, 'the drain event was emitted on the next reactor tick';
};

subtest 'Static file with cookies and session' => sub {
my $log = '';
my $cb = $t->app->log->on(message => sub { $log .= pop });
$t->get_ok('/longpoll/static')->status_is(200)->header_is(Server => 'Mojolicious (Perl)')
->header_like('Set-Cookie' => qr/bar=baz/)->header_like('Set-Cookie' => qr/mojolicious=/)
->content_type_is('text/plain;charset=UTF-8')->content_is("Hello Mojo from a static file!\n");
like $log, qr/Nothing has been rendered, expecting delayed response/, 'right message';
$t->app->log->unsubscribe(message => $cb);
};

subtest 'Custom response' => sub {
$t->get_ok('/longpoll/dynamic')->status_is(201)->header_is(Server => 'Mojolicious (Perl)')
->header_like('Set-Cookie' => qr/baz=yada/)->content_is('Dynamic!');
};

subtest 'Chunked response streaming with drain event' => sub {
my $stash = undef;
$t->app->plugins->once(before_dispatch => sub { $stash = shift->stash });
$t->get_ok('/stream')->status_is(200)->header_is(Server => 'Mojolicious (Perl)')->content_is('0123456789');
is $stash->{subscribers}, 0, 'no leaking subscribers';
ok $stash->{destroyed}, 'controller has been destroyed';
};

subtest 'Rendering of template' => sub {
my $stash = undef;
$t->app->plugins->once(before_dispatch => sub { $stash = shift->stash });
$t->get_ok('/render')->status_is(200)->header_is(Server => 'Mojolicious (Perl)')->content_is('Finish!');
Mojo::IOLoop->one_tick until $stash->{destroyed};
ok !$stash->{writing}, 'finish event timing is right';
ok $stash->{destroyed}, 'controller has been destroyed';
};

subtest 'Request timeout' => sub {
my $tx = $t->ua->request_timeout(0.5)->get('/too_long');
is $tx->error->{message}, 'Request timeout', 'right error';
$t->ua->request_timeout(0);
};

subtest 'Inactivity timeout' => sub {
my $tx = $t->ua->inactivity_timeout(0.5)->get('/too_long');
is $tx->error->{message}, 'Inactivity timeout', 'right error';
$t->ua->inactivity_timeout(20);
};

done_testing();

Expand Down

0 comments on commit 73f6fda

Please sign in to comment.