Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RSpec raises OutOfMemoryError #166

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

RSpec raises OutOfMemoryError #166

markburns opened this issue Aug 21, 2012 · 14 comments

Comments

@markburns
Copy link

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
Copy link
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
Copy link
Contributor

Yah, interesting:

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

@dchelimsky
Copy link
Contributor

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

@dchelimsky
Copy link
Contributor

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
Copy link
Contributor

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

@dchelimsky
Copy link
Contributor

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
Copy link
Contributor

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

@alindeman
Copy link
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
Copy link
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
Copy link
Contributor

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

@markburns
Copy link
Author

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 [email protected] 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
Copy link
Contributor

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
Copy link
Author

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

@dchelimsky
Copy link
Contributor

No worries @markburns.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants