Class: Flutter::Tracker

Inherits:
Object
  • Object
show all
Defined in:
lib/flutter/tracker.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(sources, exclusions, storage_class, storage_options) ⇒ Tracker

Returns a new instance of Tracker.

Parameters:

  • sources (Array<String>)
  • exclusions (Array<String>)
  • storage_class (Class<Flutter::Persistence::AbstractStorage>)
  • storage_options (Hash)

    Additionally options that should be passed to the +storage_class+ constructor



23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# File 'lib/flutter/tracker.rb', line 23

def initialize(sources, exclusions, storage_class, storage_options)
  @sources = sources.map { |s| File.absolute_path(s) }
  @exclusions = exclusions.map { |s| File.absolute_path(s) }
  @storage = storage_class.new(**storage_options)
  @test_mapping = @storage.test_mapping
  @previous_test_mapping = {}
  @test_source_mapping = {}
  @source_mapping = @storage.source_mapping
  @current_source_mapping = {}
  @path_mapping = {}
  @method_prefixes = {}
  @tracked_files = {}
  @source_hints = @storage.source_hints
  @tracker_pwd = Dir.pwd
end

Instance Attribute Details

#source_mappingHash<String, Hash<String, String>>

Mapping of source files -> callable_id -> signature

Returns:

  • (Hash<String, Hash<String, String>>)

    the current value of source_mapping



15
16
17
# File 'lib/flutter/tracker.rb', line 15

def source_mapping
  @source_mapping
end

#storagePersistence::AbstractStorage

the storage instance used for persisting the state of the tracker

Returns:



15
16
17
# File 'lib/flutter/tracker.rb', line 15

def storage
  @storage
end

#test_mappingHash<String, Hash<String, Set<String>>>

Mapping of tests to files -> callable_ids

Returns:

  • (Hash<String, Hash<String, Set<String>>>)

    the current value of test_mapping



15
16
17
# File 'lib/flutter/tracker.rb', line 15

def test_mapping
  @test_mapping
end

Instance Method Details

#persist!void

This method returns an undefined value.

Persist the state of the tracker to the storage specified by #storage



97
98
99
100
101
# File 'lib/flutter/tracker.rb', line 97

def persist!
  @storage.update_test_mapping!(@test_mapping)
  @storage.update_source_mapping!(generate_source_mapping, @source_hints)
  @storage.persist!
end

#reset!void

This method returns an undefined value.

Reset the state of the tracker and the storage that it was configured with



107
108
109
110
111
112
# File 'lib/flutter/tracker.rb', line 107

def reset!
  $stdout.puts "Resetting flutter: #{@storage}"
  @storage.clear!
  @source_mapping.clear
  @test_mapping.clear
end

#skip?(test, test_location, test_source) ⇒ TrueClass, FalseClass

Decides if a test should be skipped based on all of the following criteria being met:

  1. Test was seen before
  2. Test sources have not changed since the last time it was executed
  3. All the callables triggered within the scope of this test have no changes in their source since the last time this test was executed

Parameters:

  • test (String)

    A unique identifier for the test

  • test_location (String)

    The absolute path to the source file containing the test

  • test_source (String)

    The source code of the test itself

Returns:

  • (TrueClass, FalseClass)

    If the test should be skipped



72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
# File 'lib/flutter/tracker.rb', line 72

def skip?(test, test_location, test_source)
  test_location_rel = relative_path(test_location)
  @test_source_mapping.fetch(test_location_rel) do
    @test_source_mapping[test_location_rel] = {}
  end[test] = Digest::SHA1.hexdigest(test_source)
  test_seen = @test_mapping.key?(test)

  test_source_unchanged = @test_source_mapping[test_location_rel][test] == @source_mapping.dig(
    test_location_rel, test
  )
  return false unless test_seen && test_source_unchanged

  sources = @test_mapping[test] || {}
  sources.map do |file, methods|
    @current_source_mapping[file] ||= Flutter::Parser.new(file, @source_hints[file]).signatures
    methods.map do |method|
      @source_mapping.dig(file, method) == @current_source_mapping.dig(file, method)
    end.all?
  end.all?
end

#start(test) ⇒ Object

Starts tracking calls made by +test+

Parameters:

  • test (String)

    A unique identifier for the test



41
42
43
44
45
46
47
48
49
# File 'lib/flutter/tracker.rb', line 41

def start(test)
  # Delete test from the in-memory mapping to allow each new test run
  # to store all the functions that the test calls into
  @previous_test_mapping[test] = @test_mapping.delete(test)
  @current_tracepoint = TracePoint.new(:call) do |tp|
    hit!(test, tp)
  end
  @current_tracepoint&.enable
end

#stop(test, success) ⇒ Object

End tracking (should be called after a call to #start)

Parameters:

  • test (String)

    A unique identifier for the test

  • success (TrueClass, FalseClass)

    Whether the test succeeded



54
55
56
57
# File 'lib/flutter/tracker.rb', line 54

def stop(test, success)
  @current_tracepoint&.disable
  @test_mapping[test].merge!(@previous_test_mapping.delete(test) || {}) { |_, old, new| old + new } unless success
end

#to_sObject



114
115
116
# File 'lib/flutter/tracker.rb', line 114

def to_s
  @storage.to_s
end