jinx 2.1.1
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/.gitignore +14 -0
- data/.rspec +3 -0
- data/.yardopts +1 -0
- data/Gemfile +6 -0
- data/Gemfile.lock +27 -0
- data/History.md +6 -0
- data/LEGAL +5 -0
- data/LICENSE +22 -0
- data/README.md +44 -0
- data/Rakefile +41 -0
- data/examples/family/README.md +10 -0
- data/examples/family/ext/build.xml +35 -0
- data/examples/family/ext/src/family/Address.java +68 -0
- data/examples/family/ext/src/family/Child.java +24 -0
- data/examples/family/ext/src/family/DomainObject.java +26 -0
- data/examples/family/ext/src/family/Household.java +36 -0
- data/examples/family/ext/src/family/Parent.java +48 -0
- data/examples/family/ext/src/family/Person.java +42 -0
- data/examples/family/lib/family.rb +15 -0
- data/examples/family/lib/family/address.rb +6 -0
- data/examples/family/lib/family/domain_object.rb +6 -0
- data/examples/family/lib/family/household.rb +6 -0
- data/examples/family/lib/family/parent.rb +16 -0
- data/examples/family/lib/family/person.rb +6 -0
- data/examples/model/README.md +25 -0
- data/examples/model/ext/build.xml +35 -0
- data/examples/model/ext/src/domain/Child.java +192 -0
- data/examples/model/ext/src/domain/Dependent.java +29 -0
- data/examples/model/ext/src/domain/DomainObject.java +26 -0
- data/examples/model/ext/src/domain/Independent.java +83 -0
- data/examples/model/ext/src/domain/Parent.java +129 -0
- data/examples/model/ext/src/domain/Person.java +14 -0
- data/examples/model/lib/model.rb +13 -0
- data/examples/model/lib/model/child.rb +13 -0
- data/examples/model/lib/model/domain_object.rb +6 -0
- data/examples/model/lib/model/independent.rb +11 -0
- data/examples/model/lib/model/parent.rb +17 -0
- data/jinx.gemspec +22 -0
- data/lib/jinx.rb +3 -0
- data/lib/jinx/active_support/README.txt +2 -0
- data/lib/jinx/active_support/core_ext/string.rb +7 -0
- data/lib/jinx/active_support/core_ext/string/inflections.rb +167 -0
- data/lib/jinx/active_support/inflections.rb +55 -0
- data/lib/jinx/active_support/inflector.rb +398 -0
- data/lib/jinx/cli/application.rb +36 -0
- data/lib/jinx/cli/command.rb +214 -0
- data/lib/jinx/helpers/array.rb +108 -0
- data/lib/jinx/helpers/boolean.rb +42 -0
- data/lib/jinx/helpers/case_insensitive_hash.rb +39 -0
- data/lib/jinx/helpers/class.rb +149 -0
- data/lib/jinx/helpers/collection.rb +33 -0
- data/lib/jinx/helpers/collections.rb +11 -0
- data/lib/jinx/helpers/collector.rb +20 -0
- data/lib/jinx/helpers/conditional_enumerator.rb +21 -0
- data/lib/jinx/helpers/enumerable.rb +242 -0
- data/lib/jinx/helpers/enumerate.rb +35 -0
- data/lib/jinx/helpers/error.rb +15 -0
- data/lib/jinx/helpers/file_separator.rb +65 -0
- data/lib/jinx/helpers/filter.rb +52 -0
- data/lib/jinx/helpers/flattener.rb +38 -0
- data/lib/jinx/helpers/hash.rb +12 -0
- data/lib/jinx/helpers/hashable.rb +502 -0
- data/lib/jinx/helpers/inflector.rb +36 -0
- data/lib/jinx/helpers/key_transformer_hash.rb +43 -0
- data/lib/jinx/helpers/lazy_hash.rb +44 -0
- data/lib/jinx/helpers/log.rb +106 -0
- data/lib/jinx/helpers/math.rb +12 -0
- data/lib/jinx/helpers/merge.rb +60 -0
- data/lib/jinx/helpers/module.rb +18 -0
- data/lib/jinx/helpers/multi_enumerator.rb +31 -0
- data/lib/jinx/helpers/options.rb +92 -0
- data/lib/jinx/helpers/os.rb +19 -0
- data/lib/jinx/helpers/partial_order.rb +37 -0
- data/lib/jinx/helpers/pretty_print.rb +207 -0
- data/lib/jinx/helpers/set.rb +8 -0
- data/lib/jinx/helpers/stopwatch.rb +76 -0
- data/lib/jinx/helpers/transformer.rb +24 -0
- data/lib/jinx/helpers/transitive_closure.rb +55 -0
- data/lib/jinx/helpers/uniquifier.rb +50 -0
- data/lib/jinx/helpers/validation.rb +33 -0
- data/lib/jinx/helpers/visitor.rb +370 -0
- data/lib/jinx/import/class_path_modifier.rb +77 -0
- data/lib/jinx/import/java.rb +337 -0
- data/lib/jinx/importer.rb +240 -0
- data/lib/jinx/metadata.rb +155 -0
- data/lib/jinx/metadata/attribute_enumerator.rb +73 -0
- data/lib/jinx/metadata/dependency.rb +244 -0
- data/lib/jinx/metadata/id_alias.rb +23 -0
- data/lib/jinx/metadata/introspector.rb +179 -0
- data/lib/jinx/metadata/inverse.rb +170 -0
- data/lib/jinx/metadata/java_property.rb +169 -0
- data/lib/jinx/metadata/propertied.rb +500 -0
- data/lib/jinx/metadata/property.rb +401 -0
- data/lib/jinx/metadata/property_characteristics.rb +114 -0
- data/lib/jinx/resource.rb +862 -0
- data/lib/jinx/resource/copy_visitor.rb +36 -0
- data/lib/jinx/resource/inversible.rb +90 -0
- data/lib/jinx/resource/match_visitor.rb +180 -0
- data/lib/jinx/resource/matcher.rb +20 -0
- data/lib/jinx/resource/merge_visitor.rb +73 -0
- data/lib/jinx/resource/mergeable.rb +185 -0
- data/lib/jinx/resource/reference_enumerator.rb +49 -0
- data/lib/jinx/resource/reference_path_visitor.rb +38 -0
- data/lib/jinx/resource/reference_visitor.rb +55 -0
- data/lib/jinx/resource/unique.rb +35 -0
- data/lib/jinx/version.rb +3 -0
- data/spec/defaults_spec.rb +30 -0
- data/spec/definitions/model/alias/child.rb +5 -0
- data/spec/definitions/model/base/child.rb +5 -0
- data/spec/definitions/model/base/domain_object.rb +5 -0
- data/spec/definitions/model/base/independent.rb +5 -0
- data/spec/definitions/model/defaults/child.rb +5 -0
- data/spec/definitions/model/dependency/child.rb +5 -0
- data/spec/definitions/model/dependency/parent.rb +6 -0
- data/spec/definitions/model/inverse/child.rb +5 -0
- data/spec/definitions/model/inverse/independent.rb +5 -0
- data/spec/definitions/model/inverse/parent.rb +5 -0
- data/spec/definitions/model/mandatory/child.rb +6 -0
- data/spec/dependency_spec.rb +47 -0
- data/spec/family_spec.rb +64 -0
- data/spec/inverse_spec.rb +53 -0
- data/spec/mandatory_spec.rb +43 -0
- data/spec/metadata_spec.rb +68 -0
- data/spec/resource_spec.rb +30 -0
- data/spec/spec_helper.rb +3 -0
- data/spec/support/model.rb +19 -0
- data/test/fixtures/line_separator/cr_line_sep.txt +1 -0
- data/test/fixtures/line_separator/crlf_line_sep.txt +3 -0
- data/test/fixtures/line_separator/lf_line_sep.txt +3 -0
- data/test/fixtures/mixed/ext/build.xml +35 -0
- data/test/fixtures/mixed/ext/src/mixed/Case/Example.java +5 -0
- data/test/helper.rb +7 -0
- data/test/lib/jinx/command_test.rb +41 -0
- data/test/lib/jinx/helpers/boolean_test.rb +27 -0
- data/test/lib/jinx/helpers/class_test.rb +60 -0
- data/test/lib/jinx/helpers/collections_test.rb +402 -0
- data/test/lib/jinx/helpers/file_separator_test.rb +29 -0
- data/test/lib/jinx/helpers/inflector_test.rb +11 -0
- data/test/lib/jinx/helpers/lazy_hash_test.rb +32 -0
- data/test/lib/jinx/helpers/module_test.rb +24 -0
- data/test/lib/jinx/helpers/options_test.rb +66 -0
- data/test/lib/jinx/helpers/partial_order_test.rb +41 -0
- data/test/lib/jinx/helpers/pretty_print_test.rb +83 -0
- data/test/lib/jinx/helpers/stopwatch_test.rb +16 -0
- data/test/lib/jinx/helpers/transitive_closure_test.rb +80 -0
- data/test/lib/jinx/helpers/visitor_test.rb +288 -0
- data/test/lib/jinx/import/java_test.rb +78 -0
- data/test/lib/jinx/import/mixed_case_test.rb +16 -0
- metadata +272 -0
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
require File.dirname(__FILE__) + '/../../../helper'
|
|
2
|
+
require 'test/unit'
|
|
3
|
+
require 'jinx/helpers/file_separator'
|
|
4
|
+
|
|
5
|
+
class FileSeparatorTest < Test::Unit::TestCase
|
|
6
|
+
FIXTURES = File.dirname(__FILE__) + '/../../../fixtures/line_separator'
|
|
7
|
+
LF_FILE = File.join(FIXTURES, 'lf_line_sep.txt')
|
|
8
|
+
CR_FILE = File.join(FIXTURES, 'cr_line_sep.txt')
|
|
9
|
+
CRLF_FILE = File.join(FIXTURES, 'crlf_line_sep.txt')
|
|
10
|
+
|
|
11
|
+
def test_lf_line_separator
|
|
12
|
+
verify_read(LF_FILE, "LF")
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def test_cr_line_separator
|
|
16
|
+
verify_read(CR_FILE, "CR")
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def test_crlf_line_separator
|
|
20
|
+
verify_read(CRLF_FILE, "CRLF")
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def verify_read(file, type)
|
|
24
|
+
lines = File.open(file) { |io| io.readlines }
|
|
25
|
+
assert_equal(3, lines.size, "#{type} line separator not recognized in readlines")
|
|
26
|
+
lines = File.open(file) { |io| io.to_a }
|
|
27
|
+
assert_equal(3, lines.size, "#{type} line separator not recognized in to_a")
|
|
28
|
+
end
|
|
29
|
+
end
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
require File.dirname(__FILE__) + '/../../../helper'
|
|
2
|
+
require 'test/unit'
|
|
3
|
+
require 'jinx/helpers/inflector'
|
|
4
|
+
|
|
5
|
+
class InflectorTest < Test::Unit::TestCase
|
|
6
|
+
def test_quantified_s
|
|
7
|
+
assert_equal("1 person", "person".quantify(1))
|
|
8
|
+
assert_equal("2 people", "person".quantify(2))
|
|
9
|
+
assert_equal("0 people", "person".quantify(0))
|
|
10
|
+
end
|
|
11
|
+
end
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
require File.dirname(__FILE__) + '/../../../helper'
|
|
2
|
+
require "test/unit"
|
|
3
|
+
require 'jinx/helpers/lazy_hash'
|
|
4
|
+
|
|
5
|
+
class LazyHastTest < Test::Unit::TestCase
|
|
6
|
+
|
|
7
|
+
def test_value_factory
|
|
8
|
+
hash = Jinx::LazyHash.new { |key| key.to_s }
|
|
9
|
+
assert_equal('1', hash[1], "Factory return value is incorrect")
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def test_default_value_factory
|
|
13
|
+
hash = Jinx::LazyHash.new
|
|
14
|
+
assert_nil(hash[1], "Default factory does not return")
|
|
15
|
+
assert(hash.has_key?(1), "Default entry not created")
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def test_nil_key
|
|
19
|
+
hash = Jinx::LazyHash.new
|
|
20
|
+
assert_nil(hash[nil], "nil key does not return")
|
|
21
|
+
assert(!hash.has_key?(nil), "Entry created for nil key")
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def test_reject_missing_value
|
|
25
|
+
hash = Jinx::LazyHash.new(:compact => true)
|
|
26
|
+
assert(!hash.has_key?(1), "Default entry created for nil value")
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def test_fetch
|
|
30
|
+
assert_raises(IndexError, "Fetch non-existent doesn't raise IndexError") { Jinx::LazyHash.new.fetch(:a) }
|
|
31
|
+
end
|
|
32
|
+
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
require File.dirname(__FILE__) + '/../../../helper'
|
|
2
|
+
require "test/unit"
|
|
3
|
+
require 'jinx/helpers/module'
|
|
4
|
+
|
|
5
|
+
module Outer
|
|
6
|
+
module Middle
|
|
7
|
+
class C; end
|
|
8
|
+
end
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
class ModuleTest < Test::Unit::TestCase
|
|
12
|
+
def test_module_with_name
|
|
13
|
+
assert_equal(Outer::Middle, Outer.module_with_name('Middle'), "Unqualified module incorrect")
|
|
14
|
+
assert_nil(Outer.module_with_name('Zed'), "Missing module incorrectly resolves to non-nil value")
|
|
15
|
+
assert_equal(Outer::Middle::C, Outer.module_with_name('Middle::C'), "Qualified module incorrect")
|
|
16
|
+
assert_equal(Outer, Kernel.module_with_name('Outer'), "Top-level module incorrect")
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def test_parent_module
|
|
20
|
+
assert_equal(Outer, Outer::Middle.parent_module, "Middle parent module incorrect")
|
|
21
|
+
assert_equal(Outer::Middle, Outer::Middle::C.parent_module, "Inner parent module incorrect")
|
|
22
|
+
assert_equal(Kernel, Outer.parent_module, "Outer parent module incorrect")
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
require File.dirname(__FILE__) + '/../../../helper'
|
|
2
|
+
require "test/unit"
|
|
3
|
+
require 'jinx/helpers/options'
|
|
4
|
+
|
|
5
|
+
class OptionsTest < Test::Unit::TestCase
|
|
6
|
+
def test_present
|
|
7
|
+
assert(Options.get(:key, {:key => true}), "Option true value not returned")
|
|
8
|
+
assert(!Options.get(:key, {:key => false}), "Option true value not returned")
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def test_nil_value
|
|
12
|
+
assert_equal(:a, Options.get(:key, {:key => nil}, :a), "Options nil value not returned")
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def test_false_with_true_default
|
|
16
|
+
assert_equal(false, Options.get(:key, {:key => false}, true), "Option false value with true default doesn't return false")
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def test_missing
|
|
20
|
+
assert_nil(Options.get(:key, {}), "Missing option incorrectly found")
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def test_default_value
|
|
24
|
+
assert_equal(:a, Options.get(:key, {}, :a), "Option default value not used")
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def test_nil_with_false_default
|
|
28
|
+
assert_equal(false, Options.get(:key, nil, false), "Option default value not used")
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def test_default_block
|
|
32
|
+
assert_equal(:b, Options.get(:key, {}) { :b }, "Option default block not called")
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def test_symbol
|
|
36
|
+
assert(Options.get(:key, :key), "Option not found in singleton options")
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def test_array
|
|
40
|
+
assert(Options.get(:b, [:a, :b]), "Option not found in array options")
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def test_array_with_hash
|
|
44
|
+
assert_equal(:c, Options.get(:b, [:a, {:b => :c}]), "Option not found in array options")
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def test_collection_value
|
|
48
|
+
assert_equal([:a], Options.get(:key, {:key => [:a]}, []), "Option array value not returned")
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def test_empty_to_hash
|
|
52
|
+
assert_equal({}, Options.to_hash(), "Option to_hash with empty argument list not an empty hash")
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def test_nil_to_hash
|
|
56
|
+
assert_equal({}, Options.to_hash(nil), "Option to_hash with nil argument list not an empty hash")
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def test_hash_to_hash
|
|
60
|
+
assert_equal({:a => 1}, Options.to_hash({:a => 1}), "Option to_hash with hash argument list not an empty hash")
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def test_list_to_hash
|
|
64
|
+
assert_equal({:a => 1, :b => true, :c => 2}, Options.to_hash({:a => 1}, :b, :c => 2), "Option to_hash with list argument list incorrect")
|
|
65
|
+
end
|
|
66
|
+
end
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
require File.dirname(__FILE__) + '/../../../helper'
|
|
2
|
+
require "test/unit"
|
|
3
|
+
require 'jinx/helpers/partial_order'
|
|
4
|
+
|
|
5
|
+
class Queued
|
|
6
|
+
include Jinx::PartialOrder
|
|
7
|
+
|
|
8
|
+
attr_reader :queue
|
|
9
|
+
|
|
10
|
+
def initialize(on)
|
|
11
|
+
@queue = on.push(self)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def <=>(other)
|
|
15
|
+
queue.index(self) <=> other.queue.index(other) if queue.equal?(other.queue)
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
class PartialOrderTest < Test::Unit::TestCase
|
|
20
|
+
def test_same_queue
|
|
21
|
+
q = []
|
|
22
|
+
a = Queued.new(q)
|
|
23
|
+
assert_equal(a, a, "Same value, queue not equal")
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def test_different_eql_queue
|
|
27
|
+
a = Queued.new([])
|
|
28
|
+
@b = Queued.new([])
|
|
29
|
+
assert_nil(a <=> @b, "Same value, different queue <=> not nil")
|
|
30
|
+
assert_not_equal(a, @b, "Same value, different queue is equal")
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def test_less_than
|
|
34
|
+
q = []
|
|
35
|
+
a = Queued.new(q)
|
|
36
|
+
b = Queued.new(q)
|
|
37
|
+
c = Queued.new([])
|
|
38
|
+
assert(a < b, "Comparison incorrect")
|
|
39
|
+
assert_nil(a < c, "Comparison incorrect")
|
|
40
|
+
end
|
|
41
|
+
end
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
require File.dirname(__FILE__) + '/../../../helper'
|
|
2
|
+
require "test/unit"
|
|
3
|
+
require 'set'
|
|
4
|
+
require 'date'
|
|
5
|
+
require 'jinx/helpers/pretty_print'
|
|
6
|
+
|
|
7
|
+
class PrettyPrintTest < Test::Unit::TestCase
|
|
8
|
+
def test_nil
|
|
9
|
+
assert_equal('nil', nil.pp_s, 'Nil pretty print incorrect')
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def test_date_time
|
|
13
|
+
date = DateTime.civil(2009, 4, 15, 5, 55, 55)
|
|
14
|
+
assert_equal(date.strftime, date.pp_s, 'Date pretty print incorrect')
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def test_array
|
|
18
|
+
assert_equal('[:a, :b]', [:a, :b].pp_s, 'Array pretty print incorrect')
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def test_java_collection
|
|
22
|
+
a = Java::JavaUtil::ArrayList.new
|
|
23
|
+
a << :a << :b
|
|
24
|
+
assert_equal(a.to_a.pp_s, a.pp_s, 'Java collection pretty print incorrect')
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def test_java_collection_cycle
|
|
28
|
+
a = Java::JavaUtil::ArrayList.new
|
|
29
|
+
a << :a << a
|
|
30
|
+
assert_equal('[:a, [...]]', a.pp_s(:single_line), 'Cyclic set pretty print incorrect')
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def test_hash
|
|
34
|
+
assert_equal('{:a=>a, :b=>b}', {:a => 'a', :b => 'b'}.pp_s(:single_line), 'Hash pretty print incorrect')
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def test_qp
|
|
38
|
+
assert_equal('1', 1.qp, 'Numeric quick print incorrect')
|
|
39
|
+
assert_equal('nil', nil.qp, 'nil quick print incorrect')
|
|
40
|
+
assert_equal('a', 'a'.qp, 'String quick print incorrect')
|
|
41
|
+
assert_equal(':a', :a.qp, 'Symbol quick print incorrect')
|
|
42
|
+
assert_equal('[:a]', [:a].qp, 'Array quick print incorrect')
|
|
43
|
+
assert_equal('TestCase', Test::Unit::TestCase.qp, 'Class quick print incorrect')
|
|
44
|
+
|
|
45
|
+
x = {:a => 'a', :b => 'b'}
|
|
46
|
+
x.qp
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
assert_equal('{:a=>a, :b=>b}', {:a => 'a', :b => 'b'}.qp, 'Hash quick print incorrect')
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def test_set
|
|
53
|
+
assert_equal([:a].pp_s, [:a].to_set.pp_s, 'Set pretty print incorrect')
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def test_set_cycle
|
|
57
|
+
a = [:a].to_set
|
|
58
|
+
a << a
|
|
59
|
+
assert_equal('[:a, [...]]', a.pp_s(:single_line), 'Cyclic set pretty print incorrect')
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def test_single_line_argument
|
|
63
|
+
a = [].fill(:a, 0, 80)
|
|
64
|
+
assert(a.pp_s =~ /\n/, 'Test array not long enough')
|
|
65
|
+
assert(!a.pp_s(:single_line).include?("\n"), 'Single line option ignored')
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def test_single_line_option
|
|
69
|
+
a = [].fill(:a, 0, 80)
|
|
70
|
+
assert_equal(a.pp_s(:single_line => true), a.pp_s(:single_line), 'Single line option ignored')
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def test_print_wrapper_block
|
|
74
|
+
tuples = [[:a, :b], [:c]]
|
|
75
|
+
wrapper = PrintWrapper.new { |tuple| "<#{tuple.join(',')}>" }
|
|
76
|
+
wrappers = tuples.wrap{ |tuple| wrapper.wrap(tuple) }
|
|
77
|
+
assert_equal("[<a,b>, <c>]", wrappers.pp_s)
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def test_wrapper_block
|
|
81
|
+
assert_equal("[<a,b>, <c>]", [[:a, :b], [:c]].pp_s { |tuple| "<#{tuple.join(',')}>" })
|
|
82
|
+
end
|
|
83
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
require File.dirname(__FILE__) + '/../../../helper'
|
|
2
|
+
require "test/unit"
|
|
3
|
+
require 'jinx/helpers/stopwatch'
|
|
4
|
+
|
|
5
|
+
class StopwatchTest < Test::Unit::TestCase
|
|
6
|
+
def setup
|
|
7
|
+
@timer = Jinx::Stopwatch.new
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def test_run
|
|
11
|
+
t1 = @timer.run { 1000000.times { " " * 100 } }
|
|
12
|
+
t2 = @timer.run { 1000000.times { " " * 100 } }
|
|
13
|
+
assert_equal(t1.elapsed + t2.elapsed, @timer.elapsed, "Elapsed time incorrectly accumulated")
|
|
14
|
+
assert_equal(t1.cpu + t2.cpu, @timer.cpu, "CPU time incorrectly accumulated")
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
require File.dirname(__FILE__) + '/../../../helper'
|
|
2
|
+
require "test/unit"
|
|
3
|
+
require 'jinx/helpers/collections'
|
|
4
|
+
|
|
5
|
+
require 'jinx/helpers/transitive_closure'
|
|
6
|
+
|
|
7
|
+
class TransitiveClosureTest < Test::Unit::TestCase
|
|
8
|
+
# Verifies closure iteration for the following hierarchy:
|
|
9
|
+
# root -> a, e
|
|
10
|
+
# a -> b, c
|
|
11
|
+
# c -> d
|
|
12
|
+
# The expected iteration is +root+ preceding +a+ and +e+, +a+ preceding +b+ and +c+, +c+ preceding +d+.
|
|
13
|
+
def test_hierarchy
|
|
14
|
+
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)
|
|
15
|
+
verify_closure([root, a, b, c, d, e], root.transitive_closure(:children))
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def test_internal
|
|
19
|
+
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)
|
|
20
|
+
verify_closure([a, b, c, d], a.transitive_closure(:children))
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def test_leaf
|
|
24
|
+
leaf = Node.new(1)
|
|
25
|
+
verify_closure([leaf], leaf.transitive_closure(:children))
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def test_collection
|
|
29
|
+
a = Node.new('a'); b = Node.new('b'); c = Node.new('c', a); d = Node.new('d', b); e = Node.new('e', c)
|
|
30
|
+
verify_closure([a, b, c, d, e], [a, b].transitive_closure(:children))
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def test_cycle
|
|
34
|
+
root= Node.new('root'); a = Node.new('a', root); b = Node.new('b', a); c = Node.new('c', a); c.children << root
|
|
35
|
+
expected = [root, a, b, c].to_set
|
|
36
|
+
verify_closure([root, a, b, c], root.transitive_closure(:children))
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def test_class_hierarchy
|
|
40
|
+
result = [C, D].transitive_closure { |k| [k.superclass] }
|
|
41
|
+
assert_equal([D, C].to_set, result[0..1].to_set, "Class hierarchy closure incomparable leaf class order incorrect")
|
|
42
|
+
assert_equal([B, A, Object], result[2..-1], "Class hierarchy closure comparable non-leaf class order incorrect")
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def verify_closure(content, closure)
|
|
46
|
+
assert_equal(content.to_set, closure.to_set, "Hierarchy closure incorrect")
|
|
47
|
+
# Verify that no child succeeds the parent.
|
|
48
|
+
closure.each_with_index do |node, index|
|
|
49
|
+
par = node.parent
|
|
50
|
+
if content.include?(par) then
|
|
51
|
+
assert(closure.index(par) < index, "Child #{node} precedes parent #{par}")
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
private
|
|
57
|
+
|
|
58
|
+
class A; end
|
|
59
|
+
class B < A; end
|
|
60
|
+
class C < B; end
|
|
61
|
+
class D < A; end
|
|
62
|
+
|
|
63
|
+
class Node
|
|
64
|
+
attr_reader :parent, :children, :value
|
|
65
|
+
|
|
66
|
+
def initialize(value, parent=nil)
|
|
67
|
+
super()
|
|
68
|
+
@value = value
|
|
69
|
+
@parent = parent
|
|
70
|
+
@children = []
|
|
71
|
+
parent.children << self if parent
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def to_s
|
|
75
|
+
value.to_s
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
alias :inspect :to_s
|
|
79
|
+
end
|
|
80
|
+
end
|
|
@@ -0,0 +1,288 @@
|
|
|
1
|
+
require File.dirname(__FILE__) + '/../../../helper'
|
|
2
|
+
require "test/unit"
|
|
3
|
+
|
|
4
|
+
# JRuby SyncEnumerator moved from generator to REXML in JRuby 1.5.
|
|
5
|
+
require 'rexml/document'
|
|
6
|
+
require 'jinx/helpers/collections'
|
|
7
|
+
|
|
8
|
+
require 'jinx/helpers/visitor'
|
|
9
|
+
|
|
10
|
+
class Node
|
|
11
|
+
attr_reader :parent, :children, :friends
|
|
12
|
+
|
|
13
|
+
attr_accessor :value
|
|
14
|
+
|
|
15
|
+
def initialize(value, parent=nil)
|
|
16
|
+
@value = value
|
|
17
|
+
@children = []
|
|
18
|
+
@friends = []
|
|
19
|
+
@parent = parent
|
|
20
|
+
@parent.children << self if @parent
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def <=>(other)
|
|
24
|
+
value <=> other.value if other
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def to_s
|
|
28
|
+
"#{self.class.name}@#{hash}{value => #{value}}"
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
alias :inspect :to_s
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
class VistorTest < Test::Unit::TestCase
|
|
35
|
+
def test_visit
|
|
36
|
+
parent = Node.new(1)
|
|
37
|
+
child = Node.new(2, parent)
|
|
38
|
+
multiplier = 1
|
|
39
|
+
visitor = Jinx::Visitor.new { |node| node.children }
|
|
40
|
+
result = visitor.visit(parent) { |node| node.value *= (multiplier *= 2) }
|
|
41
|
+
assert_equal(2, parent.value, "Visit parent value incorrect")
|
|
42
|
+
assert_equal(8, child.value, "Visit child value incorrect")
|
|
43
|
+
assert_equal(2, result, "Visit result incorrect")
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def test_cycle
|
|
47
|
+
parent = Node.new(1)
|
|
48
|
+
child = Node.new(2, parent)
|
|
49
|
+
child.children << parent
|
|
50
|
+
multiplier = 2
|
|
51
|
+
visitor = Jinx::Visitor.new { |node| node.children }
|
|
52
|
+
visitor.visit(parent) { |node| node.value *= multiplier }
|
|
53
|
+
assert_equal(2, parent.value, "Cycle parent value incorrect")
|
|
54
|
+
assert_equal(4, child.value, "Cycle child value incorrect")
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def test_depth_first
|
|
58
|
+
parent = Node.new(1)
|
|
59
|
+
child = Node.new(2, parent)
|
|
60
|
+
multiplier = 1
|
|
61
|
+
visitor = Jinx::Visitor.new(:depth_first) { |node| node.children }
|
|
62
|
+
visitor.visit(parent) { |node| node.value *= (multiplier *= 2) }
|
|
63
|
+
assert_equal(4, parent.value, "Depth-first parent value incorrect")
|
|
64
|
+
assert_equal(4, child.value, "Depth-first child value incorrect")
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def test_return
|
|
68
|
+
parent = Node.new(1)
|
|
69
|
+
child = Node.new(2, parent)
|
|
70
|
+
result = increment(parent, 2)
|
|
71
|
+
assert_nil(result, "Pre-emptive return incorrect")
|
|
72
|
+
assert_equal(2, parent.value, "Pre-emptive return parent value incorrect")
|
|
73
|
+
assert_equal(2, child.value, "Pre-emptive return child value incorrect")
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def test_visited_detection
|
|
77
|
+
parent = Node.new(1)
|
|
78
|
+
child = Node.new(2, parent)
|
|
79
|
+
c2 = Node.new(3, parent)
|
|
80
|
+
c2.children << child
|
|
81
|
+
visitor = Jinx::Visitor.new { |node| node.children }
|
|
82
|
+
visitor.visit(parent) { |node| node.value += 1 }
|
|
83
|
+
assert_equal(3, child.value, "Child visited twice")
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def test_root_cycle
|
|
87
|
+
parent = Node.new(1)
|
|
88
|
+
c1 = Node.new(2, parent)
|
|
89
|
+
c2 = Node.new(3, parent)
|
|
90
|
+
c2.children << parent
|
|
91
|
+
gc11 = Node.new(4, c1)
|
|
92
|
+
gc12 = Node.new(5, c1)
|
|
93
|
+
gc12.children << c1
|
|
94
|
+
gc121 = Node.new(6, gc12)
|
|
95
|
+
gc121.children << parent
|
|
96
|
+
visitor = Jinx::Visitor.new { |node| node.children }
|
|
97
|
+
result = visitor.visit(parent)
|
|
98
|
+
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")
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def increment(parent, limit)
|
|
102
|
+
visitor = Jinx::Visitor.new { |node| node.children }
|
|
103
|
+
visitor.visit(parent) { |node| node.value < limit ? node.value += 1 : return }
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def test_collection
|
|
107
|
+
p1 = Node.new(1)
|
|
108
|
+
child = Node.new(2, p1)
|
|
109
|
+
p2 = Node.new(3)
|
|
110
|
+
p2.children << child
|
|
111
|
+
visitor = Jinx::Visitor.new { |pair| REXML::SyncEnumerator.new(pair.first.children, pair.last.children).to_a }
|
|
112
|
+
result = visitor.to_enum([p1, p2]).map { |pair| [pair.first.value, pair.last.value] }
|
|
113
|
+
assert_equal([[1, 3], [2, 2]], result.to_a, "Collection visit result incorrect")
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
def node_value(node)
|
|
117
|
+
node.value if node
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
def test_enumeration
|
|
121
|
+
parent = Node.new(1)
|
|
122
|
+
c1 = Node.new(2, parent)
|
|
123
|
+
c2 = Node.new(3, parent)
|
|
124
|
+
visitor = Jinx::Visitor.new { |node| node.children }
|
|
125
|
+
result = visitor.to_enum(parent).map { |node| node.value }
|
|
126
|
+
assert_equal([1, 2, 3], result, "Enumeration result incorrect")
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
def test_exclude_cycles
|
|
130
|
+
parent = Node.new(1)
|
|
131
|
+
c1 = Node.new(2, parent)
|
|
132
|
+
gc11 = Node.new(3, c1)
|
|
133
|
+
gc11.children << c1
|
|
134
|
+
c2 = Node.new(4, parent)
|
|
135
|
+
gc21 = Node.new(5, c2)
|
|
136
|
+
gc21.children << parent
|
|
137
|
+
visitor = Jinx::Visitor.new(:prune_cycle) { |node| node.children }
|
|
138
|
+
result = visitor.to_enum(parent).map { |node| node.value }
|
|
139
|
+
assert_equal([1, 2, 3], result, "Exclude result incorrect")
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
def test_missing_block
|
|
143
|
+
parent = Node.new(1)
|
|
144
|
+
c1 = Node.new(2, parent)
|
|
145
|
+
c2 = Node.new(3, parent)
|
|
146
|
+
visitor = Jinx::Visitor.new { |node| node.children }
|
|
147
|
+
visitor.visit(parent)
|
|
148
|
+
assert_equal([parent, c1, c2], visitor.visited.values.sort, "Missing visit operator result incorrect")
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
def test_filter
|
|
152
|
+
parent = Node.new(1)
|
|
153
|
+
c1 = Node.new(2, parent)
|
|
154
|
+
c2 = Node.new(3, parent)
|
|
155
|
+
gc1 = Node.new(4, c1)
|
|
156
|
+
gc2 = Node.new(5, c1)
|
|
157
|
+
visitor = Jinx::Visitor.new { |node| node.children }.filter { |parent, children| children.first if parent.value < 4 }
|
|
158
|
+
result = visitor.to_enum(parent).map { |node| node.value }
|
|
159
|
+
assert_equal([1, 2, 4], result, "Filter result incorrect")
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
def test_sync_without_block
|
|
163
|
+
p1 = Node.new(1)
|
|
164
|
+
c11 = Node.new(2, p1)
|
|
165
|
+
c12 = Node.new(3, p1)
|
|
166
|
+
gc111 = Node.new(4, c11)
|
|
167
|
+
gc121 = Node.new(5, c12)
|
|
168
|
+
p2 = Node.new(6)
|
|
169
|
+
c21 = Node.new(7, p2)
|
|
170
|
+
c22 = Node.new(8, p2)
|
|
171
|
+
gc211 = Node.new(9, c21)
|
|
172
|
+
visitor = Jinx::Visitor.new { |node| node.children }.sync
|
|
173
|
+
result = visitor.to_enum(p1, p2).map { |pair| pair.map { |node| node.value unless node.nil? } }
|
|
174
|
+
assert_equal([[1, 6], [2, 7], [4, 9], [3, 8], [5, nil]], result, "Sync without block result incorrect")
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
def test_sync_with_matcher
|
|
178
|
+
p1 = Node.new(1)
|
|
179
|
+
c11 = Node.new(2, p1)
|
|
180
|
+
c12 = Node.new(3, p1)
|
|
181
|
+
gc111 = Node.new(4, c11)
|
|
182
|
+
gc121 = Node.new(5, c12)
|
|
183
|
+
p2 = Node.new(1)
|
|
184
|
+
c21 = Node.new(2, p2)
|
|
185
|
+
c22 = Node.new(3, p2)
|
|
186
|
+
gc211 = Node.new(5, c21)
|
|
187
|
+
visitor = Jinx::Visitor.new { |node| node.children }
|
|
188
|
+
synced = visitor.sync { |nodes, others| nodes.to_compact_hash { |n| others.detect { |o| n.value == o.value } } }
|
|
189
|
+
result = synced.to_enum(p1, p2).map { |pair| pair.map { |node| node.value if node } }
|
|
190
|
+
assert_equal([[1, 1], [2, 2], [4, nil], [3, 3], [5, nil]], result, "Sync with block result incorrect")
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
def test_sync_noncollection
|
|
194
|
+
p1 = Node.new(1)
|
|
195
|
+
child = Node.new(2, p1)
|
|
196
|
+
p2 = Node.new(3)
|
|
197
|
+
p2.children << child
|
|
198
|
+
visitor = Jinx::Visitor.new { |node| node.children.first }.sync
|
|
199
|
+
value_hash = {}
|
|
200
|
+
result = visitor.visit(p1, p2) { |first, last| value_hash[node_value(first)] = node_value(last) }
|
|
201
|
+
assert_equal({1 => 3, 2 => 2}, value_hash, "Sync with non-collection children result incorrect")
|
|
202
|
+
result = visitor.to_enum(p1, p2).map { |first, last| [node_value(first), node_value(last)] }
|
|
203
|
+
assert_equal([[1, 3], [2, 2]], result.to_a, "Sync with non-collection children result incorrect")
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
def test_sync_missing
|
|
207
|
+
p1 = Node.new(1)
|
|
208
|
+
p2 = Node.new(2)
|
|
209
|
+
c1 = Node.new(3, p1)
|
|
210
|
+
c2 = Node.new(4, p2)
|
|
211
|
+
gcren = Node.new(5, c2)
|
|
212
|
+
visitor = Jinx::Visitor.new { |node| node.children.first }.sync
|
|
213
|
+
result = visitor.to_enum(p1, p2).map { |pair| [node_value(pair.first), node_value(pair.last)] }
|
|
214
|
+
assert_equal([[1, 2], [3, 4]], result.to_a, "Sync with missing children result incorrect")
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
def test_missing_node
|
|
218
|
+
parent = Node.new(1)
|
|
219
|
+
child = Node.new(2, parent)
|
|
220
|
+
multiplier = 2
|
|
221
|
+
visitor = Jinx::Visitor.new { |node| node.children unless node == child }
|
|
222
|
+
visitor.visit(parent) { |node| node.value *= multiplier }
|
|
223
|
+
assert_equal(2, parent.value, "Missing node parent value incorrect")
|
|
224
|
+
assert_equal(4, child.value, "Missing node child value incorrect")
|
|
225
|
+
end
|
|
226
|
+
|
|
227
|
+
def test_noncollection_traversal
|
|
228
|
+
parent = Node.new(1)
|
|
229
|
+
child = Node.new(2, parent)
|
|
230
|
+
multiplier = 2
|
|
231
|
+
Jinx::Visitor.new { |node| node.parent }.visit(child) { |node| node.value *= multiplier }
|
|
232
|
+
assert_equal(2, parent.value, "Non-collection parent value incorrect")
|
|
233
|
+
assert_equal(4, child.value, "Non-collection child value incorrect")
|
|
234
|
+
end
|
|
235
|
+
|
|
236
|
+
def test_parent
|
|
237
|
+
parent = Node.new(1)
|
|
238
|
+
c1 = Node.new(2, parent)
|
|
239
|
+
c2 = Node.new(3, parent)
|
|
240
|
+
gc = Node.new(4, c1)
|
|
241
|
+
visitor = Jinx::Visitor.new { |node| node.children }
|
|
242
|
+
visitor.visit(parent) { |node| node.value = visitor.parent.nil? ? 0 : visitor.parent.value + 1 }
|
|
243
|
+
assert_equal(0, parent.value, "Parent value incorrect")
|
|
244
|
+
assert_equal(1, c1.value, "Child value incorrect")
|
|
245
|
+
assert_equal(1, c2.value, "Child value incorrect")
|
|
246
|
+
assert_equal(2, gc.value, "gc value incorrect")
|
|
247
|
+
end
|
|
248
|
+
|
|
249
|
+
def test_parent_depth_first
|
|
250
|
+
# An interesting variant: the parent node value is not reset until after the children are visited
|
|
251
|
+
parent = Node.new(1)
|
|
252
|
+
c1 = Node.new(2, parent)
|
|
253
|
+
c2 = Node.new(3, parent)
|
|
254
|
+
gc = Node.new(4, c1)
|
|
255
|
+
visitor = Jinx::Visitor.new(:depth_first) { |node| node.children }
|
|
256
|
+
visitor.visit(parent) { |node| node.value = visitor.parent.nil? ? 0 : visitor.parent.value + 1 }
|
|
257
|
+
assert_equal(0, parent.value, "Parent value incorrect")
|
|
258
|
+
assert_equal(2, c1.value, "Child value incorrect")
|
|
259
|
+
assert_equal(2, c2.value, "Child value incorrect")
|
|
260
|
+
assert_equal(3, gc.value, "gc value incorrect")
|
|
261
|
+
end
|
|
262
|
+
|
|
263
|
+
def test_visited
|
|
264
|
+
parent = Node.new(1)
|
|
265
|
+
c1 = Node.new(nil, parent)
|
|
266
|
+
c2 = Node.new(nil, parent)
|
|
267
|
+
gc = Node.new(nil, c1)
|
|
268
|
+
visitor = Jinx::Visitor.new { |node| node.children }
|
|
269
|
+
visitor.visit(parent) { |node| node.value ||= visitor.visited[node.parent] + 1 }
|
|
270
|
+
assert_equal(1, parent.value, "Parent value incorrect")
|
|
271
|
+
assert_equal(2, c1.value, "Child value incorrect")
|
|
272
|
+
assert_equal(2, c2.value, "Child value incorrect")
|
|
273
|
+
assert_equal(3, gc.value, "gc value incorrect")
|
|
274
|
+
end
|
|
275
|
+
|
|
276
|
+
def test_visited_result
|
|
277
|
+
parent = Node.new(1)
|
|
278
|
+
c1 = Node.new(2, parent)
|
|
279
|
+
c2 = Node.new(3, parent)
|
|
280
|
+
gc = Node.new(4, c1)
|
|
281
|
+
visitor = Jinx::Visitor.new { |node| node.children }
|
|
282
|
+
visitor.visit(parent) { |node| node.value + 1 }
|
|
283
|
+
assert_equal(2, visitor.visited[parent], "Parent visited value incorrect")
|
|
284
|
+
assert_equal(3, visitor.visited[c1], "Child visited value incorrect")
|
|
285
|
+
assert_equal(4, visitor.visited[c2], "Child visited value incorrect")
|
|
286
|
+
assert_equal(5, visitor.visited[gc], "gc visited value incorrect")
|
|
287
|
+
end
|
|
288
|
+
end
|