Group
Extension

Mojolicious/t/mojo/websocket_frames.t

use Mojo::Base -strict;

use Test::More;
use Mojo::Transaction::WebSocket;
use Mojo::WebSocket qw(WS_BINARY WS_CLOSE WS_CONTINUATION WS_PING WS_PONG WS_TEXT), qw(build_frame parse_frame);

# Simple text frame roundtrip
my $bytes = build_frame 0, 1, 0, 0, 0, WS_TEXT, 'whatever';
is $bytes, "\x81\x08\x77\x68\x61\x74\x65\x76\x65\x72", 'right frame';
my $frame = parse_frame \(my $dummy = $bytes), 262144;
is $frame->[0],                               1,          'fin flag is set';
is $frame->[1],                               0,          'rsv1 flag is not set';
is $frame->[2],                               0,          'rsv2 flag is not set';
is $frame->[3],                               0,          'rsv3 flag is not set';
is $frame->[4],                               1,          'text frame';
is $frame->[5],                               'whatever', 'right payload';
is build_frame(0, 1, 0, 0, 0, 1, 'whatever'), $bytes,     'frames are equal';

# Simple ping frame roundtrip
$bytes = build_frame 0, 1, 0, 0, 0, WS_PING, 'whatever';
is $bytes, "\x89\x08\x77\x68\x61\x74\x65\x76\x65\x72", 'right frame';
$frame = parse_frame \($dummy = $bytes), 262144;
is $frame->[0],                               1,          'fin flag is set';
is $frame->[1],                               0,          'rsv1 flag is not set';
is $frame->[2],                               0,          'rsv2 flag is not set';
is $frame->[3],                               0,          'rsv3 flag is not set';
is $frame->[4],                               9,          'ping frame';
is $frame->[5],                               'whatever', 'right payload';
is build_frame(0, 1, 0, 0, 0, 9, 'whatever'), $bytes,     'frames are equal';

# Simple pong frame roundtrip
$bytes = build_frame 0, 1, 0, 0, 0, WS_PONG, 'whatever';
is $bytes, "\x8a\x08\x77\x68\x61\x74\x65\x76\x65\x72", 'right frame';
$frame = parse_frame \($dummy = $bytes), 262144;
is $frame->[0],                                1,          'fin flag is set';
is $frame->[1],                                0,          'rsv1 flag is not set';
is $frame->[2],                                0,          'rsv2 flag is not set';
is $frame->[3],                                0,          'rsv3 flag is not set';
is $frame->[4],                                10,         'pong frame';
is $frame->[5],                                'whatever', 'right payload';
is build_frame(0, 1, 0, 0, 0, 10, 'whatever'), $bytes,     'frames are equal';

# Simple text frame roundtrip with all flags set
$bytes = build_frame 0, 1, 1, 1, 1, 1, 'whatever';
is $bytes, "\xf1\x08\x77\x68\x61\x74\x65\x76\x65\x72", 'right frame';
$frame = parse_frame \($dummy = $bytes), 262144;
is $frame->[0],                               1,          'fin flag is set';
is $frame->[1],                               1,          'rsv1 flag is set';
is $frame->[2],                               1,          'rsv2 flag is set';
is $frame->[3],                               1,          'rsv3 flag is set';
is $frame->[4],                               1,          'text frame';
is $frame->[5],                               'whatever', 'right payload';
is build_frame(0, 1, 1, 1, 1, 1, 'whatever'), $bytes,     'frames are equal';

# Simple text frame roundtrip without FIN bit
$bytes = build_frame 0, 0, 0, 0, 0, 1, 'whatever';
is $bytes, "\x01\x08\x77\x68\x61\x74\x65\x76\x65\x72", 'right frame';
$frame = parse_frame \($dummy = $bytes), 262144;
is $frame->[0],                               0,          'fin flag is not set';
is $frame->[1],                               0,          'rsv1 flag is not set';
is $frame->[2],                               0,          'rsv2 flag is not set';
is $frame->[3],                               0,          'rsv3 flag is not set';
is $frame->[4],                               1,          'text frame';
is $frame->[5],                               'whatever', 'right payload';
is build_frame(0, 0, 0, 0, 0, 1, 'whatever'), $bytes,     'frames are equal';

# Simple text frame roundtrip with RSV1 flags set
$bytes = build_frame(0, 1, 1, 0, 0, 1, 'whatever');
is $bytes, "\xc1\x08\x77\x68\x61\x74\x65\x76\x65\x72", 'right frame';
$frame = parse_frame \($dummy = $bytes), 262144;
is $frame->[0],                               1,          'fin flag is set';
is $frame->[1],                               1,          'rsv1 flag is set';
is $frame->[2],                               0,          'rsv2 flag is not set';
is $frame->[3],                               0,          'rsv3 flag is not set';
is $frame->[4],                               1,          'text frame';
is $frame->[5],                               'whatever', 'right payload';
is build_frame(0, 1, 1, 0, 0, 1, 'whatever'), $bytes,     'frames are equal';

# Simple continuation frame roundtrip with RSV2 flags set
$bytes = build_frame(0, 1, 0, 1, 0, WS_CONTINUATION, 'whatever');
is $bytes, "\xa0\x08\x77\x68\x61\x74\x65\x76\x65\x72", 'right frame';
$frame = parse_frame \($dummy = $bytes), 262144;
is $frame->[0],                               1,          'fin flag is set';
is $frame->[1],                               0,          'rsv1 flag is not set';
is $frame->[2],                               1,          'rsv2 flag is set';
is $frame->[3],                               0,          'rsv3 flag is not set';
is $frame->[4],                               0,          'continuation frame';
is $frame->[5],                               'whatever', 'right payload';
is build_frame(0, 1, 0, 1, 0, 0, 'whatever'), $bytes,     'frames are equal';

# Simple text frame roundtrip with RSV3 flags set
$bytes = build_frame(0, 1, 0, 0, 1, 1, 'whatever');
is $bytes, "\x91\x08\x77\x68\x61\x74\x65\x76\x65\x72", 'right frame';
$frame = parse_frame \($dummy = $bytes), 262144;
is $frame->[0],                               1,          'fin flag is set';
is $frame->[1],                               0,          'rsv1 flag is not set';
is $frame->[2],                               0,          'rsv2 flag is not set';
is $frame->[3],                               1,          'rsv3 flag is set';
is $frame->[4],                               1,          'text frame';
is $frame->[5],                               'whatever', 'right payload';
is build_frame(0, 1, 0, 0, 1, 1, 'whatever'), $bytes,     'frames are equal';

# Simple binary frame roundtrip
$bytes = build_frame(0, 1, 0, 0, 0, WS_BINARY, 'works');
is $bytes, "\x82\x05\x77\x6f\x72\x6b\x73", 'right frame';
$frame = parse_frame \($dummy = $bytes), 262144;
is $frame->[0],                                     1,       'fin flag is set';
is $frame->[1],                                     0,       'rsv1 flag is not set';
is $frame->[2],                                     0,       'rsv2 flag is not set';
is $frame->[3],                                     0,       'rsv3 flag is not set';
is $frame->[4],                                     2,       'binary frame';
is $frame->[5],                                     'works', 'right payload';
is $bytes = build_frame(0, 1, 0, 0, 0, 2, 'works'), $bytes,  'frames are equal';

# Masked text frame roundtrip
$bytes = build_frame 1, 1, 0, 0, 0, 1, 'also works';
$frame = parse_frame \($dummy = $bytes), 262144;
is $frame->[0], 1,            'fin flag is set';
is $frame->[1], 0,            'rsv1 flag is not set';
is $frame->[2], 0,            'rsv2 flag is not set';
is $frame->[3], 0,            'rsv3 flag is not set';
is $frame->[4], 1,            'text frame';
is $frame->[5], 'also works', 'right payload';
isnt(build_frame(0, 1, 0, 0, 0, 2, 'also works'), $bytes, 'frames are not equal');

# Masked binary frame roundtrip
$bytes = build_frame(1, 1, 0, 0, 0, 2, 'just works');
$frame = parse_frame \($dummy = $bytes), 262144;
is $frame->[0], 1,            'fin flag is set';
is $frame->[1], 0,            'rsv1 flag is not set';
is $frame->[2], 0,            'rsv2 flag is not set';
is $frame->[3], 0,            'rsv3 flag is not set';
is $frame->[4], 2,            'binary frame';
is $frame->[5], 'just works', 'right payload';
isnt(build_frame(0, 1, 0, 0, 0, 2, 'just works'), $bytes, 'frames are not equal');

# One-character text frame roundtrip
$bytes = build_frame(0, 1, 0, 0, 0, 1, 'a');
is $bytes, "\x81\x01\x61", 'right frame';
$frame = parse_frame \($dummy = $bytes), 262144;
is $frame->[0],                        1,      'fin flag is set';
is $frame->[1],                        0,      'rsv1 flag is not set';
is $frame->[2],                        0,      'rsv2 flag is not set';
is $frame->[3],                        0,      'rsv3 flag is not set';
is $frame->[4],                        1,      'text frame';
is $frame->[5],                        'a',    'right payload';
is build_frame(0, 1, 0, 0, 0, 1, 'a'), $bytes, 'frames are equal';

# One-byte binary frame roundtrip
$bytes = build_frame(0, 1, 0, 0, 0, 2, 'a');
is $bytes, "\x82\x01\x61", 'right frame';
$frame = parse_frame \($dummy = $bytes), 262144;
is $frame->[0],                                 1,      'fin flag is set';
is $frame->[1],                                 0,      'rsv1 flag is not set';
is $frame->[2],                                 0,      'rsv2 flag is not set';
is $frame->[3],                                 0,      'rsv3 flag is not set';
is $frame->[4],                                 2,      'binary frame';
is $frame->[5],                                 'a',    'right payload';
is $bytes = build_frame(0, 1, 0, 0, 0, 2, 'a'), $bytes, 'frames are equal';

# 16-bit text frame roundtrip
$bytes = build_frame(0, 1, 0, 0, 0, 1, 'hi' x 10000);
is $bytes, "\x81\x7e\x4e\x20" . ("\x68\x69" x 10000), 'right frame';
$frame = parse_frame \($dummy = $bytes), 262144;
is $frame->[0],                                 1,            'fin flag is set';
is $frame->[1],                                 0,            'rsv1 flag is not set';
is $frame->[2],                                 0,            'rsv2 flag is not set';
is $frame->[3],                                 0,            'rsv3 flag is not set';
is $frame->[4],                                 1,            'text frame';
is $frame->[5],                                 'hi' x 10000, 'right payload';
is build_frame(0, 1, 0, 0, 0, 1, 'hi' x 10000), $bytes,       'frames are equal';

# 64-bit text frame roundtrip
$bytes = build_frame(0, 1, 0, 0, 0, 1, 'hi' x 200000);
is $bytes, "\x81\x7f\x00\x00\x00\x00\x00\x06\x1a\x80" . ("\x68\x69" x 200000), 'right frame';
$frame = parse_frame \($dummy = $bytes), 500000;
is $frame->[0],                                  1,             'fin flag is set';
is $frame->[1],                                  0,             'rsv1 flag is not set';
is $frame->[2],                                  0,             'rsv2 flag is not set';
is $frame->[3],                                  0,             'rsv3 flag is not set';
is $frame->[4],                                  1,             'text frame';
is $frame->[5],                                  'hi' x 200000, 'right payload';
is build_frame(0, 1, 0, 0, 0, 1, 'hi' x 200000), $bytes,        'frames are equal';

# Empty text frame roundtrip
$bytes = build_frame(0, 1, 0, 0, 0, 1, '');
is $bytes, "\x81\x00", 'right frame';
$frame = parse_frame \($dummy = $bytes), 262144;
is $frame->[0],                       1,      'fin flag is set';
is $frame->[1],                       0,      'rsv1 flag is not set';
is $frame->[2],                       0,      'rsv2 flag is not set';
is $frame->[3],                       0,      'rsv3 flag is not set';
is $frame->[4],                       1,      'text frame';
is $frame->[5],                       '',     'no payload';
is build_frame(0, 1, 0, 0, 0, 1, ''), $bytes, 'frames are equal';

# Empty close frame roundtrip
$bytes = build_frame(0, 1, 0, 0, 0, WS_CLOSE, '');
is $bytes, "\x88\x00", 'right frame';
$frame = parse_frame \($dummy = $bytes), 262144;
is $frame->[0],                       1,      'fin flag is set';
is $frame->[1],                       0,      'rsv1 flag is not set';
is $frame->[2],                       0,      'rsv2 flag is not set';
is $frame->[3],                       0,      'rsv3 flag is not set';
is $frame->[4],                       8,      'close frame';
is $frame->[5],                       '',     'no payload';
is build_frame(0, 1, 0, 0, 0, 8, ''), $bytes, 'frames are equal';

# Masked empty binary frame roundtrip
$bytes = build_frame(1, 1, 0, 0, 0, 2, '');
$frame = parse_frame \($dummy = $bytes), 262144;
is $frame->[0], 1,  'fin flag is set';
is $frame->[1], 0,  'rsv1 flag is not set';
is $frame->[2], 0,  'rsv2 flag is not set';
is $frame->[3], 0,  'rsv3 flag is not set';
is $frame->[4], 2,  'binary frame';
is $frame->[5], '', 'no payload';
isnt(build_frame(0, 1, 0, 0, 0, 2, ''), $bytes, 'frames are not equal');

# Size limit
$bytes = build_frame(0, 1, 0, 0, 0, WS_BINARY, 'works');
is $bytes, "\x82\x05\x77\x6f\x72\x6b\x73", 'right frame';
$frame = parse_frame \($dummy = $bytes), 4;
ok $frame,      'true';
ok !ref $frame, 'not a reference';

# Incomplete frame
is parse_frame(\($dummy = "\x82\x05\x77\x6f\x72\x6b"), 262144), undef, 'incomplete frame';

# Fragmented message
my $fragmented = Mojo::Transaction::WebSocket->new;
my $text;
$fragmented->on(text => sub { $text = pop });
$fragmented->parse_message([0, 0, 0, 0, WS_TEXT, 'wo']);
ok !$text, 'text event has not been emitted yet';
$fragmented->parse_message([0, 0, 0, 0, WS_CONTINUATION, 'r']);
ok !$text, 'text event has not been emitted yet';
$fragmented->parse_message([1, 0, 0, 0, WS_CONTINUATION, 'ks!']);
is $text, 'works!', 'right payload';

# Compressed binary message
my $compressed = Mojo::Transaction::WebSocket->new({compressed => 1});
$frame = $compressed->build_message({binary => 'just works'});
is $frame->[0], 1,         'fin flag is set';
is $frame->[1], 1,         'rsv1 flag is set';
is $frame->[2], 0,         'rsv2 flag is not set';
is $frame->[3], 0,         'rsv3 flag is not set';
is $frame->[4], WS_BINARY, 'binary frame';
ok $frame->[5], 'has payload';
my $payload = $compressed->build_message({binary => 'just works'})->[5];
isnt $frame->[5], $payload, 'different payload';
ok length $frame->[5] > length $payload, 'payload is smaller';
my $uncompressed = Mojo::Transaction::WebSocket->new;
my $frame2       = $uncompressed->build_message({binary => 'just works'});
is $frame2->[0], 1,         'fin flag is set';
is $frame2->[1], 0,         'rsv1 flag is not set';
is $frame2->[2], 0,         'rsv2 flag is not set';
is $frame2->[3], 0,         'rsv3 flag is not set';
is $frame2->[4], WS_BINARY, 'binary frame';
ok $frame2->[5], 'has payload';
isnt $frame->[5], $frame2->[5],                                                'different payload';
is $frame2->[5],  $uncompressed->build_message({binary => 'just works'})->[5], 'same payload';

# Compressed fragmented message
my $fragmented_compressed = Mojo::Transaction::WebSocket->new({compressed => 1});
$text = undef;
$fragmented_compressed->on(message => sub { $text = pop });
my $compressed_payload = $fragmented_compressed->build_message({text => 'just works'})->[5];
ok !$text, 'message event has not been emitted yet';
$fragmented_compressed->parse_message([0, 1, 0, 0, WS_TEXT, substr($compressed_payload, 0, 3)]);
ok !$text, 'message event has not been emitted yet';
$fragmented_compressed->parse_message([0, 0, 0, 0, WS_CONTINUATION, substr($compressed_payload, 3, 3)]);
ok !$text, 'message event has not been emitted yet';
$fragmented_compressed->parse_message([1, 0, 0, 0, WS_CONTINUATION, substr($compressed_payload, 6)]);
is $text, 'just works', 'decoded correctly';

done_testing();


Powered by Groonga
Maintained by Kenichi Ishigaki <ishigaki@cpan.org>. If you find anything, submit it on GitHub.