3
# $Id: errors.t 1379 2005-03-09 18:27:05Z theory $
5
##############################################################################
7
##############################################################################
9
use Test::More $] < 5.008
10
? (skip_all => 'Older Carp lacks @CARP_NOT support')
13
my $fn = File::Spec->catfile('t', 'errors.t');
16
main::use_ok('Class::Meta');
17
main::use_ok('Class::Meta::Types::String');
20
##############################################################################
21
# Packages we'll use for testing type errors.
24
$INC{'NoAttrBuild.pm'} = __FILE__;
28
$INC{'NoAttrGet.pm'} = __FILE__;
33
$INC{'NoAttrSet.pm'} = __FILE__;
35
##############################################################################
36
# Create some simple classes.
37
##############################################################################
39
package Class::Meta::Testing;
42
my $cm = Class::Meta->new;
43
$cm->add_constructor( name => 'new' );
44
$cm->add_attribute( name => 'tail', type => 'string' );
48
package Class::Meta::TestAbstract;
49
@Class::Meta::TestAbstract::ISA = qw(Class::Meta::Testing);
52
my $cm = Class::Meta->new(abstract => 1);
58
##############################################################################
59
# Test Class::Meta errors.
60
eval { Class::Meta->new('foobar') };
61
chk('odd number to Class::Meta->new',
62
qr/Odd number of parameters in call to new()/);
64
my $cm = Class::Meta->new( package => 'foobar' );
65
eval { Class::Meta->new( package => 'foobar' ) };
67
##############################################################################
68
# Test Class::Meta::Attribute errors.
69
eval { Class::Meta::Attribute->new };
70
chk('Attribute->new protected',
71
qr/ cannot create Class::Meta::Attribute objects/);
73
eval { $cm->add_attribute('foo') };
74
chk('odd number to Class::Meta::Attribute->new',
75
qr/Odd number of parameters in call to new()/);
77
eval { $cm->add_attribute(desc => 'foo') };
78
chk('Attribute name required',
79
qr/Parameter 'name' is required in call to new()/);
81
eval { $cm->add_attribute(name => 'fo&o') };
82
chk('Invalid attribute name',
83
qr/Attribute 'fo&o' is not a valid attribute name/);
85
# Create an attribute to use for a few tests. It's private so that there are
87
ok( my $attr = $cm->add_attribute( name => 'foo',
89
view => Class::Meta::PRIVATE),
90
"Create 'foo' attribute");
92
eval { $cm->add_attribute( name => 'foo') };
93
chk('Attribute exists', qr/Attribute 'foo' already exists/);
95
for my $p (qw(view authz create context)) {
96
eval { $cm->add_attribute( name => 'hey', $p => 100) };
97
chk("Invalid Attribute $p", qr/Not a valid $p parameter: '100'/);
101
chk('No attribute get method', qr/Cannot get attribute 'foo'/);
104
chk('No attribute set method', qr/Cannot set attribute 'foo'/);
106
eval { $attr->build };
107
chk('Attribute->build protected',
108
qr/ cannot call Class::Meta::Attribute->build/);
110
##############################################################################
111
# Test Class::Meta::Class errors.
112
eval { Class::Meta::Class->new };
113
chk('Class->new protected',
114
qr/ cannot create Class::Meta::Class objects/);
116
eval { Class::Meta->new( package => 'foobar' ) };
117
chk('Duplicate class', qr/Class object for class 'foobar' already exists/);
119
eval { $cm->class->build };
120
chk('Class->build protected',
121
qr/ cannot call Class::Meta::Class->build/);
123
##############################################################################
124
# Test Class::Meta::Constructor errors.
125
my $ctor = $cm->class->constructors('new');
126
eval { Class::Meta::Constructor->new };
127
chk('Constructor->new protected',
128
qr/ cannot create Class::Meta::Constructor objects/);
130
eval { $cm->add_constructor('foo') };
131
chk('odd number to Class::Meta::Constructor->new',
132
qr/Odd number of parameters in call to new()/);
134
eval { $cm->add_constructor(desc => 'foo') };
135
chk('Constructor name required',
136
qr/Parameter 'name' is required in call to new()/);
138
eval { $cm->add_constructor(name => 'fo&o') };
139
chk('Invalid constructor name',
140
qr/Constructor 'fo&o' is not a valid constructor name/);
142
# Create an constructor to use for a few tests. It's private so that it
143
# can't be called from here.
144
ok( $ctor = $cm->add_constructor( name => 'newer',
145
view => Class::Meta::PRIVATE),
146
"Create 'newer' constructor");
148
eval { $cm->add_constructor( name => 'newer') };
149
chk('Constructor exists', qr/Method 'newer' already exists/);
151
eval { $cm->add_constructor( name => 'hey', view => 100) };
152
chk("Invalid Constructor view", qr/Not a valid view parameter: '100'/);
154
eval { $cm->add_constructor( name => 'hey', caller => 100) };
155
chk("Invalid Constructor caller",
156
qr/Parameter caller must be a code reference/);
158
eval { $ctor->call };
159
chk('Cannot call constructor', qr/Cannot call constructor 'newer'/);
161
eval { $ctor->build };
162
chk('Constructor->build protected',
163
qr/ cannot call Class::Meta::Constructor->build/);
165
# Make sure that the actual constructor's own errors are thrown.
166
eval { Class::Meta::Testing->new( foo => 1 ) };
167
chk('Invalid parameter to generated constructor',
168
qr/No such attribute 'foo' in Class::Meta::Testing objects/);
170
##############################################################################
171
# Test Class::Meta::Method errors.
172
eval { Class::Meta::Method->new };
173
chk('Method->new protected',
174
qr/ cannot create Class::Meta::Method objects/);
176
eval { $cm->add_method('foo') };
177
chk('odd number to Class::Meta::Method->new',
178
qr/Odd number of parameters in call to new()/);
180
eval { $cm->add_method(desc => 'foo') };
181
chk('Method name required',
182
qr/Parameter 'name' is required in call to new()/);
184
eval { $cm->add_method(name => 'fo&o') };
185
chk('Invalid method name',
186
qr/Method 'fo&o' is not a valid method name/);
188
# Create an method to use for a few tests. It's private so that it
189
# can't be called from here.
190
ok( my $meth = $cm->add_method( name => 'hail',
191
view => Class::Meta::PRIVATE),
192
"Create 'hail' method");
194
eval { $cm->add_method( name => 'hail') };
195
chk('Method exists', qr/Method 'hail' already exists/);
197
for my $p (qw(view context)) {
198
eval { $cm->add_method( name => 'hey', $p => 100) };
199
chk("Invalid Method $p", qr/Not a valid $p parameter: '100'/);
202
eval { $cm->add_method( name => 'hey', caller => 100) };
203
chk("Invalid Method caller", qr/Parameter caller must be a code reference/);
205
eval { $meth->call };
206
chk('Cannot call method', qr/Cannot call method 'hail'/);
208
##############################################################################
209
# Test Class::Meta::Type errors.
210
eval { Class::Meta::Type->new };
211
chk(' Missing type', qr/Type argument required/);
213
eval { Class::Meta::Type->new('foo') };
214
chk('Invalid type', qr/Type 'foo' does not exist/);
216
eval { Class::Meta::Type->add };
217
chk('Type key required', qr/Parameter 'key' is required/);
219
eval { Class::Meta::Type->add( key => 'foo') };
220
chk('Type name required', qr/Parameter 'name' is required/);
222
eval { Class::Meta::Type->add( key => 'string', name => 'string' ) };
223
chk('Type already exists', qr/Type 'string' already defined/);
225
eval { Class::Meta::Type->add( key => 'foo', name => 'foo', check => {}) };
226
chk('Invalid type check',
227
qr/Paremter 'check' in call to add\(\) must be a code reference/);
229
eval { Class::Meta::Type->add( key => 'foo', name => 'foo', check => [{}]) };
230
chk('Invalid type check array',
231
qr/Paremter 'check' in call to add\(\) must be a code reference/);
234
Class::Meta::Type->add( key => 'foo',
236
builder => 'NoAttrBuild');
238
chk('No build', qr/No such function 'NoAttrBuild::build\(\)'/);
241
Class::Meta::Type->add( key => 'foo',
243
builder => 'NoAttrGet');
245
chk('No attr get', qr/No such function 'NoAttrGet::build_attr_get\(\)'/);
248
Class::Meta::Type->add( key => 'foo',
250
builder => 'NoAttrSet');
252
chk('No attr set', qr/No such function 'NoAttrSet::build_attr_set\(\)'/);
254
eval { Class::Meta::Type->build };
255
chk('Type->build protected', qr/ cannot call Class::Meta::Type->build/);
257
eval { Class::Meta->default_error_handler('') };
258
chk('Bad error handler', qr/Error handler must be a code reference/);
260
# Make sure we get an error for invalid class error handlers.
261
eval { Class::Meta->new(error_handler => '') };
262
chk('Class cannot have invalid error handler',
263
qr/Error handler must be a code reference/);
266
Class::Meta->default_error_handler(sub { $foo = shift });
268
# Some places still use the default, of course.
270
Class::Meta::Type->add( key => 'foo',
272
builder => 'NoAttrSet');
274
like( $foo, qr/No such function 'NoAttrSet::build_attr_set\(\)'/,
275
"New error handler");
277
# Others muse use the original, since the class object was defined before
278
# we set up the new default.
279
eval { $cm->class->build };
280
chk('Class->build still protected',
281
qr/ cannot call Class::Meta::Class->build/);
283
# Test the abstract attribute.
284
is( Class::Meta::Testing->my_class->abstract, 0,
285
"Testing class isn't abstract" );
286
is( Class::Meta::TestAbstract->my_class->abstract, 1,
287
"TestAbstract class isn't abstract" );
289
eval { Class::Meta::TestAbstract->new };
290
chk( 'Cannot create from abstract class',
291
qr/^Cannot construct objects of astract class Class::Meta::TestAbstract/);
293
##############################################################################
294
# This function handles all the tests.
295
##############################################################################
297
my ($name, $qr) = @_;
298
# Catch the exception.
299
ok( my $err = $@, "Caught $name error" );
301
like( $err, $qr, "Correct error" );
302
# Make sure it refers to this file.
303
like( $err, qr/(?:at\s+\Q$fn\E|\Q$fn\E\s+at)\s+line/, 'Correct context' );
304
# Make sure it doesn't refer to other Class::Meta files.
305
unlike( $err, qr|lib/Class/Meta|, 'Not incorrect context')