summaryrefslogtreecommitdiff
path: root/spec/ruby/core/exception/system_call_error_spec.rb
blob: c510ae440fa9f60db609ac6684d1ba903594b625 (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
require_relative '../../spec_helper'
require_relative 'fixtures/common'

describe "SystemCallError" do
  before :each do
    ScratchPad.clear
  end

  it "can be subclassed" do
    ExceptionSpecs::SCESub = Class.new(SystemCallError) do
      def initialize
        ScratchPad.record :initialize
      end
    end

    exc = ExceptionSpecs::SCESub.new
    ScratchPad.recorded.should equal(:initialize)
    exc.should be_an_instance_of(ExceptionSpecs::SCESub)
  end
end

describe "SystemCallError.new" do
  before :all do
    @example_errno = Errno::EINVAL::Errno
    @example_errno_class = Errno::EINVAL
    @last_known_errno = Errno.constants.size - 1
    @unknown_errno = Errno.constants.size
  end

  it "requires at least one argument" do
    -> { SystemCallError.new }.should raise_error(ArgumentError)
  end

  it "accepts single Fixnum argument as errno" do
    SystemCallError.new(-2**24).errno.should == -2**24
    SystemCallError.new(-1).errno.should == -1
    SystemCallError.new(0).errno.should == 0
    SystemCallError.new(@last_known_errno).errno.should == @last_known_errno
    SystemCallError.new(@unknown_errno).errno.should == @unknown_errno
    SystemCallError.new(2**24).errno.should == 2**24
  end

  it "constructs a SystemCallError for an unknown error number" do
    SystemCallError.new(-2**24).should be_an_instance_of(SystemCallError)
    SystemCallError.new(-1).should be_an_instance_of(SystemCallError)
    SystemCallError.new(@unknown_errno).should be_an_instance_of(SystemCallError)
    SystemCallError.new(2**24).should be_an_instance_of(SystemCallError)
  end

  it "constructs the appropriate Errno class" do
    e = SystemCallError.new(@example_errno)
    e.should be_kind_of(SystemCallError)
    e.should be_an_instance_of(@example_errno_class)
  end

  it "accepts an optional custom message preceding the errno" do
    exc = SystemCallError.new("custom message", @example_errno)
    exc.should be_an_instance_of(@example_errno_class)
    exc.errno.should == @example_errno
    exc.message.should == 'Invalid argument - custom message'
  end

  it "accepts an optional third argument specifying the location" do
    exc = SystemCallError.new("custom message", @example_errno, "location")
    exc.should be_an_instance_of(@example_errno_class)
    exc.errno.should == @example_errno
    exc.message.should == 'Invalid argument @ location - custom message'
  end

  it "coerces location if it is not a String" do
    e = SystemCallError.new('foo', 1, :not_a_string)
    e.message.should =~ /@ not_a_string - foo/
  end

  it "returns an arity of -1 for the initialize method" do
    SystemCallError.instance_method(:initialize).arity.should == -1
  end

  it "converts to Integer if errno is a Float" do
    SystemCallError.new('foo', 2.0).should == SystemCallError.new('foo', 2)
    SystemCallError.new('foo', 2.9).should == SystemCallError.new('foo', 2)
  end

  it "converts to Integer if errno is a Complex convertible to Integer" do
    SystemCallError.new('foo', Complex(2.9, 0)).should == SystemCallError.new('foo', 2)
  end

  it "raises TypeError if message is not a String" do
    -> { SystemCallError.new(:foo, 1) }.should raise_error(TypeError, /no implicit conversion of Symbol into String/)
  end

  it "raises TypeError if errno is not an Integer" do
    -> { SystemCallError.new('foo', 'bar') }.should raise_error(TypeError, /no implicit conversion of String into Integer/)
  end

  it "raises RangeError if errno is a Complex not convertible to Integer" do
    -> { SystemCallError.new('foo', Complex(2.9, 1)) }.should raise_error(RangeError, /can't convert/)
  end
end

describe "SystemCallError#errno" do
  it "returns nil when no errno given" do
    SystemCallError.new("message").errno.should == nil
  end

  it "returns the errno given as optional argument to new" do
    SystemCallError.new("message", -2**20).errno.should == -2**20
    SystemCallError.new("message", -1).errno.should == -1
    SystemCallError.new("message", 0).errno.should == 0
    SystemCallError.new("message", 1).errno.should == 1
    SystemCallError.new("message", 42).errno.should == 42
    SystemCallError.new("message", 2**20).errno.should == 2**20
  end
end

describe "SystemCallError#message" do
  it "returns the default message when no message is given" do
    platform_is :aix do
      SystemCallError.new(2**28).message.should =~ /Error .*occurred/i
    end
    platform_is_not :aix do
      SystemCallError.new(2**28).message.should =~ /Unknown error/i
    end
  end

  it "returns the message given as an argument to new" do
    SystemCallError.new("message", 1).message.should =~ /message/
    SystemCallError.new("XXX").message.should =~ /XXX/
  end
end