Skip to content

Instantly share code, notes, and snippets.

@JoshCheek
Created July 12, 2022 19:14
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save JoshCheek/baa4ed3829b43d0e995a6afc5aa57792 to your computer and use it in GitHub Desktop.
Save JoshCheek/baa4ed3829b43d0e995a6afc5aa57792 to your computer and use it in GitHub Desktop.
Example how how stubbing methods could be threadsafe (IDK if this is how RSpec does it or not)
# really rudimentary stubbing mechanism (eg doesn't support unstubbing)
def stub(obj, method, *expected, result)
Thread.current[:stubs] ||= {}
Thread.current[:stubs][method] ||= {}
Thread.current[:stubs][method][expected] = result
obj.define_singleton_method method do |*actual| # we'll ignore keyword args here for simplicity
Thread.current[:stubs][method].fetch(actual) do
raise "#{method} invoked with unexpected args: #{actual.inspect}"
end
end
end
t1 = t2 = nil
t1 = Thread.new do
Thread.current.abort_on_exception = true
stub ENV, :[], 'KEY', "value from line #{__LINE__}"
puts "THREAD1: ENV['KEY'] = #{ENV['KEY'].inspect}"
Thread.pass until t2.stop?
t2.run
sleep
puts "THREAD1: ENV['KEY'] = #{ENV['KEY'].inspect}"
Thread.pass until t2.stop?
t2.run
end
t2 = Thread.new do
Thread.current.abort_on_exception = true
stub ENV, :[], 'KEY', "value from line #{__LINE__}"
sleep
puts "THREAD2: ENV['KEY'] = #{ENV['KEY'].inspect}"
Thread.pass until t1.stop?
t1.run
sleep
puts "THREAD2: ENV['KEY'] = #{ENV['KEY'].inspect}"
end
t1.run
[t1, t2].each &:join
# >> THREAD1: ENV['KEY'] = "value from line 17"
# >> THREAD2: ENV['KEY'] = "value from line 29"
# >> THREAD1: ENV['KEY'] = "value from line 17"
# >> THREAD2: ENV['KEY'] = "value from line 29"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment