treequel 1.0.4 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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' ).
|