# -*- cperl -*-
use ExtUtils::testlib;
use Test::More tests => 24;
use Test::Memory::Cycle;
use Config::Model;
use warnings;
no warnings qw(once);
use strict;
use Data::Dumper;
# use Config::Model::ObjTreeScanner;
use vars qw/$model/;
$model = Config::Model->new( legacy => 'ignore', );
my $arg = shift || '';
my $trace = $arg =~ /t/ ? 1 : 0;
Config::Model::Exception::Any->Trace(1) if $arg =~ /e/;
$Data::Dumper::Indent = 1;
use Log::Log4perl qw(:easy);
Log::Log4perl->easy_init( $arg =~ /l/ ? $TRACE : $WARN );
ok( 1, "compiled" );
my $inst = $model->instance(
root_class_name => 'Master',
model_file => 't/big_model.pm',
instance_name => 'test1'
);
ok( $inst, "created dummy instance" );
my $root = $inst->config_root;
ok( $root, "created root" );
Config::Model::Exception::Any->Trace(1) if $trace =~ /e/;
my @data = ( [
'Z',
"std_id:foo",
{
'Z' => { 'next_step' => { 'Z' => '' } },
'X' => { 'next_step' => { 'X' => '' } },
'DX' => { 'next_step' => { 'DX' => '' } } }
],
[
'ab2', 'warp',
{
'ab2' => {
'next_step' => {
'warp2' =>
{ 'next_class' => { 'SubSlave2' => { 'next_step' => { 'ab2' => '' } } } },
'sub_slave' =>
{ 'next_step' => { 'sub_slave' => { 'next_step' => { 'ab2' => '' } } } } }
},
'aa2' => {
'next_step' => {
'warp2' =>
{ 'next_class' => { 'SubSlave2' => { 'next_step' => { 'aa2' => '' } } } },
'sub_slave' =>
{ 'next_step' => { 'sub_slave' => { 'next_step' => { 'aa2' => '' } } } } }
},
'X' => { 'next_step' => { 'X' => '', 'std_id' => { 'next_step' => { 'X' => '' } } } },
'ac' => { 'next_step' => { 'sub_slave' => { 'next_step' => { 'ac' => '' } } } },
'Y' => { 'next_step' => { 'Y' => '' } },
'DX' => { 'next_step' => { 'std_id' => { 'next_step' => { 'DX' => '' } } } },
'Z' => {
'next_step' => {
'warp2' =>
{ 'next_class' => { 'SubSlave2' => { 'next_step' => { 'Z' => '' } } } },
'std_id' => { 'next_step' => { 'Z' => '' } },
'sub_slave' =>
{ 'next_step' => { 'sub_slave' => { 'next_step' => { 'Z' => '' } } } } }
},
'ab' => { 'next_step' => { 'sub_slave' => { 'next_step' => { 'ab' => '' } } } },
'ad2' => {
'next_step' => {
'warp2' =>
{ 'next_class' => { 'SubSlave2' => { 'next_step' => { 'ad2' => '' } } } },
'sub_slave' =>
{ 'next_step' => { 'sub_slave' => { 'next_step' => { 'ad2' => '' } } } } }
},
'ad' => { 'next_step' => { 'sub_slave' => { 'next_step' => { 'ad' => '' } } } },
'aa' => { 'next_step' => { 'sub_slave' => { 'next_step' => { 'aa' => '' } } } },
'ac2' => {
'next_step' => {
'warp2' =>
{ 'next_class' => { 'SubSlave2' => { 'next_step' => { 'ac2' => '' } } } },
'sub_slave' =>
{ 'next_step' => { 'sub_slave' => { 'next_step' => { 'ac2' => '' } } } } } }
}
],
[
'Z', '!',
{
'string_with_def' => { 'next_step' => { 'string_with_def' => '' } },
'aa2' => {
'next_step' => {
'slave_y' => {
'next_step' => {
'warp2' => {
'next_class' =>
{ 'SubSlave2' => { 'next_step' => { 'aa2' => '' } } }
},
'sub_slave' => {
'next_step' => { 'sub_slave' => { 'next_step' => { 'aa2' => '' } } }
} }
},
'warp' => {
'next_class' => {
'SlaveY' => {
'next_step' => {
'warp2' => {
'next_class' =>
{ 'SubSlave2' => { 'next_step' => { 'aa2' => '' } } }
},
'sub_slave' => {
'next_step' =>
{ 'sub_slave' => { 'next_step' => { 'aa2' => '' } } } }
} } } } }
},
'Y' => {
'next_step' => {
'slave_y' => { 'next_step' => { 'Y' => '' } },
'warp' => { 'next_class' => { 'SlaveY' => { 'next_step' => { 'Y' => '' } } } } }
},
'DX' => {
'next_step' => {
'slave_y' =>
{ 'next_step' => { 'std_id' => { 'next_step' => { 'DX' => '' } } } },
'olist' => { 'next_step' => { 'DX' => '' } },
'warp' => {
'next_class' => {
'SlaveZ' => { 'next_step' => { 'DX' => '' } },
'SlaveY' => {
'next_step' => { 'std_id' => { 'next_step' => { 'DX' => '' } } } } }
},
'std_id' => { 'next_step' => { 'DX' => '' } } }
},
'Z' => {
'next_step' => {
'slave_y' => {
'next_step' => {
'warp2' => {
'next_class' => { 'SubSlave2' => { 'next_step' => { 'Z' => '' } } }
},
'std_id' => { 'next_step' => { 'Z' => '' } },
'sub_slave' => {
'next_step' => { 'sub_slave' => { 'next_step' => { 'Z' => '' } } } }
}
},
'olist' => { 'next_step' => { 'Z' => '' } },
'warp' => {
'next_class' => {
'SlaveZ' => { 'next_step' => { 'Z' => '' } },
'SlaveY' => {
'next_step' => {
'warp2' => {
'next_class' =>
{ 'SubSlave2' => { 'next_step' => { 'Z' => '' } } }
},
'std_id' => { 'next_step' => { 'Z' => '' } },
'sub_slave' => {
'next_step' =>
{ 'sub_slave' => { 'next_step' => { 'Z' => '' } } } } }
} }
},
'std_id' => { 'next_step' => { 'Z' => '' } } }
},
'ad2' => {
'next_step' => {
'slave_y' => {
'next_step' => {
'warp2' => {
'next_class' =>
{ 'SubSlave2' => { 'next_step' => { 'ad2' => '' } } }
},
'sub_slave' => {
'next_step' => { 'sub_slave' => { 'next_step' => { 'ad2' => '' } } }
} }
},
'warp' => {
'next_class' => {
'SlaveY' => {
'next_step' => {
'warp2' => {
'next_class' =>
{ 'SubSlave2' => { 'next_step' => { 'ad2' => '' } } }
},
'sub_slave' => {
'next_step' =>
{ 'sub_slave' => { 'next_step' => { 'ad2' => '' } } } }
} } } } }
},
'tree_macro' => { 'next_step' => { 'tree_macro' => '' } },
'a_string' => { 'next_step' => { 'a_string' => '' } },
'ad' => {
'next_step' => {
'slave_y' =>
{ 'next_step' => { 'sub_slave' => { 'next_step' => { 'ad' => '' } } } },
'warp' => {
'next_class' => {
'SlaveY' => {
'next_step' => { 'sub_slave' => { 'next_step' => { 'ad' => '' } } }
} } } }
},
'ordered_hash' => { 'next_step' => { 'ordered_hash' => '' } },
'aa' => {
'next_step' => {
'slave_y' =>
{ 'next_step' => { 'sub_slave' => { 'next_step' => { 'aa' => '' } } } },
'warp' => {
'next_class' => {
'SlaveY' => {
'next_step' => { 'sub_slave' => { 'next_step' => { 'aa' => '' } } }
} } } }
},
'ac2' => {
'next_step' => {
'slave_y' => {
'next_step' => {
'warp2' => {
'next_class' =>
{ 'SubSlave2' => { 'next_step' => { 'ac2' => '' } } }
},
'sub_slave' => {
'next_step' => { 'sub_slave' => { 'next_step' => { 'ac2' => '' } } }
} }
},
'warp' => {
'next_class' => {
'SlaveY' => {
'next_step' => {
'warp2' => {
'next_class' =>
{ 'SubSlave2' => { 'next_step' => { 'ac2' => '' } } }
},
'sub_slave' => {
'next_step' =>
{ 'sub_slave' => { 'next_step' => { 'ac2' => '' } } } }
} } } } }
},
'lista' => { 'next_step' => { 'lista' => '' } },
'hash_b' => { 'next_step' => { 'hash_b' => '' } },
'ab2' => {
'next_step' => {
'slave_y' => {
'next_step' => {
'warp2' => {
'next_class' =>
{ 'SubSlave2' => { 'next_step' => { 'ab2' => '' } } }
},
'sub_slave' => {
'next_step' => { 'sub_slave' => { 'next_step' => { 'ab2' => '' } } }
} }
},
'warp' => {
'next_class' => {
'SlaveY' => {
'next_step' => {
'warp2' => {
'next_class' =>
{ 'SubSlave2' => { 'next_step' => { 'ab2' => '' } } }
},
'sub_slave' => {
'next_step' =>
{ 'sub_slave' => { 'next_step' => { 'ab2' => '' } } } }
} } } } }
},
'int_v' => { 'next_step' => { 'int_v' => '' } },
'listb' => { 'next_step' => { 'listb' => '' } },
'my_reference' => { 'next_step' => { 'my_reference' => '' } },
'X' => {
'next_step' => {
'slave_y' => {
'next_step' => { 'X' => '', 'std_id' => { 'next_step' => { 'X' => '' } } }
},
'olist' => { 'next_step' => { 'X' => '' } },
'warp' => {
'next_class' => {
'SlaveZ' => { 'next_step' => { 'X' => '' } },
'SlaveY' => {
'next_step' =>
{ 'X' => '', 'std_id' => { 'next_step' => { 'X' => '' } } } } }
},
'std_id' => { 'next_step' => { 'X' => '' } } }
},
'ac' => {
'next_step' => {
'slave_y' =>
{ 'next_step' => { 'sub_slave' => { 'next_step' => { 'ac' => '' } } } },
'warp' => {
'next_class' => {
'SlaveY' => {
'next_step' => { 'sub_slave' => { 'next_step' => { 'ac' => '' } } }
} } } }
},
'a_uniline' => { 'next_step' => { 'a_uniline' => '' } },
'ab' => {
'next_step' => {
'slave_y' =>
{ 'next_step' => { 'sub_slave' => { 'next_step' => { 'ab' => '' } } } },
'warp' => {
'next_class' => {
'SlaveY' => {
'next_step' => { 'sub_slave' => { 'next_step' => { 'ab' => '' } } }
} } } }
},
'my_check_list' => { 'next_step' => { 'my_check_list' => '' } },
'hash_a' => { 'next_step' => { 'hash_a' => '' } } } ] );
my @items = $root->model_searcher->get_searchable_elements;
my @expected = qw/DX X Y Z a_string a_uniline aa aa2 ab ab2 ac ac2 ad ad2
hash_a hash_b int_v lista listb my_check_list
my_reference ordered_hash string_with_def tree_macro/;
is_deeply( \@items, \@expected, "list of searchable items" );
foreach my $item (@data) {
next unless @$item == 3;
my $node = $root->grab( $item->[1] );
my $model_searcher = $node->model_searcher->prepare( element => $item->[0] );
is_deeply( $model_searcher->{data},
$item->[2],
"verify search data on " . $node->config_class_name . "($item->[0],$item->[1])" )
|| print Dumper $model_searcher->{data};
}
my $model_searcher = $root->model_searcher->prepare( element => 'X' );
$root->load("tree_macro=XZ");
my $step = $model_searcher->next_step();
is_deeply( $step, [qw/olist slave_y std_id warp/], 'check first step' );
my $obj = $model_searcher->choose('warp');
is( $obj->name, 'warp', 'check chosen object' );
my $target = $model_searcher->auto_choose( sub { }, sub { } );
is( $target->name, 'warp X', 'check auto chosen object for X' );
$step = $model_searcher->next_step();
is_deeply( $step, [], 'check that no more steps are left' );
# no user choice to look for aa
$root->load("tree_macro=XY");
$model_searcher = $root->model_searcher->prepare( element => 'aa' );
$model_searcher->choose('warp');
$target = $model_searcher->auto_choose( sub { }, sub { } );
is( $target->name, 'warp sub_slave aa', 'check auto chosen object for aa' );
# try choose_next
$model_searcher = $root->model_searcher->prepare( element => 'aa' );
$model_searcher->choose('warp');
$step = $model_searcher->next_choice();
is_deeply( $step, [], 'check that no more steps are left after next_choice' );
$target = $model_searcher->current_object;
is( $target->name, 'warp sub_slave aa', 'check chosen object for aa' );
$model_searcher = $root->model_searcher->prepare( element => 'DX' );
$root->load("tree_macro=XZ");
my $cb1 = sub {
my $object = shift;
is( $object->config_class_name, 'Master', 'check object of element call-back (DX))' );
is_deeply( [@_], [qw/olist slave_y std_id warp/], 'check param of element call-back (DX)' );
return 'warp';
};
$target = $model_searcher->auto_choose( $cb1, sub { } );
is( $target->name, 'warp DX', 'check auto chosen object for DX (warp)' );
# restart and try through olist
$model_searcher->reset;
$target = $model_searcher->auto_choose( sub { 'olist' }, sub { return 1; } );
is( $target->name, 'olist:1 DX', 'check auto_choose target for DX (olist)' );
# restart and try through std_d
$model_searcher->reset;
$target = $model_searcher->auto_choose( sub { 'std_id' }, sub { return 'foo'; } );
is( $target->name, 'std_id:foo DX', 'check auto_choose target for DX (std_id)' );
# restart and try through std_d with next_choice
$model_searcher->reset;
$step = $model_searcher->next_choice();
is_deeply( $step, [qw/olist slave_y std_id warp/], 'next_choice 1' );
$model_searcher->choose('std_id');
ok( 1, "std_id choice done" );
#print $root->dump_tree(full_dump =>1) ;
$step = $model_searcher->next_choice();
is_deeply( $step, [], 'next_choice 2' );
is( $model_searcher->current_object->name, 'std_id:foo DX', 'next_choice target' );
memory_cycle_ok($model);