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 )