REXML (1.8.6-p110) backwards compatibility problem with rcov

When I upgraded my Ubuntu 6.06.1 system from its stock ruby-1.8.4 to
ruby-1.8.6-p110, I found that the previously working rcov-0.8.0.2 was
raising REXML exceptions when it tried to generate its output (*)

I needed to make a couple of patches to REXML to fix this. The first
patch
is because rcov passes Fixnums as attribute values, e.g.

   table_(:cellpadding => 0, :cellspacing => 0, :align => "right")

This could have been fixed at the rcov side, but since it did used to
work
with rexml, I consider this a backwards-compatibility failure. The fix
is
trivial:

— rexml/text.rb.orig 2007-10-22 08:00:04.000000000 +0100
+++ rexml/text.rb 2007-10-22 08:00:33.000000000 +0100
@@ -286,7 +286,7 @@
EREFERENCE = /&(?!#{Entity::NAME};)/
# Escapes all possible entities
def Text::normalize( input, doctype=nil, entity_filter=nil )

  •  copy = input
    
  •  copy = input.to_s
     # Doing it like this rather than in a loop improves the speed
     #copy = copy.gsub( EREFERENCE, '&' )
     copy = copy.gsub( "&", "&" )
    

(Note that there are other places in this file which might benefit from
a
to_s as well)

The second is almost certainly a bug in REXML: it’s a misnamed local
variable.

— rexml/document.rb.orig 2007-10-22 08:02:36.000000000 +0100
+++ rexml/document.rb 2007-10-22 08:03:01.000000000 +0100
@@ -183,7 +183,7 @@
output = Output.new( output, xml_decl.encoding )
end
formatter = if indent > -1

  •      if transitive
    
  •      if trans
           REXML::Formatters::Transitive.new( indent, ie_hack )
         else
           REXML::Formatters::Pretty.new( indent, ie_hack )
    

After these changes, rcov seems to run happily.

I wasn’t sure where best to post this problem and its solution:
ruby-core
(since REXML is in the ruby standard library), the REXML home site, or
the
rcov home site. So I’m posting it here instead :slight_smile:

Regards,

Brian.

(*) The exception I saw initially was:

/usr/local/lib/ruby/1.8/rexml/text.rb:292:in normalize': private methodgsub’ called for 0:Fixnum (NoMethodError)
from /usr/local/lib/ruby/1.8/rexml/element.rb:1084:in []=' from /usr/local/lib/ruby/1.8/rexml/element.rb:586:inadd_attribute’
from (eval):490:in table_' from (eval):490:ineach’
from (eval):490:in table_' from (eval):490:ineach’
from (eval):490:in table_' from /usr/local/lib/ruby/gems/1.8/gems/rcov-0.8.0.2/lib/rcov/report.rb:702:informat_overview’
… 61 levels…

After I fixed this by adding to_s in Text::normalize, I got

/usr/local/lib/ruby/1.8/rexml/document.rb:186:in write': undefined local variable or methodtransitive’ for …
</>:REXML::Document (NameError)
from (eval):93:in pretty' from /usr/local/lib/ruby/gems/1.8/gems/rcov-0.8.0.2/lib/rcov/report.rb:727:informat_overview’
from
/usr/local/lib/ruby/gems/1.8/gems/rcov-0.8.0.2/lib/rcov/report.rb:758:in
create_index' from (eval):104:increate’
from (eval):80:in tracking_additions' from (eval):103:increate’
from (eval):372:in x_' from /usr/local/lib/ruby/gems/1.8/gems/rcov-0.8.0.2/lib/rcov/report.rb:758:increate_index’
… 21 levels…

On Mon, Oct 22, 2007 at 08:50:24AM +0100, Brian C. wrote:

The second is almost certainly a bug in REXML: it’s a misnamed local
variable.

Oh, I see there’s a fix for this in trunk already, committed 9 days ago:
http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/lib/rexml/document.rb?r1=13597&r2=13686
(but I don’t think it has been merged to branches/ruby_1_8_6)

I can’t see a fix for Fixnum attribute values though.

Regards,

Brian.

Nice catch!

After applying both fixes, I now get this:

/usr/local/lib/ruby/1.8/rexml/formatters/pretty.rb:131:in []': no implicit conversion from nil to integer (TypeError) from /usr/local/lib/ruby/1.8/rexml/formatters/pretty.rb:131:inwrap’
from /usr/local/lib/ruby/1.8/rexml/formatters/pretty.rb:131:in
wrap' from /usr/local/lib/ruby/1.8/rexml/formatters/pretty.rb:90:inwrite_text’
from /usr/local/lib/ruby/1.8/rexml/formatters/default.rb:50:in
write' from /usr/local/lib/ruby/1.8/rexml/formatters/pretty.rb:75:inwrite_element’
from /usr/local/lib/ruby/1.8/rexml/formatters/pretty.rb:73:in
each' from /usr/local/lib/ruby/1.8/rexml/formatters/pretty.rb:73:inwrite_element’
from /usr/local/lib/ruby/1.8/rexml/formatters/default.rb:31:in
`write’
… 16 levels…

rcov outputs the index.html file and the first few controller files,
so I can trace it to which file it’s getting choked on, but were there
any other fixes you had to put in?

Thanks,

Sean

Ive also applied both fixes and Im seeing exactly the same problem.
Any updates on this?

/usr/local/lib/ruby/1.8/rexml/formatters/pretty.rb:131:in `[]’: no

write_element' from /usr/local/lib/ruby/1.8/rexml/formatters/default.rb:31:inwrite’
… 16 levels…

Thanks,

I got these string of errors in the order reported also. I solved this
by editing the following files:

…prefix…/ruby/gems/1.8/gems/rspec-1.0.8/lib/spec/rake/verify_rcov.rb
…prefix…/ruby/1.8/rexml/formatters/pretty.rb

Plus the files already patched by this point. It seems like if your
stack trace says formatters/default.rb instead of formatters/pretty.rb
then that is the file you need to patch.

My formatters/pretty.rb patch looks like the following:

place = string.rindex(’ ‘, width) || width # Position in string with last ’ ’ before cutoff
< place = string.rindex(’ ', width) # Position in string with last ’ ’
before cutoff

My rake/verify_rcov.rb patch looks like:

if line =~ / (\d+.\d+)% </tt>   </td>/
< if line =~ /<tt.*?>(\d+.\d+)%</tt> </td>/

Hope that helps someone,
Susan

unknown wrote:

Ive also applied both fixes and Im seeing exactly the same problem.
Any updates on this?

/usr/local/lib/ruby/1.8/rexml/formatters/pretty.rb:131:in `[]’: no

write_element' from /usr/local/lib/ruby/1.8/rexml/formatters/default.rb:31:inwrite’
… 16 levels…

Thanks,

S. Potter wrote:

I got these string of errors in the order reported also. I solved this
by editing the following files:

…prefix…/ruby/gems/1.8/gems/rspec-1.0.8/lib/spec/rake/verify_rcov.rb
…prefix…/ruby/1.8/rexml/formatters/pretty.rb

Plus the files already patched by this point. It seems like if your
stack trace says formatters/default.rb instead of formatters/pretty.rb
then that is the file you need to patch.

My formatters/pretty.rb patch looks like the following:

place = string.rindex(’ ‘, width) || width # Position in string with last ’ ’ before cutoff
< place = string.rindex(’ ', width) # Position in string with last ’ ’
before cutoff

My rake/verify_rcov.rb patch looks like:

if line =~ / (\d+.\d+)% </tt>   </td>/
< if line =~ /<tt.*?>(\d+.\d+)%</tt> </td>/

Hope that helps someone,
Susan

unknown wrote:

Ive also applied both fixes and Im seeing exactly the same problem.
Any updates on this?

/usr/local/lib/ruby/1.8/rexml/formatters/pretty.rb:131:in `[]’: no

write_element' from /usr/local/lib/ruby/1.8/rexml/formatters/default.rb:31:inwrite’
… 16 levels…

Thanks,

I have done all the fixes except for the fix to:
…prefix…/ruby/gems/1.8/gems/rspec-1.0.8/lib/spec/rake/verify_rcov.rb

Cant find the right file to modify to try that fix…

After doing the fix to:
…prefix…/ruby/1.8/rexml/formatters/pretty.rb
I am now getting this for an error:
572 tests, 115117 assertions, 0 failures, 0 errors
/usr/lib/ruby/1.8/rexml/formatters/pretty.rb:131:in wrap': stack level too deep (SystemStackError) from /usr/lib/ruby/1.8/rexml/formatters/pretty.rb:131:inwrap’
from /usr/lib/ruby/1.8/rexml/formatters/pretty.rb:90:in write_text' from /usr/lib/ruby/1.8/rexml/formatters/default.rb:50:inwrite’
from /usr/lib/ruby/1.8/rexml/formatters/pretty.rb:75:in
write_element' from /usr/lib/ruby/1.8/rexml/formatters/pretty.rb:73:ineach’
from /usr/lib/ruby/1.8/rexml/formatters/pretty.rb:73:in
write_element' from /usr/lib/ruby/1.8/rexml/formatters/default.rb:31:inwrite’
from /usr/lib/ruby/1.8/rexml/formatters/pretty.rb:75:in
write_element' ... 12 levels... from /usr/lib/ruby/1.8/rcov.rb:628:ineach’
from /usr/lib/ruby/1.8/rcov.rb:628:in `dump_coverage_info’
from /usr/bin/rcov:405
from /usr/lib/ruby/1.8/test/unit.rb:278

Any suggestions or help you guys can give me?

Thanks Susan.

For the record, I’m running “rake test:functionals” on a Rails 2.1
project using:

ruby 1.8.7-p22 from Macports 1.600 on OS X (Tiger)
rcov 0.8.1.2.0

and getting the error:
/opt/local/lib/ruby/1.8/rexml/formatters/pretty.rb:131:in `[]’: no
implicit conversion from nil to integer (TypeError)

until I applied the patch below to pretty.rb

S. Potter wrote:

My formatters/pretty.rb patch looks like the following:

place = string.rindex(’ ', width) || width # Position in string with last ’ ’ before cutoff

Any suggestions or help you guys can give me?

I’m having the same issues as Jeff but am running ruby 1.8.7

Sean H. wrote:

Nice catch!

After applying both fixes, I now get this:

/usr/local/lib/ruby/1.8/rexml/formatters/pretty.rb:131:in `[]’: no
implicit conversion from nil to integer (TypeError)

Hey Sean, it looks like the rexml code is assuming that there’ll be a ’
’ somewhere in the code to wrap on. I was able to fix this with the
following patch to the pretty.rb file :

— /opt/ruby-1.8.7-p72/lib/ruby/1.8/rexml/formatters/pretty.rb.OLD
2009-02-15 14:47:32.000000000 -0600
+++ /opt/ruby-1.8.7-p72/lib/ruby/1.8/rexml/formatters/pretty.rb
2009-02-15 14:48:50.000000000 -0600
@@ -126,10 +126,11 @@

   def wrap(string, width)
     # Recursively wrap string at width.
     return string if string.length <= width
     place = string.rindex(' ', width) # Position in string with 

last ’ ’ before cutoff

  •    return string if place.nil? # there aren't any ' 's before 
    

cutoff, nothing to split on.
return string[0,place] + “\n” + wrap(string[place+1…-1],
width)
end

 end

end

Roy Truelove wrote:

Sean H. wrote:

Nice catch!

After applying both fixes, I now get this:

/usr/local/lib/ruby/1.8/rexml/formatters/pretty.rb:131:in `[]’: no
implicit conversion from nil to integer (TypeError)

Hey Sean, it looks like the rexml code is assuming that there’ll be a ’
’ somewhere in the code to wrap on. I was able to fix this with the
following patch to the pretty.rb file :

— /opt/ruby-1.8.7-p72/lib/ruby/1.8/rexml/formatters/pretty.rb.OLD
2009-02-15 14:47:32.000000000 -0600
+++ /opt/ruby-1.8.7-p72/lib/ruby/1.8/rexml/formatters/pretty.rb
2009-02-15 14:48:50.000000000 -0600
@@ -126,10 +126,11 @@

   def wrap(string, width)
     # Recursively wrap string at width.
     return string if string.length <= width
     place = string.rindex(' ', width) # Position in string with 

last ’ ’ before cutoff

  •    return string if place.nil? # there aren't any ' 's before 
    

cutoff, nothing to split on.
return string[0,place] + “\n” + wrap(string[place+1…-1],
width)
end

 end

end

There might still be spaces in the string, how about,

— pretty.rb.old 2009-05-06 10:50:37.000000000 +1000
+++ pretty.rb 2009-05-06 10:55:37.000000000 +1000
@@ -128,6 +128,8 @@
# Recursively wrap string at width.
return string if string.length <= width
place = string.rindex(’ ', width) # Position in string with
last ’ ’ before cutoff

  •    place = string.index(' ') if place.nil?
    
  •    return string if place.nil? # there aren't any ' 's before 
    

cutoff, nothing to split on.
return string[0,place] + “\n” + wrap(string[place+1…-1],
width)
end