|
|
@@ -27,6 +27,7 @@ class IssueNestedSetConcurrencyTest < ActiveSupport::TestCase |
|
|
|
self.use_transactional_fixtures = false |
|
|
|
|
|
|
|
def setup |
|
|
|
skip if sqlite? |
|
|
|
CustomField.delete_all |
|
|
|
end |
|
|
|
|
|
|
@@ -35,38 +36,60 @@ class IssueNestedSetConcurrencyTest < ActiveSupport::TestCase |
|
|
|
end |
|
|
|
|
|
|
|
def test_concurrency |
|
|
|
skip if sqlite? |
|
|
|
with_settings :notified_events => [] do |
|
|
|
# Generates an issue and destroys it in order |
|
|
|
# to load all needed classes before starting threads |
|
|
|
i = Issue.generate! |
|
|
|
i.destroy |
|
|
|
# Generates an issue and destroys it in order |
|
|
|
# to load all needed classes before starting threads |
|
|
|
i = Issue.generate! |
|
|
|
i.destroy |
|
|
|
|
|
|
|
root = Issue.generate! |
|
|
|
assert_difference 'Issue.count', 60 do |
|
|
|
threads = [] |
|
|
|
3.times do |i| |
|
|
|
threads << Thread.new(i) do |
|
|
|
ActiveRecord::Base.connection_pool.with_connection do |
|
|
|
begin |
|
|
|
10.times do |
|
|
|
i = Issue.generate! :parent_issue_id => root.id |
|
|
|
c1 = Issue.generate! :parent_issue_id => i.id |
|
|
|
c2 = Issue.generate! :parent_issue_id => i.id |
|
|
|
c3 = Issue.generate! :parent_issue_id => i.id |
|
|
|
c2.reload.destroy |
|
|
|
c1.reload.destroy |
|
|
|
end |
|
|
|
rescue Exception => e |
|
|
|
Thread.current[:exception] = e.message |
|
|
|
end |
|
|
|
root = Issue.generate! |
|
|
|
assert_difference 'Issue.count', 60 do |
|
|
|
threaded(3) do |
|
|
|
10.times do |
|
|
|
i = Issue.generate! :parent_issue_id => root.id |
|
|
|
c1 = Issue.generate! :parent_issue_id => i.id |
|
|
|
c2 = Issue.generate! :parent_issue_id => i.id |
|
|
|
c3 = Issue.generate! :parent_issue_id => i.id |
|
|
|
c2.reload.destroy |
|
|
|
c1.reload.destroy |
|
|
|
end |
|
|
|
end |
|
|
|
end |
|
|
|
end |
|
|
|
|
|
|
|
def test_concurrent_subtasks_creation |
|
|
|
root = Issue.generate! |
|
|
|
assert_difference 'Issue.count', 30 do |
|
|
|
threaded(3) do |
|
|
|
10.times do |
|
|
|
Issue.generate! :parent_issue_id => root.id |
|
|
|
end |
|
|
|
end |
|
|
|
end |
|
|
|
root.reload |
|
|
|
assert_equal [1, 62], [root.lft, root.rgt] |
|
|
|
children_bounds = root.children.sort_by(&:lft).map {|c| [c.lft, c.rgt]}.flatten |
|
|
|
assert_equal (2..61).to_a, children_bounds |
|
|
|
end |
|
|
|
|
|
|
|
private |
|
|
|
|
|
|
|
def threaded(count, &block) |
|
|
|
with_settings :notified_events => [] do |
|
|
|
threads = [] |
|
|
|
count.times do |i| |
|
|
|
threads << Thread.new(i) do |
|
|
|
ActiveRecord::Base.connection_pool.with_connection do |
|
|
|
begin |
|
|
|
yield |
|
|
|
rescue Exception => e |
|
|
|
Thread.current[:exception] = e.message |
|
|
|
end |
|
|
|
end |
|
|
|
end |
|
|
|
threads.each do |thread| |
|
|
|
thread.join |
|
|
|
assert_nil thread[:exception] |
|
|
|
end |
|
|
|
end |
|
|
|
threads.each do |thread| |
|
|
|
thread.join |
|
|
|
assert_nil thread[:exception] |
|
|
|
end |
|
|
|
end |
|
|
|
end |