From 58daab21cd043e1dc37024a7f99b396788372918 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sat, 9 Mar 2024 14:19:48 +0100 Subject: Merging upstream version 1.44.3. Signed-off-by: Daniel Baumann --- .../h2o/libh2o/misc/p5-net-fastcgi/t/000_load.t | 29 ++++ .../p5-net-fastcgi/t/020_protocol/001_header.t | 51 ++++++ .../t/020_protocol/005_record_length.t | 44 +++++ .../t/020_protocol/010_build_record.t | 44 +++++ .../t/020_protocol/015_build_stream.t | 82 ++++++++++ .../t/020_protocol/020_begin_request_body.t | 41 +++++ .../t/020_protocol/025_begin_request_record.t | 30 ++++ .../t/020_protocol/027_begin_request.t | 97 +++++++++++ .../t/020_protocol/030_end_request_body.t | 42 +++++ .../t/020_protocol/035_end_request_record.t | 30 ++++ .../t/020_protocol/037_end_request.t | 87 ++++++++++ .../t/020_protocol/040_unknown_type_body.t | 42 +++++ .../t/020_protocol/045_unknown_type_record.t | 30 ++++ .../t/020_protocol/050_parse_record.t | 180 +++++++++++++++++++++ .../t/020_protocol/055_parse_record_body.t | 98 +++++++++++ .../p5-net-fastcgi/t/020_protocol/060_params.t | 79 +++++++++ .../t/020_protocol/065_record_type.t | 105 ++++++++++++ .../misc/p5-net-fastcgi/t/020_protocol/070_names.t | 80 +++++++++ .../t/020_protocol/080_dump_record.t | 51 ++++++ .../t/020_protocol/085_dump_record_body.t | 150 +++++++++++++++++ .../libh2o/misc/p5-net-fastcgi/t/lib/myconfig.pm | 9 ++ 21 files changed, 1401 insertions(+) create mode 100644 web/server/h2o/libh2o/misc/p5-net-fastcgi/t/000_load.t create mode 100644 web/server/h2o/libh2o/misc/p5-net-fastcgi/t/020_protocol/001_header.t create mode 100644 web/server/h2o/libh2o/misc/p5-net-fastcgi/t/020_protocol/005_record_length.t create mode 100644 web/server/h2o/libh2o/misc/p5-net-fastcgi/t/020_protocol/010_build_record.t create mode 100644 web/server/h2o/libh2o/misc/p5-net-fastcgi/t/020_protocol/015_build_stream.t create mode 100644 web/server/h2o/libh2o/misc/p5-net-fastcgi/t/020_protocol/020_begin_request_body.t create mode 100644 web/server/h2o/libh2o/misc/p5-net-fastcgi/t/020_protocol/025_begin_request_record.t create mode 100644 web/server/h2o/libh2o/misc/p5-net-fastcgi/t/020_protocol/027_begin_request.t create mode 100644 web/server/h2o/libh2o/misc/p5-net-fastcgi/t/020_protocol/030_end_request_body.t create mode 100644 web/server/h2o/libh2o/misc/p5-net-fastcgi/t/020_protocol/035_end_request_record.t create mode 100644 web/server/h2o/libh2o/misc/p5-net-fastcgi/t/020_protocol/037_end_request.t create mode 100644 web/server/h2o/libh2o/misc/p5-net-fastcgi/t/020_protocol/040_unknown_type_body.t create mode 100644 web/server/h2o/libh2o/misc/p5-net-fastcgi/t/020_protocol/045_unknown_type_record.t create mode 100644 web/server/h2o/libh2o/misc/p5-net-fastcgi/t/020_protocol/050_parse_record.t create mode 100644 web/server/h2o/libh2o/misc/p5-net-fastcgi/t/020_protocol/055_parse_record_body.t create mode 100644 web/server/h2o/libh2o/misc/p5-net-fastcgi/t/020_protocol/060_params.t create mode 100644 web/server/h2o/libh2o/misc/p5-net-fastcgi/t/020_protocol/065_record_type.t create mode 100644 web/server/h2o/libh2o/misc/p5-net-fastcgi/t/020_protocol/070_names.t create mode 100644 web/server/h2o/libh2o/misc/p5-net-fastcgi/t/020_protocol/080_dump_record.t create mode 100644 web/server/h2o/libh2o/misc/p5-net-fastcgi/t/020_protocol/085_dump_record_body.t create mode 100644 web/server/h2o/libh2o/misc/p5-net-fastcgi/t/lib/myconfig.pm (limited to 'web/server/h2o/libh2o/misc/p5-net-fastcgi/t') diff --git a/web/server/h2o/libh2o/misc/p5-net-fastcgi/t/000_load.t b/web/server/h2o/libh2o/misc/p5-net-fastcgi/t/000_load.t new file mode 100644 index 000000000..1436a558b --- /dev/null +++ b/web/server/h2o/libh2o/misc/p5-net-fastcgi/t/000_load.t @@ -0,0 +1,29 @@ +#!perl + +use strict; +use warnings; + +use lib 't/lib', 'lib'; +use myconfig; + +use Test::More tests => 5; + +BEGIN { + use_ok('Net::FastCGI'); + use_ok('Net::FastCGI::Constant'); + use_ok('Net::FastCGI::IO'); + use_ok('Net::FastCGI::Protocol'); + + if ( $ENV{NET_FASTCGI_PP} ) { + use_ok('Net::FastCGI::Protocol::PP'); + } + else { + use_ok('Net::FastCGI::Protocol::XS'); + } +} + +diag("Net::FastCGI $Net::FastCGI::VERSION, Perl $], $^X"); +diag("NET_FASTCGI_PP=$ENV{NET_FASTCGI_PP}"); + + + diff --git a/web/server/h2o/libh2o/misc/p5-net-fastcgi/t/020_protocol/001_header.t b/web/server/h2o/libh2o/misc/p5-net-fastcgi/t/020_protocol/001_header.t new file mode 100644 index 000000000..8e1476b5e --- /dev/null +++ b/web/server/h2o/libh2o/misc/p5-net-fastcgi/t/020_protocol/001_header.t @@ -0,0 +1,51 @@ +#!perl + +use strict; +use warnings; + +use lib 't/lib', 'lib'; +use myconfig; + +use Test::More tests => 13; +use Test::HexString; +use Test::Exception; + +BEGIN { + use_ok('Net::FastCGI::Protocol', qw[ build_header + parse_header ]); +} + +my @tests = ( + # octets type request_id content_length padding_length + ["\x01\x00\x00\x00\x00\x00\x00\x00", 0, 0, 0, 0 ], + ["\x01\xFF\xFF\xFF\xFF\xFF\xFF\x00", 0xFF, 0xFFFF, 0xFFFF, 0xFF ], +); + +foreach my $test (@tests) { + my $expected = $test->[0]; + my $got = build_header(@$test[1..4]); + is_hexstr($got, $expected, 'build_header()'); +} + +foreach my $test (@tests) { + my @expected = @$test[1..4]; + my @got = parse_header($test->[0]); + is_deeply(\@got, \@expected, "parse_header() in list context"); +} + +my @components = qw(type request_id content_length padding_length); +foreach my $test (@tests) { + my $expected; @$expected{@components} = @$test[1..4]; + my $got = parse_header($test->[0]); + is_deeply($got, $expected, "parse_header() in scalar context"); +} + + +throws_ok { parse_header("") } qr/FastCGI: Insufficient .* FCGI_Header/; +throws_ok { parse_header(undef) } qr/FastCGI: Insufficient .* FCGI_Header/; +throws_ok { parse_header("\x00\x00\x00\x00\x00\x00\x00\x00") } qr/^FastCGI: Protocol version mismatch/; +throws_ok { parse_header("\xFF\x00\x00\x00\x00\x00\x00\x00") } qr/^FastCGI: Protocol version mismatch/; + +throws_ok { build_header() } qr/^Usage: /; +throws_ok { parse_header() } qr/^Usage: /; + diff --git a/web/server/h2o/libh2o/misc/p5-net-fastcgi/t/020_protocol/005_record_length.t b/web/server/h2o/libh2o/misc/p5-net-fastcgi/t/020_protocol/005_record_length.t new file mode 100644 index 000000000..1d2381980 --- /dev/null +++ b/web/server/h2o/libh2o/misc/p5-net-fastcgi/t/020_protocol/005_record_length.t @@ -0,0 +1,44 @@ +#!perl + +use strict; +use warnings; + +use lib 't/lib', 'lib'; +use myconfig; + +use Test::More tests => 18; +use Test::Exception; + +BEGIN { + use_ok('Net::FastCGI::Constant', qw[:all]); + use_ok('Net::FastCGI::Protocol', qw[ build_header + build_record + get_record_length ]); +} + + +is get_record_length(undef), 0, 'get_record_length(undef)'; + +{ + for my $len (0..7) { + is get_record_length("\x00" x $len), 0, qq; + } +} + +{ + for my $len (8, 16, 32, 64) { + my $record = build_record(0, 0, "\x00" x $len); + is get_record_length($record), FCGI_HEADER_LEN + $len; + } +} + +{ + my $header = build_header(0, 0, 8192, 250); + is get_record_length($header), FCGI_HEADER_LEN + 8192 + 250; +} + +# get_record_length(octets) +for (0, 2) { + throws_ok { get_record_length((1) x $_) } qr/^Usage: /; +} + diff --git a/web/server/h2o/libh2o/misc/p5-net-fastcgi/t/020_protocol/010_build_record.t b/web/server/h2o/libh2o/misc/p5-net-fastcgi/t/020_protocol/010_build_record.t new file mode 100644 index 000000000..9f321261c --- /dev/null +++ b/web/server/h2o/libh2o/misc/p5-net-fastcgi/t/020_protocol/010_build_record.t @@ -0,0 +1,44 @@ +#!perl + +use strict; +use warnings; + +use lib 't/lib', 'lib'; +use myconfig; + +use Test::More tests => 11; +use Test::HexString; +use Test::Exception; + +BEGIN { + use_ok('Net::FastCGI::Protocol', qw[ build_record ]); +} + +my @tests = ( + # octets type request_id content + [ "\x01\x00\x00\x00\x00\x00\x00\x00", 0, 0, undef ], + [ "\x01\xFF\xFF\xFF\x00\x00\x00\x00", 0xFF, 0xFFFF, undef ], + [ "\x01\x01\x00\x01\x00\x01\x07\x00\x01\x00\x00\x00\x00\x00\x00\x00", 1, 1, "\x01" ], + [ "\x01\x01\x00\x01\x00\x05\x03\x00\x01\x01\x01\x01\x01\x00\x00\x00", 1, 1, "\x01\x01\x01\x01\x01" ], + [ "\x01\x01\x00\x01\x00\x08\x00\x00\x01\x01\x01\x01\x01\x01\x01\x01", 1, 1, "\x01\x01\x01\x01\x01\x01\x01\x01" ], +); + +foreach my $test (@tests) { + my $expected = $test->[0]; + my $got = build_record(@$test[1..3]); + is_hexstr($got, $expected, 'build_record()'); +} + +{ + my $exp = "\x01\x01\x00\x02\x00\x00\x00\x00"; + my $got = build_record(1, 2); + is_hexstr($got, $exp, 'build_record(1, 2)'); +} + +throws_ok { build_record( 0, 0, "\x00" x (0xFFFF + 1) ) } qr/^Invalid Argument: 'content' cannot exceed/; + +# build_record(type, request_id [, content]) +for (0..1, 4) { + throws_ok { build_record((1) x $_) } qr/^Usage: /; +} + diff --git a/web/server/h2o/libh2o/misc/p5-net-fastcgi/t/020_protocol/015_build_stream.t b/web/server/h2o/libh2o/misc/p5-net-fastcgi/t/020_protocol/015_build_stream.t new file mode 100644 index 000000000..233f225fd --- /dev/null +++ b/web/server/h2o/libh2o/misc/p5-net-fastcgi/t/020_protocol/015_build_stream.t @@ -0,0 +1,82 @@ +#!perl + +use strict; +use warnings; + +use lib 't/lib', 'lib'; +use myconfig; + +use Test::More tests => 12; +use Test::HexString; +use Test::Exception; + +BEGIN { + use_ok('Net::FastCGI::Protocol', qw[ build_stream ]); +} + +sub TRUE () { !!1 } +sub FALSE () { !!0 } + +my @tests = ( + # expected, type, request_id, content, terminate + [ "", 1, 1, '', FALSE ], + [ "", 1, 1, undef, FALSE ], + [ "\x01\x01\x00\x01\x00\x00\x00\x00", 1, 1, '', TRUE ], + [ "\x01\x01\x00\x01\x00\x00\x00\x00", 1, 1, undef, TRUE ], + + [ "\x01\x01\x00\x01\x00\x03\x05\x00" + . "FOO\x00\x00\x00\x00\x00", 1, 1, 'FOO', FALSE ], + + [ "\x01\x01\x00\x01\x00\x03\x05\x00" + . "FOO\x00\x00\x00\x00\x00" + . "\x01\x01\x00\x01\x00\x00\x00\x00", 1, 1, 'FOO', TRUE ], +); + +foreach my $test (@tests) { + my $expected = $test->[0]; + my $got = build_stream(@$test[1..4]); + is_hexstr($got, $expected, 'build_stream()'); +} + +{ + my $header = "\x01\x01\x00\x01\x7F\xF8\x00\x00"; + my $content = "x" x 32760; + my $trailer = "\x01\x01\x00\x01\x00\x00\x00\x00"; + + { + my $expected = $header . $content; + my $got = build_stream(1,1, $content); + is_hexstr($got, $expected, 'build_stream(content_length: 32760 terminate:false)'); + } + + { + my $expected = $header . $content . $trailer; + my $got = build_stream(1,1, $content, 1); + is_hexstr($got, $expected, 'build_stream(content_length: 32760 terminate:true)'); + } +} + +{ + my $records = "\x01\x01\x00\x01\x7F\xF8\x00\x00" # H1 + . "x" x 32760 # C1 + . "\x01\x01\x00\x01\x00\x08\x00\x00" # H2 + . "x" x 8 # C2 + ; + my $content = "x" x 32768; + my $trailer = "\x01\x01\x00\x01\x00\x00\x00\x00"; + + { + my $expected = $records; + my $got = build_stream(1,1, $content); + is_hexstr($got, $records, 'build_stream(content_length: 32768 terminate:false)'); + } + + { + my $expected = $records . $trailer; + my $got = build_stream(1,1, $content, 1); + is_hexstr($got, $expected, 'build_stream(content_length: 32768 terminate:true)'); + } +} + +throws_ok { build_stream() } qr/^Usage: /; + diff --git a/web/server/h2o/libh2o/misc/p5-net-fastcgi/t/020_protocol/020_begin_request_body.t b/web/server/h2o/libh2o/misc/p5-net-fastcgi/t/020_protocol/020_begin_request_body.t new file mode 100644 index 000000000..031a7d173 --- /dev/null +++ b/web/server/h2o/libh2o/misc/p5-net-fastcgi/t/020_protocol/020_begin_request_body.t @@ -0,0 +1,41 @@ +#!perl + +use strict; +use warnings; + +use lib 't/lib', 'lib'; +use myconfig; + +use Test::More tests => 9; +use Test::HexString; +use Test::Exception; + +BEGIN { + use_ok('Net::FastCGI::Protocol', qw[ build_begin_request_body + parse_begin_request_body ]); +} + +my @tests = ( + # octets role flags + [ "\x00\x00\x00\x00\x00\x00\x00\x00", 0, 0 ], + [ "\xFF\xFF\xFF\x00\x00\x00\x00\x00", 0xFFFF, 0xFF ], +); + +foreach my $test (@tests) { + my $expected = $test->[0]; + my $got = build_begin_request_body(@$test[1..2]); + is_hexstr($got, $expected, 'build_begin_request_body()'); +} + +foreach my $test (@tests) { + my @expected = @$test[1..2]; + my @got = parse_begin_request_body($test->[0]); + is_deeply(\@got, \@expected, "parse_begin_request_body()"); +} + +throws_ok { parse_begin_request_body("") } qr/^FastCGI: Insufficient .* FCGI_BeginRequestBody/; +throws_ok { parse_begin_request_body(undef) } qr/^FastCGI: Insufficient .* FCGI_BeginRequestBody/; + +throws_ok { build_begin_request_body() } qr/^Usage: /; +throws_ok { parse_begin_request_body() } qr/^Usage: /; + diff --git a/web/server/h2o/libh2o/misc/p5-net-fastcgi/t/020_protocol/025_begin_request_record.t b/web/server/h2o/libh2o/misc/p5-net-fastcgi/t/020_protocol/025_begin_request_record.t new file mode 100644 index 000000000..50f944321 --- /dev/null +++ b/web/server/h2o/libh2o/misc/p5-net-fastcgi/t/020_protocol/025_begin_request_record.t @@ -0,0 +1,30 @@ +#!perl + +use strict; +use warnings; + +use lib 't/lib', 'lib'; +use myconfig; + +use Test::More tests => 4; +use Test::HexString; +use Test::Exception; + +BEGIN { + use_ok('Net::FastCGI::Protocol', qw[ build_begin_request_record ]); +} + +my @tests = ( + # octets request_id role flags + [ "\x01\x01\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 0, 0, 0 ], + [ "\x01\x01\xFF\xFF\x00\x08\x00\x00\xFF\xFF\xFF\x00\x00\x00\x00\x00", 0xFFFF, 0xFFFF, 0xFF ], +); + +foreach my $test (@tests) { + my $expected = $test->[0]; + my $got = build_begin_request_record(@$test[1..3]); + is_hexstr($got, $expected, 'build_begin_request_record()'); +} + +throws_ok { build_begin_request_record() } qr/^Usage: /; + diff --git a/web/server/h2o/libh2o/misc/p5-net-fastcgi/t/020_protocol/027_begin_request.t b/web/server/h2o/libh2o/misc/p5-net-fastcgi/t/020_protocol/027_begin_request.t new file mode 100644 index 000000000..e5d6c91f6 --- /dev/null +++ b/web/server/h2o/libh2o/misc/p5-net-fastcgi/t/020_protocol/027_begin_request.t @@ -0,0 +1,97 @@ +#!perl + +use strict; +use warnings; + +use lib 't/lib', 'lib'; +use myconfig; + +use Test::More tests => 15; +use Test::HexString; +use Test::Exception; + +BEGIN { + use_ok('Net::FastCGI::Protocol', qw[ build_begin_request ]); + use_ok('Net::FastCGI::Constant', qw[ :type :role ]); +} + +{ + my $begin = "\x01\x01\x00\x01\x00\x08\x00\x00" # FCGI_Header id=1 + . "\x00\x01\x00\x00\x00\x00\x00\x00"; # FCGI_BeginRequestBody role=FCGI_RESPONDER + + my $params = "\x01\x04\x00\x01\x00\x00\x00\x00"; # FCGI_Header type=FCGI_PARAMS + + { + my $exp = $begin . $params; + my $got = build_begin_request(1, FCGI_RESPONDER, 0, {}); + is_hexstr($got, $exp, q); + } + + my $stdin = "\x01\x05\x00\x01\x00\x00\x00\x00"; # FCGI_Header type=FCGI_STDIN + + { + my $exp = $begin . $params . $stdin; + my $got = build_begin_request(1, FCGI_RESPONDER, 0, {}, ''); + is_hexstr($got, $exp, q); + } + + { + my $exp = $begin . $params . $stdin; + my $got = build_begin_request(1, FCGI_RESPONDER, 0, {}, undef); + is_hexstr($got, $exp, q); + } + + my $data = "\x01\x08\x00\x01\x00\x00\x00\x00"; # FCGI_Header type=FCGI_DATA + + { + my $exp = $begin . $params . $stdin . $data; + my $got = build_begin_request(1, FCGI_RESPONDER, 0, {}, '', undef); + is_hexstr($got, $exp, q); + } + + { + my $exp = $begin . $params . $stdin . $data; + my $got = build_begin_request(1, FCGI_RESPONDER, 0, {}, undef, ''); + is_hexstr($got, $exp, q); + } +} + +{ + my $begin = "\x01\x01\x00\x01\x00\x08\x00\x00" # FCGI_Header id=1 + . "\x00\x01\x00\x00\x00\x00\x00\x00"; # FCGI_BeginRequestBody role=FCGI_RESPONDER + + my $params = "\x01\x04\x00\x01\x00\x08\x00\x00" # FCGI_Header type=FCGI_PARAMS + . "\x03\x03FooBar" + . "\x01\x04\x00\x01\x00\x00\x00\x00"; + + { + my $exp = $begin . $params; + my $got = build_begin_request(1, FCGI_RESPONDER, 0, { Foo => 'Bar' }); + is_hexstr($got, $exp, q!build_begin_request(1, FCGI_RESPONDER, 0, { Foo => 'Bar' })!); + } + + my $stdin = "\x01\x05\x00\x01\x03\xFC\x04\x00" # FCGI_Header type=FCGI_STDIN + . "x" x 1020 . "\0" x 4 + . "\x01\x05\x00\x01\x00\x00\x00\x00"; + { + my $exp = $begin . $params . $stdin; + my $got = build_begin_request(1, FCGI_RESPONDER, 0, { Foo => 'Bar' }, 'x' x 1020); + is_hexstr($got, $exp, q!build_begin_request(1, FCGI_RESPONDER, 0, { Foo => 'Bar' }, 'x' x 1020)!); + } + + my $data = "\x01\x08\x00\x01\x04\x00\x00\x00" # FCGI_Header type=FCGI_DATA + . "y" x 1024 + . "\x01\x08\x00\x01\x00\x00\x00\x00"; + + { + my $exp = $begin . $params . $stdin . $data; + my $got = build_begin_request(1, FCGI_RESPONDER, 0, { Foo => 'Bar' }, 'x' x 1020, 'y' x 1024); + is_hexstr($got, $exp, q!build_begin_request(1, FCGI_RESPONDER, 0, { Foo => 'Bar' }, 'x' x 1020, 'y' x 1024)!); + } +} + +# build_begin_request(request_id, role, flags, params [, stdin [, data]]) +for (0..3, 7) { + throws_ok { build_begin_request((1) x $_) } qr/^Usage: /; +} + diff --git a/web/server/h2o/libh2o/misc/p5-net-fastcgi/t/020_protocol/030_end_request_body.t b/web/server/h2o/libh2o/misc/p5-net-fastcgi/t/020_protocol/030_end_request_body.t new file mode 100644 index 000000000..783408d4a --- /dev/null +++ b/web/server/h2o/libh2o/misc/p5-net-fastcgi/t/020_protocol/030_end_request_body.t @@ -0,0 +1,42 @@ +#!perl + +use strict; +use warnings; + +use lib 't/lib', 'lib'; +use myconfig; + +use Test::More tests => 9; +use Test::HexString; +use Test::Exception; + +BEGIN { + use_ok('Net::FastCGI::Protocol', qw[ build_end_request_body + parse_end_request_body ]); +} + +my @tests = ( + # octets app_status protocol_status + [ "\x00\x00\x00\x00\x00\x00\x00\x00", 0, 0 ], + [ "\xFF\xFF\xFF\xFF\xFF\x00\x00\x00", 0xFFFFFFFF, 0xFF ], +); + +foreach my $test (@tests) { + my $expected = $test->[0]; + my $got = build_end_request_body(@$test[1..2]); + is_hexstr($got, $expected, 'build_end_request_body()'); +} + +foreach my $test (@tests) { + my @expected = @$test[1..2]; + my @got = parse_end_request_body($test->[0]); + is_deeply(\@got, \@expected, "parse_end_request_body()"); +} + + +throws_ok { parse_end_request_body("") } qr/^FastCGI: Insufficient .* FCGI_EndRequestBody/; +throws_ok { parse_end_request_body(undef) } qr/^FastCGI: Insufficient .* FCGI_EndRequestBody/; + +throws_ok { build_end_request_body() } qr/^Usage: /; +throws_ok { parse_end_request_body() } qr/^Usage: /; + diff --git a/web/server/h2o/libh2o/misc/p5-net-fastcgi/t/020_protocol/035_end_request_record.t b/web/server/h2o/libh2o/misc/p5-net-fastcgi/t/020_protocol/035_end_request_record.t new file mode 100644 index 000000000..f76dbd1f2 --- /dev/null +++ b/web/server/h2o/libh2o/misc/p5-net-fastcgi/t/020_protocol/035_end_request_record.t @@ -0,0 +1,30 @@ +#!perl + +use strict; +use warnings; + +use lib 't/lib', 'lib'; +use myconfig; + +use Test::More tests => 4; +use Test::HexString; +use Test::Exception; + +BEGIN { + use_ok('Net::FastCGI::Protocol', qw[ build_end_request_record ]); +} + +my @tests = ( + # octets request_id app_status protocol_status + [ "\x01\x03\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 0, 0, 0 ], + [ "\x01\x03\xFF\xFF\x00\x08\x00\x00\xFF\xFF\xFF\xFF\xFF\x00\x00\x00", 0xFFFF, 0xFFFFFFFF, 0xFF ], +); + +foreach my $test (@tests) { + my $expected = $test->[0]; + my $got = build_end_request_record(@$test[1..3]); + is_hexstr($got, $expected, 'build_end_request_record()'); +} + +throws_ok { build_end_request_record() } qr/^Usage: /; + diff --git a/web/server/h2o/libh2o/misc/p5-net-fastcgi/t/020_protocol/037_end_request.t b/web/server/h2o/libh2o/misc/p5-net-fastcgi/t/020_protocol/037_end_request.t new file mode 100644 index 000000000..c7c421c54 --- /dev/null +++ b/web/server/h2o/libh2o/misc/p5-net-fastcgi/t/020_protocol/037_end_request.t @@ -0,0 +1,87 @@ +#!perl + +use strict; +use warnings; + +use lib 't/lib', 'lib'; +use myconfig; + +use Test::More tests => 13; +use Test::HexString; +use Test::Exception; + +BEGIN { + use_ok('Net::FastCGI::Protocol', qw[ build_end_request ]); + use_ok('Net::FastCGI::Constant', qw[ :type :protocol_status ]); +} + +{ + my $end = "\x01\x03\x00\x01\x00\x08\x00\x00" # FCGI_Header id=1 + . "\x00\x00\x00\x00\x00\x00\x00\x00" # FCGI_EndRequestBody + ; + + { + my $got = build_end_request(1, 0, FCGI_REQUEST_COMPLETE); + is_hexstr($got, $end, q); + } + + my $stdout = "\x01\x06\x00\x01\x00\x00\x00\x00"; # FCGI_Header type=FCGI_STDOUT + + { + my $exp = $stdout . $end; + my $got = build_end_request(1, 0, FCGI_REQUEST_COMPLETE, ''); + is_hexstr($got, $exp, q); + } + + { + my $exp = $stdout . $end; + my $got = build_end_request(1, 0, FCGI_REQUEST_COMPLETE, undef); + is_hexstr($got, $exp, q); + } + + my $stderr = "\x01\x07\x00\x01\x00\x00\x00\x00"; # FCGI_Header type=FCGI_STDERR + + { + my $exp = $stdout . $stderr . $end; + my $got = build_end_request(1, 0, FCGI_REQUEST_COMPLETE, '', undef); + is_hexstr($got, $exp, q); + } + + { + my $exp = $stdout . $stderr . $end; + my $got = build_end_request(1, 0, FCGI_REQUEST_COMPLETE, undef, ''); + is_hexstr($got, $exp, q); + } +} + +{ + my $end = "\x01\x03\x00\x01\x00\x08\x00\x00" # FCGI_Header id=1 + . "\x00\x00\x00\x00\x00\x00\x00\x00" # FCGI_EndRequestBody + ; + + my $stdout = "\x01\x06\x00\x01\x03\xFC\x04\x00" # FCGI_Header type=FCGI_STDOUT + . "x" x 1020 . "\0" x 4 + . "\x01\x06\x00\x01\x00\x00\x00\x00"; + + { + my $exp = $stdout . $end; + my $got = build_end_request(1, 0, FCGI_REQUEST_COMPLETE, 'x' x 1020); + is_hexstr($got, $exp, q); + } + + my $stderr = "\x01\x07\x00\x01\x04\x00\x00\x00" # FCGI_Header type=FCGI_STDERR + . "y" x 1024 + . "\x01\x07\x00\x01\x00\x00\x00\x00"; + + { + my $exp = $stdout . $stderr . $end; + my $got = build_end_request(1, 0, FCGI_REQUEST_COMPLETE, 'x' x 1020, 'y' x 1024); + is_hexstr($got, $exp, q); + } +} + +# build_end_request(request_id, app_status, protocol_status [, stdout [, stderr]]) +for (0..2, 6) { + throws_ok { build_end_request((1) x $_) } qr/^Usage: /; +} + diff --git a/web/server/h2o/libh2o/misc/p5-net-fastcgi/t/020_protocol/040_unknown_type_body.t b/web/server/h2o/libh2o/misc/p5-net-fastcgi/t/020_protocol/040_unknown_type_body.t new file mode 100644 index 000000000..27e0d3791 --- /dev/null +++ b/web/server/h2o/libh2o/misc/p5-net-fastcgi/t/020_protocol/040_unknown_type_body.t @@ -0,0 +1,42 @@ +#!perl + +use strict; +use warnings; + +use lib 't/lib', 'lib'; +use myconfig; + +use Test::More tests => 9; +use Test::HexString; +use Test::Exception; + +BEGIN { + use_ok('Net::FastCGI::Protocol', qw[ build_unknown_type_body + parse_unknown_type_body ]); +} + +my @tests = ( + # octets type + [ "\x00\x00\x00\x00\x00\x00\x00\x00", 0 ], + [ "\xFF\x00\x00\x00\x00\x00\x00\x00", 0xFF ], +); + +foreach my $test (@tests) { + my $expected = $test->[0]; + my $got = build_unknown_type_body($test->[1]); + is_hexstr($got, $expected, 'build_unknown_type_body()'); +} + +foreach my $test (@tests) { + my @expected = $test->[1]; + my @got = parse_unknown_type_body($test->[0]); + is_deeply(\@got, \@expected, "parse_unknown_type_body()"); +} + + +throws_ok { parse_unknown_type_body("") } qr/^^FastCGI: Insufficient .* FCGI_UnknownTypeBody/; +throws_ok { parse_unknown_type_body(undef) } qr/^^FastCGI: Insufficient .* FCGI_UnknownTypeBody/; + +throws_ok { build_unknown_type_body() } qr/^Usage: /; +throws_ok { parse_unknown_type_body() } qr/^Usage: /; + diff --git a/web/server/h2o/libh2o/misc/p5-net-fastcgi/t/020_protocol/045_unknown_type_record.t b/web/server/h2o/libh2o/misc/p5-net-fastcgi/t/020_protocol/045_unknown_type_record.t new file mode 100644 index 000000000..8ee053ab2 --- /dev/null +++ b/web/server/h2o/libh2o/misc/p5-net-fastcgi/t/020_protocol/045_unknown_type_record.t @@ -0,0 +1,30 @@ +#!perl + +use strict; +use warnings; + +use lib 't/lib', 'lib'; +use myconfig; + +use Test::More tests => 4; +use Test::HexString; +use Test::Exception; + +BEGIN { + use_ok('Net::FastCGI::Protocol', qw[ build_unknown_type_record ]); +} + +my @tests = ( + # octets type + [ "\x01\x0B\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 0 ], + [ "\x01\x0B\x00\x00\x00\x08\x00\x00\xFF\x00\x00\x00\x00\x00\x00\x00", 0xFF ], +); + +foreach my $test (@tests) { + my $expected = $test->[0]; + my $got = build_unknown_type_record($test->[1]); + is_hexstr($got, $expected, 'build_unknown_type_record()'); +} + +throws_ok { build_unknown_type_record() } qr/^Usage: /; + diff --git a/web/server/h2o/libh2o/misc/p5-net-fastcgi/t/020_protocol/050_parse_record.t b/web/server/h2o/libh2o/misc/p5-net-fastcgi/t/020_protocol/050_parse_record.t new file mode 100644 index 000000000..34c5fb923 --- /dev/null +++ b/web/server/h2o/libh2o/misc/p5-net-fastcgi/t/020_protocol/050_parse_record.t @@ -0,0 +1,180 @@ +#!perl + +use strict; +use warnings; + +use lib 't/lib', 'lib'; +use myconfig; + +use Test::More tests => 54; +use Test::HexString; +use Test::Exception; + +BEGIN { + use_ok('Net::FastCGI::Constant', qw[:all]); + use_ok('Net::FastCGI::Protocol', qw[ build_header + build_record + build_stream + parse_record ]); +} + +my @records_ok = ( + [ + "\x01\x01\x00\x01\x00\x08\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00", + "\x00\x01\x00\x00\x00\x00\x00\x00", + { type => FCGI_BEGIN_REQUEST, + request_id => 1, + role => FCGI_RESPONDER, + flags => 0 } + ], + [ + "\x01\x02\x00\x01\x00\x00\x00\x00", + "", + { type => FCGI_ABORT_REQUEST, + request_id => 1 } + ], + [ + "\x01\x03\x00\x01\x00\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", + "\x00\x00\x00\x00\x00\x00\x00\x00", + { type => FCGI_END_REQUEST, + request_id => 1, + protocol_status => 0, + app_status => 0 } + ], + [ + "\x01\x04\x00d\x00\x0B\x05\x00FCGI_PARAMS\x00\x00\x00\x00\x00", + "FCGI_PARAMS", + { type => FCGI_PARAMS, + request_id => 100, + content => 'FCGI_PARAMS' } + ], + [ + "\x01\x05\x00\xC8\x00\x0A\x06\x00FCGI_STDIN\x00\x00\x00\x00\x00\x00", + "FCGI_STDIN", + { type => FCGI_STDIN, + request_id => 200, + content => 'FCGI_STDIN' } + ], + [ + "\x01\x06\x01\x2C\x00\x0B\x05\x00FCGI_STDOUT\x00\x00\x00\x00\x00", + "FCGI_STDOUT", + { type => FCGI_STDOUT, + request_id => 300, + content => 'FCGI_STDOUT' } + ], + [ + "\x01\x07\x01\x90\x00\x0B\x05\x00FCGI_STDERR\x00\x00\x00\x00\x00", + "FCGI_STDERR", + { type => FCGI_STDERR, + request_id => 400, + content => 'FCGI_STDERR' } + ], + [ + "\x01\x08\x01\xF4\x00\x09\x07\x00FCGI_DATA\x00\x00\x00\x00\x00\x00\x00", + "FCGI_DATA", + { type => FCGI_DATA, + request_id => 500, + content => 'FCGI_DATA' } + ], + [ + "\x01\x09\x00\x00\x00\x0D\x03\x00\x03\x03BarBaZ\x03\x00FOO\x00\x00\x00", + "\x03\x03BarBaZ\x03\x00FOO", + { type => FCGI_GET_VALUES, + request_id => FCGI_NULL_REQUEST_ID, + values => { FOO => '', Bar => 'BaZ' } + } + ], + [ + "\x01\x0A\x00\x00\x00\x17\x01\x00\x04\x01BETA2\x05\x01ALPHA1\x05\x01GAMMA3\x00", + "\x04\x01BETA2\x05\x01ALPHA1\x05\x01GAMMA3", + { type => FCGI_GET_VALUES_RESULT, + request_id => FCGI_NULL_REQUEST_ID, + values => { ALPHA => 1, BETA => 2, GAMMA => 3 } + } + ], + [ + "\x01\x0B\x00\x00\x00\x08\x00\x00\x64\x00\x00\x00\x00\x00\x00\x00", + "\x64\x00\x00\x00\x00\x00\x00\x00", + { type => FCGI_UNKNOWN_TYPE, + request_id => FCGI_NULL_REQUEST_ID, + unknown_type => 100 } + ], + [ + "\x01\x6F\x00\xDE\x00\x04\x04\x00oops\x00\x00\x00\x00", + "oops", + { type => 111, + request_id => 222, + content => 'oops' } + ], + [ + "\x01\xFF\xFF\xFF\x00\x00\x00\x00", + "", + { type => 0xFF, + request_id => 0xFFFF } + ], +); + +foreach my $test (@records_ok) { + my $expected = $test->[2]; + my $got = parse_record($test->[0]); + is_deeply($got, $expected, "parse_record() in scalar context"); +} + +foreach my $test (@records_ok) { + my @expected = ($test->[2]->{type}, $test->[2]->{request_id}, $test->[1]); + my @got = parse_record($test->[0]); + is_deeply(\@got, \@expected, "parse_record() in list context"); +} + +my @headers_malformed = ( + # type, request_id, content_length, padding_length + [ FCGI_BEGIN_REQUEST, 0, 0, 0 ], + [ FCGI_BEGIN_REQUEST, 1, 0, 0 ], + [ FCGI_ABORT_REQUEST, 0, 0, 0 ], + [ FCGI_END_REQUEST, 0, 0, 0 ], + [ FCGI_END_REQUEST, 1, 0, 0 ], + [ FCGI_PARAMS, 0, 0, 0 ], + [ FCGI_STDIN, 0, 0, 0 ], + [ FCGI_STDOUT, 0, 0, 0 ], + [ FCGI_STDERR, 0, 0, 0 ], + [ FCGI_DATA, 0, 0, 0 ], + [ FCGI_GET_VALUES, 1, 0, 0 ], + [ FCGI_GET_VALUES_RESULT, 1, 0, 0 ], + [ FCGI_UNKNOWN_TYPE, 0, 0, 0 ], + [ FCGI_UNKNOWN_TYPE, 1, 0, 0 ] +); + +foreach my $test (@headers_malformed) { + my $octets = build_header(@$test); + throws_ok { parse_record($octets) } qr/^FastCGI: Malformed/; +} + +{ + my $octets = build_header(FCGI_ABORT_REQUEST, 1, 8, 0) . "\x00" x 8; + throws_ok { parse_record($octets) } qr/^FastCGI: Malformed/; +} + +my @stream_types = ( + FCGI_PARAMS, + FCGI_STDIN, + FCGI_STDOUT, + FCGI_STDERR, + FCGI_DATA +); + +foreach my $type (@stream_types) { + my $expected = { type => $type, request_id => 1, content => '' }; + my $octets = build_record($type, 1, ''); + my $got = parse_record($octets); + is_deeply($got, $expected, "parse_record(stream record) in scalar context"); +} + +foreach my $type (@stream_types) { + my @expected = ($type, 1, ''); + my $octets = build_record($type, 1, ''); + my @got = parse_record($octets); + is_deeply(\@got, \@expected, "parse_record(stream record) in list context"); +} + +throws_ok { parse_record() } qr/^Usage: /; + diff --git a/web/server/h2o/libh2o/misc/p5-net-fastcgi/t/020_protocol/055_parse_record_body.t b/web/server/h2o/libh2o/misc/p5-net-fastcgi/t/020_protocol/055_parse_record_body.t new file mode 100644 index 000000000..35f3793c6 --- /dev/null +++ b/web/server/h2o/libh2o/misc/p5-net-fastcgi/t/020_protocol/055_parse_record_body.t @@ -0,0 +1,98 @@ +#!perl + +use strict; +use warnings; + +use lib 't/lib', 'lib'; +use myconfig; + +use Test::More tests => 33; +use Test::HexString; +use Test::Exception; + +BEGIN { + use_ok('Net::FastCGI::Constant', qw[:all]); + use_ok('Net::FastCGI::Protocol', qw[ build_header + build_record + build_stream + parse_record_body ]); +} + +my @ok = ( + [ + "\x00\x01\x01\x00\x00\x00\x00\x00", + { type => FCGI_BEGIN_REQUEST, + request_id => 1, + role => 1, + flags => 1 } + ], + [ + "\x00\x00\x00\x01\x01\x00\x00\x00", + { type => FCGI_END_REQUEST, + request_id => 1, + app_status => 1, + protocol_status => 1 } + ], + [ + undef, + { type => FCGI_STDIN, + request_id => 1, + content => '' } + ], + [ + "", + { type => FCGI_PARAMS, + request_id => 1, + content => '' } + ], + [ + "\x01\x01A1\x01\x01B2", + { type => FCGI_GET_VALUES, + request_id => FCGI_NULL_REQUEST_ID, + values => { A => 1, B => 2 } } + ], + [ + undef, + { type => FCGI_GET_VALUES_RESULT, + request_id => FCGI_NULL_REQUEST_ID, + values => {} } + ] +); + +foreach my $test (@ok) { + my $exp = $test->[1]; + my $got = parse_record_body($exp->{type}, $exp->{request_id}, $test->[0]); + is_deeply($got, $exp, "parse_record_body()"); +} + +my @malformed = ( + # type, request_id + [ FCGI_BEGIN_REQUEST, 0 ], + [ FCGI_END_REQUEST, 0 ], + [ FCGI_PARAMS, 0 ], + [ FCGI_STDIN, 0 ], + [ FCGI_STDOUT, 0 ], + [ FCGI_STDERR, 0 ], + [ FCGI_DATA, 0 ], + [ FCGI_GET_VALUES, 1 ], + [ FCGI_GET_VALUES_RESULT, 1 ], + [ FCGI_UNKNOWN_TYPE, 1 ] +); + +foreach my $test (@malformed) { + my ($type, $request_id) = @$test; + throws_ok { parse_record_body($type, $request_id, '') } qr/^FastCGI: Malformed/; +} + +{ + my $content = "\x00" x (FCGI_MAX_CONTENT_LEN + 1); + foreach my $type (0..12) { + throws_ok { parse_record_body($type, 0, $content) } qr/^Invalid Argument: 'content' cannot exceed/; + } +} + +# parse_record_body(type, request_id, content) +for (0, 4) { + throws_ok { parse_record_body((1) x $_) } qr/^Usage: /; +} + diff --git a/web/server/h2o/libh2o/misc/p5-net-fastcgi/t/020_protocol/060_params.t b/web/server/h2o/libh2o/misc/p5-net-fastcgi/t/020_protocol/060_params.t new file mode 100644 index 000000000..92d9a64c7 --- /dev/null +++ b/web/server/h2o/libh2o/misc/p5-net-fastcgi/t/020_protocol/060_params.t @@ -0,0 +1,79 @@ +#!perl + +use strict; +use warnings; + +use lib 't/lib', 'lib'; +use myconfig; + +use Test::More tests => 38; +use Test::HexString; +use Test::Exception; + +BEGIN { + use_ok('Net::FastCGI::Protocol', qw[ build_params + check_params + parse_params ]); +} + +sub TRUE () { !!1 } +sub FALSE () { !!0 } + +my @tests = ( + # octets params + [ "", { } ], + [ "\x00\x00", { '' => '' }, ], + [ "\x01\x01\x31\x31", { 1 => 1 }, ], + [ "\x01\x01\x41\x42\x01\x01\x43\x44\x01\x01\x45\x46", { A => 'B', C => 'D', E => 'F' } ], +); + +foreach my $test (@tests) { + my ($expected, $params) = @$test; + my $got = join '', map { + build_params({ $_ => $params->{$_} }) + } sort keys %$params; + is_hexstr($got, $expected, 'build_params()'); +} + +is_hexstr("\x03\x00foo", build_params({foo => undef}), 'build_params({foo => undef})'); +is_hexstr("\x7F\x00" . "x" x 127, build_params({ "x" x 127 => '' })); +is_hexstr("\x00\x7F" . "x" x 127, build_params({ '' => "x" x 127 })); +is_hexstr("\x80\x00\x00\x80\x00" . "x" x 128, build_params({ "x" x 128 => '' })); +is_hexstr("\x00\x80\x00\x00\x80" . "x" x 128, build_params({ '' => "x" x 128 })); + +foreach my $test (@tests) { + my $expected = $test->[1]; + my $got = parse_params($test->[0]); + is_deeply($got, $expected, 'parse_params()'); +} + +foreach my $test (@tests) { + my $octets = $test->[0]; + is(check_params($octets), TRUE, 'check_params(octets) eq TRUE'); +} + +my @insufficient = ( + "\x00", + "\x01", + "\x00\x01", + "\x01\x00", + "\x00\xFF", + "\x01\xFF\x00", + "\x00\x80\x00\x00\x80", + "\x80\x00\x00\x80\x00", +); + +foreach my $test (@insufficient) { + throws_ok { parse_params($test) } qr/^FastCGI: Insufficient .* FCGI_NameValuePair/; +} + +foreach my $test (@insufficient) { + is(check_params($test), FALSE, 'check_params(octets) eq FALSE'); +} + +is(check_params(undef), FALSE, 'check_params(undef) eq FALSE'); + +throws_ok { check_params() } qr/^Usage: /; +throws_ok { build_params() } qr/^Usage: /; +throws_ok { parse_params() } qr/^Usage: /; + diff --git a/web/server/h2o/libh2o/misc/p5-net-fastcgi/t/020_protocol/065_record_type.t b/web/server/h2o/libh2o/misc/p5-net-fastcgi/t/020_protocol/065_record_type.t new file mode 100644 index 000000000..5836a05bc --- /dev/null +++ b/web/server/h2o/libh2o/misc/p5-net-fastcgi/t/020_protocol/065_record_type.t @@ -0,0 +1,105 @@ +#!perl + +use strict; +use warnings; + +use lib 't/lib', 'lib'; +use myconfig; + +use Test::More tests => 55; +use Test::Exception; + +BEGIN { + use_ok('Net::FastCGI::Constant', qw[ :type ] ); + use_ok('Net::FastCGI::Protocol', qw[ is_discrete_type + is_known_type + is_management_type + is_stream_type ] ); +} + +sub TRUE () { !!1 } +sub FALSE () { !!0 } + +{ + my @known = ( + FCGI_BEGIN_REQUEST, + FCGI_ABORT_REQUEST, + FCGI_END_REQUEST, + FCGI_PARAMS, + FCGI_STDIN, + FCGI_STDOUT, + FCGI_STDERR, + FCGI_DATA, + FCGI_GET_VALUES, + FCGI_GET_VALUES_RESULT, + FCGI_UNKNOWN_TYPE, + FCGI_MAXTYPE, + ); + + foreach my $type (@known) { + is( is_known_type($type), TRUE, qq/is_known_type($type) = true/ ); + } +} + +{ + my @discrete = ( + FCGI_BEGIN_REQUEST, + FCGI_ABORT_REQUEST, + FCGI_END_REQUEST, + FCGI_GET_VALUES, + FCGI_GET_VALUES_RESULT, + FCGI_UNKNOWN_TYPE, + ); + + foreach my $type ( @discrete ) { + is( is_stream_type($type), FALSE, qq/is_stream_type($type) = false/ ); + is( is_discrete_type($type), TRUE, qq/is_discrete_type($type) = true/ ); + } +} + +{ + my @management = ( + FCGI_GET_VALUES, + FCGI_GET_VALUES_RESULT, + FCGI_UNKNOWN_TYPE, + ); + + foreach my $type (@management) { + is( is_management_type($type), TRUE, qq/is_management_type($type) = true/ ); + } +} + +{ + my @stream = ( + FCGI_PARAMS, + FCGI_STDIN, + FCGI_STDOUT, + FCGI_STDERR, + FCGI_DATA, + ); + + foreach my $type (@stream) { + is( is_stream_type($type), TRUE, qq/is_stream_type($type) = true/ ); + is( is_discrete_type($type), FALSE, qq/is_discrete_type($type) = false/ ); + } +} + +{ + my @subnames = qw( + is_known_type + is_discrete_type + is_management_type + is_stream_type + ); + + foreach my $name (@subnames) { + my $sub = __PACKAGE__->can($name); + is($sub->($_), FALSE, qq/$name($_) = false/) for (-10, 0, 12); + } +} + +throws_ok { is_known_type() } qr/^Usage: /; +throws_ok { is_discrete_type() } qr/^Usage: /; +throws_ok { is_management_type() } qr/^Usage: /; +throws_ok { is_stream_type() } qr/^Usage: /; + diff --git a/web/server/h2o/libh2o/misc/p5-net-fastcgi/t/020_protocol/070_names.t b/web/server/h2o/libh2o/misc/p5-net-fastcgi/t/020_protocol/070_names.t new file mode 100644 index 000000000..86af502d6 --- /dev/null +++ b/web/server/h2o/libh2o/misc/p5-net-fastcgi/t/020_protocol/070_names.t @@ -0,0 +1,80 @@ +#!perl + +use strict; +use warnings; + +use lib 't/lib', 'lib'; +use myconfig; + +use Test::More tests => 29; +use Test::Exception; + +BEGIN { + use_ok('Net::FastCGI::Constant', qw[ :type :role :protocol_status ] ); + use_ok('Net::FastCGI::Protocol', qw[ get_type_name + get_role_name + get_protocol_status_name ] ); +} + +{ + my @tests = ( + [ FCGI_BEGIN_REQUEST, 'FCGI_BEGIN_REQUEST' ], + [ FCGI_ABORT_REQUEST, 'FCGI_ABORT_REQUEST' ], + [ FCGI_END_REQUEST, 'FCGI_END_REQUEST' ], + [ FCGI_PARAMS, 'FCGI_PARAMS' ], + [ FCGI_STDIN, 'FCGI_STDIN' ], + [ FCGI_STDOUT, 'FCGI_STDOUT' ], + [ FCGI_STDERR, 'FCGI_STDERR' ], + [ FCGI_DATA, 'FCGI_DATA' ], + [ FCGI_GET_VALUES, 'FCGI_GET_VALUES' ], + [ FCGI_GET_VALUES_RESULT, 'FCGI_GET_VALUES_RESULT' ], + [ FCGI_UNKNOWN_TYPE, 'FCGI_UNKNOWN_TYPE' ], + ); + + foreach my $test ( @tests ) { + my ( $type, $name ) = @$test; + is( get_type_name($type), $name, qq/get_type_name($type) = $name/ ); + } + + foreach my $type ( 0, 0xFF ) { + is(get_type_name($type), sprintf('0x%.2X', $type)); + } +} + +{ + my @tests = ( + [ FCGI_RESPONDER, 'FCGI_RESPONDER' ], + [ FCGI_AUTHORIZER, 'FCGI_AUTHORIZER' ], + [ FCGI_FILTER, 'FCGI_FILTER' ], + ); + + foreach my $test ( @tests ) { + my ( $role, $name ) = @$test; + is( get_role_name($role), $name, qq/get_role_name($role) = $name/ ); + } + + foreach my $role ( 0, 0xFF, 0xFFFF ) { + is(get_role_name($role), sprintf('0x%.4X', $role)); + } +} + +{ + my @tests = ( + [ FCGI_REQUEST_COMPLETE, 'FCGI_REQUEST_COMPLETE' ], + [ FCGI_CANT_MPX_CONN, 'FCGI_CANT_MPX_CONN' ], + [ FCGI_OVERLOADED, 'FCGI_OVERLOADED' ], + [ FCGI_UNKNOWN_ROLE, 'FCGI_UNKNOWN_ROLE' ], + ); + + foreach my $test ( @tests ) { + my ( $status, $name ) = @$test; + is( get_protocol_status_name($status), $name, qq/get_protocol_status_name($status) = $name/ ); + } + + is(get_protocol_status_name(0xFF), '0xFF'); +} + +throws_ok { get_type_name() } qr/^Usage: /; +throws_ok { get_role_name() } qr/^Usage: /; +throws_ok { get_protocol_status_name() } qr/^Usage: /; + diff --git a/web/server/h2o/libh2o/misc/p5-net-fastcgi/t/020_protocol/080_dump_record.t b/web/server/h2o/libh2o/misc/p5-net-fastcgi/t/020_protocol/080_dump_record.t new file mode 100644 index 000000000..0e0bb5dee --- /dev/null +++ b/web/server/h2o/libh2o/misc/p5-net-fastcgi/t/020_protocol/080_dump_record.t @@ -0,0 +1,51 @@ +#!perl + +use strict; +use warnings; + +use lib 't/lib', 'lib'; +use myconfig; + +use Test::More tests => 9; +use Test::Exception; + +BEGIN { + use_ok('Net::FastCGI::Protocol', qw[build_record dump_record]); +} + +{ + my $record = build_record(0, 0, "\x00\x01\x02\x03\x04\x05\x06\x07"); + my $dump = dump_record($record); + like $dump, qr/\A \{0x00, \s 0, \s "\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07"\}/x; +} + +{ + my $record = build_record(0, 0, "\x00\x01\x02\x03\x04\x05\x06\x07"); + + for my $len (0, 8) { + my $dump = dump_record(substr($record, 0, $len)); + like $dump, qr/\A \{ Malformed \s FCGI_Record }/x, "Insufficient octets"; + } +} + +{ + for my $header ("\x00\x00\x00\x00\x00\x00\x00\x00", + "\xFF\x00\x00\x00\x00\x00\x00\x00") { + my $dump = dump_record($header); + like $dump, qr/\A \{ Malformed \s FCGI_Record }/x, "Protocol version mismatch"; + } +} + +# dump_record(type, request_id [, content]) deprecated +{ + my $dump = dump_record(0, 0); + like $dump, qr/\A \{0x00, \s 0, \s ""\}/x; +} +{ + my $dump = dump_record(0, 0, "\x00\x01\x02\x03\x04\x05\x06\x07"); + like $dump, qr/\A \{0x00, \s 0, \s "\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07"\}/x; +} + +# dump_record(octets) +throws_ok { dump_record() } qr/^Usage: /; + diff --git a/web/server/h2o/libh2o/misc/p5-net-fastcgi/t/020_protocol/085_dump_record_body.t b/web/server/h2o/libh2o/misc/p5-net-fastcgi/t/020_protocol/085_dump_record_body.t new file mode 100644 index 000000000..af00d7a33 --- /dev/null +++ b/web/server/h2o/libh2o/misc/p5-net-fastcgi/t/020_protocol/085_dump_record_body.t @@ -0,0 +1,150 @@ +#!perl + +use strict; +use warnings; + +use lib 't/lib', 'lib'; +use myconfig; + +use Test::More tests => 64; +use Test::HexString; +use Test::Exception; + +BEGIN { + use_ok('Net::FastCGI::Constant', qw[:all]); + use_ok('Net::FastCGI::Protocol', qw[:all]); +} + +my @KNOWN_TYPES = ( + FCGI_BEGIN_REQUEST, + FCGI_ABORT_REQUEST, + FCGI_END_REQUEST, + FCGI_PARAMS, + FCGI_STDIN, + FCGI_STDOUT, + FCGI_STDERR, + FCGI_DATA, + FCGI_GET_VALUES, + FCGI_GET_VALUES_RESULT, + FCGI_UNKNOWN_TYPE, +); + +foreach my $type (@KNOWN_TYPES) { + like dump_record_body($type, 0), qr/\A\{ $FCGI_TYPE_NAME[$type]\, \s+ 0/x; +} + +foreach my $type (FCGI_PARAMS, FCGI_GET_VALUES, FCGI_GET_VALUES_RESULT) { + my $name = $FCGI_TYPE_NAME[$type]; + { + my $dump = dump_record_body($type, 1, ''); + like $dump, qr/\A \{ $name\, \s+ 1\, \s ""/x; + } + { + my $dump = dump_record_body($type, 1, build_params({ '' => '' })); + like $dump, qr/\A \{ $name\, \s+ 1\, \s "\\000\\000"/x; + } + { + my $dump = dump_record_body($type, 1, build_params({ 'Foo' => '' })); + like $dump, qr/\A \{ $name\, \s+ 1\, \s "\\003\\000Foo"/x; + } + { + my $dump = dump_record_body($type, 1, build_params({ "Foo\r\n" => "\x01\x02" })); + like $dump, qr/\A \{ $name\, \s+ 1\, \s "\\005\\002Foo\\r\\n\\x01\\x02/x; + } + { + my $dump = dump_record_body($type, 1, build_params({ 'x' => 'y' x 128 })); + like $dump, qr/\A \{ $name\, \s+ 1\, \s "\\001\\200\\000\\000\\200 x y+/x; + } + { + my $dump = dump_record_body($type, 1, "\001\001"); + like $dump, qr/\A \{ $name\, \s+ 1\, \s Malformed \s FCGI_NameValuePair/x; + } +} + +# Streams +{ + my @tests = ( + [ FCGI_STDIN, 1, "Foo\r\n\t", + qr/\A \{ FCGI_STDIN\, \s+ 1\, \s \"Foo\\r\\n\\t/x ], + [ FCGI_STDOUT, 1, "\x00\x01\x02\x03\x04\x05\x06\x07", + qr/\A \{ FCGI_STDOUT\, \s+ 1\, \s \"\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07/x ], + [ FCGI_STDERR, 1, "Foo \x01\x02 Bar\n", + qr/\A \{ FCGI_STDERR\, \s+ 1\, \s \"Foo\x20\\x01\\x02\x20Bar\\n/x ], + [ FCGI_DATA, 1, 'x' x 80, + qr/\A \{ FCGI_DATA\, \s+ 1\, \s \" x+ \s \.\.\./x ], + ); + + foreach my $test (@tests) { + my ($type, $request_id, $content, $expected) = @$test; + my $dump = dump_record_body($type, $request_id, $content); + like $dump, $expected; + } +} + +# FCGI_BEGIN_REQUEST +{ + my @tests = ( + [ build_begin_request_body(FCGI_RESPONDER, FCGI_KEEP_CONN), + qr/\A \{ FCGI_BEGIN_REQUEST\, \s+ 1\, \s \{ FCGI_RESPONDER\, \s+ FCGI_KEEP_CONN\}/x ], + [ build_begin_request_body(FCGI_FILTER, FCGI_KEEP_CONN | 0x10), + qr/\A \{ FCGI_BEGIN_REQUEST\, \s+ 1\, \s \{ FCGI_FILTER\, \s+ FCGI_KEEP_CONN|0x10\}/x ], + [ build_begin_request_body(FCGI_AUTHORIZER, 0), + qr/\A \{ FCGI_BEGIN_REQUEST\, \s+ 1\, \s \{ FCGI_AUTHORIZER\, \s+ 0\}/x ], + [ build_begin_request_body(0, 0x80), + qr/\A \{ FCGI_BEGIN_REQUEST\, \s+ 1\, \s \{ 0x0000\, \s+ 0x80\}/x ], + map([ $_, + qr/\A \{ FCGI_BEGIN_REQUEST\, \s+ 1\, \s \{ Malformed \s FCGI_BeginRequestBody/x ], + ('', "\x00" x 10)), + ); + + foreach my $test (@tests) { + my ($content, $expected) = @$test; + my $dump = dump_record_body(FCGI_BEGIN_REQUEST, 1, $content); + like $dump, $expected; + } +} + +# FCGI_END_REQUEST +{ + my @tests = ( + [ build_end_request_body(10, 0x80), + qr/\A \{ FCGI_END_REQUEST\, \s+ 1\, \s \{ 10\, \s+ 0x80\}/x ], + map([ $_, + qr/\A \{ FCGI_END_REQUEST\, \s+ 1\, \s \{ Malformed \s FCGI_EndRequestBody/x ], + ('', "\x00" x 10)), + map([ build_end_request_body(0, $_), + qr/\A \{ FCGI_END_REQUEST\, \s+ 1\, \s \{ 0\, \s+ $FCGI_PROTOCOL_STATUS_NAME[$_]\}/x ], + (0..3)), + ); + + foreach my $test (@tests) { + my ($content, $expected) = @$test; + my $dump = dump_record_body(FCGI_END_REQUEST, 1, $content); + like $dump, $expected; + } +} + +# FCGI_UNKNOWN_TYPE +{ + my @tests = ( + [ build_unknown_type_body(0), + qr/\A \{ FCGI_UNKNOWN_TYPE\, \s+ 0\, \s \{ 0/x ], + map([ build_unknown_type_body($_), + qr/\A \{ FCGI_UNKNOWN_TYPE\, \s+ 0\, \s \{ $FCGI_TYPE_NAME[$_]/x ], + @KNOWN_TYPES), + map([ $_, + qr/\A \{ FCGI_UNKNOWN_TYPE\, \s+ 0\, \s \{ Malformed \s FCGI_UnknownTypeBody/x ], + ('', "\x00" x 10)), + ); + + foreach my $test (@tests) { + my ($content, $expected) = @$test; + my $dump = dump_record_body(FCGI_UNKNOWN_TYPE, 0, $content); + like $dump, $expected; + } +} + + +throws_ok { dump_record_body() } qr/^Usage: /; +throws_ok { dump_record_body(0, 0, undef, 0) } qr/^Usage: /; + diff --git a/web/server/h2o/libh2o/misc/p5-net-fastcgi/t/lib/myconfig.pm b/web/server/h2o/libh2o/misc/p5-net-fastcgi/t/lib/myconfig.pm new file mode 100644 index 000000000..1d4f63482 --- /dev/null +++ b/web/server/h2o/libh2o/misc/p5-net-fastcgi/t/lib/myconfig.pm @@ -0,0 +1,9 @@ +package myconfig; + +use strict; + +BEGIN { + $ENV{NET_FASTCGI_PP} = 0 + !(-e "XS.xs" || -e "../XS.xs"); +} + +1; -- cgit v1.2.3