65 lines
1.8 KiB
Ruby
65 lines
1.8 KiB
Ruby
|
# frozen_string_literal: true
|
||
|
|
||
|
module Gitlab
|
||
|
module Ci
|
||
|
module Parsers
|
||
|
module Coverage
|
||
|
class Cobertura
|
||
|
CoberturaParserError = Class.new(Gitlab::Ci::Parsers::ParserError)
|
||
|
|
||
|
def parse!(xml_data, coverage_report)
|
||
|
root = Hash.from_xml(xml_data)
|
||
|
|
||
|
parse_all(root, coverage_report)
|
||
|
rescue Nokogiri::XML::SyntaxError
|
||
|
raise CoberturaParserError, "XML parsing failed"
|
||
|
rescue
|
||
|
raise CoberturaParserError, "Cobertura parsing failed"
|
||
|
end
|
||
|
|
||
|
private
|
||
|
|
||
|
def parse_all(root, coverage_report)
|
||
|
return unless root.present?
|
||
|
|
||
|
root.each do |key, value|
|
||
|
parse_node(key, value, coverage_report)
|
||
|
end
|
||
|
end
|
||
|
|
||
|
def parse_node(key, value, coverage_report)
|
||
|
if key == 'class'
|
||
|
Array.wrap(value).each do |item|
|
||
|
parse_class(item, coverage_report)
|
||
|
end
|
||
|
elsif value.is_a?(Hash)
|
||
|
parse_all(value, coverage_report)
|
||
|
elsif value.is_a?(Array)
|
||
|
value.each do |item|
|
||
|
parse_all(item, coverage_report)
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
def parse_class(file, coverage_report)
|
||
|
return unless file["filename"].present? && file["lines"].present?
|
||
|
|
||
|
parsed_lines = parse_lines(file["lines"])
|
||
|
|
||
|
coverage_report.add_file(file["filename"], Hash[parsed_lines])
|
||
|
end
|
||
|
|
||
|
def parse_lines(lines)
|
||
|
line_array = Array.wrap(lines["line"])
|
||
|
|
||
|
line_array.map do |line|
|
||
|
# Using `Integer()` here to raise exception on invalid values
|
||
|
[Integer(line["number"]), Integer(line["hits"])]
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
end
|