spec_lock.rb 3.6 KB

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