aboutsummaryrefslogtreecommitdiffstats
path: root/spec/rubyspec/core/comparable/equal_value_spec.rb
blob: 2bc22771b44d40e0bf7c1ce4504c0f421e613bdb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
require File.expand_path('../../../spec_helper', __FILE__)
require File.expand_path('../fixtures/classes', __FILE__)

describe "Comparable#==" do
  a = b = nil
  before :each do
    a = ComparableSpecs::Weird.new(0)
    b = ComparableSpecs::Weird.new(10)
  end

  it "returns true if other is the same as self" do
    (a == a).should == true
    (b == b).should == true
  end

  it "calls #<=> on self with other and returns true if #<=> returns 0" do
    a.should_receive(:<=>).once.and_return(0)
    (a == b).should == true
  end

  it "calls #<=> on self with other and returns true if #<=> returns 0.0" do
    a.should_receive(:<=>).once.and_return(0.0)
    (a == b).should == true
  end

  it "returns false if calling #<=> on self returns a positive Integer" do
    a.should_receive(:<=>).once.and_return(1)
    (a == b).should == false
  end

  it "returns false if calling #<=> on self returns a negative Integer" do
    a.should_receive(:<=>).once.and_return(-1)
    (a == b).should == false
  end

  context "when #<=> returns nil" do
    before :each do
      a.should_receive(:<=>).once.and_return(nil)
    end

    it "returns false" do
      (a == b).should be_false
    end
  end

  context "when #<=> returns nor nil neither an Integer" do
    before :each do
      a.should_receive(:<=>).once.and_return("abc")
    end

    ruby_version_is ""..."2.3" do
      it "returns false" do
        (a == b).should be_false
      end
    end

    ruby_version_is "2.3" do
      it "raises an ArgumentError" do
        lambda { (a == b) }.should raise_error(ArgumentError)
      end
    end
  end

  context "when #<=> raises an exception" do
    context "if it is a StandardError" do
      before :each do
        a.should_receive(:<=>).once.and_raise(StandardError)
      end

      ruby_version_is ""..."2.3" do
        # Behaviour confirmed by MRI test suite
        it "returns false" do
          (a == b).should be_false
        end
      end

      ruby_version_is "2.3" do
        it "lets it go through" do
          lambda { (a == b) }.should raise_error(StandardError)
        end
      end
    end

    context "if it is a subclass of StandardError" do
      # TypeError < StandardError
      before :each do
        a.should_receive(:<=>).once.and_raise(TypeError)
      end

      ruby_version_is ""..."2.3" do
        it "returns false" do
          (a == b).should be_false
        end
      end

      ruby_version_is "2.3" do
        it "lets it go through" do
          lambda { (a == b) }.should raise_error(TypeError)
        end
      end
    end

    it "lets it go through if it is not a StandardError" do
      a.should_receive(:<=>).once.and_raise(Exception)
      lambda { (a == b) }.should raise_error(Exception)
    end
  end

  context "when #<=> is not defined" do
    before :each do
      @a = ComparableSpecs::WithoutCompareDefined.new
      @b = ComparableSpecs::WithoutCompareDefined.new
    end

    it "returns true for identical objects" do
      @a.should == @a
    end

    it "returns false and does not recurse infinitely" do
      @a.should_not == @b
    end
  end

  context "when #<=> calls super" do
    before :each do
      @a = ComparableSpecs::CompareCallingSuper.new
      @b = ComparableSpecs::CompareCallingSuper.new
    end

    it "returns true for identical objects" do
      @a.should == @a
    end

    it "calls the defined #<=> only once for different objects" do
      @a.should_not == @b
      @a.calls.should == 1
    end
  end
end