must 0.2.8 → 0.2.9

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,5 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
5
+ .ruby-version
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
@@ -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
- bool = targets.any?{|klass| is_a?(klass)}
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{ raise Invalid, Must::StructInfo::Differ.new(@object, target, "").execute.to_s }
113
+ block ||= proc{ Must::Differ.new(@object, target, "").execute! }
109
114
  valid?(struct?(target), &block)
110
115
  end
111
116
 
@@ -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
@@ -1,3 +1,3 @@
1
1
  module Must
2
- VERSION = "0.2.8"
2
+ VERSION = "0.2.9"
3
3
  end
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 ShouldNotEmpty < Invalid; end
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
@@ -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
@@ -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
- specify "show more info about struct differs" do
7
- lambda {
8
- obj.must.struct({String => [Hash]})
9
- }.should raise_error(/expected \{String=>\[Hash\]/)
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: 7
4
+ hash: 5
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 2
9
- - 8
10
- version: 0.2.8
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-02-22 00:00:00 Z
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
-
@@ -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