Skip to content

Commit

Permalink
Split socket_spec.cr into separate files
Browse files Browse the repository at this point in the history
  • Loading branch information
straight-shoota committed Sep 11, 2018
1 parent 58a8e27 commit be83d8b
Show file tree
Hide file tree
Showing 10 changed files with 659 additions and 620 deletions.
90 changes: 89 additions & 1 deletion spec/std/socket/address_spec.cr
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
require "spec"
require "socket/address"
require "socket"

describe Socket::Address do
describe ".parse" do
Expand Down Expand Up @@ -161,3 +161,91 @@ describe Socket::UNIXAddress do
end
end
end

describe Socket do
# Tests from libc-test:
# http://repo.or.cz/libc-test.git/blob/master:/src/functional/inet_pton.c
it ".ip?" do
# dotted-decimal notation
Socket.ip?("0.0.0.0").should be_true
Socket.ip?("127.0.0.1").should be_true
Socket.ip?("10.0.128.31").should be_true
Socket.ip?("255.255.255.255").should be_true

# numbers-and-dots notation, but not dotted-decimal
# Socket.ip?("1.2.03.4").should be_false # fails on darwin
Socket.ip?("1.2.0x33.4").should be_false
Socket.ip?("1.2.0XAB.4").should be_false
Socket.ip?("1.2.0xabcd").should be_false
Socket.ip?("1.0xabcdef").should be_false
Socket.ip?("00377.0x0ff.65534").should be_false

# invalid
Socket.ip?(".1.2.3").should be_false
Socket.ip?("1..2.3").should be_false
Socket.ip?("1.2.3.").should be_false
Socket.ip?("1.2.3.4.5").should be_false
Socket.ip?("1.2.3.a").should be_false
Socket.ip?("1.256.2.3").should be_false
Socket.ip?("1.2.4294967296.3").should be_false
Socket.ip?("1.2.-4294967295.3").should be_false
Socket.ip?("1.2. 3.4").should be_false

# ipv6
Socket.ip?(":").should be_false
Socket.ip?("::").should be_true
Socket.ip?("::1").should be_true
Socket.ip?(":::").should be_false
Socket.ip?(":192.168.1.1").should be_false
Socket.ip?("::192.168.1.1").should be_true
Socket.ip?("0:0:0:0:0:0:192.168.1.1").should be_true
Socket.ip?("0:0::0:0:0:192.168.1.1").should be_true
# Socket.ip?("::012.34.56.78").should be_false # fails on darwin
Socket.ip?(":ffff:192.168.1.1").should be_false
Socket.ip?("::ffff:192.168.1.1").should be_true
Socket.ip?(".192.168.1.1").should be_false
Socket.ip?(":.192.168.1.1").should be_false
Socket.ip?("a:0b:00c:000d:E:F::").should be_true
# Socket.ip?("a:0b:00c:000d:0000e:f::").should be_false # fails on GNU libc
Socket.ip?("1:2:3:4:5:6::").should be_true
Socket.ip?("1:2:3:4:5:6:7::").should be_true
Socket.ip?("1:2:3:4:5:6:7:8::").should be_false
Socket.ip?("1:2:3:4:5:6:7::9").should be_false
Socket.ip?("::1:2:3:4:5:6").should be_true
Socket.ip?("::1:2:3:4:5:6:7").should be_true
Socket.ip?("::1:2:3:4:5:6:7:8").should be_false
Socket.ip?("a:b::c:d:e:f").should be_true
Socket.ip?("ffff:c0a8:5e4").should be_false
Socket.ip?(":ffff:c0a8:5e4").should be_false
Socket.ip?("0:0:0:0:0:ffff:c0a8:5e4").should be_true
Socket.ip?("0:0:0:0:ffff:c0a8:5e4").should be_false
Socket.ip?("0::ffff:c0a8:5e4").should be_true
Socket.ip?("::0::ffff:c0a8:5e4").should be_false
Socket.ip?("c0a8").should be_false
end

describe ".unix" do
it "creates a unix socket" do
sock = Socket.unix
sock.should be_a(Socket)
sock.family.should eq(Socket::Family::UNIX)
sock.type.should eq(Socket::Type::STREAM)

sock = Socket.unix(Socket::Type::DGRAM)
sock.type.should eq(Socket::Type::DGRAM)
end
end

it ".accept" do
server = Socket.new(Socket::Family::INET, Socket::Type::STREAM, Socket::Protocol::TCP)
server.bind("0.0.0.0", 11234)
server.listen

spawn { TCPSocket.new("127.0.0.1", 11234).close }

client = server.accept
client.family.should eq(Socket::Family::INET)
client.type.should eq(Socket::Type::STREAM)
client.protocol.should eq(Socket::Protocol::TCP)
end
end
61 changes: 61 additions & 0 deletions spec/std/socket/addrinfo_spec.cr
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
require "spec"
require "socket"

describe Socket::Addrinfo do
describe ".resolve" do
it "returns an array" do
addrinfos = Socket::Addrinfo.resolve("localhost", 80, type: Socket::Type::STREAM)
typeof(addrinfos).should eq(Array(Socket::Addrinfo))
addrinfos.size.should_not eq(0)
end

it "yields each result" do
Socket::Addrinfo.resolve("localhost", 80, type: Socket::Type::DGRAM) do |addrinfo|
typeof(addrinfo).should eq(Socket::Addrinfo)
end
end

it "eventually raises returned error" do
expect_raises(Socket::Error) do
Socket::Addrinfo.resolve("localhost", 80, type: Socket::Type::DGRAM) do |addrinfo|
Socket::Error.new("please fail")
end
end
end
end

describe ".tcp" do
it "returns an array" do
addrinfos = Socket::Addrinfo.tcp("localhost", 80)
typeof(addrinfos).should eq(Array(Socket::Addrinfo))
addrinfos.size.should_not eq(0)
end

it "yields each result" do
Socket::Addrinfo.tcp("localhost", 80) do |addrinfo|
typeof(addrinfo).should eq(Socket::Addrinfo)
end
end
end

describe ".udp" do
it "returns an array" do
addrinfos = Socket::Addrinfo.udp("localhost", 80)
typeof(addrinfos).should eq(Array(Socket::Addrinfo))
addrinfos.size.should_not eq(0)
end

it "yields each result" do
Socket::Addrinfo.udp("localhost", 80) do |addrinfo|
typeof(addrinfo).should eq(Socket::Addrinfo)
end
end
end

describe "#ip_address" do
it do
addrinfos = Socket::Addrinfo.udp("localhost", 80)
typeof(addrinfos.first.ip_address).should eq(Socket::IPAddress)
end
end
end
29 changes: 29 additions & 0 deletions spec/std/socket/socket_spec.cr
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
require "spec"
require "socket"

describe Socket do
describe ".unix" do
it "creates a unix socket" do
sock = Socket.unix
sock.should be_a(Socket)
sock.family.should eq(Socket::Family::UNIX)
sock.type.should eq(Socket::Type::STREAM)

sock = Socket.unix(Socket::Type::DGRAM)
sock.type.should eq(Socket::Type::DGRAM)
end
end

it ".accept" do
server = Socket.new(Socket::Family::INET, Socket::Type::STREAM, Socket::Protocol::TCP)
server.bind("0.0.0.0", 11234)
server.listen

spawn { TCPSocket.new("127.0.0.1", 11234).close }

client = server.accept
client.family.should eq(Socket::Family::INET)
client.type.should eq(Socket::Type::STREAM)
client.protocol.should eq(Socket::Protocol::TCP)
end
end
7 changes: 7 additions & 0 deletions spec/std/socket/spec_helper.cr
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
require "spec"

def unused_local_port
TCPServer.open("::", 0) do |server|
server.local_address.port
end
end
37 changes: 37 additions & 0 deletions spec/std/socket/tcp_server_spec.cr
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
require "./spec_helper"
require "socket"

describe TCPServer do
it "creates a raw socket" do
sock = TCPServer.new
sock.family.should eq(Socket::Family::INET)

sock = TCPServer.new(Socket::Family::INET6)
sock.family.should eq(Socket::Family::INET6)
end

it "fails when port is in use" do
port = unused_local_port

expect_raises Errno, /(already|Address) in use/ do
sock = Socket.tcp(Socket::Family::INET6)
sock.bind(Socket::IPAddress.new("::1", port))

TCPServer.open("::1", port) { }
end
end

it "doesn't reuse the TCP port by default (SO_REUSEPORT)" do
TCPServer.open("::", 0) do |server|
expect_raises(Errno) do
TCPServer.open("::", server.local_address.port) { }
end
end
end

it "reuses the TCP port (SO_REUSEPORT)" do
TCPServer.open("::", 0, reuse_port: true) do |server|
TCPServer.open("::", server.local_address.port, reuse_port: true) { }
end
end
end
113 changes: 113 additions & 0 deletions spec/std/socket/tcp_socket_spec.cr
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
require "spec"
require "socket"

describe TCPSocket do
it "creates a raw socket" do
sock = TCPSocket.new
sock.family.should eq(Socket::Family::INET)

sock = TCPSocket.new(Socket::Family::INET6)
sock.family.should eq(Socket::Family::INET6)
end

it "sends and receives messages" do
port = TCPServer.open("::", 0) do |server|
server.local_address.port
end
port.should be > 0

TCPServer.open("::", port) do |server|
server.local_address.family.should eq(Socket::Family::INET6)
server.local_address.port.should eq(port)
server.local_address.address.should eq("::")

# test protocol specific socket options
server.reuse_address?.should be_true # defaults to true
(server.reuse_address = false).should be_false
server.reuse_address?.should be_false
(server.reuse_address = true).should be_true
server.reuse_address?.should be_true

{% unless flag?(:openbsd) %}
(server.keepalive = false).should be_false
server.keepalive?.should be_false
(server.keepalive = true).should be_true
server.keepalive?.should be_true
{% end %}

(server.linger = nil).should be_nil
server.linger.should be_nil
(server.linger = 42).should eq 42
server.linger.should eq 42

TCPSocket.open("localhost", server.local_address.port) do |client|
# The commented lines are actually dependent on the system configuration,
# so for now we keep it commented. Once we can force the family
# we can uncomment them.

# client.local_address.family.should eq(Socket::Family::INET)
# client.local_address.address.should eq("127.0.0.1")

sock = server.accept
sock.sync?.should eq(server.sync?)

# sock.local_address.family.should eq(Socket::Family::INET6)
# sock.local_address.port.should eq(12345)
# sock.local_address.address.should eq("::ffff:127.0.0.1")

# sock.remote_address.family.should eq(Socket::Family::INET6)
# sock.remote_address.address.should eq("::ffff:127.0.0.1")

# test protocol specific socket options
(client.tcp_nodelay = true).should be_true
client.tcp_nodelay?.should be_true
(client.tcp_nodelay = false).should be_false
client.tcp_nodelay?.should be_false

{% unless flag?(:openbsd) %}
(client.tcp_keepalive_idle = 42).should eq 42
client.tcp_keepalive_idle.should eq 42
(client.tcp_keepalive_interval = 42).should eq 42
client.tcp_keepalive_interval.should eq 42
(client.tcp_keepalive_count = 42).should eq 42
client.tcp_keepalive_count.should eq 42
{% end %}

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

# test sync flag propagation after accept
server.sync = !server.sync?

TCPSocket.open("localhost", server.local_address.port) do |client|
sock = server.accept
sock.sync?.should eq(server.sync?)
end
end
end

it "fails when connection is refused" do
port = TCPServer.open("localhost", 0) do |server|
server.local_address.port
end

expect_raises(Errno, "Error connecting to 'localhost:#{port}': Connection refused") do
TCPSocket.new("localhost", port)
end
end

it "fails when host doesn't exist" do
expect_raises(Socket::Error, /No address/i) do
TCPSocket.new("doesnotexist.example.org.", 12345)
end
end

it "fails (rather than segfault on darwin) when host doesn't exist and port is 0" do
expect_raises(Socket::Error, /No address/i) do
TCPSocket.new("doesnotexist.example.org.", 0)
end
end
end
Loading

0 comments on commit be83d8b

Please sign in to comment.