Regression of #57 (Encoding::UndefinedConversionError) in versions >= 0.4.0
jayhendren opened this issue · 7 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
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!