Skip to content
This repository has been archived by the owner on Nov 30, 2024. It is now read-only.

Switch rspec local data to a thread accessor #610

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions Changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@ Enchancements
* Improve diff for `anything` matchers by hiding the value "anything" is matched
against. (Karl Heitmann, #599)

Bug Fixes:

* Switch current thread data to alias/accessors to avoid issues with mocked systems.
(Jon Rowe, #610)

### 3.13.1 / 2024-02-23
[Full Changelog](http://github.com/rspec/rspec-support/compare/v3.13.0...v3.13.1)

Expand Down
12 changes: 10 additions & 2 deletions lib/rspec/support.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
# frozen_string_literal: true

class Thread
attr_accessor :__rspec_local_data

class << self
alias __rspec_current_thread current
end
end

module RSpec
module Support
# @api private
Expand Down Expand Up @@ -91,9 +99,9 @@ def self.class_of(object)
end

# A single thread local variable so we don't excessively pollute that namespace.
if RUBY_VERSION.to_f >= 2
if RUBY_VERSION.to_f != 1.9
def self.thread_local_data
Thread.current.thread_variable_get(:__rspec) || Thread.current.thread_variable_set(:__rspec, {})
Thread.__rspec_current_thread.__rspec_local_data ||= {}
end
else
def self.thread_local_data
Expand Down
33 changes: 32 additions & 1 deletion spec/rspec/support_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -196,14 +196,45 @@ def object.some_method
end

if defined?(Fiber) && RUBY_VERSION.to_f >= 2.0
it "shares data across fibres" do
broken_on_jruby =
if RSpec::Support::Ruby.jruby?
"As Fiber.new creates a new thread on JRuby this is currently " \
"broken. There are alternative implementations that do work but " \
"they cause issues for mocks, so given this is a minor edge case " \
"and thread data is already broken, its acceptable. Pending " \
"because future JRuby may fix this. see: "\
"https://github.com/jruby/jruby/issues/1806 and " \
"https://github.com/rspec/rspec-support/pull/610"
else
false
end

it "shares data across fibers", :pending => broken_on_jruby do
RSpec::Support.thread_local_data[:__for_test] = :oh_hai

Fiber.new do
expect(RSpec::Support.thread_local_data[:__for_test]).to eq(:oh_hai)
end.resume
end
end

it "works when Thread.current is mocked" do
expect(Thread).to_not receive(:current)

RSpec::Support.thread_local_data[:__for_test] = :oh_hai
expect(RSpec::Support.thread_local_data[:__for_test]).to eq :oh_hai
end

it "works when Thread#thread_variable_get and Thread#thread_variable_set are mocked" do
expect(Thread.current).to receive(:thread_variable_set).with(:test, true).once.and_return(true)
expect(Thread.current).to receive(:thread_variable_get).with(:test).once.and_return(true)

Thread.current.thread_variable_set(:test, true)
expect(Thread.current.thread_variable_get(:test)).to eq true

RSpec::Support.thread_local_data[:__for_test] = :oh_hai
expect(RSpec::Support.thread_local_data[:__for_test]).to eq :oh_hai
end
end

describe "failure notification" do
Expand Down
Loading