webrick 1.3.1 → 1.6.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (71) hide show
  1. checksums.yaml +7 -0
  2. data/Gemfile +3 -0
  3. data/LICENSE.txt +22 -0
  4. data/README.md +63 -0
  5. data/Rakefile +10 -0
  6. data/bin/console +14 -0
  7. data/bin/setup +8 -0
  8. data/lib/webrick.rb +7 -7
  9. data/lib/webrick/accesslog.rb +12 -6
  10. data/lib/webrick/cgi.rb +58 -5
  11. data/lib/webrick/compat.rb +2 -1
  12. data/lib/webrick/config.rb +47 -10
  13. data/lib/webrick/cookie.rb +69 -7
  14. data/lib/webrick/htmlutils.rb +4 -2
  15. data/lib/webrick/httpauth.rb +6 -5
  16. data/lib/webrick/httpauth/authenticator.rb +13 -8
  17. data/lib/webrick/httpauth/basicauth.rb +16 -8
  18. data/lib/webrick/httpauth/digestauth.rb +35 -32
  19. data/lib/webrick/httpauth/htdigest.rb +12 -8
  20. data/lib/webrick/httpauth/htgroup.rb +10 -6
  21. data/lib/webrick/httpauth/htpasswd.rb +46 -9
  22. data/lib/webrick/httpauth/userdb.rb +1 -0
  23. data/lib/webrick/httpproxy.rb +93 -48
  24. data/lib/webrick/httprequest.rb +201 -31
  25. data/lib/webrick/httpresponse.rb +235 -70
  26. data/lib/webrick/https.rb +90 -2
  27. data/lib/webrick/httpserver.rb +45 -15
  28. data/lib/webrick/httpservlet.rb +6 -5
  29. data/lib/webrick/httpservlet/abstract.rb +5 -6
  30. data/lib/webrick/httpservlet/cgi_runner.rb +3 -2
  31. data/lib/webrick/httpservlet/cgihandler.rb +29 -11
  32. data/lib/webrick/httpservlet/erbhandler.rb +4 -3
  33. data/lib/webrick/httpservlet/filehandler.rb +136 -65
  34. data/lib/webrick/httpservlet/prochandler.rb +15 -1
  35. data/lib/webrick/httpstatus.rb +24 -14
  36. data/lib/webrick/httputils.rb +134 -17
  37. data/lib/webrick/httpversion.rb +28 -1
  38. data/lib/webrick/log.rb +25 -5
  39. data/lib/webrick/server.rb +234 -74
  40. data/lib/webrick/ssl.rb +100 -12
  41. data/lib/webrick/utils.rb +98 -69
  42. data/lib/webrick/version.rb +6 -1
  43. data/webrick.gemspec +76 -0
  44. metadata +73 -72
  45. data/README.txt +0 -21
  46. data/sample/webrick/demo-app.rb +0 -66
  47. data/sample/webrick/demo-multipart.cgi +0 -12
  48. data/sample/webrick/demo-servlet.rb +0 -6
  49. data/sample/webrick/demo-urlencoded.cgi +0 -12
  50. data/sample/webrick/hello.cgi +0 -11
  51. data/sample/webrick/hello.rb +0 -8
  52. data/sample/webrick/httpd.rb +0 -23
  53. data/sample/webrick/httpproxy.rb +0 -25
  54. data/sample/webrick/httpsd.rb +0 -33
  55. data/test/openssl/utils.rb +0 -313
  56. data/test/ruby/envutil.rb +0 -208
  57. data/test/webrick/test_cgi.rb +0 -134
  58. data/test/webrick/test_cookie.rb +0 -131
  59. data/test/webrick/test_filehandler.rb +0 -285
  60. data/test/webrick/test_httpauth.rb +0 -167
  61. data/test/webrick/test_httpproxy.rb +0 -282
  62. data/test/webrick/test_httprequest.rb +0 -411
  63. data/test/webrick/test_httpresponse.rb +0 -49
  64. data/test/webrick/test_httpserver.rb +0 -305
  65. data/test/webrick/test_httputils.rb +0 -96
  66. data/test/webrick/test_httpversion.rb +0 -40
  67. data/test/webrick/test_server.rb +0 -67
  68. data/test/webrick/test_utils.rb +0 -64
  69. data/test/webrick/utils.rb +0 -58
  70. data/test/webrick/webrick.cgi +0 -36
  71. data/test/webrick/webrick_long_filename.cgi +0 -36
@@ -1,33 +0,0 @@
1
- require "webrick"
2
- require "webrick/https"
3
-
4
- hostname = WEBrick::Utils::getservername
5
- subject = [["O", "ruby-lang.org"], ["OU", "sample"], ["CN", hostname]]
6
- comment = "Comment for self-signed certificate"
7
-
8
- httpd = WEBrick::HTTPServer.new(
9
- :DocumentRoot => File::dirname(__FILE__),
10
- :Port => 10443,
11
- :SSLEnable => true,
12
-
13
- # Specify key pair and server certificate.
14
- # :SSLPrivateKey => OpenSSL::PKey::RSA.new(File.read("server.key")),
15
- # :SSLCertificate => OpenSSL::X509::Certificate.new(File.read("server.crt")),
16
-
17
- # specify the following SSL options if you want to use auto
18
- # generated self-signed certificate.
19
- :SSLCertName => subject,
20
- :SSLComment => comment,
21
-
22
- :CGIPathEnv => ENV["PATH"] # PATH environment variable for CGI.
23
- )
24
-
25
- require "./hello"
26
- httpd.mount("/hello", HelloServlet)
27
-
28
- require "./demo-servlet"
29
- httpd.mount("/urlencoded", DemoServlet, "application/x-www-form-urlencoded")
30
- httpd.mount("/multipart", DemoServlet, "multipart/form-data")
31
-
32
- trap(:INT){ httpd.shutdown }
33
- httpd.start
@@ -1,313 +0,0 @@
1
- begin
2
- require "openssl"
3
- rescue LoadError
4
- end
5
- require "test/unit"
6
- require "digest/md5"
7
- require 'tempfile'
8
- require "rbconfig"
9
- require "socket"
10
- require_relative '../ruby/envutil'
11
-
12
- module OpenSSL::TestUtils
13
- TEST_KEY_RSA1024 = OpenSSL::PKey::RSA.new <<-_end_of_pem_
14
- -----BEGIN RSA PRIVATE KEY-----
15
- MIICXgIBAAKBgQDLwsSw1ECnPtT+PkOgHhcGA71nwC2/nL85VBGnRqDxOqjVh7Cx
16
- aKPERYHsk4BPCkE3brtThPWc9kjHEQQ7uf9Y1rbCz0layNqHyywQEVLFmp1cpIt/
17
- Q3geLv8ZD9pihowKJDyMDiN6ArYUmZczvW4976MU3+l54E6lF/JfFEU5hwIDAQAB
18
- AoGBAKSl/MQarye1yOysqX6P8fDFQt68VvtXkNmlSiKOGuzyho0M+UVSFcs6k1L0
19
- maDE25AMZUiGzuWHyaU55d7RXDgeskDMakD1v6ZejYtxJkSXbETOTLDwUWTn618T
20
- gnb17tU1jktUtU67xK/08i/XodlgnQhs6VoHTuCh3Hu77O6RAkEA7+gxqBuZR572
21
- 74/akiW/SuXm0SXPEviyO1MuSRwtI87B02D0qgV8D1UHRm4AhMnJ8MCs1809kMQE
22
- JiQUCrp9mQJBANlt2ngBO14us6NnhuAseFDTBzCHXwUUu1YKHpMMmxpnGqaldGgX
23
- sOZB3lgJsT9VlGf3YGYdkLTNVbogQKlKpB8CQQDiSwkb4vyQfDe8/NpU5Not0fII
24
- 8jsDUCb+opWUTMmfbxWRR3FBNu8wnym/m19N4fFj8LqYzHX4KY0oVPu6qvJxAkEA
25
- wa5snNekFcqONLIE4G5cosrIrb74sqL8GbGb+KuTAprzj5z1K8Bm0UW9lTjVDjDi
26
- qRYgZfZSL+x1P/54+xTFSwJAY1FxA/N3QPCXCjPh5YqFxAMQs2VVYTfg+t0MEcJD
27
- dPMQD5JX6g5HKnHFg2mZtoXQrWmJSn7p8GJK8yNTopEErA==
28
- -----END RSA PRIVATE KEY-----
29
- _end_of_pem_
30
-
31
- TEST_KEY_RSA2048 = OpenSSL::PKey::RSA.new <<-_end_of_pem_
32
- -----BEGIN RSA PRIVATE KEY-----
33
- MIIEpAIBAAKCAQEAuV9ht9J7k4NBs38jOXvvTKY9gW8nLICSno5EETR1cuF7i4pN
34
- s9I1QJGAFAX0BEO4KbzXmuOvfCpD3CU+Slp1enenfzq/t/e/1IRW0wkJUJUFQign
35
- 4CtrkJL+P07yx18UjyPlBXb81ApEmAB5mrJVSrWmqbjs07JbuS4QQGGXLc+Su96D
36
- kYKmSNVjBiLxVVSpyZfAY3hD37d60uG+X8xdW5v68JkRFIhdGlb6JL8fllf/A/bl
37
- NwdJOhVr9mESHhwGjwfSeTDPfd8ZLE027E5lyAVX9KZYcU00mOX+fdxOSnGqS/8J
38
- DRh0EPHDL15RcJjV2J6vZjPb0rOYGDoMcH+94wIDAQABAoIBAAzsamqfYQAqwXTb
39
- I0CJtGg6msUgU7HVkOM+9d3hM2L791oGHV6xBAdpXW2H8LgvZHJ8eOeSghR8+dgq
40
- PIqAffo4x1Oma+FOg3A0fb0evyiACyrOk+EcBdbBeLo/LcvahBtqnDfiUMQTpy6V
41
- seSoFCwuN91TSCeGIsDpRjbG1vxZgtx+uI+oH5+ytqJOmfCksRDCkMglGkzyfcl0
42
- Xc5CUhIJ0my53xijEUQl19rtWdMnNnnkdbG8PT3LZlOta5Do86BElzUYka0C6dUc
43
- VsBDQ0Nup0P6rEQgy7tephHoRlUGTYamsajGJaAo1F3IQVIrRSuagi7+YpSpCqsW
44
- wORqorkCgYEA7RdX6MDVrbw7LePnhyuaqTiMK+055/R1TqhB1JvvxJ1CXk2rDL6G
45
- 0TLHQ7oGofd5LYiemg4ZVtWdJe43BPZlVgT6lvL/iGo8JnrncB9Da6L7nrq/+Rvj
46
- XGjf1qODCK+LmreZWEsaLPURIoR/Ewwxb9J2zd0CaMjeTwafJo1CZvcCgYEAyCgb
47
- aqoWvUecX8VvARfuA593Lsi50t4MEArnOXXcd1RnXoZWhbx5rgO8/ATKfXr0BK/n
48
- h2GF9PfKzHFm/4V6e82OL7gu/kLy2u9bXN74vOvWFL5NOrOKPM7Kg+9I131kNYOw
49
- Ivnr/VtHE5s0dY7JChYWE1F3vArrOw3T00a4CXUCgYEA0SqY+dS2LvIzW4cHCe9k
50
- IQqsT0yYm5TFsUEr4sA3xcPfe4cV8sZb9k/QEGYb1+SWWZ+AHPV3UW5fl8kTbSNb
51
- v4ng8i8rVVQ0ANbJO9e5CUrepein2MPL0AkOATR8M7t7dGGpvYV0cFk8ZrFx0oId
52
- U0PgYDotF/iueBWlbsOM430CgYEAqYI95dFyPI5/AiSkY5queeb8+mQH62sdcCCr
53
- vd/w/CZA/K5sbAo4SoTj8dLk4evU6HtIa0DOP63y071eaxvRpTNqLUOgmLh+D6gS
54
- Cc7TfLuFrD+WDBatBd5jZ+SoHccVrLR/4L8jeodo5FPW05A+9gnKXEXsTxY4LOUC
55
- 9bS4e1kCgYAqVXZh63JsMwoaxCYmQ66eJojKa47VNrOeIZDZvd2BPVf30glBOT41
56
- gBoDG3WMPZoQj9pb7uMcrnvs4APj2FIhMU8U15LcPAj59cD6S6rWnAxO8NFK7HQG
57
- 4Jxg3JNNf8ErQoCHb1B3oVdXJkmbJkARoDpBKmTCgKtP8ADYLmVPQw==
58
- -----END RSA PRIVATE KEY-----
59
- _end_of_pem_
60
-
61
- TEST_KEY_DSA256 = OpenSSL::PKey::DSA.new <<-_end_of_pem_
62
- -----BEGIN DSA PRIVATE KEY-----
63
- MIH3AgEAAkEAhk2libbY2a8y2Pt21+YPYGZeW6wzaW2yfj5oiClXro9XMR7XWLkE
64
- 9B7XxLNFCS2gmCCdMsMW1HulaHtLFQmB2wIVAM43JZrcgpu6ajZ01VkLc93gu/Ed
65
- AkAOhujZrrKV5CzBKutKLb0GVyVWmdC7InoNSMZEeGU72rT96IjM59YzoqmD0pGM
66
- 3I1o4cGqg1D1DfM1rQlnN1eSAkBq6xXfEDwJ1mLNxF6q8Zm/ugFYWR5xcX/3wFiT
67
- b4+EjHP/DbNh9Vm5wcfnDBJ1zKvrMEf2xqngYdrV/3CiGJeKAhRvL57QvJZcQGvn
68
- ISNX5cMzFHRW3Q==
69
- -----END DSA PRIVATE KEY-----
70
- _end_of_pem_
71
-
72
- TEST_KEY_DSA512 = OpenSSL::PKey::DSA.new <<-_end_of_pem_
73
- -----BEGIN DSA PRIVATE KEY-----
74
- MIH4AgEAAkEA5lB4GvEwjrsMlGDqGsxrbqeFRh6o9OWt6FgTYiEEHaOYhkIxv0Ok
75
- RZPDNwOG997mDjBnvDJ1i56OmS3MbTnovwIVAJgub/aDrSDB4DZGH7UyarcaGy6D
76
- AkB9HdFw/3td8K4l1FZHv7TCZeJ3ZLb7dF3TWoGUP003RCqoji3/lHdKoVdTQNuR
77
- S/m6DlCwhjRjiQ/lBRgCLCcaAkEAjN891JBjzpMj4bWgsACmMggFf57DS0Ti+5++
78
- Q1VB8qkJN7rA7/2HrCR3gTsWNb1YhAsnFsoeRscC+LxXoXi9OAIUBG98h4tilg6S
79
- 55jreJD3Se3slps=
80
- -----END DSA PRIVATE KEY-----
81
- _end_of_pem_
82
-
83
- if defined?(OpenSSL::PKey::EC)
84
-
85
- TEST_KEY_EC_P256V1 = OpenSSL::PKey::EC.new <<-_end_of_pem_
86
- -----BEGIN EC PRIVATE KEY-----
87
- MHcCAQEEIID49FDqcf1O1eO8saTgG70UbXQw9Fqwseliit2aWhH1oAoGCCqGSM49
88
- AwEHoUQDQgAEFglk2c+oVUIKQ64eZG9bhLNPWB7lSZ/ArK41eGy5wAzU/0G51Xtt
89
- CeBUl+MahZtn9fO1JKdF4qJmS39dXnpENg==
90
- -----END EC PRIVATE KEY-----
91
- _end_of_pem_
92
-
93
- end
94
-
95
- TEST_KEY_DH512 = OpenSSL::PKey::DH.new <<-_end_of_pem_
96
- -----BEGIN DH PARAMETERS-----
97
- MEYCQQDmWXGPqk76sKw/edIOdhAQD4XzjJ+AR/PTk2qzaGs+u4oND2yU5D2NN4wr
98
- aPgwHyJBiK1/ebK3tYcrSKrOoRyrAgEC
99
- -----END DH PARAMETERS-----
100
- _end_of_pem_
101
-
102
- module_function
103
-
104
- def issue_cert(dn, key, serial, not_before, not_after, extensions,
105
- issuer, issuer_key, digest)
106
- cert = OpenSSL::X509::Certificate.new
107
- issuer = cert unless issuer
108
- issuer_key = key unless issuer_key
109
- cert.version = 2
110
- cert.serial = serial
111
- cert.subject = dn
112
- cert.issuer = issuer.subject
113
- cert.public_key = key.public_key
114
- cert.not_before = not_before
115
- cert.not_after = not_after
116
- ef = OpenSSL::X509::ExtensionFactory.new
117
- ef.subject_certificate = cert
118
- ef.issuer_certificate = issuer
119
- extensions.each{|oid, value, critical|
120
- cert.add_extension(ef.create_extension(oid, value, critical))
121
- }
122
- cert.sign(issuer_key, digest)
123
- cert
124
- end
125
-
126
- def issue_crl(revoke_info, serial, lastup, nextup, extensions,
127
- issuer, issuer_key, digest)
128
- crl = OpenSSL::X509::CRL.new
129
- crl.issuer = issuer.subject
130
- crl.version = 1
131
- crl.last_update = lastup
132
- crl.next_update = nextup
133
- revoke_info.each{|rserial, time, reason_code|
134
- revoked = OpenSSL::X509::Revoked.new
135
- revoked.serial = rserial
136
- revoked.time = time
137
- enum = OpenSSL::ASN1::Enumerated(reason_code)
138
- ext = OpenSSL::X509::Extension.new("CRLReason", enum)
139
- revoked.add_extension(ext)
140
- crl.add_revoked(revoked)
141
- }
142
- ef = OpenSSL::X509::ExtensionFactory.new
143
- ef.issuer_certificate = issuer
144
- ef.crl = crl
145
- crlnum = OpenSSL::ASN1::Integer(serial)
146
- crl.add_extension(OpenSSL::X509::Extension.new("crlNumber", crlnum))
147
- extensions.each{|oid, value, critical|
148
- crl.add_extension(ef.create_extension(oid, value, critical))
149
- }
150
- crl.sign(issuer_key, digest)
151
- crl
152
- end
153
-
154
- def get_subject_key_id(cert)
155
- asn1_cert = OpenSSL::ASN1.decode(cert)
156
- tbscert = asn1_cert.value[0]
157
- pkinfo = tbscert.value[6]
158
- publickey = pkinfo.value[1]
159
- pkvalue = publickey.value
160
- OpenSSL::Digest::SHA1.hexdigest(pkvalue).scan(/../).join(":").upcase
161
- end
162
-
163
- def silent
164
- begin
165
- back, $VERBOSE = $VERBOSE, nil
166
- yield
167
- ensure
168
- $VERBOSE = back
169
- end
170
- end
171
-
172
- class OpenSSL::SSLTestCase < Test::Unit::TestCase
173
- RUBY = EnvUtil.rubybin
174
- SSL_SERVER = File.join(File.dirname(__FILE__), "ssl_server.rb")
175
- PORT = 20443
176
- ITERATIONS = ($0 == __FILE__) ? 100 : 10
177
-
178
- def setup
179
- @ca_key = OpenSSL::TestUtils::TEST_KEY_RSA2048
180
- @svr_key = OpenSSL::TestUtils::TEST_KEY_RSA1024
181
- @cli_key = OpenSSL::TestUtils::TEST_KEY_DSA256
182
- @ca = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=CA")
183
- @svr = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=localhost")
184
- @cli = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=localhost")
185
- now = Time.at(Time.now.to_i)
186
- ca_exts = [
187
- ["basicConstraints","CA:TRUE",true],
188
- ["keyUsage","cRLSign,keyCertSign",true],
189
- ]
190
- ee_exts = [
191
- ["keyUsage","keyEncipherment,digitalSignature",true],
192
- ]
193
- @ca_cert = issue_cert(@ca, @ca_key, 1, now, now+3600, ca_exts, nil, nil, OpenSSL::Digest::SHA1.new)
194
- @svr_cert = issue_cert(@svr, @svr_key, 2, now, now+1800, ee_exts, @ca_cert, @ca_key, OpenSSL::Digest::SHA1.new)
195
- @cli_cert = issue_cert(@cli, @cli_key, 3, now, now+1800, ee_exts, @ca_cert, @ca_key, OpenSSL::Digest::SHA1.new)
196
- @server = nil
197
- end
198
-
199
- def teardown
200
- end
201
-
202
- def issue_cert(*arg)
203
- OpenSSL::TestUtils.issue_cert(*arg)
204
- end
205
-
206
- def issue_crl(*arg)
207
- OpenSSL::TestUtils.issue_crl(*arg)
208
- end
209
-
210
- def readwrite_loop(ctx, ssl)
211
- while line = ssl.gets
212
- if line =~ /^STARTTLS$/
213
- ssl.accept
214
- next
215
- end
216
- ssl.write(line)
217
- end
218
- rescue OpenSSL::SSL::SSLError
219
- rescue IOError
220
- ensure
221
- ssl.close rescue nil
222
- end
223
-
224
- def server_loop(ctx, ssls, server_proc)
225
- loop do
226
- ssl = nil
227
- begin
228
- ssl = ssls.accept
229
- rescue OpenSSL::SSL::SSLError
230
- retry
231
- end
232
-
233
- Thread.start do
234
- Thread.current.abort_on_exception = true
235
- server_proc.call(ctx, ssl)
236
- end
237
- end
238
- rescue Errno::EBADF, IOError, Errno::EINVAL, Errno::ECONNABORTED, Errno::ENOTSOCK
239
- end
240
-
241
- DHParam = OpenSSL::PKey::DH.new(128)
242
- def start_server(port0, verify_mode, start_immediately, args = {}, &block)
243
- ctx_proc = args[:ctx_proc]
244
- server_proc = args[:server_proc]
245
- server_proc ||= method(:readwrite_loop)
246
-
247
- store = OpenSSL::X509::Store.new
248
- store.add_cert(@ca_cert)
249
- store.purpose = OpenSSL::X509::PURPOSE_SSL_CLIENT
250
- ctx = OpenSSL::SSL::SSLContext.new
251
- ctx.cert_store = store
252
- #ctx.extra_chain_cert = [ ca_cert ]
253
- ctx.cert = @svr_cert
254
- ctx.key = @svr_key
255
- ctx.tmp_dh_callback = proc { DHParam }
256
- ctx.verify_mode = verify_mode
257
- ctx_proc.call(ctx) if ctx_proc
258
-
259
- Socket.do_not_reverse_lookup = true
260
- tcps = nil
261
- port = port0
262
- begin
263
- tcps = TCPServer.new("127.0.0.1", port)
264
- rescue Errno::EADDRINUSE
265
- port += 1
266
- retry
267
- end
268
-
269
- ssls = OpenSSL::SSL::SSLServer.new(tcps, ctx)
270
- ssls.start_immediately = start_immediately
271
-
272
- begin
273
- server = Thread.new do
274
- Thread.current.abort_on_exception = true
275
- server_loop(ctx, ssls, server_proc)
276
- end
277
-
278
- $stderr.printf("%s started: pid=%d port=%d\n", SSL_SERVER, $$, port) if $DEBUG
279
-
280
- block.call(server, port.to_i)
281
- ensure
282
- begin
283
- begin
284
- tcps.shutdown
285
- rescue Errno::ENOTCONN
286
- # when `Errno::ENOTCONN: Socket is not connected' on some platforms,
287
- # call #close instead of #shutdown.
288
- tcps.close
289
- tcps = nil
290
- end if (tcps)
291
- if (server)
292
- server.join(5)
293
- if server.alive?
294
- server.kill
295
- server.join
296
- flunk("TCPServer was closed and SSLServer is still alive") unless $!
297
- end
298
- end
299
- ensure
300
- tcps.close if (tcps)
301
- end
302
- end
303
- end
304
-
305
- def starttls(ssl)
306
- ssl.puts("STARTTLS")
307
- sleep 1 # When this line is eliminated, process on Cygwin blocks
308
- # forever at ssl.connect. But I don't know why it does.
309
- ssl.connect
310
- end
311
- end
312
-
313
- end if defined?(OpenSSL)
data/test/ruby/envutil.rb DELETED
@@ -1,208 +0,0 @@
1
- require "open3"
2
- require "timeout"
3
-
4
- module EnvUtil
5
- def rubybin
6
- unless ENV["RUBYOPT"]
7
-
8
- end
9
- if ruby = ENV["RUBY"]
10
- return ruby
11
- end
12
- ruby = "ruby"
13
- rubyexe = ruby+".exe"
14
- 3.times do
15
- if File.exist? ruby and File.executable? ruby and !File.directory? ruby
16
- return File.expand_path(ruby)
17
- end
18
- if File.exist? rubyexe and File.executable? rubyexe
19
- return File.expand_path(rubyexe)
20
- end
21
- ruby = File.join("..", ruby)
22
- end
23
- if defined?(RbConfig.ruby)
24
- RbConfig.ruby
25
- else
26
- "ruby"
27
- end
28
- end
29
- module_function :rubybin
30
-
31
- LANG_ENVS = %w"LANG LC_ALL LC_CTYPE"
32
-
33
- def invoke_ruby(args, stdin_data="", capture_stdout=false, capture_stderr=false, opt={})
34
- in_c, in_p = IO.pipe
35
- out_p, out_c = IO.pipe if capture_stdout
36
- err_p, err_c = IO.pipe if capture_stderr && capture_stderr != :merge_to_stdout
37
- opt = opt.dup
38
- opt[:in] = in_c
39
- opt[:out] = out_c if capture_stdout
40
- opt[:err] = capture_stderr == :merge_to_stdout ? out_c : err_c if capture_stderr
41
- if enc = opt.delete(:encoding)
42
- out_p.set_encoding(enc) if out_p
43
- err_p.set_encoding(enc) if err_p
44
- end
45
- timeout = opt.delete(:timeout) || 10
46
- c = "C"
47
- child_env = {}
48
- LANG_ENVS.each {|lc| child_env[lc] = c}
49
- if Array === args and Hash === args.first
50
- child_env.update(args.shift)
51
- end
52
- args = [args] if args.kind_of?(String)
53
- pid = spawn(child_env, EnvUtil.rubybin, *args, opt)
54
- in_c.close
55
- out_c.close if capture_stdout
56
- err_c.close if capture_stderr && capture_stderr != :merge_to_stdout
57
- if block_given?
58
- return yield in_p, out_p, err_p
59
- else
60
- th_stdout = Thread.new { out_p.read } if capture_stdout
61
- th_stderr = Thread.new { err_p.read } if capture_stderr && capture_stderr != :merge_to_stdout
62
- in_p.write stdin_data.to_str
63
- in_p.close
64
- if (!th_stdout || th_stdout.join(timeout)) && (!th_stderr || th_stderr.join(timeout))
65
- stdout = th_stdout.value if capture_stdout
66
- stderr = th_stderr.value if capture_stderr && capture_stderr != :merge_to_stdout
67
- else
68
- raise Timeout::Error
69
- end
70
- out_p.close if capture_stdout
71
- err_p.close if capture_stderr && capture_stderr != :merge_to_stdout
72
- Process.wait pid
73
- status = $?
74
- return stdout, stderr, status
75
- end
76
- ensure
77
- [in_c, in_p, out_c, out_p, err_c, err_p].each do |io|
78
- io.close if io && !io.closed?
79
- end
80
- [th_stdout, th_stderr].each do |th|
81
- (th.kill; th.join) if th
82
- end
83
- end
84
- module_function :invoke_ruby
85
-
86
- alias rubyexec invoke_ruby
87
- class << self
88
- alias rubyexec invoke_ruby
89
- end
90
-
91
- def verbose_warning
92
- class << (stderr = "")
93
- alias write <<
94
- end
95
- stderr, $stderr, verbose, $VERBOSE = $stderr, stderr, $VERBOSE, true
96
- yield stderr
97
- ensure
98
- stderr, $stderr, $VERBOSE = $stderr, stderr, verbose
99
- return stderr
100
- end
101
- module_function :verbose_warning
102
-
103
- def suppress_warning
104
- verbose, $VERBOSE = $VERBOSE, nil
105
- yield
106
- ensure
107
- $VERBOSE = verbose
108
- end
109
- module_function :suppress_warning
110
-
111
- def under_gc_stress
112
- stress, GC.stress = GC.stress, true
113
- yield
114
- ensure
115
- GC.stress = stress
116
- end
117
- module_function :under_gc_stress
118
- end
119
-
120
- module Test
121
- module Unit
122
- module Assertions
123
- public
124
- def assert_normal_exit(testsrc, message = '', opt = {})
125
- if opt.include?(:child_env)
126
- opt = opt.dup
127
- child_env = [opt.delete(:child_env)] || []
128
- else
129
- child_env = []
130
- end
131
- out, _, status = EnvUtil.invoke_ruby(child_env + %W'-W0', testsrc, true, :merge_to_stdout, opt)
132
- pid = status.pid
133
- faildesc = proc do
134
- signo = status.termsig
135
- signame = Signal.list.invert[signo]
136
- sigdesc = "signal #{signo}"
137
- if signame
138
- sigdesc = "SIG#{signame} (#{sigdesc})"
139
- end
140
- if status.coredump?
141
- sigdesc << " (core dumped)"
142
- end
143
- full_message = ''
144
- if !message.empty?
145
- full_message << message << "\n"
146
- end
147
- full_message << "pid #{pid} killed by #{sigdesc}"
148
- if !out.empty?
149
- out << "\n" if /\n\z/ !~ out
150
- full_message << "\n#{out.gsub(/^/, '| ')}"
151
- end
152
- full_message
153
- end
154
- assert !status.signaled?, faildesc
155
- end
156
-
157
- def assert_in_out_err(args, test_stdin = "", test_stdout = [], test_stderr = [], message = nil, opt={})
158
- stdout, stderr, status = EnvUtil.invoke_ruby(args, test_stdin, true, true, opt)
159
- if block_given?
160
- yield(stdout.lines.map {|l| l.chomp }, stderr.lines.map {|l| l.chomp })
161
- else
162
- if test_stdout.is_a?(Regexp)
163
- assert_match(test_stdout, stdout, message)
164
- else
165
- assert_equal(test_stdout, stdout.lines.map {|l| l.chomp }, message)
166
- end
167
- if test_stderr.is_a?(Regexp)
168
- assert_match(test_stderr, stderr, message)
169
- else
170
- assert_equal(test_stderr, stderr.lines.map {|l| l.chomp }, message)
171
- end
172
- status
173
- end
174
- end
175
-
176
- def assert_ruby_status(args, test_stdin="", message=nil, opt={})
177
- _, _, status = EnvUtil.invoke_ruby(args, test_stdin, false, false, opt)
178
- m = message ? "#{message} (#{status.inspect})" : "ruby exit status is not success: #{status.inspect}"
179
- assert(status.success?, m)
180
- end
181
-
182
- def assert_warn(msg)
183
- stderr = EnvUtil.verbose_warning { yield }
184
- assert(msg === stderr, "warning message #{stderr.inspect} is expected to match #{msg.inspect}")
185
- end
186
-
187
- end
188
- end
189
- end
190
-
191
- begin
192
- require 'rbconfig'
193
- rescue LoadError
194
- else
195
- module RbConfig
196
- @ruby = EnvUtil.rubybin
197
- class << self
198
- undef ruby if method_defined?(:ruby)
199
- attr_reader :ruby
200
- end
201
- dir = File.dirname(ruby)
202
- name = File.basename(ruby, CONFIG['EXEEXT'])
203
- CONFIG['bindir'] = dir
204
- CONFIG['ruby_install_name'] = name
205
- CONFIG['RUBY_INSTALL_NAME'] = name
206
- Gem::ConfigMap[:bindir] = dir if defined?(Gem::ConfigMap)
207
- end
208
- end