treequel 1.0.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 +354 -0
- data/LICENSE +27 -0
- data/README +66 -0
- data/Rakefile +345 -0
- data/Rakefile.local +43 -0
- data/bin/treeirb +14 -0
- data/bin/treequel +229 -0
- data/examples/company-directory.rb +112 -0
- data/examples/ldap-monitor.rb +143 -0
- data/examples/ldap-monitor/public/css/master.css +328 -0
- data/examples/ldap-monitor/public/images/card_small.png +0 -0
- data/examples/ldap-monitor/public/images/chain_small.png +0 -0
- data/examples/ldap-monitor/public/images/globe_small.png +0 -0
- data/examples/ldap-monitor/public/images/globe_small_green.png +0 -0
- data/examples/ldap-monitor/public/images/plug.png +0 -0
- data/examples/ldap-monitor/public/images/shadows/large-30-down.png +0 -0
- data/examples/ldap-monitor/public/images/tick.png +0 -0
- data/examples/ldap-monitor/public/images/tick_circle.png +0 -0
- data/examples/ldap-monitor/public/images/treequel-favicon.png +0 -0
- data/examples/ldap-monitor/views/backends.erb +41 -0
- data/examples/ldap-monitor/views/connections.erb +74 -0
- data/examples/ldap-monitor/views/databases.erb +39 -0
- data/examples/ldap-monitor/views/dump_subsystem.erb +14 -0
- data/examples/ldap-monitor/views/index.erb +14 -0
- data/examples/ldap-monitor/views/layout.erb +35 -0
- data/examples/ldap-monitor/views/listeners.erb +30 -0
- data/examples/ldap_state.rb +62 -0
- data/lib/treequel.rb +145 -0
- data/lib/treequel/branch.rb +589 -0
- data/lib/treequel/branchcollection.rb +204 -0
- data/lib/treequel/branchset.rb +360 -0
- data/lib/treequel/constants.rb +604 -0
- data/lib/treequel/directory.rb +541 -0
- data/lib/treequel/exceptions.rb +32 -0
- data/lib/treequel/filter.rb +704 -0
- data/lib/treequel/mixins.rb +325 -0
- data/lib/treequel/schema.rb +245 -0
- data/lib/treequel/schema/attributetype.rb +252 -0
- data/lib/treequel/schema/ldapsyntax.rb +96 -0
- data/lib/treequel/schema/matchingrule.rb +124 -0
- data/lib/treequel/schema/matchingruleuse.rb +124 -0
- data/lib/treequel/schema/objectclass.rb +289 -0
- data/lib/treequel/sequel_integration.rb +26 -0
- data/lib/treequel/utils.rb +169 -0
- data/rake/191_compat.rb +26 -0
- data/rake/dependencies.rb +76 -0
- data/rake/helpers.rb +434 -0
- data/rake/hg.rb +261 -0
- data/rake/manual.rb +782 -0
- data/rake/packaging.rb +135 -0
- data/rake/publishing.rb +318 -0
- data/rake/rdoc.rb +30 -0
- data/rake/style.rb +62 -0
- data/rake/svn.rb +668 -0
- data/rake/testing.rb +187 -0
- data/rake/verifytask.rb +64 -0
- data/rake/win32.rb +190 -0
- data/spec/lib/constants.rb +93 -0
- data/spec/lib/helpers.rb +100 -0
- data/spec/treequel/branch_spec.rb +569 -0
- data/spec/treequel/branchcollection_spec.rb +213 -0
- data/spec/treequel/branchset_spec.rb +376 -0
- data/spec/treequel/directory_spec.rb +487 -0
- data/spec/treequel/filter_spec.rb +482 -0
- data/spec/treequel/mixins_spec.rb +330 -0
- data/spec/treequel/schema/attributetype_spec.rb +237 -0
- data/spec/treequel/schema/ldapsyntax_spec.rb +83 -0
- data/spec/treequel/schema/matchingrule_spec.rb +158 -0
- data/spec/treequel/schema/matchingruleuse_spec.rb +137 -0
- data/spec/treequel/schema/objectclass_spec.rb +262 -0
- data/spec/treequel/schema_spec.rb +118 -0
- data/spec/treequel/utils_spec.rb +49 -0
- data/spec/treequel_spec.rb +179 -0
- metadata +169 -0
@@ -0,0 +1,482 @@
|
|
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( libdir ) unless $LOAD_PATH.include?( libdir )
|
10
|
+
}
|
11
|
+
|
12
|
+
require 'rubygems'
|
13
|
+
gem 'rspec', '>= 1.2.6'
|
14
|
+
|
15
|
+
require 'spec'
|
16
|
+
require 'spec/lib/constants'
|
17
|
+
require 'spec/lib/helpers'
|
18
|
+
|
19
|
+
require 'treequel/filter'
|
20
|
+
|
21
|
+
|
22
|
+
include Treequel::TestConstants
|
23
|
+
include Treequel::Constants
|
24
|
+
|
25
|
+
#####################################################################
|
26
|
+
### C O N T E X T S
|
27
|
+
#####################################################################
|
28
|
+
|
29
|
+
describe Treequel::Filter do
|
30
|
+
include Treequel::SpecHelpers
|
31
|
+
|
32
|
+
before( :all ) do
|
33
|
+
setup_logging( :fatal )
|
34
|
+
end
|
35
|
+
|
36
|
+
after( :all ) do
|
37
|
+
reset_logging()
|
38
|
+
end
|
39
|
+
|
40
|
+
|
41
|
+
it "knows that it is promiscuous (will match any entry) if its component is promiscuous" do
|
42
|
+
Treequel::Filter.new.should be_promiscuous()
|
43
|
+
end
|
44
|
+
|
45
|
+
it "knows that it isn't promiscuous if its component isn't promiscuous" do
|
46
|
+
Treequel::Filter.new( :uid, 'batgirl' ).should_not be_promiscuous()
|
47
|
+
end
|
48
|
+
|
49
|
+
|
50
|
+
it "defaults to selecting everything" do
|
51
|
+
Treequel::Filter.new.to_s.should == '(objectClass=*)'
|
52
|
+
end
|
53
|
+
|
54
|
+
it "can be created from a string literal" do
|
55
|
+
Treequel::Filter.new( '(uid=bargrab)' ).to_s.should == '(uid=bargrab)'
|
56
|
+
end
|
57
|
+
|
58
|
+
it "wraps string literal instances in parens if it requires them" do
|
59
|
+
Treequel::Filter.new( 'uid=bargrab' ).to_s.should == '(uid=bargrab)'
|
60
|
+
end
|
61
|
+
|
62
|
+
it "parses a single Symbol argument as a presence filter" do
|
63
|
+
Treequel::Filter.new( :uid ).to_s.should == '(uid=*)'
|
64
|
+
end
|
65
|
+
|
66
|
+
it "parses a single-element Array with a Symbol as a presence filter" do
|
67
|
+
Treequel::Filter.new( [:uid] ).to_s.should == '(uid=*)'
|
68
|
+
end
|
69
|
+
|
70
|
+
it "parses a Symbol+value pair as a simple item equal filter" do
|
71
|
+
Treequel::Filter.new( :uid, 'bigthung' ).to_s.should == '(uid=bigthung)'
|
72
|
+
end
|
73
|
+
|
74
|
+
it "parses a single-item Symbol+value hash as a simple item equal filter" do
|
75
|
+
Treequel::Filter.new({ :uidNumber => 3036 }).to_s.should == '(uidNumber=3036)'
|
76
|
+
end
|
77
|
+
|
78
|
+
it "parses a Symbol+value pair in an Array as a simple item equal filter" do
|
79
|
+
Treequel::Filter.new( [:uid, 'bigthung'] ).to_s.should == '(uid=bigthung)'
|
80
|
+
end
|
81
|
+
|
82
|
+
it "parses a multi-value Hash as an ANDed collection of simple item equals filters" do
|
83
|
+
expr = Treequel::Filter.new( :givenName => 'Michael', :sn => 'Granger' )
|
84
|
+
gnpat = Regexp.quote( '(givenName=Michael)' )
|
85
|
+
snpat = Regexp.quote( '(sn=Granger)' )
|
86
|
+
|
87
|
+
expr.to_s.should =~ /\(&(#{gnpat}#{snpat}|#{snpat}#{gnpat})\)/i
|
88
|
+
end
|
89
|
+
|
90
|
+
it "parses an AND expression with only a single clause" do
|
91
|
+
Treequel::Filter.new( [:&, [:uid, 'kunglung']] ).to_s.should == '(&(uid=kunglung))'
|
92
|
+
end
|
93
|
+
|
94
|
+
it "parses an AND expression with multiple clauses" do
|
95
|
+
Treequel::Filter.new( [:and, [:uid, 'kunglung'], [:name, 'chunger']] ).to_s.
|
96
|
+
should == '(&(uid=kunglung)(name=chunger))'
|
97
|
+
end
|
98
|
+
|
99
|
+
it "parses an OR expression with only a single clause" do
|
100
|
+
Treequel::Filter.new( [:|, [:uid, 'kunglung']] ).to_s.should == '(|(uid=kunglung))'
|
101
|
+
end
|
102
|
+
|
103
|
+
it "parses an OR expression with multiple clauses" do
|
104
|
+
Treequel::Filter.new( [:or, [:uid, 'kunglung'], [:name, 'chunger']] ).to_s.
|
105
|
+
should == '(|(uid=kunglung)(name=chunger))'
|
106
|
+
end
|
107
|
+
|
108
|
+
it "parses an OR expression with String literal clauses" do
|
109
|
+
Treequel::Filter.new( :or, ['cn~=facet', 'cn=structure', 'cn=envision'] ).to_s.
|
110
|
+
should == '(|(cn~=facet)(cn=structure)(cn=envision))'
|
111
|
+
end
|
112
|
+
|
113
|
+
it "infers the OR-hash form if the expression is Symbol => Array" do
|
114
|
+
Treequel::Filter.new( :uid => %w[lar bin fon guh] ).to_s.
|
115
|
+
should == '(|(uid=lar)(uid=bin)(uid=fon)(uid=guh))'
|
116
|
+
end
|
117
|
+
|
118
|
+
it "correctly includes OR subfilters in a Hash if the value is an Array" do
|
119
|
+
fstr = Treequel::Filter.new( :objectClass => 'inetOrgPerson', :uid => %w[lar bin fon guh] ).to_s
|
120
|
+
|
121
|
+
fstr.should include('(|(uid=lar)(uid=bin)(uid=fon)(uid=guh))')
|
122
|
+
fstr.should include('(objectClass=inetOrgPerson)')
|
123
|
+
fstr.should =~ /^\(&/
|
124
|
+
end
|
125
|
+
|
126
|
+
it "parses a NOT expression with only a single clause" do
|
127
|
+
Treequel::Filter.new( [:'!', [:uid, 'kunglung']] ).to_s.should == '(!(uid=kunglung))'
|
128
|
+
end
|
129
|
+
|
130
|
+
it "parses a Range item as a boolean ANDed expression" do
|
131
|
+
filter = Treequel::Filter.new( :uid, 200..1000 ).to_s.should == '(&(uid>=200)(uid<=1000))'
|
132
|
+
end
|
133
|
+
|
134
|
+
it "parses a exclusive Range correctly" do
|
135
|
+
filter = Treequel::Filter.new( :uid, 200...1000 ).to_s.should == '(&(uid>=200)(uid<=999))'
|
136
|
+
end
|
137
|
+
|
138
|
+
it "parses a Range item with non-numeric components" do
|
139
|
+
filter = Treequel::Filter.new( :lastName => 'Dale'..'Darby' ).to_s.
|
140
|
+
should == '(&(lastName>=Dale)(lastName<=Darby))'
|
141
|
+
end
|
142
|
+
|
143
|
+
it "raises an exception with a NOT expression that contains more than one clause" do
|
144
|
+
expect {
|
145
|
+
Treequel::Filter.new( :not, [:uid, 'kunglung'], [:name, 'chunger'] )
|
146
|
+
}.to raise_error( ArgumentError )
|
147
|
+
end
|
148
|
+
|
149
|
+
|
150
|
+
it "parses a Substring item from a filter that includes an asterisk" do
|
151
|
+
filter = Treequel::Filter.new( :portrait, "\\ff\\d8\\ff\\e0*" )
|
152
|
+
filter.component.class.should == Treequel::Filter::SubstringItemComponent
|
153
|
+
end
|
154
|
+
|
155
|
+
it "parses a Present item from a filter that is only an asterisk" do
|
156
|
+
filter = Treequel::Filter.new( :disabled, "*" )
|
157
|
+
filter.component.class.should == Treequel::Filter::PresentItemComponent
|
158
|
+
end
|
159
|
+
|
160
|
+
it "raises an error when an extensible item filter is given" do
|
161
|
+
expect {
|
162
|
+
Treequel::Filter.new( :'cn:1.2.3.4.5:', 'Fred Flintstone' )
|
163
|
+
}.to raise_error( NotImplementedError, /extensible.*supported/i )
|
164
|
+
end
|
165
|
+
|
166
|
+
|
167
|
+
it "parses a complex nested expression" do
|
168
|
+
Treequel::Filter.new(
|
169
|
+
[:and,
|
170
|
+
[:or,
|
171
|
+
[:and, [:chungability,'fantagulous'], [:l, 'the moon']],
|
172
|
+
[:chungability, '*grunt*'],
|
173
|
+
[:hunker]],
|
174
|
+
[:not, [:description, 'mediocre']] ]
|
175
|
+
).to_s.should == '(&(|(&(chungability=fantagulous)(l=the moon))' +
|
176
|
+
'(chungability=*grunt*)(hunker=*))(!(description=mediocre)))'
|
177
|
+
end
|
178
|
+
|
179
|
+
|
180
|
+
### Operators
|
181
|
+
describe "operator methods" do
|
182
|
+
|
183
|
+
before( :each ) do
|
184
|
+
@filter1 = Treequel::Filter.new( :uid, :buckrogers )
|
185
|
+
@filter2 = Treequel::Filter.new( :l, :mars )
|
186
|
+
end
|
187
|
+
|
188
|
+
it "compares as equal with another filter if their components are equal" do
|
189
|
+
otherfilter = mock( "other filter" )
|
190
|
+
otherfilter.should_receive( :component ).and_return( :componentobj )
|
191
|
+
@filter1.component = :componentobj
|
192
|
+
|
193
|
+
@filter1.should == otherfilter
|
194
|
+
end
|
195
|
+
|
196
|
+
it "creates a new AND filter out of two filters that are added together" do
|
197
|
+
result = @filter1 + @filter2
|
198
|
+
result.should be_a( Treequel::Filter )
|
199
|
+
end
|
200
|
+
|
201
|
+
it "creates a new AND filter out of two filters that are bitwise-ANDed together" do
|
202
|
+
result = @filter1 & @filter2
|
203
|
+
result.should be_a( Treequel::Filter )
|
204
|
+
end
|
205
|
+
|
206
|
+
it "doesn't include the left operand in an AND filter if it is promiscuous" do
|
207
|
+
pfilter = Treequel::Filter.new
|
208
|
+
result = pfilter & @filter2
|
209
|
+
|
210
|
+
result.should == @filter2
|
211
|
+
end
|
212
|
+
|
213
|
+
it "doesn't include the right operand in an AND filter if it is promiscuous" do
|
214
|
+
pfilter = Treequel::Filter.new
|
215
|
+
result = @filter1 & pfilter
|
216
|
+
|
217
|
+
result.should == @filter1
|
218
|
+
end
|
219
|
+
|
220
|
+
end
|
221
|
+
|
222
|
+
describe "components:" do
|
223
|
+
|
224
|
+
before( :each ) do
|
225
|
+
@filter1 = stub( "filter1", :to_s => '(filter1)' )
|
226
|
+
@filter2 = stub( "filter2", :to_s => '(filter2)' )
|
227
|
+
end
|
228
|
+
|
229
|
+
|
230
|
+
describe Treequel::Filter::FilterList do
|
231
|
+
it "stringifies by joining its stringified members" do
|
232
|
+
Treequel::Filter::FilterList.new( @filter1, @filter2 ).to_s.
|
233
|
+
should == '(filter1)(filter2)'
|
234
|
+
end
|
235
|
+
end
|
236
|
+
|
237
|
+
describe Treequel::Filter::Component do
|
238
|
+
it "is an abstract class" do
|
239
|
+
expect {
|
240
|
+
Treequel::Filter::Component.new
|
241
|
+
}.to raise_error( NoMethodError )
|
242
|
+
end
|
243
|
+
|
244
|
+
it "is non-promiscuous by default" do
|
245
|
+
Class.new( Treequel::Filter::Component ).new.should_not be_promiscuous()
|
246
|
+
end
|
247
|
+
|
248
|
+
end
|
249
|
+
|
250
|
+
|
251
|
+
describe Treequel::Filter::SimpleItemComponent do
|
252
|
+
before( :each ) do
|
253
|
+
@component = Treequel::Filter::SimpleItemComponent.new( :uid, 'schlange' )
|
254
|
+
end
|
255
|
+
|
256
|
+
it "can parse a component object from a string literal" do
|
257
|
+
comp = Treequel::Filter::SimpleItemComponent.parse_from_string( 'description=screamer' )
|
258
|
+
comp.filtertype.should == :equal
|
259
|
+
comp.filtertype_op.should == '='
|
260
|
+
comp.attribute.should == 'description'
|
261
|
+
comp.value.should == 'screamer'
|
262
|
+
end
|
263
|
+
|
264
|
+
it "raises an ExpressionError if it can't parse a string literal" do
|
265
|
+
expect { Treequel::Filter::SimpleItemComponent.parse_from_string( 'whatev!' ) }.
|
266
|
+
to raise_error( Treequel::ExpressionError, /unable to parse/i )
|
267
|
+
end
|
268
|
+
|
269
|
+
it "uses the 'equal' operator if none is specified" do
|
270
|
+
@component.filtertype.should == :equal
|
271
|
+
end
|
272
|
+
|
273
|
+
it "knows what the appropriate operator is for its filtertype" do
|
274
|
+
@component.filtertype_op.should == '='
|
275
|
+
end
|
276
|
+
|
277
|
+
it "knows what the appropriate operator is for its filtertype even if it's set to a string" do
|
278
|
+
@component.filtertype = 'greater'
|
279
|
+
@component.filtertype_op.should == '>='
|
280
|
+
end
|
281
|
+
|
282
|
+
it "stringifies as <attribute><operator><value>" do
|
283
|
+
@component.to_s.should == 'uid=schlange'
|
284
|
+
end
|
285
|
+
|
286
|
+
it "uses the '~=' operator if its filtertype is 'approx'" do
|
287
|
+
@component.filtertype = :approx
|
288
|
+
@component.filtertype_op.should == '~='
|
289
|
+
end
|
290
|
+
|
291
|
+
it "uses the '>=' operator if its filtertype is 'greater'" do
|
292
|
+
@component.filtertype = :greater
|
293
|
+
@component.filtertype_op.should == '>='
|
294
|
+
end
|
295
|
+
|
296
|
+
it "uses the '<=' operator if its filtertype is 'less'" do
|
297
|
+
@component.filtertype = :less
|
298
|
+
@component.filtertype_op.should == '<='
|
299
|
+
end
|
300
|
+
|
301
|
+
it "raises an error if it's created with an unknown filtertype" do
|
302
|
+
expect {
|
303
|
+
Treequel::Filter::SimpleItemComponent.new( :uid, 'schlange', :fork )
|
304
|
+
}.to raise_error( Treequel::ExpressionError, /invalid/i )
|
305
|
+
|
306
|
+
end
|
307
|
+
|
308
|
+
end
|
309
|
+
|
310
|
+
|
311
|
+
describe Treequel::Filter::SubstringItemComponent do
|
312
|
+
|
313
|
+
before( :each ) do
|
314
|
+
@component = Treequel::Filter::SubstringItemComponent.new( :description, '*basecamp*' )
|
315
|
+
end
|
316
|
+
|
317
|
+
|
318
|
+
it "can parse a component object from a string literal" do
|
319
|
+
comp = Treequel::Filter::SubstringItemComponent.parse_from_string( 'description=*basecamp*' )
|
320
|
+
comp.attribute.should == 'description'
|
321
|
+
comp.options.should == ''
|
322
|
+
comp.pattern.should == '*basecamp*'
|
323
|
+
end
|
324
|
+
|
325
|
+
it "can parse a component object from a string literal with attribute options" do
|
326
|
+
jpeg_portraits = Treequel::Filter::SubstringItemComponent.
|
327
|
+
parse_from_string( "portrait;binary=\\xff\\xd8\\xff\\xe0*" )
|
328
|
+
jpeg_portraits.attribute.should == 'portrait'
|
329
|
+
jpeg_portraits.options.should == ';binary'
|
330
|
+
jpeg_portraits.pattern.should == "\\xff\\xd8\\xff\\xe0*"
|
331
|
+
end
|
332
|
+
|
333
|
+
it "raises an ExpressionError if it can't parse a string literal" do
|
334
|
+
expect { Treequel::Filter::SubstringItemComponent.parse_from_string( 'whatev>=1' ) }.
|
335
|
+
to raise_error( Treequel::ExpressionError, /unable to parse/i )
|
336
|
+
end
|
337
|
+
|
338
|
+
end
|
339
|
+
|
340
|
+
|
341
|
+
describe Treequel::Filter::AndComponent do
|
342
|
+
it "stringifies as its filters ANDed together" do
|
343
|
+
Treequel::Filter::AndComponent.new( @filter1, @filter2 ).to_s.
|
344
|
+
should == '&(filter1)(filter2)'
|
345
|
+
end
|
346
|
+
|
347
|
+
it "allows a single filter" do
|
348
|
+
Treequel::Filter::AndComponent.new( @filter1 ).to_s.
|
349
|
+
should == '&(filter1)'
|
350
|
+
end
|
351
|
+
end
|
352
|
+
|
353
|
+
describe Treequel::Filter::OrComponent do
|
354
|
+
it "stringifies as its filters ORed together" do
|
355
|
+
Treequel::Filter::OrComponent.new( @filter1, @filter2 ).to_s.
|
356
|
+
should == '|(filter1)(filter2)'
|
357
|
+
end
|
358
|
+
|
359
|
+
it "allows a single filter" do
|
360
|
+
Treequel::Filter::OrComponent.new( @filter1 ).to_s.
|
361
|
+
should == '|(filter1)'
|
362
|
+
end
|
363
|
+
|
364
|
+
end
|
365
|
+
|
366
|
+
describe Treequel::Filter::NotComponent do
|
367
|
+
it "stringifies as the negation of its filter" do
|
368
|
+
Treequel::Filter::NotComponent.new( @filter1 ).to_s.
|
369
|
+
should == '!(filter1)'
|
370
|
+
end
|
371
|
+
|
372
|
+
it "can't be created with multiple filters" do
|
373
|
+
expect {
|
374
|
+
Treequel::Filter::NotComponent.new( @filter1, @filter2 )
|
375
|
+
}.to raise_error( ArgumentError, /2 for 1/i )
|
376
|
+
end
|
377
|
+
end
|
378
|
+
end
|
379
|
+
|
380
|
+
describe "support for Sequel expressions" do
|
381
|
+
|
382
|
+
before( :each ) do
|
383
|
+
pending "requires the 'sequel' library" unless Sequel.const_defined?( :Model )
|
384
|
+
end
|
385
|
+
|
386
|
+
it "supports the boolean expression syntax" do
|
387
|
+
pending( "inequality operators don't work under 1.9.1" ) if
|
388
|
+
vvec( RUBY_VERSION ) > vvec( '1.8.7' )
|
389
|
+
filter = Treequel::Filter.new( :uid >= 2000 )
|
390
|
+
filter.should be_a( Treequel::Filter )
|
391
|
+
filter.to_s.should == '(uid>=2000)'
|
392
|
+
end
|
393
|
+
|
394
|
+
it "supports Sequel expressions in ANDed subexpressions" do
|
395
|
+
pending( "inequality operators don't work under 1.9.1" ) if
|
396
|
+
vvec( RUBY_VERSION ) > vvec( '1.8.7' )
|
397
|
+
filter = Treequel::Filter.new( :and, [:uid >= 1024], [:uid <= 65535] )
|
398
|
+
filter.should be_a( Treequel::Filter )
|
399
|
+
filter.to_s.should == '(&(uid>=1024)(uid<=65535))'
|
400
|
+
end
|
401
|
+
|
402
|
+
it "advises user to use '>=' instead of '>' in expressions" do
|
403
|
+
pending( "inequality operators don't work under 1.9.1" ) if
|
404
|
+
vvec( RUBY_VERSION ) > vvec( '1.8.7' )
|
405
|
+
expect {
|
406
|
+
Treequel::Filter.new( :uid > 1024 )
|
407
|
+
}.to raise_error( Treequel::ExpressionError, /greater-than-or-equal/i )
|
408
|
+
end
|
409
|
+
|
410
|
+
it "advises user to use '<=' instead of '<' in expressions" do
|
411
|
+
pending( "inequality operators don't work under 1.9.1" ) if
|
412
|
+
vvec( RUBY_VERSION ) > vvec( '1.8.7' )
|
413
|
+
expect {
|
414
|
+
Treequel::Filter.new( :activated < Time.now )
|
415
|
+
}.to raise_error( Treequel::ExpressionError, /less-than-or-equal/i )
|
416
|
+
end
|
417
|
+
|
418
|
+
it "supports the 'LIKE' expression syntax with a single string argument" do
|
419
|
+
filter = Treequel::Filter.new( :cn.like('mar*n') )
|
420
|
+
filter.should be_a( Treequel::Filter )
|
421
|
+
filter.to_s.should == '(cn=mar*n)'
|
422
|
+
end
|
423
|
+
|
424
|
+
it "treats a LIKE expression with no asterisks as an 'approx' filter" do
|
425
|
+
filter = Treequel::Filter.new( :cn.like('maylin') )
|
426
|
+
filter.should be_a( Treequel::Filter )
|
427
|
+
filter.to_s.should == '(cn~=maylin)'
|
428
|
+
end
|
429
|
+
|
430
|
+
it "supports the 'LIKE' expression syntax with multiple string arguments" do
|
431
|
+
filter = Treequel::Filter.new( :cn.like('may*', 'mah*') )
|
432
|
+
filter.should be_a( Treequel::Filter )
|
433
|
+
filter.to_s.should == '(|(cn=may*)(cn=mah*))'
|
434
|
+
end
|
435
|
+
|
436
|
+
it "raises an exception when given a 'LIKE' expression with a regex argument" do
|
437
|
+
expect {
|
438
|
+
Treequel::Filter.new( :cn.like(/^ma.*/) )
|
439
|
+
}.to raise_error( Treequel::ExpressionError, /regex/i )
|
440
|
+
end
|
441
|
+
|
442
|
+
it "raises an exception when given a 'LIKE' expression with a regex argument with flags" do
|
443
|
+
expect {
|
444
|
+
Treequel::Filter.new( :cn.like(/^ma.*/i) )
|
445
|
+
}.to raise_error( Treequel::ExpressionError, /regex/i )
|
446
|
+
end
|
447
|
+
|
448
|
+
it "raises an exception when given a 'LIKE' expression with a mix of regex and string " +
|
449
|
+
"arguments" do
|
450
|
+
expect {
|
451
|
+
Treequel::Filter.new( :cn.like('maylin', /^mi.*/i) )
|
452
|
+
}.to raise_error( Treequel::ExpressionError, /regex/i )
|
453
|
+
end
|
454
|
+
|
455
|
+
it "supports negation of a 'exists' expression via the Sequel ~ syntax" do
|
456
|
+
filter = Treequel::Filter.new( ~:cn )
|
457
|
+
filter.should be_a( Treequel::Filter )
|
458
|
+
filter.to_s.should == '(!(cn=*))'
|
459
|
+
end
|
460
|
+
|
461
|
+
it "supports negation of a simple equality expression via the Sequel ~ syntax" do
|
462
|
+
filter = Treequel::Filter.new( ~{ :l => 'anoos' } )
|
463
|
+
filter.should be_a( Treequel::Filter )
|
464
|
+
filter.to_s.should == '(!(l=anoos))'
|
465
|
+
end
|
466
|
+
|
467
|
+
it "supports negation of an approximate-match expression via the Sequel ~ syntax" do
|
468
|
+
filter = Treequel::Filter.new( ~:cn.like('maylin') )
|
469
|
+
filter.should be_a( Treequel::Filter )
|
470
|
+
filter.to_s.should == '(!(cn~=maylin))'
|
471
|
+
end
|
472
|
+
|
473
|
+
it "supports negation of a matching expression via the Sequel ~ syntax" do
|
474
|
+
filter = Treequel::Filter.new( ~:cn.like('may*i*') )
|
475
|
+
filter.should be_a( Treequel::Filter )
|
476
|
+
filter.to_s.should == '(!(cn=may*i*))'
|
477
|
+
end
|
478
|
+
end
|
479
|
+
end
|
480
|
+
|
481
|
+
|
482
|
+
# vim: set nosta noet ts=4 sw=4:
|