rubytree 0.8.3 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,118 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # tree_merge_handler.rb
4
+ #
5
+ # Author: Anupam Sengupta
6
+ # Time-stamp: <2013-12-31 21:52:59 anupam>
7
+ #
8
+ # Copyright (C) 2013 Anupam Sengupta (anupamsg@gmail.com)
9
+ #
10
+ # All rights reserved.
11
+ #
12
+ # Redistribution and use in source and binary forms, with or without modification,
13
+ # are permitted provided that the following conditions are met:
14
+ #
15
+ # - Redistributions of source code must retain the above copyright notice, this
16
+ # list of conditions and the following disclaimer.
17
+ #
18
+ # - Redistributions in binary form must reproduce the above copyright notice, this
19
+ # list of conditions and the following disclaimer in the documentation and/or
20
+ # other materials provided with the distribution.
21
+ #
22
+ # - Neither the name of the organization nor the names of its contributors may
23
+ # be used to endorse or promote products derived from this software without
24
+ # specific prior written permission.
25
+ #
26
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
27
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
29
+ # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
30
+ # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
31
+ # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
32
+ # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
33
+ # ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34
+ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
35
+ # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36
+ #
37
+
38
+ # Provides utility methods to merge two {Tree::TreeNode} based trees.
39
+ # @since 0.9.0
40
+ module Tree::Utils::TreeMergeHandler
41
+
42
+ # @!group Merging Trees
43
+
44
+ # Merge two trees that share the same root node and returns <em>a new tree</em>.
45
+ #
46
+ # The new tree contains the contents of the merge between _other_tree_ and
47
+ # self. Duplicate nodes (coming from _other_tree_) will *NOT* be overwritten
48
+ # in self.
49
+ #
50
+ # @author Darren Oakley (https://github.com/dazoakley)
51
+ #
52
+ # @param [Tree::TreeNode] other_tree The other tree to merge with.
53
+ # @return [Tree::TreeNode] the resulting tree following the merge.
54
+ #
55
+ # @raise [TypeError] This exception is raised if _other_tree_ is not a {Tree::TreeNode}.
56
+ # @raise [ArgumentError] This exception is raised if _other_tree_ does not have the same root node as self.
57
+ def merge(other_tree)
58
+ check_merge_prerequisites(other_tree)
59
+ new_tree = merge_trees( self.root.dup, other_tree.root )
60
+ end
61
+
62
+ # Merge in another tree (that shares the same root node) into +this+ tree.
63
+ # Duplicate nodes (coming from _other_tree_) will NOT be overwritten in
64
+ # self.
65
+ #
66
+ # @author Darren Oakley (https://github.com/dazoakley)
67
+ #
68
+ # @param [Tree::TreeNode] other_tree The other tree to merge with.
69
+ #
70
+ # @raise [TypeError] This exception is raised if _other_tree_ is not a {Tree::TreeNode}.
71
+ # @raise [ArgumentError] This exception is raised if _other_tree_ does not have the same root node as self.
72
+ def merge!(other_tree)
73
+ check_merge_prerequisites( other_tree )
74
+ merge_trees( self.root, other_tree.root )
75
+ end
76
+
77
+ private
78
+
79
+ # Utility function to check that the conditions for a tree merge are met.
80
+ #
81
+ # @author Darren Oakley (https://github.com/dazoakley)
82
+ #
83
+ # @see #merge
84
+ # @see #merge!
85
+ def check_merge_prerequisites(other_tree)
86
+ unless other_tree.is_a?(Tree::TreeNode)
87
+ raise TypeError, 'You can only merge in another instance of Tree::TreeNode'
88
+ end
89
+
90
+ unless self.root.name == other_tree.root.name
91
+ raise ArgumentError, 'Unable to merge trees as they do not share the same root'
92
+ end
93
+ end
94
+
95
+ # Utility function to recursivley merge two subtrees.
96
+ #
97
+ # @author Darren Oakley (https://github.com/dazoakley)
98
+ #
99
+ # @param [Tree::TreeNode] tree1 The target tree to merge into.
100
+ # @param [Tree::TreeNode] tree2 The donor tree (that will be merged into target).
101
+ # @raise [Tree::TreeNode] The merged tree.
102
+ def merge_trees(tree1, tree2)
103
+ names1 = tree1.has_children? ? tree1.children.map { |child| child.name } : []
104
+ names2 = tree2.has_children? ? tree2.children.map { |child| child.name } : []
105
+
106
+ names_to_merge = names2 - names1
107
+ names_to_merge.each do |name|
108
+ tree1 << tree2[name].detached_subtree_copy
109
+ end
110
+
111
+ tree1.children.each do |child|
112
+ merge_trees( child, tree2[child.name] ) unless tree2[child.name].nil?
113
+ end
114
+
115
+ return tree1
116
+ end
117
+
118
+ end
@@ -0,0 +1,41 @@
1
+ # utils.rb - This file is part of the RubyTree package.
2
+ #
3
+ # = utils.rb - Provides utility functions and mixins for RubyTree.
4
+ #
5
+ # Author:: Anupam Sengupta (anupamsg@gmail.com)
6
+ #
7
+ # Time-stamp: <2012-08-25 22:01:17 anupam>
8
+ #
9
+ # Copyright (C) 2012 Anupam Sengupta <anupamsg@gmail.com>
10
+ #
11
+ # All rights reserved.
12
+ #
13
+ # Redistribution and use in source and binary forms, with or without modification,
14
+ # are permitted provided that the following conditions are met:
15
+ #
16
+ # - Redistributions of source code must retain the above copyright notice, this
17
+ # list of conditions and the following disclaimer.
18
+ #
19
+ # - Redistributions in binary form must reproduce the above copyright notice, this
20
+ # list of conditions and the following disclaimer in the documentation and/or
21
+ # other materials provided with the distribution.
22
+ #
23
+ # - Neither the name of the organization nor the names of its contributors may
24
+ # be used to endorse or promote products derived from this software without
25
+ # specific prior written permission.
26
+ #
27
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
28
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
30
+ # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
31
+ # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
32
+ # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
33
+ # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
34
+ # ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
35
+ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
36
+ # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37
+
38
+ # Provides utilities and mixin modules for RubyTree.
39
+ module Tree::Utils
40
+ # Empty module. Being used as a namespace.
41
+ end
@@ -1,11 +1,10 @@
1
- #--
2
1
  # version.rb - This file is part of the RubyTree package.
3
2
  #
4
3
  # This file provides the version number for Rubytree.
5
4
  #
6
5
  # Author:: Anupam Sengupta (anupamsg@gmail.com)
7
6
  #
8
- # Copyright (c) 2012 Anupam Sengupta
7
+ # Copyright (c) 2012, 2013 Anupam Sengupta
9
8
  #
10
9
  # All rights reserved.
11
10
  #
@@ -35,7 +34,8 @@
35
34
  # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36
35
  #
37
36
 
37
+ #
38
38
  module Tree
39
39
  # Rubytree Package Version
40
- VERSION = '0.8.3'
40
+ VERSION = '0.9.0'
41
41
  end
@@ -3,7 +3,7 @@
3
3
  # test_binarytree.rb - This file is part of the RubyTree package.
4
4
  #
5
5
  #
6
- # Copyright (c) 2006, 2007, 2008, 2009, 2010, 2012 Anupam Sengupta
6
+ # Copyright (c) 2006, 2007, 2008, 2009, 2010, 2012, 2013 Anupam Sengupta
7
7
  #
8
8
  # All rights reserved.
9
9
  #
@@ -86,6 +86,50 @@ module TestTree
86
86
  end
87
87
  end
88
88
 
89
+ # Test the inordered_each method.
90
+ def test_inordered_each
91
+ a = Tree::BinaryTreeNode.new("a")
92
+ b = Tree::BinaryTreeNode.new("b")
93
+ c = Tree::BinaryTreeNode.new("c")
94
+ d = Tree::BinaryTreeNode.new("d")
95
+ e = Tree::BinaryTreeNode.new("e")
96
+ f = Tree::BinaryTreeNode.new("f")
97
+ g = Tree::BinaryTreeNode.new("g")
98
+ h = Tree::BinaryTreeNode.new("h")
99
+ i = Tree::BinaryTreeNode.new("i")
100
+
101
+ # Create the following Tree
102
+ # f <-- level 0 (Root)
103
+ # / \
104
+ # b g <-- level 1
105
+ # / \ \
106
+ # a d i <-- level 2
107
+ # / \ /
108
+ # c e h <-- level 3
109
+ f << b << a
110
+ f << g
111
+ b << d << c
112
+ d << e
113
+ g.right_child = i # This needs to be explicit
114
+ i << h
115
+
116
+ # The expected order of response
117
+ expected_array = [a, b, c, d, e, f, g, h, i]
118
+
119
+ result_array = []
120
+ result = f.inordered_each { |node| result_array << node.detached_copy}
121
+
122
+ assert_equal(result, f) # each should return the original object
123
+
124
+ expected_array.each_index do |i|
125
+ # Match only the names.
126
+ assert_equal(expected_array[i].name, result_array[i].name)
127
+ end
128
+
129
+ assert_equal(Enumerator, f.inordered_each.class) if defined?(Enumerator.class )# Without a block
130
+ assert_equal(Enumerable::Enumerator, f.inordered_each.class) if defined?(Enumerable::Enumerator.class )# Without a block
131
+ end
132
+
89
133
  # Test the left_child method.
90
134
  def test_left_child
91
135
  @root << @left_child1
@@ -203,6 +247,7 @@ module TestTree
203
247
 
204
248
  assert_warn(DeprecatedMethodWarning) {@root.leftChild = @left_child2}
205
249
  assert_warn(DeprecatedMethodWarning) {@root.rightChild = @right_child2}
250
+ assert_raise(NoMethodError) {@root.to_snake_case("ABCD")} # Make sure the right method is visible
206
251
 
207
252
  end
208
253
 
@@ -0,0 +1,70 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # test_subclassed_node.rb - This file is part of the RubyTree package.
4
+ #
5
+ # Copyright (c) 2012 Anupam Sengupta
6
+ #
7
+ # All rights reserved.
8
+ #
9
+ # Redistribution and use in source and binary forms, with or without modification,
10
+ # are permitted provided that the following conditions are met:
11
+ #
12
+ # - Redistributions of source code must retain the above copyright notice, this
13
+ # list of conditions and the following disclaimer.
14
+ #
15
+ # - Redistributions in binary form must reproduce the above copyright notice, this
16
+ # list of conditions and the following disclaimer in the documentation and/or
17
+ # other materials provided with the distribution.
18
+ #
19
+ # - Neither the name of the organization nor the names of its contributors may
20
+ # be used to endorse or promote products derived from this software without
21
+ # specific prior written permission.
22
+ #
23
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
24
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26
+ # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
27
+ # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28
+ # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29
+ # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
30
+ # ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31
+ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32
+ # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33
+ #
34
+
35
+ require 'test/unit'
36
+ require 'json'
37
+ require 'tree'
38
+
39
+ module TestTree
40
+
41
+ # Test class for the Tree node.
42
+ class TestSubclassedTreeNode < Test::Unit::TestCase
43
+
44
+ # A subclassed node to test various inheritance related features.
45
+ class MyNode < Tree::TreeNode
46
+ # A dummy method to test the camelCasedMethod resolution
47
+ def my_dummy_method
48
+ "Hello"
49
+ end
50
+ end
51
+
52
+ def test_subclassed_camelcase_methods
53
+ root = MyNode.new("Root")
54
+
55
+ assert_equal("Hello", root.my_dummy_method)
56
+
57
+ # We should get a warning as we are invoking the camelCase version of the dummy method.
58
+ assert_warn(DeprecatedMethodWarning) { root.send('MyDummyMethod') }
59
+
60
+ # Test if the structured_warnings can be disabled to call the CamelCa
61
+ DeprecatedMethodWarning.disable do
62
+ assert_equal("Hello", root.myDummyMethod)
63
+ end
64
+
65
+ end
66
+
67
+ end
68
+ end
69
+
70
+ __END__
@@ -0,0 +1,88 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # test_thread_and_fiber.rb - This file is part of the RubyTree package.
4
+ #
5
+ # Copyright (c) 2012, 2013 Anupam Sengupta
6
+ #
7
+ # All rights reserved.
8
+ #
9
+ # Redistribution and use in source and binary forms, with or without modification,
10
+ # are permitted provided that the following conditions are met:
11
+ #
12
+ # - Redistributions of source code must retain the above copyright notice, this
13
+ # list of conditions and the following disclaimer.
14
+ #
15
+ # - Redistributions in binary form must reproduce the above copyright notice, this
16
+ # list of conditions and the following disclaimer in the documentation and/or
17
+ # other materials provided with the distribution.
18
+ #
19
+ # - Neither the name of the organization nor the names of its contributors may
20
+ # be used to endorse or promote products derived from this software without
21
+ # specific prior written permission.
22
+ #
23
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
24
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26
+ # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
27
+ # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28
+ # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29
+ # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
30
+ # ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31
+ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32
+ # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33
+ #
34
+
35
+ require 'test/unit'
36
+ require 'json'
37
+ require 'tree'
38
+
39
+ module TestTree
40
+ # Test class for the Tree node.
41
+ class TestFiberAndThreadOnNode < Test::Unit::TestCase
42
+
43
+ # Test long and unbalanced trees
44
+ def create_long_depth_trees(depth=100)
45
+ tree = Tree::TreeNode.new("/")
46
+ current = tree
47
+ depth.times do |i|
48
+ new_node = Tree::TreeNode.new("#{i}")
49
+ current << new_node
50
+ current = new_node
51
+ end
52
+
53
+ tree.each { |n| nil }
54
+ tree
55
+ end
56
+
57
+ # Test the recursive methods with a fiber. The stack usage is causing
58
+ # failure for very large depths on unbalanced nodes.
59
+ def test_fiber_for_recursion
60
+ return unless defined?(Fiber.class) # Fibers exist only from Ruby 1.9 onwards.
61
+ assert_nothing_thrown do
62
+ Fiber.new do
63
+ depth = 1000 # Use a reasonably large depth, which would trip a recursive stack
64
+ root = create_long_depth_trees(depth)
65
+ assert_equal(depth+1, root.size)
66
+ end.resume
67
+ end
68
+
69
+ end # test_fiber
70
+
71
+ # Test the recursive methods with a thread. The stack usage is causing
72
+ # failure for very large depths on unbalanced nodes.
73
+ def test_thread_for_recursion
74
+ assert_nothing_thrown do
75
+ depth = 1000 # Use a reasonably large depth, which would trip a recursive stack
76
+ Thread.abort_on_exception = true
77
+ Thread.new do
78
+ root = create_long_depth_trees(depth)
79
+ assert_equal(depth+1, root.size)
80
+ end
81
+ end
82
+
83
+ end # test_thread
84
+
85
+ end
86
+ end
87
+
88
+ __END__
@@ -2,7 +2,7 @@
2
2
 
3
3
  # test_tree.rb - This file is part of the RubyTree package.
4
4
  #
5
- # Copyright (c) 2006, 2007, 2008, 2009, 2010, 2011, 2012 Anupam Sengupta
5
+ # Copyright (c) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 Anupam Sengupta
6
6
  #
7
7
  # All rights reserved.
8
8
  #
@@ -145,7 +145,6 @@ module TestTree
145
145
  first_node = Tree::TreeNode.new(1)
146
146
  second_node = Tree::TreeNode.new(2)
147
147
 
148
-
149
148
  assert_equal(first_node <=> nil, +1)
150
149
  assert_equal(first_node <=> second_node, -1)
151
150
 
@@ -164,6 +163,24 @@ module TestTree
164
163
  StandardWarning.enable
165
164
  end
166
165
 
166
+ # Test the inclusion of Comparable
167
+ def test_is_comparable
168
+ nodeA = Tree::TreeNode.new("NodeA", "Some Content")
169
+ nodeB = Tree::TreeNode.new("NodeB", "Some Content")
170
+ nodeC = Tree::TreeNode.new("NodeC", "Some Content")
171
+
172
+ # Check if the nodes compare correctly
173
+ assert(nodeA < nodeB, "Node A is lexically 'less than' node B")
174
+ assert(nodeA <= nodeB, "Node A is lexically 'less than' node B")
175
+ assert(nodeB > nodeA, "Node B is lexically 'greater than' node A")
176
+ assert(nodeB >= nodeA, "Node B is lexically 'greater than' node A")
177
+
178
+ assert(!(nodeA == nodeB), "Node A and Node B are not equal")
179
+ assert(nodeB.between?(nodeA, nodeC), "Node B is lexically between node A and node C")
180
+
181
+
182
+ end
183
+
167
184
  # Test the to_s method. This is probably a little fragile right now.
168
185
  def test_to_s
169
186
  a_node = Tree::TreeNode.new("A Node", "Some Content")
@@ -250,14 +267,16 @@ module TestTree
250
267
 
251
268
  # Lets first collect the siblings in an array.
252
269
  siblings = []
253
- @child1.siblings { |sibling| siblings << sibling}
270
+ result = @child1.siblings { |sibling| siblings << sibling}
254
271
 
272
+ assert_equal(@child1, result)
255
273
  assert_equal(2, siblings.length, "Should have two siblings")
256
274
  assert(siblings.include?(@child2), "Should have 2nd child as sibling")
257
275
  assert(siblings.include?(@child3), "Should have 3rd child as sibling")
258
276
 
259
277
  siblings.clear
260
278
  siblings = @child1.siblings
279
+ assert_equal(Array, siblings.class)
261
280
  assert_equal(2, siblings.length, "Should have two siblings")
262
281
 
263
282
  siblings.clear
@@ -267,6 +286,7 @@ module TestTree
267
286
  siblings.clear
268
287
  siblings = @root.siblings
269
288
  assert_equal(0, siblings.length, "Root should not have any siblings")
289
+
270
290
  end
271
291
 
272
292
  # Test the is_only_child? method.
@@ -465,21 +485,26 @@ module TestTree
465
485
  assert_equal(0, child.node_height, "The subtree at #{child.name} should have a height of 0")
466
486
  end
467
487
 
468
- children = []
469
- for child in @root.children
470
- children << child
471
- end
488
+ result_array = @root.children
489
+
490
+ assert_equal(3, result_array.length, "Should have three direct children")
491
+ assert(!result_array.include?(@root), "Should not have root")
492
+ assert_equal(result_array[0], @child1, "Should have child 1")
493
+ assert_equal(result_array[1], @child2, "Should have child 2")
494
+ assert_equal(result_array[2], @child3, "Should have child 3")
495
+ assert(!result_array.include?(@child4), "Should not have child 4")
496
+
497
+ # Lets try the block version of the method.
498
+ result_array.clear
499
+ result = @root.children {|child| result_array << child}
500
+ assert_equal(@root, result)
501
+ result_array.length
502
+ assert_equal(3, result_array.length, "Should have three children")
503
+ assert_equal(result_array[0], @child1, "Should have child 1")
504
+ assert_equal(result_array[1], @child2, "Should have child 2")
505
+ assert_equal(result_array[2], @child3, "Should have child 3")
506
+ assert(!result_array.include?(@child4), "Should not have child 4")
472
507
 
473
- assert_equal(3, children.length, "Should have three direct children")
474
- assert(!children.include?(@root), "Should not have root")
475
- assert(children.include?(@child1), "Should have child 1")
476
- assert(children.include?(@child2), "Should have child 2")
477
- assert(children.include?(@child3), "Should have child 3")
478
- assert(!children.include?(@child4), "Should not have child 4")
479
-
480
- children.clear
481
- children = @root.children
482
- assert_equal(3, children.length, "Should have three children")
483
508
  end
484
509
 
485
510
  # Test the first_child method.
@@ -547,15 +572,27 @@ module TestTree
547
572
  def test_each_leaf
548
573
  setup_test_tree
549
574
 
550
- nodes = []
551
- @root.each_leaf { |node| nodes << node }
575
+ result_array = []
576
+ result = @root.each_leaf { |node| result_array << node }
577
+ assert_equal(@root, result)
578
+ assert_equal(3, result_array.length, "Should have THREE LEAF NODES")
579
+ assert(!result_array.include?(@root), "Should not have root")
580
+ assert(result_array.include?(@child1), "Should have child 1")
581
+ assert(result_array.include?(@child2), "Should have child 2")
582
+ assert(!result_array.include?(@child3), "Should not have child 3")
583
+ assert(result_array.include?(@child4), "Should have child 4")
584
+
585
+ # Now lets try without the block
586
+ result_array.clear
587
+ result_array = @root.each_leaf
588
+ assert_equal(Array, result_array.class)
589
+ assert_equal(3, result_array.length, "Should have THREE LEAF NODES")
590
+ assert(!result_array.include?(@root), "Should not have root")
591
+ assert(result_array.include?(@child1), "Should have child 1")
592
+ assert(result_array.include?(@child2), "Should have child 2")
593
+ assert(!result_array.include?(@child3), "Should not have child 3")
594
+ assert(result_array.include?(@child4), "Should have child 4")
552
595
 
553
- assert_equal(3, nodes.length, "Should have THREE LEAF NODES")
554
- assert(!nodes.include?(@root), "Should not have root")
555
- assert(nodes.include?(@child1), "Should have child 1")
556
- assert(nodes.include?(@child2), "Should have child 2")
557
- assert(!nodes.include?(@child3), "Should not have child 3")
558
- assert(nodes.include?(@child4), "Should have child 4")
559
596
  end
560
597
 
561
598
  # Test the parent method.
@@ -795,11 +832,15 @@ module TestTree
795
832
 
796
833
  # Create the response
797
834
  result_array = Array.new
798
- j.breadth_each { |node| result_array << node.detached_copy }
835
+ result = j.breadth_each { |node| result_array << node.detached_copy }
799
836
 
837
+ assert_equal(j, result)
800
838
  expected_array.each_index do |i|
801
839
  assert_equal(expected_array[i].name, result_array[i].name) # Match only the names.
802
840
  end
841
+
842
+ assert_equal(Enumerator, j.breadth_each.class) if defined?(Enumerator.class )# Without a block
843
+ assert_equal(Enumerable::Enumerator, j.breadth_each.class) if defined?(Enumerable::Enumerator.class )# Without a block
803
844
  end
804
845
 
805
846
  # Test the preordered_each method.
@@ -828,12 +869,56 @@ module TestTree
828
869
  j << k << z
829
870
 
830
871
  result_array = []
831
- j.preordered_each { |node| result_array << node.detached_copy}
872
+ result = j.preordered_each { |node| result_array << node.detached_copy}
873
+
874
+ assert_equal(j, result) # Each returns the invocation target
832
875
 
833
876
  expected_array.each_index do |i|
834
877
  # Match only the names.
835
878
  assert_equal(expected_array[i].name, result_array[i].name)
836
879
  end
880
+
881
+ assert_equal(Enumerator, j.preordered_each.class) if defined?(Enumerator.class )# Without a block
882
+ assert_equal(Enumerable::Enumerator, j.preordered_each.class) if defined?(Enumerable::Enumerator.class )# Without a block
883
+ end
884
+
885
+ # Test the postordered_each method.
886
+ def test_postordered_each
887
+ j = Tree::TreeNode.new("j")
888
+ f = Tree::TreeNode.new("f")
889
+ k = Tree::TreeNode.new("k")
890
+ a = Tree::TreeNode.new("a")
891
+ d = Tree::TreeNode.new("d")
892
+ h = Tree::TreeNode.new("h")
893
+ z = Tree::TreeNode.new("z")
894
+
895
+ # The expected order of response
896
+ expected_array = [d, a, h, f, z, k, j]
897
+
898
+ # Create the following Tree
899
+ # j <-- level 0 (Root)
900
+ # / \
901
+ # f k <-- level 1
902
+ # / \ \
903
+ # a h z <-- level 2
904
+ # \
905
+ # d <-- level 3
906
+ j << f << a << d
907
+ f << h
908
+ j << k << z
909
+
910
+ result_array = []
911
+ result = j.postordered_each { |node| result_array << node.detached_copy}
912
+
913
+ assert_equal(j, result) # Each returns the invocation target
914
+
915
+ expected_array.each_index do |i|
916
+ # Match only the names.
917
+ assert_equal(expected_array[i].name, result_array[i].name)
918
+ end
919
+
920
+ assert_equal(Enumerator, j.postordered_each.class) if defined?(Enumerator.class )# Without a block
921
+ assert_equal(Enumerable::Enumerator, j.postordered_each.class) if defined?(Enumerable::Enumerator.class )# Without a block
837
922
  end
838
923
 
839
924
  # test the detached_copy method.
@@ -1021,7 +1106,7 @@ module TestTree
1021
1106
  ]
1022
1107
  }.to_json
1023
1108
 
1024
- tree = JSON.parse(tree_as_json)
1109
+ tree = JSON.parse(tree_as_json, :create_additions => true)
1025
1110
 
1026
1111
  assert_equal(@root.name, tree.root.name, "Root should be returned")
1027
1112
  assert_equal(@child1.name, tree[0].name, "Child 1 should be returned")
@@ -1037,7 +1122,7 @@ module TestTree
1037
1122
 
1038
1123
  j = root_node.to_json
1039
1124
 
1040
- k = JSON.parse(j)
1125
+ k = JSON.parse(j, :create_additions => true)
1041
1126
 
1042
1127
  assert_equal(k.name, root_node.name, "Root should be returned")
1043
1128
  assert_equal(k[0].name, root_node[0].name, "Child 1 should be returned")
@@ -1050,10 +1135,10 @@ module TestTree
1050
1135
  setup_test_tree
1051
1136
 
1052
1137
  meth_names_to_test = %w{isRoot? isLeaf? hasContent?
1053
- hasChildren? setAsRoot! firstChild lastChild
1138
+ hasChildren? firstChild lastChild
1054
1139
  firstSibling isFirstSibling? lastSibling isLastSibling?
1055
1140
  isOnlyChild? nextSibling previousSibling nodeHeight nodeDepth
1056
- createDumpRep removeFromParent! removeAll! freezeTree! }
1141
+ removeFromParent! removeAll! freezeTree! }
1057
1142
 
1058
1143
  require 'structured_warnings'
1059
1144
 
@@ -1065,7 +1150,7 @@ module TestTree
1065
1150
  assert_warn(DeprecatedMethodWarning) {@root.send(meth_name)}
1066
1151
  end
1067
1152
 
1068
- # Special Case for printTree to avoid putting stuff on the STDOUT during the unit test.
1153
+ # Special Case for printTree to avoid putting stuff on the STDOUT during the unit test.
1069
1154
  begin
1070
1155
  require 'stringio'
1071
1156
  $stdout = StringIO.new
@@ -1115,10 +1200,8 @@ module TestTree
1115
1200
  assert_raise(ArgumentError) {root << root}
1116
1201
 
1117
1202
  # And now a scenario where the node addition is done down the hierarchy
1118
- # @todo This scenario is not yet fixed.
1119
1203
  child = Tree::TreeNode.new("child")
1120
- root << child << root
1121
- # puts root # This will throw a stack trace
1204
+ assert_raise(RuntimeError) { root << child << root }
1122
1205
  end
1123
1206
 
1124
1207
  # Test whether the tree_leaf method works correctly
@@ -1132,6 +1215,97 @@ module TestTree
1132
1215
 
1133
1216
  end
1134
1217
 
1218
+ # Test if node names are really unique in the whole tree
1219
+ def test_unique_node_names
1220
+ setup_test_tree
1221
+
1222
+ assert_raise(RuntimeError) { @root << @child1 }
1223
+ assert_raise(RuntimeError) { @root.first_child << @child2 }
1224
+ end
1225
+
1226
+ # Setup function to build some extra trees to play with.
1227
+ def setup_other_test_tree
1228
+ # Build up another tree
1229
+ #
1230
+ # ROOT
1231
+ # |
1232
+ # |-- Child1
1233
+ # | |
1234
+ # | |-- Child1a
1235
+ # | |-- Child1b
1236
+ # |
1237
+ # |-- Child3
1238
+ # |
1239
+ # |-- Child3a -- Child3a1
1240
+ #
1241
+ @other_tree = @root.detached_copy
1242
+ @other_tree << @child1.detached_copy
1243
+ @other_tree["Child1"] << Tree::TreeNode.new("Child1a", "GrandChild Node 1a")
1244
+ @other_tree["Child1"] << Tree::TreeNode.new("Child1b", "GrandChild Node 1b")
1245
+ @other_tree << @child3.detached_copy
1246
+ @other_tree["Child3"] << Tree::TreeNode.new("Child3a", "GrandChild Node 3a")
1247
+ @other_tree["Child3"]["Child3a"] << Tree::TreeNode.new("Child3a1", "GreatGrandChild Node 3a1")
1248
+
1249
+ # And another (different) one so we can test exceptions...
1250
+ @other_tree2 = Tree::TreeNode.new("ROOTIE", "A different root")
1251
+ @other_tree2 << Tree::TreeNode.new("new_child1", "New Child 1")
1252
+ end
1253
+
1254
+ # Test tree merging.
1255
+ def test_merge
1256
+ setup_test_tree
1257
+ setup_other_test_tree
1258
+
1259
+ merged_tree = @root.merge(@other_tree)
1260
+
1261
+ # puts "\n\ntest_merge:\n\n"
1262
+ # @root.print_tree
1263
+ # puts "\n"
1264
+ # @other_tree.print_tree
1265
+ # puts "\n"
1266
+ # merged_tree.print_tree
1267
+
1268
+ assert( @root["Child1"]["Child1a"].nil?, ".merge() has altered self." )
1269
+ assert( @root["Child1"]["Child1b"].nil?, ".merge() has altered self." )
1270
+ assert( @root["Child3"]["Child3a"].nil?, ".merge() has altered self." )
1271
+ assert( merged_tree.is_a?(Tree::TreeNode) )
1272
+ assert( !merged_tree["Child1"]["Child1a"].nil?, ".merge() has not included ['Child1']['Child1a'] from other_tree." )
1273
+ assert( !merged_tree["Child1"]["Child1b"].nil?, ".merge() has not included ['Child1']['Child1b'] from other_tree." )
1274
+ assert( !merged_tree["Child3"]["Child3a"].nil?, ".merge() has not included ['Child3']['Child3a'] from other_tree." )
1275
+ assert( !merged_tree["Child2"].nil?, ".merge() has not included ['Child2'] from self." )
1276
+ assert( !merged_tree["Child3"]["Child3a"]["Child3a1"].nil?, ".merge() has not included ['Child3']['Child3a']['Child3a1'] from other_tree." )
1277
+ assert( !merged_tree["Child3"]["Child4"].nil?, ".merge() has not included ['Child3']['Child4'] from self." )
1278
+
1279
+ assert_raise(ArgumentError) { @root.merge(@other_tree2) }
1280
+ assert_raise(TypeError) { @root.merge('ROOT') }
1281
+ end
1282
+
1283
+ # Test tree merging.
1284
+ def test_merge_bang
1285
+ setup_test_tree
1286
+ setup_other_test_tree
1287
+
1288
+ # puts "\n\ntest_merge_bang:\n\n"
1289
+ # @root.print_tree
1290
+ # puts "\n"
1291
+ # @other_tree.print_tree
1292
+
1293
+ @root.merge!(@other_tree)
1294
+
1295
+ # puts "\n"
1296
+ # @root.print_tree
1297
+
1298
+ assert( !@root["Child1"]["Child1a"].nil?, ".merge() has not included ['Child1']['Child1a'] from other_tree." )
1299
+ assert( !@root["Child1"]["Child1b"].nil?, ".merge() has not included ['Child1']['Child1b'] from other_tree." )
1300
+ assert( !@root["Child3"]["Child3a"].nil?, ".merge() has not included ['Child3']['Child3a'] from other_tree." )
1301
+ assert( !@root["Child2"].nil?, ".merge() has not included ['Child2'] from self." )
1302
+ assert( !@root["Child3"]["Child3a"]["Child3a1"].nil?, ".merge() has not included ['Child3']['Child3a']['Child3a1'] from other_tree." )
1303
+ assert( !@root["Child3"]["Child4"].nil?, ".merge() has not included ['Child3']['Child4'] from self." )
1304
+
1305
+ assert_raise(ArgumentError) { @root.merge!(@other_tree2) }
1306
+ assert_raise(TypeError) { @root.merge!('ROOT') }
1307
+ end
1308
+
1135
1309
  end
1136
1310
  end
1137
1311