acts-as-dag 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.rdoc +282 -0
- data/lib/active_record/acts/dag.rb +800 -0
- data/test/dag_test.rb +816 -0
- metadata +67 -0
data/test/dag_test.rb
ADDED
@@ -0,0 +1,816 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require 'rubygems'
|
3
|
+
gem 'activerecord', '= 2.3.8'
|
4
|
+
require 'active_record'
|
5
|
+
require "./init"
|
6
|
+
|
7
|
+
|
8
|
+
ActiveRecord::Base.establish_connection(:adapter => "sqlite3", :database => "#{File.dirname(__FILE__)}/database.test")
|
9
|
+
|
10
|
+
#Used for basic graph link testing
|
11
|
+
class Default < ActiveRecord::Base
|
12
|
+
acts_as_dag_links :node_class_name => 'Node'
|
13
|
+
set_table_name 'edges'
|
14
|
+
end
|
15
|
+
|
16
|
+
#Used for polymorphic graph link testing
|
17
|
+
class Poly < ActiveRecord::Base
|
18
|
+
acts_as_dag_links :polymorphic => true
|
19
|
+
set_table_name 'poly_edges'
|
20
|
+
end
|
21
|
+
|
22
|
+
#Used for redefinition testing
|
23
|
+
class Redefiner < ActiveRecord::Base
|
24
|
+
acts_as_dag_links :node_class_name => 'Redefiner',
|
25
|
+
:direct_column => 'd',
|
26
|
+
:count_column => 'c',
|
27
|
+
:ancestor_id_column => 'foo_id',
|
28
|
+
:descendant_id_column => 'bar_id'
|
29
|
+
set_table_name 'edges2'
|
30
|
+
end
|
31
|
+
|
32
|
+
class Node < ActiveRecord::Base
|
33
|
+
has_dag_links :link_class_name => 'Default'
|
34
|
+
set_table_name 'nodes'
|
35
|
+
end
|
36
|
+
|
37
|
+
class RedefNode < ActiveRecord::Base
|
38
|
+
has_dag_links :link_class_name => 'Redefiner'
|
39
|
+
set_table_name 'redef_nodes'
|
40
|
+
end
|
41
|
+
|
42
|
+
class AlphaNode < ActiveRecord::Base
|
43
|
+
has_dag_links :link_class_name => 'Poly',
|
44
|
+
:descendant_class_names => ['BetaNode','GammaNode','ZetaNode']
|
45
|
+
set_table_name 'alpha_nodes'
|
46
|
+
end
|
47
|
+
|
48
|
+
class BetaNode < ActiveRecord::Base
|
49
|
+
has_dag_links :link_class_name => 'Poly',
|
50
|
+
:ancestor_class_names => ['AlphaNode','BetaNode'],
|
51
|
+
:descendant_class_names => ['BetaNode','GammaNode','ZetaNode']
|
52
|
+
set_table_name 'beta_nodes'
|
53
|
+
end
|
54
|
+
|
55
|
+
class GammaNode < ActiveRecord::Base
|
56
|
+
has_dag_links :link_class_name => 'Poly',
|
57
|
+
:ancestor_class_names => ['AlphaNode','BetaNode','GammaNode'],
|
58
|
+
:descendant_class_names => ['GammaNode','ZetaNode']
|
59
|
+
set_table_name 'gamma_nodes'
|
60
|
+
end
|
61
|
+
|
62
|
+
class ZetaNode < ActiveRecord::Base
|
63
|
+
has_dag_links :link_class_name => 'Poly',
|
64
|
+
:ancestor_class_names => ['AlphaNode','BetaNode','GammaNode']
|
65
|
+
set_table_name 'zeta_nodes'
|
66
|
+
end
|
67
|
+
|
68
|
+
|
69
|
+
#Unit Tests for the DAG plugin
|
70
|
+
class DagTest < Test::Unit::TestCase
|
71
|
+
|
72
|
+
#Setups up database in memory
|
73
|
+
def setup
|
74
|
+
ActiveRecord::Schema.define(:version => 1) do
|
75
|
+
create_table :edges do |t|
|
76
|
+
t.column :ancestor_id, :integer
|
77
|
+
t.column :descendant_id, :integer
|
78
|
+
t.column :direct, :boolean
|
79
|
+
t.column :count, :integer
|
80
|
+
end
|
81
|
+
|
82
|
+
create_table :edges2 do |t|
|
83
|
+
t.column :foo_id, :integer
|
84
|
+
t.column :bar_id, :integer
|
85
|
+
t.column :d, :boolean
|
86
|
+
t.column :c, :integer
|
87
|
+
end
|
88
|
+
|
89
|
+
create_table :nodes do |t|
|
90
|
+
t.column :name, :string
|
91
|
+
end
|
92
|
+
|
93
|
+
create_table :alpha_nodes do |t|
|
94
|
+
t.column :name, :string
|
95
|
+
end
|
96
|
+
|
97
|
+
create_table :beta_nodes do |t|
|
98
|
+
t.column :name, :string
|
99
|
+
end
|
100
|
+
|
101
|
+
create_table :gamma_nodes do |t|
|
102
|
+
t.column :name, :string
|
103
|
+
end
|
104
|
+
|
105
|
+
create_table :zeta_nodes do |t|
|
106
|
+
t.column :name, :string
|
107
|
+
end
|
108
|
+
|
109
|
+
create_table :redef_nodes do |t|
|
110
|
+
t.column :name, :string
|
111
|
+
end
|
112
|
+
|
113
|
+
create_table :poly_edges do |t|
|
114
|
+
t.column :ancestor_id, :integer
|
115
|
+
t.column :ancestor_type, :string
|
116
|
+
t.column :descendant_id, :integer
|
117
|
+
t.column :descendant_type, :string
|
118
|
+
t.column :direct, :boolean
|
119
|
+
t.column :count, :integer
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
#Brings down database
|
125
|
+
def teardown
|
126
|
+
ActiveRecord::Base.connection.tables.each do |table|
|
127
|
+
ActiveRecord::Base.connection.drop_table(table)
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
#Test ancestor id column default value
|
132
|
+
def test_ancestor_id_column_default
|
133
|
+
assert_equal 'ancestor_id', Default.acts_as_dag_options[:ancestor_id_column]
|
134
|
+
end
|
135
|
+
|
136
|
+
#Test descendant id column default value
|
137
|
+
def test_descendant_id_column_default
|
138
|
+
assert_equal 'descendant_id', Default.acts_as_dag_options[:descendant_id_column]
|
139
|
+
end
|
140
|
+
|
141
|
+
#Test direct column default value
|
142
|
+
def test_direct_column_default
|
143
|
+
assert_equal 'direct', Default.acts_as_dag_options[:direct_column]
|
144
|
+
end
|
145
|
+
|
146
|
+
#Test count column default value
|
147
|
+
def test_count_column_default
|
148
|
+
assert_equal 'count', Default.acts_as_dag_options[:count_column]
|
149
|
+
end
|
150
|
+
|
151
|
+
#Test ancestor type column default value
|
152
|
+
def test_ancestor_type_column_default
|
153
|
+
assert_equal 'ancestor_type', Poly.acts_as_dag_options[:ancestor_type_column]
|
154
|
+
end
|
155
|
+
|
156
|
+
#Test descendant type column default value
|
157
|
+
def test_descendant_type_column_default
|
158
|
+
assert_equal 'descendant_type', Poly.acts_as_dag_options[:descendant_type_column]
|
159
|
+
end
|
160
|
+
|
161
|
+
#Test polymorphic option default value
|
162
|
+
def test_polymorphic_default
|
163
|
+
assert Poly.acts_as_dag_options[:polymorphic]
|
164
|
+
assert !Default.acts_as_dag_options[:polymorphic]
|
165
|
+
end
|
166
|
+
|
167
|
+
#more defaults here
|
168
|
+
|
169
|
+
#Tests ancestor_id_column_name instance and class method
|
170
|
+
def test_ancestor_id_column_name
|
171
|
+
assert_equal 'ancestor_id', Default.ancestor_id_column_name
|
172
|
+
assert_equal 'ancestor_id', Default.new.ancestor_id_column_name
|
173
|
+
end
|
174
|
+
|
175
|
+
#Tests descendant_id_column_name instance and class method
|
176
|
+
def test_descendant_id_column_name
|
177
|
+
assert_equal 'descendant_id', Default.descendant_id_column_name
|
178
|
+
assert_equal 'descendant_id', Default.new.descendant_id_column_name
|
179
|
+
end
|
180
|
+
|
181
|
+
#Tests direct_column_name instance and class method
|
182
|
+
def test_direct_column_name
|
183
|
+
assert_equal 'direct', Default.direct_column_name
|
184
|
+
assert_equal 'direct', Default.new.direct_column_name
|
185
|
+
end
|
186
|
+
|
187
|
+
#Tests count_column_name instance and class method
|
188
|
+
def test_count_column_name
|
189
|
+
assert_equal 'count', Default.count_column_name
|
190
|
+
assert_equal 'count', Default.new.count_column_name
|
191
|
+
end
|
192
|
+
|
193
|
+
#Tests ancestor_type_column_name polymorphic instance and class method
|
194
|
+
def test_ancestor_type_column_name
|
195
|
+
assert_equal 'ancestor_type', Poly.ancestor_type_column_name
|
196
|
+
assert_equal 'ancestor_type', Poly.new.ancestor_type_column_name
|
197
|
+
end
|
198
|
+
|
199
|
+
#Tests descendant_type_column_name polymorphic instance and class method
|
200
|
+
def test_descendant_type_column_name
|
201
|
+
assert_equal 'descendant_type', Poly.descendant_type_column_name
|
202
|
+
assert_equal 'descendant_type', Poly.new.descendant_type_column_name
|
203
|
+
end
|
204
|
+
|
205
|
+
#Tests that count is a protected function and cannot be assigned
|
206
|
+
def test_count_protected
|
207
|
+
assert_raises(ActiveRecord::ActiveRecordError) { d = Default.new(:count => 1) }
|
208
|
+
assert_raises(ActiveRecord::ActiveRecordError) { d = Default.new()
|
209
|
+
d.count = 8 }
|
210
|
+
end
|
211
|
+
|
212
|
+
#Tests that direct is a protected function and cannot be assigned
|
213
|
+
#def test_direct_protected
|
214
|
+
# assert_raises(ActiveRecord::ActiveRecordError) { d = Default.new(:direct => 1) }
|
215
|
+
# assert_raises(ActiveRecord::ActiveRecordError) { d = Default.new()
|
216
|
+
# d.direct = false }
|
217
|
+
#end
|
218
|
+
|
219
|
+
#Tests that make_direct instance method trues direct value and registers change
|
220
|
+
def test_make_direct_method
|
221
|
+
d = Default.new
|
222
|
+
assert !d.direct_changed?
|
223
|
+
d.make_direct
|
224
|
+
assert d.direct_changed?
|
225
|
+
assert d.direct
|
226
|
+
end
|
227
|
+
|
228
|
+
#Tests that make_indirect instance method falses direct value and registers change
|
229
|
+
def test_make_indirect_method
|
230
|
+
d = Default.new
|
231
|
+
assert !d.direct_changed?
|
232
|
+
d.make_indirect
|
233
|
+
assert d.direct_changed?
|
234
|
+
assert !d.direct
|
235
|
+
end
|
236
|
+
|
237
|
+
#Tests that changes register initial settings
|
238
|
+
def test_direct_changed_init_pass_in
|
239
|
+
d = Default.new(:direct => true)
|
240
|
+
assert d.direct_changed?
|
241
|
+
end
|
242
|
+
#Tests that endpoint construction works
|
243
|
+
def test_make_endpoint
|
244
|
+
a = Node.create!
|
245
|
+
p = Default::EndPoint.from(a)
|
246
|
+
assert p.matches?(a)
|
247
|
+
end
|
248
|
+
|
249
|
+
#Tests that polymorphic endpoint construction works
|
250
|
+
def test_make_endpoint_poly
|
251
|
+
a = AlphaNode.create!
|
252
|
+
p = Poly::EndPoint.from(a)
|
253
|
+
assert p.matches?(a)
|
254
|
+
end
|
255
|
+
|
256
|
+
#Tests that source is correct
|
257
|
+
def test_source_method
|
258
|
+
a = Node.create!
|
259
|
+
b = Node.create!
|
260
|
+
edge = Default.new(:ancestor => a, :descendant => b)
|
261
|
+
s = edge.source
|
262
|
+
assert s.matches?(a)
|
263
|
+
end
|
264
|
+
|
265
|
+
#Tests that sink is correct
|
266
|
+
def test_sink_method
|
267
|
+
a = Node.create!
|
268
|
+
b = Node.create!
|
269
|
+
edge = Default.new(:ancestor => a, :descendant => b)
|
270
|
+
s = edge.sink
|
271
|
+
assert s.matches?(b)
|
272
|
+
end
|
273
|
+
|
274
|
+
#Tests that source is correct for polymorphic graphs
|
275
|
+
def test_source_method_poly
|
276
|
+
a = AlphaNode.create!
|
277
|
+
b = AlphaNode.create!
|
278
|
+
edge = Poly.new(:ancestor => a, :descendant => b)
|
279
|
+
s = edge.source
|
280
|
+
assert s.matches?(a)
|
281
|
+
end
|
282
|
+
|
283
|
+
#Tests that sink is correct for polymorphic graphs
|
284
|
+
def test_sink_method_poly
|
285
|
+
a = AlphaNode.create!
|
286
|
+
b = AlphaNode.create!
|
287
|
+
edge = Poly.new(:ancestor => a, :descendant => b)
|
288
|
+
s = edge.sink
|
289
|
+
assert s.matches?(b)
|
290
|
+
end
|
291
|
+
|
292
|
+
#Tests that source is correct when created from a model
|
293
|
+
def test_source_method_on_resource
|
294
|
+
a = Node.create!
|
295
|
+
s = Default::Source.from(a)
|
296
|
+
assert s.matches?(a)
|
297
|
+
end
|
298
|
+
|
299
|
+
#Tests that sink is correct when created from a model
|
300
|
+
def test_sink_method_on_resource
|
301
|
+
a = Node.create!
|
302
|
+
s = Default::Source.from(a)
|
303
|
+
assert s.matches?(a)
|
304
|
+
end
|
305
|
+
|
306
|
+
#Tests that source is correct when created from a model for a polymorphic graph
|
307
|
+
def test_source_method_on_resource_poly
|
308
|
+
a = AlphaNode.create!
|
309
|
+
s = Poly::Source.from(a)
|
310
|
+
assert s.matches?(a)
|
311
|
+
end
|
312
|
+
|
313
|
+
#Tests that sink is correct when created from a model for a polymorphic graph
|
314
|
+
def test_sink_method_on_resource_poly
|
315
|
+
a = AlphaNode.create!
|
316
|
+
s = Poly::Source.from(a)
|
317
|
+
assert s.matches?(a)
|
318
|
+
end
|
319
|
+
|
320
|
+
#Tests that class method for build works
|
321
|
+
def test_build_lonely_edge
|
322
|
+
a = Node.create!
|
323
|
+
b = Node.create!
|
324
|
+
e = Default.build_edge(a,b)
|
325
|
+
assert e.source.matches?(a)
|
326
|
+
assert e.sink.matches?(b)
|
327
|
+
end
|
328
|
+
|
329
|
+
#Tests that create_edge works
|
330
|
+
def test_create_lonely_edge
|
331
|
+
a = Node.create!
|
332
|
+
b = Node.create!
|
333
|
+
e = Default.create_edge(a,b)
|
334
|
+
assert e
|
335
|
+
end
|
336
|
+
|
337
|
+
#Tests that create_edge! works
|
338
|
+
def test_create_exla_lonely_edge
|
339
|
+
a = Node.create!
|
340
|
+
b = Node.create!
|
341
|
+
e = Default.create_edge!(a,b)
|
342
|
+
assert_equal e.ancestor, a
|
343
|
+
assert_equal e.descendant, b
|
344
|
+
end
|
345
|
+
|
346
|
+
#Tests that find edge works
|
347
|
+
def test_find_lonely_edge
|
348
|
+
a = Node.create!
|
349
|
+
b = Node.create!
|
350
|
+
e = Default.create_edge(a,b)
|
351
|
+
e = Default.find_edge(a,b)
|
352
|
+
assert_equal e.ancestor, a
|
353
|
+
assert_equal e.descendant, b
|
354
|
+
end
|
355
|
+
|
356
|
+
#Tests that find link works and find_edge rejects indirects
|
357
|
+
def test_find_lonely_link
|
358
|
+
a = Node.create!
|
359
|
+
b = Node.create!
|
360
|
+
e = Default.create_edge(a,b)
|
361
|
+
e = Default.find_link(a,b)
|
362
|
+
assert_equal e.ancestor, a
|
363
|
+
assert_equal e.descendant, b
|
364
|
+
end
|
365
|
+
|
366
|
+
#Tests that we catch links that would be duplicated on creation
|
367
|
+
def test_validation_on_create_duplication_catch
|
368
|
+
a = Node.create!
|
369
|
+
b = Node.create!
|
370
|
+
e = Default.create_edge(a,b)
|
371
|
+
e2 = Default.create_edge(a,b)
|
372
|
+
assert !e2
|
373
|
+
assert_raises(ActiveRecord::RecordInvalid) { e3 = Default.create_edge!(a,b) }
|
374
|
+
end
|
375
|
+
|
376
|
+
#Tests that we catch reversed links on creation (cycles)
|
377
|
+
def test_validation_on_create_reverse_catch
|
378
|
+
a = Node.create!
|
379
|
+
b = Node.create!
|
380
|
+
e = Default.create_edge(a,b)
|
381
|
+
e2 = Default.create_edge(b,a)
|
382
|
+
assert !e2
|
383
|
+
assert_raises(ActiveRecord::RecordInvalid) { e3 = Default.create_edge!(b,a) }
|
384
|
+
end
|
385
|
+
|
386
|
+
#Tests that we catch self to self links on creation (self cycles)
|
387
|
+
def test_validation_on_create_short_cycle_catch
|
388
|
+
a = Node.create!
|
389
|
+
b = Node.create!
|
390
|
+
e = Default.create_edge(a,a)
|
391
|
+
assert !e
|
392
|
+
assert_raises(ActiveRecord::RecordInvalid) { e = Default.create_edge!(a,a) }
|
393
|
+
end
|
394
|
+
|
395
|
+
#Tests that a direct edge with 1 count cannot be made indirect on update
|
396
|
+
def test_validation_on_update_indirect_catch
|
397
|
+
a = Node.create!
|
398
|
+
b = Node.create!
|
399
|
+
e = Default.create_edge!(a,b)
|
400
|
+
e.make_indirect
|
401
|
+
assert !e.save
|
402
|
+
assert_raises(ActiveRecord::RecordInvalid) { e.save! }
|
403
|
+
end
|
404
|
+
|
405
|
+
#Tests that nochanges fails save and save!
|
406
|
+
def test_validation_on_update_no_change_catch
|
407
|
+
a = Node.create!
|
408
|
+
b = Node.create!
|
409
|
+
e = Default.create_edge!(a,b)
|
410
|
+
assert !e.save
|
411
|
+
assert_raises(ActiveRecord::RecordInvalid) { e.save! }
|
412
|
+
end
|
413
|
+
|
414
|
+
#Tests that destroyable? works as required
|
415
|
+
def tests_destroyable
|
416
|
+
a = Node.create!
|
417
|
+
b = Node.create!
|
418
|
+
e = Default.create_edge!(a,b)
|
419
|
+
assert e.destroyable?
|
420
|
+
c = Node.create!
|
421
|
+
f = Default.create_edge!(b,c)
|
422
|
+
assert !Default.find_link(a,c).destroyable?
|
423
|
+
end
|
424
|
+
|
425
|
+
#Tests that destroy link works
|
426
|
+
def tests_destroy_link
|
427
|
+
a = Node.create!
|
428
|
+
b = Node.create!
|
429
|
+
e = Default.create_edge!(a,b)
|
430
|
+
e.destroy
|
431
|
+
assert Default.find_edge(a,b).nil?
|
432
|
+
e = Default.create_edge!(a,b)
|
433
|
+
c = Node.create!
|
434
|
+
f = Default.create_edge!(b,c)
|
435
|
+
assert_raises(ActiveRecord::ActiveRecordError) { Default.find_link(a,c).destroy }
|
436
|
+
end
|
437
|
+
|
438
|
+
#Tests the balancing of a graph in the transitive simple case
|
439
|
+
def test_create_pair_link_transitive
|
440
|
+
a = Node.create!
|
441
|
+
b = Node.create!
|
442
|
+
c = Node.create!
|
443
|
+
e = Default.create_edge!(a,b)
|
444
|
+
f = Default.create_edge!(b,c)
|
445
|
+
g = Default.find_link(a,c)
|
446
|
+
h = Default.find_edge(a,c)
|
447
|
+
assert_equal g.ancestor, a
|
448
|
+
assert_equal g.descendant, c
|
449
|
+
assert_nil h
|
450
|
+
end
|
451
|
+
|
452
|
+
#Tests the ability to make an indirect link direct
|
453
|
+
def test_make_direct_link
|
454
|
+
a = Node.create!
|
455
|
+
b = Node.create!
|
456
|
+
c = Node.create!
|
457
|
+
e = Default.create_edge!(a,b)
|
458
|
+
f = Default.create_edge!(b,c)
|
459
|
+
g = Default.find_link(a,c)
|
460
|
+
g.make_direct
|
461
|
+
g.save!
|
462
|
+
assert_equal true, g.direct?
|
463
|
+
assert_equal 2, g.count
|
464
|
+
end
|
465
|
+
|
466
|
+
#Tests the ability to make a direct link indirect
|
467
|
+
def test_make_indirect_link
|
468
|
+
a = Node.create!
|
469
|
+
b = Node.create!
|
470
|
+
c = Node.create!
|
471
|
+
e = Default.create_edge!(a,b)
|
472
|
+
f = Default.create_edge!(b,c)
|
473
|
+
g = Default.find_link(a,c)
|
474
|
+
g.make_direct
|
475
|
+
g.save!
|
476
|
+
g.make_indirect
|
477
|
+
g.save!
|
478
|
+
assert_equal false, g.direct?
|
479
|
+
assert_equal 1, g.count
|
480
|
+
end
|
481
|
+
|
482
|
+
#Tests advanced transitive cases for chain graph rebalancing
|
483
|
+
def test_create_chain_disjoint
|
484
|
+
a = Node.create!
|
485
|
+
b = Node.create!
|
486
|
+
c = Node.create!
|
487
|
+
d = Node.create!
|
488
|
+
e = Default.create_edge!(a,b)
|
489
|
+
f = Default.create_edge!(c,d)
|
490
|
+
g = Default.create_edge!(b,c)
|
491
|
+
#a to c
|
492
|
+
test = Default.find_link(a,c)
|
493
|
+
testnil = Default.find_edge(a,c)
|
494
|
+
assert_equal test.ancestor, a
|
495
|
+
assert_equal test.descendant, c
|
496
|
+
assert_nil testnil
|
497
|
+
#a to d
|
498
|
+
test = Default.find_link(a,d)
|
499
|
+
testnil = Default.find_edge(a,d)
|
500
|
+
assert_equal test.ancestor, a
|
501
|
+
assert_equal test.descendant, d
|
502
|
+
assert_nil testnil
|
503
|
+
#b to d
|
504
|
+
test = Default.find_link(b,d)
|
505
|
+
testnil = Default.find_edge(b,d)
|
506
|
+
assert_equal test.ancestor, b
|
507
|
+
assert_equal test.descendant, d
|
508
|
+
assert_nil testnil
|
509
|
+
end
|
510
|
+
|
511
|
+
#Tests class method connect
|
512
|
+
def test_manual_connect_lonely_edge
|
513
|
+
a = Node.create!
|
514
|
+
b = Node.create!
|
515
|
+
e = Default.connect!(a,b)
|
516
|
+
e2 = Default.find_edge(a,b)
|
517
|
+
assert e2.direct?
|
518
|
+
assert_equal 1, e2.count
|
519
|
+
assert_equal e,e2
|
520
|
+
assert_equal e2.ancestor, a
|
521
|
+
assert_equal e2.descendant, b
|
522
|
+
end
|
523
|
+
|
524
|
+
#Tests simple indirect link creation
|
525
|
+
def test_auto_simple_cross
|
526
|
+
a = Node.create!
|
527
|
+
b = Node.create!
|
528
|
+
c = Node.create!
|
529
|
+
e = Default.connect(a,b)
|
530
|
+
e2 = Default.connect(b,c)
|
531
|
+
indirect = Default.find_link(a,c)
|
532
|
+
assert !indirect.nil?
|
533
|
+
assert !indirect.direct?
|
534
|
+
assert_equal 1, indirect.count
|
535
|
+
assert_equal a, indirect.ancestor
|
536
|
+
assert_equal c, indirect.descendant
|
537
|
+
end
|
538
|
+
|
539
|
+
##########################
|
540
|
+
#TESTS FOR has_dag_links #
|
541
|
+
##########################
|
542
|
+
|
543
|
+
#Tests has_many links_as_ancestor
|
544
|
+
def test_has_many_links_as_ancestor
|
545
|
+
a = Node.create!
|
546
|
+
b = Node.create!
|
547
|
+
e = a.links_as_ancestor.build
|
548
|
+
e.descendant = b
|
549
|
+
e.save!
|
550
|
+
assert_equal e.ancestor, a
|
551
|
+
assert_equal e.descendant, b
|
552
|
+
end
|
553
|
+
|
554
|
+
#Tests has_many links_as_descendant
|
555
|
+
def test_has_many_links_as_descendant
|
556
|
+
a = Node.create!
|
557
|
+
b = Node.create!
|
558
|
+
e = b.links_as_descendant.build
|
559
|
+
e.ancestor = a
|
560
|
+
e.save!
|
561
|
+
assert_equal e.ancestor, a
|
562
|
+
assert_equal e.descendant, b
|
563
|
+
end
|
564
|
+
|
565
|
+
#Tests has_many links_as_parent
|
566
|
+
def test_has_many_links_as_parent
|
567
|
+
a = Node.create!
|
568
|
+
b = Node.create!
|
569
|
+
e = a.links_as_parent.build
|
570
|
+
e.descendant = b
|
571
|
+
e.save!
|
572
|
+
assert_equal e.ancestor, a
|
573
|
+
assert_equal e.descendant, b
|
574
|
+
end
|
575
|
+
|
576
|
+
#Tests has_many links_as_child
|
577
|
+
def test_has_many_links_as_child
|
578
|
+
a = Node.create!
|
579
|
+
b = Node.create!
|
580
|
+
e = b.links_as_child.build
|
581
|
+
e.ancestor = a
|
582
|
+
e.save!
|
583
|
+
assert_equal e.ancestor, a
|
584
|
+
assert_equal e.descendant, b
|
585
|
+
end
|
586
|
+
|
587
|
+
#Tests has_many descendants
|
588
|
+
def test_has_many_descendants
|
589
|
+
a = Node.create!
|
590
|
+
b = Node.create!
|
591
|
+
a.descendants << b
|
592
|
+
e = Default.find_link(a,b)
|
593
|
+
assert !e.nil?
|
594
|
+
end
|
595
|
+
|
596
|
+
#Tests has_many ancestors
|
597
|
+
def test_has_many_ancestors
|
598
|
+
a = Node.create!
|
599
|
+
b = Node.create!
|
600
|
+
b.ancestors << a
|
601
|
+
e = Default.find_link(a,b)
|
602
|
+
assert !e.nil?
|
603
|
+
end
|
604
|
+
|
605
|
+
#Tests has_many children
|
606
|
+
def test_has_many_children
|
607
|
+
a = Node.create!
|
608
|
+
b = Node.create!
|
609
|
+
a.children << b
|
610
|
+
e = Default.find_link(a,b)
|
611
|
+
assert !e.nil?
|
612
|
+
end
|
613
|
+
|
614
|
+
#Tests has_many parents
|
615
|
+
def test_has_many_parents
|
616
|
+
a = Node.create!
|
617
|
+
b = Node.create!
|
618
|
+
b.parents << a
|
619
|
+
e = Default.find_link(a,b)
|
620
|
+
assert !e.nil?
|
621
|
+
end
|
622
|
+
|
623
|
+
#Tests leaf? instance method
|
624
|
+
def test_leaf_instance_method
|
625
|
+
a = Node.create!
|
626
|
+
assert a.leaf?
|
627
|
+
b = Node.create!
|
628
|
+
a.children << b
|
629
|
+
a.reload
|
630
|
+
b.reload
|
631
|
+
assert !a.leaf?
|
632
|
+
assert b.leaf?
|
633
|
+
end
|
634
|
+
|
635
|
+
#Tests root? instance method
|
636
|
+
def test_root_instance_method
|
637
|
+
a = Node.create!
|
638
|
+
b = Node.create!
|
639
|
+
assert b.root?
|
640
|
+
a.children << b
|
641
|
+
a.reload
|
642
|
+
b.reload
|
643
|
+
assert !b.root?
|
644
|
+
assert a.root?
|
645
|
+
end
|
646
|
+
|
647
|
+
#Tests has_many links_as_ancestor
|
648
|
+
def test_has_many_links_as_ancestor_poly
|
649
|
+
a = BetaNode.create!
|
650
|
+
b = BetaNode.create!
|
651
|
+
e = a.links_as_ancestor.build
|
652
|
+
e.descendant = b
|
653
|
+
e.save!
|
654
|
+
assert_equal e.ancestor, a
|
655
|
+
assert_equal e.descendant, b
|
656
|
+
end
|
657
|
+
|
658
|
+
#Tests has_many links_as_descendant
|
659
|
+
def test_has_many_links_as_descendant_poly
|
660
|
+
a = BetaNode.create!
|
661
|
+
b = BetaNode.create!
|
662
|
+
e = b.links_as_descendant.build
|
663
|
+
e.ancestor = a
|
664
|
+
e.save!
|
665
|
+
assert_equal e.ancestor, a
|
666
|
+
assert_equal e.descendant, b
|
667
|
+
end
|
668
|
+
|
669
|
+
#Tests has_many links_as_parent
|
670
|
+
def test_has_many_links_as_parent_poly
|
671
|
+
a = BetaNode.create!
|
672
|
+
b = BetaNode.create!
|
673
|
+
e = a.links_as_parent.build
|
674
|
+
e.descendant = b
|
675
|
+
e.save!
|
676
|
+
assert_equal e.ancestor, a
|
677
|
+
assert_equal e.descendant, b
|
678
|
+
end
|
679
|
+
|
680
|
+
#Tests has_many links_as_child
|
681
|
+
def test_has_many_links_as_child_poly
|
682
|
+
a = BetaNode.create!
|
683
|
+
b = BetaNode.create!
|
684
|
+
e = b.links_as_child.build
|
685
|
+
e.ancestor = a
|
686
|
+
e.save!
|
687
|
+
assert_equal e.ancestor, a
|
688
|
+
assert_equal e.descendant, b
|
689
|
+
end
|
690
|
+
|
691
|
+
#Tests leaf? instance method
|
692
|
+
def test_leaf_instance_method_poly
|
693
|
+
a = BetaNode.create!
|
694
|
+
assert a.leaf?
|
695
|
+
b = BetaNode.create!
|
696
|
+
a.child_beta_nodes << b
|
697
|
+
a.reload
|
698
|
+
b.reload
|
699
|
+
assert !a.leaf?
|
700
|
+
assert b.leaf?
|
701
|
+
end
|
702
|
+
|
703
|
+
#Tests root? instance method
|
704
|
+
def test_root_instance_method_poly
|
705
|
+
a = BetaNode.create!
|
706
|
+
b = BetaNode.create!
|
707
|
+
assert b.root?
|
708
|
+
a.child_beta_nodes << b
|
709
|
+
a.reload
|
710
|
+
b.reload
|
711
|
+
assert !b.root?
|
712
|
+
assert a.root?
|
713
|
+
end
|
714
|
+
|
715
|
+
#Tests has_many links_as_ancestor_for_*
|
716
|
+
def test_has_many_links_as_ancestor_for
|
717
|
+
a = AlphaNode.create!
|
718
|
+
b = BetaNode.create!
|
719
|
+
e = a.links_as_ancestor_for_beta_nodes.build
|
720
|
+
e.descendant = b
|
721
|
+
e.save!
|
722
|
+
assert_equal e.ancestor, a
|
723
|
+
assert_equal e.descendant, b
|
724
|
+
end
|
725
|
+
|
726
|
+
#Tests has_many links_as_descendant_for_*
|
727
|
+
def test_has_many_links_as_descendant_for
|
728
|
+
a = AlphaNode.create!
|
729
|
+
b = BetaNode.create!
|
730
|
+
e = b.links_as_descendant_for_alpha_nodes.build
|
731
|
+
e.ancestor = a
|
732
|
+
e.save!
|
733
|
+
assert_equal e.ancestor, a
|
734
|
+
assert_equal e.descendant, b
|
735
|
+
end
|
736
|
+
|
737
|
+
#Tests has_many links_as_parent_for_*
|
738
|
+
def test_has_many_links_as_parent_for
|
739
|
+
a = AlphaNode.create!
|
740
|
+
b = BetaNode.create!
|
741
|
+
e = a.links_as_parent_for_beta_nodes.build
|
742
|
+
e.descendant = b
|
743
|
+
e.save!
|
744
|
+
assert_equal e.ancestor, a
|
745
|
+
assert_equal e.descendant, b
|
746
|
+
end
|
747
|
+
|
748
|
+
#Tests has_many links_as_child_for_*
|
749
|
+
def test_has_many_links_as_child_for
|
750
|
+
a = AlphaNode.create!
|
751
|
+
b = BetaNode.create!
|
752
|
+
e = b.links_as_child_for_alpha_nodes.build
|
753
|
+
e.ancestor = a
|
754
|
+
e.save!
|
755
|
+
assert_equal e.ancestor, a
|
756
|
+
assert_equal e.descendant, b
|
757
|
+
end
|
758
|
+
|
759
|
+
#Tests has_many descendant_type
|
760
|
+
def test_has_many_descendant_dvds
|
761
|
+
a = AlphaNode.create!
|
762
|
+
b = BetaNode.create!
|
763
|
+
a.descendant_beta_nodes << b
|
764
|
+
e = Poly.find_link(a,b)
|
765
|
+
assert !e.nil?
|
766
|
+
end
|
767
|
+
|
768
|
+
#Tests has_many ancestor_type
|
769
|
+
def test_has_many_ancestor_dvds
|
770
|
+
a = AlphaNode.create!
|
771
|
+
b = BetaNode.create!
|
772
|
+
b.ancestor_alpha_nodes << a
|
773
|
+
e = Poly.find_link(a,b)
|
774
|
+
assert !e.nil?
|
775
|
+
end
|
776
|
+
|
777
|
+
#Tests has_many child_dvds
|
778
|
+
def test_has_many_child_dvds
|
779
|
+
a = AlphaNode.create!
|
780
|
+
b = BetaNode.create!
|
781
|
+
a.child_beta_nodes << b
|
782
|
+
e = Poly.find_link(a,b)
|
783
|
+
assert !e.nil?
|
784
|
+
end
|
785
|
+
|
786
|
+
#Tests has_many parents
|
787
|
+
def test_has_many_parent_dvds
|
788
|
+
a = AlphaNode.create!
|
789
|
+
b = BetaNode.create!
|
790
|
+
b.parent_alpha_nodes << a
|
791
|
+
e = Poly.find_link(a,b)
|
792
|
+
assert !e.nil?
|
793
|
+
end
|
794
|
+
|
795
|
+
#Tests leaf_for_*? instance method
|
796
|
+
def test_leaf_for_instance_method
|
797
|
+
a = BetaNode.create!
|
798
|
+
b = BetaNode.create!
|
799
|
+
assert a.leaf_for_beta_nodes?
|
800
|
+
a.ancestor_beta_nodes << b
|
801
|
+
a.reload
|
802
|
+
b.reload
|
803
|
+
assert !b.leaf_for_beta_nodes?
|
804
|
+
end
|
805
|
+
|
806
|
+
#Tests root_for_*? instance method
|
807
|
+
def test_root_for_instance_method
|
808
|
+
a = BetaNode.create!
|
809
|
+
b = BetaNode.create!
|
810
|
+
assert a.root_for_beta_nodes?
|
811
|
+
a.descendant_beta_nodes << b
|
812
|
+
a.reload
|
813
|
+
b.reload
|
814
|
+
assert !b.root_for_beta_nodes?
|
815
|
+
end
|
816
|
+
end
|