eac-rack 1.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (111) hide show
  1. data/COPYING +18 -0
  2. data/KNOWN-ISSUES +21 -0
  3. data/README +399 -0
  4. data/bin/rackup +4 -0
  5. data/contrib/rack_logo.svg +111 -0
  6. data/example/lobster.ru +4 -0
  7. data/example/protectedlobster.rb +14 -0
  8. data/example/protectedlobster.ru +8 -0
  9. data/lib/rack.rb +92 -0
  10. data/lib/rack/adapter/camping.rb +22 -0
  11. data/lib/rack/auth/abstract/handler.rb +37 -0
  12. data/lib/rack/auth/abstract/request.rb +37 -0
  13. data/lib/rack/auth/basic.rb +58 -0
  14. data/lib/rack/auth/digest/md5.rb +124 -0
  15. data/lib/rack/auth/digest/nonce.rb +51 -0
  16. data/lib/rack/auth/digest/params.rb +55 -0
  17. data/lib/rack/auth/digest/request.rb +40 -0
  18. data/lib/rack/builder.rb +80 -0
  19. data/lib/rack/cascade.rb +41 -0
  20. data/lib/rack/chunked.rb +49 -0
  21. data/lib/rack/commonlogger.rb +49 -0
  22. data/lib/rack/conditionalget.rb +47 -0
  23. data/lib/rack/config.rb +15 -0
  24. data/lib/rack/content_length.rb +29 -0
  25. data/lib/rack/content_type.rb +23 -0
  26. data/lib/rack/deflater.rb +96 -0
  27. data/lib/rack/directory.rb +157 -0
  28. data/lib/rack/etag.rb +23 -0
  29. data/lib/rack/file.rb +90 -0
  30. data/lib/rack/handler.rb +88 -0
  31. data/lib/rack/handler/cgi.rb +61 -0
  32. data/lib/rack/handler/evented_mongrel.rb +8 -0
  33. data/lib/rack/handler/fastcgi.rb +89 -0
  34. data/lib/rack/handler/lsws.rb +63 -0
  35. data/lib/rack/handler/mongrel.rb +90 -0
  36. data/lib/rack/handler/scgi.rb +62 -0
  37. data/lib/rack/handler/swiftiplied_mongrel.rb +8 -0
  38. data/lib/rack/handler/thin.rb +18 -0
  39. data/lib/rack/handler/webrick.rb +69 -0
  40. data/lib/rack/head.rb +19 -0
  41. data/lib/rack/lint.rb +575 -0
  42. data/lib/rack/lobster.rb +65 -0
  43. data/lib/rack/lock.rb +16 -0
  44. data/lib/rack/logger.rb +20 -0
  45. data/lib/rack/methodoverride.rb +27 -0
  46. data/lib/rack/mime.rb +206 -0
  47. data/lib/rack/mock.rb +189 -0
  48. data/lib/rack/nulllogger.rb +18 -0
  49. data/lib/rack/recursive.rb +57 -0
  50. data/lib/rack/reloader.rb +109 -0
  51. data/lib/rack/request.rb +271 -0
  52. data/lib/rack/response.rb +149 -0
  53. data/lib/rack/rewindable_input.rb +100 -0
  54. data/lib/rack/runtime.rb +27 -0
  55. data/lib/rack/sendfile.rb +142 -0
  56. data/lib/rack/server.rb +212 -0
  57. data/lib/rack/session/abstract/id.rb +140 -0
  58. data/lib/rack/session/cookie.rb +90 -0
  59. data/lib/rack/session/memcache.rb +119 -0
  60. data/lib/rack/session/pool.rb +100 -0
  61. data/lib/rack/showexceptions.rb +349 -0
  62. data/lib/rack/showstatus.rb +106 -0
  63. data/lib/rack/static.rb +38 -0
  64. data/lib/rack/urlmap.rb +56 -0
  65. data/lib/rack/utils.rb +614 -0
  66. data/rack.gemspec +38 -0
  67. data/test/spec_rack_auth_basic.rb +73 -0
  68. data/test/spec_rack_auth_digest.rb +226 -0
  69. data/test/spec_rack_builder.rb +84 -0
  70. data/test/spec_rack_camping.rb +51 -0
  71. data/test/spec_rack_cascade.rb +48 -0
  72. data/test/spec_rack_cgi.rb +89 -0
  73. data/test/spec_rack_chunked.rb +62 -0
  74. data/test/spec_rack_commonlogger.rb +61 -0
  75. data/test/spec_rack_conditionalget.rb +41 -0
  76. data/test/spec_rack_config.rb +24 -0
  77. data/test/spec_rack_content_length.rb +43 -0
  78. data/test/spec_rack_content_type.rb +30 -0
  79. data/test/spec_rack_deflater.rb +127 -0
  80. data/test/spec_rack_directory.rb +61 -0
  81. data/test/spec_rack_etag.rb +17 -0
  82. data/test/spec_rack_fastcgi.rb +89 -0
  83. data/test/spec_rack_file.rb +75 -0
  84. data/test/spec_rack_handler.rb +43 -0
  85. data/test/spec_rack_head.rb +30 -0
  86. data/test/spec_rack_lint.rb +528 -0
  87. data/test/spec_rack_lobster.rb +45 -0
  88. data/test/spec_rack_lock.rb +38 -0
  89. data/test/spec_rack_logger.rb +21 -0
  90. data/test/spec_rack_methodoverride.rb +60 -0
  91. data/test/spec_rack_mock.rb +243 -0
  92. data/test/spec_rack_mongrel.rb +189 -0
  93. data/test/spec_rack_nulllogger.rb +13 -0
  94. data/test/spec_rack_recursive.rb +77 -0
  95. data/test/spec_rack_request.rb +545 -0
  96. data/test/spec_rack_response.rb +221 -0
  97. data/test/spec_rack_rewindable_input.rb +118 -0
  98. data/test/spec_rack_runtime.rb +35 -0
  99. data/test/spec_rack_sendfile.rb +86 -0
  100. data/test/spec_rack_session_cookie.rb +73 -0
  101. data/test/spec_rack_session_memcache.rb +273 -0
  102. data/test/spec_rack_session_pool.rb +172 -0
  103. data/test/spec_rack_showexceptions.rb +21 -0
  104. data/test/spec_rack_showstatus.rb +72 -0
  105. data/test/spec_rack_static.rb +37 -0
  106. data/test/spec_rack_thin.rb +91 -0
  107. data/test/spec_rack_urlmap.rb +215 -0
  108. data/test/spec_rack_utils.rb +554 -0
  109. data/test/spec_rack_webrick.rb +130 -0
  110. data/test/spec_rackup.rb +154 -0
  111. metadata +311 -0
@@ -0,0 +1,73 @@
1
+ require 'test/spec'
2
+
3
+ require 'rack/session/cookie'
4
+ require 'rack/mock'
5
+ require 'rack/response'
6
+
7
+ context "Rack::Session::Cookie" do
8
+ incrementor = lambda { |env|
9
+ env["rack.session"]["counter"] ||= 0
10
+ env["rack.session"]["counter"] += 1
11
+ Rack::Response.new(env["rack.session"].inspect).to_a
12
+ }
13
+
14
+ specify "creates a new cookie" do
15
+ res = Rack::MockRequest.new(Rack::Session::Cookie.new(incrementor)).get("/")
16
+ res["Set-Cookie"].should.match("rack.session=")
17
+ res.body.should.equal '{"counter"=>1}'
18
+ end
19
+
20
+ specify "loads from a cookie" do
21
+ res = Rack::MockRequest.new(Rack::Session::Cookie.new(incrementor)).get("/")
22
+ cookie = res["Set-Cookie"]
23
+ res = Rack::MockRequest.new(Rack::Session::Cookie.new(incrementor)).
24
+ get("/", "HTTP_COOKIE" => cookie)
25
+ res.body.should.equal '{"counter"=>2}'
26
+ cookie = res["Set-Cookie"]
27
+ res = Rack::MockRequest.new(Rack::Session::Cookie.new(incrementor)).
28
+ get("/", "HTTP_COOKIE" => cookie)
29
+ res.body.should.equal '{"counter"=>3}'
30
+ end
31
+
32
+ specify "survives broken cookies" do
33
+ res = Rack::MockRequest.new(Rack::Session::Cookie.new(incrementor)).
34
+ get("/", "HTTP_COOKIE" => "rack.session=blarghfasel")
35
+ res.body.should.equal '{"counter"=>1}'
36
+ end
37
+
38
+ bigcookie = lambda { |env|
39
+ env["rack.session"]["cookie"] = "big" * 3000
40
+ Rack::Response.new(env["rack.session"].inspect).to_a
41
+ }
42
+
43
+ specify "barks on too big cookies" do
44
+ lambda {
45
+ Rack::MockRequest.new(Rack::Session::Cookie.new(bigcookie)).
46
+ get("/", :fatal => true)
47
+ }.should.raise(Rack::MockRequest::FatalWarning)
48
+ end
49
+
50
+ specify "loads from a cookie wih integrity hash" do
51
+ res = Rack::MockRequest.new(Rack::Session::Cookie.new(incrementor, :secret => 'test')).get("/")
52
+ cookie = res["Set-Cookie"]
53
+ res = Rack::MockRequest.new(Rack::Session::Cookie.new(incrementor, :secret => 'test')).
54
+ get("/", "HTTP_COOKIE" => cookie)
55
+ res.body.should.equal '{"counter"=>2}'
56
+ cookie = res["Set-Cookie"]
57
+ res = Rack::MockRequest.new(Rack::Session::Cookie.new(incrementor, :secret => 'test')).
58
+ get("/", "HTTP_COOKIE" => cookie)
59
+ res.body.should.equal '{"counter"=>3}'
60
+ end
61
+
62
+ specify "ignores tampered with session cookies" do
63
+ app = Rack::Session::Cookie.new(incrementor, :secret => 'test')
64
+ response1 = Rack::MockRequest.new(app).get("/")
65
+ _, digest = response1["Set-Cookie"].split("--")
66
+ tampered_with_cookie = "hackerman-was-here" + "--" + digest
67
+ response2 = Rack::MockRequest.new(app).get("/", "HTTP_COOKIE" =>
68
+ tampered_with_cookie)
69
+
70
+ # The tampered-with cookie is ignored, so we get back an identical Set-Cookie
71
+ response2["Set-Cookie"].should.equal(response1["Set-Cookie"])
72
+ end
73
+ end
@@ -0,0 +1,273 @@
1
+ require 'test/spec'
2
+
3
+ begin
4
+ require 'rack/session/memcache'
5
+ require 'rack/mock'
6
+ require 'rack/response'
7
+ require 'thread'
8
+
9
+ context "Rack::Session::Memcache" do
10
+ session_key = Rack::Session::Memcache::DEFAULT_OPTIONS[:key]
11
+ session_match = /#{session_key}=([0-9a-fA-F]+);/
12
+ incrementor = lambda do |env|
13
+ env["rack.session"]["counter"] ||= 0
14
+ env["rack.session"]["counter"] += 1
15
+ Rack::Response.new(env["rack.session"].inspect).to_a
16
+ end
17
+ drop_session = proc do |env|
18
+ env['rack.session.options'][:drop] = true
19
+ incrementor.call(env)
20
+ end
21
+ renew_session = proc do |env|
22
+ env['rack.session.options'][:renew] = true
23
+ incrementor.call(env)
24
+ end
25
+ defer_session = proc do |env|
26
+ env['rack.session.options'][:defer] = true
27
+ incrementor.call(env)
28
+ end
29
+
30
+ specify "faults on no connection" do
31
+ if RUBY_VERSION < "1.9"
32
+ lambda do
33
+ Rack::Session::Memcache.new incrementor, :memcache_server => 'nosuchserver'
34
+ end.should.raise
35
+ else
36
+ lambda do
37
+ Rack::Session::Memcache.new incrementor, :memcache_server => 'nosuchserver'
38
+ end.should.raise ArgumentError
39
+ end
40
+ end
41
+
42
+ specify "connect to existing server" do
43
+ test_pool = MemCache.new incrementor, :namespace => 'test:rack:session'
44
+ end
45
+
46
+ specify "creates a new cookie" do
47
+ pool = Rack::Session::Memcache.new(incrementor)
48
+ res = Rack::MockRequest.new(pool).get("/")
49
+ res["Set-Cookie"].should.match("#{session_key}=")
50
+ res.body.should.equal '{"counter"=>1}'
51
+ end
52
+
53
+ specify "determines session from a cookie" do
54
+ pool = Rack::Session::Memcache.new(incrementor)
55
+ req = Rack::MockRequest.new(pool)
56
+ res = req.get("/")
57
+ cookie = res["Set-Cookie"]
58
+ req.get("/", "HTTP_COOKIE" => cookie).
59
+ body.should.equal '{"counter"=>2}'
60
+ req.get("/", "HTTP_COOKIE" => cookie).
61
+ body.should.equal '{"counter"=>3}'
62
+ end
63
+
64
+ specify "survives nonexistant cookies" do
65
+ bad_cookie = "rack.session=blarghfasel"
66
+ pool = Rack::Session::Memcache.new(incrementor)
67
+ res = Rack::MockRequest.new(pool).
68
+ get("/", "HTTP_COOKIE" => bad_cookie)
69
+ res.body.should.equal '{"counter"=>1}'
70
+ cookie = res["Set-Cookie"][session_match]
71
+ cookie.should.not.match(/#{bad_cookie}/)
72
+ end
73
+
74
+ specify "maintains freshness" do
75
+ pool = Rack::Session::Memcache.new(incrementor, :expire_after => 3)
76
+ res = Rack::MockRequest.new(pool).get('/')
77
+ res.body.should.include '"counter"=>1'
78
+ cookie = res["Set-Cookie"]
79
+ res = Rack::MockRequest.new(pool).get('/', "HTTP_COOKIE" => cookie)
80
+ res["Set-Cookie"].should.equal cookie
81
+ res.body.should.include '"counter"=>2'
82
+ puts 'Sleeping to expire session' if $DEBUG
83
+ sleep 4
84
+ res = Rack::MockRequest.new(pool).get('/', "HTTP_COOKIE" => cookie)
85
+ res["Set-Cookie"].should.not.equal cookie
86
+ res.body.should.include '"counter"=>1'
87
+ end
88
+
89
+ specify "deletes cookies with :drop option" do
90
+ pool = Rack::Session::Memcache.new(incrementor)
91
+ req = Rack::MockRequest.new(pool)
92
+ drop = Rack::Utils::Context.new(pool, drop_session)
93
+ dreq = Rack::MockRequest.new(drop)
94
+
95
+ res0 = req.get("/")
96
+ session = (cookie = res0["Set-Cookie"])[session_match]
97
+ res0.body.should.equal '{"counter"=>1}'
98
+
99
+ res1 = req.get("/", "HTTP_COOKIE" => cookie)
100
+ res1["Set-Cookie"][session_match].should.equal session
101
+ res1.body.should.equal '{"counter"=>2}'
102
+
103
+ res2 = dreq.get("/", "HTTP_COOKIE" => cookie)
104
+ res2["Set-Cookie"].should.equal nil
105
+ res2.body.should.equal '{"counter"=>3}'
106
+
107
+ res3 = req.get("/", "HTTP_COOKIE" => cookie)
108
+ res3["Set-Cookie"][session_match].should.not.equal session
109
+ res3.body.should.equal '{"counter"=>1}'
110
+ end
111
+
112
+ specify "provides new session id with :renew option" do
113
+ pool = Rack::Session::Memcache.new(incrementor)
114
+ req = Rack::MockRequest.new(pool)
115
+ renew = Rack::Utils::Context.new(pool, renew_session)
116
+ rreq = Rack::MockRequest.new(renew)
117
+
118
+ res0 = req.get("/")
119
+ session = (cookie = res0["Set-Cookie"])[session_match]
120
+ res0.body.should.equal '{"counter"=>1}'
121
+
122
+ res1 = req.get("/", "HTTP_COOKIE" => cookie)
123
+ res1["Set-Cookie"][session_match].should.equal session
124
+ res1.body.should.equal '{"counter"=>2}'
125
+
126
+ res2 = rreq.get("/", "HTTP_COOKIE" => cookie)
127
+ new_cookie = res2["Set-Cookie"]
128
+ new_session = new_cookie[session_match]
129
+ new_session.should.not.equal session
130
+ res2.body.should.equal '{"counter"=>3}'
131
+
132
+ res3 = req.get("/", "HTTP_COOKIE" => new_cookie)
133
+ res3["Set-Cookie"][session_match].should.equal new_session
134
+ res3.body.should.equal '{"counter"=>4}'
135
+ end
136
+
137
+ specify "omits cookie with :defer option" do
138
+ pool = Rack::Session::Memcache.new(incrementor)
139
+ req = Rack::MockRequest.new(pool)
140
+ defer = Rack::Utils::Context.new(pool, defer_session)
141
+ dreq = Rack::MockRequest.new(defer)
142
+
143
+ res0 = req.get("/")
144
+ session = (cookie = res0["Set-Cookie"])[session_match]
145
+ res0.body.should.equal '{"counter"=>1}'
146
+
147
+ res1 = req.get("/", "HTTP_COOKIE" => cookie)
148
+ res1["Set-Cookie"][session_match].should.equal session
149
+ res1.body.should.equal '{"counter"=>2}'
150
+
151
+ res2 = dreq.get("/", "HTTP_COOKIE" => cookie)
152
+ res2["Set-Cookie"].should.equal nil
153
+ res2.body.should.equal '{"counter"=>3}'
154
+
155
+ res3 = req.get("/", "HTTP_COOKIE" => cookie)
156
+ res3["Set-Cookie"][session_match].should.equal session
157
+ res3.body.should.equal '{"counter"=>4}'
158
+ end
159
+
160
+ specify "deep hashes are correctly updated" do
161
+ store = nil
162
+ hash_check = proc do |env|
163
+ session = env['rack.session']
164
+ unless session.include? 'test'
165
+ session.update :a => :b, :c => { :d => :e },
166
+ :f => { :g => { :h => :i} }, 'test' => true
167
+ else
168
+ session[:f][:g][:h] = :j
169
+ end
170
+ [200, {}, session.inspect]
171
+ end
172
+ pool = Rack::Session::Memcache.new(hash_check)
173
+ req = Rack::MockRequest.new(pool)
174
+
175
+ res0 = req.get("/")
176
+ session_id = (cookie = res0["Set-Cookie"])[session_match, 1]
177
+ ses0 = pool.pool.get(session_id, true)
178
+
179
+ res1 = req.get("/", "HTTP_COOKIE" => cookie)
180
+ ses1 = pool.pool.get(session_id, true)
181
+
182
+ ses1.should.not.equal ses0
183
+ end
184
+
185
+ # anyone know how to do this better?
186
+ specify "multithread: should cleanly merge sessions" do
187
+ next unless $DEBUG
188
+ warn 'Running multithread test for Session::Memcache'
189
+ pool = Rack::Session::Memcache.new(incrementor)
190
+ req = Rack::MockRequest.new(pool)
191
+
192
+ res = req.get('/')
193
+ res.body.should.equal '{"counter"=>1}'
194
+ cookie = res["Set-Cookie"]
195
+ session_id = cookie[session_match, 1]
196
+
197
+ delta_incrementor = lambda do |env|
198
+ # emulate disconjoinment of threading
199
+ env['rack.session'] = env['rack.session'].dup
200
+ Thread.stop
201
+ env['rack.session'][(Time.now.usec*rand).to_i] = true
202
+ incrementor.call(env)
203
+ end
204
+ tses = Rack::Utils::Context.new pool, delta_incrementor
205
+ treq = Rack::MockRequest.new(tses)
206
+ tnum = rand(7).to_i+5
207
+ r = Array.new(tnum) do
208
+ Thread.new(treq) do |run|
209
+ run.get('/', "HTTP_COOKIE" => cookie, 'rack.multithread' => true)
210
+ end
211
+ end.reverse.map{|t| t.run.join.value }
212
+ r.each do |request|
213
+ request['Set-Cookie'].should.equal cookie
214
+ request.body.should.include '"counter"=>2'
215
+ end
216
+
217
+ session = pool.pool.get(session_id)
218
+ session.size.should.be tnum+1 # counter
219
+ session['counter'].should.be 2 # meeeh
220
+
221
+ tnum = rand(7).to_i+5
222
+ r = Array.new(tnum) do |i|
223
+ delta_time = proc do |env|
224
+ env['rack.session'][i] = Time.now
225
+ Thread.stop
226
+ env['rack.session'] = env['rack.session'].dup
227
+ env['rack.session'][i] -= Time.now
228
+ incrementor.call(env)
229
+ end
230
+ app = Rack::Utils::Context.new pool, time_delta
231
+ req = Rack::MockRequest.new app
232
+ Thread.new(req) do |run|
233
+ run.get('/', "HTTP_COOKIE" => cookie, 'rack.multithread' => true)
234
+ end
235
+ end.reverse.map{|t| t.run.join.value }
236
+ r.each do |request|
237
+ request['Set-Cookie'].should.equal cookie
238
+ request.body.should.include '"counter"=>3'
239
+ end
240
+
241
+ session = pool.pool.get(session_id)
242
+ session.size.should.be tnum+1
243
+ session['counter'].should.be 3
244
+
245
+ drop_counter = proc do |env|
246
+ env['rack.session'].delete 'counter'
247
+ env['rack.session']['foo'] = 'bar'
248
+ [200, {'Content-Type'=>'text/plain'}, env['rack.session'].inspect]
249
+ end
250
+ tses = Rack::Utils::Context.new pool, drop_counter
251
+ treq = Rack::MockRequest.new(tses)
252
+ tnum = rand(7).to_i+5
253
+ r = Array.new(tnum) do
254
+ Thread.new(treq) do |run|
255
+ run.get('/', "HTTP_COOKIE" => cookie, 'rack.multithread' => true)
256
+ end
257
+ end.reverse.map{|t| t.run.join.value }
258
+ r.each do |request|
259
+ request['Set-Cookie'].should.equal cookie
260
+ request.body.should.include '"foo"=>"bar"'
261
+ end
262
+
263
+ session = pool.pool.get(session_id)
264
+ session.size.should.be r.size+1
265
+ session['counter'].should.be.nil?
266
+ session['foo'].should.equal 'bar'
267
+ end
268
+ end
269
+ rescue RuntimeError
270
+ $stderr.puts "Skipping Rack::Session::Memcache tests. Start memcached and try again."
271
+ rescue LoadError
272
+ $stderr.puts "Skipping Rack::Session::Memcache tests (Memcache is required). `gem install memcache-client` and try again."
273
+ end
@@ -0,0 +1,172 @@
1
+ require 'test/spec'
2
+
3
+ require 'rack/session/pool'
4
+ require 'rack/mock'
5
+ require 'rack/response'
6
+ require 'thread'
7
+
8
+ context "Rack::Session::Pool" do
9
+ session_key = Rack::Session::Pool::DEFAULT_OPTIONS[:key]
10
+ session_match = /#{session_key}=[0-9a-fA-F]+;/
11
+ incrementor = lambda do |env|
12
+ env["rack.session"]["counter"] ||= 0
13
+ env["rack.session"]["counter"] += 1
14
+ Rack::Response.new(env["rack.session"].inspect).to_a
15
+ end
16
+ drop_session = proc do |env|
17
+ env['rack.session.options'][:drop] = true
18
+ incrementor.call(env)
19
+ end
20
+ renew_session = proc do |env|
21
+ env['rack.session.options'][:renew] = true
22
+ incrementor.call(env)
23
+ end
24
+ defer_session = proc do |env|
25
+ env['rack.session.options'][:defer] = true
26
+ incrementor.call(env)
27
+ end
28
+
29
+ specify "creates a new cookie" do
30
+ pool = Rack::Session::Pool.new(incrementor)
31
+ res = Rack::MockRequest.new(pool).get("/")
32
+ res["Set-Cookie"].should.match session_match
33
+ res.body.should.equal '{"counter"=>1}'
34
+ end
35
+
36
+ specify "determines session from a cookie" do
37
+ pool = Rack::Session::Pool.new(incrementor)
38
+ req = Rack::MockRequest.new(pool)
39
+ cookie = req.get("/")["Set-Cookie"]
40
+ req.get("/", "HTTP_COOKIE" => cookie).
41
+ body.should.equal '{"counter"=>2}'
42
+ req.get("/", "HTTP_COOKIE" => cookie).
43
+ body.should.equal '{"counter"=>3}'
44
+ end
45
+
46
+ specify "survives nonexistant cookies" do
47
+ pool = Rack::Session::Pool.new(incrementor)
48
+ res = Rack::MockRequest.new(pool).
49
+ get("/", "HTTP_COOKIE" => "#{session_key}=blarghfasel")
50
+ res.body.should.equal '{"counter"=>1}'
51
+ end
52
+
53
+ specify "deletes cookies with :drop option" do
54
+ pool = Rack::Session::Pool.new(incrementor)
55
+ req = Rack::MockRequest.new(pool)
56
+ drop = Rack::Utils::Context.new(pool, drop_session)
57
+ dreq = Rack::MockRequest.new(drop)
58
+
59
+ res0 = req.get("/")
60
+ session = (cookie = res0["Set-Cookie"])[session_match]
61
+ res0.body.should.equal '{"counter"=>1}'
62
+ pool.pool.size.should.be 1
63
+
64
+ res1 = req.get("/", "HTTP_COOKIE" => cookie)
65
+ res1["Set-Cookie"][session_match].should.equal session
66
+ res1.body.should.equal '{"counter"=>2}'
67
+ pool.pool.size.should.be 1
68
+
69
+ res2 = dreq.get("/", "HTTP_COOKIE" => cookie)
70
+ res2["Set-Cookie"].should.equal nil
71
+ res2.body.should.equal '{"counter"=>3}'
72
+ pool.pool.size.should.be 0
73
+
74
+ res3 = req.get("/", "HTTP_COOKIE" => cookie)
75
+ res3["Set-Cookie"][session_match].should.not.equal session
76
+ res3.body.should.equal '{"counter"=>1}'
77
+ pool.pool.size.should.be 1
78
+ end
79
+
80
+ specify "provides new session id with :renew option" do
81
+ pool = Rack::Session::Pool.new(incrementor)
82
+ req = Rack::MockRequest.new(pool)
83
+ renew = Rack::Utils::Context.new(pool, renew_session)
84
+ rreq = Rack::MockRequest.new(renew)
85
+
86
+ res0 = req.get("/")
87
+ session = (cookie = res0["Set-Cookie"])[session_match]
88
+ res0.body.should.equal '{"counter"=>1}'
89
+ pool.pool.size.should.be 1
90
+
91
+ res1 = req.get("/", "HTTP_COOKIE" => cookie)
92
+ res1["Set-Cookie"][session_match].should.equal session
93
+ res1.body.should.equal '{"counter"=>2}'
94
+ pool.pool.size.should.be 1
95
+
96
+ res2 = rreq.get("/", "HTTP_COOKIE" => cookie)
97
+ new_cookie = res2["Set-Cookie"]
98
+ new_session = new_cookie[session_match]
99
+ new_session.should.not.equal session
100
+ res2.body.should.equal '{"counter"=>3}'
101
+ pool.pool.size.should.be 1
102
+
103
+ res3 = req.get("/", "HTTP_COOKIE" => new_cookie)
104
+ res3["Set-Cookie"][session_match].should.equal new_session
105
+ res3.body.should.equal '{"counter"=>4}'
106
+ pool.pool.size.should.be 1
107
+ end
108
+
109
+ specify "omits cookie with :defer option" do
110
+ pool = Rack::Session::Pool.new(incrementor)
111
+ req = Rack::MockRequest.new(pool)
112
+ defer = Rack::Utils::Context.new(pool, defer_session)
113
+ dreq = Rack::MockRequest.new(defer)
114
+
115
+ res0 = req.get("/")
116
+ session = (cookie = res0["Set-Cookie"])[session_match]
117
+ res0.body.should.equal '{"counter"=>1}'
118
+ pool.pool.size.should.be 1
119
+
120
+ res1 = req.get("/", "HTTP_COOKIE" => cookie)
121
+ res1["Set-Cookie"][session_match].should.equal session
122
+ res1.body.should.equal '{"counter"=>2}'
123
+ pool.pool.size.should.be 1
124
+
125
+ res2 = dreq.get("/", "HTTP_COOKIE" => cookie)
126
+ res2["Set-Cookie"].should.equal nil
127
+ res2.body.should.equal '{"counter"=>3}'
128
+ pool.pool.size.should.be 1
129
+
130
+ res3 = req.get("/", "HTTP_COOKIE" => cookie)
131
+ res3["Set-Cookie"][session_match].should.equal session
132
+ res3.body.should.equal '{"counter"=>4}'
133
+ pool.pool.size.should.be 1
134
+ end
135
+
136
+ # anyone know how to do this better?
137
+ specify "multithread: should merge sessions" do
138
+ next unless $DEBUG
139
+ warn 'Running multithread tests for Session::Pool'
140
+ pool = Rack::Session::Pool.new(incrementor)
141
+ req = Rack::MockRequest.new(pool)
142
+
143
+ res = req.get('/')
144
+ res.body.should.equal '{"counter"=>1}'
145
+ cookie = res["Set-Cookie"]
146
+ sess_id = cookie[/#{pool.key}=([^,;]+)/,1]
147
+
148
+ delta_incrementor = lambda do |env|
149
+ # emulate disconjoinment of threading
150
+ env['rack.session'] = env['rack.session'].dup
151
+ Thread.stop
152
+ env['rack.session'][(Time.now.usec*rand).to_i] = true
153
+ incrementor.call(env)
154
+ end
155
+ tses = Rack::Utils::Context.new pool, delta_incrementor
156
+ treq = Rack::MockRequest.new(tses)
157
+ tnum = rand(7).to_i+5
158
+ r = Array.new(tnum) do
159
+ Thread.new(treq) do |run|
160
+ run.get('/', "HTTP_COOKIE" => cookie, 'rack.multithread' => true)
161
+ end
162
+ end.reverse.map{|t| t.run.join.value }
163
+ r.each do |res|
164
+ res['Set-Cookie'].should.equal cookie
165
+ res.body.should.include '"counter"=>2'
166
+ end
167
+
168
+ session = pool.pool[sess_id]
169
+ session.size.should.be tnum+1 # counter
170
+ session['counter'].should.be 2 # meeeh
171
+ end
172
+ end