Module: RSpecTracer::Tracker::IOHooks Private

Defined in:
lib/rspec_tracer/tracker/io_hooks.rb,
lib/rspec_tracer/tracker/io_hooks/io.rb,
lib/rspec_tracer/tracker/io_hooks/file.rb,
lib/rspec_tracer/tracker/io_hooks/json.rb,
lib/rspec_tracer/tracker/io_hooks/yaml.rb,
lib/rspec_tracer/tracker/io_hooks/kernel.rb

Overview

This module is part of a private API. You should avoid using this module if possible, as it may be removed or be changed in the future.

Internal IOHooks — see RSpecTracer for the user-facing surface.

Defined Under Namespace

Modules: FileReads, IOReads, JSONReads, KernelReads, YAMLReads

Constant Summary collapse

DEFAULT_EXTENSIONS =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

Non-Ruby extensions the hook is interested in. .rb is covered by CoverageAdapter, so it’s excluded from the default :data allow-set. Kernel#load uses a separate predicate (.rb only).

%w[
  .yml .yaml .json .erb .haml .slim .builder .jbuilder .ru .rake
].to_set.freeze
BUCKET_KEY =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

:rspec_tracer_io_bucket
REENTRY_KEY =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

Re-entry guard: Digest::SHA256.file internally opens the file, which re-fires the File.open hook. Without this flag, the first hooked read blows the stack via infinite recursion.

:rspec_tracer_io_in_hook

Class Attribute Summary collapse

Class Method Summary collapse

Class Attribute Details

.rootObject (readonly)

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



64
65
66
# File 'lib/rspec_tracer/tracker/io_hooks.rb', line 64

def root
  @root
end

Class Method Details

.clear_bucketObject

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

rubocop:enable Naming/AccessorMethodName



125
126
127
# File 'lib/rspec_tracer/tracker/io_hooks.rb', line 125

def clear_bucket
  Thread.current[BUCKET_KEY] = nil
end

.current_bucketObject

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



99
100
101
# File 'lib/rspec_tracer/tracker/io_hooks.rb', line 99

def current_bucket
  Thread.current[BUCKET_KEY]
end

.install(root:, filter: ->(_path) { true }, extensions: DEFAULT_EXTENSIONS) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
# File 'lib/rspec_tracer/tracker/io_hooks.rb', line 66

def install(root:, filter: ->(_path) { true }, extensions: DEFAULT_EXTENSIONS)
  @root = File.expand_path(root)
  @root_prefix = "#{@root}/"
  @extensions = extensions
  @filter = filter

  ::File.singleton_class.prepend(FileReads)
  ::IO.singleton_class.prepend(IOReads)
  ::YAML.singleton_class.prepend(YAMLReads) if defined?(::YAML)
  ::JSON.singleton_class.prepend(JSONReads) if defined?(::JSON)
  # Two prepends: singleton_class catches `Kernel.load('x')`,
  # the module itself catches implicit `load 'x'` in method
  # bodies (via Object's ancestor chain). `module_function`
  # on Kernel creates two separate method objects, so both
  # dispatch paths must be instrumented independently.
  ::Kernel.singleton_class.prepend(KernelReads)
  ::Kernel.prepend(KernelReads)

  self
end

.installed?Boolean

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns:

  • (Boolean)


95
96
97
# File 'lib/rspec_tracer/tracker/io_hooks.rb', line 95

def installed?
  !@root_prefix.nil?
end

.record(path) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Record a :data input (File/IO/YAML/JSON hooks). The allow-predicate is the coordinator’s default extension + filter combo.



132
133
134
135
136
# File 'lib/rspec_tracer/tracker/io_hooks.rb', line 132

def record(path)
  _record(path, :data) do |p|
    @extensions.include?(File.extname(p)) && @filter.call(p)
  end
end

.record_ruby_load(path) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Record a :ruby input (Kernel#load hook). Belt-and-suspenders for dynamically-constructed load paths that might bypass the Coverage module’s require-graph observation. The example registry dedupes overlap with CoverageAdapter.



142
143
144
# File 'lib/rspec_tracer/tracker/io_hooks.rb', line 142

def record_ruby_load(path)
  _record(path, :ruby) { |p| p.end_with?('.rb') }
end

.set_bucket(bucket) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Non-block lifecycle for integration with RSpec hooks (which can’t wrap the example body in a Ruby block). The Tracker coordinator calls set_bucket at example_started time and clear_bucket at example_finished time. Unlike with_bucket, these do not save/restore a prior bucket - the coordinator owns the Thread.current slot for the span of an example. rubocop:disable Naming/AccessorMethodName



120
121
122
# File 'lib/rspec_tracer/tracker/io_hooks.rb', line 120

def set_bucket(bucket)
  Thread.current[BUCKET_KEY] = bucket
end

.uninstallObject

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



87
88
89
90
91
92
93
# File 'lib/rspec_tracer/tracker/io_hooks.rb', line 87

def uninstall
  @root = nil
  @root_prefix = nil
  @extensions = nil
  @filter = nil
  self
end

.with_bucket(bucket) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



103
104
105
106
107
108
109
110
111
# File 'lib/rspec_tracer/tracker/io_hooks.rb', line 103

def with_bucket(bucket)
  prev = Thread.current[BUCKET_KEY]
  Thread.current[BUCKET_KEY] = bucket
  begin
    yield
  ensure
    Thread.current[BUCKET_KEY] = prev
  end
end