PAGI-Tools
view release on metacpan or search on metacpan
t/request-body-stream.t view on Meta::CPAN
use strict;
use warnings;
use Test2::V0;
use Future::AsyncAwait;
use File::Temp qw(tempfile);
use PAGI::Request::BodyStream;
# Mock receive function
sub mock_receive {
my @chunks = @_;
my $i = 0;
return sub {
my $chunk = $chunks[$i++];
return Future->done($chunk);
};
}
subtest 'basic streaming' => sub {
my $receive = mock_receive(
{ type => 'http.request', body => 'Hello', more => 1 },
{ type => 'http.request', body => ' World', more => 0 },
);
my $stream = PAGI::Request::BodyStream->new(receive => $receive);
my $chunk1 = $stream->next_chunk->get;
is $chunk1, 'Hello', 'first chunk';
ok !$stream->is_done, 'not done yet';
my $chunk2 = $stream->next_chunk->get;
is $chunk2, ' World', 'second chunk';
ok $stream->is_done, 'done after last chunk';
is $stream->bytes_read, 11, 'bytes_read correct';
};
subtest 'max_bytes limit' => sub {
my $receive = mock_receive(
{ type => 'http.request', body => 'Hello World', more => 0 },
);
my $stream = PAGI::Request::BodyStream->new(
receive => $receive,
max_bytes => 5,
);
like dies { $stream->next_chunk->get }, qr/max_bytes exceeded/, 'throws on limit exceeded';
};
subtest 'UTF-8 decoding' => sub {
my $receive = mock_receive(
{ type => 'http.request', body => "caf\xc3\xa9", more => 0 },
);
my $stream = PAGI::Request::BodyStream->new(
receive => $receive,
decode => 'UTF-8',
);
my $chunk = $stream->next_chunk->get;
is $chunk, "café", 'UTF-8 decoded';
};
subtest 'disconnect handling' => sub {
my $receive = mock_receive(
{ type => 'http.request', body => 'Hello', more => 1 },
{ type => 'http.disconnect' },
);
my $stream = PAGI::Request::BodyStream->new(receive => $receive);
my $chunk1 = $stream->next_chunk->get;
is $chunk1, 'Hello', 'first chunk';
my $chunk2 = $stream->next_chunk->get;
is $chunk2, undef, 'undef on disconnect';
ok $stream->is_done, 'done after disconnect';
};
t/request-body-stream.t view on Meta::CPAN
subtest 'bytes_read tracking' => sub {
my $receive = mock_receive(
{ type => 'http.request', body => '12345', more => 1 },
{ type => 'http.request', body => '67890', more => 0 },
);
my $stream = PAGI::Request::BodyStream->new(receive => $receive);
is $stream->bytes_read, 0, 'zero before reading';
$stream->next_chunk->get;
is $stream->bytes_read, 5, 'five after first chunk';
$stream->next_chunk->get;
is $stream->bytes_read, 10, 'ten after second chunk';
};
subtest 'stream_to_file rejects decode option' => sub {
my $receive = mock_receive(
{ type => 'http.request', body => 'test', more => 0 },
);
my $stream = PAGI::Request::BodyStream->new(
receive => $receive,
decode => 'UTF-8',
);
like dies { $stream->stream_to_file('/tmp/test.bin')->get },
qr/cannot be used with decode/,
'stream_to_file throws with decode option';
};
subtest 'PAGI::Request body_stream' => sub {
use PAGI::Request;
my $chunks = [
{ type => 'http.request', body => 'Hello', more => 1 },
{ type => 'http.request', body => ' World', more => 0 },
];
my $i = 0;
my $receive = sub { Future->done($chunks->[$i++]) };
my $scope = { method => 'POST', path => '/', headers => [] };
my $req = PAGI::Request->new($scope, $receive);
my $stream = $req->body_stream;
isa_ok $stream, 'PAGI::Request::BodyStream';
my $chunk1 = $stream->next_chunk->get;
is $chunk1, 'Hello', 'first chunk via Request';
};
subtest 'body_stream mutual exclusivity' => sub {
use PAGI::Request;
# Streaming then buffered should fail
my $scope1 = { method => 'POST', path => '/', headers => [] };
my $receive1 = sub { Future->done({ type => 'http.request', body => 'test', more => 0 }) };
my $req1 = PAGI::Request->new($scope1, $receive1);
$req1->body_stream;
like dies { $req1->body->get }, qr/streaming/, 'body after stream fails';
# Buffered then streaming should fail
my $scope2 = { method => 'POST', path => '/', headers => [] };
my $receive2 = sub { Future->done({ type => 'http.request', body => 'x', more => 0 }) };
my $req2 = PAGI::Request->new($scope2, $receive2);
$req2->body->get;
like dies { $req2->body_stream }, qr/consumed|read/, 'stream after body fails';
};
done_testing;
( run in 1.042 second using v1.01-cache-2.11-cpan-6aa56a78535 )