summaryrefslogtreecommitdiff
path: root/lib/gitlab/ci/parsers
diff options
context:
space:
mode:
authorShinya Maeda <shinya@gitlab.com>2018-09-04 12:09:24 +0000
committerKamil TrzciƄski <ayufan@ayufan.eu>2018-09-04 12:09:24 +0000
commitc41492dd40c2b7bda9ada002938d1cbb86905948 (patch)
treec946f15daaeb4de3a2e5da127cecc7d648b03ad3 /lib/gitlab/ci/parsers
parentf7c1a5e1ed7003f9c35e9f81b94789562f968f57 (diff)
downloadgitlab-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.rb45
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)