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.

Files changed (137) hide show
  1. data/CHANGELOG +263 -0
  2. data/COPYING +18 -0
  3. data/README +69 -0
  4. data/Rakefile +36 -0
  5. data/benchmark/abc +51 -0
  6. data/benchmark/benchmarker.rb +80 -0
  7. data/benchmark/runner +82 -0
  8. data/bin/thin +6 -0
  9. data/example/adapter.rb +32 -0
  10. data/example/async_app.ru +126 -0
  11. data/example/async_chat.ru +247 -0
  12. data/example/async_tailer.ru +100 -0
  13. data/example/config.ru +22 -0
  14. data/example/monit_sockets +20 -0
  15. data/example/monit_unixsock +20 -0
  16. data/example/myapp.rb +1 -0
  17. data/example/ramaze.ru +12 -0
  18. data/example/thin.god +80 -0
  19. data/example/thin_solaris_smf.erb +36 -0
  20. data/example/thin_solaris_smf.readme.txt +150 -0
  21. data/example/vlad.rake +64 -0
  22. data/ext/thin_parser/common.rl +55 -0
  23. data/ext/thin_parser/ext_help.h +14 -0
  24. data/ext/thin_parser/extconf.rb +6 -0
  25. data/ext/thin_parser/parser.c +452 -0
  26. data/ext/thin_parser/parser.h +49 -0
  27. data/ext/thin_parser/parser.rl +157 -0
  28. data/ext/thin_parser/thin.c +433 -0
  29. data/lib/rack/adapter/loader.rb +79 -0
  30. data/lib/rack/adapter/rails.rb +181 -0
  31. data/lib/thin.rb +46 -0
  32. data/lib/thin/backends/base.rb +141 -0
  33. data/lib/thin/backends/swiftiply_client.rb +56 -0
  34. data/lib/thin/backends/tcp_server.rb +29 -0
  35. data/lib/thin/backends/unix_server.rb +51 -0
  36. data/lib/thin/command.rb +53 -0
  37. data/lib/thin/connection.rb +222 -0
  38. data/lib/thin/controllers/cluster.rb +127 -0
  39. data/lib/thin/controllers/controller.rb +183 -0
  40. data/lib/thin/controllers/service.rb +75 -0
  41. data/lib/thin/controllers/service.sh.erb +39 -0
  42. data/lib/thin/daemonizing.rb +174 -0
  43. data/lib/thin/headers.rb +39 -0
  44. data/lib/thin/logging.rb +54 -0
  45. data/lib/thin/request.rb +153 -0
  46. data/lib/thin/response.rb +101 -0
  47. data/lib/thin/runner.rb +209 -0
  48. data/lib/thin/server.rb +247 -0
  49. data/lib/thin/stats.html.erb +216 -0
  50. data/lib/thin/stats.rb +52 -0
  51. data/lib/thin/statuses.rb +43 -0
  52. data/lib/thin/version.rb +32 -0
  53. data/lib/thin_parser.so +0 -0
  54. data/spec/backends/swiftiply_client_spec.rb +66 -0
  55. data/spec/backends/tcp_server_spec.rb +33 -0
  56. data/spec/backends/unix_server_spec.rb +37 -0
  57. data/spec/command_spec.rb +25 -0
  58. data/spec/configs/cluster.yml +9 -0
  59. data/spec/configs/single.yml +9 -0
  60. data/spec/connection_spec.rb +106 -0
  61. data/spec/controllers/cluster_spec.rb +235 -0
  62. data/spec/controllers/controller_spec.rb +129 -0
  63. data/spec/controllers/service_spec.rb +50 -0
  64. data/spec/daemonizing_spec.rb +192 -0
  65. data/spec/headers_spec.rb +40 -0
  66. data/spec/logging_spec.rb +46 -0
  67. data/spec/perf/request_perf_spec.rb +50 -0
  68. data/spec/perf/response_perf_spec.rb +19 -0
  69. data/spec/perf/server_perf_spec.rb +39 -0
  70. data/spec/rack/loader_spec.rb +29 -0
  71. data/spec/rack/rails_adapter_spec.rb +106 -0
  72. data/spec/rails_app/app/controllers/application.rb +10 -0
  73. data/spec/rails_app/app/controllers/simple_controller.rb +19 -0
  74. data/spec/rails_app/app/helpers/application_helper.rb +3 -0
  75. data/spec/rails_app/app/views/simple/index.html.erb +15 -0
  76. data/spec/rails_app/config/boot.rb +109 -0
  77. data/spec/rails_app/config/environment.rb +64 -0
  78. data/spec/rails_app/config/environments/development.rb +18 -0
  79. data/spec/rails_app/config/environments/production.rb +19 -0
  80. data/spec/rails_app/config/environments/test.rb +22 -0
  81. data/spec/rails_app/config/initializers/inflections.rb +10 -0
  82. data/spec/rails_app/config/initializers/mime_types.rb +5 -0
  83. data/spec/rails_app/config/routes.rb +35 -0
  84. data/spec/rails_app/public/404.html +30 -0
  85. data/spec/rails_app/public/422.html +30 -0
  86. data/spec/rails_app/public/500.html +30 -0
  87. data/spec/rails_app/public/dispatch.cgi +10 -0
  88. data/spec/rails_app/public/dispatch.fcgi +24 -0
  89. data/spec/rails_app/public/dispatch.rb +10 -0
  90. data/spec/rails_app/public/favicon.ico +0 -0
  91. data/spec/rails_app/public/images/rails.png +0 -0
  92. data/spec/rails_app/public/index.html +277 -0
  93. data/spec/rails_app/public/javascripts/application.js +2 -0
  94. data/spec/rails_app/public/javascripts/controls.js +963 -0
  95. data/spec/rails_app/public/javascripts/dragdrop.js +972 -0
  96. data/spec/rails_app/public/javascripts/effects.js +1120 -0
  97. data/spec/rails_app/public/javascripts/prototype.js +4225 -0
  98. data/spec/rails_app/public/robots.txt +5 -0
  99. data/spec/rails_app/script/about +3 -0
  100. data/spec/rails_app/script/console +3 -0
  101. data/spec/rails_app/script/destroy +3 -0
  102. data/spec/rails_app/script/generate +3 -0
  103. data/spec/rails_app/script/performance/benchmarker +3 -0
  104. data/spec/rails_app/script/performance/profiler +3 -0
  105. data/spec/rails_app/script/performance/request +3 -0
  106. data/spec/rails_app/script/plugin +3 -0
  107. data/spec/rails_app/script/process/inspector +3 -0
  108. data/spec/rails_app/script/process/reaper +3 -0
  109. data/spec/rails_app/script/process/spawner +3 -0
  110. data/spec/rails_app/script/runner +3 -0
  111. data/spec/rails_app/script/server +3 -0
  112. data/spec/request/mongrel_spec.rb +39 -0
  113. data/spec/request/parser_spec.rb +215 -0
  114. data/spec/request/persistent_spec.rb +35 -0
  115. data/spec/request/processing_spec.rb +45 -0
  116. data/spec/response_spec.rb +91 -0
  117. data/spec/runner_spec.rb +168 -0
  118. data/spec/server/builder_spec.rb +44 -0
  119. data/spec/server/pipelining_spec.rb +110 -0
  120. data/spec/server/robustness_spec.rb +34 -0
  121. data/spec/server/stopping_spec.rb +55 -0
  122. data/spec/server/swiftiply.yml +6 -0
  123. data/spec/server/swiftiply_spec.rb +32 -0
  124. data/spec/server/tcp_spec.rb +57 -0
  125. data/spec/server/threaded_spec.rb +27 -0
  126. data/spec/server/unix_socket_spec.rb +26 -0
  127. data/spec/server_spec.rb +96 -0
  128. data/spec/spec_helper.rb +219 -0
  129. data/tasks/announce.rake +22 -0
  130. data/tasks/deploy.rake +13 -0
  131. data/tasks/email.erb +30 -0
  132. data/tasks/gem.rake +74 -0
  133. data/tasks/rdoc.rake +25 -0
  134. data/tasks/site.rake +15 -0
  135. data/tasks/spec.rake +49 -0
  136. data/tasks/stats.rake +28 -0
  137. metadata +246 -0
@@ -0,0 +1,129 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+ require 'ostruct'
3
+ include Controllers
4
+
5
+ describe Controller, 'start' do
6
+ before do
7
+ @controller = Controller.new(:address => '0.0.0.0',
8
+ :port => 3000,
9
+ :pid => 'thin.pid',
10
+ :log => 'thin.log',
11
+ :timeout => 60,
12
+ :max_conns => 2000,
13
+ :max_persistent_conns => 1000,
14
+ :adapter => 'rails')
15
+
16
+ @server = OpenStruct.new
17
+ @adapter = OpenStruct.new
18
+
19
+ Server.should_receive(:new).with('0.0.0.0', 3000, @controller.options).and_return(@server)
20
+ @server.should_receive(:config)
21
+ Rack::Adapter::Rails.stub!(:new).and_return(@adapter)
22
+ end
23
+
24
+ it "should configure server" do
25
+ @controller.start
26
+
27
+ @server.app.should == @adapter
28
+ @server.pid_file.should == 'thin.pid'
29
+ @server.log_file.should == 'thin.log'
30
+ @server.maximum_connections.should == 2000
31
+ @server.maximum_persistent_connections.should == 1000
32
+ end
33
+
34
+ it "should start as daemon" do
35
+ @controller.options[:daemonize] = true
36
+ @controller.options[:user] = true
37
+ @controller.options[:group] = true
38
+
39
+ @server.should_receive(:daemonize)
40
+ @server.should_receive(:change_privilege)
41
+
42
+ @controller.start
43
+ end
44
+
45
+ it "should configure Rails adapter" do
46
+ Rack::Adapter::Rails.should_receive(:new).with(@controller.options.merge(:root => nil))
47
+
48
+ @controller.start
49
+ end
50
+
51
+ it "should mount app under :prefix" do
52
+ @controller.options[:prefix] = '/app'
53
+ @controller.start
54
+
55
+ @server.app.class.should == Rack::URLMap
56
+ end
57
+
58
+ it "should mount Stats adapter under :stats" do
59
+ @controller.options[:stats] = '/stats'
60
+ @controller.start
61
+
62
+ @server.app.class.should == Stats::Adapter
63
+ end
64
+
65
+ it "should load app from Rack config" do
66
+ @controller.options[:rackup] = File.dirname(__FILE__) + '/../../example/config.ru'
67
+ @controller.start
68
+
69
+ @server.app.class.should == Proc
70
+ end
71
+
72
+ it "should load app from ruby file" do
73
+ @controller.options[:rackup] = File.dirname(__FILE__) + '/../../example/myapp.rb'
74
+ @controller.start
75
+
76
+ @server.app.should == Myapp
77
+ end
78
+
79
+ it "should throwup if rackup is not a .ru or .rb file" do
80
+ proc do
81
+ @controller.options[:rackup] = File.dirname(__FILE__) + '/../../example/myapp.foo'
82
+ @controller.start
83
+ end.should raise_error(RuntimeError, /please/)
84
+ end
85
+
86
+ it "should set server as threaded" do
87
+ @controller.options[:threaded] = true
88
+ @controller.start
89
+
90
+ @server.threaded.should be_true
91
+ end
92
+
93
+ it "should set RACK_ENV" do
94
+ @controller.options[:rackup] = File.dirname(__FILE__) + '/../../example/config.ru'
95
+ @controller.options[:environment] = "lolcat"
96
+ @controller.start
97
+
98
+ ENV['RACK_ENV'].should == "lolcat"
99
+ end
100
+
101
+ end
102
+
103
+ describe Controller do
104
+ before do
105
+ @controller = Controller.new(:pid => 'thin.pid', :timeout => 10)
106
+ @controller.stub!(:wait_for_file)
107
+ end
108
+
109
+ it "should stop" do
110
+ Server.should_receive(:kill).with('thin.pid', 10)
111
+ @controller.stop
112
+ end
113
+
114
+ it "should restart" do
115
+ Server.should_receive(:restart).with('thin.pid')
116
+ @controller.restart
117
+ end
118
+
119
+ it "should write configuration file" do
120
+ silence_stream(STDOUT) do
121
+ Controller.new(:config => 'test.yml', :port => 5000, :address => '127.0.0.1').config
122
+ end
123
+
124
+ File.read('test.yml').should include('port: 5000', 'address: 127.0.0.1')
125
+ File.read('test.yml').should_not include('config: ')
126
+
127
+ File.delete('test.yml')
128
+ end
129
+ end
@@ -0,0 +1,50 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+ include Controllers
3
+
4
+ describe Service do
5
+ before(:all) do
6
+ silence_stream(STDERR) do
7
+ Service::INITD_PATH = 'tmp/sandbox' + Service::INITD_PATH
8
+ Service::DEFAULT_CONFIG_PATH = 'tmp/sandbox' + Service::DEFAULT_CONFIG_PATH
9
+ end
10
+ end
11
+
12
+ before do
13
+ Thin.stub!(:linux?).and_return(true)
14
+ FileUtils.mkdir_p 'tmp/sandbox'
15
+
16
+ @service = Service.new(:all => 'spec/configs')
17
+ end
18
+
19
+ it "should call command for each config file" do
20
+ Command.should_receive(:run).with(:start, :config => 'spec/configs/cluster.yml', :daemonize => true)
21
+ Command.should_receive(:run).with(:start, :config => 'spec/configs/single.yml', :daemonize => true)
22
+
23
+ @service.start
24
+ end
25
+
26
+ it "should create /etc/init.d/thin file when calling install" do
27
+ @service.install
28
+
29
+ File.exist?(Service::INITD_PATH).should be_true
30
+ File.read(Service::INITD_PATH).should include('CONFIG_PATH=tmp/sandbox/etc/thin',
31
+ 'SCRIPT_NAME=tmp/sandbox/etc/init.d/thin',
32
+ 'DAEMON=' + Command.script)
33
+ end
34
+
35
+ it "should create /etc/thin dir when calling install" do
36
+ @service.install
37
+
38
+ File.directory?(Service::DEFAULT_CONFIG_PATH).should be_true
39
+ end
40
+
41
+ it "should include specified path in /etc/init.d/thin script" do
42
+ @service.install('tmp/sandbox/usr/thin')
43
+
44
+ File.read(Service::INITD_PATH).should include('CONFIG_PATH=tmp/sandbox/usr/thin')
45
+ end
46
+
47
+ after do
48
+ FileUtils.rm_rf 'tmp/sandbox'
49
+ end
50
+ end
@@ -0,0 +1,192 @@
1
+ require File.dirname(__FILE__) + '/spec_helper'
2
+
3
+ class TestServer
4
+ include Logging # Daemonizable should include this?
5
+ include Daemonizable
6
+
7
+ def stop
8
+ end
9
+
10
+ def name
11
+ 'Thin test server'
12
+ end
13
+ end
14
+
15
+ describe 'Daemonizing' do
16
+ before :all do
17
+ @logfile = File.dirname(__FILE__) + '/../log/daemonizing_test.log'
18
+ @pidfile = 'test.pid'
19
+ File.delete(@logfile) if File.exist?(@logfile)
20
+ File.delete(@pidfile) if File.exist?(@pidfile)
21
+ end
22
+
23
+ before :each do
24
+ @server = TestServer.new
25
+ @server.log_file = @logfile
26
+ @server.pid_file = @pidfile
27
+ @pid = nil
28
+ end
29
+
30
+ it 'should have a pid file' do
31
+ @server.should respond_to(:pid_file)
32
+ @server.should respond_to(:pid_file=)
33
+ end
34
+
35
+ it 'should create a pid file' do
36
+ @pid = fork do
37
+ @server.daemonize
38
+ sleep 1
39
+ end
40
+
41
+ sleep 1
42
+ Process.wait(@pid)
43
+ File.exist?(@server.pid_file).should be_true
44
+ @pid = @server.pid
45
+
46
+ proc { sleep 0.1 while File.exist?(@server.pid_file) }.should take_less_then(5)
47
+ end
48
+
49
+ it 'should redirect stdio to a log file' do
50
+ @pid = fork do
51
+ @server.log_file = 'daemon_test.log'
52
+ @server.daemonize
53
+
54
+ puts "simple puts"
55
+ STDERR.puts "STDERR.puts"
56
+ STDOUT.puts "STDOUT.puts"
57
+ end
58
+ Process.wait(@pid)
59
+ # Wait for the file to close and magical stuff to happen
60
+ proc { sleep 0.1 until File.exist?('daemon_test.log') }.should take_less_then(3)
61
+ sleep 0.5
62
+
63
+ @pid = @server.pid
64
+
65
+ log = File.read('daemon_test.log')
66
+ log.should include('simple puts', 'STDERR.puts', 'STDOUT.puts')
67
+
68
+ File.delete 'daemon_test.log'
69
+ end
70
+
71
+ it 'should change privilege' do
72
+ @pid = fork do
73
+ @server.daemonize
74
+ @server.change_privilege('root', 'admin')
75
+ end
76
+ Process.wait(@pid)
77
+ $?.should be_a_success
78
+ end
79
+
80
+ it 'should kill process in pid file' do
81
+ @pid = fork do
82
+ @server.daemonize
83
+ loop { sleep 3 }
84
+ end
85
+
86
+ server_should_start_in_less_then 3
87
+
88
+ @pid = @server.pid
89
+
90
+ silence_stream STDOUT do
91
+ TestServer.kill(@server.pid_file, 1)
92
+ end
93
+
94
+ File.exist?(@server.pid_file).should be_false
95
+ end
96
+
97
+ it 'should force kill process in pid file' do
98
+ @pid = fork do
99
+ @server.daemonize
100
+ loop { sleep 3 }
101
+ end
102
+
103
+ server_should_start_in_less_then 3
104
+
105
+ @pid = @server.pid
106
+
107
+ silence_stream STDOUT do
108
+ TestServer.kill(@server.pid_file, 0)
109
+ end
110
+
111
+ File.exist?(@server.pid_file).should be_false
112
+ end
113
+
114
+ it 'should send kill signal if timeout' do
115
+ @pid = fork do
116
+ @server.should_receive(:stop) # pretend we cannot handle the INT signal
117
+ @server.daemonize
118
+ sleep 5
119
+ end
120
+
121
+ server_should_start_in_less_then 10
122
+
123
+ @pid = @server.pid
124
+
125
+ silence_stream STDOUT do
126
+ TestServer.kill(@server.pid_file, 1)
127
+ end
128
+
129
+ sleep 1
130
+
131
+ File.exist?(@server.pid_file).should be_false
132
+ Process.running?(@pid).should be_false
133
+ end
134
+
135
+ it "should restart" do
136
+ @pid = fork do
137
+ @server.on_restart {}
138
+ @server.daemonize
139
+ sleep 5
140
+ end
141
+
142
+ server_should_start_in_less_then 10
143
+
144
+ @pid = @server.pid
145
+
146
+ silence_stream STDOUT do
147
+ TestServer.restart(@server.pid_file)
148
+ end
149
+
150
+ proc { sleep 0.1 while File.exist?(@server.pid_file) }.should take_less_then(10)
151
+ end
152
+
153
+ it "should not restart when not running" do
154
+ silence_stream STDOUT do
155
+ TestServer.restart(@server.pid_file)
156
+ end
157
+ end
158
+
159
+ it "should exit and raise if pid file already exist" do
160
+ @pid = fork do
161
+ @server.daemonize
162
+ sleep 5
163
+ end
164
+ server_should_start_in_less_then 10
165
+
166
+ @pid = @server.pid
167
+
168
+ proc { @server.daemonize }.should raise_error(PidFileExist)
169
+
170
+ File.exist?(@server.pid_file).should be_true
171
+ end
172
+
173
+ it "should should delete pid file if stale" do
174
+ # Create a file w/ a PID that does not exist
175
+ File.open(@server.pid_file, 'w') { |f| f << 999999999 }
176
+
177
+ @server.send(:remove_stale_pid_file)
178
+
179
+ File.exist?(@server.pid_file).should be_false
180
+ end
181
+
182
+ after do
183
+ Process.kill(9, @pid.to_i) if @pid && Process.running?(@pid.to_i)
184
+ Process.kill(9, @server.pid) if @server.pid && Process.running?(@server.pid)
185
+ File.delete(@server.pid_file) rescue nil
186
+ end
187
+
188
+ private
189
+ def server_should_start_in_less_then(sec=10)
190
+ proc { sleep 0.1 until File.exist?(@server.pid_file) }.should take_less_then(10)
191
+ end
192
+ end
@@ -0,0 +1,40 @@
1
+ require File.dirname(__FILE__) + '/spec_helper'
2
+
3
+ describe Headers do
4
+ before do
5
+ @headers = Headers.new
6
+ end
7
+
8
+ it 'should allow duplicate on some fields' do
9
+ @headers['Set-Cookie'] = 'twice'
10
+ @headers['Set-Cookie'] = 'is cooler the once'
11
+
12
+ @headers.to_s.should == "Set-Cookie: twice\r\nSet-Cookie: is cooler the once\r\n"
13
+ end
14
+
15
+ it 'should overwrite value on non duplicate fields' do
16
+ @headers['Host'] = 'this is unique'
17
+ @headers['Host'] = 'so is this'
18
+
19
+ @headers.to_s.should == "Host: this is unique\r\n"
20
+ end
21
+
22
+ it 'should output to string' do
23
+ @headers['Host'] = 'localhost:3000'
24
+ @headers['Set-Cookie'] = 'twice'
25
+ @headers['Set-Cookie'] = 'is cooler the once'
26
+
27
+ @headers.to_s.should == "Host: localhost:3000\r\nSet-Cookie: twice\r\nSet-Cookie: is cooler the once\r\n"
28
+ end
29
+
30
+ it 'should ignore nil values' do
31
+ @headers['Something'] = nil
32
+ @headers.to_s.should_not include('Something: ')
33
+ end
34
+
35
+ it 'should format Time values correctly' do
36
+ time = Time.now
37
+ @headers['Modified-At'] = time
38
+ @headers.to_s.should include("Modified-At: #{time.httpdate}")
39
+ end
40
+ end
@@ -0,0 +1,46 @@
1
+ require File.dirname(__FILE__) + '/spec_helper'
2
+
3
+ class TestLogging
4
+ include Logging
5
+ end
6
+
7
+ describe Logging do
8
+ before do
9
+ Logging.silent = false
10
+ @object = TestLogging.new
11
+ end
12
+
13
+ it "should output debug when set to true" do
14
+ Logging.debug = true
15
+ @object.should_receive(:puts)
16
+ @object.debug 'hi'
17
+ end
18
+
19
+ it "should output trace when set to true" do
20
+ Logging.trace = true
21
+ @object.should_receive(:puts)
22
+ @object.trace 'hi'
23
+ end
24
+
25
+ it "should not output when silenced" do
26
+ Logging.silent = true
27
+ @object.should_not_receive(:puts)
28
+ @object.log 'hi'
29
+ end
30
+
31
+ it "should not output when silenced as instance method" do
32
+ @object.silent = true
33
+
34
+ @object.should_not_receive(:puts)
35
+ @object.log 'hi'
36
+ end
37
+
38
+ it "should be usable as module functions" do
39
+ Logging.silent = true
40
+ Logging.log "hi"
41
+ end
42
+
43
+ after do
44
+ Logging.silent = true
45
+ end
46
+ end