File Coverage

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


line stmt bran cond sub pod time code
1             package Test::Role::TinyCommons::Tree;
2              
3             our $AUTHORITY = 'cpan:PERLANCAR'; # AUTHORITY
4             our $DATE = '2021-05-06'; # DATE
5             our $DIST = 'Role-TinyCommons-Tree'; # DIST
6             our $VERSION = '0.126'; # VERSION
7              
8 4     4   193274 use strict;
  4         24  
  4         106  
9 4     4   19 use warnings;
  4         7  
  4         105  
10 4     4   1682 use Test::Exception;
  4         11157  
  4         15  
11 4     4   963 use Test::More 0.98;
  4         72  
  4         27  
12              
13 4     4   937 use Exporter qw(import);
  4         8  
  4         8320  
14             our @EXPORT_OK = qw(test_role_tinycommons_tree);
15              
16             sub test_role_tinycommons_tree {
17 2     2 1 213 my %args = @_;
18              
19 2         7 my $c = $args{class};
20 2         5 my $c1 = $args{subclass1};
21 2         4 my $c2 = $args{subclass2};
22              
23 2   50     13 my $a1 = $args{attribute1} || 'id';
24              
25 2   50     9 my $m = $args{constructor_name} || 'new';
26              
27             subtest "Tree::Node" => sub {
28 2     2   1998 my $pnode = $c->new;
29 2         1511 my $mode1 = $c->new;
30 2         33 my $mode2 = $c->new;
31             lives_ok {
32 2         75 $mode1->parent($pnode);
33 2         13 $mode2->parent($pnode);
34 2         23 $pnode->children([$mode1, $mode2]);
35 2         33 } "set parent & children";
36 2         824 is_deeply($mode1->parent, $pnode, "get parent (1)");
37 2         1406 is_deeply($mode2->parent, $pnode, "get parent (1)");
38 2         1061 my @children = $pnode->children;
39 2 50 33     26 @children = @{$children[0]}
  2         6  
40             if @children==1 && ref($children[0]) eq 'ARRAY';
41 2         8 is_deeply(\@children, [$mode1, $mode2], "get children");
42 2         22 };
43              
44             subtest "Tree::FromStruct" => sub {
45 2     2   1325 my $tree;
46              
47             my $struct = {
48             ( _instantiate => $args{code_instantiate} ) x
49             !!$args{code_instantiate},
50 2         28 _pass_attributes => 0,
51             _constructor => $m,
52              
53             $a1 => 0, _children => [
54             {$a1 => 1, _children => [
55             {$a1 => 3},
56             {$a1 => 4, _class=>$c2},
57             {$a1 => 5, _class=>$c2},
58             {$a1 => 6, _class=>$c1},
59             {$a1 => 7},
60             ]},
61             {$a1 => 2, _children => [
62             {$a1 => 8, _class => $c2, _children => [
63             {$a1 => 9, _class => $c1},
64             ]},
65             ]},
66             ],
67             };
68              
69 2         11 $tree = $c->new_from_struct($struct);
70              
71 2         4 my $exp_tree = do {
72 2         18 my $n0 = $c ->$m; $n0->$a1(0);
  2         25  
73              
74 2         20 my $n1 = $c ->$m; $n1->$a1(1); $n1->parent($n0);
  2         22  
  2         9  
75 2         19 my $n2 = $c ->$m; $n2->$a1(2); $n2->parent($n0);
  2         23  
  2         10  
76 2         9 $n0->children([$n1, $n2]);
77              
78 2         37 my $n3 = $c ->$m; $n3->$a1(3); $n3->parent($n1);
  2         23  
  2         10  
79 2         50 my $n4 = $c2->$m; $n4->$a1(4); $n4->parent($n1);
  2         26  
  2         35  
80 2         86 my $n5 = $c2->$m; $n5->$a1(5); $n5->parent($n1);
  2         33  
  2         9  
81 2         23 my $n6 = $c1->$m; $n6->$a1(6); $n6->parent($n1);
  2         23  
  2         9  
82 2         19 my $n7 = $c ->$m; $n7->$a1(7); $n7->parent($n1);
  2         22  
  2         8  
83 2         9 $n1->children([$n3, $n4, $n5, $n6, $n7]);
84              
85 2         22 my $n8 = $c2->$m; $n8->$a1(8); $n8->parent($n2);
  2         23  
  2         9  
86 2         9 $n2->children([$n8]);
87              
88 2         19 my $n9 = $c1->$m; $n9->$a1(9); $n9->parent($n8);
  2         39  
  2         11  
89 2         10 $n8->children([$n9]);
90              
91 2         9 $n0;
92             };
93              
94 2 50       7 is_deeply($tree, $exp_tree, "result") or diag explain $tree;
95              
96 2         8634 $tree =
97             Code::Includable::Tree::FromStruct::new_from_struct($c, $struct);
98              
99 2         8 is_deeply($tree, $exp_tree, "result (sub call)");
100              
101 2 50       4189 } if $args{test_fromstruct};
102              
103             subtest "Tree::NodeMethods" => sub {
104 2     2   1346 my ($n0, $n1, $n2, $n3, $n4, $n5, $n6, $n7, $n8, $n9);
105              
106             BUILD:
107             {
108 2         4 $n0 = $c ->$m; $n0->$a1(0);
  2         27  
  2         30  
109              
110 2         21 $n1 = $c ->$m; $n1->$a1(1); $n1->parent($n0);
  2         22  
  2         11  
111 2         20 $n2 = $c ->$m; $n2->$a1(2); $n2->parent($n0);
  2         23  
  2         8  
112 2         9 $n0->children([$n1, $n2]);
113              
114 2         24 $n3 = $c ->$m; $n3->$a1(3); $n3->parent($n1);
  2         22  
  2         8  
115 2         20 $n4 = $c2->$m; $n4->$a1(4); $n4->parent($n1);
  2         25  
  2         8  
116 2         20 $n5 = $c2->$m; $n5->$a1(5); $n5->parent($n1);
  2         22  
  2         9  
117 2         18 $n6 = $c1->$m; $n6->$a1(6); $n6->parent($n1);
  2         24  
  2         9  
118 2         18 $n7 = $c ->$m; $n7->$a1(7); $n7->parent($n1);
  2         23  
  2         8  
119 2         10 $n1->children([$n3, $n4, $n5, $n6, $n7]);
120              
121 2         21 $n8 = $c2->$m; $n8->$a1(8); $n8->parent($n2);
  2         35  
  2         9  
122 2         23 $n2->children([$n8]);
123              
124 2         26 $n9 = $c1->$m; $n9->$a1(9); $n9->parent($n8);
  2         25  
  2         19  
125 2         11 $n8->children([$n9]);
126              
127             # structure:
128             # 0 (c)
129             # 1 (c)
130             # 3 (c)
131             # 4 (c2)
132             # 5 (c2)
133             # 6 (c1)
134             # 7 (c)
135             # 2 (c)
136             # 8 (c2)
137             # 9 (c1)
138             }
139              
140 2         33 is_deeply([$n9->ancestors],
141             [$n8, $n2, $n0],
142             "ancestors (1)");
143 2         1666 is_deeply([Code::Includable::Tree::NodeMethods::ancestors($n9)],
144             [$n8, $n2, $n0],
145             "ancestors (1) (sub call)");
146 2         1682 is_deeply([$n0->ancestors],
147             [],
148             "ancestors (2)");
149 2         917 is_deeply([Code::Includable::Tree::NodeMethods::ancestors($n0)],
150             [],
151             "ancestors (2) (sub call)");
152              
153 2         1162 is_deeply([$n0->descendants],
154             [$n1, $n2, $n3, $n4, $n5, $n6, $n7, $n8, $n9],
155             "descendants");
156 2         3100 is_deeply([Code::Includable::Tree::NodeMethods::descendants($n0)],
157             [$n1, $n2, $n3, $n4, $n5, $n6, $n7, $n8, $n9],
158             "descendants (sub call)");
159              
160 2         3234 is_deeply([$n0->descendants_depth_first],
161             [$n1, $n3, $n4, $n5, $n6, $n7, $n2, $n8, $n9],
162             "descendants_depth_first");
163 2         3205 is_deeply([Code::Includable::Tree::NodeMethods::descendants_depth_first($n0)],
164             [$n1, $n3, $n4, $n5, $n6, $n7, $n2, $n8, $n9],
165             "descendants_depth_first (sub call)");
166              
167             # XXX test walk
168              
169 2         3124 is_deeply($n0->first_node(sub { $_[0]->id == 5 }),
  10         28  
170             $n5, "first_node");
171 2         1372 is_deeply(Code::Includable::Tree::NodeMethods::first_node($n0, sub { $_[0]->id == 5 }),
  10         27  
172             $n5, "first_node (sub call)");
173              
174 2         1176 ok( $n1->is_first_child, "is_first_child [1]");
175 2         618 ok(!$n2->is_first_child, "is_first_child [2]");
176 2         593 ok(!$n0->is_first_child, "is_first_child [3]");
177 2         595 ok( Code::Includable::Tree::NodeMethods::is_first_child($n1), "is_first_child [1] (sub call)");
178 2         747 ok(!Code::Includable::Tree::NodeMethods::is_first_child($n2), "is_first_child [2] (sub call)");
179 2         594 ok(!Code::Includable::Tree::NodeMethods::is_first_child($n0), "is_first_child [3] (sub call)");
180              
181 2         666 ok(!$n1->is_last_child, "is_last_child [1]");
182 2         1810 ok( $n2->is_last_child, "is_last_child [2]");
183 2         678 ok(!$n0->is_last_child, "is_last_child [3]");
184 2         591 ok(!Code::Includable::Tree::NodeMethods::is_last_child($n1), "is_last_child [1] (sub call)");
185 2         573 ok( Code::Includable::Tree::NodeMethods::is_last_child($n2), "is_last_child [2] (sub call)");
186 2         570 ok(!Code::Includable::Tree::NodeMethods::is_last_child($n0), "is_last_child [3] (sub call)");
187              
188 2         505 ok(!$n1->is_only_child, "is_only_child [1]");
189 2         547 ok( $n8->is_only_child, "is_only_child [2]");
190 2         512 ok(!$n0->is_only_child, "is_only_child [3]");
191 2         498 ok(!Code::Includable::Tree::NodeMethods::is_only_child($n1), "is_only_child [1] (sub call)");
192 2         642 ok( Code::Includable::Tree::NodeMethods::is_only_child($n8), "is_only_child [2] (sub call)");
193 2         883 ok(!Code::Includable::Tree::NodeMethods::is_only_child($n0), "is_only_child [3] (sub call)");
194              
195 2         555 ok( $n1 ->is_nth_child(1), "is_nth_child [1]");
196 2         629 ok(!$n1 ->is_nth_child(2), "is_nth_child [2]");
197 2         563 ok( $n2 ->is_nth_child(2), "is_nth_child [3]");
198 2         1166 ok( Code::Includable::Tree::NodeMethods::is_nth_child($n1, 1), "is_nth_child [1] (sub call)");
199 2         560 ok(!Code::Includable::Tree::NodeMethods::is_nth_child($n1, 2), "is_nth_child [2] (sub call)");
200 2         597 ok( Code::Includable::Tree::NodeMethods::is_nth_child($n2, 2), "is_nth_child [3] (sub call)");
201              
202 2         614 ok(!$n1 ->is_nth_last_child(1), "is_nth_last_child [1]");
203 2         566 ok( $n1 ->is_nth_last_child(2), "is_nth_last_child [2]");
204 2         571 ok(!$n2 ->is_nth_last_child(2), "is_nth_last_child [3]");
205 2         559 ok(!Code::Includable::Tree::NodeMethods::is_nth_last_child($n1, 1), "is_nth_last_child [1] (sub call)");
206 2         505 ok( Code::Includable::Tree::NodeMethods::is_nth_last_child($n1, 2), "is_nth_last_child [2] (sub call)");
207 2         591 ok(!Code::Includable::Tree::NodeMethods::is_nth_last_child($n2, 2), "is_nth_last_child [3] (sub call)");
208              
209 2         579 ok( $n3 ->is_first_child_of_type, "is_first_child_of_type [1]");
210 2         567 ok( $n4 ->is_first_child_of_type, "is_first_child_of_type [2]");
211 2         576 ok(!$n5 ->is_first_child_of_type, "is_first_child_of_type [3]");
212 2         528 ok( $n6 ->is_first_child_of_type, "is_first_child_of_type [4]");
213 2         638 ok(!$n7 ->is_first_child_of_type, "is_first_child_of_type [4]");
214 2         567 ok( Code::Includable::Tree::NodeMethods::is_first_child_of_type($n3), "is_first_child_of_type [1] (sub call)");
215 2         680 ok( Code::Includable::Tree::NodeMethods::is_first_child_of_type($n4), "is_first_child_of_type [2] (sub call)");
216 2         666 ok(!Code::Includable::Tree::NodeMethods::is_first_child_of_type($n5), "is_first_child_of_type [3] (sub call)");
217 2         525 ok( Code::Includable::Tree::NodeMethods::is_first_child_of_type($n6), "is_first_child_of_type [4] (sub call)");
218 2         596 ok(!Code::Includable::Tree::NodeMethods::is_first_child_of_type($n7), "is_first_child_of_type [4] (sub call)");
219              
220 2         615 ok(!$n3 ->is_last_child_of_type, "is_last_child_of_type [1]");
221 2         559 ok(!$n4 ->is_last_child_of_type, "is_last_child_of_type [2]");
222 2         537 ok( $n5 ->is_last_child_of_type, "is_last_child_of_type [3]");
223 2         614 ok( $n6 ->is_last_child_of_type, "is_last_child_of_type [4]");
224 2         571 ok( $n7 ->is_last_child_of_type, "is_last_child_of_type [5]");
225 2         1060 ok(!Code::Includable::Tree::NodeMethods::is_last_child_of_type($n3), "is_last_child_of_type [1] (sub call)");
226 2         657 ok(!Code::Includable::Tree::NodeMethods::is_last_child_of_type($n4), "is_last_child_of_type [2] (sub call)");
227 2         675 ok( Code::Includable::Tree::NodeMethods::is_last_child_of_type($n5), "is_last_child_of_type [3] (sub call)");
228 2         601 ok( Code::Includable::Tree::NodeMethods::is_last_child_of_type($n6), "is_last_child_of_type [4] (sub call)");
229 2         616 ok( Code::Includable::Tree::NodeMethods::is_last_child_of_type($n7), "is_last_child_of_type [5] (sub call)");
230              
231 2         649 ok(!$n3 ->is_last_child_of_type, "is_last_child_of_type [1]");
232 2         727 ok(!$n4 ->is_last_child_of_type, "is_last_child_of_type [2]");
233 2         644 ok( $n5 ->is_last_child_of_type, "is_last_child_of_type [3]");
234 2         666 ok( $n6 ->is_last_child_of_type, "is_last_child_of_type [4]");
235 2         554 ok( $n7 ->is_last_child_of_type, "is_last_child_of_type [5]");
236 2         599 ok(!Code::Includable::Tree::NodeMethods::is_last_child_of_type($n3), "is_last_child_of_type [1] (sub call)");
237 2         861 ok(!Code::Includable::Tree::NodeMethods::is_last_child_of_type($n4), "is_last_child_of_type [2] (sub call)");
238 2         629 ok( Code::Includable::Tree::NodeMethods::is_last_child_of_type($n5), "is_last_child_of_type [3] (sub call)");
239 2         542 ok( Code::Includable::Tree::NodeMethods::is_last_child_of_type($n6), "is_last_child_of_type [4] (sub call)");
240 2         552 ok( Code::Includable::Tree::NodeMethods::is_last_child_of_type($n7), "is_last_child_of_type [5] (sub call)");
241              
242 2         579 ok( $n3 ->is_nth_child_of_type(1), "is_nth_child_of_type [1]");
243 2         621 ok(!$n3 ->is_nth_child_of_type(2), "is_nth_child_of_type [2]");
244 2         594 ok( $n4 ->is_nth_child_of_type(1), "is_nth_child_of_type [3]");
245 2         576 ok(!$n4 ->is_nth_child_of_type(2), "is_nth_child_of_type [4]");
246 2         547 ok( Code::Includable::Tree::NodeMethods::is_nth_child_of_type($n3, 1), "is_nth_child_of_type [1] (sub call)");
247 2         586 ok(!Code::Includable::Tree::NodeMethods::is_nth_child_of_type($n3, 2), "is_nth_child_of_type [2] (sub call)");
248 2         575 ok( Code::Includable::Tree::NodeMethods::is_nth_child_of_type($n4, 1), "is_nth_child_of_type [3] (sub call)");
249 2         640 ok(!Code::Includable::Tree::NodeMethods::is_nth_child_of_type($n4, 2), "is_nth_child_of_type [4] (sub call)");
250              
251 2         543 ok(!$n3 ->is_nth_last_child_of_type(1), "is_nth_last_child_of_type [1]");
252 2         636 ok( $n3 ->is_nth_last_child_of_type(2), "is_nth_last_child_of_type [2]");
253 2         565 ok(!$n4 ->is_nth_last_child_of_type(1), "is_nth_last_child_of_type [3]");
254 2         572 ok( $n4 ->is_nth_last_child_of_type(2), "is_nth_last_child_of_type [4]");
255 2         550 ok(!Code::Includable::Tree::NodeMethods::is_nth_last_child_of_type($n3, 1), "is_nth_last_child_of_type [1] (sub call)");
256 2         579 ok( Code::Includable::Tree::NodeMethods::is_nth_last_child_of_type($n3, 2), "is_nth_last_child_of_type [2] (sub call)");
257 2         651 ok(!Code::Includable::Tree::NodeMethods::is_nth_last_child_of_type($n4, 1), "is_nth_last_child_of_type [3] (sub call)");
258 2         596 ok( Code::Includable::Tree::NodeMethods::is_nth_last_child_of_type($n4, 2), "is_nth_last_child_of_type [4] (sub call)");
259              
260 2         583 ok(!$n3 ->is_only_child_of_type, "is_only_child_of_type [1]");
261 2         609 ok( $n6 ->is_only_child_of_type, "is_only_child_of_type [2]");
262 2         633 ok(!Code::Includable::Tree::NodeMethods::is_only_child_of_type($n3), "is_only_child_of_type [1]");
263 2         610 ok( Code::Includable::Tree::NodeMethods::is_only_child_of_type($n6), "is_only_child_of_type [2]");
264              
265 2         848 is_deeply($n3->prev_sibling, undef, "prev_sibling [1]");
266 2         1215 is_deeply($n5->prev_sibling, $n4 , "prev_sibling [2]");
267 2         1230 is_deeply($n7->prev_sibling, $n6 , "prev_sibling [3]");
268 2         1083 is_deeply(Code::Includable::Tree::NodeMethods::prev_sibling($n3), undef, "prev_sibling [1] (sub call)");
269 2         742 is_deeply(Code::Includable::Tree::NodeMethods::prev_sibling($n5), $n4 , "prev_sibling [2] (sub call)");
270 2         1048 is_deeply(Code::Includable::Tree::NodeMethods::prev_sibling($n7), $n6 , "prev_sibling [3] (sub call)");
271              
272 2         1094 is_deeply($n3->next_sibling, $n4 , "next_sibling [1]");
273 2         969 is_deeply($n5->next_sibling, $n6 , "next_sibling [2]");
274 2         985 is_deeply($n7->next_sibling, undef, "next_sibling [3]");
275 2         796 is_deeply(Code::Includable::Tree::NodeMethods::next_sibling($n3), $n4 , "next_sibling [1] (sub call)");
276 2         1107 is_deeply(Code::Includable::Tree::NodeMethods::next_sibling($n5), $n6 , "next_sibling [2] (sub call)");
277 2         970 is_deeply(Code::Includable::Tree::NodeMethods::next_sibling($n7), undef, "next_sibling [3] (sub call)");
278              
279 2         794 is_deeply([$n3->prev_siblings], [] , "prev_siblings [1] (sub call)");
280 2         1009 is_deeply([$n5->prev_siblings], [$n3, $n4], "prev_siblings [2] (sub call)");
281 2         1491 is_deeply([Code::Includable::Tree::NodeMethods::prev_siblings($n3)], [] , "prev_siblings [1] (sub call)");
282 2         901 is_deeply([Code::Includable::Tree::NodeMethods::prev_siblings($n5)], [$n3, $n4], "prev_siblings [2] (sub call)");
283              
284 2         1425 is_deeply([$n5->next_siblings], [$n6, $n7], "next_siblings [1] (sub call)");
285 2         1473 is_deeply([$n7->next_siblings], [] , "next_siblings [2] (sub call)");
286 2         977 is_deeply([Code::Includable::Tree::NodeMethods::next_siblings($n5)], [$n6, $n7], "next_siblings [1] (sub call)");
287 2         1404 is_deeply([Code::Includable::Tree::NodeMethods::next_siblings($n7)], [] , "next_siblings [2] (sub call)");
288              
289             # check
290             {
291 2         22 lives_ok { $n0->check({check_root=>1}) };
  2         85  
292              
293 2         608 $n3->parent($n2);
294 2         18 lives_ok { $n0->check };
  2         50  
295 2         597 dies_ok { $n1->check };
  2         77  
296 2         597 dies_ok { $n1->check({recurse=>1}) };
  2         63  
297 2         604 $n3->parent($n1);
298              
299             # opt:check_root=1
300 2         10 $n0->parent($n0);
301 2         14 dies_ok { $n0->check({check_root => 1}) };
  2         54  
302 2         615 $n0->parent(undef);
303             }
304              
305             # remove
306             {
307 2         970 my @children;
  2         8  
  2         5  
308              
309 2         8 Code::Includable::Tree::NodeMethods::remove($n8);
310 2         16 @children = $n2->children;
311 2 50 33     24 if (@children == 1 && ref $children[0] eq 'ARRAY') { @children = @{ $children[0] } }
  2         4  
  2         17  
312 2 50       10 is_deeply(\@children, [])
313             or diag explain \@children;
314              
315 2         1012 Code::Includable::Tree::NodeMethods::remove($n6);
316 2         16 @children = $n1->children;
317 2 100 66     16 if (@children == 1 && ref $children[0] eq 'ARRAY') { @children = @{ $children[0] } }
  1         2  
  1         3  
318 2 50       8 is_deeply(\@children, [$n3, $n4, $n5, $n7])
319             or diag explain \@children;
320             }
321              
322 2 50       10349 } if $args{test_nodemethods};
323             }
324              
325             1;
326             # ABSTRACT: Test suite for Role::TinyCommons::Tree
327              
328             __END__