actionpack 2.2.3 → 2.3.2

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of actionpack might be problematic. Click here for more details.

Files changed (264) hide show
  1. data/CHANGELOG +433 -375
  2. data/MIT-LICENSE +1 -1
  3. data/README +21 -75
  4. data/Rakefile +1 -1
  5. data/lib/action_controller.rb +80 -43
  6. data/lib/action_controller/assertions/model_assertions.rb +1 -0
  7. data/lib/action_controller/assertions/response_assertions.rb +43 -16
  8. data/lib/action_controller/assertions/routing_assertions.rb +1 -1
  9. data/lib/action_controller/assertions/selector_assertions.rb +17 -12
  10. data/lib/action_controller/assertions/tag_assertions.rb +1 -4
  11. data/lib/action_controller/base.rb +153 -82
  12. data/lib/action_controller/benchmarking.rb +9 -9
  13. data/lib/action_controller/caching.rb +9 -11
  14. data/lib/action_controller/caching/actions.rb +11 -18
  15. data/lib/action_controller/caching/fragments.rb +28 -20
  16. data/lib/action_controller/caching/pages.rb +13 -15
  17. data/lib/action_controller/caching/sweeping.rb +2 -2
  18. data/lib/action_controller/cgi_ext.rb +0 -1
  19. data/lib/action_controller/cgi_ext/cookie.rb +2 -0
  20. data/lib/action_controller/cgi_process.rb +54 -162
  21. data/lib/action_controller/cookies.rb +13 -25
  22. data/lib/action_controller/dispatcher.rb +43 -122
  23. data/lib/action_controller/failsafe.rb +52 -0
  24. data/lib/action_controller/flash.rb +38 -47
  25. data/lib/action_controller/helpers.rb +13 -9
  26. data/lib/action_controller/http_authentication.rb +203 -23
  27. data/lib/action_controller/integration.rb +126 -70
  28. data/lib/action_controller/layout.rb +36 -39
  29. data/lib/action_controller/middleware_stack.rb +119 -0
  30. data/lib/action_controller/middlewares.rb +13 -0
  31. data/lib/action_controller/mime_responds.rb +19 -4
  32. data/lib/action_controller/mime_type.rb +8 -0
  33. data/lib/action_controller/params_parser.rb +71 -0
  34. data/lib/action_controller/performance_test.rb +0 -1
  35. data/lib/action_controller/polymorphic_routes.rb +36 -30
  36. data/lib/action_controller/reloader.rb +14 -0
  37. data/lib/action_controller/request.rb +107 -499
  38. data/lib/action_controller/request_forgery_protection.rb +7 -39
  39. data/lib/action_controller/rescue.rb +55 -35
  40. data/lib/action_controller/resources.rb +34 -31
  41. data/lib/action_controller/response.rb +99 -57
  42. data/lib/action_controller/rewindable_input.rb +28 -0
  43. data/lib/action_controller/routing.rb +7 -7
  44. data/lib/action_controller/routing/builder.rb +4 -1
  45. data/lib/action_controller/routing/optimisations.rb +1 -1
  46. data/lib/action_controller/routing/recognition_optimisation.rb +1 -2
  47. data/lib/action_controller/routing/route.rb +15 -5
  48. data/lib/action_controller/routing/route_set.rb +82 -35
  49. data/lib/action_controller/routing/segments.rb +35 -0
  50. data/lib/action_controller/session/abstract_store.rb +181 -0
  51. data/lib/action_controller/session/cookie_store.rb +197 -175
  52. data/lib/action_controller/session/mem_cache_store.rb +36 -83
  53. data/lib/action_controller/session_management.rb +26 -134
  54. data/lib/action_controller/streaming.rb +24 -7
  55. data/lib/action_controller/templates/rescues/diagnostics.erb +2 -2
  56. data/lib/action_controller/templates/rescues/template_error.erb +2 -2
  57. data/lib/action_controller/test_case.rb +87 -30
  58. data/lib/action_controller/test_process.rb +145 -104
  59. data/lib/action_controller/uploaded_file.rb +44 -0
  60. data/lib/action_controller/url_rewriter.rb +3 -6
  61. data/lib/action_controller/vendor/html-scanner.rb +16 -0
  62. data/lib/action_controller/vendor/html-scanner/html/selector.rb +1 -1
  63. data/lib/action_controller/vendor/rack-1.0/rack.rb +89 -0
  64. data/lib/action_controller/vendor/rack-1.0/rack/adapter/camping.rb +22 -0
  65. data/lib/action_controller/vendor/rack-1.0/rack/auth/abstract/handler.rb +37 -0
  66. data/lib/action_controller/vendor/rack-1.0/rack/auth/abstract/request.rb +37 -0
  67. data/lib/action_controller/vendor/rack-1.0/rack/auth/basic.rb +58 -0
  68. data/lib/action_controller/vendor/rack-1.0/rack/auth/digest/md5.rb +124 -0
  69. data/lib/action_controller/vendor/rack-1.0/rack/auth/digest/nonce.rb +51 -0
  70. data/lib/action_controller/vendor/rack-1.0/rack/auth/digest/params.rb +55 -0
  71. data/lib/action_controller/vendor/rack-1.0/rack/auth/digest/request.rb +40 -0
  72. data/lib/action_controller/vendor/rack-1.0/rack/auth/openid.rb +480 -0
  73. data/lib/action_controller/vendor/rack-1.0/rack/builder.rb +63 -0
  74. data/lib/action_controller/vendor/rack-1.0/rack/cascade.rb +36 -0
  75. data/lib/action_controller/vendor/rack-1.0/rack/chunked.rb +49 -0
  76. data/lib/action_controller/vendor/rack-1.0/rack/commonlogger.rb +61 -0
  77. data/lib/action_controller/vendor/rack-1.0/rack/conditionalget.rb +45 -0
  78. data/lib/action_controller/vendor/rack-1.0/rack/content_length.rb +29 -0
  79. data/lib/action_controller/vendor/rack-1.0/rack/content_type.rb +23 -0
  80. data/lib/action_controller/vendor/rack-1.0/rack/deflater.rb +85 -0
  81. data/lib/action_controller/vendor/rack-1.0/rack/directory.rb +153 -0
  82. data/lib/action_controller/vendor/rack-1.0/rack/file.rb +88 -0
  83. data/lib/action_controller/vendor/rack-1.0/rack/handler.rb +48 -0
  84. data/lib/action_controller/vendor/rack-1.0/rack/handler/cgi.rb +61 -0
  85. data/lib/action_controller/vendor/rack-1.0/rack/handler/evented_mongrel.rb +8 -0
  86. data/lib/action_controller/vendor/rack-1.0/rack/handler/fastcgi.rb +89 -0
  87. data/lib/action_controller/vendor/rack-1.0/rack/handler/lsws.rb +55 -0
  88. data/lib/action_controller/vendor/rack-1.0/rack/handler/mongrel.rb +84 -0
  89. data/lib/action_controller/vendor/rack-1.0/rack/handler/scgi.rb +59 -0
  90. data/lib/action_controller/vendor/rack-1.0/rack/handler/swiftiplied_mongrel.rb +8 -0
  91. data/lib/action_controller/vendor/rack-1.0/rack/handler/thin.rb +18 -0
  92. data/lib/action_controller/vendor/rack-1.0/rack/handler/webrick.rb +67 -0
  93. data/lib/action_controller/vendor/rack-1.0/rack/head.rb +19 -0
  94. data/lib/action_controller/vendor/rack-1.0/rack/lint.rb +462 -0
  95. data/lib/action_controller/vendor/rack-1.0/rack/lobster.rb +65 -0
  96. data/lib/action_controller/vendor/rack-1.0/rack/lock.rb +16 -0
  97. data/lib/action_controller/vendor/rack-1.0/rack/methodoverride.rb +27 -0
  98. data/lib/action_controller/vendor/rack-1.0/rack/mime.rb +204 -0
  99. data/lib/action_controller/vendor/rack-1.0/rack/mock.rb +160 -0
  100. data/lib/action_controller/vendor/rack-1.0/rack/recursive.rb +57 -0
  101. data/lib/action_controller/vendor/rack-1.0/rack/reloader.rb +64 -0
  102. data/lib/action_controller/vendor/rack-1.0/rack/request.rb +241 -0
  103. data/lib/action_controller/vendor/rack-1.0/rack/response.rb +179 -0
  104. data/lib/action_controller/vendor/rack-1.0/rack/session/abstract/id.rb +142 -0
  105. data/lib/action_controller/vendor/rack-1.0/rack/session/cookie.rb +91 -0
  106. data/lib/action_controller/vendor/rack-1.0/rack/session/memcache.rb +109 -0
  107. data/lib/action_controller/vendor/rack-1.0/rack/session/pool.rb +100 -0
  108. data/lib/action_controller/vendor/rack-1.0/rack/showexceptions.rb +349 -0
  109. data/lib/action_controller/vendor/rack-1.0/rack/showstatus.rb +106 -0
  110. data/lib/action_controller/vendor/rack-1.0/rack/static.rb +38 -0
  111. data/lib/action_controller/vendor/rack-1.0/rack/urlmap.rb +55 -0
  112. data/lib/action_controller/vendor/rack-1.0/rack/utils.rb +392 -0
  113. data/lib/action_controller/verification.rb +1 -1
  114. data/lib/action_pack.rb +1 -1
  115. data/lib/action_pack/version.rb +2 -2
  116. data/lib/action_view.rb +22 -17
  117. data/lib/action_view/base.rb +53 -79
  118. data/lib/action_view/erb/util.rb +38 -0
  119. data/lib/action_view/helpers.rb +24 -5
  120. data/lib/action_view/helpers/active_record_helper.rb +2 -2
  121. data/lib/action_view/helpers/asset_tag_helper.rb +81 -50
  122. data/lib/action_view/helpers/atom_feed_helper.rb +1 -1
  123. data/lib/action_view/helpers/benchmark_helper.rb +26 -5
  124. data/lib/action_view/helpers/date_helper.rb +82 -7
  125. data/lib/action_view/helpers/form_helper.rb +295 -64
  126. data/lib/action_view/helpers/form_options_helper.rb +160 -18
  127. data/lib/action_view/helpers/form_tag_helper.rb +2 -2
  128. data/lib/action_view/helpers/number_helper.rb +31 -18
  129. data/lib/action_view/helpers/prototype_helper.rb +2 -12
  130. data/lib/action_view/helpers/sanitize_helper.rb +0 -10
  131. data/lib/action_view/helpers/scriptaculous_helper.rb +1 -0
  132. data/lib/action_view/helpers/tag_helper.rb +3 -4
  133. data/lib/action_view/helpers/text_helper.rb +99 -122
  134. data/lib/action_view/helpers/translation_helper.rb +19 -1
  135. data/lib/action_view/helpers/url_helper.rb +25 -2
  136. data/lib/action_view/inline_template.rb +1 -1
  137. data/lib/action_view/locale/en.yml +19 -1
  138. data/lib/action_view/partials.rb +46 -9
  139. data/lib/action_view/paths.rb +28 -84
  140. data/lib/action_view/reloadable_template.rb +117 -0
  141. data/lib/action_view/renderable.rb +28 -35
  142. data/lib/action_view/renderable_partial.rb +3 -4
  143. data/lib/action_view/template.rb +172 -31
  144. data/lib/action_view/template_error.rb +8 -9
  145. data/lib/action_view/template_handler.rb +1 -1
  146. data/lib/action_view/template_handlers.rb +9 -6
  147. data/lib/action_view/template_handlers/erb.rb +2 -39
  148. data/lib/action_view/template_handlers/rjs.rb +1 -0
  149. data/lib/action_view/test_case.rb +27 -1
  150. data/test/abstract_unit.rb +23 -17
  151. data/test/active_record_unit.rb +5 -4
  152. data/test/activerecord/active_record_store_test.rb +139 -106
  153. data/test/activerecord/render_partial_with_record_identification_test.rb +5 -21
  154. data/test/controller/action_pack_assertions_test.rb +25 -23
  155. data/test/controller/addresses_render_test.rb +3 -6
  156. data/test/controller/assert_select_test.rb +83 -70
  157. data/test/controller/base_test.rb +11 -13
  158. data/test/controller/benchmark_test.rb +3 -3
  159. data/test/controller/caching_test.rb +34 -24
  160. data/test/controller/capture_test.rb +3 -6
  161. data/test/controller/content_type_test.rb +3 -6
  162. data/test/controller/cookie_test.rb +31 -66
  163. data/test/controller/deprecation/deprecated_base_methods_test.rb +9 -11
  164. data/test/controller/dispatcher_test.rb +23 -28
  165. data/test/controller/fake_models.rb +8 -0
  166. data/test/controller/filters_test.rb +6 -2
  167. data/test/controller/flash_test.rb +2 -6
  168. data/test/controller/helper_test.rb +15 -1
  169. data/test/controller/html-scanner/document_test.rb +1 -1
  170. data/test/controller/html-scanner/sanitizer_test.rb +1 -1
  171. data/test/controller/http_basic_authentication_test.rb +88 -0
  172. data/test/controller/http_digest_authentication_test.rb +178 -0
  173. data/test/controller/integration_test.rb +56 -52
  174. data/test/controller/layout_test.rb +46 -44
  175. data/test/controller/middleware_stack_test.rb +90 -0
  176. data/test/controller/mime_responds_test.rb +7 -11
  177. data/test/controller/mime_type_test.rb +9 -0
  178. data/test/controller/polymorphic_routes_test.rb +235 -151
  179. data/test/controller/rack_test.rb +52 -81
  180. data/test/controller/redirect_test.rb +6 -14
  181. data/test/controller/render_test.rb +273 -60
  182. data/test/controller/request/json_params_parsing_test.rb +45 -0
  183. data/test/controller/request/multipart_params_parsing_test.rb +223 -0
  184. data/test/controller/request/query_string_parsing_test.rb +120 -0
  185. data/test/controller/request/url_encoded_params_parsing_test.rb +184 -0
  186. data/test/controller/request/xml_params_parsing_test.rb +88 -0
  187. data/test/controller/request_forgery_protection_test.rb +17 -98
  188. data/test/controller/request_test.rb +45 -530
  189. data/test/controller/rescue_test.rb +45 -22
  190. data/test/controller/resources_test.rb +112 -37
  191. data/test/controller/routing_test.rb +1442 -1384
  192. data/test/controller/selector_test.rb +3 -3
  193. data/test/controller/send_file_test.rb +30 -3
  194. data/test/controller/session/cookie_store_test.rb +169 -240
  195. data/test/controller/session/mem_cache_store_test.rb +94 -148
  196. data/test/controller/session/test_session_test.rb +58 -0
  197. data/test/controller/test_test.rb +32 -13
  198. data/test/controller/url_rewriter_test.rb +54 -4
  199. data/test/controller/verification_test.rb +1 -1
  200. data/test/controller/view_paths_test.rb +15 -15
  201. data/test/controller/webservice_test.rb +178 -147
  202. data/test/fixtures/alternate_helpers/foo_helper.rb +3 -0
  203. data/test/fixtures/layout_tests/alt/layouts/alt.rhtml +0 -0
  204. data/test/fixtures/layouts/default_html.html.erb +1 -0
  205. data/test/fixtures/layouts/xhr.html.erb +2 -0
  206. data/test/fixtures/multipart/empty +10 -0
  207. data/test/fixtures/multipart/hello.txt +1 -0
  208. data/test/fixtures/multipart/none +9 -0
  209. data/test/fixtures/public/500.da.html +1 -0
  210. data/test/fixtures/quiz/questions/_question.html.erb +1 -0
  211. data/test/fixtures/replies.yml +1 -1
  212. data/test/fixtures/test/_one.html.erb +1 -0
  213. data/test/fixtures/test/_two.html.erb +1 -0
  214. data/test/fixtures/test/dont_pick_me +1 -0
  215. data/test/fixtures/test/hello.builder +1 -1
  216. data/test/fixtures/test/hello_world.da.html.erb +1 -0
  217. data/test/fixtures/test/hello_world.erb~ +1 -0
  218. data/test/fixtures/test/hello_world.pt-BR.html.erb +1 -0
  219. data/test/fixtures/test/malformed/malformed.en.html.erb~ +1 -0
  220. data/test/fixtures/test/malformed/malformed.erb~ +1 -0
  221. data/test/fixtures/test/malformed/malformed.html.erb~ +1 -0
  222. data/test/fixtures/test/render_explicit_html_template.js.rjs +1 -0
  223. data/test/fixtures/test/render_implicit_html_template.js.rjs +1 -0
  224. data/test/fixtures/test/render_implicit_html_template_from_xhr_request.da.html.erb +1 -0
  225. data/test/fixtures/test/render_implicit_html_template_from_xhr_request.html.erb +1 -0
  226. data/test/fixtures/test/render_implicit_js_template_without_layout.js.erb +1 -0
  227. data/test/fixtures/test/utf8.html.erb +2 -0
  228. data/test/template/active_record_helper_i18n_test.rb +31 -33
  229. data/test/template/active_record_helper_test.rb +34 -0
  230. data/test/template/asset_tag_helper_test.rb +52 -14
  231. data/test/template/atom_feed_helper_test.rb +3 -5
  232. data/test/template/benchmark_helper_test.rb +50 -24
  233. data/test/template/compiled_templates_test.rb +177 -33
  234. data/test/template/date_helper_i18n_test.rb +88 -81
  235. data/test/template/date_helper_test.rb +427 -43
  236. data/test/template/form_helper_test.rb +243 -44
  237. data/test/template/form_options_helper_test.rb +631 -565
  238. data/test/template/form_tag_helper_test.rb +9 -2
  239. data/test/template/javascript_helper_test.rb +0 -5
  240. data/test/template/number_helper_i18n_test.rb +60 -48
  241. data/test/template/number_helper_test.rb +1 -0
  242. data/test/template/render_test.rb +117 -35
  243. data/test/template/test_test.rb +4 -6
  244. data/test/template/text_helper_test.rb +129 -50
  245. data/test/template/translation_helper_test.rb +23 -19
  246. data/test/template/url_helper_test.rb +35 -2
  247. data/test/view/test_case_test.rb +8 -0
  248. metadata +197 -23
  249. data/lib/action_controller/assertions.rb +0 -69
  250. data/lib/action_controller/caching/sql_cache.rb +0 -18
  251. data/lib/action_controller/cgi_ext/session.rb +0 -53
  252. data/lib/action_controller/components.rb +0 -169
  253. data/lib/action_controller/rack_process.rb +0 -297
  254. data/lib/action_controller/request_profiler.rb +0 -169
  255. data/lib/action_controller/session/active_record_store.rb +0 -340
  256. data/lib/action_controller/session/drb_server.rb +0 -32
  257. data/lib/action_controller/session/drb_store.rb +0 -35
  258. data/test/controller/cgi_test.rb +0 -269
  259. data/test/controller/components_test.rb +0 -156
  260. data/test/controller/http_authentication_test.rb +0 -54
  261. data/test/controller/integration_upload_test.rb +0 -43
  262. data/test/controller/session_fixation_test.rb +0 -89
  263. data/test/controller/session_management_test.rb +0 -178
  264. data/test/fixtures/test/hello_world.js +0 -1
@@ -303,7 +303,7 @@ class SelectorTest < Test::Unit::TestCase
303
303
  assert_equal 1, @matches.size
304
304
  assert_equal "2", @matches[0].attributes["id"]
305
305
  # Before first and past last returns nothing.:
306
- assert_raises(ArgumentError) { select("tr:nth-child(-1)") }
306
+ assert_raise(ArgumentError) { select("tr:nth-child(-1)") }
307
307
  select("tr:nth-child(0)")
308
308
  assert_equal 0, @matches.size
309
309
  select("tr:nth-child(5)")
@@ -597,8 +597,8 @@ class SelectorTest < Test::Unit::TestCase
597
597
 
598
598
  def test_negation_details
599
599
  parse(%Q{<p id="1"></p><p id="2"></p><p id="3"></p>})
600
- assert_raises(ArgumentError) { select(":not(") }
601
- assert_raises(ArgumentError) { select(":not(:not())") }
600
+ assert_raise(ArgumentError) { select(":not(") }
601
+ assert_raise(ArgumentError) { select(":not(:not())") }
602
602
  select("p:not(#1):not(#3)")
603
603
  assert_equal 1, @matches.size
604
604
  assert_equal "2", @matches[0].attributes["id"]
@@ -19,7 +19,8 @@ class SendFileController < ActionController::Base
19
19
  def rescue_action(e) raise end
20
20
  end
21
21
 
22
- class SendFileTest < Test::Unit::TestCase
22
+ class SendFileTest < ActionController::TestCase
23
+ tests SendFileController
23
24
  include TestFileUtils
24
25
 
25
26
  Mime::Type.register "image/png", :png unless defined? Mime::PNG
@@ -69,6 +70,7 @@ class SendFileTest < Test::Unit::TestCase
69
70
 
70
71
  assert_equal @controller.file_path, response.headers['X-Sendfile']
71
72
  assert response.body.blank?
73
+ assert !response.etag?
72
74
  end
73
75
 
74
76
  def test_data
@@ -118,17 +120,42 @@ class SendFileTest < Test::Unit::TestCase
118
120
  assert_equal 'private', h['Cache-Control']
119
121
  end
120
122
 
123
+ def test_send_file_headers_with_mime_lookup_with_symbol
124
+ options = {
125
+ :length => 1,
126
+ :type => :png
127
+ }
128
+
129
+ @controller.headers = {}
130
+ @controller.send(:send_file_headers!, options)
131
+
132
+ headers = @controller.headers
133
+
134
+ assert_equal 'image/png', headers['Content-Type']
135
+ end
136
+
137
+
138
+ def test_send_file_headers_with_bad_symbol
139
+ options = {
140
+ :length => 1,
141
+ :type => :this_type_is_not_registered
142
+ }
143
+
144
+ @controller.headers = {}
145
+ assert_raise(ArgumentError){ @controller.send(:send_file_headers!, options) }
146
+ end
147
+
121
148
  %w(file data).each do |method|
122
149
  define_method "test_send_#{method}_status" do
123
150
  @controller.options = { :stream => false, :status => 500 }
124
151
  assert_nothing_raised { assert_not_nil process(method) }
125
- assert_equal '500 Internal Server Error', @response.headers['Status']
152
+ assert_equal '500 Internal Server Error', @response.status
126
153
  end
127
154
 
128
155
  define_method "test_default_send_#{method}_status" do
129
156
  @controller.options = { :stream => false }
130
157
  assert_nothing_raised { assert_not_nil process(method) }
131
- assert_equal ActionController::Base::DEFAULT_RENDER_STATUS_CODE, @response.headers['Status']
158
+ assert_equal ActionController::Base::DEFAULT_RENDER_STATUS_CODE, @response.status
132
159
  end
133
160
  end
134
161
  end
@@ -1,310 +1,239 @@
1
1
  require 'abstract_unit'
2
- require 'action_controller/cgi_process'
3
- require 'action_controller/cgi_ext'
4
-
5
2
  require 'stringio'
6
3
 
4
+ class CookieStoreTest < ActionController::IntegrationTest
5
+ SessionKey = '_myapp_session'
6
+ SessionSecret = 'b3c631c314c0bbca50c1b2843150fe33'
7
+
8
+ DispatcherApp = ActionController::Dispatcher.new
9
+ CookieStoreApp = ActionController::Session::CookieStore.new(DispatcherApp, :key => SessionKey, :secret => SessionSecret)
10
+
11
+ Verifier = ActiveSupport::MessageVerifier.new(SessionSecret, 'SHA1')
12
+
13
+ SignedBar = "BAh7BjoIZm9vIghiYXI%3D--fef868465920f415f2c0652d6910d3af288a0367"
7
14
 
8
- class CGI::Session::CookieStore
9
- def ensure_secret_secure_with_test_hax(secret)
10
- if secret == CookieStoreTest.default_session_options['secret']
11
- return true
12
- else
13
- ensure_secret_secure_without_test_hax(secret)
15
+ class TestController < ActionController::Base
16
+ def no_session_access
17
+ head :ok
14
18
  end
15
- end
16
- alias_method_chain :ensure_secret_secure, :test_hax
17
- end
18
19
 
20
+ def persistent_session_id
21
+ render :text => session[:session_id]
22
+ end
19
23
 
20
- # Expose for tests.
21
- class CGI
22
- attr_reader :output_cookies, :output_hidden
24
+ def set_session_value
25
+ session[:foo] = "bar"
26
+ render :text => Rack::Utils.escape(Verifier.generate(session.to_hash))
27
+ end
23
28
 
24
- class Session
25
- attr_reader :dbman
29
+ def get_session_value
30
+ render :text => "foo: #{session[:foo].inspect}"
31
+ end
26
32
 
27
- class CookieStore
28
- attr_reader :data, :original, :cookie_options
33
+ def get_session_id
34
+ render :text => "foo: #{session[:foo].inspect}; id: #{request.session_options[:id]}"
29
35
  end
30
- end
31
- end
32
36
 
33
- class CookieStoreTest < Test::Unit::TestCase
34
- def self.default_session_options
35
- { 'database_manager' => CGI::Session::CookieStore,
36
- 'session_key' => '_myapp_session',
37
- 'secret' => 'Keep it secret; keep it safe.',
38
- 'no_cookies' => true,
39
- 'no_hidden' => true,
40
- 'session_http_only' => true
41
- }
42
- end
37
+ def call_reset_session
38
+ reset_session
39
+ head :ok
40
+ end
43
41
 
44
- def self.cookies
45
- { :empty => ['BAgw--0686dcaccc01040f4bd4f35fe160afe9bc04c330', {}],
46
- :a_one => ['BAh7BiIGYWkG--5689059497d7f122a7119f171aef81dcfd807fec', { 'a' => 1 }],
47
- :typical => ['BAh7ByIMdXNlcl9pZGkBeyIKZmxhc2h7BiILbm90aWNlIgxIZXkgbm93--9d20154623b9eeea05c62ab819be0e2483238759', { 'user_id' => 123, 'flash' => { 'notice' => 'Hey now' }}],
48
- :flashed => ['BAh7ByIMdXNlcl9pZGkBeyIKZmxhc2h7AA==--bf9785a666d3c4ac09f7fe3353496b437546cfbf', { 'user_id' => 123, 'flash' => {} }],
49
- :double_escaped => [CGI.escape('BAh7ByIMdXNlcl9pZGkBeyIKZmxhc2h7AA%3D%3D--bf9785a666d3c4ac09f7fe3353496b437546cfbf'), { 'user_id' => 123, 'flash' => {} }] }
42
+ def raise_data_overflow
43
+ session[:foo] = 'bye!' * 1024
44
+ head :ok
45
+ end
50
46
 
47
+ def rescue_action(e) raise end
51
48
  end
52
49
 
53
50
  def setup
54
- ENV.delete('HTTP_COOKIE')
51
+ @integration_session = open_session(CookieStoreApp)
55
52
  end
56
53
 
57
54
  def test_raises_argument_error_if_missing_session_key
58
- [nil, ''].each do |blank|
59
- assert_raise(ArgumentError, blank.inspect) { new_session 'session_key' => blank }
60
- end
55
+ assert_raise(ArgumentError, nil.inspect) {
56
+ ActionController::Session::CookieStore.new(nil,
57
+ :key => nil, :secret => SessionSecret)
58
+ }
59
+
60
+ assert_raise(ArgumentError, ''.inspect) {
61
+ ActionController::Session::CookieStore.new(nil,
62
+ :key => '', :secret => SessionSecret)
63
+ }
61
64
  end
62
65
 
63
66
  def test_raises_argument_error_if_missing_secret
64
- [nil, ''].each do |blank|
65
- assert_raise(ArgumentError, blank.inspect) { new_session 'secret' => blank }
66
- end
67
+ assert_raise(ArgumentError, nil.inspect) {
68
+ ActionController::Session::CookieStore.new(nil,
69
+ :key => SessionKey, :secret => nil)
70
+ }
71
+
72
+ assert_raise(ArgumentError, ''.inspect) {
73
+ ActionController::Session::CookieStore.new(nil,
74
+ :key => SessionKey, :secret => '')
75
+ }
67
76
  end
68
77
 
69
78
  def test_raises_argument_error_if_secret_is_probably_insecure
70
- ["password", "secret", "12345678901234567890123456789"].each do |blank|
71
- assert_raise(ArgumentError, blank.inspect) { new_session 'secret' => blank }
72
- end
73
- end
79
+ assert_raise(ArgumentError, "password".inspect) {
80
+ ActionController::Session::CookieStore.new(nil,
81
+ :key => SessionKey, :secret => "password")
82
+ }
74
83
 
75
- def test_reconfigures_session_to_omit_id_cookie_and_hidden_field
76
- new_session do |session|
77
- assert_equal true, @options['no_hidden']
78
- assert_equal true, @options['no_cookies']
79
- end
80
- end
84
+ assert_raise(ArgumentError, "secret".inspect) {
85
+ ActionController::Session::CookieStore.new(nil,
86
+ :key => SessionKey, :secret => "secret")
87
+ }
81
88
 
82
- def test_restore_unmarshals_missing_cookie_as_empty_hash
83
- new_session do |session|
84
- assert_nil session.dbman.data
85
- assert_nil session['test']
86
- assert_equal Hash.new, session.dbman.data
87
- end
89
+ assert_raise(ArgumentError, "12345678901234567890123456789".inspect) {
90
+ ActionController::Session::CookieStore.new(nil,
91
+ :key => SessionKey, :secret => "12345678901234567890123456789")
92
+ }
88
93
  end
89
94
 
90
- def test_restore_unmarshals_good_cookies
91
- cookies(:empty, :a_one, :typical).each do |value, expected|
92
- set_cookie! value
93
- new_session do |session|
94
- assert_nil session['lazy loads the data hash']
95
- assert_equal expected, session.dbman.data
96
- end
97
- end
95
+ def test_setting_session_value
96
+ with_test_route_set do
97
+ get '/set_session_value'
98
+ assert_response :success
99
+ assert_equal "_myapp_session=#{response.body}; path=/; HttpOnly",
100
+ headers['Set-Cookie']
101
+ end
98
102
  end
99
103
 
100
- def test_restore_deletes_tampered_cookies
101
- set_cookie! 'a--b'
102
- new_session do |session|
103
- assert_raise(CGI::Session::CookieStore::TamperedWithCookie) { session['fail'] }
104
- assert_cookie_deleted session
105
- end
104
+ def test_getting_session_value
105
+ with_test_route_set do
106
+ cookies[SessionKey] = SignedBar
107
+ get '/get_session_value'
108
+ assert_response :success
109
+ assert_equal 'foo: "bar"', response.body
110
+ end
106
111
  end
107
112
 
108
- def test_restores_double_encoded_cookies
109
- set_cookie! cookie_value(:double_escaped)
110
- new_session do |session|
111
- session.dbman.restore
112
- assert_equal session["user_id"], 123
113
- assert_equal session["flash"], {}
114
- end
115
- end
113
+ def test_getting_session_id
114
+ with_test_route_set do
115
+ cookies[SessionKey] = SignedBar
116
+ get '/persistent_session_id'
117
+ assert_response :success
118
+ assert_equal response.body.size, 32
119
+ session_id = response.body
116
120
 
117
- def test_close_doesnt_write_cookie_if_data_is_blank
118
- new_session do |session|
119
- assert_no_cookies session
120
- session.close
121
- assert_no_cookies session
121
+ get '/get_session_id'
122
+ assert_response :success
123
+ assert_equal "foo: \"bar\"; id: #{session_id}", response.body
122
124
  end
123
125
  end
124
126
 
125
- def test_close_doesnt_write_cookie_if_data_is_unchanged
126
- set_cookie! cookie_value(:typical)
127
- new_session do |session|
128
- assert_no_cookies session
129
- session['user_id'] = session['user_id']
130
- session.close
131
- assert_no_cookies session
127
+ def test_disregards_tampered_sessions
128
+ with_test_route_set do
129
+ cookies[SessionKey] = "BAh7BjoIZm9vIghiYXI%3D--123456780"
130
+ get '/get_session_value'
131
+ assert_response :success
132
+ assert_equal 'foo: nil', response.body
132
133
  end
133
134
  end
134
135
 
135
136
  def test_close_raises_when_data_overflows
136
- set_cookie! cookie_value(:empty)
137
- new_session do |session|
138
- session['overflow'] = 'bye!' * 1024
139
- assert_raise(CGI::Session::CookieStore::CookieOverflow) { session.close }
140
- assert_no_cookies session
141
- end
142
- end
143
-
144
- def test_close_marshals_and_writes_cookie
145
- set_cookie! cookie_value(:typical)
146
- new_session do |session|
147
- assert_no_cookies session
148
- session['flash'] = {}
149
- assert_no_cookies session
150
- session.close
151
- assert_equal 1, session.cgi.output_cookies.size
152
- cookie = session.cgi.output_cookies.first
153
- assert_cookie cookie, cookie_value(:flashed)
154
- assert_http_only_cookie cookie
155
- assert_secure_cookie cookie, false
156
- end
157
- end
158
-
159
- def test_writes_non_secure_cookie_by_default
160
- set_cookie! cookie_value(:typical)
161
- new_session do |session|
162
- session['flash'] = {}
163
- session.close
164
- cookie = session.cgi.output_cookies.first
165
- assert_secure_cookie cookie,false
137
+ with_test_route_set do
138
+ assert_raise(ActionController::Session::CookieStore::CookieOverflow) {
139
+ get '/raise_data_overflow'
140
+ }
166
141
  end
167
142
  end
168
143
 
169
- def test_writes_secure_cookie
170
- set_cookie! cookie_value(:typical)
171
- new_session('session_secure'=>true) do |session|
172
- session['flash'] = {}
173
- session.close
174
- cookie = session.cgi.output_cookies.first
175
- assert_secure_cookie cookie
144
+ def test_doesnt_write_session_cookie_if_session_is_not_accessed
145
+ with_test_route_set do
146
+ get '/no_session_access'
147
+ assert_response :success
148
+ assert_equal "", headers['Set-Cookie']
176
149
  end
177
150
  end
178
151
 
179
- def test_http_only_cookie_by_default
180
- set_cookie! cookie_value(:typical)
181
- new_session do |session|
182
- session['flash'] = {}
183
- session.close
184
- cookie = session.cgi.output_cookies.first
185
- assert_http_only_cookie cookie
152
+ def test_doesnt_write_session_cookie_if_session_is_unchanged
153
+ with_test_route_set do
154
+ cookies[SessionKey] = "BAh7BjoIZm9vIghiYXI%3D--" +
155
+ "fef868465920f415f2c0652d6910d3af288a0367"
156
+ get '/no_session_access'
157
+ assert_response :success
158
+ assert_equal "", headers['Set-Cookie']
186
159
  end
187
160
  end
188
161
 
189
- def test_overides_http_only_cookie
190
- set_cookie! cookie_value(:typical)
191
- new_session('session_http_only'=>false) do |session|
192
- session['flash'] = {}
193
- session.close
194
- cookie = session.cgi.output_cookies.first
195
- assert_http_only_cookie cookie, false
196
- end
197
- end
162
+ def test_setting_session_value_after_session_reset
163
+ with_test_route_set do
164
+ get '/set_session_value'
165
+ assert_response :success
166
+ session_payload = response.body
167
+ assert_equal "_myapp_session=#{response.body}; path=/; HttpOnly",
168
+ headers['Set-Cookie']
198
169
 
199
- def test_delete_writes_expired_empty_cookie_and_sets_data_to_nil
200
- set_cookie! cookie_value(:typical)
201
- new_session do |session|
202
- assert_no_cookies session
203
- session.delete
204
- assert_cookie_deleted session
170
+ get '/call_reset_session'
171
+ assert_response :success
172
+ assert_not_equal [], headers['Set-Cookie']
173
+ assert_not_equal session_payload, cookies[SessionKey]
205
174
 
206
- # @data is set to nil so #close doesn't send another cookie.
207
- session.close
208
- assert_cookie_deleted session
175
+ get '/get_session_value'
176
+ assert_response :success
177
+ assert_equal 'foo: nil', response.body
209
178
  end
210
179
  end
211
180
 
212
- def test_new_session_doesnt_reuse_deleted_cookie_data
213
- set_cookie! cookie_value(:typical)
214
-
215
- new_session do |session|
216
- assert_not_nil session['user_id']
217
- session.delete
218
-
219
- # Start a new session using the same CGI instance.
220
- post_delete_session = CGI::Session.new(session.cgi, self.class.default_session_options)
221
- assert_nil post_delete_session['user_id']
181
+ def test_persistent_session_id
182
+ with_test_route_set do
183
+ cookies[SessionKey] = SignedBar
184
+ get '/persistent_session_id'
185
+ assert_response :success
186
+ assert_equal response.body.size, 32
187
+ session_id = response.body
188
+ get '/persistent_session_id'
189
+ assert_equal session_id, response.body
190
+ reset!
191
+ get '/persistent_session_id'
192
+ assert_not_equal session_id, response.body
222
193
  end
223
194
  end
224
195
 
225
- private
226
- def assert_no_cookies(session)
227
- assert_nil session.cgi.output_cookies, session.cgi.output_cookies.inspect
228
- end
196
+ def test_session_store_with_expire_after
197
+ app = ActionController::Session::CookieStore.new(DispatcherApp, :key => SessionKey, :secret => SessionSecret, :expire_after => 5.hours)
198
+ @integration_session = open_session(app)
229
199
 
230
- def assert_cookie_deleted(session, message = 'Expected session deletion cookie to be set')
231
- assert_equal 1, session.cgi.output_cookies.size
232
- cookie = session.cgi.output_cookies.first
233
- assert_cookie cookie, nil, 1.year.ago.to_date, "#{message}: #{cookie.name} => #{cookie.value}"
234
- end
200
+ with_test_route_set do
201
+ # First request accesses the session
202
+ time = Time.local(2008, 4, 24)
203
+ Time.stubs(:now).returns(time)
204
+ expected_expiry = (time + 5.hours).gmtime.strftime("%a, %d-%b-%Y %H:%M:%S GMT")
235
205
 
236
- def assert_cookie(cookie, value = nil, expires = nil, message = nil)
237
- assert_equal '_myapp_session', cookie.name, message
238
- assert_equal [value].compact, cookie.value, message
239
- assert_equal expires, cookie.expires ? cookie.expires.to_date : cookie.expires, message
240
- end
206
+ cookies[SessionKey] = SignedBar
241
207
 
242
- def assert_secure_cookie(cookie,value=true)
243
- assert cookie.secure==value
244
- end
208
+ get '/set_session_value'
209
+ assert_response :success
245
210
 
246
- def assert_http_only_cookie(cookie,value=true)
247
- assert cookie.http_only==value
248
- end
211
+ cookie_body = response.body
212
+ assert_equal "_myapp_session=#{cookie_body}; path=/; expires=#{expected_expiry}; HttpOnly",
213
+ headers['Set-Cookie']
249
214
 
250
- def cookies(*which)
251
- self.class.cookies.values_at(*which)
252
- end
215
+ # Second request does not access the session
216
+ time = Time.local(2008, 4, 25)
217
+ Time.stubs(:now).returns(time)
218
+ expected_expiry = (time + 5.hours).gmtime.strftime("%a, %d-%b-%Y %H:%M:%S GMT")
253
219
 
254
- def cookie_value(which)
255
- self.class.cookies[which].first
256
- end
220
+ get '/no_session_access'
221
+ assert_response :success
257
222
 
258
- def set_cookie!(value)
259
- ENV['HTTP_COOKIE'] = "_myapp_session=#{value}"
223
+ assert_equal "_myapp_session=#{cookie_body}; path=/; expires=#{expected_expiry}; HttpOnly",
224
+ headers['Set-Cookie']
260
225
  end
226
+ end
261
227
 
262
- def new_session(options = {})
263
- with_cgi do |cgi|
264
- assert_nil cgi.output_hidden, "Output hidden params should be empty: #{cgi.output_hidden.inspect}"
265
- assert_nil cgi.output_cookies, "Output cookies should be empty: #{cgi.output_cookies.inspect}"
266
-
267
- @options = self.class.default_session_options.merge(options)
268
- session = CGI::Session.new(cgi, @options)
269
- ObjectSpace.undefine_finalizer(session)
270
-
271
- assert_nil cgi.output_hidden, "Output hidden params should be empty: #{cgi.output_hidden.inspect}"
272
- assert_nil cgi.output_cookies, "Output cookies should be empty: #{cgi.output_cookies.inspect}"
273
-
274
- yield session if block_given?
275
- session
228
+ private
229
+ def with_test_route_set
230
+ with_routing do |set|
231
+ set.draw do |map|
232
+ map.with_options :controller => "cookie_store_test/test" do |c|
233
+ c.connect "/:action"
234
+ end
235
+ end
236
+ yield
276
237
  end
277
238
  end
278
-
279
- def with_cgi
280
- ENV['REQUEST_METHOD'] = 'GET'
281
- ENV['HTTP_HOST'] = 'example.com'
282
- ENV['QUERY_STRING'] = ''
283
-
284
- cgi = CGI.new('query', StringIO.new(''))
285
- yield cgi if block_given?
286
- cgi
287
- end
288
- end
289
-
290
-
291
- class CookieStoreWithBlockAsSecretTest < CookieStoreTest
292
- def self.default_session_options
293
- CookieStoreTest.default_session_options.merge 'secret' => Proc.new { 'Keep it secret; keep it safe.' }
294
- end
295
- end
296
-
297
-
298
- class CookieStoreWithMD5DigestTest < CookieStoreTest
299
- def self.default_session_options
300
- CookieStoreTest.default_session_options.merge 'digest' => 'MD5'
301
- end
302
-
303
- def self.cookies
304
- { :empty => ['BAgw--0415cc0be9579b14afc22ee2d341aa21', {}],
305
- :a_one => ['BAh7BiIGYWkG--5a0ed962089cc6600ff44168a5d59bc8', { 'a' => 1 }],
306
- :typical => ['BAh7ByIMdXNlcl9pZGkBeyIKZmxhc2h7BiILbm90aWNlIgxIZXkgbm93--f426763f6ef435b3738b493600db8d64', { 'user_id' => 123, 'flash' => { 'notice' => 'Hey now' }}],
307
- :flashed => ['BAh7ByIMdXNlcl9pZGkBeyIKZmxhc2h7AA==--0af9156650dab044a53a91a4ddec2c51', { 'user_id' => 123, 'flash' => {} }],
308
- :double_escaped => [CGI.escape('BAh7ByIMdXNlcl9pZGkBeyIKZmxhc2h7AA%3D%3D--0af9156650dab044a53a91a4ddec2c51'), { 'user_id' => 123, 'flash' => {} }] }
309
- end
310
239
  end