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,89 +1,94 @@
1
+ require 'minitest/autorun'
1
2
  begin
2
3
  require 'rack/handler/thin'
3
4
  require File.expand_path('../testrequest', __FILE__)
4
5
  require 'timeout'
5
6
 
6
7
  describe Rack::Handler::Thin do
7
- extend TestRequest::Helpers
8
+ include TestRequest::Helpers
8
9
 
9
- @app = Rack::Lint.new(TestRequest.new)
10
- @server = nil
11
- Thin::Logging.silent = true
10
+ before do
11
+ @app = Rack::Lint.new(TestRequest.new)
12
+ @server = nil
13
+ Thin::Logging.silent = true
12
14
 
13
- @thread = Thread.new do
14
- Rack::Handler::Thin.run(@app, :Host => @host='127.0.0.1', :Port => @port=9204, :tag => "tag") do |server|
15
- @server = server
15
+ @thread = Thread.new do
16
+ Rack::Handler::Thin.run(@app, :Host => @host='127.0.0.1', :Port => @port=9204, :tag => "tag") do |server|
17
+ @server = server
18
+ end
16
19
  end
20
+
21
+ Thread.pass until @server && @server.running?
22
+ end
23
+
24
+ after do
25
+ @server.stop!
26
+ @thread.join
17
27
  end
18
28
 
19
- Thread.pass until @server && @server.running?
20
29
 
21
- should "respond" do
30
+ it "respond" do
22
31
  GET("/")
23
- response.should.not.be.nil
32
+ response.wont_be :nil?
24
33
  end
25
34
 
26
- should "be a Thin" do
35
+ it "be a Thin" do
27
36
  GET("/")
28
- status.should.equal 200
29
- response["SERVER_SOFTWARE"].should =~ /thin/
30
- response["HTTP_VERSION"].should.equal "HTTP/1.1"
31
- response["SERVER_PROTOCOL"].should.equal "HTTP/1.1"
32
- response["SERVER_PORT"].should.equal "9204"
33
- response["SERVER_NAME"].should.equal "127.0.0.1"
37
+ status.must_equal 200
38
+ response["SERVER_SOFTWARE"].must_match(/thin/)
39
+ response["HTTP_VERSION"].must_equal "HTTP/1.1"
40
+ response["SERVER_PROTOCOL"].must_equal "HTTP/1.1"
41
+ response["SERVER_PORT"].must_equal "9204"
42
+ response["SERVER_NAME"].must_equal "127.0.0.1"
34
43
  end
35
44
 
36
- should "have rack headers" do
45
+ it "have rack headers" do
37
46
  GET("/")
38
- response["rack.version"].should.equal [1,0]
39
- response["rack.multithread"].should.equal false
40
- response["rack.multiprocess"].should.equal false
41
- response["rack.run_once"].should.equal false
47
+ response["rack.version"].must_equal [1,0]
48
+ response["rack.multithread"].must_equal false
49
+ response["rack.multiprocess"].must_equal false
50
+ response["rack.run_once"].must_equal false
42
51
  end
43
52
 
44
- should "have CGI headers on GET" do
53
+ it "have CGI headers on GET" do
45
54
  GET("/")
46
- response["REQUEST_METHOD"].should.equal "GET"
47
- response["REQUEST_PATH"].should.equal "/"
48
- response["PATH_INFO"].should.be.equal "/"
49
- response["QUERY_STRING"].should.equal ""
50
- response["test.postdata"].should.equal ""
55
+ response["REQUEST_METHOD"].must_equal "GET"
56
+ response["REQUEST_PATH"].must_equal "/"
57
+ response["PATH_INFO"].must_equal "/"
58
+ response["QUERY_STRING"].must_equal ""
59
+ response["test.postdata"].must_equal ""
51
60
 
52
61
  GET("/test/foo?quux=1")
53
- response["REQUEST_METHOD"].should.equal "GET"
54
- response["REQUEST_PATH"].should.equal "/test/foo"
55
- response["PATH_INFO"].should.equal "/test/foo"
56
- response["QUERY_STRING"].should.equal "quux=1"
62
+ response["REQUEST_METHOD"].must_equal "GET"
63
+ response["REQUEST_PATH"].must_equal "/test/foo"
64
+ response["PATH_INFO"].must_equal "/test/foo"
65
+ response["QUERY_STRING"].must_equal "quux=1"
57
66
  end
58
67
 
59
- should "have CGI headers on POST" do
68
+ it "have CGI headers on POST" do
60
69
  POST("/", {"rack-form-data" => "23"}, {'X-test-header' => '42'})
61
- status.should.equal 200
62
- response["REQUEST_METHOD"].should.equal "POST"
63
- response["REQUEST_PATH"].should.equal "/"
64
- response["QUERY_STRING"].should.equal ""
65
- response["HTTP_X_TEST_HEADER"].should.equal "42"
66
- response["test.postdata"].should.equal "rack-form-data=23"
70
+ status.must_equal 200
71
+ response["REQUEST_METHOD"].must_equal "POST"
72
+ response["REQUEST_PATH"].must_equal "/"
73
+ response["QUERY_STRING"].must_equal ""
74
+ response["HTTP_X_TEST_HEADER"].must_equal "42"
75
+ response["test.postdata"].must_equal "rack-form-data=23"
67
76
  end
68
77
 
69
- should "support HTTP auth" do
78
+ it "support HTTP auth" do
70
79
  GET("/test", {:user => "ruth", :passwd => "secret"})
71
- response["HTTP_AUTHORIZATION"].should.equal "Basic cnV0aDpzZWNyZXQ="
80
+ response["HTTP_AUTHORIZATION"].must_equal "Basic cnV0aDpzZWNyZXQ="
72
81
  end
73
82
 
74
- should "set status" do
83
+ it "set status" do
75
84
  GET("/test?secret")
76
- status.should.equal 403
77
- response["rack.url_scheme"].should.equal "http"
85
+ status.must_equal 403
86
+ response["rack.url_scheme"].must_equal "http"
78
87
  end
79
88
 
80
- should "set tag for server" do
81
- @server.tag.should.equal 'tag'
89
+ it "set tag for server" do
90
+ @server.tag.must_equal 'tag'
82
91
  end
83
-
84
- @server.stop!
85
- @thread.kill
86
-
87
92
  end
88
93
 
89
94
  rescue LoadError
@@ -1,3 +1,4 @@
1
+ require 'minitest/autorun'
1
2
  require 'rack/urlmap'
2
3
  require 'rack/mock'
3
4
 
@@ -17,51 +18,51 @@ describe Rack::URLMap do
17
18
  }))
18
19
 
19
20
  res = Rack::MockRequest.new(map).get("/")
20
- res.should.be.not_found
21
+ res.must_be :not_found?
21
22
 
22
23
  res = Rack::MockRequest.new(map).get("/qux")
23
- res.should.be.not_found
24
+ res.must_be :not_found?
24
25
 
25
26
  res = Rack::MockRequest.new(map).get("/foo")
26
- res.should.be.ok
27
- res["X-ScriptName"].should.equal "/foo"
28
- res["X-PathInfo"].should.equal ""
27
+ res.must_be :ok?
28
+ res["X-ScriptName"].must_equal "/foo"
29
+ res["X-PathInfo"].must_equal ""
29
30
 
30
31
  res = Rack::MockRequest.new(map).get("/foo/")
31
- res.should.be.ok
32
- res["X-ScriptName"].should.equal "/foo"
33
- res["X-PathInfo"].should.equal "/"
32
+ res.must_be :ok?
33
+ res["X-ScriptName"].must_equal "/foo"
34
+ res["X-PathInfo"].must_equal "/"
34
35
 
35
36
  res = Rack::MockRequest.new(map).get("/foo/bar")
36
- res.should.be.ok
37
- res["X-ScriptName"].should.equal "/foo/bar"
38
- res["X-PathInfo"].should.equal ""
37
+ res.must_be :ok?
38
+ res["X-ScriptName"].must_equal "/foo/bar"
39
+ res["X-PathInfo"].must_equal ""
39
40
 
40
41
  res = Rack::MockRequest.new(map).get("/foo/bar/")
41
- res.should.be.ok
42
- res["X-ScriptName"].should.equal "/foo/bar"
43
- res["X-PathInfo"].should.equal "/"
42
+ res.must_be :ok?
43
+ res["X-ScriptName"].must_equal "/foo/bar"
44
+ res["X-PathInfo"].must_equal "/"
44
45
 
45
46
  res = Rack::MockRequest.new(map).get("/foo///bar//quux")
46
- res.status.should.equal 200
47
- res.should.be.ok
48
- res["X-ScriptName"].should.equal "/foo/bar"
49
- res["X-PathInfo"].should.equal "//quux"
47
+ res.status.must_equal 200
48
+ res.must_be :ok?
49
+ res["X-ScriptName"].must_equal "/foo/bar"
50
+ res["X-PathInfo"].must_equal "//quux"
50
51
 
51
52
  res = Rack::MockRequest.new(map).get("/foo/quux", "SCRIPT_NAME" => "/bleh")
52
- res.should.be.ok
53
- res["X-ScriptName"].should.equal "/bleh/foo"
54
- res["X-PathInfo"].should.equal "/quux"
53
+ res.must_be :ok?
54
+ res["X-ScriptName"].must_equal "/bleh/foo"
55
+ res["X-PathInfo"].must_equal "/quux"
55
56
 
56
57
  res = Rack::MockRequest.new(map).get("/bar", 'HTTP_HOST' => 'foo.org')
57
- res.should.be.ok
58
- res["X-ScriptName"].should.equal "/bar"
59
- res["X-PathInfo"].should.be.empty
58
+ res.must_be :ok?
59
+ res["X-ScriptName"].must_equal "/bar"
60
+ res["X-PathInfo"].must_be :empty?
60
61
 
61
62
  res = Rack::MockRequest.new(map).get("/bar/", 'HTTP_HOST' => 'foo.org')
62
- res.should.be.ok
63
- res["X-ScriptName"].should.equal "/bar"
64
- res["X-PathInfo"].should.equal '/'
63
+ res.must_be :ok?
64
+ res["X-ScriptName"].must_equal "/bar"
65
+ res["X-PathInfo"].must_equal '/'
65
66
  end
66
67
 
67
68
 
@@ -93,37 +94,37 @@ describe Rack::URLMap do
93
94
  ))
94
95
 
95
96
  res = Rack::MockRequest.new(map).get("/")
96
- res.should.be.ok
97
- res["X-Position"].should.equal "default.org"
97
+ res.must_be :ok?
98
+ res["X-Position"].must_equal "default.org"
98
99
 
99
100
  res = Rack::MockRequest.new(map).get("/", "HTTP_HOST" => "bar.org")
100
- res.should.be.ok
101
- res["X-Position"].should.equal "bar.org"
101
+ res.must_be :ok?
102
+ res["X-Position"].must_equal "bar.org"
102
103
 
103
104
  res = Rack::MockRequest.new(map).get("/", "HTTP_HOST" => "foo.org")
104
- res.should.be.ok
105
- res["X-Position"].should.equal "foo.org"
105
+ res.must_be :ok?
106
+ res["X-Position"].must_equal "foo.org"
106
107
 
107
108
  res = Rack::MockRequest.new(map).get("/", "HTTP_HOST" => "subdomain.foo.org", "SERVER_NAME" => "foo.org")
108
- res.should.be.ok
109
- res["X-Position"].should.equal "subdomain.foo.org"
109
+ res.must_be :ok?
110
+ res["X-Position"].must_equal "subdomain.foo.org"
110
111
 
111
112
  res = Rack::MockRequest.new(map).get("http://foo.org/")
112
- res.should.be.ok
113
- res["X-Position"].should.equal "foo.org"
113
+ res.must_be :ok?
114
+ res["X-Position"].must_equal "foo.org"
114
115
 
115
116
  res = Rack::MockRequest.new(map).get("/", "HTTP_HOST" => "example.org")
116
- res.should.be.ok
117
- res["X-Position"].should.equal "default.org"
117
+ res.must_be :ok?
118
+ res["X-Position"].must_equal "default.org"
118
119
 
119
120
  res = Rack::MockRequest.new(map).get("/",
120
121
  "HTTP_HOST" => "example.org:9292",
121
122
  "SERVER_PORT" => "9292")
122
- res.should.be.ok
123
- res["X-Position"].should.equal "default.org"
123
+ res.must_be :ok?
124
+ res["X-Position"].must_equal "default.org"
124
125
  end
125
126
 
126
- should "be nestable" do
127
+ it "be nestable" do
127
128
  map = Rack::Lint.new(Rack::URLMap.new("/foo" =>
128
129
  Rack::URLMap.new("/bar" =>
129
130
  Rack::URLMap.new("/quux" => lambda { |env|
@@ -136,16 +137,16 @@ describe Rack::URLMap do
136
137
  ))))
137
138
 
138
139
  res = Rack::MockRequest.new(map).get("/foo/bar")
139
- res.should.be.not_found
140
+ res.must_be :not_found?
140
141
 
141
142
  res = Rack::MockRequest.new(map).get("/foo/bar/quux")
142
- res.should.be.ok
143
- res["X-Position"].should.equal "/foo/bar/quux"
144
- res["X-PathInfo"].should.equal ""
145
- res["X-ScriptName"].should.equal "/foo/bar/quux"
143
+ res.must_be :ok?
144
+ res["X-Position"].must_equal "/foo/bar/quux"
145
+ res["X-PathInfo"].must_equal ""
146
+ res["X-ScriptName"].must_equal "/foo/bar/quux"
146
147
  end
147
148
 
148
- should "route root apps correctly" do
149
+ it "route root apps correctly" do
149
150
  map = Rack::Lint.new(Rack::URLMap.new("/" => lambda { |env|
150
151
  [200,
151
152
  { "Content-Type" => "text/plain",
@@ -163,31 +164,31 @@ describe Rack::URLMap do
163
164
  ))
164
165
 
165
166
  res = Rack::MockRequest.new(map).get("/foo/bar")
166
- res.should.be.ok
167
- res["X-Position"].should.equal "foo"
168
- res["X-PathInfo"].should.equal "/bar"
169
- res["X-ScriptName"].should.equal "/foo"
167
+ res.must_be :ok?
168
+ res["X-Position"].must_equal "foo"
169
+ res["X-PathInfo"].must_equal "/bar"
170
+ res["X-ScriptName"].must_equal "/foo"
170
171
 
171
172
  res = Rack::MockRequest.new(map).get("/foo")
172
- res.should.be.ok
173
- res["X-Position"].should.equal "foo"
174
- res["X-PathInfo"].should.equal ""
175
- res["X-ScriptName"].should.equal "/foo"
173
+ res.must_be :ok?
174
+ res["X-Position"].must_equal "foo"
175
+ res["X-PathInfo"].must_equal ""
176
+ res["X-ScriptName"].must_equal "/foo"
176
177
 
177
178
  res = Rack::MockRequest.new(map).get("/bar")
178
- res.should.be.ok
179
- res["X-Position"].should.equal "root"
180
- res["X-PathInfo"].should.equal "/bar"
181
- res["X-ScriptName"].should.equal ""
179
+ res.must_be :ok?
180
+ res["X-Position"].must_equal "root"
181
+ res["X-PathInfo"].must_equal "/bar"
182
+ res["X-ScriptName"].must_equal ""
182
183
 
183
184
  res = Rack::MockRequest.new(map).get("")
184
- res.should.be.ok
185
- res["X-Position"].should.equal "root"
186
- res["X-PathInfo"].should.equal "/"
187
- res["X-ScriptName"].should.equal ""
185
+ res.must_be :ok?
186
+ res["X-Position"].must_equal "root"
187
+ res["X-PathInfo"].must_equal "/"
188
+ res["X-ScriptName"].must_equal ""
188
189
  end
189
190
 
190
- should "not squeeze slashes" do
191
+ it "not squeeze slashes" do
191
192
  map = Rack::Lint.new(Rack::URLMap.new("/" => lambda { |env|
192
193
  [200,
193
194
  { "Content-Type" => "text/plain",
@@ -205,13 +206,13 @@ describe Rack::URLMap do
205
206
  ))
206
207
 
207
208
  res = Rack::MockRequest.new(map).get("/http://example.org/bar")
208
- res.should.be.ok
209
- res["X-Position"].should.equal "root"
210
- res["X-PathInfo"].should.equal "/http://example.org/bar"
211
- res["X-ScriptName"].should.equal ""
209
+ res.must_be :ok?
210
+ res["X-Position"].must_equal "root"
211
+ res["X-PathInfo"].must_equal "/http://example.org/bar"
212
+ res["X-ScriptName"].must_equal ""
212
213
  end
213
214
 
214
- should "not be case sensitive with hosts" do
215
+ it "not be case sensitive with hosts" do
215
216
  map = Rack::Lint.new(Rack::URLMap.new("http://example.org/" => lambda { |env|
216
217
  [200,
217
218
  { "Content-Type" => "text/plain",
@@ -222,15 +223,15 @@ describe Rack::URLMap do
222
223
  ))
223
224
 
224
225
  res = Rack::MockRequest.new(map).get("http://example.org/")
225
- res.should.be.ok
226
- res["X-Position"].should.equal "root"
227
- res["X-PathInfo"].should.equal "/"
228
- res["X-ScriptName"].should.equal ""
226
+ res.must_be :ok?
227
+ res["X-Position"].must_equal "root"
228
+ res["X-PathInfo"].must_equal "/"
229
+ res["X-ScriptName"].must_equal ""
229
230
 
230
231
  res = Rack::MockRequest.new(map).get("http://EXAMPLE.ORG/")
231
- res.should.be.ok
232
- res["X-Position"].should.equal "root"
233
- res["X-PathInfo"].should.equal "/"
234
- res["X-ScriptName"].should.equal ""
232
+ res.must_be :ok?
233
+ res["X-Position"].must_equal "root"
234
+ res["X-PathInfo"].must_equal "/"
235
+ res["X-ScriptName"].must_equal ""
235
236
  end
236
237
  end
@@ -1,288 +1,312 @@
1
1
  # -*- encoding: utf-8 -*-
2
+ require 'minitest/autorun'
2
3
  require 'rack/utils'
3
4
  require 'rack/mock'
4
5
  require 'timeout'
5
6
 
6
7
  describe Rack::Utils do
7
8
 
8
- # A helper method which checks
9
- # if certain query parameters
10
- # are equal.
11
- def equal_query_to(query)
12
- parts = query.split('&')
13
- lambda{|other| (parts & other.split('&')) == parts }
9
+ def assert_sets exp, act
10
+ exp = Set.new exp.split '&'
11
+ act = Set.new act.split '&'
12
+
13
+ assert_equal exp, act
14
+ end
15
+
16
+ def assert_query exp, act
17
+ assert_sets exp, Rack::Utils.build_query(act)
14
18
  end
15
19
 
16
- def kcodeu
17
- one8 = RUBY_VERSION.to_f < 1.9
18
- default_kcode, $KCODE = $KCODE, 'U' if one8
19
- yield
20
- ensure
21
- $KCODE = default_kcode if one8
20
+ def assert_nested_query exp, act
21
+ assert_sets exp, Rack::Utils.build_nested_query(act)
22
+ end
23
+
24
+ it 'can be mixed in and used' do
25
+ instance = Class.new {
26
+ include Rack::Utils
27
+
28
+ public :parse_nested_query
29
+ public :parse_query
30
+ }.new
31
+
32
+ assert_equal({ "foo" => "bar" }, instance.parse_nested_query("foo=bar"))
33
+ assert_equal({ "foo" => "bar" }, instance.parse_query("foo=bar"))
22
34
  end
23
35
 
24
- should "round trip binary data" do
36
+ it "round trip binary data" do
25
37
  r = [218, 0].pack 'CC'
26
- if defined?(::Encoding)
27
38
  z = Rack::Utils.unescape(Rack::Utils.escape(r), Encoding::BINARY)
28
- else
29
- z = Rack::Utils.unescape(Rack::Utils.escape(r))
30
- end
31
- r.should.equal z
39
+ r.must_equal z
32
40
  end
33
41
 
34
- should "escape correctly" do
35
- Rack::Utils.escape("fo<o>bar").should.equal "fo%3Co%3Ebar"
36
- Rack::Utils.escape("a space").should.equal "a+space"
42
+ it "escape correctly" do
43
+ Rack::Utils.escape("fo<o>bar").must_equal "fo%3Co%3Ebar"
44
+ Rack::Utils.escape("a space").must_equal "a+space"
37
45
  Rack::Utils.escape("q1!2\"'w$5&7/z8)?\\").
38
- should.equal "q1%212%22%27w%245%267%2Fz8%29%3F%5C"
46
+ must_equal "q1%212%22%27w%245%267%2Fz8%29%3F%5C"
39
47
  end
40
48
 
41
- should "escape correctly for multibyte characters" do
49
+ it "escape correctly for multibyte characters" do
42
50
  matz_name = "\xE3\x81\xBE\xE3\x81\xA4\xE3\x82\x82\xE3\x81\xA8".unpack("a*")[0] # Matsumoto
43
- matz_name.force_encoding("UTF-8") if matz_name.respond_to? :force_encoding
44
- Rack::Utils.escape(matz_name).should.equal '%E3%81%BE%E3%81%A4%E3%82%82%E3%81%A8'
51
+ matz_name.force_encoding(Encoding::UTF_8)
52
+ Rack::Utils.escape(matz_name).must_equal '%E3%81%BE%E3%81%A4%E3%82%82%E3%81%A8'
45
53
  matz_name_sep = "\xE3\x81\xBE\xE3\x81\xA4 \xE3\x82\x82\xE3\x81\xA8".unpack("a*")[0] # Matsu moto
46
54
  matz_name_sep.force_encoding("UTF-8") if matz_name_sep.respond_to? :force_encoding
47
- Rack::Utils.escape(matz_name_sep).should.equal '%E3%81%BE%E3%81%A4+%E3%82%82%E3%81%A8'
48
- end
49
-
50
- if RUBY_VERSION[/^\d+\.\d+/] == '1.8'
51
- should "escape correctly for multibyte characters if $KCODE is set to 'U'" do
52
- kcodeu do
53
- matz_name = "\xE3\x81\xBE\xE3\x81\xA4\xE3\x82\x82\xE3\x81\xA8".unpack("a*")[0] # Matsumoto
54
- matz_name.force_encoding("UTF-8") if matz_name.respond_to? :force_encoding
55
- Rack::Utils.escape(matz_name).should.equal '%E3%81%BE%E3%81%A4%E3%82%82%E3%81%A8'
56
- matz_name_sep = "\xE3\x81\xBE\xE3\x81\xA4 \xE3\x82\x82\xE3\x81\xA8".unpack("a*")[0] # Matsu moto
57
- matz_name_sep.force_encoding("UTF-8") if matz_name_sep.respond_to? :force_encoding
58
- Rack::Utils.escape(matz_name_sep).should.equal '%E3%81%BE%E3%81%A4+%E3%82%82%E3%81%A8'
59
- end
60
- end
55
+ Rack::Utils.escape(matz_name_sep).must_equal '%E3%81%BE%E3%81%A4+%E3%82%82%E3%81%A8'
56
+ end
61
57
 
62
- should "unescape multibyte characters correctly if $KCODE is set to 'U'" do
63
- kcodeu do
64
- Rack::Utils.unescape('%E3%81%BE%E3%81%A4+%E3%82%82%E3%81%A8').should.equal(
65
- "\xE3\x81\xBE\xE3\x81\xA4 \xE3\x82\x82\xE3\x81\xA8".unpack("a*")[0])
66
- end
67
- end
58
+ it "escape objects that responds to to_s" do
59
+ Rack::Utils.escape(:id).must_equal "id"
68
60
  end
69
61
 
70
- should "escape objects that responds to to_s" do
71
- kcodeu do
72
- Rack::Utils.escape(:id).should.equal "id"
73
- end
62
+ it "escape non-UTF8 strings" do
63
+ Rack::Utils.escape("ø".encode("ISO-8859-1")).must_equal "%F8"
74
64
  end
75
65
 
76
- if "".respond_to?(:encode)
77
- should "escape non-UTF8 strings" do
78
- Rack::Utils.escape("ø".encode("ISO-8859-1")).should.equal "%F8"
66
+ it "not hang on escaping long strings that end in % (http://redmine.ruby-lang.org/issues/5149)" do
67
+ Timeout.timeout(1) do
68
+ lambda {
69
+ URI.decode_www_form_component "A string that causes catastrophic backtracking as it gets longer %"
70
+ }.must_raise ArgumentError
79
71
  end
80
72
  end
81
-
82
- should "not hang on escaping long strings that end in % (http://redmine.ruby-lang.org/issues/5149)" do
83
- lambda {
84
- timeout(1) do
85
- lambda {
86
- URI.decode_www_form_component "A string that causes catastrophic backtracking as it gets longer %"
87
- }.should.raise(ArgumentError)
88
- end
89
- }.should.not.raise(Timeout::Error)
90
- end
91
73
 
92
- should "escape path spaces with %20" do
93
- Rack::Utils.escape_path("foo bar").should.equal "foo%20bar"
74
+ it "escape path spaces with %20" do
75
+ Rack::Utils.escape_path("foo bar").must_equal "foo%20bar"
94
76
  end
95
77
 
96
- should "unescape correctly" do
97
- Rack::Utils.unescape("fo%3Co%3Ebar").should.equal "fo<o>bar"
98
- Rack::Utils.unescape("a+space").should.equal "a space"
99
- Rack::Utils.unescape("a%20space").should.equal "a space"
78
+ it "unescape correctly" do
79
+ Rack::Utils.unescape("fo%3Co%3Ebar").must_equal "fo<o>bar"
80
+ Rack::Utils.unescape("a+space").must_equal "a space"
81
+ Rack::Utils.unescape("a%20space").must_equal "a space"
100
82
  Rack::Utils.unescape("q1%212%22%27w%245%267%2Fz8%29%3F%5C").
101
- should.equal "q1!2\"'w$5&7/z8)?\\"
83
+ must_equal "q1!2\"'w$5&7/z8)?\\"
102
84
  end
103
85
 
104
- should "parse query strings correctly" do
86
+ it "parse query strings correctly" do
105
87
  Rack::Utils.parse_query("foo=bar").
106
- should.equal "foo" => "bar"
88
+ must_equal "foo" => "bar"
107
89
  Rack::Utils.parse_query("foo=\"bar\"").
108
- should.equal "foo" => "\"bar\""
90
+ must_equal "foo" => "\"bar\""
109
91
  Rack::Utils.parse_query("foo=bar&foo=quux").
110
- should.equal "foo" => ["bar", "quux"]
92
+ must_equal "foo" => ["bar", "quux"]
111
93
  Rack::Utils.parse_query("foo=1&bar=2").
112
- should.equal "foo" => "1", "bar" => "2"
94
+ must_equal "foo" => "1", "bar" => "2"
113
95
  Rack::Utils.parse_query("my+weird+field=q1%212%22%27w%245%267%2Fz8%29%3F").
114
- should.equal "my weird field" => "q1!2\"'w$5&7/z8)?"
115
- Rack::Utils.parse_query("foo%3Dbaz=bar").should.equal "foo=baz" => "bar"
116
- Rack::Utils.parse_query("=").should.equal "" => ""
117
- Rack::Utils.parse_query("=value").should.equal "" => "value"
118
- Rack::Utils.parse_query("key=").should.equal "key" => ""
119
- Rack::Utils.parse_query("&key&").should.equal "key" => nil
120
- Rack::Utils.parse_query(";key;", ";,").should.equal "key" => nil
121
- Rack::Utils.parse_query(",key,", ";,").should.equal "key" => nil
122
- Rack::Utils.parse_query(";foo=bar,;", ";,").should.equal "foo" => "bar"
123
- Rack::Utils.parse_query(",foo=bar;,", ";,").should.equal "foo" => "bar"
124
- end
125
-
126
- should "not create infinite loops with cycle structures" do
96
+ must_equal "my weird field" => "q1!2\"'w$5&7/z8)?"
97
+ Rack::Utils.parse_query("foo%3Dbaz=bar").must_equal "foo=baz" => "bar"
98
+ Rack::Utils.parse_query("=").must_equal "" => ""
99
+ Rack::Utils.parse_query("=value").must_equal "" => "value"
100
+ Rack::Utils.parse_query("key=").must_equal "key" => ""
101
+ Rack::Utils.parse_query("&key&").must_equal "key" => nil
102
+ Rack::Utils.parse_query(";key;", ";,").must_equal "key" => nil
103
+ Rack::Utils.parse_query(",key,", ";,").must_equal "key" => nil
104
+ Rack::Utils.parse_query(";foo=bar,;", ";,").must_equal "foo" => "bar"
105
+ Rack::Utils.parse_query(",foo=bar;,", ";,").must_equal "foo" => "bar"
106
+ end
107
+
108
+ it "not create infinite loops with cycle structures" do
127
109
  ex = { "foo" => nil }
128
110
  ex["foo"] = ex
129
111
 
130
- params = Rack::Utils::KeySpaceConstrainedParams.new
112
+ params = Rack::Utils::KeySpaceConstrainedParams.new(65536)
131
113
  params['foo'] = params
132
- lambda {
133
- params.to_params_hash.to_s.should.equal ex.to_s
134
- }.should.not.raise
114
+ params.to_params_hash.to_s.must_equal ex.to_s
115
+ end
116
+
117
+ it "parse nil as an empty query string" do
118
+ Rack::Utils.parse_nested_query(nil).must_equal({})
135
119
  end
136
120
 
137
- should "raise an exception if the params are too deep" do
121
+ it "raise an exception if the params are too deep" do
138
122
  len = Rack::Utils.param_depth_limit
139
123
 
140
124
  lambda {
141
125
  Rack::Utils.parse_nested_query("foo#{"[a]" * len}=bar")
142
- }.should.raise(RangeError)
126
+ }.must_raise(RangeError)
143
127
 
144
- lambda {
145
- Rack::Utils.parse_nested_query("foo#{"[a]" * (len - 1)}=bar")
146
- }.should.not.raise
128
+ Rack::Utils.parse_nested_query("foo#{"[a]" * (len - 1)}=bar")
147
129
  end
148
130
 
149
- should "parse nested query strings correctly" do
131
+ it "parse nested query strings correctly" do
150
132
  Rack::Utils.parse_nested_query("foo").
151
- should.equal "foo" => nil
133
+ must_equal "foo" => nil
152
134
  Rack::Utils.parse_nested_query("foo=").
153
- should.equal "foo" => ""
135
+ must_equal "foo" => ""
154
136
  Rack::Utils.parse_nested_query("foo=bar").
155
- should.equal "foo" => "bar"
137
+ must_equal "foo" => "bar"
156
138
  Rack::Utils.parse_nested_query("foo=\"bar\"").
157
- should.equal "foo" => "\"bar\""
139
+ must_equal "foo" => "\"bar\""
158
140
 
159
141
  Rack::Utils.parse_nested_query("foo=bar&foo=quux").
160
- should.equal "foo" => "quux"
142
+ must_equal "foo" => "quux"
161
143
  Rack::Utils.parse_nested_query("foo&foo=").
162
- should.equal "foo" => ""
144
+ must_equal "foo" => ""
163
145
  Rack::Utils.parse_nested_query("foo=1&bar=2").
164
- should.equal "foo" => "1", "bar" => "2"
146
+ must_equal "foo" => "1", "bar" => "2"
165
147
  Rack::Utils.parse_nested_query("&foo=1&&bar=2").
166
- should.equal "foo" => "1", "bar" => "2"
148
+ must_equal "foo" => "1", "bar" => "2"
167
149
  Rack::Utils.parse_nested_query("foo&bar=").
168
- should.equal "foo" => nil, "bar" => ""
150
+ must_equal "foo" => nil, "bar" => ""
169
151
  Rack::Utils.parse_nested_query("foo=bar&baz=").
170
- should.equal "foo" => "bar", "baz" => ""
152
+ must_equal "foo" => "bar", "baz" => ""
171
153
  Rack::Utils.parse_nested_query("my+weird+field=q1%212%22%27w%245%267%2Fz8%29%3F").
172
- should.equal "my weird field" => "q1!2\"'w$5&7/z8)?"
154
+ must_equal "my weird field" => "q1!2\"'w$5&7/z8)?"
173
155
 
174
156
  Rack::Utils.parse_nested_query("a=b&pid%3D1234=1023").
175
- should.equal "pid=1234" => "1023", "a" => "b"
157
+ must_equal "pid=1234" => "1023", "a" => "b"
176
158
 
177
159
  Rack::Utils.parse_nested_query("foo[]").
178
- should.equal "foo" => [nil]
160
+ must_equal "foo" => [nil]
179
161
  Rack::Utils.parse_nested_query("foo[]=").
180
- should.equal "foo" => [""]
162
+ must_equal "foo" => [""]
181
163
  Rack::Utils.parse_nested_query("foo[]=bar").
182
- should.equal "foo" => ["bar"]
164
+ must_equal "foo" => ["bar"]
183
165
  Rack::Utils.parse_nested_query("foo[]=bar&foo").
184
- should.equal "foo" => nil
166
+ must_equal "foo" => nil
185
167
  Rack::Utils.parse_nested_query("foo[]=bar&foo[").
186
- should.equal "foo" => ["bar"], "foo[" => nil
168
+ must_equal "foo" => ["bar"], "foo[" => nil
187
169
  Rack::Utils.parse_nested_query("foo[]=bar&foo[=baz").
188
- should.equal "foo" => ["bar"], "foo[" => "baz"
170
+ must_equal "foo" => ["bar"], "foo[" => "baz"
189
171
  Rack::Utils.parse_nested_query("foo[]=bar&foo[]").
190
- should.equal "foo" => ["bar", nil]
172
+ must_equal "foo" => ["bar", nil]
191
173
  Rack::Utils.parse_nested_query("foo[]=bar&foo[]=").
192
- should.equal "foo" => ["bar", ""]
174
+ must_equal "foo" => ["bar", ""]
193
175
 
194
176
  Rack::Utils.parse_nested_query("foo[]=1&foo[]=2").
195
- should.equal "foo" => ["1", "2"]
177
+ must_equal "foo" => ["1", "2"]
196
178
  Rack::Utils.parse_nested_query("foo=bar&baz[]=1&baz[]=2&baz[]=3").
197
- should.equal "foo" => "bar", "baz" => ["1", "2", "3"]
179
+ must_equal "foo" => "bar", "baz" => ["1", "2", "3"]
198
180
  Rack::Utils.parse_nested_query("foo[]=bar&baz[]=1&baz[]=2&baz[]=3").
199
- should.equal "foo" => ["bar"], "baz" => ["1", "2", "3"]
181
+ must_equal "foo" => ["bar"], "baz" => ["1", "2", "3"]
200
182
 
201
183
  Rack::Utils.parse_nested_query("x[y][z]=1").
202
- should.equal "x" => {"y" => {"z" => "1"}}
184
+ must_equal "x" => {"y" => {"z" => "1"}}
203
185
  Rack::Utils.parse_nested_query("x[y][z][]=1").
204
- should.equal "x" => {"y" => {"z" => ["1"]}}
186
+ must_equal "x" => {"y" => {"z" => ["1"]}}
205
187
  Rack::Utils.parse_nested_query("x[y][z]=1&x[y][z]=2").
206
- should.equal "x" => {"y" => {"z" => "2"}}
188
+ must_equal "x" => {"y" => {"z" => "2"}}
207
189
  Rack::Utils.parse_nested_query("x[y][z][]=1&x[y][z][]=2").
208
- should.equal "x" => {"y" => {"z" => ["1", "2"]}}
190
+ must_equal "x" => {"y" => {"z" => ["1", "2"]}}
209
191
 
210
192
  Rack::Utils.parse_nested_query("x[y][][z]=1").
211
- should.equal "x" => {"y" => [{"z" => "1"}]}
193
+ must_equal "x" => {"y" => [{"z" => "1"}]}
212
194
  Rack::Utils.parse_nested_query("x[y][][z][]=1").
213
- should.equal "x" => {"y" => [{"z" => ["1"]}]}
195
+ must_equal "x" => {"y" => [{"z" => ["1"]}]}
214
196
  Rack::Utils.parse_nested_query("x[y][][z]=1&x[y][][w]=2").
215
- should.equal "x" => {"y" => [{"z" => "1", "w" => "2"}]}
197
+ must_equal "x" => {"y" => [{"z" => "1", "w" => "2"}]}
216
198
 
217
199
  Rack::Utils.parse_nested_query("x[y][][v][w]=1").
218
- should.equal "x" => {"y" => [{"v" => {"w" => "1"}}]}
200
+ must_equal "x" => {"y" => [{"v" => {"w" => "1"}}]}
219
201
  Rack::Utils.parse_nested_query("x[y][][z]=1&x[y][][v][w]=2").
220
- should.equal "x" => {"y" => [{"z" => "1", "v" => {"w" => "2"}}]}
202
+ must_equal "x" => {"y" => [{"z" => "1", "v" => {"w" => "2"}}]}
221
203
 
222
204
  Rack::Utils.parse_nested_query("x[y][][z]=1&x[y][][z]=2").
223
- should.equal "x" => {"y" => [{"z" => "1"}, {"z" => "2"}]}
205
+ must_equal "x" => {"y" => [{"z" => "1"}, {"z" => "2"}]}
224
206
  Rack::Utils.parse_nested_query("x[y][][z]=1&x[y][][w]=a&x[y][][z]=2&x[y][][w]=3").
225
- should.equal "x" => {"y" => [{"z" => "1", "w" => "a"}, {"z" => "2", "w" => "3"}]}
207
+ must_equal "x" => {"y" => [{"z" => "1", "w" => "a"}, {"z" => "2", "w" => "3"}]}
226
208
 
227
209
  lambda { Rack::Utils.parse_nested_query("x[y]=1&x[y]z=2") }.
228
- should.raise(Rack::Utils::ParameterTypeError).
229
- message.should.equal "expected Hash (got String) for param `y'"
210
+ must_raise(Rack::Utils::ParameterTypeError).
211
+ message.must_equal "expected Hash (got String) for param `y'"
230
212
 
231
213
  lambda { Rack::Utils.parse_nested_query("x[y]=1&x[]=1") }.
232
- should.raise(Rack::Utils::ParameterTypeError).
233
- message.should.match(/expected Array \(got [^)]*\) for param `x'/)
214
+ must_raise(Rack::Utils::ParameterTypeError).
215
+ message.must_match(/expected Array \(got [^)]*\) for param `x'/)
234
216
 
235
217
  lambda { Rack::Utils.parse_nested_query("x[y]=1&x[y][][w]=2") }.
236
- should.raise(Rack::Utils::ParameterTypeError).
237
- message.should.equal "expected Array (got String) for param `y'"
238
-
239
- if RUBY_VERSION.to_f > 1.9
240
- lambda { Rack::Utils.parse_nested_query("foo%81E=1") }.
241
- should.raise(Rack::Utils::InvalidParameterError).
242
- message.should.equal "invalid byte sequence in UTF-8"
218
+ must_raise(Rack::Utils::ParameterTypeError).
219
+ message.must_equal "expected Array (got String) for param `y'"
220
+
221
+ lambda { Rack::Utils.parse_nested_query("foo%81E=1") }.
222
+ must_raise(Rack::Utils::InvalidParameterError).
223
+ message.must_equal "invalid byte sequence in UTF-8"
224
+ end
225
+
226
+ it "allow setting the params hash class to use for parsing query strings" do
227
+ begin
228
+ default_parser = Rack::Utils.default_query_parser
229
+ param_parser_class = Class.new(Rack::QueryParser::Params) do
230
+ def initialize(*)
231
+ super
232
+ @params = Hash.new{|h,k| h[k.to_s] if k.is_a?(Symbol)}
233
+ end
234
+ end
235
+ Rack::Utils.default_query_parser = Rack::QueryParser.new(param_parser_class, 65536, 100)
236
+ Rack::Utils.parse_query(",foo=bar;,", ";,")[:foo].must_equal "bar"
237
+ Rack::Utils.parse_nested_query("x[y][][z]=1&x[y][][w]=2")[:x][:y][0][:z].must_equal "1"
238
+ ensure
239
+ Rack::Utils.default_query_parser = default_parser
243
240
  end
244
241
  end
245
242
 
246
- should "build query strings correctly" do
247
- Rack::Utils.build_query("foo" => "bar").should.be equal_query_to("foo=bar")
248
- Rack::Utils.build_query("foo" => ["bar", "quux"]).
249
- should.be equal_query_to("foo=bar&foo=quux")
250
- Rack::Utils.build_query("foo" => "1", "bar" => "2").
251
- should.be equal_query_to("foo=1&bar=2")
252
- Rack::Utils.build_query("my weird field" => "q1!2\"'w$5&7/z8)?").
253
- should.be equal_query_to("my+weird+field=q1%212%22%27w%245%267%2Fz8%29%3F")
254
- end
255
-
256
- should "build nested query strings correctly" do
257
- Rack::Utils.build_nested_query("foo" => nil).should.equal "foo"
258
- Rack::Utils.build_nested_query("foo" => "").should.equal "foo="
259
- Rack::Utils.build_nested_query("foo" => "bar").should.equal "foo=bar"
260
-
261
- Rack::Utils.build_nested_query("foo" => "1", "bar" => "2").
262
- should.be equal_query_to("foo=1&bar=2")
263
- Rack::Utils.build_nested_query("foo" => 1, "bar" => 2).
264
- should.be equal_query_to("foo=1&bar=2")
265
- Rack::Utils.build_nested_query("my weird field" => "q1!2\"'w$5&7/z8)?").
266
- should.be equal_query_to("my+weird+field=q1%212%22%27w%245%267%2Fz8%29%3F")
267
-
268
- Rack::Utils.build_nested_query("foo" => [nil]).
269
- should.equal "foo[]"
270
- Rack::Utils.build_nested_query("foo" => [""]).
271
- should.equal "foo[]="
272
- Rack::Utils.build_nested_query("foo" => ["bar"]).
273
- should.equal "foo[]=bar"
274
- Rack::Utils.build_nested_query('foo' => []).
275
- should.equal ''
276
- Rack::Utils.build_nested_query('foo' => {}).
277
- should.equal ''
278
- Rack::Utils.build_nested_query('foo' => 'bar', 'baz' => []).
279
- should.equal 'foo=bar'
280
- Rack::Utils.build_nested_query('foo' => 'bar', 'baz' => {}).
281
- should.equal 'foo=bar'
282
-
283
- # The ordering of the output query string is unpredictable with 1.8's
284
- # unordered hash. Test that build_nested_query performs the inverse
285
- # function of parse_nested_query.
243
+ it "build query strings correctly" do
244
+ assert_query "foo=bar", "foo" => "bar"
245
+ assert_query "foo=bar&foo=quux", "foo" => ["bar", "quux"]
246
+ assert_query "foo=1&bar=2", "foo" => "1", "bar" => "2"
247
+ assert_query("my+weird+field=q1%212%22%27w%245%267%2Fz8%29%3F",
248
+ "my weird field" => "q1!2\"'w$5&7/z8)?")
249
+ end
250
+
251
+ it "build nested query strings correctly" do
252
+ Rack::Utils.build_nested_query("foo" => nil).must_equal "foo"
253
+ Rack::Utils.build_nested_query("foo" => "").must_equal "foo="
254
+ Rack::Utils.build_nested_query("foo" => "bar").must_equal "foo=bar"
255
+
256
+ assert_nested_query("foo=1&bar=2",
257
+ "foo" => "1", "bar" => "2")
258
+ assert_nested_query("foo=1&bar=2",
259
+ "foo" => 1, "bar" => 2)
260
+ assert_nested_query("my+weird+field=q1%212%22%27w%245%267%2Fz8%29%3F",
261
+ "my weird field" => "q1!2\"'w$5&7/z8)?")
262
+
263
+ Rack::Utils.build_nested_query("foo" => [nil]).must_equal "foo[]"
264
+ Rack::Utils.build_nested_query("foo" => [""]).must_equal "foo[]="
265
+ Rack::Utils.build_nested_query("foo" => ["bar"]).must_equal "foo[]=bar"
266
+ Rack::Utils.build_nested_query('foo' => []).must_equal ''
267
+ Rack::Utils.build_nested_query('foo' => {}).must_equal ''
268
+ Rack::Utils.build_nested_query('foo' => 'bar', 'baz' => []).must_equal 'foo=bar'
269
+ Rack::Utils.build_nested_query('foo' => 'bar', 'baz' => {}).must_equal 'foo=bar'
270
+
271
+ Rack::Utils.build_nested_query('foo' => nil, 'bar' => '').
272
+ must_equal 'foo&bar='
273
+ Rack::Utils.build_nested_query('foo' => 'bar', 'baz' => '').
274
+ must_equal 'foo=bar&baz='
275
+ Rack::Utils.build_nested_query('foo' => ['1', '2']).
276
+ must_equal 'foo[]=1&foo[]=2'
277
+ Rack::Utils.build_nested_query('foo' => 'bar', 'baz' => ['1', '2', '3']).
278
+ must_equal 'foo=bar&baz[]=1&baz[]=2&baz[]=3'
279
+ Rack::Utils.build_nested_query('foo' => ['bar'], 'baz' => ['1', '2', '3']).
280
+ must_equal 'foo[]=bar&baz[]=1&baz[]=2&baz[]=3'
281
+ Rack::Utils.build_nested_query('foo' => ['bar'], 'baz' => ['1', '2', '3']).
282
+ must_equal 'foo[]=bar&baz[]=1&baz[]=2&baz[]=3'
283
+ Rack::Utils.build_nested_query('x' => { 'y' => { 'z' => '1' } }).
284
+ must_equal 'x[y][z]=1'
285
+ Rack::Utils.build_nested_query('x' => { 'y' => { 'z' => ['1'] } }).
286
+ must_equal 'x[y][z][]=1'
287
+ Rack::Utils.build_nested_query('x' => { 'y' => { 'z' => ['1', '2'] } }).
288
+ must_equal 'x[y][z][]=1&x[y][z][]=2'
289
+ Rack::Utils.build_nested_query('x' => { 'y' => [{ 'z' => '1' }] }).
290
+ must_equal 'x[y][][z]=1'
291
+ Rack::Utils.build_nested_query('x' => { 'y' => [{ 'z' => ['1'] }] }).
292
+ must_equal 'x[y][][z][]=1'
293
+ Rack::Utils.build_nested_query('x' => { 'y' => [{ 'z' => '1', 'w' => '2' }] }).
294
+ must_equal 'x[y][][z]=1&x[y][][w]=2'
295
+ Rack::Utils.build_nested_query('x' => { 'y' => [{ 'v' => { 'w' => '1' } }] }).
296
+ must_equal 'x[y][][v][w]=1'
297
+ Rack::Utils.build_nested_query('x' => { 'y' => [{ 'z' => '1', 'v' => { 'w' => '2' } }] }).
298
+ must_equal 'x[y][][z]=1&x[y][][v][w]=2'
299
+ Rack::Utils.build_nested_query('x' => { 'y' => [{ 'z' => '1' }, { 'z' => '2' }] }).
300
+ must_equal 'x[y][][z]=1&x[y][][z]=2'
301
+ Rack::Utils.build_nested_query('x' => { 'y' => [{ 'z' => '1', 'w' => 'a' }, { 'z' => '2', 'w' => '3' }] }).
302
+ must_equal 'x[y][][z]=1&x[y][][w]=a&x[y][][z]=2&x[y][][w]=3'
303
+
304
+ lambda { Rack::Utils.build_nested_query("foo=bar") }.
305
+ must_raise(ArgumentError).
306
+ message.must_equal "value must be a Hash"
307
+ end
308
+
309
+ should 'perform the inverse function of #parse_nested_query' do
286
310
  [{"foo" => nil, "bar" => ""},
287
311
  {"foo" => "bar", "baz" => ""},
288
312
  {"foo" => ["1", "2"]},
@@ -302,293 +326,341 @@ describe Rack::Utils do
302
326
  {"x" => {"y" => [{"z" => "1", "w" => "a"}, {"z" => "2", "w" => "3"}]}}
303
327
  ].each { |params|
304
328
  qs = Rack::Utils.build_nested_query(params)
305
- Rack::Utils.parse_nested_query(qs).should.equal params
329
+ Rack::Utils.parse_nested_query(qs).must_equal params
306
330
  }
307
331
 
308
332
  lambda { Rack::Utils.build_nested_query("foo=bar") }.
309
- should.raise(ArgumentError).
310
- message.should.equal "value must be a Hash"
333
+ must_raise(ArgumentError).
334
+ message.must_equal "value must be a Hash"
311
335
  end
312
336
 
313
- should "parse query strings that have a non-existent value" do
337
+ it "parse query strings that have a non-existent value" do
314
338
  key = "post/2011/08/27/Deux-%22rat%C3%A9s%22-de-l-Universit"
315
- Rack::Utils.parse_query(key).should.equal Rack::Utils.unescape(key) => nil
339
+ Rack::Utils.parse_query(key).must_equal Rack::Utils.unescape(key) => nil
316
340
  end
317
341
 
318
- should "build query strings without = with non-existent values" do
342
+ it "build query strings without = with non-existent values" do
319
343
  key = "post/2011/08/27/Deux-%22rat%C3%A9s%22-de-l-Universit"
320
344
  key = Rack::Utils.unescape(key)
321
- Rack::Utils.build_query(key => nil).should.equal Rack::Utils.escape(key)
345
+ Rack::Utils.build_query(key => nil).must_equal Rack::Utils.escape(key)
322
346
  end
323
347
 
324
- should "parse q-values" do
348
+ it "parse q-values" do
325
349
  # XXX handle accept-extension
326
- Rack::Utils.q_values("foo;q=0.5,bar,baz;q=0.9").should.equal [
350
+ Rack::Utils.q_values("foo;q=0.5,bar,baz;q=0.9").must_equal [
327
351
  [ 'foo', 0.5 ],
328
352
  [ 'bar', 1.0 ],
329
353
  [ 'baz', 0.9 ]
330
354
  ]
331
355
  end
332
356
 
333
- should "select best quality match" do
334
- Rack::Utils.best_q_match("text/html", %w[text/html]).should.equal "text/html"
357
+ it "select best quality match" do
358
+ Rack::Utils.best_q_match("text/html", %w[text/html]).must_equal "text/html"
335
359
 
336
360
  # More specific matches are preferred
337
- Rack::Utils.best_q_match("text/*;q=0.5,text/html;q=1.0", %w[text/html]).should.equal "text/html"
361
+ Rack::Utils.best_q_match("text/*;q=0.5,text/html;q=1.0", %w[text/html]).must_equal "text/html"
338
362
 
339
363
  # Higher quality matches are preferred
340
- Rack::Utils.best_q_match("text/*;q=0.5,text/plain;q=1.0", %w[text/plain text/html]).should.equal "text/plain"
364
+ Rack::Utils.best_q_match("text/*;q=0.5,text/plain;q=1.0", %w[text/plain text/html]).must_equal "text/plain"
341
365
 
342
366
  # Respect requested content type
343
- Rack::Utils.best_q_match("application/json", %w[application/vnd.lotus-1-2-3 application/json]).should.equal "application/json"
367
+ Rack::Utils.best_q_match("application/json", %w[application/vnd.lotus-1-2-3 application/json]).must_equal "application/json"
344
368
 
345
369
  # All else equal, the available mimes are preferred in order
346
- Rack::Utils.best_q_match("text/*", %w[text/html text/plain]).should.equal "text/html"
347
- Rack::Utils.best_q_match("text/plain,text/html", %w[text/html text/plain]).should.equal "text/html"
370
+ Rack::Utils.best_q_match("text/*", %w[text/html text/plain]).must_equal "text/html"
371
+ Rack::Utils.best_q_match("text/plain,text/html", %w[text/html text/plain]).must_equal "text/html"
348
372
 
349
373
  # When there are no matches, return nil:
350
- Rack::Utils.best_q_match("application/json", %w[text/html text/plain]).should.equal nil
374
+ Rack::Utils.best_q_match("application/json", %w[text/html text/plain]).must_equal nil
351
375
  end
352
376
 
353
- should "escape html entities [&><'\"/]" do
354
- Rack::Utils.escape_html("foo").should.equal "foo"
355
- Rack::Utils.escape_html("f&o").should.equal "f&amp;o"
356
- Rack::Utils.escape_html("f<o").should.equal "f&lt;o"
357
- Rack::Utils.escape_html("f>o").should.equal "f&gt;o"
358
- Rack::Utils.escape_html("f'o").should.equal "f&#x27;o"
359
- Rack::Utils.escape_html('f"o').should.equal "f&quot;o"
360
- Rack::Utils.escape_html("f/o").should.equal "f&#x2F;o"
361
- Rack::Utils.escape_html("<foo></foo>").should.equal "&lt;foo&gt;&lt;&#x2F;foo&gt;"
377
+ it "escape html entities [&><'\"/]" do
378
+ Rack::Utils.escape_html("foo").must_equal "foo"
379
+ Rack::Utils.escape_html("f&o").must_equal "f&amp;o"
380
+ Rack::Utils.escape_html("f<o").must_equal "f&lt;o"
381
+ Rack::Utils.escape_html("f>o").must_equal "f&gt;o"
382
+ Rack::Utils.escape_html("f'o").must_equal "f&#x27;o"
383
+ Rack::Utils.escape_html('f"o').must_equal "f&quot;o"
384
+ Rack::Utils.escape_html("f/o").must_equal "f&#x2F;o"
385
+ Rack::Utils.escape_html("<foo></foo>").must_equal "&lt;foo&gt;&lt;&#x2F;foo&gt;"
362
386
  end
363
387
 
364
- should "escape html entities even on MRI when it's bugged" do
388
+ it "escape html entities even on MRI when it's bugged" do
365
389
  test_escape = lambda do
366
- kcodeu do
367
- Rack::Utils.escape_html("\300<").should.equal "\300&lt;"
368
- end
390
+ Rack::Utils.escape_html("\300<").must_equal "\300&lt;"
369
391
  end
370
392
 
371
- if RUBY_VERSION.to_f < 1.9
372
- test_escape.call
373
- else
374
- test_escape.should.raise(ArgumentError)
375
- end
393
+ test_escape.must_raise ArgumentError
376
394
  end
377
395
 
378
- if "".respond_to?(:encode)
379
- should "escape html entities in unicode strings" do
396
+ it "escape html entities in unicode strings" do
380
397
  # the following will cause warnings if the regex is poorly encoded:
381
- Rack::Utils.escape_html("☃").should.equal "☃"
382
- end
398
+ Rack::Utils.escape_html("☃").must_equal "☃"
383
399
  end
384
400
 
385
- should "figure out which encodings are acceptable" do
401
+ it "figure out which encodings are acceptable" do
386
402
  helper = lambda do |a, b|
387
403
  Rack::Request.new(Rack::MockRequest.env_for("", "HTTP_ACCEPT_ENCODING" => a))
388
404
  Rack::Utils.select_best_encoding(a, b)
389
405
  end
390
406
 
391
- helper.call(%w(), [["x", 1]]).should.equal(nil)
392
- helper.call(%w(identity), [["identity", 0.0]]).should.equal(nil)
393
- helper.call(%w(identity), [["*", 0.0]]).should.equal(nil)
407
+ helper.call(%w(), [["x", 1]]).must_equal nil
408
+ helper.call(%w(identity), [["identity", 0.0]]).must_equal nil
409
+ helper.call(%w(identity), [["*", 0.0]]).must_equal nil
394
410
 
395
- helper.call(%w(identity), [["compress", 1.0], ["gzip", 1.0]]).should.equal("identity")
411
+ helper.call(%w(identity), [["compress", 1.0], ["gzip", 1.0]]).must_equal "identity"
396
412
 
397
- helper.call(%w(compress gzip identity), [["compress", 1.0], ["gzip", 1.0]]).should.equal("compress")
398
- helper.call(%w(compress gzip identity), [["compress", 0.5], ["gzip", 1.0]]).should.equal("gzip")
413
+ helper.call(%w(compress gzip identity), [["compress", 1.0], ["gzip", 1.0]]).must_equal "compress"
414
+ helper.call(%w(compress gzip identity), [["compress", 0.5], ["gzip", 1.0]]).must_equal "gzip"
399
415
 
400
- helper.call(%w(foo bar identity), []).should.equal("identity")
401
- helper.call(%w(foo bar identity), [["*", 1.0]]).should.equal("foo")
402
- helper.call(%w(foo bar identity), [["*", 1.0], ["foo", 0.9]]).should.equal("bar")
416
+ helper.call(%w(foo bar identity), []).must_equal "identity"
417
+ helper.call(%w(foo bar identity), [["*", 1.0]]).must_equal "foo"
418
+ helper.call(%w(foo bar identity), [["*", 1.0], ["foo", 0.9]]).must_equal "bar"
403
419
 
404
- helper.call(%w(foo bar identity), [["foo", 0], ["bar", 0]]).should.equal("identity")
405
- helper.call(%w(foo bar baz identity), [["*", 0], ["identity", 0.1]]).should.equal("identity")
420
+ helper.call(%w(foo bar identity), [["foo", 0], ["bar", 0]]).must_equal "identity"
421
+ helper.call(%w(foo bar baz identity), [["*", 0], ["identity", 0.1]]).must_equal "identity"
406
422
  end
407
423
 
408
- should "return the bytesize of String" do
409
- Rack::Utils.bytesize("FOO\xE2\x82\xAC").should.equal 6
424
+ it "should perform constant time string comparison" do
425
+ Rack::Utils.secure_compare('a', 'a').must_equal true
426
+ Rack::Utils.secure_compare('a', 'b').must_equal false
410
427
  end
411
428
 
412
- should "should perform constant time string comparison" do
413
- Rack::Utils.secure_compare('a', 'a').should.equal true
414
- Rack::Utils.secure_compare('a', 'b').should.equal false
429
+ it "return status code for integer" do
430
+ Rack::Utils.status_code(200).must_equal 200
415
431
  end
416
432
 
417
- should "return status code for integer" do
418
- Rack::Utils.status_code(200).should.equal 200
433
+ it "return status code for string" do
434
+ Rack::Utils.status_code("200").must_equal 200
419
435
  end
420
436
 
421
- should "return status code for string" do
422
- Rack::Utils.status_code("200").should.equal 200
437
+ it "return status code for symbol" do
438
+ Rack::Utils.status_code(:ok).must_equal 200
423
439
  end
424
440
 
425
- should "return status code for symbol" do
426
- Rack::Utils.status_code(:ok).should.equal 200
441
+ it "return rfc2822 format from rfc2822 helper" do
442
+ Rack::Utils.rfc2822(Time.at(0).gmtime).must_equal "Thu, 01 Jan 1970 00:00:00 -0000"
427
443
  end
428
444
 
429
- should "return rfc2822 format from rfc2822 helper" do
430
- Rack::Utils.rfc2822(Time.at(0).gmtime).should == "Thu, 01 Jan 1970 00:00:00 -0000"
445
+ it "return rfc2109 format from rfc2109 helper" do
446
+ Rack::Utils.rfc2109(Time.at(0).gmtime).must_equal "Thu, 01-Jan-1970 00:00:00 GMT"
431
447
  end
432
448
 
433
- should "return rfc2109 format from rfc2109 helper" do
434
- Rack::Utils.rfc2109(Time.at(0).gmtime).should == "Thu, 01-Jan-1970 00:00:00 GMT"
449
+ it "clean directory traversal" do
450
+ Rack::Utils.clean_path_info("/cgi/../cgi/test").must_equal "/cgi/test"
451
+ Rack::Utils.clean_path_info(".").must_be_empty
452
+ Rack::Utils.clean_path_info("test/..").must_be_empty
435
453
  end
436
454
 
437
- should "clean directory traversal" do
438
- Rack::Utils.clean_path_info("/cgi/../cgi/test").should.equal "/cgi/test"
439
- Rack::Utils.clean_path_info(".").should.empty
440
- Rack::Utils.clean_path_info("test/..").should.empty
455
+ it "clean unsafe directory traversal to safe path" do
456
+ Rack::Utils.clean_path_info("/../README.rdoc").must_equal "/README.rdoc"
457
+ Rack::Utils.clean_path_info("../test/spec_utils.rb").must_equal "test/spec_utils.rb"
441
458
  end
442
459
 
443
- should "clean unsafe directory traversal to safe path" do
444
- Rack::Utils.clean_path_info("/../README.rdoc").should.equal "/README.rdoc"
445
- Rack::Utils.clean_path_info("../test/spec_utils.rb").should.equal "test/spec_utils.rb"
460
+ it "not clean directory traversal with encoded periods" do
461
+ Rack::Utils.clean_path_info("/%2E%2E/README").must_equal "/%2E%2E/README"
462
+ end
463
+
464
+ it "clean slash only paths" do
465
+ Rack::Utils.clean_path_info("/").must_equal "/"
466
+ end
467
+ end
468
+
469
+ describe Rack::Utils, "cookies" do
470
+ it "parses cookies" do
471
+ env = Rack::MockRequest.env_for("", "HTTP_COOKIE" => "zoo=m")
472
+ Rack::Utils.parse_cookies(env).must_equal({"zoo" => "m"})
473
+
474
+ env = Rack::MockRequest.env_for("", "HTTP_COOKIE" => "foo=%")
475
+ Rack::Utils.parse_cookies(env).must_equal({"foo" => "%"})
476
+
477
+ env = Rack::MockRequest.env_for("", "HTTP_COOKIE" => "foo=bar;foo=car")
478
+ Rack::Utils.parse_cookies(env).must_equal({"foo" => "bar"})
479
+
480
+ env = Rack::MockRequest.env_for("", "HTTP_COOKIE" => "foo=bar;quux=h&m")
481
+ Rack::Utils.parse_cookies(env).must_equal({"foo" => "bar", "quux" => "h&m"})
482
+
483
+ env = Rack::MockRequest.env_for("", "HTTP_COOKIE" => "foo=bar").freeze
484
+ Rack::Utils.parse_cookies(env).must_equal({"foo" => "bar"})
446
485
  end
447
486
 
448
- should "not clean directory traversal with encoded periods" do
449
- Rack::Utils.clean_path_info("/%2E%2E/README").should.equal "/%2E%2E/README"
487
+ it "adds new cookies to nil header" do
488
+ Rack::Utils.add_cookie_to_header(nil, 'name', 'value').must_equal 'name=value'
450
489
  end
451
490
 
452
- should "clean slash only paths" do
453
- Rack::Utils.clean_path_info("/").should.equal "/"
491
+ it "adds new cookies to blank header" do
492
+ header = ''
493
+ Rack::Utils.add_cookie_to_header(header, 'name', 'value').must_equal 'name=value'
494
+ header.must_equal ''
495
+ end
496
+
497
+ it "adds new cookies to string header" do
498
+ header = 'existing-cookie'
499
+ Rack::Utils.add_cookie_to_header(header, 'name', 'value').must_equal "existing-cookie\nname=value"
500
+ header.must_equal 'existing-cookie'
501
+ end
502
+
503
+ it "adds new cookies to array header" do
504
+ header = %w[ existing-cookie ]
505
+ Rack::Utils.add_cookie_to_header(header, 'name', 'value').must_equal "existing-cookie\nname=value"
506
+ header.must_equal %w[ existing-cookie ]
507
+ end
508
+
509
+ it "adds new cookies to an unrecognized header" do
510
+ lambda {
511
+ Rack::Utils.add_cookie_to_header(Object.new, 'name', 'value')
512
+ }.must_raise ArgumentError
454
513
  end
455
514
  end
456
515
 
457
516
  describe Rack::Utils, "byte_range" do
458
- should "ignore missing or syntactically invalid byte ranges" do
459
- Rack::Utils.byte_ranges({},500).should.equal nil
460
- Rack::Utils.byte_ranges({"HTTP_RANGE" => "foobar"},500).should.equal nil
461
- Rack::Utils.byte_ranges({"HTTP_RANGE" => "furlongs=123-456"},500).should.equal nil
462
- Rack::Utils.byte_ranges({"HTTP_RANGE" => "bytes="},500).should.equal nil
463
- Rack::Utils.byte_ranges({"HTTP_RANGE" => "bytes=-"},500).should.equal nil
464
- Rack::Utils.byte_ranges({"HTTP_RANGE" => "bytes=123,456"},500).should.equal nil
517
+ it "ignore missing or syntactically invalid byte ranges" do
518
+ Rack::Utils.byte_ranges({},500).must_equal nil
519
+ Rack::Utils.byte_ranges({"HTTP_RANGE" => "foobar"},500).must_equal nil
520
+ Rack::Utils.byte_ranges({"HTTP_RANGE" => "furlongs=123-456"},500).must_equal nil
521
+ Rack::Utils.byte_ranges({"HTTP_RANGE" => "bytes="},500).must_equal nil
522
+ Rack::Utils.byte_ranges({"HTTP_RANGE" => "bytes=-"},500).must_equal nil
523
+ Rack::Utils.byte_ranges({"HTTP_RANGE" => "bytes=123,456"},500).must_equal nil
465
524
  # A range of non-positive length is syntactically invalid and ignored:
466
- Rack::Utils.byte_ranges({"HTTP_RANGE" => "bytes=456-123"},500).should.equal nil
467
- Rack::Utils.byte_ranges({"HTTP_RANGE" => "bytes=456-455"},500).should.equal nil
525
+ Rack::Utils.byte_ranges({"HTTP_RANGE" => "bytes=456-123"},500).must_equal nil
526
+ Rack::Utils.byte_ranges({"HTTP_RANGE" => "bytes=456-455"},500).must_equal nil
468
527
  end
469
528
 
470
- should "parse simple byte ranges" do
471
- Rack::Utils.byte_ranges({"HTTP_RANGE" => "bytes=123-456"},500).should.equal [(123..456)]
472
- Rack::Utils.byte_ranges({"HTTP_RANGE" => "bytes=123-"},500).should.equal [(123..499)]
473
- Rack::Utils.byte_ranges({"HTTP_RANGE" => "bytes=-100"},500).should.equal [(400..499)]
474
- Rack::Utils.byte_ranges({"HTTP_RANGE" => "bytes=0-0"},500).should.equal [(0..0)]
475
- Rack::Utils.byte_ranges({"HTTP_RANGE" => "bytes=499-499"},500).should.equal [(499..499)]
529
+ it "parse simple byte ranges" do
530
+ Rack::Utils.byte_ranges({"HTTP_RANGE" => "bytes=123-456"},500).must_equal [(123..456)]
531
+ Rack::Utils.byte_ranges({"HTTP_RANGE" => "bytes=123-"},500).must_equal [(123..499)]
532
+ Rack::Utils.byte_ranges({"HTTP_RANGE" => "bytes=-100"},500).must_equal [(400..499)]
533
+ Rack::Utils.byte_ranges({"HTTP_RANGE" => "bytes=0-0"},500).must_equal [(0..0)]
534
+ Rack::Utils.byte_ranges({"HTTP_RANGE" => "bytes=499-499"},500).must_equal [(499..499)]
476
535
  end
477
536
 
478
- should "parse several byte ranges" do
479
- Rack::Utils.byte_ranges({"HTTP_RANGE" => "bytes=500-600,601-999"},1000).should.equal [(500..600),(601..999)]
537
+ it "parse several byte ranges" do
538
+ Rack::Utils.byte_ranges({"HTTP_RANGE" => "bytes=500-600,601-999"},1000).must_equal [(500..600),(601..999)]
480
539
  end
481
540
 
482
- should "truncate byte ranges" do
483
- Rack::Utils.byte_ranges({"HTTP_RANGE" => "bytes=123-999"},500).should.equal [(123..499)]
484
- Rack::Utils.byte_ranges({"HTTP_RANGE" => "bytes=600-999"},500).should.equal []
485
- Rack::Utils.byte_ranges({"HTTP_RANGE" => "bytes=-999"},500).should.equal [(0..499)]
541
+ it "truncate byte ranges" do
542
+ Rack::Utils.byte_ranges({"HTTP_RANGE" => "bytes=123-999"},500).must_equal [(123..499)]
543
+ Rack::Utils.byte_ranges({"HTTP_RANGE" => "bytes=600-999"},500).must_equal []
544
+ Rack::Utils.byte_ranges({"HTTP_RANGE" => "bytes=-999"},500).must_equal [(0..499)]
486
545
  end
487
546
 
488
- should "ignore unsatisfiable byte ranges" do
489
- Rack::Utils.byte_ranges({"HTTP_RANGE" => "bytes=500-501"},500).should.equal []
490
- Rack::Utils.byte_ranges({"HTTP_RANGE" => "bytes=500-"},500).should.equal []
491
- Rack::Utils.byte_ranges({"HTTP_RANGE" => "bytes=999-"},500).should.equal []
492
- Rack::Utils.byte_ranges({"HTTP_RANGE" => "bytes=-0"},500).should.equal []
547
+ it "ignore unsatisfiable byte ranges" do
548
+ Rack::Utils.byte_ranges({"HTTP_RANGE" => "bytes=500-501"},500).must_equal []
549
+ Rack::Utils.byte_ranges({"HTTP_RANGE" => "bytes=500-"},500).must_equal []
550
+ Rack::Utils.byte_ranges({"HTTP_RANGE" => "bytes=999-"},500).must_equal []
551
+ Rack::Utils.byte_ranges({"HTTP_RANGE" => "bytes=-0"},500).must_equal []
493
552
  end
494
553
 
495
- should "handle byte ranges of empty files" do
496
- Rack::Utils.byte_ranges({"HTTP_RANGE" => "bytes=123-456"},0).should.equal []
497
- Rack::Utils.byte_ranges({"HTTP_RANGE" => "bytes=0-"},0).should.equal []
498
- Rack::Utils.byte_ranges({"HTTP_RANGE" => "bytes=-100"},0).should.equal []
499
- Rack::Utils.byte_ranges({"HTTP_RANGE" => "bytes=0-0"},0).should.equal []
500
- Rack::Utils.byte_ranges({"HTTP_RANGE" => "bytes=-0"},0).should.equal []
554
+ it "handle byte ranges of empty files" do
555
+ Rack::Utils.byte_ranges({"HTTP_RANGE" => "bytes=123-456"},0).must_equal []
556
+ Rack::Utils.byte_ranges({"HTTP_RANGE" => "bytes=0-"},0).must_equal []
557
+ Rack::Utils.byte_ranges({"HTTP_RANGE" => "bytes=-100"},0).must_equal []
558
+ Rack::Utils.byte_ranges({"HTTP_RANGE" => "bytes=0-0"},0).must_equal []
559
+ Rack::Utils.byte_ranges({"HTTP_RANGE" => "bytes=-0"},0).must_equal []
501
560
  end
502
561
  end
503
562
 
504
563
  describe Rack::Utils::HeaderHash do
505
- should "retain header case" do
564
+ it "retain header case" do
506
565
  h = Rack::Utils::HeaderHash.new("Content-MD5" => "d5ff4e2a0 ...")
507
566
  h['ETag'] = 'Boo!'
508
- h.to_hash.should.equal "Content-MD5" => "d5ff4e2a0 ...", "ETag" => 'Boo!'
567
+ h.to_hash.must_equal "Content-MD5" => "d5ff4e2a0 ...", "ETag" => 'Boo!'
509
568
  end
510
569
 
511
- should "check existence of keys case insensitively" do
570
+ it "check existence of keys case insensitively" do
512
571
  h = Rack::Utils::HeaderHash.new("Content-MD5" => "d5ff4e2a0 ...")
513
- h.should.include 'content-md5'
514
- h.should.not.include 'ETag'
572
+ h.must_include 'content-md5'
573
+ h.wont_include 'ETag'
574
+ end
575
+
576
+ it "create deep HeaderHash copy on dup" do
577
+ h1 = Rack::Utils::HeaderHash.new("Content-MD5" => "d5ff4e2a0 ...")
578
+ h2 = h1.dup
579
+
580
+ h1.must_include 'content-md5'
581
+ h2.must_include 'content-md5'
582
+
583
+ h2.delete("Content-MD5")
584
+
585
+ h2.wont_include 'content-md5'
586
+ h1.must_include 'content-md5'
515
587
  end
516
588
 
517
- should "merge case-insensitively" do
589
+ it "merge case-insensitively" do
518
590
  h = Rack::Utils::HeaderHash.new("ETag" => 'HELLO', "content-length" => '123')
519
591
  merged = h.merge("Etag" => 'WORLD', 'Content-Length' => '321', "Foo" => 'BAR')
520
- merged.should.equal "Etag"=>'WORLD', "Content-Length"=>'321', "Foo"=>'BAR'
592
+ merged.must_equal "Etag"=>'WORLD', "Content-Length"=>'321', "Foo"=>'BAR'
521
593
  end
522
594
 
523
- should "overwrite case insensitively and assume the new key's case" do
595
+ it "overwrite case insensitively and assume the new key's case" do
524
596
  h = Rack::Utils::HeaderHash.new("Foo-Bar" => "baz")
525
597
  h["foo-bar"] = "bizzle"
526
- h["FOO-BAR"].should.equal "bizzle"
527
- h.length.should.equal 1
528
- h.to_hash.should.equal "foo-bar" => "bizzle"
598
+ h["FOO-BAR"].must_equal "bizzle"
599
+ h.length.must_equal 1
600
+ h.to_hash.must_equal "foo-bar" => "bizzle"
529
601
  end
530
602
 
531
- should "be converted to real Hash" do
603
+ it "be converted to real Hash" do
532
604
  h = Rack::Utils::HeaderHash.new("foo" => "bar")
533
- h.to_hash.should.be.instance_of Hash
605
+ h.to_hash.must_be_instance_of Hash
534
606
  end
535
607
 
536
- should "convert Array values to Strings when converting to Hash" do
608
+ it "convert Array values to Strings when converting to Hash" do
537
609
  h = Rack::Utils::HeaderHash.new("foo" => ["bar", "baz"])
538
- h.to_hash.should.equal({ "foo" => "bar\nbaz" })
610
+ h.to_hash.must_equal({ "foo" => "bar\nbaz" })
539
611
  end
540
612
 
541
- should "replace hashes correctly" do
613
+ it "replace hashes correctly" do
542
614
  h = Rack::Utils::HeaderHash.new("Foo-Bar" => "baz")
543
615
  j = {"foo" => "bar"}
544
616
  h.replace(j)
545
- h["foo"].should.equal "bar"
617
+ h["foo"].must_equal "bar"
546
618
  end
547
619
 
548
- should "be able to delete the given key case-sensitively" do
620
+ it "be able to delete the given key case-sensitively" do
549
621
  h = Rack::Utils::HeaderHash.new("foo" => "bar")
550
622
  h.delete("foo")
551
- h["foo"].should.be.nil
552
- h["FOO"].should.be.nil
623
+ h["foo"].must_be_nil
624
+ h["FOO"].must_be_nil
553
625
  end
554
626
 
555
- should "be able to delete the given key case-insensitively" do
627
+ it "be able to delete the given key case-insensitively" do
556
628
  h = Rack::Utils::HeaderHash.new("foo" => "bar")
557
629
  h.delete("FOO")
558
- h["foo"].should.be.nil
559
- h["FOO"].should.be.nil
630
+ h["foo"].must_be_nil
631
+ h["FOO"].must_be_nil
560
632
  end
561
633
 
562
- should "return the deleted value when #delete is called on an existing key" do
634
+ it "return the deleted value when #delete is called on an existing key" do
563
635
  h = Rack::Utils::HeaderHash.new("foo" => "bar")
564
- h.delete("Foo").should.equal("bar")
636
+ h.delete("Foo").must_equal "bar"
565
637
  end
566
638
 
567
- should "return nil when #delete is called on a non-existant key" do
639
+ it "return nil when #delete is called on a non-existant key" do
568
640
  h = Rack::Utils::HeaderHash.new("foo" => "bar")
569
- h.delete("Hello").should.be.nil
641
+ h.delete("Hello").must_be_nil
570
642
  end
571
643
 
572
- should "avoid unnecessary object creation if possible" do
644
+ it "avoid unnecessary object creation if possible" do
573
645
  a = Rack::Utils::HeaderHash.new("foo" => "bar")
574
646
  b = Rack::Utils::HeaderHash.new(a)
575
- b.object_id.should.equal(a.object_id)
576
- b.should.equal(a)
647
+ b.object_id.must_equal a.object_id
648
+ b.must_equal a
577
649
  end
578
650
 
579
- should "convert Array values to Strings when responding to #each" do
651
+ it "convert Array values to Strings when responding to #each" do
580
652
  h = Rack::Utils::HeaderHash.new("foo" => ["bar", "baz"])
581
653
  h.each do |k,v|
582
- k.should.equal("foo")
583
- v.should.equal("bar\nbaz")
654
+ k.must_equal "foo"
655
+ v.must_equal "bar\nbaz"
584
656
  end
585
657
  end
586
658
 
587
- should "not create headers out of thin air" do
659
+ it "not create headers out of thin air" do
588
660
  h = Rack::Utils::HeaderHash.new
589
661
  h['foo']
590
- h['foo'].should.be.nil
591
- h.should.not.include 'foo'
662
+ h['foo'].must_be_nil
663
+ h.wont_include 'foo'
592
664
  end
593
665
  end
594
666
 
@@ -605,27 +677,27 @@ describe Rack::Utils::Context do
605
677
  test_target4 = proc{|e| [200,{'Content-Type'=>'text/plain', 'Content-Length'=>'0'},['']] }
606
678
  test_app = ContextTest.new test_target4
607
679
 
608
- should "set context correctly" do
609
- test_app.app.should.equal test_target4
680
+ it "set context correctly" do
681
+ test_app.app.must_equal test_target4
610
682
  c1 = Rack::Utils::Context.new(test_app, test_target1)
611
- c1.for.should.equal test_app
612
- c1.app.should.equal test_target1
683
+ c1.for.must_equal test_app
684
+ c1.app.must_equal test_target1
613
685
  c2 = Rack::Utils::Context.new(test_app, test_target2)
614
- c2.for.should.equal test_app
615
- c2.app.should.equal test_target2
686
+ c2.for.must_equal test_app
687
+ c2.app.must_equal test_target2
616
688
  end
617
689
 
618
- should "alter app on recontexting" do
690
+ it "alter app on recontexting" do
619
691
  c1 = Rack::Utils::Context.new(test_app, test_target1)
620
692
  c2 = c1.recontext(test_target2)
621
- c2.for.should.equal test_app
622
- c2.app.should.equal test_target2
693
+ c2.for.must_equal test_app
694
+ c2.app.must_equal test_target2
623
695
  c3 = c2.recontext(test_target3)
624
- c3.for.should.equal test_app
625
- c3.app.should.equal test_target3
696
+ c3.for.must_equal test_app
697
+ c3.app.must_equal test_target3
626
698
  end
627
699
 
628
- should "run different apps" do
700
+ it "run different apps" do
629
701
  c1 = Rack::Utils::Context.new test_app, test_target1
630
702
  c2 = c1.recontext test_target2
631
703
  c3 = c2.recontext test_target3
@@ -633,15 +705,15 @@ describe Rack::Utils::Context do
633
705
  a4 = Rack::Lint.new c4
634
706
  a5 = Rack::Lint.new test_app
635
707
  r1 = c1.call('hello')
636
- r1.should.equal 'hello world'
708
+ r1.must_equal 'hello world'
637
709
  r2 = c2.call(2)
638
- r2.should.equal 4
710
+ r2.must_equal 4
639
711
  r3 = c3.call(:misc_symbol)
640
- r3.should.be.nil
712
+ r3.must_be_nil
641
713
  r4 = Rack::MockRequest.new(a4).get('/')
642
- r4.status.should.equal 200
714
+ r4.status.must_equal 200
643
715
  r5 = Rack::MockRequest.new(a5).get('/')
644
- r5.status.should.equal 200
645
- r4.body.should.equal r5.body
716
+ r5.status.must_equal 200
717
+ r4.body.must_equal r5.body
646
718
  end
647
719
  end