sj26 / rspec_junit_formatter

RSpec results that your CI can read

Home Page:http://rubygems.org/gems/rspec_junit_formatter

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Regression of #57 (Encoding::UndefinedConversionError) in versions >= 0.4.0

jayhendren opened this issue · comments

Looks like #57 was fixed in 0.3.0, but regressed in 0.4.0.

The following code generates the following error in versions >= 0.4.0, but not 0.3.0. So far I have only been able to reproduce the error when using Serverspec; I haven't yet figured out how to reproduce in plain RSpec.

RSpec.configure do |c|
  c.add_formatter('RspecJunitFormatter', '/tmp/foo.xml')
end

describe 'foo' do
  describe command('echo oøps') do
    its(:stdout) { is_expected.to contain('o') }
  end
end
       foo
         Command "echo oøps"
           stdout
             should contain "o"
       
       Finished in 0.02209 seconds (files took 0.26107 seconds to load)
       1 example, 0 failures
       
       Traceback (most recent call last):
       	25: from /opt/chef/embedded/bin/rspec:23:in `<main>'
       	24: from /opt/chef/embedded/bin/rspec:23:in `load'
       	23: from /tmp/verifier/gems/gems/rspec-core-3.8.0/exe/rspec:4:in `<top (required)>'
       	22: from /tmp/verifier/gems/gems/rspec-core-3.8.0/lib/rspec/core/runner.rb:45:in `invoke'
       	21: from /tmp/verifier/gems/gems/rspec-core-3.8.0/lib/rspec/core/runner.rb:71:in `run'
       	20: from /tmp/verifier/gems/gems/rspec-core-3.8.0/lib/rspec/core/runner.rb:87:in `run'
       	19: from /tmp/verifier/gems/gems/rspec-core-3.8.0/lib/rspec/core/runner.rb:110:in `run_specs'
       	18: from /tmp/verifier/gems/gems/rspec-core-3.8.0/lib/rspec/core/reporter.rb:76:in `report'
       	17: from /tmp/verifier/gems/gems/rspec-core-3.8.0/lib/rspec/core/reporter.rb:166:in `finish'
       	16: from /tmp/verifier/gems/gems/rspec-core-3.8.0/lib/rspec/core/reporter.rb:186:in `close_after'
       	15: from /tmp/verifier/gems/gems/rspec-core-3.8.0/lib/rspec/core/reporter.rb:177:in `block in finish'
       	14: from /tmp/verifier/gems/gems/rspec-core-3.8.0/lib/rspec/core/reporter.rb:200:in `notify'
       	13: from /tmp/verifier/gems/gems/rspec-core-3.8.0/lib/rspec/core/reporter.rb:200:in `each'
       	12: from /tmp/verifier/gems/gems/rspec-core-3.8.0/lib/rspec/core/reporter.rb:201:in `block in notify'
       	11: from /tmp/verifier/gems/gems/rspec_junit_formatter-0.4.0/lib/rspec_junit_formatter/rspec3.rb:19:in `dump_summary'
       	10: from /tmp/verifier/gems/gems/rspec_junit_formatter-0.4.0/lib/rspec_junit_formatter/rspec3.rb:113:in `without_color'
       	 9: from /tmp/verifier/gems/gems/rspec_junit_formatter-0.4.0/lib/rspec_junit_formatter/rspec3.rb:100:in `swap_rspec_configuration'
       	 8: from /tmp/verifier/gems/gems/rspec_junit_formatter-0.4.0/lib/rspec_junit_formatter/rspec3.rb:19:in `block in dump_summary'
       	 7: from /tmp/verifier/gems/gems/rspec_junit_formatter-0.4.0/lib/rspec_junit_formatter.rb:32:in `xml_dump'
       	 6: from /tmp/verifier/gems/gems/rspec_junit_formatter-0.4.0/lib/rspec_junit_formatter.rb:37:in `xml_dump_examples'
       	 5: from /tmp/verifier/gems/gems/rspec_junit_formatter-0.4.0/lib/rspec_junit_formatter.rb:37:in `each'
       	 4: from /tmp/verifier/gems/gems/rspec_junit_formatter-0.4.0/lib/rspec_junit_formatter.rb:44:in `block in xml_dump_examples'
       	 3: from /tmp/verifier/gems/gems/rspec_junit_formatter-0.4.0/lib/rspec_junit_formatter.rb:74:in `xml_dump_example'
       	 2: from /tmp/verifier/gems/gems/rspec_junit_formatter-0.4.0/lib/rspec_junit_formatter.rb:81:in `xml_dump_output'
       	 1: from /tmp/verifier/gems/gems/rspec_junit_formatter-0.4.0/lib/rspec_junit_formatter.rb:165:in `escape'
       /tmp/verifier/gems/gems/rspec_junit_formatter-0.4.0/lib/rspec_junit_formatter.rb:165:in `encode': "\xC3" from ASCII-8BIT to UTF-8 (Encoding::UndefinedConversionError)

There are no errors if I remove the ø character:

describe 'foo' do
  describe command('echo oops') do
    its(:stdout) { is_expected.to contain('o') }
  end
end

Sounds to me like serverspec is interfering with encodings? Can you reproduce in plain rspec?

I wouldn't be surprised if ServerSpec is doing something funky. However, considering that the bug appeared when changing nothing except upgrading rspec_junit_formatter from 0.3.0 to 0.4.0 and that rspec_junit_formatter is the only thing besides rspec in the stack trace, this smells like an issue with rspec_junit_formatter to me.

I'm working on reproducing without ServerSpec. I'm having a bit of trouble but I feel like I'm getting close.

Ok, so I'm starting to get this one figured out. There's a few different puzzle pieces here. It's still not clear to me exactly where the issue lies, though I'm starting to suspect Serverspec is doing something wrong.

First, starting in version 0.4.0, rspec_junit_formatter starting processing :stdout and :stderr in example metadata. This is why I'm only seeing the issue with versions >= 0.4.0.

Second, Serverspec always saves stdout to example metadata (this does not appear to be configurable behavior in Serverspec, otherwise I would simply disable it and close this issue and move on).

Finally, Serverspec uses a very low-level way to read command output involving reading from pipes 4096 bytes at a time using IO.select and looping over IO#read_nonblock(4096). As far as I can tell, this often results in an output string (incorrectly?) labeled with ASCII-8BIT encoding. If I override this method to use something a bit more abstract, like IO.read(), then the output usually is UTF-8 encoding and I don't have any encoding issues.

I'm not really sure where the ASCII-8BIT encoding is ultimately coming from. That's what I'm looking into right now.

There are a couple things I wish existed that would allow for workarounds:

  • A configuration option in Serverspec to toggle recording command stdout to example metadata
  • A configuration option in rspec_junit_formatter to toggle processing stdout/stderr stored in example metadata

@Poohblah did you find anything? I seem to have the same issue.

Wisdom of the Ancients

I just pinned to version 0.3.x of this gem and moved on.

IIRC, I considered opening a PR against Serverspec, but that was a lot more work than just pinning one gem version. I barely use the junit output at all, so it simply wasn't worth my time investment.

Thank you for the update. That is what I ended up doing as well. So I guess this issue can be closed.

Sorry folks, encodings are hard!