File: unix_socket_spec.cr

package info (click to toggle)
crystal 1.14.0%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 24,384 kB
  • sloc: javascript: 6,400; sh: 695; makefile: 269; ansic: 121; python: 105; cpp: 77; xml: 32
file content (116 lines) | stat: -rw-r--r-- 3,417 bytes parent folder | download
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
require "spec"
require "socket"
require "../../support/tempfile"

# TODO: Windows networking in the interpreter requires #12495
{% if flag?(:interpreted) && flag?(:win32) %}
  pending UNIXSocket
  {% skip_file %}
{% end %}

describe UNIXSocket do
  it "raises when path is too long" do
    with_tempfile("unix_socket-too_long-#{("a" * 2048)}.sock") do |path|
      expect_raises(ArgumentError, "Path size exceeds the maximum size") { UNIXSocket.new(path) }
      File.exists?(path).should be_false
    end
  end

  it "sends and receives messages" do
    with_tempfile("unix_socket.sock") do |path|
      UNIXServer.open(path) do |server|
        server.local_address.family.should eq(Socket::Family::UNIX)
        server.local_address.path.should eq(path)

        UNIXSocket.open(path) do |client|
          client.local_address.family.should eq(Socket::Family::UNIX)
          client.local_address.path.should eq(path)

          server.accept do |sock|
            sock.local_address.family.should eq(Socket::Family::UNIX)
            sock.local_address.path.should eq(path)

            sock.remote_address.family.should eq(Socket::Family::UNIX)
            sock.remote_address.path.should eq(path)

            client << "ping"
            sock.gets(4).should eq("ping")
            sock << "pong"
            client.gets(4).should eq("pong")
          end
        end
      end
    end
  end

  it "sync flag after accept" do
    with_tempfile("unix_socket-accept.sock") do |path|
      UNIXServer.open(path) do |server|
        UNIXSocket.open(path) do |client|
          server.accept do |sock|
            sock.sync?.should eq(server.sync?)
          end
        end

        server.sync = !server.sync?

        UNIXSocket.open(path) do |client|
          server.accept do |sock|
            sock.sync?.should eq(server.sync?)
          end
        end
      end
    end
  end

  # `LibC.socketpair` is not supported in Winsock 2.0 yet:
  # https://devblogs.microsoft.com/commandline/af_unix-comes-to-windows/#unsupportedunavailable
  {% unless flag?(:win32) %}
    it "creates a pair of sockets" do
      UNIXSocket.pair do |left, right|
        left.local_address.family.should eq(Socket::Family::UNIX)
        left.local_address.path.should eq("")

        left << "ping"
        right.gets(4).should eq("ping")

        right << "pong"
        left.gets(4).should eq("pong")
      end
    end

    it "tests read and write timeouts" do
      UNIXSocket.pair do |left, right|
        # BUG: shrink the socket buffers first
        left.write_timeout = 0.1.milliseconds
        right.read_timeout = 0.1.milliseconds
        buf = ("a" * IO::DEFAULT_BUFFER_SIZE).to_slice

        expect_raises(IO::TimeoutError, "Write timed out") do
          loop { left.write buf }
        end

        expect_raises(IO::TimeoutError, "Read timed out") do
          loop { right.read buf }
        end
      end
    end

    it "tests socket options" do
      UNIXSocket.pair do |left, right|
        size = 12000
        # linux returns size * 2
        sizes = [size, size * 2]

        (left.send_buffer_size = size).should eq(size)
        sizes.should contain(left.send_buffer_size)

        (left.recv_buffer_size = size).should eq(size)
        sizes.should contain(left.recv_buffer_size)

        left.close_on_exec?.should be_true
        right.close_on_exec?.should be_true
      end
    end
  {% end %}
end