mt: just break when attempting TDB methods inside #each
[ruby-tdb.git] / test / test_tdb_mt.rb
blob0e3517c04756f00f4323f4aad9ea48947237db7f
1 # -*- encoding: binary -*-
2 $stdout.sync = $stderr.sync = true
3 require 'test/unit'
4 require 'tempfile'
5 $-w = true
6 require 'tdb'
8 class Test_TDB_MT < Test::Unit::TestCase
9   def setup
10     @tdb = @tmp = nil
11     @start_pid = $$
12   end
14   def teardown
15     return if @start_pid != $$
16     @tmp.close! if @tmp.respond_to?(:close!)
17     @tdb.close if @tdb && ! @tdb.closed?
18   end
20   def test_make_threadsafe
21     @tdb = TDB.new(nil)
22     assert_kind_of TDB, @tdb
23     assert ! @tdb.threadsafe?
24     assert_nothing_raised { @tdb.threadsafe! }
25     assert @tdb.threadsafe?
26   end
28   def test_init_threadsafe
29     @tdb = TDB.new(nil, :threadsafe => true)
30     assert @tdb.threadsafe?
31     @tdb.close
32     @tdb = TDB.new(nil, :threadsafe => false)
33     assert ! @tdb.threadsafe?
34     @tdb.close
35     @tdb = TDB.new(nil)
36     assert ! @tdb.threadsafe?
37     @tdb.close
38   end
40   def test_thread_safe_torture_test
41     @tmp = Tempfile.new('tdb_test')
42     File.unlink(@tmp.path)
43     @tdb = TDB.new(@tmp.path)
44     assert_nothing_raised { @tdb.threadsafe! }
45     Thread.abort_on_exception = true
46     nr = 1000
47     blob = 'foo' * 1000
48     crazy = proc do
49       threads = []
50       t = Thread.new do
51         while true
52           Thread.pass
53           @tdb.to_a
54         end
55       end
56       threads << Thread.new { nr.times { |i| @tdb[i.to_s] = blob } }
57       threads << Thread.new { nr.times { |i| @tdb[i.to_s] = blob } }
58       threads << Thread.new { nr.times { |i| @tdb[i.to_s] = blob } }
59       threads << Thread.new { nr.times { |i| @tdb[i.to_s] = blob } }
60       threads << Thread.new { nr.times { |i| @tdb[i.to_s] = blob } }
61       threads << t
62       sleep 1
63       t.kill
64       threads.each { |t| t.join }
65     end
66     10.times { fork &crazy }
67     Process.waitall.each do |(pid,status)|
68       assert status.success?, status.inspect
69     end
70     nr.times { |i| assert_equal blob, @tdb[i.to_s] }
71   end
73   def test_check_methods
74     m = TDB.instance_methods.sort
75     m -= Object.instance_methods
76     m -= Enumerable.instance_methods
77     m.map! { |x| x.to_sym }
78     mt = TDB::MT.instance_methods.sort
79     m -= [ :threadsafe! ]
80     m += [ :include?, :member? ]
81     m.sort!
82     unwrapped = ( (m - mt) | (mt - m)).uniq
83     assert unwrapped.empty?, "unwrapped methods: #{unwrapped.inspect}"
84     @tdb = TDB.new(nil)
85     respond_to?(:refute_match) and
86       m.each { |meth| refute_match(/\bTDB::MT\b/, @tdb.method(meth).to_s) }
87     @tdb.threadsafe!
88     m.each { |meth| assert_match(/\bTDB::MT\b/, @tdb.method(meth).to_s) }
89   end
90 end