oval 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.fixtures.yml +3 -0
- data/.gitignore +18 -0
- data/.rspec +3 -0
- data/.scripts/build-module.sh +25 -0
- data/.travis.yml +22 -0
- data/.yardopts +4 -0
- data/CHANGELOG +2 -0
- data/Gemfile +17 -0
- data/LICENSE +13 -0
- data/Modulefile +8 -0
- data/README.md +280 -0
- data/README_DEVEL.md +27 -0
- data/Rakefile +25 -0
- data/lib/oval.rb +18 -0
- data/lib/oval/anything.rb +12 -0
- data/lib/oval/array_item.rb +25 -0
- data/lib/oval/base.rb +58 -0
- data/lib/oval/class_decl_base.rb +27 -0
- data/lib/oval/collection.rb +125 -0
- data/lib/oval/hash_item.rb +41 -0
- data/lib/oval/instance_of.rb +11 -0
- data/lib/oval/kind_of.rb +11 -0
- data/lib/oval/one_of.rb +36 -0
- data/lib/oval/options.rb +61 -0
- data/lib/oval/subclass_of.rb +11 -0
- data/oval.gemspec +19 -0
- data/spec/spec_helper.rb +13 -0
- data/spec/unit/oval/anything_spec.rb +38 -0
- data/spec/unit/oval/array_item_spec.rb +60 -0
- data/spec/unit/oval/base_spec.rb +184 -0
- data/spec/unit/oval/class_decl_base_spec.rb +73 -0
- data/spec/unit/oval/collection_spec.rb +267 -0
- data/spec/unit/oval/hash_item_spec.rb +146 -0
- data/spec/unit/oval/instance_of_spec.rb +44 -0
- data/spec/unit/oval/kind_of_spec.rb +45 -0
- data/spec/unit/oval/one_of_spec.rb +62 -0
- data/spec/unit/oval/options_spec.rb +215 -0
- data/spec/unit/oval/subclass_of_spec.rb +34 -0
- data/spec/unit/oval_spec.rb +75 -0
- metadata +123 -0
data/oval.gemspec
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
lib = File.expand_path(File.join(File.dirname(__FILE__),'lib'))
|
2
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
3
|
+
|
4
|
+
Gem::Specification.new do |gem|
|
5
|
+
gem.name = 'oval'
|
6
|
+
gem.version = '0.0.1'
|
7
|
+
gem.authors = ["Pawel Tomulik"]
|
8
|
+
gem.email = ["ptomulik@meil.pw.edu.pl"]
|
9
|
+
gem.description = %q{Validate options when passed to methods}
|
10
|
+
gem.summary = %q{Using hashes to pass options to methods is a very common ruby practice. With **Oval** method authors may restrict callers to pass only declared options that meet requirements described in a hash declaration.}
|
11
|
+
gem.homepage = "https://github.com/ptomulik/rubygems-oval"
|
12
|
+
gem.license = "Apache 2.0"
|
13
|
+
gem.files = `git ls-files`.split($/)
|
14
|
+
gem.executables = []
|
15
|
+
gem.test_files = gem.files.grep(/^(test|spec|features)/)
|
16
|
+
gem.require_paths = ["lib"]
|
17
|
+
|
18
|
+
gem.add_development_dependency "rake"
|
19
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'oval/anything'
|
3
|
+
describe Oval::Anything do
|
4
|
+
let(:subject) { described_class.instance }
|
5
|
+
context 'the class' do
|
6
|
+
it { described_class.should respond_to :instance }
|
7
|
+
it { described_class.should respond_to :[] }
|
8
|
+
it { described_class.should_not respond_to :new }
|
9
|
+
end
|
10
|
+
context 'an instance' do
|
11
|
+
it { should respond_to :validate }
|
12
|
+
end
|
13
|
+
describe "instance (i.e. class method called instance)" do
|
14
|
+
it "should return singleton" do
|
15
|
+
previous = described_class.instance
|
16
|
+
described_class.instance.should be previous
|
17
|
+
end
|
18
|
+
end
|
19
|
+
describe "[]" do
|
20
|
+
it "should == #{described_class}.instance" do
|
21
|
+
described_class.stubs(:instance).once.with().returns :ok
|
22
|
+
described_class[].should be :ok
|
23
|
+
end
|
24
|
+
end
|
25
|
+
describe "#validate" do
|
26
|
+
# It should accept anything, which is quite hard to test, so I put here
|
27
|
+
# some random stuff ...
|
28
|
+
[
|
29
|
+
:symbol, nil, 1, 2.1, '', Array, NilClass, Object, Module,
|
30
|
+
Class.new, /regex/
|
31
|
+
].each do |x|
|
32
|
+
context "validate(#{x.inspect})" do
|
33
|
+
let(:x) { x }
|
34
|
+
it { expect { subject.validate(x) }.to_not raise_error }
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require 'spec_helper.rb'
|
2
|
+
require 'oval/array_item.rb'
|
3
|
+
|
4
|
+
describe Oval::ArrayItem do
|
5
|
+
context 'the class' do
|
6
|
+
it { described_class.should respond_to :[] }
|
7
|
+
end
|
8
|
+
context 'an instance' do
|
9
|
+
let(:subject) { described_class[:item_decl0] }
|
10
|
+
it { should respond_to :validate }
|
11
|
+
it { should respond_to :item_decl }
|
12
|
+
end
|
13
|
+
|
14
|
+
describe "[]" do
|
15
|
+
context "#{described_class.name}[:item_decl0]" do
|
16
|
+
it "should == new(:item_decl0)" do
|
17
|
+
described_class.stubs(:new).once.with(:item_decl0).returns :ok
|
18
|
+
described_class[:item_decl0].should be :ok
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
describe "item_decl" do
|
24
|
+
let(:subject) { described_class[:item_decl0] }
|
25
|
+
context "#{described_class.name}[:item_decl0].item_decl" do
|
26
|
+
it { subject.item_decl.should be :item_decl0 }
|
27
|
+
end
|
28
|
+
context "when @item_decl = :item_decl1" do
|
29
|
+
before { subject.instance_variable_set(:@item_decl, :item_decl1) }
|
30
|
+
it { subject.item_decl.should be :item_decl1 }
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
describe "item_decl=" do
|
35
|
+
let(:subject) { described_class[:item_decl0] }
|
36
|
+
context "item_decl = :item_decl1" do
|
37
|
+
it "should assign @item_decl = :item_decl1" do
|
38
|
+
subject.send(:item_decl=, :item_decl1)
|
39
|
+
subject.instance_variable_get(:@item_decl).should be :item_decl1
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
describe "#validate" do
|
45
|
+
let(:subject) { described_class[:item_decl0] }
|
46
|
+
context "validate(:item1,0)" do
|
47
|
+
it 'should invoke self.class.ensure_match(:item1,:item_decl0,nil) once' do
|
48
|
+
described_class.expects(:ensure_match).once.with(:item1,:item_decl0,nil)
|
49
|
+
subject.validate(:item1,0)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
context "validate(:item1,0,'foo')" do
|
53
|
+
it 'should invoke self.class.ensure_match(:item1,:item_decl0,"foo[0]") once' do
|
54
|
+
described_class.expects(:ensure_match).once.with(:item1,:item_decl0,"foo[0]")
|
55
|
+
subject.validate(:item1,0,'foo')
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
@@ -0,0 +1,184 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'oval/base'
|
3
|
+
|
4
|
+
describe Oval::Base do
|
5
|
+
context "the class" do
|
6
|
+
[
|
7
|
+
:ensure_equal,
|
8
|
+
:ensure_match,
|
9
|
+
:[],
|
10
|
+
:for_subject,
|
11
|
+
:enumerate,
|
12
|
+
].each do |method|
|
13
|
+
it { described_class.should respond_to method }
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
context "an instance" do
|
18
|
+
let(:subject) { described_class[:shape0] }
|
19
|
+
[
|
20
|
+
:validate,
|
21
|
+
:for_subject,
|
22
|
+
:enumerate,
|
23
|
+
].each do |method|
|
24
|
+
it { should respond_to method }
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
describe "ensure_match" do
|
29
|
+
context "ensure_match(:foo,:bar)" do
|
30
|
+
it "should invoke ensure_equal(:foo,:bar,nil) once" do
|
31
|
+
described_class.expects(:ensure_equal).once.with(:foo,:bar,nil)
|
32
|
+
expect { described_class.ensure_match(:foo,:bar) }.to_not raise_error
|
33
|
+
end
|
34
|
+
end
|
35
|
+
context "ensure_match(:foo,:bar,'subj1')" do
|
36
|
+
it "should invoke ensure_equal(:foo,:bar,'subj1') once" do
|
37
|
+
described_class.expects(:ensure_equal).once.with(:foo,:bar,'subj1')
|
38
|
+
expect { described_class.ensure_match(:foo,:bar,'subj1') }.to_not raise_error
|
39
|
+
end
|
40
|
+
end
|
41
|
+
context "ensure_match(:foo,shape)" do
|
42
|
+
let(:shape) { described_class[:shape0] }
|
43
|
+
it "should invoke shape.validate(:foo,nil) once" do
|
44
|
+
shape.expects(:validate).once.with(:foo,nil)
|
45
|
+
expect { described_class.ensure_match(:foo,shape) }.to_not raise_error
|
46
|
+
end
|
47
|
+
end
|
48
|
+
context "ensure_match(:foo,shape,'subj1')" do
|
49
|
+
let(:shape) { described_class[:shape0] }
|
50
|
+
it "should invoke shape.validate(:foo,'subj1') once" do
|
51
|
+
shape.expects(:validate).once.with(:foo,'subj1')
|
52
|
+
expect { described_class.ensure_match(:foo,shape,'subj1') }.to_not raise_error
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
describe "[]" do
|
58
|
+
[ [], [:arg1], [:arg1,:arg2] ].each do |args|
|
59
|
+
context "[#{args.map{|x| x.inspect}.join(', ')}]" do
|
60
|
+
let(:args) { args }
|
61
|
+
it "should == new(#{args.map{|x| x.inspect}.join(', ')})" do
|
62
|
+
described_class.expects(:new).once.with(*args).returns :ok
|
63
|
+
described_class[*args].should be :ok
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
describe "#validate" do
|
70
|
+
let(:subject) { described_class[:shape0] }
|
71
|
+
let(:msg) { "This method should be overwritten by a subclass" }
|
72
|
+
[ [], [:arg1,:arg2,:arg3] ].each do |args|
|
73
|
+
context "validate(#{args.map{|x| x.inspect}.join(', ')})" do
|
74
|
+
let(:args) { args }
|
75
|
+
before { described_class.expects(:validate).never }
|
76
|
+
it { expect { subject.validate(*args) }.to raise_error ArgumentError }
|
77
|
+
end
|
78
|
+
end
|
79
|
+
context "validate(:value)" do
|
80
|
+
it { expect { subject.validate(:value) }.to raise_error NotImplementedError, msg}
|
81
|
+
end
|
82
|
+
context "validate(:value,:subj1)" do
|
83
|
+
it { expect { subject.validate(:value,:subj1) }.to raise_error NotImplementedError, msg}
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
## describe "#validate_shape" do
|
88
|
+
## let(:subject) { described_class[:shape0] }
|
89
|
+
## let(:msg) { "This method should be overwritten by a subclass" }
|
90
|
+
## [ [:arg1,:arg2] ].each do |args|
|
91
|
+
## context "validate_shape(#{args.map{|x| x.inspect}.join(', ')})" do
|
92
|
+
## let(:args) { args }
|
93
|
+
## it { expect { subject.validate_shape(*args) }.to raise_error ArgumentError }
|
94
|
+
## end
|
95
|
+
## end
|
96
|
+
## context "validate_shape()" do
|
97
|
+
## it { expect { subject.validate_shape() }.to raise_error NotImplementedError, msg}
|
98
|
+
## end
|
99
|
+
## context "validate_shape(:subj1)" do
|
100
|
+
## it { expect { subject.validate_shape(:subj1) }.to raise_error NotImplementedError, msg}
|
101
|
+
## end
|
102
|
+
## end
|
103
|
+
|
104
|
+
|
105
|
+
## describe "shape" do
|
106
|
+
#### before { described_class.stubs(:validate_shape) }
|
107
|
+
## context "new(:shape0).shape" do
|
108
|
+
## it { described_class.new(:shape0).shape.should be :shape0 }
|
109
|
+
## end
|
110
|
+
## context "when @shape == :shape1" do
|
111
|
+
## let(:subject) { described_class.new(:shape0) }
|
112
|
+
## before { subject.instance_variable_set(:@shape,:shape1) }
|
113
|
+
## it { subject.shape.should be :shape1 }
|
114
|
+
## end
|
115
|
+
## end
|
116
|
+
##
|
117
|
+
## describe "#shape=" do
|
118
|
+
#### before { described_class.stubs(:validate_shape) }
|
119
|
+
## let(:subject) { described_class.new(:shape0) }
|
120
|
+
## context "#shape = :shape1" do
|
121
|
+
#### it "should call self.class.validate_shape(:shape1) once" do
|
122
|
+
#### subject # reference before re-stubbing validate_shape
|
123
|
+
#### described_class.stubs(:validate_shape).never
|
124
|
+
#### described_class.stubs(:validate_shape).once.with(:shape1,'Base')
|
125
|
+
#### expect { subject.send(:shape=,:shape1) }.to_not raise_error
|
126
|
+
#### end
|
127
|
+
## it "should assign @shape = :shape1" do
|
128
|
+
## subject.send(:shape=, :shape1)
|
129
|
+
## subject.instance_variable_get(:@shape).should be :shape1
|
130
|
+
## end
|
131
|
+
## end
|
132
|
+
## end
|
133
|
+
|
134
|
+
describe "for_subject" do
|
135
|
+
[
|
136
|
+
[nil,""],
|
137
|
+
["Subj1", " for Subj1"],
|
138
|
+
[:subj, " for subj"],
|
139
|
+
].each do |arg,res|
|
140
|
+
context "for_subject(#{arg.inspect})" do
|
141
|
+
let(:arg) { arg }
|
142
|
+
let(:res) { res }
|
143
|
+
it { described_class.send(:for_subject,arg).should == res }
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
describe "#for_subject" do
|
149
|
+
## before { described_class.stubs(:validate_shape) }
|
150
|
+
let(:subject) { described_class.new(:shape0) }
|
151
|
+
context "for_subject(:subj1)" do
|
152
|
+
it "should == self.class.for_subject(subject)" do
|
153
|
+
described_class.expects(:for_subject).once.with(:subj1).returns :ok
|
154
|
+
subject.send(:for_subject,:subj1).should be :ok
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
describe "enumerate" do
|
160
|
+
[
|
161
|
+
[[[],'and'],'none'],
|
162
|
+
[[['one'],'and'],'"one"'],
|
163
|
+
[[['one','two'],'and'],'"one" and "two"'],
|
164
|
+
[[['one','two','three'],'and'],'"one", "two" and "three"'],
|
165
|
+
].each do |args,res|
|
166
|
+
context "enumerate(#{args.map{|x| x.inspect}.join(', ')})" do
|
167
|
+
let(:args) { args }
|
168
|
+
let(:res) { res }
|
169
|
+
it { described_class.send(:enumerate,*args).should == res }
|
170
|
+
end
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
describe "#enumerate" do
|
175
|
+
## before { described_class.stubs(:validate_shape) }
|
176
|
+
let(:subject) { described_class.new(:shape0) }
|
177
|
+
context "enumerate([],'and')" do
|
178
|
+
it "should == self.class.enumerate(subject)" do
|
179
|
+
described_class.expects(:enumerate).once.with([],'and').returns :ok
|
180
|
+
subject.send(:enumerate,[],'and').should be :ok
|
181
|
+
end
|
182
|
+
end
|
183
|
+
end
|
184
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'oval/class_decl_base'
|
3
|
+
|
4
|
+
describe Oval::ClassDeclBase do
|
5
|
+
context "the class" do
|
6
|
+
[
|
7
|
+
:[],
|
8
|
+
].each do |method|
|
9
|
+
it { described_class.should respond_to method }
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
context "an instance" do
|
14
|
+
let(:subject) { described_class[:klass0] }
|
15
|
+
before { described_class.any_instance.stubs(:validate_class) }
|
16
|
+
it { should be_kind_of Oval::Base }
|
17
|
+
[
|
18
|
+
:validate_class,
|
19
|
+
:klass,
|
20
|
+
:klass=,
|
21
|
+
].each do |method|
|
22
|
+
it { should respond_to method }
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
describe "#validate_class" do
|
27
|
+
let(:subject) { described_class.new(:klass0) }
|
28
|
+
before do
|
29
|
+
described_class.any_instance.stubs(:validate_class)
|
30
|
+
subject
|
31
|
+
described_class.any_instance.unstub(:validate_class)
|
32
|
+
end
|
33
|
+
context "validate_class(:symbol1)" do
|
34
|
+
let(:msg) { "Invalid class :symbol1 for ClassDeclBase" }
|
35
|
+
it { expect { subject.send(:validate_class,:symbol1) }.to raise_error Oval::DeclError, msg }
|
36
|
+
end
|
37
|
+
[ Array, String, NilClass ].each do |klass|
|
38
|
+
context "validate_class(#{klass.name})" do
|
39
|
+
let(:klass) { klass }
|
40
|
+
it { expect { subject.send(:validate_class,klass) }.to_not raise_error }
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
describe "klass" do
|
46
|
+
before { described_class.any_instance.stubs(:validate_class) }
|
47
|
+
context "new(:klass0).klass" do
|
48
|
+
it { described_class.new(:klass0).klass.should be :klass0 }
|
49
|
+
end
|
50
|
+
context "when @klass == :klass1" do
|
51
|
+
let(:subject) { described_class.new(:klass0) }
|
52
|
+
before { subject.instance_variable_set(:@klass,:klass1) }
|
53
|
+
it { subject.klass.should be :klass1 }
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
describe "#klass=" do
|
58
|
+
before { described_class.any_instance.stubs(:validate_class) }
|
59
|
+
let(:subject) { described_class.new(:klass0) }
|
60
|
+
context "#klass = :klass1" do
|
61
|
+
it "should call self.class.validate_class(:klass1) once" do
|
62
|
+
subject # reference before re-stubbing validate_class
|
63
|
+
subject.stubs(:validate_class).never
|
64
|
+
subject.stubs(:validate_class).once.with(:klass1)
|
65
|
+
expect { subject.send(:klass=,:klass1) }.to_not raise_error
|
66
|
+
end
|
67
|
+
it "should assign @klass = :klass1" do
|
68
|
+
subject.send(:klass=, :klass1)
|
69
|
+
subject.instance_variable_get(:@klass).should be :klass1
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,267 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'oval/collection'
|
3
|
+
require 'oval/one_of'
|
4
|
+
require 'oval/instance_of'
|
5
|
+
require 'oval/kind_of'
|
6
|
+
|
7
|
+
describe Oval::Collection do
|
8
|
+
## Anything = Oval::Anything
|
9
|
+
## SubclassOf = Oval::SubclassOf
|
10
|
+
## InstanceOf = Oval::InstanceOf
|
11
|
+
## KindOf = Oval::KindOf
|
12
|
+
## OneOf = Oval::OneOf
|
13
|
+
## DeclError = Oval::DeclError
|
14
|
+
## ValueError = Oval::ValueError
|
15
|
+
describe 'the class' do
|
16
|
+
it { described_class.should respond_to :[] }
|
17
|
+
it { described_class.should respond_to :new }
|
18
|
+
it { described_class.should respond_to :validate_class_decl }
|
19
|
+
end
|
20
|
+
describe 'an instance' do
|
21
|
+
let(:subject) { described_class[Array,nil] }
|
22
|
+
it { should respond_to :validate }
|
23
|
+
it { should respond_to :class_decl }
|
24
|
+
it { should respond_to :class_decl= }
|
25
|
+
it { should respond_to :item_decl }
|
26
|
+
it { should respond_to :item_decl= }
|
27
|
+
it { should respond_to :select_item_validator }
|
28
|
+
end
|
29
|
+
|
30
|
+
describe "[]" do
|
31
|
+
context "[]" do
|
32
|
+
it { expect { described_class[] }.to raise_error ArgumentError, /wrong number of arguments / }
|
33
|
+
end
|
34
|
+
context "[:arg1,:arg2,:arg3]" do
|
35
|
+
it { expect { described_class[:arg1,:arg2,:arg3] }.to raise_error ArgumentError, /wrong number of arguments / }
|
36
|
+
end
|
37
|
+
context "[:arg1]" do
|
38
|
+
it "should == new(:arg1,Oval::Anything[])" do
|
39
|
+
described_class.expects(:new).once.with(:arg1,Oval::Anything[]).returns :ok
|
40
|
+
described_class[:arg1].should be :ok
|
41
|
+
end
|
42
|
+
end
|
43
|
+
context "[:arg1,:arg2]" do
|
44
|
+
it "should == new(:arg1,:arg2)" do
|
45
|
+
described_class.expects(:new).once.with(:arg1,:arg2).returns :ok
|
46
|
+
described_class[:arg1,:arg2].should be :ok
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
describe "new" do
|
52
|
+
context "new(:arg1,:arg2)" do
|
53
|
+
it "should assign self.class_decl=:arg1 and self.item_decl=:arg2 in seqence" do
|
54
|
+
seq = sequence('assignments')
|
55
|
+
described_class.any_instance.expects(:class_decl=).once.with(:arg1).in_sequence(seq)
|
56
|
+
described_class.any_instance.expects(:item_decl=).once.with(:arg2).in_sequence(seq)
|
57
|
+
expect { described_class.new(:arg1,:arg2) }.to_not raise_error
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
describe "validate_class_decl" do
|
63
|
+
[
|
64
|
+
[Array, "Array"],
|
65
|
+
[Hash, "Hash" ],
|
66
|
+
[Class.new(Array), "Class.new(Array)" ],
|
67
|
+
[Class.new(Hash), "Class.new(Hash)" ],
|
68
|
+
[Oval::SubclassOf[Array], "Oval::SubclassOf[Array]" ],
|
69
|
+
[Oval::SubclassOf[Hash], "Oval::SubclassOf[Hash]" ],
|
70
|
+
[Oval::SubclassOf[Class.new(Array)], "Oval::SubclassOf[Class.new(Array)]" ],
|
71
|
+
[Oval::SubclassOf[Class.new(Hash)], "Oval::SubclassOf[Class.new(Hash)]" ],
|
72
|
+
].each do |decl,desc|
|
73
|
+
context "validate_class_decl(#{desc})" do
|
74
|
+
let(:decl) { decl }
|
75
|
+
it { expect { described_class.validate_class_decl(decl) }.to_not raise_error }
|
76
|
+
end
|
77
|
+
end
|
78
|
+
[ 'a', nil, 0, {}, [] ].each do |decl|
|
79
|
+
context "validate_class_decl(#{decl.inspect})" do
|
80
|
+
let(:decl) { decl }
|
81
|
+
let(:msg) { "Invalid collection class declarator #{decl.inspect}. Should be a (subclass of) Hash or Array" }
|
82
|
+
it { expect { described_class.validate_class_decl(decl) }.to raise_error Oval::DeclError, msg }
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
## describe "validate_item_decl" do
|
88
|
+
## [
|
89
|
+
## [Hash, "Hash"],
|
90
|
+
## [Class.new(Hash), "Class.new(Hash)" ],
|
91
|
+
## ].each do |class_decl,class_desc|
|
92
|
+
## context "validate_item_decl(:decl1, #{class_desc})" do
|
93
|
+
## let(:class_decl) { class_decl }
|
94
|
+
## it "should invoke validate_hash_item_decl(:decl1) once" do
|
95
|
+
## described_class.stubs(:validate_hash_item_decl).once.with(:decl1)
|
96
|
+
## expect { described_class.validate_item_decl(:decl1,class_decl) }.to_not raise_error
|
97
|
+
## end
|
98
|
+
## end
|
99
|
+
## end
|
100
|
+
## [
|
101
|
+
## [Array, "Array"],
|
102
|
+
## [Class.new(Array), "Class.new(Array)" ],
|
103
|
+
## ].each do |class_decl,class_desc|
|
104
|
+
## context "validate_item_decl(:decl1, #{class_desc})" do
|
105
|
+
## let(:class_decl) { class_decl }
|
106
|
+
## it "should not invoke validate_hash_item_decl(:decl1)" do
|
107
|
+
## described_class.stubs(:validate_hash_item_decl).never
|
108
|
+
## expect { described_class.validate_item_decl(:decl1,class_decl) }.to_not raise_error
|
109
|
+
## end
|
110
|
+
## end
|
111
|
+
## end
|
112
|
+
## end
|
113
|
+
|
114
|
+
describe "#class_decl" do
|
115
|
+
before do
|
116
|
+
described_class.stubs(:validate_class_decl)
|
117
|
+
described_class.any_instance.stubs(:item_decl=)
|
118
|
+
end
|
119
|
+
context "new(:class_decl0,:item_decl0).class_decl" do
|
120
|
+
it { described_class.new(:class_decl0,:item_decl0).class_decl.should be :class_decl0 }
|
121
|
+
end
|
122
|
+
context "when @class_decl == :class_decl1" do
|
123
|
+
let(:subject) { described_class.new(:class_decl0) }
|
124
|
+
before { subject.instance_variable_set(:@class_decl,:class_decl1) }
|
125
|
+
it { subject.class_decl.should be :class_decl1 }
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
describe "#class_decl=" do
|
130
|
+
before do
|
131
|
+
described_class.stubs(:validate_class_decl)
|
132
|
+
described_class.any_instance.stubs(:item_decl=)
|
133
|
+
end
|
134
|
+
let(:subject) { described_class.new(:class_decl0,:item_decl0) }
|
135
|
+
context "#class_decl = :class_decl1" do
|
136
|
+
it "should call self.class.validate_class_decl(:class_decl1) once" do
|
137
|
+
subject # reference before re-stubbing validate_class_decl
|
138
|
+
described_class.stubs(:validate_class_decl).never
|
139
|
+
described_class.stubs(:validate_class_decl).once.with(:class_decl1)
|
140
|
+
expect { subject.send(:class_decl=,:class_decl1) }.to_not raise_error
|
141
|
+
end
|
142
|
+
it "should assign @class_decl = :class_decl1" do
|
143
|
+
subject.send(:class_decl=, :class_decl1)
|
144
|
+
subject.instance_variable_get(:@class_decl).should be :class_decl1
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
describe "#item_decl" do
|
150
|
+
before do
|
151
|
+
described_class.any_instance.stubs(:class_decl=)
|
152
|
+
described_class.any_instance.stubs(:bind_item_validator)
|
153
|
+
end
|
154
|
+
context "new(:class_decl0, :item_decl0).item_decl" do
|
155
|
+
it { described_class.new(:class_decl0,:item_decl0).item_decl.should be :item_decl0 }
|
156
|
+
end
|
157
|
+
context "when @item_decl == :item_decl1" do
|
158
|
+
let(:subject) { described_class.new(:item_decl0) }
|
159
|
+
before { subject.instance_variable_set(:@item_decl,:item_decl1) }
|
160
|
+
it { subject.item_decl.should be :item_decl1 }
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
describe "#item_decl=" do
|
165
|
+
let(:subject) { described_class.new(:class_decl0,:item_decl0) }
|
166
|
+
before do
|
167
|
+
described_class.any_instance.stubs(:class_decl=)
|
168
|
+
described_class.any_instance.stubs(:bind_item_validator)
|
169
|
+
end
|
170
|
+
context "#item_decl = :item_decl1" do
|
171
|
+
it "should call bind_item_validator(:item_decl1) once" do
|
172
|
+
subject.expects(:bind_item_validator).once.with(:item_decl1)
|
173
|
+
expect { subject.send(:item_decl=,:item_decl1) }.to_not raise_error
|
174
|
+
end
|
175
|
+
it "should assign @item_decl = :item_decl1" do
|
176
|
+
subject.send(:item_decl=, :item_decl1)
|
177
|
+
subject.instance_variable_get(:@item_decl).should be :item_decl1
|
178
|
+
end
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
describe "#select_item_validator" do
|
183
|
+
before do
|
184
|
+
described_class.any_instance.stubs(:class_decl=).once.with(:class_decl0)
|
185
|
+
described_class.any_instance.stubs(:item_decl=).once.with(:item_decl0)
|
186
|
+
end
|
187
|
+
let(:subject) { described_class.new(:class_decl0,:item_decl0) }
|
188
|
+
[
|
189
|
+
[Hash, 'Hash'],
|
190
|
+
[Class.new(Hash), 'Class.new(Hash)'],
|
191
|
+
].each do |klass,desc|
|
192
|
+
context "when #klass == #{desc}" do
|
193
|
+
before { subject.stubs(:klass).with().returns(klass) }
|
194
|
+
it { subject.send(:select_item_validator).should be Oval::HashItem }
|
195
|
+
end
|
196
|
+
end
|
197
|
+
[
|
198
|
+
[Array, 'Array'],
|
199
|
+
[Class.new(Array), 'Class.new(Array)'],
|
200
|
+
].each do |klass,desc|
|
201
|
+
context "when #klass == #{desc}" do
|
202
|
+
before { subject.stubs(:klass).with().returns(klass) }
|
203
|
+
it { subject.send(:select_item_validator).should be Oval::ArrayItem }
|
204
|
+
end
|
205
|
+
end
|
206
|
+
[ String, Fixnum, 1, nil, 0 ].each do |klass|
|
207
|
+
context "when #klass == #{klass.inspect}" do
|
208
|
+
before { subject.stubs(:klass).with().returns(klass) }
|
209
|
+
let(:msg) { "Invalid class #{klass.inspect} assigned to klass. It seems like we have a bug in #{described_class.name}" }
|
210
|
+
it { expect { subject.send(:select_item_validator) }.to raise_error RuntimeError, msg }
|
211
|
+
end
|
212
|
+
end
|
213
|
+
end
|
214
|
+
|
215
|
+
describe "#validate" do
|
216
|
+
class HashSubclass < Hash; end
|
217
|
+
class ArraySubclass < Array; end
|
218
|
+
# Valid collections
|
219
|
+
[
|
220
|
+
#
|
221
|
+
# Hash
|
222
|
+
#
|
223
|
+
["Hash", Hash, Oval::Anything[], {:foo => :FOO}],
|
224
|
+
["Hash", Hash, Oval::Anything, {:foo => :FOO}],
|
225
|
+
["Hash", Hash, {Oval::Anything => Oval::Anything}, {:foo => :FOO}],
|
226
|
+
["HashSubclass", HashSubclass, {Oval::Anything => Oval::Anything}, HashSubclass[{:foo => :FOO}]],
|
227
|
+
["Oval::SubclassOf[Hash]", Oval::SubclassOf[Hash], {Oval::Anything => Oval::Anything}, HashSubclass[{:foo => :FOO}]],
|
228
|
+
|
229
|
+
["Hash", Hash, {Oval::InstanceOf[Symbol] => Oval::InstanceOf[Symbol]}, {:foo => :FOO}],
|
230
|
+
["Hash", Hash, {Oval::InstanceOf[String] => Oval::KindOf[Fixnum]}, {'one' => 1, 'two' => 2}],
|
231
|
+
#
|
232
|
+
# Array
|
233
|
+
#
|
234
|
+
["Array", Array, Oval::Anything[], [:foo, :bar]],
|
235
|
+
["Array", Array, Oval::Anything, [:foo,:bar]],
|
236
|
+
["ArraySubclass", ArraySubclass, Oval::Anything, ArraySubclass[:foo,:bar]],
|
237
|
+
["Oval::SubclassOf[Array]", Oval::SubclassOf[Array], Oval::Anything, ArraySubclass[:foo, :bar]],
|
238
|
+
].each do |class_desc,class_decl,item_decl,collection|
|
239
|
+
context "#{described_class.name}[#{class_desc},#{item_decl.inspect}].validate(#{collection.inspect},'collection')" do
|
240
|
+
let(:subject) { described_class[class_decl, item_decl] }
|
241
|
+
let(:collection) { collection}
|
242
|
+
it { expect { subject.validate(collection,'collection') }.to_not raise_error }
|
243
|
+
end
|
244
|
+
end
|
245
|
+
# Invalid collections
|
246
|
+
[
|
247
|
+
["Hash", Hash, {Oval::Anything => Oval::Anything}, :symbol, 'Invalid value Symbol for collection.class. Should be equal Hash'],
|
248
|
+
["Hash", Hash, {Oval::Anything => Oval::Anything}, [], 'Invalid value Array for collection.class. Should be equal Hash'],
|
249
|
+
["HashSubclass", HashSubclass, {Oval::Anything => Oval::Anything}, [], 'Invalid value Array for collection.class. Should be equal HashSubclass'],
|
250
|
+
["HashSubclass", HashSubclass, {Oval::Anything => Oval::Anything}, {:foo => :FOO}, 'Invalid value Hash for collection.class. Should be equal HashSubclass'],
|
251
|
+
["Array", Array, Oval::Anything, :symbol, 'Invalid value Symbol for collection.class. Should be equal Array'],
|
252
|
+
["Array", Array, Oval::Anything, {}, 'Invalid value Hash for collection.class. Should be equal Array'],
|
253
|
+
["ArraySubclass", ArraySubclass, Oval::Anything, {:foo => :FOO}, 'Invalid value Hash for collection.class. Should be equal ArraySubclass'],
|
254
|
+
["ArraySubclass", ArraySubclass, Oval::Anything, [:foo, :bar], 'Invalid value Array for collection.class. Should be equal ArraySubclass'],
|
255
|
+
["Hash", Hash, {Oval::InstanceOf[Symbol] => Oval::InstanceOf[Symbol]}, {:foo => :FOO, 'bar' => :BAR}, "Invalid object \"bar\" of type String for collection key. Should be an instance of Symbol"],
|
256
|
+
["Hash", Hash, {Oval::InstanceOf[String] => Oval::KindOf[Fixnum]}, {'one' => 1, 'two' => :TWO}, "Invalid object :TWO of type Symbol for collection[\"two\"]. Should be a kind of Fixnum"],
|
257
|
+
["Array", Array, Oval::InstanceOf[String], ['one', :two], "Invalid object :two of type Symbol for collection[1]. Should be an instance of String"],
|
258
|
+
].each do |class_desc,class_decl,item_decl, collection, msg|
|
259
|
+
context "#{described_class.name}[#{class_desc},#{item_decl.inspect}].validate(#{collection.inspect},'collection')" do
|
260
|
+
let(:subject) { described_class[class_decl, item_decl] }
|
261
|
+
let(:collection) { collection }
|
262
|
+
let(:msg) { msg }
|
263
|
+
it { expect { subject.validate(collection,'collection') }.to raise_error Oval::ValueError, msg}
|
264
|
+
end
|
265
|
+
end
|
266
|
+
end
|
267
|
+
end
|