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