File Coverage

blib/lib/Test/Role/TinyCommons/Tree.pm
Criterion Covered Total %
statement 258 258 100.0
branch 9 16 56.2
condition 6 13 46.1
subroutine 9 9 100.0
pod 1 1 100.0
total 283 297 95.2


line stmt bran cond sub pod time code
1             package Test::Role::TinyCommons::Tree;
2              
3 4     4   223336 use strict;
  4         35  
  4         129  
4 4     4   23 use warnings;
  4         191  
  4         240  
5 4     4   1944 use Test::Exception;
  4         14125  
  4         16  
6 4     4   1151 use Test::More 0.98;
  4         75  
  4         28  
7              
8 4     4   1064 use Exporter qw(import);
  4         12  
  4         11037  
9              
10             our $AUTHORITY = 'cpan:PERLANCAR'; # AUTHORITY
11             our $DATE = '2021-10-07'; # DATE
12             our $DIST = 'Role-TinyCommons-Tree'; # DIST
13             our $VERSION = '0.128'; # VERSION
14              
15             our @EXPORT_OK = qw(test_role_tinycommons_tree);
16              
17             sub test_role_tinycommons_tree {
18 2     2 1 216 my %args = @_;
19              
20 2         7 my $c = $args{class};
21 2         5 my $c1 = $args{subclass1};
22 2         6 my $c2 = $args{subclass2};
23              
24 2   50     15 my $a1 = $args{attribute1} || 'id';
25              
26 2   50     11 my $m = $args{constructor_name} || 'new';
27              
28             subtest "Tree::Node" => sub {
29 2     2   2257 my $pnode = $c->new;
30 2         1360 my $mode1 = $c->new;
31 2         38 my $mode2 = $c->new;
32             lives_ok {
33 2         88 $mode1->parent($pnode);
34 2         16 $mode2->parent($pnode);
35 2         15 $pnode->children([$mode1, $mode2]);
36 2         39 } "set parent & children";
37 2         952 is_deeply($mode1->parent, $pnode, "get parent (1)");
38 2         1326 is_deeply($mode2->parent, $pnode, "get parent (1)");
39 2         1133 my @children = $pnode->children;
40 2 50 33     27 @children = @{$children[0]}
  2         6  
41             if @children==1 && ref($children[0]) eq 'ARRAY';
42 2         11 is_deeply(\@children, [$mode1, $mode2], "get children");
43 2         24 };
44              
45             subtest "Tree::FromStruct" => sub {
46 2     2   1460 my $tree;
47              
48             my $struct = {
49             ( _instantiate => $args{code_instantiate} ) x
50             !!$args{code_instantiate},
51 2         33 _pass_attributes => 0,
52             _constructor => $m,
53              
54             $a1 => 0, _children => [
55             {$a1 => 1, _children => [
56             {$a1 => 3},
57             {$a1 => 4, _class=>$c2},
58             {$a1 => 5, _class=>$c2},
59             {$a1 => 6, _class=>$c1},
60             {$a1 => 7},
61             ]},
62             {$a1 => 2, _children => [
63             {$a1 => 8, _class => $c2, _children => [
64             {$a1 => 9, _class => $c1},
65             ]},
66             ]},
67             ],
68             };
69              
70 2         14 $tree = $c->new_from_struct($struct);
71              
72 2         6 my $exp_tree = do {
73 2         24 my $n0 = $c ->$m; $n0->$a1(0);
  2         29  
74              
75 2         24 my $n1 = $c ->$m; $n1->$a1(1); $n1->parent($n0);
  2         28  
  2         11  
76 2         61 my $n2 = $c ->$m; $n2->$a1(2); $n2->parent($n0);
  2         72  
  2         15  
77 2         12 $n0->children([$n1, $n2]);
78              
79 2         33 my $n3 = $c ->$m; $n3->$a1(3); $n3->parent($n1);
  2         64  
  2         12  
80 2         30 my $n4 = $c2->$m; $n4->$a1(4); $n4->parent($n1);
  2         29  
  2         11  
81 2         22 my $n5 = $c2->$m; $n5->$a1(5); $n5->parent($n1);
  2         29  
  2         11  
82 2         22 my $n6 = $c1->$m; $n6->$a1(6); $n6->parent($n1);
  2         28  
  2         10  
83 2         24 my $n7 = $c ->$m; $n7->$a1(7); $n7->parent($n1);
  2         26  
  2         11  
84 2         12 $n1->children([$n3, $n4, $n5, $n6, $n7]);
85              
86 2         25 my $n8 = $c2->$m; $n8->$a1(8); $n8->parent($n2);
  2         29  
  2         10  
87 2         9 $n2->children([$n8]);
88              
89 2         26 my $n9 = $c1->$m; $n9->$a1(9); $n9->parent($n8);
  2         29  
  2         9  
90 2         11 $n8->children([$n9]);
91              
92 2         11 $n0;
93             };
94              
95 2 50       8 is_deeply($tree, $exp_tree, "result") or diag explain $tree;
96              
97 2         9883 $tree =
98             Code::Includable::Tree::FromStruct::new_from_struct($c, $struct);
99              
100 2         10 is_deeply($tree, $exp_tree, "result (sub call)");
101              
102 2 50       4532 } if $args{test_fromstruct};
103              
104             subtest "Tree::NodeMethods" => sub {
105 2     2   1585 my ($n0, $n1, $n2, $n3, $n4, $n5, $n6, $n7, $n8, $n9);
106              
107             BUILD:
108             {
109 2         5 $n0 = $c ->$m; $n0->$a1(0);
  2         33  
  2         35  
110              
111 2         27 $n1 = $c ->$m; $n1->$a1(1); $n1->parent($n0);
  2         29  
  2         12  
112 2         23 $n2 = $c ->$m; $n2->$a1(2); $n2->parent($n0);
  2         27  
  2         11  
113 2         26 $n0->children([$n1, $n2]);
114              
115 2         30 $n3 = $c ->$m; $n3->$a1(3); $n3->parent($n1);
  2         28  
  2         12  
116 2         24 $n4 = $c2->$m; $n4->$a1(4); $n4->parent($n1);
  2         31  
  2         10  
117 2         24 $n5 = $c2->$m; $n5->$a1(5); $n5->parent($n1);
  2         30  
  2         10  
118 2         24 $n6 = $c1->$m; $n6->$a1(6); $n6->parent($n1);
  2         29  
  2         10  
119 2         22 $n7 = $c ->$m; $n7->$a1(7); $n7->parent($n1);
  2         28  
  2         16  
120 2         12 $n1->children([$n3, $n4, $n5, $n6, $n7]);
121              
122 2         33 $n8 = $c2->$m; $n8->$a1(8); $n8->parent($n2);
  2         30  
  2         10  
123 2         10 $n2->children([$n8]);
124              
125 2         27 $n9 = $c1->$m; $n9->$a1(9); $n9->parent($n8);
  2         30  
  2         11  
126 2         9 $n8->children([$n9]);
127              
128             # structure:
129             # 0 (c)
130             # 1 (c)
131             # 3 (c)
132             # 4 (c2)
133             # 5 (c2)
134             # 6 (c1)
135             # 7 (c)
136             # 2 (c)
137             # 8 (c2)
138             # 9 (c1)
139             }
140              
141 2         28 is_deeply([$n9->ancestors],
142             [$n8, $n2, $n0],
143             "ancestors (1)");
144 2         1934 is_deeply([Code::Includable::Tree::NodeMethods::ancestors($n9)],
145             [$n8, $n2, $n0],
146             "ancestors (1) (sub call)");
147 2         2203 is_deeply([$n0->ancestors],
148             [],
149             "ancestors (2)");
150 2         1167 is_deeply([Code::Includable::Tree::NodeMethods::ancestors($n0)],
151             [],
152             "ancestors (2) (sub call)");
153              
154 2         1157 is_deeply([$n9->retrieve_parent],
155             [$n8],
156             "retrieve_parent (1)");
157 2         1431 ok( $n1->retrieve_parent, "retrieve_parent [1]");
158             # XXX more
159              
160 2         696 is_deeply([$n0->descendants],
161             [$n1, $n2, $n3, $n4, $n5, $n6, $n7, $n8, $n9],
162             "descendants");
163 2         3559 is_deeply([Code::Includable::Tree::NodeMethods::descendants($n0)],
164             [$n1, $n2, $n3, $n4, $n5, $n6, $n7, $n8, $n9],
165             "descendants (sub call)");
166              
167 2         3821 is_deeply([$n0->descendants_depth_first],
168             [$n1, $n3, $n4, $n5, $n6, $n7, $n2, $n8, $n9],
169             "descendants_depth_first");
170 2         3545 is_deeply([Code::Includable::Tree::NodeMethods::descendants_depth_first($n0)],
171             [$n1, $n3, $n4, $n5, $n6, $n7, $n2, $n8, $n9],
172             "descendants_depth_first (sub call)");
173              
174             # XXX test walk
175              
176 2         3446 is_deeply($n0->first_node(sub { $_[0]->id == 5 }),
  10         35  
177             $n5, "first_node");
178 2         1232 is_deeply(Code::Includable::Tree::NodeMethods::first_node($n0, sub { $_[0]->id == 5 }),
  10         35  
179             $n5, "first_node (sub call)");
180              
181 2         1179 ok( $n1->is_first_child, "is_first_child [1]");
182 2         778 ok(!$n2->is_first_child, "is_first_child [2]");
183 2         706 ok(!$n0->is_first_child, "is_first_child [3]");
184 2         687 ok( Code::Includable::Tree::NodeMethods::is_first_child($n1), "is_first_child [1] (sub call)");
185 2         700 ok(!Code::Includable::Tree::NodeMethods::is_first_child($n2), "is_first_child [2] (sub call)");
186 2         1031 ok(!Code::Includable::Tree::NodeMethods::is_first_child($n0), "is_first_child [3] (sub call)");
187              
188 2         718 ok(!$n1->is_last_child, "is_last_child [1]");
189 2         773 ok( $n2->is_last_child, "is_last_child [2]");
190 2         702 ok(!$n0->is_last_child, "is_last_child [3]");
191 2         671 ok(!Code::Includable::Tree::NodeMethods::is_last_child($n1), "is_last_child [1] (sub call)");
192 2         714 ok( Code::Includable::Tree::NodeMethods::is_last_child($n2), "is_last_child [2] (sub call)");
193 2         718 ok(!Code::Includable::Tree::NodeMethods::is_last_child($n0), "is_last_child [3] (sub call)");
194              
195 2         675 ok(!$n1->is_only_child, "is_only_child [1]");
196 2         733 ok( $n8->is_only_child, "is_only_child [2]");
197 2         647 ok(!$n0->is_only_child, "is_only_child [3]");
198 2         708 ok(!Code::Includable::Tree::NodeMethods::is_only_child($n1), "is_only_child [1] (sub call)");
199 2         685 ok( Code::Includable::Tree::NodeMethods::is_only_child($n8), "is_only_child [2] (sub call)");
200 2         725 ok(!Code::Includable::Tree::NodeMethods::is_only_child($n0), "is_only_child [3] (sub call)");
201              
202 2         694 ok( $n1 ->is_nth_child(1), "is_nth_child [1]");
203 2         734 ok(!$n1 ->is_nth_child(2), "is_nth_child [2]");
204 2         707 ok( $n2 ->is_nth_child(2), "is_nth_child [3]");
205 2         676 ok( Code::Includable::Tree::NodeMethods::is_nth_child($n1, 1), "is_nth_child [1] (sub call)");
206 2         721 ok(!Code::Includable::Tree::NodeMethods::is_nth_child($n1, 2), "is_nth_child [2] (sub call)");
207 2         818 ok( Code::Includable::Tree::NodeMethods::is_nth_child($n2, 2), "is_nth_child [3] (sub call)");
208              
209 2         672 ok(!$n1 ->is_nth_last_child(1), "is_nth_last_child [1]");
210 2         680 ok( $n1 ->is_nth_last_child(2), "is_nth_last_child [2]");
211 2         1214 ok(!$n2 ->is_nth_last_child(2), "is_nth_last_child [3]");
212 2         650 ok(!Code::Includable::Tree::NodeMethods::is_nth_last_child($n1, 1), "is_nth_last_child [1] (sub call)");
213 2         708 ok( Code::Includable::Tree::NodeMethods::is_nth_last_child($n1, 2), "is_nth_last_child [2] (sub call)");
214 2         743 ok(!Code::Includable::Tree::NodeMethods::is_nth_last_child($n2, 2), "is_nth_last_child [3] (sub call)");
215              
216 2         679 ok( $n3 ->is_first_child_of_type, "is_first_child_of_type [1]");
217 2         801 ok( $n4 ->is_first_child_of_type, "is_first_child_of_type [2]");
218 2         749 ok(!$n5 ->is_first_child_of_type, "is_first_child_of_type [3]");
219 2         737 ok( $n6 ->is_first_child_of_type, "is_first_child_of_type [4]");
220 2         678 ok(!$n7 ->is_first_child_of_type, "is_first_child_of_type [4]");
221 2         722 ok( Code::Includable::Tree::NodeMethods::is_first_child_of_type($n3), "is_first_child_of_type [1] (sub call)");
222 2         700 ok( Code::Includable::Tree::NodeMethods::is_first_child_of_type($n4), "is_first_child_of_type [2] (sub call)");
223 2         676 ok(!Code::Includable::Tree::NodeMethods::is_first_child_of_type($n5), "is_first_child_of_type [3] (sub call)");
224 2         713 ok( Code::Includable::Tree::NodeMethods::is_first_child_of_type($n6), "is_first_child_of_type [4] (sub call)");
225 2         708 ok(!Code::Includable::Tree::NodeMethods::is_first_child_of_type($n7), "is_first_child_of_type [4] (sub call)");
226              
227 2         709 ok(!$n3 ->is_last_child_of_type, "is_last_child_of_type [1]");
228 2         723 ok(!$n4 ->is_last_child_of_type, "is_last_child_of_type [2]");
229 2         759 ok( $n5 ->is_last_child_of_type, "is_last_child_of_type [3]");
230 2         701 ok( $n6 ->is_last_child_of_type, "is_last_child_of_type [4]");
231 2         694 ok( $n7 ->is_last_child_of_type, "is_last_child_of_type [5]");
232 2         672 ok(!Code::Includable::Tree::NodeMethods::is_last_child_of_type($n3), "is_last_child_of_type [1] (sub call)");
233 2         693 ok(!Code::Includable::Tree::NodeMethods::is_last_child_of_type($n4), "is_last_child_of_type [2] (sub call)");
234 2         744 ok( Code::Includable::Tree::NodeMethods::is_last_child_of_type($n5), "is_last_child_of_type [3] (sub call)");
235 2         735 ok( Code::Includable::Tree::NodeMethods::is_last_child_of_type($n6), "is_last_child_of_type [4] (sub call)");
236 2         689 ok( Code::Includable::Tree::NodeMethods::is_last_child_of_type($n7), "is_last_child_of_type [5] (sub call)");
237              
238 2         687 ok(!$n3 ->is_last_child_of_type, "is_last_child_of_type [1]");
239 2         668 ok(!$n4 ->is_last_child_of_type, "is_last_child_of_type [2]");
240 2         709 ok( $n5 ->is_last_child_of_type, "is_last_child_of_type [3]");
241 2         712 ok( $n6 ->is_last_child_of_type, "is_last_child_of_type [4]");
242 2         705 ok( $n7 ->is_last_child_of_type, "is_last_child_of_type [5]");
243 2         668 ok(!Code::Includable::Tree::NodeMethods::is_last_child_of_type($n3), "is_last_child_of_type [1] (sub call)");
244 2         668 ok(!Code::Includable::Tree::NodeMethods::is_last_child_of_type($n4), "is_last_child_of_type [2] (sub call)");
245 2         752 ok( Code::Includable::Tree::NodeMethods::is_last_child_of_type($n5), "is_last_child_of_type [3] (sub call)");
246 2         725 ok( Code::Includable::Tree::NodeMethods::is_last_child_of_type($n6), "is_last_child_of_type [4] (sub call)");
247 2         675 ok( Code::Includable::Tree::NodeMethods::is_last_child_of_type($n7), "is_last_child_of_type [5] (sub call)");
248              
249 2         676 ok( $n3 ->is_nth_child_of_type(1), "is_nth_child_of_type [1]");
250 2         735 ok(!$n3 ->is_nth_child_of_type(2), "is_nth_child_of_type [2]");
251 2         698 ok( $n4 ->is_nth_child_of_type(1), "is_nth_child_of_type [3]");
252 2         703 ok(!$n4 ->is_nth_child_of_type(2), "is_nth_child_of_type [4]");
253 2         699 ok( Code::Includable::Tree::NodeMethods::is_nth_child_of_type($n3, 1), "is_nth_child_of_type [1] (sub call)");
254 2         711 ok(!Code::Includable::Tree::NodeMethods::is_nth_child_of_type($n3, 2), "is_nth_child_of_type [2] (sub call)");
255 2         702 ok( Code::Includable::Tree::NodeMethods::is_nth_child_of_type($n4, 1), "is_nth_child_of_type [3] (sub call)");
256 2         689 ok(!Code::Includable::Tree::NodeMethods::is_nth_child_of_type($n4, 2), "is_nth_child_of_type [4] (sub call)");
257              
258 2         714 ok(!$n3 ->is_nth_last_child_of_type(1), "is_nth_last_child_of_type [1]");
259 2         730 ok( $n3 ->is_nth_last_child_of_type(2), "is_nth_last_child_of_type [2]");
260 2         716 ok(!$n4 ->is_nth_last_child_of_type(1), "is_nth_last_child_of_type [3]");
261 2         750 ok( $n4 ->is_nth_last_child_of_type(2), "is_nth_last_child_of_type [4]");
262 2         715 ok(!Code::Includable::Tree::NodeMethods::is_nth_last_child_of_type($n3, 1), "is_nth_last_child_of_type [1] (sub call)");
263 2         740 ok( Code::Includable::Tree::NodeMethods::is_nth_last_child_of_type($n3, 2), "is_nth_last_child_of_type [2] (sub call)");
264 2         675 ok(!Code::Includable::Tree::NodeMethods::is_nth_last_child_of_type($n4, 1), "is_nth_last_child_of_type [3] (sub call)");
265 2         672 ok( Code::Includable::Tree::NodeMethods::is_nth_last_child_of_type($n4, 2), "is_nth_last_child_of_type [4] (sub call)");
266              
267 2         695 ok(!$n3 ->is_only_child_of_type, "is_only_child_of_type [1]");
268 2         707 ok( $n6 ->is_only_child_of_type, "is_only_child_of_type [2]");
269 2         693 ok(!Code::Includable::Tree::NodeMethods::is_only_child_of_type($n3), "is_only_child_of_type [1]");
270 2         693 ok( Code::Includable::Tree::NodeMethods::is_only_child_of_type($n6), "is_only_child_of_type [2]");
271              
272 2         703 is_deeply($n3->prev_sibling, undef, "prev_sibling [1]");
273 2         1032 is_deeply($n5->prev_sibling, $n4 , "prev_sibling [2]");
274 2         1305 is_deeply($n7->prev_sibling, $n6 , "prev_sibling [3]");
275 2         1212 is_deeply(Code::Includable::Tree::NodeMethods::prev_sibling($n3), undef, "prev_sibling [1] (sub call)");
276 2         920 is_deeply(Code::Includable::Tree::NodeMethods::prev_sibling($n5), $n4 , "prev_sibling [2] (sub call)");
277 2         1184 is_deeply(Code::Includable::Tree::NodeMethods::prev_sibling($n7), $n6 , "prev_sibling [3] (sub call)");
278              
279 2         1214 is_deeply($n3->next_sibling, $n4 , "next_sibling [1]");
280 2         1253 is_deeply($n5->next_sibling, $n6 , "next_sibling [2]");
281 2         1210 is_deeply($n7->next_sibling, undef, "next_sibling [3]");
282 2         893 is_deeply(Code::Includable::Tree::NodeMethods::next_sibling($n3), $n4 , "next_sibling [1] (sub call)");
283 2         1154 is_deeply(Code::Includable::Tree::NodeMethods::next_sibling($n5), $n6 , "next_sibling [2] (sub call)");
284 2         1225 is_deeply(Code::Includable::Tree::NodeMethods::next_sibling($n7), undef, "next_sibling [3] (sub call)");
285              
286 2         896 is_deeply([$n3->prev_siblings], [] , "prev_siblings [1] (sub call)");
287 2         1290 is_deeply([$n5->prev_siblings], [$n3, $n4], "prev_siblings [2] (sub call)");
288 2         1703 is_deeply([Code::Includable::Tree::NodeMethods::prev_siblings($n3)], [] , "prev_siblings [1] (sub call)");
289 2         1151 is_deeply([Code::Includable::Tree::NodeMethods::prev_siblings($n5)], [$n3, $n4], "prev_siblings [2] (sub call)");
290              
291 2         1756 is_deeply([$n5->next_siblings], [$n6, $n7], "next_siblings [1] (sub call)");
292 2         1671 is_deeply([$n7->next_siblings], [] , "next_siblings [2] (sub call)");
293 2         1197 is_deeply([Code::Includable::Tree::NodeMethods::next_siblings($n5)], [$n6, $n7], "next_siblings [1] (sub call)");
294 2         1740 is_deeply([Code::Includable::Tree::NodeMethods::next_siblings($n7)], [] , "next_siblings [2] (sub call)");
295              
296 2         1113 ok( $n0->is_root, "is_root [0]");
297 2         696 ok(!$n1->is_root, "is_root [1]");
298              
299             # check
300             {
301 2         33 lives_ok { $n0->check({check_root=>1}) };
  2         113  
302              
303 2         750 $n3->parent($n2);
304 2         22 lives_ok { $n0->check };
  2         73  
305 2         718 dies_ok { $n1->check };
  2         74  
306 2         1403 dies_ok { $n1->check({recurse=>1}) };
  2         108  
307 2         984 $n3->parent($n1);
308              
309             # opt:check_root=1
310 2         13 $n0->parent($n0);
311 2         20 dies_ok { $n0->check({check_root => 1}) };
  2         67  
312 2         711 $n0->parent(undef);
313             }
314              
315             # remove
316             {
317 2         677 my @children;
  2         12  
  2         4  
318              
319 2         24 Code::Includable::Tree::NodeMethods::remove($n8);
320 2         16 @children = $n2->children;
321 2 50 33     31 if (@children == 1 && ref $children[0] eq 'ARRAY') { @children = @{ $children[0] } }
  2         4  
  2         7  
322 2 50       12 is_deeply(\@children, [])
323             or diag explain \@children;
324              
325 2         1217 Code::Includable::Tree::NodeMethods::remove($n6);
326 2         17 @children = $n1->children;
327 2 100 66     22 if (@children == 1 && ref $children[0] eq 'ARRAY') { @children = @{ $children[0] } }
  1         3  
  1         4  
328 2 50       13 is_deeply(\@children, [$n3, $n4, $n5, $n7])
329             or diag explain \@children;
330             }
331              
332 2 50       11998 } if $args{test_nodemethods};
333             }
334              
335             1;
336             # ABSTRACT: Test suite for Role::TinyCommons::Tree
337              
338             __END__