about summary refs log tree commit homepage
path: root/test/http.rb
diff options
context:
space:
mode:
Diffstat (limited to 'test/http.rb')
-rw-r--r--test/http.rb67
1 files changed, 66 insertions, 1 deletions
diff --git a/test/http.rb b/test/http.rb
index df51836..b1fd3b3 100644
--- a/test/http.rb
+++ b/test/http.rb
@@ -6,7 +6,7 @@ require 'test/test_helper'
 require 'digest/md5'
 require 'net/http'
 require 'time'
-$stderr.sync = $stdout.sync = Thread.abort_on_exception = true
+require 'timeout'
 
 class TestHTTP < Test::Unit::TestCase
   def setup
@@ -221,4 +221,69 @@ class TestHTTP < Test::Unit::TestCase
     buf = @client.readpartial(666)
     assert_match %r{\AHTTP/1\.1 400 Bad Request\r\n}, buf
   end
+
+  def test_iosem_concurrency
+    fifo = "#@tmpdir/dev666/fifo.%u.fid"
+    Dir.mkdir("#@tmpdir/dev666")
+    Dir.mkdir("#@tmpdir/dev333")
+    File.open("#@tmpdir/dev333/fast.fid", "w") { |fp| fp.write('.') }
+    File.open("#@tmpdir/dev666/fast.fid", "w") { |fp| fp.write('.') }
+
+    # create 10 threads which are blocked on the FIFO read
+    nr = 10
+    nr.times do |i|
+      assert system("mkfifo", fifo % i), "mkfifo #{fifo % i}"
+    end
+    threads = []
+    nr.times do |i|
+      thr = Thread.new(i) do |_i|
+        res = nil
+        Net::HTTP.start(@host, @port) do |http|
+          res = http.request(Net::HTTP::Get.new("/dev666/fifo.%u.fid" % _i))
+        end
+        res
+      end
+      threads << thr
+    end
+
+    # start a fast request to the bogged down device, it should get queued
+    # FIXME: still racy
+    t_yield
+    @client.write("GET /dev666/fast.fid HTTP/1.0\r\n")
+    t_yield
+    @client.write("\r\n")
+
+    # fast request to a free device
+    Net::HTTP.start(@host, @port) do |http|
+      res = http.request(Net::HTTP::Get.new("/dev333/fast.fid"))
+      assert_equal 200, res.code.to_i
+    end
+
+    # slow device should still be stuck
+    assert_equal nil, IO.select([@client], nil, nil, 2)
+    cr = Thread.new do
+      val = @client.read
+      [ val, Time.now ]
+    end
+    wr_start = Time.now
+
+    # wake up the blocked threads
+    writer = Thread.new do
+      nr.times do |i|
+        File.open(fifo % i, "w") { |fp| fp.write(i.to_s) }
+      end
+    end
+
+    # blocked threads return
+    threads.each do |t|
+      assert_equal 403, t.value.code.to_i
+    end
+    writer.join
+
+    # fast device should be readable, now
+    fast_response, fast_finish = Timeout.timeout(5) { cr.value }
+    assert_match(%r{\AHTTP/1\.1 200 OK}, fast_response)
+    assert_match(%r{\r\n\r\n\.\z}, fast_response)
+    assert_operator fast_finish, :>, wr_start
+  end
 end