actionpack 1.9.1 → 1.10.1

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 (123) hide show
  1. data/CHANGELOG +237 -0
  2. data/README +12 -12
  3. data/lib/action_controller.rb +17 -12
  4. data/lib/action_controller/assertions.rb +119 -67
  5. data/lib/action_controller/base.rb +184 -102
  6. data/lib/action_controller/benchmarking.rb +35 -6
  7. data/lib/action_controller/caching.rb +115 -58
  8. data/lib/action_controller/cgi_ext/cgi_methods.rb +54 -21
  9. data/lib/action_controller/cgi_ext/cookie_performance_fix.rb +39 -35
  10. data/lib/action_controller/cgi_ext/raw_post_data_fix.rb +34 -21
  11. data/lib/action_controller/cgi_process.rb +23 -20
  12. data/lib/action_controller/components.rb +11 -2
  13. data/lib/action_controller/dependencies.rb +0 -5
  14. data/lib/action_controller/deprecated_redirects.rb +17 -0
  15. data/lib/action_controller/filters.rb +13 -9
  16. data/lib/action_controller/flash.rb +7 -7
  17. data/lib/action_controller/helpers.rb +1 -14
  18. data/lib/action_controller/layout.rb +40 -29
  19. data/lib/action_controller/macros/auto_complete.rb +52 -0
  20. data/lib/action_controller/macros/in_place_editing.rb +32 -0
  21. data/lib/action_controller/pagination.rb +44 -28
  22. data/lib/action_controller/request.rb +54 -40
  23. data/lib/action_controller/rescue.rb +8 -6
  24. data/lib/action_controller/routing.rb +77 -28
  25. data/lib/action_controller/scaffolding.rb +10 -14
  26. data/lib/action_controller/session/active_record_store.rb +36 -7
  27. data/lib/action_controller/session_management.rb +126 -0
  28. data/lib/action_controller/streaming.rb +14 -5
  29. data/lib/action_controller/templates/rescues/_request_and_response.rhtml +1 -1
  30. data/lib/action_controller/templates/rescues/_trace.rhtml +24 -0
  31. data/lib/action_controller/templates/rescues/diagnostics.rhtml +2 -13
  32. data/lib/action_controller/templates/rescues/template_error.rhtml +4 -2
  33. data/lib/action_controller/templates/scaffolds/list.rhtml +1 -1
  34. data/lib/action_controller/test_process.rb +35 -17
  35. data/lib/action_controller/upload_progress.rb +52 -0
  36. data/lib/action_controller/url_rewriter.rb +21 -16
  37. data/lib/action_controller/vendor/html-scanner/html/document.rb +2 -2
  38. data/lib/action_controller/vendor/html-scanner/html/node.rb +30 -3
  39. data/lib/action_pack/version.rb +9 -0
  40. data/lib/action_view.rb +1 -1
  41. data/lib/action_view/base.rb +204 -60
  42. data/lib/action_view/compiled_templates.rb +70 -0
  43. data/lib/action_view/helpers/active_record_helper.rb +7 -3
  44. data/lib/action_view/helpers/asset_tag_helper.rb +22 -12
  45. data/lib/action_view/helpers/capture_helper.rb +2 -10
  46. data/lib/action_view/helpers/date_helper.rb +21 -13
  47. data/lib/action_view/helpers/form_helper.rb +14 -10
  48. data/lib/action_view/helpers/form_options_helper.rb +4 -4
  49. data/lib/action_view/helpers/form_tag_helper.rb +59 -25
  50. data/lib/action_view/helpers/java_script_macros_helper.rb +188 -0
  51. data/lib/action_view/helpers/javascript_helper.rb +68 -133
  52. data/lib/action_view/helpers/javascripts/controls.js +427 -165
  53. data/lib/action_view/helpers/javascripts/dragdrop.js +256 -277
  54. data/lib/action_view/helpers/javascripts/effects.js +766 -277
  55. data/lib/action_view/helpers/javascripts/prototype.js +906 -218
  56. data/lib/action_view/helpers/javascripts/slider.js +258 -0
  57. data/lib/action_view/helpers/number_helper.rb +4 -3
  58. data/lib/action_view/helpers/pagination_helper.rb +42 -27
  59. data/lib/action_view/helpers/tag_helper.rb +25 -11
  60. data/lib/action_view/helpers/text_helper.rb +119 -13
  61. data/lib/action_view/helpers/upload_progress_helper.rb +2 -2
  62. data/lib/action_view/helpers/url_helper.rb +68 -21
  63. data/lib/action_view/partials.rb +17 -6
  64. data/lib/action_view/template_error.rb +19 -24
  65. data/rakefile +4 -3
  66. data/test/abstract_unit.rb +2 -1
  67. data/test/controller/action_pack_assertions_test.rb +62 -2
  68. data/test/controller/active_record_assertions_test.rb +5 -6
  69. data/test/controller/active_record_store_test.rb +23 -1
  70. data/test/controller/addresses_render_test.rb +4 -0
  71. data/test/controller/{base_tests.rb → base_test.rb} +4 -3
  72. data/test/controller/benchmark_test.rb +36 -0
  73. data/test/controller/caching_filestore.rb +22 -40
  74. data/test/controller/capture_test.rb +10 -1
  75. data/test/controller/cgi_test.rb +145 -23
  76. data/test/controller/components_test.rb +50 -0
  77. data/test/controller/custom_handler_test.rb +3 -3
  78. data/test/controller/fake_controllers.rb +24 -0
  79. data/test/controller/filters_test.rb +6 -6
  80. data/test/controller/flash_test.rb +6 -6
  81. data/test/controller/fragment_store_setting_test.rb +45 -0
  82. data/test/controller/helper_test.rb +1 -3
  83. data/test/controller/new_render_test.rb +119 -7
  84. data/test/controller/redirect_test.rb +11 -1
  85. data/test/controller/render_test.rb +34 -1
  86. data/test/controller/request_test.rb +14 -5
  87. data/test/controller/routing_test.rb +238 -42
  88. data/test/controller/send_file_test.rb +11 -10
  89. data/test/controller/session_management_test.rb +94 -0
  90. data/test/controller/test_test.rb +194 -5
  91. data/test/controller/url_rewriter_test.rb +46 -0
  92. data/test/fixtures/layouts/talk_from_action.rhtml +2 -0
  93. data/test/fixtures/layouts/yield.rhtml +2 -0
  94. data/test/fixtures/multipart/binary_file +0 -0
  95. data/test/fixtures/multipart/large_text_file +10 -0
  96. data/test/fixtures/multipart/mixed_files +0 -0
  97. data/test/fixtures/multipart/single_parameter +5 -0
  98. data/test/fixtures/multipart/text_file +10 -0
  99. data/test/fixtures/test/_customer_greeting.rhtml +1 -0
  100. data/test/fixtures/test/_hash_object.rhtml +1 -0
  101. data/test/fixtures/test/_person.rhtml +2 -0
  102. data/test/fixtures/test/action_talk_to_layout.rhtml +2 -0
  103. data/test/fixtures/test/content_for.rhtml +2 -0
  104. data/test/fixtures/test/potential_conflicts.rhtml +4 -0
  105. data/test/template/active_record_helper_test.rb +15 -8
  106. data/test/template/asset_tag_helper_test.rb +40 -16
  107. data/test/template/compiled_templates_tests.rb +63 -0
  108. data/test/template/date_helper_test.rb +80 -4
  109. data/test/template/form_helper_test.rb +48 -42
  110. data/test/template/form_options_helper_test.rb +40 -40
  111. data/test/template/form_tag_helper_test.rb +21 -15
  112. data/test/template/java_script_macros_helper_test.rb +56 -0
  113. data/test/template/javascript_helper_test.rb +70 -47
  114. data/test/template/number_helper_test.rb +2 -0
  115. data/test/template/tag_helper_test.rb +9 -0
  116. data/test/template/text_helper_test.rb +146 -1
  117. data/test/template/upload_progress_helper_testx.rb +11 -147
  118. data/test/template/url_helper_test.rb +90 -22
  119. data/test/testing_sandbox.rb +26 -0
  120. metadata +37 -7
  121. data/lib/action_controller/auto_complete.rb +0 -47
  122. data/lib/action_controller/deprecated_renders_and_redirects.rb +0 -76
  123. data/lib/action_controller/session.rb +0 -14
@@ -53,6 +53,7 @@ module CommonActiveRecordStoreTests
53
53
  @new_session.close
54
54
  end
55
55
  end
56
+
56
57
  end
57
58
 
58
59
  class ActiveRecordStoreTest < Test::Unit::TestCase
@@ -77,6 +78,28 @@ class ActiveRecordStoreTest < Test::Unit::TestCase
77
78
  end
78
79
  end
79
80
 
81
+ class ColumnLimitTest < Test::Unit::TestCase
82
+
83
+ def setup
84
+ @session_class = CGI::Session::ActiveRecordStore::Session
85
+ @session_class.create_table!
86
+ end
87
+
88
+ def teardown
89
+ @session_class.drop_table!
90
+ end
91
+
92
+ def test_protection_from_data_larger_than_column
93
+ # Can't test this unless there is a limit
94
+ return unless limit = @session_class.data_column_size_limit
95
+ too_big = ':(' * limit
96
+ s = @session_class.new(:session_id => '666', :data => {'foo' => too_big})
97
+ s.data
98
+ assert_raises(ActionController::SessionOverflowError) { s.save }
99
+ end
100
+
101
+ end
102
+
80
103
 
81
104
  class DeprecatedActiveRecordStoreTest < ActiveRecordStoreTest
82
105
  def setup
@@ -94,7 +117,6 @@ class DeprecatedActiveRecordStoreTest < ActiveRecordStoreTest
94
117
  def teardown
95
118
  session_class.connection.execute 'drop table old_sessions'
96
119
  session_class.table_name = 'sessions'
97
- session_class.send :setup_sessid_compatibility!
98
120
  end
99
121
  end
100
122
 
@@ -9,6 +9,10 @@ class Address
9
9
  def Address.find_all(arg1, arg2, arg3, arg4)
10
10
  []
11
11
  end
12
+
13
+ def self.find(*args)
14
+ []
15
+ end
12
16
  end
13
17
 
14
18
  class AddressesTestController < ActionController::Base
@@ -1,5 +1,6 @@
1
1
  require File.dirname(__FILE__) + '/../abstract_unit'
2
2
  require 'test/unit'
3
+ require 'pp' # require 'pp' early to prevent hidden_methods from not picking up the pretty-print methods until too late
3
4
 
4
5
  # This file currently contains a few controller UTs
5
6
  # I couldn't find where the current base tests are, so I created this file.
@@ -63,10 +64,10 @@ class ControllerInstanceTests < Test::Unit::TestCase
63
64
 
64
65
  @non_empty_controllers = [Controllers::NonEmptyController.new,
65
66
  Controllers::Submodule::ContainedNonEmptyController.new]
66
-
67
67
  end
68
+
68
69
  def test_action_methods
69
- @empty_controllers.each {|c| assert_equal [], c.send(:action_methods), "#{c.class.controller_path} should be empty!"}
70
- @non_empty_controllers.each {|c| assert_equal ["public_action"], c.send(:action_methods), "#{c.class.controller_path} should not be empty!"}
70
+ @empty_controllers.each {|c| assert_equal({}, c.send(:action_methods), "#{c.class.controller_path} should be empty!")}
71
+ @non_empty_controllers.each {|c| assert_equal({"public_action"=>true}, c.send(:action_methods), "#{c.class.controller_path} should not be empty!")}
71
72
  end
72
73
  end
@@ -0,0 +1,36 @@
1
+ require File.dirname(__FILE__) + '/../abstract_unit'
2
+ require 'test/unit'
3
+
4
+ # Provide a static version of the Controllers module instead of the auto-loading version.
5
+ # We don't want these tests to fail when dependencies are to blame.
6
+ module Controllers
7
+ class BenchmarkedController < ActionController::Base
8
+ def public_action
9
+ render :nothing => true
10
+ end
11
+
12
+ def rescue_action(e)
13
+ raise e
14
+ end
15
+ end
16
+ end
17
+
18
+ class BenchmarkTest < Test::Unit::TestCase
19
+ class MockLogger
20
+ def method_missing(*args)
21
+ end
22
+ end
23
+
24
+ def setup
25
+ @controller = Controllers::BenchmarkedController.new
26
+ # benchmark doesn't do anything unless a logger is set
27
+ @controller.logger = MockLogger.new
28
+ @request, @response = ActionController::TestRequest.new, ActionController::TestResponse.new
29
+ @request.host = "test.actioncontroller.i"
30
+ end
31
+
32
+ def test_with_http_1_0_request
33
+ @request.host = nil
34
+ assert_nothing_raised { get :public_action }
35
+ end
36
+ end
@@ -1,16 +1,15 @@
1
1
  require 'fileutils'
2
2
  require File.dirname(__FILE__) + '/../abstract_unit'
3
3
 
4
- #generate the greatest logging class that ever lived
5
4
  class TestLogDevice < Logger::LogDevice
6
5
  attr :last_message, true
7
6
 
8
7
  def initialize
9
- @last_message=String.new
8
+ @last_message=String.new
10
9
  end
11
10
 
12
11
  def write(message)
13
- @last_message << message
12
+ @last_message << message
14
13
  end
15
14
 
16
15
  def clear
@@ -23,14 +22,13 @@ TestLog = TestLogDevice.new
23
22
  RAILS_DEFAULT_LOGGER = Logger.new(TestLog)
24
23
  ActionController::Base.logger = RAILS_DEFAULT_LOGGER
25
24
 
26
- #generate a random key to ensure the cache is always in a different location
27
- RANDOM_KEY = rand(99999999).to_s
28
- FILE_STORE_PATH = File.dirname(__FILE__) + '/../temp/' + RANDOM_KEY
29
- ActionController::Base.perform_caching = true
30
- ActionController::Base.fragment_cache_store = ActionController::Caching::Fragments::FileStore.new(FILE_STORE_PATH)
31
-
32
- #setup the routing information...not sure if this does anything
33
- ActionController::Routing::Routes.connect "test", :controller => 'test', :action => 'render_to_cache'
25
+ def use_store
26
+ #generate a random key to ensure the cache is always in a different location
27
+ RANDOM_KEY = rand(99999999).to_s
28
+ FILE_STORE_PATH = File.dirname(__FILE__) + '/../temp/' + RANDOM_KEY
29
+ ActionController::Base.perform_caching = true
30
+ ActionController::Base.fragment_cache_store = :file_store, FILE_STORE_PATH
31
+ end
34
32
 
35
33
  class TestController < ActionController::Base
36
34
  caches_action :render_to_cache, :index
@@ -45,48 +43,32 @@ class FileStoreTest < Test::Unit::TestCase
45
43
  def setup
46
44
  @request = ActionController::TestRequest.new
47
45
  @response = ActionController::TestResponse.new
46
+ @controller = TestController.new
48
47
  @request.host = "hostname.com"
49
48
  end
50
-
51
- #To prime the cache with hostname.com/test
52
- def test_render_to_cache_prime_a
53
- @request.path_parameters = {:controller => "test"}
54
- assert_fragment_cached do process_request end
55
- end
56
-
57
- #To prime the cache with hostname.com/test/render_to_cache
58
- def test_render_to_cache_prime_b
59
- @request.path_parameters = {:action => "render_to_cache", :controller => "test"}
60
- assert_fragment_cached do process_request end
49
+
50
+ def teardown
51
+ FileUtils.rm_rf(FILE_STORE_PATH)
61
52
  end
62
53
 
63
- #To hit the cache with hostname.com/test
64
- def test_render_to_cache_zhit_a
65
- @request.path_parameters = {:controller => "test"}
66
- assert_fragment_hit do process_request end
54
+ def test_render_cached
55
+ assert_fragment_cached { get :render_to_cache }
56
+ assert_fragment_hit { get :render_to_cache }
67
57
  end
68
58
 
69
- #To hit the cache with hostname.com/test/render_to_cache
70
- def test_render_to_cache_zhit_b
71
- @request.path_parameters = {:action => "render_to_cache", :controller => "test"}
72
- assert_fragment_hit do process_request end
73
- end
74
59
 
75
60
  private
76
- def process_request
77
- TestController.process(@request, @response)
78
- end
79
-
80
- def assert_fragment_cached(&proc)
81
- proc.call
61
+ def assert_fragment_cached
62
+ yield
82
63
  assert(TestLog.last_message.include?("Cached fragment:"), "--ERROR-- FileStore write failed ----")
83
64
  assert(!TestLog.last_message.include?("Couldn't create cache directory:"), "--ERROR-- FileStore create directory failed ----")
84
65
  TestLog.clear
85
66
  end
86
67
 
87
- def assert_fragment_hit(&proc)
88
- proc.call
89
- assert(TestLog.last_message.include?( "Fragment hit:"), "--ERROR-- Fragment not found in FileStore ----")
68
+ def assert_fragment_hit
69
+ yield
70
+ assert(TestLog.last_message.include?("Fragment read:"), "--ERROR-- Fragment not found in FileStore ----")
71
+ assert(!TestLog.last_message.include?("Cached fragment:"), "--ERROR-- Did cache ----")
90
72
  TestLog.clear
91
73
  end
92
74
  end
@@ -4,6 +4,10 @@ class CaptureController < ActionController::Base
4
4
  def self.controller_name; "test"; end
5
5
  def self.controller_path; "test"; end
6
6
 
7
+ def content_for
8
+ render :layout => "talk_from_action"
9
+ end
10
+
7
11
  def rescue_action(e) raise end
8
12
  end
9
13
 
@@ -27,11 +31,16 @@ class CaptureTest < Test::Unit::TestCase
27
31
  get :capturing
28
32
  assert_equal "Dreamy days", @response.body.strip
29
33
  end
34
+
35
+ def test_content_for
36
+ get :content_for
37
+ assert_equal "<title>Putting stuff in the title!</title>\n\nGreat stuff!", @response.body
38
+ end
30
39
 
31
40
  def test_update_element_with_capture
32
41
  get :update_element_with_capture
33
42
  assert_equal(
34
- "<script type=\"text/javascript\">$('products').innerHTML = '\\n <p>Product 1</p>\\n <p>Product 2</p>\\n';\n</script>" +
43
+ "<script type=\"text/javascript\">\n//<![CDATA[\n$('products').innerHTML = '\\n <p>Product 1</p>\\n <p>Product 2</p>\\n';\n\n//]]>\n</script>" +
35
44
  "\n\n$('status').innerHTML = '\\n <b>You bought something!</b>\\n';",
36
45
  @response.body.strip
37
46
  )
@@ -1,18 +1,9 @@
1
- $:.unshift File.dirname(__FILE__) + "/../../lib"
1
+ require File.dirname(__FILE__) + '/../abstract_unit'
2
+ require 'action_controller/cgi_process'
3
+ require 'action_controller/cgi_ext/cgi_ext'
2
4
 
3
- require 'test/unit'
4
- require 'action_controller/cgi_ext/cgi_methods'
5
- require 'stringio'
6
-
7
- class MockUploadedFile < StringIO
8
- def content_type
9
- "img/jpeg"
10
- end
11
5
 
12
- def original_filename
13
- "my_file.doc"
14
- end
15
- end
6
+ require 'stringio'
16
7
 
17
8
  class CGITest < Test::Unit::TestCase
18
9
  def setup
@@ -24,6 +15,8 @@ class CGITest < Test::Unit::TestCase
24
15
  "action=update_order&full_name=Lau%20Taarnskov&products=4&products=2&products=3"
25
16
  @query_string_with_many_equal = "action=create_customer&full_name=abc=def=ghi"
26
17
  @query_string_without_equal = "action"
18
+ @query_string_with_many_ampersands =
19
+ "&action=create_customer&&&full_name=David%20Heinemeier%20Hansson"
27
20
  end
28
21
 
29
22
  def test_query_string
@@ -76,7 +69,14 @@ class CGITest < Test::Unit::TestCase
76
69
  CGIMethods.parse_query_parameters(@query_string_without_equal)
77
70
  )
78
71
  end
79
-
72
+
73
+ def test_query_string_with_many_ampersands
74
+ assert_equal(
75
+ { "action" => "create_customer", "full_name" => "David Heinemeier Hansson"},
76
+ CGIMethods.parse_query_parameters(@query_string_with_many_ampersands)
77
+ )
78
+ end
79
+
80
80
  def test_parse_params
81
81
  input = {
82
82
  "customers[boston][first][name]" => [ "David" ],
@@ -116,15 +116,20 @@ class CGITest < Test::Unit::TestCase
116
116
  end
117
117
 
118
118
  def test_parse_params_from_multipart_upload
119
- mock_file = MockUploadedFile.new
119
+ mockup = Struct.new(:content_type, :original_filename)
120
+ file = mockup.new('img/jpeg', 'foo.jpg')
121
+ ie_file = mockup.new('img/jpeg', 'c:\\Documents and Settings\\foo\\Desktop\\bar.jpg')
120
122
 
121
123
  input = {
122
124
  "something" => [ StringIO.new("") ],
123
125
  "array_of_stringios" => [[ StringIO.new("One"), StringIO.new("Two") ]],
124
126
  "mixed_types_array" => [[ StringIO.new("Three"), "NotStringIO" ]],
125
- "mixed_types_as_checkboxes[strings][nested]" => [[ mock_file, "String", StringIO.new("StringIO")]],
127
+ "mixed_types_as_checkboxes[strings][nested]" => [[ file, "String", StringIO.new("StringIO")]],
128
+ "ie_mixed_types_as_checkboxes[strings][nested]" => [[ ie_file, "String", StringIO.new("StringIO")]],
126
129
  "products[string]" => [ StringIO.new("Apple Computer") ],
127
- "products[file]" => [ mock_file ]
130
+ "products[file]" => [ file ],
131
+ "ie_products[string]" => [ StringIO.new("Microsoft") ],
132
+ "ie_products[file]" => [ ie_file ]
128
133
  }
129
134
 
130
135
  expected_output = {
@@ -132,17 +137,35 @@ class CGITest < Test::Unit::TestCase
132
137
  "array_of_stringios" => ["One", "Two"],
133
138
  "mixed_types_array" => [ "Three", "NotStringIO" ],
134
139
  "mixed_types_as_checkboxes" => {
135
- "strings"=> {
136
- "nested"=>[ mock_file, "String", "StringIO" ]
140
+ "strings" => {
141
+ "nested" => [ file, "String", "StringIO" ]
137
142
  },
138
143
  },
139
- "products" => {
140
- "string" => "Apple Computer",
141
- "file" => mock_file
144
+ "ie_mixed_types_as_checkboxes" => {
145
+ "strings" => {
146
+ "nested" => [ ie_file, "String", "StringIO" ]
147
+ },
148
+ },
149
+ "products" => {
150
+ "string" => "Apple Computer",
151
+ "file" => file
152
+ },
153
+ "ie_products" => {
154
+ "string" => "Microsoft",
155
+ "file" => ie_file
142
156
  }
143
157
  }
144
158
 
145
- assert_equal expected_output, CGIMethods.parse_request_parameters(input)
159
+ params = CGIMethods.parse_request_parameters(input)
160
+ assert_equal expected_output, params
161
+
162
+ # Lone filenames are preserved.
163
+ assert_equal 'foo.jpg', params['mixed_types_as_checkboxes']['strings']['nested'].first.original_filename
164
+ assert_equal 'foo.jpg', params['products']['file'].original_filename
165
+
166
+ # But full Windows paths are reduced to their basename.
167
+ assert_equal 'bar.jpg', params['ie_mixed_types_as_checkboxes']['strings']['nested'].first.original_filename
168
+ assert_equal 'bar.jpg', params['ie_products']['file'].original_filename
146
169
  end
147
170
 
148
171
  def test_parse_params_with_file
@@ -206,3 +229,102 @@ class CGITest < Test::Unit::TestCase
206
229
  end
207
230
  end
208
231
 
232
+ class MultipartCGITest < Test::Unit::TestCase
233
+ FIXTURE_PATH = File.dirname(__FILE__) + '/../fixtures/multipart'
234
+
235
+ def setup
236
+ ENV['REQUEST_METHOD'] = 'POST'
237
+ ENV['CONTENT_LENGTH'] = '0'
238
+ ENV['CONTENT_TYPE'] = 'multipart/form-data, boundary=AaB03x'
239
+ end
240
+
241
+ def test_single_parameter
242
+ params = process('single_parameter')
243
+ assert_equal({ 'foo' => 'bar' }, params)
244
+ end
245
+
246
+ def test_text_file
247
+ params = process('text_file')
248
+ assert_equal %w(file foo), params.keys.sort
249
+ assert_equal 'bar', params['foo']
250
+
251
+ file = params['file']
252
+ assert_kind_of StringIO, file
253
+ assert_equal 'file.txt', file.original_filename
254
+ assert_equal "text/plain\r", file.content_type
255
+ assert_equal 'contents', file.read
256
+ end
257
+
258
+ def test_large_text_file
259
+ params = process('large_text_file')
260
+ assert_equal %w(file foo), params.keys.sort
261
+ assert_equal 'bar', params['foo']
262
+
263
+ file = params['file']
264
+ assert_kind_of Tempfile, file
265
+ assert_equal 'file.txt', file.original_filename
266
+ assert_equal "text/plain\r", file.content_type
267
+ assert ('a' * 20480) == file.read
268
+ end
269
+
270
+ def test_binary_file
271
+ params = process('binary_file')
272
+ assert_equal %w(file flowers foo), params.keys.sort
273
+ assert_equal 'bar', params['foo']
274
+
275
+ file = params['file']
276
+ assert_kind_of StringIO, file
277
+ assert_equal 'file.txt', file.original_filename
278
+ assert_equal "text/plain\r", file.content_type
279
+ assert_equal 'contents', file.read
280
+
281
+ file = params['flowers']
282
+ assert_kind_of StringIO, file
283
+ assert_equal 'flowers.jpg', file.original_filename
284
+ assert_equal "image/jpeg\r", file.content_type
285
+ assert_equal 19512, file.size
286
+ #assert_equal File.read(File.dirname(__FILE__) + '/../../../activerecord/test/fixtures/flowers.jpg'), file.read
287
+ end
288
+
289
+ def test_mixed_files
290
+ params = process('mixed_files')
291
+ assert_equal %w(files foo), params.keys.sort
292
+ assert_equal 'bar', params['foo']
293
+
294
+ # Ruby CGI doesn't handle multipart/mixed for us.
295
+ assert_kind_of StringIO, params['files']
296
+ assert_equal 19756, params['files'].size
297
+ end
298
+
299
+ private
300
+ def process(name)
301
+ old_stdin = $stdin
302
+ File.open(File.join(FIXTURE_PATH, name), 'rb') do |file|
303
+ ENV['CONTENT_LENGTH'] = file.stat.size.to_s
304
+ $stdin = file
305
+ CGIMethods.parse_request_parameters CGI.new.params
306
+ end
307
+ ensure
308
+ $stdin = old_stdin
309
+ end
310
+ end
311
+
312
+
313
+ class CGIRequestTest < Test::Unit::TestCase
314
+ def setup
315
+ @request_hash = {"HTTP_MAX_FORWARDS"=>"10", "SERVER_NAME"=>"glu.ttono.us:8007", "FCGI_ROLE"=>"RESPONDER", "HTTP_X_FORWARDED_HOST"=>"glu.ttono.us", "HTTP_ACCEPT_ENCODING"=>"gzip, deflate", "HTTP_USER_AGENT"=>"Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en) AppleWebKit/312.5.1 (KHTML, like Gecko) Safari/312.3.1", "PATH_INFO"=>"", "HTTP_ACCEPT_LANGUAGE"=>"en", "HTTP_HOST"=>"glu.ttono.us:8007", "SERVER_PROTOCOL"=>"HTTP/1.1", "REDIRECT_URI"=>"/dispatch.fcgi", "SCRIPT_NAME"=>"/dispatch.fcgi", "SERVER_ADDR"=>"207.7.108.53", "REMOTE_ADDR"=>"207.7.108.53", "SERVER_SOFTWARE"=>"lighttpd/1.4.5", "HTTP_COOKIE"=>"_session_id=c84ace84796670c052c6ceb2451fb0f2; is_admin=yes", "HTTP_X_FORWARDED_SERVER"=>"glu.ttono.us", "REQUEST_URI"=>"/admin", "DOCUMENT_ROOT"=>"/home/kevinc/sites/typo/public", "SERVER_PORT"=>"8007", "QUERY_STRING"=>"", "REMOTE_PORT"=>"63137", "GATEWAY_INTERFACE"=>"CGI/1.1", "HTTP_X_FORWARDED_FOR"=>"65.88.180.234", "HTTP_ACCEPT"=>"*/*", "SCRIPT_FILENAME"=>"/home/kevinc/sites/typo/public/dispatch.fcgi", "REDIRECT_STATUS"=>"200", "REQUEST_METHOD"=>"GET"}
316
+ @fake_cgi = Struct.new(:env_table).new(@request_hash)
317
+ @request = ActionController::CgiRequest.new(@fake_cgi)
318
+ end
319
+
320
+ def test_proxy_request
321
+ assert_equal 'glu.ttono.us', @request.host_with_port
322
+ end
323
+
324
+ def test_http_host
325
+ @request_hash.delete "HTTP_X_FORWARDED_HOST"
326
+ @request_hash['HTTP_HOST'] = "rubyonrails.org:8080"
327
+ assert_equal "rubyonrails.org:8080", @request.host_with_port
328
+ end
329
+
330
+ end