| /* |
| * 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.backward_codecs.lucene70; |
| |
| import java.io.IOException; |
| import java.util.ArrayList; |
| import java.util.List; |
| import org.apache.lucene.search.DocIdSetIterator; |
| import org.apache.lucene.store.Directory; |
| import org.apache.lucene.store.IOContext; |
| import org.apache.lucene.store.IndexInput; |
| import org.apache.lucene.store.IndexOutput; |
| import org.apache.lucene.util.BitSetIterator; |
| import org.apache.lucene.util.FixedBitSet; |
| import org.apache.lucene.util.LuceneTestCase; |
| import org.apache.lucene.util.TestUtil; |
| |
| public class TestIndexedDISI extends LuceneTestCase { |
| |
| public void testEmpty() throws IOException { |
| int maxDoc = TestUtil.nextInt(random(), 1, 100000); |
| FixedBitSet set = new FixedBitSet(maxDoc); |
| try (Directory dir = newDirectory()) { |
| doTest(set, dir); |
| } |
| } |
| |
| public void testOneDoc() throws IOException { |
| int maxDoc = TestUtil.nextInt(random(), 1, 100000); |
| FixedBitSet set = new FixedBitSet(maxDoc); |
| set.set(random().nextInt(maxDoc)); |
| try (Directory dir = newDirectory()) { |
| doTest(set, dir); |
| } |
| } |
| |
| public void testTwoDocs() throws IOException { |
| int maxDoc = TestUtil.nextInt(random(), 1, 100000); |
| FixedBitSet set = new FixedBitSet(maxDoc); |
| set.set(random().nextInt(maxDoc)); |
| set.set(random().nextInt(maxDoc)); |
| try (Directory dir = newDirectory()) { |
| doTest(set, dir); |
| } |
| } |
| |
| public void testAllDocs() throws IOException { |
| int maxDoc = TestUtil.nextInt(random(), 1, 100000); |
| FixedBitSet set = new FixedBitSet(maxDoc); |
| set.set(1, maxDoc); |
| try (Directory dir = newDirectory()) { |
| doTest(set, dir); |
| } |
| } |
| |
| public void testHalfFull() throws IOException { |
| int maxDoc = TestUtil.nextInt(random(), 1, 100000); |
| FixedBitSet set = new FixedBitSet(maxDoc); |
| for (int i = random().nextInt(2); i < maxDoc; i += TestUtil.nextInt(random(), 1, 3)) { |
| set.set(i); |
| } |
| try (Directory dir = newDirectory()) { |
| doTest(set, dir); |
| } |
| } |
| |
| public void testDocRange() throws IOException { |
| try (Directory dir = newDirectory()) { |
| for (int iter = 0; iter < 10; ++iter) { |
| int maxDoc = TestUtil.nextInt(random(), 1, 1000000); |
| FixedBitSet set = new FixedBitSet(maxDoc); |
| final int start = random().nextInt(maxDoc); |
| final int end = TestUtil.nextInt(random(), start + 1, maxDoc); |
| set.set(start, end); |
| doTest(set, dir); |
| } |
| } |
| } |
| |
| public void testSparseDenseBoundary() throws IOException { |
| try (Directory dir = newDirectory()) { |
| FixedBitSet set = new FixedBitSet(200000); |
| int start = 65536 + random().nextInt(100); |
| |
| // we set MAX_ARRAY_LENGTH bits so the encoding will be sparse |
| set.set(start, start + IndexedDISI.MAX_ARRAY_LENGTH); |
| long length; |
| try (IndexOutput out = dir.createOutput("sparse", IOContext.DEFAULT)) { |
| IndexedDISI.writeBitSet(new BitSetIterator(set, IndexedDISI.MAX_ARRAY_LENGTH), out); |
| length = out.getFilePointer(); |
| } |
| try (IndexInput in = dir.openInput("sparse", IOContext.DEFAULT)) { |
| IndexedDISI disi = new IndexedDISI(in, 0L, length, IndexedDISI.MAX_ARRAY_LENGTH); |
| assertEquals(start, disi.nextDoc()); |
| assertEquals(IndexedDISI.Method.SPARSE, disi.method); |
| } |
| doTest(set, dir); |
| |
| // now we set one more bit so the encoding will be dense |
| set.set(start + IndexedDISI.MAX_ARRAY_LENGTH + random().nextInt(100)); |
| try (IndexOutput out = dir.createOutput("bar", IOContext.DEFAULT)) { |
| IndexedDISI.writeBitSet(new BitSetIterator(set, IndexedDISI.MAX_ARRAY_LENGTH + 1), out); |
| length = out.getFilePointer(); |
| } |
| try (IndexInput in = dir.openInput("bar", IOContext.DEFAULT)) { |
| IndexedDISI disi = new IndexedDISI(in, 0L, length, IndexedDISI.MAX_ARRAY_LENGTH + 1); |
| assertEquals(start, disi.nextDoc()); |
| assertEquals(IndexedDISI.Method.DENSE, disi.method); |
| } |
| doTest(set, dir); |
| } |
| } |
| |
| public void testOneDocMissing() throws IOException { |
| int maxDoc = TestUtil.nextInt(random(), 1, 1000000); |
| FixedBitSet set = new FixedBitSet(maxDoc); |
| set.set(0, maxDoc); |
| set.clear(random().nextInt(maxDoc)); |
| try (Directory dir = newDirectory()) { |
| doTest(set, dir); |
| } |
| } |
| |
| public void testFewMissingDocs() throws IOException { |
| try (Directory dir = newDirectory()) { |
| int numIters = atLeast(10); |
| for (int iter = 0; iter < numIters; ++iter) { |
| int maxDoc = TestUtil.nextInt(random(), 1, 100000); |
| FixedBitSet set = new FixedBitSet(maxDoc); |
| set.set(0, maxDoc); |
| final int numMissingDocs = TestUtil.nextInt(random(), 2, 1000); |
| for (int i = 0; i < numMissingDocs; ++i) { |
| set.clear(random().nextInt(maxDoc)); |
| } |
| doTest(set, dir); |
| } |
| } |
| } |
| |
| public void testRandom() throws IOException { |
| try (Directory dir = newDirectory()) { |
| int numIters = atLeast(3); |
| for (int i = 0; i < numIters; ++i) { |
| doTestRandom(dir); |
| } |
| } |
| } |
| |
| private void doTestRandom(Directory dir) throws IOException { |
| List<Integer> docs = new ArrayList<>(); |
| final int maxStep = TestUtil.nextInt(random(), 1, 1 << TestUtil.nextInt(random(), 2, 20)); |
| final int numDocs = |
| TestUtil.nextInt(random(), 1, Math.min(100000, Integer.MAX_VALUE / maxStep)); |
| for (int doc = -1, i = 0; i < numDocs; ++i) { |
| doc += TestUtil.nextInt(random(), 1, maxStep); |
| docs.add(doc); |
| } |
| final int maxDoc = docs.get(docs.size() - 1) + TestUtil.nextInt(random(), 1, 100); |
| |
| FixedBitSet set = new FixedBitSet(maxDoc); |
| for (int doc : docs) { |
| set.set(doc); |
| } |
| |
| doTest(set, dir); |
| } |
| |
| private void doTest(FixedBitSet set, Directory dir) throws IOException { |
| final int cardinality = set.cardinality(); |
| long length; |
| try (IndexOutput out = dir.createOutput("foo", IOContext.DEFAULT)) { |
| IndexedDISI.writeBitSet(new BitSetIterator(set, cardinality), out); |
| length = out.getFilePointer(); |
| } |
| |
| try (IndexInput in = dir.openInput("foo", IOContext.DEFAULT)) { |
| IndexedDISI disi = new IndexedDISI(in, 0L, length, cardinality); |
| BitSetIterator disi2 = new BitSetIterator(set, cardinality); |
| int i = 0; |
| for (int doc = disi2.nextDoc(); doc != DocIdSetIterator.NO_MORE_DOCS; doc = disi2.nextDoc()) { |
| assertEquals(doc, disi.nextDoc()); |
| assertEquals(i++, disi.index()); |
| } |
| assertEquals(DocIdSetIterator.NO_MORE_DOCS, disi.nextDoc()); |
| } |
| |
| for (int step : new int[] {1, 10, 100, 1000, 10000, 100000}) { |
| try (IndexInput in = dir.openInput("foo", IOContext.DEFAULT)) { |
| IndexedDISI disi = new IndexedDISI(in, 0L, length, cardinality); |
| BitSetIterator disi2 = new BitSetIterator(set, cardinality); |
| int index = -1; |
| while (true) { |
| int target = disi2.docID() + step; |
| int doc; |
| do { |
| doc = disi2.nextDoc(); |
| index++; |
| } while (doc < target); |
| assertEquals(doc, disi.advance(target)); |
| if (doc == DocIdSetIterator.NO_MORE_DOCS) { |
| break; |
| } |
| assertEquals(index, disi.index()); |
| } |
| } |
| } |
| |
| for (int step : new int[] {10, 100, 1000, 10000, 100000}) { |
| try (IndexInput in = dir.openInput("foo", IOContext.DEFAULT)) { |
| IndexedDISI disi = new IndexedDISI(in, 0L, length, cardinality); |
| BitSetIterator disi2 = new BitSetIterator(set, cardinality); |
| int index = -1; |
| for (int target = 0; target < set.length(); ) { |
| target += TestUtil.nextInt(random(), 0, step); |
| int doc = disi2.docID(); |
| while (doc < target) { |
| doc = disi2.nextDoc(); |
| index++; |
| } |
| |
| boolean exists = disi.advanceExact(target); |
| assertEquals(doc == target, exists); |
| if (exists) { |
| assertEquals(index, disi.index()); |
| } else if (random().nextBoolean()) { |
| assertEquals(doc, disi.nextDoc()); |
| assertEquals(index, disi.index()); |
| target = doc; |
| } |
| } |
| } |
| } |
| |
| dir.deleteFile("foo"); |
| } |
| } |