add --shared
[pylucene.git] / lucene-java-3.4.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.optimize();
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               this.input = input;
170           }      
171                 
172           @Override
173           public byte readByte() throws IOException {
174               return this.input.readByte();
175           }
176     
177           @Override
178           public void readBytes(byte[] b, int offset, int len) throws IOException {
179               this.input.readBytes(b, offset, len);        
180           }
181     
182           @Override
183           public void close() throws IOException {
184               this.input.close();
185           }
186     
187           @Override
188           public long getFilePointer() {
189               return this.input.getFilePointer();
190           }
191     
192           @Override
193           public void seek(long pos) throws IOException {
194               TestLazyProxSkipping.this.seeksCounter++;
195               this.input.seek(pos);
196           }
197     
198           @Override
199           public long length() {
200               return this.input.length();
201           }
202           
203           @Override
204           public Object clone() {
205               return new SeeksCountingStream((IndexInput) this.input.clone());
206           }
207       
208     }
209 }