Problem with test:units:rcov

B

Brian Candler

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 :)

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.
 
B

Brian Candler

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:in `require'
/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:in `load_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 method `exclude' 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:in `require'
/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:in `load_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 method `exclude' 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.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top