diff options
author | Shinya Maeda <shinya@gitlab.com> | 2018-09-04 12:09:24 +0000 |
---|---|---|
committer | Kamil TrzciĆski <ayufan@ayufan.eu> | 2018-09-04 12:09:24 +0000 |
commit | c41492dd40c2b7bda9ada002938d1cbb86905948 (patch) | |
tree | c946f15daaeb4de3a2e5da127cecc7d648b03ad3 /lib/gitlab/ci/parsers | |
parent | f7c1a5e1ed7003f9c35e9f81b94789562f968f57 (diff) | |
download | gitlab-ce-c41492dd40c2b7bda9ada002938d1cbb86905948.tar.gz |
Fix bugs/edge cases of JUnitParser
Diffstat (limited to 'lib/gitlab/ci/parsers')
-rw-r--r-- | lib/gitlab/ci/parsers/junit.rb | 45 |
1 files changed, 21 insertions, 24 deletions
diff --git a/lib/gitlab/ci/parsers/junit.rb b/lib/gitlab/ci/parsers/junit.rb index 3c4668ec13b..d1c136f2009 100644 --- a/lib/gitlab/ci/parsers/junit.rb +++ b/lib/gitlab/ci/parsers/junit.rb @@ -2,18 +2,14 @@ module Gitlab module Ci module Parsers class Junit - attr_reader :data - JunitParserError = Class.new(StandardError) def parse!(xml_data, test_suite) - @data = Hash.from_xml(xml_data) + root = Hash.from_xml(xml_data) - each_suite do |testcases| - testcases.each do |testcase| - test_case = create_test_case(testcase) - test_suite.add_test_case(test_case) - end + all_cases(root) do |test_case| + test_case = create_test_case(test_case) + test_suite.add_test_case(test_case) end rescue REXML::ParseException => e raise JunitParserError, "XML parsing failed: #{e.message}" @@ -23,26 +19,27 @@ module Gitlab private - def each_suite - testsuites.each do |testsuite| - yield testcases(testsuite) - end - end + def all_cases(root, parent = nil, &blk) + return unless root.present? - def testsuites - if data['testsuites'] - data['testsuites']['testsuite'] - else - [data['testsuite']] + [root].flatten.compact.map do |node| + next unless node.is_a?(Hash) + + # we allow only one top-level 'testsuites' + all_cases(node['testsuites'], root, &blk) unless parent + + # we require at least one level of testsuites or testsuite + each_case(node['testcase'], &blk) if parent + + # we allow multiple nested 'testsuite' (eg. PHPUnit) + all_cases(node['testsuite'], root, &blk) end end - def testcases(testsuite) - if testsuite['testcase'].is_a?(Array) - testsuite['testcase'] - else - [testsuite['testcase']] - end + def each_case(testcase, &blk) + return unless testcase.present? + + [testcase].flatten.compact.map(&blk) end def create_test_case(data) |