require "spec" require "socket" require "../../support/tempfile" 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 "initializes with `Path` paths" do with_tempfile("unix_socket.sock") do |path| path_path = Path.new(path) UNIXServer.open(path_path) do |server| server.local_address.family.should eq(Socket::Family::UNIX) server.local_address.path.should eq(path) UNIXSocket.open(path_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) 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 it "#send, #receive" do with_tempfile("unix_socket-receive.sock") do |path| UNIXServer.open(path) do |server| UNIXSocket.open(path) do |client| server.accept do |sock| client.send "ping" message, address = sock.receive message.should eq("ping") typeof(address).should eq(Socket::UNIXAddress) address.path.should eq "" sock.send "pong" message, address = client.receive message.should eq("pong") typeof(address).should eq(Socket::UNIXAddress) # The value of path seems to be system-specific. Some implementations # return the socket path, others an empty path. ["", path].should contain address.path 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