thin 1.2.3-x86-mswin32
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of thin might be problematic. Click here for more details.
- data/CHANGELOG +263 -0
- data/COPYING +18 -0
- data/README +69 -0
- data/Rakefile +36 -0
- data/benchmark/abc +51 -0
- data/benchmark/benchmarker.rb +80 -0
- data/benchmark/runner +82 -0
- data/bin/thin +6 -0
- data/example/adapter.rb +32 -0
- data/example/async_app.ru +126 -0
- data/example/async_chat.ru +247 -0
- data/example/async_tailer.ru +100 -0
- data/example/config.ru +22 -0
- data/example/monit_sockets +20 -0
- data/example/monit_unixsock +20 -0
- data/example/myapp.rb +1 -0
- data/example/ramaze.ru +12 -0
- data/example/thin.god +80 -0
- data/example/thin_solaris_smf.erb +36 -0
- data/example/thin_solaris_smf.readme.txt +150 -0
- data/example/vlad.rake +64 -0
- data/ext/thin_parser/common.rl +55 -0
- data/ext/thin_parser/ext_help.h +14 -0
- data/ext/thin_parser/extconf.rb +6 -0
- data/ext/thin_parser/parser.c +452 -0
- data/ext/thin_parser/parser.h +49 -0
- data/ext/thin_parser/parser.rl +157 -0
- data/ext/thin_parser/thin.c +433 -0
- data/lib/rack/adapter/loader.rb +79 -0
- data/lib/rack/adapter/rails.rb +181 -0
- data/lib/thin.rb +46 -0
- data/lib/thin/backends/base.rb +141 -0
- data/lib/thin/backends/swiftiply_client.rb +56 -0
- data/lib/thin/backends/tcp_server.rb +29 -0
- data/lib/thin/backends/unix_server.rb +51 -0
- data/lib/thin/command.rb +53 -0
- data/lib/thin/connection.rb +222 -0
- data/lib/thin/controllers/cluster.rb +127 -0
- data/lib/thin/controllers/controller.rb +183 -0
- data/lib/thin/controllers/service.rb +75 -0
- data/lib/thin/controllers/service.sh.erb +39 -0
- data/lib/thin/daemonizing.rb +174 -0
- data/lib/thin/headers.rb +39 -0
- data/lib/thin/logging.rb +54 -0
- data/lib/thin/request.rb +153 -0
- data/lib/thin/response.rb +101 -0
- data/lib/thin/runner.rb +209 -0
- data/lib/thin/server.rb +247 -0
- data/lib/thin/stats.html.erb +216 -0
- data/lib/thin/stats.rb +52 -0
- data/lib/thin/statuses.rb +43 -0
- data/lib/thin/version.rb +32 -0
- data/lib/thin_parser.so +0 -0
- data/spec/backends/swiftiply_client_spec.rb +66 -0
- data/spec/backends/tcp_server_spec.rb +33 -0
- data/spec/backends/unix_server_spec.rb +37 -0
- data/spec/command_spec.rb +25 -0
- data/spec/configs/cluster.yml +9 -0
- data/spec/configs/single.yml +9 -0
- data/spec/connection_spec.rb +106 -0
- data/spec/controllers/cluster_spec.rb +235 -0
- data/spec/controllers/controller_spec.rb +129 -0
- data/spec/controllers/service_spec.rb +50 -0
- data/spec/daemonizing_spec.rb +192 -0
- data/spec/headers_spec.rb +40 -0
- data/spec/logging_spec.rb +46 -0
- data/spec/perf/request_perf_spec.rb +50 -0
- data/spec/perf/response_perf_spec.rb +19 -0
- data/spec/perf/server_perf_spec.rb +39 -0
- data/spec/rack/loader_spec.rb +29 -0
- data/spec/rack/rails_adapter_spec.rb +106 -0
- data/spec/rails_app/app/controllers/application.rb +10 -0
- data/spec/rails_app/app/controllers/simple_controller.rb +19 -0
- data/spec/rails_app/app/helpers/application_helper.rb +3 -0
- data/spec/rails_app/app/views/simple/index.html.erb +15 -0
- data/spec/rails_app/config/boot.rb +109 -0
- data/spec/rails_app/config/environment.rb +64 -0
- data/spec/rails_app/config/environments/development.rb +18 -0
- data/spec/rails_app/config/environments/production.rb +19 -0
- data/spec/rails_app/config/environments/test.rb +22 -0
- data/spec/rails_app/config/initializers/inflections.rb +10 -0
- data/spec/rails_app/config/initializers/mime_types.rb +5 -0
- data/spec/rails_app/config/routes.rb +35 -0
- data/spec/rails_app/public/404.html +30 -0
- data/spec/rails_app/public/422.html +30 -0
- data/spec/rails_app/public/500.html +30 -0
- data/spec/rails_app/public/dispatch.cgi +10 -0
- data/spec/rails_app/public/dispatch.fcgi +24 -0
- data/spec/rails_app/public/dispatch.rb +10 -0
- data/spec/rails_app/public/favicon.ico +0 -0
- data/spec/rails_app/public/images/rails.png +0 -0
- data/spec/rails_app/public/index.html +277 -0
- data/spec/rails_app/public/javascripts/application.js +2 -0
- data/spec/rails_app/public/javascripts/controls.js +963 -0
- data/spec/rails_app/public/javascripts/dragdrop.js +972 -0
- data/spec/rails_app/public/javascripts/effects.js +1120 -0
- data/spec/rails_app/public/javascripts/prototype.js +4225 -0
- data/spec/rails_app/public/robots.txt +5 -0
- data/spec/rails_app/script/about +3 -0
- data/spec/rails_app/script/console +3 -0
- data/spec/rails_app/script/destroy +3 -0
- data/spec/rails_app/script/generate +3 -0
- data/spec/rails_app/script/performance/benchmarker +3 -0
- data/spec/rails_app/script/performance/profiler +3 -0
- data/spec/rails_app/script/performance/request +3 -0
- data/spec/rails_app/script/plugin +3 -0
- data/spec/rails_app/script/process/inspector +3 -0
- data/spec/rails_app/script/process/reaper +3 -0
- data/spec/rails_app/script/process/spawner +3 -0
- data/spec/rails_app/script/runner +3 -0
- data/spec/rails_app/script/server +3 -0
- data/spec/request/mongrel_spec.rb +39 -0
- data/spec/request/parser_spec.rb +215 -0
- data/spec/request/persistent_spec.rb +35 -0
- data/spec/request/processing_spec.rb +45 -0
- data/spec/response_spec.rb +91 -0
- data/spec/runner_spec.rb +168 -0
- data/spec/server/builder_spec.rb +44 -0
- data/spec/server/pipelining_spec.rb +110 -0
- data/spec/server/robustness_spec.rb +34 -0
- data/spec/server/stopping_spec.rb +55 -0
- data/spec/server/swiftiply.yml +6 -0
- data/spec/server/swiftiply_spec.rb +32 -0
- data/spec/server/tcp_spec.rb +57 -0
- data/spec/server/threaded_spec.rb +27 -0
- data/spec/server/unix_socket_spec.rb +26 -0
- data/spec/server_spec.rb +96 -0
- data/spec/spec_helper.rb +219 -0
- data/tasks/announce.rake +22 -0
- data/tasks/deploy.rake +13 -0
- data/tasks/email.erb +30 -0
- data/tasks/gem.rake +74 -0
- data/tasks/rdoc.rake +25 -0
- data/tasks/site.rake +15 -0
- data/tasks/spec.rake +49 -0
- data/tasks/stats.rake +28 -0
- metadata +246 -0
data/lib/thin/stats.rb
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'erb'
|
2
|
+
|
3
|
+
module Thin
|
4
|
+
module Stats
|
5
|
+
# Rack adapter to log stats about a Rack application.
|
6
|
+
class Adapter
|
7
|
+
include ERB::Util
|
8
|
+
|
9
|
+
def initialize(app, path='/stats')
|
10
|
+
@app = app
|
11
|
+
@path = path
|
12
|
+
|
13
|
+
@template = ERB.new(File.read(File.dirname(__FILE__) + '/stats.html.erb'))
|
14
|
+
|
15
|
+
@requests = 0
|
16
|
+
@requests_finished = 0
|
17
|
+
@start_time = Time.now
|
18
|
+
end
|
19
|
+
|
20
|
+
def call(env)
|
21
|
+
if env['PATH_INFO'].index(@path) == 0
|
22
|
+
serve(env)
|
23
|
+
else
|
24
|
+
log(env) { @app.call(env) }
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def log(env)
|
29
|
+
@requests += 1
|
30
|
+
@last_request = Rack::Request.new(env)
|
31
|
+
request_started_at = Time.now
|
32
|
+
|
33
|
+
response = yield
|
34
|
+
|
35
|
+
@requests_finished += 1
|
36
|
+
@last_request_time = Time.now - request_started_at
|
37
|
+
|
38
|
+
response
|
39
|
+
end
|
40
|
+
|
41
|
+
def serve(env)
|
42
|
+
body = @template.result(binding)
|
43
|
+
|
44
|
+
[
|
45
|
+
200,
|
46
|
+
{ 'Content-Type' => 'text/html' },
|
47
|
+
[body]
|
48
|
+
]
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module Thin
|
2
|
+
# Every standard HTTP code mapped to the appropriate message.
|
3
|
+
# Stolent from Mongrel.
|
4
|
+
HTTP_STATUS_CODES = {
|
5
|
+
100 => 'Continue',
|
6
|
+
101 => 'Switching Protocols',
|
7
|
+
200 => 'OK',
|
8
|
+
201 => 'Created',
|
9
|
+
202 => 'Accepted',
|
10
|
+
203 => 'Non-Authoritative Information',
|
11
|
+
204 => 'No Content',
|
12
|
+
205 => 'Reset Content',
|
13
|
+
206 => 'Partial Content',
|
14
|
+
300 => 'Multiple Choices',
|
15
|
+
301 => 'Moved Permanently',
|
16
|
+
302 => 'Moved Temporarily',
|
17
|
+
303 => 'See Other',
|
18
|
+
304 => 'Not Modified',
|
19
|
+
305 => 'Use Proxy',
|
20
|
+
400 => 'Bad Request',
|
21
|
+
401 => 'Unauthorized',
|
22
|
+
402 => 'Payment Required',
|
23
|
+
403 => 'Forbidden',
|
24
|
+
404 => 'Not Found',
|
25
|
+
405 => 'Method Not Allowed',
|
26
|
+
406 => 'Not Acceptable',
|
27
|
+
407 => 'Proxy Authentication Required',
|
28
|
+
408 => 'Request Time-out',
|
29
|
+
409 => 'Conflict',
|
30
|
+
410 => 'Gone',
|
31
|
+
411 => 'Length Required',
|
32
|
+
412 => 'Precondition Failed',
|
33
|
+
413 => 'Request Entity Too Large',
|
34
|
+
414 => 'Request-URI Too Large',
|
35
|
+
415 => 'Unsupported Media Type',
|
36
|
+
500 => 'Internal Server Error',
|
37
|
+
501 => 'Not Implemented',
|
38
|
+
502 => 'Bad Gateway',
|
39
|
+
503 => 'Service Unavailable',
|
40
|
+
504 => 'Gateway Time-out',
|
41
|
+
505 => 'HTTP Version not supported'
|
42
|
+
}
|
43
|
+
end
|
data/lib/thin/version.rb
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
module Thin
|
2
|
+
# Raised when a feature is not supported on the
|
3
|
+
# current platform.
|
4
|
+
class PlatformNotSupported < RuntimeError; end
|
5
|
+
|
6
|
+
module VERSION #:nodoc:
|
7
|
+
MAJOR = 1
|
8
|
+
MINOR = 2
|
9
|
+
TINY = 3
|
10
|
+
|
11
|
+
STRING = [MAJOR, MINOR, TINY].join('.')
|
12
|
+
|
13
|
+
CODENAME = "Flaming Astroboy".freeze
|
14
|
+
|
15
|
+
RACK = [1, 0].freeze # Rack protocol version
|
16
|
+
end
|
17
|
+
|
18
|
+
NAME = 'thin'.freeze
|
19
|
+
SERVER = "#{NAME} #{VERSION::STRING} codename #{VERSION::CODENAME}".freeze
|
20
|
+
|
21
|
+
def self.win?
|
22
|
+
RUBY_PLATFORM =~ /mswin|mingw/
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.linux?
|
26
|
+
RUBY_PLATFORM =~ /linux/
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.ruby_18?
|
30
|
+
RUBY_VERSION =~ /^1\.8/
|
31
|
+
end
|
32
|
+
end
|
data/lib/thin_parser.so
ADDED
Binary file
|
@@ -0,0 +1,66 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper'
|
2
|
+
|
3
|
+
describe Backends::SwiftiplyClient do
|
4
|
+
before do
|
5
|
+
@backend = Backends::SwiftiplyClient.new('0.0.0.0', 3333)
|
6
|
+
@backend.server = mock('server', :null_object => true)
|
7
|
+
end
|
8
|
+
|
9
|
+
it "should connect" do
|
10
|
+
EventMachine.run do
|
11
|
+
@backend.connect
|
12
|
+
EventMachine.stop
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should disconnect" do
|
17
|
+
EventMachine.run do
|
18
|
+
@backend.connect
|
19
|
+
@backend.disconnect
|
20
|
+
EventMachine.stop
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
describe SwiftiplyConnection do
|
26
|
+
before do
|
27
|
+
@connection = SwiftiplyConnection.new(nil)
|
28
|
+
@connection.backend = Backends::SwiftiplyClient.new('0.0.0.0', 3333)
|
29
|
+
@connection.backend.server = mock('server', :null_object => true)
|
30
|
+
end
|
31
|
+
|
32
|
+
it do
|
33
|
+
@connection.should be_persistent
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should send handshake on connection_completed" do
|
37
|
+
@connection.should_receive(:send_data).with('swiftclient000000000d0500')
|
38
|
+
@connection.connection_completed
|
39
|
+
end
|
40
|
+
|
41
|
+
it "should reconnect on unbind" do
|
42
|
+
@connection.backend.stub!(:running?).and_return(true)
|
43
|
+
@connection.stub!(:rand).and_return(0) # Make sure we don't wait
|
44
|
+
|
45
|
+
@connection.should_receive(:reconnect).with('0.0.0.0', 3333)
|
46
|
+
|
47
|
+
EventMachine.run do
|
48
|
+
@connection.unbind
|
49
|
+
EventMachine.add_timer(0) { EventMachine.stop }
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
it "should not reconnect when not running" do
|
54
|
+
@connection.backend.stub!(:running?).and_return(false)
|
55
|
+
EventMachine.should_not_receive(:add_timer)
|
56
|
+
@connection.unbind
|
57
|
+
end
|
58
|
+
|
59
|
+
it "should have a host_ip" do
|
60
|
+
@connection.send(:host_ip).should == [0, 0, 0, 0]
|
61
|
+
end
|
62
|
+
|
63
|
+
it "should generate swiftiply_handshake based on key" do
|
64
|
+
@connection.send(:swiftiply_handshake, 'key').should == 'swiftclient000000000d0503key'
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper'
|
2
|
+
|
3
|
+
describe Backends::TcpServer do
|
4
|
+
before do
|
5
|
+
@backend = Backends::TcpServer.new('0.0.0.0', 3333)
|
6
|
+
end
|
7
|
+
|
8
|
+
it "should not use epoll" do
|
9
|
+
@backend.no_epoll = true
|
10
|
+
EventMachine.should_not_receive(:epoll)
|
11
|
+
@backend.config
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should use epoll" do
|
15
|
+
EventMachine.should_receive(:epoll)
|
16
|
+
@backend.config
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should connect" do
|
20
|
+
EventMachine.run do
|
21
|
+
@backend.connect
|
22
|
+
EventMachine.stop
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should disconnect" do
|
27
|
+
EventMachine.run do
|
28
|
+
@backend.connect
|
29
|
+
@backend.disconnect
|
30
|
+
EventMachine.stop
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper'
|
2
|
+
|
3
|
+
describe Backends::UnixServer do
|
4
|
+
before do
|
5
|
+
@backend = Backends::UnixServer.new('/tmp/thin-test.sock')
|
6
|
+
end
|
7
|
+
|
8
|
+
it "should connect" do
|
9
|
+
EventMachine.run do
|
10
|
+
@backend.connect
|
11
|
+
EventMachine.stop
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should disconnect" do
|
16
|
+
EventMachine.run do
|
17
|
+
@backend.connect
|
18
|
+
@backend.disconnect
|
19
|
+
EventMachine.stop
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should remove socket file on close" do
|
24
|
+
@backend.close
|
25
|
+
File.exist?('/tmp/thin-test.sock').should be_false
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
describe UnixConnection do
|
30
|
+
before do
|
31
|
+
@connection = UnixConnection.new(nil)
|
32
|
+
end
|
33
|
+
|
34
|
+
it "should return 127.0.0.1 as remote_address" do
|
35
|
+
@connection.remote_address.should == '127.0.0.1'
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
2
|
+
|
3
|
+
describe Command do
|
4
|
+
before do
|
5
|
+
Command.script = 'thin'
|
6
|
+
@command = Command.new(:start, :port => 3000, :daemonize => true, :log => 'hi.log',
|
7
|
+
:require => %w(rubygems thin), :no_epoll => true)
|
8
|
+
end
|
9
|
+
|
10
|
+
it 'should shellify command' do
|
11
|
+
out = @command.shellify
|
12
|
+
out.should include('--port=3000', '--daemonize', '--log="hi.log"', 'thin start --')
|
13
|
+
out.should_not include('--pid')
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'should shellify Array argument to multiple parameters' do
|
17
|
+
out = @command.shellify
|
18
|
+
out.should include('--require="rubygems"', '--require="thin"')
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'should convert _ to - in option name' do
|
22
|
+
out = @command.shellify
|
23
|
+
out.should include('--no-epoll')
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,106 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
2
|
+
|
3
|
+
describe Connection do
|
4
|
+
before do
|
5
|
+
@connection = Connection.new(mock('EM', :null_object => true))
|
6
|
+
@connection.post_init
|
7
|
+
@connection.app = proc do |env|
|
8
|
+
[200, {}, ['']]
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should parse on receive_data" do
|
13
|
+
@connection.request.should_receive(:parse).with('GET')
|
14
|
+
@connection.receive_data('GET')
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should close connection on InvalidRequest error in receive_data" do
|
18
|
+
@connection.request.stub!(:parse).and_raise(InvalidRequest)
|
19
|
+
@connection.should_receive(:close_connection)
|
20
|
+
@connection.receive_data('')
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should process when parsing complete" do
|
24
|
+
@connection.request.should_receive(:parse).and_return(true)
|
25
|
+
@connection.should_receive(:process)
|
26
|
+
@connection.receive_data('GET')
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should process" do
|
30
|
+
@connection.process
|
31
|
+
end
|
32
|
+
|
33
|
+
it "should rescue error in process" do
|
34
|
+
@connection.app.should_receive(:call).and_raise(StandardError)
|
35
|
+
@connection.process
|
36
|
+
end
|
37
|
+
|
38
|
+
it "should rescue Timeout error in process" do
|
39
|
+
@connection.app.should_receive(:call).and_raise(Timeout::Error.new("timeout error not rescued"))
|
40
|
+
@connection.process
|
41
|
+
end
|
42
|
+
|
43
|
+
it "should not return HTTP_X_FORWARDED_FOR as remote_address" do
|
44
|
+
@connection.request.env['HTTP_X_FORWARDED_FOR'] = '1.2.3.4'
|
45
|
+
@connection.stub!(:socket_address).and_return("127.0.0.1")
|
46
|
+
@connection.remote_address.should == "127.0.0.1"
|
47
|
+
end
|
48
|
+
|
49
|
+
it "should return nil on error retreiving remote_address" do
|
50
|
+
@connection.stub!(:get_peername).and_raise(RuntimeError)
|
51
|
+
@connection.remote_address.should be_nil
|
52
|
+
end
|
53
|
+
|
54
|
+
it "should return nil on nil get_peername" do
|
55
|
+
@connection.stub!(:get_peername).and_return(nil)
|
56
|
+
@connection.remote_address.should be_nil
|
57
|
+
end
|
58
|
+
|
59
|
+
it "should return nil on empty get_peername" do
|
60
|
+
@connection.stub!(:get_peername).and_return('')
|
61
|
+
@connection.remote_address.should be_nil
|
62
|
+
end
|
63
|
+
|
64
|
+
it "should return remote_address" do
|
65
|
+
@connection.stub!(:get_peername).and_return(Socket.pack_sockaddr_in(3000, '127.0.0.1'))
|
66
|
+
@connection.remote_address.should == '127.0.0.1'
|
67
|
+
end
|
68
|
+
|
69
|
+
it "should not be persistent" do
|
70
|
+
@connection.should_not be_persistent
|
71
|
+
end
|
72
|
+
|
73
|
+
it "should be persistent when response is and allowed" do
|
74
|
+
@connection.response.stub!(:persistent?).and_return(true)
|
75
|
+
@connection.can_persist!
|
76
|
+
@connection.should be_persistent
|
77
|
+
end
|
78
|
+
|
79
|
+
it "should not be persistent when response is but not allowed" do
|
80
|
+
@connection.response.persistent!
|
81
|
+
@connection.should_not be_persistent
|
82
|
+
end
|
83
|
+
|
84
|
+
it "should set request env as rack.multithread" do
|
85
|
+
EventMachine.should_receive(:defer)
|
86
|
+
|
87
|
+
@connection.threaded = true
|
88
|
+
@connection.process
|
89
|
+
|
90
|
+
@connection.request.env["rack.multithread"].should == true
|
91
|
+
end
|
92
|
+
|
93
|
+
it "should set as threaded when app.deferred? is true" do
|
94
|
+
@connection.app.should_receive(:deferred?).and_return(true)
|
95
|
+
@connection.should be_threaded
|
96
|
+
end
|
97
|
+
|
98
|
+
it "should not set as threaded when app.deferred? is false" do
|
99
|
+
@connection.app.should_receive(:deferred?).and_return(false)
|
100
|
+
@connection.should_not be_threaded
|
101
|
+
end
|
102
|
+
|
103
|
+
it "should not set as threaded when app do not respond to deferred?" do
|
104
|
+
@connection.should_not be_threaded
|
105
|
+
end
|
106
|
+
end
|
@@ -0,0 +1,235 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper'
|
2
|
+
include Controllers
|
3
|
+
|
4
|
+
describe Cluster, "with host and port" do
|
5
|
+
before do
|
6
|
+
@cluster = Cluster.new(:chdir => '/rails_app',
|
7
|
+
:address => '0.0.0.0',
|
8
|
+
:port => 3000,
|
9
|
+
:servers => 3,
|
10
|
+
:timeout => 10,
|
11
|
+
:log => 'thin.log',
|
12
|
+
:pid => 'thin.pid'
|
13
|
+
)
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'should include port number in file names' do
|
17
|
+
@cluster.send(:include_server_number, 'thin.log', 3000).should == 'thin.3000.log'
|
18
|
+
@cluster.send(:include_server_number, 'thin.pid', 3000).should == 'thin.3000.pid'
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'should call each server' do
|
22
|
+
calls = []
|
23
|
+
@cluster.send(:with_each_server) do |port|
|
24
|
+
calls << port
|
25
|
+
end
|
26
|
+
calls.should == [3000, 3001, 3002]
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'should start on each port' do
|
30
|
+
Command.should_receive(:run).with(:start, options_for_port(3000))
|
31
|
+
Command.should_receive(:run).with(:start, options_for_port(3001))
|
32
|
+
Command.should_receive(:run).with(:start, options_for_port(3002))
|
33
|
+
|
34
|
+
@cluster.start
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'should stop on each port' do
|
38
|
+
Command.should_receive(:run).with(:stop, options_for_port(3000))
|
39
|
+
Command.should_receive(:run).with(:stop, options_for_port(3001))
|
40
|
+
Command.should_receive(:run).with(:stop, options_for_port(3002))
|
41
|
+
|
42
|
+
@cluster.stop
|
43
|
+
end
|
44
|
+
|
45
|
+
private
|
46
|
+
def options_for_port(port)
|
47
|
+
{ :daemonize => true, :log => "thin.#{port}.log", :timeout => 10, :address => "0.0.0.0", :port => port, :pid => "thin.#{port}.pid", :chdir => "/rails_app" }
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
describe Cluster, "with UNIX socket" do
|
52
|
+
before do
|
53
|
+
@cluster = Cluster.new(:chdir => '/rails_app',
|
54
|
+
:socket => '/tmp/thin.sock',
|
55
|
+
:address => '0.0.0.0',
|
56
|
+
:port => 3000,
|
57
|
+
:servers => 3,
|
58
|
+
:timeout => 10,
|
59
|
+
:log => 'thin.log',
|
60
|
+
:pid => 'thin.pid'
|
61
|
+
)
|
62
|
+
end
|
63
|
+
|
64
|
+
it 'should include socket number in file names' do
|
65
|
+
@cluster.send(:include_server_number, 'thin.sock', 0).should == 'thin.0.sock'
|
66
|
+
@cluster.send(:include_server_number, 'thin', 0).should == 'thin.0'
|
67
|
+
end
|
68
|
+
|
69
|
+
it "should exclude :address and :port options" do
|
70
|
+
@cluster.options.should_not have_key(:address)
|
71
|
+
@cluster.options.should_not have_key(:port)
|
72
|
+
end
|
73
|
+
|
74
|
+
it 'should call each server' do
|
75
|
+
calls = []
|
76
|
+
@cluster.send(:with_each_server) do |n|
|
77
|
+
calls << n
|
78
|
+
end
|
79
|
+
calls.should == [0, 1, 2]
|
80
|
+
end
|
81
|
+
|
82
|
+
it 'should start each server' do
|
83
|
+
Command.should_receive(:run).with(:start, options_for_socket(0))
|
84
|
+
Command.should_receive(:run).with(:start, options_for_socket(1))
|
85
|
+
Command.should_receive(:run).with(:start, options_for_socket(2))
|
86
|
+
|
87
|
+
@cluster.start
|
88
|
+
end
|
89
|
+
|
90
|
+
it 'should stop each server' do
|
91
|
+
Command.should_receive(:run).with(:stop, options_for_socket(0))
|
92
|
+
Command.should_receive(:run).with(:stop, options_for_socket(1))
|
93
|
+
Command.should_receive(:run).with(:stop, options_for_socket(2))
|
94
|
+
|
95
|
+
@cluster.stop
|
96
|
+
end
|
97
|
+
|
98
|
+
|
99
|
+
private
|
100
|
+
def options_for_socket(number)
|
101
|
+
{ :daemonize => true, :log => "thin.#{number}.log", :timeout => 10, :socket => "/tmp/thin.#{number}.sock", :pid => "thin.#{number}.pid", :chdir => "/rails_app" }
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
describe Cluster, "controlling only one server" do
|
106
|
+
before do
|
107
|
+
@cluster = Cluster.new(:chdir => '/rails_app',
|
108
|
+
:address => '0.0.0.0',
|
109
|
+
:port => 3000,
|
110
|
+
:servers => 3,
|
111
|
+
:timeout => 10,
|
112
|
+
:log => 'thin.log',
|
113
|
+
:pid => 'thin.pid',
|
114
|
+
:only => 3001
|
115
|
+
)
|
116
|
+
end
|
117
|
+
|
118
|
+
it 'should call only specified server' do
|
119
|
+
calls = []
|
120
|
+
@cluster.send(:with_each_server) do |n|
|
121
|
+
calls << n
|
122
|
+
end
|
123
|
+
calls.should == [3001]
|
124
|
+
end
|
125
|
+
|
126
|
+
it "should start only specified server" do
|
127
|
+
Command.should_receive(:run).with(:start, options_for_port(3001))
|
128
|
+
|
129
|
+
@cluster.start
|
130
|
+
end
|
131
|
+
|
132
|
+
private
|
133
|
+
def options_for_port(port)
|
134
|
+
{ :daemonize => true, :log => "thin.#{port}.log", :timeout => 10, :address => "0.0.0.0", :port => port, :pid => "thin.#{port}.pid", :chdir => "/rails_app" }
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
describe Cluster, "controlling only one server with UNIX socket" do
|
139
|
+
before do
|
140
|
+
@cluster = Cluster.new(:chdir => '/rails_app',
|
141
|
+
:socket => '/tmp/thin.sock',
|
142
|
+
:address => '0.0.0.0',
|
143
|
+
:port => 3000,
|
144
|
+
:servers => 3,
|
145
|
+
:timeout => 10,
|
146
|
+
:log => 'thin.log',
|
147
|
+
:pid => 'thin.pid',
|
148
|
+
:only => 1
|
149
|
+
)
|
150
|
+
end
|
151
|
+
|
152
|
+
it 'should call only specified server' do
|
153
|
+
calls = []
|
154
|
+
@cluster.send(:with_each_server) do |n|
|
155
|
+
calls << n
|
156
|
+
end
|
157
|
+
calls.should == [1]
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
describe Cluster, "controlling only one server, by sequence number" do
|
162
|
+
before do
|
163
|
+
@cluster = Cluster.new(:chdir => '/rails_app',
|
164
|
+
:address => '0.0.0.0',
|
165
|
+
:port => 3000,
|
166
|
+
:servers => 3,
|
167
|
+
:timeout => 10,
|
168
|
+
:log => 'thin.log',
|
169
|
+
:pid => 'thin.pid',
|
170
|
+
:only => 1
|
171
|
+
)
|
172
|
+
end
|
173
|
+
|
174
|
+
it 'should call only specified server' do
|
175
|
+
calls = []
|
176
|
+
@cluster.send(:with_each_server) do |n|
|
177
|
+
calls << n
|
178
|
+
end
|
179
|
+
calls.should == [3001]
|
180
|
+
end
|
181
|
+
|
182
|
+
it "should start only specified server" do
|
183
|
+
Command.should_receive(:run).with(:start, options_for_port(3001))
|
184
|
+
|
185
|
+
@cluster.start
|
186
|
+
end
|
187
|
+
|
188
|
+
private
|
189
|
+
def options_for_port(port)
|
190
|
+
{ :daemonize => true, :log => "thin.#{port}.log", :timeout => 10, :address => "0.0.0.0", :port => port, :pid => "thin.#{port}.pid", :chdir => "/rails_app" }
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
describe Cluster, "with Swiftiply" do
|
195
|
+
before do
|
196
|
+
@cluster = Cluster.new(:chdir => '/rails_app',
|
197
|
+
:address => '0.0.0.0',
|
198
|
+
:port => 3000,
|
199
|
+
:servers => 3,
|
200
|
+
:timeout => 10,
|
201
|
+
:log => 'thin.log',
|
202
|
+
:pid => 'thin.pid',
|
203
|
+
:swiftiply => true
|
204
|
+
)
|
205
|
+
end
|
206
|
+
|
207
|
+
it 'should call each server' do
|
208
|
+
calls = []
|
209
|
+
@cluster.send(:with_each_server) do |n|
|
210
|
+
calls << n
|
211
|
+
end
|
212
|
+
calls.should == [0, 1, 2]
|
213
|
+
end
|
214
|
+
|
215
|
+
it 'should start each server' do
|
216
|
+
Command.should_receive(:run).with(:start, options_for_swiftiply(0))
|
217
|
+
Command.should_receive(:run).with(:start, options_for_swiftiply(1))
|
218
|
+
Command.should_receive(:run).with(:start, options_for_swiftiply(2))
|
219
|
+
|
220
|
+
@cluster.start
|
221
|
+
end
|
222
|
+
|
223
|
+
it 'should stop each server' do
|
224
|
+
Command.should_receive(:run).with(:stop, options_for_swiftiply(0))
|
225
|
+
Command.should_receive(:run).with(:stop, options_for_swiftiply(1))
|
226
|
+
Command.should_receive(:run).with(:stop, options_for_swiftiply(2))
|
227
|
+
|
228
|
+
@cluster.stop
|
229
|
+
end
|
230
|
+
|
231
|
+
private
|
232
|
+
def options_for_swiftiply(number)
|
233
|
+
{ :address => '0.0.0.0', :port => 3000, :daemonize => true, :log => "thin.#{number}.log", :timeout => 10, :pid => "thin.#{number}.pid", :chdir => "/rails_app", :swiftiply => true }
|
234
|
+
end
|
235
|
+
end
|