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 Mehr).
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
ld_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 Fernandez, as far as I know.
It was most probably discovered by some anonymous Japanese Rubyist before I
popularized it to some extent, though