summaryrefslogtreecommitdiff
path: root/spec/ruby/library/socket/socket/recvfrom_nonblock_spec.rb
blob: 5596f91bb86b07dc973d45c591ea71aacc3fbeea (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_relative '../spec_helper'
require_relative '../fixtures/classes'

describe 'Socket#recvfrom_nonblock' do
  SocketSpecs.each_ip_protocol do |family, ip_address|
    before do
      @server = Socket.new(family, :DGRAM)
      @client = Socket.new(family, :DGRAM)
    end

    after do
      @client.close
      @server.close
    end

    platform_is_not :windows do
      describe 'using an unbound socket' do
        it 'raises IO::WaitReadable' do
          -> { @server.recvfrom_nonblock(1) }.should raise_error(IO::WaitReadable)
        end
      end
    end

    describe 'using a bound socket' do
      before do
        @server.bind(Socket.sockaddr_in(0, ip_address))
        @client.connect(@server.getsockname)
      end

      describe 'without any data available' do
        it 'raises IO::WaitReadable' do
          -> { @server.recvfrom_nonblock(1) }.should raise_error(IO::WaitReadable)
        end

        it 'returns :wait_readable with exception: false' do
          @server.recvfrom_nonblock(1, exception: false).should == :wait_readable
        end
      end

      describe 'with data available' do
        before do
          @client.write('hello')
        end

        platform_is_not :windows do
          it 'returns an Array containing the data and an Addrinfo' do
            IO.select([@server])
            ret = @server.recvfrom_nonblock(1)

            ret.should be_an_instance_of(Array)
            ret.length.should == 2
          end
        end

        it "allows an output buffer as third argument" do
          @client.write('hello')

          IO.select([@server])
          buffer = +''
          message, = @server.recvfrom_nonblock(5, 0, buffer)

          message.should.equal?(buffer)
          buffer.should == 'hello'
        end

        it "preserves the encoding of the given buffer" do
          @client.write('hello')

          IO.select([@server])
          buffer = ''.encode(Encoding::ISO_8859_1)
          @server.recvfrom_nonblock(5, 0, buffer)

          buffer.encoding.should == Encoding::ISO_8859_1
        end

        describe 'the returned data' do
          it 'is the same as the sent data' do
            5.times do
              @client.write('hello')

              IO.select([@server])
              msg, _ = @server.recvfrom_nonblock(5)

              msg.should == 'hello'
            end
          end
        end

        platform_is_not :windows do
          describe 'the returned Array' do
            before do
              IO.select([@server])
              @array = @server.recvfrom_nonblock(1)
            end

            it 'contains the data at index 0' do
              @array[0].should == 'h'
            end

            it 'contains an Addrinfo at index 1' do
              @array[1].should be_an_instance_of(Addrinfo)
            end
          end

          describe 'the returned Addrinfo' do
            before do
              IO.select([@server])
              @addr = @server.recvfrom_nonblock(1)[1]
            end

            it 'uses AF_INET as the address family' do
              @addr.afamily.should == family
            end

            it 'uses SOCK_DGRAM as the socket type' do
              @addr.socktype.should == Socket::SOCK_DGRAM
            end

            it 'uses PF_INET as the protocol family' do
              @addr.pfamily.should == family
            end

            it 'uses 0 as the protocol' do
              @addr.protocol.should == 0
            end

            it 'uses the IP address of the client' do
              @addr.ip_address.should == ip_address
            end

            it 'uses the port of the client' do
              @addr.ip_port.should == @client.local_address.ip_port
            end
          end
        end
      end
    end
  end
end