Index: src/test/org/apache/lucene/index/TestFieldDataStore.java
===================================================================
RCS file: src/test/org/apache/lucene/index/TestFieldDataStore.java
diff -N src/test/org/apache/lucene/index/TestFieldDataStore.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ src/test/org/apache/lucene/index/TestFieldDataStore.java 1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,257 @@
+package org.apache.lucene.index;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.Enumeration;
+import java.util.TreeSet;
+
+import junit.framework.TestCase;
+
+import org.apache.lucene.analysis.Analyzer;
+import org.apache.lucene.analysis.WhitespaceAnalyzer;
+import org.apache.lucene.document.Document;
+import org.apache.lucene.document.Field;
+import org.apache.lucene.store.RAMDirectory;
+
+/**
+ * Tests segmented field data storage (files *.fdt, *.fd1, *.fd2 etc.)
+ *
+ * @author Christian Kohlschuetter
+ */
+public class TestFieldDataStore extends TestCase {
+ private Analyzer a = new WhitespaceAnalyzer();
+
+ /*
+ * @see TestCase#setUp()
+ */
+ protected void setUp() throws Exception {
+ super.setUp();
+ }
+
+ /*
+ * @see TestCase#tearDown()
+ */
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ public void test1_regular() throws IOException {
+ internal1(false);
+ }
+
+ public void test1_compound() throws IOException {
+ internal1(true);
+ }
+
+ private void internal1(boolean useCompound) throws IOException {
+ RAMDirectory dir = new RAMDirectory();
+
+ IndexWriter iw = new IndexWriter(dir, a, true);
+ iw.setUseCompoundFile(useCompound);
+
+ Document doc;
+
+ /**
+ * Create three test documents
+ *
+ * Document 1 and 3 are regular (docStore is always == 0)
+ *
+ * Document 2 contains nine fields: two in docStore 0, three in
+ * docStore 1 and four in docStore 2
+ */
+
+ doc = new Document();
+ doc.add(Field.Keyword("regular", "doc1"));
+ iw.addDocument(doc);
+
+ doc = new Document();
+ doc.add(Field.Keyword("FIELD_0_STORE_0", "0/0"));
+ doc.add(Field.Keyword("FIELD_1_STORE_0", "1/0"));
+ doc.add(Field.Keyword("FIELD_0_STORE_1", "0/1").setDataStore(1));
+ doc.add(Field.Keyword("FIELD_1_STORE_1", "1/1").setDataStore(1));
+ doc.add(Field.Keyword("FIELD_2_STORE_1", "2/1").setDataStore(1));
+ doc.add(Field.Keyword("FIELD_0_STORE_2", "0/2").setDataStore(2));
+ doc.add(Field.Keyword("FIELD_1_STORE_2", "1/2").setDataStore(2));
+ doc.add(Field.Keyword("FIELD_2_STORE_2", "2/2").setDataStore(2));
+ doc.add(Field.Keyword("FIELD_3_STORE_2", "3/2").setDataStore(2));
+ iw.addDocument(doc);
+
+ /**
+ * This document cannot be added since the dataStoreID is
+ * non-contiguous. We will get an IOException when calling addDocument(doc)
+ */
+ doc = new Document();
+ doc.add(Field.Keyword("regular", "doc"));
+ doc.add(Field.Keyword("BADFIELD", "99").setDataStore(99));
+
+ boolean ok = false;
+ try {
+ iw.addDocument(doc);
+ } catch (IOException e) {
+ ok = true;
+ }
+ assertTrue("Did not receive expected IOException", ok);
+
+ /**
+ * A regular document again
+ */
+ doc = new Document();
+ doc.add(Field.Keyword("regular", "doc2"));
+ iw.addDocument(doc);
+
+ iw.close();
+
+ /**
+ * Now check the index
+ */
+ IndexReader ir = IndexReader.open(dir);
+ Enumeration e;
+ Field f;
+ assertEquals(3, ir.numDocs());
+
+ TreeSet tsExpected = new TreeSet(Arrays.asList(new String[] {
+ "", // is this correct?
+ "FIELD_0_STORE_0", "FIELD_1_STORE_0", "FIELD_0_STORE_1",
+ "FIELD_1_STORE_1", "FIELD_2_STORE_1", "FIELD_0_STORE_2",
+ "FIELD_1_STORE_2", "FIELD_2_STORE_2", "FIELD_3_STORE_2", "regular"
+ }));
+
+ TreeSet tsReal = new TreeSet(ir.getFieldNames());
+ assertEquals(tsExpected, tsReal);
+
+ /**
+ * Checks a regular document with all field data in the standard .fdt
+ * file (field store 0)
+ */
+ doc = ir.document(0);
+ e = doc.fields();
+ f = (Field) e.nextElement();
+ assertEquals("regular", f.name());
+ assertEquals("doc1", f.stringValue());
+ assertEquals(0, f.getDataStore());
+ assertFalse(e.hasMoreElements());
+
+ /**
+ * Checks ir.document(1,0) and ir.document(1,1) and ir.document(1,2)
+ */
+ for(int sm = 0; sm <= 2; sm++) {
+ doc = ir.document(1, sm);
+ e = doc.fields();
+ for(int sn = 0; sn <= sm; sn++) {
+ for(int fn = 0; fn < 2 + sn * 1; fn++) {
+ f = (Field) e.nextElement();
+ assertEquals("FIELD_" + fn + "_STORE_" + sn, f.name());
+ assertEquals(fn + "/" + sn, f.stringValue());
+ assertEquals(sn, f.getDataStore());
+ }
+ }
+
+ /**
+ * The following assert will fail with sm==0 or sm==1 if a
+ * docStore-unaware IndexReader is used as in that case, all field
+ * stores are read (see {@link IndexReader.document(int, int)})
+ *
+ * Solution: Overload {@link IndexReader.document(int, int)}in the
+ * specific subclass.
+ */
+ assertFalse(e.hasMoreElements());
+ }
+
+ /**
+ * Checks ir.document(1), which is equivalent to ir.document(1,2) in
+ * this test scenario
+ */
+ doc = ir.document(1);
+ e = doc.fields();
+ for(int sn = 0; sn <= 2; sn++) {
+ for(int fn = 0; fn < 2 + sn * 1; fn++) {
+ f = (Field) e.nextElement();
+ assertEquals("FIELD_" + fn + "_STORE_" + sn, f.name());
+ assertEquals(fn + "/" + sn, f.stringValue());
+ assertEquals(sn, f.getDataStore());
+ }
+ }
+ assertFalse(e.hasMoreElements());
+
+ /**
+ * Checks a regular document with all field data in the standard .fdt
+ * file (field store 0)
+ */
+ doc = ir.document(2);
+ e = doc.fields();
+ f = (Field) e.nextElement();
+ assertEquals("regular", f.name());
+ assertEquals("doc2", f.stringValue());
+ assertEquals(0, f.getDataStore());
+ assertFalse(e.hasMoreElements());
+
+ /**
+ * Check directory contents
+ *
+ * This sub-test will fail when new file types are introduced.
+ */
+ String[] names = dir.list();
+
+ TreeSet files = getSuffixes(names);
+
+ TreeSet expectedFiles;
+ if(useCompound) {
+ expectedFiles = new TreeSet(Arrays.asList(new String[] {
+ "deletable", "segments", "cfs"
+ }));
+
+ assertEquals(expectedFiles, files);
+
+ String compoundFile = null;
+ for(int i=0;i