lalala 4.0.0.dev.136 → 4.0.0.dev.141
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitmodules +0 -3
- data/lalala.gemspec +2 -6
- data/lib/lalala/version.rb +1 -1
- data/lib/lalala.rb +0 -1
- metadata +19 -53
- data/vendor/deps/closure_tree/.gitignore +0 -12
- data/vendor/deps/closure_tree/.travis.yml +0 -22
- data/vendor/deps/closure_tree/.yardopts +0 -3
- data/vendor/deps/closure_tree/Gemfile +0 -2
- data/vendor/deps/closure_tree/MIT-LICENSE +0 -19
- data/vendor/deps/closure_tree/README.md +0 -641
- data/vendor/deps/closure_tree/Rakefile +0 -26
- data/vendor/deps/closure_tree/ci/Gemfile.rails-3.0.x +0 -5
- data/vendor/deps/closure_tree/ci/Gemfile.rails-3.1.x +0 -4
- data/vendor/deps/closure_tree/ci/Gemfile.rails-3.2.x +0 -4
- data/vendor/deps/closure_tree/closure_tree.gemspec +0 -31
- data/vendor/deps/closure_tree/lib/closure_tree/acts_as_tree.rb +0 -55
- data/vendor/deps/closure_tree/lib/closure_tree/columns.rb +0 -123
- data/vendor/deps/closure_tree/lib/closure_tree/deterministic_ordering.rb +0 -49
- data/vendor/deps/closure_tree/lib/closure_tree/model.rb +0 -386
- data/vendor/deps/closure_tree/lib/closure_tree/numeric_deterministic_ordering.rb +0 -93
- data/vendor/deps/closure_tree/lib/closure_tree/version.rb +0 -3
- data/vendor/deps/closure_tree/lib/closure_tree/with_advisory_lock.rb +0 -18
- data/vendor/deps/closure_tree/lib/closure_tree.rb +0 -8
- data/vendor/deps/closure_tree/spec/cuisine_type_spec.rb +0 -30
- data/vendor/deps/closure_tree/spec/db/database.yml +0 -19
- data/vendor/deps/closure_tree/spec/db/schema.rb +0 -109
- data/vendor/deps/closure_tree/spec/fixtures/labels.yml +0 -55
- data/vendor/deps/closure_tree/spec/fixtures/tags.yml +0 -98
- data/vendor/deps/closure_tree/spec/hash_tree_spec.rb +0 -91
- data/vendor/deps/closure_tree/spec/label_spec.rb +0 -356
- data/vendor/deps/closure_tree/spec/namespace_type_spec.rb +0 -13
- data/vendor/deps/closure_tree/spec/parallel_prepend_sibling_spec.rb +0 -45
- data/vendor/deps/closure_tree/spec/parallel_spec.rb +0 -59
- data/vendor/deps/closure_tree/spec/spec_helper.rb +0 -57
- data/vendor/deps/closure_tree/spec/support/models.rb +0 -74
- data/vendor/deps/closure_tree/spec/tag_spec.rb +0 -469
- data/vendor/deps/closure_tree/spec/user_spec.rb +0 -136
- data/vendor/deps/closure_tree/tests.sh +0 -19
@@ -1,356 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
def delete_all_labels
|
4
|
-
LabelHierarchy.delete_all
|
5
|
-
Label.delete_all
|
6
|
-
end
|
7
|
-
|
8
|
-
def create_label_tree
|
9
|
-
@d1 = Label.find_or_create_by_path %w(a1 b1 c1 d1)
|
10
|
-
@c1 = @d1.parent
|
11
|
-
@b1 = @c1.parent
|
12
|
-
@a1 = @b1.parent
|
13
|
-
@d2 = Label.find_or_create_by_path %w(a1 b1 c2 d2)
|
14
|
-
@c2 = @d2.parent
|
15
|
-
@d3 = Label.find_or_create_by_path %w(a2 b2 c3 d3)
|
16
|
-
@c3 = @d3.parent
|
17
|
-
@b2 = @c3.parent
|
18
|
-
@a2 = @b2.parent
|
19
|
-
Label.update_all("sort_order = id")
|
20
|
-
end
|
21
|
-
|
22
|
-
def create_preorder_tree(suffix = "")
|
23
|
-
%w(
|
24
|
-
a/l/n/r
|
25
|
-
a/l/n/q
|
26
|
-
a/l/n/p
|
27
|
-
a/l/n/o
|
28
|
-
a/l/m
|
29
|
-
a/b/h/i/j/k
|
30
|
-
a/b/c/d/g
|
31
|
-
a/b/c/d/f
|
32
|
-
a/b/c/d/e
|
33
|
-
).shuffle.each { |ea| Label.find_or_create_by_path(ea.split('/').collect { |ea| "#{ea}#{suffix}" }) }
|
34
|
-
|
35
|
-
Label.roots.each_with_index do |root, root_idx|
|
36
|
-
root.order_value = root_idx
|
37
|
-
root.save!
|
38
|
-
root.self_and_descendants.each do |ea|
|
39
|
-
ea.children.to_a.sort_by(&:name).each_with_index do |ea, idx|
|
40
|
-
ea.order_value = idx
|
41
|
-
ea.save!
|
42
|
-
end
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
describe Label do
|
48
|
-
|
49
|
-
context "destruction" do
|
50
|
-
it "properly destroys descendents" do
|
51
|
-
c = Label.find_or_create_by_path %w(a b c)
|
52
|
-
b = c.parent
|
53
|
-
a = c.root
|
54
|
-
a.destroy
|
55
|
-
Label.exists?(a).should be_false
|
56
|
-
Label.exists?(b).should be_false
|
57
|
-
Label.exists?(c).should be_false
|
58
|
-
end
|
59
|
-
end
|
60
|
-
|
61
|
-
context "Base Label class" do
|
62
|
-
it "should find or create by path" do
|
63
|
-
# class method:
|
64
|
-
c = Label.find_or_create_by_path(%w{grandparent parent child})
|
65
|
-
c.ancestry_path.should == %w{grandparent parent child}
|
66
|
-
c.name.should == "child"
|
67
|
-
c.parent.name.should == "parent"
|
68
|
-
end
|
69
|
-
end
|
70
|
-
|
71
|
-
context "DateLabel" do
|
72
|
-
it "should find or create by path" do
|
73
|
-
date = DateLabel.find_or_create_by_path(%w{2011 November 23})
|
74
|
-
date.ancestry_path.should == %w{2011 November 23}
|
75
|
-
date.parent
|
76
|
-
date.self_and_ancestors.each { |ea| ea.class.should == DateLabel }
|
77
|
-
date.name.should == "23"
|
78
|
-
date.parent.name.should == "November"
|
79
|
-
end
|
80
|
-
end
|
81
|
-
|
82
|
-
context "DirectoryLabel" do
|
83
|
-
it "should find or create by path" do
|
84
|
-
dir = DirectoryLabel.find_or_create_by_path(%w{grandparent parent child})
|
85
|
-
dir.ancestry_path.should == %w{grandparent parent child}
|
86
|
-
dir.name.should == "child"
|
87
|
-
dir.parent.name.should == "parent"
|
88
|
-
dir.parent.parent.name.should == "grandparent"
|
89
|
-
dir.root.name.should == "grandparent"
|
90
|
-
dir.id.should_not == Label.find_or_create_by_path(%w{grandparent parent child})
|
91
|
-
dir.self_and_ancestors.each { |ea| ea.class.should == DirectoryLabel }
|
92
|
-
end
|
93
|
-
end
|
94
|
-
|
95
|
-
context "Mixed class tree" do
|
96
|
-
it "should support mixed type ancestors" do
|
97
|
-
[Label, DateLabel, DirectoryLabel, EventLabel].permutation do |classes|
|
98
|
-
delete_all_labels
|
99
|
-
classes.each { |c| c.all.should(be_empty, "class #{c} wasn't cleaned out") }
|
100
|
-
names = ('A'..'Z').to_a.first(classes.size)
|
101
|
-
instances = classes.collect { |clazz| clazz.new(:name => names.shift) }
|
102
|
-
a = instances.first
|
103
|
-
a.save!
|
104
|
-
a.name.should == "A"
|
105
|
-
instances[1..-1].each_with_index do |ea, idx|
|
106
|
-
instances[idx].children << ea
|
107
|
-
end
|
108
|
-
roots = classes.first.roots
|
109
|
-
i = instances.shift
|
110
|
-
roots.should =~ [i]
|
111
|
-
while (!instances.empty?) do
|
112
|
-
child = instances.shift
|
113
|
-
i.children.should =~ [child]
|
114
|
-
i = child
|
115
|
-
end
|
116
|
-
end
|
117
|
-
end
|
118
|
-
|
119
|
-
it "supports children << and add_child" do
|
120
|
-
a = EventLabel.create!(:name => "a")
|
121
|
-
b = DateLabel.new(:name => "b")
|
122
|
-
a.children << b
|
123
|
-
c = Label.new(:name => "c")
|
124
|
-
b.add_child(c)
|
125
|
-
|
126
|
-
a.self_and_descendants.collect do |ea|
|
127
|
-
ea.class
|
128
|
-
end.should == [EventLabel, DateLabel, Label]
|
129
|
-
|
130
|
-
a.self_and_descendants.collect do |ea|
|
131
|
-
ea.name
|
132
|
-
end.should == %w(a b c)
|
133
|
-
end
|
134
|
-
end
|
135
|
-
|
136
|
-
context "find_all_by_generation" do
|
137
|
-
before :all do
|
138
|
-
delete_all_labels
|
139
|
-
create_label_tree
|
140
|
-
end
|
141
|
-
|
142
|
-
it "finds roots from the class method" do
|
143
|
-
Label.find_all_by_generation(0).to_a.should == [@a1, @a2]
|
144
|
-
end
|
145
|
-
|
146
|
-
it "finds roots from themselves" do
|
147
|
-
@a1.find_all_by_generation(0).to_a.should == [@a1]
|
148
|
-
end
|
149
|
-
|
150
|
-
it "finds itself for non-roots" do
|
151
|
-
@b1.find_all_by_generation(0).to_a.should == [@b1]
|
152
|
-
end
|
153
|
-
|
154
|
-
it "finds children for roots" do
|
155
|
-
Label.find_all_by_generation(1).to_a.should == [@b1, @b2]
|
156
|
-
end
|
157
|
-
|
158
|
-
it "finds children" do
|
159
|
-
@a1.find_all_by_generation(1).to_a.should == [@b1]
|
160
|
-
@b1.find_all_by_generation(1).to_a.should == [@c1, @c2]
|
161
|
-
end
|
162
|
-
|
163
|
-
it "finds grandchildren for roots" do
|
164
|
-
Label.find_all_by_generation(2).to_a.should == [@c1, @c2, @c3]
|
165
|
-
end
|
166
|
-
|
167
|
-
it "finds grandchildren" do
|
168
|
-
@a1.find_all_by_generation(2).to_a.should == [@c1, @c2]
|
169
|
-
@b1.find_all_by_generation(2).to_a.should == [@d1, @d2]
|
170
|
-
end
|
171
|
-
|
172
|
-
it "finds great-grandchildren for roots" do
|
173
|
-
Label.find_all_by_generation(3).to_a.should == [@d1, @d2, @d3]
|
174
|
-
end
|
175
|
-
end
|
176
|
-
|
177
|
-
context "loading through self_and_ scopes" do
|
178
|
-
before :all do
|
179
|
-
delete_all_labels
|
180
|
-
create_label_tree
|
181
|
-
end
|
182
|
-
|
183
|
-
it "self_and_descendants should result in one select" do
|
184
|
-
DB_QUERIES.clear
|
185
|
-
a1_array = @a1.self_and_descendants
|
186
|
-
a1_array.collect { |ea| ea.name }.should == %w(a1 b1 c1 c2 d1 d2)
|
187
|
-
DB_QUERIES.size.should == 1
|
188
|
-
end
|
189
|
-
|
190
|
-
it "self_and_ancestors should result in one select" do
|
191
|
-
DB_QUERIES.clear
|
192
|
-
d1_array = @d1.self_and_ancestors
|
193
|
-
d1_array.collect { |ea| ea.name }.should == %w(d1 c1 b1 a1)
|
194
|
-
DB_QUERIES.size.should == 1
|
195
|
-
end
|
196
|
-
end
|
197
|
-
|
198
|
-
context "deterministically orders with polymorphic siblings" do
|
199
|
-
before :each do
|
200
|
-
@parent = Label.create!(:name => "parent")
|
201
|
-
@a = EventLabel.new(:name => "a")
|
202
|
-
@b = DirectoryLabel.new(:name => "b")
|
203
|
-
@c = DateLabel.new(:name => "c")
|
204
|
-
@parent.children << @a
|
205
|
-
@a.append_sibling(@b)
|
206
|
-
@b.append_sibling(@c)
|
207
|
-
end
|
208
|
-
|
209
|
-
it "when inserted before" do
|
210
|
-
@b.append_sibling(@a)
|
211
|
-
# Have to reload because the sort_order will have changed out from under the references:
|
212
|
-
@b.reload.sort_order.should be < @a.reload.sort_order
|
213
|
-
@a.reload.sort_order.should be < @c.reload.sort_order
|
214
|
-
end
|
215
|
-
|
216
|
-
it "when inserted before" do
|
217
|
-
@b.append_sibling(@a, use_update_all = false)
|
218
|
-
# Have to reload because the sort_order will have changed out from under the references:
|
219
|
-
@b.reload.sort_order.should be < @a.reload.sort_order
|
220
|
-
@a.reload.sort_order.should be < @c.reload.sort_order
|
221
|
-
end
|
222
|
-
end
|
223
|
-
|
224
|
-
it "behaves like the readme" do
|
225
|
-
root = Label.create(:name => "root")
|
226
|
-
a = Label.create(:name => "a", :parent => root)
|
227
|
-
b = Label.create(:name => "b")
|
228
|
-
c = Label.create(:name => "c")
|
229
|
-
|
230
|
-
a.append_sibling(b)
|
231
|
-
root.reload.children.collect(&:name).should == %w(a b)
|
232
|
-
|
233
|
-
a.prepend_sibling(b)
|
234
|
-
root.reload.children.collect(&:name).should == %w(b a)
|
235
|
-
|
236
|
-
a.append_sibling(c)
|
237
|
-
root.reload.children.collect(&:name).should == %w(b a c)
|
238
|
-
|
239
|
-
b.append_sibling(c)
|
240
|
-
root.reload.children.collect(&:name).should == %w(b c a)
|
241
|
-
end
|
242
|
-
|
243
|
-
context "Deterministic siblings sort with custom integer column" do
|
244
|
-
delete_all_labels
|
245
|
-
fixtures :labels
|
246
|
-
|
247
|
-
before :each do
|
248
|
-
Label.rebuild!
|
249
|
-
end
|
250
|
-
|
251
|
-
it "orders siblings_before and siblings_after correctly" do
|
252
|
-
labels(:c16).self_and_siblings.to_a.should == [labels(:c16), labels(:c17), labels(:c18), labels(:c19)]
|
253
|
-
labels(:c16).siblings_before.to_a.should == []
|
254
|
-
labels(:c16).siblings_after.to_a.should == [labels(:c17), labels(:c18), labels(:c19)]
|
255
|
-
end
|
256
|
-
|
257
|
-
it "should prepend a node as a sibling of another node" do
|
258
|
-
labels(:c16).prepend_sibling(labels(:c17))
|
259
|
-
labels(:c16).self_and_siblings.to_a.should == [labels(:c17), labels(:c16), labels(:c18), labels(:c19)]
|
260
|
-
labels(:c19).prepend_sibling(labels(:c16))
|
261
|
-
labels(:c16).self_and_siblings.to_a.should == [labels(:c17), labels(:c18), labels(:c16), labels(:c19)]
|
262
|
-
labels(:c16).siblings_before.to_a.should == [labels(:c17), labels(:c18)]
|
263
|
-
labels(:c16).siblings_after.to_a.should == [labels(:c19)]
|
264
|
-
end
|
265
|
-
|
266
|
-
it "should prepend a node as a sibling of another node (!update_all)" do
|
267
|
-
labels(:c16).prepend_sibling(labels(:c17), false)
|
268
|
-
labels(:c16).self_and_siblings.to_a.should == [labels(:c17), labels(:c16), labels(:c18), labels(:c19)]
|
269
|
-
labels(:c19).reload.prepend_sibling(labels(:c16).reload, false)
|
270
|
-
labels(:c16).self_and_siblings.to_a.should == [labels(:c17), labels(:c18), labels(:c16), labels(:c19)]
|
271
|
-
labels(:c16).siblings_before.to_a.should == [labels(:c17), labels(:c18)]
|
272
|
-
labels(:c16).siblings_after.to_a.should == [labels(:c19)]
|
273
|
-
end
|
274
|
-
|
275
|
-
it "appends a node as a sibling of another node" do
|
276
|
-
labels(:c19).append_sibling(labels(:c17))
|
277
|
-
labels(:c16).self_and_siblings.to_a.should == [labels(:c16), labels(:c18), labels(:c19), labels(:c17)]
|
278
|
-
labels(:c16).append_sibling(labels(:c19))
|
279
|
-
labels(:c16).self_and_siblings.to_a.should == [labels(:c16), labels(:c19), labels(:c18), labels(:c17)]
|
280
|
-
labels(:c16).siblings_before.to_a.should == []
|
281
|
-
labels(:c16).siblings_after.to_a.should == labels(:c16).siblings.to_a
|
282
|
-
end
|
283
|
-
|
284
|
-
it "should move a node before another node (update_all)" do
|
285
|
-
labels(:c2).ancestry_path.should == %w{a1 b2 c2}
|
286
|
-
labels(:b2).prepend_sibling(labels(:c2))
|
287
|
-
labels(:c2).ancestry_path.should == %w{a1 c2}
|
288
|
-
labels(:c2).self_and_siblings.to_a.should == [labels(:b1), labels(:c2), labels(:b2)]
|
289
|
-
labels(:c2).siblings_before.to_a.should == [labels(:b1)]
|
290
|
-
labels(:c2).siblings_after.to_a.should == [labels(:b2)]
|
291
|
-
labels(:b1).siblings_after.to_a.should == [labels(:c2), labels(:b2)]
|
292
|
-
end
|
293
|
-
|
294
|
-
it "should move a node after another node (update_all)" do
|
295
|
-
labels(:c2).ancestry_path.should == %w{a1 b2 c2}
|
296
|
-
labels(:b2).append_sibling(labels(:c2))
|
297
|
-
labels(:c2).ancestry_path.should == %w{a1 c2}
|
298
|
-
labels(:c2).self_and_siblings.to_a.should == [labels(:b1), labels(:b2), labels(:c2)]
|
299
|
-
end
|
300
|
-
|
301
|
-
it "should move a node before another node" do
|
302
|
-
labels(:c2).ancestry_path.should == %w{a1 b2 c2}
|
303
|
-
labels(:b2).prepend_sibling(labels(:c2), false)
|
304
|
-
labels(:c2).ancestry_path.should == %w{a1 c2}
|
305
|
-
labels(:c2).self_and_siblings.to_a.should == [labels(:b1), labels(:c2), labels(:b2)]
|
306
|
-
end
|
307
|
-
|
308
|
-
it "should move a node before another node which has an uninitialized sort_order" do
|
309
|
-
labels(:f3).ancestry_path.should == %w{f3}
|
310
|
-
labels(:e2).children << labels(:f3)
|
311
|
-
labels(:f3).reload.ancestry_path.should == %w{a1 b2 c2 d2 e2 f3}
|
312
|
-
labels(:f3).self_and_siblings.to_a.should == [labels(:f3)]
|
313
|
-
labels(:f3).prepend_sibling labels(:f4)
|
314
|
-
labels(:f3).siblings_before.to_a.should == [labels(:f4)]
|
315
|
-
labels(:f3).self_and_siblings.to_a.should == [labels(:f4), labels(:f3)]
|
316
|
-
end
|
317
|
-
|
318
|
-
it "should move a node after another node which has an uninitialized sort_order" do
|
319
|
-
labels(:f3).ancestry_path.should == %w{f3}
|
320
|
-
labels(:e2).children << labels(:f3)
|
321
|
-
labels(:f3).reload.ancestry_path.should == %w{a1 b2 c2 d2 e2 f3}
|
322
|
-
labels(:f3).self_and_siblings.to_a.should == [labels(:f3)]
|
323
|
-
labels(:f3).append_sibling labels(:f4)
|
324
|
-
labels(:f3).siblings_after.to_a.should == [labels(:f4)]
|
325
|
-
labels(:f3).self_and_siblings.to_a.should == [labels(:f3), labels(:f4)]
|
326
|
-
end
|
327
|
-
|
328
|
-
it "should move a node after another node" do
|
329
|
-
labels(:c2).ancestry_path.should == %w{a1 b2 c2}
|
330
|
-
labels(:b2).append_sibling(labels(:c2), false)
|
331
|
-
labels(:c2).ancestry_path.should == %w{a1 c2}
|
332
|
-
labels(:c2).self_and_siblings.to_a.should == [labels(:b1), labels(:b2), labels(:c2)]
|
333
|
-
labels(:c2).append_sibling(labels(:e2), false)
|
334
|
-
labels(:e2).self_and_siblings.to_a.should == [labels(:b1), labels(:b2), labels(:c2), labels(:e2)]
|
335
|
-
labels(:a1).self_and_descendants.collect(&:name).should == %w(a1 b1 b2 c2 e2 d2 c1-six c1-seven c1-eight c1-nine)
|
336
|
-
labels(:a1).leaves.collect(&:name).should == %w(b2 e2 d2 c1-six c1-seven c1-eight c1-nine)
|
337
|
-
end
|
338
|
-
end
|
339
|
-
|
340
|
-
context "preorder" do
|
341
|
-
it "returns descendants in proper order" do
|
342
|
-
delete_all_labels
|
343
|
-
create_preorder_tree
|
344
|
-
a = Label.root
|
345
|
-
a.name.should == "a"
|
346
|
-
expected = ('a'..'r').to_a
|
347
|
-
a.self_and_descendants_preordered.collect { |ea| ea.name }.should == expected
|
348
|
-
Label.roots_and_descendants_preordered.collect { |ea| ea.name }.should == expected
|
349
|
-
create_preorder_tree("1")
|
350
|
-
# Should be no change:
|
351
|
-
a.reload.self_and_descendants_preordered.collect { |ea| ea.name }.should == expected
|
352
|
-
expected += ('a'..'r').collect { |ea| "#{ea}1" }
|
353
|
-
Label.roots_and_descendants_preordered.collect { |ea| ea.name }.should == expected
|
354
|
-
end
|
355
|
-
end unless ENV["DB"] == "sqlite"
|
356
|
-
end
|
@@ -1,13 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe Namespace::Type do
|
4
|
-
|
5
|
-
context "class injection" do
|
6
|
-
it "should build hierarchy classname correctly" do
|
7
|
-
Namespace::Type.hierarchy_class.to_s.should == "Namespace::TypeHierarchy"
|
8
|
-
Namespace::Type.hierarchy_class_name.should == "Namespace::TypeHierarchy"
|
9
|
-
Namespace::Type.short_hierarchy_class_name.should == "TypeHierarchy"
|
10
|
-
end
|
11
|
-
end
|
12
|
-
|
13
|
-
end
|
@@ -1,45 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
require 'securerandom'
|
3
|
-
|
4
|
-
describe "threadhot" do
|
5
|
-
|
6
|
-
before :each do
|
7
|
-
LabelHierarchy.delete_all
|
8
|
-
Label.delete_all
|
9
|
-
@iterations = 5
|
10
|
-
@workers = 8
|
11
|
-
end
|
12
|
-
|
13
|
-
def prepend_sibling_at_even_second(run_at)
|
14
|
-
ActiveRecord::Base.connection.reconnect!
|
15
|
-
sibling = Label.new(:name => SecureRandom.hex(10))
|
16
|
-
target = Label.find(@target.id)
|
17
|
-
sleep(run_at - Time.now.to_f)
|
18
|
-
target.prepend_sibling sibling
|
19
|
-
end
|
20
|
-
|
21
|
-
def run_workers
|
22
|
-
start_time = Time.now.to_i + 2
|
23
|
-
@times = @iterations.times.collect { |ea| start_time + (ea * 2) }
|
24
|
-
@names = @times.collect { |ea| ea.to_s }
|
25
|
-
@threads = @workers.times.collect do
|
26
|
-
Thread.new do
|
27
|
-
@times.each { |ea| prepend_sibling_at_even_second(ea) }
|
28
|
-
end
|
29
|
-
end
|
30
|
-
@threads.each { |ea| ea.join }
|
31
|
-
end
|
32
|
-
|
33
|
-
it "prepend_sibling on a non-root node doesn't cause deadlocks" do
|
34
|
-
@target = Label.find_or_create_by_path %w(root parent)
|
35
|
-
run_workers
|
36
|
-
children = Label.roots
|
37
|
-
uniq_sort_orders = children.collect { |ea| ea.sort_order }.uniq
|
38
|
-
children.size.should == uniq_sort_orders.size
|
39
|
-
|
40
|
-
# The only non-root node should be "root":
|
41
|
-
Label.all.select { |ea| ea.root? }.should == [@target.parent]
|
42
|
-
end
|
43
|
-
|
44
|
-
# SQLite doesn't like parallelism, and Rails 3.0 and 3.1 have known threading issues. SKIP.
|
45
|
-
end if ((ENV["DB"] != "sqlite3") && (ActiveRecord::VERSION::STRING =~ /^3.2/))
|
@@ -1,59 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe "threadhot" do
|
4
|
-
|
5
|
-
before :each do
|
6
|
-
TagHierarchy.delete_all
|
7
|
-
Tag.delete_all
|
8
|
-
@iterations = 5
|
9
|
-
@workers = 8
|
10
|
-
@parent = nil
|
11
|
-
end
|
12
|
-
|
13
|
-
def find_or_create_at_even_second(run_at)
|
14
|
-
sleep(run_at - Time.now.to_f)
|
15
|
-
ActiveRecord::Base.connection.reconnect!
|
16
|
-
(@parent || Tag).find_or_create_by_path([run_at.to_s, :a, :b, :c].compact)
|
17
|
-
end
|
18
|
-
|
19
|
-
def run_workers
|
20
|
-
start_time = Time.now.to_i + 2
|
21
|
-
@times = @iterations.times.collect { |ea| start_time + (ea * 2) }
|
22
|
-
@names = @times.collect { |ea| ea.to_s }
|
23
|
-
@threads = @workers.times.collect do
|
24
|
-
Thread.new do
|
25
|
-
@times.each { |ea| find_or_create_at_even_second(ea) }
|
26
|
-
end
|
27
|
-
end
|
28
|
-
@threads.each { |ea| ea.join }
|
29
|
-
end
|
30
|
-
|
31
|
-
|
32
|
-
it "class method will not create dupes" do
|
33
|
-
run_workers
|
34
|
-
Tag.roots.collect { |ea| ea.name.to_i }.should =~ @times
|
35
|
-
# No dupe children:
|
36
|
-
%w(a b c).each do |ea|
|
37
|
-
Tag.find_all_by_name(ea).size.should == @iterations
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
it "instance method will not create dupes" do
|
42
|
-
@parent = Tag.create!(:name => "root")
|
43
|
-
run_workers
|
44
|
-
@parent.reload.children.collect { |ea| ea.name.to_i }.should =~ @times
|
45
|
-
Tag.find_all_by_name(@names).size.should == @iterations
|
46
|
-
%w(a b c).each do |ea|
|
47
|
-
Tag.find_all_by_name(ea).size.should == @iterations
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
it "creates dupe roots without advisory locks" do
|
52
|
-
# disable with_advisory_lock:
|
53
|
-
Tag.should_receive(:with_advisory_lock).any_number_of_times { |lock_name, &block| block.call }
|
54
|
-
run_workers
|
55
|
-
Tag.find_all_by_name(@names).size.should > @iterations
|
56
|
-
end
|
57
|
-
|
58
|
-
# SQLite doesn't like parallelism, and Rails 3.0 and 3.1 have known threading issues. SKIP.
|
59
|
-
end if ((ENV["DB"] != "sqlite") && (ActiveRecord::VERSION::STRING =~ /^3.2/))
|
@@ -1,57 +0,0 @@
|
|
1
|
-
$:.unshift(File.dirname(__FILE__) + '/../lib')
|
2
|
-
plugin_test_dir = File.dirname(__FILE__)
|
3
|
-
|
4
|
-
require 'rubygems'
|
5
|
-
require 'bundler/setup'
|
6
|
-
|
7
|
-
require 'rspec'
|
8
|
-
require 'logger'
|
9
|
-
|
10
|
-
require 'action_controller' # rspec-rails needs this :(
|
11
|
-
require 'closure_tree'
|
12
|
-
require 'tmpdir'
|
13
|
-
|
14
|
-
#log = Logger.new(STDOUT)
|
15
|
-
#log.sev_threshold = Logger::DEBUG
|
16
|
-
#ActiveRecord::Base.logger = log
|
17
|
-
|
18
|
-
require 'yaml'
|
19
|
-
require 'erb'
|
20
|
-
ENV["DB"] ||= "mysql"
|
21
|
-
ActiveRecord::Base.table_name_prefix = ENV['DB_PREFIX'].to_s
|
22
|
-
ActiveRecord::Base.table_name_suffix = ENV['DB_SUFFIX'].to_s
|
23
|
-
ActiveRecord::Base.configurations = YAML::load(ERB.new(IO.read(plugin_test_dir + "/db/database.yml")).result)
|
24
|
-
ActiveRecord::Base.establish_connection(ENV["DB"])
|
25
|
-
ActiveRecord::Migration.verbose = false
|
26
|
-
require 'db/schema'
|
27
|
-
require 'support/models'
|
28
|
-
require 'rspec/rails' # TODO: clean this up-- I don't want to pull the elephant through the mouse hole just for fixture support
|
29
|
-
|
30
|
-
DB_QUERIES = []
|
31
|
-
|
32
|
-
ActiveRecord::ConnectionAdapters::AbstractAdapter.class_eval do
|
33
|
-
def log_with_query_append(query, *args, &block)
|
34
|
-
DB_QUERIES << query
|
35
|
-
log_without_query_append(query, *args, &block)
|
36
|
-
end
|
37
|
-
|
38
|
-
alias_method_chain :log, :query_append
|
39
|
-
end
|
40
|
-
|
41
|
-
Thread.abort_on_exception = true
|
42
|
-
|
43
|
-
RSpec.configure do |config|
|
44
|
-
config.fixture_path = "#{plugin_test_dir}/fixtures"
|
45
|
-
# true runs the tests 1 second faster, but then you can't
|
46
|
-
# see what's going on while debuggering with different db connections.
|
47
|
-
config.use_transactional_fixtures = false
|
48
|
-
config.after(:each) do
|
49
|
-
DB_QUERIES.clear
|
50
|
-
end
|
51
|
-
config.before(:all) do
|
52
|
-
ENV['FLOCK_DIR'] = Dir.mktmpdir
|
53
|
-
end
|
54
|
-
config.after(:all) do
|
55
|
-
FileUtils.remove_entry_secure ENV['FLOCK_DIR']
|
56
|
-
end
|
57
|
-
end
|
@@ -1,74 +0,0 @@
|
|
1
|
-
require 'uuidtools'
|
2
|
-
|
3
|
-
class Tag < ActiveRecord::Base
|
4
|
-
acts_as_tree :dependent => :destroy, :order => "name"
|
5
|
-
before_destroy :add_destroyed_tag
|
6
|
-
attr_accessible :name
|
7
|
-
|
8
|
-
def to_s
|
9
|
-
name
|
10
|
-
end
|
11
|
-
|
12
|
-
def add_destroyed_tag
|
13
|
-
# Proof for the tests that the destroy rather than the delete method was called:
|
14
|
-
DestroyedTag.create(:name => name)
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
class DestroyedTag < ActiveRecord::Base
|
19
|
-
attr_accessible :name
|
20
|
-
end
|
21
|
-
|
22
|
-
class User < ActiveRecord::Base
|
23
|
-
acts_as_tree :parent_column_name => "referrer_id",
|
24
|
-
:name_column => 'email',
|
25
|
-
:hierarchy_class_name => 'ReferralHierarchy',
|
26
|
-
:hierarchy_table_name => 'referral_hierarchies'
|
27
|
-
|
28
|
-
has_many :contracts
|
29
|
-
|
30
|
-
def indirect_contracts
|
31
|
-
Contract.where(:user_id => descendant_ids)
|
32
|
-
end
|
33
|
-
|
34
|
-
attr_accessible :email, :referrer
|
35
|
-
|
36
|
-
def to_s
|
37
|
-
email
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
class Contract < ActiveRecord::Base
|
42
|
-
belongs_to :user
|
43
|
-
end
|
44
|
-
|
45
|
-
class Label < ActiveRecord::Base
|
46
|
-
attr_accessible :name # < - make sure order doesn't matter
|
47
|
-
acts_as_tree :order => "sort_order",
|
48
|
-
:parent_column_name => "mother_id",
|
49
|
-
:dependent => :destroy
|
50
|
-
|
51
|
-
def to_s
|
52
|
-
"#{self.class}: #{name}"
|
53
|
-
end
|
54
|
-
end
|
55
|
-
|
56
|
-
class EventLabel < Label
|
57
|
-
end
|
58
|
-
|
59
|
-
class DateLabel < Label
|
60
|
-
end
|
61
|
-
|
62
|
-
class DirectoryLabel < Label
|
63
|
-
end
|
64
|
-
|
65
|
-
class CuisineType < ActiveRecord::Base
|
66
|
-
acts_as_tree
|
67
|
-
end
|
68
|
-
|
69
|
-
module Namespace
|
70
|
-
class Type < ActiveRecord::Base
|
71
|
-
acts_as_tree :dependent => :destroy
|
72
|
-
attr_accessible :name
|
73
|
-
end
|
74
|
-
end
|