API-Docker
view release on metacpan or search on metacpan
t/transport_shape.t view on Meta::CPAN
# karr k30 -- a bare JSON scalar is a JSON value like any other
# ===========================================================================
subtest 'a body that is a JSON scalar is decoded, not returned as bytes' => sub {
is fake_client('null')->get('/x'), undef,
'null decodes to undef, not to the string "null"';
my $true = fake_client('true')->get('/x');
ok $true, 'true is true';
is "$true", '1', 'and is the JSON boolean, which stringifies to 1';
my $false = fake_client('false')->get('/x');
ok defined $false, 'false is a value, not an absence';
ok !$false, 'and it is false';
is fake_client('42')->get('/x'), 42, 'a bare number';
is fake_client('-1.5')->get('/x'), -1.5, 'a negative one';
is fake_client('"hello"')->get('/x'), 'hello',
'a quoted string, without its quotes';
is fake_client(qq{ null\n})->get('/x'), undef,
'leading whitespace and a trailing newline do not stop it';
};
subtest 'the two endpoints that send a bare null' => sub {
# computePrivileges starts from a `var privileges types.PluginPrivileges`
# and appends only what the plugin config asks for, so a plugin needing
# nothing marshals a nil Go slice. GET /containers/{id}/changes does the
# same for a container that changed nothing. Both are documented as
# returning an ArrayRef, and both used to hand over 'null' instead -- which
# /plugins/pull would then have been POSTed as a JSON string where the
# engine expects an array.
is fake_client('null')->get('/plugins/privileges', params => { remote => 'x' }),
undef, 'GET /plugins/privileges: null is undef, which is not iterable-looking';
is fake_client('null')->get('/containers/deadbeef/changes'), undef,
'GET /containers/{id}/changes: the same';
};
subtest 'a body that is not JSON is still returned as itself' => sub {
# GET /_ping answers with the two bytes OK and no JSON anywhere.
is fake_client('OK')->get('/_ping'), 'OK', 'the ping body survives';
# The eval decides, not the pattern: these start with a character the
# pattern lets through and are not JSON.
is fake_client('null pointer dereference')->get('/x'),
'null pointer dereference', 'a sentence starting with null';
is fake_client('42 things happened')->get('/x'), '42 things happened',
'a sentence starting with a digit';
is fake_client('{not json')->get('/x'), '{not json',
'and a body that only looks like an object';
};
subtest 'raw is still bytes, whatever they spell' => sub {
is fake_client('null')->get('/x', raw => 1), 'null',
'raw => 1 hands back the four characters, decoding nothing';
};
# ===========================================================================
# karr k33 -- an ArrayRef param is the same parameter given more than once
# ===========================================================================
subtest 'an ArrayRef param expands to repeated pairs' => sub {
my $c = fake_client('');
$c->get('/images/get', params => { names => ['alpine:3', 'registry:2'] });
is $c->request_line,
'GET /v1.41/images/get?names=alpine:3&names=registry:2 HTTP/1.1',
'one names= pair per element, and the reference colon is left raw';
};
subtest 'element order is the caller\'s, key order is sorted' => sub {
my $c = fake_client('');
$c->get('/x', params => { z => 1, names => ['b', 'a'], a => 2 });
is $c->request_line, 'GET /v1.41/x?a=2&names=b&names=a&z=1 HTTP/1.1',
'keys sorted, but b still precedes a inside the list';
};
subtest 'the elements are escaped the way a single value is' => sub {
my $c = fake_client('');
$c->get('/images/get', params => { names => ['my repo/img:1', 'a&b=c'] });
is $c->request_line,
'GET /v1.41/images/get?names=my%20repo/img:1&names=a%26b%3Dc HTTP/1.1',
'a space, an ampersand and an equals sign are encoded; / and : are not';
};
subtest 'the empty and undef corners of a list' => sub {
my $c = fake_client('');
$c->get('/images/get', params => { names => [] });
is $c->request_line, 'GET /v1.41/images/get HTTP/1.1',
'an empty ArrayRef appends no query string at all, not a bare ?';
$c = fake_client('');
$c->get('/x', params => { names => ['a', undef, 'b'] });
is $c->request_line, 'GET /v1.41/x?names=a&names=b HTTP/1.1',
'an undef element is skipped, like an undef value is';
};
subtest 'a scalar and a HashRef param are unchanged' => sub {
my $c = fake_client('');
$c->get('/containers/json', params => { all => 1, filters => { status => ['running'] } });
is $c->request_line,
'GET /v1.41/containers/json?all=1&filters=%7B%22status%22:%5B%22running%22%5D%7D HTTP/1.1',
'a scalar stays one pair and a HashRef is still JSON-encoded; the colon in the JSON is left raw, like every other colon';
$c = fake_client('');
$c->get('/x', params => { f => [ { a => 1 }, { b => 2 } ] });
my ($qs) = $c->request_line =~ /\?(\S+) HTTP/;
my @encoded = map { my ($v) = /^f=(.*)$/; $v =~ s/%([0-9A-Fa-f]{2})/chr hex $1/ge; $v }
split /&/, $qs;
is_deeply [ map { decode_json($_) } @encoded ], [ { a => 1 }, { b => 2 } ],
'a HashRef inside a list is JSON-encoded per element, same rule';
};
# ===========================================================================
# karr k34 -- zero bytes is a different answer in each shape
# ===========================================================================
subtest 'an empty body keeps the shape the caller asked for' => sub {
my $raw = fake_client('')->get('/images/get', raw => 1);
( run in 3.328 seconds using v1.01-cache-2.11-cpan-302cb4679cc )