##// END OF EJS Templates
Adds a test for #6579....
Jean-Philippe Lang -
r13646:8ad326f1609c
parent child
Show More
@@ -1,73 +1,96
1 # Redmine - project management software
1 # Redmine - project management software
2 # Copyright (C) 2006-2015 Jean-Philippe Lang
2 # Copyright (C) 2006-2015 Jean-Philippe Lang
3 #
3 #
4 # This program is free software; you can redistribute it and/or
4 # This program is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License
5 # modify it under the terms of the GNU General Public License
6 # as published by the Free Software Foundation; either version 2
6 # as published by the Free Software Foundation; either version 2
7 # of the License, or (at your option) any later version.
7 # of the License, or (at your option) any later version.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU General Public License
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software
15 # along with this program; if not, write to the Free Software
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
17
18 require File.expand_path('../../test_helper', __FILE__)
18 require File.expand_path('../../test_helper', __FILE__)
19
19
20 class IssueNestedSetConcurrencyTest < ActiveSupport::TestCase
20 class IssueNestedSetConcurrencyTest < ActiveSupport::TestCase
21 fixtures :projects, :users,
21 fixtures :projects, :users,
22 :trackers, :projects_trackers,
22 :trackers, :projects_trackers,
23 :enabled_modules,
23 :enabled_modules,
24 :issue_statuses,
24 :issue_statuses,
25 :enumerations
25 :enumerations
26
26
27 self.use_transactional_fixtures = false
27 self.use_transactional_fixtures = false
28
28
29 def setup
29 def setup
30 skip if sqlite?
30 CustomField.delete_all
31 CustomField.delete_all
31 end
32 end
32
33
33 def teardown
34 def teardown
34 Issue.delete_all
35 Issue.delete_all
35 end
36 end
36
37
37 def test_concurrency
38 def test_concurrency
38 skip if sqlite?
39 with_settings :notified_events => [] do
40 # Generates an issue and destroys it in order
39 # Generates an issue and destroys it in order
41 # to load all needed classes before starting threads
40 # to load all needed classes before starting threads
42 i = Issue.generate!
41 i = Issue.generate!
43 i.destroy
42 i.destroy
44
43
45 root = Issue.generate!
44 root = Issue.generate!
46 assert_difference 'Issue.count', 60 do
45 assert_difference 'Issue.count', 60 do
47 threads = []
46 threaded(3) do
48 3.times do |i|
49 threads << Thread.new(i) do
50 ActiveRecord::Base.connection_pool.with_connection do
51 begin
52 10.times do
47 10.times do
53 i = Issue.generate! :parent_issue_id => root.id
48 i = Issue.generate! :parent_issue_id => root.id
54 c1 = Issue.generate! :parent_issue_id => i.id
49 c1 = Issue.generate! :parent_issue_id => i.id
55 c2 = Issue.generate! :parent_issue_id => i.id
50 c2 = Issue.generate! :parent_issue_id => i.id
56 c3 = Issue.generate! :parent_issue_id => i.id
51 c3 = Issue.generate! :parent_issue_id => i.id
57 c2.reload.destroy
52 c2.reload.destroy
58 c1.reload.destroy
53 c1.reload.destroy
59 end
54 end
55 end
56 end
57 end
58
59 def test_concurrent_subtasks_creation
60 root = Issue.generate!
61 assert_difference 'Issue.count', 30 do
62 threaded(3) do
63 10.times do
64 Issue.generate! :parent_issue_id => root.id
65 end
66 end
67 end
68 root.reload
69 assert_equal [1, 62], [root.lft, root.rgt]
70 children_bounds = root.children.sort_by(&:lft).map {|c| [c.lft, c.rgt]}.flatten
71 assert_equal (2..61).to_a, children_bounds
72 end
73
74 private
75
76 def threaded(count, &block)
77 with_settings :notified_events => [] do
78 threads = []
79 count.times do |i|
80 threads << Thread.new(i) do
81 ActiveRecord::Base.connection_pool.with_connection do
82 begin
83 yield
60 rescue Exception => e
84 rescue Exception => e
61 Thread.current[:exception] = e.message
85 Thread.current[:exception] = e.message
62 end
86 end
63 end
87 end
64 end
88 end
65 end
89 end
66 threads.each do |thread|
90 threads.each do |thread|
67 thread.join
91 thread.join
68 assert_nil thread[:exception]
92 assert_nil thread[:exception]
69 end
93 end
70 end
94 end
71 end
95 end
72 end
96 end
73 end
General Comments 0
You need to be logged in to leave comments. Login now