Redid conversion to Test::Fatal
[gitmo/Moose.git] / t / 030_roles / 011_overriding.t
CommitLineData
4c15a12d 1#!/usr/bin/perl
2
3use strict;
4use warnings;
5
a28e50e4 6use Test::More;
b10dde3a 7use Test::Fatal;
4c15a12d 8
7ff56534 9
d03bd989 10{
c4538447 11 # test no conflicts here
12 package Role::A;
13 use Moose::Role;
4c15a12d 14
c4538447 15 sub bar { 'Role::A::bar' }
4c15a12d 16
c4538447 17 package Role::B;
18 use Moose::Role;
4c15a12d 19
c4538447 20 sub xxy { 'Role::B::xxy' }
4c15a12d 21
c4538447 22 package Role::C;
23 use Moose::Role;
d03bd989 24
b10dde3a 25 ::is( ::exception {
c4538447 26 with qw(Role::A Role::B); # no conflict here
b10dde3a 27 }, undef, "define role C" );
4c15a12d 28
c4538447 29 sub foo { 'Role::C::foo' }
30 sub zot { 'Role::C::zot' }
4c15a12d 31
c4538447 32 package Class::A;
33 use Moose;
4c15a12d 34
b10dde3a 35 ::is( ::exception {
f6bee6fe 36 with qw(Role::C);
b10dde3a 37 }, undef, "define class A" );
d03bd989 38
c4538447 39 sub zot { 'Class::A::zot' }
40}
4c15a12d 41
c4538447 42can_ok( Class::A->new, qw(foo bar xxy zot) );
4c15a12d 43
c4538447 44is( Class::A->new->foo, "Role::C::foo", "... got the right foo method" );
45is( Class::A->new->zot, "Class::A::zot", "... got the right zot method" );
46is( Class::A->new->bar, "Role::A::bar", "... got the right bar method" );
47is( Class::A->new->xxy, "Role::B::xxy", "... got the right xxy method" );
4c15a12d 48
49{
c4538447 50 # check that when a role is added to another role
bb153262 51 # and they conflict and the method they conflict
d03bd989 52 # with is then required.
53
c4538447 54 package Role::A::Conflict;
55 use Moose::Role;
d03bd989 56
c4538447 57 with 'Role::A';
d03bd989 58
c4538447 59 sub bar { 'Role::A::Conflict::bar' }
d03bd989 60
c4538447 61 package Class::A::Conflict;
62 use Moose;
d03bd989 63
b10dde3a 64 ::like( ::exception {
c4538447 65 with 'Role::A::Conflict';
b10dde3a 66 }, qr/Due to a method name conflict in roles 'Role::A' and 'Role::A::Conflict', the method 'bar' must be implemented or excluded by 'Class::A::Conflict'/, '... did not fufill the requirement of &bar method' );
d03bd989 67
c4538447 68 package Class::A::Resolved;
69 use Moose;
d03bd989 70
b10dde3a 71 ::is( ::exception {
f6bee6fe 72 with 'Role::A::Conflict';
b10dde3a 73 }, undef, '... did fufill the requirement of &bar method' );
d03bd989 74
c4538447 75 sub bar { 'Class::A::Resolved::bar' }
76}
4c15a12d 77
c4538447 78ok(Role::A::Conflict->meta->requires_method('bar'), '... Role::A::Conflict created the bar requirement');
4c15a12d 79
c4538447 80can_ok( Class::A::Resolved->new, qw(bar) );
4c15a12d 81
c4538447 82is( Class::A::Resolved->new->bar, 'Class::A::Resolved::bar', "... got the right bar method" );
4c15a12d 83
c4538447 84{
85 # check that when two roles are composed, they conflict
86 # but the composing role can resolve that conflict
d03bd989 87
c4538447 88 package Role::D;
89 use Moose::Role;
4c15a12d 90
c4538447 91 sub foo { 'Role::D::foo' }
d03bd989 92 sub bar { 'Role::D::bar' }
4c15a12d 93
c4538447 94 package Role::E;
95 use Moose::Role;
4c15a12d 96
c4538447 97 sub foo { 'Role::E::foo' }
98 sub xxy { 'Role::E::xxy' }
4c15a12d 99
c4538447 100 package Role::F;
101 use Moose::Role;
4c15a12d 102
b10dde3a 103 ::is( ::exception {
c4538447 104 with qw(Role::D Role::E); # conflict between 'foo's here
b10dde3a 105 }, undef, "define role Role::F" );
d03bd989 106
c4538447 107 sub foo { 'Role::F::foo' }
d03bd989 108 sub zot { 'Role::F::zot' }
109
c4538447 110 package Class::B;
111 use Moose;
d03bd989 112
b10dde3a 113 ::is( ::exception {
f6bee6fe 114 with qw(Role::F);
b10dde3a 115 }, undef, "define class Class::B" );
d03bd989 116
c4538447 117 sub zot { 'Class::B::zot' }
118}
4c15a12d 119
c4538447 120can_ok( Class::B->new, qw(foo bar xxy zot) );
4c15a12d 121
c4538447 122is( Class::B->new->foo, "Role::F::foo", "... got the &foo method okay" );
123is( Class::B->new->zot, "Class::B::zot", "... got the &zot method okay" );
124is( Class::B->new->bar, "Role::D::bar", "... got the &bar method okay" );
125is( Class::B->new->xxy, "Role::E::xxy", "... got the &xxy method okay" );
126
127ok(!Role::F->meta->requires_method('foo'), '... Role::F fufilled the &foo requirement');
128
129{
130 # check that a conflict can be resolved
d03bd989 131 # by a role, but also new ones can be
c4538447 132 # created just as easily ...
d03bd989 133
c4538447 134 package Role::D::And::E::Conflict;
135 use Moose::Role;
136
b10dde3a 137 ::is( ::exception {
c4538447 138 with qw(Role::D Role::E); # conflict between 'foo's here
b10dde3a 139 }, undef, "... define role Role::D::And::E::Conflict" );
d03bd989 140
c4538447 141 sub foo { 'Role::D::And::E::Conflict::foo' } # this overrides ...
d03bd989 142
143 # but these conflict
144 sub xxy { 'Role::D::And::E::Conflict::xxy' }
145 sub bar { 'Role::D::And::E::Conflict::bar' }
4c15a12d 146
147}
148
c4538447 149ok(!Role::D::And::E::Conflict->meta->requires_method('foo'), '... Role::D::And::E::Conflict fufilled the &foo requirement');
150ok(Role::D::And::E::Conflict->meta->requires_method('xxy'), '... Role::D::And::E::Conflict adds the &xxy requirement');
151ok(Role::D::And::E::Conflict->meta->requires_method('bar'), '... Role::D::And::E::Conflict adds the &bar requirement');
152
4c15a12d 153{
154 # conflict propagation
d03bd989 155
c4538447 156 package Role::H;
157 use Moose::Role;
4c15a12d 158
c4538447 159 sub foo { 'Role::H::foo' }
d03bd989 160 sub bar { 'Role::H::bar' }
4c15a12d 161
c4538447 162 package Role::J;
163 use Moose::Role;
4c15a12d 164
c4538447 165 sub foo { 'Role::J::foo' }
166 sub xxy { 'Role::J::xxy' }
4c15a12d 167
c4538447 168 package Role::I;
169 use Moose::Role;
4c15a12d 170
b10dde3a 171 ::is( ::exception {
4c15a12d 172 with qw(Role::J Role::H); # conflict between 'foo's here
b10dde3a 173 }, undef, "define role Role::I" );
d03bd989 174
c4538447 175 sub zot { 'Role::I::zot' }
f3e76c8f 176 sub zzy { 'Role::I::zzy' }
4c15a12d 177
c4538447 178 package Class::C;
179 use Moose;
d03bd989 180
b10dde3a 181 ::like( ::exception {
4c15a12d 182 with qw(Role::I);
b10dde3a 183 }, qr/Due to a method name conflict in roles 'Role::H' and 'Role::J', the method 'foo' must be implemented or excluded by 'Class::C'/, "defining class Class::C fails" );
4c15a12d 184
c4538447 185 sub zot { 'Class::C::zot' }
4c15a12d 186
c4538447 187 package Class::E;
188 use Moose;
189
b10dde3a 190 ::is( ::exception {
f6bee6fe 191 with qw(Role::I);
b10dde3a 192 }, undef, "resolved with method" );
c4538447 193
194 sub foo { 'Class::E::foo' }
d03bd989 195 sub zot { 'Class::E::zot' }
c4538447 196}
197
198can_ok( Class::E->new, qw(foo bar xxy zot) );
4c15a12d 199
c4538447 200is( Class::E->new->foo, "Class::E::foo", "... got the right &foo method" );
201is( Class::E->new->zot, "Class::E::zot", "... got the right &zot method" );
202is( Class::E->new->bar, "Role::H::bar", "... got the right &bar method" );
203is( Class::E->new->xxy, "Role::J::xxy", "... got the right &xxy method" );
4c15a12d 204
c4538447 205ok(Role::I->meta->requires_method('foo'), '... Role::I still have the &foo requirement');
206
207{
b10dde3a 208 is( exception {
f3e76c8f 209 package Class::D;
210 use Moose;
fb1e11d5 211
f3e76c8f 212 has foo => ( default => __PACKAGE__ . "::foo", is => "rw" );
fb1e11d5 213
f3e76c8f 214 sub zot { 'Class::D::zot' }
fb1e11d5 215
f6bee6fe 216 with qw(Role::I);
fb1e11d5 217
b10dde3a 218 }, undef, "resolved with attr" );
fb1e11d5 219
f3e76c8f 220 can_ok( Class::D->new, qw(foo bar xxy zot) );
221 is( eval { Class::D->new->bar }, "Role::H::bar", "bar" );
222 is( eval { Class::D->new->zzy }, "Role::I::zzy", "zzy" );
4c15a12d 223
224 is( eval { Class::D->new->foo }, "Class::D::foo", "foo" );
225 is( eval { Class::D->new->zot }, "Class::D::zot", "zot" );
4c15a12d 226
4c15a12d 227}
228
a28e50e4 229done_testing;