1 package com.atlassian.bonnie;
2
3 import junit.framework.TestCase;
4 import org.apache.lucene.analysis.standard.StandardAnalyzer;
5 import org.apache.lucene.document.Document;
6 import org.apache.lucene.document.Field;
7 import org.apache.lucene.index.IndexReader;
8 import org.apache.lucene.index.IndexWriter;
9 import org.apache.lucene.index.Term;
10 import org.apache.lucene.search.Hits;
11 import org.apache.lucene.search.IndexSearcher;
12 import org.apache.lucene.search.TermQuery;
13 import org.apache.lucene.store.FSDirectory;
14 import org.apache.lucene.store.RAMDirectory;
15
16 import java.io.File;
17 import java.io.IOException;
18
19 public class TestLuceneConnection extends TestCase
20 {
21 LuceneConnection lcon;
22
23 private File tempDir;
24
25 private static final String FIELD_NAME = "content.space";
26
27 private static final String FIELD_VALUE = "space";
28
29 protected void setUp() throws Exception
30 {
31 super.setUp();
32 tempDir = File.createTempFile("lucene", "conn");
33 tempDir.delete();
34 tempDir.mkdirs();
35 lcon = new LuceneConnection(tempDir, new StandardAnalyzer());
36 }
37
38 protected void tearDown() throws Exception
39 {
40 super.tearDown();
41 }
42
43 public void testSetReindexing() throws IOException
44 {
45
46 assertFalse(new File(tempDir, LuceneConnection.REINDEXING_FILENAME).exists());
47
48 lcon.setReIndexing(true);
49 assertTrue(new File(tempDir, LuceneConnection.REINDEXING_FILENAME).exists());
50
51 lcon.setReIndexing(false);
52 assertFalse(new File(tempDir, LuceneConnection.REINDEXING_FILENAME).exists());
53
54
55 final int numDocs = 20;
56 lcon.getNumDocs();
57
58 lcon.setReIndexing(true);
59 addDocsToIndex(numDocs);
60
61 assertEquals(0, lcon.getNumDocs());
62
63 lcon.setReIndexing(false);
64 assertEquals(numDocs, lcon.getNumDocs());
65 }
66
67 public void testUnlockIfNeeded() throws IOException
68 {
69
70 lcon.withWriter(new LuceneConnection.WriterAction()
71 {
72 public void perform(IndexWriter writer) throws IOException
73 {}
74 });
75
76
77 IndexWriter writer = new IndexWriter(tempDir, new StandardAnalyzer(), false);
78 writer.addDocument(createDocument());
79
80 lcon.setAlwaysUnlock(false);
81 try
82 {
83 lcon.withWriter(new LuceneConnection.WriterAction()
84 {
85 public void perform(IndexWriter writer) throws IOException
86 {}
87 });
88 fail("Something wrong with testUnlockIfNeeded testcase");
89 }
90 catch (LuceneException e)
91 {}
92
93 lcon.setAlwaysUnlock(true);
94 lcon.withWriter(new LuceneConnection.WriterAction()
95 {
96 public void perform(IndexWriter writer) throws IOException
97 {}
98 });
99 }
100
101
102
103
104
105 public void testSearch() throws IOException
106 {
107 lcon = new LuceneConnection(FSDirectory.getDirectory(tempDir), new StandardAnalyzer(), new LuceneConnection.Configuration()
108 {
109
110 public int getBatchMaxBufferedDocs()
111 {
112 return 100;
113 }
114
115 public int getBatchMaxMergeDocs()
116 {
117 return 200;
118 }
119
120 public int getBatchMergeFactor()
121 {
122 return 300;
123 }
124
125 public int getInteractiveMaxBufferedDocs()
126 {
127 return 10;
128 }
129
130 public int getInteractiveMaxMergeDocs()
131 {
132 return 20;
133 }
134
135 public int getInteractiveMergeFactor()
136 {
137 return 30;
138 }
139
140 public int getMaxFieldLength()
141 {
142 return 1000000;
143 }
144
145
146
147 public boolean isCompoundIndexFileFormat()
148 {
149 return false;
150 }
151 });
152 final int numDocs = 5;
153 addDocsToIndex(numDocs);
154
155
156 final IndexSearcher[] s = new IndexSearcher[] { null };
157 lcon.withSearch(new LuceneConnection.SearcherAction()
158 {
159 public void perform(IndexSearcher searcher) throws IOException
160 {
161 s[0] = searcher;
162 }
163 });
164 try
165 {
166 s[0].search(new TermQuery(new Term(FIELD_NAME, FIELD_VALUE)));
167 fail("Searcher not being closed.");
168 }
169 catch (Exception e)
170 {}
171 }
172
173 private void addDocsToIndex(final int numDocs)
174 {
175 lcon.withWriter(new LuceneConnection.WriterAction()
176 {
177 public void perform(IndexWriter writer) throws IOException
178 {
179 for (int i = 0; i < numDocs; ++i)
180 writer.addDocument(createDocument());
181 }
182 });
183 }
184
185 public void testMultiThreaded() throws InterruptedException
186 {
187 addDocsToIndex(5);
188 final Thread[] t = new Thread[1];
189
190 final boolean[] innerThreadExecuted = new boolean[]
191 { false };
192
193
194 lcon.withWriter(new LuceneConnection.WriterAction()
195 {
196 public void perform(final IndexWriter writer) throws IOException
197 {
198 writer.addDocument(createDocument());
199
200 t[0] = new Thread()
201 {
202 public void run()
203 {
204
205
206 lcon.withReaderAndDeletes(new LuceneConnection.ReaderAction()
207 {
208 public Object perform(IndexReader reader) throws IOException
209 {
210 innerThreadExecuted[0] = true;
211 assertEquals("threaded withWriter: Added document not detected from thread", 6, reader.numDocs());
212 reader.deleteDocument(0);
213 return null;
214 }
215 });
216 }
217 };
218 t[0].start();
219 Thread.yield();
220 assertFalse(innerThreadExecuted[0]);
221 }
222 });
223 t[0].join();
224 assertTrue(innerThreadExecuted[0]);
225 assertEquals("threaded withWriter: Document not deleted in thread", 5, lcon.getNumDocs());
226
227 innerThreadExecuted[0] = false;
228
229
230 lcon.withReaderAndDeletes(new LuceneConnection.ReaderAction()
231 {
232 public Object perform(final IndexReader reader) throws IOException
233 {
234 reader.deleteDocument(1);
235 t[0] = new Thread()
236 {
237 public void run()
238 {
239 lcon.withReader(new LuceneConnection.ReaderAction()
240 {
241 public Object perform(IndexReader reader) throws IOException
242 {
243 assertEquals("threaded withReaderAndDeletes: deleted document not detected", 4, reader.numDocs());
244 return null;
245 }
246 });
247
248
249
250 lcon.withWriter(new LuceneConnection.WriterAction()
251 {
252 public void perform(IndexWriter writer) throws IOException
253 {
254 innerThreadExecuted[0] = true;
255 writer.addDocument(createDocument());
256 }
257 });
258 }
259 };
260 t[0].start();
261 Thread.yield();
262 assertFalse(innerThreadExecuted[0]);
263 return null;
264 }
265 });
266 t[0].join();
267 assertTrue(innerThreadExecuted[0]);
268 assertEquals("threaded withReaderAndDeletes: Document not added in thread", 5, lcon.getNumDocs());
269 }
270
271
272
273
274
275
276
277 public void testDefaultConfiguration() throws Exception
278 {
279 lcon.withWriter(new LuceneConnection.WriterAction()
280 {
281 public void perform(IndexWriter writer) throws IOException
282 {
283 assertEquals(4, writer.getMergeFactor());
284 assertEquals(300, writer.getMaxBufferedDocs());
285 assertEquals(5000, writer.getMaxMergeDocs());
286 assertTrue(writer.getUseCompoundFile());
287 }
288 }, LuceneConnection.WRITER_INTERACTIVE);
289
290 lcon.withWriter(new LuceneConnection.WriterAction()
291 {
292 public void perform(IndexWriter writer) throws IOException
293 {
294 assertEquals(50, writer.getMergeFactor());
295 assertEquals(300, writer.getMaxBufferedDocs());
296 assertEquals(Integer.MAX_VALUE, writer.getMaxMergeDocs());
297 assertTrue(writer.getUseCompoundFile());
298 }
299 }, LuceneConnection.WRITER_BATCH);
300 }
301
302
303
304
305
306
307
308 public void testCustomConfiguration() throws Exception
309 {
310 LuceneConnection.Configuration config = new LuceneConnection.Configuration()
311 {
312
313 public int getBatchMaxBufferedDocs()
314 {
315 return 100;
316 }
317
318 public int getBatchMaxMergeDocs()
319 {
320 return 200;
321 }
322
323 public int getBatchMergeFactor()
324 {
325 return 300;
326 }
327
328 public int getInteractiveMaxBufferedDocs()
329 {
330 return 10;
331 }
332
333 public int getInteractiveMaxMergeDocs()
334 {
335 return 20;
336 }
337
338 public int getInteractiveMergeFactor()
339 {
340 return 30;
341 }
342
343 public int getMaxFieldLength()
344 {
345 return 1000000;
346 }
347
348 public boolean isCompoundIndexFileFormat()
349 {
350 return false;
351 }
352 };
353 assertLuceneConnectionConfig(new LuceneConnection(new RAMDirectory(), new StandardAnalyzer(), config));
354 assertLuceneConnectionConfig(new LuceneConnection(tempDir, new StandardAnalyzer(), config));
355 }
356
357 private void assertLuceneConnectionConfig(LuceneConnection lcon)
358 {
359 lcon.withWriter(new LuceneConnection.WriterAction()
360 {
361 public void perform(IndexWriter writer) throws IOException
362 {
363 assertEquals(30, writer.getMergeFactor());
364 assertEquals(10, writer.getMaxBufferedDocs());
365 assertEquals(20, writer.getMaxMergeDocs());
366 assertFalse(writer.getUseCompoundFile());
367 }
368 }, LuceneConnection.WRITER_INTERACTIVE);
369
370 lcon.withWriter(new LuceneConnection.WriterAction()
371 {
372 public void perform(IndexWriter writer) throws IOException
373 {
374 assertEquals(300, writer.getMergeFactor());
375 assertEquals(100, writer.getMaxBufferedDocs());
376 assertEquals(200, writer.getMaxMergeDocs());
377 assertFalse(writer.getUseCompoundFile());
378 }
379 }, LuceneConnection.WRITER_BATCH);
380 }
381
382 private Document createDocument()
383 {
384 Document d = new Document();
385 d.add(new Field(FIELD_NAME, FIELD_VALUE, Field.Store.YES, Field.Index.TOKENIZED));
386 return d;
387 }
388 }