rsense-server 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (137) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +23 -0
  3. data/Gemfile +14 -0
  4. data/Guardfile +5 -0
  5. data/LICENSE.txt +1 -0
  6. data/README.md +51 -0
  7. data/Rakefile +9 -0
  8. data/bin/_rsense.rb +115 -0
  9. data/config/puma.rb +2 -0
  10. data/lib/rsense/server/code.rb +38 -0
  11. data/lib/rsense/server/command/completion_result.rb +11 -0
  12. data/lib/rsense/server/command/special_meth.rb +18 -0
  13. data/lib/rsense/server/command/type_inference_method.rb +24 -0
  14. data/lib/rsense/server/command.rb +239 -0
  15. data/lib/rsense/server/config.rb +70 -0
  16. data/lib/rsense/server/gem_path.rb +18 -0
  17. data/lib/rsense/server/listeners/find_definition_event_listener.rb +91 -0
  18. data/lib/rsense/server/listeners/where_event_listener.rb +39 -0
  19. data/lib/rsense/server/load_path.rb +62 -0
  20. data/lib/rsense/server/options.rb +85 -0
  21. data/lib/rsense/server/parser.rb +17 -0
  22. data/lib/rsense/server/path_info.rb +17 -0
  23. data/lib/rsense/server/project.rb +24 -0
  24. data/lib/rsense/server/version.rb +5 -0
  25. data/lib/rsense/server.rb +18 -0
  26. data/rsense-server.gemspec +35 -0
  27. data/spec/fixtures/config_fixture/.rsense +4 -0
  28. data/spec/fixtures/deeply/nested/thing.rb +0 -0
  29. data/spec/fixtures/find_def_sample.json +10 -0
  30. data/spec/fixtures/sample.json +10 -0
  31. data/spec/fixtures/test_gem/.gitignore +22 -0
  32. data/spec/fixtures/test_gem/Gemfile +4 -0
  33. data/spec/fixtures/test_gem/LICENSE.txt +22 -0
  34. data/spec/fixtures/test_gem/README.md +29 -0
  35. data/spec/fixtures/test_gem/Rakefile +2 -0
  36. data/spec/fixtures/test_gem/lib/sample/version.rb +3 -0
  37. data/spec/fixtures/test_gem/lib/sample.rb +16 -0
  38. data/spec/fixtures/test_gem/sample.gemspec +23 -0
  39. data/spec/fixtures/test_gem/test.json +10 -0
  40. data/spec/rsense/server/code_spec.rb +44 -0
  41. data/spec/rsense/server/command/special_meth_spec.rb +23 -0
  42. data/spec/rsense/server/command_spec.rb +108 -0
  43. data/spec/rsense/server/config_spec.rb +27 -0
  44. data/spec/rsense/server/gem_path_spec.rb +16 -0
  45. data/spec/rsense/server/load_path_spec.rb +63 -0
  46. data/spec/rsense/server/options_spec.rb +33 -0
  47. data/spec/rsense/server/path_info_spec.rb +11 -0
  48. data/spec/rsense/server/project_spec.rb +18 -0
  49. data/spec/rsense/server_spec.rb +7 -0
  50. data/spec/spec_helper.rb +16 -0
  51. data/vendor/gems/puma-2.8.2-java/COPYING +55 -0
  52. data/vendor/gems/puma-2.8.2-java/DEPLOYMENT.md +92 -0
  53. data/vendor/gems/puma-2.8.2-java/Gemfile +17 -0
  54. data/vendor/gems/puma-2.8.2-java/History.txt +532 -0
  55. data/vendor/gems/puma-2.8.2-java/LICENSE +26 -0
  56. data/vendor/gems/puma-2.8.2-java/Manifest.txt +68 -0
  57. data/vendor/gems/puma-2.8.2-java/README.md +251 -0
  58. data/vendor/gems/puma-2.8.2-java/Rakefile +158 -0
  59. data/vendor/gems/puma-2.8.2-java/bin/puma +10 -0
  60. data/vendor/gems/puma-2.8.2-java/bin/puma-wild +17 -0
  61. data/vendor/gems/puma-2.8.2-java/bin/pumactl +12 -0
  62. data/vendor/gems/puma-2.8.2-java/docs/config.md +0 -0
  63. data/vendor/gems/puma-2.8.2-java/docs/nginx.md +80 -0
  64. data/vendor/gems/puma-2.8.2-java/docs/signals.md +42 -0
  65. data/vendor/gems/puma-2.8.2-java/ext/puma_http11/PumaHttp11Service.java +17 -0
  66. data/vendor/gems/puma-2.8.2-java/ext/puma_http11/ext_help.h +15 -0
  67. data/vendor/gems/puma-2.8.2-java/ext/puma_http11/extconf.rb +8 -0
  68. data/vendor/gems/puma-2.8.2-java/ext/puma_http11/http11_parser.c +1225 -0
  69. data/vendor/gems/puma-2.8.2-java/ext/puma_http11/http11_parser.h +64 -0
  70. data/vendor/gems/puma-2.8.2-java/ext/puma_http11/http11_parser.java.rl +161 -0
  71. data/vendor/gems/puma-2.8.2-java/ext/puma_http11/http11_parser.rl +146 -0
  72. data/vendor/gems/puma-2.8.2-java/ext/puma_http11/http11_parser_common.rl +54 -0
  73. data/vendor/gems/puma-2.8.2-java/ext/puma_http11/io_buffer.c +155 -0
  74. data/vendor/gems/puma-2.8.2-java/ext/puma_http11/mini_ssl.c +195 -0
  75. data/vendor/gems/puma-2.8.2-java/ext/puma_http11/org/jruby/puma/Http11.java +225 -0
  76. data/vendor/gems/puma-2.8.2-java/ext/puma_http11/org/jruby/puma/Http11Parser.java +488 -0
  77. data/vendor/gems/puma-2.8.2-java/ext/puma_http11/org/jruby/puma/MiniSSL.java +289 -0
  78. data/vendor/gems/puma-2.8.2-java/ext/puma_http11/puma_http11.c +491 -0
  79. data/vendor/gems/puma-2.8.2-java/lib/puma/accept_nonblock.rb +23 -0
  80. data/vendor/gems/puma-2.8.2-java/lib/puma/app/status.rb +59 -0
  81. data/vendor/gems/puma-2.8.2-java/lib/puma/binder.rb +298 -0
  82. data/vendor/gems/puma-2.8.2-java/lib/puma/capistrano.rb +86 -0
  83. data/vendor/gems/puma-2.8.2-java/lib/puma/cli.rb +587 -0
  84. data/vendor/gems/puma-2.8.2-java/lib/puma/client.rb +289 -0
  85. data/vendor/gems/puma-2.8.2-java/lib/puma/cluster.rb +389 -0
  86. data/vendor/gems/puma-2.8.2-java/lib/puma/compat.rb +18 -0
  87. data/vendor/gems/puma-2.8.2-java/lib/puma/configuration.rb +377 -0
  88. data/vendor/gems/puma-2.8.2-java/lib/puma/const.rb +165 -0
  89. data/vendor/gems/puma-2.8.2-java/lib/puma/control_cli.rb +251 -0
  90. data/vendor/gems/puma-2.8.2-java/lib/puma/daemon_ext.rb +25 -0
  91. data/vendor/gems/puma-2.8.2-java/lib/puma/delegation.rb +11 -0
  92. data/vendor/gems/puma-2.8.2-java/lib/puma/detect.rb +4 -0
  93. data/vendor/gems/puma-2.8.2-java/lib/puma/events.rb +130 -0
  94. data/vendor/gems/puma-2.8.2-java/lib/puma/io_buffer.rb +7 -0
  95. data/vendor/gems/puma-2.8.2-java/lib/puma/java_io_buffer.rb +45 -0
  96. data/vendor/gems/puma-2.8.2-java/lib/puma/jruby_restart.rb +83 -0
  97. data/vendor/gems/puma-2.8.2-java/lib/puma/minissl.rb +148 -0
  98. data/vendor/gems/puma-2.8.2-java/lib/puma/null_io.rb +34 -0
  99. data/vendor/gems/puma-2.8.2-java/lib/puma/puma_http11.jar +0 -0
  100. data/vendor/gems/puma-2.8.2-java/lib/puma/rack_default.rb +7 -0
  101. data/vendor/gems/puma-2.8.2-java/lib/puma/rack_patch.rb +45 -0
  102. data/vendor/gems/puma-2.8.2-java/lib/puma/reactor.rb +183 -0
  103. data/vendor/gems/puma-2.8.2-java/lib/puma/runner.rb +146 -0
  104. data/vendor/gems/puma-2.8.2-java/lib/puma/server.rb +801 -0
  105. data/vendor/gems/puma-2.8.2-java/lib/puma/single.rb +102 -0
  106. data/vendor/gems/puma-2.8.2-java/lib/puma/tcp_logger.rb +32 -0
  107. data/vendor/gems/puma-2.8.2-java/lib/puma/thread_pool.rb +185 -0
  108. data/vendor/gems/puma-2.8.2-java/lib/puma/util.rb +9 -0
  109. data/vendor/gems/puma-2.8.2-java/lib/puma.rb +14 -0
  110. data/vendor/gems/puma-2.8.2-java/lib/rack/handler/puma.rb +66 -0
  111. data/vendor/gems/puma-2.8.2-java/puma.gemspec +55 -0
  112. data/vendor/gems/puma-2.8.2-java/test/test_app_status.rb +92 -0
  113. data/vendor/gems/puma-2.8.2-java/test/test_cli.rb +173 -0
  114. data/vendor/gems/puma-2.8.2-java/test/test_config.rb +26 -0
  115. data/vendor/gems/puma-2.8.2-java/test/test_http10.rb +27 -0
  116. data/vendor/gems/puma-2.8.2-java/test/test_http11.rb +144 -0
  117. data/vendor/gems/puma-2.8.2-java/test/test_integration.rb +165 -0
  118. data/vendor/gems/puma-2.8.2-java/test/test_iobuffer.rb +38 -0
  119. data/vendor/gems/puma-2.8.2-java/test/test_minissl.rb +25 -0
  120. data/vendor/gems/puma-2.8.2-java/test/test_null_io.rb +31 -0
  121. data/vendor/gems/puma-2.8.2-java/test/test_persistent.rb +238 -0
  122. data/vendor/gems/puma-2.8.2-java/test/test_puma_server.rb +323 -0
  123. data/vendor/gems/puma-2.8.2-java/test/test_rack_handler.rb +10 -0
  124. data/vendor/gems/puma-2.8.2-java/test/test_rack_server.rb +141 -0
  125. data/vendor/gems/puma-2.8.2-java/test/test_tcp_rack.rb +42 -0
  126. data/vendor/gems/puma-2.8.2-java/test/test_thread_pool.rb +156 -0
  127. data/vendor/gems/puma-2.8.2-java/test/test_unix_socket.rb +39 -0
  128. data/vendor/gems/puma-2.8.2-java/test/test_ws.rb +89 -0
  129. data/vendor/gems/puma-2.8.2-java/tools/jungle/README.md +9 -0
  130. data/vendor/gems/puma-2.8.2-java/tools/jungle/init.d/README.md +54 -0
  131. data/vendor/gems/puma-2.8.2-java/tools/jungle/init.d/puma +332 -0
  132. data/vendor/gems/puma-2.8.2-java/tools/jungle/init.d/run-puma +3 -0
  133. data/vendor/gems/puma-2.8.2-java/tools/jungle/upstart/README.md +61 -0
  134. data/vendor/gems/puma-2.8.2-java/tools/jungle/upstart/puma-manager.conf +31 -0
  135. data/vendor/gems/puma-2.8.2-java/tools/jungle/upstart/puma.conf +63 -0
  136. data/vendor/gems/puma-2.8.2-java/tools/trickletest.rb +45 -0
  137. metadata +389 -0
@@ -0,0 +1,238 @@
1
+ require 'puma'
2
+ require 'test/unit'
3
+ require 'timeout'
4
+
5
+ class TestPersistent < Test::Unit::TestCase
6
+ def setup
7
+ @valid_request = "GET / HTTP/1.1\r\nHost: test.com\r\nContent-Type: text/plain\r\n\r\n"
8
+ @close_request = "GET / HTTP/1.1\r\nHost: test.com\r\nContent-Type: text/plain\r\nConnection: close\r\n\r\n"
9
+ @http10_request = "GET / HTTP/1.0\r\nHost: test.com\r\nContent-Type: text/plain\r\n\r\n"
10
+ @keep_request = "GET / HTTP/1.0\r\nHost: test.com\r\nContent-Type: text/plain\r\nConnection: Keep-Alive\r\n\r\n"
11
+
12
+ @valid_post = "POST / HTTP/1.1\r\nHost: test.com\r\nContent-Type: text/plain\r\nContent-Length: 5\r\n\r\nhello"
13
+ @valid_no_body = "GET / HTTP/1.1\r\nHost: test.com\r\nX-Status: 204\r\nContent-Type: text/plain\r\n\r\n"
14
+
15
+ @headers = { "X-Header" => "Works" }
16
+ @body = ["Hello"]
17
+ @inputs = []
18
+
19
+ @simple = lambda do |env|
20
+ @inputs << env['rack.input']
21
+ status = Integer(env['HTTP_X_STATUS'] || 200)
22
+ [status, @headers, @body]
23
+ end
24
+
25
+ @host = "127.0.0.1"
26
+ @port = 9988
27
+
28
+ @server = Puma::Server.new @simple
29
+ @server.add_tcp_listener "127.0.0.1", 9988
30
+ @server.max_threads = 1
31
+ @server.run
32
+
33
+ @client = TCPSocket.new "127.0.0.1", 9988
34
+ end
35
+
36
+ def teardown
37
+ @client.close
38
+ @server.stop(true)
39
+ end
40
+
41
+ def lines(count, s=@client)
42
+ str = ""
43
+ timeout(5) do
44
+ count.times { str << s.gets }
45
+ end
46
+ str
47
+ end
48
+
49
+ def test_one_with_content_length
50
+ @client << @valid_request
51
+ sz = @body[0].size.to_s
52
+
53
+ assert_equal "HTTP/1.1 200 OK\r\nX-Header: Works\r\nContent-Length: #{sz}\r\n\r\n", lines(4)
54
+ assert_equal "Hello", @client.read(5)
55
+ end
56
+
57
+ def test_two_back_to_back
58
+ @client << @valid_request
59
+ sz = @body[0].size.to_s
60
+
61
+ assert_equal "HTTP/1.1 200 OK\r\nX-Header: Works\r\nContent-Length: #{sz}\r\n\r\n", lines(4)
62
+ assert_equal "Hello", @client.read(5)
63
+
64
+ @client << @valid_request
65
+ sz = @body[0].size.to_s
66
+
67
+ assert_equal "HTTP/1.1 200 OK\r\nX-Header: Works\r\nContent-Length: #{sz}\r\n\r\n", lines(4)
68
+ assert_equal "Hello", @client.read(5)
69
+ end
70
+
71
+ def test_post_then_get
72
+ @client << @valid_post
73
+ sz = @body[0].size.to_s
74
+
75
+ assert_equal "HTTP/1.1 200 OK\r\nX-Header: Works\r\nContent-Length: #{sz}\r\n\r\n", lines(4)
76
+ assert_equal "Hello", @client.read(5)
77
+
78
+ @client << @valid_request
79
+ sz = @body[0].size.to_s
80
+
81
+ assert_equal "HTTP/1.1 200 OK\r\nX-Header: Works\r\nContent-Length: #{sz}\r\n\r\n", lines(4)
82
+ assert_equal "Hello", @client.read(5)
83
+ end
84
+
85
+ def test_no_body_then_get
86
+ @client << @valid_no_body
87
+ assert_equal "HTTP/1.1 204 No Content\r\nX-Header: Works\r\n\r\n", lines(3)
88
+
89
+ @client << @valid_request
90
+ sz = @body[0].size.to_s
91
+
92
+ assert_equal "HTTP/1.1 200 OK\r\nX-Header: Works\r\nContent-Length: #{sz}\r\n\r\n", lines(4)
93
+ assert_equal "Hello", @client.read(5)
94
+ end
95
+
96
+ def test_chunked
97
+ @body << "Chunked"
98
+
99
+ @client << @valid_request
100
+
101
+ assert_equal "HTTP/1.1 200 OK\r\nX-Header: Works\r\nTransfer-Encoding: chunked\r\n\r\n5\r\nHello\r\n7\r\nChunked\r\n0\r\n\r\n", lines(10)
102
+ end
103
+
104
+ def test_no_chunked_in_http10
105
+ @body << "Chunked"
106
+
107
+ @client << @http10_request
108
+
109
+ assert_equal "HTTP/1.0 200 OK\r\nX-Header: Works\r\nConnection: close\r\n\r\n", lines(4)
110
+ assert_equal "HelloChunked", @client.read
111
+ end
112
+
113
+ def test_hex
114
+ str = "This is longer and will be in hex"
115
+ @body << str
116
+
117
+ @client << @valid_request
118
+
119
+ assert_equal "HTTP/1.1 200 OK\r\nX-Header: Works\r\nTransfer-Encoding: chunked\r\n\r\n5\r\nHello\r\n#{str.size.to_s(16)}\r\n#{str}\r\n0\r\n\r\n", lines(10)
120
+
121
+ end
122
+
123
+ def test_client11_close
124
+ @client << @close_request
125
+ sz = @body[0].size.to_s
126
+
127
+ assert_equal "HTTP/1.1 200 OK\r\nX-Header: Works\r\nConnection: close\r\nContent-Length: #{sz}\r\n\r\n", lines(5)
128
+ assert_equal "Hello", @client.read(5)
129
+ end
130
+
131
+ def test_client10_close
132
+ @client << @http10_request
133
+ sz = @body[0].size.to_s
134
+
135
+ assert_equal "HTTP/1.0 200 OK\r\nX-Header: Works\r\nConnection: close\r\nContent-Length: #{sz}\r\n\r\n", lines(5)
136
+ assert_equal "Hello", @client.read(5)
137
+ end
138
+
139
+ def test_one_with_keep_alive_header
140
+ @client << @keep_request
141
+ sz = @body[0].size.to_s
142
+
143
+ assert_equal "HTTP/1.0 200 OK\r\nX-Header: Works\r\nConnection: Keep-Alive\r\nContent-Length: #{sz}\r\n\r\n", lines(5)
144
+ assert_equal "Hello", @client.read(5)
145
+ end
146
+
147
+ def test_persistent_timeout
148
+ @server.persistent_timeout = 2
149
+ @client << @valid_request
150
+ sz = @body[0].size.to_s
151
+
152
+ assert_equal "HTTP/1.1 200 OK\r\nX-Header: Works\r\nContent-Length: #{sz}\r\n\r\n", lines(4)
153
+ assert_equal "Hello", @client.read(5)
154
+
155
+ sleep 3
156
+
157
+ assert_raises EOFError do
158
+ @client.read_nonblock(1)
159
+ end
160
+ end
161
+
162
+ def test_app_sets_content_length
163
+ @body = ["hello", " world"]
164
+ @headers['Content-Length'] = "11"
165
+
166
+ @client << @valid_request
167
+
168
+ assert_equal "HTTP/1.1 200 OK\r\nX-Header: Works\r\nContent-Length: 11\r\n\r\n",
169
+ lines(4)
170
+ assert_equal "hello world", @client.read(11)
171
+ end
172
+
173
+ def test_allow_app_to_chunk_itself
174
+ @headers = {'Transfer-Encoding' => "chunked" }
175
+
176
+ @body = ["5\r\nhello\r\n0\r\n\r\n"]
177
+
178
+ @client << @valid_request
179
+
180
+ assert_equal "HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n5\r\nhello\r\n0\r\n\r\n", lines(7)
181
+ end
182
+
183
+
184
+ def test_two_requests_in_one_chunk
185
+ @server.persistent_timeout = 3
186
+
187
+ req = @valid_request.to_s
188
+ req << "GET /second HTTP/1.1\r\nHost: test.com\r\nContent-Type: text/plain\r\n\r\n"
189
+
190
+ @client << req
191
+
192
+ sz = @body[0].size.to_s
193
+
194
+ assert_equal "HTTP/1.1 200 OK\r\nX-Header: Works\r\nContent-Length: #{sz}\r\n\r\n", lines(4)
195
+ assert_equal "Hello", @client.read(5)
196
+
197
+ assert_equal "HTTP/1.1 200 OK\r\nX-Header: Works\r\nContent-Length: #{sz}\r\n\r\n", lines(4)
198
+ assert_equal "Hello", @client.read(5)
199
+ end
200
+
201
+ def test_second_request_not_in_first_req_body
202
+ @server.persistent_timeout = 3
203
+
204
+ req = @valid_request.to_s
205
+ req << "GET /second HTTP/1.1\r\nHost: test.com\r\nContent-Type: text/plain\r\n\r\n"
206
+
207
+ @client << req
208
+
209
+ sz = @body[0].size.to_s
210
+
211
+ assert_equal "HTTP/1.1 200 OK\r\nX-Header: Works\r\nContent-Length: #{sz}\r\n\r\n", lines(4)
212
+ assert_equal "Hello", @client.read(5)
213
+
214
+ assert_equal "HTTP/1.1 200 OK\r\nX-Header: Works\r\nContent-Length: #{sz}\r\n\r\n", lines(4)
215
+ assert_equal "Hello", @client.read(5)
216
+
217
+ assert_kind_of Puma::NullIO, @inputs[0]
218
+ assert_kind_of Puma::NullIO, @inputs[1]
219
+ end
220
+
221
+ def test_keepalive_doesnt_starve_clients
222
+ sz = @body[0].size.to_s
223
+
224
+ @client << @valid_request
225
+
226
+ c2 = TCPSocket.new @host, @port
227
+ c2 << @valid_request
228
+
229
+ out = IO.select([c2], nil, nil, 1)
230
+
231
+ assert out, "select returned nil"
232
+ assert_equal c2, out.first.first
233
+
234
+ assert_equal "HTTP/1.1 200 OK\r\nX-Header: Works\r\nContent-Length: #{sz}\r\n\r\n", lines(4, c2)
235
+ assert_equal "Hello", c2.read(5)
236
+ end
237
+
238
+ end
@@ -0,0 +1,323 @@
1
+ require "rbconfig"
2
+ require 'test/unit'
3
+ require 'socket'
4
+ require 'openssl'
5
+
6
+ require 'puma/minissl'
7
+ require 'puma/server'
8
+
9
+ require 'net/https'
10
+
11
+ class TestPumaServer < Test::Unit::TestCase
12
+
13
+ def setup
14
+ @port = 3212
15
+ @host = "127.0.0.1"
16
+
17
+ @app = lambda { |env| [200, {}, [env['rack.url_scheme']]] }
18
+
19
+ @events = Puma::Events.new STDOUT, STDERR
20
+ @server = Puma::Server.new @app, @events
21
+
22
+ if defined?(JRUBY_VERSION)
23
+ @ssl_key = File.expand_path "../../examples/puma/keystore.jks", __FILE__
24
+ @ssl_cert = @ssl_key
25
+ else
26
+ @ssl_key = File.expand_path "../../examples/puma/puma_keypair.pem", __FILE__
27
+ @ssl_cert = File.expand_path "../../examples/puma/cert_puma.pem", __FILE__
28
+ end
29
+ end
30
+
31
+ def teardown
32
+ @server.stop(true)
33
+ end
34
+
35
+ def test_url_scheme_for_https
36
+ ctx = Puma::MiniSSL::Context.new
37
+
38
+ ctx.key = @ssl_key
39
+ ctx.cert = @ssl_cert
40
+
41
+ ctx.verify_mode = Puma::MiniSSL::VERIFY_NONE
42
+
43
+ @server.add_ssl_listener @host, @port, ctx
44
+ @server.run
45
+
46
+ http = Net::HTTP.new @host, @port
47
+ http.use_ssl = true
48
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
49
+
50
+ body = nil
51
+ http.start do
52
+ req = Net::HTTP::Get.new "/", {}
53
+
54
+ http.request(req) do |rep|
55
+ body = rep.body
56
+ end
57
+ end
58
+
59
+ assert_equal "https", body
60
+ end unless defined? JRUBY_VERSION
61
+
62
+ def test_proper_stringio_body
63
+ data = nil
64
+
65
+ @server.app = proc do |env|
66
+ data = env['rack.input'].read
67
+ [200, {}, ["ok"]]
68
+ end
69
+
70
+ @server.add_tcp_listener @host, @port
71
+ @server.run
72
+
73
+ fifteen = "1" * 15
74
+
75
+ sock = TCPSocket.new @host, @port
76
+ sock << "PUT / HTTP/1.0\r\nContent-Length: 30\r\n\r\n#{fifteen}"
77
+ sleep 0.1 # important so that the previous data is sent as a packet
78
+ sock << fifteen
79
+
80
+ sock.read
81
+
82
+ assert_equal "#{fifteen}#{fifteen}", data
83
+ end
84
+
85
+ def test_puma_socket
86
+ body = "HTTP/1.1 750 Upgraded to Awesome\r\nDone: Yep!\r\n"
87
+ @server.app = proc do |env|
88
+ io = env['puma.socket']
89
+
90
+ io.write body
91
+
92
+ io.close
93
+
94
+ [-1, {}, []]
95
+ end
96
+
97
+ @server.add_tcp_listener @host, @port
98
+ @server.run
99
+
100
+ sock = TCPSocket.new @host, @port
101
+ sock << "PUT / HTTP/1.0\r\n\r\nHello"
102
+
103
+ assert_equal body, sock.read
104
+ end
105
+
106
+ def test_very_large_return
107
+ giant = "x" * 2056610
108
+
109
+ @server.app = proc do |env|
110
+ [200, {}, [giant]]
111
+ end
112
+
113
+ @server.add_tcp_listener @host, @port
114
+ @server.run
115
+
116
+ sock = TCPSocket.new @host, @port
117
+ sock << "GET / HTTP/1.0\r\n\r\n"
118
+
119
+ while true
120
+ line = sock.gets
121
+ break if line == "\r\n"
122
+ end
123
+
124
+ out = sock.read
125
+
126
+ assert_equal giant.bytesize, out.bytesize
127
+ end
128
+
129
+ def test_respect_x_forwarded_proto
130
+ @server.app = proc do |env|
131
+ [200, {}, [env['SERVER_PORT']]]
132
+ end
133
+
134
+ @server.add_tcp_listener @host, @port
135
+ @server.run
136
+
137
+ req = Net::HTTP::Get.new("/")
138
+ req['HOST'] = "example.com"
139
+ req['X_FORWARDED_PROTO'] = "https"
140
+
141
+ res = Net::HTTP.start @host, @port do |http|
142
+ http.request(req)
143
+ end
144
+
145
+ assert_equal "443", res.body
146
+ end
147
+
148
+ def test_default_server_port
149
+ @server.app = proc do |env|
150
+ [200, {}, [env['SERVER_PORT']]]
151
+ end
152
+
153
+ @server.add_tcp_listener @host, @port
154
+ @server.run
155
+
156
+ req = Net::HTTP::Get.new("/")
157
+ req['HOST'] = "example.com"
158
+
159
+ res = Net::HTTP.start @host, @port do |http|
160
+ http.request(req)
161
+ end
162
+
163
+ assert_equal "80", res.body
164
+ end
165
+
166
+ def test_HEAD_has_no_body
167
+ @server.app = proc { |env| [200, {"Foo" => "Bar"}, ["hello"]] }
168
+
169
+ @server.add_tcp_listener @host, @port
170
+ @server.run
171
+
172
+ sock = TCPSocket.new @host, @port
173
+ sock << "HEAD / HTTP/1.0\r\n\r\n"
174
+
175
+ data = sock.read
176
+
177
+ assert_equal "HTTP/1.0 200 OK\r\nFoo: Bar\r\nContent-Length: 5\r\n\r\n", data
178
+ end
179
+
180
+ def test_GET_with_empty_body_has_sane_chunking
181
+ @server.app = proc { |env| [200, {}, [""]] }
182
+
183
+ @server.add_tcp_listener @host, @port
184
+ @server.run
185
+
186
+ sock = TCPSocket.new @host, @port
187
+ sock << "HEAD / HTTP/1.0\r\n\r\n"
188
+
189
+ data = sock.read
190
+
191
+ assert_equal "HTTP/1.0 200 OK\r\nContent-Length: 0\r\n\r\n", data
192
+ end
193
+
194
+ def test_GET_with_no_body_has_sane_chunking
195
+ @server.app = proc { |env| [200, {}, []] }
196
+
197
+ @server.add_tcp_listener @host, @port
198
+ @server.run
199
+
200
+ sock = TCPSocket.new @host, @port
201
+ sock << "HEAD / HTTP/1.0\r\n\r\n"
202
+
203
+ data = sock.read
204
+
205
+ assert_equal "HTTP/1.0 200 OK\r\n\r\n", data
206
+ end
207
+
208
+ def test_doesnt_print_backtrace_in_production
209
+ @events = Puma::Events.strings
210
+ @server = Puma::Server.new @app, @events
211
+
212
+ @server.app = proc { |e| raise "don't leak me bro" }
213
+ @server.leak_stack_on_error = false
214
+ @server.add_tcp_listener @host, @port
215
+ @server.run
216
+
217
+ sock = TCPSocket.new @host, @port
218
+ sock << "GET / HTTP/1.0\r\n\r\n"
219
+
220
+ data = sock.read
221
+
222
+ assert_not_match(/don't leak me bro/, data)
223
+ assert_match(/HTTP\/1.0 500 Internal Server Error/, data)
224
+ end
225
+
226
+ def test_prints_custom_error
227
+ @events = Puma::Events.strings
228
+ re = lambda { |err| [302, {'Content-Type' => 'text', 'Location' => 'foo.html'}, ['302 found']] }
229
+ @server = Puma::Server.new @app, @events, {lowlevel_error_handler: re}
230
+
231
+ @server.app = proc { |e| raise "don't leak me bro" }
232
+ @server.add_tcp_listener @host, @port
233
+ @server.run
234
+
235
+ sock = TCPSocket.new @host, @port
236
+ sock << "GET / HTTP/1.0\r\n\r\n"
237
+
238
+ data = sock.read
239
+ assert_match(/HTTP\/1.0 302 Found/, data)
240
+ end
241
+
242
+ def test_custom_http_codes_10
243
+ @server.app = proc { |env| [449, {}, [""]] }
244
+
245
+ @server.add_tcp_listener @host, @port
246
+ @server.run
247
+
248
+ sock = TCPSocket.new @host, @port
249
+
250
+ sock << "GET / HTTP/1.0\r\n\r\n"
251
+
252
+ data = sock.read
253
+
254
+ assert_equal "HTTP/1.0 449 CUSTOM\r\nConnection: close\r\nContent-Length: 0\r\n\r\n", data
255
+ end
256
+
257
+ def test_custom_http_codes_11
258
+ @server.app = proc { |env| [449, {}, [""]] }
259
+
260
+ @server.add_tcp_listener @host, @port
261
+ @server.run
262
+
263
+ sock = TCPSocket.new @host, @port
264
+ sock << "GET / HTTP/1.1\r\n\r\n"
265
+
266
+ data = sock.read
267
+
268
+ assert_equal "HTTP/1.1 449 CUSTOM\r\nContent-Length: 0\r\n\r\n", data
269
+ end
270
+
271
+ def test_HEAD_returns_content_headers
272
+ @server.app = proc { |env| [200, {"Content-Type" => "application/pdf",
273
+ "Content-Length" => "4242"}, []] }
274
+
275
+ @server.add_tcp_listener @host, @port
276
+ @server.run
277
+
278
+ sock = TCPSocket.new @host, @port
279
+
280
+ sock << "HEAD / HTTP/1.0\r\n\r\n"
281
+
282
+ data = sock.read
283
+
284
+ assert_equal "HTTP/1.0 200 OK\r\nContent-Type: application/pdf\r\nContent-Length: 4242\r\n\r\n", data
285
+ end
286
+
287
+ def test_status_hook_fires_when_server_changes_states
288
+
289
+ states = []
290
+
291
+ @events.register(:state) { |s| states << s }
292
+
293
+ @server.app = proc { |env| [200, {}, [""]] }
294
+
295
+ @server.add_tcp_listener @host, @port
296
+ @server.run
297
+
298
+ sock = TCPSocket.new @host, @port
299
+ sock << "HEAD / HTTP/1.0\r\n\r\n"
300
+
301
+ sock.read
302
+
303
+ assert_equal [:booting, :running], states
304
+
305
+ @server.stop(true)
306
+
307
+ assert_equal [:booting, :running, :stop, :done], states
308
+ end
309
+
310
+ def test_timeout_in_data_phase
311
+ @server.first_data_timeout = 2
312
+ @server.add_tcp_listener @host, @port
313
+ @server.run
314
+
315
+ client = TCPSocket.new @host, @port
316
+
317
+ client << "POST / HTTP/1.1\r\nHost: test.com\r\nContent-Type: text/plain\r\nContent-Length: 5\r\n\r\n"
318
+
319
+ data = client.gets
320
+
321
+ assert_equal "HTTP/1.1 408 Request Timeout\r\n", data
322
+ end
323
+ end
@@ -0,0 +1,10 @@
1
+ require 'test/unit'
2
+
3
+ class TestPumaUnixSocket < Test::Unit::TestCase
4
+ def test_handler
5
+ handler = Rack::Handler.get(:puma)
6
+ assert_equal Rack::Handler::Puma, handler
7
+ handler = Rack::Handler.get('Puma')
8
+ assert_equal Rack::Handler::Puma, handler
9
+ end
10
+ end
@@ -0,0 +1,141 @@
1
+ require 'test/unit'
2
+ require 'puma'
3
+ require 'rack/lint'
4
+ require 'test/testhelp'
5
+ require 'rack/commonlogger'
6
+ require 'puma/rack_patch'
7
+
8
+ class TestRackServer < Test::Unit::TestCase
9
+
10
+ class ErrorChecker
11
+ def initialize(app)
12
+ @app = app
13
+ @exception = nil
14
+ @env = nil
15
+ end
16
+
17
+ attr_reader :exception, :env
18
+
19
+ def call(env)
20
+ begin
21
+ @env = env
22
+ return @app.call(env)
23
+ rescue Exception => e
24
+ @exception = e
25
+
26
+ [
27
+ 500,
28
+ { "X-Exception" => e.message, "X-Exception-Class" => e.class.to_s },
29
+ ["Error detected"]
30
+ ]
31
+ end
32
+ end
33
+ end
34
+
35
+ class ServerLint < Rack::Lint
36
+ def call(env)
37
+ assert("No env given") { env }
38
+ check_env env
39
+
40
+ @app.call(env)
41
+ end
42
+ end
43
+
44
+ def setup
45
+ @valid_request = "GET / HTTP/1.1\r\nHost: test.com\r\nContent-Type: text/plain\r\n\r\n"
46
+
47
+ @simple = lambda { |env| [200, { "X-Header" => "Works" }, ["Hello"]] }
48
+ @server = Puma::Server.new @simple
49
+ @server.add_tcp_listener "127.0.0.1", 9998
50
+
51
+ @stopped = false
52
+ end
53
+
54
+ def stop
55
+ @server.stop(true)
56
+ @stopped = true
57
+ end
58
+
59
+ def teardown
60
+ @server.stop(true) unless @stopped
61
+ end
62
+
63
+ def test_lint
64
+ @checker = ErrorChecker.new ServerLint.new(@simple)
65
+ @server.app = @checker
66
+
67
+ @server.run
68
+
69
+ hit(['http://127.0.0.1:9998/test'])
70
+
71
+ stop
72
+
73
+ if exc = @checker.exception
74
+ raise exc
75
+ end
76
+ end
77
+
78
+ def test_large_post_body
79
+ @checker = ErrorChecker.new ServerLint.new(@simple)
80
+ @server.app = @checker
81
+
82
+ @server.run
83
+
84
+ big = "x" * (1024 * 16)
85
+
86
+ Net::HTTP.post_form URI.parse('http://127.0.0.1:9998/test'),
87
+ { "big" => big }
88
+
89
+ stop
90
+
91
+ if exc = @checker.exception
92
+ raise exc
93
+ end
94
+ end
95
+
96
+ def test_path_info
97
+ input = nil
98
+ @server.app = lambda { |env| input = env; @simple.call(env) }
99
+ @server.run
100
+
101
+ hit(['http://127.0.0.1:9998/test/a/b/c'])
102
+
103
+ stop
104
+
105
+ assert_equal "/test/a/b/c", input['PATH_INFO']
106
+ end
107
+
108
+ def test_after_reply
109
+ closed = false
110
+
111
+ @server.app = lambda do |env|
112
+ env['rack.after_reply'] << lambda { closed = true }
113
+ @simple.call(env)
114
+ end
115
+
116
+ @server.run
117
+
118
+ hit(['http://127.0.0.1:9998/test'])
119
+
120
+ stop
121
+
122
+ assert_equal true, closed
123
+ end
124
+
125
+ def test_common_logger
126
+ log = StringIO.new
127
+
128
+ logger = Rack::CommonLogger.new(@simple, log)
129
+
130
+ @server.app = logger
131
+
132
+ @server.run
133
+
134
+ hit(['http://127.0.0.1:9998/test'])
135
+
136
+ stop
137
+
138
+ assert_match %r!GET /test HTTP/1\.1!, log.string
139
+ end
140
+
141
+ end