summaryrefslogtreecommitdiff
path: root/spec/ruby/optional/capi/exception_spec.rb
blob: b0a8a2860ee90a021d463e95ef44cd0cc7bf6f09 (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
140
141
142
143
144
145
146
147
require_relative 'spec_helper'

load_extension("exception")

describe "C-API Exception function" do
  before :each do
    @s = CApiExceptionSpecs.new
  end

  describe "rb_exc_new" do
    it "creates an exception from a C string and length" do
      @s.rb_exc_new('foo').to_s.should == 'foo'
    end
  end

  describe "rb_exc_new2" do
    it "creates an exception from a C string" do
      @s.rb_exc_new2('foo').to_s.should == 'foo'
    end
  end

  describe "rb_exc_new3" do
    it "creates an exception from a Ruby string" do
      @s.rb_exc_new3('foo').to_s.should == 'foo'
    end
  end

  describe "rb_exc_raise" do
    it "raises passed exception" do
      runtime_error = RuntimeError.new '42'
      -> { @s.rb_exc_raise(runtime_error) }.should raise_error(RuntimeError, '42')
    end

    it "raises an exception with an empty backtrace" do
      runtime_error = RuntimeError.new '42'
      runtime_error.set_backtrace []
      -> { @s.rb_exc_raise(runtime_error) }.should raise_error(RuntimeError, '42')
    end

    it "sets $! to the raised exception when not rescuing from an another exception" do
      runtime_error = RuntimeError.new '42'
      runtime_error.set_backtrace []
      begin
        @s.rb_exc_raise(runtime_error)
      rescue
        $!.should == runtime_error
      end
    end

    it "sets $! to the raised exception when $! when rescuing from an another exception" do
      runtime_error = RuntimeError.new '42'
      runtime_error.set_backtrace []
      begin
        begin
          raise StandardError
        rescue
          @s.rb_exc_raise(runtime_error)
        end
      rescue
        $!.should == runtime_error
      end
    end
  end

  describe "rb_errinfo" do
    it "is cleared when entering a C method" do
      begin
        raise StandardError
      rescue
        $!.class.should == StandardError
        @s.rb_errinfo().should == nil
      end
    end

    it "does not clear $! in the calling method" do
      begin
        raise StandardError
      rescue
        @s.rb_errinfo()
        $!.class.should == StandardError
      end
    end
  end

  describe "rb_set_errinfo" do
    after :each do
      @s.rb_set_errinfo(nil)
    end

    it "accepts nil" do
      @s.rb_set_errinfo(nil).should be_nil
    end

    it "accepts an Exception instance" do
      @s.rb_set_errinfo(Exception.new).should be_nil
    end

    it "raises a TypeError if the object is not nil or an Exception instance" do
      -> { @s.rb_set_errinfo("error") }.should raise_error(TypeError)
    end
  end

  describe "rb_make_exception" do
    it "returns a RuntimeError when given a String argument" do
      e = @s.rb_make_exception(["Message"])
      e.class.should == RuntimeError
      e.message.should == "Message"
    end

    it "returns the exception when given an Exception argument" do
      exc = Exception.new
      e = @s.rb_make_exception([exc])
      e.should == exc
    end

    it "returns the exception with the given class and message" do
      e = @s.rb_make_exception([Exception, "Message"])
      e.class.should == Exception
      e.message.should == "Message"
    end

    it "returns the exception with the given class, message, and backtrace" do
      e = @s.rb_make_exception([Exception, "Message", ["backtrace 1"]])
      e.class.should == Exception
      e.message.should == "Message"
      e.backtrace.should == ["backtrace 1"]
    end

    it "raises a TypeError for incorrect types" do
      -> { @s.rb_make_exception([nil]) }.should raise_error(TypeError)
      -> { @s.rb_make_exception([Object.new]) }.should raise_error(TypeError)
      obj = Object.new
      def obj.exception
        "not exception type"
      end
      -> { @s.rb_make_exception([obj]) }.should raise_error(TypeError)
    end

    it "raises an ArgumentError for too many arguments" do
      -> { @s.rb_make_exception([Exception, "Message", ["backtrace 1"], "extra"])  }.should raise_error(ArgumentError)
    end

    it "returns nil for empty arguments" do
      @s.rb_make_exception([]).should == nil
    end
  end
end