rack 1.6.13 → 2.0.0.alpha

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of rack might be problematic. Click here for more details.

Files changed (138) hide show
  1. checksums.yaml +5 -5
  2. data/HISTORY.md +139 -18
  3. data/README.rdoc +17 -25
  4. data/Rakefile +6 -14
  5. data/SPEC +8 -9
  6. data/contrib/rack_logo.svg +164 -111
  7. data/lib/rack.rb +70 -21
  8. data/lib/rack/auth/digest/request.rb +1 -1
  9. data/lib/rack/body_proxy.rb +14 -9
  10. data/lib/rack/builder.rb +3 -3
  11. data/lib/rack/chunked.rb +5 -5
  12. data/lib/rack/{commonlogger.rb → common_logger.rb} +2 -2
  13. data/lib/rack/{conditionalget.rb → conditional_get.rb} +0 -0
  14. data/lib/rack/content_length.rb +2 -2
  15. data/lib/rack/deflater.rb +4 -4
  16. data/lib/rack/directory.rb +49 -55
  17. data/lib/rack/etag.rb +2 -1
  18. data/lib/rack/events.rb +154 -0
  19. data/lib/rack/file.rb +55 -40
  20. data/lib/rack/handler.rb +2 -24
  21. data/lib/rack/handler/cgi.rb +15 -16
  22. data/lib/rack/handler/fastcgi.rb +13 -14
  23. data/lib/rack/handler/lsws.rb +11 -11
  24. data/lib/rack/handler/scgi.rb +15 -15
  25. data/lib/rack/handler/thin.rb +3 -0
  26. data/lib/rack/handler/webrick.rb +22 -24
  27. data/lib/rack/head.rb +15 -17
  28. data/lib/rack/lint.rb +38 -38
  29. data/lib/rack/lobster.rb +1 -1
  30. data/lib/rack/lock.rb +6 -10
  31. data/lib/rack/logger.rb +2 -2
  32. data/lib/rack/media_type.rb +38 -0
  33. data/lib/rack/{methodoverride.rb → method_override.rb} +4 -11
  34. data/lib/rack/mime.rb +18 -5
  35. data/lib/rack/mock.rb +35 -52
  36. data/lib/rack/multipart.rb +35 -6
  37. data/lib/rack/multipart/generator.rb +4 -4
  38. data/lib/rack/multipart/parser.rb +273 -158
  39. data/lib/rack/multipart/uploaded_file.rb +1 -2
  40. data/lib/rack/{nulllogger.rb → null_logger.rb} +1 -1
  41. data/lib/rack/query_parser.rb +174 -0
  42. data/lib/rack/recursive.rb +8 -8
  43. data/lib/rack/reloader.rb +1 -2
  44. data/lib/rack/request.rb +370 -304
  45. data/lib/rack/response.rb +129 -56
  46. data/lib/rack/rewindable_input.rb +1 -12
  47. data/lib/rack/runtime.rb +10 -18
  48. data/lib/rack/sendfile.rb +5 -7
  49. data/lib/rack/server.rb +31 -25
  50. data/lib/rack/session/abstract/id.rb +93 -135
  51. data/lib/rack/session/cookie.rb +26 -28
  52. data/lib/rack/session/memcache.rb +8 -14
  53. data/lib/rack/session/pool.rb +14 -21
  54. data/lib/rack/show_exceptions.rb +386 -0
  55. data/lib/rack/{showstatus.rb → show_status.rb} +3 -3
  56. data/lib/rack/static.rb +30 -5
  57. data/lib/rack/tempfile_reaper.rb +2 -2
  58. data/lib/rack/urlmap.rb +13 -14
  59. data/lib/rack/utils.rb +128 -221
  60. data/rack.gemspec +9 -5
  61. data/test/builder/an_underscore_app.rb +5 -0
  62. data/test/builder/options.ru +1 -1
  63. data/test/cgi/test.fcgi +1 -0
  64. data/test/cgi/test.gz +0 -0
  65. data/test/helper.rb +31 -0
  66. data/test/multipart/filename_with_encoded_words +7 -0
  67. data/test/multipart/{filename_with_null_byte → filename_with_single_quote} +1 -1
  68. data/test/multipart/quoted +15 -0
  69. data/test/multipart/rack-logo.png +0 -0
  70. data/test/registering_handler/rack/handler/registering_myself.rb +1 -1
  71. data/test/spec_auth_basic.rb +20 -19
  72. data/test/spec_auth_digest.rb +47 -46
  73. data/test/spec_body_proxy.rb +27 -27
  74. data/test/spec_builder.rb +51 -41
  75. data/test/spec_cascade.rb +24 -22
  76. data/test/spec_cgi.rb +49 -67
  77. data/test/spec_chunked.rb +36 -34
  78. data/test/{spec_commonlogger.rb → spec_common_logger.rb} +23 -21
  79. data/test/{spec_conditionalget.rb → spec_conditional_get.rb} +29 -28
  80. data/test/spec_config.rb +3 -2
  81. data/test/spec_content_length.rb +18 -17
  82. data/test/spec_content_type.rb +13 -12
  83. data/test/spec_deflater.rb +66 -40
  84. data/test/spec_directory.rb +72 -27
  85. data/test/spec_etag.rb +32 -31
  86. data/test/spec_events.rb +133 -0
  87. data/test/spec_fastcgi.rb +50 -72
  88. data/test/spec_file.rb +96 -77
  89. data/test/spec_handler.rb +19 -34
  90. data/test/spec_head.rb +15 -14
  91. data/test/spec_lint.rb +162 -197
  92. data/test/spec_lobster.rb +24 -23
  93. data/test/spec_lock.rb +69 -39
  94. data/test/spec_logger.rb +4 -3
  95. data/test/spec_media_type.rb +42 -0
  96. data/test/spec_method_override.rb +83 -0
  97. data/test/spec_mime.rb +19 -19
  98. data/test/spec_mock.rb +196 -151
  99. data/test/spec_multipart.rb +310 -202
  100. data/test/{spec_nulllogger.rb → spec_null_logger.rb} +5 -4
  101. data/test/spec_recursive.rb +17 -14
  102. data/test/spec_request.rb +763 -607
  103. data/test/spec_response.rb +209 -156
  104. data/test/spec_rewindable_input.rb +50 -40
  105. data/test/spec_runtime.rb +11 -10
  106. data/test/spec_sendfile.rb +30 -35
  107. data/test/spec_server.rb +78 -52
  108. data/test/spec_session_abstract_id.rb +11 -33
  109. data/test/spec_session_cookie.rb +97 -65
  110. data/test/spec_session_memcache.rb +63 -101
  111. data/test/spec_session_pool.rb +48 -84
  112. data/test/spec_show_exceptions.rb +80 -0
  113. data/test/{spec_showstatus.rb → spec_show_status.rb} +36 -35
  114. data/test/spec_static.rb +71 -32
  115. data/test/spec_tempfile_reaper.rb +11 -10
  116. data/test/spec_thin.rb +55 -50
  117. data/test/spec_urlmap.rb +79 -78
  118. data/test/spec_utils.rb +417 -345
  119. data/test/spec_version.rb +2 -8
  120. data/test/spec_webrick.rb +77 -67
  121. data/test/static/foo.html +1 -0
  122. data/test/testrequest.rb +1 -1
  123. data/test/unregistered_handler/rack/handler/unregistered.rb +1 -1
  124. data/test/unregistered_handler/rack/handler/unregistered_long_one.rb +1 -1
  125. metadata +116 -71
  126. data/KNOWN-ISSUES +0 -44
  127. data/lib/rack/backports/uri/common_18.rb +0 -56
  128. data/lib/rack/backports/uri/common_192.rb +0 -52
  129. data/lib/rack/backports/uri/common_193.rb +0 -29
  130. data/lib/rack/handler/evented_mongrel.rb +0 -8
  131. data/lib/rack/handler/mongrel.rb +0 -106
  132. data/lib/rack/handler/swiftiplied_mongrel.rb +0 -8
  133. data/lib/rack/showexceptions.rb +0 -387
  134. data/lib/rack/utils/okjson.rb +0 -600
  135. data/test/spec_methodoverride.rb +0 -111
  136. data/test/spec_mongrel.rb +0 -182
  137. data/test/spec_session_persisted_secure_secure_session_hash.rb +0 -73
  138. data/test/spec_showexceptions.rb +0 -98
@@ -1,3 +1,4 @@
1
+ require 'minitest/autorun'
1
2
  require 'rack/handler'
2
3
 
3
4
  class Rack::Handler::Lobster; end
@@ -5,66 +6,50 @@ class RockLobster; end
5
6
 
6
7
  describe Rack::Handler do
7
8
  it "has registered default handlers" do
8
- Rack::Handler.get('cgi').should.equal Rack::Handler::CGI
9
- Rack::Handler.get('webrick').should.equal Rack::Handler::WEBrick
9
+ Rack::Handler.get('cgi').must_equal Rack::Handler::CGI
10
+ Rack::Handler.get('webrick').must_equal Rack::Handler::WEBrick
10
11
 
11
12
  begin
12
- Rack::Handler.get('fastcgi').should.equal Rack::Handler::FastCGI
13
- rescue LoadError
14
- end
15
-
16
- begin
17
- Rack::Handler.get('mongrel').should.equal Rack::Handler::Mongrel
13
+ Rack::Handler.get('fastcgi').must_equal Rack::Handler::FastCGI
18
14
  rescue LoadError
19
15
  end
20
16
  end
21
17
 
22
- should "raise LoadError if handler doesn't exist" do
18
+ it "raise LoadError if handler doesn't exist" do
23
19
  lambda {
24
20
  Rack::Handler.get('boom')
25
- }.should.raise(LoadError)
26
- end
21
+ }.must_raise(LoadError)
27
22
 
28
- should "raise LoadError if handler isn't nested under Rack::Handler" do
29
- # Feature-detect whether Ruby can do non-inherited const lookups.
30
- # If it can't, then Rack::Handler may lookup non-handler toplevel
31
- # constants, so the best we can do is no-op here and not test it.
32
- begin
33
- Rack::Handler._const_get('Object', false)
34
- rescue NameError
35
- lambda {
36
- Rack::Handler.get('Object')
37
- }.should.raise(LoadError)
38
- end
23
+ lambda {
24
+ Rack::Handler.get('Object')
25
+ }.must_raise(LoadError)
39
26
  end
40
27
 
41
- should "get unregistered, but already required, handler by name" do
42
- Rack::Handler.get('Lobster').should.equal Rack::Handler::Lobster
28
+ it "get unregistered, but already required, handler by name" do
29
+ Rack::Handler.get('Lobster').must_equal Rack::Handler::Lobster
43
30
  end
44
31
 
45
- should "register custom handler" do
32
+ it "register custom handler" do
46
33
  Rack::Handler.register('rock_lobster', 'RockLobster')
47
- Rack::Handler.get('rock_lobster').should.equal RockLobster
34
+ Rack::Handler.get('rock_lobster').must_equal RockLobster
48
35
  end
49
36
 
50
- should "not need registration for properly coded handlers even if not already required" do
37
+ it "not need registration for properly coded handlers even if not already required" do
51
38
  begin
52
39
  $LOAD_PATH.push File.expand_path('../unregistered_handler', __FILE__)
53
- Rack::Handler.get('Unregistered').should.equal Rack::Handler::Unregistered
54
- lambda {
55
- Rack::Handler.get('UnRegistered')
56
- }.should.raise LoadError
57
- Rack::Handler.get('UnregisteredLongOne').should.equal Rack::Handler::UnregisteredLongOne
40
+ Rack::Handler.get('Unregistered').must_equal Rack::Handler::Unregistered
41
+ lambda { Rack::Handler.get('UnRegistered') }.must_raise LoadError
42
+ Rack::Handler.get('UnregisteredLongOne').must_equal Rack::Handler::UnregisteredLongOne
58
43
  ensure
59
44
  $LOAD_PATH.delete File.expand_path('../unregistered_handler', __FILE__)
60
45
  end
61
46
  end
62
47
 
63
- should "allow autoloaded handlers to be registered properly while being loaded" do
48
+ it "allow autoloaded handlers to be registered properly while being loaded" do
64
49
  path = File.expand_path('../registering_handler', __FILE__)
65
50
  begin
66
51
  $LOAD_PATH.push path
67
- Rack::Handler.get('registering_myself').should.equal Rack::Handler::RegisteringMyself
52
+ Rack::Handler.get('registering_myself').must_equal Rack::Handler::RegisteringMyself
68
53
  ensure
69
54
  $LOAD_PATH.delete path
70
55
  end
@@ -1,3 +1,4 @@
1
+ require 'minitest/autorun'
1
2
  require 'rack/head'
2
3
  require 'rack/lint'
3
4
  require 'rack/mock'
@@ -15,31 +16,31 @@ describe Rack::Head do
15
16
  return response, body
16
17
  end
17
18
 
18
- should "pass GET, POST, PUT, DELETE, OPTIONS, TRACE requests" do
19
+ it "pass GET, POST, PUT, DELETE, OPTIONS, TRACE requests" do
19
20
  %w[GET POST PUT DELETE OPTIONS TRACE].each do |type|
20
21
  resp, _ = test_response("REQUEST_METHOD" => type)
21
22
 
22
- resp[0].should.equal(200)
23
- resp[1].should.equal({"Content-type" => "test/plain", "Content-length" => "3"})
24
- resp[2].to_enum.to_a.should.equal(["foo"])
23
+ resp[0].must_equal 200
24
+ resp[1].must_equal "Content-type" => "test/plain", "Content-length" => "3"
25
+ resp[2].to_enum.to_a.must_equal ["foo"]
25
26
  end
26
27
  end
27
28
 
28
- should "remove body from HEAD requests" do
29
+ it "remove body from HEAD requests" do
29
30
  resp, _ = test_response("REQUEST_METHOD" => "HEAD")
30
31
 
31
- resp[0].should.equal(200)
32
- resp[1].should.equal({"Content-type" => "test/plain", "Content-length" => "3"})
33
- resp[2].to_enum.to_a.should.equal([])
32
+ resp[0].must_equal 200
33
+ resp[1].must_equal "Content-type" => "test/plain", "Content-length" => "3"
34
+ resp[2].to_enum.to_a.must_equal []
34
35
  end
35
36
 
36
- should "close the body when it is removed" do
37
+ it "close the body when it is removed" do
37
38
  resp, body = test_response("REQUEST_METHOD" => "HEAD")
38
- resp[0].should.equal(200)
39
- resp[1].should.equal({"Content-type" => "test/plain", "Content-length" => "3"})
40
- resp[2].to_enum.to_a.should.equal([])
41
- body.should.not.be.closed
39
+ resp[0].must_equal 200
40
+ resp[1].must_equal "Content-type" => "test/plain", "Content-length" => "3"
41
+ resp[2].to_enum.to_a.must_equal []
42
+ body.wont_be :closed?
42
43
  resp[2].close
43
- body.should.be.closed
44
+ body.must_be :closed?
44
45
  end
45
46
  end
@@ -1,3 +1,4 @@
1
+ require 'minitest/autorun'
1
2
  require 'stringio'
2
3
  require 'tempfile'
3
4
  require 'rack/lint'
@@ -8,129 +9,127 @@ describe Rack::Lint do
8
9
  Rack::MockRequest.env_for("/", *args)
9
10
  end
10
11
 
11
- should "pass valid request" do
12
- lambda {
13
- Rack::Lint.new(lambda { |env|
14
- [200, {"Content-type" => "test/plain", "Content-length" => "3"}, ["foo"]]
15
- }).call(env({}))
16
- }.should.not.raise
12
+ it "pass valid request" do
13
+ Rack::Lint.new(lambda { |env|
14
+ [200, {"Content-type" => "test/plain", "Content-length" => "3"}, ["foo"]]
15
+ }).call(env({})).first.must_equal 200
17
16
  end
18
17
 
19
- should "notice fatal errors" do
20
- lambda { Rack::Lint.new(nil).call }.should.raise(Rack::Lint::LintError).
21
- message.should.match(/No env given/)
18
+ it "notice fatal errors" do
19
+ lambda { Rack::Lint.new(nil).call }.must_raise(Rack::Lint::LintError).
20
+ message.must_match(/No env given/)
22
21
  end
23
22
 
24
- should "notice environment errors" do
25
- lambda { Rack::Lint.new(nil).call 5 }.should.raise(Rack::Lint::LintError).
26
- message.should.match(/not a Hash/)
23
+ it "notice environment errors" do
24
+ lambda { Rack::Lint.new(nil).call 5 }.must_raise(Rack::Lint::LintError).
25
+ message.must_match(/not a Hash/)
27
26
 
28
27
  lambda {
29
28
  e = env
30
29
  e.delete("REQUEST_METHOD")
31
30
  Rack::Lint.new(nil).call(e)
32
- }.should.raise(Rack::Lint::LintError).
33
- message.should.match(/missing required key REQUEST_METHOD/)
31
+ }.must_raise(Rack::Lint::LintError).
32
+ message.must_match(/missing required key REQUEST_METHOD/)
34
33
 
35
34
  lambda {
36
35
  e = env
37
36
  e.delete("SERVER_NAME")
38
37
  Rack::Lint.new(nil).call(e)
39
- }.should.raise(Rack::Lint::LintError).
40
- message.should.match(/missing required key SERVER_NAME/)
38
+ }.must_raise(Rack::Lint::LintError).
39
+ message.must_match(/missing required key SERVER_NAME/)
41
40
 
42
41
 
43
42
  lambda {
44
43
  Rack::Lint.new(nil).call(env("HTTP_CONTENT_TYPE" => "text/plain"))
45
- }.should.raise(Rack::Lint::LintError).
46
- message.should.match(/contains HTTP_CONTENT_TYPE/)
44
+ }.must_raise(Rack::Lint::LintError).
45
+ message.must_match(/contains HTTP_CONTENT_TYPE/)
47
46
 
48
47
  lambda {
49
48
  Rack::Lint.new(nil).call(env("HTTP_CONTENT_LENGTH" => "42"))
50
- }.should.raise(Rack::Lint::LintError).
51
- message.should.match(/contains HTTP_CONTENT_LENGTH/)
49
+ }.must_raise(Rack::Lint::LintError).
50
+ message.must_match(/contains HTTP_CONTENT_LENGTH/)
52
51
 
53
52
  lambda {
54
53
  Rack::Lint.new(nil).call(env("FOO" => Object.new))
55
- }.should.raise(Rack::Lint::LintError).
56
- message.should.match(/non-string value/)
54
+ }.must_raise(Rack::Lint::LintError).
55
+ message.must_match(/non-string value/)
57
56
 
58
57
  lambda {
59
58
  Rack::Lint.new(nil).call(env("rack.version" => "0.2"))
60
- }.should.raise(Rack::Lint::LintError).
61
- message.should.match(/must be an Array/)
59
+ }.must_raise(Rack::Lint::LintError).
60
+ message.must_match(/must be an Array/)
62
61
 
63
62
  lambda {
64
63
  Rack::Lint.new(nil).call(env("rack.url_scheme" => "gopher"))
65
- }.should.raise(Rack::Lint::LintError).
66
- message.should.match(/url_scheme unknown/)
64
+ }.must_raise(Rack::Lint::LintError).
65
+ message.must_match(/url_scheme unknown/)
67
66
 
68
67
  lambda {
69
68
  Rack::Lint.new(nil).call(env("rack.session" => []))
70
- }.should.raise(Rack::Lint::LintError).
71
- message.should.equal("session [] must respond to store and []=")
69
+ }.must_raise(Rack::Lint::LintError).
70
+ message.must_equal "session [] must respond to store and []="
72
71
 
73
72
  lambda {
74
73
  Rack::Lint.new(nil).call(env("rack.logger" => []))
75
- }.should.raise(Rack::Lint::LintError).
76
- message.should.equal("logger [] must respond to info")
74
+ }.must_raise(Rack::Lint::LintError).
75
+ message.must_equal "logger [] must respond to info"
77
76
 
78
77
  lambda {
79
78
  Rack::Lint.new(nil).call(env("rack.multipart.buffer_size" => 0))
80
- }.should.raise(Rack::Lint::LintError).
81
- message.should.equal("rack.multipart.buffer_size must be an Integer > 0 if specified")
79
+ }.must_raise(Rack::Lint::LintError).
80
+ message.must_equal "rack.multipart.buffer_size must be an Integer > 0 if specified"
82
81
 
83
82
  lambda {
84
83
  Rack::Lint.new(nil).call(env("rack.multipart.tempfile_factory" => Tempfile))
85
- }.should.raise(Rack::Lint::LintError).
86
- message.should.equal("rack.multipart.tempfile_factory must respond to #call")
84
+ }.must_raise(Rack::Lint::LintError).
85
+ message.must_equal "rack.multipart.tempfile_factory must respond to #call"
87
86
 
88
87
  lambda {
89
88
  Rack::Lint.new(lambda { |env|
90
89
  env['rack.multipart.tempfile_factory'].call("testfile", "text/plain")
91
90
  }).call(env("rack.multipart.tempfile_factory" => lambda { |filename, content_type| Object.new }))
92
- }.should.raise(Rack::Lint::LintError).
93
- message.should.equal("rack.multipart.tempfile_factory return value must respond to #<<")
91
+ }.must_raise(Rack::Lint::LintError).
92
+ message.must_equal "rack.multipart.tempfile_factory return value must respond to #<<"
94
93
 
95
94
  lambda {
96
95
  Rack::Lint.new(nil).call(env("REQUEST_METHOD" => "FUCKUP?"))
97
- }.should.raise(Rack::Lint::LintError).
98
- message.should.match(/REQUEST_METHOD/)
96
+ }.must_raise(Rack::Lint::LintError).
97
+ message.must_match(/REQUEST_METHOD/)
99
98
 
100
99
  lambda {
101
100
  Rack::Lint.new(nil).call(env("SCRIPT_NAME" => "howdy"))
102
- }.should.raise(Rack::Lint::LintError).
103
- message.should.match(/must start with/)
101
+ }.must_raise(Rack::Lint::LintError).
102
+ message.must_match(/must start with/)
104
103
 
105
104
  lambda {
106
105
  Rack::Lint.new(nil).call(env("PATH_INFO" => "../foo"))
107
- }.should.raise(Rack::Lint::LintError).
108
- message.should.match(/must start with/)
106
+ }.must_raise(Rack::Lint::LintError).
107
+ message.must_match(/must start with/)
109
108
 
110
109
  lambda {
111
110
  Rack::Lint.new(nil).call(env("CONTENT_LENGTH" => "xcii"))
112
- }.should.raise(Rack::Lint::LintError).
113
- message.should.match(/Invalid CONTENT_LENGTH/)
111
+ }.must_raise(Rack::Lint::LintError).
112
+ message.must_match(/Invalid CONTENT_LENGTH/)
114
113
 
115
114
  lambda {
116
115
  e = env
117
116
  e.delete("PATH_INFO")
118
117
  e.delete("SCRIPT_NAME")
119
118
  Rack::Lint.new(nil).call(e)
120
- }.should.raise(Rack::Lint::LintError).
121
- message.should.match(/One of .* must be set/)
119
+ }.must_raise(Rack::Lint::LintError).
120
+ message.must_match(/One of .* must be set/)
122
121
 
123
122
  lambda {
124
123
  Rack::Lint.new(nil).call(env("SCRIPT_NAME" => "/"))
125
- }.should.raise(Rack::Lint::LintError).
126
- message.should.match(/cannot be .* make it ''/)
124
+ }.must_raise(Rack::Lint::LintError).
125
+ message.must_match(/cannot be .* make it ''/)
127
126
  end
128
127
 
129
- should "notice input errors" do
128
+ it "notice input errors" do
130
129
  lambda {
131
130
  Rack::Lint.new(nil).call(env("rack.input" => ""))
132
- }.should.raise(Rack::Lint::LintError).
133
- message.should.match(/does not respond to #gets/)
131
+ }.must_raise(Rack::Lint::LintError).
132
+ message.must_match(/does not respond to #gets/)
134
133
 
135
134
  lambda {
136
135
  input = Object.new
@@ -138,8 +137,8 @@ describe Rack::Lint do
138
137
  false
139
138
  end
140
139
  Rack::Lint.new(nil).call(env("rack.input" => input))
141
- }.should.raise(Rack::Lint::LintError).
142
- message.should.match(/is not opened in binary mode/)
140
+ }.must_raise(Rack::Lint::LintError).
141
+ message.must_match(/is not opened in binary mode/)
143
142
 
144
143
  lambda {
145
144
  input = Object.new
@@ -151,54 +150,54 @@ describe Rack::Lint do
151
150
  result
152
151
  end
153
152
  Rack::Lint.new(nil).call(env("rack.input" => input))
154
- }.should.raise(Rack::Lint::LintError).
155
- message.should.match(/does not have ASCII-8BIT as its external encoding/)
153
+ }.must_raise(Rack::Lint::LintError).
154
+ message.must_match(/does not have ASCII-8BIT as its external encoding/)
156
155
  end
157
156
 
158
- should "notice error errors" do
157
+ it "notice error errors" do
159
158
  lambda {
160
159
  Rack::Lint.new(nil).call(env("rack.errors" => ""))
161
- }.should.raise(Rack::Lint::LintError).
162
- message.should.match(/does not respond to #puts/)
160
+ }.must_raise(Rack::Lint::LintError).
161
+ message.must_match(/does not respond to #puts/)
163
162
  end
164
163
 
165
- should "notice status errors" do
164
+ it "notice status errors" do
166
165
  lambda {
167
166
  Rack::Lint.new(lambda { |env|
168
167
  ["cc", {}, ""]
169
168
  }).call(env({}))
170
- }.should.raise(Rack::Lint::LintError).
171
- message.should.match(/must be >=100 seen as integer/)
169
+ }.must_raise(Rack::Lint::LintError).
170
+ message.must_match(/must be >=100 seen as integer/)
172
171
 
173
172
  lambda {
174
173
  Rack::Lint.new(lambda { |env|
175
174
  [42, {}, ""]
176
175
  }).call(env({}))
177
- }.should.raise(Rack::Lint::LintError).
178
- message.should.match(/must be >=100 seen as integer/)
176
+ }.must_raise(Rack::Lint::LintError).
177
+ message.must_match(/must be >=100 seen as integer/)
179
178
  end
180
179
 
181
- should "notice header errors" do
180
+ it "notice header errors" do
182
181
  lambda {
183
182
  Rack::Lint.new(lambda { |env|
184
183
  [200, Object.new, []]
185
184
  }).call(env({}))
186
- }.should.raise(Rack::Lint::LintError).
187
- message.should.equal("headers object should respond to #each, but doesn't (got Object as headers)")
185
+ }.must_raise(Rack::Lint::LintError).
186
+ message.must_equal "headers object should respond to #each, but doesn't (got Object as headers)"
188
187
 
189
188
  lambda {
190
189
  Rack::Lint.new(lambda { |env|
191
190
  [200, {true=>false}, []]
192
191
  }).call(env({}))
193
- }.should.raise(Rack::Lint::LintError).
194
- message.should.equal("header key must be a string, was TrueClass")
192
+ }.must_raise(Rack::Lint::LintError).
193
+ message.must_equal "header key must be a string, was TrueClass"
195
194
 
196
195
  lambda {
197
196
  Rack::Lint.new(lambda { |env|
198
197
  [200, {"Status" => "404"}, []]
199
198
  }).call(env({}))
200
- }.should.raise(Rack::Lint::LintError).
201
- message.should.match(/must not contain Status/)
199
+ }.must_raise(Rack::Lint::LintError).
200
+ message.must_match(/must not contain Status/)
202
201
 
203
202
  # From RFC 7230:<F24><F25>
204
203
  # Most HTTP header field values are defined using common syntax
@@ -206,9 +205,9 @@ describe Rack::Lint do
206
205
  # whitespace or specific delimiting characters. Delimiters are chosen
207
206
  # from the set of US-ASCII visual characters not allowed in a token
208
207
  # (DQUOTE and "(),/:;<=>?@[\]{}").
209
- #
208
+ #
210
209
  # token = 1*tchar
211
- #
210
+ #
212
211
  # tchar = "!" / "#" / "$" / "%" / "&" / "'" / "*"
213
212
  # / "+" / "-" / "." / "^" / "_" / "`" / "|" / "~"
214
213
  # / DIGIT / ALPHA
@@ -219,157 +218,151 @@ describe Rack::Lint do
219
218
  Rack::Lint.new(lambda { |env|
220
219
  [200, {invalid_header => "text/plain"}, []]
221
220
  }).call(env({}))
222
- }.should.raise(Rack::Lint::LintError, "on invalid header: #{invalid_header}").
223
- message.should.equal("invalid header name: #{invalid_header}")
221
+ }.must_raise(Rack::Lint::LintError, "on invalid header: #{invalid_header}").
222
+ message.must_equal("invalid header name: #{invalid_header}")
224
223
  end
225
224
  valid_headers = 0.upto(127).map(&:chr) - invalid_headers
226
225
  valid_headers.each do |valid_header|
227
- lambda {
228
- Rack::Lint.new(lambda { |env|
229
- [200, {valid_header => "text/plain"}, []]
230
- }).call(env({}))
231
- }.should.not.raise(Rack::Lint::LintError, "on valid header: #{valid_header}")
226
+ Rack::Lint.new(lambda { |env|
227
+ [200, {valid_header => "text/plain"}, []]
228
+ }).call(env({})).first.must_equal 200
232
229
  end
233
230
 
234
231
  lambda {
235
232
  Rack::Lint.new(lambda { |env|
236
233
  [200, {"Foo" => Object.new}, []]
237
234
  }).call(env({}))
238
- }.should.raise(Rack::Lint::LintError).
239
- message.should.equal("a header value must be a String, but the value of 'Foo' is a Object")
235
+ }.must_raise(Rack::Lint::LintError).
236
+ message.must_equal "a header value must be a String, but the value of 'Foo' is a Object"
240
237
 
241
238
  lambda {
242
239
  Rack::Lint.new(lambda { |env|
243
240
  [200, {"Foo" => [1, 2, 3]}, []]
244
241
  }).call(env({}))
245
- }.should.raise(Rack::Lint::LintError).
246
- message.should.equal("a header value must be a String, but the value of 'Foo' is a Array")
242
+ }.must_raise(Rack::Lint::LintError).
243
+ message.must_equal "a header value must be a String, but the value of 'Foo' is a Array"
247
244
 
248
245
 
249
246
  lambda {
250
247
  Rack::Lint.new(lambda { |env|
251
248
  [200, {"Foo-Bar" => "text\000plain"}, []]
252
249
  }).call(env({}))
253
- }.should.raise(Rack::Lint::LintError).
254
- message.should.match(/invalid header/)
255
-
256
- # line ends (010) should be allowed in header values.
257
- lambda {
258
- Rack::Lint.new(lambda { |env|
259
- [200, {"Foo-Bar" => "one\ntwo\nthree", "Content-Length" => "0", "Content-Type" => "text/plain" }, []]
260
- }).call(env({}))
261
- }.should.not.raise(Rack::Lint::LintError)
262
-
263
- # non-Hash header responses should be allowed
264
- lambda {
265
- Rack::Lint.new(lambda { |env|
266
- [200, [%w(Content-Type text/plain), %w(Content-Length 0)], []]
267
- }).call(env({}))
268
- }.should.not.raise(TypeError)
250
+ }.must_raise(Rack::Lint::LintError).
251
+ message.must_match(/invalid header/)
252
+
253
+ # line ends (010).must_be :allowed in header values.?
254
+ Rack::Lint.new(lambda { |env|
255
+ [200, {"Foo-Bar" => "one\ntwo\nthree", "Content-Length" => "0", "Content-Type" => "text/plain" }, []]
256
+ }).call(env({})).first.must_equal 200
257
+
258
+ # non-Hash header responses.must_be :allowed?
259
+ Rack::Lint.new(lambda { |env|
260
+ [200, [%w(Content-Type text/plain), %w(Content-Length 0)], []]
261
+ }).call(env({})).first.must_equal 200
269
262
  end
270
263
 
271
- should "notice content-type errors" do
264
+ it "notice content-type errors" do
272
265
  # lambda {
273
266
  # Rack::Lint.new(lambda { |env|
274
267
  # [200, {"Content-length" => "0"}, []]
275
268
  # }).call(env({}))
276
- # }.should.raise(Rack::Lint::LintError).
277
- # message.should.match(/No Content-Type/)
269
+ # }.must_raise(Rack::Lint::LintError).
270
+ # message.must_match(/No Content-Type/)
278
271
 
279
272
  [100, 101, 204, 205, 304].each do |status|
280
273
  lambda {
281
274
  Rack::Lint.new(lambda { |env|
282
275
  [status, {"Content-type" => "text/plain", "Content-length" => "0"}, []]
283
276
  }).call(env({}))
284
- }.should.raise(Rack::Lint::LintError).
285
- message.should.match(/Content-Type header found/)
277
+ }.must_raise(Rack::Lint::LintError).
278
+ message.must_match(/Content-Type header found/)
286
279
  end
287
280
  end
288
281
 
289
- should "notice content-length errors" do
282
+ it "notice content-length errors" do
290
283
  [100, 101, 204, 205, 304].each do |status|
291
284
  lambda {
292
285
  Rack::Lint.new(lambda { |env|
293
286
  [status, {"Content-length" => "0"}, []]
294
287
  }).call(env({}))
295
- }.should.raise(Rack::Lint::LintError).
296
- message.should.match(/Content-Length header found/)
288
+ }.must_raise(Rack::Lint::LintError).
289
+ message.must_match(/Content-Length header found/)
297
290
  end
298
291
 
299
292
  lambda {
300
293
  Rack::Lint.new(lambda { |env|
301
294
  [200, {"Content-type" => "text/plain", "Content-Length" => "1"}, []]
302
295
  }).call(env({}))[2].each { }
303
- }.should.raise(Rack::Lint::LintError).
304
- message.should.match(/Content-Length header was 1, but should be 0/)
296
+ }.must_raise(Rack::Lint::LintError).
297
+ message.must_match(/Content-Length header was 1, but should be 0/)
305
298
  end
306
299
 
307
- should "notice body errors" do
300
+ it "notice body errors" do
308
301
  lambda {
309
302
  body = Rack::Lint.new(lambda { |env|
310
303
  [200, {"Content-type" => "text/plain","Content-length" => "3"}, [1,2,3]]
311
304
  }).call(env({}))[2]
312
305
  body.each { |part| }
313
- }.should.raise(Rack::Lint::LintError).
314
- message.should.match(/yielded non-string/)
306
+ }.must_raise(Rack::Lint::LintError).
307
+ message.must_match(/yielded non-string/)
315
308
  end
316
309
 
317
- should "notice input handling errors" do
310
+ it "notice input handling errors" do
318
311
  lambda {
319
312
  Rack::Lint.new(lambda { |env|
320
313
  env["rack.input"].gets("\r\n")
321
314
  [201, {"Content-type" => "text/plain", "Content-length" => "0"}, []]
322
315
  }).call(env({}))
323
- }.should.raise(Rack::Lint::LintError).
324
- message.should.match(/gets called with arguments/)
316
+ }.must_raise(Rack::Lint::LintError).
317
+ message.must_match(/gets called with arguments/)
325
318
 
326
319
  lambda {
327
320
  Rack::Lint.new(lambda { |env|
328
321
  env["rack.input"].read(1, 2, 3)
329
322
  [201, {"Content-type" => "text/plain", "Content-length" => "0"}, []]
330
323
  }).call(env({}))
331
- }.should.raise(Rack::Lint::LintError).
332
- message.should.match(/read called with too many arguments/)
324
+ }.must_raise(Rack::Lint::LintError).
325
+ message.must_match(/read called with too many arguments/)
333
326
 
334
327
  lambda {
335
328
  Rack::Lint.new(lambda { |env|
336
329
  env["rack.input"].read("foo")
337
330
  [201, {"Content-type" => "text/plain", "Content-length" => "0"}, []]
338
331
  }).call(env({}))
339
- }.should.raise(Rack::Lint::LintError).
340
- message.should.match(/read called with non-integer and non-nil length/)
332
+ }.must_raise(Rack::Lint::LintError).
333
+ message.must_match(/read called with non-integer and non-nil length/)
341
334
 
342
335
  lambda {
343
336
  Rack::Lint.new(lambda { |env|
344
337
  env["rack.input"].read(-1)
345
338
  [201, {"Content-type" => "text/plain", "Content-length" => "0"}, []]
346
339
  }).call(env({}))
347
- }.should.raise(Rack::Lint::LintError).
348
- message.should.match(/read called with a negative length/)
340
+ }.must_raise(Rack::Lint::LintError).
341
+ message.must_match(/read called with a negative length/)
349
342
 
350
343
  lambda {
351
344
  Rack::Lint.new(lambda { |env|
352
345
  env["rack.input"].read(nil, nil)
353
346
  [201, {"Content-type" => "text/plain", "Content-length" => "0"}, []]
354
347
  }).call(env({}))
355
- }.should.raise(Rack::Lint::LintError).
356
- message.should.match(/read called with non-String buffer/)
348
+ }.must_raise(Rack::Lint::LintError).
349
+ message.must_match(/read called with non-String buffer/)
357
350
 
358
351
  lambda {
359
352
  Rack::Lint.new(lambda { |env|
360
353
  env["rack.input"].read(nil, 1)
361
354
  [201, {"Content-type" => "text/plain", "Content-length" => "0"}, []]
362
355
  }).call(env({}))
363
- }.should.raise(Rack::Lint::LintError).
364
- message.should.match(/read called with non-String buffer/)
356
+ }.must_raise(Rack::Lint::LintError).
357
+ message.must_match(/read called with non-String buffer/)
365
358
 
366
359
  lambda {
367
360
  Rack::Lint.new(lambda { |env|
368
361
  env["rack.input"].rewind(0)
369
362
  [201, {"Content-type" => "text/plain", "Content-length" => "0"}, []]
370
363
  }).call(env({}))
371
- }.should.raise(Rack::Lint::LintError).
372
- message.should.match(/rewind called with arguments/)
364
+ }.must_raise(Rack::Lint::LintError).
365
+ message.must_match(/rewind called with arguments/)
373
366
 
374
367
  weirdio = Object.new
375
368
  class << weirdio
@@ -413,40 +406,40 @@ describe Rack::Lint do
413
406
  env["rack.input"].gets
414
407
  [201, {"Content-type" => "text/plain", "Content-length" => "0"}, []]
415
408
  }).call(env("rack.input" => weirdio))
416
- }.should.raise(Rack::Lint::LintError).
417
- message.should.match(/gets didn't return a String/)
409
+ }.must_raise(Rack::Lint::LintError).
410
+ message.must_match(/gets didn't return a String/)
418
411
 
419
412
  lambda {
420
413
  Rack::Lint.new(lambda { |env|
421
414
  env["rack.input"].each { |x| }
422
415
  [201, {"Content-type" => "text/plain", "Content-length" => "0"}, []]
423
416
  }).call(env("rack.input" => weirdio))
424
- }.should.raise(Rack::Lint::LintError).
425
- message.should.match(/each didn't yield a String/)
417
+ }.must_raise(Rack::Lint::LintError).
418
+ message.must_match(/each didn't yield a String/)
426
419
 
427
420
  lambda {
428
421
  Rack::Lint.new(lambda { |env|
429
422
  env["rack.input"].read
430
423
  [201, {"Content-type" => "text/plain", "Content-length" => "0"}, []]
431
424
  }).call(env("rack.input" => weirdio))
432
- }.should.raise(Rack::Lint::LintError).
433
- message.should.match(/read didn't return nil or a String/)
425
+ }.must_raise(Rack::Lint::LintError).
426
+ message.must_match(/read didn't return nil or a String/)
434
427
 
435
428
  lambda {
436
429
  Rack::Lint.new(lambda { |env|
437
430
  env["rack.input"].read
438
431
  [201, {"Content-type" => "text/plain", "Content-length" => "0"}, []]
439
432
  }).call(env("rack.input" => eof_weirdio))
440
- }.should.raise(Rack::Lint::LintError).
441
- message.should.match(/read\(nil\) returned nil on EOF/)
433
+ }.must_raise(Rack::Lint::LintError).
434
+ message.must_match(/read\(nil\) returned nil on EOF/)
442
435
 
443
436
  lambda {
444
437
  Rack::Lint.new(lambda { |env|
445
438
  env["rack.input"].rewind
446
439
  [201, {"Content-type" => "text/plain", "Content-length" => "0"}, []]
447
440
  }).call(env("rack.input" => weirdio))
448
- }.should.raise(Rack::Lint::LintError).
449
- message.should.match(/rewind raised Errno::ESPIPE/)
441
+ }.must_raise(Rack::Lint::LintError).
442
+ message.must_match(/rewind raised Errno::ESPIPE/)
450
443
 
451
444
 
452
445
  lambda {
@@ -454,97 +447,69 @@ describe Rack::Lint do
454
447
  env["rack.input"].close
455
448
  [201, {"Content-type" => "text/plain", "Content-length" => "0"}, []]
456
449
  }).call(env({}))
457
- }.should.raise(Rack::Lint::LintError).
458
- message.should.match(/close must not be called/)
450
+ }.must_raise(Rack::Lint::LintError).
451
+ message.must_match(/close must not be called/)
459
452
  end
460
453
 
461
- should "notice error handling errors" do
454
+ it "notice error handling errors" do
462
455
  lambda {
463
456
  Rack::Lint.new(lambda { |env|
464
457
  env["rack.errors"].write(42)
465
458
  [201, {"Content-type" => "text/plain", "Content-length" => "0"}, []]
466
459
  }).call(env({}))
467
- }.should.raise(Rack::Lint::LintError).
468
- message.should.match(/write not called with a String/)
460
+ }.must_raise(Rack::Lint::LintError).
461
+ message.must_match(/write not called with a String/)
469
462
 
470
463
  lambda {
471
464
  Rack::Lint.new(lambda { |env|
472
465
  env["rack.errors"].close
473
466
  [201, {"Content-type" => "text/plain", "Content-length" => "0"}, []]
474
467
  }).call(env({}))
475
- }.should.raise(Rack::Lint::LintError).
476
- message.should.match(/close must not be called/)
468
+ }.must_raise(Rack::Lint::LintError).
469
+ message.must_match(/close must not be called/)
477
470
  end
478
471
 
479
- should "notice HEAD errors" do
480
- lambda {
481
- Rack::Lint.new(lambda { |env|
482
- [200, {"Content-type" => "test/plain", "Content-length" => "3"}, []]
483
- }).call(env({"REQUEST_METHOD" => "HEAD"}))
484
- }.should.not.raise
472
+ it "notice HEAD errors" do
473
+ Rack::Lint.new(lambda { |env|
474
+ [200, {"Content-type" => "test/plain", "Content-length" => "3"}, []]
475
+ }).call(env({"REQUEST_METHOD" => "HEAD"})).first.must_equal 200
485
476
 
486
477
  lambda {
487
478
  Rack::Lint.new(lambda { |env|
488
479
  [200, {"Content-type" => "test/plain", "Content-length" => "3"}, ["foo"]]
489
480
  }).call(env({"REQUEST_METHOD" => "HEAD"}))[2].each { }
490
- }.should.raise(Rack::Lint::LintError).
491
- message.should.match(/body was given for HEAD/)
481
+ }.must_raise(Rack::Lint::LintError).
482
+ message.must_match(/body was given for HEAD/)
492
483
  end
493
484
 
494
- should "pass valid read calls" do
485
+ def assert_lint(*args)
495
486
  hello_str = "hello world"
496
- hello_str.force_encoding("ASCII-8BIT") if hello_str.respond_to? :force_encoding
497
- lambda {
498
- Rack::Lint.new(lambda { |env|
499
- env["rack.input"].read
500
- [201, {"Content-type" => "text/plain", "Content-length" => "0"}, []]
501
- }).call(env({"rack.input" => StringIO.new(hello_str)}))
502
- }.should.not.raise(Rack::Lint::LintError)
503
-
504
- lambda {
505
- Rack::Lint.new(lambda { |env|
506
- env["rack.input"].read(0)
507
- [201, {"Content-type" => "text/plain", "Content-length" => "0"}, []]
508
- }).call(env({"rack.input" => StringIO.new(hello_str)}))
509
- }.should.not.raise(Rack::Lint::LintError)
510
-
511
- lambda {
512
- Rack::Lint.new(lambda { |env|
513
- env["rack.input"].read(1)
514
- [201, {"Content-type" => "text/plain", "Content-length" => "0"}, []]
515
- }).call(env({"rack.input" => StringIO.new(hello_str)}))
516
- }.should.not.raise(Rack::Lint::LintError)
517
-
518
- lambda {
519
- Rack::Lint.new(lambda { |env|
520
- env["rack.input"].read(nil)
521
- [201, {"Content-type" => "text/plain", "Content-length" => "0"}, []]
522
- }).call(env({"rack.input" => StringIO.new(hello_str)}))
523
- }.should.not.raise(Rack::Lint::LintError)
487
+ hello_str.force_encoding(Encoding::ASCII_8BIT)
524
488
 
525
- lambda {
526
- Rack::Lint.new(lambda { |env|
527
- env["rack.input"].read(nil, '')
528
- [201, {"Content-type" => "text/plain", "Content-length" => "0"}, []]
529
- }).call(env({"rack.input" => StringIO.new(hello_str)}))
530
- }.should.not.raise(Rack::Lint::LintError)
489
+ Rack::Lint.new(lambda { |env|
490
+ env["rack.input"].send(:read, *args)
491
+ [201, {"Content-type" => "text/plain", "Content-length" => "0"}, []]
492
+ }).call(env({"rack.input" => StringIO.new(hello_str)})).
493
+ first.must_equal 201
494
+ end
531
495
 
532
- lambda {
533
- Rack::Lint.new(lambda { |env|
534
- env["rack.input"].read(1, '')
535
- [201, {"Content-type" => "text/plain", "Content-length" => "0"}, []]
536
- }).call(env({"rack.input" => StringIO.new(hello_str)}))
537
- }.should.not.raise(Rack::Lint::LintError)
496
+ it "pass valid read calls" do
497
+ assert_lint
498
+ assert_lint 0
499
+ assert_lint 1
500
+ assert_lint nil
501
+ assert_lint nil, ''
502
+ assert_lint 1, ''
538
503
  end
539
504
  end
540
505
 
541
506
  describe "Rack::Lint::InputWrapper" do
542
- should "delegate :rewind to underlying IO object" do
507
+ it "delegate :rewind to underlying IO object" do
543
508
  io = StringIO.new("123")
544
509
  wrapper = Rack::Lint::InputWrapper.new(io)
545
- wrapper.read.should.equal "123"
546
- wrapper.read.should.equal ""
510
+ wrapper.read.must_equal "123"
511
+ wrapper.read.must_equal ""
547
512
  wrapper.rewind
548
- wrapper.read.should.equal "123"
513
+ wrapper.read.must_equal "123"
549
514
  end
550
515
  end