#!/usr/bin/perl
use warnings;
use strict;
use utf8;
use open qw(:std :utf8);
use lib qw(lib ../lib);
use Test::More tests => 53;
use Encode qw(decode encode);
BEGIN {
# Подготовка объекта тестирования для работы с utf8
my $builder = Test::More->builder;
binmode $builder->output, ":utf8";
binmode $builder->failure_output, ":utf8";
binmode $builder->todo_output, ":utf8";
use_ok 'DR::Tarantool::Iterator';
}
use constant MODEL => 'DR::Tarantool::Iterator';
is eval { MODEL->new }, undef, 'empty constructor';
like $@, qr{usage:}, 'error message';
my $iter = MODEL->new([1, 2, 3]);
ok $iter, 'constructor';
isa_ok $iter => MODEL;
is $iter->count, 3, '$iter->count';
is $iter->item(0), 1, '$iter->item(0)';
is $iter->item(1), 2, '$iter->item(1)';
is $iter->item(2), 3, '$iter->item(2)';
is $iter->item(-1), 3, '$iter->item(-1)';
is $iter->item(-2), 2, '$iter->item(-2)';
is $iter->item(-3), 1, '$iter->item(-3)';
is eval { $iter->item(3) }, undef, '$iter->item(3) (out of bound)';
like $@, qr{wrong item number: 3}, 'error message';
is eval { $iter->item(-4) }, undef, '$iter->item(-4) (out of bound)';
like $@, qr{wrong item number: -4}, 'error message';
is eval { $iter->item('abc') }, undef, '$iter->item("abc")';
like $@, qr{wrong item number format: abc}, 'error message';
is eval { $iter->item(undef) }, undef, '$iter->item(undef)';
like $@, qr{wrong item number format: undef}, 'error message';
my @res;
while(my $o = $iter->next) { push @res => $o }
is_deeply \@res, [ 1, 2, 3 ], '$iter->next';
is $iter->next, 1, '$iter->next (first)';
is $iter->reset, 0, '$iter->reset returns old iterator position';
@res = ();
while(my $o = $iter->next) { push @res => $o }
is_deeply \@res, [ 1, 2, 3 ], '$iter->next';
$iter->reset;
is_deeply scalar $iter->all, [ 1, 2, 3 ], '$iter->all';
$iter->next;
is_deeply scalar $iter->all, [ 1, 2, 3 ], '$iter->all (after next)';
@res = ();
while(my $o = $iter->next) { push @res => $o }
is_deeply \@res, [ 2, 3 ], '$iter->next after $iter->all';
is_deeply scalar $iter->all(sub { $_[0] + 1 }), [ 2, 3, 4 ],
'$iter->all(sub { .. })';
is_deeply scalar $iter->all(sub { $_[0] + 1 }, sub { $_[0] + 2 }),
[ [ 2, 3 ], [ 3, 4 ], [ 4, 5 ] ],
'$iter->all(sub { ... }, sub { ... })';
$iter->item_class('Test::Iterator::Class');
$iter->item_constructor('constructor');
my $item = $iter->item(2);
isa_ok $item => 'Test::Iterator::Class';
is eval { $item->value }, 3, '$item->value';
$iter->reset;
$iter->item_constructor(undef);
$item = $iter->next;
isa_ok $item => 'Test::Iterator::Class';
is $$item, 1, 'blessed (not constructed)';
$item = $iter->next;
isa_ok $item => 'Test::Iterator::Class';
is $$item, 2, 'blessed (not constructed)';
$iter->item_class(undef);
$item = $iter->next;
is $item, 3, 'unblessed item';
$iter = MODEL->new([3, 4, 5],
item_class => [ 'Test::Iterator::Class', 'constructor' ]
);
isa_ok $iter->next, 'Test::Iterator::Class';
is eval { $iter->next->value }, 4, '$iter->item(1)->value';
$iter = MODEL->new([ 5, 6, 7 ],
item_class => 'Test::Iterator::Class',
item_constructor => 'constructor'
);
isa_ok $iter->next, 'Test::Iterator::Class';
is eval { $iter->next->value }, 6, '$iter->item(1)->value';
$iter = MODEL->new(
[ 8, 9, 10 ],
item_class => 'Test::Iterator::Class',
data => { 1 => [ 2, 3] }
);
isa_ok $iter->next, 'Test::Iterator::Class';
is eval { ${ $iter->next } }, 9, '$iter->item(1) usually blessed';
is_deeply $iter->data, { 1 => [ 2, 3] }, '$iter->data (get)';
is_deeply $iter->data([ 4, { 5 => 6} ]), [ 4, { 5 => 6 } ], '$iter->data (set)';
is_deeply $iter->data, [ 4, { 5 => 6 } ], '$iter->data (get)';
$iter = MODEL->new([3, 2, 1, 102, 0, -10]);
my $iter2 = $iter->clone(1);
my $iter3 = $iter->clone;
$iter->raw_sort(sub { $_[0] <=> $_[1] });
is_deeply [ $iter->all ], [ -10, 0, 1, 2, 3, 102 ], 'raw_sort';
is_deeply [ $iter3->all ], [ $iter->all ], '->clone(0)->raw_sort';
is_deeply [ $iter2->all ], [ 3, 2, 1, 102, 0, -10 ], '->clone(1)->raw_sort';
$iter->item_class('Test::Iterator::Class', 'constructor');
$iter->sort(sub { $_[1]->value <=> $_[0]->value });
$iter->item_class(undef, undef);
is_deeply scalar $iter->all, [ 102, 3, 2, 1, 0, -10 ], '->sort';
$iter2 = $iter->grep(sub { $_[0] > 2 });
is_deeply scalar $iter2->all, [ 102, 3 ], '->grep';
$iter2 = $iter->grep(sub { $_[0] > 200 });
is_deeply scalar $iter2->all, [ ], '->grep';
$iter->item_class('Test::Iterator::Class', 'constructor');
$iter->data(\123);
$iter2 = $iter->grep(sub { $_[0]->value < 10 });
$iter3 = $iter->raw_grep(sub { $_[0] < 10 });
$iter2->item_class(undef, undef);
$iter3->item_class(undef, undef);
is_deeply scalar $iter2->all, [ 3, 2, 1, 0, -10 ], '->grep';
is_deeply scalar $iter2->all, scalar $iter3->all, 'raw_grep';
package Test::Iterator::Class;
use Test::More;
sub constructor {
my ($class, $v) = @_;
return bless { value => $v } => ref($class) || $class;
}
sub value {
my ($self) = @_;
return $self->{value};
}