From c6c2f7782e2270ee4684d2405376a186aa806fcd Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Fri, 3 Dec 2010 17:27:53 -0800 Subject: add optional thread-safety on a per-object basis Thread-safety is useful sometimes and needless overhead otherwise. Default to whatever TDB upstream defaults to. --- test/test_tdb_mt.rb | 85 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 test/test_tdb_mt.rb (limited to 'test') diff --git a/test/test_tdb_mt.rb b/test/test_tdb_mt.rb new file mode 100644 index 0000000..0fbe09f --- /dev/null +++ b/test/test_tdb_mt.rb @@ -0,0 +1,85 @@ +# -*- encoding: binary -*- +$stdout.sync = $stderr.sync = true +require 'test/unit' +require 'tempfile' +$-w = true +require 'tdb' + +class Test_TDB_MT < Test::Unit::TestCase + def setup + @tdb = @tmp = nil + @start_pid = $$ + end + + def teardown + return if @start_pid != $$ + @tmp.close! if @tmp.respond_to?(:close!) + @tdb.close if @tdb && ! @tdb.closed? + end + + def test_make_threadsafe + @tdb = TDB.new(nil) + assert_kind_of TDB, @tdb + assert ! @tdb.threadsafe? + assert_nothing_raised { @tdb.threadsafe! } + assert @tdb.threadsafe? + @tdb.each { |k,v| assert_equal v, @tdb[k] } + end + + def test_init_threadsafe + @tdb = TDB.new(nil, :threadsafe => true) + assert @tdb.threadsafe? + @tdb.close + @tdb = TDB.new(nil, :threadsafe => false) + assert ! @tdb.threadsafe? + @tdb.close + @tdb = TDB.new(nil) + assert ! @tdb.threadsafe? + @tdb.close + end + + def test_thread_safe_torture_test + @tdb = TDB.new(nil) + assert_nothing_raised { @tdb.threadsafe! } + pid = fork do + Thread.abort_on_exception = true + threads = [] + blob = 'foo' * 1000 + nr = 10000 + t = Thread.new do + while true + Thread.pass + @tdb.to_a + end + end + threads << Thread.new { nr.times { |i| @tdb[i.to_s] = blob } } + threads << Thread.new { nr.times { |i| @tdb[i.to_s] = blob } } + threads << Thread.new { nr.times { |i| @tdb[i.to_s] = blob } } + threads << Thread.new { nr.times { |i| @tdb[i.to_s] = blob } } + threads << t + + t.kill + threads.each { |t| t.join } + end + _, status = Process.waitpid2(pid) + assert status.success?, status.inspect + end + + def test_check_methods + m = TDB.instance_methods.sort + m -= Object.instance_methods + m -= Enumerable.instance_methods + m.map! { |x| x.to_sym } + mt = TDB::MT.instance_methods.sort + m -= [ :threadsafe! ] + m += [ :include?, :member? ] + m.sort! + unwrapped = ( (m - mt) | (mt - m)).uniq + assert unwrapped.empty?, "unwrapped methods: #{unwrapped.inspect}" + @tdb = TDB.new(nil) + respond_to?(:refute_match) and + m.each { |meth| refute_match(/\bTDB::MT\b/, @tdb.method(meth).to_s) } + @tdb.threadsafe! + m.each { |meth| assert_match(/\bTDB::MT\b/, @tdb.method(meth).to_s) } + end +end -- cgit v1.2.3-24-ge0c7