caruby-core 1.4.4 → 1.4.5

Sign up to get free protection for your applications and to get access to all the features.
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