require 'spec_helper'
require 'mach/error'
require 'mach/functions'
require 'mach/semaphore'

module Mach
  describe 'low level semaphore functions' do
    include Functions

    it 'raises exception with invalid args' do
      p = proc { semaphore_create(mach_task_self, nil, 1234, 1) }
      p.must_raise Error::INVALID_ARGUMENT
    end
  end

  describe Semaphore do
    it 'creates a semaphore' do
      sem = Semaphore.new
      sem.destroy
    end

    it 'raises exception with invalid args' do
      p = proc { Semaphore.new(:sync_policy => :no_such) }
      p.must_raise ArgumentError # Error::INVALID_ARGUMENT
    end

    it 'signals/waits in same task' do
      sem = Semaphore.new(:value => 0)
      sem.signal
      sem.wait
      sem.destroy
    end
  end
end

require 'spec_helper'
require 'mach'

module Mach
  describe 'low level semaphore functions' do
    include Functions

    it 'raises exception with invalid args' do
      p = proc { semaphore_create(mach_task_self, nil, 1234, 1) }
      p.must_raise Error::INVALID_ARGUMENT
    end
  end

  describe Semaphore do
    it 'creates a semaphore' do
      sem = Semaphore.new
      sem.destroy
    end

    it 'raises exception with invalid args' do
      p = proc { Semaphore.new(:sync_policy => :no_such) }
      p.must_raise ArgumentError # Error::INVALID_ARGUMENT
    end

    it 'signals/waits in same task' do
      sem = Semaphore.new(:value => 0)
      sem.signal
      sem.wait
      sem.destroy
    end

    it 'coordinates access to shared resource between two tasks' do
      sem = Semaphore.new(:value => 0)

      port = Port.new
      port.insert_right(:make_send)
      Task.self.set_bootstrap_port(port)

      child = fork do
        parent_port = Task.self.get_bootstrap_port
        Task.self.copy_send(parent_port)
        # parent will copy send rights to sem into child task
        sleep 0.5
        sem.signal
        Kernel.exit!
      end

      child_task_port = port.receive_right

      start = Time.now.to_f
      sem.insert_right(:copy_send, :ipc_space => child_task_port)
      sem.wait
      elapsed = Time.now.to_f - start

      Process.wait child

      elapsed.must be_gt(0.4)
    end
  end
end

Add test demonstrating copying semaphore from parent to child.
Add test demonstrating copying semaphore from parent to child.
