eactionpack 2.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (338) hide show
  1. data/CHANGELOG +7 -0
  2. data/MIT-LICENSE +21 -0
  3. data/README +469 -0
  4. data/RUNNING_UNIT_TESTS +24 -0
  5. data/Rakefile +146 -0
  6. data/install.rb +30 -0
  7. data/lib/action_controller.rb +79 -0
  8. data/lib/action_controller/assertions.rb +69 -0
  9. data/lib/action_controller/assertions/dom_assertions.rb +39 -0
  10. data/lib/action_controller/assertions/model_assertions.rb +20 -0
  11. data/lib/action_controller/assertions/response_assertions.rb +172 -0
  12. data/lib/action_controller/assertions/routing_assertions.rb +146 -0
  13. data/lib/action_controller/assertions/selector_assertions.rb +491 -0
  14. data/lib/action_controller/assertions/tag_assertions.rb +130 -0
  15. data/lib/action_controller/base.rb +1288 -0
  16. data/lib/action_controller/benchmarking.rb +94 -0
  17. data/lib/action_controller/caching.rb +72 -0
  18. data/lib/action_controller/caching/actions.rb +144 -0
  19. data/lib/action_controller/caching/fragments.rb +138 -0
  20. data/lib/action_controller/caching/pages.rb +154 -0
  21. data/lib/action_controller/caching/sql_cache.rb +18 -0
  22. data/lib/action_controller/caching/sweeping.rb +97 -0
  23. data/lib/action_controller/cgi_ext.rb +16 -0
  24. data/lib/action_controller/cgi_ext/cookie.rb +110 -0
  25. data/lib/action_controller/cgi_ext/query_extension.rb +22 -0
  26. data/lib/action_controller/cgi_ext/session.rb +73 -0
  27. data/lib/action_controller/cgi_ext/stdinput.rb +24 -0
  28. data/lib/action_controller/cgi_process.rb +223 -0
  29. data/lib/action_controller/components.rb +166 -0
  30. data/lib/action_controller/cookies.rb +96 -0
  31. data/lib/action_controller/dispatcher.rb +162 -0
  32. data/lib/action_controller/filters.rb +642 -0
  33. data/lib/action_controller/flash.rb +172 -0
  34. data/lib/action_controller/headers.rb +31 -0
  35. data/lib/action_controller/helpers.rb +221 -0
  36. data/lib/action_controller/http_authentication.rb +124 -0
  37. data/lib/action_controller/integration.rb +634 -0
  38. data/lib/action_controller/layout.rb +309 -0
  39. data/lib/action_controller/mime_responds.rb +173 -0
  40. data/lib/action_controller/mime_type.rb +186 -0
  41. data/lib/action_controller/mime_types.rb +20 -0
  42. data/lib/action_controller/polymorphic_routes.rb +191 -0
  43. data/lib/action_controller/record_identifier.rb +102 -0
  44. data/lib/action_controller/request.rb +764 -0
  45. data/lib/action_controller/request_forgery_protection.rb +140 -0
  46. data/lib/action_controller/request_profiler.rb +169 -0
  47. data/lib/action_controller/rescue.rb +258 -0
  48. data/lib/action_controller/resources.rb +572 -0
  49. data/lib/action_controller/response.rb +76 -0
  50. data/lib/action_controller/routing.rb +387 -0
  51. data/lib/action_controller/routing/builder.rb +203 -0
  52. data/lib/action_controller/routing/optimisations.rb +120 -0
  53. data/lib/action_controller/routing/recognition_optimisation.rb +162 -0
  54. data/lib/action_controller/routing/route.rb +240 -0
  55. data/lib/action_controller/routing/route_set.rb +436 -0
  56. data/lib/action_controller/routing/routing_ext.rb +46 -0
  57. data/lib/action_controller/routing/segments.rb +283 -0
  58. data/lib/action_controller/session/active_record_store.rb +340 -0
  59. data/lib/action_controller/session/cookie_store.rb +166 -0
  60. data/lib/action_controller/session/drb_server.rb +32 -0
  61. data/lib/action_controller/session/drb_store.rb +35 -0
  62. data/lib/action_controller/session/mem_cache_store.rb +98 -0
  63. data/lib/action_controller/session_management.rb +158 -0
  64. data/lib/action_controller/status_codes.rb +88 -0
  65. data/lib/action_controller/streaming.rb +155 -0
  66. data/lib/action_controller/templates/rescues/_request_and_response.erb +24 -0
  67. data/lib/action_controller/templates/rescues/_trace.erb +26 -0
  68. data/lib/action_controller/templates/rescues/diagnostics.erb +11 -0
  69. data/lib/action_controller/templates/rescues/layout.erb +29 -0
  70. data/lib/action_controller/templates/rescues/missing_template.erb +2 -0
  71. data/lib/action_controller/templates/rescues/routing_error.erb +10 -0
  72. data/lib/action_controller/templates/rescues/template_error.erb +21 -0
  73. data/lib/action_controller/templates/rescues/unknown_action.erb +2 -0
  74. data/lib/action_controller/test_case.rb +83 -0
  75. data/lib/action_controller/test_process.rb +526 -0
  76. data/lib/action_controller/url_rewriter.rb +142 -0
  77. data/lib/action_controller/vendor/html-scanner/html/document.rb +68 -0
  78. data/lib/action_controller/vendor/html-scanner/html/node.rb +537 -0
  79. data/lib/action_controller/vendor/html-scanner/html/sanitizer.rb +173 -0
  80. data/lib/action_controller/vendor/html-scanner/html/selector.rb +828 -0
  81. data/lib/action_controller/vendor/html-scanner/html/tokenizer.rb +105 -0
  82. data/lib/action_controller/vendor/html-scanner/html/version.rb +11 -0
  83. data/lib/action_controller/verification.rb +130 -0
  84. data/lib/action_pack.rb +24 -0
  85. data/lib/action_pack/version.rb +9 -0
  86. data/lib/action_view.rb +44 -0
  87. data/lib/action_view/base.rb +335 -0
  88. data/lib/action_view/helpers/active_record_helper.rb +276 -0
  89. data/lib/action_view/helpers/asset_tag_helper.rb +599 -0
  90. data/lib/action_view/helpers/atom_feed_helper.rb +143 -0
  91. data/lib/action_view/helpers/benchmark_helper.rb +33 -0
  92. data/lib/action_view/helpers/cache_helper.rb +40 -0
  93. data/lib/action_view/helpers/capture_helper.rb +161 -0
  94. data/lib/action_view/helpers/date_helper.rb +711 -0
  95. data/lib/action_view/helpers/debug_helper.rb +31 -0
  96. data/lib/action_view/helpers/form_helper.rb +767 -0
  97. data/lib/action_view/helpers/form_options_helper.rb +458 -0
  98. data/lib/action_view/helpers/form_tag_helper.rb +458 -0
  99. data/lib/action_view/helpers/javascript_helper.rb +148 -0
  100. data/lib/action_view/helpers/number_helper.rb +186 -0
  101. data/lib/action_view/helpers/record_identification_helper.rb +20 -0
  102. data/lib/action_view/helpers/record_tag_helper.rb +59 -0
  103. data/lib/action_view/helpers/sanitize_helper.rb +229 -0
  104. data/lib/action_view/helpers/tag_helper.rb +134 -0
  105. data/lib/action_view/helpers/text_helper.rb +507 -0
  106. data/lib/action_view/helpers/url_helper.rb +573 -0
  107. data/lib/action_view/inline_template.rb +20 -0
  108. data/lib/action_view/partial_template.rb +70 -0
  109. data/lib/action_view/partials.rb +158 -0
  110. data/lib/action_view/template.rb +125 -0
  111. data/lib/action_view/template_error.rb +110 -0
  112. data/lib/action_view/template_finder.rb +176 -0
  113. data/lib/action_view/template_handler.rb +34 -0
  114. data/lib/action_view/template_handlers/builder.rb +27 -0
  115. data/lib/action_view/template_handlers/compilable.rb +128 -0
  116. data/lib/action_view/template_handlers/erb.rb +56 -0
  117. data/lib/action_view/test_case.rb +58 -0
  118. data/lib/actionpack.rb +1 -0
  119. data/test/abstract_unit.rb +36 -0
  120. data/test/active_record_unit.rb +105 -0
  121. data/test/activerecord/active_record_store_test.rb +141 -0
  122. data/test/activerecord/render_partial_with_record_identification_test.rb +191 -0
  123. data/test/adv_attr_test.rb +20 -0
  124. data/test/controller/action_pack_assertions_test.rb +543 -0
  125. data/test/controller/addresses_render_test.rb +43 -0
  126. data/test/controller/assert_select_test.rb +331 -0
  127. data/test/controller/base_test.rb +219 -0
  128. data/test/controller/benchmark_test.rb +32 -0
  129. data/test/controller/caching_test.rb +581 -0
  130. data/test/controller/capture_test.rb +89 -0
  131. data/test/controller/cgi_test.rb +116 -0
  132. data/test/controller/components_test.rb +140 -0
  133. data/test/controller/content_type_test.rb +139 -0
  134. data/test/controller/controller_fixtures/app/controllers/admin/user_controller.rb +0 -0
  135. data/test/controller/controller_fixtures/app/controllers/user_controller.rb +0 -0
  136. data/test/controller/controller_fixtures/vendor/plugins/bad_plugin/lib/plugin_controller.rb +0 -0
  137. data/test/controller/cookie_test.rb +146 -0
  138. data/test/controller/custom_handler_test.rb +45 -0
  139. data/test/controller/deprecation/deprecated_base_methods_test.rb +37 -0
  140. data/test/controller/dispatcher_test.rb +105 -0
  141. data/test/controller/fake_controllers.rb +33 -0
  142. data/test/controller/fake_models.rb +11 -0
  143. data/test/controller/filter_params_test.rb +49 -0
  144. data/test/controller/filters_test.rb +881 -0
  145. data/test/controller/flash_test.rb +146 -0
  146. data/test/controller/header_test.rb +14 -0
  147. data/test/controller/helper_test.rb +210 -0
  148. data/test/controller/html-scanner/cdata_node_test.rb +15 -0
  149. data/test/controller/html-scanner/document_test.rb +148 -0
  150. data/test/controller/html-scanner/node_test.rb +89 -0
  151. data/test/controller/html-scanner/sanitizer_test.rb +269 -0
  152. data/test/controller/html-scanner/tag_node_test.rb +238 -0
  153. data/test/controller/html-scanner/text_node_test.rb +50 -0
  154. data/test/controller/html-scanner/tokenizer_test.rb +131 -0
  155. data/test/controller/http_authentication_test.rb +54 -0
  156. data/test/controller/integration_test.rb +252 -0
  157. data/test/controller/integration_upload_test.rb +43 -0
  158. data/test/controller/layout_test.rb +255 -0
  159. data/test/controller/mime_responds_test.rb +514 -0
  160. data/test/controller/mime_type_test.rb +84 -0
  161. data/test/controller/new_render_test.rb +843 -0
  162. data/test/controller/polymorphic_routes_test.rb +174 -0
  163. data/test/controller/record_identifier_test.rb +139 -0
  164. data/test/controller/redirect_test.rb +289 -0
  165. data/test/controller/render_test.rb +484 -0
  166. data/test/controller/request_forgery_protection_test.rb +305 -0
  167. data/test/controller/request_test.rb +928 -0
  168. data/test/controller/rescue_test.rb +517 -0
  169. data/test/controller/resources_test.rb +873 -0
  170. data/test/controller/routing_test.rb +2464 -0
  171. data/test/controller/selector_test.rb +628 -0
  172. data/test/controller/send_file_test.rb +138 -0
  173. data/test/controller/session/cookie_store_test.rb +258 -0
  174. data/test/controller/session/mem_cache_store_test.rb +181 -0
  175. data/test/controller/session_fixation_test.rb +89 -0
  176. data/test/controller/session_management_test.rb +178 -0
  177. data/test/controller/test_test.rb +695 -0
  178. data/test/controller/url_rewriter_test.rb +310 -0
  179. data/test/controller/verification_test.rb +270 -0
  180. data/test/controller/view_paths_test.rb +140 -0
  181. data/test/controller/webservice_test.rb +229 -0
  182. data/test/fixtures/addresses/list.erb +1 -0
  183. data/test/fixtures/bad_customers/_bad_customer.html.erb +1 -0
  184. data/test/fixtures/companies.yml +24 -0
  185. data/test/fixtures/company.rb +10 -0
  186. data/test/fixtures/content_type/render_default_content_types_for_respond_to.rhtml +1 -0
  187. data/test/fixtures/content_type/render_default_for_js.js.erb +1 -0
  188. data/test/fixtures/content_type/render_default_for_rhtml.rhtml +1 -0
  189. data/test/fixtures/content_type/render_default_for_rxml.rxml +1 -0
  190. data/test/fixtures/customers/_customer.html.erb +1 -0
  191. data/test/fixtures/db_definitions/sqlite.sql +49 -0
  192. data/test/fixtures/developer.rb +9 -0
  193. data/test/fixtures/developers.yml +21 -0
  194. data/test/fixtures/developers_projects.yml +13 -0
  195. data/test/fixtures/fun/games/hello_world.erb +1 -0
  196. data/test/fixtures/functional_caching/_partial.erb +3 -0
  197. data/test/fixtures/functional_caching/fragment_cached.html.erb +2 -0
  198. data/test/fixtures/functional_caching/html_fragment_cached_with_partial.html.erb +1 -0
  199. data/test/fixtures/functional_caching/js_fragment_cached_with_partial.js.rjs +1 -0
  200. data/test/fixtures/good_customers/_good_customer.html.erb +1 -0
  201. data/test/fixtures/helpers/abc_helper.rb +5 -0
  202. data/test/fixtures/helpers/fun/games_helper.rb +3 -0
  203. data/test/fixtures/helpers/fun/pdf_helper.rb +3 -0
  204. data/test/fixtures/layout_tests/alt/hello.rhtml +1 -0
  205. data/test/fixtures/layout_tests/layouts/controller_name_space/nested.rhtml +1 -0
  206. data/test/fixtures/layout_tests/layouts/item.rhtml +1 -0
  207. data/test/fixtures/layout_tests/layouts/layout_test.rhtml +1 -0
  208. data/test/fixtures/layout_tests/layouts/multiple_extensions.html.erb +1 -0
  209. data/test/fixtures/layout_tests/layouts/third_party_template_library.mab +1 -0
  210. data/test/fixtures/layout_tests/views/hello.rhtml +1 -0
  211. data/test/fixtures/layouts/block_with_layout.erb +3 -0
  212. data/test/fixtures/layouts/builder.builder +3 -0
  213. data/test/fixtures/layouts/partial_with_layout.erb +3 -0
  214. data/test/fixtures/layouts/standard.erb +1 -0
  215. data/test/fixtures/layouts/talk_from_action.erb +2 -0
  216. data/test/fixtures/layouts/yield.erb +2 -0
  217. data/test/fixtures/mascot.rb +3 -0
  218. data/test/fixtures/mascots.yml +4 -0
  219. data/test/fixtures/mascots/_mascot.html.erb +1 -0
  220. data/test/fixtures/multipart/binary_file +0 -0
  221. data/test/fixtures/multipart/boundary_problem_file +10 -0
  222. data/test/fixtures/multipart/bracketed_param +5 -0
  223. data/test/fixtures/multipart/large_text_file +10 -0
  224. data/test/fixtures/multipart/mixed_files +0 -0
  225. data/test/fixtures/multipart/mona_lisa.jpg +0 -0
  226. data/test/fixtures/multipart/single_parameter +5 -0
  227. data/test/fixtures/multipart/text_file +10 -0
  228. data/test/fixtures/override/test/hello_world.erb +1 -0
  229. data/test/fixtures/override2/layouts/test/sub.erb +1 -0
  230. data/test/fixtures/post_test/layouts/post.html.erb +1 -0
  231. data/test/fixtures/post_test/layouts/super_post.iphone.erb +1 -0
  232. data/test/fixtures/post_test/post/index.html.erb +1 -0
  233. data/test/fixtures/post_test/post/index.iphone.erb +1 -0
  234. data/test/fixtures/post_test/super_post/index.html.erb +1 -0
  235. data/test/fixtures/post_test/super_post/index.iphone.erb +1 -0
  236. data/test/fixtures/project.rb +3 -0
  237. data/test/fixtures/projects.yml +7 -0
  238. data/test/fixtures/public/404.html +1 -0
  239. data/test/fixtures/public/500.html +1 -0
  240. data/test/fixtures/public/images/rails.png +0 -0
  241. data/test/fixtures/public/javascripts/application.js +1 -0
  242. data/test/fixtures/public/javascripts/bank.js +1 -0
  243. data/test/fixtures/public/javascripts/robber.js +1 -0
  244. data/test/fixtures/public/javascripts/version.1.0.js +1 -0
  245. data/test/fixtures/public/stylesheets/bank.css +1 -0
  246. data/test/fixtures/public/stylesheets/robber.css +1 -0
  247. data/test/fixtures/public/stylesheets/version.1.0.css +1 -0
  248. data/test/fixtures/replies.yml +15 -0
  249. data/test/fixtures/reply.rb +7 -0
  250. data/test/fixtures/respond_to/all_types_with_layout.html.erb +1 -0
  251. data/test/fixtures/respond_to/custom_constant_handling_without_block.mobile.erb +1 -0
  252. data/test/fixtures/respond_to/iphone_with_html_response_type.html.erb +1 -0
  253. data/test/fixtures/respond_to/iphone_with_html_response_type.iphone.erb +1 -0
  254. data/test/fixtures/respond_to/layouts/missing.html.erb +1 -0
  255. data/test/fixtures/respond_to/layouts/standard.html.erb +1 -0
  256. data/test/fixtures/respond_to/layouts/standard.iphone.erb +1 -0
  257. data/test/fixtures/respond_to/using_defaults.html.erb +1 -0
  258. data/test/fixtures/respond_to/using_defaults.js.rjs +1 -0
  259. data/test/fixtures/respond_to/using_defaults.xml.builder +1 -0
  260. data/test/fixtures/respond_to/using_defaults_with_type_list.html.erb +1 -0
  261. data/test/fixtures/respond_to/using_defaults_with_type_list.js.rjs +1 -0
  262. data/test/fixtures/respond_to/using_defaults_with_type_list.xml.builder +1 -0
  263. data/test/fixtures/scope/test/modgreet.erb +1 -0
  264. data/test/fixtures/shared.html.erb +1 -0
  265. data/test/fixtures/symlink_parent/symlinked_layout.erb +5 -0
  266. data/test/fixtures/test/_customer.erb +1 -0
  267. data/test/fixtures/test/_customer_counter.erb +1 -0
  268. data/test/fixtures/test/_customer_greeting.erb +1 -0
  269. data/test/fixtures/test/_form.erb +1 -0
  270. data/test/fixtures/test/_hash_greeting.erb +1 -0
  271. data/test/fixtures/test/_hash_object.erb +2 -0
  272. data/test/fixtures/test/_hello.builder +1 -0
  273. data/test/fixtures/test/_labelling_form.erb +1 -0
  274. data/test/fixtures/test/_layout_for_partial.html.erb +3 -0
  275. data/test/fixtures/test/_partial.erb +1 -0
  276. data/test/fixtures/test/_partial.html.erb +1 -0
  277. data/test/fixtures/test/_partial.js.erb +1 -0
  278. data/test/fixtures/test/_partial_for_use_in_layout.html.erb +1 -0
  279. data/test/fixtures/test/_partial_only.erb +1 -0
  280. data/test/fixtures/test/_person.erb +2 -0
  281. data/test/fixtures/test/_raise.html.erb +1 -0
  282. data/test/fixtures/test/action_talk_to_layout.erb +2 -0
  283. data/test/fixtures/test/block_content_for.erb +2 -0
  284. data/test/fixtures/test/calling_partial_with_layout.html.erb +1 -0
  285. data/test/fixtures/test/capturing.erb +4 -0
  286. data/test/fixtures/test/content_for.erb +2 -0
  287. data/test/fixtures/test/content_for_concatenated.erb +3 -0
  288. data/test/fixtures/test/content_for_with_parameter.erb +2 -0
  289. data/test/fixtures/test/delete_with_js.rjs +2 -0
  290. data/test/fixtures/test/dot.directory/render_file_with_ivar.erb +1 -0
  291. data/test/fixtures/test/enum_rjs_test.rjs +6 -0
  292. data/test/fixtures/test/erb_content_for.erb +2 -0
  293. data/test/fixtures/test/formatted_html_erb.html.erb +1 -0
  294. data/test/fixtures/test/formatted_xml_erb.builder +1 -0
  295. data/test/fixtures/test/formatted_xml_erb.html.erb +1 -0
  296. data/test/fixtures/test/formatted_xml_erb.xml.erb +1 -0
  297. data/test/fixtures/test/greeting.erb +1 -0
  298. data/test/fixtures/test/greeting.js.rjs +1 -0
  299. data/test/fixtures/test/hello.builder +4 -0
  300. data/test/fixtures/test/hello_world.erb +1 -0
  301. data/test/fixtures/test/hello_world_container.builder +3 -0
  302. data/test/fixtures/test/hello_world_from_rxml.builder +4 -0
  303. data/test/fixtures/test/hello_world_with_layout_false.erb +1 -0
  304. data/test/fixtures/test/hello_xml_world.builder +11 -0
  305. data/test/fixtures/test/list.erb +1 -0
  306. data/test/fixtures/test/non_erb_block_content_for.builder +4 -0
  307. data/test/fixtures/test/potential_conflicts.erb +4 -0
  308. data/test/fixtures/test/render_file_from_template.html.erb +1 -0
  309. data/test/fixtures/test/render_file_with_ivar.erb +1 -0
  310. data/test/fixtures/test/render_file_with_locals.erb +1 -0
  311. data/test/fixtures/test/render_to_string_test.erb +1 -0
  312. data/test/fixtures/test/update_element_with_capture.erb +9 -0
  313. data/test/fixtures/test/using_layout_around_block.html.erb +1 -0
  314. data/test/fixtures/topic.rb +3 -0
  315. data/test/fixtures/topics.yml +22 -0
  316. data/test/fixtures/topics/_topic.html.erb +1 -0
  317. data/test/template/active_record_helper_test.rb +268 -0
  318. data/test/template/asset_tag_helper_test.rb +514 -0
  319. data/test/template/atom_feed_helper_test.rb +179 -0
  320. data/test/template/benchmark_helper_test.rb +60 -0
  321. data/test/template/date_helper_test.rb +1791 -0
  322. data/test/template/deprecated_erb_variable_test.rb +9 -0
  323. data/test/template/erb_util_test.rb +24 -0
  324. data/test/template/form_helper_test.rb +885 -0
  325. data/test/template/form_options_helper_test.rb +1333 -0
  326. data/test/template/form_tag_helper_test.rb +272 -0
  327. data/test/template/javascript_helper_test.rb +73 -0
  328. data/test/template/number_helper_test.rb +97 -0
  329. data/test/template/record_tag_helper_test.rb +54 -0
  330. data/test/template/sanitize_helper_test.rb +48 -0
  331. data/test/template/tag_helper_test.rb +77 -0
  332. data/test/template/template_finder_test.rb +73 -0
  333. data/test/template/template_object_test.rb +95 -0
  334. data/test/template/test_test.rb +56 -0
  335. data/test/template/text_helper_test.rb +367 -0
  336. data/test/template/url_helper_test.rb +544 -0
  337. data/test/testing_sandbox.rb +15 -0
  338. metadata +469 -0
@@ -0,0 +1,138 @@
1
+ require 'abstract_unit'
2
+
3
+
4
+ module TestFileUtils
5
+ def file_name() File.basename(__FILE__) end
6
+ def file_path() File.expand_path(__FILE__) end
7
+ def file_data() File.open(file_path, 'rb') { |f| f.read } end
8
+ end
9
+
10
+
11
+ class SendFileController < ActionController::Base
12
+ include TestFileUtils
13
+ layout "layouts/standard" # to make sure layouts don't interfere
14
+
15
+ attr_writer :options
16
+ def options() @options ||= {} end
17
+
18
+ def file() send_file(file_path, options) end
19
+ def data() send_data(file_data, options) end
20
+
21
+ def rescue_action(e) raise end
22
+ end
23
+
24
+ SendFileController.view_paths = [ File.dirname(__FILE__) + "/../fixtures/" ]
25
+
26
+ class SendFileTest < Test::Unit::TestCase
27
+ include TestFileUtils
28
+
29
+ Mime::Type.register "image/png", :png unless defined? Mime::PNG
30
+
31
+ def setup
32
+ @controller = SendFileController.new
33
+ @request = ActionController::TestRequest.new
34
+ @response = ActionController::TestResponse.new
35
+ end
36
+
37
+ def test_file_nostream
38
+ @controller.options = { :stream => false }
39
+ response = nil
40
+ assert_nothing_raised { response = process('file') }
41
+ assert_not_nil response
42
+ assert_kind_of String, response.body
43
+ assert_equal file_data, response.body
44
+ end
45
+
46
+ def test_file_stream
47
+ response = nil
48
+ assert_nothing_raised { response = process('file') }
49
+ assert_not_nil response
50
+ assert_kind_of Proc, response.body
51
+
52
+ require 'stringio'
53
+ output = StringIO.new
54
+ output.binmode
55
+ assert_nothing_raised { response.body.call(response, output) }
56
+ assert_equal file_data, output.string
57
+ end
58
+
59
+ def test_file_url_based_filename
60
+ @controller.options = { :url_based_filename => true }
61
+ response = nil
62
+ assert_nothing_raised { response = process('file') }
63
+ assert_not_nil response
64
+ assert_equal "attachment", response.headers["Content-Disposition"]
65
+ end
66
+
67
+ def test_x_sendfile_header
68
+ @controller.options = { :x_sendfile => true }
69
+
70
+ response = nil
71
+ assert_nothing_raised { response = process('file') }
72
+ assert_not_nil response
73
+
74
+ assert_equal @controller.file_path, response.headers['X-Sendfile']
75
+ assert response.body.blank?
76
+ end
77
+
78
+ def test_data
79
+ response = nil
80
+ assert_nothing_raised { response = process('data') }
81
+ assert_not_nil response
82
+
83
+ assert_kind_of String, response.body
84
+ assert_equal file_data, response.body
85
+ end
86
+
87
+ def test_headers_after_send_shouldnt_include_charset
88
+ response = process('data')
89
+ assert_equal "application/octet-stream", response.content_type
90
+
91
+ response = process('file')
92
+ assert_equal "application/octet-stream", response.content_type
93
+ end
94
+
95
+ # Test that send_file_headers! is setting the correct HTTP headers.
96
+ def test_send_file_headers!
97
+ options = {
98
+ :length => 1,
99
+ :type => Mime::PNG,
100
+ :disposition => 'disposition',
101
+ :filename => 'filename'
102
+ }
103
+
104
+ # Do it a few times: the resulting headers should be identical
105
+ # no matter how many times you send with the same options.
106
+ # Test resolving Ticket #458.
107
+ @controller.headers = {}
108
+ @controller.send(:send_file_headers!, options)
109
+ @controller.send(:send_file_headers!, options)
110
+ @controller.send(:send_file_headers!, options)
111
+
112
+ h = @controller.headers
113
+ assert_equal 1, h['Content-Length']
114
+ assert_equal 'image/png', h['Content-Type']
115
+ assert_equal 'disposition; filename="filename"', h['Content-Disposition']
116
+ assert_equal 'binary', h['Content-Transfer-Encoding']
117
+
118
+ # test overriding Cache-Control: no-cache header to fix IE open/save dialog
119
+ @controller.headers = { 'Cache-Control' => 'no-cache' }
120
+ @controller.send(:send_file_headers!, options)
121
+ h = @controller.headers
122
+ assert_equal 'private', h['Cache-Control']
123
+ end
124
+
125
+ %w(file data).each do |method|
126
+ define_method "test_send_#{method}_status" do
127
+ @controller.options = { :stream => false, :status => 500 }
128
+ assert_nothing_raised { assert_not_nil process(method) }
129
+ assert_equal '500 Internal Server Error', @response.headers['Status']
130
+ end
131
+
132
+ define_method "test_default_send_#{method}_status" do
133
+ @controller.options = { :stream => false }
134
+ assert_nothing_raised { assert_not_nil process(method) }
135
+ assert_equal ActionController::Base::DEFAULT_RENDER_STATUS_CODE, @response.headers['Status']
136
+ end
137
+ end
138
+ end
@@ -0,0 +1,258 @@
1
+ require 'abstract_unit'
2
+ require 'action_controller/cgi_process'
3
+ require 'action_controller/cgi_ext'
4
+
5
+ require 'stringio'
6
+
7
+
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)
14
+ end
15
+ end
16
+ alias_method_chain :ensure_secret_secure, :test_hax
17
+ end
18
+
19
+
20
+ # Expose for tests.
21
+ class CGI
22
+ attr_reader :output_cookies, :output_hidden
23
+
24
+ class Session
25
+ attr_reader :dbman
26
+
27
+ class CookieStore
28
+ attr_reader :data, :original, :cookie_options
29
+ end
30
+ end
31
+ end
32
+
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
+ end
41
+
42
+ def self.cookies
43
+ { :empty => ['BAgw--0686dcaccc01040f4bd4f35fe160afe9bc04c330', {}],
44
+ :a_one => ['BAh7BiIGYWkG--5689059497d7f122a7119f171aef81dcfd807fec', { 'a' => 1 }],
45
+ :typical => ['BAh7ByIMdXNlcl9pZGkBeyIKZmxhc2h7BiILbm90aWNlIgxIZXkgbm93--9d20154623b9eeea05c62ab819be0e2483238759', { 'user_id' => 123, 'flash' => { 'notice' => 'Hey now' }}],
46
+ :flashed => ['BAh7ByIMdXNlcl9pZGkBeyIKZmxhc2h7AA==--bf9785a666d3c4ac09f7fe3353496b437546cfbf', { 'user_id' => 123, 'flash' => {} }],
47
+ :double_escaped => [CGI.escape('BAh7ByIMdXNlcl9pZGkBeyIKZmxhc2h7AA%3D%3D--bf9785a666d3c4ac09f7fe3353496b437546cfbf'), { 'user_id' => 123, 'flash' => {} }] }
48
+
49
+ end
50
+
51
+ def setup
52
+ ENV.delete('HTTP_COOKIE')
53
+ end
54
+
55
+ def test_raises_argument_error_if_missing_session_key
56
+ [nil, ''].each do |blank|
57
+ assert_raise(ArgumentError, blank.inspect) { new_session 'session_key' => blank }
58
+ end
59
+ end
60
+
61
+ def test_raises_argument_error_if_missing_secret
62
+ [nil, ''].each do |blank|
63
+ assert_raise(ArgumentError, blank.inspect) { new_session 'secret' => blank }
64
+ end
65
+ end
66
+
67
+ def test_raises_argument_error_if_secret_is_probably_insecure
68
+ ["password", "secret", "12345678901234567890123456789"].each do |blank|
69
+ assert_raise(ArgumentError, blank.inspect) { new_session 'secret' => blank }
70
+ end
71
+ end
72
+
73
+ def test_reconfigures_session_to_omit_id_cookie_and_hidden_field
74
+ new_session do |session|
75
+ assert_equal true, @options['no_hidden']
76
+ assert_equal true, @options['no_cookies']
77
+ end
78
+ end
79
+
80
+ def test_restore_unmarshals_missing_cookie_as_empty_hash
81
+ new_session do |session|
82
+ assert_nil session.dbman.data
83
+ assert_nil session['test']
84
+ assert_equal Hash.new, session.dbman.data
85
+ end
86
+ end
87
+
88
+ def test_restore_unmarshals_good_cookies
89
+ cookies(:empty, :a_one, :typical).each do |value, expected|
90
+ set_cookie! value
91
+ new_session do |session|
92
+ assert_nil session['lazy loads the data hash']
93
+ assert_equal expected, session.dbman.data
94
+ end
95
+ end
96
+ end
97
+
98
+ def test_restore_deletes_tampered_cookies
99
+ set_cookie! 'a--b'
100
+ new_session do |session|
101
+ assert_raise(CGI::Session::CookieStore::TamperedWithCookie) { session['fail'] }
102
+ assert_cookie_deleted session
103
+ end
104
+ end
105
+
106
+ def test_restores_double_encoded_cookies
107
+ set_cookie! cookie_value(:double_escaped)
108
+ new_session do |session|
109
+ session.dbman.restore
110
+ assert_equal session["user_id"], 123
111
+ assert_equal session["flash"], {}
112
+ end
113
+ end
114
+
115
+ def test_close_doesnt_write_cookie_if_data_is_blank
116
+ new_session do |session|
117
+ assert_no_cookies session
118
+ session.close
119
+ assert_no_cookies session
120
+ end
121
+ end
122
+
123
+ def test_close_doesnt_write_cookie_if_data_is_unchanged
124
+ set_cookie! cookie_value(:typical)
125
+ new_session do |session|
126
+ assert_no_cookies session
127
+ session['user_id'] = session['user_id']
128
+ session.close
129
+ assert_no_cookies session
130
+ end
131
+ end
132
+
133
+ def test_close_raises_when_data_overflows
134
+ set_cookie! cookie_value(:empty)
135
+ new_session do |session|
136
+ session['overflow'] = 'bye!' * 1024
137
+ assert_raise(CGI::Session::CookieStore::CookieOverflow) { session.close }
138
+ assert_no_cookies session
139
+ end
140
+ end
141
+
142
+ def test_close_marshals_and_writes_cookie
143
+ set_cookie! cookie_value(:typical)
144
+ new_session do |session|
145
+ assert_no_cookies session
146
+ session['flash'] = {}
147
+ assert_no_cookies session
148
+ session.close
149
+ assert_equal 1, session.cgi.output_cookies.size
150
+ cookie = session.cgi.output_cookies.first
151
+ assert_cookie cookie, cookie_value(:flashed)
152
+ end
153
+ end
154
+
155
+ def test_delete_writes_expired_empty_cookie_and_sets_data_to_nil
156
+ set_cookie! cookie_value(:typical)
157
+ new_session do |session|
158
+ assert_no_cookies session
159
+ session.delete
160
+ assert_cookie_deleted session
161
+
162
+ # @data is set to nil so #close doesn't send another cookie.
163
+ session.close
164
+ assert_cookie_deleted session
165
+ end
166
+ end
167
+
168
+ def test_new_session_doesnt_reuse_deleted_cookie_data
169
+ set_cookie! cookie_value(:typical)
170
+
171
+ new_session do |session|
172
+ assert_not_nil session['user_id']
173
+ session.delete
174
+
175
+ # Start a new session using the same CGI instance.
176
+ post_delete_session = CGI::Session.new(session.cgi, self.class.default_session_options)
177
+ assert_nil post_delete_session['user_id']
178
+ end
179
+ end
180
+
181
+ private
182
+ def assert_no_cookies(session)
183
+ assert_nil session.cgi.output_cookies, session.cgi.output_cookies.inspect
184
+ end
185
+
186
+ def assert_cookie_deleted(session, message = 'Expected session deletion cookie to be set')
187
+ assert_equal 1, session.cgi.output_cookies.size
188
+ cookie = session.cgi.output_cookies.first
189
+ assert_cookie cookie, nil, 1.year.ago.to_date, "#{message}: #{cookie.name} => #{cookie.value}"
190
+ end
191
+
192
+ def assert_cookie(cookie, value = nil, expires = nil, message = nil)
193
+ assert_equal '_myapp_session', cookie.name, message
194
+ assert_equal [value].compact, cookie.value, message
195
+ assert_equal expires, cookie.expires ? cookie.expires.to_date : cookie.expires, message
196
+ end
197
+
198
+
199
+ def cookies(*which)
200
+ self.class.cookies.values_at(*which)
201
+ end
202
+
203
+ def cookie_value(which)
204
+ self.class.cookies[which].first
205
+ end
206
+
207
+ def set_cookie!(value)
208
+ ENV['HTTP_COOKIE'] = "_myapp_session=#{value}"
209
+ end
210
+
211
+ def new_session(options = {})
212
+ with_cgi do |cgi|
213
+ assert_nil cgi.output_hidden, "Output hidden params should be empty: #{cgi.output_hidden.inspect}"
214
+ assert_nil cgi.output_cookies, "Output cookies should be empty: #{cgi.output_cookies.inspect}"
215
+
216
+ @options = self.class.default_session_options.merge(options)
217
+ session = CGI::Session.new(cgi, @options)
218
+
219
+ assert_nil cgi.output_hidden, "Output hidden params should be empty: #{cgi.output_hidden.inspect}"
220
+ assert_nil cgi.output_cookies, "Output cookies should be empty: #{cgi.output_cookies.inspect}"
221
+
222
+ yield session if block_given?
223
+ session
224
+ end
225
+ end
226
+
227
+ def with_cgi
228
+ ENV['REQUEST_METHOD'] = 'GET'
229
+ ENV['HTTP_HOST'] = 'example.com'
230
+ ENV['QUERY_STRING'] = ''
231
+
232
+ cgi = CGI.new('query', StringIO.new(''))
233
+ yield cgi if block_given?
234
+ cgi
235
+ end
236
+ end
237
+
238
+
239
+ class CookieStoreWithBlockAsSecretTest < CookieStoreTest
240
+ def self.default_session_options
241
+ CookieStoreTest.default_session_options.merge 'secret' => Proc.new { 'Keep it secret; keep it safe.' }
242
+ end
243
+ end
244
+
245
+
246
+ class CookieStoreWithMD5DigestTest < CookieStoreTest
247
+ def self.default_session_options
248
+ CookieStoreTest.default_session_options.merge 'digest' => 'MD5'
249
+ end
250
+
251
+ def self.cookies
252
+ { :empty => ['BAgw--0415cc0be9579b14afc22ee2d341aa21', {}],
253
+ :a_one => ['BAh7BiIGYWkG--5a0ed962089cc6600ff44168a5d59bc8', { 'a' => 1 }],
254
+ :typical => ['BAh7ByIMdXNlcl9pZGkBeyIKZmxhc2h7BiILbm90aWNlIgxIZXkgbm93--f426763f6ef435b3738b493600db8d64', { 'user_id' => 123, 'flash' => { 'notice' => 'Hey now' }}],
255
+ :flashed => ['BAh7ByIMdXNlcl9pZGkBeyIKZmxhc2h7AA==--0af9156650dab044a53a91a4ddec2c51', { 'user_id' => 123, 'flash' => {} }],
256
+ :double_escaped => [CGI.escape('BAh7ByIMdXNlcl9pZGkBeyIKZmxhc2h7AA%3D%3D--0af9156650dab044a53a91a4ddec2c51'), { 'user_id' => 123, 'flash' => {} }] }
257
+ end
258
+ end
@@ -0,0 +1,181 @@
1
+ require 'abstract_unit'
2
+ require 'action_controller/cgi_process'
3
+ require 'action_controller/cgi_ext'
4
+
5
+
6
+ class CGI::Session
7
+ def cache
8
+ dbman.instance_variable_get(:@cache)
9
+ end
10
+ end
11
+
12
+
13
+ uses_mocha 'MemCacheStore tests' do
14
+ if defined? MemCache::MemCacheError
15
+
16
+ class MemCacheStoreTest < Test::Unit::TestCase
17
+ SESSION_KEY_RE = /^session:[0-9a-z]+/
18
+ CONN_TEST_KEY = 'connection_test'
19
+ MULTI_TEST_KEY = '0123456789'
20
+ TEST_DATA = 'Hello test'
21
+
22
+ def self.get_mem_cache_if_available
23
+ begin
24
+ require 'memcache'
25
+ cache = MemCache.new('127.0.0.1')
26
+ # Test availability of the connection
27
+ cache.set(CONN_TEST_KEY, 1)
28
+ unless cache.get(CONN_TEST_KEY) == 1
29
+ puts 'Warning: memcache server available but corrupted.'
30
+ return nil
31
+ end
32
+ rescue LoadError, MemCache::MemCacheError
33
+ return nil
34
+ end
35
+ return cache
36
+ end
37
+
38
+ CACHE = get_mem_cache_if_available
39
+
40
+
41
+ def test_initialization
42
+ assert_raise(ArgumentError) { new_session('session_id' => '!invalid_id') }
43
+ new_session do |s|
44
+ assert_equal Hash.new, s.cache.get('session:' + s.session_id)
45
+ end
46
+ end
47
+
48
+
49
+ def test_storage
50
+ d = rand(0xffff)
51
+ new_session do |s|
52
+ session_key = 'session:' + s.session_id
53
+ unless CACHE
54
+ s.cache.expects(:get).with(session_key) \
55
+ .returns(:test => d)
56
+ s.cache.expects(:set).with(session_key,
57
+ has_entry(:test, d),
58
+ 0)
59
+ end
60
+ s[:test] = d
61
+ s.close
62
+ assert_equal d, s.cache.get(session_key)[:test]
63
+ assert_equal d, s[:test]
64
+ end
65
+ end
66
+
67
+ def test_deletion
68
+ new_session do |s|
69
+ session_key = 'session:' + s.session_id
70
+ unless CACHE
71
+ s.cache.expects(:delete)
72
+ s.cache.expects(:get).with(session_key) \
73
+ .returns(nil)
74
+ end
75
+ s[:test] = rand(0xffff)
76
+ s.delete
77
+ assert_nil s.cache.get(session_key)
78
+ end
79
+ end
80
+
81
+
82
+ def test_other_session_retrieval
83
+ new_session do |sa|
84
+ unless CACHE
85
+ sa.cache.expects(:set).with('session:' + sa.session_id,
86
+ has_entry(:test, TEST_DATA),
87
+ 0)
88
+ end
89
+ sa[:test] = TEST_DATA
90
+ sa.close
91
+ new_session('session_id' => sa.session_id) do |sb|
92
+ unless CACHE
93
+ sb.cache.expects(:[]).with('session:' + sb.session_id) \
94
+ .returns(:test => TEST_DATA)
95
+ end
96
+ assert_equal(TEST_DATA, sb[:test])
97
+ end
98
+ end
99
+ end
100
+
101
+
102
+ def test_multiple_sessions
103
+ s_slots = Array.new(10)
104
+ operation = :write
105
+ last_data = nil
106
+ reads = writes = 0
107
+ 50.times do
108
+ current = rand(10)
109
+ s_slots[current] ||= new_session('session_id' => MULTI_TEST_KEY,
110
+ 'new_session' => true)
111
+ s = s_slots[current]
112
+ case operation
113
+ when :write
114
+ last_data = rand(0xffff)
115
+ unless CACHE
116
+ s.cache.expects(:set).with('session:' + MULTI_TEST_KEY,
117
+ { :test => last_data },
118
+ 0)
119
+ end
120
+ s[:test] = last_data
121
+ s.close
122
+ writes += 1
123
+ when :read
124
+ # Make CGI::Session#[] think there was no data retrieval yet.
125
+ # Normally, the session caches the data during its lifetime.
126
+ s.instance_variable_set(:@data, nil)
127
+ unless CACHE
128
+ s.cache.expects(:[]).with('session:' + MULTI_TEST_KEY) \
129
+ .returns(:test => last_data)
130
+ end
131
+ d = s[:test]
132
+ assert_equal(last_data, d, "OK reads: #{reads}, OK writes: #{writes}")
133
+ reads += 1
134
+ end
135
+ operation = rand(5) == 0 ? :write : :read
136
+ end
137
+ end
138
+
139
+
140
+
141
+ private
142
+ def obtain_session_options
143
+ options = { 'database_manager' => CGI::Session::MemCacheStore,
144
+ 'session_key' => '_test_app_session'
145
+ }
146
+ # if don't have running memcache server we use mock instead
147
+ unless CACHE
148
+ options['cache'] = c = mock
149
+ c.stubs(:[]).with(regexp_matches(SESSION_KEY_RE))
150
+ c.stubs(:get).with(regexp_matches(SESSION_KEY_RE)) \
151
+ .returns(Hash.new)
152
+ c.stubs(:add).with(regexp_matches(SESSION_KEY_RE),
153
+ instance_of(Hash),
154
+ 0)
155
+ end
156
+ options
157
+ end
158
+
159
+
160
+ def new_session(options = {})
161
+ with_cgi do |cgi|
162
+ @options = obtain_session_options.merge(options)
163
+ session = CGI::Session.new(cgi, @options)
164
+ yield session if block_given?
165
+ return session
166
+ end
167
+ end
168
+
169
+ def with_cgi
170
+ ENV['REQUEST_METHOD'] = 'GET'
171
+ ENV['HTTP_HOST'] = 'example.com'
172
+ ENV['QUERY_STRING'] = ''
173
+
174
+ cgi = CGI.new('query', StringIO.new(''))
175
+ yield cgi if block_given?
176
+ cgi
177
+ end
178
+ end
179
+
180
+ end # defined? MemCache
181
+ end # uses_mocha