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

Commit b16deab

Browse files
committed
Use Mutex from core, prevent it from being stubbed
1 parent adc9a6e commit b16deab

File tree

4 files changed

+9
-90
lines changed

4 files changed

+9
-90
lines changed

lib/rspec/support/mutex.rb

Lines changed: 5 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -1,73 +1,11 @@
11
module RSpec
22
module Support
3-
# On 1.8.7, it's in the stdlib.
4-
# We don't want to load the stdlib, b/c this is a test tool, and can affect
5-
# the test environment, causing tests to pass where they should fail.
6-
#
7-
# So we're transcribing/modifying it from
8-
# https://github.com/ruby/ruby/blob/v1_8_7_374/lib/thread.rb#L56
9-
# Some methods we don't need are deleted. Anything I don't
10-
# understand (there's quite a bit, actually) is left in.
11-
#
12-
# Some formating changes are made to appease the robot overlord:
13-
# https://travis-ci.org/rspec/rspec-core/jobs/54410874
3+
# This class protects us against Mutex.new stubbed out within tests.
144
# @private
15-
class Mutex
16-
def initialize
17-
@waiting = []
18-
@locked = false
19-
@waiting.taint
20-
taint
5+
class Mutex < ::Mutex
6+
class << self
7+
define_method(:new, &::Mutex.method(:new))
218
end
22-
23-
# @private
24-
def lock
25-
while Thread.critical = true && @locked
26-
@waiting.push Thread.current
27-
Thread.stop
28-
end
29-
@locked = true
30-
Thread.critical = false
31-
self
32-
end
33-
34-
# @private
35-
def unlock
36-
return unless @locked
37-
Thread.critical = true
38-
@locked = false
39-
wakeup_and_run_waiting_thread
40-
self
41-
end
42-
43-
# @private
44-
def synchronize
45-
lock
46-
begin
47-
yield
48-
ensure
49-
unlock
50-
end
51-
end
52-
53-
private
54-
55-
def wakeup_and_run_waiting_thread
56-
begin
57-
t = @waiting.shift
58-
t.wakeup if t
59-
rescue ThreadError
60-
retry
61-
end
62-
Thread.critical = false
63-
begin
64-
t.run if t
65-
rescue ThreadError
66-
:noop
67-
end
68-
end
69-
70-
# Avoid warnings for library wide checks spec
71-
end unless defined?(::RSpec::Support::Mutex) || defined?(::Mutex)
9+
end
7210
end
7311
end

lib/rspec/support/reentrant_mutex.rb

Lines changed: 2 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
RSpec::Support.require_rspec_support "mutex"
2+
13
module RSpec
24
module Support
35
# Allows a thread to lock out other threads from a critical section of code,
@@ -6,10 +8,6 @@ module Support
68
# Based on Monitor as of 2.2 -
79
# https://github.com/ruby/ruby/blob/eb7ddaa3a47bf48045d26c72eb0f263a53524ebc/lib/monitor.rb#L9
810
#
9-
# Depends on Mutex, but Mutex is only available as part of core since 1.9.1:
10-
# exists - http://ruby-doc.org/core-1.9.1/Mutex.html
11-
# dne - http://ruby-doc.org/core-1.9.0/Mutex.html
12-
#
1311
# @private
1412
class ReentrantMutex
1513
def initialize
@@ -40,22 +38,5 @@ def exit
4038
@mutex.unlock
4139
end
4240
end
43-
44-
if defined? ::Mutex
45-
# On 1.9 and up, this is in core, so we just use the real one
46-
class Mutex < ::Mutex
47-
# If you mock Mutex.new you break our usage of Mutex, so
48-
# instead we capture the original method to return Mutexs.
49-
NEW_MUTEX_METHOD = Mutex.method(:new)
50-
51-
def self.new
52-
NEW_MUTEX_METHOD.call
53-
end
54-
end
55-
else # For 1.8.7
56-
# :nocov:
57-
RSpec::Support.require_rspec_support "mutex"
58-
# :nocov:
59-
end
6041
end
6142
end

spec/rspec/support/mutex_spec.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
require 'rspec/support/mutex'
22

33
RSpec.describe RSpec::Support::Mutex do
4-
it "allows ::Mutex to be mocked", :if => defined?(::Mutex) do
4+
it "allows ::Mutex to be mocked" do
55
expect(Mutex).to receive(:new)
66
::Mutex.new
77
end

spec/rspec/support/reentrant_mutex_spec.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
require 'thread_order'
33

44
# There are no assertions specifically
5-
# They are pass if they don't deadlock
5+
# They pass if they don't deadlock
66
RSpec.describe RSpec::Support::ReentrantMutex do
77
let!(:mutex) { described_class.new }
88
let!(:order) { ThreadOrder.new }

0 commit comments

Comments
 (0)