1#!/usr/bin/perl
2
3use strict;
4use warnings;
5
6use Test::More tests => 37;
7use Test::Exception;
8
9BEGIN { 
10    use_ok('Tree::Simple::Visitor::Sort');
11    use_ok('Tree::Simple::Visitor::GetAllDescendents');
12}
13
14use Tree::Simple;
15
16my $tree = Tree::Simple->new(Tree::Simple->ROOT)
17                       ->addChildren(
18                            Tree::Simple->new("1")
19                                        ->addChildren(
20                                            Tree::Simple->new("1.3"),
21                                            Tree::Simple->new("1.2")
22                                                        ->addChildren(
23                                                            Tree::Simple->new("1.2.2"),
24                                                            Tree::Simple->new("1.2.1")
25                                                        ),
26                                            Tree::Simple->new("1.1")                                                                                                
27                                        ),
28                            Tree::Simple->new("4")                                                        
29                                        ->addChildren(
30                                            Tree::Simple->new("4.1")
31                                        ),    
32                            Tree::Simple->new("2")
33                                        ->addChildren(
34                                            Tree::Simple->new("2.1"),
35                                            Tree::Simple->new("2.2")
36                                        ),                            
37                            Tree::Simple->new("3")
38                                        ->addChildren(
39                                            Tree::Simple->new("3.3"),
40                                            Tree::Simple->new("3.2"),
41                                            Tree::Simple->new("3.1")                                                                                                
42                                        )                            
43                        
44                       );
45isa_ok($tree, 'Tree::Simple');
46
47can_ok("Tree::Simple::Visitor::Sort", 'new');
48
49# try normal sort
50{    
51    my $visitor = Tree::Simple::Visitor::Sort->new();
52    isa_ok($visitor, 'Tree::Simple::Visitor::Sort');
53    isa_ok($visitor, 'Tree::Simple::Visitor');    
54    
55    can_ok($visitor, 'visit');
56    
57    $tree->accept($visitor);
58    
59    my $visitor_check = Tree::Simple::Visitor::GetAllDescendents->new();
60    isa_ok($visitor_check, 'Tree::Simple::Visitor::GetAllDescendents');
61
62    $tree->accept($visitor_check);    
63    
64    is_deeply(
65        [ $visitor_check->getAllDescendents() ], 
66        [ qw/1 1.1 1.2 1.2.1 1.2.2 1.3 2 2.1 2.2 3 3.1 3.2 3.3 4 4.1/ ], 
67        '... our tree is as expected after sort');
68    
69}
70
71# try sort with a node filter 
72{    
73    my $visitor = Tree::Simple::Visitor::Sort->new();
74    isa_ok($visitor, 'Tree::Simple::Visitor::Sort');
75    
76    my $tree = Tree::Simple->new(Tree::Simple->ROOT)
77                       ->addChildren(
78                            Tree::Simple->new([ 1 ])
79                                        ->addChildren(
80                                            Tree::Simple->new([ 1, 3 ]),
81                                            Tree::Simple->new([ 1, 2 ])
82                                                        ->addChildren(
83                                                            Tree::Simple->new([ 1, 2, 2 ]),
84                                                            Tree::Simple->new([ 1, 2, 1 ])
85                                                        ),
86                                            Tree::Simple->new([ 1, 1])                                                                                                
87                                        ),  
88                            Tree::Simple->new([ 2 ])
89                                        ->addChildren(
90                                            Tree::Simple->new([ 2, 1 ]),
91                                            Tree::Simple->new([ 2, 2 ] )
92                                        )                                                   
93                       );
94    isa_ok($tree, 'Tree::Simple');    
95    
96    can_ok($visitor, 'setNodeFilter');    
97    $visitor->setNodeFilter(sub {
98        my ($t) = @_;
99        # sort on the last part of the node
100        return $t->getNodeValue()->[-1];
101    });              
102    
103    $tree->accept($visitor);
104    
105    my $visitor_check = Tree::Simple::Visitor::GetAllDescendents->new();
106    isa_ok($visitor_check, 'Tree::Simple::Visitor::GetAllDescendents');
107
108    $tree->accept($visitor_check);    
109    
110    is_deeply(
111        [ $visitor_check->getAllDescendents() ], 
112        [ [1], [1, 1], [1, 2], [1, 2, 1], [1, 2, 2], [1, 3], [2], [2, 1], [2, 2] ], 
113        '... our tree is as expected after sort');
114}
115    
116# try custom sort function 
117{    
118    my $visitor = Tree::Simple::Visitor::Sort->new();
119    isa_ok($visitor, 'Tree::Simple::Visitor::Sort');
120    
121    can_ok($visitor, 'setSortFunction');    
122    $visitor->setSortFunction($visitor->REVERSE);    
123    
124    $tree->accept($visitor);
125    
126    my $visitor_check = Tree::Simple::Visitor::GetAllDescendents->new();
127    isa_ok($visitor_check, 'Tree::Simple::Visitor::GetAllDescendents');
128
129    $tree->accept($visitor_check);    
130    
131    is_deeply(
132        [ $visitor_check->getAllDescendents() ], 
133        [ qw/4 4.1 3 3.3 3.2 3.1 2 2.2 2.1 1 1.3 1.2 1.2.2 1.2.1 1.1 / ], 
134        '... our tree is as expected after sort');
135}
136
137# check all our pre-built functions
138is(ref(Tree::Simple::Visitor::Sort->REVERSE), 'CODE', '... it is a code reference');
139# already tested above
140
141is(ref(Tree::Simple::Visitor::Sort->NUMERIC), 'CODE', '... it is a code reference');
142cmp_ok(Tree::Simple::Visitor::Sort->NUMERIC->(Tree::Simple->new(5), Tree::Simple->new(4)), 
143        '==', 1, '... the numeric sort works');
144
145is(ref(Tree::Simple::Visitor::Sort->REVERSE_NUMERIC),      'CODE', '... it is a code reference');
146cmp_ok(Tree::Simple::Visitor::Sort->REVERSE_NUMERIC->(Tree::Simple->new(5), Tree::Simple->new(4)), 
147        '==', -1, '... the reverse numeric sort works');
148
149is(ref(Tree::Simple::Visitor::Sort->ALPHABETICAL),         'CODE', '... it is a code reference');
150cmp_ok(Tree::Simple::Visitor::Sort->ALPHABETICAL->(Tree::Simple->new("A"), Tree::Simple->new("a")), 
151        '==', 0, '... the alphabetical sort works');
152
153is(ref(Tree::Simple::Visitor::Sort->REVERSE_ALPHABETICAL), 'CODE', '... it is a code reference');
154cmp_ok(Tree::Simple::Visitor::Sort->REVERSE_ALPHABETICAL->(Tree::Simple->new("a"), Tree::Simple->new("b")), 
155        '==', 1, '... the reverse alphabetical sort works');
156
157# test some weird stuff
158{
159
160    my $visitor = Tree::Simple::Visitor::Sort->new();
161    isa_ok($visitor, 'Tree::Simple::Visitor::Sort'); 
162    
163    # test visitiing a leaf node
164    my $leaf = Tree::Simple->new("leaf");
165    $leaf->accept($visitor);
166
167}
168
169# test the errors
170{
171    my $visitor = Tree::Simple::Visitor::Sort->new();
172    isa_ok($visitor, 'Tree::Simple::Visitor::Sort');
173    isa_ok($visitor, 'Tree::Simple::Visitor');
174    
175    # check visit
176    throws_ok {
177        $visitor->visit();
178    } qr/Insufficient Arguments/, '... got the error we expected';  
179    
180    throws_ok {
181        $visitor->visit("Fail");
182    } qr/Insufficient Arguments/, '... got the error we expected';                           
183
184    throws_ok {
185        $visitor->visit([]);
186    } qr/Insufficient Arguments/, '... got the error we expected'; 
187    
188    throws_ok {
189        $visitor->visit(bless({}, "Fail"));
190    } qr/Insufficient Arguments/, '... got the error we expected';  
191    
192    # check the handler errors
193    throws_ok {
194        $visitor->setSortFunction();
195    } qr/Insufficient Arguments/, '... got the error we expected';      
196    
197    throws_ok {
198        $visitor->setSortFunction("Fail");
199    } qr/Insufficient Arguments/, '... got the error we expected';     
200    
201    throws_ok {
202        $visitor->setSortFunction([]);
203    } qr/Insufficient Arguments/, '... got the error we expected';    
204          
205}
206