Merge pull request #1621 from chef/adamleff/replace-nokogiri

Replace Nokogiri with REXML in the JUnit formatter
This commit is contained in:
Adam Leff 2017-04-03 17:24:17 -04:00 committed by GitHub
commit 5e94600eb3
6 changed files with 60 additions and 65 deletions

View file

@ -51,18 +51,11 @@ do_build() {
local _libxslt_dir local _libxslt_dir
_bundler_dir="$(pkg_path_for bundler)" _bundler_dir="$(pkg_path_for bundler)"
_libxml2_dir="$(pkg_path_for libxml2)"
_libxslt_dir="$(pkg_path_for libxslt)"
export GEM_HOME=${pkg_path}/vendor/bundle export GEM_HOME=${pkg_path}/vendor/bundle
export GEM_PATH=${_bundler_dir}:${GEM_HOME} export GEM_PATH=${_bundler_dir}:${GEM_HOME}
export BUNDLE_SILENCE_ROOT_WARNING=1 export BUNDLE_SILENCE_ROOT_WARNING=1
# don't let bundler split up the nokogiri config string (it breaks
# the build), so specify it as an env var instead
export NOKOGIRI_CONFIG="--use-system-libraries --with-zlib-dir=${_zlib_dir} --with-xslt-dir=${_libxslt_dir} --with-xml2-include=${_libxml2_dir}/include/libxml2 --with-xml2-lib=${_libxml2_dir}/lib"
bundle config build.nokogiri "${NOKOGIRI_CONFIG}"
bundle install --jobs "$(nproc)" --retry 5 --standalone \ bundle install --jobs "$(nproc)" --retry 5 --standalone \
--path "$pkg_prefix/bundle" \ --path "$pkg_prefix/bundle" \
--binstubs "$pkg_prefix/bin" --binstubs "$pkg_prefix/bin"

View file

@ -39,7 +39,6 @@ Gem::Specification.new do |spec|
spec.add_dependency 'mixlib-log' spec.add_dependency 'mixlib-log'
spec.add_dependency 'sslshake', '~> 1' spec.add_dependency 'sslshake', '~> 1'
spec.add_dependency 'parallel', '~> 1.9' spec.add_dependency 'parallel', '~> 1.9'
spec.add_dependency 'nokogiri', '~> 1.6'
spec.add_dependency 'faraday', '>=0.9.0' spec.add_dependency 'faraday', '>=0.9.0'
spec.add_dependency 'toml', '~> 0.1' spec.add_dependency 'toml', '~> 0.1'
spec.add_dependency 'addressable', '~> 2.5' spec.add_dependency 'addressable', '~> 2.5'

View file

@ -795,51 +795,61 @@ class InspecRspecJUnit < InspecRspecJson
# #
# This is the last method is invoked through the formatter interface. # This is the last method is invoked through the formatter interface.
# Converts the junit formatter constructed output_hash into nokogiri generated # Converts the junit formatter constructed output_hash into REXML generated
# XML and writes it to output. # XML and writes it to output.
# #
def close(_notification) def close(_notification)
require 'nokogiri' require 'rexml/document'
xml_output = Nokogiri::XML::Builder.new { |xml| xml_output = REXML::Document.new
xml.testsuites do xml_output.add(REXML::XMLDecl.new)
testsuites = REXML::Element.new('testsuites')
xml_output.add(testsuites)
@output_hash[:profiles].each do |profile| @output_hash[:profiles].each do |profile|
build_profile_xml(xml, profile) testsuites.add(build_profile_xml(profile))
end end
end
}.to_xml formatter = REXML::Formatters::Pretty.new
output.puts xml_output formatter.compact = true
output.puts formatter.write(xml_output.xml_decl, '')
output.puts formatter.write(xml_output.root, '')
end end
private private
def build_profile_xml(xml, profile) def build_profile_xml(profile)
xml.testsuite( profile_xml = REXML::Element.new('testsuite')
name: profile[:name], profile_xml.add_attribute('name', profile[:name])
tests: count_profile_tests(profile), profile_xml.add_attribute('tests', count_profile_tests(profile))
failed: count_profile_failed_tests(profile), profile_xml.add_attribute('failed', count_profile_failed_tests(profile))
) do
profile[:controls].each do |control| profile[:controls].each do |control|
build_control_xml(xml, control) next if control[:results].nil?
end
end
end
def build_control_xml(xml, control)
return if control[:results].nil?
control[:results].each do |result| control[:results].each do |result|
build_result_xml(xml, control, result) profile_xml.add(build_result_xml(control, result))
end end
end end
def build_result_xml(xml, control, result) profile_xml
test_class = control[:title].nil? ? 'Anonymous' : control[:id] end
xml.testcase(name: result[:code_desc], class: test_class, time: result[:run_time]) do
def build_result_xml(control, result)
result_xml = REXML::Element.new('testcase')
result_xml.add_attribute('name', result[:code_desc])
result_xml.add_attribute('class', control[:title].nil? ? 'Anonymous' : control[:id])
result_xml.add_attribute('time', result[:run_time])
if result[:status] == 'failed' if result[:status] == 'failed'
xml.failure(message: result[:message]) failure_element = REXML::Element.new('failure')
failure_element.add_attribute('message', result[:message])
result_xml.add(failure_element)
elsif result[:status] == 'skipped' elsif result[:status] == 'skipped'
xml.skipped result_xml.add_element('skipped')
end
end end
result_xml
end end
def count_profile_tests(profile) def count_profile_tests(profile)

View file

@ -23,7 +23,6 @@ dependency 'ruby'
dependency 'rubygems' dependency 'rubygems'
dependency 'bundler' dependency 'bundler'
dependency 'rb-readline' dependency 'rb-readline'
dependency 'nokogiri'
dependency 'appbundler' dependency 'appbundler'
license :project_license license :project_license

View file

@ -2,7 +2,7 @@
# author: John Kerry # author: John Kerry
require 'functional/helper' require 'functional/helper'
require 'nokogiri' require 'rexml/document'
describe 'inspec exec with junit formatter' do describe 'inspec exec with junit formatter' do
include FunctionalHelper include FunctionalHelper
@ -11,47 +11,47 @@ describe 'inspec exec with junit formatter' do
out = inspec('exec ' + example_control + ' --format junit --no-create-lockfile') out = inspec('exec ' + example_control + ' --format junit --no-create-lockfile')
out.stderr.must_equal '' out.stderr.must_equal ''
out.exit_status.must_equal 0 out.exit_status.must_equal 0
doc = Nokogiri::XML(out.stdout) doc = REXML::Document.new(out.stdout)
doc.errors.length.must_equal 0 doc.has_elements?.must_equal true
end end
it 'can execute the profile with the junit formatter' do it 'can execute the profile with the junit formatter' do
out = inspec('exec ' + example_profile + ' --format junit --no-create-lockfile') out = inspec('exec ' + example_profile + ' --format junit --no-create-lockfile')
out.stderr.must_equal '' out.stderr.must_equal ''
out.exit_status.must_equal 0 out.exit_status.must_equal 0
doc = Nokogiri::XML(out.stdout) doc = REXML::Document.new(out.stdout)
doc.errors.length.must_equal 0 doc.has_elements?.must_equal true
end end
describe 'execute a profile with junit formatting' do describe 'execute a profile with junit formatting' do
let(:doc) { Nokogiri::XML(inspec('exec ' + example_profile + ' --format junit --no-create-lockfile').stdout) } let(:doc) { REXML::Document.new(inspec('exec ' + example_profile + ' --format junit --no-create-lockfile').stdout) }
describe 'the document' do describe 'the document' do
it 'has only one testsuite' do it 'has only one testsuite' do
doc.xpath("//testsuite").length.must_equal 1 doc.elements.to_a("//testsuite").length.must_equal 1
end end
end end
describe 'the test suite' do describe 'the test suite' do
let(:suite) { doc.xpath("//testsuites/testsuite").first} let(:suite) { doc.elements.to_a("//testsuites/testsuite").first }
it 'must have 5 testcase children' do it 'must have 5 testcase children' do
suite.xpath("//testcase").length.must_equal 5 suite.elements.to_a("//testcase").length.must_equal 5
end end
it 'has the tests attribute with 5 total tests' do it 'has the tests attribute with 5 total tests' do
suite["tests"].must_equal "5" suite.attribute('tests').value.must_equal "5"
end end
it 'has the failures attribute with 0 total tests' do it 'has the failures attribute with 0 total tests' do
suite["failed"].must_equal "0" suite.attribute('failed').value.must_equal "0"
end end
it 'has 2 elements named "File /tmp should be directory"' do it 'has 2 elements named "File /tmp should be directory"' do
suite.xpath("//testcase[@name='File /tmp should be directory']").length.must_equal 2 REXML::XPath.match(suite, "//testcase[@name='File /tmp should be directory']").length.must_equal 2
end end
describe 'the testcase named "gordon_config Can\'t find file ..."' do describe 'the testcase named "gordon_config Can\'t find file ..."' do
let(:gordon_yml_tests) { suite.xpath("//testcase[@class='gordon-1.0' and @name='gordon_config']") } let(:gordon_yml_tests) { REXML::XPath.match(suite, "//testcase[@class='gordon-1.0' and @name='gordon_config']") }
let(:first_gordon_test) {gordon_yml_tests.first} let(:first_gordon_test) {gordon_yml_tests.first}
it 'should be unique' do it 'should be unique' do
@ -59,7 +59,7 @@ describe 'inspec exec with junit formatter' do
end end
it 'should be skipped' do it 'should be skipped' do
first_gordon_test.xpath("//skipped").length.must_equal 1 first_gordon_test.elements.to_a('//skipped').length.must_equal 1
end end
end end
end end

View file

@ -8,7 +8,6 @@ PATH
json (>= 1.8, < 3.0) json (>= 1.8, < 3.0)
method_source (~> 0.8) method_source (~> 0.8)
mixlib-log mixlib-log
nokogiri (~> 1.6)
parallel (~> 1.9) parallel (~> 1.9)
pry (~> 0) pry (~> 0)
rainbow (~> 2) rainbow (~> 2)
@ -56,7 +55,7 @@ GEM
concurrent-ruby (1.0.5) concurrent-ruby (1.0.5)
contracts (0.13.0) contracts (0.13.0)
diff-lcs (1.3) diff-lcs (1.3)
docker-api (1.33.2) docker-api (1.33.3)
excon (>= 0.38.0) excon (>= 0.38.0)
json json
dotenv (2.2.0) dotenv (2.2.0)
@ -67,13 +66,12 @@ GEM
eventmachine (1.2.3) eventmachine (1.2.3)
excon (0.55.0) excon (0.55.0)
execjs (2.7.0) execjs (2.7.0)
faraday (0.11.0) faraday (0.12.0.1)
multipart-post (>= 1.2, < 3) multipart-post (>= 1.2, < 3)
fast_blank (1.0.0) fast_blank (1.0.0)
fastimage (2.1.0) fastimage (2.1.0)
ffi (1.9.18) ffi (1.9.18)
github-markup (1.5.0) github-markup (1.6.0)
rinku
gssapi (1.2.0) gssapi (1.2.0)
ffi (>= 1.0.1) ffi (>= 1.0.1)
gyoku (1.3.1) gyoku (1.3.1)
@ -148,7 +146,6 @@ GEM
middleman-syntax (3.0.0) middleman-syntax (3.0.0)
middleman-core (>= 3.2) middleman-core (>= 3.2)
rouge (~> 2.0) rouge (~> 2.0)
mini_portile2 (2.1.0)
minitest (5.10.1) minitest (5.10.1)
mixlib-log (1.7.1) mixlib-log (1.7.1)
mixlib-shellout (2.2.7) mixlib-shellout (2.2.7)
@ -157,8 +154,6 @@ GEM
net-scp (1.2.1) net-scp (1.2.1)
net-ssh (>= 2.6.5) net-ssh (>= 2.6.5)
net-ssh (4.1.0) net-ssh (4.1.0)
nokogiri (1.7.1)
mini_portile2 (~> 2.1.0)
nori (2.6.0) nori (2.6.0)
padrino-helpers (0.13.3.3) padrino-helpers (0.13.3.3)
i18n (~> 0.6, >= 0.6.7) i18n (~> 0.6, >= 0.6.7)
@ -183,7 +178,6 @@ GEM
rb-inotify (0.9.8) rb-inotify (0.9.8)
ffi (>= 0.5.0) ffi (>= 0.5.0)
redcarpet (3.4.0) redcarpet (3.4.0)
rinku (2.0.2)
rouge (2.0.7) rouge (2.0.7)
rspec (3.5.0) rspec (3.5.0)
rspec-core (~> 3.5.0) rspec-core (~> 3.5.0)
@ -233,7 +227,7 @@ GEM
winrm-fs (~> 1.0) winrm-fs (~> 1.0)
tzinfo (1.2.3) tzinfo (1.2.3)
thread_safe (~> 0.1) thread_safe (~> 0.1)
uglifier (3.1.11) uglifier (3.1.13)
execjs (>= 0.3.0, < 3) execjs (>= 0.3.0, < 3)
winrm (2.1.3) winrm (2.1.3)
builder (>= 2.1.2) builder (>= 2.1.2)