Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

convert t/mojolicious/longpolling_lite_app.t to use subtests #1683

Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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