about summary refs log tree commit homepage
path: root/test/unit/test_semaphore.rb
diff options
context:
space:
mode:
Diffstat (limited to 'test/unit/test_semaphore.rb')
-rw-r--r--test/unit/test_semaphore.rb118
1 files changed, 118 insertions, 0 deletions
diff --git a/test/unit/test_semaphore.rb b/test/unit/test_semaphore.rb
new file mode 100644
index 0000000..5ce70f7
--- /dev/null
+++ b/test/unit/test_semaphore.rb
@@ -0,0 +1,118 @@
+root_dir = File.join(File.dirname(__FILE__), "../..")
+require File.join(root_dir, "test/test_helper")
+require File.join(root_dir, "lib/mongrel/semaphore")
+
+class TestSemaphore < Test::Unit::TestCase
+  def setup
+    super
+    
+    @semaphore = Semaphore.new
+  end
+  
+  def test_wait_prevents_thread_from_running
+    thread = Thread.new { @semaphore.wait }
+    give_up_my_time_slice
+    
+    assert thread.stop?
+  end
+  
+  def test_signal_allows_waiting_thread_to_run
+    ran = false
+    thread = Thread.new { @semaphore.wait; ran = true }
+    give_up_my_time_slice
+    
+    @semaphore.signal
+    give_up_my_time_slice
+    
+    assert ran
+  end
+  
+  def test_wait_allows_only_specified_number_of_resources
+    @semaphore = Semaphore.new(1)
+    
+    run_count = 0
+    thread1 = Thread.new { @semaphore.wait; run_count += 1 }
+    thread2 = Thread.new { @semaphore.wait; run_count += 1 }
+    give_up_my_time_slice
+    
+    assert_equal 1, run_count
+  end
+  
+  def test_semaphore_serializes_threads
+    @semaphore = Semaphore.new(1)
+    
+    result = ""
+    thread1 = Thread.new do
+      @semaphore.wait
+      4.times do |i|
+        give_up_my_time_slice
+        result << i.to_s
+      end
+      @semaphore.signal
+    end
+    
+    thread2 = Thread.new do
+      @semaphore.wait
+      ("a".."d").each do |char|
+        give_up_my_time_slice
+        result << char
+      end
+      @semaphore.signal
+    end
+    
+    give_up_my_time_slice
+    @semaphore.wait
+    
+    assert_equal "0123abcd", result
+  end
+  
+  def test_synchronize_many_threads
+    @semaphore = Semaphore.new(1)
+    
+    result = []
+    5.times do |i|
+      Thread.new do
+        @semaphore.wait
+        2.times { |j| result << [i, j] }
+        @semaphore.signal
+      end
+    end
+    
+    give_up_my_time_slice
+    @semaphore.wait
+    
+    5.times do |i|
+      2.times do |j|
+        assert_equal i, result[2 * i + j][0]
+        assert_equal j, result[2 * i + j][1]
+      end
+    end
+  end
+  
+  def test_synchronize_ensures_signal
+    @semaphore = Semaphore.new(1)
+    threads = []
+    run_count = 0
+    threads << Thread.new do
+      @semaphore.synchronize { run_count += 1 }
+    end
+    threads << Thread.new do
+      @semaphore.synchronize { run_count += 1; raise "I'm throwing an error." }
+    end
+    threads << Thread.new do
+      @semaphore.synchronize { run_count += 1 }
+    end
+    
+    give_up_my_time_slice
+    @semaphore.wait
+    
+    assert !threads.any? { |thread| thread.alive? }
+    assert_equal 3, run_count
+  end
+  
+  private
+  
+  def give_up_my_time_slice
+    sleep(0)
+  end
+end \ No newline at end of file