PageRenderTime 102ms CodeModel.GetById 10ms app.highlight 88ms RepoModel.GetById 1ms app.codeStats 0ms

/vendor/bundle/jruby/2.1/gems/rack-1.5.2/test/spec_session_memcache.rb

https://github.com/delowong/logstash
Ruby | 321 lines | 275 code | 42 blank | 4 comment | 2 complexity | b8f34bf7cdbf030a0f708e2170de05d2 MD5 | raw file
  1begin
  2  require 'rack/session/memcache'
  3  require 'rack/lint'
  4  require 'rack/mock'
  5  require 'thread'
  6
  7  describe Rack::Session::Memcache do
  8    session_key = Rack::Session::Memcache::DEFAULT_OPTIONS[:key]
  9    session_match = /#{session_key}=([0-9a-fA-F]+);/
 10    incrementor = lambda do |env|
 11      env["rack.session"]["counter"] ||= 0
 12      env["rack.session"]["counter"] += 1
 13      Rack::Response.new(env["rack.session"].inspect).to_a
 14    end
 15    drop_session = Rack::Lint.new(proc do |env|
 16      env['rack.session.options'][:drop] = true
 17      incrementor.call(env)
 18    end)
 19    renew_session = Rack::Lint.new(proc do |env|
 20      env['rack.session.options'][:renew] = true
 21      incrementor.call(env)
 22    end)
 23    defer_session = Rack::Lint.new(proc do |env|
 24      env['rack.session.options'][:defer] = true
 25      incrementor.call(env)
 26    end)
 27    skip_session = Rack::Lint.new(proc do |env|
 28      env['rack.session.options'][:skip] = true
 29      incrementor.call(env)
 30    end)
 31    incrementor = Rack::Lint.new(incrementor)
 32
 33    # test memcache connection
 34    Rack::Session::Memcache.new(incrementor)
 35
 36    it "faults on no connection" do
 37      lambda{
 38        Rack::Session::Memcache.new(incrementor, :memcache_server => 'nosuchserver')
 39      }.should.raise
 40    end
 41
 42    it "connects to existing server" do
 43      test_pool = MemCache.new(incrementor, :namespace => 'test:rack:session')
 44      test_pool.namespace.should.equal 'test:rack:session'
 45    end
 46
 47    it "passes options to MemCache" do
 48      pool = Rack::Session::Memcache.new(incrementor, :namespace => 'test:rack:session')
 49      pool.pool.namespace.should.equal 'test:rack:session'
 50    end
 51
 52    it "creates a new cookie" do
 53      pool = Rack::Session::Memcache.new(incrementor)
 54      res = Rack::MockRequest.new(pool).get("/")
 55      res["Set-Cookie"].should.include("#{session_key}=")
 56      res.body.should.equal '{"counter"=>1}'
 57    end
 58
 59    it "determines session from a cookie" do
 60      pool = Rack::Session::Memcache.new(incrementor)
 61      req = Rack::MockRequest.new(pool)
 62      res = req.get("/")
 63      cookie = res["Set-Cookie"]
 64      req.get("/", "HTTP_COOKIE" => cookie).
 65        body.should.equal '{"counter"=>2}'
 66      req.get("/", "HTTP_COOKIE" => cookie).
 67        body.should.equal '{"counter"=>3}'
 68    end
 69
 70    it "determines session only from a cookie by default" do
 71      pool = Rack::Session::Memcache.new(incrementor)
 72      req = Rack::MockRequest.new(pool)
 73      res = req.get("/")
 74      sid = res["Set-Cookie"][session_match, 1]
 75      req.get("/?rack.session=#{sid}").
 76        body.should.equal '{"counter"=>1}'
 77      req.get("/?rack.session=#{sid}").
 78        body.should.equal '{"counter"=>1}'
 79    end
 80
 81    it "determines session from params" do
 82      pool = Rack::Session::Memcache.new(incrementor, :cookie_only => false)
 83      req = Rack::MockRequest.new(pool)
 84      res = req.get("/")
 85      sid = res["Set-Cookie"][session_match, 1]
 86      req.get("/?rack.session=#{sid}").
 87        body.should.equal '{"counter"=>2}'
 88      req.get("/?rack.session=#{sid}").
 89        body.should.equal '{"counter"=>3}'
 90    end
 91
 92    it "survives nonexistant cookies" do
 93      bad_cookie = "rack.session=blarghfasel"
 94      pool = Rack::Session::Memcache.new(incrementor)
 95      res = Rack::MockRequest.new(pool).
 96        get("/", "HTTP_COOKIE" => bad_cookie)
 97      res.body.should.equal '{"counter"=>1}'
 98      cookie = res["Set-Cookie"][session_match]
 99      cookie.should.not.match(/#{bad_cookie}/)
100    end
101
102    it "maintains freshness" do
103      pool = Rack::Session::Memcache.new(incrementor, :expire_after => 3)
104      res = Rack::MockRequest.new(pool).get('/')
105      res.body.should.include '"counter"=>1'
106      cookie = res["Set-Cookie"]
107      res = Rack::MockRequest.new(pool).get('/', "HTTP_COOKIE" => cookie)
108      res["Set-Cookie"].should.equal cookie
109      res.body.should.include '"counter"=>2'
110      puts 'Sleeping to expire session' if $DEBUG
111      sleep 4
112      res = Rack::MockRequest.new(pool).get('/', "HTTP_COOKIE" => cookie)
113      res["Set-Cookie"].should.not.equal cookie
114      res.body.should.include '"counter"=>1'
115    end
116
117    it "does not send the same session id if it did not change" do
118      pool = Rack::Session::Memcache.new(incrementor)
119      req = Rack::MockRequest.new(pool)
120
121      res0 = req.get("/")
122      cookie = res0["Set-Cookie"][session_match]
123      res0.body.should.equal '{"counter"=>1}'
124
125      res1 = req.get("/", "HTTP_COOKIE" => cookie)
126      res1["Set-Cookie"].should.be.nil
127      res1.body.should.equal '{"counter"=>2}'
128
129      res2 = req.get("/", "HTTP_COOKIE" => cookie)
130      res2["Set-Cookie"].should.be.nil
131      res2.body.should.equal '{"counter"=>3}'
132    end
133
134    it "deletes cookies with :drop option" do
135      pool = Rack::Session::Memcache.new(incrementor)
136      req = Rack::MockRequest.new(pool)
137      drop = Rack::Utils::Context.new(pool, drop_session)
138      dreq = Rack::MockRequest.new(drop)
139
140      res1 = req.get("/")
141      session = (cookie = res1["Set-Cookie"])[session_match]
142      res1.body.should.equal '{"counter"=>1}'
143
144      res2 = dreq.get("/", "HTTP_COOKIE" => cookie)
145      res2["Set-Cookie"].should.equal nil
146      res2.body.should.equal '{"counter"=>2}'
147
148      res3 = req.get("/", "HTTP_COOKIE" => cookie)
149      res3["Set-Cookie"][session_match].should.not.equal session
150      res3.body.should.equal '{"counter"=>1}'
151    end
152
153    it "provides new session id with :renew option" do
154      pool = Rack::Session::Memcache.new(incrementor)
155      req = Rack::MockRequest.new(pool)
156      renew = Rack::Utils::Context.new(pool, renew_session)
157      rreq = Rack::MockRequest.new(renew)
158
159      res1 = req.get("/")
160      session = (cookie = res1["Set-Cookie"])[session_match]
161      res1.body.should.equal '{"counter"=>1}'
162
163      res2 = rreq.get("/", "HTTP_COOKIE" => cookie)
164      new_cookie = res2["Set-Cookie"]
165      new_session = new_cookie[session_match]
166      new_session.should.not.equal session
167      res2.body.should.equal '{"counter"=>2}'
168
169      res3 = req.get("/", "HTTP_COOKIE" => new_cookie)
170      res3.body.should.equal '{"counter"=>3}'
171
172      # Old cookie was deleted
173      res4 = req.get("/", "HTTP_COOKIE" => cookie)
174      res4.body.should.equal '{"counter"=>1}'
175    end
176
177    it "omits cookie with :defer option but still updates the state" do
178      pool = Rack::Session::Memcache.new(incrementor)
179      count = Rack::Utils::Context.new(pool, incrementor)
180      defer = Rack::Utils::Context.new(pool, defer_session)
181      dreq = Rack::MockRequest.new(defer)
182      creq = Rack::MockRequest.new(count)
183
184      res0 = dreq.get("/")
185      res0["Set-Cookie"].should.equal nil
186      res0.body.should.equal '{"counter"=>1}'
187
188      res0 = creq.get("/")
189      res1 = dreq.get("/", "HTTP_COOKIE" => res0["Set-Cookie"])
190      res1.body.should.equal '{"counter"=>2}'
191      res2 = dreq.get("/", "HTTP_COOKIE" => res0["Set-Cookie"])
192      res2.body.should.equal '{"counter"=>3}'
193    end
194
195    it "omits cookie and state update with :skip option" do
196      pool = Rack::Session::Memcache.new(incrementor)
197      count = Rack::Utils::Context.new(pool, incrementor)
198      skip = Rack::Utils::Context.new(pool, skip_session)
199      sreq = Rack::MockRequest.new(skip)
200      creq = Rack::MockRequest.new(count)
201
202      res0 = sreq.get("/")
203      res0["Set-Cookie"].should.equal nil
204      res0.body.should.equal '{"counter"=>1}'
205
206      res0 = creq.get("/")
207      res1 = sreq.get("/", "HTTP_COOKIE" => res0["Set-Cookie"])
208      res1.body.should.equal '{"counter"=>2}'
209      res2 = sreq.get("/", "HTTP_COOKIE" => res0["Set-Cookie"])
210      res2.body.should.equal '{"counter"=>2}'
211    end
212
213    it "updates deep hashes correctly" do
214      hash_check = proc do |env|
215        session = env['rack.session']
216        unless session.include? 'test'
217          session.update :a => :b, :c => { :d => :e },
218            :f => { :g => { :h => :i} }, 'test' => true
219        else
220          session[:f][:g][:h] = :j
221        end
222        [200, {}, [session.inspect]]
223      end
224      pool = Rack::Session::Memcache.new(hash_check)
225      req = Rack::MockRequest.new(pool)
226
227      res0 = req.get("/")
228      session_id = (cookie = res0["Set-Cookie"])[session_match, 1]
229      ses0 = pool.pool.get(session_id, true)
230
231      req.get("/", "HTTP_COOKIE" => cookie)
232      ses1 = pool.pool.get(session_id, true)
233
234      ses1.should.not.equal ses0
235    end
236
237    # anyone know how to do this better?
238    it "cleanly merges sessions when multithreaded" do
239      unless $DEBUG
240        1.should.equal 1 # fake assertion to appease the mighty bacon
241        next
242      end
243      warn 'Running multithread test for Session::Memcache'
244      pool = Rack::Session::Memcache.new(incrementor)
245      req = Rack::MockRequest.new(pool)
246
247      res = req.get('/')
248      res.body.should.equal '{"counter"=>1}'
249      cookie = res["Set-Cookie"]
250      session_id = cookie[session_match, 1]
251
252      delta_incrementor = lambda do |env|
253        # emulate disconjoinment of threading
254        env['rack.session'] = env['rack.session'].dup
255        Thread.stop
256        env['rack.session'][(Time.now.usec*rand).to_i] = true
257        incrementor.call(env)
258      end
259      tses = Rack::Utils::Context.new pool, delta_incrementor
260      treq = Rack::MockRequest.new(tses)
261      tnum = rand(7).to_i+5
262      r = Array.new(tnum) do
263        Thread.new(treq) do |run|
264          run.get('/', "HTTP_COOKIE" => cookie, 'rack.multithread' => true)
265        end
266      end.reverse.map{|t| t.run.join.value }
267      r.each do |request|
268        request['Set-Cookie'].should.equal cookie
269        request.body.should.include '"counter"=>2'
270      end
271
272      session = pool.pool.get(session_id)
273      session.size.should.equal tnum+1 # counter
274      session['counter'].should.equal 2 # meeeh
275
276      tnum = rand(7).to_i+5
277      r = Array.new(tnum) do |i|
278        app = Rack::Utils::Context.new pool, time_delta
279        req = Rack::MockRequest.new app
280        Thread.new(req) do |run|
281          run.get('/', "HTTP_COOKIE" => cookie, 'rack.multithread' => true)
282        end
283      end.reverse.map{|t| t.run.join.value }
284      r.each do |request|
285        request['Set-Cookie'].should.equal cookie
286        request.body.should.include '"counter"=>3'
287      end
288
289      session = pool.pool.get(session_id)
290      session.size.should.be tnum+1
291      session['counter'].should.be 3
292
293      drop_counter = proc do |env|
294        env['rack.session'].delete 'counter'
295        env['rack.session']['foo'] = 'bar'
296        [200, {'Content-Type'=>'text/plain'}, env['rack.session'].inspect]
297      end
298      tses = Rack::Utils::Context.new pool, drop_counter
299      treq = Rack::MockRequest.new(tses)
300      tnum = rand(7).to_i+5
301      r = Array.new(tnum) do
302        Thread.new(treq) do |run|
303          run.get('/', "HTTP_COOKIE" => cookie, 'rack.multithread' => true)
304        end
305      end.reverse.map{|t| t.run.join.value }
306      r.each do |request|
307        request['Set-Cookie'].should.equal cookie
308        request.body.should.include '"foo"=>"bar"'
309      end
310
311      session = pool.pool.get(session_id)
312      session.size.should.be r.size+1
313      session['counter'].should.be.nil?
314      session['foo'].should.equal 'bar'
315    end
316  end
317rescue RuntimeError
318  $stderr.puts "Skipping Rack::Session::Memcache tests. Start memcached and try again."
319rescue LoadError
320  $stderr.puts "Skipping Rack::Session::Memcache tests (Memcache is required). `gem install memcache-client` and try again."
321end