class Covet::LogFile
Represents log file of JSON coverage information for each test method. For each write of a memory buffer to disk, a separate index file keeps track of the file offset and bytes written for the buffer. This is so that when there lots of tests in a test suite, we don't have to keep all coverage information in memory. Instead, we flush the information and write it to disk at certain intervals. This way, we can also load the information in chunks as well, using the same index file.
Constants
- LoadError
Attributes
name[R]
writes[R]
Public Class Methods
new(options = {})
click to toggle source
# File lib/covet/log_file.rb, line 19 def initialize(options = {}) @mode = options[:mode] || 'w' @name = options[:filename] || File.join(Dir.pwd, 'run_log.json') if @mode != 'r' # We only want to create the real file during the `write_end` method, so write to # a tempfile until then. This is in case the user stops their test suite with an # interrupt. @tmpfile = Tempfile.new(File.basename(@name)) @tmpname = @tmpfile.path else @tmpfile = nil @tmpname = nil end @index_file = LogFileIndex.new(:filename => options[:index_filename]) @writes = 0 end
Public Instance Methods
file_exists?()
click to toggle source
# File lib/covet/log_file.rb, line 93 def file_exists? File.exist?(@name) end
load!()
click to toggle source
# File lib/covet/log_file.rb, line 61 def load! JSON.load(File.read(@name)) end
load_buf!(buf_idx)
click to toggle source
@raises LogFile::LoadError @return Array
# File lib/covet/log_file.rb, line 79 def load_buf!(buf_idx) @index_file.reload!('r') reload!('r') index = JSON.load(File.read(@index_file.name)) pos, bytes_to_read = index[buf_idx] load_buf_from_file!(pos, bytes_to_read) end
load_each_buf!() { |res| ... }
click to toggle source
Yields each coverage buffer (Array) one a time from the run log. @raises LogFile::LoadError
# File lib/covet/log_file.rb, line 67 def load_each_buf! # yields @index_file.reload!('r') reload!('r') index = JSON.load(File.read(@index_file.name)) index.each do |(pos, bytes_to_read)| res = load_buf_from_file!(pos, bytes_to_read) yield res # @var Array end end
load_run_stats!()
click to toggle source
@raises LogFile::LoadError @return Hash
# File lib/covet/log_file.rb, line 89 def load_run_stats! load_buf!(-1).last[-1] end
reload!(mode)
click to toggle source
re-opens file, can raise Errno::ENOENT
# File lib/covet/log_file.rb, line 98 def reload!(mode) if @file && !@file.closed? @file.close end @file = File.open(@name, mode) end
write_buf(buf)
click to toggle source
# File lib/covet/log_file.rb, line 42 def write_buf(buf) check_can_write! pos_start = @tmpfile.pos @tmpfile.write(JSON.dump(buf) + ',') @writes += 1 pos_after = @tmpfile.pos @index_file.add_index(pos_start, pos_after - pos_start) end
write_end()
click to toggle source
# File lib/covet/log_file.rb, line 51 def write_end check_can_write! @tmpfile.pos -= 1 # remove final comma at end of array @tmpfile.write(']') @writes += 1 @tmpfile.close FileUtils.cp(@tmpfile, @name) @index_file.finish! end
write_start()
click to toggle source
# File lib/covet/log_file.rb, line 36 def write_start check_can_write! @tmpfile.write('[') @writes += 1 end
Private Instance Methods
check_can_write!()
click to toggle source
# File lib/covet/log_file.rb, line 111 def check_can_write! if @mode == 'r' raise "For writing to the log file, you must construct it with a different :mode" end end
file()
click to toggle source
# File lib/covet/log_file.rb, line 107 def file @file ||= File.open(@name, @mode) end
load_buf_from_file!(pos, bytes_to_read)
click to toggle source
@raises LogFile::LoadError @return Array
# File lib/covet/log_file.rb, line 119 def load_buf_from_file!(pos, bytes_to_read) file.pos = pos buf = file.read(bytes_to_read) if buf.end_with?(',', ']]') buf = buf[0..-2] end JSON.load(buf) rescue JSON::ParserError => e raise LogFile::LoadError, e.message end