caruby-core 1.4.4 → 1.4.5

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.
Files changed (37) hide show
  1. data/History.txt +2 -0
  2. data/README.md +0 -2
  3. data/lib/caruby/migration/migrator.rb +1 -1
  4. data/lib/caruby/version.rb +1 -1
  5. data/test/lib/caruby/csv/csv_mapper_test.rb +40 -0
  6. data/test/lib/caruby/csv/csvio_test.rb +69 -0
  7. data/test/lib/caruby/database/persistable_test.rb +92 -0
  8. data/test/lib/caruby/domain/domain_test.rb +126 -0
  9. data/test/lib/caruby/domain/inversible_test.rb +99 -0
  10. data/test/lib/caruby/domain/reference_visitor_test.rb +130 -0
  11. data/test/lib/caruby/import/java_test.rb +58 -0
  12. data/test/lib/caruby/util/cache_test.rb +23 -0
  13. data/test/lib/caruby/util/class_test.rb +61 -0
  14. data/test/lib/caruby/util/collection_test.rb +379 -0
  15. data/test/lib/caruby/util/command_test.rb +55 -0
  16. data/test/lib/caruby/util/controlled_value_test.rb +26 -0
  17. data/test/lib/caruby/util/domain_extent_test.rb +60 -0
  18. data/test/lib/caruby/util/file_separator_test.rb +30 -0
  19. data/test/lib/caruby/util/inflector_test.rb +12 -0
  20. data/test/lib/caruby/util/lazy_hash_test.rb +34 -0
  21. data/test/lib/caruby/util/merge_test.rb +83 -0
  22. data/test/lib/caruby/util/module_test.rb +29 -0
  23. data/test/lib/caruby/util/options_test.rb +59 -0
  24. data/test/lib/caruby/util/partial_order_test.rb +41 -0
  25. data/test/lib/caruby/util/person_test.rb +115 -0
  26. data/test/lib/caruby/util/pretty_print_test.rb +85 -0
  27. data/test/lib/caruby/util/properties_test.rb +50 -0
  28. data/test/lib/caruby/util/stopwatch_test.rb +18 -0
  29. data/test/lib/caruby/util/topological_sync_enumerator_test.rb +69 -0
  30. data/test/lib/caruby/util/transitive_closure_test.rb +59 -0
  31. data/test/lib/caruby/util/tree_test.rb +23 -0
  32. data/test/lib/caruby/util/trie_test.rb +14 -0
  33. data/test/lib/caruby/util/validation_test.rb +14 -0
  34. data/test/lib/caruby/util/version_test.rb +31 -0
  35. data/test/lib/caruby/util/visitor_test.rb +277 -0
  36. data/test/lib/caruby/util/weak_hash_test.rb +45 -0
  37. metadata +179 -161
@@ -0,0 +1,85 @@
1
+ $:.unshift 'lib'
2
+
3
+ require "test/unit"
4
+
5
+ require 'set'
6
+ require 'date'
7
+ require 'caruby/util/pretty_print'
8
+
9
+ class PrettyPrintTest < Test::Unit::TestCase
10
+ def test_nil
11
+ assert_equal('nil', nil.pp_s, 'Nil pretty print incorrect')
12
+ end
13
+
14
+ def test_date_time
15
+ date = DateTime.civil(2009, 4, 15, 5, 55, 55)
16
+ assert_equal(date.strftime, date.pp_s, 'Date pretty print incorrect')
17
+ end
18
+
19
+ def test_array
20
+ assert_equal('[:a, :b]', [:a, :b].pp_s, 'Array pretty print incorrect')
21
+ end
22
+
23
+ def test_java_collection
24
+ a = Java::JavaUtil::ArrayList.new
25
+ a << :a << :b
26
+ assert_equal(a.to_a.pp_s, a.pp_s, 'Java collection pretty print incorrect')
27
+ end
28
+
29
+ def test_java_collection_cycle
30
+ a = Java::JavaUtil::ArrayList.new
31
+ a << :a << a
32
+ assert_equal('[:a, [...]]', a.pp_s(:single_line), 'Cyclic set pretty print incorrect')
33
+ end
34
+
35
+ def test_hash
36
+ assert_equal('{:a => a, :b => b}', {:a => 'a', :b => 'b'}.pp_s(:single_line), 'Hash pretty print incorrect')
37
+ end
38
+
39
+ def test_qp
40
+ assert_equal('1', 1.qp, 'Numeric quick print incorrect')
41
+ assert_equal('nil', nil.qp, 'nil quick print incorrect')
42
+ assert_equal('a', 'a'.qp, 'String quick print incorrect')
43
+ assert_equal(':a', :a.qp, 'Symbol quick print incorrect')
44
+ assert_equal('[:a]', [:a].qp, 'Array quick print incorrect')
45
+ assert_equal('TestCase', Test::Unit::TestCase.qp, 'Class quick print incorrect')
46
+
47
+ x = {:a => 'a', :b => 'b'}
48
+ x.qp
49
+
50
+
51
+ assert_equal('{:a => a, :b => b}', {:a => 'a', :b => 'b'}.qp, 'Hash quick print incorrect')
52
+ end
53
+
54
+ def test_set
55
+ assert_equal([:a].pp_s, [:a].to_set.pp_s, 'Set pretty print incorrect')
56
+ end
57
+
58
+ def test_set_cycle
59
+ a = [:a].to_set
60
+ a << a
61
+ assert_equal('[:a, [...]]', a.pp_s(:single_line), 'Cyclic set pretty print incorrect')
62
+ end
63
+
64
+ def test_single_line_argument
65
+ a = [].fill(:a, 0, 80)
66
+ assert(a.pp_s =~ /\n/, 'Test array not long enough')
67
+ assert(!a.pp_s(:single_line).include?("\n"), 'Single line option ignored')
68
+ end
69
+
70
+ def test_single_line_option
71
+ a = [].fill(:a, 0, 80)
72
+ assert_equal(a.pp_s(:single_line => true), a.pp_s(:single_line), 'Single line option ignored')
73
+ end
74
+
75
+ def test_print_wrapper_block
76
+ tuples = [[:a, :b], [:c]]
77
+ wrapper = PrintWrapper.new { |tuple| "<#{tuple.join(',')}>" }
78
+ wrappers = tuples.wrap{ |tuple| wrapper.wrap(tuple) }
79
+ assert_equal("[<a,b>, <c>]", wrappers.pp_s)
80
+ end
81
+
82
+ def test_wrapper_block
83
+ assert_equal("[<a,b>, <c>]", [[:a, :b], [:c]].pp_s { |tuple| "<#{tuple.join(',')}>" })
84
+ end
85
+ end
@@ -0,0 +1,50 @@
1
+ $:.unshift('lib')
2
+
3
+ require "test/unit"
4
+ require 'caruby/util/properties'
5
+ require 'caruby/util/log'
6
+
7
+ class PropertiesTest < Test::Unit::TestCase
8
+ LOG_FILE = File.join('test', 'results', 'log', 'caruby.log')
9
+ FIXTURES_DIR = File.join('test', 'fixtures', 'caruby', 'util', 'properties')
10
+ INPUT_FILE = File.join(FIXTURES_DIR, 'properties.yaml')
11
+ MERGE_FILE = File.join(FIXTURES_DIR, 'merge_properties.yaml')
12
+ MERGE_PROPERTIES = ['short', 'nested']
13
+
14
+ def setup
15
+ CaRuby::Log.instance.open(LOG_FILE, :debug => true)
16
+ @properties = CaRuby::Properties.new(INPUT_FILE, :merge => MERGE_PROPERTIES)
17
+ end
18
+
19
+ def test_short_name
20
+ assert_equal('short', @properties['short'], 'Short property incorrect')
21
+ end
22
+
23
+ def test_dotted_name
24
+ assert_equal('dot', @properties['dot.property'], 'Dotted property incorrect')
25
+ end
26
+
27
+ def test_symbol
28
+ assert_equal('short', @properties[:short], 'Symbol key lookup incorrect')
29
+ end
30
+
31
+ def test_nested
32
+ assert_not_nil(@properties['nested'], 'Nested property not found')
33
+ assert_equal('A', @properties['nested']['a'], 'Nested property value incorrect')
34
+ assert_equal('B', @properties['nested']['b'], 'Nested property value incorrect')
35
+ assert_not_nil(@properties['nested']['deep'], 'Nested deep property not found')
36
+ assert_equal('U', @properties['nested']['deep']['u'], 'Nested deep property value incorrect')
37
+ end
38
+
39
+ def test_merge
40
+ @properties.load_properties_file(MERGE_FILE)
41
+ assert_equal('long', @properties['short'], 'Merge property value not overridden')
42
+ assert_equal('dash', @properties['dot.property'], 'Non-merge property value not overridden')
43
+ assert_not_nil(@properties['nested'], 'Nested property override incorrect')
44
+ assert_equal('X', @properties['nested']['a'], 'Nested property value not overridden')
45
+ assert_equal('B', @properties['nested']['b'], 'Nested property value not retained')
46
+ assert_equal('C', @properties['nested']['c'], 'Nested property value not added')
47
+ assert_equal('U', @properties['nested']['deep']['u'], 'Nested deep property value not retained')
48
+ assert_equal('V', @properties['nested']['deep']['v'], 'Nested deep property value not added')
49
+ end
50
+ end
@@ -0,0 +1,18 @@
1
+ $:.unshift 'lib'
2
+
3
+ require 'caruby/util/stopwatch'
4
+ require "test/unit"
5
+
6
+ class StopwatchTest < Test::Unit::TestCase
7
+
8
+ def setup
9
+ @timer = Stopwatch.new
10
+ end
11
+
12
+ def test_run
13
+ t1 = @timer.run { 1000000.times { " " * 100 } }
14
+ t2 = @timer.run { 1000000.times { " " * 100 } }
15
+ assert_equal(t1.elapsed + t2.elapsed, @timer.elapsed, "Elapsed time incorrectly accumulated")
16
+ assert_equal(t1.cpu + t2.cpu, @timer.cpu, "CPU time incorrectly accumulated")
17
+ end
18
+ end
@@ -0,0 +1,69 @@
1
+ $:.unshift 'lib'
2
+
3
+ require "test/unit"
4
+ require 'caruby/util/topological_sync_enumerator'
5
+
6
+ class TopologicalSyncEnumeratorTest < Test::Unit::TestCase
7
+ class Node
8
+ attr_reader :value, :parent
9
+
10
+ def initialize(value, parent=nil)
11
+ super()
12
+ @value = value
13
+ @parent = parent
14
+ end
15
+
16
+ def to_s
17
+ value.to_s
18
+ end
19
+
20
+ alias :inspect :to_s
21
+ end
22
+
23
+ def test_simple
24
+ a = Node.new(:a)
25
+ b = Node.new(:b)
26
+ c = Node.new(:c, a)
27
+ d = Node.new(:d, b)
28
+ enum = TopologicalSyncEnumerator.new([a, c], [b, d], :parent)
29
+ assert_equal([[a, b], [c, d]], enum.to_a, "Enumeration incorrect")
30
+ end
31
+
32
+ def test_many
33
+ a = Node.new(:a)
34
+ b = Node.new(:b)
35
+ c1 = Node.new(:c1, a)
36
+ c2 = Node.new(:c2, a)
37
+ d1 = Node.new(:d1, b)
38
+ d2 = Node.new(:d2, b)
39
+ enum = TopologicalSyncEnumerator.new([a, c1, c2], [b, d1, d2], :parent)
40
+ assert_equal([[a, b], [c1, d1], [c2, d2]], enum.to_a, "Enumeration incorrect")
41
+ end
42
+
43
+ def test_matcher
44
+ a = Node.new(:a)
45
+ b = Node.new(:b)
46
+ c1 = Node.new(:c1, a)
47
+ c2 = Node.new(:c2, a)
48
+ d1 = Node.new(:d1, b)
49
+ d2 = Node.new(:d2, b)
50
+ enum = TopologicalSyncEnumerator.new([a, c1, c2], [b, d1, d2], :parent) { |t, srcs| srcs.last }
51
+ assert_equal([[a, b], [c1, d2], [c2, d1]], enum.to_a, "Enumeration incorrect")
52
+ end
53
+
54
+ def test_excess_target
55
+ a = Node.new(:a)
56
+ b = Node.new(:b)
57
+ c = Node.new(:c, a)
58
+ enum = TopologicalSyncEnumerator.new([a, c], [b], :parent)
59
+ assert_equal([[a, b]], enum.to_a, "Enumeration incorrect")
60
+ end
61
+
62
+ def test_excess_source
63
+ a = Node.new(:a)
64
+ b = Node.new(:b)
65
+ d = Node.new(:d, b)
66
+ enum = TopologicalSyncEnumerator.new([a], [b, d], :parent)
67
+ assert_equal([[a, b]], enum.to_a, "Enumeration incorrect")
68
+ end
69
+ end
@@ -0,0 +1,59 @@
1
+ $:.unshift 'lib'
2
+
3
+ require "test/unit"
4
+ require 'caruby/util/collection'
5
+ require 'caruby/util/transitive_closure'
6
+
7
+ class TransitiveClosureTest < Test::Unit::TestCase
8
+ class Node
9
+ attr_reader :parent, :children, :value
10
+
11
+ def initialize(value, parent=nil)
12
+ super()
13
+ @value = value
14
+ @parent = parent
15
+ @children = []
16
+ parent.children << self if parent
17
+ end
18
+
19
+ def to_s
20
+ value.to_s
21
+ end
22
+
23
+ alias :inspect :to_s
24
+ end
25
+
26
+ def test_hierarchy
27
+ root= Node.new('root'); a = Node.new('a', root); b = Node.new('b', a); c = Node.new('c', a); d = Node.new('d', c); e = Node.new('e', root)
28
+ expected = [root, a, b, c, d, e].to_set
29
+ closure = root.transitive_closure(:children)
30
+ assert_equal(expected, closure.to_set, "Hierarchy closure incorrect")
31
+ closure.each_with_index { |node, index| closure[index..-1].each { |other| assert(!other.children.include?(node), "Order incorrect") } }
32
+ closure.reject { |node| node.parent.nil? }.each_with_index { |node, index| assert(closure[0..index].detect { |other| other.children.include?(node) }, "Order incorrect") }
33
+ end
34
+
35
+ def test_internal
36
+ root= Node.new('root'); a = Node.new('a', root); b = Node.new('b', a); c = Node.new('c', a); d = Node.new('d', c); e = Node.new('e', root)
37
+ expected = [a, b, c, d].to_set
38
+ closure = a.transitive_closure(:children)
39
+ assert_equal(expected, closure.to_set, "Hierarchy closure incorrect")
40
+ end
41
+
42
+ def test_leaf
43
+ leaf = Node.new(1)
44
+ assert_equal([leaf], leaf.transitive_closure(:children), "Leaf closure incorrect")
45
+ end
46
+
47
+ def test_collection
48
+ a = Node.new('a'); b = Node.new('b'); c = Node.new('c', a); d = Node.new('d', b); e = Node.new('e', c)
49
+ expected = [a, b, c, d, e].to_set
50
+ closure = [a, b].transitive_closure(:children)
51
+ assert_equal(expected, closure.to_set, "Hierarchy closure incorrect")
52
+ end
53
+
54
+ def test_cycle
55
+ root= Node.new('root'); a = Node.new('a', root); b = Node.new('b', a); c = Node.new('c', a); c.children << root
56
+ expected = [root, a, b, c].to_set
57
+ assert_equal(expected, a.transitive_closure(:children).to_set, "Cycle closure incorrect")
58
+ end
59
+ end
@@ -0,0 +1,23 @@
1
+ $:.unshift 'lib'
2
+
3
+ require "test/unit"
4
+ require 'caruby/util/tree'
5
+
6
+ class TreeTest < Test::Unit::TestCase
7
+ def test_tree
8
+ a = Tree.new(:a)
9
+ assert_equal(a.root, :a, "Tree root incorrect")
10
+ a << :b
11
+ b = a[:b]
12
+ assert_not_nil(b, "Subtree not found")
13
+ assert_equal(b, a.children.first, "Subtree child not found")
14
+ assert_equal(:b, b.root, "Subtree root incorrect")
15
+ assert_nil(a[:b, :c], "Subtree at non-existing path incorrect")
16
+ b << :c
17
+ assert_equal(b[:c], a[:b, :c], "Subtree at path incorrect")
18
+ end
19
+
20
+ def test_fill
21
+ assert_equal(Tree.new(:a).fill(:b, :c).root, :c, "Fill result incorrect")
22
+ end
23
+ end
@@ -0,0 +1,14 @@
1
+ $:.unshift 'lib'
2
+
3
+ require "test/unit"
4
+ require 'caruby/util/trie'
5
+
6
+ class TrieTest < Test::Unit::TestCase
7
+ def test_trie
8
+ trie = Trie.new
9
+ assert_nil(trie[:a], "Non-existing node value incorrect")
10
+ trie[:a, :b] = 1
11
+ assert_nil(trie[:a], "Existing unvalued node value incorrect")
12
+ assert_equal(1, trie[:a, :b], "Trie value incorrect")
13
+ end
14
+ end
@@ -0,0 +1,14 @@
1
+ $:.unshift 'lib'
2
+
3
+ require "test/unit"
4
+ require 'caruby/util/validation'
5
+
6
+ class ValidationTest < Test::Unit::TestCase
7
+ include Validation
8
+
9
+ def test_validate_type
10
+ assert_nothing_raised(TypeError, 'Valid argument declared invalid') { || validate_type(1 => Integer) }
11
+ assert_raises(ArgumentError, 'Missing argument declared valid') { || validate_type(nil => Integer) }
12
+ assert_raises(TypeError, 'Miscast argument declared valid') { || validate_type('a'=>Integer) }
13
+ end
14
+ end
@@ -0,0 +1,31 @@
1
+ $:.unshift 'lib'
2
+
3
+ require "test/unit"
4
+ require 'caruby/util/version'
5
+
6
+ class VersionTest < Test::Unit::TestCase
7
+ def test_major
8
+ assert_equal(0, "1".to_version <=> "1".to_version, "Version major comparison incorrect")
9
+ assert_equal(-1, "1".to_version <=> "2".to_version, "Version major comparison incorrect")
10
+ assert_equal(1, "2".to_version <=> "1".to_version, "Version major comparison incorrect")
11
+ end
12
+
13
+ def test_minor
14
+ assert_equal(0, "1.1".to_version <=> "1.1".to_version, "Version minor comparison incorrect")
15
+ assert_equal(-1, "1".to_version <=> "1.1".to_version, "Version minor comparison incorrect")
16
+ assert_equal(-1, "1.1".to_version <=> "1.2".to_version, "Version minor comparison incorrect")
17
+ assert_equal(1, "1.2".to_version <=> "1.1".to_version, "Version minor comparison incorrect")
18
+ assert_equal(1, "1.1".to_version <=> "1".to_version, "Version minor comparison incorrect")
19
+ end
20
+
21
+ def test_string_components
22
+ assert_equal(0, "1.1alpha".to_version <=> "1.1alpha".to_version, "Version string comparison incorrect")
23
+ assert_equal(1, "1.1alpha".to_version <=> "1.1".to_version, "Version string comparison incorrect")
24
+ assert_equal(-1, "1.1alpha".to_version <=> "1.2".to_version, "Version string comparison incorrect")
25
+ end
26
+
27
+ def test_predecessor
28
+ alpha = Version.new(1, '1alpha')
29
+ assert_equal(1, Version.new(1, 1, alpha) <=> alpha, "Version predecessor comparison incorrect")
30
+ end
31
+ end
@@ -0,0 +1,277 @@
1
+ $:.unshift 'lib'
2
+
3
+ require 'generator'
4
+ require "test/unit"
5
+ require 'caruby/util/collection'
6
+ require 'caruby/util/visitor'
7
+
8
+ class Node
9
+ attr_reader :parent, :children, :friends
10
+
11
+ attr_accessor :value
12
+
13
+ def initialize(value, parent=nil)
14
+ @value = value
15
+ @children = []
16
+ @friends = []
17
+ @parent = parent
18
+ @parent.children << self if @parent
19
+ end
20
+
21
+ def <=>(other)
22
+ value <=> other.value if other
23
+ end
24
+
25
+ def to_s
26
+ "#{self.class.name}@#{hash}{value => #{value}}"
27
+ end
28
+
29
+ alias :inspect :to_s
30
+ end
31
+
32
+ class VistorTest < Test::Unit::TestCase
33
+ def test_visit
34
+ parent = Node.new(1)
35
+ child = Node.new(2, parent)
36
+ multiplier = 1
37
+ result = CaRuby::Visitor.new { |node| node.children }.visit(parent) { |node| node.value *= (multiplier *= 2) }
38
+ assert_equal(2, parent.value, "Visit parent value incorrect")
39
+ assert_equal(8, child.value, "Visit child value incorrect")
40
+ assert_equal(2, result, "Visit result incorrect")
41
+ end
42
+
43
+ def test_cycle
44
+ parent = Node.new(1)
45
+ child = Node.new(2, parent)
46
+ child.children << parent
47
+ multiplier = 2
48
+ CaRuby::Visitor.new { |node| node.children }.visit(parent) { |node| node.value *= multiplier }
49
+ assert_equal(2, parent.value, "Cycle parent value incorrect")
50
+ assert_equal(4, child.value, "Cycle child value incorrect")
51
+ end
52
+
53
+ def test_depth_first
54
+ parent = Node.new(1)
55
+ child = Node.new(2, parent)
56
+ multiplier = 1
57
+ CaRuby::Visitor.new(:depth_first) { |node| node.children }.visit(parent) { |node| node.value *= (multiplier *= 2) }
58
+ assert_equal(4, parent.value, "Depth-first parent value incorrect")
59
+ assert_equal(4, child.value, "Depth-first child value incorrect")
60
+ end
61
+
62
+ def test_return
63
+ parent = Node.new(1)
64
+ child = Node.new(2, parent)
65
+ result = increment(parent, 2)
66
+ assert_nil(result, "Pre-emptive return incorrect")
67
+ assert_equal(2, parent.value, "Pre-emptive return parent value incorrect")
68
+ assert_equal(2, child.value, "Pre-emptive return child value incorrect")
69
+ end
70
+
71
+ def test_visited_detection
72
+ parent = Node.new(1)
73
+ child = Node.new(2, parent)
74
+ c2 = Node.new(3, parent)
75
+ c2.children << child
76
+ result = CaRuby::Visitor.new { |node| node.children }.visit(parent) { |node| node.value += 1 }
77
+ assert_equal(3, child.value, "Child visited twice")
78
+ end
79
+
80
+ def test_root_cycle
81
+ parent = Node.new(1)
82
+ c1 = Node.new(2, parent)
83
+ c2 = Node.new(3, parent)
84
+ c2.children << parent
85
+ gc11 = Node.new(4, c1)
86
+ gc12 = Node.new(5, c1)
87
+ gc12.children << c1
88
+ gc121 = Node.new(6, gc12)
89
+ gc121.children << parent
90
+ visitor = CaRuby::Visitor.new { |node| node.children }
91
+ result = visitor.visit(parent)
92
+ assert_equal([[2, 5, 2], [1, 2, 5, 6, 1], [1, 3, 1]], visitor.cycles.map { |cycle| cycle.map { |node| node.value } }, "Root cycles incorrect")
93
+ end
94
+
95
+ def increment(parent, limit)
96
+ CaRuby::Visitor.new { |node| node.children }.visit(parent) { |node| node.value < limit ? node.value += 1 : return }
97
+ end
98
+
99
+ def test_collection
100
+ p1 = Node.new(1)
101
+ child = Node.new(2, p1)
102
+ p2 = Node.new(3)
103
+ p2.children << child
104
+ result = CaRuby::Visitor.new { |pair| SyncEnumerator.new(pair.first.children, pair.last.children).to_a }.to_enum([p1, p2]).map { |pair| [pair.first.value, pair.last.value] }
105
+ assert_equal([[1, 3], [2, 2]], result.to_a, "Collection visit result incorrect")
106
+ end
107
+
108
+ def node_value(node)
109
+ node.value if node
110
+ end
111
+
112
+ def test_enumeration
113
+ parent = Node.new(1)
114
+ c1 = Node.new(2, parent)
115
+ c2 = Node.new(3, parent)
116
+ result = CaRuby::Visitor.new { |node| node.children }.to_enum(parent).map { |node| node.value }
117
+ assert_equal([1, 2, 3], result, "Enumeration result incorrect")
118
+ end
119
+
120
+ def test_exclude_cycles
121
+ parent = Node.new(1)
122
+ c1 = Node.new(2, parent)
123
+ gc11 = Node.new(3, c1)
124
+ gc11.children << c1
125
+ c2 = Node.new(4, parent)
126
+ gc21 = Node.new(5, c2)
127
+ gc21.children << parent
128
+ result = CaRuby::Visitor.new(:prune_cycle) { |node| node.children }.to_enum(parent).map { |node| node.value }
129
+ assert_equal([1, 2, 3], result, "Exclude result incorrect")
130
+ end
131
+
132
+ def test_missing_block
133
+ parent = Node.new(1)
134
+ c1 = Node.new(2, parent)
135
+ c2 = Node.new(3, parent)
136
+ visitor = CaRuby::Visitor.new { |node| node.children }
137
+ visitor.visit(parent)
138
+ assert_equal([parent, c1, c2], visitor.visited.values.sort, "Missing visit operator result incorrect")
139
+ end
140
+
141
+ def test_filter
142
+ parent = Node.new(1)
143
+ c1 = Node.new(2, parent)
144
+ c2 = Node.new(3, parent)
145
+ gc1 = Node.new(4, c1)
146
+ gc2 = Node.new(5, c1)
147
+ visitor = CaRuby::Visitor.new { |node| node.children }.filter { |parent, children| children.first if parent.value < 4 }
148
+ result = visitor.to_enum(parent).map { |node| node.value }
149
+ assert_equal([1, 2, 4], result, "Filter result incorrect")
150
+ end
151
+
152
+ def test_sync_without_block
153
+ p1 = Node.new(1)
154
+ c11 = Node.new(2, p1)
155
+ c12 = Node.new(3, p1)
156
+ gc111 = Node.new(4, c11)
157
+ gc121 = Node.new(5, c12)
158
+ p2 = Node.new(6)
159
+ c21 = Node.new(7, p2)
160
+ c22 = Node.new(8, p2)
161
+ gc211 = Node.new(9, c21)
162
+ visitor = CaRuby::Visitor.new { |node| node.children }.sync
163
+ result = visitor.to_enum(p1, p2).map { |pair| pair.map { |node| node.value unless node.nil? } }
164
+ assert_equal([[1, 6], [2, 7], [4, 9], [3, 8], [5, nil]], result, "Sync without block result incorrect")
165
+ end
166
+
167
+ def test_sync_with_matcher
168
+ p1 = Node.new(1)
169
+ c11 = Node.new(2, p1)
170
+ c12 = Node.new(3, p1)
171
+ gc111 = Node.new(4, c11)
172
+ gc121 = Node.new(5, c12)
173
+ p2 = Node.new(1)
174
+ c21 = Node.new(2, p2)
175
+ c22 = Node.new(3, p2)
176
+ gc211 = Node.new(5, c21)
177
+ visitor = CaRuby::Visitor.new { |node| node.children }
178
+ synced = visitor.sync { |nodes, others| nodes.to_compact_hash { |n| others.detect { |o| n.value == o.value } } }
179
+ result = synced.to_enum(p1, p2).map { |pair| pair.map { |node| node.value if node } }
180
+ assert_equal([[1, 1], [2, 2], [4, nil], [3, 3], [5, nil]], result, "Sync with block result incorrect")
181
+ end
182
+
183
+ def test_sync_noncollection
184
+ p1 = Node.new(1)
185
+ child = Node.new(2, p1)
186
+ p2 = Node.new(3)
187
+ p2.children << child
188
+ visitor = CaRuby::Visitor.new { |node| node.children.first }.sync
189
+ value_hash = {}
190
+ result = visitor.visit(p1, p2) { |first, last| value_hash[node_value(first)] = node_value(last) }
191
+ assert_equal({1 => 3, 2 => 2}, value_hash, "Sync with non-collection children result incorrect")
192
+ result = visitor.to_enum(p1, p2).map { |first, last| [node_value(first), node_value(last)] }
193
+ assert_equal([[1, 3], [2, 2]], result.to_a, "Sync with non-collection children result incorrect")
194
+ end
195
+
196
+ def test_sync_missing
197
+ p1 = Node.new(1)
198
+ p2 = Node.new(2)
199
+ c1 = Node.new(3, p1)
200
+ c2 = Node.new(4, p2)
201
+ gcren = Node.new(5, c2)
202
+ visitor = CaRuby::Visitor.new { |node| node.children.first }.sync
203
+ result = visitor.to_enum(p1, p2).map { |pair| [node_value(pair.first), node_value(pair.last)] }
204
+ assert_equal([[1, 2], [3, 4]], result.to_a, "Sync with missing children result incorrect")
205
+ end
206
+
207
+ def test_missing_node
208
+ parent = Node.new(1)
209
+ child = Node.new(2, parent)
210
+ multiplier = 2
211
+ CaRuby::Visitor.new { |node| node.children unless node == child }.visit(parent) { |node| node.value *= multiplier }
212
+ assert_equal(2, parent.value, "Missing node parent value incorrect")
213
+ assert_equal(4, child.value, "Missing node child value incorrect")
214
+ end
215
+
216
+ def test_noncollection_traversal
217
+ parent = Node.new(1)
218
+ child = Node.new(2, parent)
219
+ multiplier = 2
220
+ CaRuby::Visitor.new { |node| node.parent }.visit(child) { |node| node.value *= multiplier }
221
+ assert_equal(2, parent.value, "Non-collection parent value incorrect")
222
+ assert_equal(4, child.value, "Non-collection child value incorrect")
223
+ end
224
+
225
+ def test_parent
226
+ parent = Node.new(1)
227
+ c1 = Node.new(2, parent)
228
+ c2 = Node.new(3, parent)
229
+ gc = Node.new(4, c1)
230
+ visitor = CaRuby::Visitor.new { |node| node.children }
231
+ visitor.visit(parent) { |node| node.value = visitor.parent.nil? ? 0 : visitor.parent.value + 1 }
232
+ assert_equal(0, parent.value, "Parent value incorrect")
233
+ assert_equal(1, c1.value, "Child value incorrect")
234
+ assert_equal(1, c2.value, "Child value incorrect")
235
+ assert_equal(2, gc.value, "gc value incorrect")
236
+ end
237
+
238
+ def test_parent_depth_first
239
+ # An interesting variant: the parent node value is not reset until after the children are visited
240
+ parent = Node.new(1)
241
+ c1 = Node.new(2, parent)
242
+ c2 = Node.new(3, parent)
243
+ gc = Node.new(4, c1)
244
+ visitor = CaRuby::Visitor.new(:depth_first) { |node| node.children }
245
+ visitor.visit(parent) { |node| node.value = visitor.parent.nil? ? 0 : visitor.parent.value + 1 }
246
+ assert_equal(0, parent.value, "Parent value incorrect")
247
+ assert_equal(2, c1.value, "Child value incorrect")
248
+ assert_equal(2, c2.value, "Child value incorrect")
249
+ assert_equal(3, gc.value, "gc value incorrect")
250
+ end
251
+
252
+ def test_visited
253
+ parent = Node.new(1)
254
+ c1 = Node.new(nil, parent)
255
+ c2 = Node.new(nil, parent)
256
+ gc = Node.new(nil, c1)
257
+ visitor = CaRuby::Visitor.new { |node| node.children }
258
+ visitor.visit(parent) { |node| node.value ||= visitor.visited[node.parent] + 1 }
259
+ assert_equal(1, parent.value, "Parent value incorrect")
260
+ assert_equal(2, c1.value, "Child value incorrect")
261
+ assert_equal(2, c2.value, "Child value incorrect")
262
+ assert_equal(3, gc.value, "gc value incorrect")
263
+ end
264
+
265
+ def test_visited_result
266
+ parent = Node.new(1)
267
+ c1 = Node.new(2, parent)
268
+ c2 = Node.new(3, parent)
269
+ gc = Node.new(4, c1)
270
+ visitor = CaRuby::Visitor.new { |node| node.children }
271
+ visitor.visit(parent) { |node| node.value + 1 }
272
+ assert_equal(2, visitor.visited[parent], "Parent visited value incorrect")
273
+ assert_equal(3, visitor.visited[c1], "Child visited value incorrect")
274
+ assert_equal(4, visitor.visited[c2], "Child visited value incorrect")
275
+ assert_equal(5, visitor.visited[gc], "gc visited value incorrect")
276
+ end
277
+ end