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.
Files changed (53) hide show
  1. data/ChangeLog +130 -1
  2. data/Rakefile +8 -3
  3. data/Rakefile.local +2 -0
  4. data/bin/treeirb +6 -2
  5. data/bin/treequel +5 -4
  6. data/lib/treequel/branch.rb +133 -72
  7. data/lib/treequel/branchcollection.rb +16 -5
  8. data/lib/treequel/branchset.rb +37 -6
  9. data/lib/treequel/constants.rb +12 -0
  10. data/lib/treequel/directory.rb +96 -41
  11. data/lib/treequel/filter.rb +42 -1
  12. data/lib/treequel/model/objectclass.rb +111 -0
  13. data/lib/treequel/model.rb +363 -0
  14. data/lib/treequel/monkeypatches.rb +65 -0
  15. data/lib/treequel/schema/attributetype.rb +108 -18
  16. data/lib/treequel/schema/ldapsyntax.rb +15 -0
  17. data/lib/treequel/schema/matchingrule.rb +24 -0
  18. data/lib/treequel/schema/matchingruleuse.rb +24 -0
  19. data/lib/treequel/schema/objectclass.rb +70 -5
  20. data/lib/treequel/schema/table.rb +5 -15
  21. data/lib/treequel/schema.rb +64 -1
  22. data/lib/treequel.rb +5 -5
  23. data/rake/documentation.rb +27 -0
  24. data/rake/hg.rb +14 -2
  25. data/rake/manual.rb +1 -1
  26. data/spec/lib/constants.rb +9 -7
  27. data/spec/lib/control_behavior.rb +1 -0
  28. data/spec/lib/matchers.rb +1 -0
  29. data/spec/treequel/branch_spec.rb +229 -20
  30. data/spec/treequel/branchcollection_spec.rb +73 -39
  31. data/spec/treequel/branchset_spec.rb +59 -8
  32. data/spec/treequel/control_spec.rb +1 -0
  33. data/spec/treequel/controls/contentsync_spec.rb +1 -0
  34. data/spec/treequel/controls/pagedresults_spec.rb +1 -0
  35. data/spec/treequel/controls/sortedresults_spec.rb +1 -0
  36. data/spec/treequel/directory_spec.rb +46 -10
  37. data/spec/treequel/filter_spec.rb +28 -5
  38. data/spec/treequel/mixins_spec.rb +7 -14
  39. data/spec/treequel/model/objectclass_spec.rb +330 -0
  40. data/spec/treequel/model_spec.rb +433 -0
  41. data/spec/treequel/monkeypatches_spec.rb +118 -0
  42. data/spec/treequel/schema/attributetype_spec.rb +116 -0
  43. data/spec/treequel/schema/ldapsyntax_spec.rb +8 -0
  44. data/spec/treequel/schema/matchingrule_spec.rb +6 -1
  45. data/spec/treequel/schema/matchingruleuse_spec.rb +5 -0
  46. data/spec/treequel/schema/objectclass_spec.rb +41 -3
  47. data/spec/treequel/schema/table_spec.rb +31 -18
  48. data/spec/treequel/schema_spec.rb +13 -16
  49. data/spec/treequel_spec.rb +22 -0
  50. data.tar.gz.sig +1 -0
  51. metadata +40 -7
  52. metadata.gz.sig +0 -0
  53. 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
 
@@ -172,16 +173,38 @@ describe Treequel::Branchset do
172
173
  result.branchsets.should include( @branchset, other_branchset )
173
174
  end
174
175
 
175
- they "can be combined with a Branch into a BranchCollection by adding it" do
176
- other_branch = mock( "second treequel branch", :dn => 'theotherdn' )
177
- other_branch.stub!( :directory ).and_return( @directory )
176
+ they "return the results of the search with the additional Branch if one is added to it" do
177
+ other_branch = mock( "additional treequel branch", :dn => 'theotherdn' )
178
+ other_branch.stub!( :to_ary ).and_return( [other_branch] )
179
+ resultbranch = mock( "Result Branch" )
180
+ resultbranch2 = mock( "Result Branch 2" )
181
+
182
+ @branch.should_receive( :search ).
183
+ with( Treequel::Branchset::DEFAULT_SCOPE, @branchset.filter, @params ).
184
+ and_yield( resultbranch ).and_yield( resultbranch2 )
178
185
 
179
186
  result = @branchset + other_branch
180
- result.should be_a( Treequel::BranchCollection )
181
- result.branchsets.should have( 2 ).members
182
- result.branchsets.should include( @branchset )
183
- result.branchsets.select {|bs| bs != @branchset }.
184
- first.branch.should == other_branch
187
+ result.should have( 3 ).members
188
+ result.should include( other_branch, resultbranch, resultbranch2 )
189
+ end
190
+
191
+ #
192
+ # #-
193
+ #
194
+ they "return the results of the search without the specified object if an object is " +
195
+ "subtracted from it" do
196
+ resultbranch = stub( "Result Branch", :dn => TEST_PERSON_DN )
197
+ resultbranch2 = stub( "Result Branch 2", :dn => TEST_PERSON2_DN )
198
+
199
+ otherbranch = stub( "Subtracted Branch", :dn => TEST_PERSON2_DN )
200
+
201
+ @branch.should_receive( :search ).
202
+ with( Treequel::Branchset::DEFAULT_SCOPE, @branchset.filter, @params ).
203
+ and_yield( resultbranch ).and_yield( resultbranch2 )
204
+
205
+ result = @branchset - otherbranch
206
+ result.should have( 1 ).members
207
+ result.should_not include( resultbranch2 )
185
208
  end
186
209
 
187
210
  end
@@ -233,6 +256,24 @@ describe Treequel::Branchset do
233
256
  newset.filter_string.should == '(clothing=pants)'
234
257
  end
235
258
 
259
+ #
260
+ # #or
261
+ #
262
+
263
+ it "creates a new branchset cloned from itself with an OR clause added to to an " +
264
+ "existing filter" do
265
+ pantset = @branchset.filter( :clothing => 'pants' )
266
+ bothset = pantset.or( :clothing => 'shirt' )
267
+
268
+ bothset.filter_string.should == '(|(clothing=pants)(clothing=shirt))'
269
+ end
270
+
271
+ it "raises an exception if #or is invoked without an existing filter" do
272
+ expect {
273
+ @branchset.or( :clothing => 'shirt' )
274
+ }.to raise_exception( Treequel::ExpressionError, /no existing filter/i )
275
+ end
276
+
236
277
  #
237
278
  # #scope
238
279
  #
@@ -287,6 +328,12 @@ describe Treequel::Branchset do
287
328
  newset.select.should == [ 'l', 'cn', 'uid', 'firstName', 'lastName' ]
288
329
  end
289
330
 
331
+ it "adding attributes via #select_more should work even if there was no current " +
332
+ "attribute selection" do
333
+ newset = @branchset.select_more( :firstName, :uid, :lastName, :objectClass )
334
+ newset.select.should include( 'uid', 'firstName', 'lastName', 'objectClass' )
335
+ end
336
+
290
337
  it "uses its selection as the list of attributes to fetch when searching" do
291
338
  @branchset.options[:select] = [ :l, :cn, :uid ]
292
339
  @branch.should_receive( :search ).
@@ -432,6 +479,10 @@ describe Treequel::Branchset do
432
479
  @directory.stub!( :registered_controls ).and_return([ @control ])
433
480
  end
434
481
 
482
+ after( :each ) do
483
+ @directory = nil
484
+ end
485
+
435
486
  it "extends instances of itself with any controls registered with its Branch's Directory" do
436
487
  set = Treequel::Branchset.new( @branch )
437
488
  set.should respond_to( :yep )
@@ -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
 
@@ -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
 
@@ -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
 
@@ -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
 
@@ -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
 
@@ -88,6 +89,22 @@ describe Treequel::Directory do
88
89
  @dir.base_dn.should == TEST_BASE_DN
89
90
  end
90
91
 
92
+ it "can return its root element as a Branch instance" do
93
+ @dir = Treequel::Directory.new( @options )
94
+ @dir.base.should be_a( Treequel::Branch )
95
+ @dir.base.dn.should == TEST_BASE_DN
96
+ end
97
+
98
+ it "can return its root element as an instance of its results class if it's been set" do
99
+ subtype = Class.new( Treequel::Branch )
100
+ @dir = Treequel::Directory.new( @options )
101
+
102
+ @dir.results_class = subtype
103
+
104
+ @dir.base.should be_a( subtype )
105
+ @dir.base.dn.should == TEST_BASE_DN
106
+ end
107
+
91
108
 
92
109
  describe "instances without existing connections" do
93
110
 
@@ -539,22 +556,40 @@ describe Treequel::Directory do
539
556
 
540
557
  ### Datatype conversion
541
558
 
542
- it "allows a mapping to be overridden by a block for a valid syntax OID" do
543
- @dir.add_syntax_mapping( OIDS::BIT_STRING_SYNTAX ) do |unconverted_value|
559
+ it "allows an attribute conversion to be overridden by a block for a valid syntax OID" do
560
+ @dir.add_attribute_conversion( OIDS::BIT_STRING_SYNTAX ) do |unconverted_value, directory|
544
561
  unconverted_value.to_sym
545
562
  end
546
- @dir.convert_syntax_value( OIDS::BIT_STRING_SYNTAX, 'a_value' ).should == :a_value
563
+ @dir.convert_to_object( OIDS::BIT_STRING_SYNTAX, 'a_value' ).should == :a_value
564
+ end
565
+
566
+ it "allows an attribute conversion to be overridden by a Hash for a valid syntax OID" do
567
+ @dir.add_attribute_conversion( OIDS::BOOLEAN_SYNTAX, {'true' => true, 'false' => false} )
568
+ @dir.convert_to_object( OIDS::BOOLEAN_SYNTAX, 'true' ).should == true
569
+ end
570
+
571
+ it "allows an attribute conversion to be cleared by adding a nil mapping" do
572
+ @dir.add_attribute_conversion( OIDS::BOOLEAN_SYNTAX, {'true' => true, 'false' => false} )
573
+ @dir.add_attribute_conversion( OIDS::BOOLEAN_SYNTAX )
574
+ @dir.convert_to_object( OIDS::BOOLEAN_SYNTAX, 'true' ).should == 'true'
575
+ end
576
+
577
+ it "allows an object conversion to be overridden by a block for a valid syntax OID" do
578
+ @dir.add_object_conversion( OIDS::BIT_STRING_SYNTAX ) do |unconverted_value, directory|
579
+ unconverted_value.to_s
580
+ end
581
+ @dir.convert_to_attribute( OIDS::BIT_STRING_SYNTAX, :a_value ).should == 'a_value'
547
582
  end
548
583
 
549
- it "allows a mapping to be overridden by a Hash for a valid syntax OID" do
550
- @dir.add_syntax_mapping( OIDS::BOOLEAN_SYNTAX, {'true' => true, 'false' => false} )
551
- @dir.convert_syntax_value( OIDS::BOOLEAN_SYNTAX, 'true' ).should == true
584
+ it "allows an object conversion to be overridden by a Hash for a valid syntax OID" do
585
+ @dir.add_object_conversion( OIDS::BOOLEAN_SYNTAX, {false => 'FALSE', true => 'TRUE'} )
586
+ @dir.convert_to_attribute( OIDS::BOOLEAN_SYNTAX, false ).should == 'FALSE'
552
587
  end
553
588
 
554
- it "allows a mapping to be cleared by adding a nil mapping" do
555
- @dir.add_syntax_mapping( OIDS::BOOLEAN_SYNTAX, {'true' => true, 'false' => false} )
556
- @dir.add_syntax_mapping( OIDS::BOOLEAN_SYNTAX )
557
- @dir.convert_syntax_value( OIDS::BOOLEAN_SYNTAX, 'true' ).should == 'true'
589
+ it "allows an object conversion to be cleared by adding a nil mapping" do
590
+ @dir.add_object_conversion( OIDS::BOOLEAN_SYNTAX, {'true' => true, 'false' => false} )
591
+ @dir.add_object_conversion( OIDS::BOOLEAN_SYNTAX )
592
+ @dir.convert_to_attribute( OIDS::BOOLEAN_SYNTAX, true ).should == 'true'
558
593
  end
559
594
 
560
595
 
@@ -591,6 +626,7 @@ describe Treequel::Directory do
591
626
  end
592
627
 
593
628
  it "raises an exception if a registered control doesn't define an OID" do
629
+ @control.const_set( :OID, nil )
594
630
  expect {
595
631
  @dir.register_controls( @control )
596
632
  }.to raise_error( NotImplementedError, /doesn't define/i )
@@ -6,12 +6,10 @@ 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
- require 'rubygems'
13
- gem 'rspec', '>= 1.2.6'
14
-
15
13
  require 'spec'
16
14
  require 'spec/lib/constants'
17
15
  require 'spec/lib/helpers'
@@ -221,13 +219,27 @@ describe Treequel::Filter do
221
219
  result.should == @filter1
222
220
  end
223
221
 
222
+ it "creates a new OR filter out of two filters that are bitwise-ORed together" do
223
+ result = @filter1 | @filter2
224
+ result.should be_a( Treequel::Filter )
225
+ end
226
+
227
+ it "collapses two OR filters into a single OR clause when bitwise-ORed together" do
228
+ orfilter = @filter1 | @filter2
229
+ thirdfilter = Treequel::Filter.new( :l => :saturn )
230
+ result = ( orfilter | thirdfilter )
231
+
232
+ result.should be_a( Treequel::Filter )
233
+ result.to_s.should == '(|(uid=buckrogers)(l=mars)(l=saturn))'
234
+ end
235
+
224
236
  end
225
237
 
226
238
  describe "components:" do
227
239
 
228
240
  before( :each ) do
229
- @filter1 = stub( "filter1", :to_s => '(filter1)' )
230
- @filter2 = stub( "filter2", :to_s => '(filter2)' )
241
+ @filter1 = Treequel::Filter.new( '(filter1)' )
242
+ @filter2 = Treequel::Filter.new( '(filter2)' )
231
243
  end
232
244
 
233
245
 
@@ -236,6 +248,12 @@ describe Treequel::Filter do
236
248
  Treequel::Filter::FilterList.new( @filter1, @filter2 ).to_s.
237
249
  should == '(filter1)(filter2)'
238
250
  end
251
+
252
+ it "supports appending via the << operator" do
253
+ list = Treequel::Filter::FilterList.new( @filter1 )
254
+ ( list << @filter2 ).should == list
255
+ list.to_s.should == '(filter1)(filter2)'
256
+ end
239
257
  end
240
258
 
241
259
  describe Treequel::Filter::Component do
@@ -365,6 +383,11 @@ describe Treequel::Filter do
365
383
  should == '|(filter1)'
366
384
  end
367
385
 
386
+ it "allows futher alternations to be added to it" do
387
+ filter = Treequel::Filter::OrComponent.new( @filter1 )
388
+ filter.add_alternation( @filter2 )
389
+ filter.to_s.should == '|(filter1)(filter2)'
390
+ end
368
391
  end
369
392
 
370
393
  describe Treequel::Filter::NotComponent do
@@ -7,24 +7,17 @@ BEGIN {
7
7
  libdir = basedir + "lib"
8
8
  extdir = basedir + "ext"
9
9
 
10
+ $LOAD_PATH.unshift( basedir ) unless $LOAD_PATH.include?( basedir )
10
11
  $LOAD_PATH.unshift( libdir ) unless $LOAD_PATH.include?( libdir )
11
12
  $LOAD_PATH.unshift( extdir ) unless $LOAD_PATH.include?( extdir )
12
13
  }
13
14
 
14
- begin
15
- require 'spec'
16
- require 'spec/lib/constants'
17
- require 'spec/lib/helpers'
18
-
19
- require 'treequel'
20
- require 'treequel/mixins'
21
- rescue LoadError
22
- unless Object.const_defined?( :Gem )
23
- require 'rubygems'
24
- retry
25
- end
26
- raise
27
- end
15
+ require 'spec'
16
+ require 'spec/lib/constants'
17
+ require 'spec/lib/helpers'
18
+
19
+ require 'treequel'
20
+ require 'treequel/mixins'
28
21
 
29
22
 
30
23
  include Treequel::TestConstants
@@ -0,0 +1,330 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ BEGIN {
4
+ require 'pathname'
5
+ basedir = Pathname.new( __FILE__ ).dirname.parent.parent
6
+
7
+ libdir = basedir + "lib"
8
+
9
+ $LOAD_PATH.unshift( basedir ) unless $LOAD_PATH.include?( basedir )
10
+ $LOAD_PATH.unshift( libdir ) unless $LOAD_PATH.include?( libdir )
11
+ }
12
+
13
+ require 'spec'
14
+ require 'spec/lib/constants'
15
+ require 'spec/lib/helpers'
16
+ require 'spec/lib/matchers'
17
+
18
+ require 'treequel/model'
19
+ require 'treequel/model/objectclass'
20
+ require 'treequel/branchset'
21
+
22
+
23
+ include Treequel::TestConstants
24
+ include Treequel::Constants
25
+
26
+ #####################################################################
27
+ ### C O N T E X T S
28
+ #####################################################################
29
+
30
+ describe Treequel::Model::ObjectClass do
31
+ include Treequel::SpecHelpers,
32
+ Treequel::Matchers
33
+
34
+ class << self
35
+ alias_method :they, :it
36
+ end
37
+
38
+ before( :all ) do
39
+ setup_logging( :fatal )
40
+ end
41
+
42
+ after( :all ) do
43
+ reset_logging()
44
+ end
45
+
46
+
47
+ it "outputs a warning when it is included instead of used to extend a Module" do
48
+ Treequel::Model::ObjectClass.should_receive( :warn ).
49
+ with( /extending.*rather than appending/i )
50
+ mixin = Module.new do
51
+ include Treequel::Model::ObjectClass
52
+ end
53
+ end
54
+
55
+
56
+ describe "modules" do
57
+
58
+ after( :each ) do
59
+ Treequel::Model.objectclass_registry.clear
60
+ Treequel::Model.base_registry.clear
61
+ end
62
+
63
+ they "can declare a required objectClass" do
64
+ mixin = Module.new do
65
+ extend Treequel::Model::ObjectClass
66
+ model_objectclasses :inetOrgPerson
67
+ end
68
+
69
+ mixin.model_objectclasses.should == [:inetOrgPerson]
70
+ end
71
+
72
+ they "can declare multiple required objectClasses" do
73
+ mixin = Module.new do
74
+ extend Treequel::Model::ObjectClass
75
+ model_objectclasses :inetOrgPerson, :acmeAccount
76
+ end
77
+
78
+ mixin.model_objectclasses.should == [ :inetOrgPerson, :acmeAccount ]
79
+ end
80
+
81
+ they "can declare a single base" do
82
+ mixin = Module.new do
83
+ extend Treequel::Model::ObjectClass
84
+ model_objectclasses :device
85
+ model_bases TEST_PHONES_DN
86
+ end
87
+
88
+ mixin.model_bases.should == [TEST_PHONES_DN]
89
+ end
90
+
91
+ they "can declare base with spaces" do
92
+ mixin = Module.new do
93
+ extend Treequel::Model::ObjectClass
94
+ model_objectclasses :device
95
+ model_bases 'ou=phones, dc=acme, dc=com'
96
+ end
97
+
98
+ mixin.model_bases.should == ['ou=phones,dc=acme,dc=com']
99
+ end
100
+
101
+ they "can declare multiple bases" do
102
+ mixin = Module.new do
103
+ extend Treequel::Model::ObjectClass
104
+ model_objectclasses :ipHost
105
+ model_bases TEST_HOSTS_DN,
106
+ TEST_SUBHOSTS_DN
107
+ end
108
+
109
+ mixin.model_bases.should include( TEST_HOSTS_DN, TEST_SUBHOSTS_DN )
110
+ end
111
+
112
+ they "raises an exception when creating a search for a mixin that hasn't declared " +
113
+ "at least one objectClass or base" do
114
+ mixin = Module.new do
115
+ extend Treequel::Model::ObjectClass
116
+ end
117
+
118
+ expect {
119
+ mixin.search( @directory )
120
+ }.to raise_exception( Treequel::ModelError, /has no search criteria defined/ )
121
+ end
122
+
123
+ they "default to using Treequel::Model as their model class" do
124
+ mixin = Module.new do
125
+ extend Treequel::Model::ObjectClass
126
+ end
127
+
128
+ mixin.model_class.should == Treequel::Model
129
+ end
130
+
131
+ they "can declare a model class other than Treequel::Model" do
132
+ class MyModel < Treequel::Model; end
133
+ mixin = Module.new do
134
+ extend Treequel::Model::ObjectClass
135
+ model_class MyModel
136
+ end
137
+
138
+ mixin.model_class.should == MyModel
139
+ end
140
+
141
+ they "re-register objectClasses that have already been declared when declaring a " +
142
+ "new model class" do
143
+ class MyModel < Treequel::Model; end
144
+
145
+ mixin = Module.new do
146
+ extend Treequel::Model::ObjectClass
147
+ model_objectclasses :inetOrgPerson
148
+ model_class MyModel
149
+ end
150
+
151
+ Treequel::Model.objectclass_registry[:inetOrgPerson].should_not include( mixin )
152
+ MyModel.objectclass_registry[:inetOrgPerson].should include( mixin )
153
+ end
154
+
155
+ they "re-register bases that have already been declared when declaring a " +
156
+ "new model class" do
157
+ class MyModel < Treequel::Model; end
158
+
159
+ mixin = Module.new do
160
+ extend Treequel::Model::ObjectClass
161
+ model_bases 'ou=people,dc=acme,dc=com', 'ou=notpeople,dc=acme,dc=com'
162
+ model_class MyModel
163
+ end
164
+
165
+ Treequel::Model.base_registry['ou=people,dc=acme,dc=com'].should_not include( mixin )
166
+ MyModel.base_registry['ou=people,dc=acme,dc=com'].should include( mixin )
167
+ end
168
+
169
+ end
170
+
171
+ describe "module that has one required objectClass declared" do
172
+
173
+ before( :each ) do
174
+ @mixin = Module.new do
175
+ extend Treequel::Model::ObjectClass
176
+ model_objectclasses :inetOrgPerson
177
+ end
178
+ end
179
+
180
+ after( :each ) do
181
+ Treequel::Model.objectclass_registry.clear
182
+ end
183
+
184
+
185
+ it "is returned as one of the mixins for entries with only that objectClass" do
186
+ Treequel::Model.mixins_for_objectclasses( :inetOrgPerson ).
187
+ should include( @mixin )
188
+ end
189
+
190
+ it "is not returned in the list of mixins to apply to an entry without that objectClass" do
191
+ Treequel::Model.mixins_for_objectclasses( :device ).
192
+ should_not include( @mixin )
193
+ end
194
+
195
+ it "can set up a search for applicable entries given a Treequel::Directory to " +
196
+ "search" do
197
+ directory = mock( "Treequel directory", :registered_controls => [] )
198
+ directory.should_receive( :base_dn ).and_return( TEST_BASE_DN )
199
+
200
+ result = @mixin.search( directory )
201
+
202
+ result.should be_a( Treequel::Branchset )
203
+ result.base_dn.should == TEST_BASE_DN
204
+ result.filter.to_s.should == '(objectClass=inetOrgPerson)'
205
+ end
206
+
207
+ end
208
+
209
+ describe "module that has more than one required objectClass declared" do
210
+
211
+ before( :each ) do
212
+ @mixin = Module.new do
213
+ extend Treequel::Model::ObjectClass
214
+ model_objectclasses :device, :ipHost
215
+ end
216
+ end
217
+
218
+ after( :each ) do
219
+ Treequel::Model.objectclass_registry.clear
220
+ end
221
+
222
+
223
+ it "is returned as one of the mixins to apply to entries with all of its required " +
224
+ "objectClasses" do
225
+ Treequel::Model.mixins_for_objectclasses( :device, :ipHost ).
226
+ should include( @mixin )
227
+ end
228
+
229
+ it "is not returned in the list of mixins to apply to an entry with only one of its " +
230
+ "objectClasses" do
231
+ Treequel::Model.mixins_for_objectclasses( :device ).
232
+ should_not include( @mixin )
233
+ end
234
+
235
+ it "can set up a search for applicable entries given a Treequel::Directory to " +
236
+ "search" do
237
+ directory = mock( "Treequel directory", :registered_controls => [] )
238
+ directory.should_receive( :base_dn ).and_return( TEST_BASE_DN )
239
+
240
+ result = @mixin.search( directory )
241
+
242
+ result.should be_a( Treequel::Branchset )
243
+ result.base_dn.should == TEST_BASE_DN
244
+ result.filter.to_s.should == '(&(objectClass=device)(objectClass=ipHost))'
245
+ end
246
+
247
+ end
248
+
249
+ describe "module that has one base declared" do
250
+ before( :each ) do
251
+ @mixin = Module.new do
252
+ extend Treequel::Model::ObjectClass
253
+ model_bases TEST_PEOPLE_DN
254
+ end
255
+ end
256
+
257
+ after( :each ) do
258
+ Treequel::Model.base_registry.clear
259
+ end
260
+
261
+
262
+ it "is returned as one of the mixins to apply to an entry that is a child of its base" do
263
+ Treequel::Model.mixins_for_dn( TEST_PERSON_DN ).
264
+ should include( @mixin )
265
+ end
266
+
267
+ it "is not returned as one of the mixins to apply to an entry that is not a child of " +
268
+ "its base" do
269
+ Treequel::Model.mixins_for_dn( TEST_ROOM_DN ).
270
+ should_not include( @mixin )
271
+ end
272
+
273
+ it "can set up a search for applicable entries given a Treequel::Directory to " +
274
+ "search" do
275
+ directory = stub( "Treequel directory", :registered_controls => [] )
276
+
277
+ result = @mixin.search( directory )
278
+
279
+ result.should be_a( Treequel::Branchset )
280
+ result.base_dn.should == TEST_PEOPLE_DN
281
+ result.filter.to_s.should == '(objectClass=*)'
282
+ end
283
+
284
+ end
285
+
286
+ describe "module that has more than one base declared" do
287
+ before( :each ) do
288
+ @mixin = Module.new do
289
+ extend Treequel::Model::ObjectClass
290
+ model_bases TEST_HOSTS_DN,
291
+ TEST_SUBHOSTS_DN
292
+ end
293
+ end
294
+
295
+ after( :each ) do
296
+ Treequel::Model.base_registry.clear
297
+ end
298
+
299
+
300
+ it "is returned as one of the mixins to apply to an entry that is a child of one of " +
301
+ "its bases" do
302
+ Treequel::Model.mixins_for_dn( TEST_SUBHOST_DN ).
303
+ should include( @mixin )
304
+ end
305
+
306
+ it "is not returned as one of the mixins to apply to an entry that is not a child of " +
307
+ "its base" do
308
+ Treequel::Model.mixins_for_dn( TEST_PERSON_DN ).
309
+ should_not include( @mixin )
310
+ end
311
+
312
+ it "can set up a search for applicable entries given a Treequel::Directory to " +
313
+ "search" do
314
+ directory = stub( "Treequel directory", :registered_controls => [] )
315
+
316
+ result = @mixin.search( directory )
317
+
318
+ result.should be_a( Treequel::BranchCollection )
319
+ result.base_dns.should have( 2 ).members
320
+ result.base_dns.should include( TEST_HOSTS_DN, TEST_SUBHOSTS_DN )
321
+ result.branchsets.all? {|brset| brset.filter_string == '(objectClass=*)' }.
322
+ should be_true()
323
+ end
324
+
325
+ end
326
+
327
+ end
328
+
329
+
330
+ # vim: set nosta noet ts=4 sw=4: