File: 120_trait_errors.t

package info (click to toggle)
libclass-trait-perl 0.31-1
  • links: PTS
  • area: main
  • in suites: squeeze, wheezy
  • size: 364 kB
  • ctags: 156
  • sloc: perl: 2,467; makefile: 46
file content (253 lines) | stat: -rw-r--r-- 6,346 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
#!/usr/bin/perl

use strict;
use warnings;

use Test::More tests => 33;

sub clean_inc {
    my @packages = qw(
      Circle
      Class::Trait
      Class::Trait::Base
      Class::Trait::Config
      Extra::TSpouse
      Polygamy
      TBomb
      TDisallowed
      TSpouse
      TestTraits
    );

    foreach my $package (@packages) {
        no strict 'refs';
        foreach my $glob ( keys %{"${package}::"} ) {
            undef *{"${package}::$glob"};
        }
    }
    my @includes = map { s{::}{/}g; "$_.pm" } @packages;
    delete @INC{@includes};

}

local $SIG{__WARN__} = sub {
    my $message = shift;
    return if $message =~ /Too late to run INIT block/;
    warn $message;
};

BEGIN {
    chdir 't' if -d 't';
    unshift @INC => ( '../lib', 'test_lib' );
}

#
# Note that Class::Trait->initialize is only being called because the code is
# eval'ed and the INIT phase does not run.  This is also necessary when
# running under mod_perl
#

#
# TSpouse: fuse explode
# TBomb:   fuse explode
#

eval <<'END_PACKAGE';
package TestTraits;
use Class::Trait ( 'TSpouse', 'TBomb' );
Class::Trait->initialize;
END_PACKAGE

ok my $error = $@, 'Trying to load conflicting traits should fail';
like $error, qr/\QPackage TestTraits has conflicting methods (explode fuse)/,
  '... with an appropriate error message';

#
# TSpouse:  explode
# TBomb:    fuse explode
#

clean_inc();
eval <<'END_PACKAGE';
package TestTraits;
use Class::Trait ( 
    'TSpouse' => { exclude => ['fuse'] },
    'TBomb'
);
Class::Trait->initialize;
END_PACKAGE

ok $error = $@, 'Trying to load conflicting traits should fail';
like $error, qr/\QPackage TestTraits has conflicting methods (explode)/,
  '... with an appropriate error message';

#
# TSpouse:  explode
# TBomb:    fuse
#

clean_inc();
eval <<'END_PACKAGE';
package TestTraits;
use Class::Trait ( 
    'TSpouse' => { exclude => ['fuse']    },
    'TBomb'   => { exclude => ['explode'] },
);
Class::Trait->initialize;
END_PACKAGE

ok !$@, 'Trying to load properly configured traits should not fail';
can_ok 'TestTraits', 'fuse';
is TestTraits->fuse, 'Bomb fuse',
  '... and it should pull in the correct fuse() method';
can_ok 'TestTraits', 'explode';
is TestTraits->explode, 'Spouse explodes',
  '... and it should pull in the correct explode() method';

clean_inc();
eval <<'END_PACKAGE';
package TestTraits;
use Class::Trait ( 
    'TSpouse' => { exclude => 'explode' }
);
Class::Trait->initialize;
sub explode { 'TestTraits explode' }
END_PACKAGE

ok !$@, 'Trying to load properly configured traits should not fail';
can_ok 'TestTraits', 'fuse';
is TestTraits->fuse, 'Spouse fuse',
  '... and it should pull in the correct fuse() method';
can_ok 'TestTraits', 'explode';
is TestTraits->explode, 'TestTraits explode',
  '... and it should not pull in explicitly defined methods';

#
# Extra::TSpouse: fuse explode [ requires lawyer() ]
#           does: Original::TSpouse: fuse explode [ requires alimony() ]
#

clean_inc();
eval <<'END_PACKAGE';
package Polygamy;
use Class::Trait 'Extra::TSpouse';
Class::Trait->initialize;
sub alimony {}
END_PACKAGE

ok $@,   'Trying to load a trait which does not meet requirements should fail';
like $@, qr/\QRequirement (lawyer) for Extra::TSpouse not in Polygamy\E/,
  '... with an appropriate error message';

#
# Extra::TSpouse: fuse explode [ requires lawyer() ]
#           does: Original::TSpouse: fuse explode [ requires alimony() ]
#

clean_inc();
eval <<'END_PACKAGE';
package Polygamy;
use Class::Trait 'Extra::TSpouse';
Class::Trait->initialize;
sub lawyer {}
END_PACKAGE

ok $@,   'Trying to load a trait which does not meet requirements should fail';
like $@, qr/\QRequirement (alimony) for Extra::TSpouse not in Polygamy\E/,
  '... and @REQUIREMENTS should bubble up correctly';
clean_inc();

#
# Extra::TSpouse: fuse explode [requires lawyer()]
#           does: TSpouse: fuse explode
#

clean_inc();
eval <<'END_PACKAGE';
package Polygamy;
use Class::Trait 'Extra::TSpouse';
Class::Trait->initialize;
sub lawyer {}
sub alimony {}
END_PACKAGE

ok !$@,
'Trying to load a trait which overrides an included traits methods should succeed';

can_ok Polygamy => 'explode';
is Polygamy->explode, 'Extra spouse explodes',
  '... and we should have the correct method';

can_ok Polygamy => 'fuse';
is Polygamy->fuse, 'Spouse fuse',
  '... and we should get the composed trait method';

clean_inc();
eval <<'END_PACKAGE';
package TestTraits;
use Class::Trait ( 
    'TSpouse' => { exclude => ['fuse']    },
    'TBomb'   => { exclude => ['explode'] },
);
Class::Trait->rename_does('%%');
Class::Trait->initialize;
END_PACKAGE

ok $@,   'Trying to rename does() to an illegal method name should fail';
like $@, qr/\QIllegal name for trait relation method (%%)/,
  '... telling us that it\'s an illegal method name';

clean_inc();
eval <<'END_PACKAGE';
package TestTraits;
use Class::Trait 'Circle';
Class::Trait->initialize;
END_PACKAGE

ok $@, 'Trying to use a non-trait as a trait should fail';
like $@,
  qr/\QCircle is not a proper trait (inherits from Class::Trait::Base)\E/,
  '... telling us that it\'s not a trait';

clean_inc();
eval <<'END_PACKAGE';
package TestTraits;
use Class::Trait 'TDisallowed';
Class::Trait->initialize;
END_PACKAGE

ok $@, 'Trying to use a trait with a disallowed method should fail';
like $@,
  qr/\QTrait TDisallowed attempted to implement disallowed method DESTROY\E/,
  '... telling us what the disallowed method is';

clean_inc();
eval <<'END_PACKAGE';
package TestTraits;
use Class::Trait ( 
    'TSpouse' => { exclude => ['fuse', 'no_such_method' ]    },
    'TBomb'   => { exclude => ['explode'] },
);
Class::Trait->initialize;
END_PACKAGE

ok $@, 'Attempting to exclude a non-existent method should fail';
like $@,
qr/\QAttempt to exclude method (no_such_method) that is not in trait (TSpouse)\E/,
  '... telling us which non-existent method we tried to exclude';

clean_inc();
eval <<'END_PACKAGE';
package TestTraits;
use Class::Trait ( 
    'TSpouse' => { alias   => { no_such_method => 'fuse' } },
    'TBomb'   => { exclude => ['explode'] },
);
Class::Trait->initialize;
END_PACKAGE

ok $@, 'Attempting to alias a non-existent method should fail';
like $@,
qr/\QAttempt to alias method (no_such_method) that is not in trait (TSpouse)\E/,
  '... telling us which non-existent method we tried to alias';