mirror of https://github.com/apache/lucene.git
LUCENE-2037: switch to junit 4.7
git-svn-id: https://svn.apache.org/repos/asf/lucene/java/trunk@887569 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
9ee4ce0fd5
commit
f159d7006d
|
@ -63,6 +63,9 @@ Build
|
|||
|
||||
Test Cases
|
||||
|
||||
* LUCENE-2037 Allow Junit4 tests in our envrionment (Erick Erickson
|
||||
via Mike McCandless)
|
||||
|
||||
* LUCENE-1844: Speed up the unit tests (Mark Miller, Erick Erickson,
|
||||
Mike McCandless)
|
||||
|
||||
|
|
|
@ -47,7 +47,7 @@
|
|||
<property name="year" value="2000-${current.year}"/>
|
||||
<property name="final.name" value="lucene-${name}-${version}"/>
|
||||
|
||||
<property name="junit.jar" value="junit-3.8.2.jar"/>
|
||||
<property name="junit.jar" value="junit-4.7.jar"/>
|
||||
<property name="junit-location.jar" value="${common.dir}/lib/${junit.jar}"/>
|
||||
<path id="junit-path">
|
||||
<pathelement location="${junit-location.jar}"/>
|
||||
|
|
|
@ -1,2 +0,0 @@
|
|||
AnyObjectId[c8f711d050eff209321f799d85ebb3bbe305d481] was removed in git history.
|
||||
Apache SVN contains full history.
|
|
@ -0,0 +1,2 @@
|
|||
AnyObjectId[700ad6952c76177568f705f2666ea994da565ba4] was removed in git history.
|
||||
Apache SVN contains full history.
|
|
@ -25,19 +25,22 @@ import org.apache.lucene.document.Fieldable;
|
|||
import org.apache.lucene.index.IndexWriter;
|
||||
import org.apache.lucene.store.Directory;
|
||||
import org.apache.lucene.store.RAMDirectory;
|
||||
|
||||
import org.apache.lucene.util.LuceneTestCase;
|
||||
import org.apache.lucene.util.LuceneTestCaseJ4;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Ignore;
|
||||
|
||||
/**
|
||||
* Setup for function tests
|
||||
*/
|
||||
public abstract class FunctionTestSetup extends LuceneTestCase {
|
||||
@Ignore
|
||||
public class FunctionTestSetup extends LuceneTestCaseJ4 {
|
||||
|
||||
/**
|
||||
* Actual score computation order is slightly different than assumptios
|
||||
* this allows for a small amount of variation
|
||||
*/
|
||||
public static float TEST_SCORE_TOLERANCE_DELTA = 0.001f;
|
||||
protected static float TEST_SCORE_TOLERANCE_DELTA = 0.001f;
|
||||
|
||||
protected static final boolean DBG = false; // change to true for logging to print
|
||||
|
||||
|
@ -49,60 +52,55 @@ public abstract class FunctionTestSetup extends LuceneTestCase {
|
|||
protected static final String FLOAT_FIELD = "fff";
|
||||
|
||||
private static final String DOC_TEXT_LINES[] = {
|
||||
"Well, this is just some plain text we use for creating the ",
|
||||
"test documents. It used to be a text from an online collection ",
|
||||
"devoted to first aid, but if there was there an (online) lawyers ",
|
||||
"first aid collection with legal advices, \"it\" might have quite ",
|
||||
"probably advised one not to include \"it\"'s text or the text of ",
|
||||
"any other online collection in one's code, unless one has money ",
|
||||
"that one don't need and one is happy to donate for lawyers ",
|
||||
"charity. Anyhow at some point, rechecking the usage of this text, ",
|
||||
"it became uncertain that this text is free to use, because ",
|
||||
"the web site in the disclaimer of he eBook containing that text ",
|
||||
"was not responding anymore, and at the same time, in projGut, ",
|
||||
"searching for first aid no longer found that eBook as well. ",
|
||||
"So here we are, with a perhaps much less interesting ",
|
||||
"text for the test, but oh much much safer. ",
|
||||
"Well, this is just some plain text we use for creating the ",
|
||||
"test documents. It used to be a text from an online collection ",
|
||||
"devoted to first aid, but if there was there an (online) lawyers ",
|
||||
"first aid collection with legal advices, \"it\" might have quite ",
|
||||
"probably advised one not to include \"it\"'s text or the text of ",
|
||||
"any other online collection in one's code, unless one has money ",
|
||||
"that one don't need and one is happy to donate for lawyers ",
|
||||
"charity. Anyhow at some point, rechecking the usage of this text, ",
|
||||
"it became uncertain that this text is free to use, because ",
|
||||
"the web site in the disclaimer of he eBook containing that text ",
|
||||
"was not responding anymore, and at the same time, in projGut, ",
|
||||
"searching for first aid no longer found that eBook as well. ",
|
||||
"So here we are, with a perhaps much less interesting ",
|
||||
"text for the test, but oh much much safer. ",
|
||||
};
|
||||
|
||||
protected Directory dir;
|
||||
protected Analyzer anlzr;
|
||||
protected Directory dir = null;
|
||||
protected Analyzer anlzr = null;
|
||||
|
||||
/* @override constructor */
|
||||
public FunctionTestSetup(String name) {
|
||||
super(name);
|
||||
}
|
||||
|
||||
/* @override */
|
||||
@Override
|
||||
protected void tearDown() throws Exception {
|
||||
@After
|
||||
public void tearDown() throws Exception {
|
||||
super.tearDown();
|
||||
dir = null;
|
||||
anlzr = null;
|
||||
}
|
||||
|
||||
/* @override */
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
super.setUp();
|
||||
// prepare a small index with just a few documents.
|
||||
super.setUp();
|
||||
dir = new RAMDirectory();
|
||||
anlzr = new StandardAnalyzer(org.apache.lucene.util.Version.LUCENE_CURRENT);
|
||||
IndexWriter iw = new IndexWriter(dir, anlzr,
|
||||
IndexWriter.MaxFieldLength.LIMITED);
|
||||
IndexWriter.MaxFieldLength.LIMITED);
|
||||
// add docs not exactly in natural ID order, to verify we do check the order of docs by scores
|
||||
int remaining = N_DOCS;
|
||||
boolean done[] = new boolean[N_DOCS];
|
||||
int i = 0;
|
||||
while (remaining>0) {
|
||||
while (remaining > 0) {
|
||||
if (done[i]) {
|
||||
throw new Exception("to set this test correctly N_DOCS="+N_DOCS+" must be primary and greater than 2!");
|
||||
throw new Exception("to set this test correctly N_DOCS=" + N_DOCS + " must be primary and greater than 2!");
|
||||
}
|
||||
addDoc(iw,i);
|
||||
addDoc(iw, i);
|
||||
done[i] = true;
|
||||
i = (i+4)%N_DOCS;
|
||||
remaining --;
|
||||
i = (i + 4) % N_DOCS;
|
||||
remaining--;
|
||||
}
|
||||
iw.close();
|
||||
}
|
||||
|
@ -110,34 +108,34 @@ public abstract class FunctionTestSetup extends LuceneTestCase {
|
|||
private void addDoc(IndexWriter iw, int i) throws Exception {
|
||||
Document d = new Document();
|
||||
Fieldable f;
|
||||
int scoreAndID = i+1;
|
||||
int scoreAndID = i + 1;
|
||||
|
||||
f = new Field(ID_FIELD,id2String(scoreAndID),Field.Store.YES,Field.Index.NOT_ANALYZED); // for debug purposes
|
||||
f = new Field(ID_FIELD, id2String(scoreAndID), Field.Store.YES, Field.Index.NOT_ANALYZED); // for debug purposes
|
||||
f.setOmitNorms(true);
|
||||
d.add(f);
|
||||
|
||||
f = new Field(TEXT_FIELD,"text of doc"+scoreAndID+textLine(i),Field.Store.NO,Field.Index.ANALYZED); // for regular search
|
||||
f = new Field(TEXT_FIELD, "text of doc" + scoreAndID + textLine(i), Field.Store.NO, Field.Index.ANALYZED); // for regular search
|
||||
f.setOmitNorms(true);
|
||||
d.add(f);
|
||||
|
||||
f = new Field(INT_FIELD,""+scoreAndID,Field.Store.NO,Field.Index.NOT_ANALYZED); // for function scoring
|
||||
f = new Field(INT_FIELD, "" + scoreAndID, Field.Store.NO, Field.Index.NOT_ANALYZED); // for function scoring
|
||||
f.setOmitNorms(true);
|
||||
d.add(f);
|
||||
|
||||
f = new Field(FLOAT_FIELD,scoreAndID+".000",Field.Store.NO,Field.Index.NOT_ANALYZED); // for function scoring
|
||||
f = new Field(FLOAT_FIELD, scoreAndID + ".000", Field.Store.NO, Field.Index.NOT_ANALYZED); // for function scoring
|
||||
f.setOmitNorms(true);
|
||||
d.add(f);
|
||||
|
||||
iw.addDocument(d);
|
||||
log("added: "+d);
|
||||
log("added: " + d);
|
||||
}
|
||||
|
||||
// 17 --> ID00017
|
||||
protected String id2String(int scoreAndID) {
|
||||
String s = "000000000"+scoreAndID;
|
||||
int n = (""+N_DOCS).length() + 3;
|
||||
String s = "000000000" + scoreAndID;
|
||||
int n = ("" + N_DOCS).length() + 3;
|
||||
int k = s.length() - n;
|
||||
return "ID"+s.substring(k);
|
||||
return "ID" + s.substring(k);
|
||||
}
|
||||
|
||||
// some text line for regular search
|
||||
|
@ -151,7 +149,7 @@ public abstract class FunctionTestSetup extends LuceneTestCase {
|
|||
}
|
||||
|
||||
// debug messages (change DBG to true for anything to print)
|
||||
protected void log (Object o) {
|
||||
protected void log(Object o) {
|
||||
if (DBG) {
|
||||
System.out.println(o.toString());
|
||||
}
|
||||
|
|
|
@ -17,11 +17,11 @@ package org.apache.lucene.search.function;
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.apache.lucene.index.IndexReader;
|
||||
import org.apache.lucene.search.FieldCache;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Holds all implementations of classes in the o.a.l.s.function package as a
|
||||
* back-compatibility test. It does not run any tests per-se, however if
|
||||
|
@ -34,7 +34,6 @@ final class JustCompileSearchFunction {
|
|||
private static final String UNSUPPORTED_MSG = "unsupported: used for back-compat testing only !";
|
||||
|
||||
static final class JustCompileDocValues extends DocValues {
|
||||
|
||||
@Override
|
||||
public float floatVal(int doc) {
|
||||
throw new UnsupportedOperationException(UNSUPPORTED_MSG);
|
||||
|
@ -65,14 +64,13 @@ final class JustCompileSearchFunction {
|
|||
|
||||
@Override
|
||||
public DocValues getCachedFieldValues(FieldCache cache, String field,
|
||||
IndexReader reader) throws IOException {
|
||||
IndexReader reader) throws IOException {
|
||||
throw new UnsupportedOperationException(UNSUPPORTED_MSG);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static final class JustCompileValueSource extends ValueSource {
|
||||
|
||||
@Override
|
||||
public String description() {
|
||||
throw new UnsupportedOperationException(UNSUPPORTED_MSG);
|
||||
|
|
|
@ -17,79 +17,92 @@ package org.apache.lucene.search.function;
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import org.apache.lucene.queryParser.QueryParser;
|
||||
import org.apache.lucene.queryParser.ParseException;
|
||||
import org.apache.lucene.search.*;
|
||||
import org.apache.lucene.util.Version;
|
||||
import org.junit.Test;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
|
||||
import org.apache.lucene.index.CorruptIndexException;
|
||||
import org.apache.lucene.queryParser.QueryParser;
|
||||
import org.apache.lucene.search.Explanation;
|
||||
import org.apache.lucene.search.IndexSearcher;
|
||||
import org.apache.lucene.search.Query;
|
||||
import org.apache.lucene.search.QueryUtils;
|
||||
import org.apache.lucene.search.TopDocs;
|
||||
import org.apache.lucene.util.Version;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Test CustomScoreQuery search.
|
||||
*/
|
||||
@SuppressWarnings({"MagicNumber"})
|
||||
public class TestCustomScoreQuery extends FunctionTestSetup {
|
||||
|
||||
/* @override constructor */
|
||||
public TestCustomScoreQuery(String name) {
|
||||
super(name);
|
||||
}
|
||||
|
||||
/** Test that CustomScoreQuery of Type.BYTE returns the expected scores. */
|
||||
public void testCustomScoreByte () throws CorruptIndexException, Exception {
|
||||
/**
|
||||
* Test that CustomScoreQuery of Type.BYTE returns the expected scores.
|
||||
*/
|
||||
@Test
|
||||
public void testCustomScoreByte() throws Exception, ParseException {
|
||||
// INT field values are small enough to be parsed as byte
|
||||
doTestCustomScore(INT_FIELD,FieldScoreQuery.Type.BYTE,1.0);
|
||||
doTestCustomScore(INT_FIELD,FieldScoreQuery.Type.BYTE,2.0);
|
||||
doTestCustomScore(INT_FIELD, FieldScoreQuery.Type.BYTE, 1.0);
|
||||
doTestCustomScore(INT_FIELD, FieldScoreQuery.Type.BYTE, 2.0);
|
||||
}
|
||||
|
||||
/** Test that CustomScoreQuery of Type.SHORT returns the expected scores. */
|
||||
public void testCustomScoreShort () throws CorruptIndexException, Exception {
|
||||
/**
|
||||
* Test that CustomScoreQuery of Type.SHORT returns the expected scores.
|
||||
*/
|
||||
@Test
|
||||
public void testCustomScoreShort() throws Exception, ParseException {
|
||||
// INT field values are small enough to be parsed as short
|
||||
doTestCustomScore(INT_FIELD,FieldScoreQuery.Type.SHORT,1.0);
|
||||
doTestCustomScore(INT_FIELD,FieldScoreQuery.Type.SHORT,3.0);
|
||||
doTestCustomScore(INT_FIELD, FieldScoreQuery.Type.SHORT, 1.0);
|
||||
doTestCustomScore(INT_FIELD, FieldScoreQuery.Type.SHORT, 3.0);
|
||||
}
|
||||
|
||||
/** Test that CustomScoreQuery of Type.INT returns the expected scores. */
|
||||
public void testCustomScoreInt () throws CorruptIndexException, Exception {
|
||||
doTestCustomScore(INT_FIELD,FieldScoreQuery.Type.INT,1.0);
|
||||
doTestCustomScore(INT_FIELD,FieldScoreQuery.Type.INT,4.0);
|
||||
/**
|
||||
* Test that CustomScoreQuery of Type.INT returns the expected scores.
|
||||
*/
|
||||
@Test
|
||||
public void testCustomScoreInt() throws Exception, ParseException {
|
||||
doTestCustomScore(INT_FIELD, FieldScoreQuery.Type.INT, 1.0);
|
||||
doTestCustomScore(INT_FIELD, FieldScoreQuery.Type.INT, 4.0);
|
||||
}
|
||||
|
||||
/** Test that CustomScoreQuery of Type.FLOAT returns the expected scores. */
|
||||
public void testCustomScoreFloat () throws CorruptIndexException, Exception {
|
||||
/**
|
||||
* Test that CustomScoreQuery of Type.FLOAT returns the expected scores.
|
||||
*/
|
||||
@Test
|
||||
public void testCustomScoreFloat() throws Exception, ParseException {
|
||||
// INT field can be parsed as float
|
||||
doTestCustomScore(INT_FIELD,FieldScoreQuery.Type.FLOAT,1.0);
|
||||
doTestCustomScore(INT_FIELD,FieldScoreQuery.Type.FLOAT,5.0);
|
||||
doTestCustomScore(INT_FIELD, FieldScoreQuery.Type.FLOAT, 1.0);
|
||||
doTestCustomScore(INT_FIELD, FieldScoreQuery.Type.FLOAT, 5.0);
|
||||
// same values, but in flot format
|
||||
doTestCustomScore(FLOAT_FIELD,FieldScoreQuery.Type.FLOAT,1.0);
|
||||
doTestCustomScore(FLOAT_FIELD,FieldScoreQuery.Type.FLOAT,6.0);
|
||||
doTestCustomScore(FLOAT_FIELD, FieldScoreQuery.Type.FLOAT, 1.0);
|
||||
doTestCustomScore(FLOAT_FIELD, FieldScoreQuery.Type.FLOAT, 6.0);
|
||||
}
|
||||
|
||||
// must have static class otherwise serialization tests fail
|
||||
@SuppressWarnings({"SerializableHasSerializationMethods", "serial"})
|
||||
private static class CustomAddQuery extends CustomScoreQuery {
|
||||
// constructor
|
||||
CustomAddQuery (Query q, ValueSourceQuery qValSrc) {
|
||||
super(q,qValSrc);
|
||||
CustomAddQuery(Query q, ValueSourceQuery qValSrc) {
|
||||
super(q, qValSrc);
|
||||
}
|
||||
|
||||
/*(non-Javadoc) @see org.apache.lucene.search.function.CustomScoreQuery#name() */
|
||||
@Override
|
||||
public String name() {
|
||||
return "customAdd";
|
||||
}
|
||||
|
||||
/*(non-Javadoc) @see org.apache.lucene.search.function.CustomScoreQuery#customScore(int, float, float) */
|
||||
@Override
|
||||
public float customScore(int doc, float subQueryScore, float valSrcScore) {
|
||||
return subQueryScore + valSrcScore;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)@see org.apache.lucene.search.function.CustomScoreQuery#customExplain(int, org.apache.lucene.search.Explanation, org.apache.lucene.search.Explanation)*/
|
||||
@Override
|
||||
public Explanation customExplain(int doc, Explanation subQueryExpl, Explanation valSrcExpl) {
|
||||
float valSrcScore = valSrcExpl==null ? 0 : valSrcExpl.getValue();
|
||||
Explanation exp = new Explanation( valSrcScore + subQueryExpl.getValue(), "custom score: sum of:");
|
||||
float valSrcScore = valSrcExpl == null ? 0 : valSrcExpl.getValue();
|
||||
Explanation exp = new Explanation(valSrcScore + subQueryExpl.getValue(), "custom score: sum of:");
|
||||
exp.addDetail(subQueryExpl);
|
||||
if (valSrcExpl != null) {
|
||||
exp.addDetail(valSrcExpl);
|
||||
|
@ -99,16 +112,19 @@ public class TestCustomScoreQuery extends FunctionTestSetup {
|
|||
}
|
||||
|
||||
// must have static class otherwise serialization tests fail
|
||||
@SuppressWarnings({"SerializableHasSerializationMethods", "serial"})
|
||||
private static class CustomMulAddQuery extends CustomScoreQuery {
|
||||
// constructor
|
||||
CustomMulAddQuery(Query q, ValueSourceQuery qValSrc1, ValueSourceQuery qValSrc2) {
|
||||
super(q,new ValueSourceQuery[]{qValSrc1,qValSrc2});
|
||||
super(q, new ValueSourceQuery[]{qValSrc1, qValSrc2});
|
||||
}
|
||||
|
||||
/*(non-Javadoc) @see org.apache.lucene.search.function.CustomScoreQuery#name() */
|
||||
@Override
|
||||
public String name() {
|
||||
return "customMulAdd";
|
||||
}
|
||||
|
||||
/*(non-Javadoc) @see org.apache.lucene.search.function.CustomScoreQuery#customScore(int, float, float) */
|
||||
@Override
|
||||
public float customScore(int doc, float subQueryScore, float valSrcScores[]) {
|
||||
|
@ -120,6 +136,7 @@ public class TestCustomScoreQuery extends FunctionTestSetup {
|
|||
}
|
||||
return (subQueryScore + valSrcScores[0]) * valSrcScores[1]; // we know there are two
|
||||
}
|
||||
|
||||
/* (non-Javadoc)@see org.apache.lucene.search.function.CustomScoreQuery#customExplain(int, org.apache.lucene.search.Explanation, org.apache.lucene.search.Explanation)*/
|
||||
@Override
|
||||
public Explanation customExplain(int doc, Explanation subQueryExpl, Explanation valSrcExpls[]) {
|
||||
|
@ -141,11 +158,11 @@ public class TestCustomScoreQuery extends FunctionTestSetup {
|
|||
}
|
||||
|
||||
// Test that FieldScoreQuery returns docs with expected score.
|
||||
private void doTestCustomScore (String field, FieldScoreQuery.Type tp, double dboost) throws CorruptIndexException, Exception {
|
||||
private void doTestCustomScore(String field, FieldScoreQuery.Type tp, double dboost) throws Exception, ParseException {
|
||||
float boost = (float) dboost;
|
||||
IndexSearcher s = new IndexSearcher(dir, true);
|
||||
FieldScoreQuery qValSrc = new FieldScoreQuery(field,tp); // a query that would score by the field
|
||||
QueryParser qp = new QueryParser(Version.LUCENE_CURRENT, TEXT_FIELD,anlzr);
|
||||
FieldScoreQuery qValSrc = new FieldScoreQuery(field, tp); // a query that would score by the field
|
||||
QueryParser qp = new QueryParser(Version.LUCENE_CURRENT, TEXT_FIELD, anlzr);
|
||||
String qtxt = "first aid text"; // from the doc texts in FunctionQuerySetup.
|
||||
|
||||
// regular (boolean) query.
|
||||
|
@ -153,41 +170,41 @@ public class TestCustomScoreQuery extends FunctionTestSetup {
|
|||
log(q1);
|
||||
|
||||
// custom query, that should score the same as q1.
|
||||
CustomScoreQuery q2CustomNeutral = new CustomScoreQuery(q1);
|
||||
Query q2CustomNeutral = new CustomScoreQuery(q1);
|
||||
q2CustomNeutral.setBoost(boost);
|
||||
log(q2CustomNeutral);
|
||||
|
||||
// custom query, that should (by default) multiply the scores of q1 by that of the field
|
||||
CustomScoreQuery q3CustomMul = new CustomScoreQuery(q1,qValSrc);
|
||||
CustomScoreQuery q3CustomMul = new CustomScoreQuery(q1, qValSrc);
|
||||
q3CustomMul.setStrict(true);
|
||||
q3CustomMul.setBoost(boost);
|
||||
log(q3CustomMul);
|
||||
|
||||
// custom query, that should add the scores of q1 to that of the field
|
||||
CustomScoreQuery q4CustomAdd = new CustomAddQuery(q1,qValSrc);
|
||||
CustomScoreQuery q4CustomAdd = new CustomAddQuery(q1, qValSrc);
|
||||
q4CustomAdd.setStrict(true);
|
||||
q4CustomAdd.setBoost(boost);
|
||||
log(q4CustomAdd);
|
||||
|
||||
// custom query, that multiplies and adds the field score to that of q1
|
||||
CustomScoreQuery q5CustomMulAdd = new CustomMulAddQuery(q1,qValSrc,qValSrc);
|
||||
CustomScoreQuery q5CustomMulAdd = new CustomMulAddQuery(q1, qValSrc, qValSrc);
|
||||
q5CustomMulAdd.setStrict(true);
|
||||
q5CustomMulAdd.setBoost(boost);
|
||||
log(q5CustomMulAdd);
|
||||
|
||||
// do al the searches
|
||||
TopDocs td1 = s.search(q1,null,1000);
|
||||
TopDocs td2CustomNeutral = s.search(q2CustomNeutral,null,1000);
|
||||
TopDocs td3CustomMul = s.search(q3CustomMul,null,1000);
|
||||
TopDocs td4CustomAdd = s.search(q4CustomAdd,null,1000);
|
||||
TopDocs td5CustomMulAdd = s.search(q5CustomMulAdd,null,1000);
|
||||
TopDocs td1 = s.search(q1, null, 1000);
|
||||
TopDocs td2CustomNeutral = s.search(q2CustomNeutral, null, 1000);
|
||||
TopDocs td3CustomMul = s.search(q3CustomMul, null, 1000);
|
||||
TopDocs td4CustomAdd = s.search(q4CustomAdd, null, 1000);
|
||||
TopDocs td5CustomMulAdd = s.search(q5CustomMulAdd, null, 1000);
|
||||
|
||||
// put results in map so we can verify the scores although they have changed
|
||||
HashMap<Integer,Float> h1 = topDocsToMap(td1);
|
||||
HashMap<Integer,Float> h2CustomNeutral = topDocsToMap(td2CustomNeutral);
|
||||
HashMap<Integer,Float> h3CustomMul = topDocsToMap(td3CustomMul);
|
||||
HashMap<Integer,Float> h4CustomAdd = topDocsToMap(td4CustomAdd);
|
||||
HashMap<Integer,Float> h5CustomMulAdd = topDocsToMap(td5CustomMulAdd);
|
||||
Map<Integer,Float> h1 = topDocsToMap(td1);
|
||||
Map<Integer,Float> h2CustomNeutral = topDocsToMap(td2CustomNeutral);
|
||||
Map<Integer,Float> h3CustomMul = topDocsToMap(td3CustomMul);
|
||||
Map<Integer,Float> h4CustomAdd = topDocsToMap(td4CustomAdd);
|
||||
Map<Integer,Float> h5CustomMulAdd = topDocsToMap(td5CustomMulAdd);
|
||||
|
||||
verifyResults(boost, s,
|
||||
h1, h2CustomNeutral, h3CustomMul, h4CustomAdd, h5CustomMulAdd,
|
||||
|
@ -196,7 +213,7 @@ public class TestCustomScoreQuery extends FunctionTestSetup {
|
|||
|
||||
// verify results are as expected.
|
||||
private void verifyResults(float boost, IndexSearcher s,
|
||||
HashMap<Integer,Float> h1, HashMap<Integer,Float> h2customNeutral, HashMap<Integer,Float> h3CustomMul, HashMap<Integer,Float> h4CustomAdd, HashMap<Integer,Float> h5CustomMulAdd,
|
||||
Map<Integer,Float> h1, Map<Integer,Float> h2customNeutral, Map<Integer,Float> h3CustomMul, Map<Integer,Float> h4CustomAdd, Map<Integer,Float> h5CustomMulAdd,
|
||||
Query q1, Query q2, Query q3, Query q4, Query q5) throws Exception {
|
||||
|
||||
// verify numbers of matches
|
||||
|
@ -213,37 +230,36 @@ public class TestCustomScoreQuery extends FunctionTestSetup {
|
|||
QueryUtils.check(q5,s);
|
||||
|
||||
// verify scores ratios
|
||||
for (final Integer x : h1.keySet()) {
|
||||
for (final Integer doc : h1.keySet()) {
|
||||
|
||||
int doc = x.intValue();
|
||||
log("doc = "+doc);
|
||||
|
||||
float fieldScore = expectedFieldScore(s.getIndexReader().document(doc).get(ID_FIELD));
|
||||
log("fieldScore = "+fieldScore);
|
||||
assertTrue("fieldScore should not be 0",fieldScore>0);
|
||||
log("fieldScore = " + fieldScore);
|
||||
assertTrue("fieldScore should not be 0", fieldScore > 0);
|
||||
|
||||
float score1 = h1.get(x).floatValue();
|
||||
float score1 = h1.get(doc);
|
||||
logResult("score1=", s, q1, doc, score1);
|
||||
|
||||
float score2 = h2customNeutral.get(x).floatValue();
|
||||
float score2 = h2customNeutral.get(doc);
|
||||
logResult("score2=", s, q2, doc, score2);
|
||||
assertEquals("same score (just boosted) for neutral", boost * score1, score2, TEST_SCORE_TOLERANCE_DELTA);
|
||||
|
||||
float score3 = h3CustomMul.get(x).floatValue();
|
||||
float score3 = h3CustomMul.get(doc);
|
||||
logResult("score3=", s, q3, doc, score3);
|
||||
assertEquals("new score for custom mul", boost * fieldScore * score1, score3, TEST_SCORE_TOLERANCE_DELTA);
|
||||
|
||||
float score4 = h4CustomAdd.get(x).floatValue();
|
||||
float score4 = h4CustomAdd.get(doc);
|
||||
logResult("score4=", s, q4, doc, score4);
|
||||
assertEquals("new score for custom add", boost * (fieldScore + score1), score4, TEST_SCORE_TOLERANCE_DELTA);
|
||||
|
||||
float score5 = h5CustomMulAdd.get(x).floatValue();
|
||||
float score5 = h5CustomMulAdd.get(doc);
|
||||
logResult("score5=", s, q5, doc, score5);
|
||||
assertEquals("new score for custom mul add", boost * fieldScore * (score1 + fieldScore), score5, TEST_SCORE_TOLERANCE_DELTA);
|
||||
}
|
||||
}
|
||||
|
||||
private void logResult(String msg, IndexSearcher s, Query q, int doc, float score1) throws IOException {
|
||||
private void logResult(String msg, Searcher s, Query q, int doc, float score1) throws IOException {
|
||||
log(msg+" "+score1);
|
||||
log("Explain by: "+q);
|
||||
log(s.explain(q,doc));
|
||||
|
@ -251,10 +267,10 @@ public class TestCustomScoreQuery extends FunctionTestSetup {
|
|||
|
||||
// since custom scoring modifies the order of docs, map results
|
||||
// by doc ids so that we can later compare/verify them
|
||||
private HashMap<Integer,Float> topDocsToMap(TopDocs td) {
|
||||
HashMap<Integer,Float> h = new HashMap<Integer,Float>();
|
||||
private Map<Integer,Float> topDocsToMap(TopDocs td) {
|
||||
Map<Integer,Float> h = new HashMap<Integer,Float>();
|
||||
for (int i=0; i<td.totalHits; i++) {
|
||||
h.put(Integer.valueOf(td.scoreDocs[i].doc), Float.valueOf(td.scoreDocs[i].score));
|
||||
h.put(td.scoreDocs[i].doc, td.scoreDocs[i].score);
|
||||
}
|
||||
return h;
|
||||
}
|
||||
|
|
|
@ -17,18 +17,17 @@ package org.apache.lucene.search.function;
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import org.apache.lucene.util.LuceneTestCase;
|
||||
import org.apache.lucene.util.LuceneTestCaseJ4;
|
||||
import org.junit.Test;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
/**
|
||||
* DocValues TestCase
|
||||
*/
|
||||
public class TestDocValues extends LuceneTestCase {
|
||||
|
||||
/* @override constructor */
|
||||
public TestDocValues(String name) {
|
||||
super(name);
|
||||
}
|
||||
public class TestDocValues extends LuceneTestCaseJ4 {
|
||||
|
||||
@Test
|
||||
public void testGetMinValue() {
|
||||
float[] innerArray = new float[] { 1.0f, 2.0f, -1.0f, 100.0f };
|
||||
DocValuesTestImpl docValues = new DocValuesTestImpl(innerArray);
|
||||
|
@ -41,7 +40,7 @@ public class TestDocValues extends LuceneTestCase {
|
|||
assertTrue("max is NaN - no values in inner array", Float.isNaN(docValues
|
||||
.getMinValue()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetMaxValue() {
|
||||
float[] innerArray = new float[] { 1.0f, 2.0f, -1.0f, 10.0f };
|
||||
DocValuesTestImpl docValues = new DocValuesTestImpl(innerArray);
|
||||
|
@ -66,6 +65,7 @@ public class TestDocValues extends LuceneTestCase {
|
|||
.getMaxValue()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetAverageValue() {
|
||||
float[] innerArray = new float[] { 1.0f, 1.0f, 1.0f, 1.0f };
|
||||
DocValuesTestImpl docValues = new DocValuesTestImpl(innerArray);
|
||||
|
@ -97,7 +97,6 @@ public class TestDocValues extends LuceneTestCase {
|
|||
/**
|
||||
* @see org.apache.lucene.search.function.DocValues#floatVal(int)
|
||||
*/
|
||||
/* @Override */
|
||||
@Override
|
||||
public float floatVal(int doc) {
|
||||
return innerArray[doc];
|
||||
|
@ -106,7 +105,6 @@ public class TestDocValues extends LuceneTestCase {
|
|||
/**
|
||||
* @see org.apache.lucene.search.function.DocValues#toString(int)
|
||||
*/
|
||||
/* @Override */
|
||||
@Override
|
||||
public String toString(int doc) {
|
||||
return Integer.toString(doc);
|
||||
|
|
|
@ -18,14 +18,16 @@ package org.apache.lucene.search.function;
|
|||
*/
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.lucene.index.CorruptIndexException;
|
||||
import org.apache.lucene.index.IndexReader;
|
||||
import org.apache.lucene.search.IndexSearcher;
|
||||
import org.apache.lucene.search.Query;
|
||||
import org.apache.lucene.search.QueryUtils;
|
||||
import org.apache.lucene.search.ScoreDoc;
|
||||
import org.apache.lucene.search.TopDocs;
|
||||
import org.junit.Test;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* Test FieldScoreQuery search.
|
||||
|
@ -38,32 +40,32 @@ import org.apache.lucene.search.TopDocs;
|
|||
* <p>
|
||||
* The exact score tests use TopDocs top to verify the exact score.
|
||||
*/
|
||||
@SuppressWarnings({"UseOfSystemOutOrSystemErr"})
|
||||
public class TestFieldScoreQuery extends FunctionTestSetup {
|
||||
|
||||
/* @override constructor */
|
||||
public TestFieldScoreQuery(String name) {
|
||||
super(name);
|
||||
}
|
||||
|
||||
/** Test that FieldScoreQuery of Type.BYTE returns docs in expected order. */
|
||||
public void testRankByte () throws CorruptIndexException, Exception {
|
||||
@Test
|
||||
public void testRankByte () throws Exception {
|
||||
// INT field values are small enough to be parsed as byte
|
||||
doTestRank(INT_FIELD,FieldScoreQuery.Type.BYTE);
|
||||
}
|
||||
|
||||
/** Test that FieldScoreQuery of Type.SHORT returns docs in expected order. */
|
||||
public void testRankShort () throws CorruptIndexException, Exception {
|
||||
@Test
|
||||
public void testRankShort () throws Exception {
|
||||
// INT field values are small enough to be parsed as short
|
||||
doTestRank(INT_FIELD,FieldScoreQuery.Type.SHORT);
|
||||
}
|
||||
|
||||
/** Test that FieldScoreQuery of Type.INT returns docs in expected order. */
|
||||
public void testRankInt () throws CorruptIndexException, Exception {
|
||||
@Test
|
||||
public void testRankInt () throws Exception {
|
||||
doTestRank(INT_FIELD,FieldScoreQuery.Type.INT);
|
||||
}
|
||||
|
||||
/** Test that FieldScoreQuery of Type.FLOAT returns docs in expected order. */
|
||||
public void testRankFloat () throws CorruptIndexException, Exception {
|
||||
@Test
|
||||
public void testRankFloat () throws Exception {
|
||||
// INT field can be parsed as float
|
||||
doTestRank(INT_FIELD,FieldScoreQuery.Type.FLOAT);
|
||||
// same values, but in flot format
|
||||
|
@ -71,7 +73,7 @@ public class TestFieldScoreQuery extends FunctionTestSetup {
|
|||
}
|
||||
|
||||
// Test that FieldScoreQuery returns docs in expected order.
|
||||
private void doTestRank (String field, FieldScoreQuery.Type tp) throws CorruptIndexException, Exception {
|
||||
private void doTestRank (String field, FieldScoreQuery.Type tp) throws Exception {
|
||||
IndexSearcher s = new IndexSearcher(dir, true);
|
||||
Query q = new FieldScoreQuery(field,tp);
|
||||
log("test: "+q);
|
||||
|
@ -89,24 +91,28 @@ public class TestFieldScoreQuery extends FunctionTestSetup {
|
|||
}
|
||||
|
||||
/** Test that FieldScoreQuery of Type.BYTE returns the expected scores. */
|
||||
public void testExactScoreByte () throws CorruptIndexException, Exception {
|
||||
@Test
|
||||
public void testExactScoreByte () throws Exception {
|
||||
// INT field values are small enough to be parsed as byte
|
||||
doTestExactScore(INT_FIELD,FieldScoreQuery.Type.BYTE);
|
||||
}
|
||||
|
||||
/** Test that FieldScoreQuery of Type.SHORT returns the expected scores. */
|
||||
public void testExactScoreShort () throws CorruptIndexException, Exception {
|
||||
@Test
|
||||
public void testExactScoreShort () throws Exception {
|
||||
// INT field values are small enough to be parsed as short
|
||||
doTestExactScore(INT_FIELD,FieldScoreQuery.Type.SHORT);
|
||||
}
|
||||
|
||||
/** Test that FieldScoreQuery of Type.INT returns the expected scores. */
|
||||
public void testExactScoreInt () throws CorruptIndexException, Exception {
|
||||
@Test
|
||||
public void testExactScoreInt () throws Exception {
|
||||
doTestExactScore(INT_FIELD,FieldScoreQuery.Type.INT);
|
||||
}
|
||||
|
||||
/** Test that FieldScoreQuery of Type.FLOAT returns the expected scores. */
|
||||
public void testExactScoreFloat () throws CorruptIndexException, Exception {
|
||||
@Test
|
||||
public void testExactScoreFloat () throws Exception {
|
||||
// INT field can be parsed as float
|
||||
doTestExactScore(INT_FIELD,FieldScoreQuery.Type.FLOAT);
|
||||
// same values, but in flot format
|
||||
|
@ -114,40 +120,44 @@ public class TestFieldScoreQuery extends FunctionTestSetup {
|
|||
}
|
||||
|
||||
// Test that FieldScoreQuery returns docs with expected score.
|
||||
private void doTestExactScore (String field, FieldScoreQuery.Type tp) throws CorruptIndexException, Exception {
|
||||
private void doTestExactScore (String field, FieldScoreQuery.Type tp) throws Exception {
|
||||
IndexSearcher s = new IndexSearcher(dir, true);
|
||||
Query q = new FieldScoreQuery(field,tp);
|
||||
TopDocs td = s.search(q,null,1000);
|
||||
assertEquals("All docs should be matched!",N_DOCS,td.totalHits);
|
||||
ScoreDoc sd[] = td.scoreDocs;
|
||||
for (int i=0; i<sd.length; i++) {
|
||||
float score = sd[i].score;
|
||||
log(s.explain(q,sd[i].doc));
|
||||
String id = s.getIndexReader().document(sd[i].doc).get(ID_FIELD);
|
||||
for (ScoreDoc aSd : sd) {
|
||||
float score = aSd.score;
|
||||
log(s.explain(q, aSd.doc));
|
||||
String id = s.getIndexReader().document(aSd.doc).get(ID_FIELD);
|
||||
float expectedScore = expectedFieldScore(id); // "ID7" --> 7.0
|
||||
assertEquals("score of "+id+" shuould be "+expectedScore+" != "+score, expectedScore, score, TEST_SCORE_TOLERANCE_DELTA);
|
||||
assertEquals("score of " + id + " shuould be " + expectedScore + " != " + score, expectedScore, score, TEST_SCORE_TOLERANCE_DELTA);
|
||||
}
|
||||
}
|
||||
|
||||
/** Test that FieldScoreQuery of Type.BYTE caches/reuses loaded values and consumes the proper RAM resources. */
|
||||
public void testCachingByte () throws CorruptIndexException, Exception {
|
||||
@Test
|
||||
public void testCachingByte () throws Exception {
|
||||
// INT field values are small enough to be parsed as byte
|
||||
doTestCaching(INT_FIELD,FieldScoreQuery.Type.BYTE);
|
||||
}
|
||||
|
||||
/** Test that FieldScoreQuery of Type.SHORT caches/reuses loaded values and consumes the proper RAM resources. */
|
||||
public void testCachingShort () throws CorruptIndexException, Exception {
|
||||
@Test
|
||||
public void testCachingShort () throws Exception {
|
||||
// INT field values are small enough to be parsed as short
|
||||
doTestCaching(INT_FIELD,FieldScoreQuery.Type.SHORT);
|
||||
}
|
||||
|
||||
/** Test that FieldScoreQuery of Type.INT caches/reuses loaded values and consumes the proper RAM resources. */
|
||||
public void testCachingInt () throws CorruptIndexException, Exception {
|
||||
@Test
|
||||
public void testCachingInt () throws Exception {
|
||||
doTestCaching(INT_FIELD,FieldScoreQuery.Type.INT);
|
||||
}
|
||||
|
||||
/** Test that FieldScoreQuery of Type.FLOAT caches/reuses loaded values and consumes the proper RAM resources. */
|
||||
public void testCachingFloat () throws CorruptIndexException, Exception {
|
||||
@Test
|
||||
public void testCachingFloat () throws Exception {
|
||||
// INT field values can be parsed as float
|
||||
doTestCaching(INT_FIELD,FieldScoreQuery.Type.FLOAT);
|
||||
// same values, but in flot format
|
||||
|
@ -155,7 +165,7 @@ public class TestFieldScoreQuery extends FunctionTestSetup {
|
|||
}
|
||||
|
||||
// Test that values loaded for FieldScoreQuery are cached properly and consumes the proper RAM resources.
|
||||
private void doTestCaching (String field, FieldScoreQuery.Type tp) throws CorruptIndexException, Exception {
|
||||
private void doTestCaching (String field, FieldScoreQuery.Type tp) throws Exception {
|
||||
// prepare expected array types for comparison
|
||||
HashMap<FieldScoreQuery.Type,Object> expectedArrayTypes = new HashMap<FieldScoreQuery.Type,Object>();
|
||||
expectedArrayTypes.put(FieldScoreQuery.Type.BYTE, new byte[0]);
|
||||
|
@ -223,7 +233,7 @@ public class TestFieldScoreQuery extends FunctionTestSetup {
|
|||
}
|
||||
|
||||
private String testName() {
|
||||
return getClass().getName()+"."+getName();
|
||||
return getClass().getName()+"."+ getName();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -19,42 +19,42 @@ package org.apache.lucene.search.function;
|
|||
|
||||
import org.apache.lucene.index.CorruptIndexException;
|
||||
import org.apache.lucene.index.IndexReader;
|
||||
import org.apache.lucene.search.IndexSearcher;
|
||||
import org.apache.lucene.search.Query;
|
||||
import org.apache.lucene.search.QueryUtils;
|
||||
import org.apache.lucene.search.ScoreDoc;
|
||||
import org.apache.lucene.search.TopDocs;
|
||||
import org.apache.lucene.search.*;
|
||||
import static org.junit.Assert.*;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* Test search based on OrdFieldSource and ReverseOrdFieldSource.
|
||||
* <p>
|
||||
* <p/>
|
||||
* Tests here create an index with a few documents, each having
|
||||
* an indexed "id" field.
|
||||
* The ord values of this field are later used for scoring.
|
||||
* <p>
|
||||
* <p/>
|
||||
* The order tests use Hits to verify that docs are ordered as expected.
|
||||
* <p>
|
||||
* <p/>
|
||||
* The exact score tests use TopDocs top to verify the exact score.
|
||||
*/
|
||||
@SuppressWarnings({"UseOfSystemOutOrSystemErr"})
|
||||
public class TestOrdValues extends FunctionTestSetup {
|
||||
|
||||
/* @override constructor */
|
||||
public TestOrdValues(String name) {
|
||||
super(name);
|
||||
/**
|
||||
* Test OrdFieldSource
|
||||
*/
|
||||
@Test
|
||||
public void testOrdFieldRank() throws CorruptIndexException, Exception {
|
||||
doTestRank(ID_FIELD, true);
|
||||
}
|
||||
|
||||
/** Test OrdFieldSource */
|
||||
public void testOrdFieldRank () throws CorruptIndexException, Exception {
|
||||
doTestRank(ID_FIELD,true);
|
||||
}
|
||||
|
||||
/** Test ReverseOrdFieldSource */
|
||||
public void testReverseOrdFieldRank () throws CorruptIndexException, Exception {
|
||||
doTestRank(ID_FIELD,false);
|
||||
/**
|
||||
* Test ReverseOrdFieldSource
|
||||
*/
|
||||
@Test
|
||||
public void testReverseOrdFieldRank() throws CorruptIndexException, Exception {
|
||||
doTestRank(ID_FIELD, false);
|
||||
}
|
||||
|
||||
// Test that queries based on reverse/ordFieldScore scores correctly
|
||||
private void doTestRank (String field, boolean inOrder) throws CorruptIndexException, Exception {
|
||||
private void doTestRank(String field, boolean inOrder) throws CorruptIndexException, Exception {
|
||||
IndexSearcher s = new IndexSearcher(dir, true);
|
||||
ValueSource vs;
|
||||
if (inOrder) {
|
||||
|
@ -64,40 +64,46 @@ public class TestOrdValues extends FunctionTestSetup {
|
|||
}
|
||||
|
||||
Query q = new ValueSourceQuery(vs);
|
||||
log("test: "+q);
|
||||
QueryUtils.check(q,s);
|
||||
log("test: " + q);
|
||||
QueryUtils.check(q, s);
|
||||
ScoreDoc[] h = s.search(q, null, 1000).scoreDocs;
|
||||
assertEquals("All docs should be matched!",N_DOCS,h.length);
|
||||
assertEquals("All docs should be matched!", N_DOCS, h.length);
|
||||
String prevID = inOrder
|
||||
? "IE" // greater than all ids of docs in this test ("ID0001", etc.)
|
||||
: "IC"; // smaller than all ids of docs in this test ("ID0001", etc.)
|
||||
? "IE" // greater than all ids of docs in this test ("ID0001", etc.)
|
||||
: "IC"; // smaller than all ids of docs in this test ("ID0001", etc.)
|
||||
|
||||
for (int i=0; i<h.length; i++) {
|
||||
for (int i = 0; i < h.length; i++) {
|
||||
String resID = s.doc(h[i].doc).get(ID_FIELD);
|
||||
log(i+". score="+h[i].score+" - "+resID);
|
||||
log(s.explain(q,h[i].doc));
|
||||
log(i + ". score=" + h[i].score + " - " + resID);
|
||||
log(s.explain(q, h[i].doc));
|
||||
if (inOrder) {
|
||||
assertTrue("res id "+resID+" should be < prev res id "+prevID, resID.compareTo(prevID)<0);
|
||||
assertTrue("res id " + resID + " should be < prev res id " + prevID, resID.compareTo(prevID) < 0);
|
||||
} else {
|
||||
assertTrue("res id "+resID+" should be > prev res id "+prevID, resID.compareTo(prevID)>0);
|
||||
assertTrue("res id " + resID + " should be > prev res id " + prevID, resID.compareTo(prevID) > 0);
|
||||
}
|
||||
prevID = resID;
|
||||
}
|
||||
}
|
||||
|
||||
/** Test exact score for OrdFieldSource */
|
||||
public void testOrdFieldExactScore () throws CorruptIndexException, Exception {
|
||||
doTestExactScore(ID_FIELD,true);
|
||||
/**
|
||||
* Test exact score for OrdFieldSource
|
||||
*/
|
||||
@Test
|
||||
public void testOrdFieldExactScore() throws CorruptIndexException, Exception {
|
||||
doTestExactScore(ID_FIELD, true);
|
||||
}
|
||||
|
||||
/** Test exact score for ReverseOrdFieldSource */
|
||||
public void testReverseOrdFieldExactScore () throws CorruptIndexException, Exception {
|
||||
doTestExactScore(ID_FIELD,false);
|
||||
/**
|
||||
* Test exact score for ReverseOrdFieldSource
|
||||
*/
|
||||
@Test
|
||||
public void testReverseOrdFieldExactScore() throws CorruptIndexException, Exception {
|
||||
doTestExactScore(ID_FIELD, false);
|
||||
}
|
||||
|
||||
|
||||
// Test that queries based on reverse/ordFieldScore returns docs with expected score.
|
||||
private void doTestExactScore (String field, boolean inOrder) throws CorruptIndexException, Exception {
|
||||
private void doTestExactScore(String field, boolean inOrder) throws CorruptIndexException, Exception {
|
||||
IndexSearcher s = new IndexSearcher(dir, true);
|
||||
ValueSource vs;
|
||||
if (inOrder) {
|
||||
|
@ -106,41 +112,47 @@ public class TestOrdValues extends FunctionTestSetup {
|
|||
vs = new ReverseOrdFieldSource(field);
|
||||
}
|
||||
Query q = new ValueSourceQuery(vs);
|
||||
TopDocs td = s.search(q,null,1000);
|
||||
assertEquals("All docs should be matched!",N_DOCS,td.totalHits);
|
||||
TopDocs td = s.search(q, null, 1000);
|
||||
assertEquals("All docs should be matched!", N_DOCS, td.totalHits);
|
||||
ScoreDoc sd[] = td.scoreDocs;
|
||||
for (int i=0; i<sd.length; i++) {
|
||||
for (int i = 0; i < sd.length; i++) {
|
||||
float score = sd[i].score;
|
||||
String id = s.getIndexReader().document(sd[i].doc).get(ID_FIELD);
|
||||
log("-------- "+i+". Explain doc "+id);
|
||||
log(s.explain(q,sd[i].doc));
|
||||
float expectedScore = N_DOCS-i;
|
||||
assertEquals("score of result "+i+" shuould be "+expectedScore+" != "+score, expectedScore, score, TEST_SCORE_TOLERANCE_DELTA);
|
||||
String expectedId = inOrder
|
||||
? id2String(N_DOCS-i) // in-order ==> larger values first
|
||||
: id2String(i+1); // reverse ==> smaller values first
|
||||
assertTrue("id of result "+i+" shuould be "+expectedId+" != "+score, expectedId.equals(id));
|
||||
log("-------- " + i + ". Explain doc " + id);
|
||||
log(s.explain(q, sd[i].doc));
|
||||
float expectedScore = N_DOCS - i;
|
||||
assertEquals("score of result " + i + " shuould be " + expectedScore + " != " + score, expectedScore, score, TEST_SCORE_TOLERANCE_DELTA);
|
||||
String expectedId = inOrder
|
||||
? id2String(N_DOCS - i) // in-order ==> larger values first
|
||||
: id2String(i + 1); // reverse ==> smaller values first
|
||||
assertTrue("id of result " + i + " shuould be " + expectedId + " != " + score, expectedId.equals(id));
|
||||
}
|
||||
}
|
||||
|
||||
/** Test caching OrdFieldSource */
|
||||
public void testCachingOrd () throws CorruptIndexException, Exception {
|
||||
doTestCaching(ID_FIELD,true);
|
||||
/**
|
||||
* Test caching OrdFieldSource
|
||||
*/
|
||||
@Test
|
||||
public void testCachingOrd() throws CorruptIndexException, Exception {
|
||||
doTestCaching(ID_FIELD, true);
|
||||
}
|
||||
|
||||
/** Test caching for ReverseOrdFieldSource */
|
||||
public void tesCachingReverseOrd () throws CorruptIndexException, Exception {
|
||||
doTestCaching(ID_FIELD,false);
|
||||
/**
|
||||
* Test caching for ReverseOrdFieldSource
|
||||
*/
|
||||
@Test
|
||||
public void testCachingReverseOrd() throws CorruptIndexException, Exception {
|
||||
doTestCaching(ID_FIELD, false);
|
||||
}
|
||||
|
||||
// Test that values loaded for FieldScoreQuery are cached properly and consumes the proper RAM resources.
|
||||
private void doTestCaching (String field, boolean inOrder) throws CorruptIndexException, Exception {
|
||||
private void doTestCaching(String field, boolean inOrder) throws CorruptIndexException, Exception {
|
||||
IndexSearcher s = new IndexSearcher(dir, true);
|
||||
Object innerArray = null;
|
||||
|
||||
boolean warned = false; // print warning once
|
||||
|
||||
for (int i=0; i<10; i++) {
|
||||
for (int i = 0; i < 10; i++) {
|
||||
ValueSource vs;
|
||||
if (inOrder) {
|
||||
vs = new OrdFieldSource(field);
|
||||
|
@ -150,21 +162,20 @@ public class TestOrdValues extends FunctionTestSetup {
|
|||
ValueSourceQuery q = new ValueSourceQuery(vs);
|
||||
ScoreDoc[] h = s.search(q, null, 1000).scoreDocs;
|
||||
try {
|
||||
assertEquals("All docs should be matched!",N_DOCS,h.length);
|
||||
assertEquals("All docs should be matched!", N_DOCS, h.length);
|
||||
IndexReader[] readers = s.getIndexReader().getSequentialSubReaders();
|
||||
|
||||
for(int j = 0; j < readers.length; j++) {
|
||||
IndexReader reader = readers[j];
|
||||
if (i==0) {
|
||||
for (IndexReader reader : readers) {
|
||||
if (i == 0) {
|
||||
innerArray = q.valSrc.getValues(reader).getInnerArray();
|
||||
} else {
|
||||
log(i+". compare: "+innerArray+" to "+q.valSrc.getValues(reader).getInnerArray());
|
||||
log(i + ". compare: " + innerArray + " to " + q.valSrc.getValues(reader).getInnerArray());
|
||||
assertSame("field values should be cached and reused!", innerArray, q.valSrc.getValues(reader).getInnerArray());
|
||||
}
|
||||
}
|
||||
} catch (UnsupportedOperationException e) {
|
||||
if (!warned) {
|
||||
System.err.println("WARNING: "+testName()+" cannot fully test values of "+q);
|
||||
System.err.println("WARNING: " + testName() + " cannot fully test values of " + q);
|
||||
warned = true;
|
||||
}
|
||||
}
|
||||
|
@ -184,21 +195,20 @@ public class TestOrdValues extends FunctionTestSetup {
|
|||
}
|
||||
q = new ValueSourceQuery(vs);
|
||||
h = s.search(q, null, 1000).scoreDocs;
|
||||
assertEquals("All docs should be matched!",N_DOCS,h.length);
|
||||
assertEquals("All docs should be matched!", N_DOCS, h.length);
|
||||
IndexReader[] readers = s.getIndexReader().getSequentialSubReaders();
|
||||
|
||||
for (int j = 0; j < readers.length; j++) {
|
||||
IndexReader reader = readers[j];
|
||||
for (IndexReader reader : readers) {
|
||||
try {
|
||||
log("compare (should differ): " + innerArray + " to "
|
||||
+ q.valSrc.getValues(reader).getInnerArray());
|
||||
+ q.valSrc.getValues(reader).getInnerArray());
|
||||
assertNotSame(
|
||||
"different values shuold be loaded for a different field!",
|
||||
innerArray, q.valSrc.getValues(reader).getInnerArray());
|
||||
"different values shuold be loaded for a different field!",
|
||||
innerArray, q.valSrc.getValues(reader).getInnerArray());
|
||||
} catch (UnsupportedOperationException e) {
|
||||
if (!warned) {
|
||||
System.err.println("WARNING: " + testName()
|
||||
+ " cannot fully test values of " + q);
|
||||
+ " cannot fully test values of " + q);
|
||||
warned = true;
|
||||
}
|
||||
}
|
||||
|
@ -213,21 +223,20 @@ public class TestOrdValues extends FunctionTestSetup {
|
|||
}
|
||||
q = new ValueSourceQuery(vs);
|
||||
h = s.search(q, null, 1000).scoreDocs;
|
||||
assertEquals("All docs should be matched!",N_DOCS,h.length);
|
||||
assertEquals("All docs should be matched!", N_DOCS, h.length);
|
||||
readers = s.getIndexReader().getSequentialSubReaders();
|
||||
|
||||
for (int j = 0; j < readers.length; j++) {
|
||||
IndexReader reader = readers[j];
|
||||
for (IndexReader reader : readers) {
|
||||
try {
|
||||
log("compare (should differ): " + innerArray + " to "
|
||||
+ q.valSrc.getValues(reader).getInnerArray());
|
||||
+ q.valSrc.getValues(reader).getInnerArray());
|
||||
assertNotSame(
|
||||
"cached field values should not be reused if reader as changed!",
|
||||
innerArray, q.valSrc.getValues(reader).getInnerArray());
|
||||
"cached field values should not be reused if reader as changed!",
|
||||
innerArray, q.valSrc.getValues(reader).getInnerArray());
|
||||
} catch (UnsupportedOperationException e) {
|
||||
if (!warned) {
|
||||
System.err.println("WARNING: " + testName()
|
||||
+ " cannot fully test values of " + q);
|
||||
+ " cannot fully test values of " + q);
|
||||
warned = true;
|
||||
}
|
||||
}
|
||||
|
@ -235,7 +244,7 @@ public class TestOrdValues extends FunctionTestSetup {
|
|||
}
|
||||
|
||||
private String testName() {
|
||||
return getClass().getName()+"."+getName();
|
||||
return getClass().getName() + "." + getName();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,60 @@
|
|||
package org.apache.lucene.util;
|
||||
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
import org.junit.rules.TestWatchman;
|
||||
import org.junit.runners.model.FrameworkMethod;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
|
||||
public final class InterceptTestCaseEvents extends TestWatchman {
|
||||
private Object obj;
|
||||
|
||||
public InterceptTestCaseEvents(Object obj) {
|
||||
this.obj = obj;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void failed(Throwable e, FrameworkMethod method) {
|
||||
try {
|
||||
Method reporter = method.getMethod().getDeclaringClass().getMethod("reportAdditionalFailureInfo",(Class<?>[]) null);
|
||||
reporter.invoke(obj, (Object[])null);
|
||||
} catch (Exception e1) {
|
||||
System.err.println("InterceptTestCaseEvents.failed(). Cannot invoke reportAdditionalFailureInfo() method in" +
|
||||
" consuming class, is it declared and public?");
|
||||
}
|
||||
super.failed(e, method);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void finished(FrameworkMethod method) {
|
||||
super.finished(method);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void starting(FrameworkMethod method) {
|
||||
super.starting(method);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void succeeded(FrameworkMethod method) {
|
||||
super.succeeded(method);
|
||||
}
|
||||
}
|
|
@ -46,7 +46,11 @@ import org.apache.lucene.util.FieldCacheSanityChecker.Insanity;
|
|||
* <code>super.tearDown()</code>
|
||||
* </p>
|
||||
* @see #assertSaneFieldCaches
|
||||
*
|
||||
* @deprecated Replaced by {@link #LuceneTestCaseJ4}
|
||||
*
|
||||
*/
|
||||
@Deprecated
|
||||
public abstract class LuceneTestCase extends TestCase {
|
||||
|
||||
public LuceneTestCase() {
|
||||
|
|
|
@ -0,0 +1,254 @@
|
|||
package org.apache.lucene.util;
|
||||
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import org.apache.lucene.index.ConcurrentMergeScheduler;
|
||||
import org.apache.lucene.search.FieldCache;
|
||||
import org.apache.lucene.search.FieldCache.CacheEntry;
|
||||
import org.apache.lucene.util.FieldCacheSanityChecker.Insanity;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.rules.TestWatchman;
|
||||
|
||||
import java.io.PrintStream;
|
||||
import java.util.Arrays;
|
||||
import java.util.Iterator;
|
||||
import java.util.Random;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
/**
|
||||
* Base class for all Lucene unit tests, Junit4 variant.
|
||||
* Replaces LuceneTestCase.
|
||||
* <p>
|
||||
* </p>
|
||||
* <p>
|
||||
* If you
|
||||
* override either <code>setUp()</code> or
|
||||
* <code>tearDown()</code> in your unit test, make sure you
|
||||
* call <code>super.setUp()</code> and
|
||||
* <code>super.tearDown()</code>
|
||||
* </p>
|
||||
*
|
||||
* @After - replaces setup
|
||||
* @Before - replaces teardown
|
||||
* @Test - any public method with this annotation is a test case, regardless
|
||||
* of its name
|
||||
* <p/>
|
||||
* <p/>
|
||||
* See Junit4 documentation for a complete list of features at
|
||||
* http://junit.org/junit/javadoc/4.7/
|
||||
* <p/>
|
||||
* Import from org.junit rather than junit.framework.
|
||||
* <p/>
|
||||
* You should be able to use this class anywhere you used LuceneTestCase
|
||||
* if you annotate your derived class correctly with the annotations above
|
||||
* @see assertSaneFieldCaches
|
||||
* <p/>
|
||||
*/
|
||||
|
||||
|
||||
// If we really need functionality in runBare override from LuceneTestCase,
|
||||
// we can introduce RunBareWrapper and override runChild, and add the
|
||||
// @RunWith annotation as below. runChild will be called for
|
||||
// every test. But the functionality we used to
|
||||
// get from that override is provided by InterceptTestCaseEvents
|
||||
//@RunWith(RunBareWrapper.class)
|
||||
public class LuceneTestCaseJ4 extends TestWatchman {
|
||||
|
||||
// This is how we get control when errors occur.
|
||||
// Think of this as start/end/success/failed
|
||||
// events.
|
||||
@Rule
|
||||
public InterceptTestCaseEvents intercept = new InterceptTestCaseEvents(this);
|
||||
|
||||
public LuceneTestCaseJ4() {
|
||||
}
|
||||
|
||||
public LuceneTestCaseJ4(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
ConcurrentMergeScheduler.setTestMode();
|
||||
seed = null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Forcible purges all cache entries from the FieldCache.
|
||||
* <p>
|
||||
* This method will be called by tearDown to clean up FieldCache.DEFAULT.
|
||||
* If a (poorly written) test has some expectation that the FieldCache
|
||||
* will persist across test methods (ie: a static IndexReader) this
|
||||
* method can be overridden to do nothing.
|
||||
* </p>
|
||||
*
|
||||
* @see FieldCache#purgeAllCaches()
|
||||
*/
|
||||
protected void purgeFieldCache(final FieldCache fc) {
|
||||
fc.purgeAllCaches();
|
||||
}
|
||||
|
||||
protected String getTestLabel() {
|
||||
return getClass().getName() + "." + getName();
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() throws Exception {
|
||||
try {
|
||||
// this isn't as useful as calling directly from the scope where the
|
||||
// index readers are used, because they could be gc'ed just before
|
||||
// tearDown is called.
|
||||
// But it's better then nothing.
|
||||
assertSaneFieldCaches(getTestLabel());
|
||||
|
||||
if (ConcurrentMergeScheduler.anyUnhandledExceptions()) {
|
||||
// Clear the failure so that we don't just keep
|
||||
// failing subsequent test cases
|
||||
ConcurrentMergeScheduler.clearUnhandledExceptions();
|
||||
fail("ConcurrentMergeScheduler hit unhandled exceptions");
|
||||
}
|
||||
} finally {
|
||||
purgeFieldCache(FieldCache.DEFAULT);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts that FieldCacheSanityChecker does not detect any
|
||||
* problems with FieldCache.DEFAULT.
|
||||
* <p>
|
||||
* If any problems are found, they are logged to System.err
|
||||
* (allong with the msg) when the Assertion is thrown.
|
||||
* </p>
|
||||
* <p>
|
||||
* This method is called by tearDown after every test method,
|
||||
* however IndexReaders scoped inside test methods may be garbage
|
||||
* collected prior to this method being called, causing errors to
|
||||
* be overlooked. Tests are encouraged to keep their IndexReaders
|
||||
* scoped at the class level, or to explicitly call this method
|
||||
* directly in the same scope as the IndexReader.
|
||||
* </p>
|
||||
*
|
||||
* @see FieldCacheSanityChecker
|
||||
*/
|
||||
protected void assertSaneFieldCaches(final String msg) {
|
||||
final CacheEntry[] entries = FieldCache.DEFAULT.getCacheEntries();
|
||||
Insanity[] insanity = null;
|
||||
try {
|
||||
try {
|
||||
insanity = FieldCacheSanityChecker.checkSanity(entries);
|
||||
} catch (RuntimeException e) {
|
||||
dumpArray(msg + ": FieldCache", entries, System.err);
|
||||
throw e;
|
||||
}
|
||||
|
||||
assertEquals(msg + ": Insane FieldCache usage(s) found",
|
||||
0, insanity.length);
|
||||
insanity = null;
|
||||
} finally {
|
||||
|
||||
// report this in the event of any exception/failure
|
||||
// if no failure, then insanity will be null anyway
|
||||
if (null != insanity) {
|
||||
dumpArray(msg + ": Insane FieldCache usage(s)", insanity, System.err);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convinience method for logging an iterator.
|
||||
*
|
||||
* @param label String logged before/after the items in the iterator
|
||||
* @param iter Each next() is toString()ed and logged on it's own line. If iter is null this is logged differnetly then an empty iterator.
|
||||
* @param stream Stream to log messages to.
|
||||
*/
|
||||
public static void dumpIterator(String label, Iterator iter,
|
||||
PrintStream stream) {
|
||||
stream.println("*** BEGIN " + label + " ***");
|
||||
if (null == iter) {
|
||||
stream.println(" ... NULL ...");
|
||||
} else {
|
||||
while (iter.hasNext()) {
|
||||
stream.println(iter.next().toString());
|
||||
}
|
||||
}
|
||||
stream.println("*** END " + label + " ***");
|
||||
}
|
||||
|
||||
/**
|
||||
* Convinience method for logging an array. Wraps the array in an iterator and delegates
|
||||
*
|
||||
* @see dumpIterator(String,Iterator,PrintStream)
|
||||
*/
|
||||
public static void dumpArray(String label, Object[] objs,
|
||||
PrintStream stream) {
|
||||
Iterator iter = (null == objs) ? null : Arrays.asList(objs).iterator();
|
||||
dumpIterator(label, iter, stream);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@link Random} instance for generating random numbers during the test.
|
||||
* The random seed is logged during test execution and printed to System.out on any failure
|
||||
* for reproducing the test using {@link #newRandom(long)} with the recorded seed
|
||||
* .
|
||||
*/
|
||||
public Random newRandom() {
|
||||
if (seed != null) {
|
||||
throw new IllegalStateException("please call LuceneTestCase.newRandom only once per test");
|
||||
}
|
||||
return newRandom(seedRnd.nextLong());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@link Random} instance for generating random numbers during the test.
|
||||
* If an error occurs in the test that is not reproducible, you can use this method to
|
||||
* initialize the number generator with the seed that was printed out during the failing test.
|
||||
*/
|
||||
public Random newRandom(long seed) {
|
||||
if (this.seed != null) {
|
||||
throw new IllegalStateException("please call LuceneTestCase.newRandom only once per test");
|
||||
}
|
||||
this.seed = Long.valueOf(seed);
|
||||
return new Random(seed);
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
// We get here fro InterceptTestCaseEvents on the 'failed' event....
|
||||
public void reportAdditionalFailureInfo() {
|
||||
if (seed != null) {
|
||||
System.out.println("NOTE: random seed of testcase '" + getName() + "' was: " + seed);
|
||||
}
|
||||
}
|
||||
|
||||
// recorded seed
|
||||
protected Long seed = null;
|
||||
|
||||
// static members
|
||||
private static final Random seedRnd = new Random();
|
||||
|
||||
private String name = "";
|
||||
|
||||
}
|
Loading…
Reference in New Issue