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