qrb 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.md +5 -0
- data/Gemfile +12 -0
- data/Gemfile.lock +58 -0
- data/LICENCE.md +22 -0
- data/Manifest.txt +11 -0
- data/README.md +118 -0
- data/Rakefile +11 -0
- data/lib/qrb/Q/default.q +29 -0
- data/lib/qrb/data_type.rb +23 -0
- data/lib/qrb/errors.rb +23 -0
- data/lib/qrb/support/attribute.rb +53 -0
- data/lib/qrb/support/collection_type.rb +25 -0
- data/lib/qrb/support/dress_helper.rb +68 -0
- data/lib/qrb/support/heading.rb +57 -0
- data/lib/qrb/support/type_factory.rb +178 -0
- data/lib/qrb/support.rb +5 -0
- data/lib/qrb/syntax/ad_type.rb +25 -0
- data/lib/qrb/syntax/attribute.rb +11 -0
- data/lib/qrb/syntax/builtin_type.rb +13 -0
- data/lib/qrb/syntax/constraint_def.rb +11 -0
- data/lib/qrb/syntax/constraints.rb +18 -0
- data/lib/qrb/syntax/contract.rb +25 -0
- data/lib/qrb/syntax/definitions.rb +14 -0
- data/lib/qrb/syntax/expression.rb +12 -0
- data/lib/qrb/syntax/heading.rb +15 -0
- data/lib/qrb/syntax/lambda_expr.rb +11 -0
- data/lib/qrb/syntax/named_constraint.rb +11 -0
- data/lib/qrb/syntax/q.citrus +195 -0
- data/lib/qrb/syntax/relation_type.rb +11 -0
- data/lib/qrb/syntax/seq_type.rb +12 -0
- data/lib/qrb/syntax/set_type.rb +12 -0
- data/lib/qrb/syntax/sub_type.rb +13 -0
- data/lib/qrb/syntax/support.rb +13 -0
- data/lib/qrb/syntax/system.rb +15 -0
- data/lib/qrb/syntax/tuple_type.rb +11 -0
- data/lib/qrb/syntax/type_def.rb +14 -0
- data/lib/qrb/syntax/type_ref.rb +13 -0
- data/lib/qrb/syntax/union_type.rb +12 -0
- data/lib/qrb/syntax/unnamed_constraint.rb +11 -0
- data/lib/qrb/syntax.rb +42 -0
- data/lib/qrb/system.rb +63 -0
- data/lib/qrb/type/ad_type.rb +111 -0
- data/lib/qrb/type/builtin_type.rb +56 -0
- data/lib/qrb/type/relation_type.rb +81 -0
- data/lib/qrb/type/seq_type.rb +51 -0
- data/lib/qrb/type/set_type.rb +52 -0
- data/lib/qrb/type/sub_type.rb +94 -0
- data/lib/qrb/type/tuple_type.rb +99 -0
- data/lib/qrb/type/union_type.rb +78 -0
- data/lib/qrb/type.rb +63 -0
- data/lib/qrb/version.rb +14 -0
- data/lib/qrb.rb +63 -0
- data/qrb.gemspec +186 -0
- data/spec/acceptance/Q/test_default.rb +96 -0
- data/spec/acceptance/Q/test_parsing.rb +15 -0
- data/spec/acceptance/ad_type/test_in_q.rb +82 -0
- data/spec/acceptance/ad_type/test_in_ruby.rb +60 -0
- data/spec/spec_helper.rb +68 -0
- data/spec/unit/attribute/test_equality.rb +26 -0
- data/spec/unit/attribute/test_fetch_on.rb +50 -0
- data/spec/unit/attribute/test_initialize.rb +13 -0
- data/spec/unit/attribute/test_to_name.rb +10 -0
- data/spec/unit/heading/test_each.rb +28 -0
- data/spec/unit/heading/test_equality.rb +28 -0
- data/spec/unit/heading/test_initialize.rb +36 -0
- data/spec/unit/heading/test_size.rb +30 -0
- data/spec/unit/heading/test_to_name.rb +32 -0
- data/spec/unit/qrb/test_parse.rb +18 -0
- data/spec/unit/syntax/nodes/test_ad_type.rb +94 -0
- data/spec/unit/syntax/nodes/test_attribute.rb +25 -0
- data/spec/unit/syntax/nodes/test_builtin_type.rb +32 -0
- data/spec/unit/syntax/nodes/test_comment.rb +26 -0
- data/spec/unit/syntax/nodes/test_constraint_def.rb +27 -0
- data/spec/unit/syntax/nodes/test_constraints.rb +51 -0
- data/spec/unit/syntax/nodes/test_contract.rb +62 -0
- data/spec/unit/syntax/nodes/test_expression.rb +43 -0
- data/spec/unit/syntax/nodes/test_heading.rb +41 -0
- data/spec/unit/syntax/nodes/test_named_constraint.rb +31 -0
- data/spec/unit/syntax/nodes/test_relation_type.rb +41 -0
- data/spec/unit/syntax/nodes/test_seq_type.rb +24 -0
- data/spec/unit/syntax/nodes/test_set_type.rb +24 -0
- data/spec/unit/syntax/nodes/test_spacing.rb +25 -0
- data/spec/unit/syntax/nodes/test_sub_type.rb +52 -0
- data/spec/unit/syntax/nodes/test_tuple_type.rb +41 -0
- data/spec/unit/syntax/nodes/test_union_type.rb +23 -0
- data/spec/unit/syntax/nodes/test_unnamed_constraint.rb +31 -0
- data/spec/unit/syntax/test_compile_type.rb +22 -0
- data/spec/unit/system/test_add_type.rb +47 -0
- data/spec/unit/system/test_dsl.rb +30 -0
- data/spec/unit/system/test_dup.rb +30 -0
- data/spec/unit/system/test_fetch.rb +42 -0
- data/spec/unit/system/test_get_type.rb +30 -0
- data/spec/unit/system/test_initialize.rb +10 -0
- data/spec/unit/test_qrb.rb +15 -0
- data/spec/unit/type/ad_type/test_default_name.rb +15 -0
- data/spec/unit/type/ad_type/test_dress.rb +55 -0
- data/spec/unit/type/ad_type/test_include.rb +22 -0
- data/spec/unit/type/ad_type/test_initialize.rb +40 -0
- data/spec/unit/type/ad_type/test_name.rb +20 -0
- data/spec/unit/type/builtin_type/test_default_name.rb +12 -0
- data/spec/unit/type/builtin_type/test_dress.rb +33 -0
- data/spec/unit/type/builtin_type/test_equality.rb +26 -0
- data/spec/unit/type/builtin_type/test_include.rb +22 -0
- data/spec/unit/type/builtin_type/test_initialize.rb +12 -0
- data/spec/unit/type/builtin_type/test_name.rb +24 -0
- data/spec/unit/type/relation_type/test_default_name.rb +16 -0
- data/spec/unit/type/relation_type/test_dress.rb +164 -0
- data/spec/unit/type/relation_type/test_equality.rb +32 -0
- data/spec/unit/type/relation_type/test_include.rb +46 -0
- data/spec/unit/type/relation_type/test_initialize.rb +26 -0
- data/spec/unit/type/relation_type/test_name.rb +24 -0
- data/spec/unit/type/seq_type/test_default_name.rb +14 -0
- data/spec/unit/type/seq_type/test_dress.rb +49 -0
- data/spec/unit/type/seq_type/test_equality.rb +26 -0
- data/spec/unit/type/seq_type/test_include.rb +43 -0
- data/spec/unit/type/seq_type/test_initialize.rb +28 -0
- data/spec/unit/type/seq_type/test_name.rb +24 -0
- data/spec/unit/type/set_type/test_default_name.rb +14 -0
- data/spec/unit/type/set_type/test_dress.rb +66 -0
- data/spec/unit/type/set_type/test_equality.rb +26 -0
- data/spec/unit/type/set_type/test_include.rb +43 -0
- data/spec/unit/type/set_type/test_initialize.rb +28 -0
- data/spec/unit/type/set_type/test_name.rb +24 -0
- data/spec/unit/type/sub_type/test_default_name.rb +14 -0
- data/spec/unit/type/sub_type/test_dress.rb +75 -0
- data/spec/unit/type/sub_type/test_equality.rb +34 -0
- data/spec/unit/type/sub_type/test_include.rb +34 -0
- data/spec/unit/type/sub_type/test_initialize.rb +16 -0
- data/spec/unit/type/sub_type/test_name.rb +24 -0
- data/spec/unit/type/tuple_type/test_default_name.rb +14 -0
- data/spec/unit/type/tuple_type/test_dress.rb +112 -0
- data/spec/unit/type/tuple_type/test_equality.rb +32 -0
- data/spec/unit/type/tuple_type/test_include.rb +38 -0
- data/spec/unit/type/tuple_type/test_initialize.rb +30 -0
- data/spec/unit/type/tuple_type/test_name.rb +24 -0
- data/spec/unit/type/union_type/test_default_name.rb +12 -0
- data/spec/unit/type/union_type/test_dress.rb +43 -0
- data/spec/unit/type/union_type/test_equality.rb +30 -0
- data/spec/unit/type/union_type/test_include.rb +28 -0
- data/spec/unit/type/union_type/test_initialize.rb +24 -0
- data/spec/unit/type/union_type/test_name.rb +20 -0
- data/spec/unit/type_factory/dsl/test_adt.rb +54 -0
- data/spec/unit/type_factory/dsl/test_attribute.rb +37 -0
- data/spec/unit/type_factory/dsl/test_attributes.rb +41 -0
- data/spec/unit/type_factory/dsl/test_builtin.rb +45 -0
- data/spec/unit/type_factory/dsl/test_relation.rb +85 -0
- data/spec/unit/type_factory/dsl/test_seq.rb +57 -0
- data/spec/unit/type_factory/dsl/test_set.rb +57 -0
- data/spec/unit/type_factory/dsl/test_subtype.rb +91 -0
- data/spec/unit/type_factory/dsl/test_tuple.rb +73 -0
- data/spec/unit/type_factory/dsl/test_union.rb +81 -0
- data/spec/unit/type_factory/factory/test_builtin.rb +24 -0
- data/spec/unit/type_factory/factory/test_seq_type.rb +44 -0
- data/spec/unit/type_factory/factory/test_set_type.rb +44 -0
- data/spec/unit/type_factory/factory/test_sub_type.rb +53 -0
- data/spec/unit/type_factory/factory/test_tuple_type.rb +43 -0
- data/tasks/gem.rake +73 -0
- data/tasks/test.rake +31 -0
- metadata +344 -0
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
module Qrb
|
3
|
+
describe Syntax, "spacing" do
|
4
|
+
|
5
|
+
subject{
|
6
|
+
Syntax.parse(input, root: "spacing")
|
7
|
+
}
|
8
|
+
|
9
|
+
[
|
10
|
+
' ',
|
11
|
+
"\n",
|
12
|
+
" \t\n",
|
13
|
+
" # foo\n"
|
14
|
+
].each do |source|
|
15
|
+
context "when `#{source}`" do
|
16
|
+
let(:input){ source }
|
17
|
+
|
18
|
+
it 'should parse' do
|
19
|
+
subject.should eq(source)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
module Qrb
|
3
|
+
describe Syntax, "sub_type" do
|
4
|
+
|
5
|
+
subject{
|
6
|
+
Syntax.parse(input, root: "sub_type")
|
7
|
+
}
|
8
|
+
|
9
|
+
let(:compiled){
|
10
|
+
subject.compile(type_factory)
|
11
|
+
}
|
12
|
+
|
13
|
+
context '.Integer( i | i >= 0 )' do
|
14
|
+
let(:input){ '.Integer( i | i >= 0 )' }
|
15
|
+
|
16
|
+
it 'compiles to a SubType' do
|
17
|
+
compiled.should be_a(SubType)
|
18
|
+
compiled.super_type.should be_a(BuiltinType)
|
19
|
+
compiled.super_type.ruby_type.should be(Integer)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
context '.Integer( i | positive: i >= 0 )' do
|
24
|
+
let(:input){ '.Integer( i | positive: i >= 0 )' }
|
25
|
+
|
26
|
+
it 'compiles to a SubType' do
|
27
|
+
compiled.should be_a(SubType)
|
28
|
+
compiled.super_type.should be_a(BuiltinType)
|
29
|
+
compiled.super_type.ruby_type.should be(Integer)
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'has the correct constraints' do
|
33
|
+
compiled.constraints.keys.should eq([:positive])
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
context '.Integer( i | positive: i >= 0, ... )' do
|
38
|
+
let(:input){ '.Integer( i | positive: i >= 0, small: i <= 255 )' }
|
39
|
+
|
40
|
+
it 'compiles to a SubType' do
|
41
|
+
compiled.should be_a(SubType)
|
42
|
+
compiled.super_type.should be_a(BuiltinType)
|
43
|
+
compiled.super_type.ruby_type.should be(Integer)
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'has the correct constraints' do
|
47
|
+
compiled.constraints.keys.should eq([:positive, :small])
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
module Qrb
|
3
|
+
describe Syntax, "tuple_type" do
|
4
|
+
|
5
|
+
subject{
|
6
|
+
Syntax.parse(input, root: "tuple_type")
|
7
|
+
}
|
8
|
+
|
9
|
+
let(:compiled){
|
10
|
+
subject.compile(type_factory)
|
11
|
+
}
|
12
|
+
|
13
|
+
context 'empty heading' do
|
14
|
+
let(:input){ '{ }' }
|
15
|
+
|
16
|
+
it 'compiles to a TupleType' do
|
17
|
+
compiled.should be_a(TupleType)
|
18
|
+
compiled.heading.should be_empty
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
context '{a: .Integer}' do
|
23
|
+
let(:input){ '{a: .Integer}' }
|
24
|
+
|
25
|
+
it 'compiles to a TupleType' do
|
26
|
+
compiled.should be_a(TupleType)
|
27
|
+
compiled.heading.size.should eq(1)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
context '{a: .Integer, b: .Float}' do
|
32
|
+
let(:input){ '{a: .Integer, b: .Float}' }
|
33
|
+
|
34
|
+
it 'compiles to a TupleType' do
|
35
|
+
compiled.should be_a(TupleType)
|
36
|
+
compiled.heading.size.should eq(2)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
module Qrb
|
3
|
+
describe Syntax, "union_type" do
|
4
|
+
|
5
|
+
subject{
|
6
|
+
Syntax.parse(input, root: "union_type")
|
7
|
+
}
|
8
|
+
|
9
|
+
let(:compiled){
|
10
|
+
subject.compile(type_factory)
|
11
|
+
}
|
12
|
+
|
13
|
+
context '.Integer|.Float' do
|
14
|
+
let(:input){ '.Integer|.Float' }
|
15
|
+
|
16
|
+
it 'compiles to a UnionType' do
|
17
|
+
compiled.should be_a(UnionType)
|
18
|
+
compiled.should eq(UnionType.new([intType, floatType]))
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
module Qrb
|
3
|
+
describe Syntax, "unnamed_constraint" do
|
4
|
+
|
5
|
+
subject{
|
6
|
+
Syntax.parse(input, root: "unnamed_constraint")
|
7
|
+
}
|
8
|
+
|
9
|
+
let(:compiled){
|
10
|
+
subject.compile("a")
|
11
|
+
}
|
12
|
+
|
13
|
+
context 'a >= 10' do
|
14
|
+
let(:input){ 'a >= 10' }
|
15
|
+
|
16
|
+
it 'compiles to an Hash' do
|
17
|
+
compiled.should be_a(Hash)
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'has expected keys' do
|
21
|
+
compiled.keys.should eq([:predicate])
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'should be the correct Proc' do
|
25
|
+
compiled[:predicate].call(12).should be_true
|
26
|
+
compiled[:predicate].call(9).should be_false
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
module Qrb
|
3
|
+
describe Syntax, '.compile' do
|
4
|
+
|
5
|
+
let(:source){
|
6
|
+
<<-EOF
|
7
|
+
{
|
8
|
+
name: .String,
|
9
|
+
color: { red: .Integer, green: .Integer, blue: .Integer },
|
10
|
+
sex: .String( s | s =~ /^M|F$/ )
|
11
|
+
}
|
12
|
+
EOF
|
13
|
+
}
|
14
|
+
|
15
|
+
subject do
|
16
|
+
Syntax.compile_type(source)
|
17
|
+
end
|
18
|
+
|
19
|
+
it{ should be_a(Type) }
|
20
|
+
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'rspec'
|
2
|
+
module Qrb
|
3
|
+
describe System, "add_type" do
|
4
|
+
|
5
|
+
let(:system){ System.new }
|
6
|
+
|
7
|
+
subject{ system.add_type(type) }
|
8
|
+
|
9
|
+
context 'with a valid type' do
|
10
|
+
let(:type){ intType }
|
11
|
+
|
12
|
+
it 'should return the created type' do
|
13
|
+
subject.should be(type)
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'should add the type' do
|
17
|
+
subject
|
18
|
+
system[type.name].should be(type)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
context 'with an invalid type' do
|
23
|
+
let(:type){ "foo" }
|
24
|
+
|
25
|
+
it 'should raise an error' do
|
26
|
+
->{
|
27
|
+
subject
|
28
|
+
}.should raise_error(ArgumentError, "Qrb::Type expected, got `foo`")
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
context 'with a duplicate type name' do
|
33
|
+
let(:type){ intType }
|
34
|
+
|
35
|
+
before do
|
36
|
+
system.add_type(type)
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'should raise an error' do
|
40
|
+
->{
|
41
|
+
subject
|
42
|
+
}.should raise_error(Qrb::Error, "Duplicate type name `intType`")
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
module Qrb
|
3
|
+
describe System, "initialize" do
|
4
|
+
|
5
|
+
let(:system){ System.new }
|
6
|
+
|
7
|
+
context 'for building a tuple type' do
|
8
|
+
subject{
|
9
|
+
system.tuple(r: Integer)
|
10
|
+
}
|
11
|
+
|
12
|
+
it{ should be_a(TupleType) }
|
13
|
+
end
|
14
|
+
|
15
|
+
context 'for building a sub type' do
|
16
|
+
subject{
|
17
|
+
system.subtype(Integer){|i| i>=0 }
|
18
|
+
}
|
19
|
+
|
20
|
+
it{ should be_a(SubType) }
|
21
|
+
|
22
|
+
it 'should apply the constraint' do
|
23
|
+
->{
|
24
|
+
subject.dress(-9)
|
25
|
+
}.should raise_error(TypeError)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'rspec'
|
2
|
+
module Qrb
|
3
|
+
describe System, "dup" do
|
4
|
+
|
5
|
+
let(:system){ System.new }
|
6
|
+
|
7
|
+
before do
|
8
|
+
system.add_type(intType)
|
9
|
+
end
|
10
|
+
|
11
|
+
subject{ system.dup }
|
12
|
+
|
13
|
+
it{ should be_a(System) }
|
14
|
+
|
15
|
+
it 'should not be the same object' do
|
16
|
+
subject.should_not be(system)
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'should have intType' do
|
20
|
+
subject['intType'].should eq(intType)
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'should not share internals with the original' do
|
24
|
+
subject.add_type(floatType)
|
25
|
+
subject['floatType'].should_not be_nil
|
26
|
+
system['floatType'].should be_nil
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'rspec'
|
2
|
+
module Qrb
|
3
|
+
describe System, "fetch" do
|
4
|
+
|
5
|
+
let(:system){ System.new }
|
6
|
+
|
7
|
+
before do
|
8
|
+
system.add_type(intType)
|
9
|
+
end
|
10
|
+
|
11
|
+
subject{ system.fetch(name) }
|
12
|
+
|
13
|
+
context 'with an existing type name' do
|
14
|
+
let(:name){ "intType" }
|
15
|
+
|
16
|
+
it 'should return the type' do
|
17
|
+
subject.should eq(intType)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
context 'with a non existing type name and no block' do
|
22
|
+
let(:name){ "noSuchOne" }
|
23
|
+
|
24
|
+
it 'should raise an error' do
|
25
|
+
->{
|
26
|
+
subject
|
27
|
+
}.should raise_error(KeyError, /noSuchOne/)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
context 'with a non existing type name and a block' do
|
32
|
+
subject{
|
33
|
+
system.fetch("noSuchOne"){ "bar" }
|
34
|
+
}
|
35
|
+
|
36
|
+
it 'should yield the block' do
|
37
|
+
subject.should eq("bar")
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'rspec'
|
2
|
+
module Qrb
|
3
|
+
describe System, "[]" do
|
4
|
+
|
5
|
+
let(:system){ System.new }
|
6
|
+
|
7
|
+
before do
|
8
|
+
system.add_type(intType)
|
9
|
+
end
|
10
|
+
|
11
|
+
subject{ system[name] }
|
12
|
+
|
13
|
+
context 'with an existing type name' do
|
14
|
+
let(:name){ "intType" }
|
15
|
+
|
16
|
+
it 'should return the type' do
|
17
|
+
subject.should eq(intType)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
context 'with a non existing type name' do
|
22
|
+
let(:name){ "noSuchOne" }
|
23
|
+
|
24
|
+
it 'should return nil' do
|
25
|
+
subject.should be_nil
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
describe Qrb do
|
3
|
+
|
4
|
+
it "should have a version number" do
|
5
|
+
Qrb.const_defined?(:VERSION).should be_true
|
6
|
+
end
|
7
|
+
|
8
|
+
it 'should have DSL methods' do
|
9
|
+
t = Qrb.type(Fixnum){|i| i>=0 }
|
10
|
+
t.should be_a(Qrb::SubType)
|
11
|
+
t.dress(12).should eq(12)
|
12
|
+
->{ t.dress(-12) }.should raise_error(Qrb::TypeError)
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
module Qrb
|
3
|
+
describe AdType, "default_name" do
|
4
|
+
|
5
|
+
subject{ type.default_name }
|
6
|
+
|
7
|
+
let(:type){
|
8
|
+
AdType.new(Color, rgb: [intType, Color.method(:rgb) ],
|
9
|
+
hex: [floatType, Color.method(:hex) ])
|
10
|
+
}
|
11
|
+
|
12
|
+
it{ should eq('Color') }
|
13
|
+
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
module Qrb
|
3
|
+
describe AdType, 'dress' do
|
4
|
+
|
5
|
+
let(:type){
|
6
|
+
AdType.new(Color, rgb: [intType, ->(i){ i*2 } ],
|
7
|
+
hex: [floatType, ->(f){ f*3 } ])
|
8
|
+
}
|
9
|
+
|
10
|
+
subject{
|
11
|
+
type.dress(arg)
|
12
|
+
}
|
13
|
+
|
14
|
+
context 'with a color' do
|
15
|
+
let(:arg){ Color.new(12, 13, 15) }
|
16
|
+
|
17
|
+
it{ should be(arg) }
|
18
|
+
end
|
19
|
+
|
20
|
+
context 'with an integer' do
|
21
|
+
let(:arg){ 12 }
|
22
|
+
|
23
|
+
it{ should eq(24) }
|
24
|
+
end
|
25
|
+
|
26
|
+
context 'with a float' do
|
27
|
+
let(:arg){ 12.0 }
|
28
|
+
|
29
|
+
it{ should eq(36.0) }
|
30
|
+
end
|
31
|
+
|
32
|
+
context 'with an unrecognized' do
|
33
|
+
let(:arg){ "foo" }
|
34
|
+
|
35
|
+
it 'should raise an error' do
|
36
|
+
->{
|
37
|
+
subject
|
38
|
+
}.should raise_error(TypeError, "Invalid value `foo` for Color")
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
context 'when the upper raises an error' do
|
43
|
+
let(:type){
|
44
|
+
AdType.new(Color, rgb: [ intType, ->(t){ raise ArgumentError } ])
|
45
|
+
}
|
46
|
+
|
47
|
+
it 'should hide the error' do
|
48
|
+
err = type.dress(12) rescue $!
|
49
|
+
err.should be_a(TypeError)
|
50
|
+
err.message.should eq("Invalid value `12` for Color")
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
module Qrb
|
3
|
+
describe AdType, "include?" do
|
4
|
+
|
5
|
+
let(:type){ AdType.new(Color, {}) }
|
6
|
+
|
7
|
+
subject{ type.include?(arg) }
|
8
|
+
|
9
|
+
context 'when not included' do
|
10
|
+
let(:arg){ "12" }
|
11
|
+
|
12
|
+
it{ should be_false }
|
13
|
+
end
|
14
|
+
|
15
|
+
context 'when included' do
|
16
|
+
let(:arg){ blueviolet }
|
17
|
+
|
18
|
+
it{ should be_true }
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
module Qrb
|
3
|
+
describe AdType, 'initialize' do
|
4
|
+
|
5
|
+
subject{
|
6
|
+
AdType.new(Color, rgb: [intType, Color.method(:rgb) ],
|
7
|
+
hex: [floatType, Color.method(:hex) ])
|
8
|
+
}
|
9
|
+
|
10
|
+
context 'with valid arguments' do
|
11
|
+
it{ should be_a(AdType) }
|
12
|
+
|
13
|
+
it 'should set the instance variables' do
|
14
|
+
subject.ruby_type.should be(Color)
|
15
|
+
subject.contracts.should be_a(Hash)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
context 'with invalid arguments (I)' do
|
20
|
+
subject{ AdType.new("foo", {}) }
|
21
|
+
|
22
|
+
it 'should raise an error' do
|
23
|
+
->{
|
24
|
+
subject
|
25
|
+
}.should raise_error(ArgumentError, 'Module expected, got `foo`')
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
context 'with invalid arguments (II)' do
|
30
|
+
subject{ AdType.new(Object, "bar") }
|
31
|
+
|
32
|
+
it 'should raise an error' do
|
33
|
+
->{
|
34
|
+
subject
|
35
|
+
}.should raise_error(ArgumentError, 'Hash expected, got `bar`')
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
module Qrb
|
3
|
+
describe AdType, "name" do
|
4
|
+
|
5
|
+
subject{ type.name }
|
6
|
+
|
7
|
+
context 'when provided' do
|
8
|
+
let(:type){ AdType.new(Color, {}, "Foo") }
|
9
|
+
|
10
|
+
it{ should eq('Foo') }
|
11
|
+
end
|
12
|
+
|
13
|
+
context 'when not provided' do
|
14
|
+
let(:type){ AdType.new(Color, {}) }
|
15
|
+
|
16
|
+
it{ should eq('Color') }
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
module Qrb
|
3
|
+
describe BuiltinType, "dress" do
|
4
|
+
|
5
|
+
let(:type){ BuiltinType.new(Integer, 'int') }
|
6
|
+
|
7
|
+
subject{ type.dress(arg) }
|
8
|
+
|
9
|
+
context 'with an Integer' do
|
10
|
+
let(:arg){ 12 }
|
11
|
+
|
12
|
+
it{ should be(arg) }
|
13
|
+
end
|
14
|
+
|
15
|
+
context 'with a Float' do
|
16
|
+
let(:arg){ 12.0 }
|
17
|
+
|
18
|
+
subject{
|
19
|
+
type.dress(arg) rescue $!
|
20
|
+
}
|
21
|
+
|
22
|
+
it 'should raise an Error' do
|
23
|
+
subject.should be_a(TypeError)
|
24
|
+
subject.message.should eq("Invalid value `12.0` for int")
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'should have no location' do
|
28
|
+
subject.location.should eq('')
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
module Qrb
|
3
|
+
describe BuiltinType, "equality" do
|
4
|
+
|
5
|
+
let(:intType) { BuiltinType.new(Integer) }
|
6
|
+
let(:intType2){ BuiltinType.new(Integer) }
|
7
|
+
let(:fltType) { BuiltinType.new(Float) }
|
8
|
+
|
9
|
+
it 'should apply structural equality' do
|
10
|
+
(intType == intType2).should be_true
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'should apply distinguish different types' do
|
14
|
+
(intType == fltType).should be_false
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'should be a total function, with nil for non types' do
|
18
|
+
(intType == 12).should be_false
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'should implement hash accordingly' do
|
22
|
+
(intType.hash == intType2.hash).should be_true
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
module Qrb
|
3
|
+
describe BuiltinType, "include?" do
|
4
|
+
|
5
|
+
let(:type){ BuiltinType.new(Integer) }
|
6
|
+
|
7
|
+
subject{ type.include?(arg) }
|
8
|
+
|
9
|
+
context 'when not included' do
|
10
|
+
let(:arg){ "12" }
|
11
|
+
|
12
|
+
it{ should be_false }
|
13
|
+
end
|
14
|
+
|
15
|
+
context 'when included' do
|
16
|
+
let(:arg){ 12 }
|
17
|
+
|
18
|
+
it{ should be_true }
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
end
|