add --shared
[pylucene.git] / lucene-java-3.4.0 / lucene / src / test / org / apache / lucene / search / TestMultiTermConstantScore.java
1 package org.apache.lucene.search;
2
3 /**
4  * Licensed to the Apache Software Foundation (ASF) under one or more
5  * contributor license agreements.  See the NOTICE file distributed with
6  * this work for additional information regarding copyright ownership.
7  * The ASF licenses this file to You under the Apache License, Version 2.0
8  * (the "License"); you may not use this file except in compliance with
9  * the License.  You may obtain a copy of the License at
10  *
11  *     http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  */
19
20 import org.apache.lucene.analysis.MockAnalyzer;
21 import org.apache.lucene.analysis.MockTokenizer;
22 import org.apache.lucene.analysis.SimpleAnalyzer;
23 import org.apache.lucene.document.Document;
24 import org.apache.lucene.document.Field;
25 import org.apache.lucene.index.IndexReader;
26 import org.apache.lucene.index.RandomIndexWriter;
27 import org.apache.lucene.index.Term;
28 import org.apache.lucene.store.Directory;
29 import org.junit.AfterClass;
30 import org.junit.BeforeClass;
31 import org.junit.Test;
32
33 import java.io.IOException;
34 import java.text.Collator;
35 import java.util.Locale;
36
37 import junit.framework.Assert;
38
39 public class TestMultiTermConstantScore extends BaseTestRangeFilter {
40
41   /** threshold for comparing floats */
42   public static final float SCORE_COMP_THRESH = 1e-6f;
43
44   static Directory small;
45   static IndexReader reader;
46
47   static public void assertEquals(String m, float e, float a) {
48     Assert.assertEquals(m, e, a, SCORE_COMP_THRESH);
49   }
50
51   static public void assertEquals(String m, int e, int a) {
52     Assert.assertEquals(m, e, a);
53   }
54
55   @BeforeClass
56   public static void beforeClass() throws Exception {
57     String[] data = new String[] { "A 1 2 3 4 5 6", "Z       4 5 6", null,
58         "B   2   4 5 6", "Y     3   5 6", null, "C     3     6",
59         "X       4 5 6" };
60
61     small = newDirectory();
62     RandomIndexWriter writer = new RandomIndexWriter(random, small, 
63         newIndexWriterConfig(TEST_VERSION_CURRENT, 
64             new MockAnalyzer(random, MockTokenizer.WHITESPACE, false)).setMergePolicy(newLogMergePolicy()));
65
66     for (int i = 0; i < data.length; i++) {
67       Document doc = new Document();
68       doc.add(newField("id", String.valueOf(i), Field.Store.YES,
69           Field.Index.NOT_ANALYZED));// Field.Keyword("id",String.valueOf(i)));
70       doc
71           .add(newField("all", "all", Field.Store.YES,
72               Field.Index.NOT_ANALYZED));// Field.Keyword("all","all"));
73       if (null != data[i]) {
74         doc.add(newField("data", data[i], Field.Store.YES,
75             Field.Index.ANALYZED));// Field.Text("data",data[i]));
76       }
77       writer.addDocument(doc);
78     }
79
80     reader = writer.getReader();
81     writer.close();
82   }
83
84   @AfterClass
85   public static void afterClass() throws Exception {
86     reader.close();
87     small.close();
88     reader = null;
89     small = null;
90   }
91
92   /** macro for readability */
93   public static Query csrq(String f, String l, String h, boolean il, boolean ih) {
94     TermRangeQuery query = new TermRangeQuery(f, l, h, il, ih);
95     query.setRewriteMethod(MultiTermQuery.CONSTANT_SCORE_FILTER_REWRITE);
96     return query;
97   }
98
99   public static Query csrq(String f, String l, String h, boolean il, boolean ih, MultiTermQuery.RewriteMethod method) {
100     TermRangeQuery query = new TermRangeQuery(f, l, h, il, ih);
101     query.setRewriteMethod(method);
102     return query;
103   }
104
105   /** macro for readability */
106   public static Query csrq(String f, String l, String h, boolean il,
107       boolean ih, Collator c) {
108     TermRangeQuery query = new TermRangeQuery(f, l, h, il, ih, c);
109     query.setRewriteMethod(MultiTermQuery.CONSTANT_SCORE_FILTER_REWRITE);
110     return query;
111   }
112
113   /** macro for readability */
114   public static Query cspq(Term prefix) {
115     PrefixQuery query = new PrefixQuery(prefix);
116     query.setRewriteMethod(MultiTermQuery.CONSTANT_SCORE_FILTER_REWRITE);
117     return query;
118   }
119
120   /** macro for readability */
121   public static Query cswcq(Term wild) {
122     WildcardQuery query = new WildcardQuery(wild);
123     query.setRewriteMethod(MultiTermQuery.CONSTANT_SCORE_FILTER_REWRITE);
124     return query;
125   }
126
127   @Test
128   public void testBasics() throws IOException {
129     QueryUtils.check(csrq("data", "1", "6", T, T));
130     QueryUtils.check(csrq("data", "A", "Z", T, T));
131     QueryUtils.checkUnequal(csrq("data", "1", "6", T, T), csrq("data", "A",
132         "Z", T, T));
133
134     QueryUtils.check(cspq(new Term("data", "p*u?")));
135     QueryUtils.checkUnequal(cspq(new Term("data", "pre*")), cspq(new Term(
136         "data", "pres*")));
137
138     QueryUtils.check(cswcq(new Term("data", "p")));
139     QueryUtils.checkUnequal(cswcq(new Term("data", "pre*n?t")), cswcq(new Term(
140         "data", "pr*t?j")));
141   }
142
143   @Test
144   public void testBasicsRngCollating() throws IOException {
145     Collator c = Collator.getInstance(Locale.ENGLISH);
146     QueryUtils.check(csrq("data", "1", "6", T, T, c));
147     QueryUtils.check(csrq("data", "A", "Z", T, T, c));
148     QueryUtils.checkUnequal(csrq("data", "1", "6", T, T, c), csrq("data", "A",
149         "Z", T, T, c));
150   }
151
152   @Test
153   public void testEqualScores() throws IOException {
154     // NOTE: uses index build in *this* setUp
155
156     IndexSearcher search = newSearcher(reader);
157
158     ScoreDoc[] result;
159
160     // some hits match more terms then others, score should be the same
161
162     result = search.search(csrq("data", "1", "6", T, T), null, 1000).scoreDocs;
163     int numHits = result.length;
164     assertEquals("wrong number of results", 6, numHits);
165     float score = result[0].score;
166     for (int i = 1; i < numHits; i++) {
167       assertEquals("score for " + i + " was not the same", score,
168           result[i].score);
169     }
170
171     result = search.search(csrq("data", "1", "6", T, T, MultiTermQuery.CONSTANT_SCORE_BOOLEAN_QUERY_REWRITE), null, 1000).scoreDocs;
172     numHits = result.length;
173     assertEquals("wrong number of results", 6, numHits);
174     for (int i = 0; i < numHits; i++) {
175       assertEquals("score for " + i + " was not the same", score,
176           result[i].score);
177     }
178
179     search.close();
180   }
181
182   @Test
183   public void testBoost() throws IOException {
184     // NOTE: uses index build in *this* setUp
185
186     IndexSearcher search = newSearcher(reader);
187
188     // test for correct application of query normalization
189     // must use a non score normalizing method for this.
190     Query q = csrq("data", "1", "6", T, T);
191     q.setBoost(100);
192     search.search(q, null, new Collector() {
193       private int base = 0;
194       private Scorer scorer;
195       @Override
196       public void setScorer(Scorer scorer) throws IOException {
197         this.scorer = scorer;
198       }
199       @Override
200       public void collect(int doc) throws IOException {
201         assertEquals("score for doc " + (doc + base) + " was not correct", 1.0f, scorer.score());
202       }
203       @Override
204       public void setNextReader(IndexReader reader, int docBase) {
205         base = docBase;
206       }
207       @Override
208       public boolean acceptsDocsOutOfOrder() {
209         return true;
210       }
211     });
212
213     //
214     // Ensure that boosting works to score one clause of a query higher
215     // than another.
216     //
217     Query q1 = csrq("data", "A", "A", T, T); // matches document #0
218     q1.setBoost(.1f);
219     Query q2 = csrq("data", "Z", "Z", T, T); // matches document #1
220     BooleanQuery bq = new BooleanQuery(true);
221     bq.add(q1, BooleanClause.Occur.SHOULD);
222     bq.add(q2, BooleanClause.Occur.SHOULD);
223
224     ScoreDoc[] hits = search.search(bq, null, 1000).scoreDocs;
225     Assert.assertEquals(1, hits[0].doc);
226     Assert.assertEquals(0, hits[1].doc);
227     assertTrue(hits[0].score > hits[1].score);
228
229     q1 = csrq("data", "A", "A", T, T, MultiTermQuery.CONSTANT_SCORE_BOOLEAN_QUERY_REWRITE); // matches document #0
230     q1.setBoost(.1f);
231     q2 = csrq("data", "Z", "Z", T, T, MultiTermQuery.CONSTANT_SCORE_BOOLEAN_QUERY_REWRITE); // matches document #1
232     bq = new BooleanQuery(true);
233     bq.add(q1, BooleanClause.Occur.SHOULD);
234     bq.add(q2, BooleanClause.Occur.SHOULD);
235
236     hits = search.search(bq, null, 1000).scoreDocs;
237     Assert.assertEquals(1, hits[0].doc);
238     Assert.assertEquals(0, hits[1].doc);
239     assertTrue(hits[0].score > hits[1].score);
240
241     q1 = csrq("data", "A", "A", T, T); // matches document #0
242     q1.setBoost(10f);
243     q2 = csrq("data", "Z", "Z", T, T); // matches document #1
244     bq = new BooleanQuery(true);
245     bq.add(q1, BooleanClause.Occur.SHOULD);
246     bq.add(q2, BooleanClause.Occur.SHOULD);
247
248     hits = search.search(bq, null, 1000).scoreDocs;
249     Assert.assertEquals(0, hits[0].doc);
250     Assert.assertEquals(1, hits[1].doc);
251     assertTrue(hits[0].score > hits[1].score);
252     search.close();
253   }
254
255   @Test
256   public void testBooleanOrderUnAffected() throws IOException {
257     // NOTE: uses index build in *this* setUp
258
259     IndexSearcher search = newSearcher(reader);
260
261     // first do a regular TermRangeQuery which uses term expansion so
262     // docs with more terms in range get higher scores
263
264     Query rq = new TermRangeQuery("data", "1", "4", T, T);
265
266     ScoreDoc[] expected = search.search(rq, null, 1000).scoreDocs;
267     int numHits = expected.length;
268
269     // now do a boolean where which also contains a
270     // ConstantScoreRangeQuery and make sure hte order is the same
271
272     BooleanQuery q = new BooleanQuery();
273     q.add(rq, BooleanClause.Occur.MUST);// T, F);
274     q.add(csrq("data", "1", "6", T, T), BooleanClause.Occur.MUST);// T, F);
275
276     ScoreDoc[] actual = search.search(q, null, 1000).scoreDocs;
277
278     assertEquals("wrong numebr of hits", numHits, actual.length);
279     for (int i = 0; i < numHits; i++) {
280       assertEquals("mismatch in docid for hit#" + i, expected[i].doc,
281           actual[i].doc);
282     }
283
284     search.close();
285   }
286
287   @Test
288   public void testRangeQueryId() throws IOException {
289     // NOTE: uses index build in *super* setUp
290
291     IndexReader reader = signedIndexReader;
292     IndexSearcher search = newSearcher(reader);
293
294     int medId = ((maxId - minId) / 2);
295
296     String minIP = pad(minId);
297     String maxIP = pad(maxId);
298     String medIP = pad(medId);
299
300     int numDocs = reader.numDocs();
301
302     assertEquals("num of docs", numDocs, 1 + maxId - minId);
303
304     ScoreDoc[] result;
305
306     // test id, bounded on both ends
307
308     result = search.search(csrq("id", minIP, maxIP, T, T), null, numDocs).scoreDocs;
309     assertEquals("find all", numDocs, result.length);
310
311     result = search.search(csrq("id", minIP, maxIP, T, T, MultiTermQuery.CONSTANT_SCORE_AUTO_REWRITE_DEFAULT), null, numDocs).scoreDocs;
312     assertEquals("find all", numDocs, result.length);
313
314     result = search.search(csrq("id", minIP, maxIP, T, F), null, numDocs).scoreDocs;
315     assertEquals("all but last", numDocs - 1, result.length);
316
317     result = search.search(csrq("id", minIP, maxIP, T, F, MultiTermQuery.CONSTANT_SCORE_AUTO_REWRITE_DEFAULT), null, numDocs).scoreDocs;
318     assertEquals("all but last", numDocs - 1, result.length);
319
320     result = search.search(csrq("id", minIP, maxIP, F, T), null, numDocs).scoreDocs;
321     assertEquals("all but first", numDocs - 1, result.length);
322
323     result = search.search(csrq("id", minIP, maxIP, F, T, MultiTermQuery.CONSTANT_SCORE_AUTO_REWRITE_DEFAULT), null, numDocs).scoreDocs;
324     assertEquals("all but first", numDocs - 1, result.length);
325
326     result = search.search(csrq("id", minIP, maxIP, F, F), null, numDocs).scoreDocs;
327     assertEquals("all but ends", numDocs - 2, result.length);
328
329     result = search.search(csrq("id", minIP, maxIP, F, F, MultiTermQuery.CONSTANT_SCORE_AUTO_REWRITE_DEFAULT), null, numDocs).scoreDocs;
330     assertEquals("all but ends", numDocs - 2, result.length);
331
332     result = search.search(csrq("id", medIP, maxIP, T, T), null, numDocs).scoreDocs;
333     assertEquals("med and up", 1 + maxId - medId, result.length);
334
335     result = search.search(csrq("id", medIP, maxIP, T, T, MultiTermQuery.CONSTANT_SCORE_AUTO_REWRITE_DEFAULT), null, numDocs).scoreDocs;
336     assertEquals("med and up", 1 + maxId - medId, result.length);
337
338     result = search.search(csrq("id", minIP, medIP, T, T), null, numDocs).scoreDocs;
339     assertEquals("up to med", 1 + medId - minId, result.length);
340
341     result = search.search(csrq("id", minIP, medIP, T, T, MultiTermQuery.CONSTANT_SCORE_AUTO_REWRITE_DEFAULT), null, numDocs).scoreDocs;
342     assertEquals("up to med", 1 + medId - minId, result.length);
343
344     // unbounded id
345
346     result = search.search(csrq("id", minIP, null, T, F), null, numDocs).scoreDocs;
347     assertEquals("min and up", numDocs, result.length);
348
349     result = search.search(csrq("id", null, maxIP, F, T), null, numDocs).scoreDocs;
350     assertEquals("max and down", numDocs, result.length);
351
352     result = search.search(csrq("id", minIP, null, F, F), null, numDocs).scoreDocs;
353     assertEquals("not min, but up", numDocs - 1, result.length);
354
355     result = search.search(csrq("id", null, maxIP, F, F), null, numDocs).scoreDocs;
356     assertEquals("not max, but down", numDocs - 1, result.length);
357
358     result = search.search(csrq("id", medIP, maxIP, T, F), null, numDocs).scoreDocs;
359     assertEquals("med and up, not max", maxId - medId, result.length);
360
361     result = search.search(csrq("id", minIP, medIP, F, T), null, numDocs).scoreDocs;
362     assertEquals("not min, up to med", medId - minId, result.length);
363
364     // very small sets
365
366     result = search.search(csrq("id", minIP, minIP, F, F), null, numDocs).scoreDocs;
367     assertEquals("min,min,F,F", 0, result.length);
368
369     result = search.search(csrq("id", minIP, minIP, F, F, MultiTermQuery.CONSTANT_SCORE_AUTO_REWRITE_DEFAULT), null, numDocs).scoreDocs;
370     assertEquals("min,min,F,F", 0, result.length);
371
372     result = search.search(csrq("id", medIP, medIP, F, F), null, numDocs).scoreDocs;
373     assertEquals("med,med,F,F", 0, result.length);
374
375     result = search.search(csrq("id", medIP, medIP, F, F, MultiTermQuery.CONSTANT_SCORE_AUTO_REWRITE_DEFAULT), null, numDocs).scoreDocs;
376     assertEquals("med,med,F,F", 0, result.length);
377
378     result = search.search(csrq("id", maxIP, maxIP, F, F), null, numDocs).scoreDocs;
379     assertEquals("max,max,F,F", 0, result.length);
380
381     result = search.search(csrq("id", maxIP, maxIP, F, F, MultiTermQuery.CONSTANT_SCORE_AUTO_REWRITE_DEFAULT), null, numDocs).scoreDocs;
382     assertEquals("max,max,F,F", 0, result.length);
383
384     result = search.search(csrq("id", minIP, minIP, T, T), null, numDocs).scoreDocs;
385     assertEquals("min,min,T,T", 1, result.length);
386
387     result = search.search(csrq("id", minIP, minIP, T, T, MultiTermQuery.CONSTANT_SCORE_AUTO_REWRITE_DEFAULT), null, numDocs).scoreDocs;
388     assertEquals("min,min,T,T", 1, result.length);
389
390     result = search.search(csrq("id", null, minIP, F, T), null, numDocs).scoreDocs;
391     assertEquals("nul,min,F,T", 1, result.length);
392
393     result = search.search(csrq("id", null, minIP, F, T, MultiTermQuery.CONSTANT_SCORE_AUTO_REWRITE_DEFAULT), null, numDocs).scoreDocs;
394     assertEquals("nul,min,F,T", 1, result.length);
395
396     result = search.search(csrq("id", maxIP, maxIP, T, T), null, numDocs).scoreDocs;
397     assertEquals("max,max,T,T", 1, result.length);
398
399     result = search.search(csrq("id", maxIP, maxIP, T, T, MultiTermQuery.CONSTANT_SCORE_AUTO_REWRITE_DEFAULT), null, numDocs).scoreDocs;
400     assertEquals("max,max,T,T", 1, result.length);
401
402     result = search.search(csrq("id", maxIP, null, T, F), null, numDocs).scoreDocs;
403     assertEquals("max,nul,T,T", 1, result.length);
404
405     result = search.search(csrq("id", maxIP, null, T, F, MultiTermQuery.CONSTANT_SCORE_AUTO_REWRITE_DEFAULT), null, numDocs).scoreDocs;
406     assertEquals("max,nul,T,T", 1, result.length);
407
408     result = search.search(csrq("id", medIP, medIP, T, T), null, numDocs).scoreDocs;
409     assertEquals("med,med,T,T", 1, result.length);
410
411     result = search.search(csrq("id", medIP, medIP, T, T, MultiTermQuery.CONSTANT_SCORE_AUTO_REWRITE_DEFAULT), null, numDocs).scoreDocs;
412     assertEquals("med,med,T,T", 1, result.length);
413     
414     search.close();
415   }
416
417   @Test
418   public void testRangeQueryIdCollating() throws IOException {
419     // NOTE: uses index build in *super* setUp
420
421     IndexReader reader = signedIndexReader;
422     IndexSearcher search = newSearcher(reader);
423
424     int medId = ((maxId - minId) / 2);
425
426     String minIP = pad(minId);
427     String maxIP = pad(maxId);
428     String medIP = pad(medId);
429
430     int numDocs = reader.numDocs();
431
432     assertEquals("num of docs", numDocs, 1 + maxId - minId);
433
434     ScoreDoc[] result;
435
436     Collator c = Collator.getInstance(Locale.ENGLISH);
437
438     // test id, bounded on both ends
439
440     result = search.search(csrq("id", minIP, maxIP, T, T, c), null, numDocs).scoreDocs;
441     assertEquals("find all", numDocs, result.length);
442
443     result = search.search(csrq("id", minIP, maxIP, T, F, c), null, numDocs).scoreDocs;
444     assertEquals("all but last", numDocs - 1, result.length);
445
446     result = search.search(csrq("id", minIP, maxIP, F, T, c), null, numDocs).scoreDocs;
447     assertEquals("all but first", numDocs - 1, result.length);
448
449     result = search.search(csrq("id", minIP, maxIP, F, F, c), null, numDocs).scoreDocs;
450     assertEquals("all but ends", numDocs - 2, result.length);
451
452     result = search.search(csrq("id", medIP, maxIP, T, T, c), null, numDocs).scoreDocs;
453     assertEquals("med and up", 1 + maxId - medId, result.length);
454
455     result = search.search(csrq("id", minIP, medIP, T, T, c), null, numDocs).scoreDocs;
456     assertEquals("up to med", 1 + medId - minId, result.length);
457
458     // unbounded id
459
460     result = search.search(csrq("id", minIP, null, T, F, c), null, numDocs).scoreDocs;
461     assertEquals("min and up", numDocs, result.length);
462
463     result = search.search(csrq("id", null, maxIP, F, T, c), null, numDocs).scoreDocs;
464     assertEquals("max and down", numDocs, result.length);
465
466     result = search.search(csrq("id", minIP, null, F, F, c), null, numDocs).scoreDocs;
467     assertEquals("not min, but up", numDocs - 1, result.length);
468
469     result = search.search(csrq("id", null, maxIP, F, F, c), null, numDocs).scoreDocs;
470     assertEquals("not max, but down", numDocs - 1, result.length);
471
472     result = search.search(csrq("id", medIP, maxIP, T, F, c), null, numDocs).scoreDocs;
473     assertEquals("med and up, not max", maxId - medId, result.length);
474
475     result = search.search(csrq("id", minIP, medIP, F, T, c), null, numDocs).scoreDocs;
476     assertEquals("not min, up to med", medId - minId, result.length);
477
478     // very small sets
479
480     result = search.search(csrq("id", minIP, minIP, F, F, c), null, numDocs).scoreDocs;
481     assertEquals("min,min,F,F,c", 0, result.length);
482     result = search.search(csrq("id", medIP, medIP, F, F, c), null, numDocs).scoreDocs;
483     assertEquals("med,med,F,F,c", 0, result.length);
484     result = search.search(csrq("id", maxIP, maxIP, F, F, c), null, numDocs).scoreDocs;
485     assertEquals("max,max,F,F,c", 0, result.length);
486
487     result = search.search(csrq("id", minIP, minIP, T, T, c), null, numDocs).scoreDocs;
488     assertEquals("min,min,T,T,c", 1, result.length);
489     result = search.search(csrq("id", null, minIP, F, T, c), null, numDocs).scoreDocs;
490     assertEquals("nul,min,F,T,c", 1, result.length);
491
492     result = search.search(csrq("id", maxIP, maxIP, T, T, c), null, numDocs).scoreDocs;
493     assertEquals("max,max,T,T,c", 1, result.length);
494     result = search.search(csrq("id", maxIP, null, T, F, c), null, numDocs).scoreDocs;
495     assertEquals("max,nul,T,T,c", 1, result.length);
496
497     result = search.search(csrq("id", medIP, medIP, T, T, c), null, numDocs).scoreDocs;
498     assertEquals("med,med,T,T,c", 1, result.length);
499     
500     search.close();
501   }
502
503   @Test
504   public void testRangeQueryRand() throws IOException {
505     // NOTE: uses index build in *super* setUp
506
507     IndexReader reader = signedIndexReader;
508     IndexSearcher search = newSearcher(reader);
509
510     String minRP = pad(signedIndexDir.minR);
511     String maxRP = pad(signedIndexDir.maxR);
512
513     int numDocs = reader.numDocs();
514
515     assertEquals("num of docs", numDocs, 1 + maxId - minId);
516
517     ScoreDoc[] result;
518
519     // test extremes, bounded on both ends
520
521     result = search.search(csrq("rand", minRP, maxRP, T, T), null, numDocs).scoreDocs;
522     assertEquals("find all", numDocs, result.length);
523
524     result = search.search(csrq("rand", minRP, maxRP, T, F), null, numDocs).scoreDocs;
525     assertEquals("all but biggest", numDocs - 1, result.length);
526
527     result = search.search(csrq("rand", minRP, maxRP, F, T), null, numDocs).scoreDocs;
528     assertEquals("all but smallest", numDocs - 1, result.length);
529
530     result = search.search(csrq("rand", minRP, maxRP, F, F), null, numDocs).scoreDocs;
531     assertEquals("all but extremes", numDocs - 2, result.length);
532
533     // unbounded
534
535     result = search.search(csrq("rand", minRP, null, T, F), null, numDocs).scoreDocs;
536     assertEquals("smallest and up", numDocs, result.length);
537
538     result = search.search(csrq("rand", null, maxRP, F, T), null, numDocs).scoreDocs;
539     assertEquals("biggest and down", numDocs, result.length);
540
541     result = search.search(csrq("rand", minRP, null, F, F), null, numDocs).scoreDocs;
542     assertEquals("not smallest, but up", numDocs - 1, result.length);
543
544     result = search.search(csrq("rand", null, maxRP, F, F), null, numDocs).scoreDocs;
545     assertEquals("not biggest, but down", numDocs - 1, result.length);
546
547     // very small sets
548
549     result = search.search(csrq("rand", minRP, minRP, F, F), null, numDocs).scoreDocs;
550     assertEquals("min,min,F,F", 0, result.length);
551     result = search.search(csrq("rand", maxRP, maxRP, F, F), null, numDocs).scoreDocs;
552     assertEquals("max,max,F,F", 0, result.length);
553
554     result = search.search(csrq("rand", minRP, minRP, T, T), null, numDocs).scoreDocs;
555     assertEquals("min,min,T,T", 1, result.length);
556     result = search.search(csrq("rand", null, minRP, F, T), null, numDocs).scoreDocs;
557     assertEquals("nul,min,F,T", 1, result.length);
558
559     result = search.search(csrq("rand", maxRP, maxRP, T, T), null, numDocs).scoreDocs;
560     assertEquals("max,max,T,T", 1, result.length);
561     result = search.search(csrq("rand", maxRP, null, T, F), null, numDocs).scoreDocs;
562     assertEquals("max,nul,T,T", 1, result.length);
563
564     search.close();
565   }
566
567   @Test
568   public void testRangeQueryRandCollating() throws IOException {
569     // NOTE: uses index build in *super* setUp
570
571     // using the unsigned index because collation seems to ignore hyphens
572     IndexReader reader = unsignedIndexReader;
573     IndexSearcher search = newSearcher(reader);
574
575     String minRP = pad(unsignedIndexDir.minR);
576     String maxRP = pad(unsignedIndexDir.maxR);
577
578     int numDocs = reader.numDocs();
579
580     assertEquals("num of docs", numDocs, 1 + maxId - minId);
581
582     ScoreDoc[] result;
583
584     Collator c = Collator.getInstance(Locale.ENGLISH);
585
586     // test extremes, bounded on both ends
587
588     result = search.search(csrq("rand", minRP, maxRP, T, T, c), null, numDocs).scoreDocs;
589     assertEquals("find all", numDocs, result.length);
590
591     result = search.search(csrq("rand", minRP, maxRP, T, F, c), null, numDocs).scoreDocs;
592     assertEquals("all but biggest", numDocs - 1, result.length);
593
594     result = search.search(csrq("rand", minRP, maxRP, F, T, c), null, numDocs).scoreDocs;
595     assertEquals("all but smallest", numDocs - 1, result.length);
596
597     result = search.search(csrq("rand", minRP, maxRP, F, F, c), null, numDocs).scoreDocs;
598     assertEquals("all but extremes", numDocs - 2, result.length);
599
600     // unbounded
601
602     result = search.search(csrq("rand", minRP, null, T, F, c), null, numDocs).scoreDocs;
603     assertEquals("smallest and up", numDocs, result.length);
604
605     result = search.search(csrq("rand", null, maxRP, F, T, c), null, numDocs).scoreDocs;
606     assertEquals("biggest and down", numDocs, result.length);
607
608     result = search.search(csrq("rand", minRP, null, F, F, c), null, numDocs).scoreDocs;
609     assertEquals("not smallest, but up", numDocs - 1, result.length);
610
611     result = search.search(csrq("rand", null, maxRP, F, F, c), null, numDocs).scoreDocs;
612     assertEquals("not biggest, but down", numDocs - 1, result.length);
613
614     // very small sets
615
616     result = search.search(csrq("rand", minRP, minRP, F, F, c), null, numDocs).scoreDocs;
617     assertEquals("min,min,F,F,c", 0, result.length);
618     result = search.search(csrq("rand", maxRP, maxRP, F, F, c), null, numDocs).scoreDocs;
619     assertEquals("max,max,F,F,c", 0, result.length);
620
621     result = search.search(csrq("rand", minRP, minRP, T, T, c), null, numDocs).scoreDocs;
622     assertEquals("min,min,T,T,c", 1, result.length);
623     result = search.search(csrq("rand", null, minRP, F, T, c), null, numDocs).scoreDocs;
624     assertEquals("nul,min,F,T,c", 1, result.length);
625
626     result = search.search(csrq("rand", maxRP, maxRP, T, T, c), null, numDocs).scoreDocs;
627     assertEquals("max,max,T,T,c", 1, result.length);
628     result = search.search(csrq("rand", maxRP, null, T, F, c), null, numDocs).scoreDocs;
629     assertEquals("max,nul,T,T,c", 1, result.length);
630     
631     search.close();
632   }
633
634   @Test
635   public void testFarsi() throws Exception {
636
637     /* build an index */
638     Directory farsiIndex = newDirectory();
639     RandomIndexWriter writer = new RandomIndexWriter(random, farsiIndex, new SimpleAnalyzer(TEST_VERSION_CURRENT));
640     Document doc = new Document();
641     doc.add(newField("content", "\u0633\u0627\u0628", Field.Store.YES,
642         Field.Index.NOT_ANALYZED));
643     doc
644         .add(newField("body", "body", Field.Store.YES,
645             Field.Index.NOT_ANALYZED));
646     writer.addDocument(doc);
647
648     IndexReader reader = writer.getReader();
649     writer.close();
650
651     IndexSearcher search = newSearcher(reader);
652
653     // Neither Java 1.4.2 nor 1.5.0 has Farsi Locale collation available in
654     // RuleBasedCollator. However, the Arabic Locale seems to order the Farsi
655     // characters properly.
656     Collator c = Collator.getInstance(new Locale("ar"));
657
658     // Unicode order would include U+0633 in [ U+062F - U+0698 ], but Farsi
659     // orders the U+0698 character before the U+0633 character, so the single
660     // index Term below should NOT be returned by a ConstantScoreRangeQuery
661     // with a Farsi Collator (or an Arabic one for the case when Farsi is
662     // not supported).
663     ScoreDoc[] result = search.search(csrq("content", "\u062F", "\u0698", T, T,
664         c), null, 1000).scoreDocs;
665     assertEquals("The index Term should not be included.", 0, result.length);
666
667     result = search.search(csrq("content", "\u0633", "\u0638", T, T, c), null,
668         1000).scoreDocs;
669     assertEquals("The index Term should be included.", 1, result.length);
670     search.close();
671     reader.close();
672     farsiIndex.close();
673   }
674
675   @Test
676   public void testDanish() throws Exception {
677
678     /* build an index */
679     Directory danishIndex = newDirectory();
680     RandomIndexWriter writer = new RandomIndexWriter(random, danishIndex, new SimpleAnalyzer(TEST_VERSION_CURRENT));
681
682     // Danish collation orders the words below in the given order
683     // (example taken from TestSort.testInternationalSort() ).
684     String[] words = { "H\u00D8T", "H\u00C5T", "MAND" };
685     for (int docnum = 0 ; docnum < words.length ; ++docnum) {   
686       Document doc = new Document();
687       doc.add(newField("content", words[docnum], 
688                         Field.Store.YES, Field.Index.NOT_ANALYZED));
689       doc.add(newField("body", "body",
690                         Field.Store.YES, Field.Index.NOT_ANALYZED));
691       writer.addDocument(doc);
692     }
693     IndexReader reader = writer.getReader();
694     writer.close();
695
696     IndexSearcher search = newSearcher(reader);
697
698     Collator c = Collator.getInstance(new Locale("da", "dk"));
699
700     // Unicode order would not include "H\u00C5T" in [ "H\u00D8T", "MAND" ],
701     // but Danish collation does.
702     ScoreDoc[] result = search.search
703       (csrq("content", "H\u00D8T", "MAND", F, F, c), null, 1000).scoreDocs;
704     assertEquals("The index Term should be included.", 1, result.length);
705
706     result = search.search
707       (csrq("content", "H\u00C5T", "MAND", F, F, c), null, 1000).scoreDocs;
708     assertEquals("The index Term should not be included.", 0, result.length);
709     search.close();
710     reader.close();
711     danishIndex.close();
712   }
713 }