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;
|
this.subs[i].slice = subs[i].slice;
|
||||||
}
|
}
|
||||||
upto = -1;
|
upto = -1;
|
||||||
|
doc = -1;
|
||||||
current = null;
|
current = null;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
@ -69,6 +70,7 @@ public final class MultiDocsAndPositionsEnum extends DocsAndPositionsEnum {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int freq() throws IOException {
|
public int freq() throws IOException {
|
||||||
|
assert current != null;
|
||||||
return current.freq();
|
return current.freq();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -52,6 +52,7 @@ public final class MultiDocsEnum extends DocsEnum {
|
||||||
this.subs[i].slice = subs[i].slice;
|
this.subs[i].slice = subs[i].slice;
|
||||||
}
|
}
|
||||||
upto = -1;
|
upto = -1;
|
||||||
|
doc = -1;
|
||||||
current = null;
|
current = null;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,6 +37,7 @@ import org.apache.lucene.index.Fields;
|
||||||
import org.apache.lucene.index.IndexReader;
|
import org.apache.lucene.index.IndexReader;
|
||||||
import org.apache.lucene.index.Terms;
|
import org.apache.lucene.index.Terms;
|
||||||
import org.apache.lucene.index.TermsEnum;
|
import org.apache.lucene.index.TermsEnum;
|
||||||
|
import org.apache.lucene.search.DocIdSetIterator;
|
||||||
import org.apache.lucene.util.ArrayUtil;
|
import org.apache.lucene.util.ArrayUtil;
|
||||||
import org.apache.lucene.util.BytesRef;
|
import org.apache.lucene.util.BytesRef;
|
||||||
|
|
||||||
|
@ -128,6 +129,8 @@ public class TokenSources {
|
||||||
if (termsEnum.next() != null) {
|
if (termsEnum.next() != null) {
|
||||||
DocsAndPositionsEnum dpEnum = termsEnum.docsAndPositions(null, null, false);
|
DocsAndPositionsEnum dpEnum = termsEnum.docsAndPositions(null, null, false);
|
||||||
if (dpEnum != null) {
|
if (dpEnum != null) {
|
||||||
|
int doc = dpEnum.nextDoc();
|
||||||
|
assert doc >= 0 && doc != DocIdSetIterator.NO_MORE_DOCS;
|
||||||
int pos = dpEnum.nextPosition();
|
int pos = dpEnum.nextPosition();
|
||||||
if (pos >= 0) {
|
if (pos >= 0) {
|
||||||
return true;
|
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 java.util.Set;
|
||||||
|
|
||||||
import org.apache.lucene.codecs.PostingsFormat;
|
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.Lucene40Codec;
|
||||||
import org.apache.lucene.codecs.lucene40.Lucene40PostingsFormat;
|
import org.apache.lucene.codecs.lucene40.Lucene40PostingsFormat;
|
||||||
import org.apache.lucene.codecs.lucene40ords.Lucene40WithOrds;
|
import org.apache.lucene.codecs.lucene40ords.Lucene40WithOrds;
|
||||||
|
@ -99,6 +100,7 @@ public class RandomCodec extends Lucene40Codec {
|
||||||
new NestedPulsingPostingsFormat(),
|
new NestedPulsingPostingsFormat(),
|
||||||
new Lucene40WithOrds(),
|
new Lucene40WithOrds(),
|
||||||
new SimpleTextPostingsFormat(),
|
new SimpleTextPostingsFormat(),
|
||||||
|
new AssertingPostingsFormat(),
|
||||||
new MemoryPostingsFormat(true, random.nextFloat()),
|
new MemoryPostingsFormat(true, random.nextFloat()),
|
||||||
new MemoryPostingsFormat(false, 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:
|
// TODO: remove this, and fix those tests to wrap before putting slow around:
|
||||||
final boolean wasOriginallyAtomic = r instanceof AtomicReader;
|
final boolean wasOriginallyAtomic = r instanceof AtomicReader;
|
||||||
for (int i = 0, c = random.nextInt(6)+1; i < c; i++) {
|
for (int i = 0, c = random.nextInt(6)+1; i < c; i++) {
|
||||||
switch(random.nextInt(4)) {
|
switch(random.nextInt(5)) {
|
||||||
case 0:
|
case 0:
|
||||||
r = SlowCompositeReaderWrapper.wrap(r);
|
r = SlowCompositeReaderWrapper.wrap(r);
|
||||||
break;
|
break;
|
||||||
|
@ -1041,6 +1041,16 @@ public abstract class LuceneTestCase extends Assert {
|
||||||
new FieldFilterAtomicReader(ar, fields, true)
|
new FieldFilterAtomicReader(ar, fields, true)
|
||||||
);
|
);
|
||||||
break;
|
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:
|
default:
|
||||||
fail("should not get here");
|
fail("should not get here");
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,6 +30,7 @@ import java.util.TimeZone;
|
||||||
import org.apache.lucene.codecs.Codec;
|
import org.apache.lucene.codecs.Codec;
|
||||||
import org.apache.lucene.codecs.PostingsFormat;
|
import org.apache.lucene.codecs.PostingsFormat;
|
||||||
import org.apache.lucene.codecs.appending.AppendingCodec;
|
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.lucene40.Lucene40Codec;
|
||||||
import org.apache.lucene.codecs.mockrandom.MockRandomPostingsFormat;
|
import org.apache.lucene.codecs.mockrandom.MockRandomPostingsFormat;
|
||||||
import org.apache.lucene.codecs.simpletext.SimpleTextCodec;
|
import org.apache.lucene.codecs.simpletext.SimpleTextCodec;
|
||||||
|
@ -189,6 +190,8 @@ final class TestRuleSetupAndRestoreClassEnv extends AbstractBeforeAfterRule {
|
||||||
codec = new SimpleTextCodec();
|
codec = new SimpleTextCodec();
|
||||||
} else if ("Appending".equals(TEST_CODEC) || ("random".equals(TEST_CODEC) && randomVal == 8 && !shouldAvoidCodec("Appending"))) {
|
} else if ("Appending".equals(TEST_CODEC) || ("random".equals(TEST_CODEC) && randomVal == 8 && !shouldAvoidCodec("Appending"))) {
|
||||||
codec = new AppendingCodec();
|
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)) {
|
} else if (!"random".equals(TEST_CODEC)) {
|
||||||
codec = Codec.forName(TEST_CODEC);
|
codec = Codec.forName(TEST_CODEC);
|
||||||
} else if ("random".equals(TEST_POSTINGSFORMAT)) {
|
} else if ("random".equals(TEST_POSTINGSFORMAT)) {
|
||||||
|
|
|
@ -13,3 +13,4 @@
|
||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# 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.nestedpulsing.NestedPulsingPostingsFormat
|
||||||
org.apache.lucene.codecs.ramonly.RAMOnlyPostingsFormat
|
org.apache.lucene.codecs.ramonly.RAMOnlyPostingsFormat
|
||||||
org.apache.lucene.codecs.lucene40ords.Lucene40WithOrds
|
org.apache.lucene.codecs.lucene40ords.Lucene40WithOrds
|
||||||
|
org.apache.lucene.codecs.asserting.AssertingPostingsFormat
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue