📄 01_params-check.t
字号:
use strict;use Test::More 'no_plan';### use && import ###BEGIN { use_ok( 'Params::Check' ); Params::Check->import(qw|check last_error allow|);} ### verbose is good for debugging ###$Params::Check::VERBOSE = $Params::Check::VERBOSE = $ARGV[0] ? 1 : 0;### basic things first, allow function ###use constant FALSE => sub { 0 };use constant TRUE => sub { 1 };### allow tests ###{ ok( allow( 42, qr/^\d+$/ ), "Allow based on regex" ); ok( allow( $0, $0), " Allow based on string" ); ok( allow( 42, [0,42] ), " Allow based on list" ); ok( allow( 42, [50,sub{1}])," Allow based on list containing sub"); ok( allow( 42, TRUE ), " Allow based on constant sub" ); ok(!allow( $0, qr/^\d+$/ ), "Disallowing based on regex" ); ok(!allow( 42, $0 ), " Disallowing based on string" ); ok(!allow( 42, [0,$0] ), " Disallowing based on list" ); ok(!allow( 42, [50,sub{0}])," Disallowing based on list containing sub"); ok(!allow( 42, FALSE ), " Disallowing based on constant sub" ); ### check that allow short circuits where required { my $sub_called; allow( 1, [ 1, sub { $sub_called++ } ] ); ok( !$sub_called, "Allow short-circuits properly" ); } ### check if the subs for allow get what you expect ### for my $thing (1,'foo',[1]) { allow( $thing, sub { is_deeply(+shift,$thing, "Allow coderef gets proper args") } ); }}### default tests ###{ my $tmpl = { foo => { default => 1 } }; ### empty args first ### { my $args = check( $tmpl, {} ); ok( $args, "check() call with empty args" ); is( $args->{'foo'}, 1, " got default value" ); } ### now provide an alternate value ### { my $try = { foo => 2 }; my $args = check( $tmpl, $try ); ok( $args, "check() call with defined args" ); is_deeply( $args, $try, " found provided value in rv" ); } ### now provide a different case ### { my $try = { FOO => 2 }; my $args = check( $tmpl, $try ); ok( $args, "check() call with alternate case" ); is( $args->{foo}, 2, " found provided value in rv" ); } ### now see if we can strip leading dashes ### { local $Params::Check::STRIP_LEADING_DASHES = 1; my $try = { -foo => 2 }; my $get = { foo => 2 }; my $args = check( $tmpl, $try ); ok( $args, "check() call with leading dashes" ); is_deeply( $args, $get, " found provided value in rv" ); }}### preserve case tests ###{ my $tmpl = { Foo => { default => 1 } }; for (1,0) { local $Params::Check::PRESERVE_CASE = $_; my $expect = $_ ? { Foo => 42 } : { Foo => 1 }; my $rv = check( $tmpl, { Foo => 42 } ); ok( $rv, "check() call using PRESERVE_CASE: $_" ); is_deeply($rv, $expect, " found provided value in rv" ); } }### unknown tests ###{ ### disallow unknowns ### { my $rv = check( {}, { foo => 42 } ); is_deeply( $rv, {}, "check() call with unknown arguments" ); like( last_error(), qr/^Key 'foo' is not a valid key/, " warning recorded ok" ); } ### allow unknown ### { local $Params::Check::ALLOW_UNKNOWN = 1; my $rv = check( {}, { foo => 42 } ); is_deeply( $rv, { foo => 42 }, "check call() with unknown args allowed" ); }}### store tests ###{ my $foo; my $tmpl = { foo => { store => \$foo } }; ### with/without store duplicates ### for( 1, 0 ) { local $Params::Check::NO_DUPLICATES = $_; my $expect = $_ ? undef : 42; my $rv = check( $tmpl, { foo => 42 } ); ok( $rv, "check() call with store key, no_dup: $_" ); is( $foo, 42, " found provided value in variable" ); is( $rv->{foo}, $expect, " found provided value in variable" ); }} ### no_override tests ###{ my $tmpl = { foo => { no_override => 1, default => 42 }, }; my $rv = check( $tmpl, { foo => 13 } ); ok( $rv, "check() call with no_override key" ); is( $rv->{'foo'}, 42, " found default value in rv" ); like( last_error(), qr/^You are not allowed to override key/, " warning recorded ok" );}### strict_type tests ###{ my @list = ( [ { strict_type => 1, default => [] }, 0 ], [ { default => [] }, 1 ], ); ### check for strict_type global, and in the template key ### for my $aref (@list) { my $tmpl = { foo => $aref->[0] }; local $Params::Check::STRICT_TYPE = $aref->[1]; ### proper value ### { my $rv = check( $tmpl, { foo => [] } ); ok( $rv, "check() call with strict_type enabled" ); is( ref $rv->{foo}, 'ARRAY', " found provided value in rv" ); } ### improper value ### { my $rv = check( $tmpl, { foo => {} } ); ok( !$rv, "check() call with strict_type violated" ); like( last_error(), qr/^Key 'foo' needs to be of type 'ARRAY'/, " warning recorded ok" ); } }} ### required tests ###{ my $tmpl = { foo => { required => 1 } }; ### required value provided ### { my $rv = check( $tmpl, { foo => 42 } ); ok( $rv, "check() call with required key" ); is( $rv->{foo}, 42, " found provided value in rv" ); } ### required value omitted ### { my $rv = check( $tmpl, { } ); ok( !$rv, "check() call with required key omitted" ); like( last_error, qr/^Required option 'foo' is not provided/, " warning recorded ok" ); }}### defined tests ###{ my @list = ( [ { defined => 1, default => 1 }, 0 ], [ { default => 1 }, 1 ], ); ### check for strict_type global, and in the template key ### for my $aref (@list) { my $tmpl = { foo => $aref->[0] }; local $Params::Check::ONLY_ALLOW_DEFINED = $aref->[1]; ### value provided defined ### { my $rv = check( $tmpl, { foo => 42 } ); ok( $rv, "check() call with defined key" ); is( $rv->{foo}, 42, " found provided value in rv" ); } ### value provided undefined ### { my $rv = check( $tmpl, { foo => undef } ); ok( !$rv, "check() call with defined key undefined" ); like( last_error, qr/^Key 'foo' must be defined when passed/, " warning recorded ok" ); } }}### check + allow tests ###{ ### check if the subs for allow get what you expect ### for my $thing (1,'foo',[1]) { my $tmpl = { foo => { allow => sub { is_deeply(+shift,$thing, " Allow coderef gets proper args") } } }; my $rv = check( $tmpl, { foo => $thing } ); ok( $rv, "check() call using allow key" ); }}### invalid key tests { my $tmpl = { foo => { allow => sub { 0 } } }; for my $val ( 1, 'foo', [], bless({},__PACKAGE__) ) { my $rv = check( $tmpl, { foo => $val } ); my $text = "Key 'foo' ($val) is of invalid type"; my $re = quotemeta $text; ok(!$rv, "check() fails with unalllowed value" ); like(last_error(), qr/$re/, " $text" ); }}### warnings fatal test{ my $tmpl = { foo => { allow => sub { 0 } } }; local $Params::Check::WARNINGS_FATAL = 1; eval { check( $tmpl, { foo => 1 } ) }; ok( $@, "Call dies with fatal toggled" ); like( $@, qr/invalid type/, " error stored ok" );}### store => \$foo tests{ ### quell warnings local $SIG{__WARN__} = sub {}; my $tmpl = { foo => { store => '' } }; check( $tmpl, {} ); my $re = quotemeta q|Store variable for 'foo' is not a reference!|; like(last_error(), qr/$re/, "Caught non-reference 'store' variable" );} ### edge case tests ###{ ### if key is not provided, and value is '', will P::C treat ### that correctly? my $tmpl = { foo => { default => '' } }; my $rv = check( $tmpl, {} ); ok( $rv, "check() call with default = ''" ); ok( exists $rv->{foo}, " rv exists" ); ok( defined $rv->{foo}, " rv defined" ); ok( !$rv->{foo}, " rv false" ); is( $rv->{foo}, '', " rv = '' " );}### big template test ###{ my $lastname; ### the template to check against ### my $tmpl = { firstname => { required => 1, defined => 1 }, lastname => { required => 1, store => \$lastname }, gender => { required => 1, allow => [qr/M/i, qr/F/i], }, married => { allow => [0,1] }, age => { default => 21, allow => qr/^\d+$/, }, id_list => { default => [], strict_type => 1 }, phone => { allow => sub { 1 if +shift } }, bureau => { default => 'NSA', no_override => 1 }, }; ### the args to send ### my $try = { firstname => 'joe', lastname => 'jackson', gender => 'M', married => 1, age => 21, id_list => [1..3], phone => '555-8844', }; ### the rv we expect ### my $get = { %$try, bureau => 'NSA' }; my $rv = check( $tmpl, $try ); ok( $rv, "elaborate check() call" ); is_deeply( $rv, $get, " found provided values in rv" ); is( $rv->{lastname}, $lastname, " found provided values in rv" );}### $Params::Check::CALLER_DEPTH test{ sub wrapper { check ( @_ ) }; sub inner { wrapper( @_ ) }; sub outer { inner ( @_ ) }; outer( { dummy => { required => 1 }}, {} ); like( last_error, qr/for .*::wrapper by .*::inner$/, "wrong caller without CALLER_DEPTH" ); local $Params::Check::CALLER_DEPTH = 1; outer( { dummy => { required => 1 }}, {} ); like( last_error, qr/for .*::inner by .*::outer$/, "right caller with CALLER_DEPTH" );}### test: #23824: Bug concering the loss of the last_error ### message when checking recursively.{ ok( 1, "Test last_error() on recursive check() call" ); ### allow sub to call my $clear = sub { check( {}, {} ) if shift; 1; }; ### recursively call check() or not? for my $recurse ( 0, 1 ) { check( { a => { defined => 1 }, b => { allow => sub { $clear->( $recurse ) } }, }, { a => undef, b => undef } ); ok( last_error(), " last_error() with recurse: $recurse" ); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -