multipart_progress_testx.rb
上传用户:netsea168
上传日期:2022-07-22
资源大小:4652k
文件大小:10k
源码类别:

Ajax

开发平台:

Others

  1. require 'logger'
  2. require 'test/unit'
  3. require 'cgi'
  4. require 'stringio'
  5. DEBUG=false
  6. def test_logger
  7.   if DEBUG then ActionController::Base.logger = Logger.new(STDERR)
  8.   else ActionController::Base.logger = Logger.new(StringIO.new)
  9.   end
  10. end
  11. # Provide a static version of the Controllers module instead of the auto-loading version.
  12. # We don't want these tests to fail when dependencies are to blame.
  13. module Controllers
  14.   class EmptyController < ActionController::Base
  15.   end
  16.   class ApplicationController < ActionController::Base
  17.   end
  18.   class MockController < ActionController::Base
  19.     def initialize
  20.       super
  21.       @session = {:uploads => {}}
  22.       @params = {}
  23.     end
  24.   end
  25.   
  26.   class SingleUploadController < ActionController::Base
  27.     upload_status_for   :one
  28.     
  29.     def one; end
  30.   end
  31.   class DoubleUploadController < ActionController::Base
  32.     upload_status_for   :one, :two
  33.     
  34.     def one; end
  35.     def two; end
  36.   end
  37.   
  38.   class DoubleStatusUploadController < ActionController::Base
  39.     upload_status_for   :one, :two, :status => :custom_status
  40.     
  41.     def one; end
  42.     def two; end
  43.   end
  44.   
  45.   class DoubleSeperateController < ActionController::Base
  46.     upload_status_for :one
  47.     upload_status_for :two
  48.     
  49.     def one; end    
  50.     def two; end
  51.   end  
  52.   
  53.   class UploadController < ActionController::Base
  54.     upload_status_for   :norendered, :rendered, :redirected, :finish_param_dict, :finish_param_string, :finish_param_number
  55.     
  56.     def norendered 
  57.     end
  58.       
  59.     def rendered
  60.       render_text("rendered")
  61.     end
  62.     
  63.     def redirected
  64.       redirect_to "/redirected/"
  65.     end
  66.     
  67.     def finish_param_dict
  68.       finish_upload_status "{a: 'b'}"
  69.     end
  70.     def finish_param_string
  71.       finish_upload_status "'a string'"
  72.     end
  73.     def finish_param_number
  74.       finish_upload_status 123
  75.     end
  76.     def finish_param_number_redirect
  77.       redirect_to "/redirected/"
  78.       finish_upload_status 123
  79.     end
  80.   end
  81. end
  82. class MockIO < StringIO
  83.   def initialize(data='', &block)
  84.     test_logger.debug("MockIO inializing data: #{data[0..20]}")
  85.     @block = block
  86.     super(data)
  87.   end
  88.   def write(data)
  89.     test_logger.debug("MockIO write #{data.size} data: #{data[0..20]}")
  90.     super
  91.   end
  92.   def read(size)
  93.     test_logger.debug("MockIO getting data from super")
  94.     data = super
  95.     test_logger.debug("Calling read callback")
  96.     @block.call 
  97.     test_logger.debug("Returning data: #{data.size}")
  98.     data
  99.   end
  100. end
  101. class MockCGI < CGI
  102.   BOUNDARY = '----------0xKhTmLbOuNdArY'
  103.   FILENAME = 'dummy.nul'
  104.   attr_reader :upload_id, :session_options, :session_id
  105.   def initialize(size=1000, url='/test', &block)
  106.     @url = url
  107.     @env = {}
  108.     @sio = MockIO.new('') { block.call(self) if block_given? }
  109.     @upload_id = '1'
  110.     add_param('param1', 'value1')
  111.     add_data(size)
  112.     add_param('param1', 'value2')
  113.     add_end_boundary
  114.     init_env
  115.     @sio.rewind
  116.     super()
  117.   end
  118.   #def stdinput_without_progress
  119.   #  @sio
  120.   #end
  121.   def stdinput
  122.     @sio
  123.   end
  124.   
  125.   def env_table
  126.     @env
  127.   end
  128.   private
  129.   def init_env
  130.     @env['HTTP_HOST'] = 'localhost'
  131.     @env['SERVER_PORT'] = '80'
  132.     @env['REQUEST_METHOD'] = "POST"
  133.     @env['QUERY_STRING'] = @url.split('?')[1] || "upload_id=#{upload_id}&query_param=query_value"
  134.     @env['REQUEST_URI'] = @url
  135.     @env['SCRIPT_NAME'] = @url.split('?').first.split('/').last
  136.     @env['PATH_INFO'] = @url.split('?').first
  137.     @env['CONTENT_TYPE'] = "multipart/form-data; boundary=#{BOUNDARY}"
  138.     @env['CONTENT_LENGTH'] = @sio.tell - EOL.size
  139.     @session_options = ActionController::CgiRequest::DEFAULT_SESSION_OPTIONS.inject({}) { |options, pair| 
  140.       options[pair.first.to_s] = pair.last; options 
  141.     }
  142.     session = CGI::Session.new({}, @session_options.merge({'new_session' => true}))
  143.     @session_id = session.session_id
  144.     @env['COOKIE'] = "_session_id=#{session.session_id}"
  145.     session.close
  146.   end
  147.   def add_param(name, value)
  148.     add_boundary
  149.     @sio << "Content-Disposition: form-data; name="#{name}"" << EOL << EOL
  150.     @sio << value.to_s << EOL
  151.   end
  152.   def add_data(size)
  153.     add_boundary
  154.     @sio << "Content-Disposition: form-data; name="file"; filename="#{FILENAME}"" << EOL
  155.     @sio << "Content-Type: application/octet-stream" << EOL << EOL
  156.     @sio << "." * size
  157.     @sio << EOL
  158.   end
  159.   def add_boundary
  160.     @sio << "--" << BOUNDARY << EOL
  161.   end
  162.   def add_end_boundary
  163.     @sio << "--" << BOUNDARY << "--" << EOL
  164.   end
  165. end
  166. class MultipartProgressTest < Test::Unit::TestCase
  167.   
  168.   def test_domain_language_single
  169.     c = Controllers::SingleUploadController.new
  170.     assert_respond_to(c, :one)
  171.     assert_respond_to(c, :upload_status)
  172.     assert_respond_to(c, :finish_upload_status)
  173.   end
  174.   
  175.   def test_domain_language_double
  176.     c = Controllers::DoubleUploadController.new
  177.     assert_respond_to(c, :one)
  178.     assert_respond_to(c, :two)
  179.     assert_respond_to(c, :upload_status)
  180.     assert_respond_to(c, :finish_upload_status)
  181.   end
  182.     
  183.   def test_domain_language_double_status
  184.     c = Controllers::DoubleStatusUploadController.new
  185.     assert_respond_to(c, :one)
  186.     assert_respond_to(c, :two)
  187.     assert_respond_to(c, :custom_status)
  188.     assert_respond_to(c, :finish_upload_status)
  189.   end
  190.     
  191.   def test_domain_language_double_seperate
  192.     c = Controllers::DoubleSeperateController.new
  193.     assert_respond_to(c, :one)
  194.     assert_respond_to(c, :two)
  195.     assert_respond_to(c, :upload_status)
  196.     assert_respond_to(c, :finish_upload_status)
  197.   end
  198.   def test_finish_status_norendered
  199.     # Fails to render the upload finish script because there is no view associated with this action
  200.     test_logger.debug('test_finish_status_norendered')
  201.     res = process(:action => 'norendered', :upload_id => 1)
  202.     assert_match(/ActionView::ActionViewError/s, res.body)
  203.     
  204.     res = process(:action => :upload_status, :upload_id => 1)
  205.     assert_match(/Upload finished/s, res.body)
  206.     res = process(:action => :norendered)
  207.     assert_match(/ActionView::ActionViewError/s, res.body)
  208.   end
  209.   def test_finish_status_rendered
  210.     test_logger.debug('test_finish_status_rendered')
  211.     res = process(:action => :rendered, :upload_id => 1)
  212.     assert_match(/stop()/s, res.body)
  213.     assert_no_match(/rendered/s, res.body)
  214.     
  215.     res = process(:action => :upload_status, :upload_id => 1)
  216.     assert_match(/Upload finished/s, res.body)
  217.     
  218.     res = process(:action => :rendered)
  219.     assert_no_match(/stop()/s, res.body)
  220.     assert_match(/rendered/, res.body)
  221.   end 
  222.   
  223.   def test_finish_status_redirected
  224.     test_logger.debug('test_finish_status_redirected')
  225.     res = process(:action => :redirected, :upload_id => 1)
  226.     assert_match(/location.replace/s, res.body)
  227.     
  228.     res = process(:action => :redirected)
  229.     assert_no_match(/location.replace/s, res.body)
  230.     assert_match(//redirected//s, res.headers['location'])
  231.     assert_match(/302 .*$/, res.headers['Status'])
  232.     res = process(:action => :upload_status, :upload_id => 1)
  233.     assert_match(/Upload finished/s, res.body)
  234.   end
  235.   
  236.   def test_finish_status_finish_param
  237.     test_logger.debug('test_finish_status_param')
  238.     res = process(:action => :finish_param_string, :upload_id => 1)
  239.     assert_match(/stop('a string')/s, res.body)
  240.     assert_no_redirect res
  241.     res = process(:action => :finish_param_dict, :upload_id => 1)
  242.     assert_match(/stop({a: 'b'})/s, res.body)
  243.     assert_no_redirect res
  244.     res = process(:action => :finish_param_number, :upload_id => 1)
  245.     assert_match(/stop(123)/s, res.body)
  246.     assert_no_redirect res
  247.     res = process(:action => :finish_param_number_redirect, :upload_id => 1)
  248.     test_logger.debug('test_finish_status_param: ' + res.body)
  249.     assert_match(/stop(123)/s, res.body)
  250.     assert_match(/replace('http://localhost/redirected/').*?/s, res.body)
  251.     assert_no_redirect res
  252.   end
  253.   
  254.   def test_basic_setup
  255.     test_logger.debug('test_basic_setup')
  256.     cgi, request, response = new_request(100000)
  257.     assert_not_nil(request.session)
  258.     assert_not_nil(request.session[:uploads], "uploads collection not set")
  259.     assert_not_nil(request.session[:uploads][cgi.upload_id], "upload id not set")
  260.     progress = request.session[:uploads][cgi.upload_id]
  261.     assert_equal(true, progress.finished?)
  262.   end
  263.   def test_params
  264.     test_logger.debug('test_params')
  265.     cgi, request, response = new_request(1000)
  266.     assert(!request.params.empty?)
  267.     assert(!request.params['param1'].empty?)
  268.   end
  269.   def test_share_session
  270.     cgi, request, response = new_request(100000) do |cgi, req|
  271.       if cgi.stdinput.tell > 50000
  272.         # force a save
  273.         cgi.stdinput.save_progress rescue flunk('Something else is wrong, our wrapper isnt setup, is ActionController::Base.logger set?')
  274.         other_session = CGI::Session.new(cgi, cgi.session_options.merge({'session_id' => cgi.session_id}))
  275.         assert_not_nil(other_session[:uploads])
  276.         assert_not_nil(other_session[:uploads][cgi.upload_id])
  277.         assert_in_delta(cgi.stdinput.session[:uploads][cgi.upload_id].bitrate, other_session[:uploads][cgi.upload_id].bitrate, 1000.0, "Seperate session does not share data from original session")
  278.         other_session.close
  279.       end
  280.     end
  281.   end
  282.   def test_upload_ids
  283.     c = Controllers::MockController.new
  284.     (1..222).each do |id|
  285.       c.params = {}
  286.       assert_equal((id-1).to_s, c.last_upload_id, "last_upload_id is out of sync")
  287.       assert_equal(id.to_s, c.next_upload_id, "next_upload_id is out of sync")
  288.       assert_equal(id.to_s, c.current_upload_id, "current_upload_id is out of sync")
  289.       c.params = {:upload_id => (id-1).to_s}
  290.       assert_equal((id-1).to_s, c.current_upload_id, "current_upload_id is out of sync")
  291.       c.session[:uploads][id] = {}
  292.     end
  293.   end
  294.   private
  295.   def new_request(size=1000, url='/test', &block)
  296.     test_logger.debug('Creating MockCGI')
  297.     cgi = MockCGI.new(size, url) do |cgi|
  298.       block.call(cgi) if block_given?
  299.     end
  300.     assert(cgi.private_methods.include?("read_multipart_with_progress")) 
  301.     return [cgi, ActionController::CgiRequest.new(cgi), ActionController::CgiResponse.new(cgi)]
  302.   end
  303.   def process(options = {})
  304.     Controllers::UploadController.process(*(new_request(1000, '/upload?' + options.map {|k,v| "#{k}=#{v}"}.join('&'))[1..2]))
  305.   end
  306.   def assert_no_redirect(res)
  307.     assert_nil(res.redirected_to)
  308.     assert_nil(res.headers['location'])
  309.     assert_match(/200 .*$/, res.headers['Status'])
  310.   end
  311. end