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