Update deadlock_retry plugin with latest upstream code.
[rails.git] / vendor / plugins / deadlock_retry / test / deadlock_retry_test.rb
1 begin
2   require 'active_record'
3 rescue LoadError
4   if ENV['ACTIVERECORD_PATH'].nil?
5     abort <<MSG
6 Please set the ACTIVERECORD_PATH environment variable to the directory
7 containing the active_record.rb file.
8 MSG
9   else
10     $LOAD_PATH.unshift << ENV['ACTIVERECORD_PATH']
11     begin
12       require 'active_record'
13     rescue LoadError
14       abort "ActiveRecord could not be found."
15     end
16   end
17 end
18
19 require 'test/unit'
20 require "#{File.dirname(__FILE__)}/../lib/deadlock_retry"
21
22 class MockModel
23   @@open_transactions = 0
24
25   def self.transaction(*objects)
26     @@open_transactions += 1
27     yield
28   ensure
29     @@open_transactions -= 1
30   end
31
32   def self.open_transactions
33     @@open_transactions
34   end
35
36   def self.connection
37     self
38   end
39
40   def self.logger
41     @logger ||= Logger.new(nil)
42   end
43
44   include DeadlockRetry
45 end
46
47 class DeadlockRetryTest < Test::Unit::TestCase
48   DEADLOCK_ERROR = "MySQL::Error: Deadlock found when trying to get lock"
49   TIMEOUT_ERROR = "MySQL::Error: Lock wait timeout exceeded"
50
51   def test_no_errors
52     assert_equal :success, MockModel.transaction { :success }
53   end
54
55   def test_no_errors_with_deadlock
56     errors = [ DEADLOCK_ERROR ] * 3
57     assert_equal :success, MockModel.transaction { raise ActiveRecord::StatementInvalid, errors.shift unless errors.empty?; :success }
58     assert errors.empty?
59   end
60
61   def test_no_errors_with_lock_timeout
62     errors = [ TIMEOUT_ERROR ] * 3
63     assert_equal :success, MockModel.transaction { raise ActiveRecord::StatementInvalid, errors.shift unless errors.empty?; :success }
64     assert errors.empty?
65   end
66
67   def test_error_if_limit_exceeded
68     assert_raise(ActiveRecord::StatementInvalid) do
69       MockModel.transaction { raise ActiveRecord::StatementInvalid, DEADLOCK_ERROR }
70     end
71   end
72
73   def test_error_if_unrecognized_error
74     assert_raise(ActiveRecord::StatementInvalid) do
75       MockModel.transaction { raise ActiveRecord::StatementInvalid, "Something else" }
76     end
77   end
78
79   def test_error_in_nested_transaction_should_retry_outermost_transaction
80     tries = 0
81     errors = 0
82
83     MockModel.transaction do
84       tries += 1
85       MockModel.transaction do
86         MockModel.transaction do
87           errors += 1
88           raise ActiveRecord::StatementInvalid, "MySQL::Error: Lock wait timeout exceeded" unless errors > 3
89         end
90       end
91     end
92   
93     assert_equal 4, tries
94   end
95 end