1
##############################################################################
3
# Copyright (c) 2002 Zope Corporation and Contributors.
6
# This software is subject to the provisions of the Zope Public License,
7
# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
8
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
9
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
10
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
11
# FOR A PARTICULAR PURPOSE.
13
##############################################################################
17
class _KeywordIndexTestsBase:
19
def _getTargetClass(self):
20
from zope.index.keyword.index import KeywordIndex
23
def _populate(self, index):
25
index.index_doc(1, ('zope', 'CMF', 'Zope3'))
26
index.index_doc(2, ('the', 'quick', 'brown', 'FOX'))
27
index.index_doc(3, ('Zope',))
28
index.index_doc(4, ())
29
index.index_doc(5, ('cmf',))
31
_populated_doc_count = 4
32
_populated_word_count = 9
34
def test_normalize(self):
35
index = self._makeOne()
36
self.assertEqual(index.normalize(['Foo']), ['Foo'])
38
def test_simplesearch(self):
39
index = self._makeOne()
41
self._search(index, [''], self.IFSet())
42
self._search(index, 'cmf', self.IFSet([5]))
43
self._search(index, ['cmf'], self.IFSet([5]))
44
self._search(index, ['Zope'], self.IFSet([3]))
45
self._search(index, ['Zope3'], self.IFSet([1]))
46
self._search(index, ['foo'], self.IFSet())
48
def test_search_and(self):
49
index = self._makeOne()
51
self._search_and(index, ('CMF', 'Zope3'), self.IFSet([1]))
52
self._search_and(index, ('CMF', 'zope'), self.IFSet([1]))
53
self._search_and(index, ('cmf', 'zope4'), self.IFSet())
54
self._search_and(index, ('quick', 'FOX'), self.IFSet([2]))
56
def test_search_or(self):
57
index = self._makeOne()
59
self._search_or(index, ('cmf', 'Zope3'), self.IFSet([1, 5]))
60
self._search_or(index, ('cmf', 'zope'), self.IFSet([1, 5]))
61
self._search_or(index, ('cmf', 'zope4'), self.IFSet([5]))
62
self._search_or(index, ('zope', 'Zope'), self.IFSet([1,3]))
65
index = self._makeOne()
67
self._apply(index, ('CMF', 'Zope3'), self.IFSet([1]))
68
self._apply(index, ('CMF', 'zope'), self.IFSet([1]))
69
self._apply(index, ('cmf', 'zope4'), self.IFSet())
70
self._apply(index, ('quick', 'FOX'), self.IFSet([2]))
72
def test_apply_and(self):
73
index = self._makeOne()
75
self._apply_and(index, ('CMF', 'Zope3'), self.IFSet([1]))
76
self._apply_and(index, ('CMF', 'zope'), self.IFSet([1]))
77
self._apply_and(index, ('cmf', 'zope4'), self.IFSet())
78
self._apply_and(index, ('quick', 'FOX'), self.IFSet([2]))
80
def test_apply_or(self):
81
index = self._makeOne()
83
self._apply_or(index, ('cmf', 'Zope3'), self.IFSet([1, 5]))
84
self._apply_or(index, ('cmf', 'zope'), self.IFSet([1, 5]))
85
self._apply_or(index, ('cmf', 'zope4'), self.IFSet([5]))
86
self._apply_or(index, ('zope', 'Zope'), self.IFSet([1,3]))
88
class CaseInsensitiveKeywordIndexTestsBase:
90
def _getTargetClass(self):
91
from zope.index.keyword.index import CaseInsensitiveKeywordIndex
92
return CaseInsensitiveKeywordIndex
94
def _populate(self, index):
96
index.index_doc(1, ('zope', 'CMF', 'zope3', 'Zope3'))
97
index.index_doc(2, ('the', 'quick', 'brown', 'FOX'))
98
index.index_doc(3, ('Zope', 'zope'))
99
index.index_doc(4, ())
100
index.index_doc(5, ('cmf',))
102
_populated_doc_count = 4
103
_populated_word_count = 7
105
def test_normalize(self):
106
index = self._makeOne()
107
self.assertEqual(index.normalize(['Foo']), ['foo'])
109
def test_simplesearch(self):
110
index = self._makeOne()
111
self._populate(index)
112
self._search(index, [''], self.IFSet())
113
self._search(index, 'cmf', self.IFSet([1, 5]))
114
self._search(index, ['cmf'], self.IFSet([1, 5]))
115
self._search(index, ['zope'], self.IFSet([1, 3]))
116
self._search(index, ['zope3'], self.IFSet([1]))
117
self._search(index, ['foo'], self.IFSet())
119
def test_search_and(self):
120
index = self._makeOne()
121
self._populate(index)
122
self._search_and(index, ('cmf', 'zope3'), self.IFSet([1]))
123
self._search_and(index, ('cmf', 'zope'), self.IFSet([1]))
124
self._search_and(index, ('cmf', 'zope4'), self.IFSet())
125
self._search_and(index, ('zope', 'ZOPE'), self.IFSet([1, 3]))
127
def test_search_or(self):
128
index = self._makeOne()
129
self._populate(index)
130
self._search_or(index, ('cmf', 'zope3'), self.IFSet([1, 5]))
131
self._search_or(index, ('cmf', 'zope'), self.IFSet([1, 3, 5]))
132
self._search_or(index, ('cmf', 'zope4'), self.IFSet([1, 5]))
133
self._search_or(index, ('zope', 'ZOPE'), self.IFSet([1,3]))
135
def test_apply(self):
136
index = self._makeOne()
137
self._populate(index)
138
self._apply(index, ('cmf', 'zope3'), self.IFSet([1]))
139
self._apply(index, ('cmf', 'zope'), self.IFSet([1]))
140
self._apply(index, ('cmf', 'zope4'), self.IFSet())
141
self._apply(index, ('zope', 'ZOPE'), self.IFSet([1, 3]))
143
def test_apply_and(self):
144
index = self._makeOne()
145
self._populate(index)
146
self._apply_and(index, ('cmf', 'zope3'), self.IFSet([1]))
147
self._apply_and(index, ('cmf', 'zope'), self.IFSet([1]))
148
self._apply_and(index, ('cmf', 'zope4'), self.IFSet())
149
self._apply_and(index, ('zope', 'ZOPE'), self.IFSet([1, 3]))
151
def test_apply_or(self):
152
index = self._makeOne()
153
self._populate(index)
154
self._apply_or(index, ('cmf', 'zope3'), self.IFSet([1, 5]))
155
self._apply_or(index, ('cmf', 'zope'), self.IFSet([1, 3, 5]))
156
self._apply_or(index, ('cmf', 'zope4'), self.IFSet([1, 5]))
157
self._apply_or(index, ('zope', 'ZOPE'), self.IFSet([1,3]))
159
class _ThirtyTwoBitBase:
161
def _get_family(self):
163
return BTrees.family32
165
def IFSet(self, *args, **kw):
166
from BTrees.IFBTree import IFSet
167
return IFSet(*args, **kw)
169
class _SixtyFourBitBase:
171
def _get_family(self):
173
return BTrees.family64
175
def IFSet(self, *args, **kw):
176
from BTrees.LFBTree import LFSet
177
return LFSet(*args, **kw)
183
def _makeOne(self, family=_marker):
184
if family is _marker:
185
return self._getTargetClass()(self._get_family())
186
return self._getTargetClass()(family)
188
def _search(self, index, query, expected, mode='and'):
189
results = index.search(query, mode)
191
# results and expected are IFSets() but we can not
192
# compare them directly since __eq__() does not seem
193
# to be implemented for BTrees
194
self.assertEqual(results.keys(), expected.keys())
196
def _search_and(self, index, query, expected):
197
return self._search(index, query, expected, 'and')
199
def _search_or(self, index, query, expected):
200
return self._search(index, query, expected, 'or')
202
def _apply(self, index, query, expected, mode='and'):
203
results = index.apply(query)
204
self.assertEqual(results.keys(), expected.keys())
206
def _apply_and(self, index, query, expected):
207
results = index.apply({'operator': 'and', 'query': query})
208
self.assertEqual(results.keys(), expected.keys())
210
def _apply_or(self, index, query, expected):
211
results = index.apply({'operator': 'or', 'query': query})
212
self.assertEqual(results.keys(), expected.keys())
214
def test_class_conforms_to_IInjection(self):
215
from zope.interface.verify import verifyClass
216
from zope.index.interfaces import IInjection
217
verifyClass(IInjection, self._getTargetClass())
219
def test_instance_conforms_to_IInjection(self):
220
from zope.interface.verify import verifyObject
221
from zope.index.interfaces import IInjection
222
verifyObject(IInjection, self._makeOne())
224
def test_class_conforms_to_IIndexSearch(self):
225
from zope.interface.verify import verifyClass
226
from zope.index.interfaces import IIndexSearch
227
verifyClass(IIndexSearch, self._getTargetClass())
229
def test_instance_conforms_to_IIndexSearch(self):
230
from zope.interface.verify import verifyObject
231
from zope.index.interfaces import IIndexSearch
232
verifyObject(IIndexSearch, self._makeOne())
234
def test_class_conforms_to_IStatistics(self):
235
from zope.interface.verify import verifyClass
236
from zope.index.interfaces import IStatistics
237
verifyClass(IStatistics, self._getTargetClass())
239
def test_instance_conforms_to_IStatistics(self):
240
from zope.interface.verify import verifyObject
241
from zope.index.interfaces import IStatistics
242
verifyObject(IStatistics, self._makeOne())
244
def test_class_conforms_to_IKeywordQuerying(self):
245
from zope.interface.verify import verifyClass
246
from zope.index.keyword.interfaces import IKeywordQuerying
247
verifyClass(IKeywordQuerying, self._getTargetClass())
249
def test_instance_conforms_to_IKeywordQuerying(self):
250
from zope.interface.verify import verifyObject
251
from zope.index.keyword.interfaces import IKeywordQuerying
252
verifyObject(IKeywordQuerying, self._makeOne())
254
def test_ctor_defaults(self):
255
index = self._makeOne()
256
self.failUnless(index.family is self._get_family())
258
def test_ctor_explicit_family(self):
260
index = self._makeOne(family=BTrees.family64)
261
self.failUnless(index.family is BTrees.family64)
263
def test_empty_index(self):
264
index = self._makeOne()
265
self.assertEqual(index.documentCount(), 0)
266
self.assertEqual(index.wordCount(), 0)
267
self.failIf(index.has_doc(1))
269
def test_index_doc_string_value_raises(self):
270
index = self._makeOne()
271
self.assertRaises(TypeError, index.index_doc, 1, 'albatross')
273
def test_index_doc_single(self):
274
index = self._makeOne()
275
index.index_doc(1, ('albatross', 'cormorant'))
276
self.assertEqual(index.documentCount(), 1)
277
self.assertEqual(index.wordCount(), 2)
278
self.failUnless(index.has_doc(1))
279
self.failUnless('albatross' in index._fwd_index)
280
self.failUnless('cormorant' in index._fwd_index)
282
def test_index_doc_existing(self):
283
index = self._makeOne()
284
index.index_doc(1, ('albatross', 'cormorant'))
285
index.index_doc(1, ('buzzard', 'cormorant'))
286
self.assertEqual(index.documentCount(), 1)
287
self.assertEqual(index.wordCount(), 2)
288
self.failUnless(index.has_doc(1))
289
self.failIf('albatross' in index._fwd_index)
290
self.failUnless('buzzard' in index._fwd_index)
291
self.failUnless('cormorant' in index._fwd_index)
293
def test_index_doc_many(self):
294
index = self._makeOne()
295
self._populate(index)
296
self.assertEqual(index.documentCount(), self._populated_doc_count)
297
self.assertEqual(index.wordCount(), self._populated_word_count)
298
for docid in range(1, 6):
300
self.failIf(index.has_doc(docid))
302
self.failUnless(index.has_doc(docid))
304
def test_clear(self):
305
index = self._makeOne()
306
self._populate(index)
308
self.assertEqual(index.documentCount(), 0)
309
self.assertEqual(index.wordCount(), 0)
310
for docid in range(1, 6):
311
self.failIf(index.has_doc(docid))
313
def test_unindex_doc_missing(self):
314
index = self._makeOne()
315
index.unindex_doc(1) # doesn't raise
317
def test_unindex_no_residue(self):
318
index = self._makeOne()
319
index.index_doc(1, ('albatross', ))
321
self.assertEqual(index.documentCount(), 0)
322
self.assertEqual(index.wordCount(), 0)
323
self.failIf(index.has_doc(1))
325
def test_unindex_w_residue(self):
326
index = self._makeOne()
327
index.index_doc(1, ('albatross', ))
328
index.index_doc(2, ('albatross', 'cormorant'))
330
self.assertEqual(index.documentCount(), 1)
331
self.assertEqual(index.wordCount(), 2)
332
self.failIf(index.has_doc(1))
334
def test_hasdoc(self):
335
index = self._makeOne()
336
self._populate(index)
337
self.assertEqual(index.has_doc(1), 1)
338
self.assertEqual(index.has_doc(2), 1)
339
self.assertEqual(index.has_doc(3), 1)
340
self.assertEqual(index.has_doc(4), 0)
341
self.assertEqual(index.has_doc(5), 1)
342
self.assertEqual(index.has_doc(6), 0)
344
def test_search_bad_operator(self):
345
index = self._makeOne()
346
self.assertRaises(TypeError, index.search, 'whatever', 'maybe')
349
class KeywordIndexTests32(_KeywordIndexTestsBase,
355
class CaseInsensitiveKeywordIndexTests32(CaseInsensitiveKeywordIndexTestsBase,
361
class KeywordIndexTests64(_KeywordIndexTestsBase,
367
class CaseInsensitiveKeywordIndexTests64(CaseInsensitiveKeywordIndexTestsBase,
376
return unittest.TestSuite((
377
unittest.makeSuite(KeywordIndexTests32),
378
unittest.makeSuite(KeywordIndexTests64),
379
unittest.makeSuite(CaseInsensitiveKeywordIndexTests32),
380
unittest.makeSuite(CaseInsensitiveKeywordIndexTests64),