linkage 0.0.6 → 0.0.8
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 +10 -0
- data/Gemfile +15 -13
- data/Gemfile.lock +67 -37
- data/Guardfile +0 -2
- data/Rakefile +122 -25
- data/lib/linkage/comparator.rb +172 -0
- data/lib/linkage/comparators/binary.rb +12 -0
- data/lib/linkage/comparators/compare.rb +46 -0
- data/lib/linkage/comparators/within.rb +32 -0
- data/lib/linkage/configuration.rb +285 -153
- data/lib/linkage/data.rb +32 -7
- data/lib/linkage/dataset.rb +107 -32
- data/lib/linkage/decollation.rb +93 -0
- data/lib/linkage/expectation.rb +21 -0
- data/lib/linkage/expectations/exhaustive.rb +63 -0
- data/lib/linkage/expectations/simple.rb +168 -0
- data/lib/linkage/field.rb +30 -4
- data/lib/linkage/field_set.rb +6 -3
- data/lib/linkage/function.rb +50 -3
- data/lib/linkage/functions/binary.rb +30 -0
- data/lib/linkage/functions/cast.rb +54 -0
- data/lib/linkage/functions/length.rb +29 -0
- data/lib/linkage/functions/strftime.rb +12 -11
- data/lib/linkage/functions/trim.rb +8 -0
- data/lib/linkage/group.rb +20 -0
- data/lib/linkage/import_buffer.rb +5 -16
- data/lib/linkage/meta_object.rb +139 -0
- data/lib/linkage/result_set.rb +74 -17
- data/lib/linkage/runner/single_threaded.rb +125 -10
- data/lib/linkage/version.rb +3 -0
- data/lib/linkage.rb +11 -0
- data/linkage.gemspec +16 -121
- data/test/config.yml +5 -0
- data/test/helper.rb +73 -8
- data/test/integration/test_collation.rb +45 -0
- data/test/integration/test_configuration.rb +268 -0
- data/test/integration/test_cross_linkage.rb +4 -17
- data/test/integration/test_dataset.rb +45 -2
- data/test/integration/test_dual_linkage.rb +40 -24
- data/test/integration/test_functions.rb +22 -0
- data/test/integration/test_result_set.rb +85 -0
- data/test/integration/test_scoring.rb +84 -0
- data/test/integration/test_self_linkage.rb +5 -0
- data/test/integration/test_within_comparator.rb +100 -0
- data/test/unit/comparators/test_compare.rb +105 -0
- data/test/unit/comparators/test_within.rb +57 -0
- data/test/unit/expectations/test_exhaustive.rb +111 -0
- data/test/unit/expectations/test_simple.rb +303 -0
- data/test/unit/functions/test_binary.rb +54 -0
- data/test/unit/functions/test_cast.rb +98 -0
- data/test/unit/functions/test_length.rb +52 -0
- data/test/unit/functions/test_strftime.rb +17 -13
- data/test/unit/functions/test_trim.rb +11 -4
- data/test/unit/test_comparator.rb +124 -0
- data/test/unit/test_configuration.rb +137 -175
- data/test/unit/test_data.rb +44 -0
- data/test/unit/test_dataset.rb +73 -21
- data/test/unit/test_decollation.rb +201 -0
- data/test/unit/test_field.rb +38 -14
- data/test/unit/test_field_set.rb +12 -8
- data/test/unit/test_function.rb +83 -16
- data/test/unit/test_group.rb +28 -0
- data/test/unit/test_import_buffer.rb +13 -27
- data/test/unit/test_meta_object.rb +208 -0
- data/test/unit/test_result_set.rb +221 -3
- metadata +82 -190
@@ -0,0 +1,100 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
module IntegrationTests
|
4
|
+
class TestWithinComparator < Test::Unit::TestCase
|
5
|
+
test "within comparator with no simple expectations" do
|
6
|
+
database_for('sqlite') do |db|
|
7
|
+
db.create_table(:foo) { primary_key(:id); Integer(:num) }
|
8
|
+
db.create_table(:bar) { primary_key(:id); Integer(:num) }
|
9
|
+
db[:foo].import([:id, :num], (1..10).collect { |i| [i, i] })
|
10
|
+
db[:bar].import([:id, :num], (1..10).collect { |i| [i, i] })
|
11
|
+
end
|
12
|
+
|
13
|
+
db_opts = database_options_for('sqlite')
|
14
|
+
dataset_1 = Linkage::Dataset.new(db_opts, "foo")
|
15
|
+
dataset_2 = Linkage::Dataset.new(db_opts, "bar")
|
16
|
+
conf = dataset_1.link_with(dataset_2) do
|
17
|
+
lhs[:num].must be_within(5).of(rhs[:num])
|
18
|
+
save_results_in(db_opts)
|
19
|
+
end
|
20
|
+
|
21
|
+
runner = Linkage::SingleThreadedRunner.new(conf)
|
22
|
+
runner.execute
|
23
|
+
|
24
|
+
database_for('sqlite') do |db|
|
25
|
+
assert_equal db[:scores].count, 100
|
26
|
+
db[:scores].order(:record_1_id, :record_2_id).each do |score|
|
27
|
+
if (score[:record_2_id] - score[:record_1_id]).abs <= 5
|
28
|
+
assert_equal 1, score[:score], score.inspect
|
29
|
+
else
|
30
|
+
assert_equal 0, score[:score], score.inspect
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
test "within comparator with simple expectations" do
|
37
|
+
database_for('sqlite') do |db|
|
38
|
+
db.create_table(:foo) { primary_key(:id); Integer(:num); String(:parity) }
|
39
|
+
db.create_table(:bar) { primary_key(:id); Integer(:num); String(:parity) }
|
40
|
+
db[:foo].import([:id, :num, :parity], (1..10).collect { |i| [i, i, i % 2 == 0 ? "even" : "odd"] })
|
41
|
+
db[:bar].import([:id, :num, :parity], (1..10).collect { |i| [i, i, i % 2 == 0 ? "even" : "odd"] })
|
42
|
+
end
|
43
|
+
|
44
|
+
db_opts = database_options_for('sqlite')
|
45
|
+
dataset_1 = Linkage::Dataset.new(db_opts, "foo")
|
46
|
+
dataset_2 = Linkage::Dataset.new(db_opts, "bar")
|
47
|
+
conf = dataset_1.link_with(dataset_2) do
|
48
|
+
lhs[:parity].must == rhs[:parity]
|
49
|
+
lhs[:num].must be_within(5).of(rhs[:num])
|
50
|
+
save_results_in(db_opts)
|
51
|
+
end
|
52
|
+
|
53
|
+
runner = Linkage::SingleThreadedRunner.new(conf)
|
54
|
+
runner.execute
|
55
|
+
|
56
|
+
database_for('sqlite') do |db|
|
57
|
+
assert_equal db[:scores].count, 50
|
58
|
+
db[:scores].order(:record_1_id, :record_2_id).each do |score|
|
59
|
+
if (score[:record_2_id] - score[:record_1_id]).abs <= 5
|
60
|
+
assert_equal 1, score[:score]
|
61
|
+
else
|
62
|
+
assert_equal 0, score[:score]
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
test "within comparator with simple expectations and functions" do
|
69
|
+
database_for('sqlite') do |db|
|
70
|
+
db.create_table(:foo) { primary_key(:id); Integer(:num); String(:parity) }
|
71
|
+
db.create_table(:bar) { primary_key(:id); Integer(:num); String(:parity) }
|
72
|
+
db[:foo].import([:id, :num, :parity], (1..10).collect { |i| [i, i, i % 2 == 0 ? "even" : "odd"] })
|
73
|
+
db[:bar].import([:id, :num, :parity], (1..10).collect { |i| [i, i, i % 2 == 0 ? "even" : "odd"] })
|
74
|
+
end
|
75
|
+
|
76
|
+
db_opts = database_options_for('sqlite')
|
77
|
+
dataset_1 = Linkage::Dataset.new(db_opts, "foo")
|
78
|
+
dataset_2 = Linkage::Dataset.new(db_opts, "bar")
|
79
|
+
conf = dataset_1.link_with(dataset_2) do
|
80
|
+
lhs[:parity].must == rhs[:parity]
|
81
|
+
cast(lhs[:num], 'integer').must be_within(5).of(cast(rhs[:num], 'integer'))
|
82
|
+
save_results_in(db_opts)
|
83
|
+
end
|
84
|
+
|
85
|
+
runner = Linkage::SingleThreadedRunner.new(conf)
|
86
|
+
runner.execute
|
87
|
+
|
88
|
+
database_for('sqlite') do |db|
|
89
|
+
assert_equal db[:scores].count, 50
|
90
|
+
db[:scores].order(:record_1_id, :record_2_id).each do |score|
|
91
|
+
if (score[:record_2_id] - score[:record_1_id]).abs <= 5
|
92
|
+
assert_equal 1, score[:score]
|
93
|
+
else
|
94
|
+
assert_equal 0, score[:score]
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
@@ -0,0 +1,105 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class UnitTests::TestCompare < Test::Unit::TestCase
|
4
|
+
def self.const_missing(name)
|
5
|
+
if Linkage::Comparators.const_defined?(name)
|
6
|
+
Linkage::Comparators.const_get(name)
|
7
|
+
else
|
8
|
+
super
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
test "subclass of Binary" do
|
13
|
+
assert_equal Binary, Compare.superclass
|
14
|
+
end
|
15
|
+
|
16
|
+
test "valid parameters" do
|
17
|
+
meta_object_1 = stub('meta object', :name => :foo, :side => :lhs, :ruby_type => { :type => Integer }, :static? => false)
|
18
|
+
meta_object_2 = stub('meta object', :object => '>', :ruby_type => { :type => String }, :static? => true, :raw? => true)
|
19
|
+
meta_object_3 = stub('meta object', :name => :bar, :side => :rhs, :ruby_type => { :type => Integer }, :static? => false)
|
20
|
+
assert_nothing_raised do
|
21
|
+
Compare.new(meta_object_1, meta_object_2, meta_object_3)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
test "score for not equal to" do
|
26
|
+
meta_object_1 = stub('meta object', :name => :foo, :side => :lhs, :ruby_type => { :type => Integer }, :static? => false)
|
27
|
+
meta_object_2 = stub('meta object', :object => '!=', :ruby_type => { :type => String }, :static? => true, :raw? => true)
|
28
|
+
meta_object_3 = stub('meta object', :name => :bar, :side => :rhs, :ruby_type => { :type => Integer }, :static? => false)
|
29
|
+
comp = Compare.new(meta_object_1, meta_object_2, meta_object_3)
|
30
|
+
assert_equal 1, comp.score({:foo => 10}, {:bar => 5})
|
31
|
+
assert_equal 0, comp.score({:foo => 5}, {:bar => 5})
|
32
|
+
assert_equal 1, comp.score({:foo => 0}, {:bar => 5})
|
33
|
+
end
|
34
|
+
|
35
|
+
test "score for greater than" do
|
36
|
+
meta_object_1 = stub('meta object', :name => :foo, :side => :lhs, :ruby_type => { :type => Integer }, :static? => false)
|
37
|
+
meta_object_2 = stub('meta object', :object => '>', :ruby_type => { :type => String }, :static? => true, :raw? => true)
|
38
|
+
meta_object_3 = stub('meta object', :name => :bar, :side => :rhs, :ruby_type => { :type => Integer }, :static? => false)
|
39
|
+
comp = Compare.new(meta_object_1, meta_object_2, meta_object_3)
|
40
|
+
assert_equal 1, comp.score({:foo => 10}, {:bar => 5})
|
41
|
+
assert_equal 0, comp.score({:foo => 5}, {:bar => 5})
|
42
|
+
assert_equal 0, comp.score({:foo => 0}, {:bar => 5})
|
43
|
+
end
|
44
|
+
|
45
|
+
test "score for greater than or equal to" do
|
46
|
+
meta_object_1 = stub('meta object', :name => :foo, :side => :lhs, :ruby_type => { :type => Integer }, :static? => false)
|
47
|
+
meta_object_2 = stub('meta object', :object => '>=', :ruby_type => { :type => String }, :static? => true, :raw? => true)
|
48
|
+
meta_object_3 = stub('meta object', :name => :bar, :side => :rhs, :ruby_type => { :type => Integer }, :static? => false)
|
49
|
+
comp = Compare.new(meta_object_1, meta_object_2, meta_object_3)
|
50
|
+
assert_equal 1, comp.score({:foo => 10}, {:bar => 5})
|
51
|
+
assert_equal 1, comp.score({:foo => 5}, {:bar => 5})
|
52
|
+
assert_equal 0, comp.score({:foo => 0}, {:bar => 5})
|
53
|
+
end
|
54
|
+
|
55
|
+
test "score for less than or equal to" do
|
56
|
+
meta_object_1 = stub('meta object', :name => :foo, :side => :lhs, :ruby_type => { :type => Integer }, :static? => false)
|
57
|
+
meta_object_2 = stub('meta object', :object => '<=', :ruby_type => { :type => String }, :static? => true, :raw? => true)
|
58
|
+
meta_object_3 = stub('meta object', :name => :bar, :side => :rhs, :ruby_type => { :type => Integer }, :static? => false)
|
59
|
+
comp = Compare.new(meta_object_1, meta_object_2, meta_object_3)
|
60
|
+
assert_equal 0, comp.score({:foo => 10}, {:bar => 5})
|
61
|
+
assert_equal 1, comp.score({:foo => 5}, {:bar => 5})
|
62
|
+
assert_equal 1, comp.score({:foo => 0}, {:bar => 5})
|
63
|
+
end
|
64
|
+
|
65
|
+
test "score for less than" do
|
66
|
+
meta_object_1 = stub('meta object', :name => :foo, :side => :lhs, :ruby_type => { :type => Integer }, :static? => false)
|
67
|
+
meta_object_2 = stub('meta object', :object => '<', :ruby_type => { :type => String }, :static? => true, :raw? => true)
|
68
|
+
meta_object_3 = stub('meta object', :name => :bar, :side => :rhs, :ruby_type => { :type => Integer }, :static? => false)
|
69
|
+
comp = Compare.new(meta_object_1, meta_object_2, meta_object_3)
|
70
|
+
assert_equal 0, comp.score({:foo => 10}, {:bar => 5})
|
71
|
+
assert_equal 0, comp.score({:foo => 5}, {:bar => 5})
|
72
|
+
assert_equal 1, comp.score({:foo => 0}, {:bar => 5})
|
73
|
+
end
|
74
|
+
|
75
|
+
test "registers itself" do
|
76
|
+
assert_equal Compare, Linkage::Comparator['compare']
|
77
|
+
end
|
78
|
+
|
79
|
+
test "requires argument from each side" do
|
80
|
+
meta_object_1 = stub('meta object', :name => :foo, :side => :lhs, :ruby_type => { :type => Integer }, :static? => false)
|
81
|
+
meta_object_2 = stub('meta object', :object => '>=', :ruby_type => { :type => String }, :static? => true, :raw? => true)
|
82
|
+
meta_object_3 = stub('meta object', :name => :bar, :side => :lhs, :ruby_type => { :type => Integer }, :static? => false)
|
83
|
+
assert_raises do
|
84
|
+
Compare.new(meta_object_1, meta_object_2, meta_object_3)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
test "requires that 3rd argument has the same type as the first argument" do
|
89
|
+
meta_object_1 = stub('meta object', :name => :foo, :side => :lhs, :ruby_type => { :type => Integer }, :static? => false)
|
90
|
+
meta_object_2 = stub('meta object', :object => '>=', :ruby_type => { :type => String }, :static? => true, :raw? => true)
|
91
|
+
meta_object_3 = stub('meta object', :name => :bar, :side => :rhs, :ruby_type => { :type => Date }, :static? => false)
|
92
|
+
assert_raises do
|
93
|
+
Compare.new(meta_object_1, meta_object_2, meta_object_3)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
test "requires raw operator to be >, >=, <=, <, or !=" do
|
98
|
+
meta_object_1 = stub('meta object', :name => :foo, :side => :lhs, :ruby_type => { :type => Integer }, :static? => false)
|
99
|
+
meta_object_2 = stub('meta object', :object => 'foo', :ruby_type => { :type => String }, :static? => true, :raw? => true)
|
100
|
+
meta_object_3 = stub('meta object', :name => :bar, :side => :rhs, :ruby_type => { :type => Integer }, :static? => false)
|
101
|
+
assert_raises do
|
102
|
+
Compare.new(meta_object_1, meta_object_2, meta_object_3)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class UnitTests::TestWithin < Test::Unit::TestCase
|
4
|
+
def self.const_missing(name)
|
5
|
+
if Linkage::Comparators.const_defined?(name)
|
6
|
+
Linkage::Comparators.const_get(name)
|
7
|
+
else
|
8
|
+
super
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
test "subclass of Binary" do
|
13
|
+
assert_equal Linkage::Comparators::Binary, Within.superclass
|
14
|
+
end
|
15
|
+
|
16
|
+
test "valid parameters" do
|
17
|
+
meta_object_1 = stub('meta object', :name => :foo, :side => :lhs, :ruby_type => { :type => Integer }, :static? => false)
|
18
|
+
meta_object_2 = stub('meta object', :object => 123, :ruby_type => { :type => Fixnum }, :static? => true, :object => 123)
|
19
|
+
meta_object_3 = stub('meta object', :name => :bar, :side => :rhs, :ruby_type => { :type => Integer }, :static? => false)
|
20
|
+
assert_nothing_raised do
|
21
|
+
Within.new(meta_object_1, meta_object_2, meta_object_3)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
test "score" do
|
26
|
+
meta_object_1 = stub('meta object', :name => :foo, :side => :lhs, :ruby_type => { :type => Integer }, :static? => false)
|
27
|
+
meta_object_2 = stub('meta object', :object => 123, :ruby_type => { :type => Fixnum }, :static? => true, :object => 123)
|
28
|
+
meta_object_3 = stub('meta object', :name => :bar, :side => :rhs, :ruby_type => { :type => Integer }, :static? => false)
|
29
|
+
comp = Within.new(meta_object_1, meta_object_2, meta_object_3)
|
30
|
+
assert_equal 1, comp.score({:foo => 123}, {:bar => 124})
|
31
|
+
assert_equal 1, comp.score({:foo => 124}, {:bar => 123})
|
32
|
+
assert_equal 1, comp.score({:foo => 0}, {:bar => 123})
|
33
|
+
assert_equal 0, comp.score({:foo => 0}, {:bar => 124})
|
34
|
+
end
|
35
|
+
|
36
|
+
test "registers itself" do
|
37
|
+
assert_equal Within, Linkage::Comparator['within']
|
38
|
+
end
|
39
|
+
|
40
|
+
test "requires argument from each side" do
|
41
|
+
meta_object_1 = stub('meta object', :name => :foo, :side => :lhs, :ruby_type => { :type => Integer }, :static? => false)
|
42
|
+
meta_object_2 = stub('meta object', :object => 123, :ruby_type => { :type => Fixnum }, :static? => true, :object => 123)
|
43
|
+
meta_object_3 = stub('meta object', :name => :bar, :side => :lhs, :ruby_type => { :type => Integer }, :static? => false)
|
44
|
+
assert_raises do
|
45
|
+
Within.new(meta_object_1, meta_object_2, meta_object_3)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
test "requires that 3rd argument has the same type as the first argument" do
|
50
|
+
meta_object_1 = stub('meta object', :name => :foo, :side => :lhs, :ruby_type => { :type => Integer }, :static? => false)
|
51
|
+
meta_object_2 = stub('meta object', :object => 123, :ruby_type => { :type => Fixnum }, :static? => true, :object => 123)
|
52
|
+
meta_object_3 = stub('meta object', :name => :bar, :side => :rhs, :ruby_type => { :type => Date }, :static? => false)
|
53
|
+
assert_raises do
|
54
|
+
Within.new(meta_object_1, meta_object_2, meta_object_3)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,111 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class UnitTests::TestExhaustive < Test::Unit::TestCase
|
4
|
+
test "initialize with comparator, threshold, and mode" do
|
5
|
+
comparator = stub('comparator')
|
6
|
+
exp = Linkage::Expectations::Exhaustive.new(comparator, 100, :min)
|
7
|
+
assert_equal comparator, exp.comparator
|
8
|
+
assert_equal 100, exp.threshold
|
9
|
+
assert_equal :min, exp.mode
|
10
|
+
end
|
11
|
+
|
12
|
+
test "kind is :self when comparator has same args on both sides" do
|
13
|
+
meta_object_1 = stub('meta object 1')
|
14
|
+
meta_object_2 = stub('meta object 2')
|
15
|
+
meta_object_1.expects(:objects_equal?).with(meta_object_2).returns(true)
|
16
|
+
comparator = stub('comparator', {
|
17
|
+
:lhs_args => [meta_object_1], :rhs_args => [meta_object_2]
|
18
|
+
})
|
19
|
+
exp = Linkage::Expectations::Exhaustive.new(comparator, 100, :min)
|
20
|
+
assert_equal :self, exp.kind
|
21
|
+
end
|
22
|
+
|
23
|
+
test "kind is :cross when comparator has args with same dataset but different number of args" do
|
24
|
+
meta_object_1 = stub('meta object 1')
|
25
|
+
meta_object_2 = stub('meta object 2')
|
26
|
+
meta_object_3 = stub('meta object 3')
|
27
|
+
meta_object_1.expects(:datasets_equal?).with(meta_object_2).returns(true)
|
28
|
+
comparator = stub('comparator', {
|
29
|
+
:lhs_args => [meta_object_1], :rhs_args => [meta_object_2, meta_object_3]
|
30
|
+
})
|
31
|
+
exp = Linkage::Expectations::Exhaustive.new(comparator, 100, :min)
|
32
|
+
assert_equal :cross, exp.kind
|
33
|
+
end
|
34
|
+
|
35
|
+
test "kind is :cross when comparator has args with same dataset but different objects" do
|
36
|
+
meta_object_1 = stub('meta object 1')
|
37
|
+
meta_object_2 = stub('meta object 2')
|
38
|
+
meta_object_1.expects(:objects_equal?).with(meta_object_2).returns(false)
|
39
|
+
meta_object_1.expects(:datasets_equal?).with(meta_object_2).returns(true)
|
40
|
+
comparator = stub('comparator', {
|
41
|
+
:lhs_args => [meta_object_1], :rhs_args => [meta_object_2]
|
42
|
+
})
|
43
|
+
exp = Linkage::Expectations::Exhaustive.new(comparator, 100, :min)
|
44
|
+
assert_equal :cross, exp.kind
|
45
|
+
end
|
46
|
+
|
47
|
+
test "kind is :dual when comparator has args with different datasets and different number of args" do
|
48
|
+
meta_object_1 = stub('meta object 1')
|
49
|
+
meta_object_2 = stub('meta object 2')
|
50
|
+
meta_object_3 = stub('meta object 3')
|
51
|
+
meta_object_1.expects(:datasets_equal?).with(meta_object_2).returns(false)
|
52
|
+
comparator = stub('comparator', {
|
53
|
+
:lhs_args => [meta_object_1], :rhs_args => [meta_object_2, meta_object_3]
|
54
|
+
})
|
55
|
+
exp = Linkage::Expectations::Exhaustive.new(comparator, 100, :min)
|
56
|
+
assert_equal :dual, exp.kind
|
57
|
+
end
|
58
|
+
|
59
|
+
test "kind is :dual when comparator has args with different datasets" do
|
60
|
+
meta_object_1 = stub('meta object 1')
|
61
|
+
meta_object_2 = stub('meta object 2')
|
62
|
+
meta_object_1.expects(:objects_equal?).with(meta_object_2).returns(false)
|
63
|
+
meta_object_1.expects(:datasets_equal?).with(meta_object_2).returns(false)
|
64
|
+
comparator = stub('comparator', {
|
65
|
+
:lhs_args => [meta_object_1], :rhs_args => [meta_object_2]
|
66
|
+
})
|
67
|
+
exp = Linkage::Expectations::Exhaustive.new(comparator, 100, :min)
|
68
|
+
assert_equal :dual, exp.kind
|
69
|
+
end
|
70
|
+
|
71
|
+
test "apply_to lhs dataset" do
|
72
|
+
dataset = stub('dataset')
|
73
|
+
new_dataset = stub('new dataset')
|
74
|
+
meta_object_1 = stub('meta object 1', :name => :foo, :to_expr => :foo)
|
75
|
+
meta_object_2 = stub('meta object 2', :name => :bar, :to_expr => :bar)
|
76
|
+
comparator = stub('comparator', :lhs_args => [meta_object_1], :rhs_args => [meta_object_2])
|
77
|
+
exp = Linkage::Expectations::Exhaustive.new(comparator, 100, :min)
|
78
|
+
dataset.expects(:select_more).with(:foo.as(:foo)).returns(new_dataset)
|
79
|
+
assert_equal new_dataset, exp.apply_to(dataset, :lhs)
|
80
|
+
end
|
81
|
+
|
82
|
+
test "apply_to rhs dataset" do
|
83
|
+
dataset = stub('dataset')
|
84
|
+
new_dataset = stub('new dataset')
|
85
|
+
meta_object_1 = stub('meta object 1', :name => :foo, :to_expr => :foo)
|
86
|
+
meta_object_2 = stub('meta object 2', :name => :bar, :to_expr => :bar)
|
87
|
+
comparator = stub('comparator', :lhs_args => [meta_object_1], :rhs_args => [meta_object_2])
|
88
|
+
exp = Linkage::Expectations::Exhaustive.new(comparator, 100, :min)
|
89
|
+
dataset.expects(:select_more).with(:bar.as(:bar)).returns(new_dataset)
|
90
|
+
assert_equal new_dataset, exp.apply_to(dataset, :rhs)
|
91
|
+
end
|
92
|
+
|
93
|
+
test "satisfied? with :equal mode" do
|
94
|
+
meta_object_1 = stub('meta object 1')
|
95
|
+
meta_object_2 = stub('meta object 2')
|
96
|
+
comparator = stub('comparator', :lhs_args => [meta_object_1], :rhs_args => [meta_object_2])
|
97
|
+
exp = Linkage::Expectations::Exhaustive.new(comparator, 50, :equal)
|
98
|
+
assert exp.satisfied?(50)
|
99
|
+
assert !exp.satisfied?(123)
|
100
|
+
end
|
101
|
+
|
102
|
+
test "satisfied? with :min mode" do
|
103
|
+
meta_object_1 = stub('meta object 1')
|
104
|
+
meta_object_2 = stub('meta object 2')
|
105
|
+
comparator = stub('comparator', :lhs_args => [meta_object_1], :rhs_args => [meta_object_2])
|
106
|
+
exp = Linkage::Expectations::Exhaustive.new(comparator, 50, :min)
|
107
|
+
assert exp.satisfied?(50)
|
108
|
+
assert exp.satisfied?(55)
|
109
|
+
assert !exp.satisfied?(45)
|
110
|
+
end
|
111
|
+
end
|
@@ -0,0 +1,303 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class UnitTests::TestSimple < Test::Unit::TestCase
|
4
|
+
test "initialize with invalid operator" do
|
5
|
+
assert_raises(ArgumentError) do
|
6
|
+
Linkage::Expectations::Simple.new(stub(), stub(), :foo)
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
test "creating filter expectation from a dynamic object and a static object" do
|
11
|
+
field = stub('meta field', :static? => false, :side => :lhs)
|
12
|
+
object = stub('meta object', :static? => true)
|
13
|
+
exp = Linkage::Expectations::Simple.create(field, object, :==)
|
14
|
+
assert_kind_of Linkage::Expectations::Filter, exp
|
15
|
+
assert_equal :lhs, exp.side
|
16
|
+
end
|
17
|
+
|
18
|
+
test "creating expectation from two static objects raises error" do
|
19
|
+
object_1 = stub('meta object 1', :static? => true)
|
20
|
+
object_2 = stub('meta object 2', :static? => true)
|
21
|
+
assert_raises(ArgumentError) do
|
22
|
+
Linkage::Expectations::Simple.create(object_1, object_2, :==)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
test "creating filter expectation from two dynamic objects with the same side" do
|
27
|
+
field_1 = stub('meta field 1', :static? => false, :side => :lhs)
|
28
|
+
field_2 = stub('meta field 2', :static? => false, :side => :lhs)
|
29
|
+
field_1.expects(:datasets_equal?).with(field_2).returns(true)
|
30
|
+
exp = Linkage::Expectations::Simple.create(field_1, field_2, :==)
|
31
|
+
assert_kind_of Linkage::Expectations::Filter, exp
|
32
|
+
assert_equal :lhs, exp.side
|
33
|
+
end
|
34
|
+
|
35
|
+
test "creating filter expectation from two dynamic objects with the same side but different datasets raises error" do
|
36
|
+
field_1 = stub('meta field 1', :static? => false, :side => :lhs)
|
37
|
+
field_2 = stub('meta field 2', :static? => false, :side => :lhs)
|
38
|
+
field_1.expects(:datasets_equal?).with(field_2).returns(false)
|
39
|
+
assert_raises(ArgumentError) do
|
40
|
+
Linkage::Expectations::Simple.create(field_1, field_2, :==)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
test "creating self expectation from two dynamic objects with different sides" do
|
45
|
+
object_1 = stub('meta object 1', :static? => false, :side => :lhs)
|
46
|
+
object_2 = stub('meta object 2', :static? => false, :side => :rhs)
|
47
|
+
object_1.expects(:objects_equal?).with(object_2).returns(true)
|
48
|
+
exp = Linkage::Expectations::Simple.create(object_1, object_2, :==)
|
49
|
+
assert_kind_of Linkage::Expectations::Self, exp
|
50
|
+
end
|
51
|
+
|
52
|
+
test "creating cross expectation from two dynamic objects with different sides but same dataset" do
|
53
|
+
object_1 = stub('meta object 1', :static? => false, :side => :lhs)
|
54
|
+
object_2 = stub('meta object 2', :static? => false, :side => :rhs)
|
55
|
+
object_1.expects(:objects_equal?).with(object_2).returns(false)
|
56
|
+
object_1.expects(:datasets_equal?).with(object_2).returns(true)
|
57
|
+
exp = Linkage::Expectations::Simple.create(object_1, object_2, :==)
|
58
|
+
assert_kind_of Linkage::Expectations::Cross, exp
|
59
|
+
end
|
60
|
+
|
61
|
+
test "creating dual expectation from two dynamic objects with different sides and datasets" do
|
62
|
+
object_1 = stub('meta object 1', :static? => false, :side => :lhs)
|
63
|
+
object_2 = stub('meta object 2', :static? => false, :side => :rhs)
|
64
|
+
object_1.expects(:objects_equal?).with(object_2).returns(false)
|
65
|
+
object_1.expects(:datasets_equal?).with(object_2).returns(false)
|
66
|
+
exp = Linkage::Expectations::Simple.create(object_1, object_2, :==)
|
67
|
+
assert_kind_of Linkage::Expectations::Dual, exp
|
68
|
+
end
|
69
|
+
|
70
|
+
test "apply_to with filter expectation (== operator)" do
|
71
|
+
dataset = stub('dataset')
|
72
|
+
meta_field_1 = stub('meta field 1', :static? => false, :side => :lhs)
|
73
|
+
meta_field_2 = stub('meta field 2', :static? => false, :side => :lhs)
|
74
|
+
meta_field_1.stubs(:datasets_equal?).with(meta_field_2).returns(true)
|
75
|
+
|
76
|
+
exp = Linkage::Expectations::Simple.create(meta_field_1, meta_field_2, :==)
|
77
|
+
meta_field_1.expects(:to_expr).returns(:foo)
|
78
|
+
meta_field_2.expects(:to_expr).returns(:bar)
|
79
|
+
dataset.expects(:filter).with({:foo => :bar}).returns(dataset)
|
80
|
+
assert_equal dataset, exp.apply_to(dataset, :lhs)
|
81
|
+
|
82
|
+
dataset.expects(:filter).never
|
83
|
+
assert_equal dataset, exp.apply_to(dataset, :rhs)
|
84
|
+
end
|
85
|
+
|
86
|
+
test "apply_to with filter expectation (!= operator)" do
|
87
|
+
dataset = stub('dataset')
|
88
|
+
meta_field_1 = stub('meta field 1', :static? => false, :side => :lhs)
|
89
|
+
meta_field_2 = stub('meta field 2', :static? => false, :side => :lhs)
|
90
|
+
meta_field_1.stubs(:datasets_equal?).with(meta_field_2).returns(true)
|
91
|
+
|
92
|
+
exp = Linkage::Expectations::Simple.create(meta_field_1, meta_field_2, :'!=')
|
93
|
+
meta_field_1.expects(:to_expr).returns(:foo)
|
94
|
+
meta_field_2.expects(:to_expr).returns(:bar)
|
95
|
+
dataset.expects(:filter).with(~{:foo => :bar}).returns(dataset)
|
96
|
+
assert_equal dataset, exp.apply_to(dataset, :lhs)
|
97
|
+
|
98
|
+
dataset.expects(:filter).never
|
99
|
+
assert_equal dataset, exp.apply_to(dataset, :rhs)
|
100
|
+
end
|
101
|
+
|
102
|
+
test "apply_to with filter expectation (> operator)" do
|
103
|
+
dataset = stub('dataset')
|
104
|
+
meta_field_1 = stub('meta field 1', :static? => false, :side => :lhs)
|
105
|
+
meta_field_2 = stub('meta field 2', :static? => false, :side => :lhs)
|
106
|
+
meta_field_1.stubs(:datasets_equal?).with(meta_field_2).returns(true)
|
107
|
+
exp = Linkage::Expectations::Simple.create(meta_field_1, meta_field_2, :>)
|
108
|
+
|
109
|
+
identifier_1 = Sequel::SQL::Identifier.new(:foo)
|
110
|
+
meta_field_1.expects(:to_identifier).returns(identifier_1)
|
111
|
+
identifier_2 = Sequel::SQL::Identifier.new(:bar)
|
112
|
+
meta_field_2.expects(:to_identifier).returns(identifier_2)
|
113
|
+
expected = Sequel::SQL::BooleanExpression.new(:>, identifier_1, identifier_2)
|
114
|
+
|
115
|
+
dataset.expects(:filter).with(expected).returns(dataset)
|
116
|
+
assert_equal dataset, exp.apply_to(dataset, :lhs)
|
117
|
+
|
118
|
+
dataset.expects(:filter).never
|
119
|
+
assert_equal dataset, exp.apply_to(dataset, :rhs)
|
120
|
+
end
|
121
|
+
|
122
|
+
test "apply_to with self expectation" do
|
123
|
+
dataset = stub('dataset')
|
124
|
+
object_1 = stub('meta object 1', {
|
125
|
+
:static? => false, :side => :lhs, :dataset => dataset,
|
126
|
+
:to_expr => :foo
|
127
|
+
})
|
128
|
+
object_2 = stub('meta object 2', {
|
129
|
+
:static? => false, :side => :rhs, :dataset => dataset,
|
130
|
+
:to_expr => :foo
|
131
|
+
})
|
132
|
+
object_1.expects(:objects_equal?).with(object_2).returns(true)
|
133
|
+
exp = Linkage::Expectations::Simple.create(object_1, object_2, :==)
|
134
|
+
|
135
|
+
merged_field = stub('merged field', :name => :foo)
|
136
|
+
object_1.expects(:merge).with(object_2).returns(merged_field)
|
137
|
+
dataset.expects(:group_match_more).with({:meta_object => object_1, :alias => :foo}).returns(dataset)
|
138
|
+
assert_equal dataset, exp.apply_to(dataset, :lhs)
|
139
|
+
|
140
|
+
dataset.expects(:group_match_more).with({:meta_object => object_2, :alias => :foo}).returns(dataset)
|
141
|
+
assert_equal dataset, exp.apply_to(dataset, :rhs)
|
142
|
+
end
|
143
|
+
|
144
|
+
test "apply_to with cross expectation" do
|
145
|
+
dataset = stub('dataset')
|
146
|
+
object_1 = stub('meta object 1', {
|
147
|
+
:static? => false, :side => :lhs, :dataset => dataset,
|
148
|
+
:to_expr => :foo
|
149
|
+
})
|
150
|
+
object_2 = stub('meta object 2', {
|
151
|
+
:static? => false, :side => :rhs, :dataset => dataset,
|
152
|
+
:to_expr => :bar
|
153
|
+
})
|
154
|
+
object_1.stubs(:objects_equal?).with(object_2).returns(false)
|
155
|
+
object_1.stubs(:datasets_equal?).with(object_2).returns(true)
|
156
|
+
exp = Linkage::Expectations::Simple.create(object_1, object_2, :==)
|
157
|
+
|
158
|
+
merged_field = stub('merged field', :name => :foo_bar)
|
159
|
+
object_1.expects(:merge).with(object_2).returns(merged_field)
|
160
|
+
dataset.expects(:group_match_more).with({:meta_object => object_1, :alias => :foo_bar}).returns(dataset)
|
161
|
+
assert_equal dataset, exp.apply_to(dataset, :lhs)
|
162
|
+
|
163
|
+
dataset.expects(:group_match_more).with({:meta_object => object_2, :alias => :foo_bar}).returns(dataset)
|
164
|
+
assert_equal dataset, exp.apply_to(dataset, :rhs)
|
165
|
+
end
|
166
|
+
|
167
|
+
test "apply_to with dual expectation" do
|
168
|
+
dataset_1 = stub('dataset 1')
|
169
|
+
object_1 = stub('meta object 1', {
|
170
|
+
:static? => false, :side => :lhs, :dataset => dataset_1,
|
171
|
+
:to_expr => :foo
|
172
|
+
})
|
173
|
+
dataset_2 = stub('dataset 2')
|
174
|
+
object_2 = stub('meta object 2', {
|
175
|
+
:static? => false, :side => :rhs, :dataset => dataset_2,
|
176
|
+
:to_expr => :foo
|
177
|
+
})
|
178
|
+
object_1.stubs(:objects_equal?).with(object_2).returns(false)
|
179
|
+
object_1.stubs(:datasets_equal?).with(object_2).returns(false)
|
180
|
+
exp = Linkage::Expectations::Simple.create(object_1, object_2, :==)
|
181
|
+
|
182
|
+
merged_field = stub('merged field', :name => :foo)
|
183
|
+
object_1.expects(:merge).with(object_2).returns(merged_field)
|
184
|
+
dataset_1.expects(:group_match_more).with({:meta_object => object_1, :alias => :foo}).returns(dataset_1)
|
185
|
+
assert_equal dataset_1, exp.apply_to(dataset_1, :lhs)
|
186
|
+
|
187
|
+
dataset_2.expects(:group_match_more).with({:meta_object => object_2, :alias => :foo}).returns(dataset_2)
|
188
|
+
assert_equal dataset_2, exp.apply_to(dataset_2, :rhs)
|
189
|
+
end
|
190
|
+
|
191
|
+
test "exactly! wraps each side inside the binary function" do
|
192
|
+
dataset_1 = stub('dataset 1')
|
193
|
+
field_1 = stub_field('field 1', :dataset => dataset_1)
|
194
|
+
meta_object_1 = stub('meta object 1', :static? => false, :side => :lhs,
|
195
|
+
:object => field_1, :dataset => dataset_1)
|
196
|
+
|
197
|
+
dataset_2 = stub('dataset 2')
|
198
|
+
field_2 = stub_field('field 2', :dataset => dataset_2)
|
199
|
+
meta_object_2 = stub('meta object 2', :static? => false, :side => :rhs,
|
200
|
+
:object => field_2, :dataset => dataset_2)
|
201
|
+
meta_object_1.stubs(:objects_equal?).with(meta_object_2).returns(true)
|
202
|
+
|
203
|
+
exp = Linkage::Expectations::Simple.create(meta_object_1, meta_object_2, :==)
|
204
|
+
|
205
|
+
klass = Linkage::Functions::Binary
|
206
|
+
func_1 = stub('binary function 1')
|
207
|
+
klass.expects(:new).with(field_1, :dataset => dataset_1).returns(func_1)
|
208
|
+
func_2 = stub('binary function 2')
|
209
|
+
klass.expects(:new).with(field_2, :dataset => dataset_2).returns(func_2)
|
210
|
+
|
211
|
+
new_meta_object_1 = stub('new meta object 1')
|
212
|
+
Linkage::MetaObject.expects(:new).with(func_1, :lhs).returns(new_meta_object_1)
|
213
|
+
new_meta_object_2 = stub('new meta object 2')
|
214
|
+
Linkage::MetaObject.expects(:new).with(func_2, :rhs).returns(new_meta_object_2)
|
215
|
+
|
216
|
+
exp.exactly!
|
217
|
+
# LAZY: assume the expectation set its meta objects appropriately
|
218
|
+
end
|
219
|
+
|
220
|
+
test "#same_except_side with two filter expectations" do
|
221
|
+
field = stub_field('foo')
|
222
|
+
meta_object_1 = stub('meta field 1', {
|
223
|
+
:static? => false, :side => :lhs, :object => field
|
224
|
+
})
|
225
|
+
meta_object_2 = stub('meta object', :static? => true)
|
226
|
+
meta_object_3 = stub('meta field 2', {
|
227
|
+
:static? => false, :side => :rhs, :object => field
|
228
|
+
})
|
229
|
+
|
230
|
+
exp_1 = Linkage::Expectations::Simple.create(meta_object_1, meta_object_2, :==)
|
231
|
+
exp_2 = Linkage::Expectations::Simple.create(meta_object_3, meta_object_2, :==)
|
232
|
+
|
233
|
+
meta_object_1.expects(:objects_equal?).with(meta_object_3).returns(true)
|
234
|
+
meta_object_2.expects(:objects_equal?).with(meta_object_2).returns(true)
|
235
|
+
assert exp_1.same_except_side?(exp_2)
|
236
|
+
end
|
237
|
+
|
238
|
+
test "#decollation_needed? is false when comparing non-string objects" do
|
239
|
+
dataset_1 = stub('dataset 1')
|
240
|
+
object_1 = stub('meta object 1', {
|
241
|
+
:static? => false, :side => :lhs, :dataset => dataset_1,
|
242
|
+
})
|
243
|
+
dataset_2 = stub('dataset 2')
|
244
|
+
object_2 = stub('meta object 2', {
|
245
|
+
:static? => false, :side => :rhs, :dataset => dataset_2,
|
246
|
+
})
|
247
|
+
merged_field = stub('merged field', :ruby_type => {:type => Fixnum})
|
248
|
+
object_1.stubs(:merge).with(object_2).returns(merged_field)
|
249
|
+
exp = Linkage::Expectations::Dual.new(object_1, object_2, :==)
|
250
|
+
assert !exp.decollation_needed?
|
251
|
+
end
|
252
|
+
|
253
|
+
test "#decollation_needed? is false when comparing two dynamic string objects with the same database type and same collation" do
|
254
|
+
dataset_1 = stub('dataset 1')
|
255
|
+
object_1 = stub('meta object 1', {
|
256
|
+
:static? => false, :side => :lhs, :dataset => dataset_1,
|
257
|
+
:collation => 'foo', :database_type => :mysql
|
258
|
+
})
|
259
|
+
dataset_2 = stub('dataset 2')
|
260
|
+
object_2 = stub('meta object 2', {
|
261
|
+
:static? => false, :side => :rhs, :dataset => dataset_2,
|
262
|
+
:collation => 'foo', :database_type => :mysql
|
263
|
+
})
|
264
|
+
merged_field = stub('merged field', :ruby_type => {:type => String})
|
265
|
+
object_1.stubs(:merge).with(object_2).returns(merged_field)
|
266
|
+
exp = Linkage::Expectations::Dual.new(object_1, object_2, :==)
|
267
|
+
assert !exp.decollation_needed?
|
268
|
+
end
|
269
|
+
|
270
|
+
test "#decollation_needed? is true when comparing two dynamic string objects with the same database type but different collations" do
|
271
|
+
dataset_1 = stub('dataset 1')
|
272
|
+
object_1 = stub('meta object 1', {
|
273
|
+
:static? => false, :side => :lhs, :dataset => dataset_1,
|
274
|
+
:collation => 'foo', :database_type => :mysql
|
275
|
+
})
|
276
|
+
dataset_2 = stub('dataset 2')
|
277
|
+
object_2 = stub('meta object 2', {
|
278
|
+
:static? => false, :side => :rhs, :dataset => dataset_2,
|
279
|
+
:collation => 'bar', :database_type => :mysql
|
280
|
+
})
|
281
|
+
merged_field = stub('merged field', :ruby_type => {:type => String})
|
282
|
+
object_1.stubs(:merge).with(object_2).returns(merged_field)
|
283
|
+
exp = Linkage::Expectations::Dual.new(object_1, object_2, :==)
|
284
|
+
assert exp.decollation_needed?
|
285
|
+
end
|
286
|
+
|
287
|
+
test "#decollation_needed? is true when comparing two dynamic string objects with same collation but different database types" do
|
288
|
+
dataset_1 = stub('dataset 1')
|
289
|
+
object_1 = stub('meta object 1', {
|
290
|
+
:static? => false, :side => :lhs, :dataset => dataset_1,
|
291
|
+
:collation => 'foo', :database_type => :foo
|
292
|
+
})
|
293
|
+
dataset_2 = stub('dataset 2')
|
294
|
+
object_2 = stub('meta object 2', {
|
295
|
+
:static? => false, :side => :rhs, :dataset => dataset_2,
|
296
|
+
:collation => 'foo', :database_type => :bar
|
297
|
+
})
|
298
|
+
merged_field = stub('merged field', :ruby_type => {:type => String})
|
299
|
+
object_1.stubs(:merge).with(object_2).returns(merged_field)
|
300
|
+
exp = Linkage::Expectations::Dual.new(object_1, object_2, :==)
|
301
|
+
assert exp.decollation_needed?
|
302
|
+
end
|
303
|
+
end
|