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