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.
- data/History.txt +2 -0
- data/README.md +0 -2
- data/lib/caruby/migration/migrator.rb +1 -1
- data/lib/caruby/version.rb +1 -1
- data/test/lib/caruby/csv/csv_mapper_test.rb +40 -0
- data/test/lib/caruby/csv/csvio_test.rb +69 -0
- data/test/lib/caruby/database/persistable_test.rb +92 -0
- data/test/lib/caruby/domain/domain_test.rb +126 -0
- data/test/lib/caruby/domain/inversible_test.rb +99 -0
- data/test/lib/caruby/domain/reference_visitor_test.rb +130 -0
- data/test/lib/caruby/import/java_test.rb +58 -0
- data/test/lib/caruby/util/cache_test.rb +23 -0
- data/test/lib/caruby/util/class_test.rb +61 -0
- data/test/lib/caruby/util/collection_test.rb +379 -0
- data/test/lib/caruby/util/command_test.rb +55 -0
- data/test/lib/caruby/util/controlled_value_test.rb +26 -0
- data/test/lib/caruby/util/domain_extent_test.rb +60 -0
- data/test/lib/caruby/util/file_separator_test.rb +30 -0
- data/test/lib/caruby/util/inflector_test.rb +12 -0
- data/test/lib/caruby/util/lazy_hash_test.rb +34 -0
- data/test/lib/caruby/util/merge_test.rb +83 -0
- data/test/lib/caruby/util/module_test.rb +29 -0
- data/test/lib/caruby/util/options_test.rb +59 -0
- data/test/lib/caruby/util/partial_order_test.rb +41 -0
- data/test/lib/caruby/util/person_test.rb +115 -0
- data/test/lib/caruby/util/pretty_print_test.rb +85 -0
- data/test/lib/caruby/util/properties_test.rb +50 -0
- data/test/lib/caruby/util/stopwatch_test.rb +18 -0
- data/test/lib/caruby/util/topological_sync_enumerator_test.rb +69 -0
- data/test/lib/caruby/util/transitive_closure_test.rb +59 -0
- data/test/lib/caruby/util/tree_test.rb +23 -0
- data/test/lib/caruby/util/trie_test.rb +14 -0
- data/test/lib/caruby/util/validation_test.rb +14 -0
- data/test/lib/caruby/util/version_test.rb +31 -0
- data/test/lib/caruby/util/visitor_test.rb +277 -0
- data/test/lib/caruby/util/weak_hash_test.rb +45 -0
- 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
|