require "../spec_helper" require "socket" require "../../support/fibers" require "../../support/channel" require "../../support/tempfile" describe UNIXServer do describe ".new" do it "raises when path is too long" do with_tempfile("unix_server-too_long-#{("a" * 2048)}.sock") do |path| expect_raises(ArgumentError, "Path size exceeds the maximum size") do UNIXServer.new(path) end File.exists?(path).should be_false end end it "creates the socket file" do with_tempfile("unix_server.sock") do |path| UNIXServer.open(path) do File.exists?(path).should be_true File.info(path).type.socket?.should be_true end File.exists?(path).should be_false end end it "creates the socket file from `Path`" do with_tempfile("unix_server.sock") do |path| path = Path.new(path) UNIXServer.open(path) do File.exists?(path).should be_true File.info(path).type.socket?.should be_true end File.exists?(path).should be_false end end it "deletes socket file on close" do with_tempfile("unix_server-close.sock") do |path| server = UNIXServer.new(path) server.close File.exists?(path).should be_false end end it "raises when socket file already exists" do with_tempfile("unix_server-twice.sock") do |path| server = UNIXServer.new(path) begin expect_raises(Socket::BindError) do UNIXServer.new(path) end ensure server.close end end end it "won't delete existing file on bind failure" do with_tempfile("unix_server-exist.sock") do |path| File.write(path, "") File.exists?(path).should be_true expect_raises(Socket::BindError) do UNIXServer.new(path) end File.exists?(path).should be_true end end end describe "accept" do it "returns the client UNIXSocket" do with_tempfile("unix_server-accept.sock") do |path| UNIXServer.open(path) do |server| UNIXSocket.open(path) do |_| client = server.accept client.should be_a(UNIXSocket) client.close end end end end it "raises when server is closed" do with_tempfile("unix_server-closed.sock") do |path| server = UNIXServer.new(path) ch = Channel(SpecChannelStatus).new(1) exception = nil schedule_timeout ch f = spawn do begin ch.send(:begin) server.accept rescue ex exception = ex end ch.send(:end) end ch.receive.should eq SpecChannelStatus::Begin # wait for the server to call accept wait_until_blocked f server.close ch.receive.should eq SpecChannelStatus::End exception.should be_a(IO::Error) exception.try(&.message).should eq("Closed stream") end end end describe "accept?" do it "returns the client UNIXSocket" do with_tempfile("unix_server-accept_.sock") do |path| UNIXServer.open(path) do |server| UNIXSocket.open(path) do |_| client = server.accept?.not_nil! client.should be_a(UNIXSocket) client.close end end end end it "returns nil when server is closed" do with_tempfile("unix_server-accept2.sock") do |path| server = UNIXServer.new(path) ch = Channel(SpecChannelStatus).new(1) ret = "initial" schedule_timeout ch f = spawn do ch.send :begin ret = server.accept? ch.send :end end ch.receive.should eq SpecChannelStatus::Begin # wait for the server to call accept wait_until_blocked f server.close ch.receive.should eq SpecChannelStatus::End ret.should be_nil end end it "sets close on exec flag" do with_tempfile("unix_socket-accept.sock") do |path| UNIXServer.open(path) do |server| UNIXSocket.open(path) do |client| server.accept? do |sock| sock.close_on_exec?.should eq CLOSE_ON_EXEC_AVAILABLE end end end end end end # Datagram socket type is not supported on Windows yet: # https://devblogs.microsoft.com/commandline/af_unix-comes-to-windows/#unsupportedunavailable # https://github.com/microsoft/WSL/issues/5272 {% unless flag?(:win32) %} describe "datagrams" do it "can send and receive datagrams" do with_tempfile("unix_dgram_server.sock") do |path| UNIXServer.open(path, Socket::Type::DGRAM) do |s| UNIXSocket.open(path, Socket::Type::DGRAM) do |c| c.send("foobar") msg, _addr = s.receive(512) msg.should eq "foobar" end end end end end {% end %} end