# Wrapped method causing infinite recursion in rcov

**URL:** <https://www.ruby-forum.com/t/wrapped-method-causing-infinite-recursion-in-rcov/100181>\
**Category:** Ruby\
**Created:** [July 27, 2006, 4:50pm UTC](https://www.ruby-forum.com/t/wrapped-method-causing-infinite-recursion-in-rcov/100181 "2006-07-27T16:50:42Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![Pedro\_CSSSSrte-Real](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/a5b964/32.png) [@Pedro\_CSSSSrte-Real](https://www.ruby-forum.com/u/Pedro_CSSSSrte-Real)\
**Post date:** [July 27, 2006, 4:50pm UTC](https://www.ruby-forum.com/t/wrapped-method-causing-infinite-recursion-in-rcov/100181/1 "2006-07-27T16:50:42Z")

</div>

I added this to my rails test helper to check for valid HTML  
automatically:

# Wrap around get to check the markup on :success requests.

alias\_method :old\_get, :get  
def get(\*args)  
old\_get(\*args)  
if @response.success?  
assert\_valid\_markup  
end  
end

This works fine with my tests. When running rcov though it creates  
infinite recursion in the call to old\_get. Has anyone tried anything  
of the sort? Is it a bug in rcov?

Pedro.

---

<div class="post-metadata">

**Author:** ![Pedro\_CSSSSrte-Real](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/a5b964/32.png) [@Pedro\_CSSSSrte-Real](https://www.ruby-forum.com/u/Pedro_CSSSSrte-Real)\
**Post date:** [July 27, 2006, 7:21pm UTC](https://www.ruby-forum.com/t/wrapped-method-causing-infinite-recursion-in-rcov/100181/2 "2006-07-27T19:21:20Z")

</div>

On 7/27/06, Caleb C. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> At a guess, (something is) rcov is also wrapping #get and using the  
> same name for the old version of the method. At least, that’s always  
> been the explanation when I’ve encountered these ‘wrapping a method  
> causes infinite recursion’ problems. Try this way instead, it should  
> eliminate any possibility that your code is participating in the  
> recursion.

I tried a different name and it didn’t work so I don’t know what’s  
actually happening. But I’d like to know. Anyone?

> old\_get=instance\_method(:get)  
> define\_method(:get) do |\*args|  
> old\_get[\*args]

I had to replace this line with:

old\_get.bind(self).call(\*args)

apparently old\_get is an UnboundMethod and needs to be bound to an  
object before it can work.

> if @response.success?  
> assert\_valid\_markup  
> end  
> end

Thanks for this solution. It’s working again now. This probably means  
that there should be an alias\_method equivalent to do this. I didn’t  
really want to change the method name, I wanted to replace it with  
something that could still call the old behavior. 0-step inheritance  
so to speak.

> This trick was originated by Mauricio F., as far as I know.

Thanks to him too then,

Pedro.

---

<div class="post-metadata">

**Author:** ![Pedro\_CSSSSrte-Real](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/a5b964/32.png) [@Pedro\_CSSSSrte-Real](https://www.ruby-forum.com/u/Pedro_CSSSSrte-Real)\
**Post date:** [July 27, 2006, 6:59pm UTC](https://www.ruby-forum.com/t/wrapped-method-causing-infinite-recursion-in-rcov/100181/3 "2006-07-27T18:59:10Z")

</div>

On 7/27/06, Pedro Côrte-Real [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> infinite recursion in the call to old\_get. Has anyone tried anything  
> of the sort? Is it a bug in rcov?

At a guess, (something is) rcov is also wrapping #get and using the  
same name for the old version of the method. At least, that’s always  
been the explanation when I’ve encountered these ‘wrapping a method  
causes infinite recursion’ problems. Try this way instead, it should  
eliminate any possibility that your code is participating in the  
recursion.

old\_get=instance\_method(:get)  
define\_method(:get) do |\*args|  
old\_get[\*args]  
if @response.success?  
assert\_valid\_markup  
end  
end

This trick was originated by Mauricio F., as far as I know.

---

<div class="post-metadata">

**Author:** ![Pedro\_CSSSSrte-Real](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/a5b964/32.png) [@Pedro\_CSSSSrte-Real](https://www.ruby-forum.com/u/Pedro_CSSSSrte-Real)\
**Post date:** [July 27, 2006, 10:55pm UTC](https://www.ruby-forum.com/t/wrapped-method-causing-infinite-recursion-in-rcov/100181/4 "2006-07-27T22:55:09Z")

</div>

I don’t like advertising my own work, but…

> old\_get=instance\_method(:get)  
> define\_method(:get) do |\*args|  
> old\_get[\*args]

This works, unless you want the method to receive a &block.  
(Though that’s fixed in Ruby 1.9.)

I would do this:

class Module  
def assert\_valid\_markup(method\_name) do  
post\_condition(method\_name) do |obj, method\_name, args, block|  
# Check it…  
end  
end  
end

class Foo  
def get(\*args)  
# The real stuff…  
end

assert\_valid\_markup :get if $DEBUG  
end

I call this assert\_valid\_markup a “monitor-function” [1]. This  
post\_condition is defined on the site as well.

gegroet,  
Erik V. - [http://www.erikveen.dds.nl/](http://www.erikveen.dds.nl/)

[1] [Ruby Monitor-Functions - Or Meta-Meta-Programming in Ruby](http://www.erikveen.dds.nl/monitorfunctions/index.html)

---

<div class="post-metadata">

**Author:** ![Pedro\_CSSSSrte-Real](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/a5b964/32.png) [@Pedro\_CSSSSrte-Real](https://www.ruby-forum.com/u/Pedro_CSSSSrte-Real)\
**Post date:** [July 27, 2006, 9:58pm UTC](https://www.ruby-forum.com/t/wrapped-method-causing-infinite-recursion-in-rcov/100181/5 "2006-07-27T21:58:17Z")

</div>

On Fri, Jul 28, 2006 at 01:57:56AM +0900, Caleb C. wrote:

> > This works fine with my tests. When running rcov though it creates  
> > infinite recursion in the call to old\_get. Has anyone tried anything  
> > of the sort? Is it a bug in rcov?
> 
> At a guess, (something is) rcov is also wrapping #get and using the  
> same name for the old version of the method. At least, that’s always  
> been the explanation when I’ve encountered these ‘wrapping a method  
> causes infinite recursion’ problems. Try this way instead, it should  
> eliminate any possibility that your code is participating in the  
> recursion.

rcov doesn’t redefine anything, it just uses a trace\_func (or the C  
equivalent  
when rcovrt is available). In theory, running a program through rcov  
shouldn’t  
change its behavior, but this is the second time I’m told there’s some  
sort of  
bothersome interference with Rails (I haven’t yet been able to fix the  
first  
issue, reported by Assaph M.).

I’d love to solve this, but I first need to reproduce the bug; a naïve  
attempt  
fails, as expected:

# $ rcov --text-counts foo.rb 1

# foo.rb

```
                                                                   | 

```

0  
class Foo; def foo; end end |  
5  
class Bar \< Foo |  
2  
alias\_method :old\_foo, :foo |  
1  
def foo; p 1; old\_foo end |  
5  
end |  
0  
|  
0  
Bar.new.foo |  
1

If you cannot show me your code, please keep a copy of the codebase  
exhibiting  
the bug. I might send you a modified rcov for you to test, if I can  
figure  
this out.

Actually, I think I know what is going on: when running under rcov, the  
file  
holding your Rails test helper is being require()d twice. If I’m right,  
it  
should be possible to infer what is going on by tracing #require, with  
e.g.

module Kernel  
req = instance\_method(:require)  
define\_method(:require) do |\*a|  
puts “-” \* 80  
puts "Kernel#require " + a.inspect  
puts caller.inspect  
req.bind(self).call(\*a)  
end  
end

and then looking for the calls where your test file was loaded. Things  
should  
be easy until that stage. After that, we’d have to see why rcov  
introduces a  
difference in the second call.

[Thinking as I write] rcov loads the files supplied in the command line  
with  
Kernel#load, so if you later #require’ any of them, it would be loaded  
twice.  
Moreover, Rake’s default test loader also works this way; here’s its  
source  
code:

ARGV.each { |f| load f unless f =~ /^-/ }

If this hunch is correct, the following patch to bin/rcov could save the  
day:

diff -rN -u old-tmp/bin/rcov new-tmp/bin/rcov  
— old-tmp/bin/rcov 2006-07-27 21:50:33.000000000 +0200  
+++ new-tmp/bin/rcov 2006-07-27 21:50:33.000000000 +0200  
@@ -450,7 +450,7 @@  
if options.replace\_prog\_name  
$0 = File.basename(File.expand\_path(prog))  
end

- load prog

- require prog  
end

Rake would also have to be changed, but I’d like to make sure the  
modification  
is appropriate before applying it to rcov and sending jweirich a patch.

> old\_get=instance\_method(:get)  
> define\_method(:get) do |\*args|  
> old\_get[\*args]  
> if @response.success?  
> assert\_valid\_markup  
> end  
> end
> 
> This trick was originated by Mauricio F., as far as I know.

It was most probably discovered by some anonymous Japanese Rubyist  
before I  
popularized it to some extent, though 🙂

---

<div class="post-metadata">

**Author:** ![Pedro\_CSSSSrte-Real](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/a5b964/32.png) [@Pedro\_CSSSSrte-Real](https://www.ruby-forum.com/u/Pedro_CSSSSrte-Real)\
**Post date:** [July 27, 2006, 11:40pm UTC](https://www.ruby-forum.com/t/wrapped-method-causing-infinite-recursion-in-rcov/100181/6 "2006-07-27T23:40:03Z")

</div>

On Fri, Jul 28, 2006 at 04:55:15AM +0900, Mauricio F. wrote:

> On Fri, Jul 28, 2006 at 01:57:56AM +0900, Caleb C. wrote:
> 
> > On 7/27/06, Pedro Côrte-Real [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:  
> > rcov doesn’t redefine anything, it just uses a trace\_func (or the C  
> > equivalent when rcovrt is available). In theory, running a program through  
> > rcov shouldn’t change its behavior, but this is the second time I’m told  
> > there’s some sort of bothersome interference with Rails (I haven’t yet been  
> > able to fix the first issue, reported by Assaph M.).  
> > ========================================  
> > Meanwhile, I’ve figured this one out. Rails was interfering with itself:  
> > rake  
> > test runs unit, functional and integration tests in three separate  
> > processes.  
> > If you load them all simultaneously, you can run into puzzling errors  
> > (reported for the wrong controllers, as  
> > SomeController.new.class != SomeController in some circumstances (!)).

So we’re down to one bug/strange interaction. Let’s address it:

if you are defining the coverage task like this:

```
Rcov::RcovTask.new(:converage) do |t|
  t.libs << "test"
  t.test_files = FileList['test/**/*_test.rb']
  t.output_dir = 'test/coverage'
  t.verbose = true
  t.rcov_opts << '--rails'
end

```

the helper could get loaded twice if it is being required in both the  
unit  
_and_ the functional tests (Rails does ugly things with $: and require).  
We  
can get some evidence to support that theory by monitoring #require, as  
shown  
in my previous message.

At any rate, I will soon implement the ability to merge coverage data  
from  
several runs, allowing you to run the tests separately and obtain a  
single  
coverage figure.

---

<div class="post-metadata">

**Author:** ![Pedro\_CSSSSrte-Real](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/a5b964/32.png) [@Pedro\_CSSSSrte-Real](https://www.ruby-forum.com/u/Pedro_CSSSSrte-Real)\
**Post date:** [July 27, 2006, 8:09pm UTC](https://www.ruby-forum.com/t/wrapped-method-causing-infinite-recursion-in-rcov/100181/7 "2006-07-27T20:09:50Z")

</div>

On 7/27/06, Pedro Côrte-Real [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> On 7/27/06, Caleb C. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:
> 
> > At a guess, (something is) rcov is also wrapping #get and using the  
> > same name for the old version of the method. At least, that’s always  
> > been the explanation when I’ve encountered these ‘wrapping a method  
> > causes infinite recursion’ problems. Try this way instead, it should  
> > eliminate any possibility that your code is participating in the  
> > recursion.
> 
> I tried a different name and it didn’t work so I don’t know what’s  
> actually happening. But I’d like to know. Anyone?

That’s odd, considering that the define\_method trick seems to be  
working for you. As I said, my diagnosis was just a guess.

> > old\_get=instance\_method(:get)  
> > define\_method(:get) do |\*args|  
> > old\_get[\*args]
> 
> I had to replace this line with:
> 
> old\_get.bind(self).call(\*args)

Ooops! My apologies for posting broken code. Looks like you got the  
idea, anyway.

> Thanks for this solution. It’s working again now. This probably means  
> that there should be an alias\_method equivalent to do this. I didn’t  
> really want to change the method name, I wanted to replace it with  
> something that could still call the old behavior. 0-step inheritance  
> so to speak.

Wrapping methods seems to be pretty common in ruby. FYI the  
define\_method trick won’t be able to wrap methods that take a block  
until ruby 1.9.

> > This trick was originated by Mauricio F., as far as I know.
> 
> Thanks to him too then,

Just a BTW, he’s the same guy that wrote rcov. So now you have 2  
things to thank him for.

---

<div class="post-metadata">

**Author:** ![Pedro\_CSSSSrte-Real](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/a5b964/32.png) [@Pedro\_CSSSSrte-Real](https://www.ruby-forum.com/u/Pedro_CSSSSrte-Real)\
**Post date:** [August 7, 2006, 7:40pm UTC](https://www.ruby-forum.com/t/wrapped-method-causing-infinite-recursion-in-rcov/100181/8 "2006-08-07T19:40:01Z")

</div>

On Fri, Jul 28, 2006 at 08:05:37PM +0900, Pedro Côrte-Real wrote:

> I just wrapped the call to that assertion so that on every successful  
> request the HTML is tested. Other than that it’s just normal tests.
> 
> Just say so if you still can’t reproduce it.

Could you try to reproduce it with rcov 0.7.0, running the unit,  
functional &  
integration tests separately as explained in [ruby-talk:206760]? I think  
the  
file was being require()d with 2 different names, in tests that break  
unless  
executed in different processes.

---

<div class="post-metadata">

**Author:** ![Pedro\_CSSSSrte-Real](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/a5b964/32.png) [@Pedro\_CSSSSrte-Real](https://www.ruby-forum.com/u/Pedro_CSSSSrte-Real)\
**Post date:** [July 28, 2006, 1:07pm UTC](https://www.ruby-forum.com/t/wrapped-method-causing-infinite-recursion-in-rcov/100181/9 "2006-07-28T13:07:11Z")

</div>

On 7/27/06, Mauricio F. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> If you cannot show me your code, please keep a copy of the codebase exhibiting  
> the bug. I might send you a modified rcov for you to test, if I can figure  
> this out.

I can send you the code if you want but you’ve pretty much seen it  
all. assert\_valid\_markup is a plugin:

[http://wiki.rubyonrails.com/rails/pages/Assert+Valid+Markup+Plugin](http://wiki.rubyonrails.com/rails/pages/Assert+Valid+Markup+Plugin)

I just wrapped the call to that assertion so that on every successful  
request the HTML is tested. Other than that it’s just normal tests.

Just say so if you still can’t reproduce it.

> ```
> req.bind(self).call(*a)
> 
> ```
> 
> code:  
> if options.replace\_prog\_name  
> $0 = File.basename(File.expand\_path(prog))  
> end
> 
> - load prog
> 
> - require prog  
> end

No, doesn’t work ☹

> It was most probably discovered by some anonymous Japanese Rubyist before I  
> popularized it to some extent, though 🙂

Thanks anyway.

Pedro.
