configurator: add :ipv6only directive
[unicorn.git] / test / unit / test_socket_helper.rb
blob8ce1023263b2d05ad5ed9d43ce55901e618abfaa
1 # -*- encoding: binary -*-
3 require 'test/test_helper'
4 require 'tempfile'
6 class TestSocketHelper < Test::Unit::TestCase
7   include Unicorn::SocketHelper
8   attr_reader :logger
9   GET_SLASH = "GET / HTTP/1.0\r\n\r\n".freeze
11   def setup
12     @log_tmp = Tempfile.new 'logger'
13     @logger = Logger.new(@log_tmp.path)
14     @test_addr = ENV['UNICORN_TEST_ADDR'] || '127.0.0.1'
15     @test6_addr = ENV['UNICORN_TEST6_ADDR'] || '::1'
16     GC.disable
17   end
19   def teardown
20     GC.enable
21   end
23   def test_bind_listen_tcp
24     port = unused_port @test_addr
25     @tcp_listener_name = "#@test_addr:#{port}"
26     @tcp_listener = bind_listen(@tcp_listener_name)
27     assert TCPServer === @tcp_listener
28     assert_equal @tcp_listener_name, sock_name(@tcp_listener)
29   end
31   def test_bind_listen_options
32     port = unused_port @test_addr
33     tcp_listener_name = "#@test_addr:#{port}"
34     tmp = Tempfile.new 'unix.sock'
35     unix_listener_name = tmp.path
36     File.unlink(tmp.path)
37     [ { :backlog => 5 }, { :sndbuf => 4096 }, { :rcvbuf => 4096 },
38       { :backlog => 16, :rcvbuf => 4096, :sndbuf => 4096 }
39     ].each do |opts|
40       assert_nothing_raised do
41         tcp_listener = bind_listen(tcp_listener_name, opts)
42         assert TCPServer === tcp_listener
43         tcp_listener.close
44         unix_listener = bind_listen(unix_listener_name, opts)
45         assert UNIXServer === unix_listener
46         unix_listener.close
47       end
48     end
49     #system('cat', @log_tmp.path)
50   end
52   def test_bind_listen_unix
53     old_umask = File.umask(0777)
54     tmp = Tempfile.new 'unix.sock'
55     @unix_listener_path = tmp.path
56     File.unlink(@unix_listener_path)
57     @unix_listener = bind_listen(@unix_listener_path)
58     assert UNIXServer === @unix_listener
59     assert_equal @unix_listener_path, sock_name(@unix_listener)
60     assert File.readable?(@unix_listener_path), "not readable"
61     assert File.writable?(@unix_listener_path), "not writable"
62     assert_equal 0777, File.umask
63     ensure
64       File.umask(old_umask)
65   end
67   def test_bind_listen_unix_umask
68     old_umask = File.umask(0777)
69     tmp = Tempfile.new 'unix.sock'
70     @unix_listener_path = tmp.path
71     File.unlink(@unix_listener_path)
72     @unix_listener = bind_listen(@unix_listener_path, :umask => 077)
73     assert UNIXServer === @unix_listener
74     assert_equal @unix_listener_path, sock_name(@unix_listener)
75     assert_equal 0140700, File.stat(@unix_listener_path).mode
76     assert_equal 0777, File.umask
77     ensure
78       File.umask(old_umask)
79   end
81   def test_bind_listen_unix_idempotent
82     test_bind_listen_unix
83     a = bind_listen(@unix_listener)
84     assert_equal a.fileno, @unix_listener.fileno
85     unix_server = server_cast(@unix_listener)
86     assert UNIXServer === unix_server
87     a = bind_listen(unix_server)
88     assert_equal a.fileno, unix_server.fileno
89     assert_equal a.fileno, @unix_listener.fileno
90   end
92   def test_bind_listen_tcp_idempotent
93     test_bind_listen_tcp
94     a = bind_listen(@tcp_listener)
95     assert_equal a.fileno, @tcp_listener.fileno
96     tcp_server = server_cast(@tcp_listener)
97     assert TCPServer === tcp_server
98     a = bind_listen(tcp_server)
99     assert_equal a.fileno, tcp_server.fileno
100     assert_equal a.fileno, @tcp_listener.fileno
101   end
103   def test_bind_listen_unix_rebind
104     test_bind_listen_unix
105     new_listener = nil
106     assert_raises(Errno::EADDRINUSE) do
107       new_listener = bind_listen(@unix_listener_path)
108     end
109     assert_nothing_raised do
110       File.unlink(@unix_listener_path)
111       new_listener = bind_listen(@unix_listener_path)
112     end
113     assert UNIXServer === new_listener
114     assert new_listener.fileno != @unix_listener.fileno
115     assert_equal sock_name(new_listener), sock_name(@unix_listener)
116     assert_equal @unix_listener_path, sock_name(new_listener)
117     pid = fork do
118       client = server_cast(new_listener).accept
119       client.syswrite('abcde')
120       exit 0
121     end
122     s = UNIXSocket.new(@unix_listener_path)
123     IO.select([s])
124     assert_equal 'abcde', s.sysread(5)
125     pid, status = Process.waitpid2(pid)
126     assert status.success?
127   end
129   def test_server_cast
130     assert_nothing_raised do
131       test_bind_listen_unix
132       test_bind_listen_tcp
133     end
134     unix_listener_socket = Socket.for_fd(@unix_listener.fileno)
135     assert Socket === unix_listener_socket
136     @unix_server = server_cast(unix_listener_socket)
137     assert_equal @unix_listener.fileno, @unix_server.fileno
138     assert UNIXServer === @unix_server
139     assert_equal(@unix_server.path, @unix_listener.path,
140                  "##{@unix_server.path} != #{@unix_listener.path}")
141     assert File.socket?(@unix_server.path)
142     assert_equal @unix_listener_path, sock_name(@unix_server)
144     tcp_listener_socket = Socket.for_fd(@tcp_listener.fileno)
145     assert Socket === tcp_listener_socket
146     @tcp_server = server_cast(tcp_listener_socket)
147     assert_equal @tcp_listener.fileno, @tcp_server.fileno
148     assert TCPServer === @tcp_server
149     assert_equal @tcp_listener_name, sock_name(@tcp_server)
150   end
152   def test_sock_name
153     test_server_cast
154     sock_name(@unix_server)
155   end
157   def test_tcp_defer_accept_default
158     port = unused_port @test_addr
159     name = "#@test_addr:#{port}"
160     sock = bind_listen(name)
161     cur = sock.getsockopt(Socket::SOL_TCP, TCP_DEFER_ACCEPT).unpack('i')[0]
162     assert cur >= 1
163   end if defined?(TCP_DEFER_ACCEPT)
165   def test_tcp_defer_accept_disable
166     port = unused_port @test_addr
167     name = "#@test_addr:#{port}"
168     sock = bind_listen(name, :tcp_defer_accept => false)
169     cur = sock.getsockopt(Socket::SOL_TCP, TCP_DEFER_ACCEPT).unpack('i')[0]
170     assert_equal 0, cur
171   end if defined?(TCP_DEFER_ACCEPT)
173   def test_tcp_defer_accept_nr
174     port = unused_port @test_addr
175     name = "#@test_addr:#{port}"
176     sock = bind_listen(name, :tcp_defer_accept => 60)
177     cur = sock.getsockopt(Socket::SOL_TCP, TCP_DEFER_ACCEPT).unpack('i')[0]
178     assert cur > 1
179   end if defined?(TCP_DEFER_ACCEPT)
181   def test_ipv6only
182     port = unused_port "#@test6_addr"
183     sock = bind_listen "[#@test6_addr]:#{port}", :ipv6only => true
184     cur = sock.getsockopt(:IPPROTO_IPV6, :IPV6_V6ONLY).unpack('i')[0]
185     assert_equal 1, cur
186     rescue Errno::EAFNOSUPPORT
187   end if RUBY_VERSION >= "1.9.2"