pylucene 3.5.0-3
[pylucene.git] / lucene-java-3.5.0 / lucene / src / test / org / apache / lucene / index / TestLazyProxSkipping.java
1 package org.apache.lucene.index;
2
3 /**
4  * Licensed to the Apache Software Foundation (ASF) under one or more
5  * contributor license agreements.  See the NOTICE file distributed with
6  * this work for additional information regarding copyright ownership.
7  * The ASF licenses this file to You under the Apache License, Version 2.0
8  * (the "License"); you may not use this file except in compliance with
9  * the License.  You may obtain a copy of the License at
10  *
11  *     http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  */
19
20 import java.io.IOException;
21
22 import org.apache.lucene.analysis.MockAnalyzer;
23 import org.apache.lucene.analysis.WhitespaceAnalyzer;
24 import org.apache.lucene.document.Document;
25 import org.apache.lucene.document.Field;
26 import org.apache.lucene.search.PhraseQuery;
27 import org.apache.lucene.search.ScoreDoc;
28 import org.apache.lucene.search.Searcher;
29 import org.apache.lucene.store.Directory;
30 import org.apache.lucene.store.IndexInput;
31 import org.apache.lucene.store.MockDirectoryWrapper;
32 import org.apache.lucene.store.RAMDirectory;
33 import org.apache.lucene.util.LuceneTestCase;
34
35 /**
36  * Tests lazy skipping on the proximity file.
37  *
38  */
39 public class TestLazyProxSkipping extends LuceneTestCase {
40     private Searcher searcher;
41     private int seeksCounter = 0;
42     
43     private String field = "tokens";
44     private String term1 = "xx";
45     private String term2 = "yy";
46     private String term3 = "zz";
47
48     private class SeekCountingDirectory extends MockDirectoryWrapper {
49       public SeekCountingDirectory(Directory delegate) {
50         super(random, delegate);
51       }
52
53       @Override
54       public IndexInput openInput(String name) throws IOException {
55         IndexInput ii = super.openInput(name);
56         if (name.endsWith(".prx")) {
57           // we decorate the proxStream with a wrapper class that allows to count the number of calls of seek()
58           ii = new SeeksCountingStream(ii);
59         }
60         return ii;
61       }
62       
63     }
64     
65     private void createIndex(int numHits) throws IOException {
66         int numDocs = 500;
67         
68         Directory directory = new SeekCountingDirectory(new RAMDirectory());
69         // note: test explicitly disables payloads
70         IndexWriter writer = new IndexWriter(
71             directory,
72             newIndexWriterConfig(TEST_VERSION_CURRENT, new WhitespaceAnalyzer(TEST_VERSION_CURRENT)).
73                 setMaxBufferedDocs(10).
74                 setMergePolicy(newLogMergePolicy(false))
75         );
76         for (int i = 0; i < numDocs; i++) {
77             Document doc = new Document();
78             String content;
79             if (i % (numDocs / numHits) == 0) {
80                 // add a document that matches the query "term1 term2"
81                 content = this.term1 + " " + this.term2;
82             } else if (i % 15 == 0) {
83                 // add a document that only contains term1
84                 content = this.term1 + " " + this.term1;
85             } else {
86                 // add a document that contains term2 but not term 1
87                 content = this.term3 + " " + this.term2;
88             }
89
90             doc.add(newField(this.field, content, Field.Store.YES, Field.Index.ANALYZED));
91             writer.addDocument(doc);
92         }
93         
94         // make sure the index has only a single segment
95         writer.forceMerge(1);
96         writer.close();
97         
98         SegmentReader reader = SegmentReader.getOnlySegmentReader(directory);
99
100       this.searcher = newSearcher(reader);
101     }
102     
103     private ScoreDoc[] search() throws IOException {
104         // create PhraseQuery "term1 term2" and search
105         PhraseQuery pq = new PhraseQuery();
106         pq.add(new Term(this.field, this.term1));
107         pq.add(new Term(this.field, this.term2));
108         return this.searcher.search(pq, null, 1000).scoreDocs;        
109     }
110     
111     private void performTest(int numHits) throws IOException {
112         createIndex(numHits);
113         this.seeksCounter = 0;
114         ScoreDoc[] hits = search();
115         // verify that the right number of docs was found
116         assertEquals(numHits, hits.length);
117         
118         // check if the number of calls of seek() does not exceed the number of hits
119         assertTrue(this.seeksCounter > 0);
120         assertTrue(this.seeksCounter <= numHits + 1);
121     }
122     
123     public void testLazySkipping() throws IOException {
124         // test whether only the minimum amount of seeks()
125         // are performed
126         performTest(5);
127         searcher.close();
128         performTest(10);
129         searcher.close();
130     }
131     
132     public void testSeek() throws IOException {
133         Directory directory = newDirectory();
134         IndexWriter writer = new IndexWriter(directory, newIndexWriterConfig( TEST_VERSION_CURRENT, new MockAnalyzer(random)));
135         for (int i = 0; i < 10; i++) {
136             Document doc = new Document();
137             doc.add(newField(this.field, "a b", Field.Store.YES, Field.Index.ANALYZED));
138             writer.addDocument(doc);
139         }
140         
141         writer.close();
142         IndexReader reader = IndexReader.open(directory, true);
143         TermPositions tp = reader.termPositions();
144         tp.seek(new Term(this.field, "b"));
145         for (int i = 0; i < 10; i++) {
146             tp.next();
147             assertEquals(tp.doc(), i);
148             assertEquals(tp.nextPosition(), 1);
149         }
150         tp.seek(new Term(this.field, "a"));
151         for (int i = 0; i < 10; i++) {
152             tp.next();
153             assertEquals(tp.doc(), i);
154             assertEquals(tp.nextPosition(), 0);
155         }
156         reader.close();
157         directory.close();
158         
159     }
160     
161
162     // Simply extends IndexInput in a way that we are able to count the number
163     // of invocations of seek()
164     class SeeksCountingStream extends IndexInput {
165           private IndexInput input;      
166           
167           
168           SeeksCountingStream(IndexInput input) {
169               super("SeekCountingStream(" + input + ")");
170               this.input = input;
171           }      
172                 
173           @Override
174           public byte readByte() throws IOException {
175               return this.input.readByte();
176           }
177     
178           @Override
179           public void readBytes(byte[] b, int offset, int len) throws IOException {
180               this.input.readBytes(b, offset, len);        
181           }
182     
183           @Override
184           public void close() throws IOException {
185               this.input.close();
186           }
187     
188           @Override
189           public long getFilePointer() {
190               return this.input.getFilePointer();
191           }
192     
193           @Override
194           public void seek(long pos) throws IOException {
195               TestLazyProxSkipping.this.seeksCounter++;
196               this.input.seek(pos);
197           }
198     
199           @Override
200           public long length() {
201               return this.input.length();
202           }
203           
204           @Override
205           public Object clone() {
206               return new SeeksCountingStream((IndexInput) this.input.clone());
207           }
208       
209     }
210 }