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