diff options
author | Samuel Williams <[email protected]> | 2022-11-17 14:50:25 -0800 |
---|---|---|
committer | GitHub <[email protected]> | 2022-11-17 14:50:25 -0800 |
commit | ea8a7287e2b96b9c24e5e89fe863e5bfa60bfdda (patch) | |
tree | 1935b65502eb16b6913d6183fc11c6f1cf4db34d /test | |
parent | 4e4b29b1a9e534554594b6f18fc0bdc462638934 (diff) |
Add support for `sockaddr_un` on Windows. (#6513)
* Windows: Fix warning about undefined if_indextoname()
* Windows: Fix UNIXSocket on MINGW and make .pair more reliable
* Windows: Use nonblock=true for read tests with scheduler
* Windows: Move socket detection from File.socket? to File.stat
Add S_IFSOCK to Windows and interpret reparse points accordingly.
Enable tests that work now.
* Windows: Use wide-char functions to UNIXSocket
This fixes behaviour with non-ASCII characters.
It also fixes deletion of temporary UNIXSocket.pair files.
* Windows: Add UNIXSocket tests for specifics of Windows impl.
* Windows: fix VC build due to missing _snwprintf
Avoid usage of _snwprintf, since it fails linking ruby.dll like so:
linking shared-library x64-vcruntime140-ruby320.dll
x64-vcruntime140-ruby320.def : error LNK2001: unresolved external symbol snwprintf
x64-vcruntime140-ruby320.def : error LNK2001: unresolved external symbol vsnwprintf_l
whereas linking miniruby.exe succeeds.
This patch uses snprintf on the UTF-8 string instead.
Also remove branch GetWindowsDirectoryW, since it doesn't work.
* Windows: Fix dangling symlink test failures
Co-authored-by: Lars Kanis <[email protected]>
Notes
Notes:
Merged-By: ioquatix <[email protected]>
Diffstat (limited to 'test')
-rw-r--r-- | test/fiber/test_enumerator.rb | 6 | ||||
-rw-r--r-- | test/fiber/test_io.rb | 23 | ||||
-rw-r--r-- | test/fileutils/test_fileutils.rb | 4 | ||||
-rw-r--r-- | test/ruby/test_file_exhaustive.rb | 2 | ||||
-rw-r--r-- | test/ruby/test_io.rb | 24 | ||||
-rw-r--r-- | test/ruby/test_io_timeout.rb | 6 | ||||
-rw-r--r-- | test/socket/test_nonblock.rb | 4 | ||||
-rw-r--r-- | test/socket/test_unix.rb | 147 |
8 files changed, 143 insertions, 73 deletions
diff --git a/test/fiber/test_enumerator.rb b/test/fiber/test_enumerator.rb index c635f474db..40f7d01725 100644 --- a/test/fiber/test_enumerator.rb +++ b/test/fiber/test_enumerator.rb @@ -10,12 +10,6 @@ class TestFiberEnumerator < Test::Unit::TestCase i, o = UNIXSocket.pair - unless i.nonblock? && o.nonblock? - i.close - o.close - omit "I/O is not non-blocking!" - end - message = String.new thread = Thread.new do diff --git a/test/fiber/test_io.rb b/test/fiber/test_io.rb index 821a169e44..de88745e57 100644 --- a/test/fiber/test_io.rb +++ b/test/fiber/test_io.rb @@ -6,14 +6,12 @@ class TestFiberIO < Test::Unit::TestCase MESSAGE = "Hello World" def test_read - omit "UNIXSocket is not defined!" unless defined?(UNIXSocket) + omit unless defined?(UNIXSocket) i, o = UNIXSocket.pair - - unless i.nonblock? && o.nonblock? - i.close - o.close - omit "I/O is not non-blocking!" + if RUBY_PLATFORM=~/mswin|mingw/ + i.nonblock = true + o.nonblock = true end message = nil @@ -46,6 +44,10 @@ class TestFiberIO < Test::Unit::TestCase 16.times.map do Thread.new do i, o = UNIXSocket.pair + if RUBY_PLATFORM=~/mswin|mingw/ + i.nonblock = true + o.nonblock = true + end scheduler = Scheduler.new Fiber.set_scheduler scheduler @@ -64,16 +66,11 @@ class TestFiberIO < Test::Unit::TestCase end def test_epipe_on_read - omit "UNIXSocket is not defined!" unless defined?(UNIXSocket) + omit unless defined?(UNIXSocket) + omit "nonblock=true isn't properly supported on Windows" if RUBY_PLATFORM=~/mswin|mingw/ i, o = UNIXSocket.pair - unless i.nonblock? && o.nonblock? - i.close - o.close - omit "I/O is not non-blocking!" - end - error = nil thread = Thread.new do diff --git a/test/fileutils/test_fileutils.rb b/test/fileutils/test_fileutils.rb index 05ba8d184a..2748bd247f 100644 --- a/test/fileutils/test_fileutils.rb +++ b/test/fileutils/test_fileutils.rb @@ -472,10 +472,14 @@ class TestFileUtils < Test::Unit::TestCase else def test_cp_r_socket pend "Skipping socket test on JRuby" if RUBY_ENGINE == 'jruby' + Dir.mkdir('tmp/cpr_src') UNIXServer.new('tmp/cpr_src/socket').close cp_r 'tmp/cpr_src', 'tmp/cpr_dest' assert_equal(true, File.socket?('tmp/cpr_dest/socket')) + rescue Errno::EINVAL => error + # On some platforms (windows) sockets cannot be copied by FileUtils. + omit error.message end if defined?(UNIXServer) end diff --git a/test/ruby/test_file_exhaustive.rb b/test/ruby/test_file_exhaustive.rb index 8cd020533b..d0472a0081 100644 --- a/test/ruby/test_file_exhaustive.rb +++ b/test/ruby/test_file_exhaustive.rb @@ -649,7 +649,7 @@ class TestFileExhaustive < Test::Unit::TestCase # ignore unsupporting filesystems rescue Errno::EPERM # Docker prohibits statx syscall by the default. - skip("statx(2) is prohibited by seccomp") + omit("statx(2) is prohibited by seccomp") end assert_raise(Errno::ENOENT) { File.birthtime(nofile) } end if File.respond_to?(:birthtime) diff --git a/test/ruby/test_io.rb b/test/ruby/test_io.rb index 6313e11179..0bf24960c6 100644 --- a/test/ruby/test_io.rb +++ b/test/ruby/test_io.rb @@ -900,6 +900,10 @@ class TestIO < Test::Unit::TestCase end if defined? UNIXSocket def test_copy_stream_socket4 + if RUBY_PLATFORM =~ /mingw|mswin/ + omit "pread(2) is not implemented." + end + with_bigsrc {|bigsrc, bigcontent| File.open(bigsrc) {|f| assert_equal(0, f.pos) @@ -916,9 +920,13 @@ class TestIO < Test::Unit::TestCase } } } - end if defined? UNIXSocket + end def test_copy_stream_socket5 + if RUBY_PLATFORM =~ /mingw|mswin/ + omit "pread(2) is not implemented." + end + with_bigsrc {|bigsrc, bigcontent| File.open(bigsrc) {|f| assert_equal(bigcontent[0,100], f.read(100)) @@ -936,9 +944,13 @@ class TestIO < Test::Unit::TestCase } } } - end if defined? UNIXSocket + end def test_copy_stream_socket6 + if RUBY_PLATFORM =~ /mingw|mswin/ + omit "pread(2) is not implemented." + end + mkcdtmpdir { megacontent = "abc" * 1234567 File.open("megasrc", "w") {|f| f << megacontent } @@ -959,9 +971,13 @@ class TestIO < Test::Unit::TestCase assert_equal(megacontent, result) } } - end if defined? UNIXSocket + end def test_copy_stream_socket7 + if RUBY_PLATFORM =~ /mingw|mswin/ + omit "pread(2) is not implemented." + end + GC.start mkcdtmpdir { megacontent = "abc" * 1234567 @@ -996,7 +1012,7 @@ class TestIO < Test::Unit::TestCase end } } - end if defined? UNIXSocket and IO.method_defined?("nonblock=") + end def test_copy_stream_strio src = StringIO.new("abcd") diff --git a/test/ruby/test_io_timeout.rb b/test/ruby/test_io_timeout.rb index ca4c0b833b..e017395980 100644 --- a/test/ruby/test_io_timeout.rb +++ b/test/ruby/test_io_timeout.rb @@ -9,12 +9,6 @@ class TestIOTimeout < Test::Unit::TestCase begin i, o = UNIXSocket.pair - unless i.nonblock? && o.nonblock? - i.close - o.close - omit "I/O is not non-blocking!" - end - yield i, o ensure i.close diff --git a/test/socket/test_nonblock.rb b/test/socket/test_nonblock.rb index d9d1e186b2..5a4688bac3 100644 --- a/test/socket/test_nonblock.rb +++ b/test/socket/test_nonblock.rb @@ -307,11 +307,13 @@ class TestSocketNonblock < Test::Unit::TestCase loop { s1.sendmsg_nonblock(buf) } end end - rescue NotImplementedError, Errno::ENOSYS, Errno::EPROTONOSUPPORT + rescue NotImplementedError, Errno::ENOSYS, Errno::EPROTONOSUPPORT, Errno::EPROTOTYPE omit "UNIXSocket.pair(:SEQPACKET) not implemented on this platform: #{$!}" end def test_sendmsg_nonblock_no_exception + omit "AF_UNIX + SEQPACKET is not supported on windows" if /mswin|mingw/ =~ RUBY_PLATFORM + buf = '*' * 4096 UNIXSocket.pair(:SEQPACKET) do |s1, s2| n = 0 diff --git a/test/socket/test_unix.rb b/test/socket/test_unix.rb index 8c74d0c939..b1dcc813e7 100644 --- a/test/socket/test_unix.rb +++ b/test/socket/test_unix.rb @@ -60,6 +60,8 @@ class TestSocket_UNIXSocket < Test::Unit::TestCase assert_not_equal s1.fileno, r.fileno r.close end + rescue NotImplementedError => error + omit error.message end def test_fd_passing_n @@ -334,62 +336,70 @@ class TestSocket_UNIXSocket < Test::Unit::TestCase end def test_noname_path - s1, s2 = UNIXSocket.pair - assert_equal("", s1.path) - assert_equal("", s2.path) - ensure - s1.close - s2.close + if /mswin|mingw/ =~ RUBY_PLATFORM + omit "unnamed pipe is emulated on windows" + end + + UNIXSocket.pair do |s1, s2| + assert_equal("", s1.path) + assert_equal("", s2.path) + end end def test_noname_addr - s1, s2 = UNIXSocket.pair - assert_equal(["AF_UNIX", ""], s1.addr) - assert_equal(["AF_UNIX", ""], s2.addr) - ensure - s1.close - s2.close + if /mswin|mingw/ =~ RUBY_PLATFORM + omit "unnamed pipe is emulated on windows" + end + + UNIXSocket.pair do |s1, s2| + assert_equal(["AF_UNIX", ""], s1.addr) + assert_equal(["AF_UNIX", ""], s2.addr) + end end def test_noname_peeraddr - s1, s2 = UNIXSocket.pair - assert_equal(["AF_UNIX", ""], s1.peeraddr) - assert_equal(["AF_UNIX", ""], s2.peeraddr) - ensure - s1.close - s2.close + if /mswin|mingw/ =~ RUBY_PLATFORM + omit "unnamed pipe is emulated on windows" + end + + UNIXSocket.pair do |s1, s2| + assert_equal(["AF_UNIX", ""], s1.peeraddr) + assert_equal(["AF_UNIX", ""], s2.peeraddr) + end end def test_noname_unpack_sockaddr_un - s1, s2 = UNIXSocket.pair - n = nil - assert_equal("", Socket.unpack_sockaddr_un(n)) if (n = s1.getsockname) != "" - assert_equal("", Socket.unpack_sockaddr_un(n)) if (n = s1.getsockname) != "" - assert_equal("", Socket.unpack_sockaddr_un(n)) if (n = s2.getsockname) != "" - assert_equal("", Socket.unpack_sockaddr_un(n)) if (n = s1.getpeername) != "" - assert_equal("", Socket.unpack_sockaddr_un(n)) if (n = s2.getpeername) != "" - ensure - s1.close - s2.close + if /mswin|mingw/ =~ RUBY_PLATFORM + omit "unnamed pipe is emulated on windows" + end + + UNIXSocket.pair do |s1, s2| + n = nil + assert_equal("", Socket.unpack_sockaddr_un(n)) if (n = s1.getsockname) != "" + assert_equal("", Socket.unpack_sockaddr_un(n)) if (n = s1.getsockname) != "" + assert_equal("", Socket.unpack_sockaddr_un(n)) if (n = s2.getsockname) != "" + assert_equal("", Socket.unpack_sockaddr_un(n)) if (n = s1.getpeername) != "" + assert_equal("", Socket.unpack_sockaddr_un(n)) if (n = s2.getpeername) != "" + end end def test_noname_recvfrom - s1, s2 = UNIXSocket.pair - s2.write("a") - assert_equal(["a", ["AF_UNIX", ""]], s1.recvfrom(10)) - ensure - s1.close - s2.close + if /mswin|mingw/ =~ RUBY_PLATFORM + omit "unnamed pipe is emulated on windows" + end + + UNIXSocket.pair do |s1, s2| + s2.write("a") + assert_equal(["a", ["AF_UNIX", ""]], s1.recvfrom(10)) + end end def test_noname_recv_nonblock - s1, s2 = UNIXSocket.pair - s2.write("a") - IO.select [s1] - assert_equal("a", s1.recv_nonblock(10)) - ensure - s1.close - s2.close + UNIXSocket.pair do |s1, s2| + s2.write("a") + IO.select [s1] + assert_equal("a", s1.recv_nonblock(10)) + end end def test_too_long_path @@ -429,12 +439,18 @@ class TestSocket_UNIXSocket < Test::Unit::TestCase rv = s1.recv(100, 0, buf) assert_equal buf.object_id, rv.object_id assert_equal "BBBBBB", rv + rescue Errno::EPROTOTYPE => error + omit error.message ensure s1.close if s1 s2.close if s2 end def test_dgram_pair_sendrecvmsg_errno_set + if /mswin|mingw/ =~ RUBY_PLATFORM + omit("AF_UNIX + SOCK_DGRAM is not supported on windows") + end + s1, s2 = to_close = UNIXSocket.pair(Socket::SOCK_DGRAM) pipe = IO.pipe to_close.concat(pipe) @@ -457,9 +473,17 @@ class TestSocket_UNIXSocket < Test::Unit::TestCase end def test_epipe # [ruby-dev:34619] + # This is a good example of why reporting the exact `errno` is a terrible + # idea for platform abstractions. + if RUBY_PLATFORM =~ /mswin|mingw/ + error = Errno::ESHUTDOWN + else + error = Errno::EPIPE + end + UNIXSocket.pair {|s1, s2| s1.shutdown(Socket::SHUT_WR) - assert_raise(Errno::EPIPE) { s1.write "a" } + assert_raise(error) { s1.write "a" } assert_equal(nil, s2.read(1)) s2.write "a" assert_equal("a", s1.read(1)) @@ -493,6 +517,45 @@ class TestSocket_UNIXSocket < Test::Unit::TestCase } end + if /mingw|mswin/ =~ RUBY_PLATFORM + + def test_unix_socket_with_encoding + Dir.mktmpdir do |tmpdir| + path = "#{tmpdir}/sockäöü".encode("cp850") + UNIXServer.open(path) do |serv| + assert File.socket?(path) + assert File.stat(path).socket? + assert File.lstat(path).socket? + assert_equal path.encode("utf-8"), serv.path + UNIXSocket.open(path) do |s1| + s2 = serv.accept + s2.close + end + end + end + end + + def test_windows_unix_socket_pair_with_umlaut + otmp = ENV['TMP'] + ENV['TMP'] = File.join(Dir.tmpdir, "äöü€") + FileUtils.mkdir_p ENV['TMP'] + + s1, s2 = UNIXSocket.pair + assert !s1.path.empty? + assert !File.exist?(s1.path) + ensure + FileUtils.rm_rf ENV['TMP'] + ENV['TMP'] = otmp + end + + def test_windows_unix_socket_pair_paths + s1, s2 = UNIXSocket.pair + assert !s1.path.empty? + assert s2.path.empty? + assert !File.exist?(s1.path) + end + end + def test_initialize Dir.mktmpdir {|d| Socket.open(Socket::AF_UNIX, Socket::SOCK_STREAM, 0) {|s| |