From: Wallace Reis Date: Sat, 4 May 2013 17:28:58 +0000 (+0200) Subject: Unicode plugin: import tests and update current ones X-Git-Tag: 5.90040~12 X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?p=catagits%2FCatalyst-Runtime.git;a=commitdiff_plain;h=550464108eada19dba470ec5d17fc849399fdab0 Unicode plugin: import tests and update current ones --- diff --git a/t/aggregate/live_plugin_loaded.t b/t/aggregate/live_plugin_loaded.t index 6795043..64161aa 100644 --- a/t/aggregate/live_plugin_loaded.t +++ b/t/aggregate/live_plugin_loaded.t @@ -15,6 +15,7 @@ my @expected = qw[ Catalyst::Plugin::Test::Inline Catalyst::Plugin::Test::MangleDollarUnderScore Catalyst::Plugin::Test::Plugin + Catalyst::Plugin::Unicode::Encoding TestApp::Plugin::AddDispatchTypes TestApp::Plugin::FullyQualified ]; diff --git a/t/aggregate/unit_core_plugin.t b/t/aggregate/unit_core_plugin.t index 16a5e24..becc3c1 100644 --- a/t/aggregate/unit_core_plugin.t +++ b/t/aggregate/unit_core_plugin.t @@ -53,6 +53,7 @@ my @expected = qw( Catalyst::Plugin::Test::Inline Catalyst::Plugin::Test::MangleDollarUnderScore Catalyst::Plugin::Test::Plugin + Catalyst::Plugin::Unicode::Encoding TestApp::Plugin::AddDispatchTypes TestApp::Plugin::FullyQualified ); diff --git a/t/lib/PluginTestApp.pm b/t/lib/PluginTestApp.pm index 29a02cd..7af690d 100644 --- a/t/lib/PluginTestApp.pm +++ b/t/lib/PluginTestApp.pm @@ -14,8 +14,9 @@ sub _test_plugins { is_deeply [ $c->registered_plugins ], [ qw/Catalyst::Plugin::Test::Plugin + Catalyst::Plugin::Unicode::Encoding TestApp::Plugin::FullyQualified/ - ], + ], '... and it should report the correct plugins'; ok $c->registered_plugins('Catalyst::Plugin::Test::Plugin'), '... or if we have a particular plugin'; diff --git a/t/lib/PluginTestApp/Controller/Root.pm b/t/lib/PluginTestApp/Controller/Root.pm index 7bec366..94f4378 100644 --- a/t/lib/PluginTestApp/Controller/Root.pm +++ b/t/lib/PluginTestApp/Controller/Root.pm @@ -49,6 +49,7 @@ sub run_time_plugins : Local { is_deeply [ $c->registered_plugins ], [ qw/Catalyst::Plugin::Test::Plugin + Catalyst::Plugin::Unicode::Encoding Faux::Plugin TestApp::Plugin::FullyQualified/ ], diff --git a/t/lib/TestApp.pm b/t/lib/TestApp.pm index a99301c..e548872 100644 --- a/t/lib/TestApp.pm +++ b/t/lib/TestApp.pm @@ -49,7 +49,7 @@ TestApp->config( action_args => { action_action_nine => { another_extra_arg => 13 } } - } + }, ); # Test bug found when re-adjusting the metaclass compat code in Moose diff --git a/t/lib/TestApp/Controller/Root.pm b/t/lib/TestApp/Controller/Root.pm index f2acb21..b626bdb 100644 --- a/t/lib/TestApp/Controller/Root.pm +++ b/t/lib/TestApp/Controller/Root.pm @@ -2,6 +2,7 @@ package TestApp::Controller::Root; use strict; use warnings; use base 'Catalyst::Controller'; +use utf8; __PACKAGE__->config->{namespace} = ''; diff --git a/t/lib/TestApp2.pm b/t/lib/TestApp2.pm new file mode 100644 index 0000000..552b8c6 --- /dev/null +++ b/t/lib/TestApp2.pm @@ -0,0 +1,20 @@ +package TestApp2; +use strict; +use warnings; +use base qw/Catalyst/; +use Catalyst qw/Params::Nested/; + +__PACKAGE__->config( + encoding => $ENV{TESTAPP_ENCODING} +) if $ENV{TESTAPP_ENCODING}; + +__PACKAGE__->config('name' => 'TestApp2'); + +__PACKAGE__->setup; + +sub handle_unicode_encoding_exception { + my ( $self, $param_value, $error_msg ) = @_; + return $param_value; +} + +1; diff --git a/t/lib/TestApp2/Controller/Root.pm b/t/lib/TestApp2/Controller/Root.pm new file mode 100644 index 0000000..0fefe63 --- /dev/null +++ b/t/lib/TestApp2/Controller/Root.pm @@ -0,0 +1,16 @@ +package TestApp2::Controller::Root; +use strict; +use warnings; +use utf8; + +__PACKAGE__->config(namespace => q{}); + +use base 'Catalyst::Controller'; + +# your actions replace this one +sub main :Path('') { + $_[1]->res->body('

It works

'); + $_[1]->res->content_type('text/html'); +} + +1; diff --git a/t/lib/TestAppUnicode.pm b/t/lib/TestAppUnicode.pm new file mode 100644 index 0000000..50ad98a --- /dev/null +++ b/t/lib/TestAppUnicode.pm @@ -0,0 +1,23 @@ +package TestAppUnicode; +use strict; +use warnings; +use TestLogger; +use base qw/Catalyst/; +use Catalyst qw/Unicode::Encoding Params::Nested/; + +__PACKAGE__->config( + encoding => $ENV{TESTAPP_ENCODING} +) if $ENV{TESTAPP_ENCODING}; + +__PACKAGE__->config('name' => 'TestAppUnicode'); + +__PACKAGE__->log(TestLogger->new); + +__PACKAGE__->setup; + +sub handle_unicode_encoding_exception { + my ( $self, $param_value, $error_msg ) = @_; + return $param_value; +} + +1; diff --git a/t/lib/TestAppUnicode/Controller/Root.pm b/t/lib/TestAppUnicode/Controller/Root.pm new file mode 100644 index 0000000..a944b95 --- /dev/null +++ b/t/lib/TestAppUnicode/Controller/Root.pm @@ -0,0 +1,80 @@ +package TestAppUnicode::Controller::Root; +use strict; +use warnings; +use utf8; + +__PACKAGE__->config(namespace => q{}); + +use base 'Catalyst::Controller'; + +sub main :Path('') { + my ($self, $ctx, $charset) = @_; + my $content_type = 'text/html'; + if ($ctx->stash->{charset}) { + $content_type .= ";charset=" . $ctx->stash->{charset}; + } + $ctx->res->body('

It works

'); + $ctx->res->content_type($content_type); +} + +sub unicode_no_enc :Local { + my ($self, $c) = @_; + my $data = "ほげ"; # hoge! + utf8::encode($data); + $c->response->body($data); + $c->res->content_type('text/plain'); + $c->encoding(undef); +} + +sub unicode :Local { + my ($self, $c) = @_; + my $data = "ほげ"; # hoge! + $c->response->body($data); # should be decoded + $c->res->content_type('text/plain'); +} + +sub not_unicode :Local { + my ($self, $c) = @_; + my $data = "\x{1234}\x{5678}"; + utf8::encode($data); # DO NOT WANT unicode + $c->response->body($data); # just some octets + $c->res->content_type('text/plain'); + $c->encoding(undef); +} + +sub latin1 :Local { + my ($self, $c) = @_; + + $c->res->content_type('text/plain'); + $c->response->body('LATIN SMALL LETTER E WITH ACUTE: é'); +} + +sub file :Local { + my ($self, $c) = @_; + close *STDERR; # i am evil. + $c->response->body($main::TEST_FILE); # filehandle from test file +} + +sub capture : Chained('/') CaptureArgs(1) {} + +sub decode_capture : Chained('capture') PathPart('') Args(0) { + my ( $self, $c, $cap_arg ) = @_; + $c->forward('main'); +} + +sub capture_charset : Chained('/') Args(1) { + my ( $self, $c, $cap_arg ) = @_; + $c->stash(charset => $cap_arg); + $c->forward('main'); +} + +sub shift_jis :Local { + my ($self, $c) = @_; + my $data = "ほげ"; # hoge! + $c->response->body($data); # should be decoded + $c->res->content_type('text/plain; charset=Shift_JIS'); + $c->encoding("Shift_JIS"); +} + +1; + diff --git a/t/lib/TestLogger.pm b/t/lib/TestLogger.pm new file mode 100644 index 0000000..f1dc7e6 --- /dev/null +++ b/t/lib/TestLogger.pm @@ -0,0 +1,23 @@ +package TestLogger; +use strict; +use warnings; + +our @LOGS; +our @ELOGS; + +sub new { + return bless {}, __PACKAGE__; +} + +sub debug { + shift; + push(@LOGS, shift()); +} + +sub warn { + shift; + push(@ELOGS, shift()); +} + +1; + diff --git a/t/live_redirect_body.t b/t/live_redirect_body.t index 913f0e9..8b9d62c 100644 --- a/t/live_redirect_body.t +++ b/t/live_redirect_body.t @@ -40,7 +40,7 @@ use Test::More; is( $response->code, 302, 'Response Code' ); # When the developer sets both the content body and content type, the set content body and content_type should get through. - is( $response->header( 'Content-Type' ), 'text/plain', 'Content Type' ); + like( $response->header( 'Content-Type' ), qr{text/plain}, 'Content Type' ); like( $response->content, qr/kind sir/, 'Content contains content set by the Controller' ); } diff --git a/t/unicode_plugin_charset_utf8.t b/t/unicode_plugin_charset_utf8.t new file mode 100644 index 0000000..9700b73 --- /dev/null +++ b/t/unicode_plugin_charset_utf8.t @@ -0,0 +1,32 @@ +use strict; +use warnings; +use Test::More; +use FindBin qw/ $Bin /; +use lib "$Bin/lib"; +use Data::Dumper; + +BEGIN { + $ENV{TESTAPP_ENCODING} = 'UTF-8'; + $ENV{TESTAPP_DEBUG} = 0; + $ENV{CATALYST_DEBUG} = 0; +} + +use Catalyst::Test 'TestAppUnicode'; + +ok request('/capture_charset/utf-8'); +is scalar(@TestLogger::LOGS), 0; + +ok request('/capture_charset/latin1'); +is scalar(@TestLogger::LOGS), 1 + or diag Dumper(\@TestLogger::LOGS); + +@TestLogger::LOGS = (); + +ok request('/capture_charset/iso-8859-1; header=present'); +is scalar(@TestLogger::LOGS), 1 + or diag Dumper(\@TestLogger::LOGS); +like $TestLogger::LOGS[0], qr/content type is 'iso-8859-1'/; + +like $TestLogger::ELOGS[0], qr/plugin is now part of core/; + +done_testing; diff --git a/t/unicode_plugin_config.t b/t/unicode_plugin_config.t new file mode 100644 index 0000000..513c978 --- /dev/null +++ b/t/unicode_plugin_config.t @@ -0,0 +1,31 @@ +#!/usr/bin/env perl + +use strict; +use warnings; +use Test::More; + +BEGIN { $ENV{TESTAPP_ENCODING} = 'UTF-8' }; + +# setup library path +use FindBin qw($Bin); +use lib "$Bin/lib"; + +BEGIN { +if ( !eval { require Test::WWW::Mechanize::Catalyst } || ! Test::WWW::Mechanize::Catalyst->VERSION('0.51') ) { + plan skip_all => 'Need Test::WWW::Mechanize::Catalyst for this test'; +} +} + +# make sure testapp works +use_ok('TestAppUnicode'); + +use Test::WWW::Mechanize::Catalyst 'TestAppUnicode'; +my $mech = Test::WWW::Mechanize::Catalyst->new; + +{ + TestAppUnicode->encoding('UTF-8'); + $mech->get_ok('http://localhost/unicode', 'encoding configured ok'); +} + +done_testing; + diff --git a/t/unicode_plugin_live.t b/t/unicode_plugin_live.t new file mode 100644 index 0000000..de810aa --- /dev/null +++ b/t/unicode_plugin_live.t @@ -0,0 +1,93 @@ +#!/usr/bin/env perl + +use strict; +use warnings; +use Test::More; +use IO::Scalar; + +# setup library path +use FindBin qw($Bin); +use lib "$Bin/lib"; + +BEGIN { +if ( !eval { require Test::WWW::Mechanize::Catalyst } || ! Test::WWW::Mechanize::Catalyst->VERSION('0.51') ) { + plan skip_all => 'Need Test::WWW::Mechanize::Catalyst for this test'; +} +} + +# make sure testapp works +use_ok('TestAppUnicode') or BAIL_OUT($@); + +our $TEST_FILE = IO::Scalar->new(\"this is a test"); +sub IO::Scalar::FILENO { -1 }; # needed? + +# a live test against TestAppUnicode, the test application +use Test::WWW::Mechanize::Catalyst 'TestAppUnicode'; +my $mech = Test::WWW::Mechanize::Catalyst->new; +$mech->get_ok('http://localhost/', 'get main page'); +$mech->content_like(qr/it works/i, 'see if it has our text'); +is ($mech->response->header('Content-Type'), 'text/html; charset=UTF-8', + 'Content-Type with charset' +); + +{ + $mech->get_ok('http://localhost/unicode_no_enc', 'get unicode_no_enc'); + + my $exp = "\xE3\x81\xBB\xE3\x81\x92"; + my $got = Encode::encode_utf8($mech->content); + + is ($mech->response->header('Content-Type'), 'text/plain', + 'Content-Type with no charset'); + + is($got, $exp, 'content contains hoge'); +} + +{ + $mech->get_ok('http://localhost/unicode', 'get unicode'); + + is ($mech->response->header('Content-Type'), 'text/plain; charset=UTF-8', + 'Content-Type with charset'); + + my $exp = "\xE3\x81\xBB\xE3\x81\x92"; + my $got = Encode::encode_utf8($mech->content); + + is($got, $exp, 'content contains hoge'); +} + +{ + $mech->get_ok('http://localhost/not_unicode', 'get bytes'); + my $exp = "\xE1\x88\xB4\xE5\x99\xB8"; + my $got = Encode::encode_utf8($mech->content); + + is($got, $exp, 'got 1234 5678'); +} + +{ + $mech->get_ok('http://localhost/file', 'get file'); + $mech->content_like(qr/this is a test/, 'got filehandle contents'); +} + +{ + # The latin 1 case is the one everyone forgets. I want to really make sure + # its right, so lets check the damn bytes. + $mech->get_ok('http://localhost/latin1', 'get latin1'); + is ($mech->response->header('Content-Type'), 'text/plain; charset=UTF-8', + 'Content-Type with charset'); + + + my $exp = "LATIN SMALL LETTER E WITH ACUTE: \xC3\xA9"; + my $got = Encode::encode_utf8($mech->content); + + is ($got, $exp, 'content octets are UTF-8'); +} + +{ + $mech->get_ok('http://localhost/shift_jis', 'get shift_jis'); + is ($mech->response->header('Content-Type'), 'text/plain; charset=Shift_JIS', 'Content-Type with charset'); + my $exp = "\xE3\x81\xBB\xE3\x81\x92"; + my $got = Encode::encode_utf8($mech->content); + is ($got, $exp, 'content octets are Shift_JIS'); +} + +done_testing; + diff --git a/t/unicode_plugin_nested_params.t b/t/unicode_plugin_nested_params.t new file mode 100644 index 0000000..b31f4ce --- /dev/null +++ b/t/unicode_plugin_nested_params.t @@ -0,0 +1,71 @@ +#!/usr/bin/env perl + +use strict; +use warnings; +use Test::More; +use utf8; + +# setup library path +use FindBin qw($Bin); +use lib "$Bin/lib"; + +BEGIN { eval { require Catalyst::Plugin::Params::Nested; 1; } || + plan skip_all => 'Need Catalyst::Plugin::Params::Nested' } + +use Catalyst::Test 'TestApp2'; +use Encode; +use HTTP::Request::Common; +use URI::Escape qw/uri_escape_utf8/; +use HTTP::Status 'is_server_error'; + +my $encode_str = "\x{e3}\x{81}\x{82}"; # e38182 is japanese 'あ' +my $decode_str = Encode::decode('utf-8' => $encode_str); +my $escape_str = uri_escape_utf8($decode_str); + +BEGIN { + eval 'require Catalyst::Plugin::Params::Nested'; + plan skip_all => 'Catalyst::Plugin::Params::Nested is required' if $@; +} + +{ + my ($res, $c) = ctx_request("/?foo.1=bar&foo.2=$escape_str"); + is( $c->res->output, '

It works

', 'Content displayed' ); + + my $got = $c->request->parameters; + my $expected = { + 'foo.1' => 'bar', + 'foo.2' => $decode_str, + 'foo' => [undef, 'bar', $decode_str], + }; + + is( $got->{foo}->[0], undef, '{foo}->[0] is undef' ); + is( $got->{foo}->[1], 'bar', '{foo}->[1] is bar' ); + ok( utf8::is_utf8( $got->{'foo.2'} ), '{foo.2} is utf8' ); + ok( utf8::is_utf8( $got->{foo}->[2] ), '{foo}->[2] is utf8' ); + is_deeply($got, $expected, 'nested params' ); +} + +{ + my ($res, $c) = ctx_request("/?foo.1=bar&foo.2=$escape_str&bar.baz=$escape_str&baz.bar.foo=$escape_str&&arr.0.1=$escape_str"); + + my $got = $c->request->parameters; + my $expected = { + 'foo.1' => 'bar', + 'foo.2' => $decode_str, + 'bar.baz' => $decode_str, + 'baz.bar.foo' => $decode_str, + 'arr.0.1' => $decode_str, + 'arr' => [ [undef, $decode_str] ], + 'foo' => [undef, 'bar', $decode_str], + 'bar' => { baz => $decode_str }, + 'baz' => { bar => { foo => $decode_str } }, + }; + + is( ref $got->{arr}->[0], 'ARRAY', '{arr}->[0] is ARRAY' ); + ok( utf8::is_utf8( $got->{arr}->[0]->[1] ), '{arr}->[0]->[1] is utf8' ); + ok( utf8::is_utf8( $got->{bar}{baz} ), '{bar}{baz} is utf8' ); + ok( utf8::is_utf8( $got->{baz}{bar}{foo} ), '{baz}{bar}{foo} is utf8' ); + is_deeply($got, $expected, 'nested params' ); +} + +done_testing(); diff --git a/t/unicode_plugin_request_decode.t b/t/unicode_plugin_request_decode.t new file mode 100644 index 0000000..a3bab97 --- /dev/null +++ b/t/unicode_plugin_request_decode.t @@ -0,0 +1,82 @@ +#!/usr/bin/env perl + +use strict; +use warnings; +use Test::More tests => 5 * 5; +use utf8; + +# setup library path +use FindBin qw($Bin); +use lib "$Bin/lib"; + +use Catalyst::Test 'TestAppUnicode'; +use Encode; +use HTTP::Request::Common; +use URI::Escape qw/uri_escape_utf8/; +use HTTP::Status 'is_server_error'; + +my $encode_str = "\x{e3}\x{81}\x{82}"; # e38182 is japanese 'あ' +my $decode_str = Encode::decode('utf-8' => $encode_str); +my $escape_str = uri_escape_utf8($decode_str); + +check_parameter(GET "/?foo=$escape_str"); +check_parameter(POST '/', ['foo' => $encode_str]); +check_parameter(POST '/', + Content_Type => 'form-data', + Content => [ + 'foo' => [ + "$Bin/unicode_plugin_request_decode.t", + $encode_str, + ] + ], +); + +check_argument(GET "/$escape_str"); +check_capture(GET "/capture/$escape_str"); + +# sending non-utf8 data +my $non_utf8_data = "%C3%E6%CB%AA"; +check_fallback(GET "/?q=${non_utf8_data}"); +check_fallback(GET "/${non_utf8_data}"); +check_fallback(GET "/capture/${non_utf8_data}"); +check_fallback(POST '/', ['foo' => $non_utf8_data]); + +sub check_parameter { + my ( undef, $c ) = ctx_request(shift); + is $c->res->output => '

It works

'; + + my $foo = $c->req->param('foo'); + ok utf8::is_utf8($foo); + is $foo => $decode_str; + + my $other_foo = $c->req->method eq 'POST' + ? $c->req->upload('foo') + ? $c->req->upload('foo')->filename + : $c->req->body_parameters->{foo} + : $c->req->query_parameters->{foo}; + ok utf8::is_utf8($other_foo); + is $other_foo => $decode_str; +} + +sub check_argument { + my ( undef, $c ) = ctx_request(shift); + is $c->res->output => '

It works

'; + + my $foo = $c->req->args->[0]; + ok utf8::is_utf8($foo); + is $foo => $decode_str; +} + +sub check_capture { + my ( undef, $c ) = ctx_request(shift); + is $c->res->output => '

It works

'; + + my $foo = $c->req->captures->[0]; + ok utf8::is_utf8($foo); + is $foo => $decode_str; +} + +sub check_fallback { + my ( $res, $c ) = ctx_request(shift); + ok(!is_server_error($res->code)) or diag('Response code is: ' . $res->code); +}