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 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