wicked_pdf icon indicating copy to clipboard operation
wicked_pdf copied to clipboard

SystemStackError with rspec in 1.4.0

Open thomasbalsloev opened this issue 5 years ago • 3 comments

Issue description

Hi @unixmonkey

I've hit a new instance of "stack level too deep" even with the new 1.4.0 (also happens in 1.2.2). This time it does not to involve the "remotipart" gem but just the "WickedPDF" gem.

Funny thing is that this exception only happens in rspec tests of endpoints which performs HTML rendering and not PDF. So when requesting the same endpoint in normal (non-testing) mode it works without problems.

It seems like an edge case but never the less it breaks our test suite and we can't be sure our stuff works.

Reverting to "WickedPDF" version 1.1.0 makes the exception go away.

Example of failing endpoint:

def export_data
    respond_to do |format|
      format.html {
        # export data and check errors
        return false if common_export === false
        render layout: 'msp_export', template: 'msp/export'
      }
      format.any { head :unsupported_media_type }
    end
  end

The above "render" command is the line 258 referred to in the backtrace below.

Simplified Rspec code:

it 'should render html with correct data' do
      expect(subject).to receive(:render)
        .with(hash_including(layout: 'msp_export', template: 'msp/export'))
        .and_call_original
      get :export_data, params: {
        :target => 'computers',
        :clients => [16],
        :fields => ['client_name', 'name']
      }, :format => :html
      expect(subject.instance_variable_get(:@data)).to eq([{:name => 'LaptopZ1', :is_online => false, :client_name => client.name}])
    end

Exception:

... (this goes on and on)...

    # /home/tb/.rvm/gems/ruby-2.6.2@rails51/gems/wicked_pdf-1.2.2/lib/wicked_pdf/pdf_helper.rb:46:in `call'
     # /home/tb/.rvm/gems/ruby-2.6.2@rails51/gems/wicked_pdf-1.2.2/lib/wicked_pdf/pdf_helper.rb:46:in `render_with_wicked_pdf'
     # /home/tb/.rvm/gems/ruby-2.6.2@rails51/gems/wicked_pdf-1.2.2/lib/wicked_pdf/pdf_helper.rb:30:in `render'
     # /home/tb/.rvm/gems/ruby-2.6.2@rails51/gems/wicked_pdf-1.2.2/lib/wicked_pdf/pdf_helper.rb:46:in `call'
     # /home/tb/.rvm/gems/ruby-2.6.2@rails51/gems/wicked_pdf-1.2.2/lib/wicked_pdf/pdf_helper.rb:46:in `render_with_wicked_pdf'
     # /home/tb/.rvm/gems/ruby-2.6.2@rails51/gems/wicked_pdf-1.2.2/lib/wicked_pdf/pdf_helper.rb:30:in `render'
     # /home/tb/.rvm/gems/ruby-2.6.2@rails51/gems/wicked_pdf-1.2.2/lib/wicked_pdf/pdf_helper.rb:46:in `call'
     # /home/tb/.rvm/gems/ruby-2.6.2@rails51/gems/wicked_pdf-1.2.2/lib/wicked_pdf/pdf_helper.rb:46:in `render_with_wicked_pdf'
     # /home/tb/.rvm/gems/ruby-2.6.2@rails51/gems/wicked_pdf-1.2.2/lib/wicked_pdf/pdf_helper.rb:30:in `render'
     # ./app/controllers/msp/clients_controller.rb:258:in `block (2 levels) in export_data'
     # /home/tb/.rvm/gems/ruby-2.6.2@rails51/gems/actionpack-5.1.7/lib/action_controller/metal/mime_responds.rb:201:in `respond_to'
     # ./app/controllers/msp/clients_controller.rb:247:in `export_data'
     # /home/tb/.rvm/gems/ruby-2.6.2@rails51/gems/actionpack-5.1.7/lib/action_controller/metal/basic_implicit_render.rb:4:in `send_action'
     # /home/tb/.rvm/gems/ruby-2.6.2@rails51/gems/actionpack-5.1.7/lib/abstract_controller/base.rb:186:in `process_action'
     # /home/tb/.rvm/gems/ruby-2.6.2@rails51/gems/actionpack-5.1.7/lib/action_controller/metal/rendering.rb:30:in `process_action'
     # /home/tb/.rvm/gems/ruby-2.6.2@rails51/gems/actionpack-5.1.7/lib/abstract_controller/callbacks.rb:20:in `block in process_action'
     # /home/tb/.rvm/gems/ruby-2.6.2@rails51/gems/activesupport-5.1.7/lib/active_support/callbacks.rb:131:in `run_callbacks'
     # /home/tb/.rvm/gems/ruby-2.6.2@rails51/gems/actionpack-5.1.7/lib/abstract_controller/callbacks.rb:19:in `process_action'
     # /home/tb/.rvm/gems/ruby-2.6.2@rails51/gems/actionpack-5.1.7/lib/action_controller/metal/rescue.rb:20:in `process_action'
     # /home/tb/.rvm/gems/ruby-2.6.2@rails51/gems/actionpack-5.1.7/lib/action_controller/metal/instrumentation.rb:32:in `block in process_action'
     # /home/tb/.rvm/gems/ruby-2.6.2@rails51/gems/activesupport-5.1.7/lib/active_support/notifications.rb:166:in `block in instrument'
     # /home/tb/.rvm/gems/ruby-2.6.2@rails51/gems/activesupport-5.1.7/lib/active_support/notifications/instrumenter.rb:21:in `instrument'
     # /home/tb/.rvm/gems/ruby-2.6.2@rails51/gems/activesupport-5.1.7/lib/active_support/notifications.rb:166:in `instrument'
     # /home/tb/.rvm/gems/ruby-2.6.2@rails51/gems/actionpack-5.1.7/lib/action_controller/metal/instrumentation.rb:30:in `process_action'
     # /home/tb/.rvm/gems/ruby-2.6.2@rails51/gems/actionpack-5.1.7/lib/action_controller/metal/params_wrapper.rb:252:in `process_action'
     # /home/tb/.rvm/gems/ruby-2.6.2@rails51/gems/activerecord-5.1.7/lib/active_record/railties/controller_runtime.rb:22:in `process_action'
     # /home/tb/.rvm/gems/ruby-2.6.2@rails51/gems/actionpack-5.1.7/lib/abstract_controller/base.rb:124:in `process'
     # /home/tb/.rvm/gems/ruby-2.6.2@rails51/gems/actionview-5.1.7/lib/action_view/rendering.rb:30:in `process'
     # /home/tb/.rvm/gems/ruby-2.6.2@rails51/gems/actionpack-5.1.7/lib/action_controller/metal.rb:189:in `dispatch'
     # /home/tb/.rvm/gems/ruby-2.6.2@rails51/gems/actionpack-5.1.7/lib/action_controller/test_case.rb:513:in `process'
     # /home/tb/.rvm/gems/ruby-2.6.2@rails51/gems/rails-controller-testing-1.0.4/lib/rails/controller/testing/template_assertions.rb:61:in `process'
     # /home/tb/.rvm/gems/ruby-2.6.2@rails51/gems/devise-4.6.2/lib/devise/test/controller_helpers.rb:35:in `block in process'
     # /home/tb/.rvm/gems/ruby-2.6.2@rails51/gems/devise-4.6.2/lib/devise/test/controller_helpers.rb:102:in `catch'
     # /home/tb/.rvm/gems/ruby-2.6.2@rails51/gems/devise-4.6.2/lib/devise/test/controller_helpers.rb:102:in `_catch_warden'
     # /home/tb/.rvm/gems/ruby-2.6.2@rails51/gems/devise-4.6.2/lib/devise/test/controller_helpers.rb:35:in `process'
     # /home/tb/.rvm/gems/ruby-2.6.2@rails51/gems/actionpack-5.1.7/lib/action_controller/test_case.rb:392:in `get'
     # /home/tb/.rvm/gems/ruby-2.6.2@rails51/gems/rails-controller-testing-1.0.4/lib/rails/controller/testing/integration.rb:13:in `block (2 levels) in <module:Integration>'
     # ./spec/controllers/msp/clients_controller_spec.rb:429:in `block (3 levels) in <top (required)>'

UPDATE:

Debugging I found that "method(:render).super_method" in "/home/tb/.rvm/gems/ruby-2.6.2@rails51/gems/wicked_pdf-1.2.2/lib/wicked_pdf/pdf_helper.rb:46:in `call'" returns: #<Method: WickedPdf::PdfHelper#render> which is the immediate cause of the loop.

Expected or desired behavior

No exception should be raised.

System specifications

Ruby: ruby 2.6.2p47 (2019-03-13 revision 67232) [x86_64-linux]

Rails: 5.1.7

Rspec:

ci_reporter_rspec (1.0.0)
    rspec (>= 2.14, < 4)
  rspec (3.8.0)
    rspec-core (~> 3.8.0)
    rspec-expectations (~> 3.8.0)
    rspec-mocks (~> 3.8.0)
  rspec-collection_matchers (1.1.3)
    rspec-expectations (>= 2.99.0.beta1)
  rspec-core (3.8.2)
    rspec-support (~> 3.8.0)
  rspec-expectations (3.8.4)
    rspec-support (~> 3.8.0)
  rspec-mocks (3.8.1)
    rspec-support (~> 3.8.0)
  rspec-rails (3.8.2)
    rspec-core (~> 3.8.0)
    rspec-expectations (~> 3.8.0)
    rspec-mocks (~> 3.8.0)
    rspec-support (~> 3.8.0)
  rspec-sidekiq (3.0.3)
    rspec-core (~> 3.0, >= 3.0.0)
  rspec-support (3.8.2)
  rspec_junit_formatter (0.4.1)
    rspec-core (>= 2, < 4, != 2.12.0)
ci_reporter_rspec
rspec
rspec-collection_matchers
rspec-rails
rspec-sidekiq (>= 2.2.0)
rspec_junit_formatter

wicked_pdf gem version (output of cat Gemfile.lock | grep wicked_pdf): wicked_pdf (1.4.0)

wkhtmltopdf version (output of wkhtmltopdf --version): wkhtmltopdf 0.12.5 (with patched qt)

platform/distribution and version (e.g. Windows 10 / Ubuntu 16.04 / Heroku cedar): Ubuntu 16.04 and Linux Mint 18.3

thomasbalsloev avatar Aug 05 '19 14:08 thomasbalsloev

Same problem arise if method render overided in controller. method(:render) return render from controller. And super_method for it return WickedPdf::PdfHelper#render.

     ...
     # ./app/controllers/application_controller.rb:70:in `render'
     # /Users/dborisov/.rbenv/versions/2.6.2/lib/ruby/gems/2.6.0/gems/wicked_pdf-1.4.0/lib/wicked_pdf/pdf_helper.rb:46:in `call'
     # /Users/dborisov/.rbenv/versions/2.6.2/lib/ruby/gems/2.6.0/gems/wicked_pdf-1.4.0/lib/wicked_pdf/pdf_helper.rb:46:in `render_with_wicked_pdf'
     # /Users/dborisov/.rbenv/versions/2.6.2/lib/ruby/gems/2.6.0/gems/wicked_pdf-1.4.0/lib/wicked_pdf/pdf_helper.rb:30:in `render'
     # ./app/controllers/application_controller.rb:70:in `render'
     # /Users/dborisov/.rbenv/versions/2.6.2/lib/ruby/gems/2.6.0/gems/wicked_pdf-1.4.0/lib/wicked_pdf/pdf_helper.rb:46:in `call'
     # /Users/dborisov/.rbenv/versions/2.6.2/lib/ruby/gems/2.6.0/gems/wicked_pdf-1.4.0/lib/wicked_pdf/pdf_helper.rb:46:in `render_with_wicked_pdf'
     # /Users/dborisov/.rbenv/versions/2.6.2/lib/ruby/gems/2.6.0/gems/wicked_pdf-1.4.0/lib/wicked_pdf/pdf_helper.rb:30:in `render'
     # ./app/controllers/application_controller.rb:70:in `render'
     ...

Error occur not only in rspec. Requestion controller in normal mode leads to SystemStackError too.

hbda avatar Aug 22 '19 06:08 hbda

We're also getting this on any version beyond 1.1. I think @hbda is on the right track - it's something to do with overriding and, perhaps, the way Rails5+ has moved from override_method_chain to Module#prepend.

Epigene avatar Aug 30 '19 13:08 Epigene

With the latest version of rspec-rails, 4.0.0, we have the issue

/.rbenv/versions/2.4.9/lib/ruby/gems/2.4.0/gems/wicked_pdf-1.4.0/lib/wicked_pdf/pdf_helper.rb:46:in `call'",
 "/Users/eproulx/.rbenv/versions/2.4.9/lib/ruby/gems/2.4.0/gems/wicked_pdf-1.4.0/lib/wicked_pdf/pdf_helper.rb:46:in `render_with_wicked_pdf'",
 "/Users/eproulx/.rbenv/versions/2.4.9/lib/ruby/gems/2.4.0/gems/wicked_pdf-1.4.0/lib/wicked_pdf/pdf_helper.rb:30:in `render'",
 "/Users/eproulx/.rbenv/versions/2.4.9/lib/ruby/gems/2.4.0/gems/wicked_pdf-1.4.0/lib/wicked_pdf/pdf_helper.rb:46:in `call'",
 "/Users/eproulx/.rbenv/versions/2.4.9/lib/ruby/gems/2.4.0/gems/wicked_pdf-1.4.0/lib/wicked_pdf/pdf_helper.rb:46:in `render_with_wicked_pdf'",
 "/Users/eproulx/.rbenv/versions/2.4.9/lib/ruby/gems/2.4.0/gems/wicked_pdf-1.4.0/lib/wicked_pdf/pdf_helper.rb:30:in `render'",
 "/Users/eproulx/.rbenv/versions/2.4.9/lib/ruby/gems/2.4.0/gems/wicked_pdf-1.4.0/lib/wicked_pdf/pdf_helper.rb:46:in `call'",
 "/Users/eproulx/.rbenv/versions/2.4.9/lib/ruby/gems/2.4.0/gems/wicked_pdf-1.4.0/lib/wicked_pdf/pdf_helper.rb:46:in `render_with_wicked_pdf'",
 "/Users/eproulx/.rbenv/versions/2.4.9/lib/ruby/gems/2.4.0/gems/wicked_pdf-1.4.0/lib/wicked_pdf/pdf_helper.rb:30:in `render'",
 "/Users/eproulx/.rbenv/versions/2.4.9/lib/ruby/gems/2.4.0/gems/wicked_pdf-1.4.0/lib/wicked_pdf/pdf_helper.rb:46:in `call'",
 "/Users/eproulx/.rbenv/versions/2.4.9/lib/ruby/gems/2.4.0/gems/wicked_pdf-1.4.0/lib/wicked_pdf/pdf_helper.rb:46:in `render_with_wicked_pdf'",
 "/Users/eproulx/.rbenv/versions/2.4.9/lib/ruby/gems/2.4.0/gems/wicked_pdf-1.4.0/lib/wicked_pdf/pdf_helper.rb:30:in `render'",
 "/Users/eproulx/.rbenv/versions/2.4.9/lib/ruby/gems/2.4.0/gems/wicked_pdf-1.4.0/lib/wicked_pdf/pdf_helper.rb:46:in `call'",

We have a spec that does

expect(controller).to receive(:render).with(plain: :calendar).and_call_original

ericproulx avatar May 14 '20 20:05 ericproulx