lazy_builder
[gitmo/Moose.git] / t / 700_xs / 001_basic.t
CommitLineData
1ea12c91 1#!/usr/bin/perl
2
3use strict;
4use warnings;
5
6use Test::More;
7use Test::Exception;
8
9BEGIN {
10 plan skip_all => "no XSLoader" unless eval { require XSLoader };
11
12 plan skip_all => $@ unless eval {
13 require Moose;
14 Moose->XSLoader::load($Moose::VERSION);
15 1;
16 };
17
18 plan 'no_plan';
19}
20
f253044f 21{
22 package Moose::XS;
23
24 sub attr_to_meta_instance {
25 my $attr = shift;
26 return $attr->associated_class->get_meta_instance;
27 }
28
fe0194bf 29 # FIXME this needs to be in a header that's written by a perl script
160f9ca7 30 my $i;
31 my %checks = map { $_ => $i++ } qw(
32 Any
33 Undef
34 Defined
35 Str
36 Num
37 Int
38 GlobRef
39 ArrayRef
40 HashRef
41 CodeRef
42 Ref
43 ScalarRef
44 FileHandle
45 RegexpRef
46 Object
47 ClassName
48 );
49
50 # aliases
51 $checks{Bool} = $checks{Item} = $checks{Any};
52 $checks{Value} = $checks{Str};
53
54 sub tc_params {
55 my $tc = shift;
56
57 return ( undef, 0, undef ) unless $tc;
58
59 if ( ref $tc eq 'Moose::Meta::TypeConstraint' or ref $tc eq 'Moose::Meta::TypeConstraint::Parameterizable') {
60 # builtin moose type #
61 return ( $tc, 1, $checks{$tc->name} );
62 } elsif ( $tc->isa("Moose::Meta::TypeConstraint::Class") ) {
63 return ( $tc, 2, $tc->class );
64 } else {
65 warn ref $tc;
66 return ( $tc, 3, $tc->_compiled_type_constraint );
67 }
68 }
69
f253044f 70 sub meta_instance_to_attr_descs {
71 my $mi = shift;
72
73 return (
74 $mi->associated_metaclass->name,
160f9ca7 75 [ map {[
76 $_,
77 [$_->slots],
78
79 $_->is_weak_ref,
80 $_->should_coerce,
81 $_->is_lazy,
82
83 tc_params($_->type_constraint),
84 $_->trigger,
85 $_->initializer,
86
87 $_->has_default,
88 $_->default,
89 $_->builder,
90 ]} $mi->get_all_attributes ]
f253044f 91 );
92 }
93}
94
7d73c8a9 95ok( defined &Moose::XS::new_getter, "new_getter" );
96ok( defined &Moose::XS::new_setter, "new_setter" );
97ok( defined &Moose::XS::new_accessor, "new_accessor" );
98ok( defined &Moose::XS::new_predicate, "new_predicate" );
1ea12c91 99
100{
101 package Foo;
102 use Moose;
103
104 has x => ( is => "rw", predicate => "has_x" );
105 has y => ( is => "ro" );
106 has z => ( reader => "z", setter => "set_z" );
de2f2e97 107 has ref => ( is => "rw", weak_ref => 1 );
4c6fbfb1 108 has i => ( isa => "Int", is => "rw" );
109 has s => ( isa => "Str", is => "rw" );
110 has a => ( isa => "ArrayRef", is => "rw" );
a812574b 111 has o => ( isa => "Object", is => "rw" );
112 has f => ( isa => "Foo", is => "rw" );
113 has c => ( isa => "ClassName", is => "rw" );
fe0194bf 114 has b => ( is => "ro", lazy_build => 1 ); # fixme type constraint checking
115
116 sub _build_b { "builded!" }
160f9ca7 117
a812574b 118 # FIXME Regexp, ScalarRef, parametrized, filehandle
7ce1a351 119
120 package Gorch;
121 use Moose;
122
123 extends qw(Foo);
124
125 package Quxx;
126 use Moose;
127
128 sub isa {
129 return $_[1] eq 'Foo';
130 }
de2f2e97 131}
132
133{
fe0194bf 134 my ( $x, $y, $z, $ref, $a, $s, $i, $o, $f, $c, $b ) = map { Foo->meta->get_attribute($_) } qw(x y z ref a s i o f c b);
de2f2e97 135 $x->Moose::XS::new_accessor("Foo::x");
136 $x->Moose::XS::new_predicate("Foo::has_x");
137 $y->Moose::XS::new_getter("Foo::y");
138 $z->Moose::XS::new_getter("Foo::z");
139 $z->Moose::XS::new_setter("Foo::set_z");
140 $ref->Moose::XS::new_accessor("Foo::ref");
4c6fbfb1 141 $a->Moose::XS::new_accessor("Foo::a");
142 $s->Moose::XS::new_accessor("Foo::s");
143 $i->Moose::XS::new_accessor("Foo::i");
a812574b 144 $o->Moose::XS::new_accessor("Foo::o");
145 $f->Moose::XS::new_accessor("Foo::f");
146 $c->Moose::XS::new_accessor("Foo::c");
fe0194bf 147 $b->Moose::XS::new_accessor("Foo::b");
1ea12c91 148}
149
1ea12c91 150
de2f2e97 151my $ref = [ ];
152
153my $foo = Foo->new( x => "ICKS", y => "WHY", z => "ZEE", ref => $ref );
1ea12c91 154
7d73c8a9 155is( $foo->x, "ICKS", "accessor as reader" );
156is( $foo->y, "WHY", "reader" );
157is( $foo->z, "ZEE", "reader" );
158is( $foo->ref, $ref, "accessor for ref" );
fe0194bf 159is( $foo->b, "builded!", "lazy builder" );
1ea12c91 160
7d73c8a9 161lives_ok { $foo->x("YASE") } "accessor";
1ea12c91 162
7d73c8a9 163is( $foo->x, "YASE", "attr value set by accessor" );
1ea12c91 164
7d73c8a9 165dies_ok { $foo->y("blah") } "reader dies when used as writer";
1ea12c91 166
7d73c8a9 167is( $foo->y, "WHY", "reader" );
1ea12c91 168
7d73c8a9 169dies_ok { $foo->z("blah") } "reader dies when used as writer";
1ea12c91 170
7d73c8a9 171is( $foo->z, "ZEE", "reader" );
1ea12c91 172
7d73c8a9 173lives_ok { $foo->set_z("new") } "writer";
1ea12c91 174
7d73c8a9 175is( $foo->z, "new", "attr set by writer" );
1ea12c91 176
7d73c8a9 177ok( $foo->has_x, "predicate" );
1ea12c91 178
7d73c8a9 179ok( !Foo->new->has_x, "predicate on new obj is false" );
1ea12c91 180
7d73c8a9 181is( $foo->ref, $ref, "ref attr" );
de2f2e97 182
7d73c8a9 183undef $ref;
184is( $foo->ref(), undef, "weak ref detstroyed" );
de2f2e97 185
186$ref = { };
187
188$foo->ref($ref);
7d73c8a9 189is( $foo->ref, $ref, "attr set" );
de2f2e97 190
191undef $ref;
7d73c8a9 192is( $foo->ref(), undef, "weak ref destroyed" );
de2f2e97 193
7ce1a351 194ok( !eval { $foo->a("not a ref"); 1 }, "ArrayRef" );
195ok( !eval { $foo->a(3); 1 }, "ArrayRef" );
196ok( !eval { $foo->a({}); 1 }, "ArrayRef" );
197ok( !eval { $foo->a(undef); 1 }, "ArrayRef" );
198ok( !eval { $foo->i(1.3); 1 }, "Int" );
199ok( !eval { $foo->i("1.3"); 1 }, "Int" );
200ok( !eval { $foo->i("foo"); 1 }, "Int" );
201ok( !eval { $foo->i(undef); 1 }, "Int" );
202ok( !eval { $foo->s(undef); 1 }, "Str" );
203ok( !eval { $foo->s([]); 1 }, "Str" );
204ok( !eval { $foo->o({}); 1 }, "Object" );
205ok( !eval { $foo->o(undef); 1 }, "Object" );
206ok( !eval { $foo->o(42); 1 }, "Object" );
207ok( !eval { $foo->o("hi ho"); 1 }, "Object" );
208ok( !eval { $foo->o(" ho"); 1 }, "Object" );
209ok( !eval { $foo->f(bless {}, "Bar"); 1 }, "Class (Foo)" );
210ok( !eval { $foo->f(undef); 1 }, "Class (Foo)" );
211ok( !eval { $foo->f("foo"); 1 }, "Class (Foo)" );
212ok( !eval { $foo->f(3); 1 }, "Class (Foo)" );
213ok( !eval { $foo->f({}); 1 }, "Class (Foo)" );
214ok( !eval { $foo->f("Foo"); 1 }, "Class (Foo)" );
215ok( !eval { $foo->c("Horse"); 1 }, "ClassName" );
216ok( !eval { $foo->c(3); 1 }, "ClassName" );
217ok( !eval { $foo->c(undef); 1 }, "ClassName" );
218ok( !eval { $foo->c("feck"); 1 }, "ClassName" );
219ok( !eval { $foo->c({}); 1 }, "ClassName" );
220
221ok( eval { $foo->a([]); 1 }, "ArrayRef" );
222ok( eval { $foo->i(3); 1 }, "Int" );
223ok( eval { $foo->i("3"); 1 }, "Int" );
224ok( eval { $foo->i("-3"); 1 }, "Int" );
0be3b17f 225ok( eval { $foo->i(" -3 "); 1 }, "Int" );
7ce1a351 226ok( eval { $foo->s("foo"); 1 }, "Str" );
227ok( eval { $foo->s(""); 1 }, "Str" );
228ok( eval { $foo->s(4); 1 }, "Str" );
229ok( eval { $foo->o(bless {}, "Bar"); 1 }, "Object" );
230ok( eval { $foo->f(Foo->new); 1 }, "Class (Foo)" );
231ok( eval { $foo->f(Gorch->new); 1 }, "Class (Foo), real subclass");
232ok( eval { $foo->f(Quxx->new); 1 }, "Class (Foo), fake subclass");
233ok( eval { $foo->c("Foo"); 1 }, "ClassName" );
234
235
236
237$foo->meta->invalidate_meta_instance();
238isa_ok( $foo->f, 'Foo' );
239$foo->meta->invalidate_meta_instance();
240isa_ok( $foo->f, 'Foo' );