treequel 1.0.4 → 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/ChangeLog +130 -1
- data/Rakefile +8 -3
- data/Rakefile.local +2 -0
- data/bin/treeirb +6 -2
- data/bin/treequel +5 -4
- data/lib/treequel/branch.rb +133 -72
- data/lib/treequel/branchcollection.rb +16 -5
- data/lib/treequel/branchset.rb +37 -6
- data/lib/treequel/constants.rb +12 -0
- data/lib/treequel/directory.rb +96 -41
- data/lib/treequel/filter.rb +42 -1
- data/lib/treequel/model/objectclass.rb +111 -0
- data/lib/treequel/model.rb +363 -0
- data/lib/treequel/monkeypatches.rb +65 -0
- data/lib/treequel/schema/attributetype.rb +108 -18
- data/lib/treequel/schema/ldapsyntax.rb +15 -0
- data/lib/treequel/schema/matchingrule.rb +24 -0
- data/lib/treequel/schema/matchingruleuse.rb +24 -0
- data/lib/treequel/schema/objectclass.rb +70 -5
- data/lib/treequel/schema/table.rb +5 -15
- data/lib/treequel/schema.rb +64 -1
- data/lib/treequel.rb +5 -5
- data/rake/documentation.rb +27 -0
- data/rake/hg.rb +14 -2
- data/rake/manual.rb +1 -1
- data/spec/lib/constants.rb +9 -7
- data/spec/lib/control_behavior.rb +1 -0
- data/spec/lib/matchers.rb +1 -0
- data/spec/treequel/branch_spec.rb +229 -20
- data/spec/treequel/branchcollection_spec.rb +73 -39
- data/spec/treequel/branchset_spec.rb +59 -8
- data/spec/treequel/control_spec.rb +1 -0
- data/spec/treequel/controls/contentsync_spec.rb +1 -0
- data/spec/treequel/controls/pagedresults_spec.rb +1 -0
- data/spec/treequel/controls/sortedresults_spec.rb +1 -0
- data/spec/treequel/directory_spec.rb +46 -10
- data/spec/treequel/filter_spec.rb +28 -5
- data/spec/treequel/mixins_spec.rb +7 -14
- data/spec/treequel/model/objectclass_spec.rb +330 -0
- data/spec/treequel/model_spec.rb +433 -0
- data/spec/treequel/monkeypatches_spec.rb +118 -0
- data/spec/treequel/schema/attributetype_spec.rb +116 -0
- data/spec/treequel/schema/ldapsyntax_spec.rb +8 -0
- data/spec/treequel/schema/matchingrule_spec.rb +6 -1
- data/spec/treequel/schema/matchingruleuse_spec.rb +5 -0
- data/spec/treequel/schema/objectclass_spec.rb +41 -3
- data/spec/treequel/schema/table_spec.rb +31 -18
- data/spec/treequel/schema_spec.rb +13 -16
- data/spec/treequel_spec.rb +22 -0
- data.tar.gz.sig +1 -0
- metadata +40 -7
- metadata.gz.sig +0 -0
- data/spec/treequel/utils_spec.rb +0 -49
@@ -6,6 +6,7 @@ BEGIN {
|
|
6
6
|
|
7
7
|
libdir = basedir + "lib"
|
8
8
|
|
9
|
+
$LOAD_PATH.unshift( basedir ) unless $LOAD_PATH.include?( basedir )
|
9
10
|
$LOAD_PATH.unshift( libdir ) unless $LOAD_PATH.include?( libdir )
|
10
11
|
}
|
11
12
|
|
@@ -29,6 +30,7 @@ describe Treequel::Branch do
|
|
29
30
|
include Treequel::SpecHelpers,
|
30
31
|
Treequel::Matchers
|
31
32
|
|
33
|
+
|
32
34
|
before( :all ) do
|
33
35
|
setup_logging( :fatal )
|
34
36
|
end
|
@@ -68,6 +70,12 @@ describe Treequel::Branch do
|
|
68
70
|
branch.entry.should == entry
|
69
71
|
end
|
70
72
|
|
73
|
+
it "raises an exception if constructed with something other than a Hash entry" do
|
74
|
+
expect {
|
75
|
+
Treequel::Branch.new( @directory, TEST_PEOPLE_DN, 18 )
|
76
|
+
}.to raise_exception( ArgumentError, /can't cast/i )
|
77
|
+
end
|
78
|
+
|
71
79
|
it "can be configured to include operational attributes for all future instances" do
|
72
80
|
Treequel::Branch.include_operational_attrs = false
|
73
81
|
Treequel::Branch.new( @directory, TEST_PEOPLE_DN ).include_operational_attrs?.should be_false
|
@@ -89,7 +97,8 @@ describe Treequel::Branch do
|
|
89
97
|
@schema.stub!( :attribute_types ).
|
90
98
|
and_return({ :cn => :a_value, :ou => :a_value })
|
91
99
|
|
92
|
-
@
|
100
|
+
@syntax = stub( "attribute ldapSyntax object", :oid => OIDS::STRING_SYNTAX )
|
101
|
+
@attribute_type = mock( "schema attribute type object", :syntax => @syntax )
|
93
102
|
end
|
94
103
|
|
95
104
|
|
@@ -110,6 +119,11 @@ describe Treequel::Branch do
|
|
110
119
|
@branch.split_dn( 2 ).should include( TEST_HOSTS_RDN, TEST_BASE_DN )
|
111
120
|
end
|
112
121
|
|
122
|
+
it "can return itself as an ldap:// URI" do
|
123
|
+
@directory.should_receive( :uri ).and_return( URI.parse("ldap://#{TEST_HOST}/#{TEST_BASE_DN}") )
|
124
|
+
@branch.uri.to_s.should == "ldap://#{TEST_HOST}/#{TEST_HOSTS_DN}?"
|
125
|
+
end
|
126
|
+
|
113
127
|
it "are Comparable if they are siblings" do
|
114
128
|
sibling = Treequel::Branch.new( @directory, TEST_PEOPLE_DN )
|
115
129
|
|
@@ -182,6 +196,19 @@ describe Treequel::Branch do
|
|
182
196
|
end
|
183
197
|
|
184
198
|
|
199
|
+
it "can fetch a child entry by RDN" do
|
200
|
+
res = @branch.get_child( 'cn=surprise' )
|
201
|
+
res.should be_a( Treequel::Branch )
|
202
|
+
res.dn.should == [ 'cn=surprise', @branch.dn ].join( ',' )
|
203
|
+
end
|
204
|
+
|
205
|
+
it "can fetch a child entry by RDN if its DN is the empty String" do
|
206
|
+
@branch.dn = ''
|
207
|
+
res = @branch.get_child( 'cn=surprise' )
|
208
|
+
res.should be_a( Treequel::Branch )
|
209
|
+
res.dn.should == 'cn=surprise'
|
210
|
+
end
|
211
|
+
|
185
212
|
it "create sub-branches for messages that match valid attributeType OIDs" do
|
186
213
|
@schema.should_receive( :attribute_types ).twice.
|
187
214
|
and_return({ :cn => :a_value, :ou => :a_value })
|
@@ -287,17 +314,19 @@ describe Treequel::Branch do
|
|
287
314
|
|
288
315
|
it "knows which objectClasses it has" do
|
289
316
|
oc_attr = mock( "objectClass attributeType object" )
|
317
|
+
string_syntax = stub( "string ldapSyntax object", :oid => OIDS::STRING_SYNTAX )
|
290
318
|
@schema.should_receive( :attribute_types ).and_return({ :objectClass => oc_attr })
|
291
319
|
oc_attr.should_receive( :single? ).and_return( false )
|
292
|
-
oc_attr.should_receive( :
|
320
|
+
oc_attr.should_receive( :syntax ).at_least( :once ).
|
321
|
+
and_return( string_syntax )
|
293
322
|
|
294
323
|
@entry.should_receive( :[] ).with( 'objectClass' ).at_least( :once ).
|
295
324
|
and_return([ 'organizationalUnit', 'extensibleObject' ])
|
296
325
|
|
297
|
-
@directory.should_receive( :
|
326
|
+
@directory.should_receive( :convert_to_object ).
|
298
327
|
with( OIDS::STRING_SYNTAX, 'organizationalUnit' ).
|
299
328
|
and_return( 'organizationalUnit' )
|
300
|
-
@directory.should_receive( :
|
329
|
+
@directory.should_receive( :convert_to_object ).
|
301
330
|
with( OIDS::STRING_SYNTAX, 'extensibleObject' ).
|
302
331
|
and_return( 'extensibleObject' )
|
303
332
|
|
@@ -309,6 +338,42 @@ describe Treequel::Branch do
|
|
309
338
|
@branch.object_classes.should == [ :ou_objectclass, :extobj_objectclass ]
|
310
339
|
end
|
311
340
|
|
341
|
+
it "knows what operational attributes it has" do
|
342
|
+
op_attrs = MINIMAL_OPERATIONAL_ATTRIBUTES.inject({}) do |hash, oa|
|
343
|
+
hash[ oa ] = mock("#{oa} attributeType object")
|
344
|
+
hash
|
345
|
+
end
|
346
|
+
@schema.should_receive( :operational_attribute_types ).and_return( op_attrs.values )
|
347
|
+
|
348
|
+
@branch.operational_attribute_types.should == op_attrs.values
|
349
|
+
end
|
350
|
+
|
351
|
+
it "knows what the OIDs of its operational attributes are" do
|
352
|
+
op_attrs = MINIMAL_OPERATIONAL_ATTRIBUTES.inject({}) do |hash, oa|
|
353
|
+
hash[ oa ] = stub("#{oa} attributeType object", :oid => :an_oid )
|
354
|
+
hash
|
355
|
+
end
|
356
|
+
@schema.should_receive( :operational_attribute_types ).at_least( :once ).
|
357
|
+
and_return( op_attrs.values )
|
358
|
+
|
359
|
+
@branch.operational_attribute_oids.should have( op_attrs.length ).members
|
360
|
+
@branch.operational_attribute_oids.should include( :an_oid )
|
361
|
+
end
|
362
|
+
|
363
|
+
it "can return the set of all its MUST attributes' OIDs based on which objectClasses " +
|
364
|
+
"it has" do
|
365
|
+
oc1 = mock( "first objectclass" )
|
366
|
+
oc2 = mock( "second objectclass" )
|
367
|
+
|
368
|
+
@branch.should_receive( :object_classes ).and_return([ oc1, oc2 ])
|
369
|
+
oc1.should_receive( :must_oids ).at_least( :once ).and_return([ :oid1, :oid2 ])
|
370
|
+
oc2.should_receive( :must_oids ).at_least( :once ).and_return([ :oid1, :oid3 ])
|
371
|
+
|
372
|
+
must_oids = @branch.must_oids
|
373
|
+
must_oids.should have( 3 ).members
|
374
|
+
must_oids.should include( :oid1, :oid2, :oid3 )
|
375
|
+
end
|
376
|
+
|
312
377
|
it "can return the set of all its MUST attributeTypes based on which objectClasses it has" do
|
313
378
|
oc1 = mock( "first objectclass" )
|
314
379
|
oc2 = mock( "second objectclass" )
|
@@ -323,7 +388,7 @@ describe Treequel::Branch do
|
|
323
388
|
end
|
324
389
|
|
325
390
|
it "can return a Hash pre-populated with pairs that correspond to its MUST attributes" do
|
326
|
-
cn_attrtype = mock( "cn attribute type", :single? =>
|
391
|
+
cn_attrtype = mock( "cn attribute type", :single? => false )
|
327
392
|
l_attrtype = mock( "l attribute type", :single? => true )
|
328
393
|
objectClass_attrtype = mock( "objectClass attribute type", :single? => false )
|
329
394
|
|
@@ -335,10 +400,24 @@ describe Treequel::Branch do
|
|
335
400
|
and_return([ cn_attrtype, l_attrtype, objectClass_attrtype ])
|
336
401
|
|
337
402
|
@branch.must_attributes_hash.
|
338
|
-
should == { :cn => '', :l => '', :objectClass => [:top] }
|
403
|
+
should == { :cn => [''], :l => '', :objectClass => [:top] }
|
339
404
|
end
|
340
405
|
|
341
406
|
|
407
|
+
it "can return the set of all its MAY attributes' OIDs based on which objectClasses " +
|
408
|
+
"it has" do
|
409
|
+
oc1 = mock( "first objectclass" )
|
410
|
+
oc2 = mock( "second objectclass" )
|
411
|
+
|
412
|
+
@branch.should_receive( :object_classes ).and_return([ oc1, oc2 ])
|
413
|
+
oc1.should_receive( :may_oids ).at_least( :once ).and_return([ :oid1, :oid2 ])
|
414
|
+
oc2.should_receive( :may_oids ).at_least( :once ).and_return([ :oid1, :oid3 ])
|
415
|
+
|
416
|
+
must_oids = @branch.may_oids
|
417
|
+
must_oids.should have( 3 ).members
|
418
|
+
must_oids.should include( :oid1, :oid2, :oid3 )
|
419
|
+
end
|
420
|
+
|
342
421
|
it "can return the set of all its MAY attributeTypes based on which objectClasses it has" do
|
343
422
|
oc1 = mock( "first objectclass" )
|
344
423
|
oc2 = mock( "second objectclass" )
|
@@ -352,20 +431,67 @@ describe Treequel::Branch do
|
|
352
431
|
must_attrs.should include( :description, :mobilePhone, :chunktype )
|
353
432
|
end
|
354
433
|
|
434
|
+
it "can return a Hash pre-populated with pairs that correspond to its MAY attributes" do
|
435
|
+
cn_attrtype = mock( "cn attribute type", :single? => false )
|
436
|
+
l_attrtype = mock( "l attribute type", :single? => true )
|
437
|
+
|
438
|
+
cn_attrtype.should_receive( :name ).at_least( :once ).and_return( :cn )
|
439
|
+
l_attrtype.should_receive( :name ).at_least( :once ).and_return( :l )
|
440
|
+
|
441
|
+
@branch.should_receive( :may_attribute_types ).at_least( :once ).
|
442
|
+
and_return([ cn_attrtype, l_attrtype ])
|
443
|
+
|
444
|
+
@branch.may_attributes_hash.
|
445
|
+
should == { :cn => [], :l => nil }
|
446
|
+
end
|
447
|
+
|
355
448
|
it "can return the set of all of its valid attributeTypes, which is a union of its " +
|
356
|
-
"MUST and MAY attributes" do
|
449
|
+
"MUST and MAY attributes plus the directory's operational attributes" do
|
357
450
|
@branch.should_receive( :must_attribute_types ).
|
358
451
|
and_return([ :cn, :l, :uid ])
|
359
452
|
@branch.should_receive( :may_attribute_types ).
|
360
453
|
and_return([ :description, :mobilePhone, :chunktype ])
|
454
|
+
@branch.should_receive( :operational_attribute_types ).
|
455
|
+
and_return([ :createTimestamp, :creatorsName ])
|
361
456
|
|
362
457
|
all_attrs = @branch.valid_attribute_types
|
363
458
|
|
364
|
-
all_attrs.should have(
|
365
|
-
all_attrs.should include( :cn, :uid, :l, :description, :mobilePhone,
|
459
|
+
all_attrs.should have( 8 ).members
|
460
|
+
all_attrs.should include( :cn, :uid, :l, :description, :mobilePhone,
|
461
|
+
:chunktype, :createTimestamp, :creatorsName )
|
462
|
+
end
|
463
|
+
|
464
|
+
it "can return a Hash pre-populated with pairs that correspond to all of its valid " +
|
465
|
+
"attributes" do
|
466
|
+
@branch.should_receive( :must_attributes_hash ).at_least( :once ).
|
467
|
+
and_return({ :cn => [''], :l => '', :objectClass => [:top] })
|
468
|
+
@branch.should_receive( :may_attributes_hash ).at_least( :once ).
|
469
|
+
and_return({ :description => nil, :givenName => [], :cn => nil })
|
470
|
+
|
471
|
+
@branch.valid_attributes_hash.should == {
|
472
|
+
:cn => [''],
|
473
|
+
:l => '',
|
474
|
+
:objectClass => [:top],
|
475
|
+
:description => nil,
|
476
|
+
:givenName => [],
|
477
|
+
}
|
478
|
+
end
|
479
|
+
|
480
|
+
|
481
|
+
it "can return the set of all of its valid attribute OIDs, which is a union of its " +
|
482
|
+
"MUST and MAY attribute OIDs" do
|
483
|
+
@branch.should_receive( :must_oids ).
|
484
|
+
and_return([ :must_oid1, :must_oid2 ])
|
485
|
+
@branch.should_receive( :may_oids ).
|
486
|
+
and_return([ :may_oid1, :may_oid2, :must_oid1 ])
|
487
|
+
|
488
|
+
all_attr_oids = @branch.valid_attribute_oids
|
489
|
+
|
490
|
+
all_attr_oids.should have( 4 ).members
|
491
|
+
all_attr_oids.should include( :must_oid1, :must_oid2, :may_oid1, :may_oid2 )
|
366
492
|
end
|
367
493
|
|
368
|
-
it "knows if
|
494
|
+
it "knows if an attribute is valid given its objectClasses" do
|
369
495
|
attrtype = mock( "attribute type object" )
|
370
496
|
|
371
497
|
@branch.should_receive( :valid_attribute_types ).
|
@@ -487,6 +613,12 @@ describe Treequel::Branch do
|
|
487
613
|
@branch.delete( :objectClass => ['apple-user',:inetOrgPerson], :cn => [] )
|
488
614
|
end
|
489
615
|
|
616
|
+
it "deletes its entry entirely if no attributes are specified" do
|
617
|
+
@directory.should_receive( :delete ).with( @branch )
|
618
|
+
@branch.delete
|
619
|
+
end
|
620
|
+
|
621
|
+
|
490
622
|
it "knows how to represent its DN as an RFC1781-style UFN" do
|
491
623
|
@branch.to_ufn.should =~ /Hosts, acme\.com/i
|
492
624
|
end
|
@@ -505,6 +637,82 @@ describe Treequel::Branch do
|
|
505
637
|
end
|
506
638
|
|
507
639
|
|
640
|
+
LONG_TEST_VALUE = 'A poet once said, "The whole universe is in ' +
|
641
|
+
'a glass of wine." We will probably never know in what sense ' +
|
642
|
+
'he meant that, for poets do not write to be understood. But ' +
|
643
|
+
'it is true that if we look at a glass of wine closely enough ' +
|
644
|
+
'we see the entire universe.'
|
645
|
+
|
646
|
+
it "knows how to split long lines in LDIF output" do
|
647
|
+
@entry.should_receive( :keys ).and_return([ 'description', 'l' ])
|
648
|
+
@entry.should_receive( :[] ).with( 'description' ).
|
649
|
+
and_return([ LONG_TEST_VALUE ])
|
650
|
+
@entry.should_receive( :[] ).with( 'l' ).
|
651
|
+
and_return([ 'Antartica', 'Galapagos' ])
|
652
|
+
|
653
|
+
ldif = @branch.to_ldif( 20 )
|
654
|
+
val = ldif[ /(description: (?:[^\n]|\n )+)/, 1 ]
|
655
|
+
lines = val.split( /\n/ )
|
656
|
+
|
657
|
+
lines.first.should =~ /.{20}/
|
658
|
+
lines[1..-2].each do |line|
|
659
|
+
line.should =~ / .{19}/
|
660
|
+
end
|
661
|
+
lines.last.should =~ / .{1,19}/
|
662
|
+
end
|
663
|
+
|
664
|
+
|
665
|
+
LONG_BINARY_TEST_VALUE = ( <<-END_VALUE ).gsub( /^\t{2}/, '' )
|
666
|
+
Once there came a man
|
667
|
+
Who said,
|
668
|
+
"Range me all men of the world in rows."
|
669
|
+
And instantly
|
670
|
+
There was terrific clamour among the people
|
671
|
+
Against being ranged in rows.
|
672
|
+
There was a loud quarrel, world-wide.
|
673
|
+
It endured for ages;
|
674
|
+
And blood was shed
|
675
|
+
By those who would not stand in rows,
|
676
|
+
And by those who pined to stand in rows.
|
677
|
+
Eventually, the man went to death, weeping.
|
678
|
+
And those who staid in bloody scuffle
|
679
|
+
Knew not the great simplicity.
|
680
|
+
END_VALUE
|
681
|
+
|
682
|
+
it "knows how to split long binary lines in LDIF output" do
|
683
|
+
@entry.should_receive( :keys ).and_return([ 'description', 'l' ])
|
684
|
+
@entry.should_receive( :[] ).with( 'description' ).
|
685
|
+
and_return([ LONG_BINARY_TEST_VALUE ])
|
686
|
+
@entry.should_receive( :[] ).with( 'l' ).
|
687
|
+
and_return([ 'Antartica', 'Galapagos' ])
|
688
|
+
|
689
|
+
ldif = @branch.to_ldif( 20 )
|
690
|
+
ldif.scan( /^description/ ).length.should == 1
|
691
|
+
|
692
|
+
val = ldif[ /^(description:: (?:[^\n]|\n )+)/, 1 ]
|
693
|
+
lines = val.split( /\n/ )
|
694
|
+
lines.first.should =~ /.{20}/
|
695
|
+
lines[1..-2].each do |line|
|
696
|
+
line.should =~ / .{19}/
|
697
|
+
end
|
698
|
+
lines.last.should =~ / .{1,19}/
|
699
|
+
end
|
700
|
+
|
701
|
+
|
702
|
+
it "knows how to represent itself as a Hash" do
|
703
|
+
@entry.should_receive( :keys ).and_return([ 'description', 'dn', 'l' ])
|
704
|
+
@entry.should_receive( :[] ).with( 'description' ).
|
705
|
+
and_return([ 'A chilly little penguin.' ])
|
706
|
+
@entry.should_receive( :[] ).with( 'l' ).
|
707
|
+
and_return([ 'Antartica', 'Galapagos' ])
|
708
|
+
|
709
|
+
@branch.to_hash.should == {
|
710
|
+
'description' => ['A chilly little penguin.'],
|
711
|
+
'l' => [ 'Antartica', 'Galapagos' ],
|
712
|
+
'dn' => TEST_HOSTS_DN,
|
713
|
+
}
|
714
|
+
end
|
715
|
+
|
508
716
|
it "returns a Treequel::BranchCollection with equivalent Branchsets if added to another " +
|
509
717
|
"Branch" do
|
510
718
|
other_branch = Treequel::Branch.new( @directory, TEST_SUBHOSTS_DN )
|
@@ -527,8 +735,8 @@ describe Treequel::Branch do
|
|
527
735
|
@entry.should_receive( :[] ).with( 'glumpy' ).at_least( :once ).
|
528
736
|
and_return([ 'glumpa1', 'glumpa2' ])
|
529
737
|
|
530
|
-
@attribute_type.stub!( :
|
531
|
-
@directory.stub!( :
|
738
|
+
@attribute_type.stub!( :syntax ).and_return( @syntax )
|
739
|
+
@directory.stub!( :convert_to_object ).and_return {|_,str| str }
|
532
740
|
|
533
741
|
@branch[ :glumpy ].should == [ 'glumpa1', 'glumpa2' ]
|
534
742
|
end
|
@@ -539,8 +747,8 @@ describe Treequel::Branch do
|
|
539
747
|
@entry.should_receive( :[] ).with( 'glumpy' ).at_least( :once ).
|
540
748
|
and_return([ 'glumpa1' ])
|
541
749
|
|
542
|
-
@attribute_type.stub!( :
|
543
|
-
@directory.stub!( :
|
750
|
+
@attribute_type.stub!( :syntax ).and_return( @syntax )
|
751
|
+
@directory.stub!( :convert_to_object ).and_return {|_,str| str }
|
544
752
|
|
545
753
|
@branch[ :glumpy ].should == 'glumpa1'
|
546
754
|
end
|
@@ -560,8 +768,8 @@ describe Treequel::Branch do
|
|
560
768
|
it "caches the value fetched from its entry" do
|
561
769
|
@schema.stub!( :attribute_types ).and_return({ :glump => @attribute_type })
|
562
770
|
@attribute_type.stub!( :single? ).and_return( true )
|
563
|
-
@attribute_type.stub!( :
|
564
|
-
@directory.stub!( :
|
771
|
+
@attribute_type.stub!( :syntax ).and_return( @syntax )
|
772
|
+
@directory.stub!( :convert_to_object ).and_return {|_,str| str }
|
565
773
|
@entry.should_receive( :[] ).with( 'glump' ).once.and_return( [:a_value] )
|
566
774
|
2.times { @branch[ :glump ] }
|
567
775
|
end
|
@@ -571,8 +779,8 @@ describe Treequel::Branch do
|
|
571
779
|
@attribute_type.should_receive( :single? ).and_return( true )
|
572
780
|
@entry.should_receive( :[] ).with( 'bvector' ).at_least( :once ).
|
573
781
|
and_return([ '010011010101B' ])
|
574
|
-
@
|
575
|
-
@directory.should_receive( :
|
782
|
+
@syntax.stub!( :oid ).and_return( OIDS::BIT_STRING_SYNTAX )
|
783
|
+
@directory.should_receive( :convert_to_object ).
|
576
784
|
with( OIDS::BIT_STRING_SYNTAX, '010011010101B' ).
|
577
785
|
and_return( 1237 )
|
578
786
|
|
@@ -599,11 +807,12 @@ describe Treequel::Branch do
|
|
599
807
|
it "clears the cache after a successful write" do
|
600
808
|
@schema.stub!( :attribute_types ).and_return({ :glorpy => @attribute_type })
|
601
809
|
@attribute_type.stub!( :single? ).and_return( true )
|
602
|
-
@attribute_type.stub!( :
|
603
|
-
@directory.stub!( :
|
810
|
+
@attribute_type.stub!( :syntax ).and_return( @syntax )
|
811
|
+
@directory.stub!( :convert_to_object ).and_return {|_,val| val }
|
604
812
|
@entry.should_receive( :[] ).with( 'glorpy' ).and_return( [:firstval], [:secondval] )
|
605
813
|
|
606
814
|
@directory.should_receive( :modify ).with( @branch, {'glorpy' => ['chunks']} )
|
815
|
+
@directory.stub!( :convert_to_attribute ).and_return {|_,val| val }
|
607
816
|
@entry.should_receive( :[]= ).with( 'glorpy', ['chunks'] )
|
608
817
|
|
609
818
|
@branch[ :glorpy ].should == :firstval
|
@@ -6,22 +6,15 @@ BEGIN {
|
|
6
6
|
|
7
7
|
libdir = basedir + "lib"
|
8
8
|
|
9
|
+
$LOAD_PATH.unshift( basedir ) unless $LOAD_PATH.include?( basedir )
|
9
10
|
$LOAD_PATH.unshift( libdir ) unless $LOAD_PATH.include?( libdir )
|
10
11
|
}
|
11
12
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
require 'spec/lib/helpers'
|
13
|
+
require 'spec'
|
14
|
+
require 'spec/lib/constants'
|
15
|
+
require 'spec/lib/helpers'
|
16
16
|
|
17
|
-
|
18
|
-
rescue LoadError
|
19
|
-
unless Object.const_defined?( :Gem )
|
20
|
-
require 'rubygems'
|
21
|
-
retry
|
22
|
-
end
|
23
|
-
raise
|
24
|
-
end
|
17
|
+
require 'treequel/branchcollection'
|
25
18
|
|
26
19
|
|
27
20
|
include Treequel::TestConstants
|
@@ -42,7 +35,7 @@ describe Treequel::BranchCollection do
|
|
42
35
|
end
|
43
36
|
|
44
37
|
before( :each ) do
|
45
|
-
@directory = mock( "treequel directory
|
38
|
+
@directory = mock( "treequel directory", :registered_controls => [] )
|
46
39
|
end
|
47
40
|
|
48
41
|
it "can be instantiated without any branchsets" do
|
@@ -51,8 +44,10 @@ describe Treequel::BranchCollection do
|
|
51
44
|
end
|
52
45
|
|
53
46
|
it "can be instantiated with one or more branchsets" do
|
54
|
-
|
55
|
-
|
47
|
+
branch1 = stub( "branch for branchset 1", :directory => @directory )
|
48
|
+
branchset1 = Treequel::Branchset.new( branch1 )
|
49
|
+
branch2 = stub( "branch for branchset 2", :directory => @directory )
|
50
|
+
branchset2 = Treequel::Branchset.new( branch2 )
|
56
51
|
|
57
52
|
collection = Treequel::BranchCollection.new( branchset1, branchset2 )
|
58
53
|
|
@@ -60,17 +55,17 @@ describe Treequel::BranchCollection do
|
|
60
55
|
end
|
61
56
|
|
62
57
|
it "wraps any object that doesn't have an #each in a Branchset" do
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
branchset2 =
|
58
|
+
branch1 = stub( "branch for branchset 1", :directory => @directory )
|
59
|
+
branchset1 = Treequel::Branchset.new( branch1 )
|
60
|
+
branch2 = stub( "branch for branchset 2", :directory => @directory )
|
61
|
+
branchset2 = Treequel::Branchset.new( branch2 )
|
67
62
|
|
68
|
-
Treequel::Branchset.should_receive( :new ).with( non_branchset1 ).
|
63
|
+
Treequel::Branchset.should_receive( :new ).with( :non_branchset1 ).
|
69
64
|
and_return( branchset1 )
|
70
|
-
Treequel::Branchset.should_receive( :new ).with( non_branchset2 ).
|
65
|
+
Treequel::Branchset.should_receive( :new ).with( :non_branchset2 ).
|
71
66
|
and_return( branchset2 )
|
72
67
|
|
73
|
-
collection = Treequel::BranchCollection.new( non_branchset1, non_branchset2 )
|
68
|
+
collection = Treequel::BranchCollection.new( :non_branchset1, :non_branchset2 )
|
74
69
|
|
75
70
|
collection.branchsets.should include( branchset1, branchset2 )
|
76
71
|
end
|
@@ -99,8 +94,13 @@ describe Treequel::BranchCollection do
|
|
99
94
|
describe "instance with two Branchsets" do
|
100
95
|
|
101
96
|
before( :each ) do
|
102
|
-
@branchset1 = mock( "branchset 1", :dn => 'cn=example1,dc=acme,dc=com', :each => 1 )
|
103
|
-
@branchset2 = mock( "branchset 2", :dn => 'cn=example2,dc=acme,dc=com', :each => 1 )
|
97
|
+
# @branchset1 = mock( "branchset 1", :dn => 'cn=example1,dc=acme,dc=com', :each => 1 )
|
98
|
+
# @branchset2 = mock( "branchset 2", :dn => 'cn=example2,dc=acme,dc=com', :each => 1 )
|
99
|
+
@branch1 = mock( "branch1", :directory => @directory )
|
100
|
+
@branchset1 = Treequel::Branchset.new( @branch1 )
|
101
|
+
|
102
|
+
@branch2 = mock( "branch2", :directory => @directory )
|
103
|
+
@branchset2 = Treequel::Branchset.new( @branch2 )
|
104
104
|
|
105
105
|
@collection = Treequel::BranchCollection.new( @branchset1, @branchset2 )
|
106
106
|
end
|
@@ -134,26 +134,51 @@ describe Treequel::BranchCollection do
|
|
134
134
|
end
|
135
135
|
|
136
136
|
it "returns a clone of itself with an additional Branchset if a Branchset is added to it" do
|
137
|
-
|
137
|
+
branch3 = mock( "branch 3", :directory => @directory )
|
138
|
+
branchset3 = Treequel::Branchset.new( branch3 )
|
139
|
+
|
138
140
|
new_collection = @collection + branchset3
|
139
141
|
|
140
142
|
new_collection.should be_an_instance_of( Treequel::BranchCollection )
|
141
143
|
new_collection.should include( @branchset1, @branchset2, branchset3 )
|
142
144
|
end
|
143
145
|
|
144
|
-
it "returns
|
145
|
-
|
146
|
-
|
147
|
-
|
146
|
+
it "returns all of the results from each of its branchsets plus the added branch if a " +
|
147
|
+
"Branch is added to it" do
|
148
|
+
@branchset1.should_receive( :each ).and_yield( :bs1_stuff )
|
149
|
+
@branchset2.should_receive( :each ).and_yield( :bs2_stuff )
|
150
|
+
added_branch = stub( "added branch", :directory => @directory )
|
151
|
+
added_branch.stub!( :to_ary ).and_return( [added_branch] )
|
148
152
|
|
149
|
-
|
150
|
-
|
153
|
+
results = @collection + added_branch
|
154
|
+
|
155
|
+
results.should have( 3 ).members
|
156
|
+
results.should include( :bs1_stuff, :bs2_stuff, added_branch )
|
157
|
+
end
|
158
|
+
|
159
|
+
it "returns all of the results from each of its branchsets minus the subtracted branch " +
|
160
|
+
"if a Branch is subtracted from it" do
|
161
|
+
results_branch1 = stub( "results branch 1", :dn => TEST_PERSON_DN )
|
162
|
+
results_branch2 = stub( "results branch 2", :dn => TEST_PERSON2_DN )
|
163
|
+
subtracted_branch = stub( "subtracted branch", :dn => TEST_PERSON_DN )
|
164
|
+
|
165
|
+
@branchset1.should_receive( :each ).and_yield( results_branch1 )
|
166
|
+
@branchset2.should_receive( :each ).and_yield( results_branch2 )
|
167
|
+
|
168
|
+
results = @collection - subtracted_branch
|
169
|
+
|
170
|
+
results.should have( 1 ).members
|
171
|
+
results.should_not include( subtracted_branch )
|
172
|
+
results.should_not include( results_branch1 )
|
151
173
|
end
|
152
174
|
|
153
175
|
it "returns a clone of itself with both collections' Branchsets if a BranchCollection is " +
|
154
176
|
"added to it" do
|
155
|
-
|
156
|
-
|
177
|
+
branch3 = stub( "branch for branchset 3", :directory => @directory )
|
178
|
+
branchset3 = Treequel::Branchset.new( branch3 )
|
179
|
+
branch4 = stub( "branch for branchset 4", :directory => @directory )
|
180
|
+
branchset4 = Treequel::Branchset.new( branch4 )
|
181
|
+
|
157
182
|
other_collection = Treequel::BranchCollection.new( branchset3, branchset4 )
|
158
183
|
|
159
184
|
new_collection = @collection + other_collection
|
@@ -164,8 +189,11 @@ describe Treequel::BranchCollection do
|
|
164
189
|
|
165
190
|
it "returns a new BranchCollection with the union of Branchsets if it is ORed with " +
|
166
191
|
"another BranchCollection" do
|
167
|
-
|
168
|
-
|
192
|
+
branch3 = stub( "branch for branchset 3", :directory => @directory )
|
193
|
+
branchset3 = Treequel::Branchset.new( branch3 )
|
194
|
+
branch4 = stub( "branch for branchset 4", :directory => @directory )
|
195
|
+
branchset4 = Treequel::Branchset.new( branch4 )
|
196
|
+
|
169
197
|
other_collection = Treequel::BranchCollection.new( branchset3, branchset4 )
|
170
198
|
|
171
199
|
new_collection = @collection | other_collection
|
@@ -176,8 +204,11 @@ describe Treequel::BranchCollection do
|
|
176
204
|
|
177
205
|
it "returns a new BranchCollection with the intersection of Branchsets if it is ANDed with " +
|
178
206
|
"another BranchCollection" do
|
179
|
-
|
180
|
-
|
207
|
+
branch3 = stub( "branch for branchset 3", :directory => @directory )
|
208
|
+
branchset3 = Treequel::Branchset.new( branch3 )
|
209
|
+
branch4 = stub( "branch for branchset 4", :directory => @directory )
|
210
|
+
branchset4 = Treequel::Branchset.new( branch4 )
|
211
|
+
|
181
212
|
other_collection = Treequel::BranchCollection.new( @branchset2, branchset3, branchset4 )
|
182
213
|
@collection << branchset4
|
183
214
|
|
@@ -188,8 +219,11 @@ describe Treequel::BranchCollection do
|
|
188
219
|
end
|
189
220
|
|
190
221
|
it "can create a clone of itself with filtered branchsets" do
|
191
|
-
|
192
|
-
|
222
|
+
branch3 = stub( "branch for branchset 3", :directory => @directory )
|
223
|
+
filtered_branchset1 = Treequel::Branchset.new( branch3 )
|
224
|
+
branch4 = stub( "branch for branchset 4", :directory => @directory )
|
225
|
+
filtered_branchset2 = Treequel::Branchset.new( branch4 )
|
226
|
+
|
193
227
|
@branchset1.should_receive( :filter ).with( :cn => 'chunkalicious' ).
|
194
228
|
and_return( filtered_branchset1 )
|
195
229
|
@branchset2.should_receive( :filter ).with( :cn => 'chunkalicious' ).
|