Using custom matcher inside of other custom matcher leads to "stack level too deep" error #592

Closed
mirasrael opened this Issue Mar 29, 2012 · 3 comments

Projects

None yet

2 participants

@mirasrael

I have the following custom matchers:

Ruby:

RSpec::Matchers.define :be_accepted do
  match do |actual|
    begin
      actual.call()
    rescue QualityMeasures::MeasureConditions::RejectedError
      false
    rescue QualityMeasures::MeasureConditions::DeclinedError
      false
    end
  end
end

RSpec::Matchers.define :be_in_population do
  match do |actual|   
    lambda { actual.in_population? }.should be_accepted
  end
end

When I'm using something like this in my spec:

Ryby:

measure.should be_in_population

it crashes with error:

SystemStackError: stack level too deep
/ruby/1.9.1/gems/rspec-expectations-2.9.0/lib/rspec/matchers/matcher.rb:225:

It worked just well before RSpec 2.9.

I was able to workaround this with direct call to $matcher_execution_context,

Ruby:

lambda { actual.in_population? }.should $matcher_execution_context.be_accepted

but it doesn't looks like a good soultion

@dchelimsky
Member

This belongs in rspec-expectations (where matchers live). There is a similar issue reported in rspec/rspec-expectations#124. Please either comment on that issue (preferred), in which case I'll reopen it, or submit a new issue there. Thx.

@dchelimsky dchelimsky closed this Mar 29, 2012
@mirasrael

Sorry for wrong tracker. It doesn't seems to be related to issue #124. I spent some time for investigation and found that it happens because of matcher method is calling for instance of RSpec::Matchers::DSL::Matcher (because it includes RSpec::Matchers and has all custom methods defined). But, in this method it set $matcher_execution_context to self and when asks respond_to?(:instance_eval) in RSpec::Matchers::Extensions::InstanceEvalWithArgs#instance_eval_with_args it falls into infinite loop in:

Ruby:

def respond_to?(method, include_private=false)
  $matcher_execution_context != self && $matcher_execution_context.respond_to?(method, include_private) || super
end

I opened pull request rspec/rspec-expectations#126 with fix for this issue.

@dchelimsky
Member

Great find. Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment