blob: 5e19bbbe698c68dfa4b29ef19d3dab2835b67eea [file] [log] [blame]
/*
* 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.
*/
package org.apache.lucene.index;
import java.util.ArrayList;
import java.util.List;
import org.apache.lucene.util.FixedBitSet;
import org.apache.lucene.util.LuceneTestCase;
import org.apache.lucene.util.TestUtil;
import static org.apache.lucene.search.DocIdSetIterator.NO_MORE_DOCS;
public class TestDocIDMerger extends LuceneTestCase {
private static class TestSubUnsorted extends DocIDMerger.Sub {
private int docID = -1;
final int valueStart;
final int maxDoc;
public TestSubUnsorted(MergeState.DocMap docMap, int maxDoc, int valueStart) {
super(docMap);
this.maxDoc = maxDoc;
this.valueStart = valueStart;
}
@Override
public int nextDoc() {
docID++;
if (docID == maxDoc) {
return NO_MORE_DOCS;
} else {
return docID;
}
}
public int getValue() {
return valueStart + docID;
}
}
public void testNoSort() throws Exception {
int subCount = TestUtil.nextInt(random(), 1, 20);
List<TestSubUnsorted> subs = new ArrayList<>();
int valueStart = 0;
for(int i=0;i<subCount;i++) {
int maxDoc = TestUtil.nextInt(random(), 1, 1000);
final int docBase = valueStart;
subs.add(new TestSubUnsorted(new MergeState.DocMap() {
@Override
public int get(int docID) {
return docBase + docID;
}
}, maxDoc, valueStart));
valueStart += maxDoc;
}
DocIDMerger<TestSubUnsorted> merger = DocIDMerger.of(subs, false);
int count = 0;
while (true) {
TestSubUnsorted sub = merger.next();
if (sub == null) {
break;
}
assertEquals(count, sub.mappedDocID);
assertEquals(count, sub.getValue());
count++;
}
assertEquals(valueStart, count);
}
private static class TestSubSorted extends DocIDMerger.Sub {
private int docID = -1;
final int maxDoc;
final int index;
public TestSubSorted(MergeState.DocMap docMap, int maxDoc, int index) {
super(docMap);
this.maxDoc = maxDoc;
this.index = index;
}
@Override
public int nextDoc() {
docID++;
if (docID == maxDoc) {
return NO_MORE_DOCS;
} else {
return docID;
}
}
@Override
public String toString() {
return "TestSubSorted(index=" + index + ", mappedDocID=" + mappedDocID+ ")";
}
}
public void testWithSort() throws Exception {
int subCount = TestUtil.nextInt(random(), 1, 20);
List<int[]> oldToNew = new ArrayList<>();
// how many docs we've written to each sub:
List<Integer> uptos = new ArrayList<>();
int totDocCount = 0;
for(int i=0;i<subCount;i++) {
int maxDoc = TestUtil.nextInt(random(), 1, 1000);
uptos.add(0);
oldToNew.add(new int[maxDoc]);
totDocCount += maxDoc;
}
List<int[]> completedSubs = new ArrayList<>();
// randomly distribute target docIDs into the segments:
for(int docID=0;docID<totDocCount;docID++) {
int sub = random().nextInt(oldToNew.size());
int upto = uptos.get(sub);
int[] subDocs = oldToNew.get(sub);
subDocs[upto] = docID;
upto++;
if (upto == subDocs.length) {
completedSubs.add(subDocs);
oldToNew.remove(sub);
uptos.remove(sub);
} else {
uptos.set(sub, upto);
}
}
assertEquals(0, oldToNew.size());
// sometimes do some deletions:
final FixedBitSet liveDocs;
if (random().nextBoolean()) {
liveDocs = new FixedBitSet(totDocCount);
liveDocs.set(0, totDocCount);
int deleteAttemptCount = TestUtil.nextInt(random(), 1, totDocCount);
for(int i=0;i<deleteAttemptCount;i++) {
liveDocs.clear(random().nextInt(totDocCount));
}
} else {
liveDocs = null;
}
List<TestSubSorted> subs = new ArrayList<>();
for(int i=0;i<subCount;i++) {
final int[] docMap = completedSubs.get(i);
subs.add(new TestSubSorted(new MergeState.DocMap() {
@Override
public int get(int docID) {
int mapped = docMap[docID];
if (liveDocs == null || liveDocs.get(mapped)) {
return mapped;
} else {
return -1;
}
}
}, docMap.length, i));
}
DocIDMerger<TestSubSorted> merger = DocIDMerger.of(subs, true);
int count = 0;
while (true) {
TestSubSorted sub = merger.next();
if (sub == null) {
break;
}
if (liveDocs != null) {
count = liveDocs.nextSetBit(count);
}
assertEquals(count, sub.mappedDocID);
count++;
}
if (liveDocs != null) {
if (count < totDocCount) {
assertEquals(NO_MORE_DOCS, liveDocs.nextSetBit(count));
} else {
assertEquals(totDocCount, count);
}
} else {
assertEquals(totDocCount, count);
}
}
}