Amazon-S3-Lite
view release on metacpan or search on metacpan
t/01-s3-lite.t view on Meta::CPAN
# success
local *Amazon::S3::Lite::_request = mock_request(
headers => {
'content-type' => 'text/plain',
'content-length' => '42',
'etag' => '"abc123"',
'last-modified' => 'Wed, 01 Jan 2025 00:00:00 GMT',
'x-amz-meta-source' => 'lambda',
},
);
my $r = $s3->head_object( 'test-bucket', 'hello.txt' );
is $r->{content_type}, 'text/plain', 'content_type';
is $r->{content_length}, 42, 'content_length is integer';
is $r->{etag}, 'abc123', 'etag stripped of quotes';
ok !exists $r->{content}, 'no content key for HEAD';
is $r->{metadata}{source}, 'lambda', 'x-amz-meta stripped to bare key';
# missing args
eval { $s3->head_object() };
like $@, qr/bucket is required/, 'croaks without bucket';
eval { $s3->head_object('b') };
like $@, qr/key is required/, 'croaks without key';
};
subtest 'get_object' => sub {
my $s3 = new_s3();
no warnings 'redefine';
# 404 returns undef
local *Amazon::S3::Lite::_request = mock_request( status => 404 );
ok !defined $s3->get_object( 'b', 'k' ), '404 returns undef';
# in-memory success
local *Amazon::S3::Lite::_request = mock_request(
content => 'hello world',
headers => {
'content-type' => 'text/plain',
'content-length' => '11',
'etag' => '"abc123"',
'last-modified' => 'Wed, 01 Jan 2025 00:00:00 GMT',
},
);
my $r = $s3->get_object( 'test-bucket', 'hello.txt' );
is $r->{content}, 'hello world', 'content returned';
is $r->{content_type}, 'text/plain', 'content_type';
is $r->{etag}, 'abc123', 'etag clean';
# range header passed through
my $captured = {};
local *Amazon::S3::Lite::_request = mock_request(
status => 206,
content => 'hello',
headers => { 'content-type' => 'text/plain', 'content-length' => '5', 'etag' => '"abc"' },
capture => \$captured,
);
$s3->get_object( 'test-bucket', 'hello.txt', range => 'bytes=0-4' );
is $captured->{headers}{Range}, 'bytes=0-4', 'Range header set';
# filename â streaming to disk
{
my ( $fh, $fname ) = tempfile( UNLINK => 1 );
close $fh;
local *Amazon::S3::Lite::_request = sub {
my ( $self, $method, $url, $headers, $content, $extra ) = @_;
$extra->{data_callback}->('hello ') if $extra->{data_callback};
$extra->{data_callback}->('world') if $extra->{data_callback};
return {
status => 200,
reason => 'OK',
headers => { 'content-type' => 'text/plain', 'content-length' => '11', 'etag' => '"abc"' },
content => '',
};
};
my $meta = $s3->get_object( 'test-bucket', 'hello.txt', filename => $fname );
ok !exists $meta->{content}, 'no content key when filename used';
ok -f $fname, 'file created';
open my $in, '<', $fname or die $!;
is do { local $/; <$in> }, 'hello world', 'file content correct';
}
};
subtest 'put_object' => sub {
my $s3 = new_s3();
my $captured = {};
no warnings 'redefine';
# scalar
local *Amazon::S3::Lite::_request = mock_request(
headers => { etag => '"newetag"' },
capture => \$captured,
);
my $etag = $s3->put_object(
'test-bucket', 'hello.txt', 'hello world',
content_type => 'text/plain',
metadata => { source => 'test' },
);
is $etag, 'newetag', 'returns clean etag';
is $captured->{headers}{'Content-Type'}, 'text/plain', 'Content-Type set';
is $captured->{headers}{'Content-Length'}, 11, 'Content-Length set';
is $captured->{headers}{'x-amz-meta-source'}, 'test', 'metadata prefixed';
ok defined $captured->{headers}{'Content-MD5'}, 'Content-MD5 set for scalar';
# scalar ref
local *Amazon::S3::Lite::_request = mock_request(
headers => { etag => '"x"' },
capture => \$captured,
);
my $data = 'from scalar ref';
$s3->put_object( 'test-bucket', 'k', \$data );
is $captured->{body}, $data, 'scalar ref dereferenced';
# real filehandle
{
my ( $fh, $fname ) = tempfile( UNLINK => 1 );
print $fh 'file content';
close $fh;
( run in 1.960 second using v1.01-cache-2.11-cpan-140bd7fdf52 )