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)
 | 
			
		||||
    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)
 | 
			
		||||
    before :each do
 | 
			
		||||
      @lock = Mutex.new
 | 
			
		||||
    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