1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142
|
require 'rack/lock'
require 'rack/mock'
class Lock
attr_reader :synchronized
def initialize
@synchronized = false
end
def synchronize
@synchronized = true
yield
end
def lock
@synchronized = true
end
def unlock
@synchronized = false
end
end
describe Rack::Lock do
describe 'Proxy' do
should 'delegate each' do
lock = Lock.new
env = Rack::MockRequest.env_for("/")
response = Class.new {
attr_accessor :close_called
def initialize; @close_called = false; end
def each; %w{ hi mom }.each { |x| yield x }; end
}.new
app = Rack::Lock.new(lambda { |inner_env| [200, {}, response] }, lock)
response = app.call(env)[2]
list = []
response.each { |x| list << x }
list.should.equal %w{ hi mom }
end
should 'delegate to_path' do
lock = Lock.new
env = Rack::MockRequest.env_for("/")
res = ['Hello World']
def res.to_path ; "/tmp/hello.txt" ; end
app = Rack::Lock.new(lambda { |inner_env| [200, {}, res] }, lock)
body = app.call(env)[2]
body.should.respond_to :to_path
body.to_path.should.equal "/tmp/hello.txt"
end
should 'not delegate to_path if body does not implement it' do
lock = Lock.new
env = Rack::MockRequest.env_for("/")
res = ['Hello World']
app = Rack::Lock.new(lambda { |inner_env| [200, {}, res] }, lock)
body = app.call(env)[2]
body.should.not.respond_to :to_path
end
end
should 'call super on close' do
lock = Lock.new
env = Rack::MockRequest.env_for("/")
response = Class.new {
attr_accessor :close_called
def initialize; @close_called = false; end
def close; @close_called = true; end
}.new
app = Rack::Lock.new(lambda { |inner_env| [200, {}, response] }, lock)
app.call(env)
response.close_called.should.equal false
response.close
response.close_called.should.equal true
end
should "not unlock until body is closed" do
lock = Lock.new
env = Rack::MockRequest.env_for("/")
response = Object.new
app = Rack::Lock.new(lambda { |inner_env| [200, {}, response] }, lock)
lock.synchronized.should.equal false
response = app.call(env)[2]
lock.synchronized.should.equal true
response.close
lock.synchronized.should.equal false
end
should "return value from app" do
lock = Lock.new
env = Rack::MockRequest.env_for("/")
body = [200, {}, %w{ hi mom }]
app = Rack::Lock.new(lambda { |inner_env| body }, lock)
app.call(env).should.equal body
end
should "call synchronize on lock" do
lock = Lock.new
env = Rack::MockRequest.env_for("/")
app = Rack::Lock.new(lambda { |inner_env|
[200, {}, %w{ a b c }]
}, lock)
lock.synchronized.should.equal false
app.call(env)
lock.synchronized.should.equal true
end
should "unlock if the app raises" do
lock = Lock.new
env = Rack::MockRequest.env_for("/")
app = Rack::Lock.new(lambda { raise Exception }, lock)
lambda { app.call(env) }.should.raise(Exception)
lock.synchronized.should.equal false
end
should "set multithread flag to false" do
app = Rack::Lock.new(lambda { |env|
env['rack.multithread'].should.equal false
[200, {}, %w{ a b c }]
})
app.call(Rack::MockRequest.env_for("/"))
end
should "reset original multithread flag when exiting lock" do
app = Class.new(Rack::Lock) {
def call(env)
env['rack.multithread'].should.equal true
super
end
}.new(lambda { |env| [200, {}, %w{ a b c }] })
app.call(Rack::MockRequest.env_for("/"))
end
end
|