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.
Files changed (66) hide show
  1. data/.gitignore +10 -0
  2. data/Gemfile +15 -13
  3. data/Gemfile.lock +67 -37
  4. data/Guardfile +0 -2
  5. data/Rakefile +122 -25
  6. data/lib/linkage/comparator.rb +172 -0
  7. data/lib/linkage/comparators/binary.rb +12 -0
  8. data/lib/linkage/comparators/compare.rb +46 -0
  9. data/lib/linkage/comparators/within.rb +32 -0
  10. data/lib/linkage/configuration.rb +285 -153
  11. data/lib/linkage/data.rb +32 -7
  12. data/lib/linkage/dataset.rb +107 -32
  13. data/lib/linkage/decollation.rb +93 -0
  14. data/lib/linkage/expectation.rb +21 -0
  15. data/lib/linkage/expectations/exhaustive.rb +63 -0
  16. data/lib/linkage/expectations/simple.rb +168 -0
  17. data/lib/linkage/field.rb +30 -4
  18. data/lib/linkage/field_set.rb +6 -3
  19. data/lib/linkage/function.rb +50 -3
  20. data/lib/linkage/functions/binary.rb +30 -0
  21. data/lib/linkage/functions/cast.rb +54 -0
  22. data/lib/linkage/functions/length.rb +29 -0
  23. data/lib/linkage/functions/strftime.rb +12 -11
  24. data/lib/linkage/functions/trim.rb +8 -0
  25. data/lib/linkage/group.rb +20 -0
  26. data/lib/linkage/import_buffer.rb +5 -16
  27. data/lib/linkage/meta_object.rb +139 -0
  28. data/lib/linkage/result_set.rb +74 -17
  29. data/lib/linkage/runner/single_threaded.rb +125 -10
  30. data/lib/linkage/version.rb +3 -0
  31. data/lib/linkage.rb +11 -0
  32. data/linkage.gemspec +16 -121
  33. data/test/config.yml +5 -0
  34. data/test/helper.rb +73 -8
  35. data/test/integration/test_collation.rb +45 -0
  36. data/test/integration/test_configuration.rb +268 -0
  37. data/test/integration/test_cross_linkage.rb +4 -17
  38. data/test/integration/test_dataset.rb +45 -2
  39. data/test/integration/test_dual_linkage.rb +40 -24
  40. data/test/integration/test_functions.rb +22 -0
  41. data/test/integration/test_result_set.rb +85 -0
  42. data/test/integration/test_scoring.rb +84 -0
  43. data/test/integration/test_self_linkage.rb +5 -0
  44. data/test/integration/test_within_comparator.rb +100 -0
  45. data/test/unit/comparators/test_compare.rb +105 -0
  46. data/test/unit/comparators/test_within.rb +57 -0
  47. data/test/unit/expectations/test_exhaustive.rb +111 -0
  48. data/test/unit/expectations/test_simple.rb +303 -0
  49. data/test/unit/functions/test_binary.rb +54 -0
  50. data/test/unit/functions/test_cast.rb +98 -0
  51. data/test/unit/functions/test_length.rb +52 -0
  52. data/test/unit/functions/test_strftime.rb +17 -13
  53. data/test/unit/functions/test_trim.rb +11 -4
  54. data/test/unit/test_comparator.rb +124 -0
  55. data/test/unit/test_configuration.rb +137 -175
  56. data/test/unit/test_data.rb +44 -0
  57. data/test/unit/test_dataset.rb +73 -21
  58. data/test/unit/test_decollation.rb +201 -0
  59. data/test/unit/test_field.rb +38 -14
  60. data/test/unit/test_field_set.rb +12 -8
  61. data/test/unit/test_function.rb +83 -16
  62. data/test/unit/test_group.rb +28 -0
  63. data/test/unit/test_import_buffer.rb +13 -27
  64. data/test/unit/test_meta_object.rb +208 -0
  65. data/test/unit/test_result_set.rb +221 -3
  66. metadata +82 -190
@@ -0,0 +1,54 @@
1
+ require 'helper'
2
+
3
+ class UnitTests::TestBinary < Test::Unit::TestCase
4
+ def self.const_missing(name)
5
+ if Linkage::Functions.const_defined?(name)
6
+ Linkage::Functions.const_get(name)
7
+ else
8
+ super
9
+ end
10
+ end
11
+
12
+ test "subclass of Function" do
13
+ assert_equal Linkage::Function, Linkage::Functions::Binary.superclass
14
+ end
15
+
16
+ test "ruby_type" do
17
+ expected = {:type => File}
18
+ assert_equal(expected, Linkage::Functions::Binary.new("foo", :dataset => stub('dataset')).ruby_type)
19
+ field = stub_field('field 1', :name => :bar, :ruby_type => {:type => String}, :dataset => stub('dataset'))
20
+ assert_equal(expected, Linkage::Functions::Binary.new(field).ruby_type)
21
+ end
22
+
23
+ test "parameters" do
24
+ assert_equal [[String]], Linkage::Functions::Binary.parameters
25
+ end
26
+
27
+ test "name" do
28
+ assert_equal "binary", Linkage::Functions::Binary.function_name
29
+ end
30
+
31
+ test "registers itself" do
32
+ assert_equal Linkage::Function["binary"], Linkage::Functions::Binary
33
+ end
34
+
35
+ test "requires dataset" do
36
+ func = Binary.new("foo")
37
+ assert_raises(RuntimeError) { func.to_expr }
38
+ end
39
+
40
+ test "to_expr for sqlite" do
41
+ func = Binary.new("foo", :dataset => stub('dataset', :database_type => :sqlite))
42
+ assert_equal "foo".cast(:blob), func.to_expr
43
+ end
44
+
45
+ test "to_expr for mysql" do
46
+ func = Binary.new("foo", :dataset => stub('dataset', :database_type => :mysql))
47
+ assert_equal "foo".cast(:binary), func.to_expr
48
+ end
49
+
50
+ test "to_expr for postgresql" do
51
+ func = Binary.new("foo", :dataset => stub('dataset', :database_type => :postgres))
52
+ assert_equal "foo".cast(:bytea), func.to_expr
53
+ end
54
+ end
@@ -0,0 +1,98 @@
1
+ require 'helper'
2
+
3
+ class UnitTests::TestCast < Test::Unit::TestCase
4
+ def self.const_missing(name)
5
+ if Linkage::Functions.const_defined?(name)
6
+ Linkage::Functions.const_get(name)
7
+ else
8
+ super
9
+ end
10
+ end
11
+
12
+ test "subclass of Function" do
13
+ assert_equal Linkage::Function, Linkage::Functions::Cast.superclass
14
+ end
15
+
16
+ test "parameters" do
17
+ assert_equal [[:any], [String]], Linkage::Functions::Cast.parameters
18
+ end
19
+
20
+ test "name" do
21
+ assert_equal "cast", Linkage::Functions::Cast.function_name
22
+ end
23
+
24
+ test "ruby_type when casting to (signed) integer" do
25
+ expected = {:type => Fixnum}
26
+ assert_equal(expected, Linkage::Functions::Cast.new('123', 'integer', :dataset => stub('dataset')).ruby_type)
27
+ field = stub_field('field 1', :name => :bar, :ruby_type => {:type => String}, :dataset => stub('dataset'))
28
+ assert_equal(expected, Linkage::Functions::Cast.new(field, 'integer').ruby_type)
29
+ end
30
+
31
+ test "ruby_type when casting to binary" do
32
+ expected = {:type => File}
33
+ assert_equal(expected, Linkage::Functions::Cast.new('123', 'binary', :dataset => stub('dataset')).ruby_type)
34
+ field = stub_field('field 1', :name => :bar, :ruby_type => {:type => String}, :dataset => stub('dataset'))
35
+ assert_equal(expected, Linkage::Functions::Cast.new(field, 'binary').ruby_type)
36
+ end
37
+
38
+ test "registers itself" do
39
+ assert_equal Linkage::Function["cast"], Linkage::Functions::Cast
40
+ end
41
+
42
+ test "to_expr for integer (sqlite)" do
43
+ func = Cast.new('foo', 'integer', :dataset => stub('dataset', :database_type => :sqlite))
44
+ assert_equal 'foo'.cast(:integer), func.to_expr
45
+ end
46
+
47
+ test "to_expr for integer (mysql)" do
48
+ func = Cast.new('foo', 'integer', :dataset => stub('dataset', :database_type => :mysql))
49
+ assert_equal 'foo'.cast(:signed), func.to_expr
50
+ end
51
+
52
+ test "to_expr for integer (postgres)" do
53
+ func = Cast.new('foo', 'integer', :dataset => stub('dataset', :database_type => :postgres))
54
+ assert_equal 'foo'.cast(:integer), func.to_expr
55
+ end
56
+
57
+ test "to_expr for integer (h2)" do
58
+ func = Cast.new('foo', 'integer', :dataset => stub('dataset', :database_type => :h2))
59
+ assert_equal 'foo'.cast(:integer), func.to_expr
60
+ end
61
+
62
+ test "to_expr for binary (sqlite)" do
63
+ func = Cast.new('foo', 'binary', :dataset => stub('dataset', :database_type => :sqlite))
64
+ assert_equal 'foo'.cast(:blob), func.to_expr
65
+ end
66
+
67
+ test "to_expr for binary (mysql)" do
68
+ func = Cast.new('foo', 'binary', :dataset => stub('dataset', :database_type => :mysql))
69
+ assert_equal 'foo'.cast(:binary), func.to_expr
70
+ end
71
+
72
+ test "to_expr for binary (postgres)" do
73
+ func = Cast.new('foo', 'binary', :dataset => stub('dataset', :database_type => :postgres))
74
+ assert_equal 'foo'.cast(:bytea), func.to_expr
75
+ end
76
+
77
+ test "to_expr for binary (h2)" do
78
+ func = Cast.new('foo', 'binary', :dataset => stub('dataset', :database_type => :h2))
79
+ assert_equal 'foo'.cast(:binary), func.to_expr
80
+ end
81
+
82
+ =begin
83
+ test "to_expr for sqlite" do
84
+ func = Cast.new("foo", :dataset => stub('dataset', :database_type => :sqlite))
85
+ assert_equal "foo".cast(:blob), func.to_expr
86
+ end
87
+
88
+ test "to_expr for mysql" do
89
+ func = Cast.new("foo", :dataset => stub('dataset', :database_type => :mysql))
90
+ assert_equal "foo".cast(:binary), func.to_expr
91
+ end
92
+
93
+ test "to_expr for postgresql" do
94
+ func = Cast.new("foo", :dataset => stub('dataset', :database_type => :postgres))
95
+ assert_equal "foo".cast(:bytea), func.to_expr
96
+ end
97
+ =end
98
+ end
@@ -0,0 +1,52 @@
1
+ require 'helper'
2
+
3
+ class UnitTests::TestLength < Test::Unit::TestCase
4
+ test "subclass of Function" do
5
+ assert_equal Linkage::Function, Linkage::Functions::Length.superclass
6
+ end
7
+
8
+ test "ruby_type for string literal" do
9
+ length = Linkage::Functions::Length.new("foo", :dataset => stub('dataset'))
10
+ assert_equal({:type => Fixnum}, length.ruby_type)
11
+ end
12
+
13
+ test "ruby_type for string field" do
14
+ field_1 = stub_field('field 1', :name => :bar, :ruby_type => {:type => String}, :dataset => stub('dataset'))
15
+ assert_equal({:type => Fixnum}, Linkage::Functions::Length.new(field_1).ruby_type)
16
+
17
+ field_2 = stub_field('field 2', :name => :bar, :ruby_type => {:type => String, :opts => {:size => 123}}, :dataset => stub('dataset'))
18
+ assert_equal({:type => Fixnum}, Linkage::Functions::Length.new(field_2).ruby_type)
19
+ end
20
+
21
+ test "ruby_type for string function" do
22
+ func = new_function('foo', {:type => String, :opts => {:junk => '123'}})
23
+ assert_equal({:type => Fixnum}, Linkage::Functions::Length.new(func.new(:dataset => stub('dataset'))).ruby_type)
24
+ end
25
+
26
+ test "parameters" do
27
+ assert_equal [[String]], Linkage::Functions::Length.parameters
28
+ end
29
+
30
+ test "name" do
31
+ assert_equal "length", Linkage::Functions::Length.function_name
32
+ end
33
+
34
+ test "to_expr for sqlite" do
35
+ func = Linkage::Functions::Length.new("foo bar", :dataset => stub('dataset', :database_type => :sqlite))
36
+ assert_equal :length.sql_function("foo bar"), func.to_expr
37
+ end
38
+
39
+ test "to_expr for mysql" do
40
+ func = Linkage::Functions::Length.new("foo bar", :dataset => stub('dataset', :database_type => :mysql))
41
+ assert_equal :char_length.sql_function("foo bar"), func.to_expr
42
+ end
43
+
44
+ test "to_expr for postgresql" do
45
+ func = Linkage::Functions::Length.new("foo bar", :dataset => stub('dataset', :database_type => :postgres))
46
+ assert_equal :char_length.sql_function("foo bar"), func.to_expr
47
+ end
48
+
49
+ test "registers itself" do
50
+ assert_equal Linkage::Function["length"], Linkage::Functions::Length
51
+ end
52
+ end
@@ -16,11 +16,11 @@ class UnitTests::TestStrftime < Test::Unit::TestCase
16
16
  test "ruby_type" do
17
17
  expected = {:type => String}
18
18
  format = "%Y-%m-%d"
19
- assert_equal(expected, Linkage::Functions::Strftime.new(Time.now, format).ruby_type)
19
+ assert_equal(expected, Linkage::Functions::Strftime.new(Time.now, format, :dataset => stub('dataset')).ruby_type)
20
20
  field = stub_field('field 1', :name => :bar, :ruby_type => {:type => Time})
21
- assert_equal(expected, Linkage::Functions::Strftime.new(field, format).ruby_type)
21
+ assert_equal(expected, Linkage::Functions::Strftime.new(field, format, :dataset => stub('dataset')).ruby_type)
22
22
  func = new_function('foo', {:type => Time, :opts => {:junk => '123'}})
23
- assert_equal(expected, Linkage::Functions::Strftime.new(func.new, format).ruby_type)
23
+ assert_equal(expected, Linkage::Functions::Strftime.new(func.new(:dataset => stub('dataset')), format).ruby_type)
24
24
  end
25
25
 
26
26
  test "parameters" do
@@ -35,22 +35,26 @@ class UnitTests::TestStrftime < Test::Unit::TestCase
35
35
  assert_equal Linkage::Function["strftime"], Linkage::Functions::Strftime
36
36
  end
37
37
 
38
+ test "requires dataset" do
39
+ func = Strftime.new(Time.now, "%Y-%m-%d")
40
+ assert_raises(RuntimeError) { func.to_expr }
41
+ end
42
+
38
43
  test "to_expr for sqlite" do
39
- args = [Time.now, "%Y-%m-%d"]
40
- func = Strftime.new(*args)
41
- assert_equal :strftime.sql_function(args[1], args[0]), func.to_expr(:sqlite)
44
+ now = Time.now
45
+ func = Strftime.new(now, "%Y-%m-%d", :dataset => stub('dataset', :database_type => :sqlite))
46
+ assert_equal :strftime.sql_function("%Y-%m-%d", now), func.to_expr
42
47
  end
43
48
 
44
49
  test "to_expr for mysql" do
45
- args = [Time.now, "%Y-%m-%d"]
46
- func = Strftime.new(*args)
47
- assert_equal :date_format.sql_function(*args), func.to_expr(:mysql)
48
- assert_equal :date_format.sql_function(*args), func.to_expr(:mysql2)
50
+ now = Time.now
51
+ func = Strftime.new(now, "%Y-%m-%d", :dataset => stub('dataset', :database_type => :mysql))
52
+ assert_equal :date_format.sql_function(now, "%Y-%m-%d"), func.to_expr
49
53
  end
50
54
 
51
55
  test "to_expr for postgresql" do
52
- args = [Time.now, "%Y-%m-%d"]
53
- func = Strftime.new(*args)
54
- assert_equal :to_char.sql_function(*args), func.to_expr(:postgres)
56
+ now = Time.now
57
+ func = Strftime.new(now, "%Y-%m-%d", :dataset => stub('dataset', :database_type => :postgres))
58
+ assert_equal :to_char.sql_function(now, "%Y-%m-%d"), func.to_expr
55
59
  end
56
60
  end
@@ -6,20 +6,21 @@ class UnitTests::TestTrim < Test::Unit::TestCase
6
6
  end
7
7
 
8
8
  test "ruby_type for string literal" do
9
- assert_equal({:type => String}, Linkage::Functions::Trim.new("foo").ruby_type)
9
+ trim = Linkage::Functions::Trim.new("foo", :dataset => stub('dataset'))
10
+ assert_equal({:type => String}, trim.ruby_type)
10
11
  end
11
12
 
12
13
  test "ruby_type for string field" do
13
- field_1 = stub_field('field 1', :name => :bar, :ruby_type => {:type => String})
14
+ field_1 = stub_field('field 1', :name => :bar, :ruby_type => {:type => String}, :dataset => stub('dataset'))
14
15
  assert_equal({:type => String}, Linkage::Functions::Trim.new(field_1).ruby_type)
15
16
 
16
- field_2 = stub_field('field 2', :name => :bar, :ruby_type => {:type => String, :opts => {:size => 123}})
17
+ field_2 = stub_field('field 2', :name => :bar, :ruby_type => {:type => String, :opts => {:size => 123}}, :dataset => stub('dataset'))
17
18
  assert_equal({:type => String, :opts => {:size => 123}}, Linkage::Functions::Trim.new(field_2).ruby_type)
18
19
  end
19
20
 
20
21
  test "ruby_type for string function" do
21
22
  func = new_function('foo', {:type => String, :opts => {:junk => '123'}})
22
- assert_equal({:type => String, :opts => {:junk => '123'}}, Linkage::Functions::Trim.new(func.new).ruby_type)
23
+ assert_equal({:type => String, :opts => {:junk => '123'}}, Linkage::Functions::Trim.new(func.new(:dataset => stub('dataset'))).ruby_type)
23
24
  end
24
25
 
25
26
  test "parameters" do
@@ -33,4 +34,10 @@ class UnitTests::TestTrim < Test::Unit::TestCase
33
34
  test "registers itself" do
34
35
  assert_equal Linkage::Function["trim"], Linkage::Functions::Trim
35
36
  end
37
+
38
+ test "collation returns argument collation if it exists" do
39
+ field_1 = stub_field('field 1', :name => :bar, :ruby_type => {:type => String}, :collation => 'foo', :dataset => stub('dataset'))
40
+ trim = Linkage::Functions::Trim.new(field_1)
41
+ assert_equal 'foo', trim.collation
42
+ end
36
43
  end
@@ -0,0 +1,124 @@
1
+ require 'helper'
2
+
3
+ class UnitTests::TestComparator < Test::Unit::TestCase
4
+ def setup
5
+ super
6
+ @_comparators = Linkage::Comparator.instance_variable_get("@comparators")
7
+ end
8
+
9
+ def teardown
10
+ Linkage::Comparator.instance_variable_set("@comparators", @_comparators)
11
+ super
12
+ end
13
+
14
+ test "comparator_name raises error in base class" do
15
+ assert_raises(NotImplementedError) { Linkage::Comparator.comparator_name }
16
+ end
17
+
18
+ test "registering subclass requires comparator_name" do
19
+ klass = Class.new(Linkage::Comparator)
20
+ assert_raises(ArgumentError) { Linkage::Comparator.register(klass) }
21
+ end
22
+
23
+ test "getting a registered subclass" do
24
+ klass = new_comparator('foo', [[String]], 0..1)
25
+ Linkage::Comparator.register(klass)
26
+ assert_equal klass, Linkage::Comparator['foo']
27
+ end
28
+
29
+ test "parameters raises error in base class" do
30
+ assert_raises(NotImplementedError) { Linkage::Comparator.parameters }
31
+ end
32
+
33
+ test "subclasses required to define parameters class method" do
34
+ klass = new_comparator('foo')
35
+ assert_raises(ArgumentError) { Linkage::Comparator.register(klass) }
36
+ end
37
+
38
+ test "subclasses required to define at least one parameter" do
39
+ klass = new_comparator('foo', [])
40
+ assert_raises(ArgumentError) { Linkage::Comparator.register(klass) }
41
+ end
42
+
43
+ test "subclasses required to define score_range class method" do
44
+ klass = new_comparator('foo', [[String]])
45
+ assert_raises(ArgumentError) { Linkage::Comparator.register(klass) }
46
+ end
47
+
48
+ test "score_range class should be a Range of two numbers" do
49
+ klass = new_comparator('foo', [[String]], "foo".."bar")
50
+ assert_raises(ArgumentError) { Linkage::Comparator.register(klass) }
51
+ end
52
+
53
+ test "subclasses required to define score method" do
54
+ klass = new_comparator('foo', [[String]]) do
55
+ remove_method :score
56
+ end
57
+ assert_raises(ArgumentError) { Linkage::Comparator.register(klass) }
58
+ end
59
+
60
+ test "comparator with one valid argument" do
61
+ klass = new_comparator('foo', [[String]])
62
+ meta_object = stub('meta object', :side => :lhs, :ruby_type => { :type => String }, :static? => false)
63
+ f = klass.new(meta_object)
64
+ end
65
+
66
+ test "comparator with one invalid argument" do
67
+ klass = new_comparator('foo', [[String]])
68
+ meta_object = stub('meta_object', :ruby_type => { :type => Fixnum }, :static? => false)
69
+ assert_raises(TypeError) { klass.new(meta_object) }
70
+ end
71
+
72
+ test "comparator with too few arguments" do
73
+ klass = new_comparator('foo', [[String]])
74
+ assert_raises(ArgumentError) { klass.new }
75
+ end
76
+
77
+ test "comparator with too many arguments" do
78
+ klass = new_comparator('foo', [[String]])
79
+ meta_object = stub('meta_object', :ruby_type => { :type => String }, :static? => false)
80
+ assert_raises(ArgumentError) { klass.new(meta_object, meta_object) }
81
+ end
82
+
83
+ test "requiring argument to be non-static" do
84
+ klass = new_comparator('foo', [[String, :static => false]])
85
+ meta_object = stub('meta_object', :ruby_type => { :type => String }, :static? => true)
86
+ assert_raise_message("argument 1 was expected to not be static") do
87
+ klass.new(meta_object)
88
+ end
89
+ end
90
+
91
+ test "requiring argument to be static" do
92
+ klass = new_comparator('foo', [[String, :static => true]])
93
+ meta_object = stub('meta_object', :ruby_type => { :type => String }, :static? => false)
94
+ assert_raise_message("argument 1 was expected to be static") do
95
+ klass.new(meta_object)
96
+ end
97
+ end
98
+
99
+ test "special :any parameter" do
100
+ klass = new_comparator('foo', [[:any]])
101
+ meta_object_1 = stub('meta_object', :side => :lhs, :ruby_type => { :type => String }, :static? => false)
102
+ meta_object_2 = stub('meta_object', :side => :rhs, :ruby_type => { :type => Fixnum }, :static? => false)
103
+ assert_nothing_raised do
104
+ klass.new(meta_object_1)
105
+ klass.new(meta_object_2)
106
+ end
107
+ end
108
+
109
+ test "lhs_args" do
110
+ klass = new_comparator('foo', [[String], [String]])
111
+ meta_object_1 = stub('meta object 1', :side => :lhs, :ruby_type => { :type => String }, :static? => false)
112
+ meta_object_2 = stub('meta object 2', :side => :rhs, :ruby_type => { :type => String }, :static? => false)
113
+ obj = klass.new(meta_object_1, meta_object_2)
114
+ assert_equal [meta_object_1], obj.lhs_args
115
+ end
116
+
117
+ test "rhs_args" do
118
+ klass = new_comparator('foo', [[String], [String]])
119
+ meta_object_1 = stub('meta object 1', :side => :lhs, :ruby_type => { :type => String }, :static? => false)
120
+ meta_object_2 = stub('meta object 2', :side => :rhs, :ruby_type => { :type => String }, :static? => false)
121
+ obj = klass.new(meta_object_1, meta_object_2)
122
+ assert_equal [meta_object_2], obj.rhs_args
123
+ end
124
+ end