Module: SimpleCov::ResultMerger::ResultsetFile

Extended by:
ResultsetFile
Included in:
ResultsetFile
Defined in:
lib/simplecov/result_merger/resultset_file.rb

Overview

Read and parse a .resultset.json with the same tolerance the historical ResultMerger had: a missing or empty file quietly returns {}, an unparseable one warns and returns {}, and malformed entries inside a valid file are warned about and dropped.

Instance Method Summary collapse

Instance Method Details

#decode(content) ⇒ Object

Valid JSON need not be an object, but everything downstream iterates command => data pairs, so anything else gets the same tolerance as a parse failure. A "null" file has long meant an empty resultset.



35
36
37
38
39
40
41
42
43
44
# File 'lib/simplecov/result_merger/resultset_file.rb', line 35

def decode(content)
  return {} unless content

  parsed = JSON.parse(content)
  return {} if parsed.nil?

  parsed.instance_of?(Hash) ? drop_malformed_entries(parsed) : invalid_resultset
rescue
  invalid_resultset
end

#drop_malformed_entries(resultset) ⇒ Object



46
47
48
49
50
51
52
# File 'lib/simplecov/result_merger/resultset_file.rb', line 46

def drop_malformed_entries(resultset)
  malformed, valid = resultset.partition { |_command_name, data| !well_formed_entry?(data) }
  return resultset if malformed.empty?

  warn "[SimpleCov]: Warning! Ignoring malformed resultset entries: #{malformed.map(&:first).sort.join(", ")}"
  valid.to_h
end

#invalid_resultsetObject



61
62
63
64
# File 'lib/simplecov/result_merger/resultset_file.rb', line 61

def invalid_resultset
  warn "[SimpleCov]: Warning! Parsing JSON content of resultset file failed"
  {}
end

#parse(path) ⇒ Object



14
15
16
17
# File 'lib/simplecov/result_merger/resultset_file.rb', line 14

def parse(path)
  data = read(path)
  decode(data)
end

#read(path) ⇒ Object

A missing or blank file quietly means "no results yet"; anything else, a 1-byte truncation included, flows through decode so corruption warns instead of silently vanishing. Read first and rescue rather than check exist?, which is racy against a concurrent clean.



23
24
25
26
27
28
29
30
# File 'lib/simplecov/result_merger/resultset_file.rb', line 23

def read(path)
  data = File.read(path)
  return if data.match?(/\A\s*\z/)

  data
rescue Errno::ENOENT
  nil
end

#well_formed_entry?(data) ⇒ Boolean

Every consumer relies on a Hash carrying a Numeric "timestamp" and a Hash "coverage". A truncated or hand-edited entry would otherwise crash out of the middle of an at_exit merge.

Returns:

  • (Boolean)


57
58
59
# File 'lib/simplecov/result_merger/resultset_file.rb', line 57

def well_formed_entry?(data)
  data.instance_of?(Hash) && data["timestamp"].is_a?(Numeric) && data["coverage"].instance_of?(Hash)
end