All of the non-mutating array helpers are now inlined.
[gitmo/Moose.git] / t / 070_native_traits / 202_trait_array.t
CommitLineData
e3c07b19 1#!/usr/bin/perl
2
3use strict;
4use warnings;
5
a28e50e4 6use Test::More;
e3c07b19 7use Test::Exception;
8use Test::Moose 'does_ok';
9
18281451 10my $sort;
862b6081 11my $less;
12my $up;
13my $prod;
14
15my %handles = (
16 add_options => 'push',
17 add_options_with_speed =>
18 [ push => 'funrolls', 'funbuns' ],
19 remove_last_option => 'pop',
20 remove_first_option => 'shift',
21 insert_options => 'unshift',
22 prepend_prerequisites_along_with =>
23 [ unshift => 'first', 'second' ],
24 get_option_at => 'get',
25 set_option_at => 'set',
26 num_options => 'count',
27 options => 'elements',
28 has_no_options => 'is_empty',
29 clear_options => 'clear',
30 splice_options => 'splice',
31 sort_options_in_place => 'sort_in_place',
32 option_accessor => 'accessor',
33 descending_options =>
34 [ sort_in_place => ( $sort = sub { $_[1] <=> $_[0] } ) ],
35 map_options => 'map',
36 up_by_one => [ map => ( $up = sub { $_ + 1 } ) ],
37 filter_options => 'grep',
38 less_than_five => [ grep => ( $less = sub { $_ < 5 } ) ],
39 find_option => 'first',
40 join_options => 'join',
41 dashify => [ join => '-' ],
42 sorted_options => 'sort',
43 randomized_options => 'shuffle',
44 unique_options => 'uniq',
45 pairwise_options => [ natatime => 2 ],
46 reduce => 'reduce',
47 product => [ reduce => ( $prod = sub { $_[0] * $_[1] } ) ],
48);
d50fc84a 49
e3c07b19 50{
d50fc84a 51
e3c07b19 52 package Stuff;
53 use Moose;
54
862b6081 55 has '_options' => (
a40b446a 56 traits => ['Array'],
d50fc84a 57 is => 'ro',
58 isa => 'ArrayRef[Str]',
59 default => sub { [] },
862b6081 60 handles => \%handles,
e3c07b19 61 );
62}
63
862b6081 64{
65 my $stuff = Stuff->new( _options => [ 10, 12 ] );
66 isa_ok( $stuff, 'Stuff' );
e3c07b19 67
862b6081 68 can_ok( $stuff, $_ ) for sort keys %handles;
e3c07b19 69
862b6081 70 is_deeply( $stuff->_options, [ 10, 12 ], '... got options' );
e3c07b19 71
862b6081 72 ok( !$stuff->has_no_options, '... we have options' );
73 is( $stuff->num_options, 2, '... got 2 options' );
e3c07b19 74
862b6081 75 is( $stuff->remove_last_option, 12, '... removed the last option' );
76 is( $stuff->remove_first_option, 10, '... removed the last option' );
e3c07b19 77
862b6081 78 is_deeply( $stuff->_options, [], '... no options anymore' );
e3c07b19 79
862b6081 80 ok( $stuff->has_no_options, '... no options' );
81 is( $stuff->num_options, 0, '... got no options' );
e3c07b19 82
862b6081 83 lives_ok {
84 $stuff->add_options( 1, 2, 3 );
85 }
86 '... set the option okay';
e3c07b19 87
862b6081 88 is_deeply( $stuff->_options, [ 1, 2, 3 ], '... got options now' );
89 is_deeply(
90 [ $stuff->options ], [ 1, 2, 3 ],
91 '... got options now (with elements method)'
92 );
e3c07b19 93
862b6081 94 ok( !$stuff->has_no_options, '... has options' );
95 is( $stuff->num_options, 3, '... got 3 options' );
e3c07b19 96
862b6081 97 is( $stuff->get_option_at(0), 1, '... get option at index 0' );
98 is( $stuff->get_option_at(1), 2, '... get option at index 1' );
99 is( $stuff->get_option_at(2), 3, '... get option at index 2' );
e3c07b19 100
910684ee 101 throws_ok { $stuff->get_option_at() }
102 qr/Must provide a valid index number as an argument/,
103 'throws an error when get_option_at is called without any arguments';
104
105 throws_ok { $stuff->get_option_at( {} ) }
106 qr/Must provide a valid index number as an argument/,
107 'throws an error when get_option_at is called with an invalid argument';
108
109 throws_ok { $stuff->get_option_at(2.2) }
110 qr/Must provide a valid index number as an argument/,
111 'throws an error when get_option_at is called with an invalid argument';
112
113 throws_ok { $stuff->get_option_at('foo') }
114 qr/Must provide a valid index number as an argument/,
115 'throws an error when get_option_at is called with an invalid argument';
116
862b6081 117 lives_ok {
118 $stuff->set_option_at( 1, 100 );
119 }
120 '... set the option okay';
e3c07b19 121
862b6081 122 is( $stuff->get_option_at(1), 100, '... get option at index 1' );
e3c07b19 123
862b6081 124 lives_ok {
125 $stuff->add_options( 10, 15 );
126 }
127 '... set the option okay';
e3c07b19 128
862b6081 129 is_deeply(
130 $stuff->_options, [ 1, 100, 3, 10, 15 ],
131 '... got more options now'
132 );
e3c07b19 133
862b6081 134 is( $stuff->num_options, 5, '... got 5 options' );
e3c07b19 135
862b6081 136 is( $stuff->remove_last_option, 15, '... removed the last option' );
e3c07b19 137
862b6081 138 is( $stuff->num_options, 4, '... got 4 options' );
139 is_deeply(
140 $stuff->_options, [ 1, 100, 3, 10 ],
141 '... got diff options now'
142 );
e3c07b19 143
862b6081 144 lives_ok {
145 $stuff->insert_options( 10, 20 );
146 }
147 '... set the option okay';
e3c07b19 148
862b6081 149 is( $stuff->num_options, 6, '... got 6 options' );
150 is_deeply(
151 $stuff->_options, [ 10, 20, 1, 100, 3, 10 ],
152 '... got diff options now'
153 );
e3c07b19 154
862b6081 155 is( $stuff->get_option_at(0), 10, '... get option at index 0' );
156 is( $stuff->get_option_at(1), 20, '... get option at index 1' );
157 is( $stuff->get_option_at(3), 100, '... get option at index 3' );
e3c07b19 158
862b6081 159 is( $stuff->remove_first_option, 10, '... getting the first option' );
e3c07b19 160
862b6081 161 is( $stuff->num_options, 5, '... got 5 options' );
162 is( $stuff->get_option_at(0), 20, '... get option at index 0' );
e3c07b19 163
862b6081 164 $stuff->clear_options;
165 is_deeply( $stuff->_options, [], "... clear options" );
e3c07b19 166
862b6081 167 $stuff->add_options( 5, 1, 2, 3 );
168 $stuff->sort_options_in_place;
169 is_deeply(
170 $stuff->_options, [ 1, 2, 3, 5 ],
171 "... sort options in place (default sort order)"
172 );
59de9de4 173
862b6081 174 $stuff->sort_options_in_place( sub { $_[1] <=> $_[0] } );
175 is_deeply(
176 $stuff->_options, [ 5, 3, 2, 1 ],
177 "... sort options in place (descending order)"
178 );
59de9de4 179
862b6081 180 $stuff->clear_options();
181 $stuff->add_options( 5, 1, 2, 3 );
182 lives_ok {
183 $stuff->descending_options();
184 }
185 '... curried sort in place lives ok';
59de9de4 186
862b6081 187 is_deeply( $stuff->_options, [ 5, 3, 2, 1 ], "... sort currying" );
59de9de4 188
862b6081 189 throws_ok { $stuff->sort_options_in_place('foo') }
190 qr/Argument must be a code reference/,
191 'error when sort_in_place receives a non-coderef argument';
59de9de4 192
862b6081 193 $stuff->clear_options;
59de9de4 194
862b6081 195 lives_ok {
196 $stuff->add_options('tree');
197 }
198 '... set the options okay';
59de9de4 199
862b6081 200 lives_ok {
201 $stuff->add_options_with_speed( 'compatible', 'safe' );
202 }
203 '... add options with speed okay';
59de9de4 204
862b6081 205 is_deeply(
206 $stuff->_options, [qw/tree funrolls funbuns compatible safe/],
207 'check options after add_options_with_speed'
208 );
59de9de4 209
862b6081 210 lives_ok {
211 $stuff->prepend_prerequisites_along_with();
212 }
213 '... add prerequisite options okay';
214
215 $stuff->clear_options;
216 $stuff->add_options( 1, 2 );
59de9de4 217
862b6081 218 lives_ok {
219 $stuff->splice_options( 1, 0, 'foo' );
220 }
221 '... splice_options works';
59de9de4 222
862b6081 223 is_deeply(
224 $stuff->_options, [ 1, 'foo', 2 ],
225 'splice added expected option'
226 );
227
228 is(
229 $stuff->option_accessor( 1 => 'foo++' ), 'foo++',
230 'set using accessor method'
231 );
232 is( $stuff->option_accessor(1), 'foo++', 'get using accessor method' );
233
234 dies_ok {
235 $stuff->insert_options(undef);
236 }
237 '... could not add an undef where a string is expected';
238
239 dies_ok {
240 $stuff->set_option( 5, {} );
241 }
242 '... could not add a hash ref where a string is expected';
243
244 dies_ok {
245 Stuff->new( _options => [ undef, 10, undef, 20 ] );
246 }
247 '... bad constructor params';
248
249 dies_ok {
250 my $stuff = Stuff->new();
251 $stuff->add_options(undef);
252 }
253 '... rejects push of an invalid type';
254
255 dies_ok {
256 my $stuff = Stuff->new();
257 $stuff->insert_options(undef);
258 }
259 '... rejects unshift of an invalid type';
260
261 dies_ok {
262 my $stuff = Stuff->new();
263 $stuff->set_option_at( 0, undef );
264 }
265 '... rejects set of an invalid type';
266
267 dies_ok {
268 my $stuff = Stuff->new();
269 $stuff->sort_in_place_options(undef);
270 }
271 '... sort rejects arg of invalid type';
272
273 dies_ok {
274 my $stuff = Stuff->new();
275 $stuff->option_accessor();
276 }
277 '... accessor rejects 0 args';
278
279 dies_ok {
280 my $stuff = Stuff->new();
281 $stuff->option_accessor( 1, 2, 3 );
282 }
283 '... accessor rejects 3 args';
d50fc84a 284}
59de9de4 285
862b6081 286{
287 my $stuff = Stuff->new( _options => [ 1 .. 10 ] );
59de9de4 288
862b6081 289 is_deeply( $stuff->_options, [ 1 .. 10 ], '... got options' );
59de9de4 290
862b6081 291 ok( !$stuff->has_no_options, '... we have options' );
292 is( $stuff->num_options, 10, '... got 2 options' );
293 cmp_ok( $stuff->get_option_at(0), '==', 1, '... get option 0' );
e3c07b19 294
862b6081 295 is_deeply(
296 [ $stuff->filter_options( sub { $_ % 2 == 0 } ) ],
297 [ 2, 4, 6, 8, 10 ],
298 '... got the right filtered values'
299 );
59de9de4 300
910684ee 301 throws_ok { $stuff->filter_options() }
302 qr/Must provide a code reference as an argument/,
303 'throws an error when filter_options is called without any arguments';
304
305 throws_ok { $stuff->filter_options( {} ) }
306 qr/Must provide a code reference as an argument/,
307 'throws an error when filter_options is called with an invalid argument';
308
862b6081 309 is_deeply(
310 [ $stuff->map_options( sub { $_ * 2 } ) ],
311 [ 2, 4, 6, 8, 10, 12, 14, 16, 18, 20 ],
312 '... got the right mapped values'
313 );
e3c07b19 314
910684ee 315 throws_ok { $stuff->map_options() }
316 qr/Must provide a code reference as an argument/,
317 'throws an error when map_options is called without any arguments';
318
319 throws_ok { $stuff->map_options( {} ) }
320 qr/Must provide a code reference as an argument/,
321 'throws an error when map_options is called with an invalid argument';
322
862b6081 323 is(
324 $stuff->find_option( sub { $_ % 2 == 0 } ), 2,
325 '.. found the right option'
326 );
59de9de4 327
910684ee 328 throws_ok { $stuff->find_option() }
329 qr/Must provide a code reference as an argument/,
330 'throws an error when find_option is called without any arguments';
331
332 throws_ok { $stuff->find_option( {} ) }
333 qr/Must provide a code reference as an argument/,
334 'throws an error when find_option is called with an invalid argument';
335
862b6081 336 is_deeply(
337 [ $stuff->options ], [ 1 .. 10 ],
338 '... got the list of options'
339 );
e3c07b19 340
862b6081 341 is(
342 $stuff->join_options(':'), '1:2:3:4:5:6:7:8:9:10',
343 '... joined the list of options by :'
344 );
e3c07b19 345
910684ee 346 throws_ok { $stuff->join_options() }
347 qr/Must provide a string as an argument/,
348 'throws an error when join_options is called without any arguments';
349
350 throws_ok { $stuff->join_options( {} ) }
351 qr/Must provide a string as an argument/,
352 'throws an error when join_options is called with an invalid argument';
353
862b6081 354 is_deeply(
355 [ $stuff->sorted_options ], [ sort ( 1 .. 10 ) ],
356 '... got sorted options (default sort order)'
357 );
358 is_deeply(
359 [ $stuff->sorted_options( sub { $_[1] <=> $_[0] } ) ],
360 [ sort { $b <=> $a } ( 1 .. 10 ) ],
361 '... got sorted options (descending sort order) '
362 );
59de9de4 363
862b6081 364 throws_ok { $stuff->sorted_options('foo') }
365 qr/Argument must be a code reference/,
366 'error when sort receives a non-coderef argument';
367
368 is_deeply(
369 [ sort { $a <=> $b } $stuff->randomized_options ],
370 [ 1 .. 10 ],
371 'randomized_options returns all options'
372 );
373
374 my @pairs;
375 $stuff->pairwise_options( sub { push @pairs, [@_] } );
376 is_deeply(
377 \@pairs,
378 [ [ 1, 2 ], [ 3, 4 ], [ 5, 6 ], [ 7, 8 ], [ 9, 10 ] ],
379 'pairwise returns pairs as expected'
380 );
381
382 is_deeply(
383 [ $stuff->less_than_five() ], [ 1 .. 4 ],
384 'less_than_five returns 1..4'
385 );
59de9de4 386
862b6081 387 is_deeply(
388 [ $stuff->up_by_one() ], [ 2 .. 11 ],
389 'up_by_one returns 2..11'
390 );
391
392 is(
393 $stuff->dashify, '1-2-3-4-5-6-7-8-9-10',
394 'dashify returns options joined by dashes'
395 );
396
397 is(
910684ee 398 $stuff->reduce( sub { $_[0] * $_[1] } ),
399 3628800,
400 'call reducing to generate a product returns expected value'
401 );
402
403 throws_ok { $stuff->reduce() }
404 qr/Must provide a code reference as an argument/,
405 'throws an error when reduce is called without any arguments';
406
407 throws_ok { $stuff->reduce( {} ) }
408 qr/Must provide a code reference as an argument/,
409 'throws an error when reduce is called with an invalid argument';
410
411 is(
862b6081 412 $stuff->product, 3628800,
413 'product returns expected value'
414 );
415
416 my $other_stuff = Stuff->new( _options => [ 1, 1, 2, 3, 5 ] );
417 is_deeply(
418 [ $other_stuff->unique_options ], [ 1, 2, 3, 5 ],
419 'unique_options returns unique options'
420 );
d50fc84a 421}
d50fc84a 422
862b6081 423{
424 my $options = Stuff->meta->get_attribute('_options');
425 does_ok( $options, 'Moose::Meta::Attribute::Native::Trait::Array' );
426
427 is_deeply(
428 $options->handles, \%handles,
429 '... got the right handles mapping'
430 );
431
432 is(
433 $options->type_constraint->type_parameter, 'Str',
434 '... got the right container type'
435 );
436}
a28e50e4 437
438done_testing;