mirror of https://github.com/apache/lucene.git
LUCENE-4211: add AssertingReader/Codec
git-svn-id: https://svn.apache.org/repos/asf/lucene/dev/trunk@1361243 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
7993e39d38
commit
9c9039582e
|
@ -55,6 +55,7 @@ public final class MultiDocsAndPositionsEnum extends DocsAndPositionsEnum {
|
|||
this.subs[i].slice = subs[i].slice;
|
||||
}
|
||||
upto = -1;
|
||||
doc = -1;
|
||||
current = null;
|
||||
return this;
|
||||
}
|
||||
|
@ -69,6 +70,7 @@ public final class MultiDocsAndPositionsEnum extends DocsAndPositionsEnum {
|
|||
|
||||
@Override
|
||||
public int freq() throws IOException {
|
||||
assert current != null;
|
||||
return current.freq();
|
||||
}
|
||||
|
||||
|
|
|
@ -52,6 +52,7 @@ public final class MultiDocsEnum extends DocsEnum {
|
|||
this.subs[i].slice = subs[i].slice;
|
||||
}
|
||||
upto = -1;
|
||||
doc = -1;
|
||||
current = null;
|
||||
return this;
|
||||
}
|
||||
|
|
|
@ -37,6 +37,7 @@ import org.apache.lucene.index.Fields;
|
|||
import org.apache.lucene.index.IndexReader;
|
||||
import org.apache.lucene.index.Terms;
|
||||
import org.apache.lucene.index.TermsEnum;
|
||||
import org.apache.lucene.search.DocIdSetIterator;
|
||||
import org.apache.lucene.util.ArrayUtil;
|
||||
import org.apache.lucene.util.BytesRef;
|
||||
|
||||
|
@ -128,6 +129,8 @@ public class TokenSources {
|
|||
if (termsEnum.next() != null) {
|
||||
DocsAndPositionsEnum dpEnum = termsEnum.docsAndPositions(null, null, false);
|
||||
if (dpEnum != null) {
|
||||
int doc = dpEnum.nextDoc();
|
||||
assert doc >= 0 && doc != DocIdSetIterator.NO_MORE_DOCS;
|
||||
int pos = dpEnum.nextPosition();
|
||||
if (pos >= 0) {
|
||||
return true;
|
||||
|
|
|
@ -0,0 +1,94 @@
|
|||
package org.apache.lucene.codecs.asserting;
|
||||
|
||||
/*
|
||||
* 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.codecs.Codec;
|
||||
import org.apache.lucene.codecs.DocValuesFormat;
|
||||
import org.apache.lucene.codecs.FieldInfosFormat;
|
||||
import org.apache.lucene.codecs.LiveDocsFormat;
|
||||
import org.apache.lucene.codecs.NormsFormat;
|
||||
import org.apache.lucene.codecs.PostingsFormat;
|
||||
import org.apache.lucene.codecs.SegmentInfoFormat;
|
||||
import org.apache.lucene.codecs.StoredFieldsFormat;
|
||||
import org.apache.lucene.codecs.TermVectorsFormat;
|
||||
import org.apache.lucene.codecs.lucene40.Lucene40Codec; // javadocs @link
|
||||
import org.apache.lucene.codecs.lucene40.Lucene40DocValuesFormat;
|
||||
import org.apache.lucene.codecs.lucene40.Lucene40FieldInfosFormat;
|
||||
import org.apache.lucene.codecs.lucene40.Lucene40LiveDocsFormat;
|
||||
import org.apache.lucene.codecs.lucene40.Lucene40NormsFormat;
|
||||
import org.apache.lucene.codecs.lucene40.Lucene40SegmentInfoFormat;
|
||||
import org.apache.lucene.codecs.lucene40.Lucene40StoredFieldsFormat;
|
||||
|
||||
/**
|
||||
* Acts like {@link Lucene40Codec} but with additional asserts.
|
||||
*/
|
||||
public class AssertingCodec extends Codec {
|
||||
|
||||
private final PostingsFormat postings = new AssertingPostingsFormat();
|
||||
private final SegmentInfoFormat infos = new Lucene40SegmentInfoFormat();
|
||||
private final StoredFieldsFormat fields = new Lucene40StoredFieldsFormat();
|
||||
private final FieldInfosFormat fieldInfos = new Lucene40FieldInfosFormat();
|
||||
private final TermVectorsFormat vectors = new AssertingTermVectorsFormat();
|
||||
private final DocValuesFormat docValues = new Lucene40DocValuesFormat();
|
||||
private final NormsFormat norms = new Lucene40NormsFormat();
|
||||
private final LiveDocsFormat liveDocs = new Lucene40LiveDocsFormat();
|
||||
|
||||
public AssertingCodec() {
|
||||
super("Asserting");
|
||||
}
|
||||
|
||||
@Override
|
||||
public PostingsFormat postingsFormat() {
|
||||
return postings;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DocValuesFormat docValuesFormat() {
|
||||
return docValues;
|
||||
}
|
||||
|
||||
@Override
|
||||
public StoredFieldsFormat storedFieldsFormat() {
|
||||
return fields;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TermVectorsFormat termVectorsFormat() {
|
||||
return vectors;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FieldInfosFormat fieldInfosFormat() {
|
||||
return fieldInfos;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SegmentInfoFormat segmentInfoFormat() {
|
||||
return infos;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NormsFormat normsFormat() {
|
||||
return norms;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LiveDocsFormat liveDocsFormat() {
|
||||
return liveDocs;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,88 @@
|
|||
package org.apache.lucene.codecs.asserting;
|
||||
|
||||
/*
|
||||
* 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 java.io.IOException;
|
||||
|
||||
import org.apache.lucene.codecs.FieldsConsumer;
|
||||
import org.apache.lucene.codecs.FieldsProducer;
|
||||
import org.apache.lucene.codecs.PostingsFormat;
|
||||
import org.apache.lucene.codecs.lucene40.Lucene40PostingsFormat;
|
||||
import org.apache.lucene.index.AssertingAtomicReader;
|
||||
import org.apache.lucene.index.FieldsEnum;
|
||||
import org.apache.lucene.index.SegmentReadState;
|
||||
import org.apache.lucene.index.SegmentWriteState;
|
||||
import org.apache.lucene.index.Terms;
|
||||
|
||||
/**
|
||||
* Just like {@link Lucene40PostingsFormat} but with additional asserts.
|
||||
*/
|
||||
public class AssertingPostingsFormat extends PostingsFormat {
|
||||
private final PostingsFormat in = new Lucene40PostingsFormat();
|
||||
|
||||
public AssertingPostingsFormat() {
|
||||
super("Asserting");
|
||||
}
|
||||
|
||||
// TODO: we could add some useful checks here?
|
||||
@Override
|
||||
public FieldsConsumer fieldsConsumer(SegmentWriteState state) throws IOException {
|
||||
return in.fieldsConsumer(state);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FieldsProducer fieldsProducer(SegmentReadState state) throws IOException {
|
||||
return new AssertingFieldsProducer(in.fieldsProducer(state));
|
||||
}
|
||||
|
||||
static class AssertingFieldsProducer extends FieldsProducer {
|
||||
private final FieldsProducer in;
|
||||
|
||||
AssertingFieldsProducer(FieldsProducer in) {
|
||||
this.in = in;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
in.close();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FieldsEnum iterator() throws IOException {
|
||||
FieldsEnum iterator = in.iterator();
|
||||
assert iterator != null;
|
||||
return new AssertingAtomicReader.AssertingFieldsEnum(iterator);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Terms terms(String field) throws IOException {
|
||||
Terms terms = in.terms(field);
|
||||
return terms == null ? null : new AssertingAtomicReader.AssertingTerms(terms);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() throws IOException {
|
||||
return in.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getUniqueTermCount() throws IOException {
|
||||
return in.getUniqueTermCount();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,72 @@
|
|||
package org.apache.lucene.codecs.asserting;
|
||||
|
||||
/*
|
||||
* 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 java.io.IOException;
|
||||
|
||||
import org.apache.lucene.codecs.TermVectorsFormat;
|
||||
import org.apache.lucene.codecs.TermVectorsReader;
|
||||
import org.apache.lucene.codecs.TermVectorsWriter;
|
||||
import org.apache.lucene.codecs.lucene40.Lucene40TermVectorsFormat;
|
||||
import org.apache.lucene.index.AssertingAtomicReader;
|
||||
import org.apache.lucene.index.FieldInfos;
|
||||
import org.apache.lucene.index.Fields;
|
||||
import org.apache.lucene.index.SegmentInfo;
|
||||
import org.apache.lucene.store.Directory;
|
||||
import org.apache.lucene.store.IOContext;
|
||||
|
||||
/**
|
||||
* Just like {@link Lucene40TermVectorsFormat} but with additional asserts.
|
||||
*/
|
||||
public class AssertingTermVectorsFormat extends TermVectorsFormat {
|
||||
private final TermVectorsFormat in = new Lucene40TermVectorsFormat();
|
||||
|
||||
@Override
|
||||
public TermVectorsReader vectorsReader(Directory directory, SegmentInfo segmentInfo, FieldInfos fieldInfos, IOContext context) throws IOException {
|
||||
return new AssertingTermVectorsReader(in.vectorsReader(directory, segmentInfo, fieldInfos, context));
|
||||
}
|
||||
|
||||
@Override
|
||||
public TermVectorsWriter vectorsWriter(Directory directory, SegmentInfo segmentInfo, IOContext context) throws IOException {
|
||||
return in.vectorsWriter(directory, segmentInfo, context);
|
||||
}
|
||||
|
||||
static class AssertingTermVectorsReader extends TermVectorsReader {
|
||||
private final TermVectorsReader in;
|
||||
|
||||
AssertingTermVectorsReader(TermVectorsReader in) {
|
||||
this.in = in;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
in.close();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Fields get(int doc) throws IOException {
|
||||
Fields fields = in.get(doc);
|
||||
return fields == null ? null : new AssertingAtomicReader.AssertingFields(fields);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TermVectorsReader clone() {
|
||||
return new AssertingTermVectorsReader(in.clone());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
|
||||
<!--
|
||||
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.
|
||||
-->
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
</head>
|
||||
<body>
|
||||
Codec for testing that asserts various contracts of the codec apis.
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,379 @@
|
|||
package org.apache.lucene.index;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.apache.lucene.search.DocIdSetIterator;
|
||||
import org.apache.lucene.util.Bits;
|
||||
import org.apache.lucene.util.BytesRef;
|
||||
import org.apache.lucene.util.automaton.CompiledAutomaton;
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* A {@link FilterAtomicReader} that can be used to apply
|
||||
* additional checks for tests.
|
||||
*/
|
||||
public class AssertingAtomicReader extends FilterAtomicReader {
|
||||
|
||||
public AssertingAtomicReader(AtomicReader in) {
|
||||
super(in);
|
||||
// check some basic reader sanity
|
||||
assert in.maxDoc() >= 0;
|
||||
assert in.numDocs() <= in.maxDoc();
|
||||
assert in.numDeletedDocs() + in.numDocs() == in.maxDoc();
|
||||
assert !in.hasDeletions() || in.numDeletedDocs() > 0 && in.numDocs() < in.maxDoc();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Fields fields() throws IOException {
|
||||
Fields fields = super.fields();
|
||||
return fields == null ? null : new AssertingFields(fields);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Fields getTermVectors(int docID) throws IOException {
|
||||
Fields fields = super.getTermVectors(docID);
|
||||
return fields == null ? null : new AssertingFields(fields);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wraps a Fields but with additional asserts
|
||||
*/
|
||||
public static class AssertingFields extends FilterFields {
|
||||
public AssertingFields(Fields in) {
|
||||
super(in);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FieldsEnum iterator() throws IOException {
|
||||
FieldsEnum fieldsEnum = super.iterator();
|
||||
assert fieldsEnum != null;
|
||||
return new AssertingFieldsEnum(fieldsEnum);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Terms terms(String field) throws IOException {
|
||||
Terms terms = super.terms(field);
|
||||
return terms == null ? null : new AssertingTerms(terms);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Wraps a FieldsEnum but with additional asserts
|
||||
*/
|
||||
public static class AssertingFieldsEnum extends FilterFieldsEnum {
|
||||
public AssertingFieldsEnum(FieldsEnum in) {
|
||||
super(in);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Terms terms() throws IOException {
|
||||
Terms terms = super.terms();
|
||||
return terms == null ? null : new AssertingTerms(terms);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Wraps a Terms but with additional asserts
|
||||
*/
|
||||
public static class AssertingTerms extends FilterTerms {
|
||||
public AssertingTerms(Terms in) {
|
||||
super(in);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TermsEnum intersect(CompiledAutomaton automaton, BytesRef bytes) throws IOException {
|
||||
TermsEnum termsEnum = super.intersect(automaton, bytes);
|
||||
assert termsEnum != null;
|
||||
return new AssertingTermsEnum(termsEnum);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TermsEnum iterator(TermsEnum reuse) throws IOException {
|
||||
// TODO: should we give this thing a random to be super-evil,
|
||||
// and randomly *not* unwrap?
|
||||
if (reuse instanceof AssertingTermsEnum) {
|
||||
reuse = ((AssertingTermsEnum) reuse).in;
|
||||
}
|
||||
TermsEnum termsEnum = super.iterator(reuse);
|
||||
assert termsEnum != null;
|
||||
return new AssertingTermsEnum(termsEnum);
|
||||
}
|
||||
}
|
||||
|
||||
static class AssertingTermsEnum extends FilterTermsEnum {
|
||||
private enum State {INITIAL, POSITIONED, UNPOSITIONED};
|
||||
private State state = State.INITIAL;
|
||||
|
||||
public AssertingTermsEnum(TermsEnum in) {
|
||||
super(in);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DocsEnum docs(Bits liveDocs, DocsEnum reuse, boolean needsFreqs) throws IOException {
|
||||
assert state == State.POSITIONED: "docs(...) called on unpositioned TermsEnum";
|
||||
|
||||
// TODO: should we give this thing a random to be super-evil,
|
||||
// and randomly *not* unwrap?
|
||||
if (reuse instanceof AssertingDocsEnum) {
|
||||
reuse = ((AssertingDocsEnum) reuse).in;
|
||||
}
|
||||
DocsEnum docs = super.docs(liveDocs, reuse, needsFreqs);
|
||||
return docs == null ? null : new AssertingDocsEnum(docs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DocsAndPositionsEnum docsAndPositions(Bits liveDocs, DocsAndPositionsEnum reuse, boolean needsOffsets) throws IOException {
|
||||
assert state == State.POSITIONED: "docsAndPositions(...) called on unpositioned TermsEnum";
|
||||
|
||||
// TODO: should we give this thing a random to be super-evil,
|
||||
// and randomly *not* unwrap?
|
||||
if (reuse instanceof AssertingDocsAndPositionsEnum) {
|
||||
reuse = ((AssertingDocsAndPositionsEnum) reuse).in;
|
||||
}
|
||||
DocsAndPositionsEnum docs = super.docsAndPositions(liveDocs, reuse, needsOffsets);
|
||||
return docs == null ? null : new AssertingDocsAndPositionsEnum(docs);
|
||||
}
|
||||
|
||||
// TODO: we should separately track if we are 'at the end' ?
|
||||
// someone should not call next() after it returns null!!!!
|
||||
@Override
|
||||
public BytesRef next() throws IOException {
|
||||
assert state == State.INITIAL || state == State.POSITIONED: "next() called on unpositioned TermsEnum";
|
||||
BytesRef result = super.next();
|
||||
if (result == null) {
|
||||
state = State.UNPOSITIONED;
|
||||
} else {
|
||||
state = State.POSITIONED;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long ord() throws IOException {
|
||||
assert state == State.POSITIONED : "ord() called on unpositioned TermsEnum";
|
||||
return super.ord();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int docFreq() throws IOException {
|
||||
assert state == State.POSITIONED : "docFreq() called on unpositioned TermsEnum";
|
||||
return super.docFreq();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long totalTermFreq() throws IOException {
|
||||
assert state == State.POSITIONED : "totalTermFreq() called on unpositioned TermsEnum";
|
||||
return super.totalTermFreq();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BytesRef term() throws IOException {
|
||||
assert state == State.POSITIONED : "term() called on unpositioned TermsEnum";
|
||||
return super.term();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void seekExact(long ord) throws IOException {
|
||||
super.seekExact(ord);
|
||||
state = State.POSITIONED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SeekStatus seekCeil(BytesRef term, boolean useCache) throws IOException {
|
||||
SeekStatus result = super.seekCeil(term, useCache);
|
||||
if (result == SeekStatus.END) {
|
||||
state = State.UNPOSITIONED;
|
||||
} else {
|
||||
state = State.POSITIONED;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean seekExact(BytesRef text, boolean useCache) throws IOException {
|
||||
if (super.seekExact(text, useCache)) {
|
||||
state = State.POSITIONED;
|
||||
return true;
|
||||
} else {
|
||||
state = State.UNPOSITIONED;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public TermState termState() throws IOException {
|
||||
assert state == State.POSITIONED : "termState() called on unpositioned TermsEnum";
|
||||
return super.termState();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void seekExact(BytesRef term, TermState state) throws IOException {
|
||||
super.seekExact(term, state);
|
||||
this.state = State.POSITIONED;
|
||||
}
|
||||
}
|
||||
|
||||
static enum DocsEnumState { START, ITERATING, FINISHED };
|
||||
static class AssertingDocsEnum extends FilterDocsEnum {
|
||||
private DocsEnumState state = DocsEnumState.START;
|
||||
|
||||
public AssertingDocsEnum(DocsEnum in) {
|
||||
super(in);
|
||||
int docid = in.docID();
|
||||
assert docid == -1 || docid == DocIdSetIterator.NO_MORE_DOCS : "invalid initial doc id: " + docid;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int nextDoc() throws IOException {
|
||||
assert state != DocsEnumState.FINISHED : "nextDoc() called after NO_MORE_DOCS";
|
||||
int nextDoc = super.nextDoc();
|
||||
assert nextDoc >= 0 : "invalid doc id: " + nextDoc;
|
||||
if (nextDoc == DocIdSetIterator.NO_MORE_DOCS) {
|
||||
state = DocsEnumState.FINISHED;
|
||||
} else {
|
||||
state = DocsEnumState.ITERATING;
|
||||
}
|
||||
return nextDoc;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int advance(int target) throws IOException {
|
||||
assert state != DocsEnumState.FINISHED : "advance() called after NO_MORE_DOCS";
|
||||
int advanced = super.advance(target);
|
||||
assert advanced >= 0 : "invalid doc id: " + advanced;
|
||||
assert advanced >= target : "backwards advance from: " + target + " to: " + advanced;
|
||||
if (advanced == DocIdSetIterator.NO_MORE_DOCS) {
|
||||
state = DocsEnumState.FINISHED;
|
||||
} else {
|
||||
state = DocsEnumState.ITERATING;
|
||||
}
|
||||
return advanced;
|
||||
}
|
||||
|
||||
// NOTE: We don't assert anything for docId(). Specifically DocsEnum javadocs
|
||||
// are ambiguous with DocIdSetIterator here, DocIdSetIterator says its ok
|
||||
// to call this method before nextDoc(), just that it must be -1 or NO_MORE_DOCS!
|
||||
|
||||
@Override
|
||||
public int freq() throws IOException {
|
||||
assert state != DocsEnumState.START : "freq() called before nextDoc()/advance()";
|
||||
assert state != DocsEnumState.FINISHED : "freq() called after NO_MORE_DOCS";
|
||||
int freq = super.freq();
|
||||
assert freq > 0;
|
||||
return freq;
|
||||
}
|
||||
}
|
||||
|
||||
static class AssertingDocsAndPositionsEnum extends FilterDocsAndPositionsEnum {
|
||||
private DocsEnumState state = DocsEnumState.START;
|
||||
private int positionMax = 0;
|
||||
private int positionCount = 0;
|
||||
|
||||
public AssertingDocsAndPositionsEnum(DocsAndPositionsEnum in) {
|
||||
super(in);
|
||||
int docid = in.docID();
|
||||
assert docid == -1 || docid == DocIdSetIterator.NO_MORE_DOCS : "invalid initial doc id: " + docid;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int nextDoc() throws IOException {
|
||||
assert state != DocsEnumState.FINISHED : "nextDoc() called after NO_MORE_DOCS";
|
||||
int nextDoc = super.nextDoc();
|
||||
assert nextDoc >= 0 : "invalid doc id: " + nextDoc;
|
||||
positionCount = 0;
|
||||
if (nextDoc == DocIdSetIterator.NO_MORE_DOCS) {
|
||||
state = DocsEnumState.FINISHED;
|
||||
positionMax = 0;
|
||||
} else {
|
||||
state = DocsEnumState.ITERATING;
|
||||
positionMax = super.freq();
|
||||
}
|
||||
return nextDoc;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int advance(int target) throws IOException {
|
||||
assert state != DocsEnumState.FINISHED : "advance() called after NO_MORE_DOCS";
|
||||
int advanced = super.advance(target);
|
||||
assert advanced >= 0 : "invalid doc id: " + advanced;
|
||||
assert advanced >= target : "backwards advance from: " + target + " to: " + advanced;
|
||||
positionCount = 0;
|
||||
if (advanced == DocIdSetIterator.NO_MORE_DOCS) {
|
||||
state = DocsEnumState.FINISHED;
|
||||
positionMax = 0;
|
||||
} else {
|
||||
state = DocsEnumState.ITERATING;
|
||||
positionMax = super.freq();
|
||||
}
|
||||
return advanced;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int freq() throws IOException {
|
||||
assert state != DocsEnumState.START : "freq() called before nextDoc()/advance()";
|
||||
assert state != DocsEnumState.FINISHED : "freq() called after NO_MORE_DOCS";
|
||||
int freq = super.freq();
|
||||
assert freq > 0;
|
||||
return freq;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int nextPosition() throws IOException {
|
||||
assert state != DocsEnumState.START : "nextPosition() called before nextDoc()/advance()";
|
||||
assert state != DocsEnumState.FINISHED : "nextPosition() called after NO_MORE_DOCS";
|
||||
assert positionCount < positionMax : "nextPosition() called more than freq() times!";
|
||||
int position = super.nextPosition();
|
||||
assert position >= 0 || position == -1 : "invalid position: " + position;
|
||||
positionCount++;
|
||||
return position;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int startOffset() throws IOException {
|
||||
assert state != DocsEnumState.START : "startOffset() called before nextDoc()/advance()";
|
||||
assert state != DocsEnumState.FINISHED : "startOffset() called after NO_MORE_DOCS";
|
||||
assert positionCount > 0 : "startOffset() called before nextPosition()!";
|
||||
return super.startOffset();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int endOffset() throws IOException {
|
||||
assert state != DocsEnumState.START : "endOffset() called before nextDoc()/advance()";
|
||||
assert state != DocsEnumState.FINISHED : "endOffset() called after NO_MORE_DOCS";
|
||||
assert positionCount > 0 : "endOffset() called before nextPosition()!";
|
||||
return super.endOffset();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BytesRef getPayload() throws IOException {
|
||||
assert state != DocsEnumState.START : "getPayload() called before nextDoc()/advance()";
|
||||
assert state != DocsEnumState.FINISHED : "getPayload() called after NO_MORE_DOCS";
|
||||
assert positionCount > 0 : "getPayload() called before nextPosition()!";
|
||||
return super.getPayload();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPayload() {
|
||||
assert state != DocsEnumState.START : "hasPayload() called before nextDoc()/advance()";
|
||||
assert state != DocsEnumState.FINISHED : "hasPayload() called after NO_MORE_DOCS";
|
||||
assert positionCount > 0 : "hasPayload() called before nextPosition()!";
|
||||
return super.hasPayload();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,90 @@
|
|||
package org.apache.lucene.index;
|
||||
|
||||
/*
|
||||
* 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 java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A {@link DirectoryReader} that wraps all its subreaders with
|
||||
* {@link AssertingAtomicReader}
|
||||
*/
|
||||
public class AssertingDirectoryReader extends DirectoryReader {
|
||||
protected DirectoryReader in;
|
||||
|
||||
public AssertingDirectoryReader(DirectoryReader in) {
|
||||
super(in.directory(), wrap(in.getSequentialSubReaders()));
|
||||
this.in = in;
|
||||
}
|
||||
|
||||
private static AtomicReader[] wrap(List<? extends AtomicReader> readers) {
|
||||
AtomicReader[] wrapped = new AtomicReader[readers.size()];
|
||||
for (int i = 0; i < readers.size(); i++) {
|
||||
wrapped[i] = new AssertingAtomicReader(readers.get(i));
|
||||
}
|
||||
return wrapped;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected DirectoryReader doOpenIfChanged() throws IOException {
|
||||
DirectoryReader d = in.doOpenIfChanged();
|
||||
return d == null ? null : new AssertingDirectoryReader(d);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected DirectoryReader doOpenIfChanged(IndexCommit commit) throws IOException {
|
||||
DirectoryReader d = in.doOpenIfChanged(commit);
|
||||
return d == null ? null : new AssertingDirectoryReader(d);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected DirectoryReader doOpenIfChanged(IndexWriter writer, boolean applyAllDeletes) throws IOException {
|
||||
DirectoryReader d = in.doOpenIfChanged(writer, applyAllDeletes);
|
||||
return d == null ? null : new AssertingDirectoryReader(d);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getVersion() {
|
||||
return in.getVersion();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCurrent() throws IOException {
|
||||
return in.isCurrent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public IndexCommit getIndexCommit() throws IOException {
|
||||
return in.getIndexCommit();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doClose() throws IOException {
|
||||
in.doClose();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getCoreCacheKey() {
|
||||
return in.getCoreCacheKey();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getCombinedCoreAndDeletesKey() {
|
||||
return in.getCombinedCoreAndDeletesKey();
|
||||
}
|
||||
}
|
|
@ -28,6 +28,7 @@ import java.util.Random;
|
|||
import java.util.Set;
|
||||
|
||||
import org.apache.lucene.codecs.PostingsFormat;
|
||||
import org.apache.lucene.codecs.asserting.AssertingPostingsFormat;
|
||||
import org.apache.lucene.codecs.lucene40.Lucene40Codec;
|
||||
import org.apache.lucene.codecs.lucene40.Lucene40PostingsFormat;
|
||||
import org.apache.lucene.codecs.lucene40ords.Lucene40WithOrds;
|
||||
|
@ -99,6 +100,7 @@ public class RandomCodec extends Lucene40Codec {
|
|||
new NestedPulsingPostingsFormat(),
|
||||
new Lucene40WithOrds(),
|
||||
new SimpleTextPostingsFormat(),
|
||||
new AssertingPostingsFormat(),
|
||||
new MemoryPostingsFormat(true, random.nextFloat()),
|
||||
new MemoryPostingsFormat(false, random.nextFloat()));
|
||||
|
||||
|
|
|
@ -1010,7 +1010,7 @@ public abstract class LuceneTestCase extends Assert {
|
|||
// TODO: remove this, and fix those tests to wrap before putting slow around:
|
||||
final boolean wasOriginallyAtomic = r instanceof AtomicReader;
|
||||
for (int i = 0, c = random.nextInt(6)+1; i < c; i++) {
|
||||
switch(random.nextInt(4)) {
|
||||
switch(random.nextInt(5)) {
|
||||
case 0:
|
||||
r = SlowCompositeReaderWrapper.wrap(r);
|
||||
break;
|
||||
|
@ -1041,6 +1041,16 @@ public abstract class LuceneTestCase extends Assert {
|
|||
new FieldFilterAtomicReader(ar, fields, true)
|
||||
);
|
||||
break;
|
||||
case 4:
|
||||
// Häckidy-Hick-Hack: a standard Reader will cause FC insanity, so we use
|
||||
// QueryUtils' reader with a fake cache key, so insanity checker cannot walk
|
||||
// along our reader:
|
||||
if (r instanceof AtomicReader) {
|
||||
r = new FCInvisibleMultiReader(new AssertingAtomicReader((AtomicReader)r));
|
||||
} else if (r instanceof DirectoryReader) {
|
||||
r = new FCInvisibleMultiReader(new AssertingDirectoryReader((DirectoryReader)r));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
fail("should not get here");
|
||||
}
|
||||
|
|
|
@ -30,6 +30,7 @@ import java.util.TimeZone;
|
|||
import org.apache.lucene.codecs.Codec;
|
||||
import org.apache.lucene.codecs.PostingsFormat;
|
||||
import org.apache.lucene.codecs.appending.AppendingCodec;
|
||||
import org.apache.lucene.codecs.asserting.AssertingCodec;
|
||||
import org.apache.lucene.codecs.lucene40.Lucene40Codec;
|
||||
import org.apache.lucene.codecs.mockrandom.MockRandomPostingsFormat;
|
||||
import org.apache.lucene.codecs.simpletext.SimpleTextCodec;
|
||||
|
@ -189,6 +190,8 @@ final class TestRuleSetupAndRestoreClassEnv extends AbstractBeforeAfterRule {
|
|||
codec = new SimpleTextCodec();
|
||||
} else if ("Appending".equals(TEST_CODEC) || ("random".equals(TEST_CODEC) && randomVal == 8 && !shouldAvoidCodec("Appending"))) {
|
||||
codec = new AppendingCodec();
|
||||
} else if ("Asserting".equals(TEST_CODEC) || ("random".equals(TEST_CODEC) && randomVal == 7 && !shouldAvoidCodec("Asserting"))) {
|
||||
codec = new AssertingCodec();
|
||||
} else if (!"random".equals(TEST_CODEC)) {
|
||||
codec = Codec.forName(TEST_CODEC);
|
||||
} else if ("random".equals(TEST_POSTINGSFORMAT)) {
|
||||
|
|
|
@ -13,3 +13,4 @@
|
|||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
org.apache.lucene.codecs.asserting.AssertingCodec
|
||||
|
|
|
@ -20,3 +20,5 @@ org.apache.lucene.codecs.mocksep.MockSepPostingsFormat
|
|||
org.apache.lucene.codecs.nestedpulsing.NestedPulsingPostingsFormat
|
||||
org.apache.lucene.codecs.ramonly.RAMOnlyPostingsFormat
|
||||
org.apache.lucene.codecs.lucene40ords.Lucene40WithOrds
|
||||
org.apache.lucene.codecs.asserting.AssertingPostingsFormat
|
||||
|
||||
|
|
Loading…
Reference in New Issue