Move common lock test behavior out of mutex spec into module.
This commit is contained in:
parent
2af2cdc852
commit
5dc3c7299e
|
@ -0,0 +1,60 @@
|
|||
module ProcessShared
|
||||
# Classes that include this module should assign a lock object to
|
||||
# @lock before each test.
|
||||
module LockBehavior
|
||||
|
||||
# Fork +n+ processes. In each, yield the block (passing the process
|
||||
# number), then call Kernel.exit! Waits for all processes to
|
||||
# complete before returning.
|
||||
def fork_many(n)
|
||||
pids = []
|
||||
n.times do |i|
|
||||
pids << fork do
|
||||
yield i
|
||||
Kernel.exit!
|
||||
end
|
||||
end
|
||||
|
||||
pids.each { |pid| ::Process.wait(pid) }
|
||||
end
|
||||
|
||||
def test_protects_access_to_a_shared_variable
|
||||
mem = SharedMemory.new(:char)
|
||||
mem.put_char(0, 0)
|
||||
|
||||
fork_many(10) do |i|
|
||||
inc = (-1) ** i # half the procs increment; half decrement
|
||||
10.times do
|
||||
@lock.lock
|
||||
begin
|
||||
mem.put_char(0, mem.get_char(0) + inc)
|
||||
sleep 0.001
|
||||
ensure
|
||||
@lock.unlock
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
mem.get_char(0).must_equal(0)
|
||||
end
|
||||
|
||||
def test_protects_access_to_a_shared_variable_with_synchronize
|
||||
mem = SharedMemory.new(:char)
|
||||
mem.put_char(0, 0)
|
||||
|
||||
fork_many(10) do |i|
|
||||
inc = (-1) ** i # half the procs increment; half decrement
|
||||
10.times do
|
||||
@lock.synchronize do
|
||||
mem.put_char(0, mem.get_char(0) + inc)
|
||||
sleep 0.001
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
mem.get_char(0).must_equal(0)
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
end
|
|
@ -1,81 +1,35 @@
|
|||
require 'spec_helper'
|
||||
require 'process_shared'
|
||||
|
||||
require 'process_shared/lock_behavior'
|
||||
|
||||
module ProcessShared
|
||||
describe Mutex do
|
||||
it 'protects access to a shared variable' do
|
||||
mutex = Mutex.new
|
||||
mem = SharedMemory.new(:char)
|
||||
mem.put_char(0, 0)
|
||||
|
||||
pids = []
|
||||
10.times do |i|
|
||||
inc = (-1) ** i # half the procs increment; half decrement
|
||||
pids << fork do
|
||||
10.times do
|
||||
mutex.lock
|
||||
begin
|
||||
mem.put_char(0, mem.get_char(0) + inc)
|
||||
sleep 0.001
|
||||
ensure
|
||||
mutex.unlock
|
||||
end
|
||||
end
|
||||
Kernel.exit!
|
||||
end
|
||||
end
|
||||
include LockBehavior
|
||||
|
||||
pids.each { |pid| ::Process.wait(pid) }
|
||||
|
||||
mem.get_char(0).must_equal(0)
|
||||
before :each do
|
||||
@lock = Mutex.new
|
||||
end
|
||||
|
||||
it 'protects access to a shared variable with synchronize' do
|
||||
mutex = Mutex.new
|
||||
mem = SharedMemory.new(:char)
|
||||
mem.put_char(0, 0)
|
||||
|
||||
pids = []
|
||||
10.times do |i|
|
||||
inc = (-1) ** i # half the procs increment; half decrement
|
||||
pids << fork do
|
||||
10.times do
|
||||
mutex.synchronize do
|
||||
mem.put_char(0, mem.get_char(0) + inc)
|
||||
sleep 0.001
|
||||
end
|
||||
end
|
||||
Kernel.exit!
|
||||
end
|
||||
end
|
||||
|
||||
pids.each { |pid| ::Process.wait(pid) }
|
||||
|
||||
mem.get_char(0).must_equal(0)
|
||||
end
|
||||
|
||||
|
||||
it 'raises exception when unlocked by other process' do
|
||||
mutex = Mutex.new
|
||||
|
||||
pid = Kernel.fork do
|
||||
mutex.lock
|
||||
@lock.lock
|
||||
sleep 0.2
|
||||
mutex.unlock
|
||||
@lock.unlock
|
||||
Kernel.exit!
|
||||
end
|
||||
|
||||
sleep 0.1
|
||||
proc { mutex.unlock }.must_raise(ProcessError)
|
||||
proc { @lock.unlock }.must_raise(ProcessError)
|
||||
|
||||
::Process.wait(pid)
|
||||
end
|
||||
|
||||
it 'raises exception when locked twice by same process' do
|
||||
mutex = Mutex.new
|
||||
|
||||
mutex.lock
|
||||
proc { mutex.lock }.must_raise(ProcessError)
|
||||
mutex.unlock
|
||||
@lock.lock
|
||||
proc { @lock.lock }.must_raise(ProcessError)
|
||||
@lock.unlock
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue