socket_helper: tunables for tcp_defer_accept/accept_filter
[unicorn.git] / test / unit / test_socket_helper.rb
blobbbce35967a56ff2e076f72b4c8f543d8d305c491
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     GC.disable
16   end
18   def teardown
19     GC.enable
20   end
22   def test_bind_listen_tcp
23     port = unused_port @test_addr
24     @tcp_listener_name = "#@test_addr:#{port}"
25     @tcp_listener = bind_listen(@tcp_listener_name)
26     assert TCPServer === @tcp_listener
27     assert_equal @tcp_listener_name, sock_name(@tcp_listener)
28   end
30   def test_bind_listen_options
31     port = unused_port @test_addr
32     tcp_listener_name = "#@test_addr:#{port}"
33     tmp = Tempfile.new 'unix.sock'
34     unix_listener_name = tmp.path
35     File.unlink(tmp.path)
36     [ { :backlog => 5 }, { :sndbuf => 4096 }, { :rcvbuf => 4096 },
37       { :backlog => 16, :rcvbuf => 4096, :sndbuf => 4096 }
38     ].each do |opts|
39       assert_nothing_raised do
40         tcp_listener = bind_listen(tcp_listener_name, opts)
41         assert TCPServer === tcp_listener
42         tcp_listener.close
43         unix_listener = bind_listen(unix_listener_name, opts)
44         assert UNIXServer === unix_listener
45         unix_listener.close
46       end
47     end
48     #system('cat', @log_tmp.path)
49   end
51   def test_bind_listen_unix
52     old_umask = File.umask(0777)
53     tmp = Tempfile.new 'unix.sock'
54     @unix_listener_path = tmp.path
55     File.unlink(@unix_listener_path)
56     @unix_listener = bind_listen(@unix_listener_path)
57     assert UNIXServer === @unix_listener
58     assert_equal @unix_listener_path, sock_name(@unix_listener)
59     assert File.readable?(@unix_listener_path), "not readable"
60     assert File.writable?(@unix_listener_path), "not writable"
61     assert_equal 0777, File.umask
62     ensure
63       File.umask(old_umask)
64   end
66   def test_bind_listen_unix_umask
67     old_umask = File.umask(0777)
68     tmp = Tempfile.new 'unix.sock'
69     @unix_listener_path = tmp.path
70     File.unlink(@unix_listener_path)
71     @unix_listener = bind_listen(@unix_listener_path, :umask => 077)
72     assert UNIXServer === @unix_listener
73     assert_equal @unix_listener_path, sock_name(@unix_listener)
74     assert_equal 0140700, File.stat(@unix_listener_path).mode
75     assert_equal 0777, File.umask
76     ensure
77       File.umask(old_umask)
78   end
80   def test_bind_listen_unix_idempotent
81     test_bind_listen_unix
82     a = bind_listen(@unix_listener)
83     assert_equal a.fileno, @unix_listener.fileno
84     unix_server = server_cast(@unix_listener)
85     assert UNIXServer === unix_server
86     a = bind_listen(unix_server)
87     assert_equal a.fileno, unix_server.fileno
88     assert_equal a.fileno, @unix_listener.fileno
89   end
91   def test_bind_listen_tcp_idempotent
92     test_bind_listen_tcp
93     a = bind_listen(@tcp_listener)
94     assert_equal a.fileno, @tcp_listener.fileno
95     tcp_server = server_cast(@tcp_listener)
96     assert TCPServer === tcp_server
97     a = bind_listen(tcp_server)
98     assert_equal a.fileno, tcp_server.fileno
99     assert_equal a.fileno, @tcp_listener.fileno
100   end
102   def test_bind_listen_unix_rebind
103     test_bind_listen_unix
104     new_listener = bind_listen(@unix_listener_path)
105     assert UNIXServer === new_listener
106     assert new_listener.fileno != @unix_listener.fileno
107     assert_equal sock_name(new_listener), sock_name(@unix_listener)
108     assert_equal @unix_listener_path, sock_name(new_listener)
109     pid = fork do
110       client = server_cast(new_listener).accept
111       client.syswrite('abcde')
112       exit 0
113     end
114     s = UNIXSocket.new(@unix_listener_path)
115     IO.select([s])
116     assert_equal 'abcde', s.sysread(5)
117     pid, status = Process.waitpid2(pid)
118     assert status.success?
119   end
121   def test_server_cast
122     assert_nothing_raised do
123       test_bind_listen_unix
124       test_bind_listen_tcp
125     end
126     unix_listener_socket = Socket.for_fd(@unix_listener.fileno)
127     assert Socket === unix_listener_socket
128     @unix_server = server_cast(unix_listener_socket)
129     assert_equal @unix_listener.fileno, @unix_server.fileno
130     assert UNIXServer === @unix_server
131     assert_equal(@unix_server.path, @unix_listener.path,
132                  "##{@unix_server.path} != #{@unix_listener.path}")
133     assert File.socket?(@unix_server.path)
134     assert_equal @unix_listener_path, sock_name(@unix_server)
136     tcp_listener_socket = Socket.for_fd(@tcp_listener.fileno)
137     assert Socket === tcp_listener_socket
138     @tcp_server = server_cast(tcp_listener_socket)
139     assert_equal @tcp_listener.fileno, @tcp_server.fileno
140     assert TCPServer === @tcp_server
141     assert_equal @tcp_listener_name, sock_name(@tcp_server)
142   end
144   def test_sock_name
145     test_server_cast
146     sock_name(@unix_server)
147   end
149   def test_tcp_defer_accept_default
150     port = unused_port @test_addr
151     name = "#@test_addr:#{port}"
152     sock = bind_listen(name)
153     cur = sock.getsockopt(Socket::SOL_TCP, TCP_DEFER_ACCEPT).unpack('i')[0]
154     assert cur >= 1
155   end if defined?(TCP_DEFER_ACCEPT)
157   def test_tcp_defer_accept_disable
158     port = unused_port @test_addr
159     name = "#@test_addr:#{port}"
160     sock = bind_listen(name, :tcp_defer_accept => false)
161     cur = sock.getsockopt(Socket::SOL_TCP, TCP_DEFER_ACCEPT).unpack('i')[0]
162     assert_equal 0, cur
163   end if defined?(TCP_DEFER_ACCEPT)
165   def test_tcp_defer_accept_nr
166     port = unused_port @test_addr
167     name = "#@test_addr:#{port}"
168     sock = bind_listen(name, :tcp_defer_accept => 60)
169     cur = sock.getsockopt(Socket::SOL_TCP, TCP_DEFER_ACCEPT).unpack('i')[0]
170     assert cur > 1
171   end if defined?(TCP_DEFER_ACCEPT)