RSpec raises OutOfMemoryError #166

Closed
markburns opened this Issue Aug 21, 2012 · 14 comments

Projects

None yet

3 participants

@markburns

Running in the debugger it seems to occur somewhere after fail_with_message

rspec-expectations-2.11.2/lib/rspec/matchers/operator_matcher.rb:70

then into
rspec-expectations-2.11.2/lib/rspec/expectations/fail_with.rb:22

during the check for all_strings
shutl_neo4j/gems/rspec-expectations-2.11.2/lib/rspec/expectations/fail_with.rb:43

this line:

args.flatten.all? {|a| String === a}

we end up in a loop inside

rack-1.4.1/lib/rack/response.rb:72

finish method

seems to be related to the aliasing of to_ary

gist to replicate available at

https://gist.github.com/3414935

@alindeman
Contributor

The problem is that [last_response].flatten makes Ruby go into an infinite loop (?)

I think it's due to flatten being recursive (e.g., [[[1, 2, 3]]].flatten == [1, 2, 3]), and Ruby is reacting oddly to recursively trying to flatten a Rack::MockResponse). I'm not totally sure why that is at this point. You might be on to something with to_ary, but I haven't dug too deep.

[1] pry(#<RSpec::Core::ExampleGroup::Nested_1>)> [[last_response]].flatten(1)
=> [last_response]
[1] pry(#<RSpec::Core::ExampleGroup::Nested_1>)> [[last_response]].flatten(0)
=> [[last_response]]
[2] pry(#<RSpec::Core::ExampleGroup::Nested_1>)> [[last_response]].flatten(-1) # recursive as many times as necessary (default)
# ... stalls forever in MRI ...

Since 044b0a6, we end up calling something like [last_response, 'egg'].flatten when generating an error message.

@dchelimsky, I'm not totally sure what flatten is used for. Since you're the committer, do you have ideas? For instance, is there a way we can avoid calling flatten or call a non-infinitely-recursive version of flatten?

@alindeman
Contributor

Yah, interesting:

[2] pry(#<RSpec::Core::ExampleGroup::Nested_1>)> last_response.to_ary.flatten
# ... stalls forever ...
@dchelimsky
Member

It's to remain compatible with custom matchers which might still return an array from expected. See #115 for more info.

@dchelimsky
Member

The way flatten works is it iterates through the elements in a collection and asks each one if it responds to to_ary. If it does it calls to_ary and then asks the same thing of each of its elements. If respond_to?(:to_ary) returns true, and to_ary returns [self], for example, you're kinda f'd. Not sure what's going on w/ Rack::MockResponse (haven't looked yet myself), but I'd look for something like that.

@alindeman
Contributor

Do you think it's our responsibility to do anything? Or is this a rack "bug"?

@dchelimsky
Member

I'm not ready to point fingers until I see where it's happening, but it sounds like something in the execution path is not playing nice with to_ary.

@dchelimsky
Member

Could also be a method_missing issue (just throwing ideas out).

@alindeman
Contributor

Rack::Response#to_ary does indeed return an array with self included for most status codes: https://github.com/rack/rack/blob/ab67e70d82911c0c86dce737c7064d0bd6daf3d4/lib/rack/response.rb#L71-83

@alindeman
Contributor

Even without RSpec involved, a Rack::Response object won't flatten correctly in an array:

[2] pry> [last_response].flatten
# ... infinite loop ...

flatten is definitely explicitly defined:

[1] pry> last_response.method(:to_ary)
=> #<Method: Rack::MockResponse(Rack::Response)#finish>
@dchelimsky
Member

And viola! Closing this. @markburns, @alindeman either of you want to report this to https://github.com/rack/rack/issues?

@dchelimsky dchelimsky closed this Aug 21, 2012
@markburns

Happy to raise it there tbh I wasn't sure of the cause or where to report but did my best. Wasn't sure where the 'blame' might lay but thought it may be the to_ary/finish aliasing. Ok hopefully can solve it.

And for anyone stumbling across this problem the solution in this case is to not compare with last_response but to compare with last_response.body

Sent from my iPhone

On 21 Aug 2012, at 23:53, David Chelimsky notifications@github.com wrote:

And viola! Closing this. @markburns, @alindeman either of you want to report this to https://github.com/rack/rack/issues?


Reply to this email directly or view it on GitHub.

@dchelimsky
Member

I went ahead and raised the issue in rack rack/rack#419 because this same issue came up in rspec-rails' tracker rspec/rspec-rails#601.

@markburns

Thanks @dchelimsky sorry, didn't get chance to raise this over there. :-)

@dchelimsky
Member

No worries @markburns.

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