forked from puma/puma
/
test_busy_worker.rb
102 lines (83 loc) · 2.69 KB
/
test_busy_worker.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
require_relative "helper"
require "puma/events"
class TestBusyWorker < Minitest::Test
def setup
skip_unless :mri # This feature only makes sense on MRI
@ios = []
@server = nil
end
def teardown
return if skipped?
@server.stop(true) if @server
@ios.each {|i| i.close unless i.closed?}
end
def new_connection
TCPSocket.new('127.0.0.1', @port).tap {|s| @ios << s}
rescue IOError
Puma::Util.purge_interrupt_queue
retry
end
def send_http(req)
new_connection << req
end
def send_http_and_read(req)
send_http(req).read
end
def with_server(**options, &app)
@requests_count = 0 # number of requests processed
@requests_running = 0 # current number of requests running
@requests_max_running = 0 # max number of requests running in parallel
@mutex = Mutex.new
request_handler = ->(env) do
@mutex.synchronize do
@requests_count += 1
@requests_running += 1
if @requests_running > @requests_max_running
@requests_max_running = @requests_running
end
end
begin
yield(env)
ensure
@mutex.synchronize do
@requests_running -= 1
end
end
end
@server = Puma::Server.new request_handler, Puma::Events.strings, **options
@server.min_threads = options[:min_threads] || 0
@server.max_threads = options[:max_threads] || 10
@port = (@server.add_tcp_listener '127.0.0.1', 0).addr[1]
@server.run
end
# Multiple concurrent requests are not processed
# sequentially as a small delay is introduced
def test_multiple_requests_waiting_on_less_busy_worker
with_server(wait_for_less_busy_worker: 1.0) do |_|
sleep(0.1)
[200, {}, [""]]
end
n = 2
Array.new(n) do
Thread.new { send_http_and_read "GET / HTTP/1.0\r\n\r\n" }
end.each(&:join)
assert_equal n, @requests_count, "number of requests needs to match"
assert_equal 0, @requests_running, "none of requests needs to be running"
assert_equal 1, @requests_max_running, "maximum number of concurrent requests needs to be 1"
end
# Multiple concurrent requests are processed
# in parallel as a delay is disabled
def test_multiple_requests_processing_in_parallel
with_server(wait_for_less_busy_worker: 0.0) do |_|
sleep(0.1)
[200, {}, [""]]
end
n = 4
Array.new(n) do
Thread.new { send_http_and_read "GET / HTTP/1.0\r\n\r\n" }
end.each(&:join)
assert_equal n, @requests_count, "number of requests needs to match"
assert_equal 0, @requests_running, "none of requests needs to be running"
assert_equal n, @requests_max_running, "maximum number of concurrent requests needs to match"
end
end