use
lib
qw( ./lib ./t/lib ../inc ./inc )
;
ok(TypeTiny->has_coercion,
"TypeTiny->has_coercion"
);
subtest
"Coercion from built-in Moose type constraint object"
=>
sub
{
my
$orig
= find_type_constraint(
"Int"
);
my
$type
= to_TypeTiny
$orig
;
should_pass(
$orig
, _ForeignTypeConstraint);
should_fail(
$type
, _ForeignTypeConstraint);
should_pass(
$type
, TypeTiny,
'to_TypeTiny converted a Moose type constraint to a Type::Tiny one'
);
is(
$type
->name,
'Int'
,
'... which has the correct name'
);
ok(
$type
->can_be_inlined,
'... and which can be inlined'
);
note
$type
->inline_check(
'$X'
);
subtest
"... and it works"
=>
sub
{
should_pass(123,
$type
);
should_fail(3.3,
$type
);
};
};
subtest
"Coercion from custom Moose type constraint object"
=>
sub
{
my
$orig
=
'Moose::Meta::TypeConstraint'
->new(
name
=>
'EvenInt'
,
parent
=> find_type_constraint(
"Int"
),
constraint
=>
sub
{
my
(
$value
) =
@_
;
$value
% 2 == 0;
},
inlined
=>
sub
{
my
(
$self
,
$var
) =
@_
;
return
sprintf
(
'do { %s } && !( %s %% 2 )'
,
$self
->parent->_inline_check(
$var
),
$var
,
);
},
message
=>
sub
{
my
(
$value
) =
@_
;
return
find_type_constraint(
"Int"
)->check(
$value
)
?
"$value isn't an integer at all"
:
"$value is odd"
;
},
);
my
$type
= to_TypeTiny
$orig
;
should_pass(
$orig
, _ForeignTypeConstraint);
should_fail(
$type
, _ForeignTypeConstraint);
should_pass(
$type
, TypeTiny,
'to_TypeTiny converted a Moose type constraint to a Type::Tiny one'
);
is(
$type
->display_name,
'EvenInt'
,
'... which has the correct display_name'
);
ok(
$type
->can_be_inlined,
'... and which can be inlined'
);
note
$type
->inline_check(
'$X'
);
subtest
"... and it works"
=>
sub
{
should_fail(3.3,
$type
);
should_fail(123,
$type
);
should_pass(124,
$type
);
};
is(
$type
->get_message(3.3),
$orig
->get_message(3.3),
'... and provides proper message'
,
);
};
my
%moose_ptype_opts
= (
name
=>
'ArrayOrHashRef'
,
parent
=> find_type_constraint(
'Ref'
),
constraint
=>
sub
{
my
$value
=
@_
?
pop
:
$_
;
ref
(
$value
) eq
'HASH'
or
ref
(
$value
) eq
'ARRAY'
;
},
constraint_generator
=>
sub
{
my
$param
=
shift
;
return
sub
{
my
$value
=
@_
?
pop
:
$_
;
if
(
ref
(
$value
) eq
'ARRAY'
) {
(
$param
->check(
$_
) or
return
)
for
@$value
;
return
1;
}
elsif
(
ref
(
$value
) eq
'HASH'
) {
(
$param
->check(
$_
) or
return
)
for
values
%$value
;
return
1;
}
return
;
};
},
);
my
$ptype_tests
=
sub
{
my
$moose
= Moose::Meta::TypeConstraint::Parameterizable->new(
%moose_ptype_opts
);
Moose::Util::TypeConstraints::register_type_constraint(
$moose
);
Moose::Util::TypeConstraints::add_parameterizable_type(
$moose
);
note
"Moose native type, no parameters"
;
ok(
$moose
->check([]) );
ok(
$moose
->check({}) );
ok(
$moose
->check([1..10]) );
ok(
$moose
->check({
foo
=> 1,
bar
=> 2}) );
ok(
$moose
->check([
'hello world'
]) );
ok( !
$moose
->check(\1) );
ok( !
$moose
->check(42) );
note
"Moose native type, parameterized with Moose type"
;
my
$moose_with_moose
=
$moose
->parameterize( find_type_constraint(
'Int'
) );
ok(
$moose_with_moose
->check([]) );
ok(
$moose_with_moose
->check({}) );
ok(
$moose_with_moose
->check([1..10]) );
ok(
$moose_with_moose
->check({
foo
=> 1,
bar
=> 2}) );
ok( !
$moose_with_moose
->check([
'hello world'
]) );
ok( !
$moose_with_moose
->check(\1) );
ok( !
$moose_with_moose
->check(42) );
note
"Moose native type, parameterized with TT type"
;
my
$moose_with_tt
=
$moose
->parameterize( Int );
ok(
$moose_with_tt
->check([]) );
ok(
$moose_with_tt
->check({}) );
ok(
$moose_with_tt
->check([1..10]) );
ok(
$moose_with_tt
->check({
foo
=> 1,
bar
=> 2}) );
ok( !
$moose_with_tt
->check([
'hello world'
]) );
ok( !
$moose_with_tt
->check(\1) );
ok( !
$moose_with_tt
->check(42) );
note
'TT type, no parameters'
;
my
$tt
= Types::TypeTiny::to_TypeTiny(
$moose
);
isa_ok(
$tt
,
'Type::Tiny'
);
is(
$tt
->display_name,
$moose_ptype_opts
{name});
should_pass([],
$tt
);
should_pass({},
$tt
);
should_pass([1..10],
$tt
);
should_pass({
foo
=> 1,
bar
=> 2},
$tt
);
should_pass([
'hello world'
],
$tt
);
should_fail(\1,
$tt
);
should_fail(42,
$tt
);
note
'TT type, parameterized with Moose type'
;
my
$tt_with_moose
=
$tt
->of( find_type_constraint(
'Int'
) );
should_pass([],
$tt_with_moose
);
should_pass({},
$tt_with_moose
);
should_pass([1..10],
$tt_with_moose
);
should_pass({
foo
=> 1,
bar
=> 2},
$tt_with_moose
);
should_fail([
'hello world'
],
$tt_with_moose
);
should_fail(\1,
$tt_with_moose
);
should_fail(42,
$tt_with_moose
);
note
'TT type, parameterized with TT type'
;
my
$tt_with_tt
=
$tt
->of( Int );
should_pass([],
$tt_with_tt
);
should_pass({},
$tt_with_tt
);
should_pass([1..10],
$tt_with_tt
);
should_pass({
foo
=> 1,
bar
=> 2},
$tt_with_tt
);
should_fail([
'hello world'
],
$tt_with_tt
);
should_fail(\1,
$tt_with_tt
);
should_fail(42,
$tt_with_tt
);
return
(
$moose
,
$moose_with_moose
,
$moose_with_tt
,
$tt
,
$tt_with_moose
,
$tt_with_tt
,
);
};
subtest
"Coercion from Moose parameterizable type constraint object"
=>
sub
{
$ptype_tests
->();
};
$moose_ptype_opts
{name} .=
'2'
;
$moose_ptype_opts
{inlined} =
sub
{
my
$var
=
pop
;
sprintf
(
'ref(%s) =~ /^(HASH|ARRAY)$/'
,
$var
);
};
$moose_ptype_opts
{inline_generator} =
sub
{
my
(
$base
,
$param
,
$var
) =
@_
;
my
$code
=
sprintf
qq{do{
if (ref($var) eq 'ARRAY') {
my \$okay = 1;
(%s or ((\$okay=0), last)) for \@{$var}
;
\
$okay
;
}
elsif
(
ref
(
$var
) eq
'HASH'
) {
my
\
$okay
= 1;
(
%s
or ((\
$okay
=0),
last
))
for
values
%%{
$var
};
\
$okay
;
}
else
{
0;
}
}}, (
$param
->_inline_check(
'$_'
)) x 2;
$code
;
};
subtest
"Coercion from Moose parameterizable type constraint object with inlining"
=>
sub
{
my
@types
=
$ptype_tests
->();
note
'check everything can be inlined'
;
for
my
$type
(
@types
) {
ok(
$type
->can_be_inlined );
ok(
length
(
$type
->_inline_check(
'$xxx'
)) );
}
note(
$types
[-1]->inline_check(
'$VALUE'
) );
};
subtest
"Coercion from Moose enum type constraint"
=>
sub
{
my
$moose
= Moose::Util::TypeConstraints::enum(
Foo
=> [
qw/ foo bar baz /
]);
ok(
$moose
->check(
"foo"
) );
ok( !
$moose
->check(
"quux"
) );
ok( !
$moose
->check(\1) );
ok( !
$moose
->check(
undef
) );
my
$tt
= Types::TypeTiny::to_TypeTiny(
$moose
);
ok(
$tt
->check(
"foo"
) );
ok( !
$tt
->check(
"quux"
) );
ok( !
$tt
->check(\1) );
ok( !
$tt
->check(
undef
) );
isa_ok(
$tt
,
'Type::Tiny::Enum'
);
is_deeply(
$tt
->
values
,
$moose
->
values
);
ok
$tt
->can_be_inlined;
note(
$tt
->inline_check(
'$STR'
) );
};
subtest
"Coercion from Moose class type constraint"
=>
sub
{
my
$moose
= Moose::Util::TypeConstraints::class_type(
FooObj
=> {
class
=>
'MyApp::Foo'
});
my
$tt
= Types::TypeTiny::to_TypeTiny(
$moose
);
isa_ok(
$tt
,
'Type::Tiny::Class'
);
is(
$tt
->class,
$moose
->class);
ok
$tt
->can_be_inlined;
note(
$tt
->inline_check(
'$OBJECT'
) );
};
subtest
"Coercion from Moose role type constraint"
=>
sub
{
my
$moose
= Moose::Util::TypeConstraints::role_type(
DoesFoo
=> {
role
=>
'MyApp::Foo'
});
my
$tt
= Types::TypeTiny::to_TypeTiny(
$moose
);
isa_ok(
$tt
,
'Type::Tiny::Role'
);
is(
$tt
->role,
$moose
->role);
ok
$tt
->can_be_inlined;
note(
$tt
->inline_check(
'$OBJECT'
) );
};
subtest
"Coercion from Moose duck type constraint"
=>
sub
{
my
$moose
= Moose::Util::TypeConstraints::duck_type(
FooInterface
=> [
qw/foo bar baz/
]);
my
$tt
= Types::TypeTiny::to_TypeTiny(
$moose
);
isa_ok(
$tt
,
'Type::Tiny::Duck'
);
is_deeply([
sort
@{
$tt
->methods} ], [
sort
@{
$moose
->methods} ]);
ok
$tt
->can_be_inlined;
note(
$tt
->inline_check(
'$OBJECT'
) );
};
subtest
"Coercion from Moose union type constraint"
=>
sub
{
my
$moose
= Moose::Util::TypeConstraints::union(
'ContainerThang'
,
[ find_type_constraint(
'ArrayRef'
), find_type_constraint(
'HashRef'
), ]
);
my
$tt
= Types::TypeTiny::to_TypeTiny(
$moose
);
is(
$tt
->display_name,
'ContainerThang'
);
isa_ok(
$tt
,
'Type::Tiny::Union'
);
ok(
$tt
->[0] == Types::Standard::ArrayRef);
ok(
$tt
->[1] == Types::Standard::HashRef);
ok
$tt
->can_be_inlined;
note(
$tt
->inline_check(
'$REF'
) );
};
subtest
"Coercion from Mouse type constraint object"
=>
sub
{
my
$orig
= Mouse::Util::TypeConstraints::find_type_constraint(
"Int"
);
my
$type
= to_TypeTiny
$orig
;
should_pass(
$orig
, _ForeignTypeConstraint);
should_fail(
$type
, _ForeignTypeConstraint);
should_pass(
$type
, TypeTiny,
'to_TypeTiny converted a Mouse type constraint to a Type::Tiny one'
);
subtest
"... and it works"
=>
sub
{
should_pass(123,
$type
);
should_fail(3.3,
$type
);
};
is(
$type
->get_message(3.3),
$orig
->get_message(3.3),
'... and provides proper message'
,
);
};
subtest
"Coercion from predicate-like coderef"
=>
sub
{
my
$orig
=
sub
{
$_
[0] =~ /\A-?[0-9]+\z/ };
my
$type
= to_TypeTiny
$orig
;
should_pass(
$orig
, _ForeignTypeConstraint);
should_fail(
$type
, _ForeignTypeConstraint);
should_pass(
$type
, TypeTiny,
'to_TypeTiny converted the coderef to a Type::Tiny object'
);
subtest
"... and it works"
=>
sub
{
should_pass(123,
$type
);
should_fail(3.3,
$type
);
};
};
subtest
"Coercion from assertion-like coderef"
=>
sub
{
my
$orig
=
sub
{
$_
[0] =~ /\A-?[0-9]+\z/ or
die
(
"not an integer"
) };
my
$type
= to_TypeTiny
$orig
;
should_pass(
$orig
, _ForeignTypeConstraint);
should_fail(
$type
, _ForeignTypeConstraint);
should_pass(
$type
, TypeTiny,
'to_TypeTiny converted the coderef to a Type::Tiny object'
);
subtest
"... and it works"
=>
sub
{
should_pass(123,
$type
);
should_fail(3.3,
$type
);
};
like(
$type
->validate(3.3),
qr/\Anot an integer/
,
'... and provides proper message'
,
);
};
subtest
"Coercion from Sub::Quote coderef"
=>
sub
{
my
$orig
= Sub::Quote::quote_sub(
q{ $_[0] =~ /\A-?[0-9]+\z/ }
);
my
$type
= to_TypeTiny
$orig
;
should_pass(
$orig
, _ForeignTypeConstraint);
should_fail(
$type
, _ForeignTypeConstraint);
should_pass(
$type
, TypeTiny,
'to_TypeTiny converted the coderef to a Type::Tiny object'
);
ok(
$type
->can_be_inlined,
'... which can be inlined'
);
note
$type
->inline_check(
'$X'
);
subtest
"... and it works"
=>
sub
{
should_pass(123,
$type
);
should_fail(3.3,
$type
);
};
};
done_testing;