summaryrefslogtreecommitdiff
path: root/spec/ruby/core/io/lineno_spec.rb
blob: e82cdd9f17ecab34221e2ec84264fb1fd54aed46 (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
require_relative '../../spec_helper'
require_relative 'fixtures/classes'

describe "IO#lineno" do
  before :each do
    @io = IOSpecs.io_fixture "lines.txt"
  end

  after :each do
    @io.close if @io
  end

  it "raises an IOError on a closed stream" do
    -> { IOSpecs.closed_io.lineno }.should raise_error(IOError)
  end

  it "raises an IOError on a write-only stream" do
    name = tmp("io_lineno.txt")
    begin
      File.open(name, 'w') do |f|
        -> { f.lineno }.should raise_error(IOError)
      end
    ensure
      rm_r name
    end
  end

  it "raises an IOError on a duplexed stream with the read side closed" do
    cmd = platform_is(:windows) ? 'rem' : 'cat'
    IO.popen(cmd, 'r+') do |p|
      p.close_read
      -> { p.lineno }.should raise_error(IOError)
    end
  end

  it "returns the current line number" do
    @io.lineno.should == 0

    count = 0
    while @io.gets
      @io.lineno.should == count += 1
    end

    @io.rewind
    @io.lineno.should == 0
  end
end

describe "IO#lineno=" do
  before :each do
    @io = IOSpecs.io_fixture "lines.txt"
  end

  after :each do
    @io.close if @io
  end

  it "raises an IOError on a closed stream" do
    -> { IOSpecs.closed_io.lineno = 5 }.should raise_error(IOError)
  end

  it "raises an IOError on a write-only stream" do
    name = tmp("io_lineno.txt")
    begin
      File.open(name, 'w') do |f|
        -> { f.lineno = 0 }.should raise_error(IOError)
      end
    ensure
      rm_r name
    end
  end

  it "raises an IOError on a duplexed stream with the read side closed" do
    cmd = platform_is(:windows) ? 'rem' : 'cat'
    IO.popen(cmd, 'r+') do |p|
      p.close_read
      -> { p.lineno = 0 }.should raise_error(IOError)
    end
  end

  it "calls #to_int on a non-numeric argument" do
    obj = mock('123')
    obj.should_receive(:to_int).and_return(123)

    @io.lineno = obj
    @io.lineno.should == 123
  end

  it "truncates a Float argument" do
    @io.lineno = 1.5
    @io.lineno.should == 1

    @io.lineno = 92233.72036854775808
    @io.lineno.should == 92233
  end

  it "raises TypeError if cannot convert argument to Integer implicitly" do
    -> { @io.lineno = "1" }.should raise_error(TypeError, 'no implicit conversion of String into Integer')
    -> { @io.lineno = nil }.should raise_error(TypeError, 'no implicit conversion from nil to integer')
  end

  it "does not accept Integers that don't fit in a C int" do
    -> { @io.lineno = 2**32 }.should raise_error(RangeError)
  end

  it "sets the current line number to the given value" do
    @io.lineno = count = 500

    while @io.gets
      @io.lineno.should == count += 1
    end

    @io.rewind
    @io.lineno.should == 0
  end

  it "does not change $." do
    original_line = $.
    numbers = [-2**30, -2**16, -2**8, -100, -10, -1, 0, 1, 10, 2**8, 2**16, 2**30]
    numbers.each do |num|
      @io.lineno = num
      @io.lineno.should == num
      $..should == original_line
    end
  end

  it "does not change $. until next read" do
    $. = 0
    $..should == 0

    @io.lineno = count = 500
    $..should == 0

    while @io.gets
      $..should == count += 1
    end
  end
end