finitio 0.7.0 → 0.8.0
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.
- checksums.yaml +5 -5
- data/CHANGELOG.md +10 -0
- data/Gemfile +1 -1
- data/Gemfile.lock +40 -41
- data/lib/finitio/generation.rb +106 -0
- data/lib/finitio/generation/ad_type.rb +10 -0
- data/lib/finitio/generation/alias_type.rb +9 -0
- data/lib/finitio/generation/any_type.rb +11 -0
- data/lib/finitio/generation/builtin_type.rb +9 -0
- data/lib/finitio/generation/hash_based_type.rb +15 -0
- data/lib/finitio/generation/heuristic.rb +8 -0
- data/lib/finitio/generation/heuristic/constant.rb +30 -0
- data/lib/finitio/generation/heuristic/random.rb +52 -0
- data/lib/finitio/generation/rel_based_type.rb +13 -0
- data/lib/finitio/generation/seq_type.rb +13 -0
- data/lib/finitio/generation/set_type.rb +13 -0
- data/lib/finitio/generation/sub_type.rb +9 -0
- data/lib/finitio/generation/union_type.rb +10 -0
- data/lib/finitio/inference.rb +51 -0
- data/lib/finitio/support.rb +18 -0
- data/lib/finitio/support/attribute.rb +8 -0
- data/lib/finitio/support/compilation.rb +18 -18
- data/lib/finitio/support/contract.rb +8 -0
- data/lib/finitio/support/fetch_scope.rb +19 -0
- data/lib/finitio/support/heading.rb +36 -1
- data/lib/finitio/syntax.rb +1 -1
- data/lib/finitio/syntax/lexer.citrus +1 -1
- data/lib/finitio/syntax/type.rb +2 -0
- data/lib/finitio/syntax/type/high_order_type_instantiation.rb +29 -0
- data/lib/finitio/syntax/type/high_order_vars.rb +16 -0
- data/lib/finitio/syntax/type/type_def.rb +11 -1
- data/lib/finitio/syntax/types.citrus +14 -1
- data/lib/finitio/system.rb +11 -1
- data/lib/finitio/type.rb +19 -0
- data/lib/finitio/type/ad_type.rb +8 -0
- data/lib/finitio/type/alias_type.rb +8 -0
- data/lib/finitio/type/any_type.rb +12 -0
- data/lib/finitio/type/builtin_type.rb +4 -0
- data/lib/finitio/type/collection_type.rb +15 -0
- data/lib/finitio/type/heading_based_type.rb +17 -0
- data/lib/finitio/type/high_order_type.rb +39 -0
- data/lib/finitio/type/multi_relation_type.rb +4 -0
- data/lib/finitio/type/multi_tuple_type.rb +4 -0
- data/lib/finitio/type/proxy_type.rb +10 -20
- data/lib/finitio/type/relation_type.rb +4 -0
- data/lib/finitio/type/seq_type.rb +1 -1
- data/lib/finitio/type/struct_type.rb +8 -0
- data/lib/finitio/type/sub_type.rb +8 -0
- data/lib/finitio/type/tuple_type.rb +4 -0
- data/lib/finitio/type/union_type.rb +19 -0
- data/lib/finitio/version.rb +1 -1
- data/spec/generation/test_generation.rb +169 -0
- data/spec/heading/test_looks_similar.rb +45 -0
- data/spec/heading/test_suppremum.rb +56 -0
- data/spec/inference/test_inference.rb +42 -0
- data/spec/spec_helper.rb +31 -6
- data/spec/support/test_compare_attrs.rb +67 -0
- data/spec/syntax/test_compile.rb +57 -0
- data/spec/type/ad_type/test_initialize.rb +1 -8
- data/spec/type/relation_type/test_suppremum.rb +104 -0
- data/spec/type/seq_type/test_suppremum.rb +54 -0
- data/spec/type/set_type/test_suppremum.rb +54 -0
- data/spec/type/test_suppremum.rb +49 -0
- data/spec/type/test_unconstrained.rb +150 -0
- data/spec/type/tuple_type/test_suppremum.rb +119 -0
- data/spec/type/union_type/test_suppremum.rb +51 -0
- data/tasks/test.rake +1 -1
- metadata +183 -144
- data/spec/type/proxy_type/test_delegation.rb +0 -37
- data/spec/type/proxy_type/test_resolve.rb +0 -29
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
module Finitio
|
3
|
+
describe Heading, "looks_similar?" do
|
4
|
+
|
5
|
+
let(:heading){
|
6
|
+
Heading.new([Attribute.new(:a, intType),
|
7
|
+
Attribute.new(:b, stringType)])
|
8
|
+
}
|
9
|
+
|
10
|
+
subject{
|
11
|
+
heading.looks_similar?(h2)
|
12
|
+
}
|
13
|
+
|
14
|
+
context 'when equal' do
|
15
|
+
let(:h2){ heading }
|
16
|
+
|
17
|
+
it 'says yes' do
|
18
|
+
expect(subject).to be_truthy
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
context 'when shared attributes are in majority' do
|
23
|
+
let(:h2){
|
24
|
+
Heading.new([Attribute.new(:a, intType),
|
25
|
+
Attribute.new(:c, stringType)])
|
26
|
+
}
|
27
|
+
|
28
|
+
it 'says yes' do
|
29
|
+
expect(subject).to be_truthy
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
context 'when shared attributes are in minority' do
|
34
|
+
let(:h2){
|
35
|
+
Heading.new([Attribute.new(:d, intType),
|
36
|
+
Attribute.new(:c, stringType)])
|
37
|
+
}
|
38
|
+
|
39
|
+
it 'says no' do
|
40
|
+
expect(subject).to be_falsy
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
module Finitio
|
3
|
+
describe Heading, "suppremum" do
|
4
|
+
|
5
|
+
subject{
|
6
|
+
left.suppremum(right)
|
7
|
+
}
|
8
|
+
|
9
|
+
let(:left){
|
10
|
+
Heading.new([Attribute.new(:a, intType),
|
11
|
+
Attribute.new(:b, stringType)])
|
12
|
+
}
|
13
|
+
|
14
|
+
context 'when both are equal' do
|
15
|
+
let(:right){
|
16
|
+
Heading.new([Attribute.new(:a, intType),
|
17
|
+
Attribute.new(:b, stringType)])
|
18
|
+
}
|
19
|
+
|
20
|
+
it 'works' do
|
21
|
+
expect(subject).to be(left)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
context 'when they are different' do
|
26
|
+
let(:right){
|
27
|
+
Heading.new([Attribute.new(:a, nilType),
|
28
|
+
Attribute.new(:b, stringType)])
|
29
|
+
}
|
30
|
+
|
31
|
+
it 'works' do
|
32
|
+
expect(subject).to be_a(Heading)
|
33
|
+
expect(subject[:a].type).to eql(UnionType.new [intType, nilType])
|
34
|
+
expect(subject[:b].type).to eql(stringType)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
context 'when they are different II' do
|
39
|
+
let(:right){
|
40
|
+
Heading.new([Attribute.new(:c, nilType),
|
41
|
+
Attribute.new(:b, stringType)])
|
42
|
+
}
|
43
|
+
|
44
|
+
it 'works' do
|
45
|
+
expect(subject).to be_a(Heading)
|
46
|
+
expect(subject[:a].type).to eql(intType)
|
47
|
+
expect(subject[:a].required).to eql(false)
|
48
|
+
expect(subject[:b].type).to eql(stringType)
|
49
|
+
expect(subject[:b].required).to eql(true)
|
50
|
+
expect(subject[:c].type).to eql(nilType)
|
51
|
+
expect(subject[:c].required).to eql(false)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'finitio/inference'
|
3
|
+
module Finitio
|
4
|
+
describe Inference do
|
5
|
+
|
6
|
+
let(:system) {
|
7
|
+
Finitio.system <<-FIO
|
8
|
+
@import finitio/data
|
9
|
+
|
10
|
+
Nil = .NilClass
|
11
|
+
Boolean = .TrueClass|.FalseClass
|
12
|
+
Integer = .Integer
|
13
|
+
Date = .Date <iso8601> .String \\( s | Date.iso8601(s) )
|
14
|
+
\\( d | d.iso8601 )
|
15
|
+
String = .String
|
16
|
+
FIO
|
17
|
+
}
|
18
|
+
|
19
|
+
let(:input) {
|
20
|
+
[
|
21
|
+
{ "id" => 1, "createdAt" => "2018-01-12", "size" => "15", "priority" => "XL", "meta" => { foo: true, bar: "foo" }, "hobbies" => [] },
|
22
|
+
{ "id" => 2, "createdAt" => "2019-02-23", "size" => "1", "priority" => "L", "meta" => { foo: true, bar: "baz" }, "hobbies" => ["testing"] },
|
23
|
+
{ "id" => 3, "createdAt" => "2018-07-15", "size" => "7", "priority" => "S", "meta" => { foo: true, bar: "bar" } },
|
24
|
+
{ "id" => 4, "createdAt" => "2019-12-12", "size" => "9", "priority" => "M", "meta" => { foo: true, baz: "baz" } },
|
25
|
+
{ "id" => 4, "createdAt" => nil, "size" => "9", "priority" => "M" },
|
26
|
+
]
|
27
|
+
}
|
28
|
+
|
29
|
+
it 'works as expected' do
|
30
|
+
result = Inference.new(system).call(input)
|
31
|
+
expect(result).to be_a(SeqType)
|
32
|
+
expect(result.elm_type).to be_a(MultiTupleType)
|
33
|
+
expect(result.elm_type[:id].type.name).to eql("Integer")
|
34
|
+
expect(result.elm_type[:createdAt].type.name).to eql("Date|Nil")
|
35
|
+
expect(result.elm_type[:size].type.name).to eql("String")
|
36
|
+
expect(result.elm_type[:priority].type.name).to eql("String")
|
37
|
+
|
38
|
+
puts result
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -2,6 +2,7 @@ $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
|
|
2
2
|
require 'path'
|
3
3
|
require 'finitio'
|
4
4
|
require 'finitio/syntax'
|
5
|
+
require 'finitio/generation'
|
5
6
|
|
6
7
|
require 'coveralls'
|
7
8
|
Coveralls.wear!
|
@@ -49,15 +50,27 @@ module SpecHelpers
|
|
49
50
|
end
|
50
51
|
|
51
52
|
def intType
|
52
|
-
Finitio::BuiltinType.new(Integer, "intType")
|
53
|
+
@intType ||= Finitio::BuiltinType.new(Integer, "intType")
|
53
54
|
end
|
54
55
|
|
55
56
|
def floatType
|
56
|
-
Finitio::BuiltinType.new(Float, "floatType")
|
57
|
+
@floatType ||= Finitio::BuiltinType.new(Float, "floatType")
|
57
58
|
end
|
58
59
|
|
59
60
|
def nilType
|
60
|
-
Finitio::BuiltinType.new(NilClass, "nilType")
|
61
|
+
@nilType ||= Finitio::BuiltinType.new(NilClass, "nilType")
|
62
|
+
end
|
63
|
+
|
64
|
+
def trueType
|
65
|
+
@trueType ||= Finitio::BuiltinType.new(TrueClass, "trueType")
|
66
|
+
end
|
67
|
+
|
68
|
+
def falseType
|
69
|
+
@falseType ||= Finitio::BuiltinType.new(FalseClass, "falseType")
|
70
|
+
end
|
71
|
+
|
72
|
+
def stringType
|
73
|
+
@stringType ||= Finitio::BuiltinType.new(String, "stringType")
|
61
74
|
end
|
62
75
|
|
63
76
|
def byte_full
|
@@ -81,15 +94,19 @@ module SpecHelpers
|
|
81
94
|
end
|
82
95
|
|
83
96
|
def byte
|
84
|
-
Finitio::SubType.new(intType, [byte_full])
|
97
|
+
@byte ||= Finitio::SubType.new(intType, [byte_full])
|
98
|
+
end
|
99
|
+
|
100
|
+
def pos_byte
|
101
|
+
@pos_byte ||= Finitio::SubType.new(byte, [positive])
|
85
102
|
end
|
86
103
|
|
87
104
|
def posInt
|
88
|
-
Finitio::SubType.new(intType, [positive])
|
105
|
+
@posInt ||= Finitio::SubType.new(intType, [positive])
|
89
106
|
end
|
90
107
|
|
91
108
|
def negInt
|
92
|
-
Finitio::SubType.new(intType, [negative])
|
109
|
+
@negInt ||= Finitio::SubType.new(intType, [negative])
|
93
110
|
end
|
94
111
|
|
95
112
|
def type_factory
|
@@ -104,6 +121,14 @@ module SpecHelpers
|
|
104
121
|
Color.new(138, 43, 226)
|
105
122
|
end
|
106
123
|
|
124
|
+
def rgb_contract
|
125
|
+
@rgb_contract ||= Finitio::Contract.new(byte, Color.method(:rgb), Finitio::IDENTITY, :rgb)
|
126
|
+
end
|
127
|
+
|
128
|
+
def hex_contract
|
129
|
+
@hex_contract ||= Finitio::Contract.new(floatType, Color.method(:hex), Finitio::IDENTITY, :hex)
|
130
|
+
end
|
131
|
+
|
107
132
|
end
|
108
133
|
|
109
134
|
RSpec.configure do |c|
|
@@ -0,0 +1,67 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
module Finitio
|
3
|
+
describe Support, "compare_attrs" do
|
4
|
+
include Support
|
5
|
+
|
6
|
+
context 'with arrays' do
|
7
|
+
it 'works on same attrs' do
|
8
|
+
h1 = [:a, :b]
|
9
|
+
h2 = [:b, :a]
|
10
|
+
shared, mine, yours = compare_attrs(h1, h2)
|
11
|
+
expect(shared).to eql([:a, :b])
|
12
|
+
expect(mine).to eql([])
|
13
|
+
expect(yours).to eql([])
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'works on not same attrs' do
|
17
|
+
h1 = [ :a, :b ]
|
18
|
+
h2 = [ :c, :a ]
|
19
|
+
shared, mine, yours = compare_attrs(h1, h2)
|
20
|
+
expect(shared).to eql([:a])
|
21
|
+
expect(mine).to eql([:b])
|
22
|
+
expect(yours).to eql([:c])
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
context 'with hashes' do
|
27
|
+
it 'works on same attrs' do
|
28
|
+
h1 = { a: 1, b: 2 }
|
29
|
+
h2 = { a: 1, b: 2 }
|
30
|
+
shared, mine, yours = compare_attrs(h1, h2)
|
31
|
+
expect(shared).to eql([:a, :b])
|
32
|
+
expect(mine).to eql([])
|
33
|
+
expect(yours).to eql([])
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'works on not same attrs' do
|
37
|
+
h1 = { a: 1, b: 2 }
|
38
|
+
h2 = { a: 1, c: 2 }
|
39
|
+
shared, mine, yours = compare_attrs(h1, h2)
|
40
|
+
expect(shared).to eql([:a])
|
41
|
+
expect(mine).to eql([:b])
|
42
|
+
expect(yours).to eql([:c])
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
context 'with a block' do
|
47
|
+
it 'works on same attrs' do
|
48
|
+
h1 = [{:name => :a}, {:name => :b}]
|
49
|
+
h2 = [{:name => :b}, {:name => :a}]
|
50
|
+
shared, mine, yours = compare_attrs(h1, h2){|a| a[:name] }
|
51
|
+
expect(shared).to eql([:a, :b])
|
52
|
+
expect(mine).to eql([])
|
53
|
+
expect(yours).to eql([])
|
54
|
+
end
|
55
|
+
|
56
|
+
it 'works on not same attrs' do
|
57
|
+
h1 = [{:name => :a}, {:name => :b}]
|
58
|
+
h2 = [{:name => :c}, {:name => :a}]
|
59
|
+
shared, mine, yours = compare_attrs(h1, h2){|a| a[:name] }
|
60
|
+
expect(shared).to eql([:a])
|
61
|
+
expect(mine).to eql([:b])
|
62
|
+
expect(yours).to eql([:c])
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
67
|
+
end
|
data/spec/syntax/test_compile.rb
CHANGED
@@ -37,5 +37,62 @@ module Finitio
|
|
37
37
|
end
|
38
38
|
end
|
39
39
|
|
40
|
+
context 'with lots of proxies to resolve' do
|
41
|
+
let(:source){
|
42
|
+
<<-EOF.strip
|
43
|
+
Deep = .String
|
44
|
+
Obj = { i: Deep }
|
45
|
+
Objs = [Obj]
|
46
|
+
EOF
|
47
|
+
}
|
48
|
+
|
49
|
+
it{ should be_a(System) }
|
50
|
+
|
51
|
+
it 'should work fine' do
|
52
|
+
expect {
|
53
|
+
subject['Objs'].dress([{i: "hello"}])
|
54
|
+
}.not_to raise_error
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
context 'with a recursive def' do
|
59
|
+
let(:source){
|
60
|
+
<<-EOF.strip
|
61
|
+
S = .String
|
62
|
+
NodeLabel = S
|
63
|
+
Tree = { label: NodeLabel, children: [Tree] }
|
64
|
+
EOF
|
65
|
+
}
|
66
|
+
|
67
|
+
it{ should be_a(System) }
|
68
|
+
|
69
|
+
it 'should work ine' do
|
70
|
+
expect {
|
71
|
+
subject['Tree'].dress({ label: "Root", children: [
|
72
|
+
{ label: "Child1", children: [] },
|
73
|
+
{ label: "Child2", children: [] }
|
74
|
+
]})
|
75
|
+
}.not_to raise_error
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
context 'with AD types' do
|
80
|
+
let(:source){
|
81
|
+
<<-EOF.strip
|
82
|
+
Colors = [Color]
|
83
|
+
Color = .Color <rgb> { r: Byte, g: Byte, b: Byte }
|
84
|
+
Byte = Int(i | i>0)
|
85
|
+
Int = .Integer
|
86
|
+
EOF
|
87
|
+
}
|
88
|
+
|
89
|
+
it{ should be_a(System) }
|
90
|
+
|
91
|
+
it 'should work ine' do
|
92
|
+
got = subject['Colors'].dress([{ r: 10, g: 15, b: 20 }])
|
93
|
+
expect(got.first).to be_a(Color)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
40
97
|
end
|
41
98
|
end
|
@@ -2,16 +2,9 @@ require 'spec_helper'
|
|
2
2
|
module Finitio
|
3
3
|
describe AdType, 'initialize' do
|
4
4
|
|
5
|
-
let(:rgb){
|
6
|
-
Contract.new(intType, Color.method(:rgb), Finitio::IDENTITY, :rgb)
|
7
|
-
}
|
8
|
-
|
9
|
-
let(:hex){
|
10
|
-
Contract.new(floatType, Color.method(:hex), Finitio::IDENTITY, :hex)
|
11
|
-
}
|
12
5
|
|
13
6
|
subject{
|
14
|
-
AdType.new(Color, [
|
7
|
+
AdType.new(Color, [rgb_contract, hex_contract])
|
15
8
|
}
|
16
9
|
|
17
10
|
context 'with valid arguments' do
|
@@ -0,0 +1,104 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
module Finitio
|
3
|
+
describe RelationType, "suppremum" do
|
4
|
+
|
5
|
+
subject{
|
6
|
+
left.suppremum(right)
|
7
|
+
}
|
8
|
+
|
9
|
+
let(:heading){
|
10
|
+
Heading.new([Attribute.new(:a, intType),
|
11
|
+
Attribute.new(:b, stringType)])
|
12
|
+
}
|
13
|
+
|
14
|
+
let(:left){
|
15
|
+
RelationType.new(heading)
|
16
|
+
}
|
17
|
+
|
18
|
+
context 'when right is not a tuple type' do
|
19
|
+
let(:right){
|
20
|
+
stringType
|
21
|
+
}
|
22
|
+
|
23
|
+
it 'builds a union type' do
|
24
|
+
expect(subject).to be_a(UnionType)
|
25
|
+
expect(subject.candidates).to eql([left, right])
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
context 'when right is an equal tuple type' do
|
30
|
+
let(:right){
|
31
|
+
RelationType.new(heading)
|
32
|
+
}
|
33
|
+
|
34
|
+
it 'keeps left' do
|
35
|
+
expect(subject).to be(left)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
context 'when right is an non-equal tuple type but compatible with RelationType' do
|
40
|
+
let(:heading2){
|
41
|
+
Heading.new([Attribute.new(:a, nilType),
|
42
|
+
Attribute.new(:b, stringType)])
|
43
|
+
}
|
44
|
+
|
45
|
+
let(:right){
|
46
|
+
RelationType.new(heading2)
|
47
|
+
}
|
48
|
+
|
49
|
+
it 'builds the suppremum as expected' do
|
50
|
+
expect(subject).to be_a(RelationType)
|
51
|
+
expect(subject.heading[:a].type).to eql(UnionType.new [intType,nilType])
|
52
|
+
expect(subject.heading[:b].type).to eql(stringType)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
context 'when right is an non-equal tuple type yielding a MultiRelationType' do
|
57
|
+
let(:heading2){
|
58
|
+
Heading.new([Attribute.new(:c, nilType),
|
59
|
+
Attribute.new(:b, stringType)])
|
60
|
+
}
|
61
|
+
|
62
|
+
let(:right){
|
63
|
+
RelationType.new(heading2)
|
64
|
+
}
|
65
|
+
|
66
|
+
it 'builds the suppremum as expected' do
|
67
|
+
expect(subject).to be_a(MultiRelationType)
|
68
|
+
expect(subject.heading[:a].type).to eql(intType)
|
69
|
+
expect(subject.heading[:a].required).to eql(false)
|
70
|
+
expect(subject.heading[:b].type).to eql(stringType)
|
71
|
+
expect(subject.heading[:b].required).to eql(true)
|
72
|
+
expect(subject.heading[:c].type).to eql(nilType)
|
73
|
+
expect(subject.heading[:c].required).to eql(false)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
context 'when right is an non-equal tuple type yielding a MultiRelationType II' do
|
78
|
+
let(:heading2){
|
79
|
+
Heading.new([Attribute.new(:a, nilType, false),
|
80
|
+
Attribute.new(:b, stringType)])
|
81
|
+
}
|
82
|
+
|
83
|
+
let(:right){
|
84
|
+
MultiRelationType.new(heading2)
|
85
|
+
}
|
86
|
+
|
87
|
+
it 'builds the suppremum as expected' do
|
88
|
+
expect(subject).to be_a(MultiRelationType)
|
89
|
+
expect(subject.heading[:a].type).to eql(UnionType.new [intType,nilType])
|
90
|
+
expect(subject.heading[:a].required).to eql(false)
|
91
|
+
expect(subject.heading[:b].type).to eql(stringType)
|
92
|
+
end
|
93
|
+
|
94
|
+
it 'works the other way round too' do
|
95
|
+
subject = right.suppremum(left)
|
96
|
+
expect(subject).to be_a(MultiRelationType)
|
97
|
+
expect(subject.heading[:a].type).to eql(UnionType.new [intType,nilType])
|
98
|
+
expect(subject.heading[:a].required).to eql(false)
|
99
|
+
expect(subject.heading[:b].type).to eql(stringType)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
end
|
104
|
+
end
|