moosex 0.0.10 → 0.0.11

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.
@@ -0,0 +1,225 @@
1
+ module MooseX
2
+ module Types
3
+
4
+ def Types.included(c)
5
+ c.extend(MooseX::Types::Core)
6
+ end
7
+
8
+ class TypeCheckError < TypeError
9
+ end
10
+
11
+ module Core
12
+
13
+ # TODO
14
+ # String
15
+ # format
16
+ # length (min, max, between, is)
17
+ # add custom message
18
+ # integer / number odd, even, >=, <=, etc
19
+ # allow new/blank
20
+ # required :method?
21
+
22
+ # Types::Numeric
23
+ # PositiveNum
24
+ # PositiveOrZeroNum
25
+ # PositiveInt
26
+ # PositiveOrZeroInt
27
+ # NegativeNum
28
+ # NegativeOrZeroNum
29
+ # NegativeInt
30
+ # NegativeOrZeroInt
31
+ # SingleDigit
32
+
33
+ def createValidator(message, &block)
34
+ l = block
35
+ l.define_singleton_method(:to_s) { message }
36
+ l
37
+ end
38
+
39
+ def isAny
40
+ createValidator("[Any]") {|value| }
41
+ end
42
+
43
+ def isConstant(constant_value)
44
+ createValidator("[Constant: '#{constant_value}' (#{constant_value.class})]") do |value|
45
+ unless value === constant_value
46
+ raise TypeCheckError,"Constant violation: value '#{value}' (#{value.class}) is not '#{constant_value}' (#{constant_value.class})"
47
+ end
48
+ end
49
+ end
50
+
51
+ def isType(type)
52
+ return type if type.is_a?(Proc)
53
+
54
+ createValidator("[Type #{type}]") do |value|
55
+ raise TypeCheckError, "Type violation: value '#{value}' (#{value.class}) is not an instance of [Type #{type}]" unless value.is_a?(type)
56
+ end
57
+ end
58
+
59
+ alias_method :isInstanceOf, :isType
60
+ alias_method :isConsumerOf, :isType
61
+
62
+ def hasMethods(*methods)
63
+ createValidator("[hasMethods #{methods}]") do |object|
64
+ methods.each do |method|
65
+ unless object.respond_to? method.to_sym
66
+ raise TypeCheckError, "hasMethods violation: object #{object} (#{object.class}) should implement method #{method}"
67
+ end
68
+ end
69
+ end
70
+ end
71
+
72
+ def isAllOf(*conditions)
73
+ createValidator("[AllOf [#{conditions.map{|t| t.to_s }.join(', ')}]]") do |value|
74
+ begin
75
+ conditions.each { |c| isType(c).call(value) }
76
+ rescue TypeCheckError => e
77
+ raise TypeCheckError, "AllOf Check violation: caused by [#{e}]"
78
+ end
79
+ end
80
+ end
81
+
82
+ def isAnyOf(*conditions)
83
+ conditions = conditions.flatten
84
+ createValidator("[AnyOf [#{conditions.map{|t| t.to_s }.join(', ')}]]") do |value|
85
+
86
+ find = false
87
+ exceptions = []
88
+
89
+ for c in conditions
90
+ begin
91
+ isType(c).call(value)
92
+ find = true
93
+ break
94
+ rescue TypeCheckError => ex
95
+ exceptions << ex
96
+ rescue => e
97
+ raise TypeCheckError, "unexpected exception #{e}"
98
+ end
99
+ end
100
+
101
+ raise TypeCheckError, "AnyOf Check violation: caused by [#{exceptions.map{|e| e.to_s}.join', '}]" unless find
102
+ end
103
+ end
104
+
105
+ def isEnum(*possible_values)
106
+ possible_constants = possible_values.flatten.map do |value|
107
+ isConstant(value)
108
+ end
109
+
110
+ createValidator("[Enum #{possible_values}]") do |value|
111
+ begin
112
+ isAnyOf(possible_constants).call(value)
113
+ rescue TypeCheckError => e
114
+ raise TypeCheckError, "Enum Check violation: value '#{value}' (#{value.class}) is not #{possible_values}"
115
+ end
116
+ end
117
+ end
118
+
119
+ def isNot(condition)
120
+ createValidator("[NOT #{condition.to_s}]") do |value|
121
+ success = false
122
+ begin
123
+ condition.call(value)
124
+ success = true
125
+ rescue TypeCheckError => e
126
+ nil
127
+ end
128
+
129
+ if success
130
+ raise TypeCheckError, "Not violation: value '#{value}' (#{value.class}) is not #{condition.to_s}"
131
+ end
132
+ end
133
+ end
134
+
135
+ def isMaybe(type)
136
+ createValidator("[Maybe #{type.to_s}]") do |value|
137
+ begin
138
+ isAnyOf(isType(type), isConstant(nil)).call(value)
139
+ rescue TypeCheckError => e
140
+ raise TypeCheckError, "Maybe violation: caused by #{e}"
141
+ end
142
+ end
143
+ end
144
+
145
+ def isArray(type=nil)
146
+ type = isAny if type.nil?
147
+
148
+ createValidator "[Array #{type.to_s}]" do |array|
149
+ isType(Array).call(array)
150
+
151
+ array.each do |item|
152
+ begin
153
+ isType(type).call(item)
154
+ rescue TypeCheckError => e
155
+ raise TypeCheckError, "Array violation: caused by #{e}"
156
+ end
157
+ end
158
+ end
159
+ end
160
+
161
+ def isHash(map={})
162
+ if map.empty?
163
+ map = {isAny => isAny }
164
+ end
165
+
166
+ keyType, valueType = map.shift
167
+
168
+ createValidator "[Hash #{keyType.to_s} => #{valueType.to_s}]" do |hash|
169
+ isType(Hash).call(hash)
170
+
171
+ hash.each_pair do| key, value|
172
+ begin
173
+ isType(keyType).call(key)
174
+ isType(valueType).call(value)
175
+ rescue TypeCheckError => e
176
+ raise TypeCheckError, "Hash violation: caused by #{e}"
177
+ end
178
+ end
179
+ end
180
+ end
181
+
182
+ def isTuple(*types)
183
+
184
+ createValidator "[Tuple [#{types.map{|t| t.to_s}.join ', '}]]" do |tuple|
185
+ isType(Array).call(tuple)
186
+
187
+ unless tuple.size == types.size
188
+ raise TypeCheckError, "Tuple violation: size should be #{types.size} instead #{tuple.size}"
189
+ end
190
+
191
+ types.each_index do |index|
192
+ begin
193
+ isType(types[index]).call(tuple[index])
194
+ rescue TypeCheckError => e
195
+ raise TypeCheckError, "Tuple violation: on position #{index} caused by #{e}"
196
+ end
197
+ end
198
+ end
199
+
200
+ end
201
+
202
+ def isSet(type=nil)
203
+ type = isAny if type.nil?
204
+
205
+ createValidator "[Set #{type.to_s}]" do |set|
206
+ isType(Array).call(set)
207
+
208
+ if set.uniq.size != set.size
209
+ duplicated = set.inject(Hash.new(0)) {|h,i| h[i] += 1; h }.select{|k,v| v > 1 }
210
+ raise TypeCheckError, "Set violation: has one or more non unique elements: #{duplicated} (value => count)"
211
+ end
212
+
213
+ set.each do |item|
214
+ begin
215
+ isType(type).call(item)
216
+ rescue TypeCheckError => e
217
+ raise TypeCheckError, "Set violation: caused by #{e}"
218
+ end
219
+ end
220
+ end
221
+ end
222
+
223
+ end
224
+ end
225
+ end
@@ -1,3 +1,3 @@
1
- module Moosex
2
- VERSION = "0.0.10"
1
+ module MooseX
2
+ VERSION = "0.0.11"
3
3
  end
data/moosex.gemspec CHANGED
@@ -5,7 +5,7 @@ require 'moosex/version'
5
5
 
6
6
  Gem::Specification.new do |spec|
7
7
  spec.name = "moosex"
8
- spec.version = Moosex::VERSION
8
+ spec.version = MooseX::VERSION
9
9
  spec.authors = ["Tiago Peczenyj"]
10
10
  spec.email = ["tiago.peczenyj@gmail.com"]
11
11
  spec.summary = %q{A postmodern object DSL for Ruby}
@@ -0,0 +1,33 @@
1
+ require 'moosex'
2
+
3
+ class SuperTypes
4
+ include MooseX
5
+ include MooseX::Types
6
+
7
+ has x: {
8
+ is: :rw,
9
+ isa: isAnyOf(
10
+ isConstant(1),
11
+ isMaybe(Integer),
12
+ isArray( hasMethods(:baz) ),
13
+ isEnum(:foo, :bar)
14
+ )
15
+ }
16
+ end
17
+
18
+ describe "SuperTypes" do
19
+ it "should verify tyoe if x" do
20
+ SuperTypes.new(x: 1)
21
+ SuperTypes.new(x: nil)
22
+ SuperTypes.new(x: 1024)
23
+ SuperTypes.new(x: [])
24
+ SuperTypes.new(x: :foo)
25
+ end
26
+
27
+ it "should raise error" do
28
+ expect {
29
+ SuperTypes.new(x: [1])
30
+ }.to raise_error(MooseX::Types::TypeCheckError,
31
+ "isa check for field x: AnyOf Check violation: caused by [Constant violation: value '[1]' (Array) is not '1' (Fixnum), Maybe violation: caused by AnyOf Check violation: caused by [Type violation: value '[1]' (Array) is not an instance of [Type Integer], Constant violation: value '[1]' (Array) is not '' (NilClass)], Array violation: caused by hasMethods violation: object 1 (Fixnum) should implement method baz, Enum Check violation: value '[1]' (Array) is not [:foo, :bar]]")
32
+ end
33
+ end
@@ -0,0 +1,96 @@
1
+ require 'moosex'
2
+
3
+ class Hooks
4
+ include MooseX
5
+
6
+ has logger: {
7
+ is: :rw,
8
+ required: true,
9
+ }
10
+
11
+ def sum(a,b,c)
12
+ self.logger.inside_method(a,b,c)
13
+ a + b + c
14
+ end
15
+
16
+ before(:sum) do |object,a,b,c|
17
+ object.logger.inside_before(a,b,c)
18
+ end
19
+
20
+ after(:sum) do |object,a,b,c|
21
+ object.logger.inside_after(a,b,c)
22
+ end
23
+ end
24
+
25
+ describe "Hooks" do
26
+ it "should call after and before" do
27
+ logger = double
28
+ logger.should_receive(:inside_method).with(1,2,3)
29
+ logger.should_receive(:inside_before).with(1,2,3)
30
+ logger.should_receive(:inside_after).with(1,2,3)
31
+
32
+ h = Hooks.new(logger: logger)
33
+ h.sum(1,2,3).should == 6
34
+ end
35
+ end
36
+
37
+ class Hooks2 < Hooks
38
+ around(:sum) do |original_method, object, a,b,c|
39
+ object.logger.inside_around_begin(a,b,c)
40
+ result = original_method.bind(object).call(a,b,c)
41
+ object.logger.inside_around_end(a,b,c)
42
+ result + 1
43
+ end
44
+
45
+ after(:sum) do |object,a,b,c|
46
+ object.logger.inside_after2(a,b,c)
47
+ end
48
+ end
49
+
50
+ describe "Hooks2" do
51
+ it "should call after and before" do
52
+ logger = double
53
+ logger.should_receive(:inside_method).with(1,2,3)
54
+ logger.should_receive(:inside_before).with(1,2,3)
55
+ logger.should_receive(:inside_after).with(1,2,3)
56
+ logger.should_receive(:inside_after2).with(1,2,3)
57
+ logger.should_receive(:inside_around_begin).with(1,2,3)
58
+ logger.should_receive(:inside_around_end).with(1,2,3)
59
+ h = Hooks2.new(logger: logger)
60
+ h.sum(1,2,3).should == 7
61
+ end
62
+ end
63
+
64
+ class OtherPoint
65
+ include MooseX
66
+
67
+ has [:x, :y ], { is: :rw, required: true }
68
+
69
+ def clear!
70
+ self.x = 0
71
+ self.y = 0
72
+ end
73
+ end
74
+
75
+ class OtherPoint3D < OtherPoint
76
+
77
+ has z: { is: :rw, required: true }
78
+
79
+ after :clear! do |object|
80
+ object.z = 0
81
+ end
82
+ end
83
+ describe "OtherPoint3D" do
84
+ it "should clear a 3d point" do
85
+ p = OtherPoint3D.new(x: 1, y: 2, z: 3)
86
+ p.x.should == 1
87
+ p.y.should == 2
88
+ p.z.should == 3
89
+
90
+ p.clear!
91
+
92
+ p.x.should == 0
93
+ p.y.should == 0
94
+ p.z.should == 0
95
+ end
96
+ end
data/spec/point_spec.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  require 'moosex'
2
+ require 'moosex/types'
2
3
 
3
4
  class Point
4
5
  include MooseX
@@ -88,13 +89,15 @@ describe "Point" do
88
89
  p = Point.new
89
90
  expect {
90
91
  p.x = "lol"
91
- }.to raise_error('isa check for "x" failed: is not instance of Integer!')
92
+ }.to raise_error(MooseX::Types::TypeCheckError,
93
+ "isa check for x=: Type violation: value 'lol' (String) is not an instance of [Type Integer]")
92
94
  end
93
95
 
94
96
  it "for x, with type check" do
95
97
  expect {
96
98
  Point.new(x: "lol")
97
- }.to raise_error('isa check for "x" failed: is not instance of Integer!')
99
+ }.to raise_error(MooseX::Types::TypeCheckError,
100
+ "isa check for field x: Type violation: value 'lol' (String) is not an instance of [Type Integer]")
98
101
  end
99
102
 
100
103
  it "clear should clean attributes" do
@@ -172,13 +175,15 @@ describe "Point3D" do
172
175
  p = Point3D.new
173
176
  expect {
174
177
  p.z = "lol"
175
- }.to raise_error('isa check for "z" failed: is not instance of Integer!')
178
+ }.to raise_error(MooseX::Types::TypeCheckError,
179
+ "isa check for z=: Type violation: value 'lol' (String) is not an instance of [Type Integer]")
176
180
  end
177
181
 
178
182
  it "for z, with type check" do
179
183
  expect {
180
184
  Point3D.new(z: "lol")
181
- }.to raise_error('isa check for "z" failed: is not instance of Integer!')
185
+ }.to raise_error(MooseX::Types::TypeCheckError,
186
+ "isa check for field z: Type violation: value 'lol' (String) is not an instance of [Type Integer]")
182
187
  end
183
188
 
184
189
  it "clear should clean attributes" do
@@ -0,0 +1,477 @@
1
+ require 'moosex/types'
2
+
3
+ module Test
4
+ include MooseX::Types
5
+ end
6
+
7
+ describe "MooseX::Types" do
8
+ describe "Any" do
9
+ it "should accept any value" do
10
+ Test.isAny.call(nil)
11
+ Test.isAny.call(1)
12
+ Test.isAny.call(0)
13
+ Test.isAny.call(true)
14
+ Test.isAny.call(false)
15
+ Test.isAny.call(:foo)
16
+ Test.isAny.call("lol")
17
+ Test.isAny.call([])
18
+ Test.isAny.call({})
19
+ end
20
+
21
+ it "should return [Any]" do
22
+ Test.isAny.to_s.should == "[Any]"
23
+ end
24
+ end
25
+
26
+ describe "Constant" do
27
+ it "should accept any value" do
28
+ Test.isConstant(nil).call(nil)
29
+ Test.isConstant(1).call(1)
30
+ Test.isConstant(0).call(0)
31
+ Test.isConstant(true).call(true)
32
+ Test.isConstant(false).call(false)
33
+ Test.isConstant(:foo).call(:foo)
34
+ Test.isConstant("lol").call("lol")
35
+ Test.isConstant([]).call([])
36
+ Test.isConstant({}).call({})
37
+ end
38
+
39
+ it "should return [Constant: value (class)]" do
40
+ Test.isConstant(nil).to_s.should == "[Constant: '' (NilClass)]"
41
+ Test.isConstant(1).to_s.should == "[Constant: '1' (Fixnum)]"
42
+ Test.isConstant(0).to_s.should == "[Constant: '0' (Fixnum)]"
43
+ Test.isConstant(true).to_s.should == "[Constant: 'true' (TrueClass)]"
44
+ Test.isConstant(false).to_s.should == "[Constant: 'false' (FalseClass)]"
45
+ Test.isConstant(:foo).to_s.should == "[Constant: 'foo' (Symbol)]"
46
+ Test.isConstant("lol").to_s.should == "[Constant: 'lol' (String)]"
47
+ Test.isConstant([]).to_s.should == "[Constant: '[]' (Array)]"
48
+ Test.isConstant({}).to_s.should == "[Constant: '{}' (Hash)]"
49
+ end
50
+
51
+ it "should raise error" do
52
+ expect {
53
+ Test.isConstant(1).call(0)
54
+ }.to raise_error(MooseX::Types::TypeCheckError, "Constant violation: value '0' (Fixnum) is not '1' (Fixnum)")
55
+ end
56
+ end
57
+
58
+ describe "Type" do
59
+
60
+ it "should accept values" do
61
+ Test.isType(NilClass).call(nil)
62
+ Test.isType(Fixnum).call(1)
63
+ Test.isType(Integer).call(1)
64
+ Test.isType(Fixnum).call(0)
65
+ Test.isType(Integer).call(0)
66
+ Test.isType(TrueClass).call(true)
67
+ Test.isType(FalseClass).call(false)
68
+ Test.isType(Symbol).call(:foo)
69
+ Test.isType(String).call("lol")
70
+ Test.isType(Array).call([])
71
+ Test.isType(Hash).call({})
72
+ end
73
+
74
+ it "should return [Type Class]" do
75
+ Test.isType(NilClass).to_s.should == "[Type NilClass]"
76
+ Test.isType(Fixnum).to_s.should == "[Type Fixnum]"
77
+ Test.isType(Integer).to_s.should == "[Type Integer]"
78
+ Test.isType(TrueClass).to_s.should == "[Type TrueClass]"
79
+ Test.isType(FalseClass).to_s.should == "[Type FalseClass]"
80
+ Test.isType(Symbol).to_s.should == "[Type Symbol]"
81
+ Test.isType(String).to_s.should == "[Type String]"
82
+ Test.isType(Array).to_s.should == "[Type Array]"
83
+ Test.isType(Hash).to_s.should == "[Type Hash]"
84
+ end
85
+
86
+ it "test aliases" do
87
+ Test.isInstanceOf(TrueClass).call(true)
88
+ Test.isConsumerOf(TrueClass).call(true)
89
+
90
+ Test.isInstanceOf(TrueClass).to_s.should == "[Type TrueClass]"
91
+ Test.isConsumerOf(TrueClass).to_s.should == "[Type TrueClass]"
92
+ end
93
+
94
+ it "Constant should raise error" do
95
+ expect {
96
+ Test.isType(Array).call({})
97
+ }.to raise_error(MooseX::Types::TypeCheckError,
98
+ "Type violation: value '{}' (Hash) is not an instance of [Type Array]")
99
+ end
100
+
101
+ end
102
+
103
+ describe "AllOf" do
104
+
105
+ it "should accept values" do
106
+ Test.isAllOf(Object).call(nil)
107
+ Test.isAllOf(Object, NilClass).call(nil)
108
+ Test.isAllOf(Fixnum).call(1)
109
+ Test.isAllOf(Fixnum,Integer).call(1)
110
+ Test.isAllOf(Fixnum,Integer,Numeric).call(1)
111
+ Test.isAllOf(Fixnum,Integer,Numeric, Test.isConstant(1)).call(1)
112
+
113
+ Test.isAllOf(Test.isAllOf(Fixnum,Integer),Numeric, Test.isConstant(1)).call(1)
114
+ end
115
+
116
+ it "shouldreturn [AllOf *]" do
117
+ Test.isAllOf(Object).to_s.should == "[AllOf [Object]]"
118
+ Test.isAllOf(Object, NilClass).to_s.should == "[AllOf [Object, NilClass]]"
119
+ Test.isAllOf(Fixnum).to_s.should == "[AllOf [Fixnum]]"
120
+ Test.isAllOf(Fixnum,Integer).to_s.should == "[AllOf [Fixnum, Integer]]"
121
+ Test.isAllOf(Fixnum,Integer,Numeric).to_s.should == "[AllOf [Fixnum, Integer, Numeric]]"
122
+ Test.isAllOf(Fixnum,Integer,Numeric, Test.isConstant(1)).to_s
123
+ .should == "[AllOf [Fixnum, Integer, Numeric, [Constant: '1' (Fixnum)]]]"
124
+
125
+ Test.isAllOf(Test.isAllOf(Fixnum,Integer),Numeric, Test.isConstant(1)).to_s
126
+ .should == "[AllOf [[AllOf [Fixnum, Integer]], Numeric, [Constant: '1' (Fixnum)]]]"
127
+ end
128
+
129
+ it "Constant should raise error" do
130
+ expect {
131
+ Test.isAllOf(Fixnum,Integer,Numeric, Test.isConstant(1)).call(2)
132
+ }.to raise_error(MooseX::Types::TypeCheckError,
133
+ "AllOf Check violation: caused by [Constant violation: value '2' (Fixnum) is not '1' (Fixnum)]")
134
+
135
+ expect {
136
+ Test.isAllOf(Fixnum,Integer,Numeric, Test.isConstant(1)).call(nil)
137
+ }.to raise_error(MooseX::Types::TypeCheckError,
138
+ "AllOf Check violation: caused by [Type violation: value '' (NilClass) is not an instance of [Type Fixnum]]")
139
+
140
+ end
141
+ end
142
+
143
+ describe "AnyOf" do
144
+
145
+ it "should accept values" do
146
+ Test.isAnyOf(Object).call(nil)
147
+ Test.isAnyOf(Object, NilClass).call(nil)
148
+
149
+ Test.isAnyOf(TrueClass, FalseClass).call(true)
150
+ Test.isAnyOf(TrueClass, FalseClass).call(false)
151
+
152
+ Test.isAnyOf(Fixnum).call(1)
153
+ Test.isAnyOf(Fixnum,Integer).call(1)
154
+ Test.isAnyOf(Fixnum,Integer,Numeric).call(1)
155
+ Test.isAnyOf(Fixnum,Integer,Numeric, Test.isConstant(1)).call(1)
156
+
157
+ Test.isAnyOf(Fixnum, String, Symbol).call(1)
158
+ Test.isAnyOf(Fixnum, String, Symbol).call("string")
159
+ Test.isAnyOf(Fixnum, String, Symbol).call(:symbol)
160
+
161
+ Test.isAnyOf(Test.isConstant(0), Test.isConstant(1)).call(1)
162
+ Test.isAnyOf(Test.isConstant(0), Test.isConstant(1)).call(0)
163
+
164
+ Test.isAnyOf(Test.isAllOf(Fixnum,Integer),Numeric, Test.isConstant(1)).call(1)
165
+ Test.isAnyOf(Test.isAllOf(Fixnum,Integer),Numeric, Test.isConstant(1)).call(2)
166
+ Test.isAnyOf(Test.isAllOf(Fixnum,Integer),Numeric, Test.isConstant(1)).call(3.0)
167
+ end
168
+
169
+ it "should return [AnyOf *]" do
170
+ Test.isAnyOf(Object).to_s.should == "[AnyOf [Object]]"
171
+ Test.isAnyOf(Object, NilClass).to_s.should == "[AnyOf [Object, NilClass]]"
172
+ Test.isAnyOf(Fixnum).to_s.should == "[AnyOf [Fixnum]]"
173
+ Test.isAnyOf(Fixnum,Integer).to_s.should == "[AnyOf [Fixnum, Integer]]"
174
+ Test.isAnyOf(Fixnum,Integer,Numeric).to_s.should == "[AnyOf [Fixnum, Integer, Numeric]]"
175
+ Test.isAnyOf(Fixnum,Integer,Numeric, Test.isConstant(1)).to_s
176
+ .should == "[AnyOf [Fixnum, Integer, Numeric, [Constant: '1' (Fixnum)]]]"
177
+
178
+ Test.isAnyOf(Test.isAllOf(Fixnum,Integer),Numeric, Test.isConstant(1)).to_s
179
+ .should == "[AnyOf [[AllOf [Fixnum, Integer]], Numeric, [Constant: '1' (Fixnum)]]]"
180
+ end
181
+
182
+ it "should raise error" do
183
+ expect {
184
+ Test.isAnyOf(TrueClass, FalseClass).call(nil)
185
+ }.to raise_error(MooseX::Types::TypeCheckError,
186
+ "AnyOf Check violation: caused by [Type violation: value '' (NilClass) is not an instance of [Type TrueClass], Type violation: value '' (NilClass) is not an instance of [Type FalseClass]]")
187
+
188
+ expect {
189
+ Test.isAnyOf(Fixnum, String, Symbol).call([])
190
+ }.to raise_error(MooseX::Types::TypeCheckError,
191
+ "AnyOf Check violation: caused by [Type violation: value '[]' (Array) is not an instance of [Type Fixnum], Type violation: value '[]' (Array) is not an instance of [Type String], Type violation: value '[]' (Array) is not an instance of [Type Symbol]]")
192
+
193
+ end
194
+ end
195
+
196
+ describe "Enum" do
197
+ it "should accept a constant value" do
198
+ Test.isEnum(1,2,3).call(1)
199
+ Test.isEnum(1,2,3).call(2)
200
+ Test.isEnum(1,2,3).call(3)
201
+ end
202
+
203
+ it "should return [Enum ...]" do
204
+ Test.isEnum(1,2,3).to_s.should == "[Enum [1, 2, 3]]"
205
+ end
206
+
207
+ it "should raise error" do
208
+ expect {
209
+ Test.isEnum(1,2,3).call(4)
210
+ }.to raise_error(MooseX::Types::TypeCheckError,
211
+ "Enum Check violation: value '4' (Fixnum) is not [1, 2, 3]")
212
+ end
213
+ end
214
+
215
+ describe "Not" do
216
+ it "should accept values" do
217
+ Test.isNot(Test.isConstant(1)).call(0)
218
+ Test.isNot(Test.isType(String)).call(0)
219
+ Test.isNot(Test.isAnyOf(TrueClass, FalseClass)).call(nil)
220
+
221
+ Test.isNot(Test.isType(Array)).call({})
222
+ Test.isNot(Test.isEnum(1,2,3)).call(4)
223
+
224
+ Test.isNot(Test.isAnyOf(Fixnum, String, Symbol)).call([])
225
+ Test.isNot(Test.isAnyOf(TrueClass, FalseClass)).call(3)
226
+
227
+ Test.isNot(Test.isAllOf(Fixnum,Integer,Numeric, Test.isConstant(1))).call(2)
228
+ Test.isNot(Test.isAllOf(Fixnum,Integer,Numeric, Test.isConstant(1))).call(nil)
229
+ end
230
+
231
+ it "shuld return [NOT ...]" do
232
+ Test.isNot(Test.isConstant(1)).to_s.should == "[NOT [Constant: '1' (Fixnum)]]"
233
+ Test.isNot(Test.isType(String)).to_s.should == "[NOT [Type String]]"
234
+ Test.isNot(Test.isAnyOf(TrueClass, FalseClass)).to_s
235
+ .should == "[NOT [AnyOf [TrueClass, FalseClass]]]"
236
+
237
+ Test.isNot(Test.isType(Array)).to_s.should == "[NOT [Type Array]]"
238
+ Test.isNot(Test.isEnum(1,2,3)).to_s.should == "[NOT [Enum [1, 2, 3]]]"
239
+
240
+ Test.isNot(Test.isAnyOf(Fixnum, String, Symbol)).to_s
241
+ .should == "[NOT [AnyOf [Fixnum, String, Symbol]]]"
242
+
243
+
244
+ Test.isNot(Test.isAllOf(Fixnum,Integer,Numeric, Test.isConstant(1))).to_s
245
+ .should == "[NOT [AllOf [Fixnum, Integer, Numeric, [Constant: '1' (Fixnum)]]]]"
246
+ end
247
+
248
+ it "should raise error" do
249
+ expect {
250
+ Test.isNot(Test.isEnum(1,2,3)).call(2)
251
+ }.to raise_error(MooseX::Types::TypeCheckError,
252
+ "Not violation: value '2' (Fixnum) is not [Enum [1, 2, 3]]")
253
+ end
254
+ end
255
+
256
+ describe "Maybe" do
257
+ it "should accept value or nil" do
258
+ Test.isMaybe(Test.isConstant(9)).call(9)
259
+ Test.isMaybe(Test.isType(TrueClass)).call(true)
260
+ Test.isMaybe(Test.isEnum(1,2,3)).call(1)
261
+
262
+ Test.isMaybe(Test.isConstant(9)).call(nil)
263
+ Test.isMaybe(Test.isType(TrueClass)).call(nil)
264
+ Test.isMaybe(Test.isEnum(1,2,3)).call(nil)
265
+
266
+ Test.isMaybe(TrueClass).call(nil)
267
+ Test.isMaybe(TrueClass).call(true)
268
+
269
+ Test.isMaybe(Test.isAllOf(Fixnum,Integer,Numeric, Test.isConstant(1))).call(nil)
270
+ end
271
+
272
+ it "should return [Maybe [...]]" do
273
+ Test.isMaybe(Test.isConstant(9)).to_s.should == "[Maybe [Constant: '9' (Fixnum)]]"
274
+ Test.isMaybe(Test.isType(TrueClass)).to_s.should == "[Maybe [Type TrueClass]]"
275
+ Test.isMaybe(TrueClass).to_s.should == "[Maybe TrueClass]"
276
+ Test.isMaybe(Test.isEnum(1,2,3)).to_s.should == "[Maybe [Enum [1, 2, 3]]]"
277
+ Test.isMaybe(Test.isAllOf(Fixnum,Integer,Numeric, Test.isConstant(1))).to_s
278
+ .should == "[Maybe [AllOf [Fixnum, Integer, Numeric, [Constant: '1' (Fixnum)]]]]"
279
+ end
280
+
281
+ it "should raise error" do
282
+ expect {
283
+ Test.isMaybe(Test.isConstant(9)).call(8)
284
+ }.to raise_error(MooseX::Types::TypeCheckError,
285
+ "Maybe violation: caused by AnyOf Check violation: caused by [Constant violation: value '8' (Fixnum) is not '9' (Fixnum), Constant violation: value '8' (Fixnum) is not '' (NilClass)]")
286
+
287
+ expect {
288
+ Test.isMaybe(TrueClass).call(false)
289
+ }.to raise_error(MooseX::Types::TypeCheckError,
290
+ "Maybe violation: caused by AnyOf Check violation: caused by [Type violation: value 'false' (FalseClass) is not an instance of [Type TrueClass], Constant violation: value 'false' (FalseClass) is not '' (NilClass)]")
291
+
292
+ end
293
+ end
294
+
295
+ describe "Array" do
296
+ it "should accept values" do
297
+ Test.isArray().call([])
298
+ Test.isArray().call([1])
299
+ Test.isArray().call([1,2])
300
+
301
+ Test.isArray(Integer).call([])
302
+ Test.isArray(Integer).call([1])
303
+ Test.isArray(Integer).call([1,2])
304
+
305
+ Test.isArray(Test.isMaybe(Integer)).call([1,2,nil])
306
+ Test.isArray(Test.isArray(Integer)).call([[1,2],[3,4]])
307
+ end
308
+
309
+ it "should return [Array ]" do
310
+ Test.isArray().to_s.should == "[Array [Any]]"
311
+ Test.isArray(Integer).to_s.should == "[Array Integer]"
312
+ Test.isArray(Test.isMaybe(Integer)).to_s.should == "[Array [Maybe Integer]]"
313
+ Test.isArray(Test.isArray(Integer)).to_s.should == "[Array [Array Integer]]"
314
+ end
315
+
316
+ it "should raise error" do
317
+ expect {
318
+ Test.isArray(Test.isArray(Test.isMaybe(Integer))).call(nil)
319
+ }.to raise_error(MooseX::Types::TypeCheckError,
320
+ "Type violation: value '' (NilClass) is not an instance of [Type Array]")
321
+
322
+ expect {
323
+ Test.isArray(Test.isArray(Test.isMaybe(Integer))).call([false])
324
+ }.to raise_error(MooseX::Types::TypeCheckError,
325
+ "Array violation: caused by Type violation: value 'false' (FalseClass) is not an instance of [Type Array]")
326
+
327
+ expect {
328
+ Test.isArray(Test.isArray(Test.isMaybe(Integer))).call([[false]])
329
+ }.to raise_error(MooseX::Types::TypeCheckError,
330
+ "Array violation: caused by Array violation: caused by Maybe violation: caused by AnyOf Check violation: caused by [Type violation: value 'false' (FalseClass) is not an instance of [Type Integer], Constant violation: value 'false' (FalseClass) is not '' (NilClass)]")
331
+ end
332
+ end
333
+
334
+ describe "Hash" do
335
+ it "should accept values" do
336
+ Test.isHash().call({})
337
+ Test.isHash().call({ a: 1 })
338
+ Test.isHash().call({ 1 => 2})
339
+
340
+ Test.isHash(Integer => Integer).call({})
341
+ Test.isHash(Integer => Integer).call({1 => 2})
342
+ Test.isHash(Integer => Integer).call({2 => 1, 4 => 5})
343
+
344
+ Test.isHash(Symbol => Test.isArray(Test.isMaybe(Test.isEnum(1,2,3))))
345
+ .call( foo: [nil, 1,2,3], bar: [nil, 2], baz: [])
346
+ end
347
+
348
+ it "should return [Hash ]" do
349
+ Test.isHash()
350
+ .to_s.should == "[Hash [Any] => [Any]]"
351
+
352
+ Test.isHash(Integer => Integer)
353
+ .to_s.should == "[Hash Integer => Integer]"
354
+
355
+ Test.isHash(Symbol => Test.isArray(Test.isMaybe(Test.isEnum(1,2,3))))
356
+ .to_s.should == "[Hash Symbol => [Array [Maybe [Enum [1, 2, 3]]]]]"
357
+ end
358
+
359
+ it "should raise error" do
360
+ expect{
361
+ Test.isHash().call(nil)
362
+ }.to raise_error(MooseX::Types::TypeCheckError,
363
+ "Type violation: value '' (NilClass) is not an instance of [Type Hash]")
364
+ expect{
365
+ Test.isHash(Symbol => Integer).call({ 1 => 2})
366
+ }.to raise_error(MooseX::Types::TypeCheckError,
367
+ "Hash violation: caused by Type violation: value '1' (Fixnum) is not an instance of [Type Symbol]")
368
+ end
369
+ end
370
+
371
+ describe "Tuple" do
372
+ it "should accept values" do
373
+ Test.isTuple().call([])
374
+
375
+ Test.isTuple(Test.isAny).call([1])
376
+ Test.isTuple(Test.isAny, Test.isAny).call([1,2])
377
+
378
+ Test.isTuple(Integer).call([1])
379
+ Test.isTuple(Integer, Integer).call([1,2])
380
+
381
+ Test.isTuple(Integer, Symbol, Test.isAny, TrueClass).call([1,:symbol, nil, true])
382
+ end
383
+
384
+ it "should return [Tuple ]" do
385
+ Test.isTuple().to_s.should == "[Tuple []]"
386
+ Test.isTuple(Integer).to_s.should == "[Tuple [Integer]]"
387
+ Test.isTuple(Integer, Integer).to_s.should == "[Tuple [Integer, Integer]]"
388
+ Test.isTuple(Integer, Symbol, Test.isAny, TrueClass).to_s
389
+ .should == "[Tuple [Integer, Symbol, [Any], TrueClass]]"
390
+ end
391
+
392
+ it "should raise error" do
393
+ expect {
394
+ Test.isTuple().call([1])
395
+ }.to raise_error(MooseX::Types::TypeCheckError,
396
+ "Tuple violation: size should be 0 instead 1")
397
+ expect {
398
+ Test.isTuple(Integer).call([])
399
+ }.to raise_error(MooseX::Types::TypeCheckError,
400
+ "Tuple violation: size should be 1 instead 0")
401
+ expect {
402
+ Test.isTuple().call(nil)
403
+ }.to raise_error(MooseX::Types::TypeCheckError,
404
+ "Type violation: value '' (NilClass) is not an instance of [Type Array]")
405
+ expect {
406
+ Test.isTuple(Integer, Symbol, Test.isAny, TrueClass).call([1,:symbol, nil, false])
407
+ }.to raise_error(MooseX::Types::TypeCheckError,
408
+ "Tuple violation: on position 3 caused by Type violation: value 'false' (FalseClass) is not an instance of [Type TrueClass]")
409
+ end
410
+ end
411
+
412
+ describe "Set" do
413
+ it "should accept values" do
414
+ Test.isSet().call([])
415
+ Test.isSet().call([1])
416
+ Test.isSet().call([1,2])
417
+
418
+ Test.isSet(Integer).call([])
419
+ Test.isSet(Integer).call([1])
420
+ Test.isSet(Integer).call([1,2])
421
+ end
422
+
423
+ it "should return [Set ]" do
424
+ Test.isSet().to_s.should == "[Set [Any]]"
425
+ Test.isSet(Integer).to_s.should == "[Set Integer]"
426
+ Test.isSet(Test.isMaybe(Integer)).to_s.should == "[Set [Maybe Integer]]"
427
+ Test.isSet(Test.isArray(Integer)).to_s.should == "[Set [Array Integer]]"
428
+ end
429
+
430
+ it "should raise error" do
431
+ expect {
432
+ Test.isSet(Test.isArray(Test.isMaybe(Integer))).call(nil)
433
+ }.to raise_error(MooseX::Types::TypeCheckError,
434
+ "Type violation: value '' (NilClass) is not an instance of [Type Array]")
435
+
436
+ expect {
437
+ Test.isSet(Test.isArray(Test.isMaybe(Integer))).call([false])
438
+ }.to raise_error(MooseX::Types::TypeCheckError,
439
+ "Set violation: caused by Type violation: value 'false' (FalseClass) is not an instance of [Type Array]")
440
+
441
+ expect {
442
+ Test.isSet(Test.isArray(Test.isMaybe(Integer))).call([[false]])
443
+ }.to raise_error(MooseX::Types::TypeCheckError,
444
+ "Set violation: caused by Array violation: caused by Maybe violation: caused by AnyOf Check violation: caused by [Type violation: value 'false' (FalseClass) is not an instance of [Type Integer], Constant violation: value 'false' (FalseClass) is not '' (NilClass)]")
445
+
446
+ expect {
447
+ Test.isSet(Integer).call([1,2,2])
448
+ }.to raise_error(MooseX::Types::TypeCheckError,
449
+ "Set violation: has one or more non unique elements: {2=>2} (value => count)")
450
+ end
451
+ end
452
+
453
+ describe "hasMethods" do
454
+ class MyFoo
455
+ def bar ; end
456
+ def baz ; end
457
+ end
458
+
459
+ it "should verify if has methods" do
460
+ Test.hasMethods(:bar).call(MyFoo.new)
461
+ Test.hasMethods(:baz).call(MyFoo.new)
462
+ Test.hasMethods(:bar, :baz).call(MyFoo.new)
463
+ end
464
+
465
+ it "should return [hasMethods ...]" do
466
+ Test.hasMethods(:bar).to_s.should == "[hasMethods [:bar]]"
467
+ Test.hasMethods(:bar, :baz).to_s.should == "[hasMethods [:bar, :baz]]"
468
+ end
469
+
470
+ it "should raise error" do
471
+ expect {
472
+ Test.hasMethods(:bar, :baz, :bam).call(1)
473
+ }.to raise_error(MooseX::Types::TypeCheckError,
474
+ "hasMethods violation: object 1 (Fixnum) should implement method bar")
475
+ end
476
+ end
477
+ end