Class: Covet::LogFile

Inherits:
Object
  • Object
show all
Defined in:
lib/covet/log_file.rb

Overview

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.

Constant Summary collapse

LoadError =
Class.new(StandardError)

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(options = {}) ⇒ LogFile

Returns a new instance of LogFile.



19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# 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

Instance Attribute Details

#nameObject (readonly)

Returns the value of attribute name.



17
18
19
# File 'lib/covet/log_file.rb', line 17

def name
  @name
end

#writesObject (readonly)

Returns the value of attribute writes.



17
18
19
# File 'lib/covet/log_file.rb', line 17

def writes
  @writes
end

Instance Method Details

#file_exists?Boolean

Returns:

  • (Boolean)


93
94
95
# File 'lib/covet/log_file.rb', line 93

def file_exists?
  File.exist?(@name)
end

#load!Object



61
62
63
# File 'lib/covet/log_file.rb', line 61

def load!
  JSON.load(File.read(@name))
end

#load_buf!(buf_idx) ⇒ Object

Returns Array.

Returns:

  • Array



79
80
81
82
83
84
85
# 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!Object

Yields each coverage buffer (Array) one a time from the run log.



67
68
69
70
71
72
73
74
75
# 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!Object

Returns Hash.

Returns:

  • Hash



89
90
91
# File 'lib/covet/log_file.rb', line 89

def load_run_stats!
  load_buf!(-1).last[-1]
end

#reload!(mode) ⇒ Object

re-opens file, can raise Errno::ENOENT



98
99
100
101
102
103
# 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) ⇒ Object



42
43
44
45
46
47
48
49
# 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_endObject



51
52
53
54
55
56
57
58
59
# 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_startObject



36
37
38
39
40
# File 'lib/covet/log_file.rb', line 36

def write_start
  check_can_write!
  @tmpfile.write('[')
  @writes += 1
end