383 lines
11 KiB
Julia
383 lines
11 KiB
Julia
# This file is a part of Julia. License is MIT: https://julialang.org/license
|
|
|
|
@test ip"127.0.0.1" == IPv4(127,0,0,1)
|
|
@test ip"192.0" == IPv4(192,0,0,0)
|
|
|
|
# These used to work, but are now disallowed. Check that they error
|
|
@test_throws ArgumentError parse(IPv4, "192.0xFFF") # IPv4(192,0,15,255)
|
|
@test_throws ArgumentError parse(IPv4, "192.0xFFFF") # IPv4(192,0,255,255)
|
|
@test_throws ArgumentError parse(IPv4, "192.0xFFFFF") # IPv4(192,15,255,255)
|
|
@test_throws ArgumentError parse(IPv4, "192.0xFFFFFF") # IPv4(192,255,255,255)
|
|
@test_throws ArgumentError parse(IPv4, "022.0.0.1") # IPv4(18,0,0,1)
|
|
|
|
@test UInt(IPv4(0x01020304)) == 0x01020304
|
|
@test Int(IPv4("1.2.3.4")) == Int(0x01020304) == Int32(0x01020304)
|
|
@test Int128(IPv6("2001:1::2")) == 42540488241204005274814694018844196866
|
|
@test_throws InexactError Int16(IPv4("1.2.3.4"))
|
|
@test_throws InexactError Int64(IPv6("2001:1::2"))
|
|
|
|
let ipv = parse(IPAddr, "127.0.0.1")
|
|
@test isa(ipv, IPv4)
|
|
@test ipv == ip"127.0.0.1"
|
|
end
|
|
|
|
@test_throws ArgumentError parse(IPv4, "192.0xFFFFFFF")
|
|
@test_throws ArgumentError IPv4(192,255,255,-1)
|
|
@test_throws ArgumentError IPv4(192,255,255,256)
|
|
|
|
@test_throws ArgumentError parse(IPv4, "192.0xFFFFFFFFF")
|
|
@test_throws ArgumentError parse(IPv4, "192.")
|
|
|
|
@test ip"::1" == IPv6(1)
|
|
@test ip"2605:2700:0:3::4713:93e3" == IPv6(parse(UInt128,"260527000000000300000000471393e3",16))
|
|
|
|
@test ip"2001:db8:0:0:0:0:2:1" == ip"2001:db8::2:1" == ip"2001:db8::0:2:1"
|
|
|
|
@test ip"0:0:0:0:0:ffff:127.0.0.1" == IPv6(0xffff7f000001)
|
|
|
|
let ipv = parse(IPAddr, "0:0:0:0:0:ffff:127.0.0.1")
|
|
@test isa(ipv, IPv6)
|
|
@test ipv == ip"0:0:0:0:0:ffff:127.0.0.1"
|
|
end
|
|
|
|
@test_throws ArgumentError IPv6(1,1,1,1,1,1,1,-1)
|
|
@test_throws ArgumentError IPv6(1,1,1,1,1,1,1,typemax(UInt16)+1)
|
|
|
|
# test InetAddr constructor
|
|
let inet = Base.InetAddr(IPv4(127,0,0,1), 1024)
|
|
@test inet.host == ip"127.0.0.1"
|
|
@test inet.port == 1024
|
|
end
|
|
# test InetAddr invalid port
|
|
@test_throws InexactError Base.InetAddr(IPv4(127,0,0,1), -1)
|
|
@test_throws InexactError Base.InetAddr(IPv4(127,0,0,1), typemax(UInt16)+1)
|
|
|
|
# isless and comparisons
|
|
@test ip"1.2.3.4" < ip"1.2.3.7" < ip"2.3.4.5"
|
|
@test ip"1.2.3.4" >= ip"1.2.3.4" >= ip"1.2.3.1"
|
|
@test isless(ip"1.2.3.4", ip"1.2.3.5")
|
|
@test_throws MethodError sort[ip"2.3.4.5", ip"1.2.3.4", ip"2001:1:2::1"]
|
|
|
|
# RFC 5952 Compliance
|
|
|
|
@test repr(ip"2001:db8:0:0:0:0:2:1") == "ip\"2001:db8::2:1\""
|
|
@test repr(ip"2001:0db8::0001") == "ip\"2001:db8::1\""
|
|
@test repr(ip"2001:db8::1:1:1:1:1") == "ip\"2001:db8:0:1:1:1:1:1\""
|
|
@test repr(ip"2001:db8:0:0:1:0:0:1") == "ip\"2001:db8::1:0:0:1\""
|
|
@test repr(ip"2001:0:0:1:0:0:0:1") == "ip\"2001:0:0:1::1\""
|
|
|
|
# test show() function for UDPSocket()
|
|
@test repr(UDPSocket()) == "UDPSocket(init)"
|
|
|
|
defaultport = rand(2000:4000)
|
|
for testport in [0, defaultport]
|
|
port = Channel(1)
|
|
tsk = @async begin
|
|
p, s = listenany(testport)
|
|
put!(port, p)
|
|
sock = accept(s)
|
|
# test write call
|
|
write(sock,"Hello World\n")
|
|
|
|
# test "locked" println to a socket
|
|
@sync begin
|
|
for i in 1:100
|
|
@async println(sock, "a", 1)
|
|
end
|
|
end
|
|
close(s)
|
|
close(sock)
|
|
end
|
|
wait(port)
|
|
@test readstring(connect(fetch(port))) == "Hello World\n" * ("a1\n"^100)
|
|
wait(tsk)
|
|
end
|
|
|
|
mktempdir() do tmpdir
|
|
socketname = is_windows() ? ("\\\\.\\pipe\\uv-test-" * randstring(6)) : joinpath(tmpdir, "socket")
|
|
c = Base.Condition()
|
|
tsk = @async begin
|
|
s = listen(socketname)
|
|
Base.notify(c)
|
|
sock = accept(s)
|
|
write(sock,"Hello World\n")
|
|
close(s)
|
|
close(sock)
|
|
end
|
|
wait(c)
|
|
@test readstring(connect(socketname)) == "Hello World\n"
|
|
wait(tsk)
|
|
end
|
|
|
|
@test_throws Base.DNSError getaddrinfo(".invalid")
|
|
@test_throws ArgumentError getaddrinfo("localhost\0") # issue #10994
|
|
@test_throws Base.UVError connect("localhost", 21452)
|
|
|
|
# test invalid port
|
|
@test_throws ArgumentError connect(ip"127.0.0.1",-1)
|
|
@test_throws ArgumentError connect(ip"127.0.0.1", typemax(UInt16)+1)
|
|
@test_throws ArgumentError connect(ip"0:0:0:0:0:ffff:127.0.0.1", -1)
|
|
@test_throws ArgumentError connect(ip"0:0:0:0:0:ffff:127.0.0.1", typemax(UInt16)+1)
|
|
|
|
p, server = listenany(defaultport)
|
|
r = Channel(1)
|
|
tsk = @async begin
|
|
put!(r, :start)
|
|
@test_throws Base.UVError accept(server)
|
|
end
|
|
@test fetch(r) === :start
|
|
close(server)
|
|
wait(tsk)
|
|
|
|
port, server = listenany(defaultport)
|
|
@async connect("localhost",port)
|
|
s1 = accept(server)
|
|
@test_throws ErrorException accept(server,s1)
|
|
@test_throws Base.UVError listen(port)
|
|
port2, server2 = listenany(port)
|
|
@test port != port2
|
|
close(server)
|
|
close(server2)
|
|
|
|
@test_throws Base.DNSError connect(".invalid",80)
|
|
|
|
begin
|
|
a = UDPSocket()
|
|
b = UDPSocket()
|
|
bind(a, ip"127.0.0.1", port)
|
|
bind(b, ip"127.0.0.1", port + 1)
|
|
|
|
c = Condition()
|
|
tsk = @async begin
|
|
@test String(recv(a)) == "Hello World"
|
|
# Issue 6505
|
|
tsk2 = @async begin
|
|
@test String(recv(a)) == "Hello World"
|
|
notify(c)
|
|
end
|
|
send(b, ip"127.0.0.1", port, "Hello World")
|
|
wait(tsk2)
|
|
end
|
|
send(b, ip"127.0.0.1", port, "Hello World")
|
|
wait(c)
|
|
wait(tsk)
|
|
|
|
tsk = @async begin
|
|
@test begin
|
|
(addr,data) = recvfrom(a)
|
|
addr == ip"127.0.0.1" && String(data) == "Hello World"
|
|
end
|
|
end
|
|
send(b, ip"127.0.0.1", port, "Hello World")
|
|
wait(tsk)
|
|
|
|
@test_throws MethodError bind(UDPSocket(),port)
|
|
|
|
close(a)
|
|
close(b)
|
|
end
|
|
if !is_windows() || Sys.windows_version() >= Sys.WINDOWS_VISTA_VER
|
|
a = UDPSocket()
|
|
b = UDPSocket()
|
|
bind(a, ip"::1", UInt16(port))
|
|
bind(b, ip"::1", UInt16(port+1))
|
|
|
|
tsk = @async begin
|
|
@test begin
|
|
(addr, data) = recvfrom(a)
|
|
addr == ip"::1" && String(data) == "Hello World"
|
|
end
|
|
end
|
|
send(b, ip"::1", port, "Hello World")
|
|
wait(tsk)
|
|
end
|
|
|
|
begin
|
|
default_port = UInt16(11011)
|
|
default_addr = IPv4("127.0.0.1")
|
|
|
|
sock = Base.TCPServer()
|
|
bind(sock,Base.InetAddr(default_addr,default_port))
|
|
listen(sock)
|
|
|
|
new_addr, new_port = getsockname(sock)
|
|
|
|
@test default_addr == new_addr
|
|
@test default_port == new_port
|
|
close(sock)
|
|
end
|
|
|
|
begin
|
|
default_port = UInt16(21011)
|
|
default_addr = IPv6("::1")
|
|
|
|
sock = Base.TCPServer()
|
|
addr = Base.InetAddr(default_addr,default_port)
|
|
bind(sock,addr)
|
|
listen(sock)
|
|
|
|
new_addr, new_port = getsockname(sock)
|
|
|
|
@test default_addr == new_addr
|
|
@test default_port == new_port
|
|
close(sock)
|
|
end
|
|
|
|
begin
|
|
default_port = UInt16(11011)
|
|
default_addr = getipaddr()
|
|
|
|
sock = Base.TCPServer()
|
|
bind(sock,Base.InetAddr(default_addr,default_port))
|
|
listen(sock)
|
|
|
|
@async begin
|
|
sleep(1)
|
|
ssock = connect(default_addr, default_port)
|
|
end
|
|
|
|
csock = accept(sock)
|
|
new_addr, new_port = getsockname(csock)
|
|
|
|
@test default_addr == new_addr
|
|
@test new_port > 0
|
|
close(csock)
|
|
close(sock)
|
|
end
|
|
|
|
# Local-machine broadcast
|
|
let
|
|
# (Mac OS X's loopback interface doesn't support broadcasts)
|
|
bcastdst = is_apple() ? ip"255.255.255.255" : ip"127.255.255.255"
|
|
|
|
function create_socket()
|
|
s = UDPSocket()
|
|
bind(s, ip"0.0.0.0", 2000, reuseaddr = true, enable_broadcast = true)
|
|
s
|
|
end
|
|
|
|
function wait_with_timeout(recvs)
|
|
TIMEOUT_VAL = 3 # seconds
|
|
t0 = time()
|
|
recvs_check = copy(recvs)
|
|
while ((length(filter!(t->!istaskdone(t), recvs_check)) > 0)
|
|
&& (time() - t0 < TIMEOUT_VAL))
|
|
sleep(0.05)
|
|
end
|
|
length(recvs_check) > 0 && error("timeout")
|
|
map(wait, recvs)
|
|
end
|
|
|
|
a, b, c = [create_socket() for i = 1:3]
|
|
try
|
|
# bsd family do not allow broadcasting to ip"255.255.255.255"
|
|
# or ip"127.255.255.255"
|
|
@static if !is_bsd() || is_apple()
|
|
send(c, bcastdst, 2000, "hello")
|
|
recvs = [@async @test String(recv(s)) == "hello" for s in (a, b)]
|
|
wait_with_timeout(recvs)
|
|
end
|
|
catch e
|
|
if isa(e, Base.UVError) && Base.uverrorname(e) == "EPERM"
|
|
warn("UDP broadcast test skipped (permission denied upon send, restrictive firewall?)")
|
|
else
|
|
rethrow()
|
|
end
|
|
end
|
|
[close(s) for s in [a, b, c]]
|
|
end
|
|
|
|
let P = Pipe()
|
|
Base.link_pipe(P)
|
|
write(P, "hello")
|
|
@test nb_available(P) == 0
|
|
@test !eof(P)
|
|
@test read(P, Char) === 'h'
|
|
@test !eof(P)
|
|
@test read(P, Char) === 'e'
|
|
@test isopen(P)
|
|
t = @async begin
|
|
# feed uv_read one more event so that it triggers the transition from active -> open
|
|
write(P, "w")
|
|
while P.out.status != Base.StatusOpen
|
|
yield() # wait for that transition
|
|
end
|
|
close(P.in)
|
|
end
|
|
# on unix, this proves that the kernel can buffer a single byte
|
|
# even with no registered active call to read
|
|
# on windows, the kernel fails to do even that
|
|
# causing the `write` call to freeze
|
|
# so we end up forced to do a slightly weaker test here
|
|
is_windows() || wait(t)
|
|
@test isopen(P) # without an active uv_reader, P shouldn't be closed yet
|
|
@test !eof(P) # should already know this,
|
|
@test isopen(P) # so it still shouldn't have an active uv_reader
|
|
@test readuntil(P, 'w') == "llow"
|
|
is_windows() && wait(t)
|
|
@test eof(P)
|
|
@test !isopen(P) # eof test should have closed this by now
|
|
close(P) # should be a no-op, just make sure
|
|
@test !isopen(P)
|
|
@test eof(P)
|
|
end
|
|
|
|
# test the method matching connect!(::TCPSocket, ::Base.InetAddr{T<:Base.IPAddr})
|
|
let
|
|
addr = Base.InetAddr(ip"127.0.0.1", 4444)
|
|
|
|
function test_connect(addr::Base.InetAddr)
|
|
srv = listen(addr)
|
|
|
|
@async try c = accept(srv); close(c) catch end
|
|
yield()
|
|
|
|
t0 = TCPSocket()
|
|
t = t0
|
|
@assert t === t0
|
|
|
|
try
|
|
t = connect(addr)
|
|
finally
|
|
close(srv)
|
|
end
|
|
|
|
test = t !== t0
|
|
close(t)
|
|
|
|
return test
|
|
end
|
|
|
|
@test test_connect(addr)
|
|
end
|
|
|
|
# Issues #18818 and #24169
|
|
mutable struct RLimit
|
|
cur::Int64
|
|
max::Int64
|
|
end
|
|
function with_ulimit(f::Function, stacksize::Int)
|
|
RLIMIT_STACK = 3 # from /usr/include/sys/resource.h
|
|
rlim = Ref(RLimit(0, 0))
|
|
# Get the current maximum stack size in bytes
|
|
rc = ccall(:getrlimit, Cint, (Cint, Ref{RLimit}), RLIMIT_STACK, rlim)
|
|
@assert rc == 0
|
|
current = rlim[].cur
|
|
try
|
|
rlim[].cur = stacksize * 1024
|
|
ccall(:setrlimit, Cint, (Cint, Ref{RLimit}), RLIMIT_STACK, rlim)
|
|
f()
|
|
finally
|
|
rlim[].cur = current
|
|
ccall(:setrlimit, Cint, (Cint, Ref{RLimit}), RLIMIT_STACK, rlim)
|
|
end
|
|
nothing
|
|
end
|
|
@static if is_apple()
|
|
@testset "Issues #18818 and #24169" begin
|
|
with_ulimit(7001) do
|
|
@test getaddrinfo("localhost") isa IPAddr
|
|
end
|
|
end
|
|
end
|