# -*- 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? 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 return @tmp = Tempfile.new('tdb_test') File.unlink(@tmp.path) @tdb = TDB.new(@tmp.path) assert_nothing_raised { @tdb.threadsafe! } Thread.abort_on_exception = true nr = 10000 blob = 'foo' * 1000 crazy = proc do threads = [] 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 << Thread.new { nr.times { |i| @tdb[i.to_s] = blob } } threads << t sleep 1 t.kill threads.each { |t| t.join } end 10.times { fork &crazy } Process.waitall.each do |(pid,status)| assert status.success?, status.inspect end nr.times { |i| assert_equal blob, @tdb[i.to_s] } end def test_check_methods m = TDB.instance_methods.sort if String === m[0] warn "skipping test under Ruby 1.8" return end 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 unwrapped -= [ :initialize ] 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