Module: RSpec::Multicore::Snapshot

Defined in:
lib/rspec/multicore/reporter_bridge.rb

Overview

Converts execution results and exceptions to bounded plain-value state.

Constant Summary collapse

RESULT_FIELDS =
%i[status started_at finished_at run_time pending_message pending_fixed].freeze

Class Method Summary collapse

Class Method Details

.apply_description(example, description) ⇒ Object



97
98
99
100
101
102
103
# File 'lib/rspec/multicore/reporter_bridge.rb', line 97

def apply_description(example, description)
   = example.
  if [:description].to_s.empty?
    [:full_description] = "#{[:full_description]}#{description}"
  end
  [:description] = description
end

.apply_example(example, data) ⇒ Object



45
46
47
48
49
50
51
52
53
54
55
56
# File 'lib/rspec/multicore/reporter_bridge.rb', line 45

def apply_example(example, data)
  description = data[:description]
  apply_description(example, description) if description && !description.empty?

  result = example.execution_result
  RESULT_FIELDS.each do |field|
    result.public_send("#{field}=", decode_value(data.fetch(:result)[field]))
  end
  result.exception = restore_failure(data.dig(:result, :exception))
  result.pending_exception = restore_failure(data.dig(:result, :pending_exception))
  example
end

.attach_failure_details(exception, cause, children) ⇒ Object



119
120
121
122
123
124
125
# File 'lib/rspec/multicore/reporter_bridge.rb', line 119

def attach_failure_details(exception, cause, children)
  exception.define_singleton_method(:cause) { cause } if cause
  if children.any? && !exception.respond_to?(:all_exceptions)
    exception.define_singleton_method(:all_exceptions) { children }
  end
  exception
end

.build_exception(data, children) ⇒ Object



110
111
112
113
114
115
116
117
# File 'lib/rspec/multicore/reporter_bridge.rb', line 110

def build_exception(data, children)
  klass = Object.const_get(data.fetch(:class))
  raise TypeError unless klass <= Exception

  children.empty? ? klass.new(data.fetch(:message)) : klass.new(children)
rescue NameError, TypeError, ArgumentError
  RemoteFailure.new(data, all_exceptions: children)
end

.cycle_failure(exception) ⇒ Object



127
128
129
130
# File 'lib/rspec/multicore/reporter_bridge.rb', line 127

def cycle_failure(exception)
  { class: exception.class.name, message: exception.message, backtrace: exception.backtrace,
    cause: nil, children: [] }
end

.decode_value(value) ⇒ Object



88
# File 'lib/rspec/multicore/reporter_bridge.rb', line 88

def decode_value(value) = value.is_a?(Hash) && value.key?(:time) ? Time.at(value[:time]) : value

.encode_value(value) ⇒ Object



86
# File 'lib/rspec/multicore/reporter_bridge.rb', line 86

def encode_value(value) = value.is_a?(Time) ? { time: value.to_f } : value

.example(example, description: nil) ⇒ Object



36
37
38
39
40
41
42
43
# File 'lib/rspec/multicore/reporter_bridge.rb', line 36

def example(example, description: nil)
  result = example.execution_result
  data = RESULT_FIELDS.to_h { [_1, encode_value(result.public_send(_1))] }
  data[:exception] = failure(result.exception)
  data[:pending_exception] = failure(result.pending_exception)

  { id: example.id, description:, result: data }
end

.failure(exception, seen = {}.compare_by_identity) ⇒ Object



58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
# File 'lib/rspec/multicore/reporter_bridge.rb', line 58

def failure(exception, seen = {}.compare_by_identity)
  return unless exception
  return cycle_failure(exception) if seen[exception]

  seen = seen.dup
  seen[exception] = true
  children = exception.respond_to?(:all_exceptions) ? exception.all_exceptions : []
  {
    class: exception.class.name,
    message: exception.message,
    backtrace: exception.backtrace,
    cause: failure(exception.cause, seen),
    children: children.map { failure(_1, seen) }
  }
end

.generated_description?Boolean

Returns:

  • (Boolean)


105
106
107
108
# File 'lib/rspec/multicore/reporter_bridge.rb', line 105

def generated_description?
  defined?(RSpec::Matchers) && RSpec::Matchers.respond_to?(:generated_description) &&
    !RSpec::Matchers.generated_description.to_s.empty?
end

.restore_failure(data) ⇒ Object



74
75
76
77
78
79
80
81
82
83
84
# File 'lib/rspec/multicore/reporter_bridge.rb', line 74

def restore_failure(data)
  return unless data

  cause = restore_failure(data[:cause])
  children = Array(data[:children]).map { restore_failure(_1) }
  exception = build_exception(data, children)
  exception.set_backtrace(data[:backtrace])
  attach_failure_details(exception, cause, children)
rescue StandardError
  RemoteFailure.new(data, cause:, all_exceptions: children)
end

.runtime_description(example) ⇒ Object



90
91
92
93
94
95
# File 'lib/rspec/multicore/reporter_bridge.rb', line 90

def runtime_description(example)
  description = example.[:description].to_s
  return description unless description.empty?

  RSpec::Matchers.generated_description.to_s if generated_description?
end