spec_setup.rb 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. require 'pp'
  2. require 'tmpdir'
  3. require 'stringio'
  4. [STDOUT, STDERR].each { |io| io.sync = true }
  5. begin
  6. require 'bacon'
  7. rescue LoadError => boom
  8. require 'rubygems' rescue nil
  9. require 'bacon'
  10. end
  11. # Set the MEMCACHED environment variable as follows to enable testing
  12. # of the MemCached meta and entity stores.
  13. ENV['MEMCACHED'] ||= 'localhost:11211'
  14. $memcached = nil
  15. $dalli = nil
  16. def have_memcached?(server=ENV['MEMCACHED'])
  17. return $memcached unless $memcached.nil?
  18. # silence warnings from memcached
  19. begin
  20. v, $VERBOSE = $VERBOSE, nil
  21. require 'memcached'
  22. ensure
  23. $VERBOSE = v
  24. end
  25. $memcached = Memcached.new(server)
  26. $memcached.set('ping', '')
  27. true
  28. rescue LoadError => boom
  29. warn "memcached library not available. related tests will be skipped."
  30. $memcached = false
  31. false
  32. rescue => boom
  33. warn "memcached not working. related tests will be skipped."
  34. $memcached = false
  35. false
  36. end
  37. have_memcached?
  38. def have_dalli?(server=ENV['MEMCACHED'])
  39. return $dalli unless $dalli.nil?
  40. require 'dalli'
  41. $dalli = Dalli::Client.new(server)
  42. $dalli.set('ping', '')
  43. true
  44. rescue LoadError => boom
  45. warn "dalli library not available. related tests will be skipped."
  46. $dalli = false
  47. false
  48. rescue => boom
  49. warn "dalli not working. related tests will be skipped."
  50. $dalli = false
  51. false
  52. end
  53. have_dalli?
  54. def need_dalli(forwhat)
  55. yield if have_dalli?
  56. end
  57. def need_memcached(forwhat)
  58. yield if have_memcached?
  59. end
  60. def need_java(forwhat)
  61. yield if RUBY_PLATFORM =~ /java/
  62. end
  63. # Setup the load path ..
  64. $LOAD_PATH.unshift File.dirname(File.dirname(__FILE__)) + '/lib'
  65. $LOAD_PATH.unshift File.dirname(__FILE__)
  66. require 'rack/cache'
  67. # Methods for constructing downstream applications / response
  68. # generators.
  69. module CacheContextHelpers
  70. # The Rack::Cache::Context instance used for the most recent
  71. # request.
  72. attr_reader :cache
  73. # An Array of Rack::Cache::Context instances used for each request, in
  74. # request order.
  75. attr_reader :caches
  76. # The Rack::Response instance result of the most recent request.
  77. attr_reader :response
  78. # An Array of Rack::Response instances for each request, in request order.
  79. attr_reader :responses
  80. # The backend application object.
  81. attr_reader :app
  82. def setup_cache_context
  83. # holds each Rack::Cache::Context
  84. @app = nil
  85. # each time a request is made, a clone of @cache_template is used
  86. # and appended to @caches.
  87. @cache_template = nil
  88. @cache = nil
  89. @caches = []
  90. @errors = StringIO.new
  91. @cache_config = nil
  92. @called = false
  93. @request = nil
  94. @response = nil
  95. @responses = []
  96. @storage = Rack::Cache::Storage.new
  97. end
  98. def teardown_cache_context
  99. @app, @cache_template, @cache, @caches, @called,
  100. @request, @response, @responses, @cache_config, @cache_prototype = nil
  101. end
  102. # A basic response with 200 status code and a tiny body.
  103. def respond_with(status=200, headers={}, body=['Hello World'], &bk)
  104. called = false
  105. @app =
  106. lambda do |env|
  107. called = true
  108. response = Rack::Response.new(body, status, headers)
  109. request = Rack::Request.new(env)
  110. bk.call(request, response) if bk
  111. response.finish
  112. end
  113. @app.meta_def(:called?) { called }
  114. @app.meta_def(:reset!) { called = false }
  115. @app
  116. end
  117. def cache_config(&block)
  118. @cache_config = block
  119. end
  120. def request(method, uri='/', opts={})
  121. opts = {
  122. 'rack.run_once' => true,
  123. 'rack.errors' => @errors,
  124. 'rack-cache.storage' => @storage
  125. }.merge(opts)
  126. fail 'response not specified (use respond_with)' if @app.nil?
  127. @app.reset! if @app.respond_to?(:reset!)
  128. @cache_prototype ||= Rack::Cache::Context.new(@app, &@cache_config)
  129. @cache = @cache_prototype.clone
  130. @caches << @cache
  131. @request = Rack::MockRequest.new(@cache)
  132. yield @cache if block_given?
  133. @response = @request.request(method.to_s.upcase, uri, opts)
  134. @responses << @response
  135. @response
  136. end
  137. def get(stem, env={}, &b)
  138. request(:get, stem, env, &b)
  139. end
  140. def head(stem, env={}, &b)
  141. request(:head, stem, env, &b)
  142. end
  143. def post(*args, &b)
  144. request(:post, *args, &b)
  145. end
  146. end
  147. module TestHelpers
  148. include FileUtils
  149. F = File
  150. @@temp_dir_count = 0
  151. def create_temp_directory
  152. @@temp_dir_count += 1
  153. path = F.join(Dir.tmpdir, "rack-cache-#{$$}-#{@@temp_dir_count}")
  154. mkdir_p path
  155. if block_given?
  156. yield path
  157. remove_entry_secure path
  158. end
  159. path
  160. end
  161. def create_temp_file(root, file, data='')
  162. path = F.join(root, file)
  163. mkdir_p F.dirname(path)
  164. F.open(path, 'w') { |io| io.write(data) }
  165. end
  166. end
  167. class Bacon::Context
  168. include TestHelpers
  169. include CacheContextHelpers
  170. end
  171. # Metaid == a few simple metaclass helper
  172. # (See http://whytheluckystiff.net/articles/seeingMetaclassesClearly.html.)
  173. class Object
  174. # The hidden singleton lurks behind everyone
  175. def metaclass; class << self; self; end; end
  176. def meta_eval(&blk); metaclass.instance_eval(&blk); end
  177. # Adds methods to a metaclass
  178. def meta_def name, &blk
  179. meta_eval { define_method name, &blk }
  180. end
  181. # Defines an instance method within a class
  182. def class_def name, &blk
  183. class_eval { define_method name, &blk }
  184. end
  185. # True when the Object is neither false or nil.
  186. def truthy?
  187. !!self
  188. end
  189. end