must 0.2.8 → 0.2.9
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/.gitignore +5 -0
- data/Rakefile +0 -23
- data/lib/must/differ.rb +72 -0
- data/lib/must/rule.rb +8 -3
- data/lib/must/struct_info.rb +0 -50
- data/lib/must/version.rb +1 -1
- data/lib/must.rb +6 -1
- data/spec/coerced_spec.rb +47 -0
- data/spec/differ_spec.rb +70 -0
- data/spec/duck_spec.rb +68 -0
- data/spec/match_spec.rb +13 -0
- data/spec/must_spec.rb +96 -0
- data/spec/struct_info_spec.rb +72 -0
- data/spec/struct_spec.rb +116 -5
- metadata +12 -10
- data/test/coerced_test.rb +0 -39
- data/test/duck_test.rb +0 -97
- data/test/match_test.rb +0 -15
- data/test/must_test.rb +0 -64
- data/test/struct_info_test.rb +0 -57
- data/test/struct_test.rb +0 -64
data/.gitignore
ADDED
data/Rakefile
CHANGED
@@ -1,24 +1 @@
|
|
1
1
|
require "bundler/gem_tasks"
|
2
|
-
|
3
|
-
require 'rake'
|
4
|
-
require 'rake/testtask'
|
5
|
-
require 'rdoc/task'
|
6
|
-
|
7
|
-
desc 'Default: run unit tests.'
|
8
|
-
task :default => :test
|
9
|
-
|
10
|
-
desc 'Test the must plugin.'
|
11
|
-
Rake::TestTask.new(:test) do |t|
|
12
|
-
t.libs << 'lib'
|
13
|
-
t.pattern = 'test/**/*_test.rb'
|
14
|
-
t.verbose = true
|
15
|
-
end
|
16
|
-
|
17
|
-
desc 'Generate documentation for the must plugin.'
|
18
|
-
Rake::RDocTask.new(:rdoc) do |rdoc|
|
19
|
-
rdoc.rdoc_dir = 'rdoc'
|
20
|
-
rdoc.title = 'Must'
|
21
|
-
rdoc.options << '--line-numbers' << '--inline-source'
|
22
|
-
rdoc.rdoc_files.include('README')
|
23
|
-
rdoc.rdoc_files.include('lib/**/*.rb')
|
24
|
-
end
|
data/lib/must/differ.rb
ADDED
@@ -0,0 +1,72 @@
|
|
1
|
+
module Must
|
2
|
+
class Differ
|
3
|
+
attr_reader :a, :b, :path
|
4
|
+
|
5
|
+
def initialize(a, b, path)
|
6
|
+
@a, @b, @path = a, b, path
|
7
|
+
end
|
8
|
+
|
9
|
+
def eq_float?(a, b)
|
10
|
+
(a - b).abs <= 0.0000001
|
11
|
+
end
|
12
|
+
|
13
|
+
def eq_object?(a, b)
|
14
|
+
a == b
|
15
|
+
end
|
16
|
+
|
17
|
+
def execute!
|
18
|
+
unless a.class == b.class
|
19
|
+
failed ClassMismatch, "%s expected [%s], but got [%s]" % [path, a.class, b.class]
|
20
|
+
end
|
21
|
+
|
22
|
+
if a.is_a?(Array)
|
23
|
+
max = [a.size, b.size].max
|
24
|
+
max.times do |i|
|
25
|
+
Differ.new(a[i], b[i], "#{path}[#{i}]").execute!
|
26
|
+
end
|
27
|
+
return true
|
28
|
+
end
|
29
|
+
|
30
|
+
if a.is_a?(Hash)
|
31
|
+
(a.keys | b.keys).each do |key|
|
32
|
+
Differ.new(a[key], b[key], "#{path}[#{key}]").execute!
|
33
|
+
end
|
34
|
+
return true
|
35
|
+
end
|
36
|
+
|
37
|
+
eq =
|
38
|
+
case a
|
39
|
+
when Float; eq_float?(a, b)
|
40
|
+
else ; eq_object?(a, b)
|
41
|
+
end
|
42
|
+
|
43
|
+
unless eq
|
44
|
+
av = a.inspect.split(//)[0..50].join
|
45
|
+
bv = b.inspect.split(//)[0..50].join
|
46
|
+
failed ValueMismatch, "%s expected %s(%s), but got %s(%s)" % [path, av, a.class, bv, a.class]
|
47
|
+
end
|
48
|
+
|
49
|
+
return true
|
50
|
+
|
51
|
+
rescue Must::ClassMismatch => err
|
52
|
+
if a.class == b.class
|
53
|
+
as = Must::StructInfo.new(a).inspect
|
54
|
+
bs = Must::StructInfo.new(b).inspect
|
55
|
+
raise Must::StructMismatch, "%s expected %s, but got %s" % [path, as, bs]
|
56
|
+
else
|
57
|
+
raise
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def execute
|
62
|
+
execute!
|
63
|
+
return true
|
64
|
+
rescue Must::Invalid
|
65
|
+
return false
|
66
|
+
end
|
67
|
+
|
68
|
+
def failed(klass, msg)
|
69
|
+
raise klass, msg
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
data/lib/must/rule.rb
CHANGED
@@ -1,5 +1,4 @@
|
|
1
1
|
require 'set'
|
2
|
-
require "must/struct_info"
|
3
2
|
|
4
3
|
module Must
|
5
4
|
class Rule
|
@@ -40,7 +39,13 @@ module Must
|
|
40
39
|
end
|
41
40
|
|
42
41
|
def kind_of(*targets, &block)
|
43
|
-
|
42
|
+
if instance?(@object)
|
43
|
+
bool = targets.any?{|klass| is_a?(klass)}
|
44
|
+
else
|
45
|
+
# check ancestors when klass
|
46
|
+
bool = (@object.ancestors & targets).any?
|
47
|
+
end
|
48
|
+
|
44
49
|
block ||= proc {
|
45
50
|
target = targets.map{|i| instance?(i) ? i.class.name : i.name}.join('|')
|
46
51
|
target = "(#{target})" if targets.size > 1
|
@@ -105,7 +110,7 @@ module Must
|
|
105
110
|
end
|
106
111
|
|
107
112
|
def struct(target, &block)
|
108
|
-
block ||= proc{
|
113
|
+
block ||= proc{ Must::Differ.new(@object, target, "").execute! }
|
109
114
|
valid?(struct?(target), &block)
|
110
115
|
end
|
111
116
|
|
data/lib/must/struct_info.rb
CHANGED
@@ -75,56 +75,6 @@ module Must
|
|
75
75
|
extend self
|
76
76
|
end
|
77
77
|
|
78
|
-
class Differ
|
79
|
-
attr_reader :a, :b, :path
|
80
|
-
|
81
|
-
def initialize(a, b, path)
|
82
|
-
@a, @b, @path = a, b, path
|
83
|
-
end
|
84
|
-
|
85
|
-
def execute!
|
86
|
-
sa = StructInfo::new(a).inspect
|
87
|
-
sb = StructInfo::new(b).inspect
|
88
|
-
|
89
|
-
unless sa == sb
|
90
|
-
failed("%s expected %s, but got %s" % [path, sb, sa])
|
91
|
-
end
|
92
|
-
|
93
|
-
if a.class == Array
|
94
|
-
max = [a.size, b.size].max
|
95
|
-
(0...max).each do |i|
|
96
|
-
Differ.new(a[i], b[i], "#{path}[#{i}]").execute!
|
97
|
-
end
|
98
|
-
return true
|
99
|
-
end
|
100
|
-
|
101
|
-
if a.class == Hash
|
102
|
-
(a.keys | b.keys).each do |key|
|
103
|
-
Differ.new(a[key], b[key], "#{path}[#{key}]").execute!
|
104
|
-
end
|
105
|
-
return true
|
106
|
-
end
|
107
|
-
|
108
|
-
unless a == b
|
109
|
-
failed("%s expected %s, but got %s" % [path, a.inspect, b.inspect])
|
110
|
-
end
|
111
|
-
|
112
|
-
return nil
|
113
|
-
end
|
114
|
-
|
115
|
-
def execute
|
116
|
-
execute!
|
117
|
-
return nil
|
118
|
-
rescue => err
|
119
|
-
return err
|
120
|
-
end
|
121
|
-
|
122
|
-
private
|
123
|
-
def failed(msg)
|
124
|
-
raise msg
|
125
|
-
end
|
126
|
-
end
|
127
|
-
|
128
78
|
######################################################################
|
129
79
|
### StructInfo
|
130
80
|
|
data/lib/must/version.rb
CHANGED
data/lib/must.rb
CHANGED
@@ -3,7 +3,9 @@ require "must/version"
|
|
3
3
|
# Must
|
4
4
|
module Must
|
5
5
|
class Invalid < StandardError; end
|
6
|
-
class
|
6
|
+
class ClassMismatch < Invalid; end
|
7
|
+
class StructMismatch < Invalid; end
|
8
|
+
class ValueMismatch < Invalid; end
|
7
9
|
|
8
10
|
def must(*args, &block)
|
9
11
|
if args.size > 0
|
@@ -15,4 +17,7 @@ module Must
|
|
15
17
|
end
|
16
18
|
|
17
19
|
require "must/rule"
|
20
|
+
require "must/differ"
|
21
|
+
require "must/struct_info"
|
22
|
+
|
18
23
|
Object.__send__ :include, Must
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Must::Rule, "coerced" do
|
4
|
+
let(:obj) { {"xyz" => ["a","b"] } }
|
5
|
+
|
6
|
+
describe "is_a" do
|
7
|
+
specify "[OK]" do
|
8
|
+
1.must.be.coerced(Integer).should == 1
|
9
|
+
1.must.be.coerced(Integer, String).should == 1
|
10
|
+
1.must.be.coerced(String, Numeric).should == 1
|
11
|
+
end
|
12
|
+
|
13
|
+
specify "[NG]" do
|
14
|
+
lambda { "1".must.be.coerced(Integer) }.should raise_error(Must::Invalid)
|
15
|
+
lambda { "1".must.be.coerced(Integer, Range) }.should raise_error(Must::Invalid)
|
16
|
+
lambda { "1".must.be.coerced(Integer){raise NotImplementedError} }.should raise_error(NotImplementedError)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
describe "coercing" do
|
21
|
+
specify "[OK]" do
|
22
|
+
1.must.be.coerced(Integer, String=>proc{|i|i.to_i}).should == 1
|
23
|
+
"1".must.be.coerced(Integer, String=>proc{|i|i.to_i}).should == 1
|
24
|
+
"1".must.be.coerced(Integer, String=>proc{|i|i.to_i}, Range=>proc{|i|i.first}).should == 1
|
25
|
+
"1".must.be.coerced(Integer, Range, String=>proc{|i|i.to_i}, Range=>proc{|i|i.first}).should == 1
|
26
|
+
"1".must.be.coerced(File, Integer, Range, String=>proc{|i|i.to_i}, Range=>proc{|i|i.first}).should == 1
|
27
|
+
end
|
28
|
+
|
29
|
+
specify "[NG]" do
|
30
|
+
lambda { "1".must.be.coerced(Integer, String=>proc{|i| /a/}) }.should raise_error(Must::Invalid)
|
31
|
+
lambda { "1".must.be.coerced(Integer, String=>proc{|i| /a/}) {raise NotImplementedError} }.should raise_error(NotImplementedError)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
describe "cascaded" do
|
36
|
+
specify "[OK]" do
|
37
|
+
1.must.be.coerced(Integer, Symbol=>:to_s, String=>:to_i).should == 1
|
38
|
+
"1".must.be.coerced(Integer, Symbol=>:to_s, String=>:to_i).should == 1
|
39
|
+
:"1".must.be.coerced(Integer, Symbol=>:to_s, String=>:to_i).should == 1
|
40
|
+
end
|
41
|
+
|
42
|
+
specify "[NG] detect livelock" do
|
43
|
+
lambda {"1".must.be.coerced(Integer, Symbol=>:to_s, String=>:intern)}.should raise_error(Must::Invalid)
|
44
|
+
lambda {:"1".must.be.coerced(Integer, Symbol=>:to_s, String=>:intern)}.should raise_error(Must::Invalid)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
data/spec/differ_spec.rb
ADDED
@@ -0,0 +1,70 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Must::Differ do
|
4
|
+
let(:a) {}
|
5
|
+
let(:b) {}
|
6
|
+
let(:path) { "obj" }
|
7
|
+
|
8
|
+
subject { lambda { Must::Differ.new(a, b, path).execute! } }
|
9
|
+
|
10
|
+
context "(same class)" do
|
11
|
+
context "(same objects)" do
|
12
|
+
let(:a) { 1 }
|
13
|
+
let(:b) { 1 }
|
14
|
+
it { should_not raise_error }
|
15
|
+
end
|
16
|
+
|
17
|
+
context "(same values)" do
|
18
|
+
let(:a) { [1] }
|
19
|
+
let(:b) { [1] }
|
20
|
+
it { should_not raise_error }
|
21
|
+
end
|
22
|
+
|
23
|
+
context "(different values)" do
|
24
|
+
let(:a) { [1] }
|
25
|
+
let(:b) { [2] }
|
26
|
+
it { should raise_error(Must::ValueMismatch) }
|
27
|
+
end
|
28
|
+
|
29
|
+
context "(different hash)" do
|
30
|
+
let(:a) { {
|
31
|
+
"currency"=>"JPY",
|
32
|
+
"strategy"=>"version_1",
|
33
|
+
} }
|
34
|
+
let(:b) { {
|
35
|
+
"currency"=>"JPY",
|
36
|
+
"strategy"=>"classic",
|
37
|
+
} }
|
38
|
+
it { should raise_error(Must::ValueMismatch) }
|
39
|
+
it { should raise_error(/strategy/) }
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
context "(same struct)" do
|
44
|
+
context "(same objects)" do
|
45
|
+
let(:x) { [ { "host" => "x" }, { "host" => "y" } ] }
|
46
|
+
let(:a) { x }
|
47
|
+
let(:b) { x }
|
48
|
+
it { should_not raise_error }
|
49
|
+
end
|
50
|
+
|
51
|
+
context "(same values)" do
|
52
|
+
let(:a) { [ { "host" => "x" }, { "host" => "y" } ] }
|
53
|
+
let(:b) { [ { "host" => "x" }, { "host" => "y" } ] }
|
54
|
+
it { should_not raise_error }
|
55
|
+
end
|
56
|
+
|
57
|
+
context "(different values)" do
|
58
|
+
let(:a) { [ { "host" => "x" }, { "host" => "y" } ] }
|
59
|
+
let(:b) { [ { "host" => "x" }, { "host" => "z" } ] }
|
60
|
+
it { should raise_error(Must::ValueMismatch) }
|
61
|
+
end
|
62
|
+
|
63
|
+
context "(different struct)" do
|
64
|
+
let(:a) { [ { "host" => "x" }, { "host" => "y" } ] }
|
65
|
+
let(:b) { [ [ "host", "x" ], [ "host" , "y" ] ] }
|
66
|
+
it { should raise_error(Must::StructMismatch) }
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
data/spec/duck_spec.rb
ADDED
@@ -0,0 +1,68 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Must::Rule, "duck" do
|
4
|
+
class CFoo
|
5
|
+
def foo; 1; end
|
6
|
+
end
|
7
|
+
|
8
|
+
module MFoo
|
9
|
+
def foo; 1; end
|
10
|
+
end
|
11
|
+
|
12
|
+
describe "duck typing test" do
|
13
|
+
specify "[OK]" do
|
14
|
+
1.must.duck(:to_s ).should == 1
|
15
|
+
1.must.duck("to_s" ).should == 1
|
16
|
+
1.must.duck(".to_s").should == 1
|
17
|
+
|
18
|
+
CFoo.must.duck(:to_s ).should == CFoo
|
19
|
+
CFoo.must.duck("to_s" ).should == CFoo
|
20
|
+
CFoo.must.duck(".to_s").should == CFoo
|
21
|
+
|
22
|
+
MFoo.must.duck(:to_s ).should == MFoo
|
23
|
+
MFoo.must.duck("to_s" ).should == MFoo
|
24
|
+
MFoo.must.duck(".to_s").should == MFoo
|
25
|
+
end
|
26
|
+
|
27
|
+
specify "[NG]" do
|
28
|
+
lambda { 1.must.duck(:foo ) }.should raise_error(Must::Invalid)
|
29
|
+
lambda { 1.must.duck("foo" ) }.should raise_error(Must::Invalid)
|
30
|
+
lambda { 1.must.duck(".foo") }.should raise_error(Must::Invalid)
|
31
|
+
|
32
|
+
lambda { CFoo.must.duck(:foo ) }.should raise_error(Must::Invalid)
|
33
|
+
lambda { CFoo.must.duck("foo" ) }.should raise_error(Must::Invalid)
|
34
|
+
lambda { CFoo.must.duck(".foo") }.should raise_error(Must::Invalid)
|
35
|
+
|
36
|
+
lambda { MFoo.must.duck(:foo ) }.should raise_error(Must::Invalid)
|
37
|
+
lambda { MFoo.must.duck("foo" ) }.should raise_error(Must::Invalid)
|
38
|
+
lambda { MFoo.must.duck(".foo") }.should raise_error(Must::Invalid)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
context "(instance duck typing)" do
|
43
|
+
specify "[OK]" do
|
44
|
+
CFoo.must.duck("#foo").should == CFoo
|
45
|
+
MFoo.must.duck("#foo").should == MFoo
|
46
|
+
end
|
47
|
+
|
48
|
+
specify "[NG]" do
|
49
|
+
lambda { 1.must.duck("#bar") }.should raise_error(Must::Invalid)
|
50
|
+
lambda { CFoo.must.duck("#bar") }.should raise_error(Must::Invalid)
|
51
|
+
lambda { MFoo.must.duck("#bar") }.should raise_error(Must::Invalid)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
context "(duck bang)" do
|
56
|
+
specify "[OK]" do
|
57
|
+
1.must.duck!("to_s").should == "1"
|
58
|
+
end
|
59
|
+
|
60
|
+
specify "[NG]" do
|
61
|
+
lambda { 1.must.duck!("foo") }.should raise_error(Must::Invalid)
|
62
|
+
end
|
63
|
+
|
64
|
+
specify "callback" do
|
65
|
+
1.must.duck!("to_xxx") { 2 }
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
data/spec/match_spec.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Must::Rule, "match" do
|
4
|
+
specify "[OK]" do
|
5
|
+
1.must.match(0..3).should == 1
|
6
|
+
'b'.must.match('a'..'c').should == 'b'
|
7
|
+
end
|
8
|
+
|
9
|
+
specify "[NG]" do
|
10
|
+
lambda { 1.must.match(2..3) }.should raise_error(Must::Invalid)
|
11
|
+
lambda { 'a'.must.match('y'..'z') }.should raise_error(Must::Invalid)
|
12
|
+
end
|
13
|
+
end
|
data/spec/must_spec.rb
ADDED
@@ -0,0 +1,96 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Must::Rule, "must" do
|
4
|
+
def ok(&block)
|
5
|
+
block.should_not raise_error
|
6
|
+
end
|
7
|
+
|
8
|
+
def ng(error = Must::Invalid, &block)
|
9
|
+
block.should raise_error(error)
|
10
|
+
end
|
11
|
+
|
12
|
+
######################################################################
|
13
|
+
### must be
|
14
|
+
|
15
|
+
describe "be" do
|
16
|
+
specify "[OK]" do
|
17
|
+
1.must.be(1).should == 1
|
18
|
+
[1,2,3].must.be([1,2,3]).should == [1,2,3]
|
19
|
+
{:a=>1, "b"=>2}.must.be({:a=>1, "b"=>2}).should == {:a=>1, "b"=>2}
|
20
|
+
String.must.be(String).should == String
|
21
|
+
end
|
22
|
+
|
23
|
+
specify "[NG]" do
|
24
|
+
ng {1.must.be 2}
|
25
|
+
end
|
26
|
+
|
27
|
+
specify "callback" do
|
28
|
+
1.must.be(2){:error}.should == :error
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
######################################################################
|
33
|
+
### must not be blank
|
34
|
+
|
35
|
+
describe "not be blank" do
|
36
|
+
if Object.instance_methods.include?("blank?")
|
37
|
+
specify do
|
38
|
+
"ok".must.not.be.blank.should == "ok"
|
39
|
+
"ok".must.not.be.blank{"ng"}.should == "ok"
|
40
|
+
"".must.not.be.blank{"ng"}.should == "ng"
|
41
|
+
ng { "".must.not.be.blank }
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
|
47
|
+
######################################################################
|
48
|
+
### must(type)
|
49
|
+
|
50
|
+
describe "type" do
|
51
|
+
specify do
|
52
|
+
"ok".must(String).should == "ok"
|
53
|
+
"ok".must(Integer, String).should == "ok"
|
54
|
+
ng { "ok".must(Integer) }
|
55
|
+
end
|
56
|
+
|
57
|
+
specify "weird but it is" do
|
58
|
+
# NOTE: this passes because 1(integer) is a kind of 2(integer)
|
59
|
+
ok { 1.must(2) }
|
60
|
+
end
|
61
|
+
|
62
|
+
specify "callback" do
|
63
|
+
"ok".must(Integer){:error}.should == :error
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
######################################################################
|
68
|
+
### kind_of
|
69
|
+
|
70
|
+
describe "kind_of" do
|
71
|
+
specify do
|
72
|
+
"ok".must.be.kind_of(String).should == "ok"
|
73
|
+
ng {"ok".must.be.kind_of(Integer)}
|
74
|
+
end
|
75
|
+
|
76
|
+
specify "multiple args" do
|
77
|
+
"ok".must.be.kind_of(Integer,String).should == "ok"
|
78
|
+
"ok".must.be.kind_of(String,Integer).should == "ok"
|
79
|
+
ng { "ok".must.be.kind_of(Integer, Array) }
|
80
|
+
end
|
81
|
+
|
82
|
+
context "(class)" do
|
83
|
+
module KindOfTest
|
84
|
+
module Core; end
|
85
|
+
class Base
|
86
|
+
include Core
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
specify "check ancestors when module given" do
|
91
|
+
ok { KindOfTest::Base.must.be.kind_of(KindOfTest::Core) }
|
92
|
+
ng { KindOfTest::Base.must.be.kind_of(Numeric) }
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Must::StructInfo do
|
4
|
+
def struct(obj)
|
5
|
+
Must::StructInfo.new(obj)
|
6
|
+
end
|
7
|
+
|
8
|
+
######################################################################
|
9
|
+
### same?
|
10
|
+
|
11
|
+
describe "#same?" do
|
12
|
+
specify do
|
13
|
+
struct(1 ).same?(Integer).should == true
|
14
|
+
struct(1 ).same?(Numeric).should == true
|
15
|
+
struct(String ).same?(Integer).should == false
|
16
|
+
|
17
|
+
struct(Integer).same?(Integer).should == true
|
18
|
+
struct(Integer).same?(Numeric).should == true
|
19
|
+
struct(Fixnum ).same?(1 ).should == true
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
######################################################################
|
24
|
+
### types
|
25
|
+
|
26
|
+
describe "#types" do
|
27
|
+
specify do
|
28
|
+
struct(1).types.should == [Fixnum]
|
29
|
+
struct(:a=>{"1"=>0.25}).types.should == [Hash, Symbol, String, Float]
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
######################################################################
|
34
|
+
### struct
|
35
|
+
|
36
|
+
describe "#compact" do
|
37
|
+
specify do
|
38
|
+
struct(1 ).compact.should == Fixnum
|
39
|
+
struct({} ).compact.should == Hash
|
40
|
+
struct([] ).compact.should == Array
|
41
|
+
struct([1]).compact.should == [Fixnum]
|
42
|
+
|
43
|
+
struct( "a"=>1 ).compact.should == {String=>Fixnum}
|
44
|
+
struct( [{"1"=>0.2}] ).compact.should == [{String=>Float}]
|
45
|
+
|
46
|
+
struct( "1.1" => {"jp"=>[{:a=>0},{:b=>2}]} ).compact.should == {String=>{String=>[{Symbol=>Fixnum}]}}
|
47
|
+
end
|
48
|
+
|
49
|
+
specify "array is represented by first element for speed" do
|
50
|
+
struct([1, "a"]).compact.should == [Fixnum]
|
51
|
+
struct(["a", 1]).compact.should == [String]
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
######################################################################
|
56
|
+
### inspect
|
57
|
+
|
58
|
+
describe "#inspect" do
|
59
|
+
specify do
|
60
|
+
struct(1 ).inspect.should == "Fixnum"
|
61
|
+
struct({} ).inspect.should == "Hash"
|
62
|
+
struct([] ).inspect.should == "Array"
|
63
|
+
struct([1]).inspect.should == "[Fixnum]"
|
64
|
+
|
65
|
+
struct( "a"=>1 ).inspect.should == "{String=>Fixnum}"
|
66
|
+
struct(["1"=>0.1]).inspect.should == "[{String=>Float}]"
|
67
|
+
|
68
|
+
struct( "1.1" => {"jp"=>[{:a=>0},{:b=>2}]} ).inspect.should == "{String=>{String=>[{Symbol=>Fixnum}]}}"
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
data/spec/struct_spec.rb
CHANGED
@@ -1,11 +1,122 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
describe Must do
|
3
|
+
describe Must, "struct" do
|
4
4
|
let(:obj) { {"xyz" => ["a","b"] } }
|
5
5
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
6
|
+
def ok(type) obj.must.struct?(type) == true ; end
|
7
|
+
def ng(type) obj.must.struct?(type) == false; end
|
8
|
+
|
9
|
+
######################################################################
|
10
|
+
### error message
|
11
|
+
|
12
|
+
describe "#struct" do
|
13
|
+
subject { lambda { obj.must.struct({String => [Hash]}) } }
|
14
|
+
|
15
|
+
it { should raise_error(Must::StructMismatch) }
|
16
|
+
it { should raise_error(/\{String=>\[Hash\]\}/) }
|
17
|
+
end
|
18
|
+
|
19
|
+
######################################################################
|
20
|
+
### basic object
|
21
|
+
|
22
|
+
describe "basic object" do
|
23
|
+
context "[]" do
|
24
|
+
let(:obj) { [] }
|
25
|
+
specify do
|
26
|
+
ok []
|
27
|
+
ng({})
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
context "1" do
|
32
|
+
let(:obj) { 1 }
|
33
|
+
specify do
|
34
|
+
ok Integer
|
35
|
+
ok Fixnum
|
36
|
+
ok 2
|
37
|
+
ng String
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
context "Fixnum" do
|
42
|
+
let(:obj) { Fixnum }
|
43
|
+
specify do
|
44
|
+
ok Fixnum
|
45
|
+
ok 2
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
context "Integer" do
|
50
|
+
let(:obj) { Integer }
|
51
|
+
specify do
|
52
|
+
ng Fixnum
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
describe "composite object" do
|
58
|
+
context "(simple hash)" do
|
59
|
+
let(:obj) { {"foo" => 1} }
|
60
|
+
|
61
|
+
specify do
|
62
|
+
ok String => Integer
|
63
|
+
ng String
|
64
|
+
ng Array
|
65
|
+
ng [String]
|
66
|
+
ng String => String
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
context "([Hash])" do
|
71
|
+
let(:obj) { [{:a=>1}, {:a=>3}] }
|
72
|
+
|
73
|
+
specify do
|
74
|
+
ok [Hash]
|
75
|
+
ng [Array]
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
context "(Hash(String, Array(Hash)))" do
|
80
|
+
let(:obj) { {"foo" => [{:a=>1}, {:a=>3}]} }
|
81
|
+
|
82
|
+
specify do
|
83
|
+
ok Hash
|
84
|
+
ng Array
|
85
|
+
ok String => Array
|
86
|
+
ng Array => Array
|
87
|
+
ok String => [Hash]
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
|
92
|
+
context "(Hash(String, Array(Hash)))" do
|
93
|
+
let(:obj) { {"foo" => [{:a=>1}, {:a=>3}]} }
|
94
|
+
|
95
|
+
specify do
|
96
|
+
ok String => []
|
97
|
+
ok String => Array
|
98
|
+
ng String => Hash
|
99
|
+
ok String => [Hash]
|
100
|
+
|
101
|
+
ok String => Array(Hash)
|
102
|
+
ng String => [Array]
|
103
|
+
ng String => Array(String)
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
context "(accept {String => [Hash]})" do
|
108
|
+
def ok(obj); obj.must.struct?({String => [Hash]}).should == true ; end
|
109
|
+
def ng(obj); obj.must.struct?({String => [Hash]}).should == false; end
|
110
|
+
|
111
|
+
specify do
|
112
|
+
ok({})
|
113
|
+
ng []
|
114
|
+
ok "foo" => []
|
115
|
+
ng "foo" => {"gp"=>"-1"}
|
116
|
+
ok "foo" => [{"gp"=>"-1"}]
|
117
|
+
ok "foo" => [{"sid"=>"45064"}, {"gp"=>"-1"}]
|
118
|
+
ng "foo" => [[{"sid"=>"45064"}]]
|
119
|
+
end
|
120
|
+
end
|
10
121
|
end
|
11
122
|
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: must
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 5
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 2
|
9
|
-
-
|
10
|
-
version: 0.2.
|
9
|
+
- 9
|
10
|
+
version: 0.2.9
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- maiha
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2013-
|
18
|
+
date: 2013-08-22 00:00:00 Z
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
21
21
|
name: rspec
|
@@ -41,24 +41,26 @@ extensions: []
|
|
41
41
|
extra_rdoc_files: []
|
42
42
|
|
43
43
|
files:
|
44
|
+
- .gitignore
|
44
45
|
- Gemfile
|
45
46
|
- README
|
46
47
|
- Rakefile
|
47
48
|
- init.rb
|
48
49
|
- install.rb
|
49
50
|
- lib/must.rb
|
51
|
+
- lib/must/differ.rb
|
50
52
|
- lib/must/rule.rb
|
51
53
|
- lib/must/struct_info.rb
|
52
54
|
- lib/must/version.rb
|
53
55
|
- must.gemspec
|
56
|
+
- spec/coerced_spec.rb
|
57
|
+
- spec/differ_spec.rb
|
58
|
+
- spec/duck_spec.rb
|
59
|
+
- spec/match_spec.rb
|
60
|
+
- spec/must_spec.rb
|
54
61
|
- spec/spec_helper.rb
|
62
|
+
- spec/struct_info_spec.rb
|
55
63
|
- spec/struct_spec.rb
|
56
|
-
- test/coerced_test.rb
|
57
|
-
- test/duck_test.rb
|
58
|
-
- test/match_test.rb
|
59
|
-
- test/must_test.rb
|
60
|
-
- test/struct_info_test.rb
|
61
|
-
- test/struct_test.rb
|
62
64
|
homepage: http://github.com/maiha/must
|
63
65
|
licenses: []
|
64
66
|
|
data/test/coerced_test.rb
DELETED
@@ -1,39 +0,0 @@
|
|
1
|
-
require 'test/unit'
|
2
|
-
require 'rubygems'
|
3
|
-
require File.join(File.dirname(__FILE__), '../init')
|
4
|
-
|
5
|
-
class CoercedTest < Test::Unit::TestCase
|
6
|
-
def test_is_a_feature
|
7
|
-
assert_equal 1, 1.must.be.coerced(Integer)
|
8
|
-
assert_equal 1, 1.must.be.coerced(Integer, String)
|
9
|
-
assert_equal 1, 1.must.be.coerced(String, Numeric)
|
10
|
-
|
11
|
-
assert_raises(Invalid) { "1".must.be.coerced(Integer) }
|
12
|
-
assert_raises(Invalid) { "1".must.be.coerced(Integer, Range) }
|
13
|
-
assert_raises(NotImplementedError) { "1".must.be.coerced(Integer){raise NotImplementedError} }
|
14
|
-
end
|
15
|
-
|
16
|
-
def test_coecing_succeeded
|
17
|
-
assert_equal 1, 1.must.be.coerced(Integer, String=>proc{|i|i.to_i})
|
18
|
-
assert_equal 1, "1".must.be.coerced(Integer, String=>proc{|i|i.to_i})
|
19
|
-
assert_equal 1, "1".must.be.coerced(Integer, String=>proc{|i|i.to_i}, Range=>proc{|i|i.first})
|
20
|
-
assert_equal 1, "1".must.be.coerced(Integer, Range, String=>proc{|i|i.to_i}, Range=>proc{|i|i.first})
|
21
|
-
assert_equal 1, "1".must.be.coerced(File, Integer, Range, String=>proc{|i|i.to_i}, Range=>proc{|i|i.first})
|
22
|
-
end
|
23
|
-
|
24
|
-
def test_coecing_failed
|
25
|
-
assert_raises(Invalid) { "1".must.be.coerced(Integer, String=>proc{|i| /a/}) }
|
26
|
-
assert_raises(NotImplementedError) { "1".must.be.coerced(Integer, String=>proc{|i| /a/}){raise NotImplementedError} }
|
27
|
-
end
|
28
|
-
|
29
|
-
def test_cascaded_coecing_succeeded
|
30
|
-
assert_equal 1, 1.must.be.coerced(Integer, Symbol=>:to_s, String=>:to_i)
|
31
|
-
assert_equal 1, "1".must.be.coerced(Integer, Symbol=>:to_s, String=>:to_i)
|
32
|
-
assert_equal 1, :"1".must.be.coerced(Integer, Symbol=>:to_s, String=>:to_i)
|
33
|
-
end
|
34
|
-
|
35
|
-
def test_detect_livelock
|
36
|
-
assert_raises(Invalid){ "1".must.be.coerced(Integer, Symbol=>:to_s, String=>:intern)}
|
37
|
-
assert_raises(Invalid){:"1".must.be.coerced(Integer, Symbol=>:to_s, String=>:intern)}
|
38
|
-
end
|
39
|
-
end
|
data/test/duck_test.rb
DELETED
@@ -1,97 +0,0 @@
|
|
1
|
-
require 'test/unit'
|
2
|
-
require 'rubygems'
|
3
|
-
require File.join(File.dirname(__FILE__), '../init')
|
4
|
-
|
5
|
-
class DuckTest < Test::Unit::TestCase
|
6
|
-
class ClassFoo
|
7
|
-
def foo; 1; end
|
8
|
-
end
|
9
|
-
|
10
|
-
module ModuleFoo
|
11
|
-
def foo; 1; end
|
12
|
-
end
|
13
|
-
|
14
|
-
def test_itself_duck_type
|
15
|
-
# succeeded
|
16
|
-
assert_equal 1, 1.must.duck(:to_s)
|
17
|
-
assert_equal 1, 1.must.duck("to_s")
|
18
|
-
assert_equal 1, 1.must.duck(".to_s")
|
19
|
-
assert_equal ClassFoo, ClassFoo.must.duck(:to_s)
|
20
|
-
assert_equal ClassFoo, ClassFoo.must.duck("to_s")
|
21
|
-
assert_equal ClassFoo, ClassFoo.must.duck(".to_s")
|
22
|
-
assert_equal ModuleFoo, ModuleFoo.must.duck(:to_s)
|
23
|
-
assert_equal ModuleFoo, ModuleFoo.must.duck("to_s")
|
24
|
-
assert_equal ModuleFoo, ModuleFoo.must.duck(".to_s")
|
25
|
-
|
26
|
-
# failed
|
27
|
-
assert_raises(Invalid) { 1.must.duck(:foo) }
|
28
|
-
assert_raises(Invalid) { 1.must.duck("foo") }
|
29
|
-
assert_raises(Invalid) { 1.must.duck(".foo") }
|
30
|
-
assert_raises(Invalid) { ClassFoo.must.duck(:foo) }
|
31
|
-
assert_raises(Invalid) { ClassFoo.must.duck("foo") }
|
32
|
-
assert_raises(Invalid) { ClassFoo.must.duck(".foo") }
|
33
|
-
assert_raises(Invalid) { ModuleFoo.must.duck(:foo) }
|
34
|
-
assert_raises(Invalid) { ModuleFoo.must.duck("foo") }
|
35
|
-
assert_raises(Invalid) { ModuleFoo.must.duck(".foo") }
|
36
|
-
end
|
37
|
-
|
38
|
-
def test_instance_duck_type
|
39
|
-
# succeeded
|
40
|
-
assert_equal ClassFoo, ClassFoo.must.duck("#foo")
|
41
|
-
assert_equal ModuleFoo, ModuleFoo.must.duck("#foo")
|
42
|
-
|
43
|
-
# failed
|
44
|
-
assert_raises(Invalid) { 1.must.duck("#bar") } # instance object
|
45
|
-
assert_raises(Invalid) { ClassFoo.must.duck("#bar") }
|
46
|
-
assert_raises(Invalid) { ModuleFoo.must.duck("#bar") }
|
47
|
-
end
|
48
|
-
|
49
|
-
def test_itself_duck_test
|
50
|
-
# succeeded
|
51
|
-
assert_equal true, 1.must.duck?(:to_s)
|
52
|
-
assert_equal true, 1.must.duck?("to_s")
|
53
|
-
assert_equal true, 1.must.duck?(".to_s")
|
54
|
-
assert_equal true, ClassFoo.must.duck?(:to_s)
|
55
|
-
assert_equal true, ClassFoo.must.duck?("to_s")
|
56
|
-
assert_equal true, ClassFoo.must.duck?(".to_s")
|
57
|
-
assert_equal true, ModuleFoo.must.duck?(:to_s)
|
58
|
-
assert_equal true, ModuleFoo.must.duck?("to_s")
|
59
|
-
assert_equal true, ModuleFoo.must.duck?(".to_s")
|
60
|
-
|
61
|
-
# failed
|
62
|
-
assert_equal false, 1.must.duck?(:foo)
|
63
|
-
assert_equal false, 1.must.duck?("foo")
|
64
|
-
assert_equal false, 1.must.duck?(".foo")
|
65
|
-
assert_equal false, ClassFoo.must.duck?(:foo)
|
66
|
-
assert_equal false, ClassFoo.must.duck?("foo")
|
67
|
-
assert_equal false, ClassFoo.must.duck?(".foo")
|
68
|
-
assert_equal false, ModuleFoo.must.duck?(:foo)
|
69
|
-
assert_equal false, ModuleFoo.must.duck?("foo")
|
70
|
-
assert_equal false, ModuleFoo.must.duck?(".foo")
|
71
|
-
end
|
72
|
-
|
73
|
-
def test_instance_duck_test
|
74
|
-
# succeeded
|
75
|
-
assert_equal true, ClassFoo.must.duck?("#foo")
|
76
|
-
assert_equal true, ModuleFoo.must.duck?("#foo")
|
77
|
-
|
78
|
-
# failed
|
79
|
-
assert_equal false, 1.must.duck?("#bar") # instance object
|
80
|
-
assert_equal false, ClassFoo.must.duck?("#bar")
|
81
|
-
assert_equal false, ModuleFoo.must.duck?("#bar")
|
82
|
-
end
|
83
|
-
|
84
|
-
def test_duck_bang
|
85
|
-
assert_equal "1", 1.must.duck!("to_s")
|
86
|
-
end
|
87
|
-
|
88
|
-
def test_duck_bang_raises_if_not_defined
|
89
|
-
assert_raise(Must::Invalid) {
|
90
|
-
ClassFoo.must.duck!("foo")
|
91
|
-
}
|
92
|
-
end
|
93
|
-
|
94
|
-
def test_duck_bang_calls_block_if_not_defined
|
95
|
-
assert_equal 2, 1.must.duck!("to_xxx") { 2 }
|
96
|
-
end
|
97
|
-
end
|
data/test/match_test.rb
DELETED
@@ -1,15 +0,0 @@
|
|
1
|
-
require 'test/unit'
|
2
|
-
require 'rubygems'
|
3
|
-
require File.join(File.dirname(__FILE__), '../init')
|
4
|
-
|
5
|
-
class MatchTest < Test::Unit::TestCase
|
6
|
-
def test_match_range
|
7
|
-
# succeeded
|
8
|
-
assert_equal 1, 1.must.match(0..3)
|
9
|
-
assert_equal 'b', 'b'.must.match('a'..'c')
|
10
|
-
|
11
|
-
# failed
|
12
|
-
assert_raises(Invalid) { 1.must.match(2..3) }
|
13
|
-
assert_raises(Invalid) { 'a'.must.match('y'..'z') }
|
14
|
-
end
|
15
|
-
end
|
data/test/must_test.rb
DELETED
@@ -1,64 +0,0 @@
|
|
1
|
-
require 'test/unit'
|
2
|
-
require 'rubygems'
|
3
|
-
require File.join(File.dirname(__FILE__), '../init')
|
4
|
-
|
5
|
-
class MustTest < Test::Unit::TestCase
|
6
|
-
|
7
|
-
######################################################################
|
8
|
-
### must be
|
9
|
-
|
10
|
-
def test_must_be
|
11
|
-
assert_nothing_raised {1.must.be 1}
|
12
|
-
assert_nothing_raised {[1,2,3].must.be [1,2,3]}
|
13
|
-
assert_nothing_raised {{:a=>1, "b"=>2}.must.be({:a=>1, "b"=>2})}
|
14
|
-
assert_nothing_raised {String.must.be String}
|
15
|
-
end
|
16
|
-
|
17
|
-
def test_must_be_error
|
18
|
-
assert_raises(Invalid) {1.must.be 2}
|
19
|
-
end
|
20
|
-
|
21
|
-
def test_must_be_with_block
|
22
|
-
assert_equal :error, 1.must.be(2) {:error}
|
23
|
-
end
|
24
|
-
|
25
|
-
def test_must_not_be_blank
|
26
|
-
if Object.instance_methods.include?("blank?")
|
27
|
-
assert_equal "ok", "ok".must.not.be.blank
|
28
|
-
assert_equal "ok", "ok".must.not.be.blank {"ng"}
|
29
|
-
assert_equal "ng", "".must.not.be.blank {"ng"}
|
30
|
-
assert_raises(Invalid) {"".must.not.be.blank}
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
######################################################################
|
35
|
-
### must(xxx)
|
36
|
-
|
37
|
-
def test_must_accepts_args_as_kind_of
|
38
|
-
assert_equal "ok", "ok".must(String)
|
39
|
-
assert_raises(Invalid) {"ok".must(Integer)}
|
40
|
-
assert_equal "ok", "ok".must(Integer, String)
|
41
|
-
|
42
|
-
# NOTE: this passes because 1(integer) is a kind of 2(integer)
|
43
|
-
assert_equal 1, 1.must(2)
|
44
|
-
end
|
45
|
-
|
46
|
-
def test_must_with_block
|
47
|
-
assert_equal :error, "ok".must(Integer) {:error}
|
48
|
-
end
|
49
|
-
|
50
|
-
######################################################################
|
51
|
-
### kind_of
|
52
|
-
|
53
|
-
def test_kind_of
|
54
|
-
assert_equal "ok", "ok".must.be.kind_of(String)
|
55
|
-
assert_raises(Invalid) {"ok".must.be.kind_of(Integer)}
|
56
|
-
end
|
57
|
-
|
58
|
-
def test_kind_of_several_args
|
59
|
-
assert_equal "ok", "ok".must.be.kind_of(Integer,String)
|
60
|
-
assert_equal "ok", "ok".must.be.kind_of(String,Integer)
|
61
|
-
assert_raises(Invalid) {"ok".must.be.kind_of(Integer, Array)}
|
62
|
-
end
|
63
|
-
end
|
64
|
-
|
data/test/struct_info_test.rb
DELETED
@@ -1,57 +0,0 @@
|
|
1
|
-
require 'test/unit'
|
2
|
-
require 'rubygems'
|
3
|
-
require File.join(File.dirname(__FILE__), '../init')
|
4
|
-
|
5
|
-
class StructInfoTest < Test::Unit::TestCase
|
6
|
-
######################################################################
|
7
|
-
### same?
|
8
|
-
|
9
|
-
def test_same_p
|
10
|
-
assert Must::StructInfo.new(1).same?(Integer)
|
11
|
-
assert Must::StructInfo.new(1).same?(Numeric)
|
12
|
-
assert ! Must::StructInfo.new(1).same?(String)
|
13
|
-
|
14
|
-
assert Must::StructInfo.new(Integer).same?(Integer)
|
15
|
-
assert Must::StructInfo.new(Integer).same?(Numeric)
|
16
|
-
assert Must::StructInfo.new(Fixnum).same?(1)
|
17
|
-
end
|
18
|
-
|
19
|
-
######################################################################
|
20
|
-
### types
|
21
|
-
|
22
|
-
def test_types
|
23
|
-
assert_equal [Fixnum], Must::StructInfo.new(1).types
|
24
|
-
assert_equal [Hash, Symbol, String, Float], Must::StructInfo.new({:a=>{"1"=>0.25}}).types
|
25
|
-
end
|
26
|
-
|
27
|
-
######################################################################
|
28
|
-
### struct
|
29
|
-
|
30
|
-
def test_compact
|
31
|
-
assert_equal(Fixnum, Must::StructInfo.new(1).compact)
|
32
|
-
assert_equal(Hash, Must::StructInfo.new({}).compact)
|
33
|
-
assert_equal(Array, Must::StructInfo.new([]).compact)
|
34
|
-
assert_equal([Fixnum], Must::StructInfo.new([1]).compact)
|
35
|
-
assert_equal({String=>Fixnum}, Must::StructInfo.new({"a"=>1}).compact)
|
36
|
-
assert_equal([{String=>Float}], Must::StructInfo.new([{"1"=>0.25}]).compact)
|
37
|
-
assert_equal({String=>{String=>[{Symbol=>Fixnum}]}}, Must::StructInfo.new({"1.1" => {"jp"=>[{:a=>0},{:b=>2}]}}).compact)
|
38
|
-
end
|
39
|
-
|
40
|
-
def test_compact_array_into_first_element
|
41
|
-
assert_equal [Fixnum], Must::StructInfo.new([1, "a"]).compact
|
42
|
-
assert_equal [String], Must::StructInfo.new(["a", 1]).compact
|
43
|
-
end
|
44
|
-
|
45
|
-
######################################################################
|
46
|
-
### pp
|
47
|
-
|
48
|
-
def test_inspect
|
49
|
-
assert_equal "Fixnum", Must::StructInfo.new(1).inspect
|
50
|
-
assert_equal "Hash", Must::StructInfo.new({}).inspect
|
51
|
-
assert_equal "Array", Must::StructInfo.new([]).inspect
|
52
|
-
assert_equal "[Fixnum]", Must::StructInfo.new([1]).inspect
|
53
|
-
assert_equal "{String=>Fixnum}", Must::StructInfo.new({"a"=>1}).inspect
|
54
|
-
assert_equal "[{String=>Float}]", Must::StructInfo.new([{"1"=>0.25}]).inspect
|
55
|
-
assert_equal "{String=>{String=>[{Symbol=>Fixnum}]}}", Must::StructInfo.new({"1.1" => {"jp"=>[{:a=>0},{:b=>2}]}}).inspect
|
56
|
-
end
|
57
|
-
end
|
data/test/struct_test.rb
DELETED
@@ -1,64 +0,0 @@
|
|
1
|
-
require 'test/unit'
|
2
|
-
require 'rubygems'
|
3
|
-
require File.join(File.dirname(__FILE__), '../init')
|
4
|
-
|
5
|
-
class StructTest < Test::Unit::TestCase
|
6
|
-
def test_struct_basic_object
|
7
|
-
assert [].must.struct?([])
|
8
|
-
assert ! [].must.struct?({})
|
9
|
-
|
10
|
-
assert 1.must.struct?(Integer)
|
11
|
-
assert 1.must.struct?(Fixnum)
|
12
|
-
assert 1.must.struct?(2)
|
13
|
-
assert ! 1.must.struct?(String)
|
14
|
-
assert Fixnum.must.struct?(Fixnum)
|
15
|
-
assert Fixnum.must.struct?(2)
|
16
|
-
assert ! Integer.must.struct?(Fixnum)
|
17
|
-
end
|
18
|
-
|
19
|
-
def test_struct_composite_objects
|
20
|
-
obj = {"foo" => 1}
|
21
|
-
assert obj.must.struct?({String => Integer})
|
22
|
-
assert ! obj.must.struct?(String)
|
23
|
-
assert ! obj.must.struct?(Array)
|
24
|
-
assert ! obj.must.struct?([String])
|
25
|
-
assert ! obj.must.struct?({String => String})
|
26
|
-
|
27
|
-
obj = [{:a=>1}, {:a=>3}]
|
28
|
-
assert obj.must.struct?([Hash])
|
29
|
-
assert ! obj.must.struct?([Array])
|
30
|
-
|
31
|
-
obj = {"foo" => [{:a=>1}, {:a=>3}]}
|
32
|
-
assert obj.must.struct?(Hash)
|
33
|
-
assert ! obj.must.struct?(Array)
|
34
|
-
assert obj.must.struct?({String => Array})
|
35
|
-
assert ! obj.must.struct?({Array => Array})
|
36
|
-
assert obj.must.struct?({String => [Hash]})
|
37
|
-
|
38
|
-
obj = {"foo" => [{:a=>1}, {:a=>3}]}
|
39
|
-
assert obj.must.struct?({String => []})
|
40
|
-
assert obj.must.struct?({String => Array})
|
41
|
-
assert ! obj.must.struct?({String => Hash})
|
42
|
-
assert obj.must.struct?({String => [Hash]})
|
43
|
-
assert obj.must.struct?({String => Array(Hash)})
|
44
|
-
assert ! obj.must.struct?({String => [Array]})
|
45
|
-
assert ! obj.must.struct?({String => Array(String)})
|
46
|
-
end
|
47
|
-
|
48
|
-
def test_struct_complicated
|
49
|
-
def ok(obj)
|
50
|
-
assert_equal obj, obj.must.struct({String => [Hash]})
|
51
|
-
end
|
52
|
-
def ng(obj)
|
53
|
-
assert_raises(Invalid){ obj.must.struct({String => [Hash]})}
|
54
|
-
end
|
55
|
-
|
56
|
-
ok({})
|
57
|
-
ng []
|
58
|
-
ok "foo" => []
|
59
|
-
ng "foo" => {"gp"=>"-1"}
|
60
|
-
ok "foo" => [{"gp"=>"-1"}]
|
61
|
-
ok "foo" => [{"sid"=>"45064"}, {"gp"=>"-1"}]
|
62
|
-
ng "foo" => [[{"sid"=>"45064"}]]
|
63
|
-
end
|
64
|
-
end
|