Add assert_valid() to Meta::TypeConstraint
[gitmo/Mouse.git] / t / 040_type_constraints / failing / 016_subtyping_parameterized_types.t
1 #!/usr/bin/perl
2
3 use strict;
4 use warnings;
5
6 use Test::More tests => 39;
7 use Test::Exception;
8
9 BEGIN {
10     use_ok("Mouse::Util::TypeConstraints");
11 }
12
13 lives_ok {
14     subtype 'MySpecialHash' => as 'HashRef[Int]';
15 } '... created the subtype special okay';
16
17 {
18     my $t = find_type_constraint('MySpecialHash');
19     isa_ok($t, 'Mouse::Meta::TypeConstraint');
20
21     is($t->name, 'MySpecialHash', '... name is correct');
22
23     my $p = $t->parent;
24     isa_ok($p, 'Mouse::Meta::TypeConstraint::Parameterized');
25     isa_ok($p, 'Mouse::Meta::TypeConstraint');
26
27     is($p->name, 'HashRef[Int]', '... parent name is correct');
28
29     ok($t->check({ one => 1, two => 2 }), '... validated {one=>1, two=>2} correctly');
30     ok(!$t->check({ one => "ONE", two => "TWO" }), '... validated it correctly');
31
32     ok( $t->equals($t), "equals to self" );
33     ok( !$t->equals( $t->parent ), "not equal to parent" );
34     ok( $t->parent->equals( $t->parent ), "parent equals to self" );
35
36     ok( !$t->is_a_type_of("ThisTypeDoesNotExist"), "not a non existant type" );
37     ok( !$t->is_subtype_of("ThisTypeDoesNotExist"), "not a subtype of a non existant type" );
38 }
39
40 lives_ok {
41     subtype 'MySpecialHashExtended'
42         => as 'HashRef[Int]'
43         => where {
44             # all values are less then 10
45             (scalar grep { $_ < 10 } values %{$_}) ? 1 : undef
46         };
47 } '... created the subtype special okay';
48
49 {
50     my $t = find_type_constraint('MySpecialHashExtended');
51     isa_ok($t, 'Mouse::Meta::TypeConstraint');
52
53     is($t->name, 'MySpecialHashExtended', '... name is correct');
54
55     my $p = $t->parent;
56     isa_ok($p, 'Mouse::Meta::TypeConstraint::Parameterized');
57     isa_ok($p, 'Mouse::Meta::TypeConstraint');
58
59     is($p->name, 'HashRef[Int]', '... parent name is correct');
60
61     ok($t->check({ one => 1, two => 2 }), '... validated it correctly');
62     ok(!$t->check({ zero => 10, one => 11, two => 12 }), '... validated { zero => 10, one => 11, two => 12 } correctly');
63     ok(!$t->check({ one => "ONE", two => "TWO" }), '... validated it correctly');
64 }
65
66 lives_ok {
67     subtype 'MyNonSpecialHash'
68         => as "HashRef"
69         => where { keys %$_ == 3 };
70 };
71
72 {
73     my $t = find_type_constraint('MyNonSpecialHash');
74
75     isa_ok($t, 'Mouse::Meta::TypeConstraint');
76     isa_ok($t, 'Mouse::Meta::TypeConstraint::Parameterizable');
77
78     ok( $t->check({ one => 1, two => "foo", three => [] }), "validated" );
79     ok( !$t->check({ one => 1 }), "failed" );
80 }
81
82 {
83     my $t = Mouse::Util::TypeConstraints::find_or_parse_type_constraint('MyNonSpecialHash[Int]');
84
85     isa_ok($t, 'Mouse::Meta::TypeConstraint');
86
87     ok( $t->check({ one => 1, two => 2, three => 3 }), "validated" );
88     ok( !$t->check({ one => 1, two => "foo", three => [] }), "failed" );
89     ok( !$t->check({ one => 1 }), "failed" );
90 }
91
92 {
93     ## Because to throw errors in M:M:Parameterizable needs Mouse loaded in
94     ## order to throw errors.  In theory the use Mouse belongs to that class
95     ## but when I put it there causes all sorts or trouble.  In theory this is
96     ## never a real problem since you are likely to use Mouse somewhere when you
97     ## are creating type constraints.
98     use Mouse ();
99
100     my $MyArrayRefInt =  subtype 'MyArrayRefInt',
101         as 'ArrayRef[Int]';
102
103     my $BiggerInt = subtype 'BiggerInt',
104         as 'Int',
105         where {$_>10};
106
107     my $SubOfMyArrayRef = subtype 'SubOfMyArrayRef',
108         as 'MyArrayRefInt[BiggerInt]';
109
110     ok $MyArrayRefInt->check([1,2,3]), '[1,2,3] is okay';
111     ok ! $MyArrayRefInt->check(["a","b"]), '["a","b"] is not';
112     ok $BiggerInt->check(100), '100 is  big enough';
113     ok ! $BiggerInt->check(5), '5 is  big enough';
114     ok $SubOfMyArrayRef->check([15,20,25]), '[15,20,25] is a bunch of big ints';
115     ok ! $SubOfMyArrayRef->check([15,5,25]), '[15,5,25] is NOT a bunch of big ints';
116
117     throws_ok sub {
118         my $SubOfMyArrayRef = subtype 'SubSubOfMyArrayRef',
119             as 'SubOfMyArrayRef[Str]';
120     }, qr/Str is not a subtype of BiggerInt/, 'Failed to parameterize with a bad type parameter';
121 }