add --shared
[pylucene.git] / lucene-java-3.4.0 / lucene / src / test / org / apache / lucene / search / TestNumericRangeQuery64.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.document.Document;
22 import org.apache.lucene.document.Field;
23 import org.apache.lucene.document.NumericField;
24 import org.apache.lucene.index.IndexReader;
25 import org.apache.lucene.index.IndexWriter;
26 import org.apache.lucene.index.RandomIndexWriter;
27 import org.apache.lucene.store.Directory;
28 import org.apache.lucene.util.LuceneTestCase;
29 import org.apache.lucene.util.NumericUtils;
30 import org.apache.lucene.util._TestUtil;
31
32 import org.junit.Test;
33 import org.junit.AfterClass;
34 import org.junit.BeforeClass;
35
36 public class TestNumericRangeQuery64 extends LuceneTestCase {
37   // distance of entries
38   private static final long distance = 66666L;
39   // shift the starting of the values to the left, to also have negative values:
40   private static final long startOffset = - 1L << 31;
41   // number of docs to generate for testing
42   private static int noDocs;
43   
44   private static Directory directory = null;
45   private static IndexReader reader = null;
46   private static IndexSearcher searcher = null;
47   
48   @BeforeClass
49   public static void beforeClass() throws Exception {
50     noDocs = atLeast(4096);
51     directory = newDirectory();
52     RandomIndexWriter writer = new RandomIndexWriter(random, directory,
53         newIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(random))
54         .setMaxBufferedDocs(_TestUtil.nextInt(random, 100, 1000))
55         .setMergePolicy(newLogMergePolicy()));
56     
57     NumericField
58       field8 = new NumericField("field8", 8, Field.Store.YES, true),
59       field6 = new NumericField("field6", 6, Field.Store.YES, true),
60       field4 = new NumericField("field4", 4, Field.Store.YES, true),
61       field2 = new NumericField("field2", 2, Field.Store.YES, true),
62       fieldNoTrie = new NumericField("field"+Integer.MAX_VALUE, Integer.MAX_VALUE, Field.Store.YES, true),
63       ascfield8 = new NumericField("ascfield8", 8, Field.Store.NO, true),
64       ascfield6 = new NumericField("ascfield6", 6, Field.Store.NO, true),
65       ascfield4 = new NumericField("ascfield4", 4, Field.Store.NO, true),
66       ascfield2 = new NumericField("ascfield2", 2, Field.Store.NO, true);
67     
68     Document doc = new Document();
69     // add fields, that have a distance to test general functionality
70     doc.add(field8); doc.add(field6); doc.add(field4); doc.add(field2); doc.add(fieldNoTrie);
71     // add ascending fields with a distance of 1, beginning at -noDocs/2 to test the correct splitting of range and inclusive/exclusive
72     doc.add(ascfield8); doc.add(ascfield6); doc.add(ascfield4); doc.add(ascfield2);
73     
74     // Add a series of noDocs docs with increasing long values, by updating the fields
75     for (int l=0; l<noDocs; l++) {
76       long val=distance*l+startOffset;
77       field8.setLongValue(val);
78       field6.setLongValue(val);
79       field4.setLongValue(val);
80       field2.setLongValue(val);
81       fieldNoTrie.setLongValue(val);
82
83       val=l-(noDocs/2);
84       ascfield8.setLongValue(val);
85       ascfield6.setLongValue(val);
86       ascfield4.setLongValue(val);
87       ascfield2.setLongValue(val);
88       writer.addDocument(doc);
89     }
90   
91     reader = writer.getReader();
92     searcher=newSearcher(reader);
93     writer.close();
94   }
95   
96   @AfterClass
97   public static void afterClass() throws Exception {
98     searcher.close();
99     searcher = null;
100     reader.close();
101     reader = null;
102     directory.close();
103     directory = null;
104   }
105   
106   @Override
107   public void setUp() throws Exception {
108     super.setUp();
109     // set the theoretical maximum term count for 8bit (see docs for the number)
110     // super.tearDown will restore the default
111     BooleanQuery.setMaxClauseCount(7*255*2 + 255);
112   }
113   
114   /** test for constant score + boolean query + filter, the other tests only use the constant score mode */
115   private void testRange(int precisionStep) throws Exception {
116     String field="field"+precisionStep;
117     int count=3000;
118     long lower=(distance*3/2)+startOffset, upper=lower + count*distance + (distance/3);
119     NumericRangeQuery<Long> q = NumericRangeQuery.newLongRange(field, precisionStep, lower, upper, true, true);
120     NumericRangeFilter<Long> f = NumericRangeFilter.newLongRange(field, precisionStep, lower, upper, true, true);
121     int lastTerms = 0;
122     for (byte i=0; i<3; i++) {
123       TopDocs topDocs;
124       int terms;
125       String type;
126       q.clearTotalNumberOfTerms();
127       f.clearTotalNumberOfTerms();
128       switch (i) {
129         case 0:
130           type = " (constant score filter rewrite)";
131           q.setRewriteMethod(MultiTermQuery.CONSTANT_SCORE_FILTER_REWRITE);
132           topDocs = searcher.search(q, null, noDocs, Sort.INDEXORDER);
133           terms = q.getTotalNumberOfTerms();
134           break;
135         case 1:
136           type = " (constant score boolean rewrite)";
137           q.setRewriteMethod(MultiTermQuery.CONSTANT_SCORE_BOOLEAN_QUERY_REWRITE);
138           topDocs = searcher.search(q, null, noDocs, Sort.INDEXORDER);
139           terms = q.getTotalNumberOfTerms();
140           break;
141         case 2:
142           type = " (filter)";
143           topDocs = searcher.search(new MatchAllDocsQuery(), f, noDocs, Sort.INDEXORDER);
144           terms = f.getTotalNumberOfTerms();
145           break;
146         default:
147           return;
148       }
149       if (VERBOSE) System.out.println("Found "+terms+" distinct terms in range for field '"+field+"'"+type+".");
150       ScoreDoc[] sd = topDocs.scoreDocs;
151       assertNotNull(sd);
152       assertEquals("Score doc count"+type, count, sd.length );
153       Document doc=searcher.doc(sd[0].doc);
154       assertEquals("First doc"+type, 2*distance+startOffset, Long.parseLong(doc.get(field)) );
155       doc=searcher.doc(sd[sd.length-1].doc);
156       assertEquals("Last doc"+type, (1+count)*distance+startOffset, Long.parseLong(doc.get(field)) );
157       if (i>0 && 
158           (searcher.getIndexReader().getSequentialSubReaders() == null || 
159            searcher.getIndexReader().getSequentialSubReaders().length == 1)) {
160         assertEquals("Distinct term number is equal for all query types", lastTerms, terms);
161       }
162       lastTerms = terms;
163     }
164   }
165
166   @Test
167   public void testRange_8bit() throws Exception {
168     testRange(8);
169   }
170   
171   @Test
172   public void testRange_6bit() throws Exception {
173     testRange(6);
174   }
175   
176   @Test
177   public void testRange_4bit() throws Exception {
178     testRange(4);
179   }
180   
181   @Test
182   public void testRange_2bit() throws Exception {
183     testRange(2);
184   }
185   
186   @Test
187   public void testInverseRange() throws Exception {
188     NumericRangeFilter<Long> f = NumericRangeFilter.newLongRange("field8", 8, 1000L, -1000L, true, true);
189     assertSame("A inverse range should return the EMPTY_DOCIDSET instance", DocIdSet.EMPTY_DOCIDSET, f.getDocIdSet(searcher.getIndexReader()));
190     f = NumericRangeFilter.newLongRange("field8", 8, Long.MAX_VALUE, null, false, false);
191     assertSame("A exclusive range starting with Long.MAX_VALUE should return the EMPTY_DOCIDSET instance",
192       DocIdSet.EMPTY_DOCIDSET, f.getDocIdSet(searcher.getIndexReader()));
193     f = NumericRangeFilter.newLongRange("field8", 8, null, Long.MIN_VALUE, false, false);
194     assertSame("A exclusive range ending with Long.MIN_VALUE should return the EMPTY_DOCIDSET instance",
195       DocIdSet.EMPTY_DOCIDSET, f.getDocIdSet(searcher.getIndexReader()));
196   }
197   
198   @Test
199   public void testOneMatchQuery() throws Exception {
200     NumericRangeQuery<Long> q = NumericRangeQuery.newLongRange("ascfield8", 8, 1000L, 1000L, true, true);
201     assertSame(MultiTermQuery.CONSTANT_SCORE_BOOLEAN_QUERY_REWRITE, q.getRewriteMethod());
202     TopDocs topDocs = searcher.search(q, noDocs);
203     ScoreDoc[] sd = topDocs.scoreDocs;
204     assertNotNull(sd);
205     assertEquals("Score doc count", 1, sd.length );
206   }
207   
208   private void testLeftOpenRange(int precisionStep) throws Exception {
209     String field="field"+precisionStep;
210     int count=3000;
211     long upper=(count-1)*distance + (distance/3) + startOffset;
212     NumericRangeQuery<Long> q=NumericRangeQuery.newLongRange(field, precisionStep, null, upper, true, true);
213     TopDocs topDocs = searcher.search(q, null, noDocs, Sort.INDEXORDER);
214     if (VERBOSE) System.out.println("Found "+q.getTotalNumberOfTerms()+" distinct terms in left open range for field '"+field+"'.");
215     ScoreDoc[] sd = topDocs.scoreDocs;
216     assertNotNull(sd);
217     assertEquals("Score doc count", count, sd.length );
218     Document doc=searcher.doc(sd[0].doc);
219     assertEquals("First doc", startOffset, Long.parseLong(doc.get(field)) );
220     doc=searcher.doc(sd[sd.length-1].doc);
221     assertEquals("Last doc", (count-1)*distance+startOffset, Long.parseLong(doc.get(field)) );
222
223     q=NumericRangeQuery.newLongRange(field, precisionStep, null, upper, false, true);
224     topDocs = searcher.search(q, null, noDocs, Sort.INDEXORDER);
225     sd = topDocs.scoreDocs;
226     assertNotNull(sd);
227     assertEquals("Score doc count", count, sd.length );
228     doc=searcher.doc(sd[0].doc);
229     assertEquals("First doc", startOffset, Long.parseLong(doc.get(field)) );
230     doc=searcher.doc(sd[sd.length-1].doc);
231     assertEquals("Last doc", (count-1)*distance+startOffset, Long.parseLong(doc.get(field)) );
232   }
233   
234   @Test
235   public void testLeftOpenRange_8bit() throws Exception {
236     testLeftOpenRange(8);
237   }
238   
239   @Test
240   public void testLeftOpenRange_6bit() throws Exception {
241     testLeftOpenRange(6);
242   }
243   
244   @Test
245   public void testLeftOpenRange_4bit() throws Exception {
246     testLeftOpenRange(4);
247   }
248   
249   @Test
250   public void testLeftOpenRange_2bit() throws Exception {
251     testLeftOpenRange(2);
252   }
253   
254   private void testRightOpenRange(int precisionStep) throws Exception {
255     String field="field"+precisionStep;
256     int count=3000;
257     long lower=(count-1)*distance + (distance/3) +startOffset;
258     NumericRangeQuery<Long> q=NumericRangeQuery.newLongRange(field, precisionStep, lower, null, true, true);
259     TopDocs topDocs = searcher.search(q, null, noDocs, Sort.INDEXORDER);
260     if (VERBOSE) System.out.println("Found "+q.getTotalNumberOfTerms()+" distinct terms in right open range for field '"+field+"'.");
261     ScoreDoc[] sd = topDocs.scoreDocs;
262     assertNotNull(sd);
263     assertEquals("Score doc count", noDocs-count, sd.length );
264     Document doc=searcher.doc(sd[0].doc);
265     assertEquals("First doc", count*distance+startOffset, Long.parseLong(doc.get(field)) );
266     doc=searcher.doc(sd[sd.length-1].doc);
267     assertEquals("Last doc", (noDocs-1)*distance+startOffset, Long.parseLong(doc.get(field)) );
268
269     q=NumericRangeQuery.newLongRange(field, precisionStep, lower, null, true, false);
270     topDocs = searcher.search(q, null, noDocs, Sort.INDEXORDER);
271     sd = topDocs.scoreDocs;
272     assertNotNull(sd);
273     assertEquals("Score doc count", noDocs-count, sd.length );
274     doc=searcher.doc(sd[0].doc);
275     assertEquals("First doc", count*distance+startOffset, Long.parseLong(doc.get(field)) );
276     doc=searcher.doc(sd[sd.length-1].doc);
277     assertEquals("Last doc", (noDocs-1)*distance+startOffset, Long.parseLong(doc.get(field)) );
278   }
279   
280   @Test
281   public void testRightOpenRange_8bit() throws Exception {
282     testRightOpenRange(8);
283   }
284   
285   @Test
286   public void testRightOpenRange_6bit() throws Exception {
287     testRightOpenRange(6);
288   }
289   
290   @Test
291   public void testRightOpenRange_4bit() throws Exception {
292     testRightOpenRange(4);
293   }
294   
295   @Test
296   public void testRightOpenRange_2bit() throws Exception {
297     testRightOpenRange(2);
298   }
299   
300   @Test
301   public void testInfiniteValues() throws Exception {
302     Directory dir = newDirectory();
303     IndexWriter writer = new IndexWriter(dir, newIndexWriterConfig(
304         TEST_VERSION_CURRENT, new MockAnalyzer(random)));
305     Document doc = new Document();
306     doc.add(new NumericField("double").setDoubleValue(Double.NEGATIVE_INFINITY));
307     doc.add(new NumericField("long").setLongValue(Long.MIN_VALUE));
308     writer.addDocument(doc);
309     
310     doc = new Document();
311     doc.add(new NumericField("double").setDoubleValue(Double.POSITIVE_INFINITY));
312     doc.add(new NumericField("long").setLongValue(Long.MAX_VALUE));
313     writer.addDocument(doc);
314     
315     doc = new Document();
316     doc.add(new NumericField("double").setDoubleValue(0.0));
317     doc.add(new NumericField("long").setLongValue(0L));
318     writer.addDocument(doc);
319     writer.close();
320     
321     IndexSearcher s = new IndexSearcher(dir);
322     
323     Query q=NumericRangeQuery.newLongRange("long", null, null, true, true);
324     TopDocs topDocs = s.search(q, 10);
325     assertEquals("Score doc count", 3,  topDocs.scoreDocs.length );
326     
327     q=NumericRangeQuery.newLongRange("long", null, null, false, false);
328     topDocs = s.search(q, 10);
329     assertEquals("Score doc count", 3,  topDocs.scoreDocs.length );
330
331     q=NumericRangeQuery.newLongRange("long", Long.MIN_VALUE, Long.MAX_VALUE, true, true);
332     topDocs = s.search(q, 10);
333     assertEquals("Score doc count", 3,  topDocs.scoreDocs.length );
334     
335     q=NumericRangeQuery.newLongRange("long", Long.MIN_VALUE, Long.MAX_VALUE, false, false);
336     topDocs = s.search(q, 10);
337     assertEquals("Score doc count", 1,  topDocs.scoreDocs.length );
338
339     q=NumericRangeQuery.newDoubleRange("double", null, null, true, true);
340     topDocs = s.search(q, 10);
341     assertEquals("Score doc count", 3,  topDocs.scoreDocs.length );
342
343     q=NumericRangeQuery.newDoubleRange("double", null, null, false, false);
344     topDocs = s.search(q, 10);
345     assertEquals("Score doc count", 3,  topDocs.scoreDocs.length );
346
347     s.close();
348     dir.close();
349   }
350   
351   private void testRandomTrieAndClassicRangeQuery(int precisionStep) throws Exception {
352     String field="field"+precisionStep;
353     int termCountT=0,termCountC=0;
354     int num = _TestUtil.nextInt(random, 10, 20);
355     for (int i = 0; i < num; i++) {
356       long lower=(long)(random.nextDouble()*noDocs*distance)+startOffset;
357       long upper=(long)(random.nextDouble()*noDocs*distance)+startOffset;
358       if (lower>upper) {
359         long a=lower; lower=upper; upper=a;
360       }
361       // test inclusive range
362       NumericRangeQuery<Long> tq=NumericRangeQuery.newLongRange(field, precisionStep, lower, upper, true, true);
363       TermRangeQuery cq=new TermRangeQuery(field, NumericUtils.longToPrefixCoded(lower), NumericUtils.longToPrefixCoded(upper), true, true);
364       TopDocs tTopDocs = searcher.search(tq, 1);
365       TopDocs cTopDocs = searcher.search(cq, 1);
366       assertEquals("Returned count for NumericRangeQuery and TermRangeQuery must be equal", cTopDocs.totalHits, tTopDocs.totalHits );
367       termCountT += tq.getTotalNumberOfTerms();
368       termCountC += cq.getTotalNumberOfTerms();
369       // test exclusive range
370       tq=NumericRangeQuery.newLongRange(field, precisionStep, lower, upper, false, false);
371       cq=new TermRangeQuery(field, NumericUtils.longToPrefixCoded(lower), NumericUtils.longToPrefixCoded(upper), false, false);
372       tTopDocs = searcher.search(tq, 1);
373       cTopDocs = searcher.search(cq, 1);
374       assertEquals("Returned count for NumericRangeQuery and TermRangeQuery must be equal", cTopDocs.totalHits, tTopDocs.totalHits );
375       termCountT += tq.getTotalNumberOfTerms();
376       termCountC += cq.getTotalNumberOfTerms();
377       // test left exclusive range
378       tq=NumericRangeQuery.newLongRange(field, precisionStep, lower, upper, false, true);
379       cq=new TermRangeQuery(field, NumericUtils.longToPrefixCoded(lower), NumericUtils.longToPrefixCoded(upper), false, true);
380       tTopDocs = searcher.search(tq, 1);
381       cTopDocs = searcher.search(cq, 1);
382       assertEquals("Returned count for NumericRangeQuery and TermRangeQuery must be equal", cTopDocs.totalHits, tTopDocs.totalHits );
383       termCountT += tq.getTotalNumberOfTerms();
384       termCountC += cq.getTotalNumberOfTerms();
385       // test right exclusive range
386       tq=NumericRangeQuery.newLongRange(field, precisionStep, lower, upper, true, false);
387       cq=new TermRangeQuery(field, NumericUtils.longToPrefixCoded(lower), NumericUtils.longToPrefixCoded(upper), true, false);
388       tTopDocs = searcher.search(tq, 1);
389       cTopDocs = searcher.search(cq, 1);
390       assertEquals("Returned count for NumericRangeQuery and TermRangeQuery must be equal", cTopDocs.totalHits, tTopDocs.totalHits );
391       termCountT += tq.getTotalNumberOfTerms();
392       termCountC += cq.getTotalNumberOfTerms();
393     }
394     if (precisionStep == Integer.MAX_VALUE && 
395         (searcher.getIndexReader().getSequentialSubReaders() == null || 
396          searcher.getIndexReader().getSequentialSubReaders().length == 1)) {
397       assertEquals("Total number of terms should be equal for unlimited precStep", termCountT, termCountC);
398     } else if (VERBOSE) {
399       System.out.println("Average number of terms during random search on '" + field + "':");
400       System.out.println(" Trie query: " + (((double)termCountT)/(num * 4)));
401       System.out.println(" Classical query: " + (((double)termCountC)/(num * 4)));
402     }
403   }
404   
405   @Test
406   public void testRandomTrieAndClassicRangeQuery_8bit() throws Exception {
407     testRandomTrieAndClassicRangeQuery(8);
408   }
409   
410   @Test
411   public void testRandomTrieAndClassicRangeQuery_6bit() throws Exception {
412     testRandomTrieAndClassicRangeQuery(6);
413   }
414   
415   @Test
416   public void testRandomTrieAndClassicRangeQuery_4bit() throws Exception {
417     testRandomTrieAndClassicRangeQuery(4);
418   }
419   
420   @Test
421   public void testRandomTrieAndClassicRangeQuery_2bit() throws Exception {
422     testRandomTrieAndClassicRangeQuery(2);
423   }
424   
425   @Test
426   public void testRandomTrieAndClassicRangeQuery_NoTrie() throws Exception {
427     testRandomTrieAndClassicRangeQuery(Integer.MAX_VALUE);
428   }
429   
430   private void testRangeSplit(int precisionStep) throws Exception {
431     String field="ascfield"+precisionStep;
432     // 10 random tests
433     int num = _TestUtil.nextInt(random, 10, 20);
434     for (int i = 0; i < num; i++) {
435       long lower=(long)(random.nextDouble()*noDocs - noDocs/2);
436       long upper=(long)(random.nextDouble()*noDocs - noDocs/2);
437       if (lower>upper) {
438         long a=lower; lower=upper; upper=a;
439       }
440       // test inclusive range
441       Query tq=NumericRangeQuery.newLongRange(field, precisionStep, lower, upper, true, true);
442       TopDocs tTopDocs = searcher.search(tq, 1);
443       assertEquals("Returned count of range query must be equal to inclusive range length", upper-lower+1, tTopDocs.totalHits );
444       // test exclusive range
445       tq=NumericRangeQuery.newLongRange(field, precisionStep, lower, upper, false, false);
446       tTopDocs = searcher.search(tq, 1);
447       assertEquals("Returned count of range query must be equal to exclusive range length", Math.max(upper-lower-1, 0), tTopDocs.totalHits );
448       // test left exclusive range
449       tq=NumericRangeQuery.newLongRange(field, precisionStep, lower, upper, false, true);
450       tTopDocs = searcher.search(tq, 1);
451       assertEquals("Returned count of range query must be equal to half exclusive range length", upper-lower, tTopDocs.totalHits );
452       // test right exclusive range
453       tq=NumericRangeQuery.newLongRange(field, precisionStep, lower, upper, true, false);
454       tTopDocs = searcher.search(tq, 1);
455       assertEquals("Returned count of range query must be equal to half exclusive range length", upper-lower, tTopDocs.totalHits );
456     }
457   }
458
459   @Test
460   public void testRangeSplit_8bit() throws Exception {
461     testRangeSplit(8);
462   }
463   
464   @Test
465   public void testRangeSplit_6bit() throws Exception {
466     testRangeSplit(6);
467   }
468   
469   @Test
470   public void testRangeSplit_4bit() throws Exception {
471     testRangeSplit(4);
472   }
473   
474   @Test
475   public void testRangeSplit_2bit() throws Exception {
476     testRangeSplit(2);
477   }
478   
479   /** we fake a double test using long2double conversion of NumericUtils */
480   private void testDoubleRange(int precisionStep) throws Exception {
481     final String field="ascfield"+precisionStep;
482     final long lower=-1000L, upper=+2000L;
483     
484     Query tq=NumericRangeQuery.newDoubleRange(field, precisionStep,
485       NumericUtils.sortableLongToDouble(lower), NumericUtils.sortableLongToDouble(upper), true, true);
486     TopDocs tTopDocs = searcher.search(tq, 1);
487     assertEquals("Returned count of range query must be equal to inclusive range length", upper-lower+1, tTopDocs.totalHits );
488     
489     Filter tf=NumericRangeFilter.newDoubleRange(field, precisionStep,
490       NumericUtils.sortableLongToDouble(lower), NumericUtils.sortableLongToDouble(upper), true, true);
491     tTopDocs = searcher.search(new MatchAllDocsQuery(), tf, 1);
492     assertEquals("Returned count of range filter must be equal to inclusive range length", upper-lower+1, tTopDocs.totalHits );
493   }
494
495   @Test
496   public void testDoubleRange_8bit() throws Exception {
497     testDoubleRange(8);
498   }
499   
500   @Test
501   public void testDoubleRange_6bit() throws Exception {
502     testDoubleRange(6);
503   }
504   
505   @Test
506   public void testDoubleRange_4bit() throws Exception {
507     testDoubleRange(4);
508   }
509   
510   @Test
511   public void testDoubleRange_2bit() throws Exception {
512     testDoubleRange(2);
513   }
514   
515   private void testSorting(int precisionStep) throws Exception {
516     String field="field"+precisionStep;
517     // 10 random tests, the index order is ascending,
518     // so using a reverse sort field should retun descending documents
519     int num = _TestUtil.nextInt(random, 10, 20);
520     for (int i = 0; i < num; i++) {
521       long lower=(long)(random.nextDouble()*noDocs*distance)+startOffset;
522       long upper=(long)(random.nextDouble()*noDocs*distance)+startOffset;
523       if (lower>upper) {
524         long a=lower; lower=upper; upper=a;
525       }
526       Query tq=NumericRangeQuery.newLongRange(field, precisionStep, lower, upper, true, true);
527       TopDocs topDocs = searcher.search(tq, null, noDocs, new Sort(new SortField(field, SortField.LONG, true)));
528       if (topDocs.totalHits==0) continue;
529       ScoreDoc[] sd = topDocs.scoreDocs;
530       assertNotNull(sd);
531       long last=Long.parseLong(searcher.doc(sd[0].doc).get(field));
532       for (int j=1; j<sd.length; j++) {
533         long act=Long.parseLong(searcher.doc(sd[j].doc).get(field));
534         assertTrue("Docs should be sorted backwards", last>act );
535         last=act;
536       }
537     }
538   }
539
540   @Test
541   public void testSorting_8bit() throws Exception {
542     testSorting(8);
543   }
544   
545   @Test
546   public void testSorting_6bit() throws Exception {
547     testSorting(6);
548   }
549   
550   @Test
551   public void testSorting_4bit() throws Exception {
552     testSorting(4);
553   }
554   
555   @Test
556   public void testSorting_2bit() throws Exception {
557     testSorting(2);
558   }
559   
560   @Test
561   public void testEqualsAndHash() throws Exception {
562     QueryUtils.checkHashEquals(NumericRangeQuery.newLongRange("test1", 4, 10L, 20L, true, true));
563     QueryUtils.checkHashEquals(NumericRangeQuery.newLongRange("test2", 4, 10L, 20L, false, true));
564     QueryUtils.checkHashEquals(NumericRangeQuery.newLongRange("test3", 4, 10L, 20L, true, false));
565     QueryUtils.checkHashEquals(NumericRangeQuery.newLongRange("test4", 4, 10L, 20L, false, false));
566     QueryUtils.checkHashEquals(NumericRangeQuery.newLongRange("test5", 4, 10L, null, true, true));
567     QueryUtils.checkHashEquals(NumericRangeQuery.newLongRange("test6", 4, null, 20L, true, true));
568     QueryUtils.checkHashEquals(NumericRangeQuery.newLongRange("test7", 4, null, null, true, true));
569     QueryUtils.checkEqual(
570       NumericRangeQuery.newLongRange("test8", 4, 10L, 20L, true, true), 
571       NumericRangeQuery.newLongRange("test8", 4, 10L, 20L, true, true)
572     );
573     QueryUtils.checkUnequal(
574       NumericRangeQuery.newLongRange("test9", 4, 10L, 20L, true, true), 
575       NumericRangeQuery.newLongRange("test9", 8, 10L, 20L, true, true)
576     );
577     QueryUtils.checkUnequal(
578       NumericRangeQuery.newLongRange("test10a", 4, 10L, 20L, true, true), 
579       NumericRangeQuery.newLongRange("test10b", 4, 10L, 20L, true, true)
580     );
581     QueryUtils.checkUnequal(
582       NumericRangeQuery.newLongRange("test11", 4, 10L, 20L, true, true), 
583       NumericRangeQuery.newLongRange("test11", 4, 20L, 10L, true, true)
584     );
585     QueryUtils.checkUnequal(
586       NumericRangeQuery.newLongRange("test12", 4, 10L, 20L, true, true), 
587       NumericRangeQuery.newLongRange("test12", 4, 10L, 20L, false, true)
588     );
589     QueryUtils.checkUnequal(
590       NumericRangeQuery.newLongRange("test13", 4, 10L, 20L, true, true), 
591       NumericRangeQuery.newFloatRange("test13", 4, 10f, 20f, true, true)
592     );
593      // difference to int range is tested in TestNumericRangeQuery32
594   }
595   
596 }