/
spec_lock.rb
142 lines (119 loc) · 3.63 KB
/
spec_lock.rb
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