add --shared
[pylucene.git] / lucene-java-3.4.0 / lucene / src / test / org / apache / lucene / search / function / TestFieldScoreQuery.java
1 package org.apache.lucene.search.function;
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 java.util.HashMap;
21
22 import org.apache.lucene.index.IndexReader;
23 import org.apache.lucene.search.IndexSearcher;
24 import org.apache.lucene.search.Query;
25 import org.apache.lucene.search.QueryUtils;
26 import org.apache.lucene.search.ScoreDoc;
27 import org.apache.lucene.search.TopDocs;
28 import org.junit.BeforeClass;
29 import org.junit.Test;
30
31 /**
32  * Test FieldScoreQuery search.
33  * <p>
34  * Tests here create an index with a few documents, each having
35  * an int value indexed  field and a float value indexed field.
36  * The values of these fields are later used for scoring.
37  * <p>
38  * The rank tests use Hits to verify that docs are ordered (by score) as expected.
39  * <p>
40  * The exact score tests use TopDocs top to verify the exact score.  
41  */
42 public class TestFieldScoreQuery extends FunctionTestSetup {
43
44   @BeforeClass
45   public static void beforeClass() throws Exception {
46     createIndex(true);
47   }
48
49   /** Test that FieldScoreQuery of Type.BYTE returns docs in expected order. */
50   @Test
51   public void testRankByte () throws Exception {
52     // INT field values are small enough to be parsed as byte
53     doTestRank(INT_FIELD,FieldScoreQuery.Type.BYTE);
54   }
55
56   /** Test that FieldScoreQuery of Type.SHORT returns docs in expected order. */
57   @Test
58   public void testRankShort () throws Exception {
59     // INT field values are small enough to be parsed as short
60     doTestRank(INT_FIELD,FieldScoreQuery.Type.SHORT);
61   }
62
63   /** Test that FieldScoreQuery of Type.INT returns docs in expected order. */
64   @Test
65   public void testRankInt () throws Exception {
66     doTestRank(INT_FIELD,FieldScoreQuery.Type.INT);
67   }
68
69   /** Test that FieldScoreQuery of Type.FLOAT returns docs in expected order. */
70   @Test
71   public void testRankFloat () throws Exception {
72     // INT field can be parsed as float
73     doTestRank(INT_FIELD,FieldScoreQuery.Type.FLOAT);
74     // same values, but in flot format
75     doTestRank(FLOAT_FIELD,FieldScoreQuery.Type.FLOAT);
76   }
77
78   // Test that FieldScoreQuery returns docs in expected order.
79   private void doTestRank (String field, FieldScoreQuery.Type tp) throws Exception {
80     IndexSearcher s = new IndexSearcher(dir, true);
81     Query q = new FieldScoreQuery(field,tp);
82     log("test: "+q);
83     QueryUtils.check(random, q,s);
84     ScoreDoc[] h = s.search(q, null, 1000).scoreDocs;
85     assertEquals("All docs should be matched!",N_DOCS,h.length);
86     String prevID = "ID"+(N_DOCS+1); // greater than all ids of docs in this test
87     for (int i=0; i<h.length; i++) {
88       String resID = s.doc(h[i].doc).get(ID_FIELD);
89       log(i+".   score="+h[i].score+"  -  "+resID);
90       log(s.explain(q,h[i].doc));
91       assertTrue("res id "+resID+" should be < prev res id "+prevID, resID.compareTo(prevID)<0);
92       prevID = resID;
93     }
94     s.close();
95   }
96
97   /** Test that FieldScoreQuery of Type.BYTE returns the expected scores. */
98   @Test
99   public void testExactScoreByte () throws Exception {
100     // INT field values are small enough to be parsed as byte
101     doTestExactScore(INT_FIELD,FieldScoreQuery.Type.BYTE);
102   }
103
104   /** Test that FieldScoreQuery of Type.SHORT returns the expected scores. */
105   @Test
106   public void testExactScoreShort () throws  Exception {
107     // INT field values are small enough to be parsed as short
108     doTestExactScore(INT_FIELD,FieldScoreQuery.Type.SHORT);
109   }
110
111   /** Test that FieldScoreQuery of Type.INT returns the expected scores. */
112   @Test
113   public void testExactScoreInt () throws  Exception {
114     doTestExactScore(INT_FIELD,FieldScoreQuery.Type.INT);
115   }
116
117   /** Test that FieldScoreQuery of Type.FLOAT returns the expected scores. */
118   @Test
119   public void testExactScoreFloat () throws  Exception {
120     // INT field can be parsed as float
121     doTestExactScore(INT_FIELD,FieldScoreQuery.Type.FLOAT);
122     // same values, but in flot format
123     doTestExactScore(FLOAT_FIELD,FieldScoreQuery.Type.FLOAT);
124   }
125
126   // Test that FieldScoreQuery returns docs with expected score.
127   private void doTestExactScore (String field, FieldScoreQuery.Type tp) throws Exception {
128     IndexSearcher s = new IndexSearcher(dir, true);
129     Query q = new FieldScoreQuery(field,tp);
130     TopDocs td = s.search(q,null,1000);
131     assertEquals("All docs should be matched!",N_DOCS,td.totalHits);
132     ScoreDoc sd[] = td.scoreDocs;
133     for (ScoreDoc aSd : sd) {
134       float score = aSd.score;
135       log(s.explain(q, aSd.doc));
136       String id = s.getIndexReader().document(aSd.doc).get(ID_FIELD);
137       float expectedScore = expectedFieldScore(id); // "ID7" --> 7.0
138       assertEquals("score of " + id + " shuould be " + expectedScore + " != " + score, expectedScore, score, TEST_SCORE_TOLERANCE_DELTA);
139     }
140     s.close();
141   }
142
143   /** Test that FieldScoreQuery of Type.BYTE caches/reuses loaded values and consumes the proper RAM resources. */
144   @Test
145   public void testCachingByte () throws  Exception {
146     // INT field values are small enough to be parsed as byte
147     doTestCaching(INT_FIELD,FieldScoreQuery.Type.BYTE);
148   }
149
150   /** Test that FieldScoreQuery of Type.SHORT caches/reuses loaded values and consumes the proper RAM resources. */
151   @Test
152   public void testCachingShort () throws  Exception {
153     // INT field values are small enough to be parsed as short
154     doTestCaching(INT_FIELD,FieldScoreQuery.Type.SHORT);
155   }
156
157   /** Test that FieldScoreQuery of Type.INT caches/reuses loaded values and consumes the proper RAM resources. */
158   @Test
159   public void testCachingInt () throws Exception {
160     doTestCaching(INT_FIELD,FieldScoreQuery.Type.INT);
161   }
162
163   /** Test that FieldScoreQuery of Type.FLOAT caches/reuses loaded values and consumes the proper RAM resources. */
164   @Test
165   public void testCachingFloat () throws  Exception {
166     // INT field values can be parsed as float
167     doTestCaching(INT_FIELD,FieldScoreQuery.Type.FLOAT);
168     // same values, but in flot format
169     doTestCaching(FLOAT_FIELD,FieldScoreQuery.Type.FLOAT);
170   }
171
172   // Test that values loaded for FieldScoreQuery are cached properly and consumes the proper RAM resources.
173   private void doTestCaching (String field, FieldScoreQuery.Type tp) throws Exception {
174     // prepare expected array types for comparison
175     HashMap<FieldScoreQuery.Type,Object> expectedArrayTypes = new HashMap<FieldScoreQuery.Type,Object>();
176     expectedArrayTypes.put(FieldScoreQuery.Type.BYTE, new byte[0]);
177     expectedArrayTypes.put(FieldScoreQuery.Type.SHORT, new short[0]);
178     expectedArrayTypes.put(FieldScoreQuery.Type.INT, new int[0]);
179     expectedArrayTypes.put(FieldScoreQuery.Type.FLOAT, new float[0]);
180     
181     IndexSearcher s = new IndexSearcher(dir, true);
182     Object[] innerArray = new Object[s.getIndexReader().getSequentialSubReaders().length];
183
184     boolean warned = false; // print warning once.
185     for (int i=0; i<10; i++) {
186       FieldScoreQuery q = new FieldScoreQuery(field,tp);
187       ScoreDoc[] h = s.search(q, null, 1000).scoreDocs;
188       assertEquals("All docs should be matched!",N_DOCS,h.length);
189       IndexReader[] readers = s.getIndexReader().getSequentialSubReaders();
190       for (int j = 0; j < readers.length; j++) {
191         IndexReader reader = readers[j];
192         try {
193           if (i == 0) {
194             innerArray[j] = q.valSrc.getValues(reader).getInnerArray();
195             log(i + ".  compare: " + innerArray[j].getClass() + " to "
196                 + expectedArrayTypes.get(tp).getClass());
197             assertEquals(
198                 "field values should be cached in the correct array type!",
199                 innerArray[j].getClass(), expectedArrayTypes.get(tp).getClass());
200           } else {
201             log(i + ".  compare: " + innerArray[j] + " to "
202                 + q.valSrc.getValues(reader).getInnerArray());
203             assertSame("field values should be cached and reused!", innerArray[j],
204                 q.valSrc.getValues(reader).getInnerArray());
205           }
206         } catch (UnsupportedOperationException e) {
207           if (!warned) {
208             System.err.println("WARNING: " + testName()
209                 + " cannot fully test values of " + q);
210             warned = true;
211           }
212         }
213       }
214     }
215     s.close();
216     // verify new values are reloaded (not reused) for a new reader
217     s = new IndexSearcher(dir, true);
218     FieldScoreQuery q = new FieldScoreQuery(field,tp);
219     ScoreDoc[] h = s.search(q, null, 1000).scoreDocs;
220     assertEquals("All docs should be matched!",N_DOCS,h.length);
221     IndexReader[] readers = s.getIndexReader().getSequentialSubReaders();
222     for (int j = 0; j < readers.length; j++) {
223       IndexReader reader = readers[j];
224       try {
225         log("compare: " + innerArray + " to "
226             + q.valSrc.getValues(reader).getInnerArray());
227         assertNotSame(
228             "cached field values should not be reused if reader as changed!",
229             innerArray, q.valSrc.getValues(reader).getInnerArray());
230       } catch (UnsupportedOperationException e) {
231         if (!warned) {
232           System.err.println("WARNING: " + testName()
233               + " cannot fully test values of " + q);
234           warned = true;
235         }
236       }
237     }
238     s.close();
239   }
240
241   private String testName() {
242     return getClass().getName()+"."+ getName();
243   }
244
245 }