Problem with test:units:rcov

I’m posting this problem here as I’m not sure whether it’s to do with
rcov,
rails_rcov, rails, rake, or my own application :slight_smile:

I had rails_rcov working perfectly last week. Now when I try it again on
the
current iteration of the same project, it bombs out:

$ rake --trace test:units:rcov
(in /home/candlerb/svn/dev/projects/deploy2/trunk)
** Invoke test:units:rcov (first_time)
** Invoke test:units:clobber_rcov (first_time)
** Execute test:units:clobber_rcov
rm -rf ./coverage/units
** Execute test:units:rcov
/usr/bin/ruby1.8
“/home/candlerb/svn/dev/projects/deploy2/trunk/vendor/plugins/rails_rcov/tasks/rails_rcov.rake”
–run-rake-task=test:units
(in /home/candlerb/svn/dev/projects/deploy2/trunk)
rake aborted!
undefined method exclude' for nil:NilClass /home/candlerb/svn/dev/projects/deploy2/trunk/Rakefile:10 (See full trace by running task with --trace) rake aborted! Command failed with status (1): [/usr/bin/ruby1.8 "/home/candlerb/svn/dev/p...] /usr/lib/ruby/gems/1.8/gems/rake-0.7.3/lib/rake.rb:719:in sh’
/usr/lib/ruby/gems/1.8/gems/rake-0.7.3/lib/rake.rb:726:in sh' /usr/lib/ruby/gems/1.8/gems/rake-0.7.3/lib/rake.rb:805:in sh’
/usr/lib/ruby/gems/1.8/gems/rake-0.7.3/lib/rake.rb:800:in sh' /usr/lib/ruby/gems/1.8/gems/rake-0.7.3/lib/rake.rb:740:in ruby’
/usr/lib/ruby/gems/1.8/gems/rake-0.7.3/lib/rake.rb:805:in ruby' /usr/lib/ruby/gems/1.8/gems/rake-0.7.3/lib/rake.rb:800:in ruby’
/home/candlerb/svn/dev/projects/deploy2/trunk/config/…/vendor/plugins/rails_rcov/tasks/rails_rcov.rake:83:in
new_rcov_task' /usr/lib/ruby/gems/1.8/gems/rake-0.7.3/lib/rake.rb:392:in execute’
/usr/lib/ruby/gems/1.8/gems/rake-0.7.3/lib/rake.rb:392:in execute' /usr/lib/ruby/gems/1.8/gems/rake-0.7.3/lib/rake.rb:362:in invoke’
/usr/lib/ruby/1.8/thread.rb:135:in synchronize' /usr/lib/ruby/gems/1.8/gems/rake-0.7.3/lib/rake.rb:355:in invoke’
/usr/lib/ruby/gems/1.8/gems/rake-0.7.3/lib/rake.rb:1739:in top_level' /usr/lib/ruby/gems/1.8/gems/rake-0.7.3/lib/rake.rb:1739:in top_level’
/usr/lib/ruby/gems/1.8/gems/rake-0.7.3/lib/rake.rb:1761:in
standard_exception_handling' /usr/lib/ruby/gems/1.8/gems/rake-0.7.3/lib/rake.rb:1733:in top_level’
/usr/lib/ruby/gems/1.8/gems/rake-0.7.3/lib/rake.rb:1711:in run' /usr/lib/ruby/gems/1.8/gems/rake-0.7.3/lib/rake.rb:1761:in standard_exception_handling’
/usr/lib/ruby/gems/1.8/gems/rake-0.7.3/lib/rake.rb:1708:in `run’
/usr/lib/ruby/gems/1.8/gems/rake-0.7.3/bin/rake:7
/usr/bin/rake:16

However, the unit tests by themselves are just fine (rake test:units)

Now, several things have changed since rcov was last working. I’ve made
a
lot of changes to the application itself - but as I say, the tests are
still
passing.

I’ve also done a gem update to get from rails 1.2.2 to 1.2.3, which
means I
have various different versions of things lying around:

$ ls /usr/lib/ruby/gems/1.8/gems/
actionmailer-1.3.2 cgi_multipart_eof_fix-2.1 rails-1.2.3
actionmailer-1.3.3 daemons-1.0.5 rake-0.7.1
actionpack-1.13.2 fastthread-1.0 rake-0.7.3
actionpack-1.13.3 flexmock-0.5.0 rcov-0.8.0.2
actionwebservice-1.2.2 gem_plugin-0.2.2 rubyforge-0.4.0
actionwebservice-1.2.3 haml-1.0.5 RubyInline-3.6.2
activerecord-1.15.2 hoe-1.2.0 sources-0.0.1
activerecord-1.15.3 mongrel-1.0.1 xml-simple-1.0.11
activesupport-1.4.1 mongrel_cluster-0.2.1 zentest-3.5.0
activesupport-1.4.2 rails-1.2.2

However I tried setting RAILS_GEM_VERSION=‘1.2.2’ in
config/environment.rb
but this made no difference.

The rails_rcov version is -r12 from subversion.

$ svn propget svn:externals vendor/plugins/
rails_rcov http://svn.codahale.com/rails_rcov

$ svn update

Fetching external item into ‘vendor/plugins/rails_rcov’
External at revision 12.

Now, what’s annoying is that there is no filename or line number to
identify
where the “undefined method `exclude’ for nil:NilClass” exception
occured,
except /home/candlerb/svn/dev/projects/deploy2/trunk/Rakefile:10
which is just

require 'tasks/rails'

Anyone got any ideas how I can narrow this down?

Thanks,

Brian.

On Tue, Apr 24, 2007 at 05:39:57PM +0900, Brian C. wrote:

I had rails_rcov working perfectly last week. Now when I try it again on the
current iteration of the same project, it bombs out:

This turns out to be an extremely weird problem. Firstly I made the
following change to rails-1.2.3/lib/tasks/rails.rb

— rails.rb.orig 2007-04-21 21:24:18.000000000 +0100
+++ rails.rb 2007-04-24 12:23:01.000000000 +0100
@@ -4,5 +4,10 @@
Dir["#{File.dirname(FILE)}/*.rake"].each { |ext| load ext }

Load any custom rakefile extensions

+begin
Dir["#{RAILS_ROOT}/lib/tasks//*.rake"].sort.each { |ext| load ext }
Dir["#{RAILS_ROOT}/vendor/plugins/
/tasks/**/*.rake"].sort.each {
|ext| load ext }
+rescue Exception => e
+STDERR.puts “XXX #{e.message}\n#{e.backtrace.join(”\n")}"
+raise
+end

(ISTM that rake should not be hiding this exception when I give --trace)

This gives me the following error:

XXX undefined method exclude' for nil:NilClass /usr/lib/ruby/gems/1.8/gems/rake-0.7.3/lib/rake/clean.rb:19 /usr/local/lib/site_ruby/1.8/rubygems/custom_require.rb:27:inrequire’
/home/candlerb/svn/dev/projects/deploy2/trunk/config/…/vendor/plugins/rails_rcov/tasks/rails_rcov.rake:30
/usr/lib/ruby/gems/1.8/gems/rails-1.2.3/lib/tasks/rails.rb:9
/usr/lib/ruby/gems/1.8/gems/rails-1.2.3/lib/tasks/rails.rb:9
/usr/local/lib/site_ruby/1.8/rubygems/custom_require.rb:27:in require' /home/candlerb/svn/dev/projects/deploy2/trunk/Rakefile:10 /usr/lib/ruby/1.8/rake.rb:1641:inload_rakefile’
/usr/lib/ruby/1.8/rake.rb:1713:in run' /home/candlerb/svn/dev/projects/deploy2/trunk/vendor/plugins/rails_rcov/tasks/rails_rcov.rake:146 rake aborted! undefined methodexclude’ for nil:NilClass
/home/candlerb/svn/dev/projects/deploy2/trunk/Rakefile:10
(See full trace by running task with --trace)

Line 19 of rake/clean.rb is

CLEAN.clear_exclude.exclude { |fn|

So it looks like CLEAN.clear_exclude is returning nil.

This is where it gets interesting. I had gems for both rake-0.7.1 and
rake-0.7.3 installed. The code for clear_exclude in rake-0.7.3 is

def clear_exclude
  @exclude_patterns = []
  @exclude_procs = []
  calculate_exclude_regexp if ! @pending
  self
end

but in rake-0.7.1 it is

def clear_exclude
  @exclude_patterns = []
  calculate_exclude_regexp if ! @pending
end

and the latter clearly could return nil. I checked that nothing was
referring to rake version 0.7.1 explicitly, but just to be on the safe
side
I uninstalled the rake-0.7.1 gem. However the problem remained.

Next I made the following changes to rake:

— gems/rake-0.7.3/lib/rake.rb.orig 2007-04-24 12:47:03.000000000
+0100
+++ gems/rake-0.7.3/lib/rake.rb 2007-04-24 12:54:36.000000000 +0100
@@ -1084,10 +1084,12 @@

 # Clear all the exclude patterns so that we exclude nothing.
 def clear_exclude

+STDERR.puts “enter clear_exclude”
@exclude_patterns = []
@exclude_procs = []
calculate_exclude_regexp if ! @pending

  •  self
    

+STDERR.puts “exit clear_exclude”

  •  return self
    

    end

    Define equality.

— gems/rake-0.7.3/lib/rake/clean.rb.orig 2007-04-24
12:49:15.000000000 +0100
+++ gems/rake-0.7.3/lib/rake/clean.rb 2007-04-24 12:57:38.000000000
+0100
@@ -16,9 +16,13 @@
require ‘rake’

CLEAN = Rake::FileList["/*~", "/*.bak", “**/core”]
-CLEAN.clear_exclude.exclude { |fn|
+STDERR.puts “AAA CLEAN=#{CLEAN.inspect}”
+cce = CLEAN.clear_exclude
+STDERR.puts “cce = #{cce.inspect}”
+cce.exclude { |fn|
fn.pathmap("%f") == ‘core’ && File.directory?(fn)
}
+STDERR.puts “BBB”

desc “Remove any temporary products.”
task :clean do

And here’s the result:

$ rake test:units:rcov(in /home/candlerb/svn/dev/projects/deploy2/trunk)
AAA CLEAN=[]
enter clear_exclude
exit clear_exclude
cce = []
BBB
rm -rf ./coverage/units
/usr/bin/ruby1.8
“/home/candlerb/svn/dev/projects/deploy2/trunk/vendor/plugins/rails_rcov/tasks/rails_rcov.rake”
–run-rake-task=test:units
(in /home/candlerb/svn/dev/projects/deploy2/trunk)
AAA CLEAN=[]
cce = /^$/
XXX undefined method exclude' for /^$/:Regexp /usr/lib/ruby/gems/1.8/gems/rake-0.7.3/lib/rake/clean.rb:22 /usr/local/lib/site_ruby/1.8/rubygems/custom_require.rb:27:inrequire’
/home/candlerb/svn/dev/projects/deploy2/trunk/config/…/vendor/plugins/rails_rcov/tasks/rails_rcov.rake:30
/usr/lib/ruby/gems/1.8/gems/rails-1.2.3/lib/tasks/rails.rb:9
/usr/lib/ruby/gems/1.8/gems/rails-1.2.3/lib/tasks/rails.rb:9
/usr/local/lib/site_ruby/1.8/rubygems/custom_require.rb:27:in require' /home/candlerb/svn/dev/projects/deploy2/trunk/Rakefile:10 /usr/lib/ruby/1.8/rake.rb:1641:inload_rakefile’
/usr/lib/ruby/1.8/rake.rb:1713:in run' /home/candlerb/svn/dev/projects/deploy2/trunk/vendor/plugins/rails_rcov/tasks/rails_rcov.rake:146 rake aborted! undefined methodexclude’ for /^$/:Regexp

This proves that the gem installation of rake-0.7.3 is being run, but it
is
so weird that I cannot understand it at all. CLEAN.clear_exclude now
appears
to be returning a regexp rather than nil. But look at the code - it
can’t
possibly be doing so!

So finally I undid all those changes and made just this one:

— gems/rake-0.7.3/lib/rake/clean.rb.orig 2007-04-24
12:49:15.000000000 +0100
+++ gems/rake-0.7.3/lib/rake/clean.rb 2007-04-24 13:00:38.000000000
+0100
@@ -16,7 +16,8 @@
require ‘rake’

CLEAN = Rake::FileList["/*~", "/*.bak", “**/core”]
-CLEAN.clear_exclude.exclude { |fn|
+CLEAN.clear_exclude
+CLEAN.exclude { |fn|
fn.pathmap("%f") == ‘core’ && File.directory?(fn)
}

and now everything works!

The only theory I have to work on is that rcov breaks the Ruby
interpreter
in such a way that “return self” no longer works. However that’s a very
wild
theory, and I’ve not been able to replicate it in a small test case.

Can anyone else think of a mechanism which would cause it to behave this
way?

Environment is Ubuntu 6.06,

$ ruby -v
ruby 1.8.4 (2005-12-24) [i486-linux]

Regards,

Brian.