Added introspection methods for method modifiers, along with tests.
[gitmo/Class-MOP.git] / t / 031_method_modifiers.t
1 #!/usr/bin/perl
2
3 use strict;
4 use warnings;
5
6 use Test::More tests => 28;
7 use Test::Exception;
8
9 use Class::MOP;
10 use Class::MOP::Method;
11
12 # test before and afters
13 {
14     my $trace = '';
15
16     my $method = Class::MOP::Method->wrap(
17         body => sub { $trace .= 'primary' },
18         package_name => 'main',
19         name         => '__ANON__',
20     );
21     isa_ok( $method, 'Class::MOP::Method' );
22
23     $method->();
24     is( $trace, 'primary', '... got the right return value from method' );
25     $trace = '';
26
27     my $wrapped = Class::MOP::Method::Wrapped->wrap($method);
28     isa_ok( $wrapped, 'Class::MOP::Method::Wrapped' );
29     isa_ok( $wrapped, 'Class::MOP::Method' );
30
31     $wrapped->();
32     is( $trace, 'primary',
33         '... got the right return value from the wrapped method' );
34     $trace = '';
35
36     lives_ok {
37         $wrapped->add_before_modifier( sub { $trace .= 'before -> ' } );
38     }
39     '... added the before modifier okay';
40
41     $wrapped->();
42     is( $trace, 'before -> primary',
43         '... got the right return value from the wrapped method (w/ before)'
44     );
45     $trace = '';
46
47     lives_ok {
48         $wrapped->add_after_modifier( sub { $trace .= ' -> after' } );
49     }
50     '... added the after modifier okay';
51
52     $wrapped->();
53     is( $trace, 'before -> primary -> after',
54         '... got the right return value from the wrapped method (w/ before)'
55     );
56     $trace = '';
57 }
58
59 # test around method
60 {
61     my $method = Class::MOP::Method->wrap(
62         sub {4},
63         package_name => 'main',
64         name         => '__ANON__',
65     );
66     isa_ok( $method, 'Class::MOP::Method' );
67
68     is( $method->(), 4, '... got the right value from the wrapped method' );
69
70     my $wrapped = Class::MOP::Method::Wrapped->wrap($method);
71     isa_ok( $wrapped, 'Class::MOP::Method::Wrapped' );
72     isa_ok( $wrapped, 'Class::MOP::Method' );
73
74     is( $wrapped->(), 4, '... got the right value from the wrapped method' );
75
76     lives_ok {
77         $wrapped->add_around_modifier( sub { ( 3, $_[0]->() ) } );
78         $wrapped->add_around_modifier( sub { ( 2, $_[0]->() ) } );
79         $wrapped->add_around_modifier( sub { ( 1, $_[0]->() ) } );
80         $wrapped->add_around_modifier( sub { ( 0, $_[0]->() ) } );
81     }
82     '... added the around modifier okay';
83
84     is_deeply(
85         [ $wrapped->() ],
86         [ 0, 1, 2, 3, 4 ],
87         '... got the right results back from the around methods (in list context)'
88     );
89
90     is( scalar $wrapped->(), 4,
91         '... got the right results back from the around methods (in scalar context)'
92     );
93 }
94
95 {
96     my @tracelog;
97
98     my $method = Class::MOP::Method->wrap(
99         sub { push @tracelog => 'primary' },
100         package_name => 'main',
101         name         => '__ANON__',
102     );
103     isa_ok( $method, 'Class::MOP::Method' );
104
105     my $wrapped = Class::MOP::Method::Wrapped->wrap($method);
106     isa_ok( $wrapped, 'Class::MOP::Method::Wrapped' );
107     isa_ok( $wrapped, 'Class::MOP::Method' );
108
109     lives_ok {
110         $wrapped->add_before_modifier( sub { push @tracelog => 'before 1' } );
111         $wrapped->add_before_modifier( sub { push @tracelog => 'before 2' } );
112         $wrapped->add_before_modifier( sub { push @tracelog => 'before 3' } );
113     }
114     '... added the before modifier okay';
115
116     lives_ok {
117         $wrapped->add_around_modifier(
118             sub { push @tracelog => 'around 1'; $_[0]->(); } );
119         $wrapped->add_around_modifier(
120             sub { push @tracelog => 'around 2'; $_[0]->(); } );
121         $wrapped->add_around_modifier(
122             sub { push @tracelog => 'around 3'; $_[0]->(); } );
123     }
124     '... added the around modifier okay';
125
126     lives_ok {
127         $wrapped->add_after_modifier( sub { push @tracelog => 'after 1' } );
128         $wrapped->add_after_modifier( sub { push @tracelog => 'after 2' } );
129         $wrapped->add_after_modifier( sub { push @tracelog => 'after 3' } );
130     }
131     '... added the after modifier okay';
132
133     $wrapped->();
134     is_deeply(
135         \@tracelog,
136         [
137             'before 3', 'before 2', 'before 1',    # last-in-first-out order
138             'around 3', 'around 2', 'around 1',    # last-in-first-out order
139             'primary',
140             'after 1', 'after 2', 'after 3',       # first-in-first-out order
141         ],
142         '... got the right tracelog from all our before/around/after methods'
143     );
144 }
145
146 # test introspection
147 {
148     sub before1 {
149     }
150
151     sub before2 {
152     }
153
154     sub before3 {
155     }
156
157     sub after1 {
158     }
159
160     sub after2 {
161     }
162
163     sub after3 {
164     }
165
166     sub around1 {
167     }
168
169     sub around2 {
170     }
171
172     sub around3 {
173     }
174
175     sub orig {
176     }
177
178     my $method = Class::MOP::Method->wrap(
179         body         => \&orig,
180         package_name => 'main',
181         name         => '__ANON__',
182     );
183
184     my $wrapped = Class::MOP::Method::Wrapped->wrap($method);
185
186     $wrapped->add_before_modifier($_)
187         for \&before1, \&before2, \&before3;
188
189     $wrapped->add_after_modifier($_)
190         for \&after1, \&after2, \&after3;
191
192     $wrapped->add_around_modifier($_)
193         for \&around1, \&around2, \&around3;
194
195     is( $wrapped->get_original_method, $method,
196         'check get_original_method' );
197
198     is_deeply( [ $wrapped->before_modifiers ],
199                [ \&before3, \&before2, \&before1 ],
200                'check before_modifiers' );
201
202     is_deeply( [ $wrapped->after_modifiers ],
203                [ \&after1, \&after2, \&after3 ],
204                'check after_modifiers' );
205
206     is_deeply( [ $wrapped->around_modifiers ],
207                [ \&around3, \&around2, \&around1 ],
208                'check around_modifiers' );
209 }
210